@flowdrop/flowdrop 1.0.0 → 1.1.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 (388) 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 +1081 -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 +46 -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 +197 -0
  36. package/dist/components/FlowDropEdge.stories.svelte.d.ts +26 -0
  37. package/dist/components/FlowDropEdge.svelte +168 -0
  38. package/dist/components/FlowDropEdge.svelte.d.ts +4 -0
  39. package/dist/components/FlowDropZone.svelte +63 -60
  40. package/dist/components/FlowDropZone.svelte.d.ts +1 -1
  41. package/dist/components/LoadingSpinner.stories.svelte +19 -19
  42. package/dist/components/LoadingSpinner.stories.svelte.d.ts +1 -1
  43. package/dist/components/LoadingSpinner.svelte +21 -21
  44. package/dist/components/LoadingSpinner.svelte.d.ts +1 -1
  45. package/dist/components/Logo.stories.svelte +13 -13
  46. package/dist/components/Logo.stories.svelte.d.ts +1 -1
  47. package/dist/components/Logo.svelte +101 -95
  48. package/dist/components/LogsSidebar.svelte +553 -546
  49. package/dist/components/LogsSidebar.svelte.d.ts +1 -1
  50. package/dist/components/MarkdownDisplay.stories.svelte +29 -23
  51. package/dist/components/MarkdownDisplay.stories.svelte.d.ts +1 -1
  52. package/dist/components/MarkdownDisplay.svelte +16 -14
  53. package/dist/components/Navbar.stories.svelte +43 -38
  54. package/dist/components/Navbar.stories.svelte.d.ts +1 -1
  55. package/dist/components/Navbar.svelte +760 -706
  56. package/dist/components/Navbar.svelte.d.ts +1 -1
  57. package/dist/components/NodeSidebar.svelte +900 -746
  58. package/dist/components/NodeSidebar.svelte.d.ts +3 -1
  59. package/dist/components/NodeStatusOverlay.stories.svelte +82 -70
  60. package/dist/components/NodeStatusOverlay.stories.svelte.d.ts +1 -1
  61. package/dist/components/NodeStatusOverlay.svelte +295 -280
  62. package/dist/components/NodeStatusOverlay.svelte.d.ts +3 -3
  63. package/dist/components/PipelineStatus.svelte +326 -300
  64. package/dist/components/PipelineStatus.svelte.d.ts +4 -4
  65. package/dist/components/PortCoordinateTracker.svelte +49 -47
  66. package/dist/components/PortCoordinateTracker.svelte.d.ts +1 -1
  67. package/dist/components/ReadOnlyDetails.svelte +156 -156
  68. package/dist/components/SchemaForm.stories.svelte +106 -98
  69. package/dist/components/SchemaForm.stories.svelte.d.ts +1 -1
  70. package/dist/components/SchemaForm.svelte +490 -463
  71. package/dist/components/SchemaForm.svelte.d.ts +2 -2
  72. package/dist/components/SettingsModal.svelte +226 -223
  73. package/dist/components/SettingsModal.svelte.d.ts +1 -1
  74. package/dist/components/SettingsPanel.svelte +637 -601
  75. package/dist/components/SettingsPanel.svelte.d.ts +1 -1
  76. package/dist/components/StatusIcon.stories.svelte +62 -49
  77. package/dist/components/StatusIcon.stories.svelte.d.ts +1 -1
  78. package/dist/components/StatusIcon.svelte +87 -87
  79. package/dist/components/StatusIcon.svelte.d.ts +2 -2
  80. package/dist/components/StatusLabel.stories.svelte +12 -12
  81. package/dist/components/StatusLabel.stories.svelte.d.ts +1 -1
  82. package/dist/components/StatusLabel.svelte +19 -19
  83. package/dist/components/ThemeToggle.stories.svelte +16 -16
  84. package/dist/components/ThemeToggle.stories.svelte.d.ts +1 -1
  85. package/dist/components/ThemeToggle.svelte +180 -169
  86. package/dist/components/ThemeToggle.svelte.d.ts +1 -1
  87. package/dist/components/UniversalNode.svelte +150 -138
  88. package/dist/components/UniversalNode.svelte.d.ts +3 -3
  89. package/dist/components/WorkflowEditor.svelte +1069 -1007
  90. package/dist/components/WorkflowEditor.svelte.d.ts +4 -4
  91. package/dist/components/form/FormArray.svelte +1034 -973
  92. package/dist/components/form/FormArray.svelte.d.ts +1 -1
  93. package/dist/components/form/FormAutocomplete.svelte +1021 -978
  94. package/dist/components/form/FormAutocomplete.svelte.d.ts +1 -1
  95. package/dist/components/form/FormCheckboxGroup.stories.svelte +23 -20
  96. package/dist/components/form/FormCheckboxGroup.stories.svelte.d.ts +1 -1
  97. package/dist/components/form/FormCheckboxGroup.svelte +136 -136
  98. package/dist/components/form/FormCodeEditor.svelte +452 -434
  99. package/dist/components/form/FormField.svelte +366 -355
  100. package/dist/components/form/FormField.svelte.d.ts +2 -2
  101. package/dist/components/form/FormFieldLight.svelte +400 -384
  102. package/dist/components/form/FormFieldLight.svelte.d.ts +1 -1
  103. package/dist/components/form/FormFieldWrapper.stories.svelte +42 -42
  104. package/dist/components/form/FormFieldWrapper.stories.svelte.d.ts +1 -1
  105. package/dist/components/form/FormFieldWrapper.svelte +100 -93
  106. package/dist/components/form/FormFieldWrapper.svelte.d.ts +1 -1
  107. package/dist/components/form/FormFieldset.svelte +108 -108
  108. package/dist/components/form/FormFieldset.svelte.d.ts +2 -2
  109. package/dist/components/form/FormMarkdownEditor.svelte +758 -725
  110. package/dist/components/form/FormNumberField.stories.svelte +25 -25
  111. package/dist/components/form/FormNumberField.stories.svelte.d.ts +1 -1
  112. package/dist/components/form/FormNumberField.svelte +88 -88
  113. package/dist/components/form/FormRangeField.stories.svelte +20 -20
  114. package/dist/components/form/FormRangeField.stories.svelte.d.ts +1 -1
  115. package/dist/components/form/FormRangeField.svelte +234 -226
  116. package/dist/components/form/FormSelect.stories.svelte +38 -38
  117. package/dist/components/form/FormSelect.stories.svelte.d.ts +1 -1
  118. package/dist/components/form/FormSelect.svelte +101 -101
  119. package/dist/components/form/FormSelect.svelte.d.ts +1 -1
  120. package/dist/components/form/FormTemplateEditor.svelte +847 -798
  121. package/dist/components/form/FormTemplateEditor.svelte.d.ts +1 -1
  122. package/dist/components/form/FormTextField.stories.svelte +29 -23
  123. package/dist/components/form/FormTextField.stories.svelte.d.ts +1 -1
  124. package/dist/components/form/FormTextField.svelte +68 -68
  125. package/dist/components/form/FormTextarea.stories.svelte +28 -25
  126. package/dist/components/form/FormTextarea.stories.svelte.d.ts +1 -1
  127. package/dist/components/form/FormTextarea.svelte +74 -74
  128. package/dist/components/form/FormToggle.stories.svelte +23 -20
  129. package/dist/components/form/FormToggle.stories.svelte.d.ts +1 -1
  130. package/dist/components/form/FormToggle.svelte +98 -98
  131. package/dist/components/form/FormUISchemaRenderer.svelte +120 -113
  132. package/dist/components/form/FormUISchemaRenderer.svelte.d.ts +3 -3
  133. package/dist/components/form/index.d.ts +19 -19
  134. package/dist/components/form/index.js +18 -18
  135. package/dist/components/form/templateAutocomplete.d.ts +2 -2
  136. package/dist/components/form/templateAutocomplete.js +64 -55
  137. package/dist/components/form/types.d.ts +6 -6
  138. package/dist/components/form/types.js +9 -4
  139. package/dist/components/icons/AlertCircleIcon.svelte +11 -0
  140. package/dist/components/icons/AlertCircleIcon.svelte.d.ts +26 -0
  141. package/dist/components/icons/CogIcon.svelte +11 -0
  142. package/dist/components/icons/CogIcon.svelte.d.ts +26 -0
  143. package/dist/components/interrupt/ChoicePrompt.stories.svelte +54 -38
  144. package/dist/components/interrupt/ChoicePrompt.stories.svelte.d.ts +1 -1
  145. package/dist/components/interrupt/ChoicePrompt.svelte +407 -383
  146. package/dist/components/interrupt/ChoicePrompt.svelte.d.ts +1 -1
  147. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte +48 -48
  148. package/dist/components/interrupt/ConfirmationPrompt.stories.svelte.d.ts +1 -1
  149. package/dist/components/interrupt/ConfirmationPrompt.svelte +280 -274
  150. package/dist/components/interrupt/ConfirmationPrompt.svelte.d.ts +1 -1
  151. package/dist/components/interrupt/FormPrompt.svelte +223 -218
  152. package/dist/components/interrupt/FormPrompt.svelte.d.ts +1 -1
  153. package/dist/components/interrupt/InterruptBubble.svelte +617 -583
  154. package/dist/components/interrupt/InterruptBubble.svelte.d.ts +2 -2
  155. package/dist/components/interrupt/ReviewPrompt.stories.svelte +66 -56
  156. package/dist/components/interrupt/ReviewPrompt.stories.svelte.d.ts +1 -1
  157. package/dist/components/interrupt/ReviewPrompt.svelte +861 -841
  158. package/dist/components/interrupt/ReviewPrompt.svelte.d.ts +1 -1
  159. package/dist/components/interrupt/TextInputPrompt.stories.svelte +38 -33
  160. package/dist/components/interrupt/TextInputPrompt.stories.svelte.d.ts +1 -1
  161. package/dist/components/interrupt/TextInputPrompt.svelte +333 -328
  162. package/dist/components/interrupt/TextInputPrompt.svelte.d.ts +1 -1
  163. package/dist/components/interrupt/index.d.ts +5 -5
  164. package/dist/components/interrupt/index.js +5 -5
  165. package/dist/components/layouts/MainLayout.svelte +724 -691
  166. package/dist/components/layouts/MainLayout.svelte.d.ts +6 -6
  167. package/dist/components/nodes/GatewayNode.stories.svelte +100 -99
  168. package/dist/components/nodes/GatewayNode.svelte +605 -571
  169. package/dist/components/nodes/GatewayNode.svelte.d.ts +3 -3
  170. package/dist/components/nodes/IdeaNode.stories.svelte +44 -43
  171. package/dist/components/nodes/IdeaNode.svelte +451 -437
  172. package/dist/components/nodes/IdeaNode.svelte.d.ts +1 -1
  173. package/dist/components/nodes/NotesNode.stories.svelte +65 -64
  174. package/dist/components/nodes/NotesNode.svelte +380 -369
  175. package/dist/components/nodes/NotesNode.svelte.d.ts +1 -1
  176. package/dist/components/nodes/SimpleNode.stories.svelte +145 -144
  177. package/dist/components/nodes/SimpleNode.svelte +486 -424
  178. package/dist/components/nodes/SimpleNode.svelte.d.ts +1 -1
  179. package/dist/components/nodes/SquareNode.stories.svelte +73 -73
  180. package/dist/components/nodes/SquareNode.svelte +439 -380
  181. package/dist/components/nodes/SquareNode.svelte.d.ts +1 -1
  182. package/dist/components/nodes/TerminalNode.stories.svelte +13 -13
  183. package/dist/components/nodes/TerminalNode.svelte +709 -670
  184. package/dist/components/nodes/TerminalNode.svelte.d.ts +1 -1
  185. package/dist/components/nodes/ToolNode.stories.svelte +181 -180
  186. package/dist/components/nodes/ToolNode.svelte +505 -447
  187. package/dist/components/nodes/ToolNode.svelte.d.ts +1 -1
  188. package/dist/components/nodes/WorkflowNode.stories.svelte +70 -46
  189. package/dist/components/nodes/WorkflowNode.svelte +621 -551
  190. package/dist/components/nodes/WorkflowNode.svelte.d.ts +3 -3
  191. package/dist/components/playground/ChatPanel.svelte +945 -889
  192. package/dist/components/playground/ExecutionLogs.svelte +495 -472
  193. package/dist/components/playground/InputCollector.svelte +449 -428
  194. package/dist/components/playground/MessageBubble.stories.svelte +47 -47
  195. package/dist/components/playground/MessageBubble.stories.svelte.d.ts +1 -1
  196. package/dist/components/playground/MessageBubble.svelte +626 -610
  197. package/dist/components/playground/MessageBubble.svelte.d.ts +1 -1
  198. package/dist/components/playground/Playground.svelte +1088 -1057
  199. package/dist/components/playground/Playground.svelte.d.ts +3 -3
  200. package/dist/components/playground/PlaygroundModal.svelte +208 -204
  201. package/dist/components/playground/PlaygroundModal.svelte.d.ts +3 -3
  202. package/dist/components/playground/SessionManager.svelte +527 -521
  203. package/dist/components/playground/SessionManager.svelte.d.ts +1 -1
  204. package/dist/config/agentSpecEndpoints.d.ts +1 -1
  205. package/dist/config/agentSpecEndpoints.js +20 -20
  206. package/dist/config/constants.d.ts +8 -0
  207. package/dist/config/constants.js +10 -2
  208. package/dist/config/defaultCategories.d.ts +1 -1
  209. package/dist/config/defaultCategories.js +86 -86
  210. package/dist/config/defaultPortConfig.d.ts +1 -1
  211. package/dist/config/defaultPortConfig.js +144 -144
  212. package/dist/config/endpoints.d.ts +4 -4
  213. package/dist/config/endpoints.js +65 -65
  214. package/dist/config/runtimeConfig.d.ts +2 -2
  215. package/dist/config/runtimeConfig.js +8 -8
  216. package/dist/core/index.d.ts +63 -59
  217. package/dist/core/index.js +35 -33
  218. package/dist/display/index.d.ts +2 -2
  219. package/dist/display/index.js +2 -2
  220. package/dist/editor/index.d.ts +62 -62
  221. package/dist/editor/index.js +53 -53
  222. package/dist/form/code.d.ts +5 -5
  223. package/dist/form/code.js +14 -14
  224. package/dist/form/fieldRegistry.d.ts +3 -3
  225. package/dist/form/fieldRegistry.js +11 -9
  226. package/dist/form/full.d.ts +8 -8
  227. package/dist/form/full.js +9 -9
  228. package/dist/form/index.d.ts +18 -18
  229. package/dist/form/index.js +16 -16
  230. package/dist/form/markdown.d.ts +4 -4
  231. package/dist/form/markdown.js +8 -8
  232. package/dist/helpers/proximityConnect.d.ts +3 -3
  233. package/dist/helpers/proximityConnect.js +34 -32
  234. package/dist/helpers/workflowEditorHelper.d.ts +5 -5
  235. package/dist/helpers/workflowEditorHelper.js +108 -96
  236. package/dist/index.d.ts +6 -6
  237. package/dist/index.js +6 -6
  238. package/dist/mocks/app-environment.js +2 -2
  239. package/dist/mocks/app-forms.js +9 -9
  240. package/dist/mocks/app-navigation.js +11 -11
  241. package/dist/mocks/app-stores.js +8 -8
  242. package/dist/playground/index.d.ts +19 -19
  243. package/dist/playground/index.js +16 -16
  244. package/dist/playground/mount.d.ts +3 -3
  245. package/dist/playground/mount.js +24 -24
  246. package/dist/registry/builtinFormats.js +13 -13
  247. package/dist/registry/builtinNodes.d.ts +2 -2
  248. package/dist/registry/builtinNodes.js +77 -77
  249. package/dist/registry/index.d.ts +4 -4
  250. package/dist/registry/index.js +4 -4
  251. package/dist/registry/nodeComponentRegistry.d.ts +8 -8
  252. package/dist/registry/nodeComponentRegistry.js +11 -9
  253. package/dist/registry/plugin.d.ts +2 -2
  254. package/dist/registry/plugin.js +11 -11
  255. package/dist/registry/workflowFormatRegistry.d.ts +3 -3
  256. package/dist/registry/workflowFormatRegistry.js +2 -2
  257. package/dist/schema/index.d.ts +1 -1
  258. package/dist/schema/index.js +2 -2
  259. package/dist/schemas/v1/workflow.schema.json +22 -107
  260. package/dist/services/agentSpecExecutionService.d.ts +3 -3
  261. package/dist/services/agentSpecExecutionService.js +59 -55
  262. package/dist/services/api.d.ts +18 -4
  263. package/dist/services/api.js +46 -43
  264. package/dist/services/apiVariableService.d.ts +1 -1
  265. package/dist/services/apiVariableService.js +41 -34
  266. package/dist/services/autoSaveService.js +8 -8
  267. package/dist/services/categoriesApi.d.ts +2 -2
  268. package/dist/services/categoriesApi.js +8 -8
  269. package/dist/services/draftStorage.d.ts +1 -1
  270. package/dist/services/draftStorage.js +11 -11
  271. package/dist/services/dynamicSchemaService.d.ts +1 -1
  272. package/dist/services/dynamicSchemaService.js +41 -39
  273. package/dist/services/globalSave.d.ts +2 -2
  274. package/dist/services/globalSave.js +53 -42
  275. package/dist/services/historyService.d.ts +1 -1
  276. package/dist/services/historyService.js +8 -8
  277. package/dist/services/interruptService.d.ts +1 -1
  278. package/dist/services/interruptService.js +35 -29
  279. package/dist/services/nodeExecutionService.d.ts +1 -1
  280. package/dist/services/nodeExecutionService.js +45 -44
  281. package/dist/services/playgroundService.d.ts +1 -1
  282. package/dist/services/playgroundService.js +29 -29
  283. package/dist/services/portConfigApi.d.ts +2 -2
  284. package/dist/services/portConfigApi.js +8 -8
  285. package/dist/services/settingsService.d.ts +2 -2
  286. package/dist/services/settingsService.js +25 -19
  287. package/dist/services/toastService.d.ts +4 -4
  288. package/dist/services/toastService.js +33 -33
  289. package/dist/services/variableService.d.ts +1 -1
  290. package/dist/services/variableService.js +36 -36
  291. package/dist/services/workflowStorage.d.ts +2 -2
  292. package/dist/services/workflowStorage.js +13 -13
  293. package/dist/settings/index.d.ts +7 -7
  294. package/dist/settings/index.js +6 -6
  295. package/dist/skins/default.d.ts +2 -0
  296. package/dist/skins/default.js +1 -0
  297. package/dist/skins/index.d.ts +13 -0
  298. package/dist/skins/index.js +30 -0
  299. package/dist/skins/slate.d.ts +2 -0
  300. package/dist/skins/slate.js +78 -0
  301. package/dist/stores/categoriesStore.svelte.d.ts +1 -1
  302. package/dist/stores/categoriesStore.svelte.js +5 -5
  303. package/dist/stores/editorStateMachine.svelte.d.ts +2 -2
  304. package/dist/stores/editorStateMachine.svelte.js +65 -33
  305. package/dist/stores/historyStore.svelte.d.ts +4 -4
  306. package/dist/stores/historyStore.svelte.js +4 -4
  307. package/dist/stores/interruptStore.svelte.d.ts +3 -3
  308. package/dist/stores/interruptStore.svelte.js +21 -21
  309. package/dist/stores/playgroundStore.svelte.d.ts +2 -2
  310. package/dist/stores/playgroundStore.svelte.js +25 -18
  311. package/dist/stores/portCoordinateStore.svelte.d.ts +2 -2
  312. package/dist/stores/portCoordinateStore.svelte.js +15 -8
  313. package/dist/stores/settingsStore.svelte.d.ts +2 -2
  314. package/dist/stores/settingsStore.svelte.js +62 -57
  315. package/dist/stores/workflowStore.svelte.d.ts +3 -3
  316. package/dist/stores/workflowStore.svelte.js +50 -47
  317. package/dist/stories/CanvasDecorator.svelte +35 -32
  318. package/dist/stories/CanvasDecorator.svelte.d.ts +2 -2
  319. package/dist/stories/EdgeDecorator.svelte +125 -0
  320. package/dist/stories/EdgeDecorator.svelte.d.ts +17 -0
  321. package/dist/stories/NodeDecorator.svelte +59 -53
  322. package/dist/stories/NodeDecorator.svelte.d.ts +1 -1
  323. package/dist/stories/utils.d.ts +2 -2
  324. package/dist/stories/utils.js +105 -67
  325. package/dist/styles/base.css +599 -595
  326. package/dist/styles/toast.css +14 -14
  327. package/dist/styles/tokens.css +409 -378
  328. package/dist/svelte-app.d.ts +9 -9
  329. package/dist/svelte-app.js +39 -39
  330. package/dist/themes/default.d.ts +2 -0
  331. package/dist/themes/default.js +9 -0
  332. package/dist/themes/index.d.ts +13 -0
  333. package/dist/themes/index.js +44 -0
  334. package/dist/themes/minimal.d.ts +2 -0
  335. package/dist/themes/minimal.js +11 -0
  336. package/dist/types/agentspec.d.ts +18 -18
  337. package/dist/types/agentspec.js +2 -2
  338. package/dist/types/auth.d.ts +1 -1
  339. package/dist/types/auth.js +6 -6
  340. package/dist/types/config.d.ts +6 -6
  341. package/dist/types/events.d.ts +2 -2
  342. package/dist/types/events.js +2 -2
  343. package/dist/types/index.d.ts +32 -32
  344. package/dist/types/index.js +6 -6
  345. package/dist/types/interrupt.d.ts +6 -6
  346. package/dist/types/interrupt.js +21 -21
  347. package/dist/types/interruptState.d.ts +12 -12
  348. package/dist/types/interruptState.js +66 -66
  349. package/dist/types/playground.d.ts +7 -7
  350. package/dist/types/playground.js +14 -14
  351. package/dist/types/settings.d.ts +5 -3
  352. package/dist/types/settings.js +25 -18
  353. package/dist/types/skin.d.ts +31 -0
  354. package/dist/types/skin.js +1 -0
  355. package/dist/types/theme.d.ts +35 -0
  356. package/dist/types/theme.js +1 -0
  357. package/dist/types/uischema.d.ts +4 -4
  358. package/dist/types/uischema.js +3 -3
  359. package/dist/utils/colors.d.ts +1 -1
  360. package/dist/utils/colors.js +97 -95
  361. package/dist/utils/config.d.ts +2 -2
  362. package/dist/utils/config.js +48 -48
  363. package/dist/utils/connections.d.ts +2 -2
  364. package/dist/utils/connections.js +15 -15
  365. package/dist/utils/errors.js +3 -3
  366. package/dist/utils/fetchWithAuth.d.ts +1 -1
  367. package/dist/utils/fetchWithAuth.js +2 -2
  368. package/dist/utils/handleIds.d.ts +2 -2
  369. package/dist/utils/handleIds.js +8 -8
  370. package/dist/utils/handlePositioning.d.ts +1 -1
  371. package/dist/utils/handlePositioning.js +2 -2
  372. package/dist/utils/icons.d.ts +1 -1
  373. package/dist/utils/icons.js +74 -74
  374. package/dist/utils/logger.d.ts +1 -1
  375. package/dist/utils/logger.js +7 -7
  376. package/dist/utils/nodeStatus.d.ts +1 -1
  377. package/dist/utils/nodeStatus.js +48 -48
  378. package/dist/utils/nodeTypes.d.ts +1 -1
  379. package/dist/utils/nodeTypes.js +21 -20
  380. package/dist/utils/nodeWrapper.d.ts +7 -7
  381. package/dist/utils/nodeWrapper.js +21 -19
  382. package/dist/utils/performanceUtils.d.ts +1 -1
  383. package/dist/utils/performanceUtils.js +2 -1
  384. package/dist/utils/sanitize.js +1 -1
  385. package/dist/utils/uischema.d.ts +2 -2
  386. package/dist/utils/uischema.js +8 -8
  387. package/dist/utils/validation.js +20 -8
  388. package/package.json +296 -291
@@ -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>