@flowdrop/flowdrop 1.0.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/LICENSE +21 -0
- package/README.md +252 -0
- package/dist/adapters/WorkflowAdapter.d.ts +167 -0
- package/dist/adapters/WorkflowAdapter.js +368 -0
- package/dist/adapters/agentspec/AgentSpecAdapter.d.ts +96 -0
- package/dist/adapters/agentspec/AgentSpecAdapter.js +626 -0
- package/dist/adapters/agentspec/agentAdapter.d.ts +59 -0
- package/dist/adapters/agentspec/agentAdapter.js +91 -0
- package/dist/adapters/agentspec/autoLayout.d.ts +34 -0
- package/dist/adapters/agentspec/autoLayout.js +127 -0
- package/dist/adapters/agentspec/componentTypeDefaults.d.ts +73 -0
- package/dist/adapters/agentspec/componentTypeDefaults.js +238 -0
- package/dist/adapters/agentspec/defaultNodeTypes.d.ts +53 -0
- package/dist/adapters/agentspec/defaultNodeTypes.js +561 -0
- package/dist/adapters/agentspec/index.d.ts +37 -0
- package/dist/adapters/agentspec/index.js +39 -0
- package/dist/adapters/agentspec/validator.d.ts +34 -0
- package/dist/adapters/agentspec/validator.js +169 -0
- package/dist/api/enhanced-client.d.ts +183 -0
- package/dist/api/enhanced-client.js +430 -0
- package/dist/components/App.svelte +981 -0
- package/dist/components/App.svelte.d.ts +54 -0
- package/dist/components/CanvasBanner.stories.svelte +29 -0
- package/dist/components/CanvasBanner.stories.svelte.d.ts +27 -0
- package/dist/components/CanvasBanner.svelte +57 -0
- package/dist/components/CanvasBanner.svelte.d.ts +8 -0
- package/dist/components/ConfigForm.svelte +1138 -0
- package/dist/components/ConfigForm.svelte.d.ts +44 -0
- package/dist/components/ConfigModal.svelte +188 -0
- package/dist/components/ConfigModal.svelte.d.ts +13 -0
- package/dist/components/ConfigPanel.stories.svelte +47 -0
- package/dist/components/ConfigPanel.stories.svelte.d.ts +27 -0
- package/dist/components/ConfigPanel.svelte +182 -0
- package/dist/components/ConfigPanel.svelte.d.ts +32 -0
- package/dist/components/ConnectionLine.svelte +32 -0
- package/dist/components/ConnectionLine.svelte.d.ts +3 -0
- package/dist/components/EdgeRefresher.svelte +41 -0
- package/dist/components/EdgeRefresher.svelte.d.ts +9 -0
- package/dist/components/FlowDropZone.svelte +83 -0
- package/dist/components/FlowDropZone.svelte.d.ts +13 -0
- package/dist/components/LoadingSpinner.stories.svelte +30 -0
- package/dist/components/LoadingSpinner.stories.svelte.d.ts +27 -0
- package/dist/components/LoadingSpinner.svelte +36 -0
- package/dist/components/LoadingSpinner.svelte.d.ts +8 -0
- package/dist/components/Logo.stories.svelte +22 -0
- package/dist/components/Logo.stories.svelte.d.ts +27 -0
- package/dist/components/Logo.svelte +102 -0
- package/dist/components/Logo.svelte.d.ts +26 -0
- package/dist/components/LogsSidebar.svelte +563 -0
- package/dist/components/LogsSidebar.svelte.d.ts +17 -0
- package/dist/components/MarkdownDisplay.stories.svelte +36 -0
- package/dist/components/MarkdownDisplay.stories.svelte.d.ts +27 -0
- package/dist/components/MarkdownDisplay.svelte +29 -0
- package/dist/components/MarkdownDisplay.svelte.d.ts +7 -0
- package/dist/components/Navbar.stories.svelte +53 -0
- package/dist/components/Navbar.stories.svelte.d.ts +27 -0
- package/dist/components/Navbar.svelte +726 -0
- package/dist/components/Navbar.svelte.d.ts +29 -0
- package/dist/components/NodeSidebar.svelte +762 -0
- package/dist/components/NodeSidebar.svelte.d.ts +9 -0
- package/dist/components/NodeStatusOverlay.stories.svelte +85 -0
- package/dist/components/NodeStatusOverlay.stories.svelte.d.ts +27 -0
- package/dist/components/NodeStatusOverlay.svelte +327 -0
- package/dist/components/NodeStatusOverlay.svelte.d.ts +11 -0
- package/dist/components/PipelineStatus.svelte +314 -0
- package/dist/components/PipelineStatus.svelte.d.ts +20 -0
- package/dist/components/PortCoordinateTracker.svelte +58 -0
- package/dist/components/PortCoordinateTracker.svelte.d.ts +12 -0
- package/dist/components/ReadOnlyDetails.svelte +170 -0
- package/dist/components/ReadOnlyDetails.svelte.d.ts +25 -0
- package/dist/components/SchemaForm.stories.svelte +116 -0
- package/dist/components/SchemaForm.stories.svelte.d.ts +27 -0
- package/dist/components/SchemaForm.svelte +536 -0
- package/dist/components/SchemaForm.svelte.d.ts +83 -0
- package/dist/components/SettingsModal.svelte +279 -0
- package/dist/components/SettingsModal.svelte.d.ts +23 -0
- package/dist/components/SettingsPanel.svelte +638 -0
- package/dist/components/SettingsPanel.svelte.d.ts +21 -0
- package/dist/components/StatusIcon.stories.svelte +60 -0
- package/dist/components/StatusIcon.stories.svelte.d.ts +27 -0
- package/dist/components/StatusIcon.svelte +119 -0
- package/dist/components/StatusIcon.svelte.d.ts +10 -0
- package/dist/components/StatusLabel.stories.svelte +17 -0
- package/dist/components/StatusLabel.stories.svelte.d.ts +27 -0
- package/dist/components/StatusLabel.svelte +33 -0
- package/dist/components/StatusLabel.svelte.d.ts +7 -0
- package/dist/components/ThemeToggle.stories.svelte +25 -0
- package/dist/components/ThemeToggle.stories.svelte.d.ts +27 -0
- package/dist/components/ThemeToggle.svelte +185 -0
- package/dist/components/ThemeToggle.svelte.d.ts +14 -0
- package/dist/components/UniversalNode.svelte +155 -0
- package/dist/components/UniversalNode.svelte.d.ts +15 -0
- package/dist/components/WorkflowEditor.svelte +1035 -0
- package/dist/components/WorkflowEditor.svelte.d.ts +23 -0
- package/dist/components/form/FormArray.svelte +1049 -0
- package/dist/components/form/FormArray.svelte.d.ts +22 -0
- package/dist/components/form/FormAutocomplete.svelte +1009 -0
- package/dist/components/form/FormAutocomplete.svelte.d.ts +25 -0
- package/dist/components/form/FormCheckboxGroup.stories.svelte +28 -0
- package/dist/components/form/FormCheckboxGroup.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormCheckboxGroup.svelte +155 -0
- package/dist/components/form/FormCheckboxGroup.svelte.d.ts +17 -0
- package/dist/components/form/FormCodeEditor.svelte +458 -0
- package/dist/components/form/FormCodeEditor.svelte.d.ts +25 -0
- package/dist/components/form/FormField.svelte +417 -0
- package/dist/components/form/FormField.svelte.d.ts +29 -0
- package/dist/components/form/FormFieldLight.svelte +425 -0
- package/dist/components/form/FormFieldLight.svelte.d.ts +18 -0
- package/dist/components/form/FormFieldWrapper.stories.svelte +53 -0
- package/dist/components/form/FormFieldWrapper.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormFieldWrapper.svelte +125 -0
- package/dist/components/form/FormFieldWrapper.svelte.d.ts +18 -0
- package/dist/components/form/FormFieldset.svelte +142 -0
- package/dist/components/form/FormFieldset.svelte.d.ts +11 -0
- package/dist/components/form/FormMarkdownEditor.svelte +752 -0
- package/dist/components/form/FormMarkdownEditor.svelte.d.ts +33 -0
- package/dist/components/form/FormNumberField.stories.svelte +36 -0
- package/dist/components/form/FormNumberField.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormNumberField.svelte +112 -0
- package/dist/components/form/FormNumberField.svelte.d.ts +25 -0
- package/dist/components/form/FormRangeField.stories.svelte +31 -0
- package/dist/components/form/FormRangeField.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormRangeField.svelte +246 -0
- package/dist/components/form/FormRangeField.svelte.d.ts +23 -0
- package/dist/components/form/FormSelect.stories.svelte +50 -0
- package/dist/components/form/FormSelect.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormSelect.svelte +129 -0
- package/dist/components/form/FormSelect.svelte.d.ts +20 -0
- package/dist/components/form/FormTemplateEditor.svelte +825 -0
- package/dist/components/form/FormTemplateEditor.svelte.d.ts +41 -0
- package/dist/components/form/FormTextField.stories.svelte +30 -0
- package/dist/components/form/FormTextField.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormTextField.svelte +91 -0
- package/dist/components/form/FormTextField.svelte.d.ts +19 -0
- package/dist/components/form/FormTextarea.stories.svelte +34 -0
- package/dist/components/form/FormTextarea.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormTextarea.svelte +97 -0
- package/dist/components/form/FormTextarea.svelte.d.ts +21 -0
- package/dist/components/form/FormToggle.stories.svelte +30 -0
- package/dist/components/form/FormToggle.stories.svelte.d.ts +27 -0
- package/dist/components/form/FormToggle.svelte +126 -0
- package/dist/components/form/FormToggle.svelte.d.ts +19 -0
- package/dist/components/form/FormUISchemaRenderer.svelte +136 -0
- package/dist/components/form/FormUISchemaRenderer.svelte.d.ts +32 -0
- package/dist/components/form/index.d.ts +50 -0
- package/dist/components/form/index.js +54 -0
- package/dist/components/form/templateAutocomplete.d.ts +29 -0
- package/dist/components/form/templateAutocomplete.js +254 -0
- package/dist/components/form/types.d.ts +485 -0
- package/dist/components/form/types.js +73 -0
- package/dist/components/interrupt/ChoicePrompt.stories.svelte +52 -0
- package/dist/components/interrupt/ChoicePrompt.stories.svelte.d.ts +27 -0
- package/dist/components/interrupt/ChoicePrompt.svelte +401 -0
- package/dist/components/interrupt/ChoicePrompt.svelte.d.ts +23 -0
- package/dist/components/interrupt/ConfirmationPrompt.stories.svelte +71 -0
- package/dist/components/interrupt/ConfirmationPrompt.stories.svelte.d.ts +27 -0
- package/dist/components/interrupt/ConfirmationPrompt.svelte +292 -0
- package/dist/components/interrupt/ConfirmationPrompt.svelte.d.ts +25 -0
- package/dist/components/interrupt/FormPrompt.svelte +236 -0
- package/dist/components/interrupt/FormPrompt.svelte.d.ts +23 -0
- package/dist/components/interrupt/InterruptBubble.svelte +601 -0
- package/dist/components/interrupt/InterruptBubble.svelte.d.ts +16 -0
- package/dist/components/interrupt/ReviewPrompt.stories.svelte +67 -0
- package/dist/components/interrupt/ReviewPrompt.stories.svelte.d.ts +27 -0
- package/dist/components/interrupt/ReviewPrompt.svelte +861 -0
- package/dist/components/interrupt/ReviewPrompt.svelte.d.ts +23 -0
- package/dist/components/interrupt/TextInputPrompt.stories.svelte +47 -0
- package/dist/components/interrupt/TextInputPrompt.stories.svelte.d.ts +27 -0
- package/dist/components/interrupt/TextInputPrompt.svelte +346 -0
- package/dist/components/interrupt/TextInputPrompt.svelte.d.ts +23 -0
- package/dist/components/interrupt/index.d.ts +13 -0
- package/dist/components/interrupt/index.js +15 -0
- package/dist/components/layouts/MainLayout.svelte +718 -0
- package/dist/components/layouts/MainLayout.svelte.d.ts +62 -0
- package/dist/components/nodes/GatewayNode.stories.svelte +108 -0
- package/dist/components/nodes/GatewayNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/GatewayNode.svelte +591 -0
- package/dist/components/nodes/GatewayNode.svelte.d.ts +15 -0
- package/dist/components/nodes/IdeaNode.stories.svelte +52 -0
- package/dist/components/nodes/IdeaNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/IdeaNode.svelte +455 -0
- package/dist/components/nodes/IdeaNode.svelte.d.ts +24 -0
- package/dist/components/nodes/NotesNode.stories.svelte +76 -0
- package/dist/components/nodes/NotesNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/NotesNode.svelte +378 -0
- package/dist/components/nodes/NotesNode.svelte.d.ts +24 -0
- package/dist/components/nodes/SimpleNode.stories.svelte +159 -0
- package/dist/components/nodes/SimpleNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/SimpleNode.svelte +451 -0
- package/dist/components/nodes/SimpleNode.svelte.d.ts +25 -0
- package/dist/components/nodes/SquareNode.stories.svelte +82 -0
- package/dist/components/nodes/SquareNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/SquareNode.svelte +407 -0
- package/dist/components/nodes/SquareNode.svelte.d.ts +25 -0
- package/dist/components/nodes/TerminalNode.stories.svelte +25 -0
- package/dist/components/nodes/TerminalNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/TerminalNode.svelte +690 -0
- package/dist/components/nodes/TerminalNode.svelte.d.ts +25 -0
- package/dist/components/nodes/ToolNode.stories.svelte +189 -0
- package/dist/components/nodes/ToolNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/ToolNode.svelte +471 -0
- package/dist/components/nodes/ToolNode.svelte.d.ts +36 -0
- package/dist/components/nodes/WorkflowNode.stories.svelte +55 -0
- package/dist/components/nodes/WorkflowNode.stories.svelte.d.ts +26 -0
- package/dist/components/nodes/WorkflowNode.svelte +571 -0
- package/dist/components/nodes/WorkflowNode.svelte.d.ts +15 -0
- package/dist/components/playground/ChatPanel.svelte +905 -0
- package/dist/components/playground/ChatPanel.svelte.d.ts +46 -0
- package/dist/components/playground/ExecutionLogs.svelte +488 -0
- package/dist/components/playground/ExecutionLogs.svelte.d.ts +14 -0
- package/dist/components/playground/InputCollector.svelte +444 -0
- package/dist/components/playground/InputCollector.svelte.d.ts +16 -0
- package/dist/components/playground/MessageBubble.stories.svelte +62 -0
- package/dist/components/playground/MessageBubble.stories.svelte.d.ts +27 -0
- package/dist/components/playground/MessageBubble.svelte +633 -0
- package/dist/components/playground/MessageBubble.svelte.d.ts +24 -0
- package/dist/components/playground/Playground.svelte +1075 -0
- package/dist/components/playground/Playground.svelte.d.ts +25 -0
- package/dist/components/playground/PlaygroundModal.svelte +220 -0
- package/dist/components/playground/PlaygroundModal.svelte.d.ts +25 -0
- package/dist/components/playground/SessionManager.svelte +538 -0
- package/dist/components/playground/SessionManager.svelte.d.ts +20 -0
- package/dist/config/agentSpecEndpoints.d.ts +70 -0
- package/dist/config/agentSpecEndpoints.js +65 -0
- package/dist/config/constants.d.ts +43 -0
- package/dist/config/constants.js +31 -0
- package/dist/config/defaultCategories.d.ts +7 -0
- package/dist/config/defaultCategories.js +126 -0
- package/dist/config/defaultPortConfig.d.ts +6 -0
- package/dist/config/defaultPortConfig.js +201 -0
- package/dist/config/endpoints.d.ts +160 -0
- package/dist/config/endpoints.js +146 -0
- package/dist/config/runtimeConfig.d.ts +47 -0
- package/dist/config/runtimeConfig.js +80 -0
- package/dist/core/index.d.ts +75 -0
- package/dist/core/index.js +92 -0
- package/dist/display/index.d.ts +29 -0
- package/dist/display/index.js +36 -0
- package/dist/editor/index.d.ts +95 -0
- package/dist/editor/index.js +138 -0
- package/dist/form/code.d.ts +101 -0
- package/dist/form/code.js +168 -0
- package/dist/form/fieldRegistry.d.ts +169 -0
- package/dist/form/fieldRegistry.js +152 -0
- package/dist/form/full.d.ts +56 -0
- package/dist/form/full.js +80 -0
- package/dist/form/index.d.ts +77 -0
- package/dist/form/index.js +91 -0
- package/dist/form/markdown.d.ts +69 -0
- package/dist/form/markdown.js +103 -0
- package/dist/helpers/nodeLayoutHelper.d.ts +14 -0
- package/dist/helpers/nodeLayoutHelper.js +19 -0
- package/dist/helpers/proximityConnect.d.ts +94 -0
- package/dist/helpers/proximityConnect.js +314 -0
- package/dist/helpers/workflowEditorHelper.d.ts +183 -0
- package/dist/helpers/workflowEditorHelper.js +595 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.js +64 -0
- package/dist/mocks/app-environment.d.ts +8 -0
- package/dist/mocks/app-environment.js +16 -0
- package/dist/mocks/app-forms.d.ts +2 -0
- package/dist/mocks/app-forms.js +22 -0
- package/dist/mocks/app-navigation.d.ts +5 -0
- package/dist/mocks/app-navigation.js +36 -0
- package/dist/mocks/app-stores.d.ts +14 -0
- package/dist/mocks/app-stores.js +26 -0
- package/dist/playground/index.d.ts +131 -0
- package/dist/playground/index.js +172 -0
- package/dist/playground/mount.d.ts +203 -0
- package/dist/playground/mount.js +235 -0
- package/dist/registry/BaseRegistry.d.ts +92 -0
- package/dist/registry/BaseRegistry.js +124 -0
- package/dist/registry/builtinFormats.d.ts +23 -0
- package/dist/registry/builtinFormats.js +70 -0
- package/dist/registry/builtinNodes.d.ts +77 -0
- package/dist/registry/builtinNodes.js +211 -0
- package/dist/registry/index.d.ts +8 -0
- package/dist/registry/index.js +12 -0
- package/dist/registry/nodeComponentRegistry.d.ts +276 -0
- package/dist/registry/nodeComponentRegistry.js +262 -0
- package/dist/registry/plugin.d.ts +215 -0
- package/dist/registry/plugin.js +249 -0
- package/dist/registry/workflowFormatRegistry.d.ts +122 -0
- package/dist/registry/workflowFormatRegistry.js +96 -0
- package/dist/schema/index.d.ts +23 -0
- package/dist/schema/index.js +23 -0
- package/dist/schemas/v1/workflow.schema.json +1078 -0
- package/dist/services/agentSpecExecutionService.d.ts +106 -0
- package/dist/services/agentSpecExecutionService.js +334 -0
- package/dist/services/api.d.ts +115 -0
- package/dist/services/api.js +214 -0
- package/dist/services/apiVariableService.d.ts +114 -0
- package/dist/services/apiVariableService.js +338 -0
- package/dist/services/autoSaveService.d.ts +112 -0
- package/dist/services/autoSaveService.js +227 -0
- package/dist/services/categoriesApi.d.ts +14 -0
- package/dist/services/categoriesApi.js +49 -0
- package/dist/services/draftStorage.d.ts +171 -0
- package/dist/services/draftStorage.js +299 -0
- package/dist/services/dynamicSchemaService.d.ts +108 -0
- package/dist/services/dynamicSchemaService.js +444 -0
- package/dist/services/globalSave.d.ts +69 -0
- package/dist/services/globalSave.js +248 -0
- package/dist/services/historyService.d.ts +208 -0
- package/dist/services/historyService.js +321 -0
- package/dist/services/interruptService.d.ts +133 -0
- package/dist/services/interruptService.js +280 -0
- package/dist/services/nodeExecutionService.d.ts +63 -0
- package/dist/services/nodeExecutionService.js +266 -0
- package/dist/services/playgroundService.d.ts +130 -0
- package/dist/services/playgroundService.js +321 -0
- package/dist/services/portConfigApi.d.ts +14 -0
- package/dist/services/portConfigApi.js +54 -0
- package/dist/services/settingsService.d.ts +92 -0
- package/dist/services/settingsService.js +196 -0
- package/dist/services/toastService.d.ts +156 -0
- package/dist/services/toastService.js +265 -0
- package/dist/services/variableService.d.ts +141 -0
- package/dist/services/variableService.js +463 -0
- package/dist/services/workflowStorage.d.ts +37 -0
- package/dist/services/workflowStorage.js +116 -0
- package/dist/settings/index.d.ts +25 -0
- package/dist/settings/index.js +33 -0
- package/dist/stores/categoriesStore.svelte.d.ts +32 -0
- package/dist/stores/categoriesStore.svelte.js +77 -0
- package/dist/stores/editorStateMachine.svelte.d.ts +42 -0
- package/dist/stores/editorStateMachine.svelte.js +132 -0
- package/dist/stores/historyStore.svelte.d.ts +136 -0
- package/dist/stores/historyStore.svelte.js +207 -0
- package/dist/stores/interruptStore.svelte.d.ts +179 -0
- package/dist/stores/interruptStore.svelte.js +346 -0
- package/dist/stores/playgroundStore.svelte.d.ts +230 -0
- package/dist/stores/playgroundStore.svelte.js +515 -0
- package/dist/stores/portCoordinateStore.svelte.d.ts +66 -0
- package/dist/stores/portCoordinateStore.svelte.js +186 -0
- package/dist/stores/settingsStore.svelte.d.ts +158 -0
- package/dist/stores/settingsStore.svelte.js +544 -0
- package/dist/stores/workflowStore.svelte.d.ts +260 -0
- package/dist/stores/workflowStore.svelte.js +649 -0
- package/dist/stories/CanvasDecorator.svelte +49 -0
- package/dist/stories/CanvasDecorator.svelte.d.ts +8 -0
- package/dist/stories/NodeDecorator.svelte +73 -0
- package/dist/stories/NodeDecorator.svelte.d.ts +8 -0
- package/dist/stories/utils.d.ts +93 -0
- package/dist/stories/utils.js +122 -0
- package/dist/styles/base.css +1300 -0
- package/dist/styles/toast.css +35 -0
- package/dist/styles/tokens.css +475 -0
- package/dist/svelte-app.d.ts +150 -0
- package/dist/svelte-app.js +295 -0
- package/dist/types/agentspec.d.ts +318 -0
- package/dist/types/agentspec.js +48 -0
- package/dist/types/auth.d.ts +263 -0
- package/dist/types/auth.js +229 -0
- package/dist/types/config.d.ts +151 -0
- package/dist/types/config.js +7 -0
- package/dist/types/events.d.ts +190 -0
- package/dist/types/events.js +30 -0
- package/dist/types/index.d.ts +1234 -0
- package/dist/types/index.js +27 -0
- package/dist/types/interrupt.d.ts +390 -0
- package/dist/types/interrupt.js +145 -0
- package/dist/types/interruptState.d.ts +211 -0
- package/dist/types/interruptState.js +308 -0
- package/dist/types/playground.d.ts +351 -0
- package/dist/types/playground.js +95 -0
- package/dist/types/settings.d.ts +189 -0
- package/dist/types/settings.js +97 -0
- package/dist/types/uischema.d.ts +144 -0
- package/dist/types/uischema.js +51 -0
- package/dist/utils/colors.d.ts +288 -0
- package/dist/utils/colors.js +548 -0
- package/dist/utils/config.d.ts +37 -0
- package/dist/utils/config.js +226 -0
- package/dist/utils/connections.d.ts +125 -0
- package/dist/utils/connections.js +414 -0
- package/dist/utils/errors.d.ts +28 -0
- package/dist/utils/errors.js +44 -0
- package/dist/utils/fetchWithAuth.d.ts +25 -0
- package/dist/utils/fetchWithAuth.js +34 -0
- package/dist/utils/handleIds.d.ts +35 -0
- package/dist/utils/handleIds.js +58 -0
- package/dist/utils/handlePositioning.d.ts +31 -0
- package/dist/utils/handlePositioning.js +35 -0
- package/dist/utils/icons.d.ts +106 -0
- package/dist/utils/icons.js +157 -0
- package/dist/utils/logger.d.ts +47 -0
- package/dist/utils/logger.js +72 -0
- package/dist/utils/nodeStatus.d.ts +53 -0
- package/dist/utils/nodeStatus.js +183 -0
- package/dist/utils/nodeTypes.d.ts +117 -0
- package/dist/utils/nodeTypes.js +244 -0
- package/dist/utils/nodeWrapper.d.ts +39 -0
- package/dist/utils/nodeWrapper.js +62 -0
- package/dist/utils/performanceUtils.d.ts +30 -0
- package/dist/utils/performanceUtils.js +108 -0
- package/dist/utils/sanitize.d.ts +19 -0
- package/dist/utils/sanitize.js +31 -0
- package/dist/utils/uischema.d.ts +52 -0
- package/dist/utils/uischema.js +88 -0
- package/dist/utils/validation.d.ts +29 -0
- package/dist/utils/validation.js +39 -0
- package/package.json +292 -0
|
@@ -0,0 +1,825 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
FormTemplateEditor Component
|
|
3
|
+
CodeMirror-based template editor for Twig/Liquid-style templates
|
|
4
|
+
|
|
5
|
+
Features:
|
|
6
|
+
- Custom syntax highlighting for {{ variable }} placeholders
|
|
7
|
+
- Inline autocomplete for template variables (triggered on {{ and .)
|
|
8
|
+
- Support for nested object drilling (user.address.city)
|
|
9
|
+
- Support for array index access (items[0].name)
|
|
10
|
+
- Dark/light theme support
|
|
11
|
+
- Consistent styling with other form components
|
|
12
|
+
- Line wrapping for better template readability
|
|
13
|
+
- Optional variable hints display (clickable buttons)
|
|
14
|
+
- Proper ARIA attributes for accessibility
|
|
15
|
+
|
|
16
|
+
Usage:
|
|
17
|
+
Use with schema format: "template" to render this editor
|
|
18
|
+
-->
|
|
19
|
+
|
|
20
|
+
<script lang="ts">
|
|
21
|
+
import { onMount, onDestroy } from 'svelte';
|
|
22
|
+
import {
|
|
23
|
+
EditorView,
|
|
24
|
+
lineNumbers,
|
|
25
|
+
highlightActiveLineGutter,
|
|
26
|
+
drawSelection,
|
|
27
|
+
highlightSpecialChars,
|
|
28
|
+
highlightActiveLine,
|
|
29
|
+
keymap,
|
|
30
|
+
tooltips,
|
|
31
|
+
Decoration,
|
|
32
|
+
ViewPlugin,
|
|
33
|
+
MatchDecorator
|
|
34
|
+
} from '@codemirror/view';
|
|
35
|
+
import { EditorState, Compartment } from '@codemirror/state';
|
|
36
|
+
import { history, historyKeymap, defaultKeymap, indentWithTab } from '@codemirror/commands';
|
|
37
|
+
import { syntaxHighlighting, defaultHighlightStyle } from '@codemirror/language';
|
|
38
|
+
import { oneDark } from '@codemirror/theme-one-dark';
|
|
39
|
+
import type {
|
|
40
|
+
VariableSchema,
|
|
41
|
+
TemplateVariablesConfig,
|
|
42
|
+
WorkflowNode,
|
|
43
|
+
WorkflowEdge,
|
|
44
|
+
AuthProvider
|
|
45
|
+
} from '../../types/index.js';
|
|
46
|
+
import { createTemplateAutocomplete } from './templateAutocomplete.js';
|
|
47
|
+
import { getVariableSchema } from '../../services/variableService.js';
|
|
48
|
+
import { logger } from '../../utils/logger.js';
|
|
49
|
+
|
|
50
|
+
interface Props {
|
|
51
|
+
/** Field identifier */
|
|
52
|
+
id: string;
|
|
53
|
+
/** Current template value */
|
|
54
|
+
value: string;
|
|
55
|
+
/** Placeholder text shown when empty */
|
|
56
|
+
placeholder?: string;
|
|
57
|
+
/** Whether the field is required */
|
|
58
|
+
required?: boolean;
|
|
59
|
+
/** Whether to use dark theme */
|
|
60
|
+
darkTheme?: boolean;
|
|
61
|
+
/** Editor height in pixels or CSS value */
|
|
62
|
+
height?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Configuration for template variable autocomplete.
|
|
65
|
+
* Controls which variables are available and how they are displayed.
|
|
66
|
+
*/
|
|
67
|
+
variables?: TemplateVariablesConfig;
|
|
68
|
+
/** Placeholder variable example for the hint */
|
|
69
|
+
placeholderExample?: string;
|
|
70
|
+
/** Whether the field is disabled (read-only) */
|
|
71
|
+
disabled?: boolean;
|
|
72
|
+
/** ARIA description ID */
|
|
73
|
+
ariaDescribedBy?: string;
|
|
74
|
+
/** Callback when value changes */
|
|
75
|
+
onChange: (value: string) => void;
|
|
76
|
+
/** Current workflow node (required for API mode) */
|
|
77
|
+
node?: WorkflowNode;
|
|
78
|
+
/** All workflow nodes (required for port-derived variables) */
|
|
79
|
+
nodes?: WorkflowNode[];
|
|
80
|
+
/** All workflow edges (required for port-derived variables) */
|
|
81
|
+
edges?: WorkflowEdge[];
|
|
82
|
+
/** Workflow ID (required for API mode) */
|
|
83
|
+
workflowId?: string;
|
|
84
|
+
/** Auth provider for API requests */
|
|
85
|
+
authProvider?: AuthProvider;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
let {
|
|
89
|
+
id,
|
|
90
|
+
value = '',
|
|
91
|
+
placeholder = 'Enter your template here...\nUse {{ variable }} for dynamic values.',
|
|
92
|
+
required = false,
|
|
93
|
+
darkTheme = false,
|
|
94
|
+
height = '250px',
|
|
95
|
+
variables,
|
|
96
|
+
placeholderExample = 'Hello {{ name }}, your order #{{ order_id }} is ready!',
|
|
97
|
+
disabled = false,
|
|
98
|
+
ariaDescribedBy,
|
|
99
|
+
onChange,
|
|
100
|
+
node,
|
|
101
|
+
nodes = [],
|
|
102
|
+
edges = [],
|
|
103
|
+
workflowId,
|
|
104
|
+
authProvider
|
|
105
|
+
}: Props = $props();
|
|
106
|
+
|
|
107
|
+
/** Loading state for API variable fetching */
|
|
108
|
+
let isLoadingVariables = $state(false);
|
|
109
|
+
|
|
110
|
+
/** Error state for API variable fetching */
|
|
111
|
+
let variableLoadError = $state<string | null>(null);
|
|
112
|
+
|
|
113
|
+
/** The effective variable schema (loaded synchronously or asynchronously) */
|
|
114
|
+
let effectiveVariableSchema = $state<VariableSchema | undefined>(undefined);
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Load variable schema on mount or when configuration changes.
|
|
118
|
+
* Handles both synchronous (schema-based) and asynchronous (API-based) loading.
|
|
119
|
+
*/
|
|
120
|
+
async function loadVariableSchema() {
|
|
121
|
+
// Reset error state
|
|
122
|
+
variableLoadError = null;
|
|
123
|
+
|
|
124
|
+
// If no variables config, clear schema
|
|
125
|
+
if (!variables) {
|
|
126
|
+
effectiveVariableSchema = undefined;
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// If variables config has static schema only (no API), use it directly
|
|
131
|
+
if (variables.schema && !variables.api && Object.keys(variables.schema.variables).length > 0) {
|
|
132
|
+
effectiveVariableSchema = variables.schema;
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// If variables config requires node context (ports or API mode)
|
|
137
|
+
if ((variables.ports !== undefined || variables.api) && node && nodes && edges) {
|
|
138
|
+
try {
|
|
139
|
+
isLoadingVariables = true;
|
|
140
|
+
effectiveVariableSchema = await getVariableSchema(
|
|
141
|
+
node,
|
|
142
|
+
nodes,
|
|
143
|
+
edges,
|
|
144
|
+
variables,
|
|
145
|
+
workflowId,
|
|
146
|
+
authProvider
|
|
147
|
+
);
|
|
148
|
+
} catch (error) {
|
|
149
|
+
logger.error('Failed to load variable schema:', error);
|
|
150
|
+
variableLoadError = error instanceof Error ? error.message : 'Failed to load variables';
|
|
151
|
+
effectiveVariableSchema = undefined;
|
|
152
|
+
} finally {
|
|
153
|
+
isLoadingVariables = false;
|
|
154
|
+
}
|
|
155
|
+
} else {
|
|
156
|
+
// No schema available
|
|
157
|
+
effectiveVariableSchema = undefined;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Retry loading variables after an error
|
|
163
|
+
*/
|
|
164
|
+
function retryLoadVariables() {
|
|
165
|
+
loadVariableSchema();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Whether to show the variable hints section.
|
|
170
|
+
* Controlled by variables.showHints (defaults to true).
|
|
171
|
+
*/
|
|
172
|
+
const showHints = $derived(variables?.showHints !== false);
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Derive the list of top-level variable names for the hints display.
|
|
176
|
+
*/
|
|
177
|
+
const displayVariables = $derived.by(() => {
|
|
178
|
+
if (effectiveVariableSchema) {
|
|
179
|
+
return Object.keys(effectiveVariableSchema.variables);
|
|
180
|
+
}
|
|
181
|
+
return [];
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
/** Reference to the container element */
|
|
185
|
+
let containerRef: HTMLDivElement | undefined = $state(undefined);
|
|
186
|
+
|
|
187
|
+
/** CodeMirror editor instance */
|
|
188
|
+
let editorView: EditorView | undefined = $state(undefined);
|
|
189
|
+
|
|
190
|
+
/** Flag to prevent update loops */
|
|
191
|
+
let isInternalUpdate = false;
|
|
192
|
+
|
|
193
|
+
/** Compartment for dynamic autocomplete reconfiguration */
|
|
194
|
+
const autocompleteCompartment = new Compartment();
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Custom Twig syntax highlighter using MatchDecorator
|
|
198
|
+
* Highlights three Twig delimiter types with different styles:
|
|
199
|
+
* - {{ expression }} — variables/output (purple)
|
|
200
|
+
* - {% block %} — control structures (teal)
|
|
201
|
+
* - {# comment #} — comments (gray/italic)
|
|
202
|
+
*/
|
|
203
|
+
const twigMatcher = new MatchDecorator({
|
|
204
|
+
regexp: /\{\{.*?\}\}|\{%.*?%\}|\{#.*?#\}/g,
|
|
205
|
+
decoration: (match) => {
|
|
206
|
+
const text = match[0];
|
|
207
|
+
if (text.startsWith('{{')) {
|
|
208
|
+
return Decoration.mark({ class: 'cm-twig-expression' });
|
|
209
|
+
} else if (text.startsWith('{%')) {
|
|
210
|
+
return Decoration.mark({ class: 'cm-twig-block' });
|
|
211
|
+
} else {
|
|
212
|
+
return Decoration.mark({ class: 'cm-twig-comment' });
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
const twigHighlighter = ViewPlugin.fromClass(
|
|
218
|
+
class {
|
|
219
|
+
decorations;
|
|
220
|
+
constructor(view: EditorView) {
|
|
221
|
+
this.decorations = twigMatcher.createDeco(view);
|
|
222
|
+
}
|
|
223
|
+
update(update: import('@codemirror/view').ViewUpdate) {
|
|
224
|
+
this.decorations = twigMatcher.updateDeco(update, this.decorations);
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
{ decorations: (v) => v.decorations }
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Handle editor content changes
|
|
232
|
+
*/
|
|
233
|
+
function handleUpdate(update: { docChanged: boolean; state: EditorState }): void {
|
|
234
|
+
if (!update.docChanged || isInternalUpdate) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const content = update.state.doc.toString();
|
|
239
|
+
onChange(content);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Create editor extensions array for template editing
|
|
244
|
+
* Includes autocomplete when variables are available
|
|
245
|
+
* When disabled is true, adds readOnly/editable so the editor cannot be modified
|
|
246
|
+
*/
|
|
247
|
+
function createExtensions() {
|
|
248
|
+
const extensions = [
|
|
249
|
+
// Position tooltips using fixed strategy so they aren't clipped by container overflow
|
|
250
|
+
tooltips({ position: 'fixed' }),
|
|
251
|
+
|
|
252
|
+
// Essential visual features
|
|
253
|
+
lineNumbers(),
|
|
254
|
+
highlightActiveLineGutter(),
|
|
255
|
+
highlightSpecialChars(),
|
|
256
|
+
highlightActiveLine(),
|
|
257
|
+
drawSelection(),
|
|
258
|
+
|
|
259
|
+
// Editing features (skip when read-only)
|
|
260
|
+
...(disabled
|
|
261
|
+
? []
|
|
262
|
+
: [history(), keymap.of([...defaultKeymap, ...historyKeymap, indentWithTab])]),
|
|
263
|
+
|
|
264
|
+
// Read-only: prevent document changes and mark content as non-editable
|
|
265
|
+
...(disabled ? [EditorState.readOnly.of(true), EditorView.editable.of(false)] : []),
|
|
266
|
+
|
|
267
|
+
// Syntax highlighting - use default for light mode, oneDark handles dark mode
|
|
268
|
+
...(darkTheme ? [] : [syntaxHighlighting(defaultHighlightStyle, { fallback: true })]),
|
|
269
|
+
|
|
270
|
+
// Twig syntax highlighting ({{ expressions }}, {% blocks %}, {# comments #})
|
|
271
|
+
twigHighlighter,
|
|
272
|
+
|
|
273
|
+
// Update listener (only fires on user edit when not disabled)
|
|
274
|
+
EditorView.updateListener.of(handleUpdate),
|
|
275
|
+
|
|
276
|
+
// Custom theme with autocomplete styling
|
|
277
|
+
EditorView.theme({
|
|
278
|
+
'&': {
|
|
279
|
+
height: height,
|
|
280
|
+
fontSize: '0.875rem',
|
|
281
|
+
fontFamily: "'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace"
|
|
282
|
+
},
|
|
283
|
+
'.cm-scroller': {
|
|
284
|
+
overflow: 'auto'
|
|
285
|
+
},
|
|
286
|
+
'.cm-content': {
|
|
287
|
+
minHeight: '100px',
|
|
288
|
+
padding: '0.5rem 0'
|
|
289
|
+
},
|
|
290
|
+
'&.cm-focused': {
|
|
291
|
+
outline: 'none'
|
|
292
|
+
},
|
|
293
|
+
'.cm-line': {
|
|
294
|
+
padding: '0 0.5rem'
|
|
295
|
+
},
|
|
296
|
+
// Twig expression: {{ variable }}
|
|
297
|
+
'.cm-twig-expression': {
|
|
298
|
+
color: '#a855f7',
|
|
299
|
+
backgroundColor: 'rgba(168, 85, 247, 0.1)',
|
|
300
|
+
borderRadius: '3px',
|
|
301
|
+
padding: '1px 2px',
|
|
302
|
+
fontWeight: '500'
|
|
303
|
+
},
|
|
304
|
+
// Twig block: {% for ... %}
|
|
305
|
+
'.cm-twig-block': {
|
|
306
|
+
color: '#14b8a6',
|
|
307
|
+
backgroundColor: 'rgba(20, 184, 166, 0.1)',
|
|
308
|
+
borderRadius: '3px',
|
|
309
|
+
padding: '1px 2px',
|
|
310
|
+
fontWeight: '500'
|
|
311
|
+
},
|
|
312
|
+
// Twig comment: {# ... #}
|
|
313
|
+
'.cm-twig-comment': {
|
|
314
|
+
color: '#6b7280',
|
|
315
|
+
fontStyle: 'italic'
|
|
316
|
+
},
|
|
317
|
+
// Autocomplete dropdown styling
|
|
318
|
+
'.cm-tooltip.cm-tooltip-autocomplete': {
|
|
319
|
+
backgroundColor: 'var(--fd-background, #ffffff)',
|
|
320
|
+
border: '1px solid var(--fd-border, #e5e7eb)',
|
|
321
|
+
borderRadius: 'var(--fd-radius-lg, 0.5rem)',
|
|
322
|
+
boxShadow: 'var(--fd-shadow-lg, 0 10px 15px -3px rgba(0, 0, 0, 0.1))',
|
|
323
|
+
padding: '0.25rem',
|
|
324
|
+
maxHeight: '200px',
|
|
325
|
+
overflow: 'auto'
|
|
326
|
+
},
|
|
327
|
+
'.cm-tooltip.cm-tooltip-autocomplete > ul': {
|
|
328
|
+
fontFamily: "'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace",
|
|
329
|
+
fontSize: '0.8125rem'
|
|
330
|
+
},
|
|
331
|
+
'.cm-tooltip.cm-tooltip-autocomplete > ul > li': {
|
|
332
|
+
padding: '0.375rem 0.625rem',
|
|
333
|
+
borderRadius: 'var(--fd-radius-md, 0.375rem)',
|
|
334
|
+
display: 'flex',
|
|
335
|
+
alignItems: 'center',
|
|
336
|
+
gap: '0.5rem'
|
|
337
|
+
},
|
|
338
|
+
'.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]': {
|
|
339
|
+
backgroundColor: 'var(--fd-accent-muted, rgba(168, 85, 247, 0.1))',
|
|
340
|
+
color: 'var(--fd-accent-hover, #7c3aed)'
|
|
341
|
+
},
|
|
342
|
+
'.cm-completionLabel': {
|
|
343
|
+
flex: '1'
|
|
344
|
+
},
|
|
345
|
+
'.cm-completionDetail': {
|
|
346
|
+
fontSize: '0.6875rem',
|
|
347
|
+
color: 'var(--fd-muted-foreground, #6b7280)',
|
|
348
|
+
opacity: '0.8'
|
|
349
|
+
}
|
|
350
|
+
}),
|
|
351
|
+
EditorView.lineWrapping,
|
|
352
|
+
EditorState.tabSize.of(2)
|
|
353
|
+
];
|
|
354
|
+
|
|
355
|
+
// Add autocomplete compartment (can be reconfigured dynamically)
|
|
356
|
+
// When disabled or no schema, use empty array
|
|
357
|
+
if (!disabled && effectiveVariableSchema) {
|
|
358
|
+
extensions.push(
|
|
359
|
+
autocompleteCompartment.of(createTemplateAutocomplete(effectiveVariableSchema))
|
|
360
|
+
);
|
|
361
|
+
} else {
|
|
362
|
+
extensions.push(autocompleteCompartment.of([]));
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (darkTheme) {
|
|
366
|
+
extensions.push(oneDark);
|
|
367
|
+
// Add dark theme overrides for Twig highlighting and autocomplete
|
|
368
|
+
extensions.push(
|
|
369
|
+
EditorView.theme({
|
|
370
|
+
'.cm-twig-expression': {
|
|
371
|
+
color: '#c084fc',
|
|
372
|
+
backgroundColor: 'rgba(192, 132, 252, 0.15)'
|
|
373
|
+
},
|
|
374
|
+
'.cm-twig-block': {
|
|
375
|
+
color: '#5eead4',
|
|
376
|
+
backgroundColor: 'rgba(94, 234, 212, 0.1)'
|
|
377
|
+
},
|
|
378
|
+
'.cm-twig-comment': {
|
|
379
|
+
color: '#6b7280'
|
|
380
|
+
},
|
|
381
|
+
'.cm-tooltip.cm-tooltip-autocomplete': {
|
|
382
|
+
backgroundColor: '#1e1e1e',
|
|
383
|
+
border: '1px solid #3e4451',
|
|
384
|
+
boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.3)'
|
|
385
|
+
},
|
|
386
|
+
'.cm-tooltip.cm-tooltip-autocomplete > ul > li[aria-selected]': {
|
|
387
|
+
backgroundColor: 'rgba(192, 132, 252, 0.2)',
|
|
388
|
+
color: '#c084fc'
|
|
389
|
+
}
|
|
390
|
+
})
|
|
391
|
+
);
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
return extensions;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Insert a variable placeholder at current cursor position
|
|
399
|
+
*/
|
|
400
|
+
function insertVariable(varName: string): void {
|
|
401
|
+
if (!editorView) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
const insertText = `{{ ${varName} }}`;
|
|
406
|
+
const { from, to } = editorView.state.selection.main;
|
|
407
|
+
|
|
408
|
+
editorView.dispatch({
|
|
409
|
+
changes: { from, to, insert: insertText },
|
|
410
|
+
selection: { anchor: from + insertText.length }
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
editorView.focus();
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Initialize CodeMirror editor and load variables on mount
|
|
418
|
+
*/
|
|
419
|
+
onMount(() => {
|
|
420
|
+
if (!containerRef) {
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
// Load variables first
|
|
425
|
+
loadVariableSchema().then(() => {
|
|
426
|
+
// Then create editor with loaded schema
|
|
427
|
+
editorView = new EditorView({
|
|
428
|
+
state: EditorState.create({
|
|
429
|
+
doc: value,
|
|
430
|
+
extensions: createExtensions()
|
|
431
|
+
}),
|
|
432
|
+
parent: containerRef
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
});
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* Clean up editor on destroy
|
|
439
|
+
*/
|
|
440
|
+
onDestroy(() => {
|
|
441
|
+
if (editorView) {
|
|
442
|
+
editorView.destroy();
|
|
443
|
+
}
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Update editor content when value prop changes externally
|
|
448
|
+
*/
|
|
449
|
+
$effect(() => {
|
|
450
|
+
if (!editorView) {
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
const currentContent = editorView.state.doc.toString();
|
|
455
|
+
|
|
456
|
+
// Only update if content actually changed and wasn't from internal edit
|
|
457
|
+
if (value !== currentContent && !isInternalUpdate) {
|
|
458
|
+
isInternalUpdate = true;
|
|
459
|
+
editorView.dispatch({
|
|
460
|
+
changes: {
|
|
461
|
+
from: 0,
|
|
462
|
+
to: editorView.state.doc.length,
|
|
463
|
+
insert: value
|
|
464
|
+
}
|
|
465
|
+
});
|
|
466
|
+
isInternalUpdate = false;
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
/**
|
|
471
|
+
* Reconfigure editor when variable schema changes (e.g., after async loading)
|
|
472
|
+
*/
|
|
473
|
+
$effect(() => {
|
|
474
|
+
// Only track effectiveVariableSchema changes
|
|
475
|
+
const schema = effectiveVariableSchema;
|
|
476
|
+
|
|
477
|
+
if (!editorView) {
|
|
478
|
+
return;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// When effectiveVariableSchema changes, reconfigure the autocomplete compartment
|
|
482
|
+
// This happens after async API loading completes
|
|
483
|
+
const newAutocomplete = !disabled && schema ? createTemplateAutocomplete(schema) : [];
|
|
484
|
+
|
|
485
|
+
editorView.dispatch({
|
|
486
|
+
effects: [autocompleteCompartment.reconfigure(newAutocomplete)]
|
|
487
|
+
});
|
|
488
|
+
});
|
|
489
|
+
</script>
|
|
490
|
+
|
|
491
|
+
<div class="form-template-editor">
|
|
492
|
+
<!-- Hidden input for form submission compatibility -->
|
|
493
|
+
<input
|
|
494
|
+
type="hidden"
|
|
495
|
+
{id}
|
|
496
|
+
name={id}
|
|
497
|
+
{value}
|
|
498
|
+
aria-describedby={ariaDescribedBy}
|
|
499
|
+
aria-required={required}
|
|
500
|
+
/>
|
|
501
|
+
|
|
502
|
+
<!-- CodeMirror container -->
|
|
503
|
+
<div
|
|
504
|
+
bind:this={containerRef}
|
|
505
|
+
class="form-template-editor__container"
|
|
506
|
+
class:form-template-editor__container--dark={darkTheme}
|
|
507
|
+
role="textbox"
|
|
508
|
+
aria-multiline="true"
|
|
509
|
+
aria-label="Template editor"
|
|
510
|
+
></div>
|
|
511
|
+
|
|
512
|
+
<!-- Loading banner (shown while fetching variables from API) -->
|
|
513
|
+
{#if isLoadingVariables}
|
|
514
|
+
<div class="form-template-editor__banner form-template-editor__banner--loading">
|
|
515
|
+
<svg
|
|
516
|
+
class="form-template-editor__banner-icon form-template-editor__banner-icon--spin"
|
|
517
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
518
|
+
fill="none"
|
|
519
|
+
viewBox="0 0 24 24"
|
|
520
|
+
>
|
|
521
|
+
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"
|
|
522
|
+
></circle>
|
|
523
|
+
<path
|
|
524
|
+
class="opacity-75"
|
|
525
|
+
fill="currentColor"
|
|
526
|
+
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
527
|
+
></path>
|
|
528
|
+
</svg>
|
|
529
|
+
<span>Loading variables...</span>
|
|
530
|
+
</div>
|
|
531
|
+
{/if}
|
|
532
|
+
|
|
533
|
+
<!-- Error banner (shown when API fetch fails) -->
|
|
534
|
+
{#if variableLoadError}
|
|
535
|
+
<div class="form-template-editor__banner form-template-editor__banner--error">
|
|
536
|
+
<svg
|
|
537
|
+
class="form-template-editor__banner-icon"
|
|
538
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
539
|
+
viewBox="0 0 20 20"
|
|
540
|
+
fill="currentColor"
|
|
541
|
+
>
|
|
542
|
+
<path
|
|
543
|
+
fill-rule="evenodd"
|
|
544
|
+
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z"
|
|
545
|
+
clip-rule="evenodd"
|
|
546
|
+
/>
|
|
547
|
+
</svg>
|
|
548
|
+
<span>{variableLoadError}</span>
|
|
549
|
+
<button
|
|
550
|
+
type="button"
|
|
551
|
+
class="form-template-editor__banner-btn"
|
|
552
|
+
onclick={retryLoadVariables}
|
|
553
|
+
title="Retry loading variables"
|
|
554
|
+
>
|
|
555
|
+
Retry
|
|
556
|
+
</button>
|
|
557
|
+
</div>
|
|
558
|
+
{/if}
|
|
559
|
+
|
|
560
|
+
<!-- Variable hints section (shown when variables are available and showHints is true) -->
|
|
561
|
+
{#if showHints && displayVariables.length > 0}
|
|
562
|
+
<div class="form-template-editor__hints">
|
|
563
|
+
<span class="form-template-editor__hints-label">Available variables:</span>
|
|
564
|
+
<div class="form-template-editor__hints-list">
|
|
565
|
+
{#each displayVariables as varName (varName)}
|
|
566
|
+
<button
|
|
567
|
+
type="button"
|
|
568
|
+
class="form-template-editor__hint-btn"
|
|
569
|
+
onclick={() => insertVariable(varName)}
|
|
570
|
+
title={`Insert {{ ${varName} }}`}
|
|
571
|
+
>
|
|
572
|
+
<code>{'{{ '}{varName}{' }}'}</code>
|
|
573
|
+
</button>
|
|
574
|
+
{/each}
|
|
575
|
+
</div>
|
|
576
|
+
</div>
|
|
577
|
+
{/if}
|
|
578
|
+
|
|
579
|
+
<!-- Placeholder hint when empty -->
|
|
580
|
+
{#if !value && placeholderExample}
|
|
581
|
+
<div class="form-template-editor__placeholder">
|
|
582
|
+
<span class="form-template-editor__placeholder-label">Example template:</span>
|
|
583
|
+
<code class="form-template-editor__placeholder-example">{placeholderExample}</code>
|
|
584
|
+
</div>
|
|
585
|
+
{/if}
|
|
586
|
+
|
|
587
|
+
<!-- Syntax help -->
|
|
588
|
+
<div class="form-template-editor__help">
|
|
589
|
+
<svg
|
|
590
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
591
|
+
viewBox="0 0 20 20"
|
|
592
|
+
fill="currentColor"
|
|
593
|
+
class="form-template-editor__help-icon"
|
|
594
|
+
>
|
|
595
|
+
<path
|
|
596
|
+
fill-rule="evenodd"
|
|
597
|
+
d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a.75.75 0 000 1.5h.253a.25.25 0 01.244.304l-.459 2.066A1.75 1.75 0 0010.747 15H11a.75.75 0 000-1.5h-.253a.25.25 0 01-.244-.304l.459-2.066A1.75 1.75 0 009.253 9H9z"
|
|
598
|
+
clip-rule="evenodd"
|
|
599
|
+
/>
|
|
600
|
+
</svg>
|
|
601
|
+
<span
|
|
602
|
+
>Use <code>{'{{ variable }}'}</code> syntax to insert dynamic values from the data input</span
|
|
603
|
+
>
|
|
604
|
+
</div>
|
|
605
|
+
</div>
|
|
606
|
+
|
|
607
|
+
<style>
|
|
608
|
+
.form-template-editor {
|
|
609
|
+
position: relative;
|
|
610
|
+
width: 100%;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
.form-template-editor__container {
|
|
614
|
+
border: 1px solid var(--fd-border);
|
|
615
|
+
border-radius: var(--fd-radius-lg);
|
|
616
|
+
overflow: hidden;
|
|
617
|
+
background-color: var(--fd-muted);
|
|
618
|
+
transition: all var(--fd-transition-normal);
|
|
619
|
+
box-shadow: var(--fd-shadow-sm);
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
.form-template-editor__container:hover {
|
|
623
|
+
border-color: var(--fd-border-strong);
|
|
624
|
+
background-color: var(--fd-background);
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
.form-template-editor__container:focus-within {
|
|
628
|
+
border-color: var(--fd-accent);
|
|
629
|
+
background-color: var(--fd-background);
|
|
630
|
+
box-shadow:
|
|
631
|
+
0 0 0 3px rgba(168, 85, 247, 0.12),
|
|
632
|
+
var(--fd-shadow-sm);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/* Dark theme overrides */
|
|
636
|
+
.form-template-editor__container--dark {
|
|
637
|
+
background-color: #282c34;
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
.form-template-editor__container--dark:hover,
|
|
641
|
+
.form-template-editor__container--dark:focus-within {
|
|
642
|
+
background-color: #282c34;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
/* CodeMirror styling overrides */
|
|
646
|
+
.form-template-editor__container :global(.cm-editor) {
|
|
647
|
+
border-radius: var(--fd-radius-lg);
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
.form-template-editor__container :global(.cm-gutters) {
|
|
651
|
+
background-color: var(--fd-subtle);
|
|
652
|
+
border-right: 1px solid var(--fd-border);
|
|
653
|
+
border-radius: var(--fd-radius-lg) 0 0 var(--fd-radius-lg);
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
.form-template-editor__container--dark :global(.cm-gutters) {
|
|
657
|
+
background-color: #21252b;
|
|
658
|
+
border-right-color: #3e4451;
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
/* Variable hints section */
|
|
662
|
+
.form-template-editor__hints {
|
|
663
|
+
margin-top: 0.625rem;
|
|
664
|
+
padding: 0.625rem;
|
|
665
|
+
background-color: var(--fd-accent-muted);
|
|
666
|
+
border: 1px solid var(--fd-accent);
|
|
667
|
+
border-radius: var(--fd-radius-md);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
.form-template-editor__hints-label {
|
|
671
|
+
display: block;
|
|
672
|
+
font-size: 0.6875rem;
|
|
673
|
+
font-weight: 500;
|
|
674
|
+
color: var(--fd-accent-hover);
|
|
675
|
+
text-transform: uppercase;
|
|
676
|
+
letter-spacing: 0.05em;
|
|
677
|
+
margin-bottom: 0.375rem;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
.form-template-editor__hints-list {
|
|
681
|
+
display: flex;
|
|
682
|
+
flex-wrap: wrap;
|
|
683
|
+
gap: 0.375rem;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
.form-template-editor__hint-btn {
|
|
687
|
+
padding: 0.25rem 0.5rem;
|
|
688
|
+
background-color: var(--fd-accent-muted);
|
|
689
|
+
border: 1px solid var(--fd-accent);
|
|
690
|
+
border-radius: var(--fd-radius-sm);
|
|
691
|
+
cursor: pointer;
|
|
692
|
+
transition: all var(--fd-transition-fast);
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
.form-template-editor__hint-btn:hover {
|
|
696
|
+
background-color: var(--fd-accent);
|
|
697
|
+
border-color: var(--fd-accent-hover);
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
.form-template-editor__hint-btn:active {
|
|
701
|
+
transform: scale(0.98);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.form-template-editor__hint-btn code {
|
|
705
|
+
font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace;
|
|
706
|
+
font-size: 0.6875rem;
|
|
707
|
+
color: var(--fd-accent-hover);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/* Placeholder hint */
|
|
711
|
+
.form-template-editor__placeholder {
|
|
712
|
+
margin-top: 0.5rem;
|
|
713
|
+
padding: 0.5rem 0.75rem;
|
|
714
|
+
background-color: var(--fd-muted);
|
|
715
|
+
border: 1px dashed var(--fd-border-strong);
|
|
716
|
+
border-radius: var(--fd-radius-md);
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
.form-template-editor__placeholder-label {
|
|
720
|
+
display: block;
|
|
721
|
+
font-size: 0.6875rem;
|
|
722
|
+
font-weight: 500;
|
|
723
|
+
color: var(--fd-muted-foreground);
|
|
724
|
+
text-transform: uppercase;
|
|
725
|
+
letter-spacing: 0.05em;
|
|
726
|
+
margin-bottom: 0.25rem;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
.form-template-editor__placeholder-example {
|
|
730
|
+
display: block;
|
|
731
|
+
font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace;
|
|
732
|
+
font-size: var(--fd-text-xs);
|
|
733
|
+
color: var(--fd-foreground);
|
|
734
|
+
word-break: break-all;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
/* Help text */
|
|
738
|
+
.form-template-editor__help {
|
|
739
|
+
display: flex;
|
|
740
|
+
align-items: flex-start;
|
|
741
|
+
gap: 0.375rem;
|
|
742
|
+
margin-top: 0.5rem;
|
|
743
|
+
font-size: 0.6875rem;
|
|
744
|
+
color: var(--fd-muted-foreground);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.form-template-editor__help-icon {
|
|
748
|
+
width: 0.875rem;
|
|
749
|
+
height: 0.875rem;
|
|
750
|
+
flex-shrink: 0;
|
|
751
|
+
margin-top: 0.0625rem;
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
.form-template-editor__help code {
|
|
755
|
+
padding: 0.0625rem 0.25rem;
|
|
756
|
+
background-color: var(--fd-subtle);
|
|
757
|
+
border-radius: var(--fd-radius-sm);
|
|
758
|
+
font-family: 'JetBrains Mono', 'Fira Code', 'Monaco', 'Menlo', monospace;
|
|
759
|
+
font-size: 0.625rem;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
/* Loading and error banners */
|
|
763
|
+
.form-template-editor__banner {
|
|
764
|
+
display: flex;
|
|
765
|
+
align-items: center;
|
|
766
|
+
gap: 0.5rem;
|
|
767
|
+
margin-top: 0.625rem;
|
|
768
|
+
padding: 0.625rem 0.75rem;
|
|
769
|
+
border-radius: var(--fd-radius-md);
|
|
770
|
+
font-size: 0.75rem;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
.form-template-editor__banner--loading {
|
|
774
|
+
background-color: rgba(59, 130, 246, 0.1);
|
|
775
|
+
border: 1px solid rgba(59, 130, 246, 0.3);
|
|
776
|
+
color: rgb(29, 78, 216);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
.form-template-editor__banner--error {
|
|
780
|
+
background-color: rgba(239, 68, 68, 0.1);
|
|
781
|
+
border: 1px solid rgba(239, 68, 68, 0.3);
|
|
782
|
+
color: rgb(185, 28, 28);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
.form-template-editor__banner-icon {
|
|
786
|
+
width: 1rem;
|
|
787
|
+
height: 1rem;
|
|
788
|
+
flex-shrink: 0;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
.form-template-editor__banner-icon--spin {
|
|
792
|
+
animation: spin 1s linear infinite;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
@keyframes spin {
|
|
796
|
+
from {
|
|
797
|
+
transform: rotate(0deg);
|
|
798
|
+
}
|
|
799
|
+
to {
|
|
800
|
+
transform: rotate(360deg);
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.form-template-editor__banner-btn {
|
|
805
|
+
margin-left: auto;
|
|
806
|
+
padding: 0.25rem 0.625rem;
|
|
807
|
+
background-color: rgba(239, 68, 68, 0.15);
|
|
808
|
+
border: 1px solid rgba(239, 68, 68, 0.3);
|
|
809
|
+
border-radius: var(--fd-radius-sm);
|
|
810
|
+
font-size: 0.6875rem;
|
|
811
|
+
font-weight: 500;
|
|
812
|
+
color: rgb(185, 28, 28);
|
|
813
|
+
cursor: pointer;
|
|
814
|
+
transition: all var(--fd-transition-fast);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
.form-template-editor__banner-btn:hover {
|
|
818
|
+
background-color: rgba(239, 68, 68, 0.25);
|
|
819
|
+
border-color: rgba(239, 68, 68, 0.5);
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
.form-template-editor__banner-btn:active {
|
|
823
|
+
transform: scale(0.98);
|
|
824
|
+
}
|
|
825
|
+
</style>
|