@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,563 +9,633 @@
9
9
  -->
10
10
 
11
11
  <script lang="ts">
12
- import { Position, Handle } from '@xyflow/svelte';
13
- import type { WorkflowNode, NodePort, DynamicPort } from '../../types/index.js';
14
- import { dynamicPortToNodePort } from '../../types/index.js';
15
- import Icon from '@iconify/svelte';
16
- import { getNodeIcon } from '../../utils/icons.js';
17
- import {
18
- getDataTypeColorToken,
19
- getCategoryColorToken,
20
- getPortBackgroundColor
21
- } from '../../utils/colors.js';
22
- import { getConnectedHandles } from '../../stores/workflowStore.svelte.js';
23
-
24
- interface Props {
25
- data: WorkflowNode['data'] & {
26
- nodeId?: string;
27
- onConfigOpen?: (node: { id: string; type: string; data: WorkflowNode['data'] }) => void;
28
- };
29
- selected?: boolean;
30
- }
31
-
32
- let props: Props = $props();
33
- let isHandleInteraction = $state(false);
34
-
35
- /**
36
- * Instance-specific title override from config.
37
- * Falls back to the original label if not set.
38
- * This allows users to customize the node title per-instance via config.
39
- */
40
- const displayTitle = $derived((props.data.config?.instanceTitle as string) || props.data.label);
41
-
42
- /**
43
- * Instance-specific description override from config.
44
- * Falls back to the metadata description if not set.
45
- * This allows users to customize the node description per-instance via config.
46
- */
47
- const displayDescription = $derived(
48
- (props.data.config?.instanceDescription as string) || props.data.metadata.description
49
- );
50
-
51
- /**
52
- * Get the hideUnconnectedHandles setting from extensions
53
- * Merges node type defaults with instance overrides
54
- */
55
- const hideUnconnectedHandles = $derived(() => {
56
- const typeDefault = props.data.metadata?.extensions?.ui?.hideUnconnectedHandles ?? false;
57
- const instanceOverride = props.data.extensions?.ui?.hideUnconnectedHandles;
58
- return instanceOverride ?? typeDefault;
59
- });
60
-
61
- /**
62
- * Dynamic inputs from config - user-defined input ports
63
- * Similar to how branches work in GatewayNode
64
- */
65
- const dynamicInputs = $derived(
66
- ((props.data.config?.dynamicInputs as DynamicPort[]) || []).map((port) =>
67
- dynamicPortToNodePort(port, 'input')
68
- )
69
- );
70
-
71
- /**
72
- * Dynamic outputs from config - user-defined output ports
73
- * Similar to how branches work in GatewayNode
74
- */
75
- const dynamicOutputs = $derived(
76
- ((props.data.config?.dynamicOutputs as DynamicPort[]) || []).map((port) =>
77
- dynamicPortToNodePort(port, 'output')
78
- )
79
- );
80
-
81
- /**
82
- * Combined input ports: static metadata inputs + dynamic config inputs
83
- */
84
- const allInputPorts = $derived([...props.data.metadata.inputs, ...dynamicInputs]);
85
-
86
- /**
87
- * Combined output ports: static metadata outputs + dynamic config outputs
88
- */
89
- const allOutputPorts = $derived([...props.data.metadata.outputs, ...dynamicOutputs]);
90
-
91
- /**
92
- * Check if a port should be visible based on connection state and settings
93
- * @param port - The port to check
94
- * @param type - Whether this is an 'input' or 'output' port
95
- * @returns true if the port should be visible
96
- */
97
- function isPortVisible(port: NodePort, type: 'input' | 'output'): boolean {
98
- // Always show if hideUnconnectedHandles is disabled
99
- if (!hideUnconnectedHandles()) {
100
- return true;
101
- }
102
-
103
- // Always show required ports
104
- if (port.required) {
105
- return true;
106
- }
107
-
108
- // Check if port is connected
109
- const handleId = `${props.data.nodeId}-${type}-${port.id}`;
110
- return getConnectedHandles().has(handleId);
111
- }
112
-
113
- /**
114
- * Derived list of visible input ports based on hideUnconnectedHandles setting
115
- * Now includes both static and dynamic inputs
116
- */
117
- const visibleInputPorts = $derived(allInputPorts.filter((port) => isPortVisible(port, 'input')));
118
-
119
- /**
120
- * Derived list of visible output ports based on hideUnconnectedHandles setting
121
- * Now includes both static and dynamic outputs
122
- */
123
- const visibleOutputPorts = $derived(
124
- allOutputPorts.filter((port) => isPortVisible(port, 'output'))
125
- );
126
-
127
- /**
128
- * Handle node click - only handle selection, no config opening
129
- */
130
- function handleNodeClick(): void {
131
- // Node selection is handled by Svelte Flow
132
- }
133
-
134
- /**
135
- * Handle double-click to open config
136
- */
137
- function handleDoubleClick(): void {
138
- openConfigSidebar();
139
- }
140
-
141
- /**
142
- * Handle configuration sidebar - now using global ConfigSidebar
143
- */
144
- function openConfigSidebar(): void {
145
- if (props.data.onConfigOpen) {
146
- // Create a WorkflowNodeType-like object for the global ConfigSidebar
147
- const nodeForConfig = {
148
- id: props.data.nodeId || 'unknown',
149
- type: 'workflowNode',
150
- data: props.data
151
- };
152
- props.data.onConfigOpen(nodeForConfig);
153
- }
154
- }
12
+ import { Position, Handle } from "@xyflow/svelte";
13
+ import type {
14
+ WorkflowNode,
15
+ NodePort,
16
+ DynamicPort,
17
+ } from "../../types/index.js";
18
+ import { dynamicPortToNodePort } from "../../types/index.js";
19
+ import Icon from "@iconify/svelte";
20
+ import { getNodeIcon } from "../../utils/icons.js";
21
+ import CogIcon from "../icons/CogIcon.svelte";
22
+ import {
23
+ getDataTypeColorToken,
24
+ getCategoryColorToken,
25
+ getPortBackgroundColor,
26
+ } from "../../utils/colors.js";
27
+ import { getConnectedHandles } from "../../stores/workflowStore.svelte.js";
28
+
29
+ interface Props {
30
+ data: WorkflowNode["data"] & {
31
+ nodeId?: string;
32
+ onConfigOpen?: (node: {
33
+ id: string;
34
+ type: string;
35
+ data: WorkflowNode["data"];
36
+ }) => void;
37
+ };
38
+ selected?: boolean;
39
+ }
40
+
41
+ let props: Props = $props();
42
+ let isHandleInteraction = $state(false);
43
+
44
+ /**
45
+ * Instance-specific title override from config.
46
+ * Falls back to the original label if not set.
47
+ * This allows users to customize the node title per-instance via config.
48
+ */
49
+ const displayTitle = $derived(
50
+ (props.data.config?.instanceTitle as string) || props.data.label,
51
+ );
52
+
53
+ /**
54
+ * Instance-specific description override from config.
55
+ * Falls back to the metadata description if not set.
56
+ * This allows users to customize the node description per-instance via config.
57
+ */
58
+ const displayDescription = $derived(
59
+ (props.data.config?.instanceDescription as string) ||
60
+ props.data.metadata.description,
61
+ );
62
+
63
+ /**
64
+ * Get the hideUnconnectedHandles setting from extensions
65
+ * Merges node type defaults with instance overrides
66
+ */
67
+ const hideUnconnectedHandles = $derived(() => {
68
+ const typeDefault =
69
+ props.data.metadata?.extensions?.ui?.hideUnconnectedHandles ?? false;
70
+ const instanceOverride = props.data.extensions?.ui?.hideUnconnectedHandles;
71
+ return instanceOverride ?? typeDefault;
72
+ });
73
+
74
+ /**
75
+ * Dynamic inputs from config - user-defined input ports
76
+ * Similar to how branches work in GatewayNode
77
+ */
78
+ const dynamicInputs = $derived(
79
+ ((props.data.config?.dynamicInputs as DynamicPort[]) || []).map((port) =>
80
+ dynamicPortToNodePort(port, "input"),
81
+ ),
82
+ );
83
+
84
+ /**
85
+ * Dynamic outputs from config - user-defined output ports
86
+ * Similar to how branches work in GatewayNode
87
+ */
88
+ const dynamicOutputs = $derived(
89
+ ((props.data.config?.dynamicOutputs as DynamicPort[]) || []).map((port) =>
90
+ dynamicPortToNodePort(port, "output"),
91
+ ),
92
+ );
93
+
94
+ /**
95
+ * Combined input ports: static metadata inputs + dynamic config inputs
96
+ */
97
+ const allInputPorts = $derived([
98
+ ...props.data.metadata.inputs,
99
+ ...dynamicInputs,
100
+ ]);
101
+
102
+ /**
103
+ * Combined output ports: static metadata outputs + dynamic config outputs
104
+ */
105
+ const allOutputPorts = $derived([
106
+ ...props.data.metadata.outputs,
107
+ ...dynamicOutputs,
108
+ ]);
109
+
110
+ /**
111
+ * Check if a port should be visible based on connection state and settings
112
+ * @param port - The port to check
113
+ * @param type - Whether this is an 'input' or 'output' port
114
+ * @returns true if the port should be visible
115
+ */
116
+ function isPortVisible(port: NodePort, type: "input" | "output"): boolean {
117
+ // Always show if hideUnconnectedHandles is disabled
118
+ if (!hideUnconnectedHandles()) {
119
+ return true;
120
+ }
121
+
122
+ // Always show required ports
123
+ if (port.required) {
124
+ return true;
125
+ }
126
+
127
+ // Check if port is connected
128
+ const handleId = `${props.data.nodeId}-${type}-${port.id}`;
129
+ return getConnectedHandles().has(handleId);
130
+ }
131
+
132
+ /**
133
+ * Derived list of visible input ports based on hideUnconnectedHandles setting
134
+ * Now includes both static and dynamic inputs
135
+ */
136
+ const visibleInputPorts = $derived(
137
+ allInputPorts.filter((port) => isPortVisible(port, "input")),
138
+ );
139
+
140
+ /**
141
+ * Derived list of visible output ports based on hideUnconnectedHandles setting
142
+ * Now includes both static and dynamic outputs
143
+ */
144
+ const visibleOutputPorts = $derived(
145
+ allOutputPorts.filter((port) => isPortVisible(port, "output")),
146
+ );
147
+
148
+ /**
149
+ * Handle node click - only handle selection, no config opening
150
+ */
151
+ function handleNodeClick(): void {
152
+ // Node selection is handled by Svelte Flow
153
+ }
154
+
155
+ /**
156
+ * Handle double-click to open config
157
+ */
158
+ function handleDoubleClick(): void {
159
+ openConfigSidebar();
160
+ }
161
+
162
+ /**
163
+ * Handle configuration sidebar - now using global ConfigSidebar
164
+ */
165
+ function openConfigSidebar(): void {
166
+ if (props.data.onConfigOpen) {
167
+ // Create a WorkflowNodeType-like object for the global ConfigSidebar
168
+ const nodeForConfig = {
169
+ id: props.data.nodeId || "unknown",
170
+ type: "workflowNode",
171
+ data: props.data,
172
+ };
173
+ props.data.onConfigOpen(nodeForConfig);
174
+ }
175
+ }
155
176
  </script>
156
177
 
157
178
  <!-- Node Container -->
158
179
  <div
159
- class="flowdrop-workflow-node"
160
- class:flowdrop-workflow-node--selected={props.selected}
161
- onclick={handleNodeClick}
162
- ondblclick={handleDoubleClick}
163
- onmouseup={() => {
164
- isHandleInteraction = false;
165
- }}
166
- data-handle-interaction={isHandleInteraction}
167
- role="button"
168
- tabindex="0"
169
- onkeydown={(e) => {
170
- if (e.key === 'Enter' || e.key === ' ') {
171
- e.preventDefault();
172
- handleDoubleClick();
173
- }
174
- }}
175
- aria-label="Workflow node: {props.data.metadata.name}"
176
- aria-describedby="node-description-{props.data.nodeId || 'unknown'}"
180
+ class="flowdrop-workflow-node"
181
+ class:flowdrop-workflow-node--selected={props.selected}
182
+ onclick={handleNodeClick}
183
+ ondblclick={handleDoubleClick}
184
+ onmouseup={() => {
185
+ isHandleInteraction = false;
186
+ }}
187
+ data-handle-interaction={isHandleInteraction}
188
+ role="button"
189
+ tabindex="0"
190
+ onkeydown={(e) => {
191
+ if (e.key === "Enter" || e.key === " ") {
192
+ e.preventDefault();
193
+ handleDoubleClick();
194
+ }
195
+ }}
196
+ aria-label="Workflow node: {props.data.metadata.name}"
197
+ aria-describedby="node-description-{props.data.nodeId || 'unknown'}"
177
198
  >
178
- <!-- Default Node Header: expands in multiples of 10 (title row 40px + gap 10px + description 20px per line) -->
179
- <div class="flowdrop-workflow-node__header">
180
- <div class="flowdrop-workflow-node__header-title">
181
- <!-- Node Icon with Squircle Background -->
182
- <div
183
- class="flowdrop-workflow-node__icon-wrapper"
184
- style="--_icon-color: {getCategoryColorToken(props.data.metadata.category)}"
185
- >
186
- <Icon
187
- icon={getNodeIcon(props.data.metadata.icon, props.data.metadata.category)}
188
- class="flowdrop-workflow-node__icon"
189
- />
190
- </div>
191
-
192
- <!-- Node Title - Icon and Title on same line -->
193
- <h3 class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1">
194
- {displayTitle}
195
- </h3>
196
-
197
- <!-- Status Indicators -->
198
- <div class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center"></div>
199
- </div>
200
- <!-- Node Description - line-height 20px so header grows in steps of 10 -->
201
- <p
202
- class="flowdrop-workflow-node__header-desc"
203
- id="node-description-{props.data.nodeId || 'unknown'}"
204
- >
205
- {displayDescription}
206
- </p>
207
- </div>
208
-
209
- <!-- Input Ports Container -->
210
- {#if visibleInputPorts.length > 0}
211
- <div class="flowdrop-workflow-node__ports">
212
- <div class="flowdrop-workflow-node__ports-list">
213
- {#each visibleInputPorts as port, inputIndex (port.id)}
214
- <div class="flowdrop-workflow-node__port">
215
- <!-- Input Handle: centered in row, at node edge (ports have no padding) -->
216
- <Handle
217
- type="target"
218
- position={Position.Left}
219
- id={`${props.data.nodeId}-input-${port.id}`}
220
- class="flowdrop-workflow-node__handle"
221
- style="top: 50%; transform: translateY(-50%); --fd-handle-fill: {getDataTypeColorToken(
222
- port.dataType
223
- )}; --fd-handle-border-color: var(--fd-handle-border);"
224
- role="button"
225
- tabindex={0}
226
- aria-label="Connect to {port.name} input port"
227
- />
228
-
229
- <!-- Port Info: padding lives here so handle position is simple -->
230
- <div class="flowdrop-workflow-node__port-content flowdrop-flex--1 flowdrop-min-w--0">
231
- <div class="flowdrop-flex flowdrop-gap--2">
232
- <span class="flowdrop-text--xs flowdrop-font--medium">{port.name}</span>
233
- <span
234
- class="flowdrop-badge flowdrop-badge--sm"
235
- style="background-color: {getPortBackgroundColor(
236
- port.dataType,
237
- 15
238
- )}; color: {getDataTypeColorToken(
239
- port.dataType
240
- )}; border: 1px solid {getPortBackgroundColor(port.dataType, 30)};"
241
- >
242
- {port.dataType}
243
- </span>
244
- {#if port.required}
245
- <span class="flowdrop-badge flowdrop-badge--error flowdrop-badge--sm"
246
- >Required</span
247
- >
248
- {/if}
249
- </div>
250
- {#if port.description}
251
- <p class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate">
252
- {port.description}
253
- </p>
254
- {/if}
255
- </div>
256
- </div>
257
- {/each}
258
- </div>
259
- </div>
260
- {/if}
261
-
262
- <!-- Output Ports Container -->
263
- {#if visibleOutputPorts.length > 0}
264
- <div class="flowdrop-workflow-node__ports">
265
- <div class="flowdrop-workflow-node__ports-list">
266
- {#each visibleOutputPorts as port, outputIndex (port.id)}
267
- <div class="flowdrop-workflow-node__port">
268
- <!-- Port Info: padding lives here so handle position is simple -->
269
- <div
270
- class="flowdrop-workflow-node__port-content flowdrop-flex--1 flowdrop-min-w--0 flowdrop-text--right"
271
- >
272
- <div class="flowdrop-flex flowdrop-gap--2 flowdrop-justify--end">
273
- <span class="flowdrop-text--xs flowdrop-font--medium">{port.name}</span>
274
- <span
275
- class="flowdrop-badge flowdrop-badge--sm"
276
- style="background-color: {getPortBackgroundColor(
277
- port.dataType,
278
- 15
279
- )}; color: {getDataTypeColorToken(
280
- port.dataType
281
- )}; border: 1px solid {getPortBackgroundColor(port.dataType, 30)};"
282
- >
283
- {port.dataType}
284
- </span>
285
- </div>
286
- {#if port.description}
287
- <p class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate">
288
- {port.description}
289
- </p>
290
- {/if}
291
- </div>
292
-
293
- <!-- Output Handle: centered in row, at node edge (ports have no padding) -->
294
- <Handle
295
- type="source"
296
- position={Position.Right}
297
- id={`${props.data.nodeId}-output-${port.id}`}
298
- class="flowdrop-workflow-node__handle"
299
- style="top: 50%; transform: translateY(-50%); --fd-handle-fill: {getDataTypeColorToken(
300
- port.dataType
301
- )}; --fd-handle-border-color: var(--fd-handle-border);"
302
- role="button"
303
- tabindex={0}
304
- aria-label="Connect from {port.name} output port"
305
- />
306
- </div>
307
- {/each}
308
- </div>
309
- </div>
310
- {/if}
311
-
312
- <!-- Config button -->
313
- <button
314
- class="flowdrop-workflow-node__config-btn"
315
- onclick={openConfigSidebar}
316
- title="Configure node"
317
- >
318
- <Icon icon="mdi:cog" />
319
- </button>
199
+ <!-- Default Node Header: expands in multiples of 10 (title row 40px + gap 10px + description 20px per line) -->
200
+ <div class="flowdrop-workflow-node__header">
201
+ <div class="flowdrop-workflow-node__header-title">
202
+ <!-- Squircle icon visibility controlled by --fd-node-icon-display -->
203
+ <div
204
+ class="flowdrop-workflow-node__icon-wrapper"
205
+ style="--_icon-color: {getCategoryColorToken(
206
+ props.data.metadata.category,
207
+ )}"
208
+ >
209
+ <Icon
210
+ icon={getNodeIcon(
211
+ props.data.metadata.icon,
212
+ props.data.metadata.category,
213
+ )}
214
+ class="flowdrop-workflow-node__icon"
215
+ />
216
+ </div>
217
+ <!-- Circle dot — visibility controlled by --fd-node-circle-display -->
218
+ <span
219
+ class="flowdrop-workflow-node__color-dot"
220
+ style="background: {getCategoryColorToken(
221
+ props.data.metadata.category,
222
+ )}"
223
+ ></span>
224
+
225
+ <!-- Node Title - Icon and Title on same line -->
226
+ <h3
227
+ class="flowdrop-text--sm flowdrop-font--medium flowdrop-truncate flowdrop-flex--1"
228
+ >
229
+ {displayTitle}
230
+ </h3>
231
+
232
+ <!-- Status Indicators -->
233
+ <div class="flowdrop-flex flowdrop-gap--2 flowdrop-items--center"></div>
234
+ </div>
235
+ <!-- Node Description - line-height 20px so header grows in steps of 10 -->
236
+ <p
237
+ class="flowdrop-workflow-node__header-desc"
238
+ id="node-description-{props.data.nodeId || 'unknown'}"
239
+ >
240
+ {displayDescription}
241
+ </p>
242
+ </div>
243
+
244
+ <!-- Input Ports Container -->
245
+ {#if visibleInputPorts.length > 0}
246
+ <div class="flowdrop-workflow-node__ports">
247
+ <div class="flowdrop-workflow-node__ports-list">
248
+ {#each visibleInputPorts as port, inputIndex (port.id)}
249
+ <div class="flowdrop-workflow-node__port">
250
+ <!-- Input Handle: centered in row, at node edge (ports have no padding) -->
251
+ <Handle
252
+ type="target"
253
+ position={Position.Left}
254
+ id={`${props.data.nodeId}-input-${port.id}`}
255
+ class="flowdrop-workflow-node__handle"
256
+ style="top: 50%; transform: translateY(-50%); --fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColorToken(
257
+ port.dataType,
258
+ )}); --fd-handle-border-color: var(--fd-handle-border);"
259
+ role="button"
260
+ tabindex={0}
261
+ aria-label="Connect to {port.name} input port"
262
+ />
263
+
264
+ <!-- Port Info: padding lives here so handle position is simple -->
265
+ <div
266
+ class="flowdrop-workflow-node__port-content flowdrop-flex--1 flowdrop-min-w--0"
267
+ >
268
+ <div class="flowdrop-flex flowdrop-gap--2">
269
+ <span class="flowdrop-text--xs flowdrop-font--medium"
270
+ >{port.name}</span
271
+ >
272
+ <span
273
+ class="flowdrop-badge flowdrop-badge--sm"
274
+ style="background-color: {getPortBackgroundColor(
275
+ port.dataType,
276
+ 15,
277
+ )}; color: {getDataTypeColorToken(
278
+ port.dataType,
279
+ )}; border: 1px solid {getPortBackgroundColor(
280
+ port.dataType,
281
+ 30,
282
+ )};"
283
+ >
284
+ {port.dataType}
285
+ </span>
286
+ {#if port.required}
287
+ <span
288
+ class="flowdrop-badge flowdrop-badge--error flowdrop-badge--sm"
289
+ >Required</span
290
+ >
291
+ {/if}
292
+ </div>
293
+ {#if port.description}
294
+ <p
295
+ class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate"
296
+ >
297
+ {port.description}
298
+ </p>
299
+ {/if}
300
+ </div>
301
+ </div>
302
+ {/each}
303
+ </div>
304
+ </div>
305
+ {/if}
306
+
307
+ <!-- Output Ports Container -->
308
+ {#if visibleOutputPorts.length > 0}
309
+ <div class="flowdrop-workflow-node__ports">
310
+ <div class="flowdrop-workflow-node__ports-list">
311
+ {#each visibleOutputPorts as port, outputIndex (port.id)}
312
+ <div class="flowdrop-workflow-node__port">
313
+ <!-- Port Info: padding lives here so handle position is simple -->
314
+ <div
315
+ class="flowdrop-workflow-node__port-content flowdrop-flex--1 flowdrop-min-w--0 flowdrop-text--right"
316
+ >
317
+ <div class="flowdrop-flex flowdrop-gap--2 flowdrop-justify--end">
318
+ <span class="flowdrop-text--xs flowdrop-font--medium"
319
+ >{port.name}</span
320
+ >
321
+ <span
322
+ class="flowdrop-badge flowdrop-badge--sm"
323
+ style="background-color: {getPortBackgroundColor(
324
+ port.dataType,
325
+ 15,
326
+ )}; color: {getDataTypeColorToken(
327
+ port.dataType,
328
+ )}; border: 1px solid {getPortBackgroundColor(
329
+ port.dataType,
330
+ 30,
331
+ )};"
332
+ >
333
+ {port.dataType}
334
+ </span>
335
+ </div>
336
+ {#if port.description}
337
+ <p
338
+ class="flowdrop-text--xs flowdrop-text--gray flowdrop-truncate"
339
+ >
340
+ {port.description}
341
+ </p>
342
+ {/if}
343
+ </div>
344
+
345
+ <!-- Output Handle: centered in row, at node edge (ports have no padding) -->
346
+ <Handle
347
+ type="source"
348
+ position={Position.Right}
349
+ id={`${props.data.nodeId}-output-${port.id}`}
350
+ class="flowdrop-workflow-node__handle"
351
+ style="top: 50%; transform: translateY(-50%); --fd-handle-fill: var(--fd-port-skin-color, {getDataTypeColorToken(
352
+ port.dataType,
353
+ )}); --fd-handle-border-color: var(--fd-handle-border);"
354
+ role="button"
355
+ tabindex={0}
356
+ aria-label="Connect from {port.name} output port"
357
+ />
358
+ </div>
359
+ {/each}
360
+ </div>
361
+ </div>
362
+ {/if}
363
+
364
+ <!-- Config button -->
365
+ <button
366
+ class="flowdrop-workflow-node__config-btn"
367
+ onclick={openConfigSidebar}
368
+ title="Configure node"
369
+ >
370
+ <CogIcon />
371
+ </button>
320
372
  </div>
321
373
 
322
374
  <style>
323
- .flowdrop-workflow-node {
324
- position: relative;
325
- background-color: var(--fd-card);
326
- border: 1.5px solid var(--fd-node-border);
327
- border-radius: var(--fd-radius-xl);
328
- box-shadow: var(--fd-shadow-md);
329
- width: var(--fd-node-default-width);
330
- z-index: 10;
331
- color: var(--fd-foreground);
332
- transition: all var(--fd-transition-fast);
333
- }
334
-
335
- .flowdrop-workflow-node:hover {
336
- box-shadow: var(--fd-shadow-lg);
337
- border-color: var(--fd-node-border-hover);
338
- }
339
-
340
- .flowdrop-workflow-node--selected {
341
- box-shadow:
342
- 0 0 0 2px var(--fd-primary-muted),
343
- var(--fd-shadow-lg);
344
- border-color: var(--fd-primary);
345
- }
346
-
347
- .flowdrop-workflow-node--selected:hover {
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:focus-visible {
355
- outline: 2px solid var(--fd-ring);
356
- outline-offset: 2px;
357
- }
358
-
359
- .flowdrop-workflow-node__header {
360
- box-sizing: border-box;
361
- padding: var(--fd-node-header-gap) var(--fd-space-xl);
362
- border-bottom: 1px solid var(--fd-border-muted);
363
- background: var(--fd-header);
364
- border-top-left-radius: var(--fd-radius-xl);
365
- border-top-right-radius: var(--fd-radius-xl);
366
- display: flex;
367
- flex-direction: column;
368
- gap: var(--fd-node-header-gap);
369
- min-height: calc(
370
- var(--fd-node-header-gap) * 2 + var(--fd-node-header-title-height) +
371
- var(--fd-node-header-desc-line)
372
- );
373
- }
374
-
375
- .flowdrop-workflow-node__header-title {
376
- display: flex;
377
- align-items: center;
378
- gap: var(--fd-space-md);
379
- min-height: var(--fd-node-header-title-height);
380
- flex-shrink: 0;
381
- }
382
-
383
- .flowdrop-workflow-node__header-desc {
384
- margin: 0;
385
- font-size: var(--fd-text-xs);
386
- color: var(--fd-muted-foreground);
387
- line-height: var(--fd-node-header-desc-line);
388
- min-height: var(--fd-node-header-desc-line);
389
- overflow: hidden;
390
- text-overflow: ellipsis;
391
- display: -webkit-box;
392
- -webkit-line-clamp: 3;
393
- line-clamp: 3;
394
- -webkit-box-orient: vertical;
395
- }
396
-
397
- /* Squircle icon wrapper - Apple-style rounded square background */
398
- .flowdrop-workflow-node__icon-wrapper {
399
- display: flex;
400
- align-items: center;
401
- justify-content: center;
402
- width: 2.25rem;
403
- height: 2.25rem;
404
- border-radius: 0.5rem;
405
- background: color-mix(in srgb, var(--_icon-color) var(--fd-node-icon-bg-opacity), transparent);
406
- flex-shrink: 0;
407
- transition: all var(--fd-transition-normal);
408
- }
409
-
410
- .flowdrop-workflow-node:hover .flowdrop-workflow-node__icon-wrapper {
411
- background: color-mix(
412
- in srgb,
413
- var(--_icon-color) var(--fd-node-icon-bg-opacity-hover),
414
- transparent
415
- );
416
- transform: scale(1.05);
417
- }
418
-
419
- .flowdrop-workflow-node__icon-wrapper :global(.flowdrop-workflow-node__icon) {
420
- width: 1.25rem;
421
- height: 1.25rem;
422
- color: var(--fd-node-icon);
423
- }
424
-
425
- .flowdrop-workflow-node__header-title h3 {
426
- margin: 0;
427
- line-height: 1;
428
- }
429
-
430
- @keyframes pulse {
431
- 0%,
432
- 100% {
433
- opacity: 1;
434
- }
435
- 50% {
436
- opacity: 0.5;
437
- }
438
- }
439
-
440
- .flowdrop-workflow-node__ports {
441
- padding: 0;
442
- }
443
-
444
- .flowdrop-workflow-node__ports-list {
445
- display: flex;
446
- flex-direction: column;
447
- gap: var(--fd-node-header-gap);
448
- padding: var(--fd-node-header-gap) 0;
449
- }
450
-
451
- .flowdrop-workflow-node__port {
452
- display: flex;
453
- align-items: center;
454
- gap: 0;
455
- min-height: var(--fd-node-port-row-height);
456
- padding: var(--fd-space-3xs) 0;
457
- position: relative;
458
- }
459
-
460
- .flowdrop-workflow-node__port-content {
461
- padding: 0 var(--fd-space-xl);
462
- }
463
-
464
- .flowdrop-badge {
465
- padding: 0.125rem var(--fd-space-3xs);
466
- border-radius: var(--fd-radius-sm);
467
- font-size: 0.625rem;
468
- font-weight: 500;
469
- text-transform: uppercase;
470
- letter-spacing: 0.05em;
471
- }
472
-
473
- .flowdrop-badge--error {
474
- background-color: var(--fd-error);
475
- color: var(--fd-error-foreground);
476
- }
477
-
478
- .flowdrop-badge--sm {
479
- font-size: 0.625rem;
480
- padding: 0.125rem var(--fd-space-3xs);
481
- }
482
-
483
- /* Handle overrides: hover scale (base 20px/12px from base.css) */
484
- :global(.flowdrop-workflow-node__handle:hover) {
485
- transform: translateY(-50%) scale(1.2);
486
- }
487
-
488
- /* Utility classes */
489
- .flowdrop-flex {
490
- display: flex;
491
- }
492
-
493
- .flowdrop-flex--1 {
494
- flex: 1;
495
- }
496
-
497
- .flowdrop-gap--2 {
498
- gap: var(--fd-space-xs);
499
- }
500
-
501
- .flowdrop-items--center {
502
- align-items: center;
503
- }
504
-
505
- .flowdrop-justify--end {
506
- justify-content: flex-end;
507
- }
508
-
509
- .flowdrop-min-w--0 {
510
- min-width: 0;
511
- }
512
-
513
- .flowdrop-text--xs {
514
- font-size: var(--fd-text-xs);
515
- line-height: 1rem;
516
- }
517
-
518
- .flowdrop-text--sm {
519
- font-size: var(--fd-text-sm);
520
- line-height: 1.25rem;
521
- }
522
-
523
- .flowdrop-text--gray {
524
- color: var(--fd-muted-foreground);
525
- }
526
-
527
- .flowdrop-font--medium {
528
- font-weight: 500;
529
- }
530
-
531
- .flowdrop-truncate {
532
- overflow: hidden;
533
- text-overflow: ellipsis;
534
- white-space: nowrap;
535
- }
536
-
537
- .flowdrop-text--right {
538
- text-align: right;
539
- }
540
-
541
- .flowdrop-workflow-node__config-btn {
542
- position: absolute;
543
- top: var(--fd-space-xs);
544
- right: var(--fd-space-xs);
545
- width: 1.5rem;
546
- height: 1.5rem;
547
- background-color: var(--fd-backdrop);
548
- border: 1px solid var(--fd-border);
549
- border-radius: var(--fd-radius-sm);
550
- color: var(--fd-muted-foreground);
551
- cursor: pointer;
552
- display: flex;
553
- align-items: center;
554
- justify-content: center;
555
- opacity: 0;
556
- transition: all var(--fd-transition-normal);
557
- backdrop-filter: var(--fd-backdrop-blur);
558
- z-index: 15;
559
- font-size: var(--fd-text-sm);
560
- }
561
-
562
- .flowdrop-workflow-node:hover .flowdrop-workflow-node__config-btn {
563
- opacity: 1;
564
- }
565
-
566
- .flowdrop-workflow-node__config-btn:hover {
567
- background-color: var(--fd-muted);
568
- border-color: var(--fd-border-strong);
569
- color: var(--fd-foreground);
570
- }
375
+ .flowdrop-workflow-node {
376
+ position: relative;
377
+ background-color: var(--fd-card);
378
+ border: 1.5px solid var(--fd-node-border);
379
+ border-radius: var(--fd-radius-xl);
380
+ box-shadow: var(--fd-shadow-md);
381
+ width: var(--fd-node-default-width);
382
+ z-index: 10;
383
+ color: var(--fd-foreground);
384
+ transition: all var(--fd-transition-fast);
385
+ }
386
+
387
+ .flowdrop-workflow-node:hover {
388
+ box-shadow: var(--fd-shadow-lg);
389
+ border-color: var(--fd-node-border-hover);
390
+ }
391
+
392
+ .flowdrop-workflow-node--selected {
393
+ box-shadow:
394
+ 0 0 0 2px var(--fd-primary-muted),
395
+ var(--fd-shadow-lg);
396
+ border-color: var(--fd-primary);
397
+ }
398
+
399
+ .flowdrop-workflow-node--selected:hover {
400
+ box-shadow:
401
+ 0 0 0 2px var(--fd-primary-muted),
402
+ var(--fd-shadow-lg);
403
+ border-color: var(--fd-primary);
404
+ }
405
+
406
+ .flowdrop-workflow-node:focus-visible {
407
+ outline: 2px solid var(--fd-ring);
408
+ outline-offset: 2px;
409
+ }
410
+
411
+ .flowdrop-workflow-node__header {
412
+ box-sizing: border-box;
413
+ padding: var(--fd-node-header-gap) var(--fd-space-xl);
414
+ border-bottom: 1px solid var(--fd-border-muted);
415
+ background: var(--fd-header);
416
+ border-top-left-radius: var(--fd-radius-xl);
417
+ border-top-right-radius: var(--fd-radius-xl);
418
+ display: flex;
419
+ flex-direction: column;
420
+ gap: var(--fd-node-header-gap);
421
+ min-height: calc(
422
+ var(--fd-node-header-gap) * 2 + var(--fd-node-header-title-height) +
423
+ var(--fd-node-header-desc-line)
424
+ );
425
+ }
426
+
427
+ .flowdrop-workflow-node__header-title {
428
+ display: flex;
429
+ align-items: center;
430
+ gap: var(--fd-space-md);
431
+ min-height: var(--fd-node-header-title-height);
432
+ flex-shrink: 0;
433
+ }
434
+
435
+ .flowdrop-workflow-node__header-desc {
436
+ margin: 0;
437
+ font-size: var(--fd-text-xs);
438
+ color: var(--fd-muted-foreground);
439
+ line-height: var(--fd-node-header-desc-line);
440
+ min-height: var(--fd-node-header-desc-line);
441
+ overflow: hidden;
442
+ text-overflow: ellipsis;
443
+ display: -webkit-box;
444
+ -webkit-line-clamp: 3;
445
+ line-clamp: 3;
446
+ -webkit-box-orient: vertical;
447
+ }
448
+
449
+ /* Squircle icon wrapper - Apple-style rounded square background */
450
+ .flowdrop-workflow-node__icon-wrapper {
451
+ display: var(--fd-node-icon-display, flex);
452
+ align-items: center;
453
+ justify-content: center;
454
+ width: 2.25rem;
455
+ height: 2.25rem;
456
+ border-radius: 0.5rem;
457
+ background: color-mix(
458
+ in srgb,
459
+ var(--_icon-color) var(--fd-node-icon-bg-opacity),
460
+ transparent
461
+ );
462
+ flex-shrink: 0;
463
+ transition: all var(--fd-transition-normal);
464
+ }
465
+
466
+ .flowdrop-workflow-node:hover .flowdrop-workflow-node__icon-wrapper {
467
+ background: color-mix(
468
+ in srgb,
469
+ var(--_icon-color) var(--fd-node-icon-bg-opacity-hover),
470
+ transparent
471
+ );
472
+ transform: scale(1.05);
473
+ }
474
+
475
+ .flowdrop-workflow-node__icon-wrapper :global(.flowdrop-workflow-node__icon) {
476
+ width: 1.25rem;
477
+ height: 1.25rem;
478
+ color: var(--fd-node-icon);
479
+ }
480
+
481
+ /* Circle dot icon — shown in minimal skin via --fd-node-circle-display */
482
+ .flowdrop-workflow-node__color-dot {
483
+ width: 10px;
484
+ height: 10px;
485
+ border-radius: 50%;
486
+ flex-shrink: 0;
487
+ display: var(--fd-node-circle-display, none);
488
+ }
489
+
490
+ .flowdrop-workflow-node__header-title h3 {
491
+ margin: 0;
492
+ line-height: 1;
493
+ }
494
+
495
+ @keyframes pulse {
496
+ 0%,
497
+ 100% {
498
+ opacity: 1;
499
+ }
500
+ 50% {
501
+ opacity: 0.5;
502
+ }
503
+ }
504
+
505
+ .flowdrop-workflow-node__ports {
506
+ padding: 0;
507
+ }
508
+
509
+ .flowdrop-workflow-node__ports-list {
510
+ display: flex;
511
+ flex-direction: column;
512
+ gap: var(--fd-node-header-gap);
513
+ padding: var(--fd-node-header-gap) 0;
514
+ }
515
+
516
+ .flowdrop-workflow-node__port {
517
+ display: flex;
518
+ align-items: center;
519
+ gap: 0;
520
+ min-height: var(--fd-node-port-row-height);
521
+ padding: var(--fd-space-3xs) 0;
522
+ position: relative;
523
+ }
524
+
525
+ .flowdrop-workflow-node__port-content {
526
+ padding: 0 var(--fd-space-xl);
527
+ }
528
+
529
+ .flowdrop-badge {
530
+ padding: 0.125rem var(--fd-space-3xs);
531
+ border-radius: var(--fd-radius-sm);
532
+ font-size: 0.625rem;
533
+ font-weight: 500;
534
+ text-transform: uppercase;
535
+ letter-spacing: 0.05em;
536
+ }
537
+
538
+ .flowdrop-badge--error {
539
+ background-color: var(--fd-error);
540
+ color: var(--fd-error-foreground);
541
+ }
542
+
543
+ .flowdrop-badge--sm {
544
+ font-size: 0.625rem;
545
+ padding: 0.125rem var(--fd-space-3xs);
546
+ }
547
+
548
+ /* Handle overrides: hover scale (base 20px/12px from base.css) */
549
+ :global(.flowdrop-workflow-node__handle:hover) {
550
+ transform: translateY(-50%) scale(1.2);
551
+ }
552
+
553
+ /* Utility classes */
554
+ .flowdrop-flex {
555
+ display: flex;
556
+ }
557
+
558
+ .flowdrop-flex--1 {
559
+ flex: 1;
560
+ }
561
+
562
+ .flowdrop-gap--2 {
563
+ gap: var(--fd-space-xs);
564
+ }
565
+
566
+ .flowdrop-items--center {
567
+ align-items: center;
568
+ }
569
+
570
+ .flowdrop-justify--end {
571
+ justify-content: flex-end;
572
+ }
573
+
574
+ .flowdrop-min-w--0 {
575
+ min-width: 0;
576
+ }
577
+
578
+ .flowdrop-text--xs {
579
+ font-size: var(--fd-text-xs);
580
+ line-height: 1rem;
581
+ }
582
+
583
+ .flowdrop-text--sm {
584
+ font-size: var(--fd-text-sm);
585
+ line-height: 1.25rem;
586
+ }
587
+
588
+ .flowdrop-text--gray {
589
+ color: var(--fd-muted-foreground);
590
+ }
591
+
592
+ .flowdrop-font--medium {
593
+ font-weight: 500;
594
+ }
595
+
596
+ .flowdrop-truncate {
597
+ overflow: hidden;
598
+ text-overflow: ellipsis;
599
+ white-space: nowrap;
600
+ }
601
+
602
+ .flowdrop-text--right {
603
+ text-align: right;
604
+ }
605
+
606
+ .flowdrop-workflow-node__config-btn :global(svg) {
607
+ width: 14px;
608
+ height: 14px;
609
+ }
610
+
611
+ .flowdrop-workflow-node__config-btn {
612
+ position: absolute;
613
+ top: var(--fd-space-xs);
614
+ right: var(--fd-space-xs);
615
+ width: 1.5rem;
616
+ height: 1.5rem;
617
+ background-color: var(--fd-backdrop);
618
+ border: 1px solid var(--fd-border);
619
+ border-radius: var(--fd-radius-sm);
620
+ color: var(--fd-muted-foreground);
621
+ cursor: pointer;
622
+ display: flex;
623
+ align-items: center;
624
+ justify-content: center;
625
+ opacity: 0;
626
+ transition: all var(--fd-transition-normal);
627
+ backdrop-filter: var(--fd-backdrop-blur);
628
+ z-index: 15;
629
+ font-size: var(--fd-text-sm);
630
+ }
631
+
632
+ .flowdrop-workflow-node:hover .flowdrop-workflow-node__config-btn {
633
+ opacity: 1;
634
+ }
635
+
636
+ .flowdrop-workflow-node__config-btn:hover {
637
+ background-color: var(--fd-muted);
638
+ border-color: var(--fd-border-strong);
639
+ color: var(--fd-foreground);
640
+ }
571
641
  </style>