@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,167 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useValidation } from '../../contexts/ValidationContext';
|
|
3
|
+
import {
|
|
4
|
+
FlowValidationError,
|
|
5
|
+
FlowValidationWarning,
|
|
6
|
+
FLOW_VALIDATION_ERROR_TYPES,
|
|
7
|
+
} from '@invect/core/types';
|
|
8
|
+
|
|
9
|
+
// Helper function to format node ID to a short display name
|
|
10
|
+
const formatNodeId = (nodeId: string): string => {
|
|
11
|
+
// Trim long UUIDs to something readable
|
|
12
|
+
if (nodeId.length > 20) {
|
|
13
|
+
return nodeId.slice(0, 8) + '…';
|
|
14
|
+
}
|
|
15
|
+
return nodeId;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
interface ValidationPanelProps {
|
|
19
|
+
className?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function ValidationPanel({ className = '' }: ValidationPanelProps) {
|
|
23
|
+
const { validationResult, hasErrors, hasWarnings } = useValidation();
|
|
24
|
+
|
|
25
|
+
if (!validationResult || (!hasErrors && !hasWarnings)) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const getErrorIcon = (error: FlowValidationError | FlowValidationWarning) => {
|
|
30
|
+
if (error.severity === 'error') {
|
|
31
|
+
return <span className="font-bold text-red-500">⚠️</span>;
|
|
32
|
+
}
|
|
33
|
+
return <span className="font-bold text-yellow-500">⚠</span>;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const getErrorTypeLabel = (type: string) => {
|
|
37
|
+
switch (type) {
|
|
38
|
+
// Errors (will cause execution failure)
|
|
39
|
+
case FLOW_VALIDATION_ERROR_TYPES.ERROR.INVALID_EDGE_REFERENCE:
|
|
40
|
+
return 'Invalid Edge Reference';
|
|
41
|
+
case FLOW_VALIDATION_ERROR_TYPES.ERROR.SELF_REFERENCING_EDGE:
|
|
42
|
+
return 'Self-Referencing Edge';
|
|
43
|
+
case FLOW_VALIDATION_ERROR_TYPES.ERROR.CIRCULAR_DEPENDENCY:
|
|
44
|
+
return 'Circular Dependency';
|
|
45
|
+
case FLOW_VALIDATION_ERROR_TYPES.ERROR.VALIDATION_SYSTEM_ERROR:
|
|
46
|
+
return 'Validation System Error';
|
|
47
|
+
|
|
48
|
+
// Warnings (flow will run but something looks off)
|
|
49
|
+
case FLOW_VALIDATION_ERROR_TYPES.WARNING.EMPTY_FLOW:
|
|
50
|
+
return 'Empty Flow';
|
|
51
|
+
case FLOW_VALIDATION_ERROR_TYPES.WARNING.ENTRY_NODE_HAS_INCOMING_EDGES:
|
|
52
|
+
return 'Entry Node Has Incoming Edges';
|
|
53
|
+
case FLOW_VALIDATION_ERROR_TYPES.WARNING.DISCONNECTED_NODE:
|
|
54
|
+
return 'Disconnected Node';
|
|
55
|
+
case FLOW_VALIDATION_ERROR_TYPES.WARNING.DUPLICATE_EDGE:
|
|
56
|
+
return 'Duplicate Edge';
|
|
57
|
+
|
|
58
|
+
// Generic fallback
|
|
59
|
+
default:
|
|
60
|
+
return 'Validation Issue';
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<div className={`bg-background border-l border-b h-full border-border p-4 ${className}`}>
|
|
66
|
+
<div className="mb-4">
|
|
67
|
+
<h3 className="text-lg font-semibold text-foreground">Flow Validation</h3>
|
|
68
|
+
<div className="text-sm text-muted-foreground">
|
|
69
|
+
{hasErrors && (
|
|
70
|
+
<span className="font-medium text-red-600">
|
|
71
|
+
{validationResult.isValid ? 0 : validationResult.errors.length} error
|
|
72
|
+
{validationResult.isValid ? 's' : validationResult.errors.length !== 1 ? 's' : ''}
|
|
73
|
+
</span>
|
|
74
|
+
)}
|
|
75
|
+
{hasErrors && hasWarnings && <span className="mx-2">•</span>}
|
|
76
|
+
{hasWarnings && (
|
|
77
|
+
<span className="font-medium text-yellow-600">
|
|
78
|
+
{validationResult.warnings?.length || 0} warning
|
|
79
|
+
{(validationResult.warnings?.length || 0) !== 1 ? 's' : ''}
|
|
80
|
+
</span>
|
|
81
|
+
)}
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div className="space-y-3">
|
|
86
|
+
{/* Errors */}
|
|
87
|
+
{!validationResult.isValid &&
|
|
88
|
+
validationResult.errors.map((error, index) => (
|
|
89
|
+
<ValidationItem
|
|
90
|
+
key={`error-${index}`}
|
|
91
|
+
error={error}
|
|
92
|
+
icon={getErrorIcon(error)}
|
|
93
|
+
typeLabel={getErrorTypeLabel(error.type)}
|
|
94
|
+
/>
|
|
95
|
+
))}
|
|
96
|
+
|
|
97
|
+
{/* Warnings */}
|
|
98
|
+
{validationResult.warnings?.map((warning, index) => (
|
|
99
|
+
<ValidationItem
|
|
100
|
+
key={`warning-${index}`}
|
|
101
|
+
error={warning}
|
|
102
|
+
icon={getErrorIcon(warning)}
|
|
103
|
+
typeLabel={getErrorTypeLabel(warning.type)}
|
|
104
|
+
/>
|
|
105
|
+
))}
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
interface ValidationItemProps {
|
|
112
|
+
error: FlowValidationError | FlowValidationWarning;
|
|
113
|
+
icon: React.ReactNode;
|
|
114
|
+
typeLabel: string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function ValidationItem({ error, icon, typeLabel }: ValidationItemProps) {
|
|
118
|
+
const severityClass =
|
|
119
|
+
error.severity === 'error'
|
|
120
|
+
? 'border-destructive/20 bg-destructive/5'
|
|
121
|
+
: 'border-border bg-muted/50';
|
|
122
|
+
|
|
123
|
+
return (
|
|
124
|
+
<div className={`border rounded-lg p-3 ${severityClass}`}>
|
|
125
|
+
<div className="flex items-start space-x-2">
|
|
126
|
+
<div className="flex-shrink-0 mt-0.5">{icon}</div>
|
|
127
|
+
<div className="flex-1 min-w-0">
|
|
128
|
+
<div className="text-sm font-medium text-foreground">{typeLabel}</div>
|
|
129
|
+
<div className="mt-1 text-sm text-muted-foreground">{error.message}</div>
|
|
130
|
+
|
|
131
|
+
{/* Additional context information */}
|
|
132
|
+
{'nodeId' in error && error.nodeId && (
|
|
133
|
+
<div className="mt-2 text-xs text-muted-foreground">
|
|
134
|
+
Node: {formatNodeId(error.nodeId)}
|
|
135
|
+
</div>
|
|
136
|
+
)}
|
|
137
|
+
{'sourceNodeId' in error &&
|
|
138
|
+
'targetNodeId' in error &&
|
|
139
|
+
error.sourceNodeId &&
|
|
140
|
+
error.targetNodeId ? (
|
|
141
|
+
<div className="mt-1 text-xs text-muted-foreground">
|
|
142
|
+
Connection: {formatNodeId(error.sourceNodeId)} → {formatNodeId(error.targetNodeId)}
|
|
143
|
+
</div>
|
|
144
|
+
) : null}
|
|
145
|
+
|
|
146
|
+
{/* Show additional edges for multiple inputs */}
|
|
147
|
+
{error.additionalContext &&
|
|
148
|
+
'additionalEdgeIds' in error.additionalContext &&
|
|
149
|
+
error.additionalContext.additionalEdgeIds ? (
|
|
150
|
+
<div className="mt-1 text-xs text-muted-foreground">
|
|
151
|
+
Additional edges: {(error.additionalContext.additionalEdgeIds as string[]).join(', ')}
|
|
152
|
+
</div>
|
|
153
|
+
) : null}
|
|
154
|
+
|
|
155
|
+
{/* Show cycle path for circular dependencies */}
|
|
156
|
+
{error.additionalContext &&
|
|
157
|
+
'cyclePath' in error.additionalContext &&
|
|
158
|
+
error.additionalContext.cyclePath ? (
|
|
159
|
+
<div className="mt-1 text-xs text-muted-foreground">
|
|
160
|
+
Cycle: {(error.additionalContext.cyclePath as string[]).join(' → ')}
|
|
161
|
+
</div>
|
|
162
|
+
) : null}
|
|
163
|
+
</div>
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { FlowEditor } from './FlowEditor';
|
|
2
|
+
export type { FlowEditorProps } from './FlowEditor';
|
|
3
|
+
export { FlowWorkbenchView } from './FlowEditor';
|
|
4
|
+
export { NodeSidebar, type SidebarMode, type NodeSidebarProps } from './NodeSidebar';
|
|
5
|
+
export { ActionsSidebar } from './ActionsSidebar';
|
|
6
|
+
export { useFlowEditorStore, useIsLoading } from './flow-editor.store';
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { useState, useRef, useEffect } from 'react';
|
|
2
|
+
import { Input } from '../ui/input';
|
|
3
|
+
import { Button } from '../ui/button';
|
|
4
|
+
import { Pencil, Check, X } from 'lucide-react';
|
|
5
|
+
import { cn } from '../../lib/utils';
|
|
6
|
+
|
|
7
|
+
interface InlineEditProps {
|
|
8
|
+
value: string;
|
|
9
|
+
onChange: (value: string) => void;
|
|
10
|
+
placeholder?: string;
|
|
11
|
+
className?: string;
|
|
12
|
+
displayClassName?: string;
|
|
13
|
+
inputClassName?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function InlineEdit({
|
|
17
|
+
value,
|
|
18
|
+
onChange,
|
|
19
|
+
placeholder = 'Enter text',
|
|
20
|
+
className,
|
|
21
|
+
displayClassName,
|
|
22
|
+
inputClassName,
|
|
23
|
+
}: InlineEditProps) {
|
|
24
|
+
const [isEditing, setIsEditing] = useState(false);
|
|
25
|
+
const [editValue, setEditValue] = useState(value);
|
|
26
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
27
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
28
|
+
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
setEditValue(value);
|
|
31
|
+
}, [value]);
|
|
32
|
+
|
|
33
|
+
useEffect(() => {
|
|
34
|
+
if (isEditing && inputRef.current) {
|
|
35
|
+
inputRef.current.focus();
|
|
36
|
+
inputRef.current.select();
|
|
37
|
+
}
|
|
38
|
+
}, [isEditing]);
|
|
39
|
+
|
|
40
|
+
useEffect(() => {
|
|
41
|
+
const handleClickOutside = (event: MouseEvent) => {
|
|
42
|
+
if (containerRef.current && !containerRef.current.contains(event.target as Node)) {
|
|
43
|
+
if (isEditing) {
|
|
44
|
+
handleCancel();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
document.addEventListener('mousedown', handleClickOutside);
|
|
50
|
+
return () => {
|
|
51
|
+
document.removeEventListener('mousedown', handleClickOutside);
|
|
52
|
+
};
|
|
53
|
+
}, [isEditing]);
|
|
54
|
+
|
|
55
|
+
const handleSave = () => {
|
|
56
|
+
if (editValue.trim()) {
|
|
57
|
+
onChange(editValue.trim());
|
|
58
|
+
setIsEditing(false);
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const handleCancel = () => {
|
|
63
|
+
setEditValue(value);
|
|
64
|
+
setIsEditing(false);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
68
|
+
if (e.key === 'Enter') {
|
|
69
|
+
handleSave();
|
|
70
|
+
} else if (e.key === 'Escape') {
|
|
71
|
+
handleCancel();
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
if (isEditing) {
|
|
76
|
+
return (
|
|
77
|
+
<div ref={containerRef} className={cn('flex items-center gap-2 max-w-md', className)}>
|
|
78
|
+
<Input
|
|
79
|
+
ref={inputRef}
|
|
80
|
+
value={editValue}
|
|
81
|
+
onChange={(e) => setEditValue(e.target.value)}
|
|
82
|
+
onKeyDown={handleKeyDown}
|
|
83
|
+
placeholder={placeholder}
|
|
84
|
+
className={cn('h-9', inputClassName)}
|
|
85
|
+
/>
|
|
86
|
+
<Button size="icon" variant="ghost" className="h-9 w-9 shrink-0" onClick={handleSave}>
|
|
87
|
+
<Check className="w-4 h-4" />
|
|
88
|
+
</Button>
|
|
89
|
+
<Button size="icon" variant="ghost" className="h-9 w-9 shrink-0" onClick={handleCancel}>
|
|
90
|
+
<X className="w-4 h-4" />
|
|
91
|
+
</Button>
|
|
92
|
+
</div>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return (
|
|
97
|
+
<div ref={containerRef} className={cn('flex items-center gap-2 group', className)}>
|
|
98
|
+
<span className={cn('cursor-pointer', displayClassName)} onClick={() => setIsEditing(true)}>
|
|
99
|
+
{value || placeholder}
|
|
100
|
+
</span>
|
|
101
|
+
<Button
|
|
102
|
+
size="icon"
|
|
103
|
+
variant="ghost"
|
|
104
|
+
className="w-8 h-8 shrink-0"
|
|
105
|
+
onClick={() => setIsEditing(true)}
|
|
106
|
+
>
|
|
107
|
+
<Pencil className="w-4 h-4" />
|
|
108
|
+
</Button>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
import { Label } from '../../ui/label';
|
|
2
|
+
import { Input } from '../../ui/input';
|
|
3
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../../ui/select';
|
|
4
|
+
import { Switch } from '../../ui/switch';
|
|
5
|
+
import { Button } from '../../ui/button';
|
|
6
|
+
import { Code2, Type, AlertCircle } from 'lucide-react';
|
|
7
|
+
import type { NodeParamField } from '../../../types/node-definition.types';
|
|
8
|
+
import { cn } from '../../../lib/utils';
|
|
9
|
+
import { DroppableInput } from './DroppableInput';
|
|
10
|
+
import { DynamicSelectField } from './DynamicSelectField';
|
|
11
|
+
import { SearchableSelectField } from './SearchableSelectField';
|
|
12
|
+
import { CodeMirrorJsEditor } from '../../ui/codemirror-js-editor';
|
|
13
|
+
import { SwitchCasesField } from './SwitchCasesField';
|
|
14
|
+
import { useFlowEditorStore } from '../flow-editor.store';
|
|
15
|
+
|
|
16
|
+
interface ConfigFieldWithTemplateProps {
|
|
17
|
+
field: NodeParamField;
|
|
18
|
+
value: unknown;
|
|
19
|
+
onChange: (value: unknown) => void;
|
|
20
|
+
templateMode: boolean;
|
|
21
|
+
onTemplateModeChange: (enabled: boolean) => void;
|
|
22
|
+
portalContainer?: HTMLElement | null;
|
|
23
|
+
/** Action / node type id — needed for dynamic option loading. */
|
|
24
|
+
nodeType?: string;
|
|
25
|
+
/** All current form values — needed for dynamic option loading. */
|
|
26
|
+
formValues?: Record<string, unknown>;
|
|
27
|
+
/** Input data from upstream nodes — used for autocomplete in code fields. */
|
|
28
|
+
inputData?: Record<string, unknown>;
|
|
29
|
+
/** Validation error message for this field (from execution errors). */
|
|
30
|
+
error?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Field types that are always in template mode (text-based inputs).
|
|
35
|
+
* These fields don't show a toggle - they always accept Nunjucks templates.
|
|
36
|
+
*/
|
|
37
|
+
const ALWAYS_TEMPLATE_TYPES = ['text', 'textarea', 'json', 'code'];
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Check if a field type should always be in template mode.
|
|
41
|
+
*/
|
|
42
|
+
function isAlwaysTemplateType(fieldType: string): boolean {
|
|
43
|
+
return ALWAYS_TEMPLATE_TYPES.includes(fieldType);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* A config field that supports toggling between static mode (normal form element)
|
|
48
|
+
* and template mode (Nunjucks template textarea).
|
|
49
|
+
*
|
|
50
|
+
* Text-based fields (text, textarea, json, code) are always in template mode.
|
|
51
|
+
* Other fields (select, number, boolean) show a toggle to switch between modes.
|
|
52
|
+
*/
|
|
53
|
+
export const ConfigFieldWithTemplate = ({
|
|
54
|
+
field,
|
|
55
|
+
value,
|
|
56
|
+
onChange,
|
|
57
|
+
templateMode,
|
|
58
|
+
onTemplateModeChange,
|
|
59
|
+
portalContainer,
|
|
60
|
+
nodeType,
|
|
61
|
+
formValues,
|
|
62
|
+
inputData,
|
|
63
|
+
error,
|
|
64
|
+
}: ConfigFieldWithTemplateProps) => {
|
|
65
|
+
if (field.hidden) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const fieldError = error ? (
|
|
70
|
+
<div className="flex items-center gap-1 text-[11px] text-destructive mt-0.5">
|
|
71
|
+
<AlertCircle className="w-3 h-3 shrink-0" />
|
|
72
|
+
<span>{error}</span>
|
|
73
|
+
</div>
|
|
74
|
+
) : null;
|
|
75
|
+
|
|
76
|
+
// Switch cases: custom field with its own rendering
|
|
77
|
+
if (field.type === 'switch-cases') {
|
|
78
|
+
const selectedNodeId = useFlowEditorStore.getState().selectedNodeId;
|
|
79
|
+
return (
|
|
80
|
+
<SwitchCasesField
|
|
81
|
+
value={value}
|
|
82
|
+
onChange={onChange as (value: unknown) => void}
|
|
83
|
+
nodeId={selectedNodeId}
|
|
84
|
+
inputData={inputData}
|
|
85
|
+
/>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Check if this field type is always in template mode
|
|
90
|
+
const alwaysTemplate = isAlwaysTemplateType(field.type);
|
|
91
|
+
const effectiveTemplateMode = alwaysTemplate || templateMode;
|
|
92
|
+
|
|
93
|
+
const templateModeToggle = (
|
|
94
|
+
<Button
|
|
95
|
+
variant="ghost"
|
|
96
|
+
size="sm"
|
|
97
|
+
className={cn(
|
|
98
|
+
'h-5 px-1.5 text-[10px] gap-0.5',
|
|
99
|
+
effectiveTemplateMode ? 'text-primary' : 'text-muted-foreground',
|
|
100
|
+
)}
|
|
101
|
+
onClick={() => onTemplateModeChange(!templateMode)}
|
|
102
|
+
title={effectiveTemplateMode ? 'Switch to static value' : 'Switch to template'}
|
|
103
|
+
>
|
|
104
|
+
{effectiveTemplateMode ? (
|
|
105
|
+
<>
|
|
106
|
+
<Code2 className="w-2.5 h-2.5" />
|
|
107
|
+
<span>Template</span>
|
|
108
|
+
</>
|
|
109
|
+
) : (
|
|
110
|
+
<>
|
|
111
|
+
<Type className="w-2.5 h-2.5" />
|
|
112
|
+
<span>Static</span>
|
|
113
|
+
</>
|
|
114
|
+
)}
|
|
115
|
+
</Button>
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// Header with or without toggle based on field type
|
|
119
|
+
const fieldHeader = (
|
|
120
|
+
<div className="flex items-center justify-between">
|
|
121
|
+
<Label htmlFor={field.name} className={cn('text-xs', error && 'text-destructive')}>
|
|
122
|
+
{field.label}
|
|
123
|
+
</Label>
|
|
124
|
+
{/* Only show toggle for non-text fields */}
|
|
125
|
+
{!alwaysTemplate && templateModeToggle}
|
|
126
|
+
</div>
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// Code fields: render a JavaScript editor with syntax highlighting and autocomplete
|
|
130
|
+
if (field.type === 'code') {
|
|
131
|
+
const codeValue =
|
|
132
|
+
typeof value === 'string'
|
|
133
|
+
? value
|
|
134
|
+
: value === null || value === undefined
|
|
135
|
+
? ''
|
|
136
|
+
: typeof value === 'object'
|
|
137
|
+
? JSON.stringify(value, null, 2)
|
|
138
|
+
: String(value);
|
|
139
|
+
return (
|
|
140
|
+
<div className="flex flex-col gap-1.5">
|
|
141
|
+
{fieldHeader}
|
|
142
|
+
<CodeMirrorJsEditor
|
|
143
|
+
value={codeValue}
|
|
144
|
+
onChange={(newValue) => onChange(newValue)}
|
|
145
|
+
placeholder={field.placeholder}
|
|
146
|
+
inputData={inputData}
|
|
147
|
+
/>
|
|
148
|
+
{fieldError}
|
|
149
|
+
</div>
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Template mode: render a DroppableInput for Nunjucks templates
|
|
154
|
+
if (effectiveTemplateMode) {
|
|
155
|
+
// Determine if this should be multiline based on original field type
|
|
156
|
+
const isMultiline = field.type === 'textarea' || field.type === 'json';
|
|
157
|
+
const rows = field.type === 'json' ? 6 : field.type === 'textarea' ? 3 : 1;
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<div className={cn('flex flex-col gap-1.5', isMultiline && 'flex-1 min-h-0')}>
|
|
161
|
+
{fieldHeader}
|
|
162
|
+
<DroppableInput
|
|
163
|
+
id={field.name}
|
|
164
|
+
className={cn('text-xs font-mono', isMultiline && 'min-h-0 flex-1')}
|
|
165
|
+
multiline={isMultiline}
|
|
166
|
+
rows={rows}
|
|
167
|
+
fillAvailableHeight={isMultiline}
|
|
168
|
+
value={
|
|
169
|
+
typeof value === 'string'
|
|
170
|
+
? value
|
|
171
|
+
: value === null || value === undefined
|
|
172
|
+
? ''
|
|
173
|
+
: JSON.stringify(value, null, 2)
|
|
174
|
+
}
|
|
175
|
+
placeholder={field.placeholder || '{{ nodeId.data.variables.output.value }}'}
|
|
176
|
+
onChange={(newValue) => onChange(newValue)}
|
|
177
|
+
disabled={field.disabled}
|
|
178
|
+
/>
|
|
179
|
+
{fieldError}
|
|
180
|
+
</div>
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Static mode: render the appropriate form element based on field type
|
|
185
|
+
// (Only reached for non-text fields when not in template mode)
|
|
186
|
+
switch (field.type) {
|
|
187
|
+
case 'select': {
|
|
188
|
+
// Dynamic options: delegate to DynamicSelectField when loadOptions is present
|
|
189
|
+
if (field.loadOptions && nodeType && formValues) {
|
|
190
|
+
return (
|
|
191
|
+
<div className="flex flex-col gap-1.5">
|
|
192
|
+
{fieldHeader}
|
|
193
|
+
<DynamicSelectField
|
|
194
|
+
actionId={nodeType}
|
|
195
|
+
field={field}
|
|
196
|
+
value={value}
|
|
197
|
+
onChange={onChange}
|
|
198
|
+
formValues={formValues}
|
|
199
|
+
portalContainer={portalContainer}
|
|
200
|
+
/>
|
|
201
|
+
{fieldError}
|
|
202
|
+
</div>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const stringValue = value === undefined || value === null ? '' : String(value);
|
|
207
|
+
const optionEntries = (field.options ?? []).map((option) => ({
|
|
208
|
+
label: option.label,
|
|
209
|
+
value: String(option.value),
|
|
210
|
+
description: option.description,
|
|
211
|
+
}));
|
|
212
|
+
const hasCurrentValue = stringValue
|
|
213
|
+
? optionEntries.some((option) => option.value === stringValue)
|
|
214
|
+
: false;
|
|
215
|
+
const renderOptions =
|
|
216
|
+
hasCurrentValue || !stringValue
|
|
217
|
+
? optionEntries
|
|
218
|
+
: [{ label: stringValue, value: stringValue, description: undefined }, ...optionEntries];
|
|
219
|
+
|
|
220
|
+
const hasDescriptions = renderOptions.some((o) => o.description);
|
|
221
|
+
|
|
222
|
+
// Use searchable combobox for selects with many options (e.g. model lists)
|
|
223
|
+
const SEARCHABLE_THRESHOLD = 10;
|
|
224
|
+
if (renderOptions.length > SEARCHABLE_THRESHOLD) {
|
|
225
|
+
return (
|
|
226
|
+
<div className="flex flex-col gap-1.5">
|
|
227
|
+
{fieldHeader}
|
|
228
|
+
<SearchableSelectField
|
|
229
|
+
id={field.name}
|
|
230
|
+
value={stringValue}
|
|
231
|
+
options={renderOptions}
|
|
232
|
+
placeholder={field.placeholder}
|
|
233
|
+
disabled={field.disabled}
|
|
234
|
+
onChange={(val) => onChange(val)}
|
|
235
|
+
/>
|
|
236
|
+
{fieldError}
|
|
237
|
+
</div>
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
<div className="flex flex-col gap-1.5">
|
|
243
|
+
{fieldHeader}
|
|
244
|
+
<Select
|
|
245
|
+
value={stringValue}
|
|
246
|
+
onValueChange={(val) => onChange(val)}
|
|
247
|
+
disabled={field.disabled}
|
|
248
|
+
>
|
|
249
|
+
<SelectTrigger id={field.name} className="font-mono text-xs">
|
|
250
|
+
<SelectValue placeholder={field.placeholder} />
|
|
251
|
+
</SelectTrigger>
|
|
252
|
+
<SelectContent className="z-[80] text-xs" container={portalContainer}>
|
|
253
|
+
{renderOptions
|
|
254
|
+
.filter((option) => option.value !== '')
|
|
255
|
+
.map((option) => (
|
|
256
|
+
<SelectItem key={option.value} value={option.value}>
|
|
257
|
+
{hasDescriptions ? (
|
|
258
|
+
<div className="flex flex-col gap-0.5 py-0.5">
|
|
259
|
+
<span className="font-medium">{option.label}</span>
|
|
260
|
+
{option.description && (
|
|
261
|
+
<span className="text-[11px] text-muted-foreground font-normal leading-tight">
|
|
262
|
+
{option.description}
|
|
263
|
+
</span>
|
|
264
|
+
)}
|
|
265
|
+
</div>
|
|
266
|
+
) : (
|
|
267
|
+
option.value
|
|
268
|
+
)}
|
|
269
|
+
</SelectItem>
|
|
270
|
+
))}
|
|
271
|
+
</SelectContent>
|
|
272
|
+
</Select>
|
|
273
|
+
{fieldError}
|
|
274
|
+
</div>
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
case 'number':
|
|
278
|
+
return (
|
|
279
|
+
<div className="flex flex-col gap-1.5">
|
|
280
|
+
{fieldHeader}
|
|
281
|
+
<Input
|
|
282
|
+
id={field.name}
|
|
283
|
+
type="number"
|
|
284
|
+
className="h-8 font-mono text-xs"
|
|
285
|
+
value={value === undefined || value === null ? '' : String(value)}
|
|
286
|
+
placeholder={field.placeholder}
|
|
287
|
+
onChange={(event) => {
|
|
288
|
+
const nextValue = event.target.value;
|
|
289
|
+
onChange(nextValue === '' ? null : Number(nextValue));
|
|
290
|
+
}}
|
|
291
|
+
disabled={field.disabled}
|
|
292
|
+
/>
|
|
293
|
+
{fieldError}
|
|
294
|
+
</div>
|
|
295
|
+
);
|
|
296
|
+
case 'boolean':
|
|
297
|
+
return (
|
|
298
|
+
<div className="flex flex-col gap-1.5">
|
|
299
|
+
{fieldHeader}
|
|
300
|
+
<div className="flex items-center gap-2 p-2 border rounded-md">
|
|
301
|
+
<Switch
|
|
302
|
+
id={field.name}
|
|
303
|
+
checked={Boolean(value)}
|
|
304
|
+
onChange={(event: React.ChangeEvent<HTMLInputElement>) =>
|
|
305
|
+
onChange(event.target.checked)
|
|
306
|
+
}
|
|
307
|
+
disabled={field.disabled}
|
|
308
|
+
/>
|
|
309
|
+
<span className="text-xs">{value ? 'Enabled' : 'Disabled'}</span>
|
|
310
|
+
</div>
|
|
311
|
+
{fieldError}
|
|
312
|
+
</div>
|
|
313
|
+
);
|
|
314
|
+
case 'credential':
|
|
315
|
+
// Credential fields show a dropdown (handled separately in CredentialsSection)
|
|
316
|
+
// Fall through to default text input for now
|
|
317
|
+
default:
|
|
318
|
+
// Fallback for any other field types
|
|
319
|
+
return (
|
|
320
|
+
<div className="flex flex-col gap-1.5">
|
|
321
|
+
{fieldHeader}
|
|
322
|
+
<DroppableInput
|
|
323
|
+
id={field.name}
|
|
324
|
+
value={(value as string) ?? ''}
|
|
325
|
+
placeholder={field.placeholder}
|
|
326
|
+
onChange={(newValue) => onChange(newValue)}
|
|
327
|
+
disabled={field.disabled}
|
|
328
|
+
className="font-mono text-xs"
|
|
329
|
+
/>
|
|
330
|
+
{fieldError}
|
|
331
|
+
</div>
|
|
332
|
+
);
|
|
333
|
+
}
|
|
334
|
+
};
|