@dfosco/storyboard-core 4.2.0-beta.3 → 4.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 (419) hide show
  1. package/commandpalette.config.json +109 -24
  2. package/dist/storyboard-ui.css +1 -1
  3. package/dist/storyboard-ui.js +16711 -27239
  4. package/dist/storyboard-ui.js.map +1 -1
  5. package/dist/tailwind.css +1 -1
  6. package/package.json +5 -2
  7. package/scaffold/agents/prompt-agent.agent.md +181 -0
  8. package/scaffold/agents/terminal-agent.agent.md +351 -0
  9. package/scaffold/codex/config.toml +246 -0
  10. package/scaffold/manifest.json +5 -10
  11. package/scaffold/skills/canvas/SKILL.md +5 -4
  12. package/scaffold/skills/ship/SKILL.md +1 -1
  13. package/scaffold/storyboard.config.json +11 -1
  14. package/src/ActionMenuButton.jsx +103 -0
  15. package/src/AutosyncMenuButton.css +67 -0
  16. package/src/AutosyncMenuButton.jsx +242 -0
  17. package/src/BranchSelect.jsx +29 -0
  18. package/src/BranchSelect.module.css +30 -0
  19. package/src/CanvasAgentsMenu.jsx +89 -0
  20. package/src/CanvasCreateMenu.jsx +611 -0
  21. package/src/CanvasSnap.css +27 -0
  22. package/src/CanvasSnap.jsx +51 -0
  23. package/src/CanvasUndoRedo.css +36 -0
  24. package/src/CanvasUndoRedo.jsx +62 -0
  25. package/src/CanvasZoomControl.css +53 -0
  26. package/src/CanvasZoomControl.jsx +49 -0
  27. package/src/CanvasZoomToFit.css +18 -0
  28. package/src/CanvasZoomToFit.jsx +26 -0
  29. package/src/CommandMenu.css +8 -0
  30. package/src/CommandMenu.jsx +287 -0
  31. package/src/CommandPalette.jsx +35 -0
  32. package/src/CommandPaletteTrigger.jsx +25 -0
  33. package/src/CommentsMenuButton.jsx +40 -0
  34. package/src/CoreUIBar.css +47 -0
  35. package/src/CoreUIBar.jsx +858 -0
  36. package/src/CreateMenuButton.jsx +117 -0
  37. package/src/HideChromeTrigger.jsx +40 -0
  38. package/src/InspectorPanel.css +109 -0
  39. package/src/InspectorPanel.jsx +632 -0
  40. package/src/PwaInstallBanner.css +42 -0
  41. package/src/PwaInstallBanner.jsx +124 -0
  42. package/src/SidePanel.jsx +261 -0
  43. package/src/ThemeMenuButton.jsx +139 -0
  44. package/src/autosync/server.js +202 -5
  45. package/src/autosync/server.test.js +111 -0
  46. package/src/canvas/__tests__/agent-integration.test.js +596 -0
  47. package/src/canvas/__tests__/helpers/browser.js +95 -0
  48. package/src/canvas/__tests__/helpers/canvas-api.js +129 -0
  49. package/src/canvas/__tests__/helpers/perf.js +118 -0
  50. package/src/canvas/__tests__/helpers/setup.js +176 -0
  51. package/src/canvas/__tests__/helpers/tmux.js +130 -0
  52. package/src/canvas/__tests__/helpers/transcript.js +132 -0
  53. package/src/canvas/__tests__/terminal-integration.test.js +177 -0
  54. package/src/canvas/hot-pool.js +756 -0
  55. package/src/canvas/materializer.js +31 -0
  56. package/src/canvas/materializer.test.js +56 -0
  57. package/src/canvas/selectedWidgets.js +65 -7
  58. package/src/canvas/server.js +1802 -22
  59. package/src/canvas/server.test.js +239 -0
  60. package/src/canvas/terminal-config.js +330 -0
  61. package/src/canvas/terminal-registry.js +41 -3
  62. package/src/canvas/terminal-server.js +1098 -37
  63. package/src/canvas/writeGuard.js +51 -3
  64. package/src/canvasConfig.js +67 -1
  65. package/src/canvasConfig.test.js +79 -1
  66. package/src/cli/agent.js +85 -0
  67. package/src/cli/branch.js +232 -0
  68. package/src/cli/canvasAdd.js +61 -14
  69. package/src/cli/canvasBatch.js +98 -0
  70. package/src/cli/canvasBounds.js +1 -1
  71. package/src/cli/canvasRead.js +1 -1
  72. package/src/cli/canvasUpdate.js +179 -0
  73. package/src/cli/compact.js +0 -2
  74. package/src/cli/create.js +40 -16
  75. package/src/cli/dev.js +158 -84
  76. package/src/cli/exit.js +23 -24
  77. package/src/cli/index.js +55 -2
  78. package/src/cli/proxy.js +96 -37
  79. package/src/cli/schemas.js +22 -4
  80. package/src/cli/server.js +149 -26
  81. package/src/cli/serverUrl.js +8 -3
  82. package/src/cli/sessions.js +133 -7
  83. package/src/cli/setup.js +138 -12
  84. package/src/cli/terminal-commands.js +20 -9
  85. package/src/cli/terminal-messaging.js +231 -0
  86. package/src/cli/terminal-welcome.js +449 -34
  87. package/src/cli/updateVersion.js +1 -1
  88. package/src/commandActions.js +1 -0
  89. package/src/commandPaletteConfig.js +9 -0
  90. package/src/comments/auth.js +2 -1
  91. package/src/comments/ui/AuthModal.jsx +114 -0
  92. package/src/comments/ui/CommentWindow.jsx +329 -0
  93. package/src/comments/ui/CommentsDrawer.jsx +102 -0
  94. package/src/comments/ui/Composer.jsx +64 -0
  95. package/src/comments/ui/authModal.test.js +1 -1
  96. package/src/comments/ui/commentWindow.js +16 -17
  97. package/src/comments/ui/commentsDrawer.js +25 -26
  98. package/src/comments/ui/composer.js +23 -24
  99. package/src/comments/ui/index.js +2 -3
  100. package/src/configSchema.js +59 -1
  101. package/src/configStore.js +161 -0
  102. package/src/core-ui-colors.css +12 -0
  103. package/src/devtools.js +17 -19
  104. package/src/devtools.test.js +18 -9
  105. package/src/featureFlags.js +12 -5
  106. package/src/fuzzySearch.test.js +10 -0
  107. package/src/index.js +15 -3
  108. package/src/lib/components/ui/alert/alert-action.jsx +11 -0
  109. package/src/lib/components/ui/alert/alert-description.jsx +11 -0
  110. package/src/lib/components/ui/alert/alert-title.jsx +11 -0
  111. package/src/lib/components/ui/alert/alert.jsx +25 -0
  112. package/src/lib/components/ui/alert/index.js +15 -15
  113. package/src/lib/components/ui/avatar/avatar-badge.jsx +22 -0
  114. package/src/lib/components/ui/avatar/avatar-fallback.jsx +18 -0
  115. package/src/lib/components/ui/avatar/avatar-group-count.jsx +19 -0
  116. package/src/lib/components/ui/avatar/avatar-group.jsx +19 -0
  117. package/src/lib/components/ui/avatar/avatar-image.jsx +15 -0
  118. package/src/lib/components/ui/avatar/avatar.jsx +19 -0
  119. package/src/lib/components/ui/avatar/index.js +20 -20
  120. package/src/lib/components/ui/badge/badge.jsx +31 -0
  121. package/src/lib/components/ui/badge/index.js +2 -2
  122. package/src/lib/components/ui/button/button.jsx +100 -0
  123. package/src/lib/components/ui/button/index.js +9 -9
  124. package/src/lib/components/ui/card/card-action.jsx +11 -0
  125. package/src/lib/components/ui/card/card-content.jsx +11 -0
  126. package/src/lib/components/ui/card/card-description.jsx +11 -0
  127. package/src/lib/components/ui/card/card-footer.jsx +11 -0
  128. package/src/lib/components/ui/card/card-header.jsx +19 -0
  129. package/src/lib/components/ui/card/card-title.jsx +11 -0
  130. package/src/lib/components/ui/card/card.jsx +17 -0
  131. package/src/lib/components/ui/card/index.js +23 -23
  132. package/src/lib/components/ui/checkbox/checkbox.jsx +29 -0
  133. package/src/lib/components/ui/checkbox/index.js +5 -5
  134. package/src/lib/components/ui/collapsible/collapsible-content.jsx +7 -0
  135. package/src/lib/components/ui/collapsible/collapsible-trigger.jsx +7 -0
  136. package/src/lib/components/ui/collapsible/collapsible.jsx +7 -0
  137. package/src/lib/components/ui/collapsible/index.js +11 -11
  138. package/src/lib/components/ui/dialog/dialog-close.jsx +7 -0
  139. package/src/lib/components/ui/dialog/dialog-content.jsx +34 -0
  140. package/src/lib/components/ui/dialog/dialog-description.jsx +15 -0
  141. package/src/lib/components/ui/dialog/dialog-footer.jsx +23 -0
  142. package/src/lib/components/ui/dialog/dialog-header.jsx +11 -0
  143. package/src/lib/components/ui/dialog/dialog-overlay.jsx +15 -0
  144. package/src/lib/components/ui/dialog/dialog-portal.jsx +4 -0
  145. package/src/lib/components/ui/dialog/dialog-title.jsx +15 -0
  146. package/src/lib/components/ui/dialog/dialog-trigger.jsx +7 -0
  147. package/src/lib/components/ui/dialog/dialog.jsx +4 -0
  148. package/src/lib/components/ui/dialog/index.js +32 -32
  149. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +8 -0
  150. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +30 -0
  151. package/src/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +22 -0
  152. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +16 -0
  153. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +7 -0
  154. package/src/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +20 -0
  155. package/src/lib/components/ui/dropdown-menu/dropdown-menu-label.jsx +17 -0
  156. package/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +4 -0
  157. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +7 -0
  158. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +29 -0
  159. package/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +15 -0
  160. package/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.jsx +16 -0
  161. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +15 -0
  162. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +23 -0
  163. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +4 -0
  164. package/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +7 -0
  165. package/src/lib/components/ui/dropdown-menu/dropdown-menu.jsx +4 -0
  166. package/src/lib/components/ui/dropdown-menu/index.js +52 -52
  167. package/src/lib/components/ui/input/index.js +5 -5
  168. package/src/lib/components/ui/input/input.jsx +19 -0
  169. package/src/lib/components/ui/label/index.js +5 -5
  170. package/src/lib/components/ui/label/label.jsx +19 -0
  171. package/src/lib/components/ui/panel/index.js +21 -21
  172. package/src/lib/components/ui/panel/panel-body.jsx +11 -0
  173. package/src/lib/components/ui/panel/panel-close.jsx +16 -0
  174. package/src/lib/components/ui/panel/panel-content.jsx +29 -0
  175. package/src/lib/components/ui/panel/panel-footer.jsx +11 -0
  176. package/src/lib/components/ui/panel/panel-header.jsx +11 -0
  177. package/src/lib/components/ui/panel/panel-title.jsx +12 -0
  178. package/src/lib/components/ui/panel/panel.jsx +4 -0
  179. package/src/lib/components/ui/popover/index.js +26 -26
  180. package/src/lib/components/ui/popover/popover-close.jsx +7 -0
  181. package/src/lib/components/ui/popover/popover-content.jsx +22 -0
  182. package/src/lib/components/ui/popover/popover-description.jsx +11 -0
  183. package/src/lib/components/ui/popover/popover-header.jsx +11 -0
  184. package/src/lib/components/ui/popover/popover-portal.jsx +4 -0
  185. package/src/lib/components/ui/popover/popover-title.jsx +11 -0
  186. package/src/lib/components/ui/popover/popover-trigger.jsx +8 -0
  187. package/src/lib/components/ui/popover/popover.jsx +4 -0
  188. package/src/lib/components/ui/searchable-list.jsx +160 -0
  189. package/src/lib/components/ui/select/index.js +35 -35
  190. package/src/lib/components/ui/select/select-content.jsx +30 -0
  191. package/src/lib/components/ui/select/select-group-heading.jsx +17 -0
  192. package/src/lib/components/ui/select/select-group.jsx +15 -0
  193. package/src/lib/components/ui/select/select-item.jsx +26 -0
  194. package/src/lib/components/ui/select/select-label.jsx +11 -0
  195. package/src/lib/components/ui/select/select-portal.jsx +4 -0
  196. package/src/lib/components/ui/select/select-scroll-down-button.jsx +18 -0
  197. package/src/lib/components/ui/select/select-scroll-up-button.jsx +18 -0
  198. package/src/lib/components/ui/select/select-separator.jsx +15 -0
  199. package/src/lib/components/ui/select/select-trigger.jsx +25 -0
  200. package/src/lib/components/ui/select/select.jsx +4 -0
  201. package/src/lib/components/ui/separator/index.js +5 -5
  202. package/src/lib/components/ui/separator/separator.jsx +22 -0
  203. package/src/lib/components/ui/sheet/index.js +32 -32
  204. package/src/lib/components/ui/sheet/sheet-close.jsx +7 -0
  205. package/src/lib/components/ui/sheet/sheet-content.jsx +35 -0
  206. package/src/lib/components/ui/sheet/sheet-description.jsx +15 -0
  207. package/src/lib/components/ui/sheet/sheet-footer.jsx +11 -0
  208. package/src/lib/components/ui/sheet/sheet-header.jsx +11 -0
  209. package/src/lib/components/ui/sheet/sheet-overlay.jsx +15 -0
  210. package/src/lib/components/ui/sheet/sheet-portal.jsx +4 -0
  211. package/src/lib/components/ui/sheet/sheet-title.jsx +15 -0
  212. package/src/lib/components/ui/sheet/sheet-trigger.jsx +7 -0
  213. package/src/lib/components/ui/sheet/sheet.jsx +4 -0
  214. package/src/lib/components/ui/textarea/index.js +5 -5
  215. package/src/lib/components/ui/textarea/textarea.jsx +18 -0
  216. package/src/lib/components/ui/toggle/index.js +6 -9
  217. package/src/lib/components/ui/toggle/toggle.jsx +36 -0
  218. package/src/lib/components/ui/toggle-group/index.js +8 -8
  219. package/src/lib/components/ui/toggle-group/toggle-group-item.jsx +29 -0
  220. package/src/lib/components/ui/toggle-group/toggle-group.jsx +43 -0
  221. package/src/lib/components/ui/tooltip/index.js +3 -3
  222. package/src/lib/components/ui/tooltip/tooltip-content.jsx +21 -0
  223. package/src/lib/components/ui/tooltip/tooltip-trigger.jsx +23 -0
  224. package/src/lib/components/ui/tooltip/tooltip.jsx +11 -0
  225. package/src/lib/components/ui/trigger-button/index.js +3 -3
  226. package/src/lib/components/ui/trigger-button/trigger-button.css +38 -0
  227. package/src/lib/components/ui/trigger-button/trigger-button.jsx +63 -0
  228. package/src/logger/devLogger.js +238 -0
  229. package/src/logger/devLogger.test.js +193 -0
  230. package/src/modes.test.js +4 -4
  231. package/src/mountStoryboardCore.js +133 -35
  232. package/src/paletteProviders.js +3 -0
  233. package/src/paletteProviders.test.js +2 -2
  234. package/src/server/index.js +104 -40
  235. package/src/sidepanel.css +214 -0
  236. package/src/smoothCorners.js +1 -1
  237. package/src/styles/tailwind.css +1 -1
  238. package/src/svelte-plugin-ui/__tests__/ModeSwitch.test.ts +8 -8
  239. package/src/svelte-plugin-ui/__tests__/ToolbarShell.test.ts +11 -10
  240. package/src/svelte-plugin-ui/components/Icon.css +11 -0
  241. package/src/svelte-plugin-ui/components/Icon.jsx +281 -0
  242. package/src/svelte-plugin-ui/components/ModeSwitch.css +90 -0
  243. package/src/svelte-plugin-ui/components/ModeSwitch.jsx +47 -0
  244. package/src/svelte-plugin-ui/components/ToolbarShell.css +80 -0
  245. package/src/svelte-plugin-ui/components/ToolbarShell.jsx +84 -0
  246. package/src/svelte-plugin-ui/components/Viewfinder.css +412 -0
  247. package/src/svelte-plugin-ui/components/Viewfinder.jsx +513 -0
  248. package/src/svelte-plugin-ui/mount.ts +12 -16
  249. package/src/toolRegistry.js +4 -4
  250. package/src/toolbarConfigStore.js +30 -0
  251. package/src/tools/handlers/autosync.js +1 -1
  252. package/src/tools/handlers/canvasAddWidget.js +1 -1
  253. package/src/tools/handlers/canvasAgents.js +20 -0
  254. package/src/tools/handlers/canvasToolbar.js +8 -8
  255. package/src/tools/handlers/commandPalette.js +9 -0
  256. package/src/tools/handlers/comments.js +2 -2
  257. package/src/tools/handlers/create.js +1 -1
  258. package/src/tools/handlers/devtools.js +19 -3
  259. package/src/tools/handlers/devtools.test.js +38 -0
  260. package/src/tools/handlers/featureFlags.js +1 -1
  261. package/src/tools/handlers/flows.js +3 -3
  262. package/src/tools/handlers/hideChrome.js +9 -0
  263. package/src/tools/handlers/paletteTheme.js +35 -0
  264. package/src/tools/handlers/theme.js +1 -1
  265. package/src/tools/registry.js +4 -1
  266. package/src/tools/surfaces/commandList.js +3 -3
  267. package/src/tools/surfaces/mainToolbar.js +3 -3
  268. package/src/tools/surfaces/registry.js +4 -4
  269. package/src/ui/design-modes.ts +2 -2
  270. package/src/ui/viewfinder.ts +1 -1
  271. package/src/vite/server-plugin.js +243 -61
  272. package/src/workshop/features/createCanvas/CreateCanvasForm.jsx +260 -0
  273. package/src/workshop/features/createCanvas/index.js +1 -1
  274. package/src/workshop/features/createFlow/CreateFlowForm.jsx +334 -0
  275. package/src/workshop/features/createFlow/index.js +1 -1
  276. package/src/workshop/features/createPage/CreatePageForm.jsx +304 -0
  277. package/src/workshop/features/createPage/index.js +1 -1
  278. package/src/workshop/features/createPrototype/CreatePrototypeForm.jsx +289 -0
  279. package/src/workshop/features/createPrototype/index.js +1 -1
  280. package/src/workshop/features/createPrototype/server.js +98 -0
  281. package/src/workshop/features/createStory/CreateStoryForm.jsx +208 -0
  282. package/src/workshop/features/createStory/index.js +1 -1
  283. package/src/workshop/ui/WorkshopPanel.jsx +98 -0
  284. package/src/workshop/ui/mount.ts +1 -1
  285. package/src/worktree/port.js +48 -0
  286. package/src/worktree/serverRegistry.js +120 -0
  287. package/toolbar.config.json +93 -42
  288. package/widgets.config.json +580 -12
  289. package/scaffold/commandpalette.config.json +0 -4
  290. package/scaffold/toolbar.config.json +0 -4
  291. package/src/ActionMenuButton.svelte +0 -119
  292. package/src/AutosyncMenuButton.svelte +0 -397
  293. package/src/CanvasCreateMenu.svelte +0 -295
  294. package/src/CanvasSnap.svelte +0 -87
  295. package/src/CanvasUndoRedo.svelte +0 -108
  296. package/src/CanvasZoomControl.svelte +0 -111
  297. package/src/CanvasZoomToFit.svelte +0 -52
  298. package/src/CommandMenu.svelte +0 -249
  299. package/src/CommandPalette.svelte +0 -33
  300. package/src/CommentsMenuButton.svelte +0 -53
  301. package/src/CoreUIBar.svelte +0 -847
  302. package/src/CreateMenuButton.svelte +0 -133
  303. package/src/DocPanel.svelte +0 -299
  304. package/src/InspectorPanel.svelte +0 -745
  305. package/src/PwaInstallBanner.svelte +0 -124
  306. package/src/SidePanel.svelte +0 -480
  307. package/src/ThemeMenuButton.svelte +0 -132
  308. package/src/comments/ui/AuthModal.svelte +0 -108
  309. package/src/comments/ui/CommentWindow.svelte +0 -333
  310. package/src/comments/ui/CommentsDrawer.svelte +0 -96
  311. package/src/comments/ui/Composer.svelte +0 -65
  312. package/src/lib/components/ui/alert/alert-action.svelte +0 -19
  313. package/src/lib/components/ui/alert/alert-description.svelte +0 -22
  314. package/src/lib/components/ui/alert/alert-title.svelte +0 -22
  315. package/src/lib/components/ui/alert/alert.svelte +0 -38
  316. package/src/lib/components/ui/avatar/avatar-badge.svelte +0 -25
  317. package/src/lib/components/ui/avatar/avatar-fallback.svelte +0 -20
  318. package/src/lib/components/ui/avatar/avatar-group-count.svelte +0 -22
  319. package/src/lib/components/ui/avatar/avatar-group.svelte +0 -22
  320. package/src/lib/components/ui/avatar/avatar-image.svelte +0 -17
  321. package/src/lib/components/ui/avatar/avatar.svelte +0 -24
  322. package/src/lib/components/ui/badge/badge.svelte +0 -44
  323. package/src/lib/components/ui/button/button.svelte +0 -108
  324. package/src/lib/components/ui/card/card-action.svelte +0 -21
  325. package/src/lib/components/ui/card/card-content.svelte +0 -19
  326. package/src/lib/components/ui/card/card-description.svelte +0 -19
  327. package/src/lib/components/ui/card/card-footer.svelte +0 -18
  328. package/src/lib/components/ui/card/card-header.svelte +0 -21
  329. package/src/lib/components/ui/card/card-title.svelte +0 -14
  330. package/src/lib/components/ui/card/card.svelte +0 -21
  331. package/src/lib/components/ui/checkbox/checkbox.svelte +0 -39
  332. package/src/lib/components/ui/collapsible/collapsible-content.svelte +0 -7
  333. package/src/lib/components/ui/collapsible/collapsible-trigger.svelte +0 -7
  334. package/src/lib/components/ui/collapsible/collapsible.svelte +0 -11
  335. package/src/lib/components/ui/dialog/dialog-close.svelte +0 -11
  336. package/src/lib/components/ui/dialog/dialog-content.svelte +0 -42
  337. package/src/lib/components/ui/dialog/dialog-description.svelte +0 -17
  338. package/src/lib/components/ui/dialog/dialog-footer.svelte +0 -29
  339. package/src/lib/components/ui/dialog/dialog-header.svelte +0 -19
  340. package/src/lib/components/ui/dialog/dialog-overlay.svelte +0 -17
  341. package/src/lib/components/ui/dialog/dialog-portal.svelte +0 -7
  342. package/src/lib/components/ui/dialog/dialog-title.svelte +0 -17
  343. package/src/lib/components/ui/dialog/dialog-trigger.svelte +0 -11
  344. package/src/lib/components/ui/dialog/dialog.svelte +0 -7
  345. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +0 -16
  346. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +0 -40
  347. package/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte +0 -27
  348. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +0 -18
  349. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte +0 -7
  350. package/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte +0 -24
  351. package/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte +0 -20
  352. package/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte +0 -7
  353. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +0 -16
  354. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +0 -34
  355. package/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte +0 -17
  356. package/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +0 -19
  357. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +0 -17
  358. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +0 -27
  359. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte +0 -7
  360. package/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +0 -7
  361. package/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte +0 -7
  362. package/src/lib/components/ui/input/input.svelte +0 -40
  363. package/src/lib/components/ui/label/label.svelte +0 -20
  364. package/src/lib/components/ui/panel/panel-body.svelte +0 -13
  365. package/src/lib/components/ui/panel/panel-close.svelte +0 -16
  366. package/src/lib/components/ui/panel/panel-content.svelte +0 -33
  367. package/src/lib/components/ui/panel/panel-footer.svelte +0 -13
  368. package/src/lib/components/ui/panel/panel-header.svelte +0 -16
  369. package/src/lib/components/ui/panel/panel-title.svelte +0 -14
  370. package/src/lib/components/ui/panel/panel.svelte +0 -15
  371. package/src/lib/components/ui/popover/popover-close.svelte +0 -7
  372. package/src/lib/components/ui/popover/popover-content.svelte +0 -27
  373. package/src/lib/components/ui/popover/popover-description.svelte +0 -19
  374. package/src/lib/components/ui/popover/popover-header.svelte +0 -19
  375. package/src/lib/components/ui/popover/popover-portal.svelte +0 -7
  376. package/src/lib/components/ui/popover/popover-title.svelte +0 -19
  377. package/src/lib/components/ui/popover/popover-trigger.svelte +0 -17
  378. package/src/lib/components/ui/popover/popover.svelte +0 -7
  379. package/src/lib/components/ui/select/select-content.svelte +0 -40
  380. package/src/lib/components/ui/select/select-group-heading.svelte +0 -19
  381. package/src/lib/components/ui/select/select-group.svelte +0 -17
  382. package/src/lib/components/ui/select/select-item.svelte +0 -38
  383. package/src/lib/components/ui/select/select-label.svelte +0 -18
  384. package/src/lib/components/ui/select/select-portal.svelte +0 -7
  385. package/src/lib/components/ui/select/select-scroll-down-button.svelte +0 -20
  386. package/src/lib/components/ui/select/select-scroll-up-button.svelte +0 -20
  387. package/src/lib/components/ui/select/select-separator.svelte +0 -17
  388. package/src/lib/components/ui/select/select-trigger.svelte +0 -27
  389. package/src/lib/components/ui/select/select.svelte +0 -11
  390. package/src/lib/components/ui/separator/separator.svelte +0 -23
  391. package/src/lib/components/ui/sheet/sheet-close.svelte +0 -7
  392. package/src/lib/components/ui/sheet/sheet-content.svelte +0 -43
  393. package/src/lib/components/ui/sheet/sheet-description.svelte +0 -17
  394. package/src/lib/components/ui/sheet/sheet-footer.svelte +0 -18
  395. package/src/lib/components/ui/sheet/sheet-header.svelte +0 -19
  396. package/src/lib/components/ui/sheet/sheet-overlay.svelte +0 -17
  397. package/src/lib/components/ui/sheet/sheet-portal.svelte +0 -7
  398. package/src/lib/components/ui/sheet/sheet-title.svelte +0 -17
  399. package/src/lib/components/ui/sheet/sheet-trigger.svelte +0 -7
  400. package/src/lib/components/ui/sheet/sheet.svelte +0 -7
  401. package/src/lib/components/ui/textarea/textarea.svelte +0 -21
  402. package/src/lib/components/ui/toggle/toggle.svelte +0 -45
  403. package/src/lib/components/ui/toggle-group/toggle-group-item.svelte +0 -35
  404. package/src/lib/components/ui/toggle-group/toggle-group.svelte +0 -63
  405. package/src/lib/components/ui/tooltip/tooltip-content.svelte +0 -24
  406. package/src/lib/components/ui/tooltip/tooltip-trigger.svelte +0 -27
  407. package/src/lib/components/ui/tooltip/tooltip.svelte +0 -9
  408. package/src/lib/components/ui/trigger-button/trigger-button.svelte +0 -106
  409. package/src/svelte-plugin-ui/components/Icon.svelte +0 -181
  410. package/src/svelte-plugin-ui/components/ModeSwitch.svelte +0 -121
  411. package/src/svelte-plugin-ui/components/ToolbarShell.svelte +0 -150
  412. package/src/svelte-plugin-ui/components/Viewfinder.svelte +0 -1001
  413. package/src/tools/handlers/docs.js +0 -11
  414. package/src/workshop/features/createCanvas/CreateCanvasForm.svelte +0 -139
  415. package/src/workshop/features/createFlow/CreateFlowForm.svelte +0 -314
  416. package/src/workshop/features/createPage/CreatePageForm.svelte +0 -249
  417. package/src/workshop/features/createPrototype/CreatePrototypeForm.svelte +0 -287
  418. package/src/workshop/features/createStory/CreateStoryForm.svelte +0 -161
  419. package/src/workshop/ui/WorkshopPanel.svelte +0 -97
@@ -1,249 +0,0 @@
1
- <!--
2
- CreatePageForm — workshop form for creating a new page inside a prototype.
3
- -->
4
-
5
- <script lang="ts">
6
- import { onMount } from 'svelte'
7
- import { Button } from '../../../lib/components/ui/button/index.js'
8
- import { Input } from '../../../lib/components/ui/input/index.js'
9
- import { Label } from '../../../lib/components/ui/label/index.js'
10
- import * as Panel from '../../../lib/components/ui/panel/index.js'
11
- import * as DropdownMenu from '../../../lib/components/ui/dropdown-menu/index.js'
12
- import * as Alert from '../../../lib/components/ui/alert/index.js'
13
-
14
- interface Props { onClose?: () => void }
15
- let { onClose }: Props = $props()
16
-
17
- interface PrototypeEntry { name: string; folder?: string }
18
- interface PartialEntry {
19
- id: string
20
- name: string
21
- kind: 'template' | 'recipe'
22
- scope: 'global' | 'prototype'
23
- prototype?: string
24
- folder?: string
25
- }
26
-
27
- let selectedPrototype = $state('')
28
- let pagePath = $state('')
29
- let template = $state('')
30
- let prototypes: PrototypeEntry[] = $state([])
31
- let partials: PartialEntry[] = $state([])
32
- let loading = $state(true)
33
- let submitting = $state(false)
34
- let error: string | null = $state(null)
35
- let success: string | null = $state(null)
36
- let templateMenuOpen = $state(false)
37
-
38
- const selectedProtoEntry = $derived(
39
- selectedPrototype ? prototypes.find((p) => p.name === selectedPrototype) : null
40
- )
41
- const pagePrefix = $derived(selectedPrototype ? `/${selectedPrototype}/` : '/prototype-name/')
42
- const pageSuffix = $derived(
43
- pagePath.startsWith(pagePrefix) ? pagePath.slice(pagePrefix.length) : pagePath
44
- )
45
- const canSubmit = $derived(!!selectedPrototype && !!pageSuffix.trim() && !submitting)
46
- const templateChoices = $derived(
47
- selectedPrototype
48
- ? partials.filter((partial) => {
49
- if (partial.scope === 'global') return true
50
- return partial.prototype === selectedPrototype && (partial.folder || '') === (selectedProtoEntry?.folder || '')
51
- })
52
- : partials.filter((partial) => partial.scope === 'global')
53
- )
54
- const globalTemplateChoices = $derived(templateChoices.filter((partial) => partial.scope === 'global'))
55
- const localTemplateChoices = $derived(
56
- templateChoices.filter((partial) => partial.scope === 'prototype')
57
- )
58
- const localTemplateHeading = $derived(
59
- selectedPrototype || ''
60
- )
61
- const globalTemplates = $derived(globalTemplateChoices.filter((partial) => partial.kind === 'template'))
62
- const globalRecipes = $derived(globalTemplateChoices.filter((partial) => partial.kind === 'recipe'))
63
- const localTemplates = $derived(localTemplateChoices.filter((partial) => partial.kind === 'template'))
64
- const localRecipes = $derived(localTemplateChoices.filter((partial) => partial.kind === 'recipe'))
65
- const templateLabel = $derived(
66
- template ? templateChoices.find((choice) => choice.id === template)?.name ?? template : 'Blank page'
67
- )
68
-
69
- function getApiUrl() {
70
- const basePath = window.__STORYBOARD_BASE_PATH__ || '/'
71
- return basePath.replace(/\/$/, '') + '/_storyboard/workshop/pages'
72
- }
73
-
74
- onMount(async () => {
75
- try {
76
- const res = await fetch(getApiUrl())
77
- if (res.ok) {
78
- const data = await res.json()
79
- prototypes = data.prototypes || []
80
- partials = data.partials || []
81
- }
82
- } catch { /* defaults */ } finally { loading = false }
83
- })
84
-
85
- $effect(() => {
86
- if (!selectedPrototype) {
87
- pagePath = ''
88
- return
89
- }
90
- if (!pagePath || !pagePath.startsWith(pagePrefix)) {
91
- pagePath = `${pagePrefix}new-page`
92
- }
93
- })
94
-
95
- $effect(() => {
96
- if (!template) return
97
- const stillAvailable = templateChoices.some((choice) => choice.id === template)
98
- if (!stillAvailable) {
99
- template = ''
100
- }
101
- })
102
-
103
- async function submit() {
104
- if (!canSubmit) return
105
- submitting = true; error = null; success = null
106
- try {
107
- const res = await fetch(getApiUrl(), {
108
- method: 'POST',
109
- headers: { 'Content-Type': 'application/json' },
110
- body: JSON.stringify({
111
- prototype: selectedPrototype,
112
- folder: selectedProtoEntry?.folder || undefined,
113
- path: pagePath.trim(),
114
- template: template || undefined,
115
- }),
116
- })
117
- const data = await res.json()
118
- if (!res.ok) { error = data.error || 'Failed to create page'; return }
119
- success = `Created ${data.path}`
120
- } catch (err: any) {
121
- error = err.message || 'Network error'
122
- } finally {
123
- submitting = false
124
- }
125
- }
126
-
127
- function handleKeydown(e: KeyboardEvent) { if (e.key === 'Enter' && canSubmit) submit() }
128
- </script>
129
-
130
- <Panel.Header>
131
- <Panel.Title>Create page</Panel.Title>
132
- <Panel.Close />
133
- </Panel.Header>
134
-
135
- <!-- svelte-ignore a11y_no_static_element_interactions -->
136
- <div class="p-4 pt-2 space-y-5" onkeydown={handleKeydown}>
137
- <div class="space-y-1">
138
- <Label for="sb-page-prototype">Prototype</Label>
139
- <select
140
- class="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
141
- id="sb-page-prototype"
142
- bind:value={selectedPrototype}
143
- disabled={loading}
144
- >
145
- <option value="">Select prototype</option>
146
- {#each prototypes as p}
147
- <option value={p.name}>{p.folder ? `${p.folder} / ${p.name}` : p.name}</option>
148
- {/each}
149
- </select>
150
- </div>
151
-
152
- <div class="space-y-1">
153
- <Label for="sb-page-path">Page path</Label>
154
- <div class="flex items-center gap-2">
155
- <span class="text-xs text-muted-foreground font-mono whitespace-nowrap">{pagePrefix}</span>
156
- <Input
157
- id="sb-page-path"
158
- placeholder="new-page"
159
- value={pageSuffix}
160
- oninput={(e: Event) => {
161
- const suffix = (e.target as HTMLInputElement).value.replace(/^\/+/, '')
162
- pagePath = `${pagePrefix}${suffix}`
163
- }}
164
- disabled={!selectedPrototype}
165
- />
166
- </div>
167
- </div>
168
-
169
- <div class="space-y-1">
170
- <Label>Template / recipe</Label>
171
- <DropdownMenu.Root bind:open={templateMenuOpen}>
172
- <DropdownMenu.Trigger>
173
- {#snippet child({ props })}
174
- <button
175
- {...props}
176
- class="flex h-9 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
177
- disabled={!selectedPrototype}
178
- >
179
- <span class={template ? 'text-foreground' : 'text-muted-foreground'}>{templateLabel}</span>
180
- <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-muted-foreground"><path d="m6 9 6 6 6-6"/></svg>
181
- </button>
182
- {/snippet}
183
- </DropdownMenu.Trigger>
184
- <DropdownMenu.Content side="left" align="start" sideOffset={8} class="min-w-[220px]">
185
- {#if template}
186
- <DropdownMenu.Item onclick={() => { template = ''; templateMenuOpen = false }}>
187
- <span class="text-muted-foreground">Blank page</span>
188
- </DropdownMenu.Item>
189
- <DropdownMenu.Separator />
190
- {/if}
191
-
192
- {#if globalTemplates.length > 0}
193
- <DropdownMenu.Group>
194
- <DropdownMenu.GroupHeading>Templates</DropdownMenu.GroupHeading>
195
- {#each globalTemplates as item (item.id)}
196
- <DropdownMenu.Item onclick={() => { template = item.id; templateMenuOpen = false }}>
197
- {item.name}
198
- </DropdownMenu.Item>
199
- {/each}
200
- </DropdownMenu.Group>
201
- {/if}
202
-
203
- {#if localTemplates.length > 0}
204
- <DropdownMenu.Separator />
205
- <DropdownMenu.Group>
206
- <DropdownMenu.GroupHeading>{localTemplateHeading} / Templates</DropdownMenu.GroupHeading>
207
- {#each localTemplates as item (item.id)}
208
- <DropdownMenu.Item onclick={() => { template = item.id; templateMenuOpen = false }}>
209
- {item.name}
210
- </DropdownMenu.Item>
211
- {/each}
212
- </DropdownMenu.Group>
213
- {/if}
214
-
215
- {#if globalRecipes.length > 0}
216
- <DropdownMenu.Separator />
217
- <DropdownMenu.Group>
218
- <DropdownMenu.GroupHeading>Recipes</DropdownMenu.GroupHeading>
219
- {#each globalRecipes as item (item.id)}
220
- <DropdownMenu.Item onclick={() => { template = item.id; templateMenuOpen = false }}>
221
- {item.name}
222
- </DropdownMenu.Item>
223
- {/each}
224
- </DropdownMenu.Group>
225
- {/if}
226
-
227
- {#if localRecipes.length > 0}
228
- <DropdownMenu.Separator />
229
- <DropdownMenu.Group>
230
- <DropdownMenu.GroupHeading>{localTemplateHeading} / Recipes</DropdownMenu.GroupHeading>
231
- {#each localRecipes as item (item.id)}
232
- <DropdownMenu.Item onclick={() => { template = item.id; templateMenuOpen = false }}>
233
- {item.name}
234
- </DropdownMenu.Item>
235
- {/each}
236
- </DropdownMenu.Group>
237
- {/if}
238
- </DropdownMenu.Content>
239
- </DropdownMenu.Root>
240
- </div>
241
-
242
- {#if error}<Alert.Root variant="destructive"><Alert.Description>{error}</Alert.Description></Alert.Root>{/if}
243
- {#if success}<Alert.Root><Alert.Description class="text-success">{success}</Alert.Description></Alert.Root>{/if}
244
- </div>
245
-
246
- <Panel.Footer>
247
- <Button variant="outline" onclick={onClose}>Cancel</Button>
248
- <Button onclick={submit} disabled={!canSubmit}>{submitting ? 'Creating…' : 'Create page'}</Button>
249
- </Panel.Footer>
@@ -1,287 +0,0 @@
1
- <!--
2
- CreatePrototypeForm — workshop form for creating a new prototype.
3
- Uses shadcn-svelte components for all form elements.
4
- -->
5
-
6
- <script lang="ts">
7
- import { onMount } from 'svelte'
8
- import { Button } from '../../../lib/components/ui/button/index.js'
9
- import { Input } from '../../../lib/components/ui/input/index.js'
10
- import { Label } from '../../../lib/components/ui/label/index.js'
11
- import { Checkbox } from '../../../lib/components/ui/checkbox/index.js'
12
- import * as Panel from '../../../lib/components/ui/panel/index.js'
13
- import * as DropdownMenu from '../../../lib/components/ui/dropdown-menu/index.js'
14
- import * as Alert from '../../../lib/components/ui/alert/index.js'
15
-
16
- interface Props { onClose?: () => void }
17
- let { onClose }: Props = $props()
18
-
19
- let name = $state('')
20
- let title = $state('')
21
- let titleTouched = $state(false)
22
- let folder = $state('')
23
- let partial = $state('')
24
- let author = $state('')
25
- let description = $state('')
26
- let createFlow = $state(false)
27
- let isExternal = $state(false)
28
- let externalUrl = $state('')
29
-
30
- interface Partial {
31
- id: string
32
- name: string
33
- kind: 'template' | 'recipe'
34
- scope: 'global' | 'prototype'
35
- prototype?: string
36
- folder?: string
37
- }
38
-
39
- let folders: string[] = $state([])
40
- let partials: Partial[] = $state([])
41
- let loading = $state(true)
42
- let submitting = $state(false)
43
- let error: string | null = $state(null)
44
- let success: string | null = $state(null)
45
-
46
- const kebabName = $derived(
47
- name.replace(/[^a-zA-Z0-9\s_-]/g, '').trim().replace(/[\s_]+/g, '-').toLowerCase().replace(/-+/g, '-').replace(/^-|-$/g, '')
48
- )
49
- const autoTitle = $derived(
50
- kebabName ? kebabName.split('-').map((s: string) => s.charAt(0).toUpperCase() + s.slice(1)).join('').replace(/([A-Z])/g, ' $1').trim() : ''
51
- )
52
- const displayTitle = $derived(titleTouched ? title : autoTitle)
53
- const routePreview = $derived(kebabName ? `/${kebabName}` : '')
54
- const nameError = $derived(
55
- name.trim() && !kebabName ? 'Name must contain at least one alphanumeric character'
56
- : name.trim() && !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(kebabName) ? 'Name must be kebab-case'
57
- : null
58
- )
59
- const urlError: string | null = $derived.by(() => {
60
- if (!isExternal || !externalUrl.trim()) return null
61
- try {
62
- const parsed = new URL(externalUrl.trim())
63
- if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return 'Must use http: or https: protocol'
64
- return null
65
- } catch {
66
- return 'Must be a valid URL (e.g. https://example.com)'
67
- }
68
- })
69
- const canSubmit = $derived(!!kebabName && !nameError && !submitting && (!isExternal || (!!externalUrl.trim() && !urlError)))
70
-
71
- const selectedFolderLabel = $derived(folder ? `${folder}.folder` : '')
72
- const scopedPartials = $derived(
73
- partials.filter((p) => {
74
- if (p.scope === 'global') return true
75
- if (!folder) return false
76
- return p.folder === folder
77
- })
78
- )
79
- const templateLabel = $derived(
80
- partial ? scopedPartials.find((p) => p.id === partial)?.name ?? partial : 'No template'
81
- )
82
- const templates = $derived(scopedPartials.filter((p) => p.kind === 'template'))
83
- const recipes = $derived(scopedPartials.filter((p) => p.kind === 'recipe'))
84
- const globalTemplates = $derived(templates.filter((p) => p.scope === 'global'))
85
- const globalRecipes = $derived(recipes.filter((p) => p.scope === 'global'))
86
- const localTemplates = $derived(templates.filter((p) => p.scope === 'prototype'))
87
- const localRecipes = $derived(recipes.filter((p) => p.scope === 'prototype'))
88
- let templateMenuOpen = $state(false)
89
-
90
- function getApiUrl() {
91
- const basePath = window.__STORYBOARD_BASE_PATH__ || '/'
92
- return basePath.replace(/\/$/, '') + '/_storyboard/workshop/prototypes'
93
- }
94
-
95
- onMount(async () => {
96
- try {
97
- const res = await fetch(getApiUrl())
98
- if (res.ok) {
99
- const data = await res.json()
100
- folders = data.folders || []
101
- if (data.partials?.length) { partials = data.partials }
102
- }
103
- } catch { /* defaults */ } finally { loading = false }
104
- })
105
-
106
- $effect(() => {
107
- if (!partial) return
108
- const stillAvailable = scopedPartials.some((p) => p.id === partial)
109
- if (!stillAvailable) {
110
- partial = ''
111
- }
112
- })
113
-
114
- function handleTitleInput(e: Event) { title = (e.target as HTMLInputElement).value; titleTouched = true }
115
- function handleTitleBlur() { if (!title.trim()) titleTouched = false }
116
-
117
- async function submit() {
118
- if (!canSubmit) return
119
- submitting = true; error = null; success = null
120
- try {
121
- const payload: Record<string, any> = { name: kebabName, title: displayTitle, folder: folder || undefined, author: author.trim() || undefined, description: description.trim() || undefined }
122
- if (isExternal) {
123
- payload.url = externalUrl.trim()
124
- } else {
125
- payload.recipe = partial || undefined
126
- payload.createFlow = createFlow
127
- }
128
- const res = await fetch(getApiUrl(), {
129
- method: 'POST', headers: { 'Content-Type': 'application/json' },
130
- body: JSON.stringify(payload),
131
- })
132
- const data = await res.json()
133
- if (!res.ok) { error = data.error || 'Failed to create prototype'; return }
134
- success = `Created ${data.path}`
135
- if (data.isExternal) {
136
- // External prototype — no local route to navigate to, just close after a moment
137
- setTimeout(() => onClose?.(), 1500)
138
- } else {
139
- setTimeout(() => { const base = (window.__STORYBOARD_BASE_PATH__ || '/').replace(/\/$/, ''); window.location.href = base + data.route }, 1500)
140
- }
141
- } catch (err: any) { error = err.message || 'Network error' } finally { submitting = false }
142
- }
143
-
144
- function handleKeydown(e: KeyboardEvent) { if (e.key === 'Enter' && canSubmit) submit() }
145
- </script>
146
-
147
- <Panel.Header>
148
- <Panel.Title>Create prototype</Panel.Title>
149
- <Panel.Close />
150
- </Panel.Header>
151
-
152
- <!-- svelte-ignore a11y_no_static_element_interactions -->
153
- <div class="p-4 pt-2 space-y-3" onkeydown={handleKeydown}>
154
- <div class="space-y-1">
155
- <Label for="sb-proto-name">Name</Label>
156
- <Input id="sb-proto-name" placeholder="e.g. my-prototype" autocomplete="off" spellcheck="false" bind:value={name} />
157
- {#if nameError}<p class="text-sm text-destructive">{nameError}</p>{/if}
158
- {#if routePreview && !isExternal}<p class="text-xs text-muted-foreground">Route: <code class="px-1 py-0.5 bg-muted rounded font-mono text-foreground text-xs">{routePreview}</code></p>{/if}
159
- </div>
160
-
161
- <div class="flex items-center gap-2">
162
- <Checkbox id="sb-proto-external" bind:checked={isExternal} />
163
- <Label for="sb-proto-external" class="text-sm font-normal cursor-pointer">External prototype</Label>
164
- </div>
165
-
166
- {#if isExternal}
167
- <div class="space-y-1">
168
- <Label for="sb-proto-url">URL</Label>
169
- <Input id="sb-proto-url" placeholder="https://example.com/prototype" autocomplete="off" spellcheck="false" bind:value={externalUrl} />
170
- {#if urlError}<p class="text-sm text-destructive">{urlError}</p>{/if}
171
- </div>
172
- {/if}
173
-
174
- <div class="space-y-1">
175
- <Label for="sb-proto-title">Title</Label>
176
- <Input id="sb-proto-title" placeholder={autoTitle || 'Auto-derived from name'} value={displayTitle} oninput={handleTitleInput} onblur={handleTitleBlur} />
177
- </div>
178
-
179
- <div class="grid grid-cols-2 gap-3">
180
- <div class="space-y-1">
181
- <Label for="sb-proto-folder">Folder</Label>
182
- <select class="flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50" id="sb-proto-folder" bind:value={folder} disabled={loading}>
183
- <option value="">None</option>
184
- {#each folders as f}<option value={f}>{f}</option>{/each}
185
- </select>
186
- </div>
187
- {#if !isExternal}
188
- <div class="space-y-1">
189
- <Label>Template</Label>
190
- <DropdownMenu.Root bind:open={templateMenuOpen}>
191
- <DropdownMenu.Trigger>
192
- {#snippet child({ props })}
193
- <button
194
- {...props}
195
- class="flex h-9 w-full items-center justify-between rounded-md border border-input bg-transparent px-3 py-1 text-sm shadow-xs transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50"
196
- disabled={loading}
197
- >
198
- <span class={partial ? 'text-foreground' : 'text-muted-foreground'}>{templateLabel}</span>
199
- <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-muted-foreground"><path d="m6 9 6 6 6-6"/></svg>
200
- </button>
201
- {/snippet}
202
- </DropdownMenu.Trigger>
203
- <DropdownMenu.Content side="left" align="start" sideOffset={8} class="min-w-[180px]">
204
- {#if partial}
205
- <DropdownMenu.Item onclick={() => { partial = ''; templateMenuOpen = false }}>
206
- <span class="text-muted-foreground">Clear selection</span>
207
- </DropdownMenu.Item>
208
- <DropdownMenu.Separator />
209
- {/if}
210
-
211
- {#if templates.length > 0}
212
- <DropdownMenu.Group>
213
- <DropdownMenu.GroupHeading>Templates</DropdownMenu.GroupHeading>
214
- {#each globalTemplates as t (t.id)}
215
- <DropdownMenu.Item onclick={() => { partial = t.id; templateMenuOpen = false }}>
216
- {t.name}
217
- </DropdownMenu.Item>
218
- {/each}
219
- </DropdownMenu.Group>
220
- {/if}
221
-
222
- {#if localTemplates.length > 0}
223
- <DropdownMenu.Separator />
224
- <DropdownMenu.Group>
225
- <DropdownMenu.GroupHeading>{selectedFolderLabel || 'Prototype local'} / Templates</DropdownMenu.GroupHeading>
226
- {#each localTemplates as t (t.id)}
227
- <DropdownMenu.Item onclick={() => { partial = t.id; templateMenuOpen = false }}>
228
- {t.name}
229
- </DropdownMenu.Item>
230
- {/each}
231
- </DropdownMenu.Group>
232
- {/if}
233
-
234
- {#if globalRecipes.length > 0}
235
- <DropdownMenu.Separator />
236
- <DropdownMenu.Group>
237
- <DropdownMenu.GroupHeading>Recipes</DropdownMenu.GroupHeading>
238
- {#each globalRecipes as r (r.id)}
239
- <DropdownMenu.Item onclick={() => { partial = r.id; templateMenuOpen = false }}>
240
- {r.name}
241
- </DropdownMenu.Item>
242
- {/each}
243
- </DropdownMenu.Group>
244
- {/if}
245
-
246
- {#if localRecipes.length > 0}
247
- <DropdownMenu.Separator />
248
- <DropdownMenu.Group>
249
- <DropdownMenu.GroupHeading>{selectedFolderLabel || 'Prototype local'} / Recipes</DropdownMenu.GroupHeading>
250
- {#each localRecipes as r (r.id)}
251
- <DropdownMenu.Item onclick={() => { partial = r.id; templateMenuOpen = false }}>
252
- {r.name}
253
- </DropdownMenu.Item>
254
- {/each}
255
- </DropdownMenu.Group>
256
- {/if}
257
- </DropdownMenu.Content>
258
- </DropdownMenu.Root>
259
- </div>
260
- {/if}
261
- </div>
262
-
263
- <div class="space-y-1">
264
- <Label for="sb-proto-author">Author</Label>
265
- <Input id="sb-proto-author" placeholder="GitHub handle(s), comma-separated" bind:value={author} />
266
- </div>
267
-
268
- <div class="space-y-1">
269
- <Label for="sb-proto-desc">Description</Label>
270
- <Input id="sb-proto-desc" placeholder="Optional description" bind:value={description} />
271
- </div>
272
-
273
- {#if !isExternal}
274
- <div class="flex items-center gap-2">
275
- <Checkbox id="sb-proto-flow" bind:checked={createFlow} />
276
- <Label for="sb-proto-flow" class="text-sm font-normal cursor-pointer">Create flow file</Label>
277
- </div>
278
- {/if}
279
-
280
- {#if error}<Alert.Root variant="destructive"><Alert.Description>{error}</Alert.Description></Alert.Root>{/if}
281
- {#if success}<Alert.Root><Alert.Description class="text-success">{success}</Alert.Description></Alert.Root>{/if}
282
- </div>
283
-
284
- <Panel.Footer>
285
- <Button variant="outline" onclick={onClose}>Cancel</Button>
286
- <Button onclick={submit} disabled={!canSubmit}>{submitting ? 'Creating\u2026' : 'Create'}</Button>
287
- </Panel.Footer>