@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
@@ -28,611 +28,647 @@
28
28
  -->
29
29
 
30
30
  <script lang="ts">
31
- import Icon from '@iconify/svelte';
32
- import { SchemaForm } from '../form/index.js';
33
- import type { ConfigSchema } from '../types/index.js';
34
- import type { SettingsCategory } from '../types/settings.js';
35
- import {
36
- SETTINGS_CATEGORIES,
37
- SETTINGS_CATEGORY_LABELS,
38
- SETTINGS_CATEGORY_ICONS
39
- } from '../types/settings.js';
40
- import {
41
- getSettings,
42
- updateSettings,
43
- resetSettings,
44
- syncSettingsToApi,
45
- getSyncStatus
46
- } from '../stores/settingsStore.svelte.js';
47
- import { logger } from '../utils/logger.js';
48
-
49
- /**
50
- * Props interface for SettingsPanel component
51
- */
52
- interface Props {
53
- /** Categories to display (defaults to all) */
54
- categories?: SettingsCategory[];
55
- /** Show the "Sync to Cloud" button */
56
- showSyncButton?: boolean;
57
- /** Show the reset button */
58
- showResetButton?: boolean;
59
- /** Callback when settings change */
60
- onSettingsChange?: (category: SettingsCategory, values: Record<string, unknown>) => void;
61
- /** Callback when close is requested */
62
- onClose?: () => void;
63
- /** Custom CSS class */
64
- class?: string;
65
- }
66
-
67
- const {
68
- categories = SETTINGS_CATEGORIES,
69
- showSyncButton = true,
70
- showResetButton = true,
71
- onSettingsChange,
72
- onClose,
73
- class: className = ''
74
- }: Props = $props();
75
-
76
- /**
77
- * Currently active tab
78
- */
79
- // svelte-ignore state_referenced_locally — initial default, user switches tabs
80
- let activeTab = $state<SettingsCategory>(categories[0] ?? 'theme');
81
-
82
- /**
83
- * Whether sync is in progress
84
- */
85
- let isSyncing = $derived(getSyncStatus().status === 'syncing');
86
-
87
- /**
88
- * JSON Schema definitions for each settings category
89
- */
90
- const schemas: Record<SettingsCategory, ConfigSchema> = {
91
- theme: {
92
- type: 'object',
93
- properties: {
94
- preference: {
95
- type: 'string',
96
- title: 'Theme Preference',
97
- description: 'Choose your preferred color scheme',
98
- oneOf: [
99
- { const: 'light', title: 'Light' },
100
- { const: 'dark', title: 'Dark' },
101
- { const: 'auto', title: 'Auto (System)' }
102
- ],
103
- default: 'auto'
104
- }
105
- }
106
- },
107
- editor: {
108
- type: 'object',
109
- properties: {
110
- showGrid: {
111
- type: 'boolean',
112
- title: 'Show Grid',
113
- description: 'Display grid lines on the canvas',
114
- default: true
115
- },
116
- snapToGrid: {
117
- type: 'boolean',
118
- title: 'Snap to Grid',
119
- description: 'Snap nodes to grid when dragging',
120
- default: true
121
- },
122
- gridSize: {
123
- type: 'number',
124
- title: 'Grid Size',
125
- description: 'Grid cell size in pixels',
126
- minimum: 5,
127
- maximum: 50,
128
- default: 20
129
- },
130
- showMinimap: {
131
- type: 'boolean',
132
- title: 'Show Minimap',
133
- description: 'Display navigation minimap',
134
- default: true
135
- },
136
- defaultZoom: {
137
- type: 'number',
138
- title: 'Default Zoom',
139
- description: 'Initial zoom level (1 = 100%)',
140
- minimum: 0.25,
141
- maximum: 2,
142
- default: 1
143
- },
144
- fitViewOnLoad: {
145
- type: 'boolean',
146
- title: 'Fit View on Load',
147
- description: 'Automatically fit workflow to view when loading',
148
- default: true
149
- },
150
- proximityConnect: {
151
- type: 'boolean',
152
- title: 'Proximity Connect',
153
- description: 'Auto-connect compatible ports when dragging nodes near each other',
154
- default: false
155
- },
156
- proximityConnectDistance: {
157
- type: 'number',
158
- title: 'Proximity Distance',
159
- description: 'Distance threshold in pixels for proximity connect',
160
- minimum: 50,
161
- maximum: 500,
162
- default: 150
163
- }
164
- }
165
- },
166
- ui: {
167
- type: 'object',
168
- properties: {
169
- sidebarWidth: {
170
- type: 'number',
171
- title: 'Sidebar Width',
172
- description: 'Width of the node sidebar in pixels',
173
- minimum: 200,
174
- maximum: 500,
175
- default: 280
176
- },
177
- sidebarCollapsed: {
178
- type: 'boolean',
179
- title: 'Sidebar Collapsed',
180
- description: 'Start with sidebar collapsed',
181
- default: false
182
- },
183
- compactMode: {
184
- type: 'boolean',
185
- title: 'Compact Mode',
186
- description: 'Use compact UI with smaller spacing',
187
- default: false
188
- }
189
- }
190
- },
191
- behavior: {
192
- type: 'object',
193
- properties: {
194
- autoSave: {
195
- type: 'boolean',
196
- title: 'Auto Save',
197
- description: 'Automatically save changes',
198
- default: false
199
- },
200
- autoSaveInterval: {
201
- type: 'number',
202
- title: 'Auto Save Interval',
203
- description: 'Time between auto-saves in milliseconds',
204
- minimum: 5000,
205
- maximum: 300000,
206
- default: 30000
207
- },
208
- undoHistoryLimit: {
209
- type: 'number',
210
- title: 'Undo History Limit',
211
- description: 'Maximum number of undo steps (0 to disable)',
212
- minimum: 0,
213
- maximum: 200,
214
- default: 0
215
- },
216
- confirmDelete: {
217
- type: 'boolean',
218
- title: 'Confirm Delete',
219
- description: 'Show confirmation before deleting nodes',
220
- default: true
221
- }
222
- }
223
- },
224
- api: {
225
- type: 'object',
226
- properties: {
227
- timeout: {
228
- type: 'number',
229
- title: 'Request Timeout',
230
- description: 'API request timeout in milliseconds',
231
- minimum: 5000,
232
- maximum: 120000,
233
- default: 30000
234
- },
235
- retryEnabled: {
236
- type: 'boolean',
237
- title: 'Enable Retry',
238
- description: 'Automatically retry failed requests',
239
- default: true
240
- },
241
- retryAttempts: {
242
- type: 'number',
243
- title: 'Retry Attempts',
244
- description: 'Maximum number of retry attempts',
245
- minimum: 1,
246
- maximum: 10,
247
- default: 3
248
- },
249
- cacheEnabled: {
250
- type: 'boolean',
251
- title: 'Enable Caching',
252
- description: 'Cache API responses for better performance',
253
- default: true
254
- }
255
- }
256
- }
257
- };
258
-
259
- /**
260
- * Get current values for a category from the store
261
- */
262
- function getCategoryValues(category: SettingsCategory): Record<string, unknown> {
263
- const settings = getSettings();
264
- const categorySettings = settings[category];
265
- // Convert to Record<string, unknown> for SchemaForm compatibility
266
- return Object.fromEntries(Object.entries(categorySettings));
267
- }
268
-
269
- /**
270
- * Handle form value changes
271
- */
272
- function handleChange(category: SettingsCategory, values: Record<string, unknown>): void {
273
- // Update the store
274
- updateSettings({ [category]: values });
275
-
276
- // Notify parent if callback provided
277
- if (onSettingsChange) {
278
- onSettingsChange(category, values);
279
- }
280
- }
281
-
282
- /**
283
- * Handle sync to cloud button click
284
- */
285
- async function handleSync(): Promise<void> {
286
- try {
287
- await syncSettingsToApi();
288
- } catch (error) {
289
- logger.error('Failed to sync settings:', error);
290
- }
291
- }
292
-
293
- /**
294
- * Handle reset button click
295
- */
296
- function handleReset(): void {
297
- if (confirm(`Reset ${SETTINGS_CATEGORY_LABELS[activeTab]} settings to defaults?`)) {
298
- resetSettings([activeTab]);
299
- }
300
- }
301
-
302
- /**
303
- * Handle reset all button click
304
- */
305
- function handleResetAll(): void {
306
- if (confirm('Reset all settings to defaults?')) {
307
- resetSettings();
308
- }
309
- }
310
-
311
- /**
312
- * Handle tab keyboard navigation
313
- */
314
- function handleTabKeydown(event: KeyboardEvent, index: number): void {
315
- const tabs = categories;
316
- let newIndex = index;
317
-
318
- switch (event.key) {
319
- case 'ArrowLeft':
320
- newIndex = index > 0 ? index - 1 : tabs.length - 1;
321
- break;
322
- case 'ArrowRight':
323
- newIndex = index < tabs.length - 1 ? index + 1 : 0;
324
- break;
325
- case 'Home':
326
- newIndex = 0;
327
- break;
328
- case 'End':
329
- newIndex = tabs.length - 1;
330
- break;
331
- default:
332
- return;
333
- }
334
-
335
- event.preventDefault();
336
- activeTab = tabs[newIndex];
337
-
338
- // Focus the new tab
339
- const tabElement = document.querySelector(
340
- `[data-tab="${tabs[newIndex]}"]`
341
- ) as HTMLElement | null;
342
- tabElement?.focus();
343
- }
31
+ import Icon from "@iconify/svelte";
32
+ import { SchemaForm } from "../form/index.js";
33
+ import type { ConfigSchema } from "../types/index.js";
34
+ import type { SettingsCategory } from "../types/settings.js";
35
+ import {
36
+ SETTINGS_CATEGORIES,
37
+ SETTINGS_CATEGORY_LABELS,
38
+ SETTINGS_CATEGORY_ICONS,
39
+ } from "../types/settings.js";
40
+ import {
41
+ getSettings,
42
+ updateSettings,
43
+ resetSettings,
44
+ syncSettingsToApi,
45
+ getSyncStatus,
46
+ } from "../stores/settingsStore.svelte.js";
47
+ import { logger } from "../utils/logger.js";
48
+
49
+ /**
50
+ * Props interface for SettingsPanel component
51
+ */
52
+ interface Props {
53
+ /** Categories to display (defaults to all) */
54
+ categories?: SettingsCategory[];
55
+ /** Show the "Sync to Cloud" button */
56
+ showSyncButton?: boolean;
57
+ /** Show the reset button */
58
+ showResetButton?: boolean;
59
+ /** Callback when settings change */
60
+ onSettingsChange?: (
61
+ category: SettingsCategory,
62
+ values: Record<string, unknown>,
63
+ ) => void;
64
+ /** Callback when close is requested */
65
+ onClose?: () => void;
66
+ /** Custom CSS class */
67
+ class?: string;
68
+ }
69
+
70
+ const {
71
+ categories = SETTINGS_CATEGORIES,
72
+ showSyncButton = true,
73
+ showResetButton = true,
74
+ onSettingsChange,
75
+ onClose,
76
+ class: className = "",
77
+ }: Props = $props();
78
+
79
+ /**
80
+ * Currently active tab
81
+ */
82
+ // svelte-ignore state_referenced_locally — initial default, user switches tabs
83
+ let activeTab = $state<SettingsCategory>(categories[0] ?? "theme");
84
+
85
+ /**
86
+ * Whether sync is in progress
87
+ */
88
+ let isSyncing = $derived(getSyncStatus().status === "syncing");
89
+
90
+ /**
91
+ * JSON Schema definitions for each settings category
92
+ */
93
+ const schemas: Record<SettingsCategory, ConfigSchema> = {
94
+ theme: {
95
+ type: "object",
96
+ properties: {
97
+ preference: {
98
+ type: "string",
99
+ title: "Theme Preference",
100
+ description: "Choose your preferred color scheme",
101
+ oneOf: [
102
+ { const: "light", title: "Light" },
103
+ { const: "dark", title: "Dark" },
104
+ { const: "auto", title: "Auto (System)" },
105
+ ],
106
+ default: "auto",
107
+ },
108
+ },
109
+ },
110
+ editor: {
111
+ type: "object",
112
+ properties: {
113
+ showGrid: {
114
+ type: "boolean",
115
+ title: "Show Grid",
116
+ description: "Display grid lines on the canvas",
117
+ default: true,
118
+ },
119
+ snapToGrid: {
120
+ type: "boolean",
121
+ title: "Snap to Grid",
122
+ description: "Snap nodes to grid when dragging",
123
+ default: true,
124
+ },
125
+ gridSize: {
126
+ type: "number",
127
+ title: "Grid Size",
128
+ description: "Grid cell size in pixels",
129
+ minimum: 5,
130
+ maximum: 50,
131
+ default: 20,
132
+ },
133
+ showMinimap: {
134
+ type: "boolean",
135
+ title: "Show Minimap",
136
+ description: "Display navigation minimap",
137
+ default: true,
138
+ },
139
+ defaultZoom: {
140
+ type: "number",
141
+ title: "Default Zoom",
142
+ description: "Initial zoom level (1 = 100%)",
143
+ minimum: 0.25,
144
+ maximum: 2,
145
+ default: 1,
146
+ },
147
+ fitViewOnLoad: {
148
+ type: "boolean",
149
+ title: "Fit View on Load",
150
+ description: "Automatically fit workflow to view when loading",
151
+ default: true,
152
+ },
153
+ proximityConnect: {
154
+ type: "boolean",
155
+ title: "Proximity Connect",
156
+ description:
157
+ "Auto-connect compatible ports when dragging nodes near each other",
158
+ default: false,
159
+ },
160
+ proximityConnectDistance: {
161
+ type: "number",
162
+ title: "Proximity Distance",
163
+ description: "Distance threshold in pixels for proximity connect",
164
+ minimum: 50,
165
+ maximum: 500,
166
+ default: 150,
167
+ },
168
+ },
169
+ },
170
+ ui: {
171
+ type: "object",
172
+ properties: {
173
+ sidebarWidth: {
174
+ type: "number",
175
+ title: "Sidebar Width",
176
+ description: "Width of the node sidebar in pixels",
177
+ minimum: 200,
178
+ maximum: 500,
179
+ default: 280,
180
+ },
181
+ sidebarCollapsed: {
182
+ type: "boolean",
183
+ title: "Sidebar Collapsed",
184
+ description: "Start with sidebar collapsed",
185
+ default: false,
186
+ },
187
+ compactMode: {
188
+ type: "boolean",
189
+ title: "Compact Mode",
190
+ description: "Use compact UI with smaller spacing",
191
+ default: false,
192
+ },
193
+ theme: {
194
+ type: "string",
195
+ title: "UI Theme",
196
+ description: "Visual style and layout of the editor",
197
+ oneOf: [
198
+ { const: "default", title: "Default" },
199
+ { const: "minimal", title: "Minimal" },
200
+ ],
201
+ default: "default",
202
+ },
203
+ },
204
+ },
205
+ behavior: {
206
+ type: "object",
207
+ properties: {
208
+ autoSave: {
209
+ type: "boolean",
210
+ title: "Auto Save",
211
+ description: "Automatically save changes",
212
+ default: false,
213
+ },
214
+ autoSaveInterval: {
215
+ type: "number",
216
+ title: "Auto Save Interval",
217
+ description: "Time between auto-saves in milliseconds",
218
+ minimum: 5000,
219
+ maximum: 300000,
220
+ default: 30000,
221
+ },
222
+ undoHistoryLimit: {
223
+ type: "number",
224
+ title: "Undo History Limit",
225
+ description: "Maximum number of undo steps (0 to disable)",
226
+ minimum: 0,
227
+ maximum: 200,
228
+ default: 0,
229
+ },
230
+ confirmDelete: {
231
+ type: "boolean",
232
+ title: "Confirm Delete",
233
+ description: "Show confirmation before deleting nodes",
234
+ default: true,
235
+ },
236
+ },
237
+ },
238
+ api: {
239
+ type: "object",
240
+ properties: {
241
+ timeout: {
242
+ type: "number",
243
+ title: "Request Timeout",
244
+ description: "API request timeout in milliseconds",
245
+ minimum: 5000,
246
+ maximum: 120000,
247
+ default: 30000,
248
+ },
249
+ retryEnabled: {
250
+ type: "boolean",
251
+ title: "Enable Retry",
252
+ description: "Automatically retry failed requests",
253
+ default: true,
254
+ },
255
+ retryAttempts: {
256
+ type: "number",
257
+ title: "Retry Attempts",
258
+ description: "Maximum number of retry attempts",
259
+ minimum: 1,
260
+ maximum: 10,
261
+ default: 3,
262
+ },
263
+ cacheEnabled: {
264
+ type: "boolean",
265
+ title: "Enable Caching",
266
+ description: "Cache API responses for better performance",
267
+ default: true,
268
+ },
269
+ },
270
+ },
271
+ };
272
+
273
+ /**
274
+ * Get current values for a category from the store
275
+ */
276
+ function getCategoryValues(
277
+ category: SettingsCategory,
278
+ ): Record<string, unknown> {
279
+ const settings = getSettings();
280
+ const categorySettings = settings[category];
281
+ // Convert to Record<string, unknown> for SchemaForm compatibility
282
+ return Object.fromEntries(Object.entries(categorySettings));
283
+ }
284
+
285
+ /**
286
+ * Handle form value changes
287
+ */
288
+ function handleChange(
289
+ category: SettingsCategory,
290
+ values: Record<string, unknown>,
291
+ ): void {
292
+ // Update the store
293
+ updateSettings({ [category]: values });
294
+
295
+ // Notify parent if callback provided
296
+ if (onSettingsChange) {
297
+ onSettingsChange(category, values);
298
+ }
299
+ }
300
+
301
+ /**
302
+ * Handle sync to cloud button click
303
+ */
304
+ async function handleSync(): Promise<void> {
305
+ try {
306
+ await syncSettingsToApi();
307
+ } catch (error) {
308
+ logger.error("Failed to sync settings:", error);
309
+ }
310
+ }
311
+
312
+ /**
313
+ * Handle reset button click
314
+ */
315
+ function handleReset(): void {
316
+ if (
317
+ confirm(
318
+ `Reset ${SETTINGS_CATEGORY_LABELS[activeTab]} settings to defaults?`,
319
+ )
320
+ ) {
321
+ resetSettings([activeTab]);
322
+ }
323
+ }
324
+
325
+ /**
326
+ * Handle reset all button click
327
+ */
328
+ function handleResetAll(): void {
329
+ if (confirm("Reset all settings to defaults?")) {
330
+ resetSettings();
331
+ }
332
+ }
333
+
334
+ /**
335
+ * Handle tab keyboard navigation
336
+ */
337
+ function handleTabKeydown(event: KeyboardEvent, index: number): void {
338
+ const tabs = categories;
339
+ let newIndex = index;
340
+
341
+ switch (event.key) {
342
+ case "ArrowLeft":
343
+ newIndex = index > 0 ? index - 1 : tabs.length - 1;
344
+ break;
345
+ case "ArrowRight":
346
+ newIndex = index < tabs.length - 1 ? index + 1 : 0;
347
+ break;
348
+ case "Home":
349
+ newIndex = 0;
350
+ break;
351
+ case "End":
352
+ newIndex = tabs.length - 1;
353
+ break;
354
+ default:
355
+ return;
356
+ }
357
+
358
+ event.preventDefault();
359
+ activeTab = tabs[newIndex];
360
+
361
+ // Focus the new tab
362
+ const tabElement = document.querySelector(
363
+ `[data-tab="${tabs[newIndex]}"]`,
364
+ ) as HTMLElement | null;
365
+ tabElement?.focus();
366
+ }
344
367
  </script>
345
368
 
346
369
  <div class="flowdrop-settings-panel {className}">
347
- <!-- Tab Navigation -->
348
- <div class="flowdrop-settings-panel__tabs" role="tablist" aria-label="Settings categories">
349
- {#each categories as category, index (category)}
350
- <button
351
- class="flowdrop-settings-panel__tab"
352
- class:flowdrop-settings-panel__tab--active={activeTab === category}
353
- role="tab"
354
- aria-selected={activeTab === category}
355
- aria-controls="panel-{category}"
356
- data-tab={category}
357
- tabindex={activeTab === category ? 0 : -1}
358
- onclick={() => (activeTab = category)}
359
- onkeydown={(e) => handleTabKeydown(e, index)}
360
- >
361
- <Icon icon={SETTINGS_CATEGORY_ICONS[category]} class="flowdrop-settings-panel__tab-icon" />
362
- <span class="flowdrop-settings-panel__tab-label">{SETTINGS_CATEGORY_LABELS[category]}</span>
363
- </button>
364
- {/each}
365
- </div>
366
-
367
- <!-- Tab Panels -->
368
- <div class="flowdrop-settings-panel__content">
369
- {#each categories as category (category)}
370
- <div
371
- id="panel-{category}"
372
- class="flowdrop-settings-panel__panel"
373
- class:flowdrop-settings-panel__panel--active={activeTab === category}
374
- role="tabpanel"
375
- aria-labelledby="tab-{category}"
376
- hidden={activeTab !== category}
377
- >
378
- {#if activeTab === category}
379
- <SchemaForm
380
- schema={schemas[category]}
381
- values={getCategoryValues(category)}
382
- onChange={(values) => handleChange(category, values)}
383
- showActions={false}
384
- />
385
- {/if}
386
- </div>
387
- {/each}
388
- </div>
389
-
390
- <!-- Footer Actions -->
391
- <div class="flowdrop-settings-panel__footer">
392
- <div class="flowdrop-settings-panel__footer-start">
393
- {#if showResetButton}
394
- <button
395
- class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--outline"
396
- onclick={handleReset}
397
- title="Reset current category to defaults"
398
- >
399
- <Icon icon="mdi:refresh" />
400
- <span>Reset</span>
401
- </button>
402
- <button
403
- class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--ghost"
404
- onclick={handleResetAll}
405
- title="Reset all settings to defaults"
406
- >
407
- Reset All
408
- </button>
409
- {/if}
410
- </div>
411
-
412
- <div class="flowdrop-settings-panel__footer-end">
413
- {#if showSyncButton}
414
- <button
415
- class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--secondary"
416
- onclick={handleSync}
417
- disabled={isSyncing}
418
- title="Sync settings to cloud"
419
- >
420
- {#if isSyncing}
421
- <Icon icon="mdi:loading" class="flowdrop-settings-panel__spin" />
422
- <span>Syncing...</span>
423
- {:else}
424
- <Icon icon="mdi:cloud-upload" />
425
- <span>Sync to Cloud</span>
426
- {/if}
427
- </button>
428
- {/if}
429
-
430
- {#if onClose}
431
- <button
432
- class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--primary"
433
- onclick={onClose}
434
- >
435
- <span>Close</span>
436
- </button>
437
- {/if}
438
- </div>
439
- </div>
440
-
441
- <!-- Sync Status Indicator -->
442
- {#if getSyncStatus().error}
443
- <div class="flowdrop-settings-panel__error">
444
- <Icon icon="mdi:alert-circle" />
445
- <span>{getSyncStatus().error}</span>
446
- </div>
447
- {:else if getSyncStatus().status === 'synced' && getSyncStatus().lastSyncedAt}
448
- <div class="flowdrop-settings-panel__synced">
449
- <Icon icon="mdi:check-circle" />
450
- <span>Synced {new Date(getSyncStatus().lastSyncedAt!).toLocaleTimeString()}</span>
451
- </div>
452
- {/if}
370
+ <!-- Tab Navigation -->
371
+ <div
372
+ class="flowdrop-settings-panel__tabs"
373
+ role="tablist"
374
+ aria-label="Settings categories"
375
+ >
376
+ {#each categories as category, index (category)}
377
+ <button
378
+ class="flowdrop-settings-panel__tab"
379
+ class:flowdrop-settings-panel__tab--active={activeTab === category}
380
+ role="tab"
381
+ aria-selected={activeTab === category}
382
+ aria-controls="panel-{category}"
383
+ data-tab={category}
384
+ tabindex={activeTab === category ? 0 : -1}
385
+ onclick={() => (activeTab = category)}
386
+ onkeydown={(e) => handleTabKeydown(e, index)}
387
+ >
388
+ <Icon
389
+ icon={SETTINGS_CATEGORY_ICONS[category]}
390
+ class="flowdrop-settings-panel__tab-icon"
391
+ />
392
+ <span class="flowdrop-settings-panel__tab-label"
393
+ >{SETTINGS_CATEGORY_LABELS[category]}</span
394
+ >
395
+ </button>
396
+ {/each}
397
+ </div>
398
+
399
+ <!-- Tab Panels -->
400
+ <div class="flowdrop-settings-panel__content">
401
+ {#each categories as category (category)}
402
+ <div
403
+ id="panel-{category}"
404
+ class="flowdrop-settings-panel__panel"
405
+ class:flowdrop-settings-panel__panel--active={activeTab === category}
406
+ role="tabpanel"
407
+ aria-labelledby="tab-{category}"
408
+ hidden={activeTab !== category}
409
+ >
410
+ {#if activeTab === category}
411
+ <SchemaForm
412
+ schema={schemas[category]}
413
+ values={getCategoryValues(category)}
414
+ onChange={(values) => handleChange(category, values)}
415
+ showActions={false}
416
+ />
417
+ {/if}
418
+ </div>
419
+ {/each}
420
+ </div>
421
+
422
+ <!-- Footer Actions -->
423
+ <div class="flowdrop-settings-panel__footer">
424
+ <div class="flowdrop-settings-panel__footer-start">
425
+ {#if showResetButton}
426
+ <button
427
+ class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--outline"
428
+ onclick={handleReset}
429
+ title="Reset current category to defaults"
430
+ >
431
+ <Icon icon="mdi:refresh" />
432
+ <span>Reset</span>
433
+ </button>
434
+ <button
435
+ class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--ghost"
436
+ onclick={handleResetAll}
437
+ title="Reset all settings to defaults"
438
+ >
439
+ Reset All
440
+ </button>
441
+ {/if}
442
+ </div>
443
+
444
+ <div class="flowdrop-settings-panel__footer-end">
445
+ {#if showSyncButton}
446
+ <button
447
+ class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--secondary"
448
+ onclick={handleSync}
449
+ disabled={isSyncing}
450
+ title="Sync settings to cloud"
451
+ >
452
+ {#if isSyncing}
453
+ <Icon icon="mdi:loading" class="flowdrop-settings-panel__spin" />
454
+ <span>Syncing...</span>
455
+ {:else}
456
+ <Icon icon="mdi:cloud-upload" />
457
+ <span>Sync to Cloud</span>
458
+ {/if}
459
+ </button>
460
+ {/if}
461
+
462
+ {#if onClose}
463
+ <button
464
+ class="flowdrop-settings-panel__btn flowdrop-settings-panel__btn--primary"
465
+ onclick={onClose}
466
+ >
467
+ <span>Close</span>
468
+ </button>
469
+ {/if}
470
+ </div>
471
+ </div>
472
+
473
+ <!-- Sync Status Indicator -->
474
+ {#if getSyncStatus().error}
475
+ <div class="flowdrop-settings-panel__error">
476
+ <Icon icon="mdi:alert-circle" />
477
+ <span>{getSyncStatus().error}</span>
478
+ </div>
479
+ {:else if getSyncStatus().status === "synced" && getSyncStatus().lastSyncedAt}
480
+ <div class="flowdrop-settings-panel__synced">
481
+ <Icon icon="mdi:check-circle" />
482
+ <span
483
+ >Synced {new Date(
484
+ getSyncStatus().lastSyncedAt!,
485
+ ).toLocaleTimeString()}</span
486
+ >
487
+ </div>
488
+ {/if}
453
489
  </div>
454
490
 
455
491
  <style>
456
- .flowdrop-settings-panel {
457
- display: flex;
458
- flex-direction: column;
459
- height: 100%;
460
- background-color: var(--fd-background);
461
- color: var(--fd-foreground);
462
- }
463
-
464
- /* Tabs */
465
- .flowdrop-settings-panel__tabs {
466
- display: flex;
467
- gap: var(--fd-space-3xs);
468
- padding: var(--fd-space-md);
469
- border-bottom: 1px solid var(--fd-border);
470
- overflow-x: auto;
471
- }
472
-
473
- .flowdrop-settings-panel__tab {
474
- display: flex;
475
- align-items: center;
476
- gap: var(--fd-space-xs);
477
- padding: var(--fd-space-xs) var(--fd-space-md);
478
- border: none;
479
- border-radius: var(--fd-radius-md);
480
- background-color: transparent;
481
- color: var(--fd-muted-foreground);
482
- font-size: var(--fd-text-sm);
483
- font-weight: 500;
484
- cursor: pointer;
485
- transition: all var(--fd-transition-fast);
486
- white-space: nowrap;
487
- }
488
-
489
- .flowdrop-settings-panel__tab:hover {
490
- background-color: var(--fd-muted);
491
- color: var(--fd-foreground);
492
- }
493
-
494
- .flowdrop-settings-panel__tab--active {
495
- background-color: var(--fd-primary);
496
- color: var(--fd-primary-foreground);
497
- }
498
-
499
- .flowdrop-settings-panel__tab--active:hover {
500
- background-color: var(--fd-primary);
501
- color: var(--fd-primary-foreground);
502
- }
503
-
504
- .flowdrop-settings-panel__tab:focus {
505
- outline: none;
506
- box-shadow: 0 0 0 2px var(--fd-ring);
507
- }
508
-
509
- :global(.flowdrop-settings-panel__tab-icon) {
510
- font-size: var(--fd-text-base);
511
- }
512
-
513
- /* Content */
514
- .flowdrop-settings-panel__content {
515
- flex: 1;
516
- overflow-y: auto;
517
- padding: var(--fd-space-xl);
518
- }
519
-
520
- .flowdrop-settings-panel__panel {
521
- display: none;
522
- }
523
-
524
- .flowdrop-settings-panel__panel--active {
525
- display: block;
526
- }
527
-
528
- /* Footer */
529
- .flowdrop-settings-panel__footer {
530
- display: flex;
531
- justify-content: space-between;
532
- align-items: center;
533
- padding: var(--fd-space-md) var(--fd-space-xl);
534
- border-top: 1px solid var(--fd-border);
535
- gap: var(--fd-space-md);
536
- }
537
-
538
- .flowdrop-settings-panel__footer-start,
539
- .flowdrop-settings-panel__footer-end {
540
- display: flex;
541
- gap: var(--fd-space-xs);
542
- align-items: center;
543
- }
544
-
545
- /* Buttons */
546
- .flowdrop-settings-panel__btn {
547
- display: inline-flex;
548
- align-items: center;
549
- gap: var(--fd-space-xs);
550
- padding: var(--fd-space-xs) var(--fd-space-md);
551
- border-radius: var(--fd-radius-md);
552
- font-size: var(--fd-text-sm);
553
- font-weight: 500;
554
- cursor: pointer;
555
- transition: all var(--fd-transition-fast);
556
- border: 1px solid transparent;
557
- }
558
-
559
- .flowdrop-settings-panel__btn:disabled {
560
- opacity: 0.5;
561
- cursor: not-allowed;
562
- }
563
-
564
- .flowdrop-settings-panel__btn--primary {
565
- background-color: var(--fd-primary);
566
- color: var(--fd-primary-foreground);
567
- border-color: var(--fd-primary);
568
- }
569
-
570
- .flowdrop-settings-panel__btn--primary:hover:not(:disabled) {
571
- opacity: 0.9;
572
- }
573
-
574
- .flowdrop-settings-panel__btn--secondary {
575
- background-color: var(--fd-secondary);
576
- color: var(--fd-secondary-foreground);
577
- border-color: var(--fd-border);
578
- }
579
-
580
- .flowdrop-settings-panel__btn--secondary:hover:not(:disabled) {
581
- background-color: var(--fd-muted);
582
- }
583
-
584
- .flowdrop-settings-panel__btn--outline {
585
- background-color: transparent;
586
- color: var(--fd-foreground);
587
- border-color: var(--fd-border);
588
- }
589
-
590
- .flowdrop-settings-panel__btn--outline:hover:not(:disabled) {
591
- background-color: var(--fd-muted);
592
- }
593
-
594
- .flowdrop-settings-panel__btn--ghost {
595
- background-color: transparent;
596
- color: var(--fd-muted-foreground);
597
- border-color: transparent;
598
- }
599
-
600
- .flowdrop-settings-panel__btn--ghost:hover:not(:disabled) {
601
- background-color: var(--fd-muted);
602
- color: var(--fd-foreground);
603
- }
604
-
605
- /* Status Indicators */
606
- .flowdrop-settings-panel__error,
607
- .flowdrop-settings-panel__synced {
608
- display: flex;
609
- align-items: center;
610
- gap: var(--fd-space-xs);
611
- padding: var(--fd-space-xs) var(--fd-space-xl);
612
- font-size: var(--fd-text-xs);
613
- }
614
-
615
- .flowdrop-settings-panel__error {
616
- background-color: var(--fd-destructive);
617
- color: var(--fd-destructive-foreground);
618
- }
619
-
620
- .flowdrop-settings-panel__synced {
621
- background-color: var(--fd-success, #22c55e);
622
- color: white;
623
- }
624
-
625
- /* Spin Animation */
626
- :global(.flowdrop-settings-panel__spin) {
627
- animation: flowdrop-spin 1s linear infinite;
628
- }
629
-
630
- @keyframes flowdrop-spin {
631
- from {
632
- transform: rotate(0deg);
633
- }
634
- to {
635
- transform: rotate(360deg);
636
- }
637
- }
492
+ .flowdrop-settings-panel {
493
+ display: flex;
494
+ flex-direction: column;
495
+ height: 100%;
496
+ background-color: var(--fd-background);
497
+ color: var(--fd-foreground);
498
+ }
499
+
500
+ /* Tabs */
501
+ .flowdrop-settings-panel__tabs {
502
+ display: flex;
503
+ gap: var(--fd-space-3xs);
504
+ padding: var(--fd-space-md);
505
+ border-bottom: 1px solid var(--fd-border);
506
+ overflow-x: auto;
507
+ }
508
+
509
+ .flowdrop-settings-panel__tab {
510
+ display: flex;
511
+ align-items: center;
512
+ gap: var(--fd-space-xs);
513
+ padding: var(--fd-space-xs) var(--fd-space-md);
514
+ border: none;
515
+ border-radius: var(--fd-radius-md);
516
+ background-color: transparent;
517
+ color: var(--fd-muted-foreground);
518
+ font-size: var(--fd-text-sm);
519
+ font-weight: 500;
520
+ cursor: pointer;
521
+ transition: all var(--fd-transition-fast);
522
+ white-space: nowrap;
523
+ }
524
+
525
+ .flowdrop-settings-panel__tab:hover {
526
+ background-color: var(--fd-muted);
527
+ color: var(--fd-foreground);
528
+ }
529
+
530
+ .flowdrop-settings-panel__tab--active {
531
+ background-color: var(--fd-primary);
532
+ color: var(--fd-primary-foreground);
533
+ }
534
+
535
+ .flowdrop-settings-panel__tab--active:hover {
536
+ background-color: var(--fd-primary);
537
+ color: var(--fd-primary-foreground);
538
+ }
539
+
540
+ .flowdrop-settings-panel__tab:focus {
541
+ outline: none;
542
+ box-shadow: 0 0 0 2px var(--fd-ring);
543
+ }
544
+
545
+ :global(.flowdrop-settings-panel__tab-icon) {
546
+ font-size: var(--fd-text-base);
547
+ }
548
+
549
+ /* Content */
550
+ .flowdrop-settings-panel__content {
551
+ flex: 1;
552
+ overflow-y: auto;
553
+ padding: var(--fd-space-xl);
554
+ }
555
+
556
+ .flowdrop-settings-panel__panel {
557
+ display: none;
558
+ }
559
+
560
+ .flowdrop-settings-panel__panel--active {
561
+ display: block;
562
+ }
563
+
564
+ /* Footer */
565
+ .flowdrop-settings-panel__footer {
566
+ display: flex;
567
+ justify-content: space-between;
568
+ align-items: center;
569
+ padding: var(--fd-space-md) var(--fd-space-xl);
570
+ border-top: 1px solid var(--fd-border);
571
+ gap: var(--fd-space-md);
572
+ }
573
+
574
+ .flowdrop-settings-panel__footer-start,
575
+ .flowdrop-settings-panel__footer-end {
576
+ display: flex;
577
+ gap: var(--fd-space-xs);
578
+ align-items: center;
579
+ }
580
+
581
+ /* Buttons */
582
+ .flowdrop-settings-panel__btn {
583
+ display: inline-flex;
584
+ align-items: center;
585
+ gap: var(--fd-space-xs);
586
+ padding: var(--fd-space-xs) var(--fd-space-md);
587
+ border-radius: var(--fd-radius-md);
588
+ font-size: var(--fd-text-sm);
589
+ font-weight: 500;
590
+ cursor: pointer;
591
+ transition: all var(--fd-transition-fast);
592
+ border: 1px solid transparent;
593
+ }
594
+
595
+ .flowdrop-settings-panel__btn:disabled {
596
+ opacity: 0.5;
597
+ cursor: not-allowed;
598
+ }
599
+
600
+ .flowdrop-settings-panel__btn--primary {
601
+ background-color: var(--fd-primary);
602
+ color: var(--fd-primary-foreground);
603
+ border-color: var(--fd-primary);
604
+ }
605
+
606
+ .flowdrop-settings-panel__btn--primary:hover:not(:disabled) {
607
+ opacity: 0.9;
608
+ }
609
+
610
+ .flowdrop-settings-panel__btn--secondary {
611
+ background-color: var(--fd-secondary);
612
+ color: var(--fd-secondary-foreground);
613
+ border-color: var(--fd-border);
614
+ }
615
+
616
+ .flowdrop-settings-panel__btn--secondary:hover:not(:disabled) {
617
+ background-color: var(--fd-muted);
618
+ }
619
+
620
+ .flowdrop-settings-panel__btn--outline {
621
+ background-color: transparent;
622
+ color: var(--fd-foreground);
623
+ border-color: var(--fd-border);
624
+ }
625
+
626
+ .flowdrop-settings-panel__btn--outline:hover:not(:disabled) {
627
+ background-color: var(--fd-muted);
628
+ }
629
+
630
+ .flowdrop-settings-panel__btn--ghost {
631
+ background-color: transparent;
632
+ color: var(--fd-muted-foreground);
633
+ border-color: transparent;
634
+ }
635
+
636
+ .flowdrop-settings-panel__btn--ghost:hover:not(:disabled) {
637
+ background-color: var(--fd-muted);
638
+ color: var(--fd-foreground);
639
+ }
640
+
641
+ /* Status Indicators */
642
+ .flowdrop-settings-panel__error,
643
+ .flowdrop-settings-panel__synced {
644
+ display: flex;
645
+ align-items: center;
646
+ gap: var(--fd-space-xs);
647
+ padding: var(--fd-space-xs) var(--fd-space-xl);
648
+ font-size: var(--fd-text-xs);
649
+ }
650
+
651
+ .flowdrop-settings-panel__error {
652
+ background-color: var(--fd-destructive);
653
+ color: var(--fd-destructive-foreground);
654
+ }
655
+
656
+ .flowdrop-settings-panel__synced {
657
+ background-color: var(--fd-success, #22c55e);
658
+ color: white;
659
+ }
660
+
661
+ /* Spin Animation */
662
+ :global(.flowdrop-settings-panel__spin) {
663
+ animation: flowdrop-spin 1s linear infinite;
664
+ }
665
+
666
+ @keyframes flowdrop-spin {
667
+ from {
668
+ transform: rotate(0deg);
669
+ }
670
+ to {
671
+ transform: rotate(360deg);
672
+ }
673
+ }
638
674
  </style>