@invect/ui 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +77 -0
- package/dist/Invect-CWpIwZ5F.js +92738 -0
- package/dist/Invect.d.ts +25 -0
- package/dist/InvectShell.d.ts +14 -0
- package/dist/api/agent-tools.api.d.ts +1 -0
- package/dist/api/client.d.ts +207 -0
- package/dist/api/credentials.api.d.ts +47 -0
- package/dist/api/executions.api.d.ts +43 -0
- package/dist/api/flows.api.d.ts +100 -0
- package/dist/api/index.d.ts +9 -0
- package/dist/api/node-data.api.d.ts +66 -0
- package/dist/api/query-keys.d.ts +22 -0
- package/dist/api/triggers.api.d.ts +44 -0
- package/dist/api/types.d.ts +147 -0
- package/dist/api/use-flow-run-stream.d.ts +12 -0
- package/dist/assets/invect-branding.d.ts +4 -0
- package/dist/assets/provider-icons/index.d.ts +8 -0
- package/dist/babel-C9OtljFZ.js +9721 -0
- package/dist/components/PageLayout.d.ts +17 -0
- package/dist/components/chat/ChatInput.d.ts +17 -0
- package/dist/components/chat/ChatMessageList.d.ts +14 -0
- package/dist/components/chat/ChatModelSelector.d.ts +11 -0
- package/dist/components/chat/ChatPanel.d.ts +19 -0
- package/dist/components/chat/ChatPromptOverlay.d.ts +13 -0
- package/dist/components/chat/ChatProviderSelector.d.ts +9 -0
- package/dist/components/chat/ChatSettingsPanel.d.ts +11 -0
- package/dist/components/chat/InlineCredentialSetup.d.ts +9 -0
- package/dist/components/chat/MarkdownRenderer.d.ts +7 -0
- package/dist/components/chat/chat-memory.d.ts +21 -0
- package/dist/components/chat/chat.store.d.ts +416 -0
- package/dist/components/chat/index.d.ts +5 -0
- package/dist/components/chat/use-chat.d.ts +28 -0
- package/dist/components/credentials/CreateCredentialModal.d.ts +13 -0
- package/dist/components/credentials/CredentialDetailDialog.d.ts +17 -0
- package/dist/components/credentials/EditCredentialModal.d.ts +11 -0
- package/dist/components/credentials/OAuth2ConnectButton.d.ts +38 -0
- package/dist/components/credentials/OAuth2ProviderSelector.d.ts +15 -0
- package/dist/components/credentials/credential-utils.d.ts +12 -0
- package/dist/components/credentials/index.d.ts +9 -0
- package/dist/components/dashboard/FailedRunsAlert.d.ts +3 -0
- package/dist/components/dashboard/FlowCard.d.ts +7 -0
- package/dist/components/dashboard/RecentActivityTable.d.ts +9 -0
- package/dist/components/dashboard/StatCard.d.ts +10 -0
- package/dist/components/dashboard/index.d.ts +5 -0
- package/dist/components/dashboard/status-helpers.d.ts +5 -0
- package/dist/components/flow-editor/ActionsSidebar.d.ts +2 -0
- package/dist/components/flow-editor/FlowEditor.d.ts +21 -0
- package/dist/components/flow-editor/FlowHeader.d.ts +9 -0
- package/dist/components/flow-editor/FlowLayout.d.ts +24 -0
- package/dist/components/flow-editor/ModeSwitcher.d.ts +7 -0
- package/dist/components/flow-editor/NodeSidebar.d.ts +24 -0
- package/dist/components/flow-editor/RunControls.d.ts +12 -0
- package/dist/components/flow-editor/ToolConfigPanel.d.ts +16 -0
- package/dist/components/flow-editor/ValidationPanel.d.ts +5 -0
- package/dist/components/flow-editor/flow-editor.store.d.ts +1 -0
- package/dist/components/flow-editor/index.d.ts +6 -0
- package/dist/components/flow-editor/inline-edit.d.ts +10 -0
- package/dist/components/flow-editor/node-config-panel/ConfigFieldWithTemplate.d.ts +26 -0
- package/dist/components/flow-editor/node-config-panel/CredentialCombobox.d.ts +21 -0
- package/dist/components/flow-editor/node-config-panel/CredentialsSection.d.ts +19 -0
- package/dist/components/flow-editor/node-config-panel/DroppableInput.d.ts +20 -0
- package/dist/components/flow-editor/node-config-panel/DynamicSelectField.d.ts +22 -0
- package/dist/components/flow-editor/node-config-panel/JsonPreviewPanel.d.ts +25 -0
- package/dist/components/flow-editor/node-config-panel/NodeConfigPanel.d.ts +14 -0
- package/dist/components/flow-editor/node-config-panel/NodeConfigPanelHeader.d.ts +15 -0
- package/dist/components/flow-editor/node-config-panel/ParametersSection.d.ts +16 -0
- package/dist/components/flow-editor/node-config-panel/SearchableSelectField.d.ts +17 -0
- package/dist/components/flow-editor/node-config-panel/SwitchCasesField.d.ts +18 -0
- package/dist/components/flow-editor/node-config-panel/hooks/index.d.ts +2 -0
- package/dist/components/flow-editor/node-config-panel/hooks/use-node-config-panel-state.d.ts +24 -0
- package/dist/components/flow-editor/node-config-panel/hooks/use-node-execution.d.ts +46 -0
- package/dist/components/flow-editor/node-config-panel/hooks/use-upstream-slots.d.ts +16 -0
- package/dist/components/flow-editor/node-config-panel/panels/AgentToolsPanel.d.ts +18 -0
- package/dist/components/flow-editor/node-config-panel/panels/ConfigurationPanel.d.ts +49 -0
- package/dist/components/flow-editor/node-config-panel/panels/DataMapperPane.d.ts +40 -0
- package/dist/components/flow-editor/node-config-panel/panels/InputPanel.d.ts +49 -0
- package/dist/components/flow-editor/node-config-panel/panels/OutputPanel.d.ts +7 -0
- package/dist/components/flow-editor/node-config-panel/panels/index.d.ts +4 -0
- package/dist/components/flow-editor/node-config-panel/types.d.ts +19 -0
- package/dist/components/flow-editor/node-config-panel/use-node-config-panel-store.d.ts +49 -0
- package/dist/components/flow-editor/node-config-panel/use-node-config-state.d.ts +26 -0
- package/dist/components/flow-editor/node-config-panel/use-run-node.d.ts +16 -0
- package/dist/components/flow-editor/node-config-panel/utils.d.ts +9 -0
- package/dist/components/flow-editor/serialize-to-sdk.d.ts +20 -0
- package/dist/components/flow-editor/toolbar-context.d.ts +2 -0
- package/dist/components/flow-editor/use-copy-paste.d.ts +7 -0
- package/dist/components/flow-editor/use-copy-paste.types.d.ts +38 -0
- package/dist/components/flow-editor/use-flow-editor.d.ts +44 -0
- package/dist/components/flow-runs-table/FlowRunsTable.d.ts +6 -0
- package/dist/components/flow-runs-table/index.d.ts +1 -0
- package/dist/components/flow-viewer/FlowRunsView.d.ts +7 -0
- package/dist/components/flow-viewer/FlowStatusView.d.ts +21 -0
- package/dist/components/flow-viewer/RunSelector.d.ts +13 -0
- package/dist/components/flow-viewer/RunsSidebar.d.ts +14 -0
- package/dist/components/flow-viewer/agent-tool-executions-list.d.ts +7 -0
- package/dist/components/flow-viewer/index.d.ts +1 -0
- package/dist/components/flow-viewer/logs-panel.d.ts +18 -0
- package/dist/components/flow-viewer/use-execution-log-data.d.ts +113 -0
- package/dist/components/graph/BatchFlowEdge.d.ts +33 -0
- package/dist/components/graph/LayoutSelector.d.ts +9 -0
- package/dist/components/graph/index.d.ts +47 -0
- package/dist/components/graph/styleUtils.d.ts +124 -0
- package/dist/components/nodes/AgentConfigPanel.d.ts +24 -0
- package/dist/components/nodes/AgentNode.d.ts +8 -0
- package/dist/components/nodes/AgentToolsBox.d.ts +41 -0
- package/dist/components/nodes/NodeAppendix.d.ts +19 -0
- package/dist/components/nodes/NodeStatusIndicator.d.ts +30 -0
- package/dist/components/nodes/NodeViewContext.d.ts +18 -0
- package/dist/components/nodes/ToolParamField.d.ts +28 -0
- package/dist/components/nodes/ToolSelectorModal.d.ts +80 -0
- package/dist/components/nodes/ToolSelectorParts.d.ts +30 -0
- package/dist/components/nodes/UniversalNode.d.ts +2 -0
- package/dist/components/nodes/createContextAwareNodes.d.ts +6 -0
- package/dist/components/nodes/index.d.ts +22 -0
- package/dist/components/nodes/nodeRegistry.d.ts +13 -0
- package/dist/components/nodes/withNodeContext.d.ts +7 -0
- package/dist/components/shared/InvectLoader.d.ts +8 -0
- package/dist/components/shared/InvectLogo.d.ts +9 -0
- package/dist/components/shared/ProviderIcon.d.ts +23 -0
- package/dist/components/side-menu/side-menu.d.ts +4 -0
- package/dist/components/sidebar/BaseSidebar.d.ts +17 -0
- package/dist/components/sidebar/index.d.ts +1 -0
- package/dist/components/triggers/CronPreview.d.ts +12 -0
- package/dist/components/triggers/index.d.ts +1 -0
- package/dist/components/ui/alert-dialog.d.ts +18 -0
- package/dist/components/ui/badge.d.ts +9 -0
- package/dist/components/ui/button.d.ts +13 -0
- package/dist/components/ui/card.d.ts +9 -0
- package/dist/components/ui/codemirror-js-editor.d.ts +25 -0
- package/dist/components/ui/codemirror-json-editor.d.ts +18 -0
- package/dist/components/ui/codemirror-nunjucks-editor.d.ts +13 -0
- package/dist/components/ui/codemirror-vscode-theme.d.ts +24 -0
- package/dist/components/ui/collapsible.d.ts +6 -0
- package/dist/components/ui/command.d.ts +18 -0
- package/dist/components/ui/dialog.d.ts +18 -0
- package/dist/components/ui/dropdown-menu.d.ts +25 -0
- package/dist/components/ui/empty-state.d.ts +21 -0
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/label.d.ts +4 -0
- package/dist/components/ui/popover.d.ts +10 -0
- package/dist/components/ui/resizable.d.ts +8 -0
- package/dist/components/ui/scroll-area.d.ts +5 -0
- package/dist/components/ui/select.d.ts +18 -0
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/slider.d.ts +4 -0
- package/dist/components/ui/switch.d.ts +3 -0
- package/dist/components/ui/table.d.ts +10 -0
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/tooltip.d.ts +7 -0
- package/dist/components/ui/tree-view.d.ts +107 -0
- package/dist/contexts/AgentToolCallbacksContext.d.ts +23 -0
- package/dist/contexts/ApiContext.d.ts +11 -0
- package/dist/contexts/FlowDataContext.d.ts +9 -0
- package/dist/contexts/NodeRegistryContext.d.ts +14 -0
- package/dist/contexts/PluginRegistryContext.d.ts +39 -0
- package/dist/contexts/ThemeProvider.d.ts +18 -0
- package/dist/contexts/ValidationContext.d.ts +22 -0
- package/dist/demo/DemoInvect.d.ts +11 -0
- package/dist/demo/FlowViewer.d.ts +31 -0
- package/dist/demo/demo-api-client.d.ts +33 -0
- package/dist/demo/index.d.ts +6 -0
- package/dist/demo/sample-data.d.ts +1538 -0
- package/dist/demo.d.ts +2 -0
- package/dist/demo.js +2774 -0
- package/dist/estree-ClbRfS-1.js +7076 -0
- package/dist/fonts/geist-cyrillic-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-latin-ext-wght-normal.woff2 +0 -0
- package/dist/fonts/geist-latin-wght-normal.woff2 +0 -0
- package/dist/fonts/iosevka-latin-400-normal.woff2 +0 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/use-document-title.d.ts +1 -0
- package/dist/hooks/use-flow-data.d.ts +22 -0
- package/dist/hooks/use-invect-portal-class.d.ts +21 -0
- package/dist/hooks/useFlowEditorStore.d.ts +1 -0
- package/dist/index.css +3 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +717 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/prettier.d.ts +13 -0
- package/dist/routes/all-flow-runs.d.ts +5 -0
- package/dist/routes/credentials.d.ts +5 -0
- package/dist/routes/flow-route-layout.d.ts +19 -0
- package/dist/routes/flow-runs.d.ts +5 -0
- package/dist/routes/flow.d.ts +5 -0
- package/dist/routes/home.d.ts +5 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/standalone-C3Df7W52.js +3463 -0
- package/dist/stores/executionViewStore.d.ts +64 -0
- package/dist/stores/flow-editor.store.d.ts +137 -0
- package/dist/stores/flowEditorStore.d.ts +1 -0
- package/dist/stores/index.d.ts +2 -0
- package/dist/stores/uiStore.d.ts +45 -0
- package/dist/types/agent-tools.types.d.ts +53 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/node-definition.types.d.ts +85 -0
- package/dist/types/plugin.types.d.ts +100 -0
- package/dist/utils/credentialBranding.d.ts +8 -0
- package/dist/utils/credentialFiltering.d.ts +20 -0
- package/dist/utils/flowTransformations.d.ts +16 -0
- package/dist/utils/layoutUtils.d.ts +23 -0
- package/dist/utils/nodeReferenceUtils.d.ts +37 -0
- package/dist/vendor.d.ts +5 -0
- package/package.json +130 -0
- package/src/.DS_Store +0 -0
- package/src/Invect.tsx +229 -0
- package/src/InvectShell.tsx +55 -0
- package/src/api/agent-tools.api.ts +23 -0
- package/src/api/client.ts +899 -0
- package/src/api/credentials.api.ts +197 -0
- package/src/api/executions.api.ts +228 -0
- package/src/api/flows.api.ts +195 -0
- package/src/api/index.ts +17 -0
- package/src/api/node-data.api.ts +167 -0
- package/src/api/query-keys.ts +44 -0
- package/src/api/triggers.api.ts +120 -0
- package/src/api/types.ts +212 -0
- package/src/api/use-flow-run-stream.ts +206 -0
- package/src/app.css +560 -0
- package/src/assets/.DS_Store +0 -0
- package/src/assets/favicon.ico +0 -0
- package/src/assets/fonts/geist-cyrillic-wght-normal.woff2 +0 -0
- package/src/assets/fonts/geist-latin-ext-wght-normal.woff2 +0 -0
- package/src/assets/fonts/geist-latin-wght-normal.woff2 +0 -0
- package/src/assets/fonts/iosevka-latin-400-normal.woff2 +0 -0
- package/src/assets/invect-branding.ts +51 -0
- package/src/assets/provider-icons/anthropic.svg +1 -0
- package/src/assets/provider-icons/anthropic_light.svg +1 -0
- package/src/assets/provider-icons/github.svg +1 -0
- package/src/assets/provider-icons/github_light.svg +1 -0
- package/src/assets/provider-icons/gmail.svg +1 -0
- package/src/assets/provider-icons/google_calendar.svg +1 -0
- package/src/assets/provider-icons/google_docs.svg +1 -0
- package/src/assets/provider-icons/google_drive.svg +1 -0
- package/src/assets/provider-icons/google_sheets.svg +1 -0
- package/src/assets/provider-icons/index.ts +55 -0
- package/src/assets/provider-icons/linear.svg +1 -0
- package/src/assets/provider-icons/openai.svg +1 -0
- package/src/assets/provider-icons/postgres.svg +1 -0
- package/src/assets/provider-icons/slack.svg +1 -0
- package/src/assets/small-loader-dark.svg +22 -0
- package/src/assets/small-loader-light.svg +22 -0
- package/src/assets/small.svg +7 -0
- package/src/components/.DS_Store +0 -0
- package/src/components/PageLayout.tsx +55 -0
- package/src/components/chat/ChatInput.tsx +115 -0
- package/src/components/chat/ChatMessageList.tsx +788 -0
- package/src/components/chat/ChatModelSelector.tsx +208 -0
- package/src/components/chat/ChatPanel.tsx +243 -0
- package/src/components/chat/ChatPromptOverlay.tsx +150 -0
- package/src/components/chat/ChatProviderSelector.tsx +135 -0
- package/src/components/chat/ChatSettingsPanel.tsx +277 -0
- package/src/components/chat/InlineCredentialSetup.tsx +343 -0
- package/src/components/chat/MarkdownRenderer.tsx +140 -0
- package/src/components/chat/chat-memory.ts +88 -0
- package/src/components/chat/chat.store.ts +479 -0
- package/src/components/chat/index.ts +5 -0
- package/src/components/chat/use-chat.ts +473 -0
- package/src/components/credentials/CreateCredentialModal.tsx +609 -0
- package/src/components/credentials/CredentialDetailDialog.tsx +882 -0
- package/src/components/credentials/EditCredentialModal.tsx +399 -0
- package/src/components/credentials/OAuth2ConnectButton.tsx +288 -0
- package/src/components/credentials/OAuth2ProviderSelector.tsx +360 -0
- package/src/components/credentials/credential-utils.ts +99 -0
- package/src/components/credentials/index.ts +10 -0
- package/src/components/dashboard/FailedRunsAlert.tsx +67 -0
- package/src/components/dashboard/FlowCard.tsx +64 -0
- package/src/components/dashboard/RecentActivityTable.tsx +92 -0
- package/src/components/dashboard/StatCard.tsx +32 -0
- package/src/components/dashboard/index.ts +5 -0
- package/src/components/dashboard/status-helpers.tsx +102 -0
- package/src/components/flow-editor/ActionsSidebar.tsx +503 -0
- package/src/components/flow-editor/FlowEditor.tsx +1002 -0
- package/src/components/flow-editor/FlowHeader.tsx +87 -0
- package/src/components/flow-editor/FlowLayout.tsx +117 -0
- package/src/components/flow-editor/ModeSwitcher.tsx +49 -0
- package/src/components/flow-editor/NodeSidebar.tsx +343 -0
- package/src/components/flow-editor/RunControls.tsx +109 -0
- package/src/components/flow-editor/ToolConfigPanel.tsx +434 -0
- package/src/components/flow-editor/ValidationPanel.tsx +167 -0
- package/src/components/flow-editor/flow-editor.store.ts +2 -0
- package/src/components/flow-editor/index.ts +6 -0
- package/src/components/flow-editor/inline-edit.tsx +111 -0
- package/src/components/flow-editor/node-config-panel/ConfigFieldWithTemplate.tsx +334 -0
- package/src/components/flow-editor/node-config-panel/CredentialCombobox.tsx +217 -0
- package/src/components/flow-editor/node-config-panel/CredentialsSection.tsx +154 -0
- package/src/components/flow-editor/node-config-panel/DroppableInput.tsx +45 -0
- package/src/components/flow-editor/node-config-panel/DynamicSelectField.tsx +223 -0
- package/src/components/flow-editor/node-config-panel/JsonPreviewPanel.tsx +134 -0
- package/src/components/flow-editor/node-config-panel/NodeConfigPanel.tsx +650 -0
- package/src/components/flow-editor/node-config-panel/NodeConfigPanelHeader.tsx +91 -0
- package/src/components/flow-editor/node-config-panel/ParametersSection.tsx +144 -0
- package/src/components/flow-editor/node-config-panel/SearchableSelectField.tsx +126 -0
- package/src/components/flow-editor/node-config-panel/SwitchCasesField.tsx +212 -0
- package/src/components/flow-editor/node-config-panel/hooks/index.ts +2 -0
- package/src/components/flow-editor/node-config-panel/hooks/use-node-config-panel-state.ts +284 -0
- package/src/components/flow-editor/node-config-panel/hooks/use-node-execution.ts +287 -0
- package/src/components/flow-editor/node-config-panel/hooks/use-upstream-slots.ts +310 -0
- package/src/components/flow-editor/node-config-panel/panels/AgentToolsPanel.tsx +837 -0
- package/src/components/flow-editor/node-config-panel/panels/ConfigurationPanel.tsx +383 -0
- package/src/components/flow-editor/node-config-panel/panels/DataMapperPane.tsx +456 -0
- package/src/components/flow-editor/node-config-panel/panels/InputPanel.tsx +338 -0
- package/src/components/flow-editor/node-config-panel/panels/OutputPanel.tsx +109 -0
- package/src/components/flow-editor/node-config-panel/panels/index.ts +4 -0
- package/src/components/flow-editor/node-config-panel/types.ts +20 -0
- package/src/components/flow-editor/node-config-panel/use-node-config-panel-store.ts +283 -0
- package/src/components/flow-editor/node-config-panel/use-node-config-state.ts +172 -0
- package/src/components/flow-editor/node-config-panel/use-run-node.ts +147 -0
- package/src/components/flow-editor/node-config-panel/utils.ts +73 -0
- package/src/components/flow-editor/serialize-to-sdk.ts +204 -0
- package/src/components/flow-editor/toolbar-context.ts +9 -0
- package/src/components/flow-editor/use-copy-paste.ts +575 -0
- package/src/components/flow-editor/use-copy-paste.types.ts +35 -0
- package/src/components/flow-editor/use-flow-editor.ts +241 -0
- package/src/components/flow-runs-table/FlowRunsTable.tsx +631 -0
- package/src/components/flow-runs-table/index.ts +1 -0
- package/src/components/flow-viewer/FlowRunsView.tsx +268 -0
- package/src/components/flow-viewer/FlowStatusView.tsx +351 -0
- package/src/components/flow-viewer/RunSelector.tsx +422 -0
- package/src/components/flow-viewer/RunsSidebar.tsx +125 -0
- package/src/components/flow-viewer/agent-tool-executions-list.tsx +298 -0
- package/src/components/flow-viewer/index.ts +1 -0
- package/src/components/flow-viewer/logs-panel.tsx +567 -0
- package/src/components/flow-viewer/use-execution-log-data.ts +374 -0
- package/src/components/graph/BatchFlowEdge.tsx +229 -0
- package/src/components/graph/LayoutSelector.tsx +42 -0
- package/src/components/graph/index.ts +61 -0
- package/src/components/graph/styleUtils.ts +375 -0
- package/src/components/nodes/.DS_Store +0 -0
- package/src/components/nodes/AgentConfigPanel.tsx +1033 -0
- package/src/components/nodes/AgentNode.tsx +298 -0
- package/src/components/nodes/AgentToolsBox.tsx +193 -0
- package/src/components/nodes/NodeAppendix.tsx +98 -0
- package/src/components/nodes/NodeStatusIndicator.tsx +74 -0
- package/src/components/nodes/NodeViewContext.tsx +45 -0
- package/src/components/nodes/ToolParamField.tsx +282 -0
- package/src/components/nodes/ToolSelectorModal.tsx +648 -0
- package/src/components/nodes/ToolSelectorParts.tsx +505 -0
- package/src/components/nodes/UniversalNode.tsx +356 -0
- package/src/components/nodes/createContextAwareNodes.ts +19 -0
- package/src/components/nodes/index.ts +45 -0
- package/src/components/nodes/nodeRegistry.ts +50 -0
- package/src/components/nodes/withNodeContext.tsx +55 -0
- package/src/components/shared/InvectLoader.tsx +59 -0
- package/src/components/shared/InvectLogo.tsx +59 -0
- package/src/components/shared/ProviderIcon.tsx +115 -0
- package/src/components/side-menu/side-menu.tsx +267 -0
- package/src/components/sidebar/BaseSidebar.tsx +148 -0
- package/src/components/sidebar/index.ts +1 -0
- package/src/components/triggers/CronPreview.tsx +243 -0
- package/src/components/triggers/index.ts +1 -0
- package/src/components/ui/alert-dialog.tsx +152 -0
- package/src/components/ui/badge.tsx +39 -0
- package/src/components/ui/button.tsx +58 -0
- package/src/components/ui/card.tsx +75 -0
- package/src/components/ui/codemirror-js-editor.tsx +432 -0
- package/src/components/ui/codemirror-json-editor.tsx +816 -0
- package/src/components/ui/codemirror-nunjucks-editor.tsx +451 -0
- package/src/components/ui/codemirror-vscode-theme.ts +243 -0
- package/src/components/ui/collapsible.tsx +12 -0
- package/src/components/ui/command.tsx +162 -0
- package/src/components/ui/dialog.tsx +140 -0
- package/src/components/ui/dropdown-menu.tsx +232 -0
- package/src/components/ui/empty-state.tsx +93 -0
- package/src/components/ui/input.tsx +26 -0
- package/src/components/ui/label.tsx +19 -0
- package/src/components/ui/popover.tsx +53 -0
- package/src/components/ui/resizable.tsx +61 -0
- package/src/components/ui/scroll-area.tsx +56 -0
- package/src/components/ui/select.tsx +179 -0
- package/src/components/ui/separator.tsx +26 -0
- package/src/components/ui/slider.tsx +58 -0
- package/src/components/ui/switch.tsx +22 -0
- package/src/components/ui/table.tsx +90 -0
- package/src/components/ui/textarea.tsx +23 -0
- package/src/components/ui/tooltip.tsx +54 -0
- package/src/components/ui/tree-view.tsx +574 -0
- package/src/contexts/AgentToolCallbacksContext.tsx +31 -0
- package/src/contexts/ApiContext.tsx +51 -0
- package/src/contexts/FlowDataContext.tsx +21 -0
- package/src/contexts/NodeRegistryContext.tsx +54 -0
- package/src/contexts/PluginRegistryContext.tsx +182 -0
- package/src/contexts/ThemeProvider.tsx +106 -0
- package/src/contexts/ValidationContext.tsx +122 -0
- package/src/demo/DemoInvect.tsx +42 -0
- package/src/demo/FlowViewer.tsx +294 -0
- package/src/demo/demo-api-client.ts +246 -0
- package/src/demo/index.ts +28 -0
- package/src/demo/sample-data.ts +1980 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-document-title.ts +8 -0
- package/src/hooks/use-flow-data.ts +144 -0
- package/src/hooks/use-invect-portal-class.ts +27 -0
- package/src/hooks/useFlowEditorStore.ts +2 -0
- package/src/index.ts +70 -0
- package/src/lib/utils.ts +6 -0
- package/src/prettier.d.ts +13 -0
- package/src/routes/all-flow-runs.tsx +27 -0
- package/src/routes/credentials.tsx +362 -0
- package/src/routes/flow-route-layout.tsx +113 -0
- package/src/routes/flow-runs.tsx +22 -0
- package/src/routes/flow.tsx +22 -0
- package/src/routes/home.tsx +282 -0
- package/src/services/index.ts +6 -0
- package/src/stores/executionViewStore.ts +211 -0
- package/src/stores/flow-editor.store.ts +738 -0
- package/src/stores/flowEditorStore.ts +2 -0
- package/src/stores/index.ts +10 -0
- package/src/stores/uiStore.ts +189 -0
- package/src/types/agent-tools.types.ts +64 -0
- package/src/types/index.ts +5 -0
- package/src/types/node-definition.types.ts +104 -0
- package/src/types/plugin.types.ts +123 -0
- package/src/utils/credentialBranding.ts +116 -0
- package/src/utils/credentialFiltering.ts +68 -0
- package/src/utils/flowTransformations.ts +137 -0
- package/src/utils/layoutUtils.ts +127 -0
- package/src/utils/nodeReferenceUtils.ts +135 -0
- package/src/vendor.d.ts +7 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { Button } from '../ui/button';
|
|
2
|
+
import { Badge } from '../ui/badge';
|
|
3
|
+
import { Save, Settings, Share2, Loader2 } from 'lucide-react';
|
|
4
|
+
import { InlineEdit } from './inline-edit';
|
|
5
|
+
import { cn } from '../../lib/utils';
|
|
6
|
+
import { usePluginRegistry } from '../../contexts/PluginRegistryContext';
|
|
7
|
+
import { useParams } from 'react-router';
|
|
8
|
+
|
|
9
|
+
interface FlowHeaderProps {
|
|
10
|
+
flowName: string;
|
|
11
|
+
onFlowNameChange: (name: string) => void;
|
|
12
|
+
isDirty?: boolean;
|
|
13
|
+
onSave?: () => Promise<boolean | void>;
|
|
14
|
+
isSaving?: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function FlowHeader({
|
|
18
|
+
flowName,
|
|
19
|
+
onFlowNameChange,
|
|
20
|
+
isDirty = false,
|
|
21
|
+
onSave,
|
|
22
|
+
isSaving = false,
|
|
23
|
+
}: FlowHeaderProps) {
|
|
24
|
+
const { flowId } = useParams();
|
|
25
|
+
const registry = usePluginRegistry();
|
|
26
|
+
const flowHeaderActions = registry.headerActions['flowHeader'] ?? [];
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<header className="flex items-center justify-between px-6 border-b h-14 border-border bg-imp-background text-card-foreground">
|
|
30
|
+
<div className="flex items-center gap-4">
|
|
31
|
+
<InlineEdit
|
|
32
|
+
value={flowName}
|
|
33
|
+
onChange={onFlowNameChange}
|
|
34
|
+
placeholder="Enter flow name"
|
|
35
|
+
displayClassName="text-lg font-semibold text-card-foreground"
|
|
36
|
+
inputClassName="h-8 w-64 text-lg font-semibold"
|
|
37
|
+
/>
|
|
38
|
+
{isDirty ? (
|
|
39
|
+
<Badge
|
|
40
|
+
variant="secondary"
|
|
41
|
+
className="gap-1.5 text-xs border-warning/40 bg-warning-muted text-warning"
|
|
42
|
+
>
|
|
43
|
+
<span className="h-1.5 w-1.5 rounded-full bg-warning" />
|
|
44
|
+
Unsaved Changes
|
|
45
|
+
</Badge>
|
|
46
|
+
) : (
|
|
47
|
+
<span className="px-3 py-1 text-xs font-medium rounded-full bg-muted text-muted-foreground">
|
|
48
|
+
Draft
|
|
49
|
+
</span>
|
|
50
|
+
)}
|
|
51
|
+
</div>
|
|
52
|
+
<div className="flex items-center gap-2">
|
|
53
|
+
<Button variant="ghost" size="icon-sm" title="Settings" aria-label="Settings">
|
|
54
|
+
<Settings className="w-4 h-4" />
|
|
55
|
+
</Button>
|
|
56
|
+
{/* Plugin-contributed header actions (e.g. Share button from RBAC) */}
|
|
57
|
+
{flowHeaderActions
|
|
58
|
+
.filter((a) => !a.permission || registry.checkPermission(a.permission, { flowId }))
|
|
59
|
+
.map((action, i) => (
|
|
60
|
+
<action.component key={`plugin-action-${i}`} flowId={flowId} basePath="" />
|
|
61
|
+
))}
|
|
62
|
+
{/* Fallback Share button when no plugin provides one */}
|
|
63
|
+
{flowHeaderActions.length === 0 && (
|
|
64
|
+
<Button variant="ghost" size="icon-sm" title="Share" aria-label="Share">
|
|
65
|
+
<Share2 className="w-4 h-4" />
|
|
66
|
+
</Button>
|
|
67
|
+
)}
|
|
68
|
+
<Button
|
|
69
|
+
variant="outline"
|
|
70
|
+
size="sm"
|
|
71
|
+
onClick={onSave}
|
|
72
|
+
disabled={!isDirty || isSaving || !onSave}
|
|
73
|
+
className={cn(
|
|
74
|
+
isDirty && 'border-primary/40 bg-primary/5 text-primary hover:bg-primary/10',
|
|
75
|
+
)}
|
|
76
|
+
>
|
|
77
|
+
{isSaving ? (
|
|
78
|
+
<Loader2 className="w-4 h-4 mr-2 animate-spin" />
|
|
79
|
+
) : (
|
|
80
|
+
<Save className="w-4 h-4 mr-2" />
|
|
81
|
+
)}
|
|
82
|
+
Save
|
|
83
|
+
</Button>
|
|
84
|
+
</div>
|
|
85
|
+
</header>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
import { Plus, PanelLeftClose, PanelLeftOpen } from 'lucide-react';
|
|
3
|
+
import { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } from '../ui/tooltip';
|
|
4
|
+
import { useUIStore } from '../../stores/uiStore';
|
|
5
|
+
import { ToolbarCollapsedProvider } from './toolbar-context';
|
|
6
|
+
|
|
7
|
+
interface FlowLayoutProps {
|
|
8
|
+
sidebar: React.ReactNode;
|
|
9
|
+
viewport: React.ReactNode;
|
|
10
|
+
modeSwitcher: React.ReactNode;
|
|
11
|
+
layoutSelector?: React.ReactNode;
|
|
12
|
+
viewportRef?: React.RefObject<HTMLDivElement | null>;
|
|
13
|
+
/** Panel that appears on the right side (e.g. tool config, node config) */
|
|
14
|
+
rightPanel?: React.ReactNode;
|
|
15
|
+
/** Chat toggle button rendered in the top-right toolbar */
|
|
16
|
+
chatToggle?: React.ReactNode;
|
|
17
|
+
/** Chat panel rendered as a right sidebar */
|
|
18
|
+
chatPanel?: React.ReactNode;
|
|
19
|
+
/** Floating chat overlay rendered above the viewport (for empty flows) */
|
|
20
|
+
chatOverlay?: React.ReactNode;
|
|
21
|
+
/** Extra controls rendered in the bottom toolbar (e.g. Run button, Active/Inactive) */
|
|
22
|
+
toolbarExtra?: React.ReactNode;
|
|
23
|
+
/** Whether the sidebar is open */
|
|
24
|
+
sidebarOpen?: boolean;
|
|
25
|
+
/** Called to toggle sidebar visibility */
|
|
26
|
+
onToggleSidebar?: () => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function FlowLayout({
|
|
30
|
+
sidebar,
|
|
31
|
+
viewport,
|
|
32
|
+
modeSwitcher,
|
|
33
|
+
layoutSelector,
|
|
34
|
+
viewportRef,
|
|
35
|
+
rightPanel,
|
|
36
|
+
chatToggle,
|
|
37
|
+
chatPanel,
|
|
38
|
+
chatOverlay,
|
|
39
|
+
toolbarExtra,
|
|
40
|
+
sidebarOpen = true,
|
|
41
|
+
onToggleSidebar,
|
|
42
|
+
}: FlowLayoutProps) {
|
|
43
|
+
const collapsed = useUIStore((s) => s.toolbarCollapsed);
|
|
44
|
+
const toggleCollapsed = useUIStore((s) => s.toggleToolbarCollapsed);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<div className="flex flex-1 min-h-0">
|
|
48
|
+
{sidebarOpen && sidebar}
|
|
49
|
+
<div
|
|
50
|
+
className="relative flex flex-col flex-1 min-h-0 overflow-hidden"
|
|
51
|
+
ref={viewportRef as React.RefObject<HTMLDivElement>}
|
|
52
|
+
>
|
|
53
|
+
{/* Mode switcher - top center */}
|
|
54
|
+
<div className="absolute left-1/2 -translate-x-1/2 top-4 z-10">{modeSwitcher}</div>
|
|
55
|
+
|
|
56
|
+
{viewport}
|
|
57
|
+
{chatOverlay}
|
|
58
|
+
|
|
59
|
+
{/* Bottom toolbar - Figma-style */}
|
|
60
|
+
{(onToggleSidebar || layoutSelector || chatToggle || toolbarExtra) && (
|
|
61
|
+
<TooltipProvider>
|
|
62
|
+
<ToolbarCollapsedProvider value={collapsed}>
|
|
63
|
+
<div className="absolute bottom-4 left-1/2 -translate-x-1/2 z-10 flex items-center gap-1 rounded-lg border border-border bg-card/90 backdrop-blur-sm shadow-md p-1">
|
|
64
|
+
{/* Collapse / expand toggle */}
|
|
65
|
+
<Tooltip>
|
|
66
|
+
<TooltipTrigger asChild>
|
|
67
|
+
<button
|
|
68
|
+
onClick={toggleCollapsed}
|
|
69
|
+
className="flex items-center justify-center w-7 h-7 rounded-md text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors"
|
|
70
|
+
>
|
|
71
|
+
{collapsed ? (
|
|
72
|
+
<PanelLeftOpen className="w-3.5 h-3.5" />
|
|
73
|
+
) : (
|
|
74
|
+
<PanelLeftClose className="w-3.5 h-3.5" />
|
|
75
|
+
)}
|
|
76
|
+
</button>
|
|
77
|
+
</TooltipTrigger>
|
|
78
|
+
<TooltipContent side="top">
|
|
79
|
+
{collapsed ? 'Expand toolbar' : 'Collapse toolbar'}
|
|
80
|
+
</TooltipContent>
|
|
81
|
+
</Tooltip>
|
|
82
|
+
|
|
83
|
+
{onToggleSidebar && (
|
|
84
|
+
<Tooltip>
|
|
85
|
+
<TooltipTrigger asChild>
|
|
86
|
+
<button
|
|
87
|
+
onClick={onToggleSidebar}
|
|
88
|
+
className="flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-md text-card-foreground hover:bg-accent hover:text-accent-foreground transition-colors"
|
|
89
|
+
title={sidebarOpen ? 'Close node panel' : 'Open node panel'}
|
|
90
|
+
>
|
|
91
|
+
<Plus className="w-3.5 h-3.5" />
|
|
92
|
+
{!collapsed && 'Add nodes'}
|
|
93
|
+
</button>
|
|
94
|
+
</TooltipTrigger>
|
|
95
|
+
{collapsed && <TooltipContent side="top">Add nodes</TooltipContent>}
|
|
96
|
+
</Tooltip>
|
|
97
|
+
)}
|
|
98
|
+
{layoutSelector}
|
|
99
|
+
{chatToggle}
|
|
100
|
+
{toolbarExtra && (
|
|
101
|
+
<>
|
|
102
|
+
<div className="w-px h-4 bg-border mx-0.5" />
|
|
103
|
+
{toolbarExtra}
|
|
104
|
+
</>
|
|
105
|
+
)}
|
|
106
|
+
</div>
|
|
107
|
+
</ToolbarCollapsedProvider>
|
|
108
|
+
</TooltipProvider>
|
|
109
|
+
)}
|
|
110
|
+
</div>
|
|
111
|
+
{rightPanel}
|
|
112
|
+
{chatPanel}
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export default FlowLayout;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { cn } from '../../lib/utils';
|
|
2
|
+
import { Button } from '../ui/button';
|
|
3
|
+
import { Edit3, History } from 'lucide-react';
|
|
4
|
+
|
|
5
|
+
export type ViewMode = 'edit' | 'runs';
|
|
6
|
+
|
|
7
|
+
interface ModeSwitcherProps {
|
|
8
|
+
mode: ViewMode;
|
|
9
|
+
onModeChange: (mode: ViewMode) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function ModeSwitcher({ mode, onModeChange }: ModeSwitcherProps) {
|
|
13
|
+
const isEditMode = mode === 'edit';
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div className="inline-flex items-center rounded-md border border-border bg-muted/40 p-0.5">
|
|
17
|
+
<Button
|
|
18
|
+
variant="ghost"
|
|
19
|
+
size="sm"
|
|
20
|
+
onClick={() => onModeChange('edit')}
|
|
21
|
+
className={cn(
|
|
22
|
+
'h-7 gap-1.5 rounded-sm px-2.5 text-xs',
|
|
23
|
+
isEditMode
|
|
24
|
+
? 'bg-card text-foreground shadow-sm hover:bg-card'
|
|
25
|
+
: 'text-muted-foreground hover:text-foreground',
|
|
26
|
+
)}
|
|
27
|
+
>
|
|
28
|
+
<Edit3 className="h-3.5 w-3.5" />
|
|
29
|
+
Edit
|
|
30
|
+
</Button>
|
|
31
|
+
<Button
|
|
32
|
+
variant="ghost"
|
|
33
|
+
size="sm"
|
|
34
|
+
onClick={() => onModeChange('runs')}
|
|
35
|
+
className={cn(
|
|
36
|
+
'h-7 gap-1.5 rounded-sm px-2.5 text-xs',
|
|
37
|
+
!isEditMode
|
|
38
|
+
? 'bg-card text-foreground shadow-sm hover:bg-card'
|
|
39
|
+
: 'text-muted-foreground hover:text-foreground',
|
|
40
|
+
)}
|
|
41
|
+
>
|
|
42
|
+
<History className="h-3.5 w-3.5" />
|
|
43
|
+
Runs
|
|
44
|
+
</Button>
|
|
45
|
+
</div>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export default ModeSwitcher;
|
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import React, { useMemo, useState } from 'react';
|
|
2
|
+
import { Button } from '../ui/button';
|
|
3
|
+
|
|
4
|
+
import { ScrollArea } from '../ui/scroll-area';
|
|
5
|
+
import { useNodeRegistry } from '../../contexts/NodeRegistryContext';
|
|
6
|
+
import type { NodeDefinition } from '../../types/node-definition.types';
|
|
7
|
+
import type { ToolDefinition, AddedToolInstance } from '../nodes/ToolSelectorModal';
|
|
8
|
+
import { ProviderIcon } from '../shared/ProviderIcon';
|
|
9
|
+
import { useFlowEditorStore } from './flow-editor.store';
|
|
10
|
+
import { ActionsSidebar } from './ActionsSidebar';
|
|
11
|
+
import { Search, Plus, X, ChevronRight, PanelLeftClose } from 'lucide-react';
|
|
12
|
+
import { cn } from '../../lib/utils';
|
|
13
|
+
import { InvectLoader } from '../shared/InvectLoader';
|
|
14
|
+
|
|
15
|
+
// ─── Types ─────────────────────────────────────────────────────────
|
|
16
|
+
|
|
17
|
+
export type SidebarMode = 'nodes' | 'actions';
|
|
18
|
+
|
|
19
|
+
export interface NodeSidebarProps {
|
|
20
|
+
/** Current display mode */
|
|
21
|
+
mode: SidebarMode;
|
|
22
|
+
|
|
23
|
+
// ─── Nodes mode props ────────────────────
|
|
24
|
+
onAddNode: (type: string) => void;
|
|
25
|
+
/** Called to collapse/hide the sidebar */
|
|
26
|
+
onCollapse?: () => void;
|
|
27
|
+
|
|
28
|
+
// ─── Actions mode props ──────────────────
|
|
29
|
+
/** Close the actions panel (returns to nodes mode) */
|
|
30
|
+
onClose?: () => void;
|
|
31
|
+
/** All available tools from API */
|
|
32
|
+
availableTools?: ToolDefinition[];
|
|
33
|
+
/** Currently added tool instances on the agent node */
|
|
34
|
+
addedTools?: AddedToolInstance[];
|
|
35
|
+
/** Called when a tool is added. Returns the new instance ID. */
|
|
36
|
+
onAddTool?: (toolId: string) => string;
|
|
37
|
+
/** Called when a tool instance is removed */
|
|
38
|
+
onRemoveTool?: (instanceId: string) => void;
|
|
39
|
+
/** Called when an added tool instance is clicked (to open config panel) */
|
|
40
|
+
onSelectTool?: (instance: AddedToolInstance) => void;
|
|
41
|
+
/** Currently selected instance (to highlight) */
|
|
42
|
+
selectedInstanceId?: string | null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
46
|
+
// Main Component
|
|
47
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
48
|
+
|
|
49
|
+
export function NodeSidebar(props: NodeSidebarProps) {
|
|
50
|
+
if (props.mode === 'actions') {
|
|
51
|
+
return <ActionsSidebar {...props} />;
|
|
52
|
+
}
|
|
53
|
+
return <NodesSidebar onAddNode={props.onAddNode} onCollapse={props.onCollapse} />;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
57
|
+
// Nodes Mode
|
|
58
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
59
|
+
|
|
60
|
+
function NodesSidebar({
|
|
61
|
+
onAddNode,
|
|
62
|
+
onCollapse,
|
|
63
|
+
}: {
|
|
64
|
+
onAddNode: (type: string) => void;
|
|
65
|
+
onCollapse?: () => void;
|
|
66
|
+
}) {
|
|
67
|
+
const [search, setSearch] = useState('');
|
|
68
|
+
// Tracks which groups the user has manually expanded (all start collapsed)
|
|
69
|
+
const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set());
|
|
70
|
+
const { isLoading, nodeDefinitions } = useNodeRegistry();
|
|
71
|
+
|
|
72
|
+
const isSearching = search.trim().length > 0;
|
|
73
|
+
|
|
74
|
+
const toggleGroup = (providerId: string) => {
|
|
75
|
+
setExpandedGroups((prev) => {
|
|
76
|
+
const next = new Set(prev);
|
|
77
|
+
if (next.has(providerId)) {
|
|
78
|
+
next.delete(providerId);
|
|
79
|
+
} else {
|
|
80
|
+
next.add(providerId);
|
|
81
|
+
}
|
|
82
|
+
return next;
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
const totalVisible = useMemo(
|
|
87
|
+
() => nodeDefinitions.filter((n) => !n.hidden).length,
|
|
88
|
+
[nodeDefinitions],
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
const getNodeSortRank = (providerId: string, node: NodeDefinition) => {
|
|
92
|
+
if (providerId === 'core') {
|
|
93
|
+
if (node.type === 'AGENT') {
|
|
94
|
+
return 0;
|
|
95
|
+
}
|
|
96
|
+
if (node.type === 'core.model') {
|
|
97
|
+
return 1;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return 2;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// Filter nodes by search, then group by provider
|
|
105
|
+
const { providerGroups, totalFiltered } = useMemo(() => {
|
|
106
|
+
const lowerSearch = search.toLowerCase();
|
|
107
|
+
|
|
108
|
+
const filtered = nodeDefinitions.filter((n) => {
|
|
109
|
+
// Never show hidden (deprecated) nodes in the palette
|
|
110
|
+
if (n.hidden) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
if (search) {
|
|
114
|
+
return (
|
|
115
|
+
n.label.toLowerCase().includes(lowerSearch) ||
|
|
116
|
+
n.description.toLowerCase().includes(lowerSearch)
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
return true;
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
// Group by provider id
|
|
123
|
+
const byProvider: Record<
|
|
124
|
+
string,
|
|
125
|
+
{ name: string; icon?: string; svgIcon?: string; nodes: NodeDefinition[] }
|
|
126
|
+
> = {};
|
|
127
|
+
for (const node of filtered) {
|
|
128
|
+
const providerId = node.provider?.id ?? 'other';
|
|
129
|
+
if (!byProvider[providerId]) {
|
|
130
|
+
byProvider[providerId] = {
|
|
131
|
+
name: node.provider?.name ?? 'Other',
|
|
132
|
+
icon: node.provider?.icon,
|
|
133
|
+
svgIcon: node.provider?.svgIcon,
|
|
134
|
+
nodes: [],
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
byProvider[providerId].nodes.push(node);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for (const [providerId, group] of Object.entries(byProvider)) {
|
|
141
|
+
group.nodes.sort((a, b) => {
|
|
142
|
+
const rankDiff = getNodeSortRank(providerId, a) - getNodeSortRank(providerId, b);
|
|
143
|
+
if (rankDiff !== 0) {
|
|
144
|
+
return rankDiff;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
return a.label.localeCompare(b.label);
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return { providerGroups: byProvider, totalFiltered: filtered.length };
|
|
152
|
+
}, [nodeDefinitions, search]);
|
|
153
|
+
|
|
154
|
+
// Sort providers: triggers first, then core, then rest alphabetical
|
|
155
|
+
const providerOrder = ['triggers', 'core', 'ai', 'logic', 'data', 'io'];
|
|
156
|
+
const sortedProviderIds = useMemo(
|
|
157
|
+
() =>
|
|
158
|
+
Object.keys(providerGroups).sort((a, b) => {
|
|
159
|
+
const idxA = providerOrder.indexOf(a);
|
|
160
|
+
const idxB = providerOrder.indexOf(b);
|
|
161
|
+
if (idxA !== -1 && idxB !== -1) {
|
|
162
|
+
return idxA - idxB;
|
|
163
|
+
}
|
|
164
|
+
if (idxA !== -1) {
|
|
165
|
+
return -1;
|
|
166
|
+
}
|
|
167
|
+
if (idxB !== -1) {
|
|
168
|
+
return 1;
|
|
169
|
+
}
|
|
170
|
+
return providerGroups[a].name.localeCompare(providerGroups[b].name);
|
|
171
|
+
}),
|
|
172
|
+
[providerGroups],
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
if (isLoading) {
|
|
176
|
+
return (
|
|
177
|
+
<div className="flex flex-col items-center justify-center border-r w-96 border-border bg-imp-background text-card-foreground">
|
|
178
|
+
<InvectLoader iconClassName="h-14" label="Loading nodes..." />
|
|
179
|
+
</div>
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
return (
|
|
184
|
+
<div className="flex flex-col min-h-0 overflow-hidden duration-200 border-r w-96 border-border bg-imp-background text-card-foreground animate-in slide-in-from-left fade-in">
|
|
185
|
+
{/* Header */}
|
|
186
|
+
<div className="flex items-center justify-between px-4 py-3 border-b border-border">
|
|
187
|
+
<h2 className="text-sm font-semibold text-card-foreground">Nodes</h2>
|
|
188
|
+
{onCollapse && (
|
|
189
|
+
<Button
|
|
190
|
+
variant="ghost"
|
|
191
|
+
size="sm"
|
|
192
|
+
className="p-0 w-7 h-7 text-muted-foreground hover:text-foreground"
|
|
193
|
+
onClick={onCollapse}
|
|
194
|
+
title="Collapse sidebar"
|
|
195
|
+
>
|
|
196
|
+
<PanelLeftClose className="w-4 h-4" />
|
|
197
|
+
</Button>
|
|
198
|
+
)}
|
|
199
|
+
</div>
|
|
200
|
+
|
|
201
|
+
{/* Search & Filters */}
|
|
202
|
+
<div className="px-4 pt-3 pb-2 space-y-2 border-b border-border">
|
|
203
|
+
<div className="relative">
|
|
204
|
+
<Search className="absolute left-3 top-1/2 h-3.5 w-3.5 -translate-y-1/2 pointer-events-none text-muted-foreground" />
|
|
205
|
+
<input
|
|
206
|
+
type="text"
|
|
207
|
+
placeholder="Search nodes…"
|
|
208
|
+
value={search}
|
|
209
|
+
onChange={(e) => setSearch(e.target.value)}
|
|
210
|
+
className="h-8 w-full rounded-lg border border-border bg-transparent pl-9 pr-3 text-xs outline-none placeholder:text-muted-foreground focus:border-primary/50"
|
|
211
|
+
/>
|
|
212
|
+
{search && (
|
|
213
|
+
<button
|
|
214
|
+
onClick={() => setSearch('')}
|
|
215
|
+
className="absolute -translate-y-1/2 right-3 top-1/2 text-muted-foreground hover:text-foreground"
|
|
216
|
+
>
|
|
217
|
+
<X className="w-3 h-3" />
|
|
218
|
+
</button>
|
|
219
|
+
)}
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
222
|
+
|
|
223
|
+
{/* List — grouped by provider */}
|
|
224
|
+
<ScrollArea className="flex-1 min-h-0 overflow-hidden">
|
|
225
|
+
<div className="p-3 space-y-4">
|
|
226
|
+
{sortedProviderIds.map((providerId) => {
|
|
227
|
+
const group = providerGroups[providerId];
|
|
228
|
+
const isCollapsed = isSearching ? false : !expandedGroups.has(providerId);
|
|
229
|
+
return (
|
|
230
|
+
<div key={providerId}>
|
|
231
|
+
<button
|
|
232
|
+
type="button"
|
|
233
|
+
onClick={() => toggleGroup(providerId)}
|
|
234
|
+
className="flex items-center gap-1.5 mb-2 w-full text-[11px] font-semibold tracking-wider uppercase text-muted-foreground hover:text-foreground transition-colors"
|
|
235
|
+
>
|
|
236
|
+
<ChevronRight
|
|
237
|
+
className={cn(
|
|
238
|
+
'w-3 h-3 shrink-0 transition-transform duration-200',
|
|
239
|
+
!isCollapsed && 'rotate-90',
|
|
240
|
+
)}
|
|
241
|
+
/>
|
|
242
|
+
<ProviderIcon
|
|
243
|
+
providerId={providerId}
|
|
244
|
+
svgIcon={group.svgIcon}
|
|
245
|
+
icon={group.icon}
|
|
246
|
+
className="w-4 h-4"
|
|
247
|
+
/>
|
|
248
|
+
<span className="flex-1 text-left">{group.name}</span>
|
|
249
|
+
<span className="text-[10px] font-normal tabular-nums">{group.nodes.length}</span>
|
|
250
|
+
</button>
|
|
251
|
+
{!isCollapsed && (
|
|
252
|
+
<div className="space-y-1.5">
|
|
253
|
+
{group.nodes.map((node) => (
|
|
254
|
+
<NodeCard key={node.type} node={node} onAddNode={onAddNode} />
|
|
255
|
+
))}
|
|
256
|
+
</div>
|
|
257
|
+
)}
|
|
258
|
+
</div>
|
|
259
|
+
);
|
|
260
|
+
})}
|
|
261
|
+
{sortedProviderIds.length === 0 && (
|
|
262
|
+
<div className="py-8 text-center text-muted-foreground">
|
|
263
|
+
<Search className="w-6 h-6 mx-auto mb-2 opacity-20" />
|
|
264
|
+
<p className="text-xs">No nodes found matching “{search}”</p>
|
|
265
|
+
</div>
|
|
266
|
+
)}
|
|
267
|
+
</div>
|
|
268
|
+
</ScrollArea>
|
|
269
|
+
|
|
270
|
+
<div className="px-4 py-2 text-xs border-t border-border text-muted-foreground">
|
|
271
|
+
{totalFiltered} of {totalVisible} nodes
|
|
272
|
+
</div>
|
|
273
|
+
</div>
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
function NodeCard({
|
|
278
|
+
node,
|
|
279
|
+
onAddNode,
|
|
280
|
+
}: {
|
|
281
|
+
node: NodeDefinition;
|
|
282
|
+
onAddNode: (type: string) => void;
|
|
283
|
+
}) {
|
|
284
|
+
const bgColor =
|
|
285
|
+
node.provider?.id === 'core' || node.provider?.id === 'triggers'
|
|
286
|
+
? 'bg-accent text-primary'
|
|
287
|
+
: 'bg-muted text-muted-foreground';
|
|
288
|
+
|
|
289
|
+
// Check if this node type has reached its maxInstances limit
|
|
290
|
+
const storeNodes = useFlowEditorStore((s) => s.nodes);
|
|
291
|
+
const isAtLimit = useMemo(() => {
|
|
292
|
+
if (node.maxInstances === null || node.maxInstances === undefined) {
|
|
293
|
+
return false;
|
|
294
|
+
}
|
|
295
|
+
const count = storeNodes.filter(
|
|
296
|
+
(n) => (n.data as Record<string, unknown>)?.type === node.type,
|
|
297
|
+
).length;
|
|
298
|
+
return count >= node.maxInstances;
|
|
299
|
+
}, [node.maxInstances, node.type, storeNodes]);
|
|
300
|
+
|
|
301
|
+
return (
|
|
302
|
+
<div
|
|
303
|
+
className={cn(
|
|
304
|
+
'relative flex items-center gap-2.5 p-2.5 transition-all border rounded-lg group border-border',
|
|
305
|
+
isAtLimit
|
|
306
|
+
? 'opacity-50 cursor-not-allowed'
|
|
307
|
+
: 'cursor-pointer hover:border-muted-foreground/50 hover:bg-muted/50',
|
|
308
|
+
)}
|
|
309
|
+
onClick={() => !isAtLimit && onAddNode(node.type)}
|
|
310
|
+
title={
|
|
311
|
+
isAtLimit ? `Only ${node.maxInstances} ${node.label} allowed per flow` : node.description
|
|
312
|
+
}
|
|
313
|
+
>
|
|
314
|
+
<div className={cn('flex h-8 w-8 shrink-0 items-center justify-center rounded-md', bgColor)}>
|
|
315
|
+
<ProviderIcon
|
|
316
|
+
providerId={node.provider?.id}
|
|
317
|
+
svgIcon={node.provider?.svgIcon}
|
|
318
|
+
icon={node.icon}
|
|
319
|
+
className="w-5 h-5"
|
|
320
|
+
/>
|
|
321
|
+
</div>
|
|
322
|
+
<div className="flex-1 min-w-0">
|
|
323
|
+
<div className="text-sm font-medium truncate">{node.label}</div>
|
|
324
|
+
<p className="overflow-hidden text-xs text-muted-foreground line-clamp-1 text-ellipsis">
|
|
325
|
+
{isAtLimit ? 'Already added to flow' : node.description}
|
|
326
|
+
</p>
|
|
327
|
+
</div>
|
|
328
|
+
{!isAtLimit && (
|
|
329
|
+
<Button
|
|
330
|
+
size="sm"
|
|
331
|
+
variant="ghost"
|
|
332
|
+
className="w-6 h-6 p-0 transition-opacity opacity-0 shrink-0 group-hover:opacity-100 hover:bg-primary/10 hover:text-primary"
|
|
333
|
+
onClick={(e) => {
|
|
334
|
+
e.stopPropagation();
|
|
335
|
+
onAddNode(node.type);
|
|
336
|
+
}}
|
|
337
|
+
>
|
|
338
|
+
<Plus className="w-3 h-3" />
|
|
339
|
+
</Button>
|
|
340
|
+
)}
|
|
341
|
+
</div>
|
|
342
|
+
);
|
|
343
|
+
}
|