@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.
Files changed (385) hide show
  1. package/README.md +50 -50
  2. package/dist/adapters/WorkflowAdapter.d.ts +1 -1
  3. package/dist/adapters/WorkflowAdapter.js +25 -25
  4. package/dist/adapters/agentspec/AgentSpecAdapter.d.ts +2 -2
  5. package/dist/adapters/agentspec/AgentSpecAdapter.js +133 -122
  6. package/dist/adapters/agentspec/agentAdapter.d.ts +2 -2
  7. package/dist/adapters/agentspec/agentAdapter.js +10 -10
  8. package/dist/adapters/agentspec/autoLayout.d.ts +1 -1
  9. package/dist/adapters/agentspec/autoLayout.js +2 -2
  10. package/dist/adapters/agentspec/componentTypeDefaults.d.ts +1 -1
  11. package/dist/adapters/agentspec/componentTypeDefaults.js +120 -120
  12. package/dist/adapters/agentspec/defaultNodeTypes.d.ts +2 -2
  13. package/dist/adapters/agentspec/defaultNodeTypes.js +307 -307
  14. package/dist/adapters/agentspec/index.d.ts +10 -10
  15. package/dist/adapters/agentspec/index.js +6 -6
  16. package/dist/adapters/agentspec/validator.d.ts +2 -2
  17. package/dist/adapters/agentspec/validator.js +22 -20
  18. package/dist/api/enhanced-client.d.ts +3 -3
  19. package/dist/api/enhanced-client.js +73 -72
  20. package/dist/components/App.svelte +1090 -961
  21. package/dist/components/App.svelte.d.ts +9 -6
  22. package/dist/components/CanvasBanner.stories.svelte +23 -20
  23. package/dist/components/CanvasBanner.stories.svelte.d.ts +1 -1
  24. package/dist/components/CanvasBanner.svelte +52 -46
  25. package/dist/components/ConfigForm.svelte +1164 -1065
  26. package/dist/components/ConfigForm.svelte.d.ts +2 -2
  27. package/dist/components/ConfigModal.svelte +180 -180
  28. package/dist/components/ConfigModal.svelte.d.ts +1 -1
  29. package/dist/components/ConfigPanel.stories.svelte +35 -35
  30. package/dist/components/ConfigPanel.stories.svelte.d.ts +1 -1
  31. package/dist/components/ConfigPanel.svelte +178 -167
  32. package/dist/components/ConfigPanel.svelte.d.ts +1 -1
  33. package/dist/components/ConnectionLine.svelte +25 -25
  34. package/dist/components/EdgeRefresher.svelte +26 -26
  35. package/dist/components/FlowDropEdge.stories.svelte +179 -143
  36. package/dist/components/FlowDropEdge.svelte +147 -147
  37. package/dist/components/FlowDropEdge.svelte.d.ts +1 -1
  38. package/dist/components/FlowDropZone.svelte +63 -60
  39. package/dist/components/FlowDropZone.svelte.d.ts +1 -1
  40. package/dist/components/LoadingSpinner.stories.svelte +19 -19
  41. package/dist/components/LoadingSpinner.stories.svelte.d.ts +1 -1
  42. package/dist/components/LoadingSpinner.svelte +21 -21
  43. package/dist/components/LoadingSpinner.svelte.d.ts +1 -1
  44. package/dist/components/Logo.stories.svelte +13 -13
  45. package/dist/components/Logo.stories.svelte.d.ts +1 -1
  46. package/dist/components/Logo.svelte +101 -95
  47. package/dist/components/LogsSidebar.svelte +553 -546
  48. package/dist/components/LogsSidebar.svelte.d.ts +1 -1
  49. package/dist/components/MarkdownDisplay.stories.svelte +29 -23
  50. package/dist/components/MarkdownDisplay.stories.svelte.d.ts +1 -1
  51. package/dist/components/MarkdownDisplay.svelte +16 -14
  52. package/dist/components/Navbar.stories.svelte +43 -38
  53. package/dist/components/Navbar.stories.svelte.d.ts +1 -1
  54. package/dist/components/Navbar.svelte +760 -706
  55. package/dist/components/Navbar.svelte.d.ts +1 -1
  56. package/dist/components/NodeSidebar.svelte +905 -746
  57. package/dist/components/NodeSidebar.svelte.d.ts +5 -1
  58. package/dist/components/NodeStatusOverlay.stories.svelte +82 -70
  59. package/dist/components/NodeStatusOverlay.stories.svelte.d.ts +1 -1
  60. package/dist/components/NodeStatusOverlay.svelte +295 -280
  61. package/dist/components/NodeStatusOverlay.svelte.d.ts +3 -3
  62. package/dist/components/PipelineStatus.svelte +326 -300
  63. package/dist/components/PipelineStatus.svelte.d.ts +4 -4
  64. package/dist/components/PortCoordinateTracker.svelte +49 -47
  65. package/dist/components/PortCoordinateTracker.svelte.d.ts +1 -1
  66. package/dist/components/ReadOnlyDetails.svelte +156 -156
  67. package/dist/components/SchemaForm.stories.svelte +106 -98
  68. package/dist/components/SchemaForm.stories.svelte.d.ts +1 -1
  69. package/dist/components/SchemaForm.svelte +490 -463
  70. package/dist/components/SchemaForm.svelte.d.ts +2 -2
  71. package/dist/components/SettingsModal.svelte +226 -223
  72. package/dist/components/SettingsModal.svelte.d.ts +1 -1
  73. package/dist/components/SettingsPanel.svelte +637 -601
  74. package/dist/components/SettingsPanel.svelte.d.ts +1 -1
  75. package/dist/components/StatusIcon.stories.svelte +62 -49
  76. package/dist/components/StatusIcon.stories.svelte.d.ts +1 -1
  77. package/dist/components/StatusIcon.svelte +87 -87
  78. package/dist/components/StatusIcon.svelte.d.ts +2 -2
  79. package/dist/components/StatusLabel.stories.svelte +12 -12
  80. package/dist/components/StatusLabel.stories.svelte.d.ts +1 -1
  81. package/dist/components/StatusLabel.svelte +19 -19
  82. package/dist/components/ThemeToggle.stories.svelte +16 -16
  83. package/dist/components/ThemeToggle.stories.svelte.d.ts +1 -1
  84. package/dist/components/ThemeToggle.svelte +180 -169
  85. package/dist/components/ThemeToggle.svelte.d.ts +1 -1
  86. package/dist/components/UniversalNode.svelte +150 -138
  87. package/dist/components/UniversalNode.svelte.d.ts +3 -3
  88. package/dist/components/WorkflowEditor.svelte +1069 -1014
  89. package/dist/components/WorkflowEditor.svelte.d.ts +4 -4
  90. package/dist/components/form/FormArray.svelte +1034 -973
  91. package/dist/components/form/FormArray.svelte.d.ts +1 -1
  92. package/dist/components/form/FormAutocomplete.svelte +1021 -978
  93. package/dist/components/form/FormAutocomplete.svelte.d.ts +1 -1
  94. package/dist/components/form/FormCheckboxGroup.stories.svelte +23 -20
  95. package/dist/components/form/FormCheckboxGroup.stories.svelte.d.ts +1 -1
  96. package/dist/components/form/FormCheckboxGroup.svelte +136 -136
  97. package/dist/components/form/FormCodeEditor.svelte +452 -434
  98. package/dist/components/form/FormField.svelte +366 -355
  99. package/dist/components/form/FormField.svelte.d.ts +2 -2
  100. package/dist/components/form/FormFieldLight.svelte +400 -384
  101. package/dist/components/form/FormFieldLight.svelte.d.ts +1 -1
  102. package/dist/components/form/FormFieldWrapper.stories.svelte +42 -42
  103. package/dist/components/form/FormFieldWrapper.stories.svelte.d.ts +1 -1
  104. package/dist/components/form/FormFieldWrapper.svelte +100 -93
  105. package/dist/components/form/FormFieldWrapper.svelte.d.ts +1 -1
  106. package/dist/components/form/FormFieldset.svelte +108 -108
  107. package/dist/components/form/FormFieldset.svelte.d.ts +2 -2
  108. package/dist/components/form/FormMarkdownEditor.svelte +758 -725
  109. package/dist/components/form/FormNumberField.stories.svelte +25 -25
  110. package/dist/components/form/FormNumberField.stories.svelte.d.ts +1 -1
  111. package/dist/components/form/FormNumberField.svelte +88 -88
  112. package/dist/components/form/FormRangeField.stories.svelte +20 -20
  113. package/dist/components/form/FormRangeField.stories.svelte.d.ts +1 -1
  114. package/dist/components/form/FormRangeField.svelte +234 -226
  115. package/dist/components/form/FormSelect.stories.svelte +38 -38
  116. package/dist/components/form/FormSelect.stories.svelte.d.ts +1 -1
  117. package/dist/components/form/FormSelect.svelte +101 -101
  118. package/dist/components/form/FormSelect.svelte.d.ts +1 -1
  119. package/dist/components/form/FormTemplateEditor.svelte +847 -798
  120. package/dist/components/form/FormTemplateEditor.svelte.d.ts +1 -1
  121. package/dist/components/form/FormTextField.stories.svelte +29 -23
  122. package/dist/components/form/FormTextField.stories.svelte.d.ts +1 -1
  123. package/dist/components/form/FormTextField.svelte +68 -68
  124. package/dist/components/form/FormTextarea.stories.svelte +28 -25
  125. package/dist/components/form/FormTextarea.stories.svelte.d.ts +1 -1
  126. package/dist/components/form/FormTextarea.svelte +74 -74
  127. package/dist/components/form/FormToggle.stories.svelte +23 -20
  128. package/dist/components/form/FormToggle.stories.svelte.d.ts +1 -1
  129. package/dist/components/form/FormToggle.svelte +98 -98
  130. package/dist/components/form/FormUISchemaRenderer.svelte +120 -113
  131. package/dist/components/form/FormUISchemaRenderer.svelte.d.ts +3 -3
  132. package/dist/components/form/index.d.ts +19 -19
  133. package/dist/components/form/index.js +18 -18
  134. package/dist/components/form/templateAutocomplete.d.ts +2 -2
  135. package/dist/components/form/templateAutocomplete.js +64 -55
  136. package/dist/components/form/types.d.ts +6 -6
  137. package/dist/components/form/types.js +9 -4
  138. package/dist/components/icons/AlertCircleIcon.svelte +11 -0
  139. package/dist/components/icons/AlertCircleIcon.svelte.d.ts +26 -0
  140. package/dist/components/icons/CogIcon.svelte +11 -0
  141. package/dist/components/icons/CogIcon.svelte.d.ts +26 -0
  142. package/dist/components/interrupt/ChoicePrompt.stories.svelte +54 -38
  143. package/dist/components/interrupt/ChoicePrompt.stories.svelte.d.ts +1 -1
  144. package/dist/components/interrupt/ChoicePrompt.svelte +407 -383
  145. package/dist/components/interrupt/ChoicePrompt.svelte.d.ts +1 -1
  146. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte +48 -48
  147. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte.d.ts +1 -1
  148. package/dist/components/interrupt/ConfirmationPrompt.svelte +280 -274
  149. package/dist/components/interrupt/ConfirmationPrompt.svelte.d.ts +1 -1
  150. package/dist/components/interrupt/FormPrompt.svelte +223 -218
  151. package/dist/components/interrupt/FormPrompt.svelte.d.ts +1 -1
  152. package/dist/components/interrupt/InterruptBubble.svelte +617 -583
  153. package/dist/components/interrupt/InterruptBubble.svelte.d.ts +2 -2
  154. package/dist/components/interrupt/ReviewPrompt.stories.svelte +66 -56
  155. package/dist/components/interrupt/ReviewPrompt.stories.svelte.d.ts +1 -1
  156. package/dist/components/interrupt/ReviewPrompt.svelte +861 -841
  157. package/dist/components/interrupt/ReviewPrompt.svelte.d.ts +1 -1
  158. package/dist/components/interrupt/TextInputPrompt.stories.svelte +38 -33
  159. package/dist/components/interrupt/TextInputPrompt.stories.svelte.d.ts +1 -1
  160. package/dist/components/interrupt/TextInputPrompt.svelte +333 -328
  161. package/dist/components/interrupt/TextInputPrompt.svelte.d.ts +1 -1
  162. package/dist/components/interrupt/index.d.ts +5 -5
  163. package/dist/components/interrupt/index.js +5 -5
  164. package/dist/components/layouts/MainLayout.svelte +724 -691
  165. package/dist/components/layouts/MainLayout.svelte.d.ts +6 -6
  166. package/dist/components/nodes/GatewayNode.stories.svelte +100 -99
  167. package/dist/components/nodes/GatewayNode.svelte +605 -571
  168. package/dist/components/nodes/GatewayNode.svelte.d.ts +3 -3
  169. package/dist/components/nodes/IdeaNode.stories.svelte +44 -43
  170. package/dist/components/nodes/IdeaNode.svelte +451 -437
  171. package/dist/components/nodes/IdeaNode.svelte.d.ts +1 -1
  172. package/dist/components/nodes/NotesNode.stories.svelte +65 -64
  173. package/dist/components/nodes/NotesNode.svelte +380 -369
  174. package/dist/components/nodes/NotesNode.svelte.d.ts +1 -1
  175. package/dist/components/nodes/SimpleNode.stories.svelte +145 -144
  176. package/dist/components/nodes/SimpleNode.svelte +486 -424
  177. package/dist/components/nodes/SimpleNode.svelte.d.ts +1 -1
  178. package/dist/components/nodes/SquareNode.stories.svelte +73 -73
  179. package/dist/components/nodes/SquareNode.svelte +439 -380
  180. package/dist/components/nodes/SquareNode.svelte.d.ts +1 -1
  181. package/dist/components/nodes/TerminalNode.stories.svelte +13 -13
  182. package/dist/components/nodes/TerminalNode.svelte +709 -670
  183. package/dist/components/nodes/TerminalNode.svelte.d.ts +1 -1
  184. package/dist/components/nodes/ToolNode.stories.svelte +181 -180
  185. package/dist/components/nodes/ToolNode.svelte +505 -447
  186. package/dist/components/nodes/ToolNode.svelte.d.ts +1 -1
  187. package/dist/components/nodes/WorkflowNode.stories.svelte +70 -46
  188. package/dist/components/nodes/WorkflowNode.svelte +621 -551
  189. package/dist/components/nodes/WorkflowNode.svelte.d.ts +3 -3
  190. package/dist/components/playground/ChatPanel.svelte +945 -889
  191. package/dist/components/playground/ExecutionLogs.svelte +495 -472
  192. package/dist/components/playground/InputCollector.svelte +449 -428
  193. package/dist/components/playground/MessageBubble.stories.svelte +47 -47
  194. package/dist/components/playground/MessageBubble.stories.svelte.d.ts +1 -1
  195. package/dist/components/playground/MessageBubble.svelte +626 -610
  196. package/dist/components/playground/MessageBubble.svelte.d.ts +1 -1
  197. package/dist/components/playground/Playground.svelte +1088 -1057
  198. package/dist/components/playground/Playground.svelte.d.ts +3 -3
  199. package/dist/components/playground/PlaygroundModal.svelte +208 -204
  200. package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -3
  201. package/dist/components/playground/SessionManager.svelte +527 -521
  202. package/dist/components/playground/SessionManager.svelte.d.ts +1 -1
  203. package/dist/config/agentSpecEndpoints.d.ts +1 -1
  204. package/dist/config/agentSpecEndpoints.js +20 -20
  205. package/dist/config/constants.js +2 -2
  206. package/dist/config/defaultCategories.d.ts +1 -1
  207. package/dist/config/defaultCategories.js +86 -86
  208. package/dist/config/defaultPortConfig.d.ts +1 -1
  209. package/dist/config/defaultPortConfig.js +144 -144
  210. package/dist/config/endpoints.d.ts +4 -4
  211. package/dist/config/endpoints.js +65 -65
  212. package/dist/config/runtimeConfig.d.ts +2 -2
  213. package/dist/config/runtimeConfig.js +8 -8
  214. package/dist/core/index.d.ts +63 -59
  215. package/dist/core/index.js +35 -33
  216. package/dist/display/index.d.ts +2 -2
  217. package/dist/display/index.js +2 -2
  218. package/dist/editor/index.d.ts +62 -62
  219. package/dist/editor/index.js +53 -53
  220. package/dist/form/code.d.ts +5 -5
  221. package/dist/form/code.js +14 -14
  222. package/dist/form/fieldRegistry.d.ts +3 -3
  223. package/dist/form/fieldRegistry.js +11 -9
  224. package/dist/form/full.d.ts +8 -8
  225. package/dist/form/full.js +9 -9
  226. package/dist/form/index.d.ts +18 -18
  227. package/dist/form/index.js +16 -16
  228. package/dist/form/markdown.d.ts +4 -4
  229. package/dist/form/markdown.js +8 -8
  230. package/dist/helpers/proximityConnect.d.ts +3 -3
  231. package/dist/helpers/proximityConnect.js +34 -32
  232. package/dist/helpers/workflowEditorHelper.d.ts +5 -5
  233. package/dist/helpers/workflowEditorHelper.js +108 -96
  234. package/dist/index.d.ts +6 -6
  235. package/dist/index.js +6 -6
  236. package/dist/mocks/app-environment.js +2 -2
  237. package/dist/mocks/app-forms.js +9 -9
  238. package/dist/mocks/app-navigation.js +11 -11
  239. package/dist/mocks/app-stores.js +8 -8
  240. package/dist/playground/index.d.ts +19 -19
  241. package/dist/playground/index.js +16 -16
  242. package/dist/playground/mount.d.ts +3 -3
  243. package/dist/playground/mount.js +24 -24
  244. package/dist/registry/builtinFormats.js +13 -13
  245. package/dist/registry/builtinNodes.d.ts +2 -2
  246. package/dist/registry/builtinNodes.js +77 -77
  247. package/dist/registry/index.d.ts +4 -4
  248. package/dist/registry/index.js +4 -4
  249. package/dist/registry/nodeComponentRegistry.d.ts +8 -8
  250. package/dist/registry/nodeComponentRegistry.js +11 -9
  251. package/dist/registry/plugin.d.ts +2 -2
  252. package/dist/registry/plugin.js +11 -11
  253. package/dist/registry/workflowFormatRegistry.d.ts +3 -3
  254. package/dist/registry/workflowFormatRegistry.js +2 -2
  255. package/dist/schema/index.d.ts +1 -1
  256. package/dist/schema/index.js +2 -2
  257. package/dist/services/agentSpecExecutionService.d.ts +3 -3
  258. package/dist/services/agentSpecExecutionService.js +59 -55
  259. package/dist/services/api.d.ts +2 -2
  260. package/dist/services/api.js +37 -37
  261. package/dist/services/apiVariableService.d.ts +1 -1
  262. package/dist/services/apiVariableService.js +41 -34
  263. package/dist/services/autoSaveService.js +8 -8
  264. package/dist/services/categoriesApi.d.ts +2 -2
  265. package/dist/services/categoriesApi.js +8 -8
  266. package/dist/services/draftStorage.d.ts +1 -1
  267. package/dist/services/draftStorage.js +11 -11
  268. package/dist/services/dynamicSchemaService.d.ts +1 -1
  269. package/dist/services/dynamicSchemaService.js +41 -39
  270. package/dist/services/globalSave.d.ts +2 -2
  271. package/dist/services/globalSave.js +41 -38
  272. package/dist/services/historyService.d.ts +1 -1
  273. package/dist/services/historyService.js +8 -8
  274. package/dist/services/interruptService.d.ts +1 -1
  275. package/dist/services/interruptService.js +35 -29
  276. package/dist/services/nodeExecutionService.d.ts +1 -1
  277. package/dist/services/nodeExecutionService.js +45 -44
  278. package/dist/services/playgroundService.d.ts +1 -1
  279. package/dist/services/playgroundService.js +29 -29
  280. package/dist/services/portConfigApi.d.ts +2 -2
  281. package/dist/services/portConfigApi.js +8 -8
  282. package/dist/services/settingsService.d.ts +2 -2
  283. package/dist/services/settingsService.js +25 -19
  284. package/dist/services/toastService.d.ts +4 -4
  285. package/dist/services/toastService.js +33 -33
  286. package/dist/services/variableService.d.ts +1 -1
  287. package/dist/services/variableService.js +36 -36
  288. package/dist/services/workflowStorage.d.ts +2 -2
  289. package/dist/services/workflowStorage.js +13 -13
  290. package/dist/settings/index.d.ts +7 -7
  291. package/dist/settings/index.js +6 -6
  292. package/dist/skins/default.d.ts +2 -0
  293. package/dist/skins/default.js +1 -0
  294. package/dist/skins/index.d.ts +13 -0
  295. package/dist/skins/index.js +30 -0
  296. package/dist/skins/slate.d.ts +2 -0
  297. package/dist/skins/slate.js +78 -0
  298. package/dist/stores/categoriesStore.svelte.d.ts +1 -1
  299. package/dist/stores/categoriesStore.svelte.js +5 -5
  300. package/dist/stores/editorStateMachine.svelte.d.ts +2 -2
  301. package/dist/stores/editorStateMachine.svelte.js +65 -33
  302. package/dist/stores/historyStore.svelte.d.ts +4 -4
  303. package/dist/stores/historyStore.svelte.js +4 -4
  304. package/dist/stores/interruptStore.svelte.d.ts +3 -3
  305. package/dist/stores/interruptStore.svelte.js +21 -21
  306. package/dist/stores/playgroundStore.svelte.d.ts +2 -2
  307. package/dist/stores/playgroundStore.svelte.js +25 -18
  308. package/dist/stores/portCoordinateStore.svelte.d.ts +2 -2
  309. package/dist/stores/portCoordinateStore.svelte.js +15 -8
  310. package/dist/stores/settingsStore.svelte.d.ts +2 -2
  311. package/dist/stores/settingsStore.svelte.js +62 -57
  312. package/dist/stores/workflowStore.svelte.d.ts +3 -3
  313. package/dist/stores/workflowStore.svelte.js +50 -47
  314. package/dist/stories/CanvasDecorator.svelte +35 -32
  315. package/dist/stories/CanvasDecorator.svelte.d.ts +2 -2
  316. package/dist/stories/EdgeDecorator.svelte +102 -99
  317. package/dist/stories/EdgeDecorator.svelte.d.ts +1 -1
  318. package/dist/stories/NodeDecorator.svelte +59 -53
  319. package/dist/stories/NodeDecorator.svelte.d.ts +1 -1
  320. package/dist/stories/utils.d.ts +2 -2
  321. package/dist/stories/utils.js +105 -67
  322. package/dist/styles/base.css +599 -595
  323. package/dist/styles/toast.css +14 -14
  324. package/dist/styles/tokens.css +409 -378
  325. package/dist/svelte-app.d.ts +12 -9
  326. package/dist/svelte-app.js +40 -39
  327. package/dist/themes/default.d.ts +2 -0
  328. package/dist/themes/default.js +9 -0
  329. package/dist/themes/index.d.ts +13 -0
  330. package/dist/themes/index.js +44 -0
  331. package/dist/themes/minimal.d.ts +2 -0
  332. package/dist/themes/minimal.js +11 -0
  333. package/dist/types/agentspec.d.ts +18 -18
  334. package/dist/types/agentspec.js +2 -2
  335. package/dist/types/auth.d.ts +1 -1
  336. package/dist/types/auth.js +6 -6
  337. package/dist/types/config.d.ts +6 -6
  338. package/dist/types/events.d.ts +2 -2
  339. package/dist/types/events.js +2 -2
  340. package/dist/types/index.d.ts +32 -32
  341. package/dist/types/index.js +6 -6
  342. package/dist/types/interrupt.d.ts +6 -6
  343. package/dist/types/interrupt.js +21 -21
  344. package/dist/types/interruptState.d.ts +12 -12
  345. package/dist/types/interruptState.js +66 -66
  346. package/dist/types/playground.d.ts +7 -7
  347. package/dist/types/playground.js +14 -14
  348. package/dist/types/settings.d.ts +5 -3
  349. package/dist/types/settings.js +25 -18
  350. package/dist/types/skin.d.ts +31 -0
  351. package/dist/types/skin.js +1 -0
  352. package/dist/types/theme.d.ts +35 -0
  353. package/dist/types/theme.js +1 -0
  354. package/dist/types/uischema.d.ts +4 -4
  355. package/dist/types/uischema.js +3 -3
  356. package/dist/utils/colors.d.ts +1 -1
  357. package/dist/utils/colors.js +97 -95
  358. package/dist/utils/config.d.ts +2 -2
  359. package/dist/utils/config.js +48 -48
  360. package/dist/utils/connections.d.ts +2 -2
  361. package/dist/utils/connections.js +15 -15
  362. package/dist/utils/errors.js +3 -3
  363. package/dist/utils/fetchWithAuth.d.ts +1 -1
  364. package/dist/utils/fetchWithAuth.js +2 -2
  365. package/dist/utils/handleIds.d.ts +2 -2
  366. package/dist/utils/handleIds.js +8 -8
  367. package/dist/utils/handlePositioning.d.ts +1 -1
  368. package/dist/utils/handlePositioning.js +2 -2
  369. package/dist/utils/icons.d.ts +1 -1
  370. package/dist/utils/icons.js +74 -74
  371. package/dist/utils/logger.d.ts +1 -1
  372. package/dist/utils/logger.js +7 -7
  373. package/dist/utils/nodeStatus.d.ts +1 -1
  374. package/dist/utils/nodeStatus.js +48 -48
  375. package/dist/utils/nodeTypes.d.ts +1 -1
  376. package/dist/utils/nodeTypes.js +21 -20
  377. package/dist/utils/nodeWrapper.d.ts +7 -7
  378. package/dist/utils/nodeWrapper.js +21 -19
  379. package/dist/utils/performanceUtils.d.ts +1 -1
  380. package/dist/utils/performanceUtils.js +2 -1
  381. package/dist/utils/sanitize.js +1 -1
  382. package/dist/utils/uischema.d.ts +2 -2
  383. package/dist/utils/uischema.js +8 -8
  384. package/dist/utils/validation.js +20 -8
  385. package/package.json +1 -1
@@ -9,583 +9,617 @@
9
9
  -->
10
10
 
11
11
  <script lang="ts">
12
- import { Position, Handle } from '@xyflow/svelte';
13
- import type { WorkflowNode, NodePort, Branch } from '../../types/index.js';
14
- import Icon from '@iconify/svelte';
15
- import { getNodeIcon } from '../../utils/icons.js';
16
- import {
17
- getDataTypeColorToken,
18
- getCategoryColorToken,
19
- getPortBackgroundColor
20
- } from '../../utils/colors.js';
21
- import { getConnectedHandles } from '../../stores/workflowStore.svelte.js';
22
-
23
- interface Props {
24
- data: WorkflowNode['data'] & {
25
- nodeId?: string;
26
- onConfigOpen?: (node: { id: string; type: string; data: WorkflowNode['data'] }) => void;
27
- };
28
- selected?: boolean;
29
- }
30
-
31
- let props: Props = $props();
32
-
33
- /**
34
- * Instance-specific title override from config.
35
- * Falls back to the original label if not set.
36
- * This allows users to customize the node title per-instance via config.
37
- */
38
- const displayTitle = $derived((props.data.config?.instanceTitle as string) || props.data.label);
39
-
40
- /**
41
- * Instance-specific description override from config.
42
- * Falls back to the metadata description if not set.
43
- * This allows users to customize the node description per-instance via config.
44
- */
45
- const displayDescription = $derived(
46
- (props.data.config?.instanceDescription as string) || props.data.metadata.description
47
- );
48
-
49
- /**
50
- * Get the hideUnconnectedHandles setting from extensions
51
- * Merges node type defaults with instance overrides
52
- */
53
- const hideUnconnectedHandles = $derived(() => {
54
- const typeDefault = props.data.metadata?.extensions?.ui?.hideUnconnectedHandles ?? false;
55
- const instanceOverride = props.data.extensions?.ui?.hideUnconnectedHandles;
56
- return instanceOverride ?? typeDefault;
57
- });
58
-
59
- /**
60
- * Check if a port should be visible based on connection state and settings
61
- * @param port - The port to check
62
- * @param type - Whether this is an 'input' or 'output' port
63
- * @returns true if the port should be visible
64
- */
65
- function isPortVisible(port: NodePort, type: 'input' | 'output'): boolean {
66
- // Always show if hideUnconnectedHandles is disabled
67
- if (!hideUnconnectedHandles()) {
68
- return true;
69
- }
70
-
71
- // Always show required ports
72
- if (port.required) {
73
- return true;
74
- }
75
-
76
- // Check if port is connected
77
- const handleId = `${props.data.nodeId}-${type}-${port.id}`;
78
- return getConnectedHandles().has(handleId);
79
- }
80
-
81
- /**
82
- * Derived list of visible input ports based on hideUnconnectedHandles setting
83
- */
84
- const visibleInputPorts = $derived(
85
- props.data.metadata.inputs.filter((port) => isPortVisible(port, 'input'))
86
- );
87
-
88
- /**
89
- * Check if a branch output should be visible based on connection state
90
- * @param branchName - The branch name to check
91
- * @returns true if the branch should be visible
92
- */
93
- function isBranchVisible(branchName: string): boolean {
94
- // Always show if hideUnconnectedHandles is disabled
95
- if (!hideUnconnectedHandles()) {
96
- return true;
97
- }
98
-
99
- // Check if branch output is connected
100
- const handleId = `${props.data.nodeId}-output-${branchName}`;
101
- return getConnectedHandles().has(handleId);
102
- }
103
-
104
- // Gateway-specific data - branches are calculated at runtime from config
105
- let branches = $derived((props.data.config?.branches as Branch[]) || []);
106
- let activeBranches = $derived(
107
- (props.data.executionInfo?.output?.active_branches as string[]) || []
108
- );
109
-
110
- /**
111
- * Derived list of visible branches based on hideUnconnectedHandles setting
112
- */
113
- const visibleBranches = $derived(branches.filter((branch) => isBranchVisible(branch.name)));
114
-
115
- /**
116
- * Handle node click - only handle selection, no config opening
117
- */
118
- function handleNodeClick(): void {
119
- // Node selection is handled by Svelte Flow
120
- }
121
-
122
- /**
123
- * Handle double-click to open config
124
- */
125
- function handleNodeDoubleClick(): void {
126
- if (props.data.onConfigOpen) {
127
- props.data.onConfigOpen({
128
- id: props.data.nodeId || '',
129
- type: 'gateway',
130
- data: props.data
131
- });
132
- }
133
- }
134
-
135
- /**
136
- * Handle keyboard events for accessibility
137
- */
138
- function handleKeydown(event: KeyboardEvent): void {
139
- if (event.key === 'Enter' || event.key === ' ') {
140
- event.preventDefault();
141
- handleNodeClick();
142
- }
143
- }
144
-
145
- /**
146
- * Check if a branch is active
147
- */
148
- function isBranchActive(branchName: string): boolean {
149
- return activeBranches.includes(branchName);
150
- }
12
+ import { Position, Handle } from "@xyflow/svelte";
13
+ import type { WorkflowNode, NodePort, Branch } from "../../types/index.js";
14
+ import Icon from "@iconify/svelte";
15
+ import { getNodeIcon } from "../../utils/icons.js";
16
+ import {
17
+ getDataTypeColorToken,
18
+ getCategoryColorToken,
19
+ getPortBackgroundColor,
20
+ } from "../../utils/colors.js";
21
+ import { getConnectedHandles } from "../../stores/workflowStore.svelte.js";
22
+
23
+ interface Props {
24
+ data: WorkflowNode["data"] & {
25
+ nodeId?: string;
26
+ onConfigOpen?: (node: {
27
+ id: string;
28
+ type: string;
29
+ data: WorkflowNode["data"];
30
+ }) => void;
31
+ };
32
+ selected?: boolean;
33
+ }
34
+
35
+ let props: Props = $props();
36
+
37
+ /**
38
+ * Instance-specific title override from config.
39
+ * Falls back to the original label if not set.
40
+ * This allows users to customize the node title per-instance via config.
41
+ */
42
+ const displayTitle = $derived(
43
+ (props.data.config?.instanceTitle as string) || props.data.label,
44
+ );
45
+
46
+ /**
47
+ * Instance-specific description override from config.
48
+ * Falls back to the metadata description if not set.
49
+ * This allows users to customize the node description per-instance via config.
50
+ */
51
+ const displayDescription = $derived(
52
+ (props.data.config?.instanceDescription as string) ||
53
+ props.data.metadata.description,
54
+ );
55
+
56
+ /**
57
+ * Get the hideUnconnectedHandles setting from extensions
58
+ * Merges node type defaults with instance overrides
59
+ */
60
+ const hideUnconnectedHandles = $derived(() => {
61
+ const typeDefault =
62
+ props.data.metadata?.extensions?.ui?.hideUnconnectedHandles ?? false;
63
+ const instanceOverride = props.data.extensions?.ui?.hideUnconnectedHandles;
64
+ return instanceOverride ?? typeDefault;
65
+ });
66
+
67
+ /**
68
+ * Check if a port should be visible based on connection state and settings
69
+ * @param port - The port to check
70
+ * @param type - Whether this is an 'input' or 'output' port
71
+ * @returns true if the port should be visible
72
+ */
73
+ function isPortVisible(port: NodePort, type: "input" | "output"): boolean {
74
+ // Always show if hideUnconnectedHandles is disabled
75
+ if (!hideUnconnectedHandles()) {
76
+ return true;
77
+ }
78
+
79
+ // Always show required ports
80
+ if (port.required) {
81
+ return true;
82
+ }
83
+
84
+ // Check if port is connected
85
+ const handleId = `${props.data.nodeId}-${type}-${port.id}`;
86
+ return getConnectedHandles().has(handleId);
87
+ }
88
+
89
+ /**
90
+ * Derived list of visible input ports based on hideUnconnectedHandles setting
91
+ */
92
+ const visibleInputPorts = $derived(
93
+ props.data.metadata.inputs.filter((port) => isPortVisible(port, "input")),
94
+ );
95
+
96
+ /**
97
+ * Check if a branch output should be visible based on connection state
98
+ * @param branchName - The branch name to check
99
+ * @returns true if the branch should be visible
100
+ */
101
+ function isBranchVisible(branchName: string): boolean {
102
+ // Always show if hideUnconnectedHandles is disabled
103
+ if (!hideUnconnectedHandles()) {
104
+ return true;
105
+ }
106
+
107
+ // Check if branch output is connected
108
+ const handleId = `${props.data.nodeId}-output-${branchName}`;
109
+ return getConnectedHandles().has(handleId);
110
+ }
111
+
112
+ // Gateway-specific data - branches are calculated at runtime from config
113
+ let branches = $derived((props.data.config?.branches as Branch[]) || []);
114
+ let activeBranches = $derived(
115
+ (props.data.executionInfo?.output?.active_branches as string[]) || [],
116
+ );
117
+
118
+ /**
119
+ * Derived list of visible branches based on hideUnconnectedHandles setting
120
+ */
121
+ const visibleBranches = $derived(
122
+ branches.filter((branch) => isBranchVisible(branch.name)),
123
+ );
124
+
125
+ /**
126
+ * Handle node click - only handle selection, no config opening
127
+ */
128
+ function handleNodeClick(): void {
129
+ // Node selection is handled by Svelte Flow
130
+ }
131
+
132
+ /**
133
+ * Handle double-click to open config
134
+ */
135
+ function handleNodeDoubleClick(): void {
136
+ if (props.data.onConfigOpen) {
137
+ props.data.onConfigOpen({
138
+ id: props.data.nodeId || "",
139
+ type: "gateway",
140
+ data: props.data,
141
+ });
142
+ }
143
+ }
144
+
145
+ /**
146
+ * Handle keyboard events for accessibility
147
+ */
148
+ function handleKeydown(event: KeyboardEvent): void {
149
+ if (event.key === "Enter" || event.key === " ") {
150
+ event.preventDefault();
151
+ handleNodeClick();
152
+ }
153
+ }
154
+
155
+ /**
156
+ * Check if a branch is active
157
+ */
158
+ function isBranchActive(branchName: string): boolean {
159
+ return activeBranches.includes(branchName);
160
+ }
151
161
  </script>
152
162
 
153
163
  <!-- Node Container -->
154
164
  <div
155
- class="flowdrop-workflow-node flowdrop-workflow-node--gateway"
156
- class:flowdrop-workflow-node--selected={props.selected}
157
- onclick={handleNodeClick}
158
- ondblclick={handleNodeDoubleClick}
159
- onkeydown={handleKeydown}
160
- role="button"
161
- tabindex="0"
162
- aria-label="Gateway node: {displayTitle}"
163
- aria-describedby="node-description-{props.data.nodeId || 'unknown'}"
165
+ class="flowdrop-workflow-node flowdrop-workflow-node--gateway"
166
+ class:flowdrop-workflow-node--selected={props.selected}
167
+ onclick={handleNodeClick}
168
+ ondblclick={handleNodeDoubleClick}
169
+ onkeydown={handleKeydown}
170
+ role="button"
171
+ tabindex="0"
172
+ aria-label="Gateway node: {displayTitle}"
173
+ aria-describedby="node-description-{props.data.nodeId || 'unknown'}"
164
174
  >
165
- <!-- Node Header: expands in multiples of 10 (title row 40px + gap 10px + description 20px per line) -->
166
- <div class="flowdrop-workflow-node__header">
167
- <div class="flowdrop-workflow-node__header-title">
168
- <!-- Node Icon with Squircle Background -->
169
- <div
170
- class="flowdrop-workflow-node__icon-wrapper"
171
- style="--_icon-color: {getCategoryColorToken(props.data.metadata.category)}"
172
- >
173
- <Icon
174
- icon={getNodeIcon(props.data.metadata.icon, props.data.metadata.category)}
175
- class="flowdrop-workflow-node__icon"
176
- />
177
- </div>
178
-
179
- <!-- Node Title - uses instanceTitle override if set -->
180
- <h3 class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1">
181
- {displayTitle}
182
- </h3>
183
- </div>
184
- <!-- Node Description - line-height 20px so header grows in steps of 10 -->
185
- <p
186
- class="flowdrop-workflow-node__header-desc"
187
- id="node-description-{props.data.nodeId || 'unknown'}"
188
- >
189
- {displayDescription}
190
- </p>
191
- </div>
192
-
193
- <!-- Input Ports Container (filtered based on hideUnconnectedHandles) -->
194
- {#if visibleInputPorts.length > 0}
195
- <div class="flowdrop-workflow-node__ports">
196
- <div class="flowdrop-workflow-node__ports-list">
197
- {#each visibleInputPorts as port, inputIndex (port.id)}
198
- <div class="flowdrop-workflow-node__port">
199
- <!-- Input Handle: centered in row, at node edge (ports have no padding) -->
200
- <Handle
201
- type="target"
202
- position={Position.Left}
203
- id={`${props.data.nodeId}-input-${port.id}`}
204
- class="flowdrop-workflow-node__handle"
205
- style="top: 50%; transform: translateY(-50%); --fd-handle-fill: {getDataTypeColorToken(
206
- port.dataType
207
- )}; --fd-handle-border-color: var(--fd-handle-border);"
208
- role="button"
209
- tabindex={0}
210
- aria-label="Connect to {port.name} input port"
211
- />
212
-
213
- <!-- Port Info: padding lives here so handle position is simple -->
214
- <div class="flowdrop-workflow-node__port-content flowdrop-flex--1 flowdrop-min-w--0">
215
- <div class="flowdrop-flex flowdrop-gap--2">
216
- <span class="flowdrop-text--xs flowdrop-font--medium">{port.name}</span>
217
- <span
218
- class="flowdrop-badge flowdrop-badge--sm"
219
- style="background-color: {getPortBackgroundColor(
220
- port.dataType,
221
- 15
222
- )}; color: {getDataTypeColorToken(
223
- port.dataType
224
- )}; border: 1px solid {getPortBackgroundColor(port.dataType, 30)};"
225
- >
226
- {port.dataType}
227
- </span>
228
- {#if port.required}
229
- <span class="flowdrop-badge flowdrop-badge--error flowdrop-badge--sm"
230
- >Required</span
231
- >
232
- {/if}
233
- </div>
234
- {#if port.description}
235
- <p class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate">
236
- {port.description}
237
- </p>
238
- {/if}
239
- </div>
240
- </div>
241
- {/each}
242
- </div>
243
- </div>
244
- {/if}
245
-
246
- <!-- Branches Section (Output Ports) - filtered based on hideUnconnectedHandles -->
247
- {#if visibleBranches.length > 0}
248
- <div class="flowdrop-workflow-node__ports">
249
- <div class="flowdrop-workflow-node__ports-list">
250
- {#each visibleBranches as branch, branchIndex (branch.name)}
251
- {@const isActive = isBranchActive(branch.name)}
252
- <div class="flowdrop-workflow-node__port">
253
- <!-- Port Info: padding lives here so handle position is simple -->
254
- <div
255
- class="flowdrop-workflow-node__port-content flowdrop-flex--1 flowdrop-min-w--0 flowdrop-text--right"
256
- >
257
- <div
258
- class="flowdrop-flex flowdrop-gap--2 flowdrop-justify--end flowdrop-items--center"
259
- >
260
- {#if isActive}
261
- <span style="color: {getDataTypeColorToken('trigger')};">
262
- <Icon icon="mdi:check-circle" />
263
- </span>
264
- {/if}
265
- <span
266
- class="flowdrop-text--xs flowdrop-font--medium"
267
- class:flowdrop-text--active={isActive}
268
- >
269
- {branch.label || branch.name}
270
- </span>
271
- <span
272
- class="flowdrop-badge flowdrop-badge--sm"
273
- style="background-color: {getPortBackgroundColor(
274
- 'trigger',
275
- 15
276
- )}; color: {getDataTypeColorToken(
277
- 'trigger'
278
- )}; border: 1px solid {getPortBackgroundColor('trigger', 30)};"
279
- >
280
- trigger
281
- </span>
282
- </div>
283
- </div>
284
-
285
- <!-- Output Handle: centered in row, at node edge (ports have no padding) -->
286
- <Handle
287
- type="source"
288
- position={Position.Right}
289
- id={`${props.data.nodeId}-output-${branch.name}`}
290
- class={`flowdrop-workflow-node__handle ${isActive ? 'flowdrop-workflow-node__handle--active' : ''}`}
291
- style="top: 50%; transform: translateY(-50%); --fd-handle-fill: {isActive
292
- ? getDataTypeColorToken('trigger')
293
- : getDataTypeColorToken(
294
- 'trigger'
295
- )}; --fd-handle-border-color: var(--fd-handle-border);"
296
- role="button"
297
- tabindex={0}
298
- aria-label="Connect from {branch.name} branch"
299
- />
300
- </div>
301
- {/each}
302
- </div>
303
- </div>
304
- {:else if branches.length === 0}
305
- <!-- No branches configured at all -->
306
- <div class="flowdrop-workflow-node__ports">
307
- <div class="workflow-node__no-branches">
308
- <Icon icon="mdi:alert-circle-outline" />
309
- <span>No branches configured</span>
310
- </div>
311
- </div>
312
- {/if}
313
- <!-- Note: When all branches are hidden due to hideUnconnectedHandles, we don't show anything -->
314
-
315
- <!-- Config button -->
316
- <button
317
- class="flowdrop-workflow-node__config-btn"
318
- onclick={handleNodeDoubleClick}
319
- title="Configure node"
320
- >
321
- <Icon icon="mdi:cog" />
322
- </button>
175
+ <!-- Node Header: expands in multiples of 10 (title row 40px + gap 10px + description 20px per line) -->
176
+ <div class="flowdrop-workflow-node__header">
177
+ <div class="flowdrop-workflow-node__header-title">
178
+ <!-- Node Icon with Squircle Background -->
179
+ <div
180
+ class="flowdrop-workflow-node__icon-wrapper"
181
+ style="--_icon-color: {getCategoryColorToken(
182
+ props.data.metadata.category,
183
+ )}"
184
+ >
185
+ <Icon
186
+ icon={getNodeIcon(
187
+ props.data.metadata.icon,
188
+ props.data.metadata.category,
189
+ )}
190
+ class="flowdrop-workflow-node__icon"
191
+ />
192
+ </div>
193
+
194
+ <!-- Node Title - uses instanceTitle override if set -->
195
+ <h3
196
+ class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
197
+ >
198
+ {displayTitle}
199
+ </h3>
200
+ </div>
201
+ <!-- Node Description - line-height 20px so header grows in steps of 10 -->
202
+ <p
203
+ class="flowdrop-workflow-node__header-desc"
204
+ id="node-description-{props.data.nodeId || 'unknown'}"
205
+ >
206
+ {displayDescription}
207
+ </p>
208
+ </div>
209
+
210
+ <!-- Input Ports Container (filtered based on hideUnconnectedHandles) -->
211
+ {#if visibleInputPorts.length > 0}
212
+ <div class="flowdrop-workflow-node__ports">
213
+ <div class="flowdrop-workflow-node__ports-list">
214
+ {#each visibleInputPorts as port, inputIndex (port.id)}
215
+ <div class="flowdrop-workflow-node__port">
216
+ <!-- Input Handle: centered in row, at node edge (ports have no padding) -->
217
+ <Handle
218
+ type="target"
219
+ position={Position.Left}
220
+ id={`${props.data.nodeId}-input-${port.id}`}
221
+ class="flowdrop-workflow-node__handle"
222
+ style="top: 50%; transform: translateY(-50%); --fd-handle-fill: {getDataTypeColorToken(
223
+ port.dataType,
224
+ )}; --fd-handle-border-color: var(--fd-handle-border);"
225
+ role="button"
226
+ tabindex={0}
227
+ aria-label="Connect to {port.name} input port"
228
+ />
229
+
230
+ <!-- Port Info: padding lives here so handle position is simple -->
231
+ <div
232
+ class="flowdrop-workflow-node__port-content flowdrop-flex--1 flowdrop-min-w--0"
233
+ >
234
+ <div class="flowdrop-flex flowdrop-gap--2">
235
+ <span class="flowdrop-text--xs flowdrop-font--medium"
236
+ >{port.name}</span
237
+ >
238
+ <span
239
+ class="flowdrop-badge flowdrop-badge--sm"
240
+ style="background-color: {getPortBackgroundColor(
241
+ port.dataType,
242
+ 15,
243
+ )}; color: {getDataTypeColorToken(
244
+ port.dataType,
245
+ )}; border: 1px solid {getPortBackgroundColor(
246
+ port.dataType,
247
+ 30,
248
+ )};"
249
+ >
250
+ {port.dataType}
251
+ </span>
252
+ {#if port.required}
253
+ <span
254
+ class="flowdrop-badge flowdrop-badge--error flowdrop-badge--sm"
255
+ >Required</span
256
+ >
257
+ {/if}
258
+ </div>
259
+ {#if port.description}
260
+ <p
261
+ class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate"
262
+ >
263
+ {port.description}
264
+ </p>
265
+ {/if}
266
+ </div>
267
+ </div>
268
+ {/each}
269
+ </div>
270
+ </div>
271
+ {/if}
272
+
273
+ <!-- Branches Section (Output Ports) - filtered based on hideUnconnectedHandles -->
274
+ {#if visibleBranches.length > 0}
275
+ <div class="flowdrop-workflow-node__ports">
276
+ <div class="flowdrop-workflow-node__ports-list">
277
+ {#each visibleBranches as branch, branchIndex (branch.name)}
278
+ {@const isActive = isBranchActive(branch.name)}
279
+ <div class="flowdrop-workflow-node__port">
280
+ <!-- Port Info: padding lives here so handle position is simple -->
281
+ <div
282
+ class="flowdrop-workflow-node__port-content flowdrop-flex--1 flowdrop-min-w--0 flowdrop-text--right"
283
+ >
284
+ <div
285
+ class="flowdrop-flex flowdrop-gap--2 flowdrop-justify--end flowdrop-items--center"
286
+ >
287
+ {#if isActive}
288
+ <span style="color: {getDataTypeColorToken('trigger')};">
289
+ <Icon icon="mdi:check-circle" />
290
+ </span>
291
+ {/if}
292
+ <span
293
+ class="flowdrop-text--xs flowdrop-font--medium"
294
+ class:flowdrop-text--active={isActive}
295
+ >
296
+ {branch.label || branch.name}
297
+ </span>
298
+ <span
299
+ class="flowdrop-badge flowdrop-badge--sm"
300
+ style="background-color: {getPortBackgroundColor(
301
+ 'trigger',
302
+ 15,
303
+ )}; color: {getDataTypeColorToken(
304
+ 'trigger',
305
+ )}; border: 1px solid {getPortBackgroundColor(
306
+ 'trigger',
307
+ 30,
308
+ )};"
309
+ >
310
+ trigger
311
+ </span>
312
+ </div>
313
+ </div>
314
+
315
+ <!-- Output Handle: centered in row, at node edge (ports have no padding) -->
316
+ <Handle
317
+ type="source"
318
+ position={Position.Right}
319
+ id={`${props.data.nodeId}-output-${branch.name}`}
320
+ class={`flowdrop-workflow-node__handle ${isActive ? "flowdrop-workflow-node__handle--active" : ""}`}
321
+ style="top: 50%; transform: translateY(-50%); --fd-handle-fill: {isActive
322
+ ? getDataTypeColorToken('trigger')
323
+ : getDataTypeColorToken(
324
+ 'trigger',
325
+ )}; --fd-handle-border-color: var(--fd-handle-border);"
326
+ role="button"
327
+ tabindex={0}
328
+ aria-label="Connect from {branch.name} branch"
329
+ />
330
+ </div>
331
+ {/each}
332
+ </div>
333
+ </div>
334
+ {:else if branches.length === 0}
335
+ <!-- No branches configured at all -->
336
+ <div class="flowdrop-workflow-node__ports">
337
+ <div class="workflow-node__no-branches">
338
+ <Icon icon="mdi:alert-circle-outline" />
339
+ <span>No branches configured</span>
340
+ </div>
341
+ </div>
342
+ {/if}
343
+ <!-- Note: When all branches are hidden due to hideUnconnectedHandles, we don't show anything -->
344
+
345
+ <!-- Config button -->
346
+ <button
347
+ class="flowdrop-workflow-node__config-btn"
348
+ onclick={handleNodeDoubleClick}
349
+ title="Configure node"
350
+ >
351
+ <Icon icon="mdi:cog" />
352
+ </button>
323
353
  </div>
324
354
 
325
355
  <style>
326
- .flowdrop-workflow-node {
327
- position: relative;
328
- background-color: var(--fd-card);
329
- border: 1.5px solid var(--fd-node-border);
330
- border-radius: var(--fd-radius-xl);
331
- box-shadow: var(--fd-shadow-md);
332
- width: var(--fd-node-default-width);
333
- z-index: 10;
334
- color: var(--fd-foreground);
335
- transition: all var(--fd-transition-fast);
336
- }
337
-
338
- .flowdrop-workflow-node--gateway {
339
- min-width: var(--fd-node-default-width);
340
- }
341
-
342
- .flowdrop-workflow-node:hover {
343
- box-shadow: var(--fd-shadow-lg);
344
- border-color: var(--fd-node-border-hover);
345
- }
346
-
347
- .flowdrop-workflow-node--selected {
348
- box-shadow:
349
- 0 0 0 2px var(--fd-primary-muted),
350
- var(--fd-shadow-lg);
351
- border-color: var(--fd-primary);
352
- }
353
-
354
- .flowdrop-workflow-node--selected:hover {
355
- box-shadow:
356
- 0 0 0 2px var(--fd-primary-muted),
357
- var(--fd-shadow-lg);
358
- border-color: var(--fd-primary);
359
- }
360
-
361
- .flowdrop-workflow-node:focus-visible {
362
- outline: 2px solid var(--fd-ring);
363
- outline-offset: 2px;
364
- }
365
-
366
- .flowdrop-workflow-node__header {
367
- box-sizing: border-box;
368
- padding: var(--fd-node-header-gap) var(--fd-space-xl);
369
- border-bottom: 1px solid var(--fd-border-muted);
370
- background: var(--fd-header);
371
- border-top-left-radius: var(--fd-radius-xl);
372
- border-top-right-radius: var(--fd-radius-xl);
373
- display: flex;
374
- flex-direction: column;
375
- gap: var(--fd-node-header-gap);
376
- min-height: calc(
377
- var(--fd-node-header-gap) * 2 + var(--fd-node-header-title-height) +
378
- var(--fd-node-header-desc-line)
379
- );
380
- }
381
-
382
- .flowdrop-workflow-node__header-title {
383
- display: flex;
384
- align-items: center;
385
- gap: var(--fd-space-md);
386
- min-height: var(--fd-node-header-title-height);
387
- flex-shrink: 0;
388
- }
389
-
390
- .flowdrop-workflow-node__header-desc {
391
- margin: 0;
392
- font-size: var(--fd-text-xs);
393
- color: var(--fd-muted-foreground);
394
- line-height: var(--fd-node-header-desc-line);
395
- min-height: var(--fd-node-header-desc-line);
396
- overflow: hidden;
397
- text-overflow: ellipsis;
398
- display: -webkit-box;
399
- -webkit-line-clamp: 3;
400
- line-clamp: 3;
401
- -webkit-box-orient: vertical;
402
- }
403
-
404
- /* Squircle icon wrapper - Apple-style rounded square background */
405
- .flowdrop-workflow-node__icon-wrapper {
406
- display: flex;
407
- align-items: center;
408
- justify-content: center;
409
- width: 2.25rem;
410
- height: 2.25rem;
411
- border-radius: 0.5rem;
412
- background: color-mix(in srgb, var(--_icon-color) var(--fd-node-icon-bg-opacity), transparent);
413
- flex-shrink: 0;
414
- transition: all var(--fd-transition-normal);
415
- }
416
-
417
- .flowdrop-workflow-node:hover .flowdrop-workflow-node__icon-wrapper {
418
- background: color-mix(
419
- in srgb,
420
- var(--_icon-color) var(--fd-node-icon-bg-opacity-hover),
421
- transparent
422
- );
423
- transform: scale(1.05);
424
- }
425
-
426
- .flowdrop-workflow-node__icon-wrapper :global(.flowdrop-workflow-node__icon) {
427
- width: 1.25rem;
428
- height: 1.25rem;
429
- color: var(--fd-node-icon);
430
- }
431
-
432
- .flowdrop-workflow-node__header-title h3 {
433
- margin: 0;
434
- line-height: 1;
435
- color: var(--fd-foreground);
436
- }
437
-
438
- .flowdrop-workflow-node__ports {
439
- padding: 0;
440
- }
441
-
442
- .flowdrop-workflow-node__ports-list {
443
- display: flex;
444
- flex-direction: column;
445
- gap: var(--fd-node-header-gap);
446
- padding: var(--fd-node-header-gap) 0;
447
- }
448
-
449
- .flowdrop-workflow-node__port {
450
- display: flex;
451
- align-items: center;
452
- gap: 0;
453
- min-height: var(--fd-node-port-row-height);
454
- padding: var(--fd-space-3xs) 0;
455
- position: relative;
456
- }
457
-
458
- .flowdrop-workflow-node__port-content {
459
- padding: 0 var(--fd-space-xl);
460
- }
461
-
462
- .flowdrop-badge {
463
- padding: 0.125rem var(--fd-space-3xs);
464
- border-radius: var(--fd-radius-sm);
465
- font-size: 0.625rem;
466
- font-weight: 500;
467
- text-transform: uppercase;
468
- letter-spacing: 0.05em;
469
- }
470
-
471
- .flowdrop-badge--error {
472
- background-color: var(--fd-error);
473
- color: var(--fd-error-foreground);
474
- }
475
-
476
- .flowdrop-badge--sm {
477
- font-size: 0.625rem;
478
- padding: 0.125rem var(--fd-space-3xs);
479
- }
480
-
481
- .workflow-node__no-branches {
482
- display: flex;
483
- align-items: center;
484
- gap: var(--fd-space-xs);
485
- padding: var(--fd-space-md);
486
- background: var(--fd-warning-muted);
487
- border: 1px solid var(--fd-warning);
488
- border-radius: var(--fd-radius-lg);
489
- color: var(--fd-warning-foreground);
490
- font-size: var(--fd-text-sm);
491
- }
492
-
493
- /* Handle overrides: hover scale, active state (base 20px/12px from base.css) */
494
- :global(.flowdrop-workflow-node__handle:hover) {
495
- transform: translateY(-50%) scale(1.2);
496
- }
497
-
498
- :global(.flowdrop-workflow-node__handle--active::before) {
499
- transform: scale(1.15);
500
- box-shadow: 0 0 0 3px color-mix(in srgb, var(--fd-success) 20%, transparent);
501
- }
502
-
503
- /* Utility classes */
504
- .flowdrop-flex {
505
- display: flex;
506
- }
507
-
508
- .flowdrop-flex--1 {
509
- flex: 1;
510
- }
511
-
512
- .flowdrop-gap--2 {
513
- gap: var(--fd-space-xs);
514
- }
515
-
516
- .flowdrop-items--center {
517
- align-items: center;
518
- }
519
-
520
- .flowdrop-justify--end {
521
- justify-content: flex-end;
522
- }
523
-
524
- .flowdrop-min-w--0 {
525
- min-width: 0;
526
- }
527
-
528
- .flowdrop-text--xs {
529
- font-size: var(--fd-text-xs);
530
- line-height: 1rem;
531
- }
532
-
533
- .flowdrop-text--sm {
534
- font-size: var(--fd-text-sm);
535
- line-height: 1.25rem;
536
- }
537
-
538
- .flowdrop-text--gray {
539
- color: var(--fd-muted-foreground);
540
- }
541
-
542
- .flowdrop-text--active {
543
- color: var(--fd-success);
544
- font-weight: 600;
545
- }
546
-
547
- .flowdrop-font--medium {
548
- font-weight: 500;
549
- }
550
-
551
- .flowdrop-truncate {
552
- overflow: hidden;
553
- text-overflow: ellipsis;
554
- white-space: nowrap;
555
- }
556
-
557
- .flowdrop-text--right {
558
- text-align: right;
559
- }
560
-
561
- .flowdrop-workflow-node__config-btn {
562
- position: absolute;
563
- top: var(--fd-space-xs);
564
- right: var(--fd-space-xs);
565
- width: 1.5rem;
566
- height: 1.5rem;
567
- background-color: var(--fd-backdrop);
568
- border: 1px solid var(--fd-border);
569
- border-radius: var(--fd-radius-sm);
570
- color: var(--fd-muted-foreground);
571
- cursor: pointer;
572
- display: flex;
573
- align-items: center;
574
- justify-content: center;
575
- opacity: 0;
576
- transition: all var(--fd-transition-normal);
577
- backdrop-filter: blur(4px);
578
- z-index: 15;
579
- font-size: var(--fd-text-sm);
580
- }
581
-
582
- .flowdrop-workflow-node:hover .flowdrop-workflow-node__config-btn {
583
- opacity: 1;
584
- }
585
-
586
- .flowdrop-workflow-node__config-btn:hover {
587
- background-color: var(--fd-muted);
588
- border-color: var(--fd-border-strong);
589
- color: var(--fd-foreground);
590
- }
356
+ .flowdrop-workflow-node {
357
+ position: relative;
358
+ background-color: var(--fd-card);
359
+ border: 1.5px solid var(--fd-node-border);
360
+ border-radius: var(--fd-radius-xl);
361
+ box-shadow: var(--fd-shadow-md);
362
+ width: var(--fd-node-default-width);
363
+ z-index: 10;
364
+ color: var(--fd-foreground);
365
+ transition: all var(--fd-transition-fast);
366
+ }
367
+
368
+ .flowdrop-workflow-node--gateway {
369
+ min-width: var(--fd-node-default-width);
370
+ }
371
+
372
+ .flowdrop-workflow-node:hover {
373
+ box-shadow: var(--fd-shadow-lg);
374
+ border-color: var(--fd-node-border-hover);
375
+ }
376
+
377
+ .flowdrop-workflow-node--selected {
378
+ box-shadow:
379
+ 0 0 0 2px var(--fd-primary-muted),
380
+ var(--fd-shadow-lg);
381
+ border-color: var(--fd-primary);
382
+ }
383
+
384
+ .flowdrop-workflow-node--selected:hover {
385
+ box-shadow:
386
+ 0 0 0 2px var(--fd-primary-muted),
387
+ var(--fd-shadow-lg);
388
+ border-color: var(--fd-primary);
389
+ }
390
+
391
+ .flowdrop-workflow-node:focus-visible {
392
+ outline: 2px solid var(--fd-ring);
393
+ outline-offset: 2px;
394
+ }
395
+
396
+ .flowdrop-workflow-node__header {
397
+ box-sizing: border-box;
398
+ padding: var(--fd-node-header-gap) var(--fd-space-xl);
399
+ border-bottom: 1px solid var(--fd-border-muted);
400
+ background: var(--fd-header);
401
+ border-top-left-radius: var(--fd-radius-xl);
402
+ border-top-right-radius: var(--fd-radius-xl);
403
+ display: flex;
404
+ flex-direction: column;
405
+ gap: var(--fd-node-header-gap);
406
+ min-height: calc(
407
+ var(--fd-node-header-gap) * 2 + var(--fd-node-header-title-height) +
408
+ var(--fd-node-header-desc-line)
409
+ );
410
+ }
411
+
412
+ .flowdrop-workflow-node__header-title {
413
+ display: flex;
414
+ align-items: center;
415
+ gap: var(--fd-space-md);
416
+ min-height: var(--fd-node-header-title-height);
417
+ flex-shrink: 0;
418
+ }
419
+
420
+ .flowdrop-workflow-node__header-desc {
421
+ margin: 0;
422
+ font-size: var(--fd-text-xs);
423
+ color: var(--fd-muted-foreground);
424
+ line-height: var(--fd-node-header-desc-line);
425
+ min-height: var(--fd-node-header-desc-line);
426
+ overflow: hidden;
427
+ text-overflow: ellipsis;
428
+ display: -webkit-box;
429
+ -webkit-line-clamp: 3;
430
+ line-clamp: 3;
431
+ -webkit-box-orient: vertical;
432
+ }
433
+
434
+ /* Squircle icon wrapper - Apple-style rounded square background */
435
+ .flowdrop-workflow-node__icon-wrapper {
436
+ display: flex;
437
+ align-items: center;
438
+ justify-content: center;
439
+ width: 2.25rem;
440
+ height: 2.25rem;
441
+ border-radius: 0.5rem;
442
+ background: color-mix(
443
+ in srgb,
444
+ var(--_icon-color) var(--fd-node-icon-bg-opacity),
445
+ transparent
446
+ );
447
+ flex-shrink: 0;
448
+ transition: all var(--fd-transition-normal);
449
+ }
450
+
451
+ .flowdrop-workflow-node:hover .flowdrop-workflow-node__icon-wrapper {
452
+ background: color-mix(
453
+ in srgb,
454
+ var(--_icon-color) var(--fd-node-icon-bg-opacity-hover),
455
+ transparent
456
+ );
457
+ transform: scale(1.05);
458
+ }
459
+
460
+ .flowdrop-workflow-node__icon-wrapper :global(.flowdrop-workflow-node__icon) {
461
+ width: 1.25rem;
462
+ height: 1.25rem;
463
+ color: var(--fd-node-icon);
464
+ }
465
+
466
+ .flowdrop-workflow-node__header-title h3 {
467
+ margin: 0;
468
+ line-height: 1;
469
+ color: var(--fd-foreground);
470
+ }
471
+
472
+ .flowdrop-workflow-node__ports {
473
+ padding: 0;
474
+ }
475
+
476
+ .flowdrop-workflow-node__ports-list {
477
+ display: flex;
478
+ flex-direction: column;
479
+ gap: var(--fd-node-header-gap);
480
+ padding: var(--fd-node-header-gap) 0;
481
+ }
482
+
483
+ .flowdrop-workflow-node__port {
484
+ display: flex;
485
+ align-items: center;
486
+ gap: 0;
487
+ min-height: var(--fd-node-port-row-height);
488
+ padding: var(--fd-space-3xs) 0;
489
+ position: relative;
490
+ }
491
+
492
+ .flowdrop-workflow-node__port-content {
493
+ padding: 0 var(--fd-space-xl);
494
+ }
495
+
496
+ .flowdrop-badge {
497
+ padding: 0.125rem var(--fd-space-3xs);
498
+ border-radius: var(--fd-radius-sm);
499
+ font-size: 0.625rem;
500
+ font-weight: 500;
501
+ text-transform: uppercase;
502
+ letter-spacing: 0.05em;
503
+ }
504
+
505
+ .flowdrop-badge--error {
506
+ background-color: var(--fd-error);
507
+ color: var(--fd-error-foreground);
508
+ }
509
+
510
+ .flowdrop-badge--sm {
511
+ font-size: 0.625rem;
512
+ padding: 0.125rem var(--fd-space-3xs);
513
+ }
514
+
515
+ .workflow-node__no-branches {
516
+ display: flex;
517
+ align-items: center;
518
+ gap: var(--fd-space-xs);
519
+ padding: var(--fd-space-md);
520
+ background: var(--fd-warning-muted);
521
+ border: 1px solid var(--fd-warning);
522
+ border-radius: var(--fd-radius-lg);
523
+ color: var(--fd-warning-foreground);
524
+ font-size: var(--fd-text-sm);
525
+ }
526
+
527
+ /* Handle overrides: hover scale, active state (base 20px/12px from base.css) */
528
+ :global(.flowdrop-workflow-node__handle:hover) {
529
+ transform: translateY(-50%) scale(1.2);
530
+ }
531
+
532
+ :global(.flowdrop-workflow-node__handle--active::before) {
533
+ transform: scale(1.15);
534
+ box-shadow: 0 0 0 3px color-mix(in srgb, var(--fd-success) 20%, transparent);
535
+ }
536
+
537
+ /* Utility classes */
538
+ .flowdrop-flex {
539
+ display: flex;
540
+ }
541
+
542
+ .flowdrop-flex--1 {
543
+ flex: 1;
544
+ }
545
+
546
+ .flowdrop-gap--2 {
547
+ gap: var(--fd-space-xs);
548
+ }
549
+
550
+ .flowdrop-items--center {
551
+ align-items: center;
552
+ }
553
+
554
+ .flowdrop-justify--end {
555
+ justify-content: flex-end;
556
+ }
557
+
558
+ .flowdrop-min-w--0 {
559
+ min-width: 0;
560
+ }
561
+
562
+ .flowdrop-text--xs {
563
+ font-size: var(--fd-text-xs);
564
+ line-height: 1rem;
565
+ }
566
+
567
+ .flowdrop-text--sm {
568
+ font-size: var(--fd-text-sm);
569
+ line-height: 1.25rem;
570
+ }
571
+
572
+ .flowdrop-text--gray {
573
+ color: var(--fd-muted-foreground);
574
+ }
575
+
576
+ .flowdrop-text--active {
577
+ color: var(--fd-success);
578
+ font-weight: 600;
579
+ }
580
+
581
+ .flowdrop-font--medium {
582
+ font-weight: 500;
583
+ }
584
+
585
+ .flowdrop-truncate {
586
+ overflow: hidden;
587
+ text-overflow: ellipsis;
588
+ white-space: nowrap;
589
+ }
590
+
591
+ .flowdrop-text--right {
592
+ text-align: right;
593
+ }
594
+
595
+ .flowdrop-workflow-node__config-btn {
596
+ position: absolute;
597
+ top: var(--fd-space-xs);
598
+ right: var(--fd-space-xs);
599
+ width: 1.5rem;
600
+ height: 1.5rem;
601
+ background-color: var(--fd-backdrop);
602
+ border: 1px solid var(--fd-border);
603
+ border-radius: var(--fd-radius-sm);
604
+ color: var(--fd-muted-foreground);
605
+ cursor: pointer;
606
+ display: flex;
607
+ align-items: center;
608
+ justify-content: center;
609
+ opacity: 0;
610
+ transition: all var(--fd-transition-normal);
611
+ backdrop-filter: blur(4px);
612
+ z-index: 15;
613
+ font-size: var(--fd-text-sm);
614
+ }
615
+
616
+ .flowdrop-workflow-node:hover .flowdrop-workflow-node__config-btn {
617
+ opacity: 1;
618
+ }
619
+
620
+ .flowdrop-workflow-node__config-btn:hover {
621
+ background-color: var(--fd-muted);
622
+ border-color: var(--fd-border-strong);
623
+ color: var(--fd-foreground);
624
+ }
591
625
  </style>