@flowdrop/flowdrop 1.0.1 → 1.2.0
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/README.md +50 -50
- package/dist/adapters/WorkflowAdapter.d.ts +1 -1
- package/dist/adapters/WorkflowAdapter.js +25 -25
- package/dist/adapters/agentspec/AgentSpecAdapter.d.ts +2 -2
- package/dist/adapters/agentspec/AgentSpecAdapter.js +133 -122
- package/dist/adapters/agentspec/agentAdapter.d.ts +2 -2
- package/dist/adapters/agentspec/agentAdapter.js +10 -10
- package/dist/adapters/agentspec/autoLayout.d.ts +1 -1
- package/dist/adapters/agentspec/autoLayout.js +2 -2
- package/dist/adapters/agentspec/componentTypeDefaults.d.ts +1 -1
- package/dist/adapters/agentspec/componentTypeDefaults.js +120 -120
- package/dist/adapters/agentspec/defaultNodeTypes.d.ts +2 -2
- package/dist/adapters/agentspec/defaultNodeTypes.js +307 -307
- package/dist/adapters/agentspec/index.d.ts +10 -10
- package/dist/adapters/agentspec/index.js +6 -6
- package/dist/adapters/agentspec/validator.d.ts +2 -2
- package/dist/adapters/agentspec/validator.js +22 -20
- package/dist/api/enhanced-client.d.ts +3 -3
- package/dist/api/enhanced-client.js +73 -72
- package/dist/components/App.svelte +1090 -961
- package/dist/components/App.svelte.d.ts +9 -6
- package/dist/components/CanvasBanner.stories.svelte +23 -20
- package/dist/components/CanvasBanner.stories.svelte.d.ts +1 -1
- package/dist/components/CanvasBanner.svelte +52 -46
- package/dist/components/ConfigForm.svelte +1164 -1065
- package/dist/components/ConfigForm.svelte.d.ts +2 -2
- package/dist/components/ConfigModal.svelte +180 -180
- package/dist/components/ConfigModal.svelte.d.ts +1 -1
- package/dist/components/ConfigPanel.stories.svelte +35 -35
- package/dist/components/ConfigPanel.stories.svelte.d.ts +1 -1
- package/dist/components/ConfigPanel.svelte +178 -167
- package/dist/components/ConfigPanel.svelte.d.ts +1 -1
- package/dist/components/ConnectionLine.svelte +25 -25
- package/dist/components/EdgeRefresher.svelte +26 -26
- package/dist/components/FlowDropEdge.stories.svelte +179 -143
- package/dist/components/FlowDropEdge.svelte +147 -147
- package/dist/components/FlowDropEdge.svelte.d.ts +1 -1
- package/dist/components/FlowDropZone.svelte +63 -60
- package/dist/components/FlowDropZone.svelte.d.ts +1 -1
- package/dist/components/LoadingSpinner.stories.svelte +19 -19
- package/dist/components/LoadingSpinner.stories.svelte.d.ts +1 -1
- package/dist/components/LoadingSpinner.svelte +21 -21
- package/dist/components/LoadingSpinner.svelte.d.ts +1 -1
- package/dist/components/Logo.stories.svelte +13 -13
- package/dist/components/Logo.stories.svelte.d.ts +1 -1
- package/dist/components/Logo.svelte +101 -95
- package/dist/components/LogsSidebar.svelte +553 -546
- package/dist/components/LogsSidebar.svelte.d.ts +1 -1
- package/dist/components/MarkdownDisplay.stories.svelte +29 -23
- package/dist/components/MarkdownDisplay.stories.svelte.d.ts +1 -1
- package/dist/components/MarkdownDisplay.svelte +16 -14
- package/dist/components/Navbar.stories.svelte +43 -38
- package/dist/components/Navbar.stories.svelte.d.ts +1 -1
- package/dist/components/Navbar.svelte +760 -706
- package/dist/components/Navbar.svelte.d.ts +1 -1
- package/dist/components/NodeSidebar.svelte +905 -746
- package/dist/components/NodeSidebar.svelte.d.ts +5 -1
- package/dist/components/NodeStatusOverlay.stories.svelte +82 -70
- package/dist/components/NodeStatusOverlay.stories.svelte.d.ts +1 -1
- package/dist/components/NodeStatusOverlay.svelte +295 -280
- package/dist/components/NodeStatusOverlay.svelte.d.ts +3 -3
- package/dist/components/PipelineStatus.svelte +326 -300
- package/dist/components/PipelineStatus.svelte.d.ts +4 -4
- package/dist/components/PortCoordinateTracker.svelte +49 -47
- package/dist/components/PortCoordinateTracker.svelte.d.ts +1 -1
- package/dist/components/ReadOnlyDetails.svelte +156 -156
- package/dist/components/SchemaForm.stories.svelte +106 -98
- package/dist/components/SchemaForm.stories.svelte.d.ts +1 -1
- package/dist/components/SchemaForm.svelte +490 -463
- package/dist/components/SchemaForm.svelte.d.ts +2 -2
- package/dist/components/SettingsModal.svelte +226 -223
- package/dist/components/SettingsModal.svelte.d.ts +1 -1
- package/dist/components/SettingsPanel.svelte +637 -601
- package/dist/components/SettingsPanel.svelte.d.ts +1 -1
- package/dist/components/StatusIcon.stories.svelte +62 -49
- package/dist/components/StatusIcon.stories.svelte.d.ts +1 -1
- package/dist/components/StatusIcon.svelte +87 -87
- package/dist/components/StatusIcon.svelte.d.ts +2 -2
- package/dist/components/StatusLabel.stories.svelte +12 -12
- package/dist/components/StatusLabel.stories.svelte.d.ts +1 -1
- package/dist/components/StatusLabel.svelte +19 -19
- package/dist/components/ThemeToggle.stories.svelte +16 -16
- package/dist/components/ThemeToggle.stories.svelte.d.ts +1 -1
- package/dist/components/ThemeToggle.svelte +180 -169
- package/dist/components/ThemeToggle.svelte.d.ts +1 -1
- package/dist/components/UniversalNode.svelte +150 -138
- package/dist/components/UniversalNode.svelte.d.ts +3 -3
- package/dist/components/WorkflowEditor.svelte +1069 -1014
- package/dist/components/WorkflowEditor.svelte.d.ts +4 -4
- package/dist/components/form/FormArray.svelte +1034 -973
- package/dist/components/form/FormArray.svelte.d.ts +1 -1
- package/dist/components/form/FormAutocomplete.svelte +1021 -978
- package/dist/components/form/FormAutocomplete.svelte.d.ts +1 -1
- package/dist/components/form/FormCheckboxGroup.stories.svelte +23 -20
- package/dist/components/form/FormCheckboxGroup.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormCheckboxGroup.svelte +136 -136
- package/dist/components/form/FormCodeEditor.svelte +452 -434
- package/dist/components/form/FormField.svelte +366 -355
- package/dist/components/form/FormField.svelte.d.ts +2 -2
- package/dist/components/form/FormFieldLight.svelte +400 -384
- package/dist/components/form/FormFieldLight.svelte.d.ts +1 -1
- package/dist/components/form/FormFieldWrapper.stories.svelte +42 -42
- package/dist/components/form/FormFieldWrapper.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormFieldWrapper.svelte +100 -93
- package/dist/components/form/FormFieldWrapper.svelte.d.ts +1 -1
- package/dist/components/form/FormFieldset.svelte +108 -108
- package/dist/components/form/FormFieldset.svelte.d.ts +2 -2
- package/dist/components/form/FormMarkdownEditor.svelte +758 -725
- package/dist/components/form/FormNumberField.stories.svelte +25 -25
- package/dist/components/form/FormNumberField.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormNumberField.svelte +88 -88
- package/dist/components/form/FormRangeField.stories.svelte +20 -20
- package/dist/components/form/FormRangeField.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormRangeField.svelte +234 -226
- package/dist/components/form/FormSelect.stories.svelte +38 -38
- package/dist/components/form/FormSelect.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormSelect.svelte +101 -101
- package/dist/components/form/FormSelect.svelte.d.ts +1 -1
- package/dist/components/form/FormTemplateEditor.svelte +847 -798
- package/dist/components/form/FormTemplateEditor.svelte.d.ts +1 -1
- package/dist/components/form/FormTextField.stories.svelte +29 -23
- package/dist/components/form/FormTextField.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormTextField.svelte +68 -68
- package/dist/components/form/FormTextarea.stories.svelte +28 -25
- package/dist/components/form/FormTextarea.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormTextarea.svelte +74 -74
- package/dist/components/form/FormToggle.stories.svelte +23 -20
- package/dist/components/form/FormToggle.stories.svelte.d.ts +1 -1
- package/dist/components/form/FormToggle.svelte +98 -98
- package/dist/components/form/FormUISchemaRenderer.svelte +120 -113
- package/dist/components/form/FormUISchemaRenderer.svelte.d.ts +3 -3
- package/dist/components/form/index.d.ts +19 -19
- package/dist/components/form/index.js +18 -18
- package/dist/components/form/templateAutocomplete.d.ts +2 -2
- package/dist/components/form/templateAutocomplete.js +64 -55
- package/dist/components/form/types.d.ts +6 -6
- package/dist/components/form/types.js +9 -4
- package/dist/components/icons/AlertCircleIcon.svelte +11 -0
- package/dist/components/icons/AlertCircleIcon.svelte.d.ts +26 -0
- package/dist/components/icons/CogIcon.svelte +11 -0
- package/dist/components/icons/CogIcon.svelte.d.ts +26 -0
- package/dist/components/interrupt/ChoicePrompt.stories.svelte +54 -38
- package/dist/components/interrupt/ChoicePrompt.stories.svelte.d.ts +1 -1
- package/dist/components/interrupt/ChoicePrompt.svelte +407 -383
- package/dist/components/interrupt/ChoicePrompt.svelte.d.ts +1 -1
- package/dist/components/interrupt/ConfirmationPrompt.stories.svelte +48 -48
- package/dist/components/interrupt/ConfirmationPrompt.stories.svelte.d.ts +1 -1
- package/dist/components/interrupt/ConfirmationPrompt.svelte +280 -274
- package/dist/components/interrupt/ConfirmationPrompt.svelte.d.ts +1 -1
- package/dist/components/interrupt/FormPrompt.svelte +223 -218
- package/dist/components/interrupt/FormPrompt.svelte.d.ts +1 -1
- package/dist/components/interrupt/InterruptBubble.svelte +617 -583
- package/dist/components/interrupt/InterruptBubble.svelte.d.ts +2 -2
- package/dist/components/interrupt/ReviewPrompt.stories.svelte +66 -56
- package/dist/components/interrupt/ReviewPrompt.stories.svelte.d.ts +1 -1
- package/dist/components/interrupt/ReviewPrompt.svelte +861 -841
- package/dist/components/interrupt/ReviewPrompt.svelte.d.ts +1 -1
- package/dist/components/interrupt/TextInputPrompt.stories.svelte +38 -33
- package/dist/components/interrupt/TextInputPrompt.stories.svelte.d.ts +1 -1
- package/dist/components/interrupt/TextInputPrompt.svelte +333 -328
- package/dist/components/interrupt/TextInputPrompt.svelte.d.ts +1 -1
- package/dist/components/interrupt/index.d.ts +5 -5
- package/dist/components/interrupt/index.js +5 -5
- package/dist/components/layouts/MainLayout.svelte +724 -691
- package/dist/components/layouts/MainLayout.svelte.d.ts +6 -6
- package/dist/components/nodes/GatewayNode.stories.svelte +100 -99
- package/dist/components/nodes/GatewayNode.svelte +605 -571
- package/dist/components/nodes/GatewayNode.svelte.d.ts +3 -3
- package/dist/components/nodes/IdeaNode.stories.svelte +44 -43
- package/dist/components/nodes/IdeaNode.svelte +451 -437
- package/dist/components/nodes/IdeaNode.svelte.d.ts +1 -1
- package/dist/components/nodes/NotesNode.stories.svelte +65 -64
- package/dist/components/nodes/NotesNode.svelte +380 -369
- package/dist/components/nodes/NotesNode.svelte.d.ts +1 -1
- package/dist/components/nodes/SimpleNode.stories.svelte +145 -144
- package/dist/components/nodes/SimpleNode.svelte +486 -424
- package/dist/components/nodes/SimpleNode.svelte.d.ts +1 -1
- package/dist/components/nodes/SquareNode.stories.svelte +73 -73
- package/dist/components/nodes/SquareNode.svelte +439 -380
- package/dist/components/nodes/SquareNode.svelte.d.ts +1 -1
- package/dist/components/nodes/TerminalNode.stories.svelte +13 -13
- package/dist/components/nodes/TerminalNode.svelte +709 -670
- package/dist/components/nodes/TerminalNode.svelte.d.ts +1 -1
- package/dist/components/nodes/ToolNode.stories.svelte +181 -180
- package/dist/components/nodes/ToolNode.svelte +505 -447
- package/dist/components/nodes/ToolNode.svelte.d.ts +1 -1
- package/dist/components/nodes/WorkflowNode.stories.svelte +70 -46
- package/dist/components/nodes/WorkflowNode.svelte +621 -551
- package/dist/components/nodes/WorkflowNode.svelte.d.ts +3 -3
- package/dist/components/playground/ChatPanel.svelte +945 -889
- package/dist/components/playground/ExecutionLogs.svelte +495 -472
- package/dist/components/playground/InputCollector.svelte +449 -428
- package/dist/components/playground/MessageBubble.stories.svelte +47 -47
- package/dist/components/playground/MessageBubble.stories.svelte.d.ts +1 -1
- package/dist/components/playground/MessageBubble.svelte +626 -610
- package/dist/components/playground/MessageBubble.svelte.d.ts +1 -1
- package/dist/components/playground/Playground.svelte +1088 -1057
- package/dist/components/playground/Playground.svelte.d.ts +3 -3
- package/dist/components/playground/PlaygroundModal.svelte +208 -204
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -3
- package/dist/components/playground/SessionManager.svelte +527 -521
- package/dist/components/playground/SessionManager.svelte.d.ts +1 -1
- package/dist/config/agentSpecEndpoints.d.ts +1 -1
- package/dist/config/agentSpecEndpoints.js +20 -20
- package/dist/config/constants.js +2 -2
- package/dist/config/defaultCategories.d.ts +1 -1
- package/dist/config/defaultCategories.js +86 -86
- package/dist/config/defaultPortConfig.d.ts +1 -1
- package/dist/config/defaultPortConfig.js +144 -144
- package/dist/config/endpoints.d.ts +4 -4
- package/dist/config/endpoints.js +65 -65
- package/dist/config/runtimeConfig.d.ts +2 -2
- package/dist/config/runtimeConfig.js +8 -8
- package/dist/core/index.d.ts +63 -59
- package/dist/core/index.js +35 -33
- package/dist/display/index.d.ts +2 -2
- package/dist/display/index.js +2 -2
- package/dist/editor/index.d.ts +62 -62
- package/dist/editor/index.js +53 -53
- package/dist/form/code.d.ts +5 -5
- package/dist/form/code.js +14 -14
- package/dist/form/fieldRegistry.d.ts +3 -3
- package/dist/form/fieldRegistry.js +11 -9
- package/dist/form/full.d.ts +8 -8
- package/dist/form/full.js +9 -9
- package/dist/form/index.d.ts +18 -18
- package/dist/form/index.js +16 -16
- package/dist/form/markdown.d.ts +4 -4
- package/dist/form/markdown.js +8 -8
- package/dist/helpers/proximityConnect.d.ts +3 -3
- package/dist/helpers/proximityConnect.js +34 -32
- package/dist/helpers/workflowEditorHelper.d.ts +5 -5
- package/dist/helpers/workflowEditorHelper.js +108 -96
- package/dist/index.d.ts +6 -6
- package/dist/index.js +6 -6
- package/dist/mocks/app-environment.js +2 -2
- package/dist/mocks/app-forms.js +9 -9
- package/dist/mocks/app-navigation.js +11 -11
- package/dist/mocks/app-stores.js +8 -8
- package/dist/playground/index.d.ts +19 -19
- package/dist/playground/index.js +16 -16
- package/dist/playground/mount.d.ts +3 -3
- package/dist/playground/mount.js +24 -24
- package/dist/registry/builtinFormats.js +13 -13
- package/dist/registry/builtinNodes.d.ts +2 -2
- package/dist/registry/builtinNodes.js +77 -77
- package/dist/registry/index.d.ts +4 -4
- package/dist/registry/index.js +4 -4
- package/dist/registry/nodeComponentRegistry.d.ts +8 -8
- package/dist/registry/nodeComponentRegistry.js +11 -9
- package/dist/registry/plugin.d.ts +2 -2
- package/dist/registry/plugin.js +11 -11
- package/dist/registry/workflowFormatRegistry.d.ts +3 -3
- package/dist/registry/workflowFormatRegistry.js +2 -2
- package/dist/schema/index.d.ts +1 -1
- package/dist/schema/index.js +2 -2
- package/dist/services/agentSpecExecutionService.d.ts +3 -3
- package/dist/services/agentSpecExecutionService.js +59 -55
- package/dist/services/api.d.ts +2 -2
- package/dist/services/api.js +37 -37
- package/dist/services/apiVariableService.d.ts +1 -1
- package/dist/services/apiVariableService.js +41 -34
- package/dist/services/autoSaveService.js +8 -8
- package/dist/services/categoriesApi.d.ts +2 -2
- package/dist/services/categoriesApi.js +8 -8
- package/dist/services/draftStorage.d.ts +1 -1
- package/dist/services/draftStorage.js +11 -11
- package/dist/services/dynamicSchemaService.d.ts +1 -1
- package/dist/services/dynamicSchemaService.js +41 -39
- package/dist/services/globalSave.d.ts +2 -2
- package/dist/services/globalSave.js +41 -38
- package/dist/services/historyService.d.ts +1 -1
- package/dist/services/historyService.js +8 -8
- package/dist/services/interruptService.d.ts +1 -1
- package/dist/services/interruptService.js +35 -29
- package/dist/services/nodeExecutionService.d.ts +1 -1
- package/dist/services/nodeExecutionService.js +45 -44
- package/dist/services/playgroundService.d.ts +1 -1
- package/dist/services/playgroundService.js +29 -29
- package/dist/services/portConfigApi.d.ts +2 -2
- package/dist/services/portConfigApi.js +8 -8
- package/dist/services/settingsService.d.ts +2 -2
- package/dist/services/settingsService.js +25 -19
- package/dist/services/toastService.d.ts +4 -4
- package/dist/services/toastService.js +33 -33
- package/dist/services/variableService.d.ts +1 -1
- package/dist/services/variableService.js +36 -36
- package/dist/services/workflowStorage.d.ts +2 -2
- package/dist/services/workflowStorage.js +13 -13
- package/dist/settings/index.d.ts +7 -7
- package/dist/settings/index.js +6 -6
- package/dist/skins/default.d.ts +2 -0
- package/dist/skins/default.js +1 -0
- package/dist/skins/index.d.ts +13 -0
- package/dist/skins/index.js +30 -0
- package/dist/skins/slate.d.ts +2 -0
- package/dist/skins/slate.js +78 -0
- package/dist/stores/categoriesStore.svelte.d.ts +1 -1
- package/dist/stores/categoriesStore.svelte.js +5 -5
- package/dist/stores/editorStateMachine.svelte.d.ts +2 -2
- package/dist/stores/editorStateMachine.svelte.js +65 -33
- package/dist/stores/historyStore.svelte.d.ts +4 -4
- package/dist/stores/historyStore.svelte.js +4 -4
- package/dist/stores/interruptStore.svelte.d.ts +3 -3
- package/dist/stores/interruptStore.svelte.js +21 -21
- package/dist/stores/playgroundStore.svelte.d.ts +2 -2
- package/dist/stores/playgroundStore.svelte.js +25 -18
- package/dist/stores/portCoordinateStore.svelte.d.ts +2 -2
- package/dist/stores/portCoordinateStore.svelte.js +15 -8
- package/dist/stores/settingsStore.svelte.d.ts +2 -2
- package/dist/stores/settingsStore.svelte.js +62 -57
- package/dist/stores/workflowStore.svelte.d.ts +3 -3
- package/dist/stores/workflowStore.svelte.js +50 -47
- package/dist/stories/CanvasDecorator.svelte +35 -32
- package/dist/stories/CanvasDecorator.svelte.d.ts +2 -2
- package/dist/stories/EdgeDecorator.svelte +102 -99
- package/dist/stories/EdgeDecorator.svelte.d.ts +1 -1
- package/dist/stories/NodeDecorator.svelte +59 -53
- package/dist/stories/NodeDecorator.svelte.d.ts +1 -1
- package/dist/stories/utils.d.ts +2 -2
- package/dist/stories/utils.js +105 -67
- package/dist/styles/base.css +599 -595
- package/dist/styles/toast.css +14 -14
- package/dist/styles/tokens.css +409 -378
- package/dist/svelte-app.d.ts +12 -9
- package/dist/svelte-app.js +40 -39
- package/dist/themes/default.d.ts +2 -0
- package/dist/themes/default.js +9 -0
- package/dist/themes/index.d.ts +13 -0
- package/dist/themes/index.js +44 -0
- package/dist/themes/minimal.d.ts +2 -0
- package/dist/themes/minimal.js +11 -0
- package/dist/types/agentspec.d.ts +18 -18
- package/dist/types/agentspec.js +2 -2
- package/dist/types/auth.d.ts +1 -1
- package/dist/types/auth.js +6 -6
- package/dist/types/config.d.ts +6 -6
- package/dist/types/events.d.ts +2 -2
- package/dist/types/events.js +2 -2
- package/dist/types/index.d.ts +32 -32
- package/dist/types/index.js +6 -6
- package/dist/types/interrupt.d.ts +6 -6
- package/dist/types/interrupt.js +21 -21
- package/dist/types/interruptState.d.ts +12 -12
- package/dist/types/interruptState.js +66 -66
- package/dist/types/playground.d.ts +7 -7
- package/dist/types/playground.js +14 -14
- package/dist/types/settings.d.ts +5 -3
- package/dist/types/settings.js +25 -18
- package/dist/types/skin.d.ts +31 -0
- package/dist/types/skin.js +1 -0
- package/dist/types/theme.d.ts +35 -0
- package/dist/types/theme.js +1 -0
- package/dist/types/uischema.d.ts +4 -4
- package/dist/types/uischema.js +3 -3
- package/dist/utils/colors.d.ts +1 -1
- package/dist/utils/colors.js +97 -95
- package/dist/utils/config.d.ts +2 -2
- package/dist/utils/config.js +48 -48
- package/dist/utils/connections.d.ts +2 -2
- package/dist/utils/connections.js +15 -15
- package/dist/utils/errors.js +3 -3
- package/dist/utils/fetchWithAuth.d.ts +1 -1
- package/dist/utils/fetchWithAuth.js +2 -2
- package/dist/utils/handleIds.d.ts +2 -2
- package/dist/utils/handleIds.js +8 -8
- package/dist/utils/handlePositioning.d.ts +1 -1
- package/dist/utils/handlePositioning.js +2 -2
- package/dist/utils/icons.d.ts +1 -1
- package/dist/utils/icons.js +74 -74
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.js +7 -7
- package/dist/utils/nodeStatus.d.ts +1 -1
- package/dist/utils/nodeStatus.js +48 -48
- package/dist/utils/nodeTypes.d.ts +1 -1
- package/dist/utils/nodeTypes.js +21 -20
- package/dist/utils/nodeWrapper.d.ts +7 -7
- package/dist/utils/nodeWrapper.js +21 -19
- package/dist/utils/performanceUtils.d.ts +1 -1
- package/dist/utils/performanceUtils.js +2 -1
- package/dist/utils/sanitize.js +1 -1
- package/dist/utils/uischema.d.ts +2 -2
- package/dist/utils/uischema.js +8 -8
- package/dist/utils/validation.js +20 -8
- package/package.json +1 -1
|
@@ -18,1121 +18,1220 @@
|
|
|
18
18
|
-->
|
|
19
19
|
|
|
20
20
|
<script lang="ts">
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
21
|
+
import { setContext } from "svelte";
|
|
22
|
+
import Icon from "@iconify/svelte";
|
|
23
|
+
import type {
|
|
24
|
+
ConfigSchema,
|
|
25
|
+
WorkflowNode,
|
|
26
|
+
WorkflowEdge,
|
|
27
|
+
NodeUIExtensions,
|
|
28
|
+
ConfigEditOptions,
|
|
29
|
+
AuthProvider,
|
|
30
|
+
} from "../types/index.js";
|
|
31
|
+
import type { UISchemaElement } from "../types/uischema.js";
|
|
32
|
+
import {
|
|
33
|
+
FormField,
|
|
34
|
+
FormFieldWrapper,
|
|
35
|
+
FormToggle,
|
|
36
|
+
} from "./form/index.js";
|
|
37
|
+
import FormUISchemaRenderer from "./form/FormUISchemaRenderer.svelte";
|
|
38
|
+
import type { FieldSchema } from "./form/index.js";
|
|
39
|
+
import {
|
|
40
|
+
getEffectiveConfigEditOptions,
|
|
41
|
+
fetchDynamicSchema,
|
|
42
|
+
resolveExternalEditUrl,
|
|
43
|
+
invalidateSchemaCache,
|
|
44
|
+
type DynamicSchemaResult,
|
|
45
|
+
} from "../services/dynamicSchemaService.js";
|
|
46
|
+
import { globalSaveWorkflow } from "../services/globalSave.js";
|
|
47
|
+
import { getAvailableVariables } from "../services/variableService.js";
|
|
48
|
+
import { logger } from "../utils/logger.js";
|
|
49
|
+
|
|
50
|
+
interface Props {
|
|
51
|
+
/** Optional workflow node (if provided, schema and values are derived from it) */
|
|
52
|
+
node?: WorkflowNode;
|
|
53
|
+
/** Direct config schema (used when node is not provided) */
|
|
54
|
+
schema?: ConfigSchema;
|
|
55
|
+
/**
|
|
56
|
+
* Optional UI Schema that controls field layout and grouping.
|
|
57
|
+
* When provided, fields render according to the UISchema tree structure.
|
|
58
|
+
* When absent, falls back to node.data.metadata.uiSchema, then flat rendering.
|
|
59
|
+
* @see https://jsonforms.io/docs/uischema
|
|
60
|
+
*/
|
|
61
|
+
uiSchema?: UISchemaElement;
|
|
62
|
+
/** Direct config values (used when node is not provided) */
|
|
63
|
+
values?: Record<string, unknown>;
|
|
64
|
+
/** Whether to show UI extension settings section */
|
|
65
|
+
showUIExtensions?: boolean;
|
|
66
|
+
/** Optional workflow ID for context in external links */
|
|
67
|
+
workflowId?: string;
|
|
68
|
+
/** Whether to also save the workflow when saving config */
|
|
69
|
+
saveWorkflowWhenSavingConfig?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* All workflow nodes (used for deriving template variables from connected nodes).
|
|
72
|
+
* When provided along with workflowEdges, enables autocomplete for template fields.
|
|
73
|
+
*/
|
|
74
|
+
workflowNodes?: WorkflowNode[];
|
|
75
|
+
/**
|
|
76
|
+
* All workflow edges (used for finding connections to derive template variables).
|
|
77
|
+
* When provided along with workflowNodes, enables autocomplete for template fields.
|
|
78
|
+
*/
|
|
79
|
+
workflowEdges?: WorkflowEdge[];
|
|
80
|
+
/** Auth provider for API requests (used for template variable API mode) */
|
|
81
|
+
authProvider?: AuthProvider;
|
|
82
|
+
/** Callback when any field value changes (fired on blur for immediate sync) */
|
|
83
|
+
onChange?: (
|
|
84
|
+
config: Record<string, unknown>,
|
|
85
|
+
uiExtensions?: NodeUIExtensions,
|
|
86
|
+
) => void;
|
|
87
|
+
/** Callback when form is saved (includes both config and extensions if enabled) */
|
|
88
|
+
onSave?: (
|
|
89
|
+
config: Record<string, unknown>,
|
|
90
|
+
uiExtensions?: NodeUIExtensions,
|
|
91
|
+
) => void;
|
|
92
|
+
/** Callback when form is cancelled */
|
|
93
|
+
onCancel?: () => void;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
let {
|
|
97
|
+
node,
|
|
98
|
+
schema,
|
|
99
|
+
uiSchema,
|
|
100
|
+
values,
|
|
101
|
+
showUIExtensions = true,
|
|
102
|
+
workflowId,
|
|
103
|
+
saveWorkflowWhenSavingConfig = false,
|
|
104
|
+
workflowNodes = [],
|
|
105
|
+
workflowEdges = [],
|
|
106
|
+
authProvider,
|
|
107
|
+
onChange,
|
|
108
|
+
onSave,
|
|
109
|
+
onCancel,
|
|
110
|
+
}: Props = $props();
|
|
111
|
+
|
|
112
|
+
// Set context for child components (e.g., FormAutocomplete)
|
|
113
|
+
// Use getter functions to ensure child components always get the current prop value,
|
|
114
|
+
// even if the prop changes after initial mount
|
|
115
|
+
setContext<() => AuthProvider | undefined>(
|
|
116
|
+
"flowdrop:getAuthProvider",
|
|
117
|
+
() => authProvider,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* State for dynamic schema loading
|
|
122
|
+
*/
|
|
123
|
+
let dynamicSchemaLoading = $state(false);
|
|
124
|
+
let dynamicSchemaError = $state<string | null>(null);
|
|
125
|
+
let fetchedDynamicSchema = $state<ConfigSchema | null>(null);
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Get the admin edit configuration for the node
|
|
129
|
+
*/
|
|
130
|
+
const configEditOptions = $derived.by<ConfigEditOptions | undefined>(() => {
|
|
131
|
+
if (!node) return undefined;
|
|
132
|
+
return getEffectiveConfigEditOptions(node);
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Determine if we should show the external edit link
|
|
137
|
+
*/
|
|
138
|
+
const showExternalEditLink = $derived.by(() => {
|
|
139
|
+
if (!configEditOptions?.externalEditLink) return false;
|
|
140
|
+
// Show if no dynamic schema, or if both exist but preferDynamicSchema is false
|
|
141
|
+
if (!configEditOptions.dynamicSchema) return true;
|
|
142
|
+
return !configEditOptions.preferDynamicSchema;
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Determine if we should use/fetch dynamic schema
|
|
147
|
+
*/
|
|
148
|
+
const useDynamicSchema = $derived.by(() => {
|
|
149
|
+
if (!configEditOptions?.dynamicSchema) return false;
|
|
150
|
+
// Use if no external link, or if both exist and preferDynamicSchema is true
|
|
151
|
+
if (!configEditOptions.externalEditLink) return true;
|
|
152
|
+
return configEditOptions.preferDynamicSchema === true;
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Get the configuration schema from node metadata, direct prop, or fetched dynamic schema
|
|
157
|
+
* Priority: fetchedDynamicSchema > direct schema prop > node metadata configSchema
|
|
158
|
+
*/
|
|
159
|
+
const configSchema = $derived.by<ConfigSchema | undefined>(() => {
|
|
160
|
+
// If we have a fetched dynamic schema, use it
|
|
161
|
+
if (fetchedDynamicSchema) {
|
|
162
|
+
return fetchedDynamicSchema;
|
|
163
|
+
}
|
|
164
|
+
// Otherwise use the direct prop or node metadata
|
|
165
|
+
return (
|
|
166
|
+
schema ?? (node?.data.metadata?.configSchema as ConfigSchema | undefined)
|
|
167
|
+
);
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Get the UI schema from direct prop or node metadata
|
|
172
|
+
* Priority: direct uiSchema prop > node metadata uiSchema
|
|
173
|
+
*/
|
|
174
|
+
const configUISchema = $derived.by<UISchemaElement | undefined>(() => {
|
|
175
|
+
return (
|
|
176
|
+
uiSchema ?? (node?.data.metadata?.uiSchema as UISchemaElement | undefined)
|
|
177
|
+
);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Check if the node needs dynamic schema loading
|
|
182
|
+
* Loads when: no static schema OR preferDynamicSchema is true
|
|
183
|
+
*/
|
|
184
|
+
const needsDynamicSchemaLoad = $derived.by(() => {
|
|
185
|
+
if (!node) return false;
|
|
186
|
+
const staticSchema = schema ?? node.data.metadata?.configSchema;
|
|
187
|
+
// Need to load if: (no static schema OR preferDynamicSchema is true) AND dynamic schema is configured
|
|
188
|
+
return (
|
|
189
|
+
(!staticSchema || configEditOptions?.preferDynamicSchema === true) &&
|
|
190
|
+
useDynamicSchema &&
|
|
191
|
+
!fetchedDynamicSchema &&
|
|
192
|
+
!dynamicSchemaLoading
|
|
193
|
+
);
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Get the current configuration from node or direct prop
|
|
198
|
+
*/
|
|
199
|
+
const initialConfig = $derived(values ?? node?.data.config ?? {});
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Create reactive configuration values using $state
|
|
203
|
+
* This fixes the Svelte 5 reactivity warnings
|
|
204
|
+
*/
|
|
205
|
+
let configValues = $state<Record<string, unknown>>({});
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* UI Extension values for display settings
|
|
209
|
+
* Merges node type defaults with instance overrides
|
|
210
|
+
*/
|
|
211
|
+
let uiExtensionValues = $state<NodeUIExtensions>({});
|
|
212
|
+
|
|
213
|
+
/**
|
|
214
|
+
* Flag to track if workflow save is in progress
|
|
215
|
+
*/
|
|
216
|
+
let isSavingWorkflow = $state(false);
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Get initial UI extensions from node (instance level overrides type level)
|
|
220
|
+
*/
|
|
221
|
+
const initialUIExtensions = $derived.by<NodeUIExtensions>(() => {
|
|
222
|
+
if (!node) return {};
|
|
223
|
+
// Merge type-level defaults with instance-level overrides
|
|
224
|
+
const typeDefaults = node.data.metadata?.extensions?.ui ?? {};
|
|
225
|
+
const instanceOverrides = node.data.extensions?.ui ?? {};
|
|
226
|
+
return { ...typeDefaults, ...instanceOverrides };
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Fetch dynamic schema when needed
|
|
231
|
+
*/
|
|
232
|
+
async function loadDynamicSchema(): Promise<void> {
|
|
233
|
+
if (!node || !configEditOptions?.dynamicSchema) return;
|
|
234
|
+
|
|
235
|
+
dynamicSchemaLoading = true;
|
|
236
|
+
dynamicSchemaError = null;
|
|
237
|
+
|
|
238
|
+
try {
|
|
239
|
+
const result: DynamicSchemaResult = await fetchDynamicSchema(
|
|
240
|
+
configEditOptions.dynamicSchema,
|
|
241
|
+
node,
|
|
242
|
+
workflowId,
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
if (result.success && result.schema) {
|
|
246
|
+
fetchedDynamicSchema = result.schema;
|
|
247
|
+
} else {
|
|
248
|
+
dynamicSchemaError =
|
|
249
|
+
result.error ??
|
|
250
|
+
configEditOptions.errorMessage ??
|
|
251
|
+
"Failed to load configuration schema";
|
|
252
|
+
}
|
|
253
|
+
} catch (err) {
|
|
254
|
+
dynamicSchemaError =
|
|
255
|
+
err instanceof Error
|
|
256
|
+
? err.message
|
|
257
|
+
: (configEditOptions.errorMessage ??
|
|
258
|
+
"Failed to load configuration schema");
|
|
259
|
+
} finally {
|
|
260
|
+
dynamicSchemaLoading = false;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Refresh the dynamic schema (invalidate cache and reload)
|
|
266
|
+
*/
|
|
267
|
+
async function refreshDynamicSchema(): Promise<void> {
|
|
268
|
+
if (!node || !configEditOptions?.dynamicSchema) return;
|
|
269
|
+
|
|
270
|
+
// Invalidate the cache first
|
|
271
|
+
invalidateSchemaCache(node, configEditOptions.dynamicSchema);
|
|
272
|
+
fetchedDynamicSchema = null;
|
|
273
|
+
|
|
274
|
+
// Reload the schema
|
|
275
|
+
await loadDynamicSchema();
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Get the resolved external edit URL
|
|
280
|
+
*/
|
|
281
|
+
function getExternalEditUrl(): string {
|
|
282
|
+
if (!node || !configEditOptions?.externalEditLink) return "#";
|
|
283
|
+
return resolveExternalEditUrl(
|
|
284
|
+
configEditOptions.externalEditLink,
|
|
285
|
+
node,
|
|
286
|
+
workflowId,
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Handle opening external edit link
|
|
292
|
+
*/
|
|
293
|
+
function handleExternalEditClick(): void {
|
|
294
|
+
if (!node || !configEditOptions?.externalEditLink) return;
|
|
295
|
+
|
|
296
|
+
const url = getExternalEditUrl();
|
|
297
|
+
const openInNewTab =
|
|
298
|
+
configEditOptions.externalEditLink.openInNewTab !== false;
|
|
299
|
+
|
|
300
|
+
if (openInNewTab) {
|
|
301
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
302
|
+
} else {
|
|
303
|
+
window.location.href = url;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Auto-load dynamic schema on mount if needed
|
|
309
|
+
*/
|
|
310
|
+
$effect(() => {
|
|
311
|
+
if (needsDynamicSchemaLoad) {
|
|
312
|
+
loadDynamicSchema();
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
/**
|
|
317
|
+
* Initialize config values when node/schema changes
|
|
318
|
+
*/
|
|
319
|
+
$effect(() => {
|
|
320
|
+
if (configSchema?.properties) {
|
|
321
|
+
const mergedConfig: Record<string, unknown> = {};
|
|
322
|
+
Object.entries(configSchema.properties).forEach(([key, field]) => {
|
|
323
|
+
const fieldConfig = field as Record<string, unknown>;
|
|
324
|
+
// Use existing value if available, otherwise use default
|
|
325
|
+
mergedConfig[key] =
|
|
326
|
+
initialConfig[key] !== undefined
|
|
327
|
+
? initialConfig[key]
|
|
328
|
+
: fieldConfig.default;
|
|
329
|
+
});
|
|
330
|
+
configValues = mergedConfig;
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Initialize UI extension values when node changes
|
|
336
|
+
*/
|
|
337
|
+
$effect(() => {
|
|
338
|
+
uiExtensionValues = {
|
|
339
|
+
hideUnconnectedHandles:
|
|
340
|
+
initialUIExtensions.hideUnconnectedHandles ?? false,
|
|
341
|
+
};
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Check if a field is required based on schema
|
|
346
|
+
*/
|
|
347
|
+
function isFieldRequired(key: string): boolean {
|
|
348
|
+
if (!configSchema?.required) return false;
|
|
349
|
+
return configSchema.required.includes(key);
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Handle field value changes from FormField components
|
|
354
|
+
*/
|
|
355
|
+
function handleFieldChange(key: string, value: unknown): void {
|
|
356
|
+
configValues[key] = value;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/**
|
|
360
|
+
* Handle form field blur - sync changes to workflow immediately
|
|
361
|
+
* Uses focusout which bubbles from child elements
|
|
362
|
+
* This enables auto-save behavior without requiring explicit Save button clicks
|
|
363
|
+
*/
|
|
364
|
+
function handleFormBlur(): void {
|
|
365
|
+
if (onChange) {
|
|
366
|
+
const extensions =
|
|
367
|
+
showUIExtensions && node ? uiExtensionValues : undefined;
|
|
368
|
+
onChange({ ...configValues }, extensions);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Handle form submission
|
|
374
|
+
* Collects both config values and UI extension values
|
|
375
|
+
* Optionally saves the workflow if the option is enabled
|
|
376
|
+
*/
|
|
377
|
+
async function handleSave(): Promise<void> {
|
|
378
|
+
// Collect all form values including hidden fields
|
|
379
|
+
const form = document.querySelector(".config-form");
|
|
380
|
+
const updatedConfig: Record<string, unknown> = { ...configValues };
|
|
381
|
+
|
|
382
|
+
if (form) {
|
|
383
|
+
const inputs = form.querySelectorAll("input, select, textarea");
|
|
384
|
+
inputs.forEach((input: Element) => {
|
|
385
|
+
const inputEl = input as
|
|
386
|
+
| HTMLInputElement
|
|
387
|
+
| HTMLSelectElement
|
|
388
|
+
| HTMLTextAreaElement;
|
|
389
|
+
// Skip UI extension fields (prefixed with ext-)
|
|
390
|
+
if (inputEl.id && !inputEl.id.startsWith("ext-")) {
|
|
391
|
+
if (
|
|
392
|
+
inputEl instanceof HTMLInputElement &&
|
|
393
|
+
inputEl.type === "checkbox"
|
|
394
|
+
) {
|
|
395
|
+
updatedConfig[inputEl.id] = inputEl.checked;
|
|
396
|
+
} else if (
|
|
397
|
+
inputEl instanceof HTMLInputElement &&
|
|
398
|
+
(inputEl.type === "number" || inputEl.type === "range")
|
|
399
|
+
) {
|
|
400
|
+
updatedConfig[inputEl.id] = inputEl.value
|
|
401
|
+
? Number(inputEl.value)
|
|
402
|
+
: inputEl.value;
|
|
403
|
+
} else if (
|
|
404
|
+
inputEl instanceof HTMLInputElement &&
|
|
405
|
+
inputEl.type === "hidden"
|
|
406
|
+
) {
|
|
407
|
+
// Parse hidden field values that might be JSON
|
|
408
|
+
try {
|
|
409
|
+
const parsed = JSON.parse(inputEl.value);
|
|
410
|
+
updatedConfig[inputEl.id] = parsed;
|
|
411
|
+
} catch {
|
|
412
|
+
// If not JSON, use raw value
|
|
413
|
+
updatedConfig[inputEl.id] = inputEl.value;
|
|
414
|
+
}
|
|
415
|
+
} else {
|
|
416
|
+
updatedConfig[inputEl.id] = inputEl.value;
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
// Preserve hidden field values from original config if not collected from form
|
|
423
|
+
if (initialConfig && configSchema?.properties) {
|
|
424
|
+
Object.entries(configSchema.properties).forEach(
|
|
425
|
+
([key, property]: [string, Record<string, unknown>]) => {
|
|
426
|
+
if (
|
|
427
|
+
property.format === "hidden" &&
|
|
428
|
+
!(key in updatedConfig) &&
|
|
429
|
+
key in initialConfig
|
|
430
|
+
) {
|
|
431
|
+
updatedConfig[key] = initialConfig[key];
|
|
432
|
+
}
|
|
433
|
+
},
|
|
434
|
+
);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// Pass UI extensions only if enabled
|
|
438
|
+
if (onSave) {
|
|
439
|
+
if (showUIExtensions && node) {
|
|
440
|
+
onSave(updatedConfig, uiExtensionValues);
|
|
441
|
+
} else {
|
|
442
|
+
onSave(updatedConfig);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
// Save workflow if the option is enabled
|
|
447
|
+
if (saveWorkflowWhenSavingConfig) {
|
|
448
|
+
isSavingWorkflow = true;
|
|
449
|
+
try {
|
|
450
|
+
await globalSaveWorkflow();
|
|
451
|
+
} catch (error) {
|
|
452
|
+
logger.error("Failed to save workflow after config save:", error);
|
|
453
|
+
} finally {
|
|
454
|
+
isSavingWorkflow = false;
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/**
|
|
460
|
+
* Convert ConfigProperty to FieldSchema for FormField component.
|
|
461
|
+
* Processes template fields to inject computed variable schema.
|
|
462
|
+
*
|
|
463
|
+
* For template fields, the `variables` config controls which input ports
|
|
464
|
+
* provide variables for autocomplete.
|
|
465
|
+
*/
|
|
466
|
+
function toFieldSchema(property: Record<string, unknown>): FieldSchema {
|
|
467
|
+
const fieldSchema = property as FieldSchema;
|
|
468
|
+
|
|
469
|
+
// Process template fields to compute variable schema
|
|
470
|
+
if (
|
|
471
|
+
fieldSchema.format === "template" &&
|
|
472
|
+
node &&
|
|
473
|
+
workflowNodes.length > 0 &&
|
|
474
|
+
workflowEdges.length > 0
|
|
475
|
+
) {
|
|
476
|
+
// Get the variables config (may be undefined or partially defined)
|
|
477
|
+
const variablesConfig = fieldSchema.variables;
|
|
478
|
+
|
|
479
|
+
// Compute the variable schema with optional port filtering and port name prefixing
|
|
480
|
+
const computedSchema = getAvailableVariables(
|
|
481
|
+
node,
|
|
482
|
+
workflowNodes,
|
|
483
|
+
workflowEdges,
|
|
484
|
+
{
|
|
485
|
+
targetPortIds: variablesConfig?.ports,
|
|
486
|
+
includePortName: variablesConfig?.includePortName,
|
|
487
|
+
},
|
|
488
|
+
);
|
|
489
|
+
|
|
490
|
+
// Merge computed schema with any pre-defined schema
|
|
491
|
+
const mergedSchema = variablesConfig?.schema
|
|
492
|
+
? {
|
|
493
|
+
variables: {
|
|
494
|
+
...computedSchema.variables,
|
|
495
|
+
...variablesConfig.schema.variables,
|
|
496
|
+
},
|
|
497
|
+
}
|
|
498
|
+
: computedSchema;
|
|
499
|
+
|
|
500
|
+
return {
|
|
501
|
+
...fieldSchema,
|
|
502
|
+
variables: {
|
|
503
|
+
...variablesConfig,
|
|
504
|
+
schema: mergedSchema,
|
|
505
|
+
},
|
|
506
|
+
} as FieldSchema;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
return fieldSchema;
|
|
510
|
+
}
|
|
462
511
|
</script>
|
|
463
512
|
|
|
464
513
|
<!-- External Edit Link Section (shown when configured and preferred) -->
|
|
465
514
|
{#if showExternalEditLink && configEditOptions?.externalEditLink}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
515
|
+
<div class="config-form__admin-edit">
|
|
516
|
+
<div class="config-form__admin-edit-header">
|
|
517
|
+
<Icon icon="heroicons:arrow-top-right-on-square" />
|
|
518
|
+
<span>External Configuration</span>
|
|
519
|
+
</div>
|
|
520
|
+
<div class="config-form__admin-edit-content">
|
|
521
|
+
<p class="config-form__admin-edit-description">
|
|
522
|
+
{configEditOptions.externalEditLink.description ??
|
|
523
|
+
"This node requires external configuration. Click the button below to open the configuration panel."}
|
|
524
|
+
</p>
|
|
525
|
+
<button
|
|
526
|
+
type="button"
|
|
527
|
+
class="config-form__button config-form__button--external"
|
|
528
|
+
onclick={handleExternalEditClick}
|
|
529
|
+
>
|
|
530
|
+
<Icon
|
|
531
|
+
icon={configEditOptions.externalEditLink.icon ??
|
|
532
|
+
"heroicons:arrow-top-right-on-square"}
|
|
533
|
+
/>
|
|
534
|
+
<span
|
|
535
|
+
>{configEditOptions.externalEditLink.label ??
|
|
536
|
+
"Configure Externally"}</span
|
|
537
|
+
>
|
|
538
|
+
</button>
|
|
539
|
+
</div>
|
|
540
|
+
</div>
|
|
488
541
|
{/if}
|
|
489
542
|
|
|
490
543
|
<!-- Dynamic Schema Loading State -->
|
|
491
544
|
{#if dynamicSchemaLoading}
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
545
|
+
<div class="config-form__loading">
|
|
546
|
+
<div class="config-form__loading-spinner"></div>
|
|
547
|
+
<p class="config-form__loading-text">
|
|
548
|
+
{configEditOptions?.loadingMessage ?? "Loading configuration options..."}
|
|
549
|
+
</p>
|
|
550
|
+
</div>
|
|
498
551
|
{:else if dynamicSchemaError}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
552
|
+
<div class="config-form__error">
|
|
553
|
+
<div class="config-form__error-header">
|
|
554
|
+
<Icon icon="heroicons:exclamation-triangle" />
|
|
555
|
+
<span>Configuration Error</span>
|
|
556
|
+
</div>
|
|
557
|
+
<div class="config-form__error-content">
|
|
558
|
+
<p class="config-form__error-message">{dynamicSchemaError}</p>
|
|
559
|
+
<div class="config-form__error-actions">
|
|
560
|
+
<button
|
|
561
|
+
type="button"
|
|
562
|
+
class="config-form__button config-form__button--secondary"
|
|
563
|
+
onclick={refreshDynamicSchema}
|
|
564
|
+
>
|
|
565
|
+
<Icon icon="heroicons:arrow-path" />
|
|
566
|
+
<span>Retry</span>
|
|
567
|
+
</button>
|
|
568
|
+
{#if configEditOptions?.externalEditLink}
|
|
569
|
+
<button
|
|
570
|
+
type="button"
|
|
571
|
+
class="config-form__button config-form__button--external"
|
|
572
|
+
onclick={handleExternalEditClick}
|
|
573
|
+
>
|
|
574
|
+
<Icon
|
|
575
|
+
icon={configEditOptions.externalEditLink.icon ??
|
|
576
|
+
"heroicons:arrow-top-right-on-square"}
|
|
577
|
+
/>
|
|
578
|
+
<span
|
|
579
|
+
>{configEditOptions.externalEditLink.label ??
|
|
580
|
+
"Use External Editor"}</span
|
|
581
|
+
>
|
|
582
|
+
</button>
|
|
583
|
+
{/if}
|
|
584
|
+
</div>
|
|
585
|
+
</div>
|
|
586
|
+
</div>
|
|
531
587
|
{:else if configSchema}
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
588
|
+
<form
|
|
589
|
+
class="config-form"
|
|
590
|
+
onfocusout={handleFormBlur}
|
|
591
|
+
onsubmit={(e) => {
|
|
592
|
+
e.preventDefault();
|
|
593
|
+
}}
|
|
594
|
+
>
|
|
595
|
+
<!-- Dynamic Schema Refresh Button -->
|
|
596
|
+
{#if fetchedDynamicSchema && configEditOptions?.showRefreshButton !== false}
|
|
597
|
+
<div class="config-form__schema-actions">
|
|
598
|
+
<button
|
|
599
|
+
type="button"
|
|
600
|
+
class="config-form__schema-refresh"
|
|
601
|
+
onclick={refreshDynamicSchema}
|
|
602
|
+
title="Refresh configuration schema"
|
|
603
|
+
>
|
|
604
|
+
<Icon icon="heroicons:arrow-path" />
|
|
605
|
+
<span>Refresh Schema</span>
|
|
606
|
+
</button>
|
|
607
|
+
{#if configEditOptions?.externalEditLink}
|
|
608
|
+
<button
|
|
609
|
+
type="button"
|
|
610
|
+
class="config-form__schema-external"
|
|
611
|
+
onclick={handleExternalEditClick}
|
|
612
|
+
title={configEditOptions.externalEditLink.description ??
|
|
613
|
+
"Open external editor"}
|
|
614
|
+
>
|
|
615
|
+
<Icon
|
|
616
|
+
icon={configEditOptions.externalEditLink.icon ??
|
|
617
|
+
"heroicons:arrow-top-right-on-square"}
|
|
618
|
+
/>
|
|
619
|
+
<span
|
|
620
|
+
>{configEditOptions.externalEditLink.label ??
|
|
621
|
+
"External Editor"}</span
|
|
622
|
+
>
|
|
623
|
+
</button>
|
|
624
|
+
{/if}
|
|
625
|
+
</div>
|
|
626
|
+
{/if}
|
|
627
|
+
|
|
628
|
+
{#if configSchema.properties}
|
|
629
|
+
<div class="config-form__fields">
|
|
630
|
+
{#if configUISchema}
|
|
631
|
+
<FormUISchemaRenderer
|
|
632
|
+
element={configUISchema}
|
|
633
|
+
schema={configSchema}
|
|
634
|
+
values={configValues}
|
|
635
|
+
requiredFields={configSchema.required ?? []}
|
|
636
|
+
onFieldChange={handleFieldChange}
|
|
637
|
+
{toFieldSchema}
|
|
638
|
+
{node}
|
|
639
|
+
nodes={workflowNodes}
|
|
640
|
+
edges={workflowEdges}
|
|
641
|
+
{workflowId}
|
|
642
|
+
{authProvider}
|
|
643
|
+
/>
|
|
644
|
+
{:else}
|
|
645
|
+
{#each Object.entries(configSchema.properties) as [key, field], index (key)}
|
|
646
|
+
{@const fieldSchema = toFieldSchema(
|
|
647
|
+
field as Record<string, unknown>,
|
|
648
|
+
)}
|
|
649
|
+
{@const required = isFieldRequired(key)}
|
|
650
|
+
|
|
651
|
+
<FormField
|
|
652
|
+
fieldKey={key}
|
|
653
|
+
schema={fieldSchema}
|
|
654
|
+
value={configValues[key]}
|
|
655
|
+
{required}
|
|
656
|
+
animationIndex={index}
|
|
657
|
+
{node}
|
|
658
|
+
nodes={workflowNodes}
|
|
659
|
+
edges={workflowEdges}
|
|
660
|
+
{workflowId}
|
|
661
|
+
{authProvider}
|
|
662
|
+
onChange={(val) => handleFieldChange(key, val)}
|
|
663
|
+
/>
|
|
664
|
+
{/each}
|
|
665
|
+
{/if}
|
|
666
|
+
</div>
|
|
667
|
+
{:else}
|
|
668
|
+
<!-- If no properties, show the raw schema for debugging -->
|
|
669
|
+
<div class="config-form__debug">
|
|
670
|
+
<div class="config-form__debug-header">
|
|
671
|
+
<Icon icon="heroicons:bug-ant" class="config-form__debug-icon" />
|
|
672
|
+
<span>Debug - Config Schema</span>
|
|
673
|
+
</div>
|
|
674
|
+
<pre class="config-form__debug-content">{JSON.stringify(
|
|
675
|
+
configSchema,
|
|
676
|
+
null,
|
|
677
|
+
2,
|
|
678
|
+
)}</pre>
|
|
679
|
+
</div>
|
|
680
|
+
{/if}
|
|
681
|
+
|
|
682
|
+
<!-- UI Extensions Section -->
|
|
683
|
+
{#if showUIExtensions && node}
|
|
684
|
+
<div class="config-form__extensions">
|
|
685
|
+
<div class="config-form__extensions-header">
|
|
686
|
+
<Icon
|
|
687
|
+
icon="heroicons:adjustments-horizontal"
|
|
688
|
+
class="config-form__extensions-icon"
|
|
689
|
+
/>
|
|
690
|
+
<span>Display Settings</span>
|
|
691
|
+
</div>
|
|
692
|
+
<div class="config-form__extensions-content">
|
|
693
|
+
<!-- Hide Unconnected Handles Toggle -->
|
|
694
|
+
<FormFieldWrapper
|
|
695
|
+
id="ext-hideUnconnectedHandles"
|
|
696
|
+
label="Hide Unconnected Ports"
|
|
697
|
+
description="Hide input and output ports that are not connected to reduce visual clutter"
|
|
698
|
+
>
|
|
699
|
+
<FormToggle
|
|
700
|
+
id="ext-hideUnconnectedHandles"
|
|
701
|
+
value={Boolean(uiExtensionValues.hideUnconnectedHandles)}
|
|
702
|
+
onLabel="Hidden"
|
|
703
|
+
offLabel="Visible"
|
|
704
|
+
ariaDescribedBy="ext-hideUnconnectedHandles-description"
|
|
705
|
+
onChange={(val) => {
|
|
706
|
+
uiExtensionValues.hideUnconnectedHandles = val;
|
|
707
|
+
handleFormBlur();
|
|
708
|
+
}}
|
|
709
|
+
/>
|
|
710
|
+
</FormFieldWrapper>
|
|
711
|
+
</div>
|
|
712
|
+
</div>
|
|
713
|
+
{/if}
|
|
714
|
+
|
|
715
|
+
<!-- Footer Actions - Only shown when onSave is provided and onChange is not -->
|
|
716
|
+
<!-- With onChange (on-blur sync), changes are saved automatically, so no Save button needed -->
|
|
717
|
+
{#if onSave && !onChange}
|
|
718
|
+
<div class="config-form__footer">
|
|
719
|
+
<button
|
|
720
|
+
type="button"
|
|
721
|
+
class="config-form__button config-form__button--secondary"
|
|
722
|
+
onclick={onCancel}
|
|
723
|
+
disabled={isSavingWorkflow}
|
|
724
|
+
>
|
|
725
|
+
<Icon icon="heroicons:x-mark" class="config-form__button-icon" />
|
|
726
|
+
<span>Cancel</span>
|
|
727
|
+
</button>
|
|
728
|
+
<button
|
|
729
|
+
type="submit"
|
|
730
|
+
class="config-form__button config-form__button--primary"
|
|
731
|
+
onclick={handleSave}
|
|
732
|
+
disabled={isSavingWorkflow}
|
|
733
|
+
>
|
|
734
|
+
{#if isSavingWorkflow}
|
|
735
|
+
<span class="config-form__button-spinner"></span>
|
|
736
|
+
<span>Saving...</span>
|
|
737
|
+
{:else}
|
|
738
|
+
<Icon icon="heroicons:check" class="config-form__button-icon" />
|
|
739
|
+
<span>Save Changes</span>
|
|
740
|
+
{/if}
|
|
741
|
+
</button>
|
|
742
|
+
</div>
|
|
743
|
+
{/if}
|
|
744
|
+
</form>
|
|
676
745
|
{:else if !dynamicSchemaLoading && !showExternalEditLink}
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
746
|
+
<div class="config-form__empty">
|
|
747
|
+
<div class="config-form__empty-icon">
|
|
748
|
+
<Icon icon="heroicons:cog-6-tooth" />
|
|
749
|
+
</div>
|
|
750
|
+
<p class="config-form__empty-text">
|
|
751
|
+
No configuration options available for this node.
|
|
752
|
+
</p>
|
|
753
|
+
{#if configEditOptions?.externalEditLink}
|
|
754
|
+
<button
|
|
755
|
+
type="button"
|
|
756
|
+
class="config-form__button config-form__button--external config-form__empty-button"
|
|
757
|
+
onclick={handleExternalEditClick}
|
|
758
|
+
>
|
|
759
|
+
<Icon
|
|
760
|
+
icon={configEditOptions.externalEditLink.icon ??
|
|
761
|
+
"heroicons:arrow-top-right-on-square"}
|
|
762
|
+
/>
|
|
763
|
+
<span
|
|
764
|
+
>{configEditOptions.externalEditLink.label ??
|
|
765
|
+
"Configure Externally"}</span
|
|
766
|
+
>
|
|
767
|
+
</button>
|
|
768
|
+
{/if}
|
|
769
|
+
</div>
|
|
695
770
|
{/if}
|
|
696
771
|
|
|
697
772
|
<style>
|
|
698
|
-
|
|
773
|
+
/* ============================================
|
|
699
774
|
CONFIG FORM - Container Styles
|
|
700
775
|
Individual field styles are in form/ components
|
|
701
776
|
============================================ */
|
|
702
777
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
778
|
+
.config-form {
|
|
779
|
+
display: flex;
|
|
780
|
+
flex-direction: column;
|
|
781
|
+
gap: var(--fd-space-3xl);
|
|
782
|
+
}
|
|
708
783
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
784
|
+
.config-form__fields {
|
|
785
|
+
display: flex;
|
|
786
|
+
flex-direction: column;
|
|
787
|
+
gap: var(--fd-space-2xl);
|
|
788
|
+
}
|
|
714
789
|
|
|
715
|
-
|
|
790
|
+
/* ============================================
|
|
716
791
|
FOOTER ACTIONS
|
|
717
792
|
Only shown when onSave is provided (legacy mode without onChange)
|
|
718
793
|
============================================ */
|
|
719
794
|
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
795
|
+
.config-form__footer {
|
|
796
|
+
display: flex;
|
|
797
|
+
gap: var(--fd-space-md);
|
|
798
|
+
justify-content: flex-end;
|
|
799
|
+
padding-top: var(--fd-space-xl);
|
|
800
|
+
border-top: 1px solid var(--fd-border-muted);
|
|
801
|
+
margin-top: var(--fd-space-xs);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/* Button Spinner */
|
|
805
|
+
.config-form__button-spinner {
|
|
806
|
+
width: 1rem;
|
|
807
|
+
height: 1rem;
|
|
808
|
+
border: 2px solid rgba(255, 255, 255, 0.3);
|
|
809
|
+
border-top-color: #ffffff;
|
|
810
|
+
border-radius: 50%;
|
|
811
|
+
animation: config-form-spin 0.6s linear infinite;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/* ============================================
|
|
740
815
|
SHARED BUTTON STYLES
|
|
741
816
|
Used by error actions, external config buttons, and footer
|
|
742
817
|
============================================ */
|
|
743
818
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
819
|
+
.config-form__button {
|
|
820
|
+
display: inline-flex;
|
|
821
|
+
align-items: center;
|
|
822
|
+
justify-content: center;
|
|
823
|
+
gap: var(--fd-space-xs);
|
|
824
|
+
padding: 0.625rem var(--fd-space-xl);
|
|
825
|
+
border-radius: var(--fd-radius-lg);
|
|
826
|
+
font-size: var(--fd-text-sm);
|
|
827
|
+
font-weight: 600;
|
|
828
|
+
font-family: inherit;
|
|
829
|
+
cursor: pointer;
|
|
830
|
+
transition: all var(--fd-transition-normal);
|
|
831
|
+
border: 1px solid transparent;
|
|
832
|
+
min-height: 2.5rem;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
.config-form__button :global(svg) {
|
|
836
|
+
width: 1rem;
|
|
837
|
+
height: 1rem;
|
|
838
|
+
flex-shrink: 0;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
.config-form__button--secondary {
|
|
842
|
+
background-color: var(--fd-background);
|
|
843
|
+
border-color: var(--fd-border);
|
|
844
|
+
color: var(--fd-foreground);
|
|
845
|
+
box-shadow: var(--fd-shadow-sm);
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
.config-form__button--secondary:hover {
|
|
849
|
+
background-color: var(--fd-muted);
|
|
850
|
+
border-color: var(--fd-border-strong);
|
|
851
|
+
color: var(--fd-foreground);
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.config-form__button--secondary:focus-visible {
|
|
855
|
+
outline: none;
|
|
856
|
+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
.config-form__button--primary {
|
|
860
|
+
background: linear-gradient(
|
|
861
|
+
135deg,
|
|
862
|
+
var(--fd-primary) 0%,
|
|
863
|
+
var(--fd-primary-hover) 100%
|
|
864
|
+
);
|
|
865
|
+
color: var(--fd-primary-foreground);
|
|
866
|
+
box-shadow:
|
|
867
|
+
0 1px 3px rgba(59, 130, 246, 0.3),
|
|
868
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
.config-form__button--primary:hover {
|
|
872
|
+
background: linear-gradient(
|
|
873
|
+
135deg,
|
|
874
|
+
var(--fd-primary-hover) 0%,
|
|
875
|
+
var(--fd-primary-hover) 100%
|
|
876
|
+
);
|
|
877
|
+
box-shadow:
|
|
878
|
+
0 4px 12px rgba(59, 130, 246, 0.35),
|
|
879
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
|
880
|
+
transform: translateY(-1px);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
.config-form__button--primary:active {
|
|
884
|
+
transform: translateY(0);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
.config-form__button--primary:focus-visible {
|
|
888
|
+
outline: none;
|
|
889
|
+
box-shadow:
|
|
890
|
+
0 0 0 3px rgba(59, 130, 246, 0.4),
|
|
891
|
+
0 4px 12px rgba(59, 130, 246, 0.35);
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
/* ============================================
|
|
812
895
|
UI EXTENSIONS SECTION
|
|
813
896
|
============================================ */
|
|
814
897
|
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
898
|
+
.config-form__extensions {
|
|
899
|
+
background-color: var(--fd-muted);
|
|
900
|
+
border: 1px solid var(--fd-border);
|
|
901
|
+
border-radius: var(--fd-radius-lg);
|
|
902
|
+
overflow: hidden;
|
|
903
|
+
margin-top: var(--fd-space-xs);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
.config-form__extensions-header {
|
|
907
|
+
display: flex;
|
|
908
|
+
align-items: center;
|
|
909
|
+
gap: var(--fd-space-xs);
|
|
910
|
+
padding: var(--fd-space-md) var(--fd-space-xl);
|
|
911
|
+
background-color: var(--fd-subtle);
|
|
912
|
+
border-bottom: 1px solid var(--fd-border);
|
|
913
|
+
font-size: 0.8125rem;
|
|
914
|
+
font-weight: 600;
|
|
915
|
+
color: var(--fd-foreground);
|
|
916
|
+
}
|
|
917
|
+
|
|
918
|
+
.config-form__extensions-header :global(svg) {
|
|
919
|
+
width: 1rem;
|
|
920
|
+
height: 1rem;
|
|
921
|
+
color: var(--fd-muted-foreground);
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
.config-form__extensions-content {
|
|
925
|
+
padding: var(--fd-space-xl);
|
|
926
|
+
display: flex;
|
|
927
|
+
flex-direction: column;
|
|
928
|
+
gap: var(--fd-space-xl);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/* ============================================
|
|
849
932
|
DEBUG SECTION
|
|
850
933
|
============================================ */
|
|
851
934
|
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
935
|
+
.config-form__debug {
|
|
936
|
+
background-color: var(--fd-warning-muted);
|
|
937
|
+
border: 1px solid var(--fd-warning);
|
|
938
|
+
border-radius: var(--fd-radius-lg);
|
|
939
|
+
overflow: hidden;
|
|
940
|
+
}
|
|
941
|
+
|
|
942
|
+
.config-form__debug-header {
|
|
943
|
+
display: flex;
|
|
944
|
+
align-items: center;
|
|
945
|
+
gap: var(--fd-space-xs);
|
|
946
|
+
padding: var(--fd-space-md) var(--fd-space-xl);
|
|
947
|
+
background-color: var(--fd-warning-muted);
|
|
948
|
+
border-bottom: 1px solid var(--fd-warning);
|
|
949
|
+
font-size: 0.8125rem;
|
|
950
|
+
font-weight: 600;
|
|
951
|
+
color: var(--fd-warning-hover);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
.config-form__debug-header :global(svg) {
|
|
955
|
+
width: 1rem;
|
|
956
|
+
height: 1rem;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
.config-form__debug-content {
|
|
960
|
+
margin: 0;
|
|
961
|
+
padding: var(--fd-space-xl);
|
|
962
|
+
font-size: var(--fd-text-xs);
|
|
963
|
+
font-family: "Monaco", "Menlo", "Ubuntu Mono", monospace;
|
|
964
|
+
color: var(--fd-foreground);
|
|
965
|
+
overflow-x: auto;
|
|
966
|
+
background-color: var(--fd-background);
|
|
967
|
+
line-height: 1.5;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/* ============================================
|
|
888
971
|
EMPTY STATE
|
|
889
972
|
============================================ */
|
|
890
973
|
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
974
|
+
.config-form__empty {
|
|
975
|
+
display: flex;
|
|
976
|
+
flex-direction: column;
|
|
977
|
+
align-items: center;
|
|
978
|
+
justify-content: center;
|
|
979
|
+
padding: var(--fd-space-6xl) var(--fd-space-3xl);
|
|
980
|
+
text-align: center;
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
.config-form__empty-icon {
|
|
984
|
+
width: 3rem;
|
|
985
|
+
height: 3rem;
|
|
986
|
+
margin-bottom: var(--fd-space-xl);
|
|
987
|
+
color: var(--fd-border);
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
.config-form__empty-icon :global(svg) {
|
|
991
|
+
width: 100%;
|
|
992
|
+
height: 100%;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
.config-form__empty-text {
|
|
996
|
+
margin: 0;
|
|
997
|
+
font-size: var(--fd-text-sm);
|
|
998
|
+
color: var(--fd-muted-foreground);
|
|
999
|
+
font-style: italic;
|
|
1000
|
+
line-height: 1.5;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
.config-form__empty-button {
|
|
1004
|
+
margin-top: var(--fd-space-xl);
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
/* ============================================
|
|
925
1008
|
ADMIN/EDIT SECTION - External Configuration
|
|
926
1009
|
============================================ */
|
|
927
1010
|
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
1011
|
+
.config-form__admin-edit {
|
|
1012
|
+
background: linear-gradient(
|
|
1013
|
+
135deg,
|
|
1014
|
+
var(--fd-info-muted) 0%,
|
|
1015
|
+
var(--fd-primary-muted) 100%
|
|
1016
|
+
);
|
|
1017
|
+
border: 1px solid var(--fd-primary);
|
|
1018
|
+
border-radius: 0.625rem;
|
|
1019
|
+
overflow: hidden;
|
|
1020
|
+
margin-bottom: var(--fd-space-xl);
|
|
1021
|
+
}
|
|
1022
|
+
|
|
1023
|
+
.config-form__admin-edit-header {
|
|
1024
|
+
display: flex;
|
|
1025
|
+
align-items: center;
|
|
1026
|
+
gap: var(--fd-space-xs);
|
|
1027
|
+
padding: var(--fd-space-md) var(--fd-space-xl);
|
|
1028
|
+
background: linear-gradient(
|
|
1029
|
+
135deg,
|
|
1030
|
+
var(--fd-primary-muted) 0%,
|
|
1031
|
+
var(--fd-primary-muted) 100%
|
|
1032
|
+
);
|
|
1033
|
+
border-bottom: 1px solid var(--fd-primary);
|
|
1034
|
+
font-size: 0.8125rem;
|
|
1035
|
+
font-weight: 600;
|
|
1036
|
+
color: var(--fd-primary-hover);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
.config-form__admin-edit-header :global(svg) {
|
|
1040
|
+
width: 1rem;
|
|
1041
|
+
height: 1rem;
|
|
1042
|
+
color: var(--fd-primary);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.config-form__admin-edit-content {
|
|
1046
|
+
padding: var(--fd-space-xl);
|
|
1047
|
+
display: flex;
|
|
1048
|
+
flex-direction: column;
|
|
1049
|
+
gap: var(--fd-space-md);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
.config-form__admin-edit-description {
|
|
1053
|
+
margin: 0;
|
|
1054
|
+
font-size: 0.8125rem;
|
|
1055
|
+
color: var(--fd-primary-hover);
|
|
1056
|
+
line-height: 1.5;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/* ============================================
|
|
969
1060
|
LOADING STATE
|
|
970
1061
|
============================================ */
|
|
971
1062
|
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1063
|
+
.config-form__loading {
|
|
1064
|
+
display: flex;
|
|
1065
|
+
flex-direction: column;
|
|
1066
|
+
align-items: center;
|
|
1067
|
+
justify-content: center;
|
|
1068
|
+
padding: var(--fd-space-6xl) var(--fd-space-3xl);
|
|
1069
|
+
gap: var(--fd-space-xl);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
.config-form__loading-spinner {
|
|
1073
|
+
width: 2.5rem;
|
|
1074
|
+
height: 2.5rem;
|
|
1075
|
+
border: 3px solid var(--fd-primary-muted);
|
|
1076
|
+
border-top-color: var(--fd-primary);
|
|
1077
|
+
border-radius: 50%;
|
|
1078
|
+
animation: config-form-spin 0.8s linear infinite;
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
@keyframes config-form-spin {
|
|
1082
|
+
to {
|
|
1083
|
+
transform: rotate(360deg);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
.config-form__loading-text {
|
|
1088
|
+
margin: 0;
|
|
1089
|
+
font-size: var(--fd-text-sm);
|
|
1090
|
+
color: var(--fd-muted-foreground);
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
/* ============================================
|
|
1003
1094
|
ERROR STATE
|
|
1004
1095
|
============================================ */
|
|
1005
1096
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1097
|
+
.config-form__error {
|
|
1098
|
+
background-color: var(--fd-error-muted);
|
|
1099
|
+
border: 1px solid var(--fd-error);
|
|
1100
|
+
border-radius: var(--fd-radius-lg);
|
|
1101
|
+
overflow: hidden;
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
.config-form__error-header {
|
|
1105
|
+
display: flex;
|
|
1106
|
+
align-items: center;
|
|
1107
|
+
gap: var(--fd-space-xs);
|
|
1108
|
+
padding: var(--fd-space-md) var(--fd-space-xl);
|
|
1109
|
+
background-color: var(--fd-error-muted);
|
|
1110
|
+
border-bottom: 1px solid var(--fd-error);
|
|
1111
|
+
font-size: 0.8125rem;
|
|
1112
|
+
font-weight: 600;
|
|
1113
|
+
color: var(--fd-error-hover);
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
.config-form__error-header :global(svg) {
|
|
1117
|
+
width: 1rem;
|
|
1118
|
+
height: 1rem;
|
|
1119
|
+
color: var(--fd-error);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
.config-form__error-content {
|
|
1123
|
+
padding: var(--fd-space-xl);
|
|
1124
|
+
display: flex;
|
|
1125
|
+
flex-direction: column;
|
|
1126
|
+
gap: var(--fd-space-md);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
.config-form__error-message {
|
|
1130
|
+
margin: 0;
|
|
1131
|
+
font-size: 0.8125rem;
|
|
1132
|
+
color: var(--fd-error);
|
|
1133
|
+
line-height: 1.5;
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
.config-form__error-actions {
|
|
1137
|
+
display: flex;
|
|
1138
|
+
gap: var(--fd-space-xs);
|
|
1139
|
+
flex-wrap: wrap;
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
/* ============================================
|
|
1052
1143
|
SCHEMA ACTIONS (Refresh, External Editor)
|
|
1053
1144
|
============================================ */
|
|
1054
1145
|
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1146
|
+
.config-form__schema-actions {
|
|
1147
|
+
display: flex;
|
|
1148
|
+
gap: var(--fd-space-xs);
|
|
1149
|
+
margin-bottom: var(--fd-space-xl);
|
|
1150
|
+
padding-bottom: var(--fd-space-md);
|
|
1151
|
+
border-bottom: 1px solid var(--fd-border-muted);
|
|
1152
|
+
}
|
|
1153
|
+
|
|
1154
|
+
.config-form__schema-refresh,
|
|
1155
|
+
.config-form__schema-external {
|
|
1156
|
+
display: inline-flex;
|
|
1157
|
+
align-items: center;
|
|
1158
|
+
gap: var(--fd-space-3xs);
|
|
1159
|
+
padding: var(--fd-space-3xs) var(--fd-space-xs);
|
|
1160
|
+
font-size: var(--fd-text-xs);
|
|
1161
|
+
font-weight: 500;
|
|
1162
|
+
font-family: inherit;
|
|
1163
|
+
border-radius: var(--fd-radius-md);
|
|
1164
|
+
cursor: pointer;
|
|
1165
|
+
transition: all var(--fd-transition-fast);
|
|
1166
|
+
border: 1px solid transparent;
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
.config-form__schema-refresh {
|
|
1170
|
+
background-color: var(--fd-muted);
|
|
1171
|
+
border-color: var(--fd-border);
|
|
1172
|
+
color: var(--fd-muted-foreground);
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
.config-form__schema-refresh:hover {
|
|
1176
|
+
background-color: var(--fd-subtle);
|
|
1177
|
+
border-color: var(--fd-border-strong);
|
|
1178
|
+
color: var(--fd-foreground);
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
.config-form__schema-refresh :global(svg),
|
|
1182
|
+
.config-form__schema-external :global(svg) {
|
|
1183
|
+
width: 0.875rem;
|
|
1184
|
+
height: 0.875rem;
|
|
1185
|
+
}
|
|
1186
|
+
|
|
1187
|
+
.config-form__schema-external {
|
|
1188
|
+
background-color: var(--fd-primary-muted);
|
|
1189
|
+
border-color: var(--fd-primary);
|
|
1190
|
+
color: var(--fd-primary-hover);
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
.config-form__schema-external:hover {
|
|
1194
|
+
background-color: var(--fd-primary-muted);
|
|
1195
|
+
border-color: var(--fd-primary-hover);
|
|
1196
|
+
color: var(--fd-primary-hover);
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
/* ============================================
|
|
1109
1200
|
EXTERNAL BUTTON STYLE
|
|
1110
1201
|
============================================ */
|
|
1111
1202
|
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1203
|
+
.config-form__button--external {
|
|
1204
|
+
background: linear-gradient(
|
|
1205
|
+
135deg,
|
|
1206
|
+
var(--fd-accent) 0%,
|
|
1207
|
+
var(--fd-primary) 100%
|
|
1208
|
+
);
|
|
1209
|
+
color: var(--fd-accent-foreground);
|
|
1210
|
+
box-shadow:
|
|
1211
|
+
0 1px 3px rgba(99, 102, 241, 0.3),
|
|
1212
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
.config-form__button--external:hover {
|
|
1216
|
+
background: linear-gradient(
|
|
1217
|
+
135deg,
|
|
1218
|
+
var(--fd-accent-hover) 0%,
|
|
1219
|
+
var(--fd-primary-hover) 100%
|
|
1220
|
+
);
|
|
1221
|
+
box-shadow:
|
|
1222
|
+
0 4px 12px rgba(99, 102, 241, 0.35),
|
|
1223
|
+
inset 0 1px 0 rgba(255, 255, 255, 0.1);
|
|
1224
|
+
transform: translateY(-1px);
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
.config-form__button--external:active {
|
|
1228
|
+
transform: translateY(0);
|
|
1229
|
+
}
|
|
1230
|
+
|
|
1231
|
+
.config-form__button--external:focus-visible {
|
|
1232
|
+
outline: none;
|
|
1233
|
+
box-shadow:
|
|
1234
|
+
0 0 0 3px rgba(99, 102, 241, 0.4),
|
|
1235
|
+
0 4px 12px rgba(99, 102, 241, 0.35);
|
|
1236
|
+
}
|
|
1138
1237
|
</style>
|