Portal Community

State Shape

// flowObserverPanelStore.ts
export interface FlowObserverPanelState {
    activeTabId    : string;
    panelHeight    : number;         // px — resizable via drag handle
    isDocked       : boolean;        // true = bottom panel; false = floating window
    tabDescriptors : TabDescriptor[]; // ordered list of available tabs
}

export interface TabDescriptor {
    id        : string;
    label     : string;
    icon      : string;          // Font Awesome icon class
    component : React.ComponentType; // Tab content component
    isBuiltIn : boolean;         // false = custom tab registered externally
}

Built-in Tabs

// Default tab descriptors registered on startup:
const DEFAULT_TABS: TabDescriptor[] = [
    { id: 'execution-status', label: 'Status',    icon: 'fa-circle-check', isBuiltIn: true },
    { id: 'node-list',        label: 'Nodes',     icon: 'fa-list',         isBuiltIn: true },
    { id: 'logs',             label: 'Logs',      icon: 'fa-scroll',       isBuiltIn: true },
    { id: 'node-inspector',   label: 'Inspector', icon: 'fa-magnifying-glass', isBuiltIn: true },
];

Custom Tab Registration

// Register a custom tab from a plugin or extension
const { registerTab } = useFlowObserverPanelStore.getState();

registerTab({
    id       : 'my-custom-tab',
    label    : 'Audit Trail',
    icon     : 'fa-shield',
    component: AuditTrailTabContent,
    isBuiltIn: false
});

// The custom tab appears in the panel tab bar and receives the same props as built-in tabs

Actions

interface FlowObserverPanelActions {
    setActiveTab  : (tabId: string) => void;
    setPanelHeight: (height: number) => void;
    setDocked     : (docked: boolean) => void;
    registerTab   : (tab: TabDescriptor) => void;
    unregisterTab : (tabId: string) => void;
}
flowObserverPanelStore does not hold execution data. It only knows which tab is showing. The actual data (logs, node statuses, inspector output) lives in executionStore. Tab components import from both stores as needed.