@flowdrop/flowdrop 1.15.0 → 2.0.0-beta.2

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.
Files changed (235) hide show
  1. package/CHANGELOG.md +508 -0
  2. package/MIGRATION-2.0.md +629 -0
  3. package/README.md +23 -23
  4. package/dist/adapters/WorkflowAdapter.d.ts +1 -1
  5. package/dist/adapters/WorkflowAdapter.js +14 -8
  6. package/dist/adapters/agentspec/AgentSpecAdapter.js +7 -7
  7. package/dist/api/enhanced-client.js +6 -11
  8. package/dist/chat/batchFeedback.d.ts +39 -0
  9. package/dist/chat/batchFeedback.js +51 -0
  10. package/dist/commands/executor.js +15 -1
  11. package/dist/commands/storeIntegration.svelte.d.ts +4 -1
  12. package/dist/commands/storeIntegration.svelte.js +26 -21
  13. package/dist/commands/types.d.ts +2 -0
  14. package/dist/components/App.svelte +163 -192
  15. package/dist/components/App.svelte.d.ts +47 -8
  16. package/dist/components/ConfigForm.svelte +77 -49
  17. package/dist/components/ConfigModal.svelte +7 -2
  18. package/dist/components/ConnectionLine.svelte +4 -2
  19. package/dist/components/Navbar.svelte +61 -1
  20. package/dist/components/NodeSidebar.svelte +27 -45
  21. package/dist/components/NodeStatusOverlay.svelte +94 -6
  22. package/dist/components/NodeSwapPicker.svelte +10 -8
  23. package/dist/components/PipelineStatus.svelte +22 -68
  24. package/dist/components/PipelineStatus.svelte.d.ts +3 -0
  25. package/dist/components/PortCoordinateTracker.svelte +5 -6
  26. package/dist/components/SchemaForm.stories.svelte +1 -3
  27. package/dist/components/SchemaForm.svelte +22 -27
  28. package/dist/components/SchemaForm.svelte.d.ts +0 -8
  29. package/dist/components/SettingsModal.svelte +8 -3
  30. package/dist/components/SettingsPanel.svelte +20 -4
  31. package/dist/components/SwapMappingEditor.svelte +67 -49
  32. package/dist/components/SwapMappingEditor.svelte.d.ts +0 -2
  33. package/dist/components/UniversalNode.svelte +9 -7
  34. package/dist/components/WorkflowEditor.svelte +121 -111
  35. package/dist/components/WorkflowEditor.svelte.d.ts +21 -10
  36. package/dist/components/chat/AIChatPanel.svelte +98 -89
  37. package/dist/components/chat/AIChatPanel.svelte.d.ts +0 -4
  38. package/dist/components/chat/CommandPreview.svelte +2 -1
  39. package/dist/components/console/CommandConsole.svelte +7 -5
  40. package/dist/components/console/ConsoleAutocomplete.svelte +10 -11
  41. package/dist/components/console/ConsoleAutocomplete.svelte.d.ts +6 -0
  42. package/dist/components/console/ConsoleInput.svelte +15 -6
  43. package/dist/components/console/ConsoleOutput.svelte +2 -1
  44. package/dist/components/form/FormArray.svelte +5 -9
  45. package/dist/components/form/FormArray.svelte.d.ts +2 -1
  46. package/dist/components/form/FormAutocomplete.svelte +16 -15
  47. package/dist/components/form/FormField.svelte +4 -2
  48. package/dist/components/form/FormFieldLight.svelte +34 -3
  49. package/dist/components/form/FormFieldLight.svelte.d.ts +12 -0
  50. package/dist/components/form/FormMarkdownEditor.svelte +9 -4
  51. package/dist/components/form/FormRangeField.svelte +1 -0
  52. package/dist/components/form/FormTemplateEditor.svelte +11 -3
  53. package/dist/components/form/FormToggle.svelte +5 -12
  54. package/dist/components/form/FormToggle.svelte.d.ts +4 -2
  55. package/dist/components/form/FormUISchemaRenderer.svelte +3 -1
  56. package/dist/components/form/templateAutocomplete.js +1 -5
  57. package/dist/components/form/types.d.ts +1 -14
  58. package/dist/components/interrupt/FormPrompt.svelte +3 -2
  59. package/dist/components/interrupt/InterruptBubble.svelte +25 -17
  60. package/dist/components/interrupt/ReviewPrompt.svelte +10 -3
  61. package/dist/components/interrupt/TextInputPrompt.svelte +2 -1
  62. package/dist/components/layouts/MainLayout.svelte +20 -13
  63. package/dist/components/layouts/MainLayout.svelte.d.ts +4 -0
  64. package/dist/components/nodes/AtomNode.svelte +17 -5
  65. package/dist/components/nodes/GatewayNode.svelte +19 -10
  66. package/dist/components/nodes/IdeaNode.svelte +7 -0
  67. package/dist/components/nodes/SimpleNode.svelte +11 -6
  68. package/dist/components/nodes/SquareNode.svelte +15 -8
  69. package/dist/components/nodes/TerminalNode.svelte +9 -4
  70. package/dist/components/nodes/ToolNode.svelte +7 -1
  71. package/dist/components/nodes/WorkflowNode.svelte +16 -7
  72. package/dist/components/playground/ChatInput.svelte +11 -14
  73. package/dist/components/playground/ChatPanel.svelte +6 -49
  74. package/dist/components/playground/ChatPanel.svelte.d.ts +0 -14
  75. package/dist/components/playground/ControlPanel.svelte +134 -123
  76. package/dist/components/playground/ControlPanel.svelte.d.ts +3 -0
  77. package/dist/components/playground/ExecutionLogs.svelte +11 -9
  78. package/dist/components/playground/InputCollector.svelte +11 -9
  79. package/dist/components/playground/MessageStream.svelte +17 -23
  80. package/dist/components/playground/PipelineKanbanView.svelte +69 -8
  81. package/dist/components/playground/PipelineKanbanView.svelte.d.ts +2 -0
  82. package/dist/components/playground/PipelinePanel.svelte +31 -8
  83. package/dist/components/playground/PipelinePanel.svelte.d.ts +2 -0
  84. package/dist/components/playground/PipelineTableView.svelte +188 -44
  85. package/dist/components/playground/PipelineTableView.svelte.d.ts +2 -0
  86. package/dist/components/playground/Playground.svelte +154 -105
  87. package/dist/components/playground/Playground.svelte.d.ts +5 -0
  88. package/dist/components/playground/PlaygroundApp.svelte +11 -1
  89. package/dist/components/playground/PlaygroundApp.svelte.d.ts +6 -0
  90. package/dist/components/playground/PlaygroundModal.svelte +18 -3
  91. package/dist/components/playground/PlaygroundModal.svelte.d.ts +6 -0
  92. package/dist/components/playground/PlaygroundStudio.svelte +40 -32
  93. package/dist/components/playground/PlaygroundStudio.svelte.d.ts +6 -0
  94. package/dist/components/playground/SessionManager.svelte +9 -12
  95. package/dist/components/playground/pipelineViewUtils.svelte.d.ts +30 -1
  96. package/dist/components/playground/pipelineViewUtils.svelte.js +40 -3
  97. package/dist/config/endpoints.d.ts +23 -7
  98. package/dist/config/endpoints.js +30 -10
  99. package/dist/core/index.d.ts +5 -6
  100. package/dist/core/index.js +8 -12
  101. package/dist/display/index.d.ts +6 -3
  102. package/dist/display/index.js +7 -5
  103. package/dist/editor/index.d.ts +20 -21
  104. package/dist/editor/index.js +26 -36
  105. package/dist/form/code.d.ts +25 -15
  106. package/dist/form/code.js +44 -41
  107. package/dist/form/fieldRegistry.d.ts +17 -13
  108. package/dist/form/fieldRegistry.js +32 -12
  109. package/dist/form/full.d.ts +19 -14
  110. package/dist/form/full.js +26 -28
  111. package/dist/form/index.d.ts +3 -4
  112. package/dist/form/index.js +6 -5
  113. package/dist/form/markdown.d.ts +13 -8
  114. package/dist/form/markdown.js +22 -23
  115. package/dist/helpers/proximityConnect.d.ts +3 -2
  116. package/dist/helpers/proximityConnect.js +2 -5
  117. package/dist/helpers/workflowEditorHelper.d.ts +14 -5
  118. package/dist/helpers/workflowEditorHelper.js +28 -25
  119. package/dist/index.d.ts +28 -24
  120. package/dist/index.js +27 -50
  121. package/dist/messages/defaults.d.ts +2 -5
  122. package/dist/messages/defaults.js +3 -6
  123. package/dist/messages/index.d.ts +0 -1
  124. package/dist/messages/index.js +0 -1
  125. package/dist/mocks/app-forms.d.ts +6 -2
  126. package/dist/mocks/app-forms.js +11 -4
  127. package/dist/openapi/v1/openapi.yaml +3 -3
  128. package/dist/playground/index.d.ts +4 -5
  129. package/dist/playground/index.js +4 -32
  130. package/dist/playground/mount.d.ts +25 -0
  131. package/dist/playground/mount.js +50 -20
  132. package/dist/registry/{BaseRegistry.d.ts → BaseRegistry.svelte.d.ts} +22 -1
  133. package/dist/registry/{BaseRegistry.js → BaseRegistry.svelte.js} +37 -1
  134. package/dist/registry/builtinFormats.d.ts +9 -18
  135. package/dist/registry/builtinFormats.js +9 -39
  136. package/dist/registry/builtinNodeTypes.d.ts +53 -0
  137. package/dist/registry/builtinNodeTypes.js +67 -0
  138. package/dist/registry/builtinNodes.d.ts +2 -64
  139. package/dist/registry/builtinNodes.js +7 -103
  140. package/dist/registry/index.d.ts +3 -4
  141. package/dist/registry/index.js +4 -6
  142. package/dist/registry/nodeComponentRegistry.d.ts +182 -15
  143. package/dist/registry/nodeComponentRegistry.js +235 -17
  144. package/dist/registry/workflowFormatRegistry.d.ts +14 -9
  145. package/dist/registry/workflowFormatRegistry.js +24 -8
  146. package/dist/{schema → schemas}/index.d.ts +2 -2
  147. package/dist/{schema → schemas}/index.js +2 -2
  148. package/dist/schemas/v1/workflow.schema.json +3 -3
  149. package/dist/services/agentSpecExecutionService.d.ts +0 -2
  150. package/dist/services/agentSpecExecutionService.js +0 -3
  151. package/dist/services/apiVariableService.d.ts +2 -1
  152. package/dist/services/apiVariableService.js +16 -47
  153. package/dist/services/autoSaveService.d.ts +7 -0
  154. package/dist/services/autoSaveService.js +6 -4
  155. package/dist/services/categoriesApi.js +3 -6
  156. package/dist/services/chatService.d.ts +9 -4
  157. package/dist/services/chatService.js +23 -28
  158. package/dist/services/draftStorage.d.ts +129 -13
  159. package/dist/services/draftStorage.js +185 -37
  160. package/dist/services/dynamicSchemaService.d.ts +2 -1
  161. package/dist/services/dynamicSchemaService.js +5 -22
  162. package/dist/services/globalSave.d.ts +13 -12
  163. package/dist/services/globalSave.js +29 -51
  164. package/dist/services/historyService.d.ts +9 -3
  165. package/dist/services/historyService.js +9 -3
  166. package/dist/services/interruptService.d.ts +15 -9
  167. package/dist/services/interruptService.js +35 -37
  168. package/dist/services/nodeExecutionService.d.ts +18 -3
  169. package/dist/services/nodeExecutionService.js +71 -45
  170. package/dist/services/playgroundService.d.ts +16 -10
  171. package/dist/services/playgroundService.js +42 -43
  172. package/dist/services/portConfigApi.js +3 -6
  173. package/dist/services/settingsService.d.ts +9 -4
  174. package/dist/services/settingsService.js +23 -12
  175. package/dist/services/variableService.d.ts +2 -1
  176. package/dist/services/variableService.js +2 -2
  177. package/dist/services/workflowStorage.js +6 -6
  178. package/dist/stores/apiContext.d.ts +56 -0
  179. package/dist/stores/apiContext.js +80 -0
  180. package/dist/stores/categoriesStore.svelte.d.ts +28 -23
  181. package/dist/stores/categoriesStore.svelte.js +69 -64
  182. package/dist/stores/getInstance.svelte.d.ts +39 -0
  183. package/dist/stores/getInstance.svelte.js +65 -0
  184. package/dist/stores/historyStore.svelte.d.ts +77 -93
  185. package/dist/stores/historyStore.svelte.js +134 -160
  186. package/dist/stores/instanceContainer.svelte.d.ts +111 -0
  187. package/dist/stores/instanceContainer.svelte.js +114 -0
  188. package/dist/stores/interruptStore.svelte.d.ts +112 -82
  189. package/dist/stores/interruptStore.svelte.js +253 -226
  190. package/dist/stores/pipelinePanelStore.svelte.d.ts +27 -3
  191. package/dist/stores/pipelinePanelStore.svelte.js +61 -14
  192. package/dist/stores/playgroundStore.svelte.d.ts +169 -222
  193. package/dist/stores/playgroundStore.svelte.js +513 -580
  194. package/dist/stores/portCoordinateStore.svelte.d.ts +57 -51
  195. package/dist/stores/portCoordinateStore.svelte.js +109 -98
  196. package/dist/stores/settingsStore.svelte.d.ts +4 -1
  197. package/dist/stores/settingsStore.svelte.js +47 -12
  198. package/dist/stores/workflowStore.svelte.d.ts +178 -213
  199. package/dist/stores/workflowStore.svelte.js +449 -501
  200. package/dist/stories/EdgeDecorator.svelte +5 -2
  201. package/dist/stories/NodeDecorator.svelte +5 -3
  202. package/dist/svelte-app.d.ts +60 -10
  203. package/dist/svelte-app.js +159 -54
  204. package/dist/types/auth.d.ts +9 -51
  205. package/dist/types/auth.js +4 -54
  206. package/dist/types/events.d.ts +6 -3
  207. package/dist/types/index.d.ts +37 -5
  208. package/dist/types/index.js +0 -1
  209. package/dist/types/navbar.d.ts +7 -0
  210. package/dist/types/playground.d.ts +18 -3
  211. package/dist/types/settings.d.ts +13 -0
  212. package/dist/types/settings.js +1 -0
  213. package/dist/utils/colors.d.ts +47 -21
  214. package/dist/utils/colors.js +69 -68
  215. package/dist/utils/connections.d.ts +9 -15
  216. package/dist/utils/connections.js +13 -32
  217. package/dist/utils/duration.d.ts +13 -0
  218. package/dist/utils/duration.js +45 -0
  219. package/dist/utils/edgeStyling.js +9 -5
  220. package/dist/utils/fetchWithAuth.d.ts +36 -15
  221. package/dist/utils/fetchWithAuth.js +53 -23
  222. package/dist/utils/icons.d.ts +5 -2
  223. package/dist/utils/icons.js +6 -5
  224. package/dist/utils/nodeSwap.d.ts +6 -2
  225. package/dist/utils/nodeSwap.js +62 -126
  226. package/dist/utils/nodeTypes.d.ts +17 -8
  227. package/dist/utils/nodeTypes.js +27 -20
  228. package/dist/utils/performanceUtils.js +7 -0
  229. package/package.json +7 -5
  230. package/dist/messages/deprecation.d.ts +0 -20
  231. package/dist/messages/deprecation.js +0 -33
  232. package/dist/registry/plugin.d.ts +0 -215
  233. package/dist/registry/plugin.js +0 -249
  234. package/dist/services/api.d.ts +0 -129
  235. package/dist/services/api.js +0 -217
@@ -45,7 +45,9 @@
45
45
  import { getSchemaOptions } from './types.js';
46
46
  import type { WorkflowNode, WorkflowEdge, AuthProvider } from '../../types/index.js';
47
47
  import { getResolvedTheme } from '../../stores/settingsStore.svelte.js';
48
- import { fieldComponentRegistry } from '../../form/fieldRegistry.js';
48
+ import { getInstance } from '../../stores/getInstance.svelte.js';
49
+
50
+ const fd = getInstance();
49
51
 
50
52
  interface Props {
51
53
  /** Unique key/id for the field */
@@ -226,7 +228,7 @@
226
228
  });
227
229
 
228
230
  const registeredAutocompleteComponent = $derived(
229
- fieldType === 'autocomplete' ? fieldComponentRegistry.resolveFieldComponent(schema) : null
231
+ fieldType === 'autocomplete' ? fd.fields.resolveFieldComponent(schema) : null
230
232
  );
231
233
 
232
234
  /**
@@ -42,10 +42,14 @@
42
42
  import FormSelect from './FormSelect.svelte';
43
43
  import FormCheckboxGroup from './FormCheckboxGroup.svelte';
44
44
  import FormArray from './FormArray.svelte';
45
- import { fieldComponentRegistry } from '../../form/fieldRegistry.js';
45
+ import { getInstance } from '../../stores/getInstance.svelte.js';
46
46
  import { getResolvedTheme } from '../../stores/settingsStore.svelte.js';
47
+
48
+ const fd = getInstance();
47
49
  import type { FieldSchema } from './types.js';
48
50
  import { getSchemaOptions } from './types.js';
51
+ import type { WorkflowNode, WorkflowEdge } from '../../types/index.js';
52
+ import type { AuthProvider } from '../../types/auth.js';
49
53
 
50
54
  interface Props {
51
55
  /** Unique key/id for the field */
@@ -58,11 +62,33 @@
58
62
  required?: boolean;
59
63
  /** Animation delay index for staggered animations */
60
64
  animationIndex?: number;
65
+ /** Current workflow node (optional, forwarded to registered editors for template variable API mode) */
66
+ node?: WorkflowNode;
67
+ /** All workflow nodes (optional, forwarded to registered editors for port-derived variables) */
68
+ nodes?: WorkflowNode[];
69
+ /** All workflow edges (optional, forwarded to registered editors for port-derived variables) */
70
+ edges?: WorkflowEdge[];
71
+ /** Workflow ID (optional, forwarded to registered editors for template variable API mode) */
72
+ workflowId?: string;
73
+ /** Auth provider (optional, forwarded to registered editors for API requests) */
74
+ authProvider?: AuthProvider;
61
75
  /** Callback when the field value changes */
62
76
  onChange: (value: unknown) => void;
63
77
  }
64
78
 
65
- let { fieldKey, schema, value, required = false, animationIndex = 0, onChange }: Props = $props();
79
+ let {
80
+ fieldKey,
81
+ schema,
82
+ value,
83
+ required = false,
84
+ animationIndex = 0,
85
+ node,
86
+ nodes,
87
+ edges,
88
+ workflowId,
89
+ authProvider,
90
+ onChange
91
+ }: Props = $props();
66
92
 
67
93
  /**
68
94
  * Computed description ID for ARIA association
@@ -84,7 +110,7 @@
84
110
  /**
85
111
  * Check if there's a registered custom component for this schema
86
112
  */
87
- const registeredComponent = $derived(fieldComponentRegistry.resolveFieldComponent(schema));
113
+ const registeredComponent = $derived(fd.fields.resolveFieldComponent(schema));
88
114
 
89
115
  /**
90
116
  * Determine the field type to render (for non-registered components)
@@ -244,6 +270,11 @@
244
270
  variables={schema.variables}
245
271
  placeholderExample={schema.placeholderExample as string | undefined}
246
272
  autocomplete={schema.autocomplete}
273
+ {node}
274
+ {nodes}
275
+ {edges}
276
+ {workflowId}
277
+ {authProvider}
247
278
  onChange={(val: unknown) => onChange(val)}
248
279
  />
249
280
  {:else if fieldType === 'checkbox-group'}
@@ -1,4 +1,6 @@
1
1
  import type { FieldSchema } from './types.js';
2
+ import type { WorkflowNode, WorkflowEdge } from '../../types/index.js';
3
+ import type { AuthProvider } from '../../types/auth.js';
2
4
  interface Props {
3
5
  /** Unique key/id for the field */
4
6
  fieldKey: string;
@@ -10,6 +12,16 @@ interface Props {
10
12
  required?: boolean;
11
13
  /** Animation delay index for staggered animations */
12
14
  animationIndex?: number;
15
+ /** Current workflow node (optional, forwarded to registered editors for template variable API mode) */
16
+ node?: WorkflowNode;
17
+ /** All workflow nodes (optional, forwarded to registered editors for port-derived variables) */
18
+ nodes?: WorkflowNode[];
19
+ /** All workflow edges (optional, forwarded to registered editors for port-derived variables) */
20
+ edges?: WorkflowEdge[];
21
+ /** Workflow ID (optional, forwarded to registered editors for template variable API mode) */
22
+ workflowId?: string;
23
+ /** Auth provider (optional, forwarded to registered editors for API requests) */
24
+ authProvider?: AuthProvider;
13
25
  /** Callback when the field value changes */
14
26
  onChange: (value: unknown) => void;
15
27
  }
@@ -409,11 +409,12 @@
409
409
  }),
410
410
  EditorView.lineWrapping,
411
411
 
412
- // Accessibility
412
+ // Accessibility + browser spellcheck (off by default, opt-in via spellChecker)
413
413
  ariaLabelCompartment.of(
414
414
  EditorView.contentAttributes.of({
415
415
  'aria-label': m().form.markdown.editor,
416
- 'aria-multiline': 'true'
416
+ 'aria-multiline': 'true',
417
+ spellcheck: String(spellChecker)
417
418
  })
418
419
  )
419
420
  ];
@@ -495,7 +496,8 @@
495
496
  ariaLabelCompartment.reconfigure(
496
497
  EditorView.contentAttributes.of({
497
498
  'aria-label': ariaLabel,
498
- 'aria-multiline': 'true'
499
+ 'aria-multiline': 'true',
500
+ spellcheck: String(spellChecker)
499
501
  })
500
502
  )
501
503
  ]
@@ -525,7 +527,8 @@
525
527
  role="toolbar"
526
528
  aria-label={m().form.markdown.toolbar}
527
529
  >
528
- {#each toolbarActions as item}
530
+ <!-- Separators have no identity of their own — disambiguate repeats by position -->
531
+ {#each toolbarActions as item, i (item === '|' ? `separator-${i}` : item.id)}
529
532
  {#if item === '|'}
530
533
  <span class="form-markdown-editor__separator"></span>
531
534
  {:else}
@@ -536,6 +539,8 @@
536
539
  onclick={item.action}
537
540
  >
538
541
  {#if item.isSvg}
542
+ <!-- item.icon is a compile-time SVG constant from toolbarActions, never user input -->
543
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -->
539
544
  <span class="form-markdown-editor__btn-svg">{@html item.icon}</span>
540
545
  {:else}
541
546
  <span
@@ -88,6 +88,7 @@
88
88
  {max}
89
89
  {step}
90
90
  {disabled}
91
+ {required}
91
92
  aria-describedby={ariaDescribedBy}
92
93
  aria-valuemin={min}
93
94
  aria-valuemax={max}
@@ -30,7 +30,8 @@
30
30
  tooltips,
31
31
  Decoration,
32
32
  ViewPlugin,
33
- MatchDecorator
33
+ MatchDecorator,
34
+ placeholder as cmPlaceholder
34
35
  } from '@codemirror/view';
35
36
  import { EditorState, Compartment } from '@codemirror/state';
36
37
  import { history, historyKeymap, defaultKeymap, indentWithTab } from '@codemirror/commands';
@@ -45,6 +46,7 @@
45
46
  } from '../../types/index.js';
46
47
  import { createTemplateAutocomplete } from './templateAutocomplete.js';
47
48
  import { getVariableSchema } from '../../services/variableService.js';
49
+ import { getInstance } from '../../stores/getInstance.svelte.js';
48
50
  import { logger } from '../../utils/logger.js';
49
51
  import { m } from '../../messages/index.js';
50
52
 
@@ -105,6 +107,9 @@
105
107
  authProvider
106
108
  }: Props = $props();
107
109
 
110
+ // Active instance — supplies endpoint configuration for API variable fetching.
111
+ const fd = getInstance();
112
+
108
113
  /** Loading state for API variable fetching */
109
114
  let isLoadingVariables = $state(false);
110
115
 
@@ -139,6 +144,7 @@
139
144
  try {
140
145
  isLoadingVariables = true;
141
146
  effectiveVariableSchema = await getVariableSchema(
147
+ fd.api.config,
142
148
  node,
143
149
  nodes,
144
150
  edges,
@@ -350,7 +356,9 @@
350
356
  }
351
357
  }),
352
358
  EditorView.lineWrapping,
353
- EditorState.tabSize.of(2)
359
+ EditorState.tabSize.of(2),
360
+ // Shown inside the editor while the document is empty
361
+ cmPlaceholder(placeholder)
354
362
  ];
355
363
 
356
364
  // Add autocomplete compartment (can be reconfigured dynamically)
@@ -570,7 +578,7 @@
570
578
  onclick={() => insertVariable(varName)}
571
579
  title={`Insert {{ ${varName} }}`}
572
580
  >
573
- <code>{'{{ '}{varName}{' }}'}</code>
581
+ <code>{`{{ ${varName} }}`}</code>
574
582
  </button>
575
583
  {/each}
576
584
  </div>
@@ -9,7 +9,7 @@
9
9
  -->
10
10
 
11
11
  <script lang="ts">
12
- import { m, warnDeprecatedProp } from '../../messages/index.js';
12
+ import { m } from '../../messages/index.js';
13
13
 
14
14
  interface Props {
15
15
  /** Field identifier */
@@ -17,11 +17,13 @@
17
17
  /** Current value */
18
18
  value: boolean;
19
19
  /**
20
- * @deprecated since v1.8 use `messages.form.toggle.enabled`. Removed in v2.0.
20
+ * Per-instance label for the on state (e.g. "Hidden" for a visibility
21
+ * toggle). Falls back to the global `messages.form.toggle.enabled`.
21
22
  */
22
23
  onLabel?: string;
23
24
  /**
24
- * @deprecated since v1.8 use `messages.form.toggle.disabled`. Removed in v2.0.
25
+ * Per-instance label for the off state. Falls back to the global
26
+ * `messages.form.toggle.disabled`.
25
27
  */
26
28
  offLabel?: string;
27
29
  /** Whether the field is disabled (read-only) */
@@ -42,15 +44,6 @@
42
44
  onChange
43
45
  }: Props = $props();
44
46
 
45
- // svelte-ignore state_referenced_locally — deprecation warns once per mount; later prop rebinds aren't relevant
46
- if (onLabel !== undefined) {
47
- warnDeprecatedProp('FormToggle', 'onLabel', 'messages.form.toggle.enabled');
48
- }
49
- // svelte-ignore state_referenced_locally
50
- if (offLabel !== undefined) {
51
- warnDeprecatedProp('FormToggle', 'offLabel', 'messages.form.toggle.disabled');
52
- }
53
-
54
47
  const resolvedOnLabel = $derived(onLabel ?? m().form.toggle.enabled);
55
48
  const resolvedOffLabel = $derived(offLabel ?? m().form.toggle.disabled);
56
49
 
@@ -4,11 +4,13 @@ interface Props {
4
4
  /** Current value */
5
5
  value: boolean;
6
6
  /**
7
- * @deprecated since v1.8 use `messages.form.toggle.enabled`. Removed in v2.0.
7
+ * Per-instance label for the on state (e.g. "Hidden" for a visibility
8
+ * toggle). Falls back to the global `messages.form.toggle.enabled`.
8
9
  */
9
10
  onLabel?: string;
10
11
  /**
11
- * @deprecated since v1.8 use `messages.form.toggle.disabled`. Removed in v2.0.
12
+ * Per-instance label for the off state. Falls back to the global
13
+ * `messages.form.toggle.disabled`.
12
14
  */
13
15
  offLabel?: string;
14
16
  /** Whether the field is disabled (read-only) */
@@ -16,7 +16,9 @@
16
16
  import type { ConfigSchema, WorkflowNode, WorkflowEdge, AuthProvider } from '../../types/index.js';
17
17
  import type { FieldSchema } from './types.js';
18
18
  import { resolveScopeToKey } from '../../utils/uischema.js';
19
- import FormField from './FormField.svelte';
19
+ // Use the registry-based light field factory so the UISchema renderer (and
20
+ // SchemaForm/ConfigForm above it) never statically pull in CodeMirror.
21
+ import FormField from './FormFieldLight.svelte';
20
22
  import FormFieldset from './FormFieldset.svelte';
21
23
  import Self from './FormUISchemaRenderer.svelte';
22
24
 
@@ -11,7 +11,7 @@
11
11
  * @module components/form/templateAutocomplete
12
12
  */
13
13
  import { autocompletion } from '@codemirror/autocomplete';
14
- import { getChildVariables, getArrayIndexSuggestions, isArrayVariable, hasChildren } from '../../services/variableService.js';
14
+ import { getChildVariables, getArrayIndexSuggestions, isArrayVariable } from '../../services/variableService.js';
15
15
  /**
16
16
  * Icon type hints for different variable types in autocomplete dropdown.
17
17
  */
@@ -56,10 +56,6 @@ function extractVariablePath(text, pos) {
56
56
  if (openBracePos === -1) {
57
57
  return null;
58
58
  }
59
- // Check if there's a closing }} after cursor (still inside expression)
60
- const afterCursor = text.slice(pos);
61
- const closingMatch = afterCursor.match(/^\s*\}\}/);
62
- const hasClosing = closingMatch !== null;
63
59
  // Extract the content between {{ and cursor
64
60
  const contentStart = openBracePos + 2;
65
61
  const content = text.slice(contentStart, pos).trimStart();
@@ -95,8 +95,7 @@ export interface BaseFieldProps<T = unknown> {
95
95
  /**
96
96
  * Properties for text input fields
97
97
  */
98
- export interface TextFieldProps extends BaseFieldProps<string> {
99
- }
98
+ export type TextFieldProps = BaseFieldProps<string>;
100
99
  /**
101
100
  * Properties for multiline text fields (textarea)
102
101
  */
@@ -432,18 +431,6 @@ export interface SchemaFormProps {
432
431
  * @default false
433
432
  */
434
433
  showActions?: boolean;
435
- /**
436
- * Label text for the save button.
437
- * Only used when showActions is true.
438
- * @default "Save"
439
- */
440
- saveLabel?: string;
441
- /**
442
- * Label text for the cancel button.
443
- * Only used when showActions is true.
444
- * @default "Cancel"
445
- */
446
- cancelLabel?: string;
447
434
  /**
448
435
  * Callback fired when the Save button is clicked.
449
436
  * Receives the final form values after collecting from DOM.
@@ -44,7 +44,8 @@
44
44
  }: Props = $props();
45
45
 
46
46
  /** Local state for form values */
47
- // svelte-ignore state_referenced_locally — initial default, user fills the form
47
+ // initial default, user fills the form
48
+ // svelte-ignore state_referenced_locally
48
49
  let formValues = $state<Record<string, unknown>>(config.defaultValues ?? {});
49
50
 
50
51
  /** Display values - either resolved or current form values */
@@ -131,7 +132,7 @@
131
132
  <div class="form-prompt__resolved-values">
132
133
  <h4 class="form-prompt__resolved-title">{interrupt.form.submittedValuesTitle}</h4>
133
134
  <div class="form-prompt__values-list">
134
- {#each Object.entries(config.schema.properties ?? {}) as [key, field]}
135
+ {#each Object.entries(config.schema.properties ?? {}) as [key, field] (key)}
135
136
  {@const value = displayValues[key]}
136
137
  {@const fieldTitle = ((field as Record<string, unknown>).title as string) ?? key}
137
138
  <div class="form-prompt__value-item">
@@ -33,11 +33,8 @@
33
33
  getErrorMessage,
34
34
  getResolvedValue
35
35
  } from '../../types/interruptState.js';
36
- import {
37
- getInterruptsMap,
38
- interruptActions,
39
- type InterruptWithState
40
- } from '../../stores/interruptStore.svelte.js';
36
+ import { type InterruptWithState } from '../../stores/interruptStore.svelte.js';
37
+ import { getInstance } from '../../stores/getInstance.svelte.js';
41
38
  import { interruptService } from '../../services/interruptService.js';
42
39
  import { logger } from '../../utils/logger.js';
43
40
  import { m } from '../../messages/index.js';
@@ -72,12 +69,14 @@
72
69
  tags
73
70
  }: Props = $props();
74
71
 
72
+ const fd = getInstance();
73
+
75
74
  /**
76
75
  * Get the current interrupt state from the store.
77
76
  * This ensures we react to store updates (like status changes).
78
77
  */
79
78
  const currentInterrupt = $derived(
80
- getInterruptsMap().get(initialInterrupt.id) ?? addMachineState(initialInterrupt)
79
+ fd.interrupts.getMap().get(initialInterrupt.id) ?? addMachineState(initialInterrupt)
81
80
  );
82
81
 
83
82
  const hierarchyItems = $derived(hierarchy ?? []);
@@ -191,7 +190,7 @@
191
190
  */
192
191
  async function handleResolve(value: unknown): Promise<void> {
193
192
  // Start the submission - state machine validates this transition
194
- const startResult = interruptActions.startSubmit(currentInterrupt.id, value);
193
+ const startResult = fd.interrupts.startSubmit(currentInterrupt.id, value);
195
194
  if (!startResult.valid) {
196
195
  logger.warn('[InterruptBubble] Cannot submit:', startResult.error);
197
196
  return;
@@ -199,19 +198,24 @@
199
198
 
200
199
  try {
201
200
  // Call API if service is configured
202
- if (interruptService.isConfigured()) {
203
- await interruptService.resolveInterrupt(currentInterrupt.id, value);
201
+ if (interruptService.isConfigured(fd.api.config)) {
202
+ await interruptService.resolveInterrupt(
203
+ fd.api.config,
204
+ currentInterrupt.id,
205
+ value,
206
+ fd.api.authProvider
207
+ );
204
208
  }
205
209
 
206
210
  // Mark as successful - transitions to resolved state
207
- interruptActions.submitSuccess(currentInterrupt.id);
211
+ fd.interrupts.submitSuccess(currentInterrupt.id);
208
212
 
209
213
  // Notify parent to refresh messages
210
214
  onResolved?.();
211
215
  } catch (err) {
212
216
  // Mark as failed - transitions to error state (can retry)
213
217
  const errorMessage = err instanceof Error ? err.message : 'Failed to submit response';
214
- interruptActions.submitFailure(currentInterrupt.id, errorMessage);
218
+ fd.interrupts.submitFailure(currentInterrupt.id, errorMessage);
215
219
  logger.error('[InterruptBubble] Resolve error:', err);
216
220
  }
217
221
  }
@@ -221,7 +225,7 @@
221
225
  */
222
226
  async function handleCancel(): Promise<void> {
223
227
  // Start the cancel - state machine validates this transition
224
- const startResult = interruptActions.startCancel(currentInterrupt.id);
228
+ const startResult = fd.interrupts.startCancel(currentInterrupt.id);
225
229
  if (!startResult.valid) {
226
230
  logger.warn('[InterruptBubble] Cannot cancel:', startResult.error);
227
231
  return;
@@ -229,19 +233,23 @@
229
233
 
230
234
  try {
231
235
  // Call API if service is configured
232
- if (interruptService.isConfigured()) {
233
- await interruptService.cancelInterrupt(currentInterrupt.id);
236
+ if (interruptService.isConfigured(fd.api.config)) {
237
+ await interruptService.cancelInterrupt(
238
+ fd.api.config,
239
+ currentInterrupt.id,
240
+ fd.api.authProvider
241
+ );
234
242
  }
235
243
 
236
244
  // Mark as successful - transitions to cancelled state
237
- interruptActions.submitSuccess(currentInterrupt.id);
245
+ fd.interrupts.submitSuccess(currentInterrupt.id);
238
246
 
239
247
  // Notify parent to refresh messages
240
248
  onResolved?.();
241
249
  } catch (err) {
242
250
  // Mark as failed - transitions to error state (can retry)
243
251
  const errorMessage = err instanceof Error ? err.message : 'Failed to cancel';
244
- interruptActions.submitFailure(currentInterrupt.id, errorMessage);
252
+ fd.interrupts.submitFailure(currentInterrupt.id, errorMessage);
245
253
  logger.error('[InterruptBubble] Cancel error:', err);
246
254
  }
247
255
  }
@@ -250,7 +258,7 @@
250
258
  * Handle retry after error
251
259
  */
252
260
  function handleRetry(): void {
253
- interruptActions.retry(currentInterrupt.id);
261
+ fd.interrupts.retry(currentInterrupt.id);
254
262
  }
255
263
 
256
264
  // Typed config getters for each prompt type
@@ -51,7 +51,8 @@
51
51
  }: Props = $props();
52
52
 
53
53
  /** Local state: map of field -> accepted boolean. Default all to true (accept). */
54
- // svelte-ignore state_referenced_locally — initial default, user toggles during review
54
+ // initial default, user toggles during review
55
+ // svelte-ignore state_referenced_locally
55
56
  let decisions = $state<Record<string, boolean>>(
56
57
  Object.fromEntries(config.changes.map((c) => [c.field, true]))
57
58
  );
@@ -346,9 +347,12 @@
346
347
  <div class="review-prompt__diff-row">
347
348
  <span class="review-prompt__diff-label">{t.original}</span>
348
349
  {#if isHtml && !isRawView}
350
+ <!-- Output of sanitizeHtml() (DOMPurify allowlist) — see utils/sanitize.ts -->
351
+ <!-- eslint-disable svelte/no-at-html-tags -->
349
352
  <span class="review-prompt__diff-value review-prompt__html-content"
350
353
  >{@html sanitizeHtml(String(change.original))}</span
351
354
  >
355
+ <!-- eslint-enable svelte/no-at-html-tags -->
352
356
  {:else if isHtml && isRawView}
353
357
  <code class="review-prompt__diff-value review-prompt__raw-html"
354
358
  >{change.original}</code
@@ -362,10 +366,13 @@
362
366
  <div class="review-prompt__diff-row">
363
367
  <span class="review-prompt__diff-label">{t.proposed}</span>
364
368
  {#if isHtml && !isRawView}
369
+ <!-- Output of sanitizeHtml() (DOMPurify allowlist) — see utils/sanitize.ts -->
370
+ <!-- eslint-disable svelte/no-at-html-tags -->
365
371
  <span
366
372
  class="review-prompt__diff-value review-prompt__diff-value--proposed review-prompt__html-content"
367
373
  >{@html sanitizeHtml(String(change.proposed))}</span
368
374
  >
375
+ <!-- eslint-enable svelte/no-at-html-tags -->
369
376
  {:else if isHtml && isRawView}
370
377
  <code
371
378
  class="review-prompt__diff-value review-prompt__diff-value--proposed review-prompt__raw-html"
@@ -382,14 +389,14 @@
382
389
  <span class="review-prompt__diff-label">{t.diff}</span>
383
390
  {#if isMultiLineDiff(diff)}
384
391
  <pre
385
- class="review-prompt__diff-value review-prompt__diff-block">{#each diff as part}{#if part.added}<span
392
+ class="review-prompt__diff-value review-prompt__diff-block">{#each diff as part, i (i)}{#if part.added}<span
386
393
  class="review-prompt__diff-token--added">{part.value}</span
387
394
  >{:else if part.removed}<span class="review-prompt__diff-token--removed"
388
395
  >{part.value}</span
389
396
  >{:else}<span>{part.value}</span>{/if}{/each}</pre>
390
397
  {:else}
391
398
  <span class="review-prompt__diff-value review-prompt__diff-inline">
392
- {#each diff as part}
399
+ {#each diff as part, i (i)}
393
400
  {#if part.added}
394
401
  <span class="review-prompt__diff-token--added">{part.value}</span>
395
402
  {:else if part.removed}
@@ -47,7 +47,8 @@
47
47
  const t = $derived(m().interrupt.text);
48
48
 
49
49
  /** Local state for input value */
50
- // svelte-ignore state_referenced_locally — initial default, user edits the input
50
+ // initial default, user edits the input
51
+ // svelte-ignore state_referenced_locally
51
52
  let inputValue = $state(config.defaultValue ?? '');
52
53
 
53
54
  /** Display value - either resolved or current input */
@@ -17,6 +17,10 @@
17
17
  * Configuration props for the MainLayout component
18
18
  */
19
19
  interface Props {
20
+ /** Overall layout height (CSS length, or a number of pixels) */
21
+ height?: string | number;
22
+ /** Overall layout width (CSS length, or a number of pixels) */
23
+ width?: string | number;
20
24
  /** Height of the header in pixels */
21
25
  headerHeight?: number;
22
26
  /** Height of the footer in pixels */
@@ -74,6 +78,8 @@
74
78
  }
75
79
 
76
80
  let {
81
+ height = '100vh',
82
+ width = '100%',
77
83
  headerHeight = 60,
78
84
  footerHeight = 48,
79
85
  showHeader = true,
@@ -103,9 +109,12 @@
103
109
  children
104
110
  }: Props = $props();
105
111
 
106
- /** Current width of the left sidebar */
107
- // svelte-ignore state_referenced_locally initial default, component owns draggable state
108
- let leftSidebarWidth = $state(initialLeftWidth);
112
+ /**
113
+ * Current width of the left sidebar.
114
+ * Writable derived: recomputes when the prop changes (external control,
115
+ * e.g. collapsed state), while drag/keyboard resizing assigns over it.
116
+ */
117
+ let leftSidebarWidth = $derived(initialLeftWidth);
109
118
 
110
119
  /** Current width of the right sidebar */
111
120
  // svelte-ignore state_referenced_locally
@@ -115,14 +124,6 @@
115
124
  // svelte-ignore state_referenced_locally
116
125
  let bottomPanelHeightState = $state(initialBottomHeight);
117
126
 
118
- /**
119
- * Sync left sidebar width with prop changes
120
- * This allows external control (e.g., collapsed state) to update the width
121
- */
122
- $effect(() => {
123
- leftSidebarWidth = initialLeftWidth;
124
- });
125
-
126
127
  /** Whether the user is currently dragging the left divider */
127
128
  let isDraggingLeft = $state(false);
128
129
 
@@ -298,6 +299,10 @@
298
299
 
299
300
  /** Computed CSS variable for bottom panel height */
300
301
  const bottomHeightVar = $derived(`${bottomPanelHeightState}px`);
302
+
303
+ /** Bare numbers mean pixels; strings pass through as CSS lengths */
304
+ const layoutHeightVar = $derived(typeof height === 'number' ? `${height}px` : height);
305
+ const layoutWidthVar = $derived(typeof width === 'number' ? `${width}px` : width);
301
306
  </script>
302
307
 
303
308
  <div
@@ -306,6 +311,8 @@
306
311
  class:flowdrop-main-layout--dragging={isDraggingLeft || isDraggingRight || isDraggingBottom}
307
312
  class:flowdrop-main-layout--dragging-vertical={isDraggingBottom}
308
313
  style="
314
+ --layout-height: {layoutHeightVar};
315
+ --layout-width: {layoutWidthVar};
309
316
  --layout-header-height: {headerHeightVar};
310
317
  --layout-footer-height: {footerHeightVar};
311
318
  --layout-left-sidebar-width: {leftWidthVar};
@@ -437,8 +444,8 @@
437
444
  .flowdrop-main-layout {
438
445
  display: flex;
439
446
  flex-direction: column;
440
- height: 100vh;
441
- width: 100%;
447
+ height: var(--layout-height, 100vh);
448
+ width: var(--layout-width, 100%);
442
449
  background: var(
443
450
  --fd-layout-background,
444
451
  linear-gradient(135deg, #f9fafb 0%, #e0e7ff 50%, #c7d2fe 100%)
@@ -2,6 +2,10 @@
2
2
  * Configuration props for the MainLayout component
3
3
  */
4
4
  interface Props {
5
+ /** Overall layout height (CSS length, or a number of pixels) */
6
+ height?: string | number;
7
+ /** Overall layout width (CSS length, or a number of pixels) */
8
+ width?: string | number;
5
9
  /** Height of the header in pixels */
6
10
  headerHeight?: number;
7
11
  /** Height of the footer in pixels */