@dfosco/storyboard-core 4.2.0-beta.2 → 4.2.0-beta.21

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 (414) hide show
  1. package/commandpalette.config.json +109 -24
  2. package/dist/storyboard-ui.css +1 -1
  3. package/dist/storyboard-ui.js +17379 -28568
  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 -0
  11. package/scaffold/skills/canvas/SKILL.md +5 -4
  12. package/scaffold/skills/ship/SKILL.md +1 -1
  13. package/scaffold/storyboard.config.json +14 -1
  14. package/scaffold/toolbar.config.json +1 -1
  15. package/src/ActionMenuButton.jsx +100 -0
  16. package/src/AutosyncMenuButton.css +67 -0
  17. package/src/AutosyncMenuButton.jsx +241 -0
  18. package/src/BranchSelect.jsx +29 -0
  19. package/src/BranchSelect.module.css +30 -0
  20. package/src/CanvasAgentsMenu.jsx +87 -0
  21. package/src/CanvasCreateMenu.jsx +609 -0
  22. package/src/CanvasSnap.css +27 -0
  23. package/src/CanvasSnap.jsx +51 -0
  24. package/src/CanvasUndoRedo.css +36 -0
  25. package/src/CanvasUndoRedo.jsx +62 -0
  26. package/src/CanvasZoomControl.css +53 -0
  27. package/src/CanvasZoomControl.jsx +49 -0
  28. package/src/CanvasZoomToFit.css +18 -0
  29. package/src/CanvasZoomToFit.jsx +26 -0
  30. package/src/CommandMenu.css +8 -0
  31. package/src/CommandMenu.jsx +286 -0
  32. package/src/CommandPalette.jsx +35 -0
  33. package/src/CommandPaletteTrigger.jsx +25 -0
  34. package/src/CommentsMenuButton.jsx +38 -0
  35. package/src/CoreUIBar.css +47 -0
  36. package/src/CoreUIBar.jsx +855 -0
  37. package/src/CreateMenuButton.jsx +116 -0
  38. package/src/HideChromeTrigger.jsx +40 -0
  39. package/src/InspectorPanel.css +109 -0
  40. package/src/InspectorPanel.jsx +629 -0
  41. package/src/PwaInstallBanner.css +42 -0
  42. package/src/PwaInstallBanner.jsx +124 -0
  43. package/src/SidePanel.jsx +260 -0
  44. package/src/ThemeMenuButton.jsx +136 -0
  45. package/src/autosync/server.js +202 -5
  46. package/src/autosync/server.test.js +112 -0
  47. package/src/canvas/__tests__/agent-integration.test.js +593 -0
  48. package/src/canvas/__tests__/helpers/browser.js +95 -0
  49. package/src/canvas/__tests__/helpers/canvas-api.js +129 -0
  50. package/src/canvas/__tests__/helpers/perf.js +118 -0
  51. package/src/canvas/__tests__/helpers/setup.js +176 -0
  52. package/src/canvas/__tests__/helpers/tmux.js +130 -0
  53. package/src/canvas/__tests__/helpers/transcript.js +129 -0
  54. package/src/canvas/__tests__/terminal-integration.test.js +175 -0
  55. package/src/canvas/hot-pool.js +757 -0
  56. package/src/canvas/materializer.js +31 -0
  57. package/src/canvas/materializer.test.js +56 -0
  58. package/src/canvas/selectedWidgets.js +65 -7
  59. package/src/canvas/server.js +1801 -22
  60. package/src/canvas/server.test.js +239 -0
  61. package/src/canvas/terminal-config.js +331 -0
  62. package/src/canvas/terminal-registry.js +38 -0
  63. package/src/canvas/terminal-server.js +1037 -29
  64. package/src/canvas/writeGuard.js +51 -3
  65. package/src/canvasConfig.js +67 -1
  66. package/src/canvasConfig.test.js +79 -1
  67. package/src/cli/agent.js +85 -0
  68. package/src/cli/branch.js +232 -0
  69. package/src/cli/canvasAdd.js +59 -12
  70. package/src/cli/canvasBatch.js +98 -0
  71. package/src/cli/canvasBounds.js +1 -1
  72. package/src/cli/canvasRead.js +1 -1
  73. package/src/cli/canvasUpdate.js +179 -0
  74. package/src/cli/create.js +38 -14
  75. package/src/cli/dev.js +157 -83
  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 +148 -25
  81. package/src/cli/serverUrl.js +8 -3
  82. package/src/cli/sessions.js +131 -5
  83. package/src/cli/setup.js +109 -11
  84. package/src/cli/terminal-commands.js +16 -8
  85. package/src/cli/terminal-messaging.js +231 -0
  86. package/src/cli/terminal-welcome.js +365 -33
  87. package/src/commandActions.js +1 -0
  88. package/src/commandPaletteConfig.js +9 -0
  89. package/src/comments/auth.js +2 -1
  90. package/src/comments/ui/AuthModal.jsx +114 -0
  91. package/src/comments/ui/CommentWindow.jsx +329 -0
  92. package/src/comments/ui/CommentsDrawer.jsx +102 -0
  93. package/src/comments/ui/Composer.jsx +64 -0
  94. package/src/comments/ui/authModal.test.js +1 -1
  95. package/src/comments/ui/commentWindow.js +16 -17
  96. package/src/comments/ui/commentsDrawer.js +25 -26
  97. package/src/comments/ui/composer.js +23 -24
  98. package/src/comments/ui/index.js +2 -3
  99. package/src/configSchema.js +59 -1
  100. package/src/configStore.js +161 -0
  101. package/src/core-ui-colors.css +12 -0
  102. package/src/devtools.js +17 -19
  103. package/src/devtools.test.js +18 -9
  104. package/src/featureFlags.js +12 -5
  105. package/src/fuzzySearch.test.js +10 -0
  106. package/src/index.js +14 -2
  107. package/src/lib/components/ui/alert/alert-action.jsx +11 -0
  108. package/src/lib/components/ui/alert/alert-description.jsx +11 -0
  109. package/src/lib/components/ui/alert/alert-title.jsx +11 -0
  110. package/src/lib/components/ui/alert/alert.jsx +25 -0
  111. package/src/lib/components/ui/alert/index.js +15 -15
  112. package/src/lib/components/ui/avatar/avatar-badge.jsx +22 -0
  113. package/src/lib/components/ui/avatar/avatar-fallback.jsx +18 -0
  114. package/src/lib/components/ui/avatar/avatar-group-count.jsx +19 -0
  115. package/src/lib/components/ui/avatar/avatar-group.jsx +19 -0
  116. package/src/lib/components/ui/avatar/avatar-image.jsx +15 -0
  117. package/src/lib/components/ui/avatar/avatar.jsx +19 -0
  118. package/src/lib/components/ui/avatar/index.js +20 -20
  119. package/src/lib/components/ui/badge/badge.jsx +31 -0
  120. package/src/lib/components/ui/badge/index.js +2 -2
  121. package/src/lib/components/ui/button/button.jsx +100 -0
  122. package/src/lib/components/ui/button/index.js +9 -9
  123. package/src/lib/components/ui/card/card-action.jsx +11 -0
  124. package/src/lib/components/ui/card/card-content.jsx +11 -0
  125. package/src/lib/components/ui/card/card-description.jsx +11 -0
  126. package/src/lib/components/ui/card/card-footer.jsx +11 -0
  127. package/src/lib/components/ui/card/card-header.jsx +19 -0
  128. package/src/lib/components/ui/card/card-title.jsx +11 -0
  129. package/src/lib/components/ui/card/card.jsx +17 -0
  130. package/src/lib/components/ui/card/index.js +23 -23
  131. package/src/lib/components/ui/checkbox/checkbox.jsx +29 -0
  132. package/src/lib/components/ui/checkbox/index.js +5 -5
  133. package/src/lib/components/ui/collapsible/collapsible-content.jsx +7 -0
  134. package/src/lib/components/ui/collapsible/collapsible-trigger.jsx +7 -0
  135. package/src/lib/components/ui/collapsible/collapsible.jsx +7 -0
  136. package/src/lib/components/ui/collapsible/index.js +11 -11
  137. package/src/lib/components/ui/dialog/dialog-close.jsx +7 -0
  138. package/src/lib/components/ui/dialog/dialog-content.jsx +34 -0
  139. package/src/lib/components/ui/dialog/dialog-description.jsx +15 -0
  140. package/src/lib/components/ui/dialog/dialog-footer.jsx +23 -0
  141. package/src/lib/components/ui/dialog/dialog-header.jsx +11 -0
  142. package/src/lib/components/ui/dialog/dialog-overlay.jsx +15 -0
  143. package/src/lib/components/ui/dialog/dialog-portal.jsx +4 -0
  144. package/src/lib/components/ui/dialog/dialog-title.jsx +15 -0
  145. package/src/lib/components/ui/dialog/dialog-trigger.jsx +7 -0
  146. package/src/lib/components/ui/dialog/dialog.jsx +4 -0
  147. package/src/lib/components/ui/dialog/index.js +32 -32
  148. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +8 -0
  149. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +30 -0
  150. package/src/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +22 -0
  151. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +16 -0
  152. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +7 -0
  153. package/src/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +20 -0
  154. package/src/lib/components/ui/dropdown-menu/dropdown-menu-label.jsx +17 -0
  155. package/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +4 -0
  156. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +7 -0
  157. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +29 -0
  158. package/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +15 -0
  159. package/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.jsx +16 -0
  160. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +15 -0
  161. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +23 -0
  162. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +4 -0
  163. package/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +7 -0
  164. package/src/lib/components/ui/dropdown-menu/dropdown-menu.jsx +4 -0
  165. package/src/lib/components/ui/dropdown-menu/index.js +52 -52
  166. package/src/lib/components/ui/input/index.js +5 -5
  167. package/src/lib/components/ui/input/input.jsx +19 -0
  168. package/src/lib/components/ui/label/index.js +5 -5
  169. package/src/lib/components/ui/label/label.jsx +19 -0
  170. package/src/lib/components/ui/panel/index.js +21 -21
  171. package/src/lib/components/ui/panel/panel-body.jsx +11 -0
  172. package/src/lib/components/ui/panel/panel-close.jsx +16 -0
  173. package/src/lib/components/ui/panel/panel-content.jsx +29 -0
  174. package/src/lib/components/ui/panel/panel-footer.jsx +11 -0
  175. package/src/lib/components/ui/panel/panel-header.jsx +11 -0
  176. package/src/lib/components/ui/panel/panel-title.jsx +12 -0
  177. package/src/lib/components/ui/panel/panel.jsx +4 -0
  178. package/src/lib/components/ui/popover/index.js +26 -26
  179. package/src/lib/components/ui/popover/popover-close.jsx +7 -0
  180. package/src/lib/components/ui/popover/popover-content.jsx +22 -0
  181. package/src/lib/components/ui/popover/popover-description.jsx +11 -0
  182. package/src/lib/components/ui/popover/popover-header.jsx +11 -0
  183. package/src/lib/components/ui/popover/popover-portal.jsx +4 -0
  184. package/src/lib/components/ui/popover/popover-title.jsx +11 -0
  185. package/src/lib/components/ui/popover/popover-trigger.jsx +8 -0
  186. package/src/lib/components/ui/popover/popover.jsx +4 -0
  187. package/src/lib/components/ui/searchable-list.jsx +159 -0
  188. package/src/lib/components/ui/select/index.js +35 -35
  189. package/src/lib/components/ui/select/select-content.jsx +30 -0
  190. package/src/lib/components/ui/select/select-group-heading.jsx +17 -0
  191. package/src/lib/components/ui/select/select-group.jsx +15 -0
  192. package/src/lib/components/ui/select/select-item.jsx +26 -0
  193. package/src/lib/components/ui/select/select-label.jsx +11 -0
  194. package/src/lib/components/ui/select/select-portal.jsx +4 -0
  195. package/src/lib/components/ui/select/select-scroll-down-button.jsx +18 -0
  196. package/src/lib/components/ui/select/select-scroll-up-button.jsx +18 -0
  197. package/src/lib/components/ui/select/select-separator.jsx +15 -0
  198. package/src/lib/components/ui/select/select-trigger.jsx +25 -0
  199. package/src/lib/components/ui/select/select.jsx +4 -0
  200. package/src/lib/components/ui/separator/index.js +5 -5
  201. package/src/lib/components/ui/separator/separator.jsx +22 -0
  202. package/src/lib/components/ui/sheet/index.js +32 -32
  203. package/src/lib/components/ui/sheet/sheet-close.jsx +7 -0
  204. package/src/lib/components/ui/sheet/sheet-content.jsx +35 -0
  205. package/src/lib/components/ui/sheet/sheet-description.jsx +15 -0
  206. package/src/lib/components/ui/sheet/sheet-footer.jsx +11 -0
  207. package/src/lib/components/ui/sheet/sheet-header.jsx +11 -0
  208. package/src/lib/components/ui/sheet/sheet-overlay.jsx +15 -0
  209. package/src/lib/components/ui/sheet/sheet-portal.jsx +4 -0
  210. package/src/lib/components/ui/sheet/sheet-title.jsx +15 -0
  211. package/src/lib/components/ui/sheet/sheet-trigger.jsx +7 -0
  212. package/src/lib/components/ui/sheet/sheet.jsx +4 -0
  213. package/src/lib/components/ui/textarea/index.js +5 -5
  214. package/src/lib/components/ui/textarea/textarea.jsx +18 -0
  215. package/src/lib/components/ui/toggle/index.js +6 -9
  216. package/src/lib/components/ui/toggle/toggle.jsx +36 -0
  217. package/src/lib/components/ui/toggle-group/index.js +8 -8
  218. package/src/lib/components/ui/toggle-group/toggle-group-item.jsx +29 -0
  219. package/src/lib/components/ui/toggle-group/toggle-group.jsx +43 -0
  220. package/src/lib/components/ui/tooltip/index.js +3 -3
  221. package/src/lib/components/ui/tooltip/tooltip-content.jsx +21 -0
  222. package/src/lib/components/ui/tooltip/tooltip-trigger.jsx +23 -0
  223. package/src/lib/components/ui/tooltip/tooltip.jsx +11 -0
  224. package/src/lib/components/ui/trigger-button/index.js +3 -3
  225. package/src/lib/components/ui/trigger-button/trigger-button.css +38 -0
  226. package/src/lib/components/ui/trigger-button/trigger-button.jsx +63 -0
  227. package/src/logger/devLogger.js +238 -0
  228. package/src/logger/devLogger.test.js +193 -0
  229. package/src/modes.test.js +4 -4
  230. package/src/mountStoryboardCore.js +123 -27
  231. package/src/paletteProviders.js +3 -0
  232. package/src/paletteProviders.test.js +2 -2
  233. package/src/server/index.js +98 -36
  234. package/src/sidepanel.css +214 -0
  235. package/src/styles/tailwind.css +1 -1
  236. package/src/svelte-plugin-ui/__tests__/ModeSwitch.test.ts +8 -8
  237. package/src/svelte-plugin-ui/__tests__/ToolbarShell.test.ts +11 -10
  238. package/src/svelte-plugin-ui/components/Icon.css +11 -0
  239. package/src/svelte-plugin-ui/components/Icon.jsx +281 -0
  240. package/src/svelte-plugin-ui/components/ModeSwitch.css +90 -0
  241. package/src/svelte-plugin-ui/components/ModeSwitch.jsx +47 -0
  242. package/src/svelte-plugin-ui/components/ToolbarShell.css +80 -0
  243. package/src/svelte-plugin-ui/components/ToolbarShell.jsx +84 -0
  244. package/src/svelte-plugin-ui/components/Viewfinder.css +412 -0
  245. package/src/svelte-plugin-ui/components/Viewfinder.jsx +512 -0
  246. package/src/svelte-plugin-ui/mount.ts +12 -16
  247. package/src/toolRegistry.js +4 -4
  248. package/src/toolbarConfigStore.js +30 -0
  249. package/src/tools/handlers/autosync.js +1 -1
  250. package/src/tools/handlers/canvasAddWidget.js +1 -1
  251. package/src/tools/handlers/canvasAgents.js +19 -0
  252. package/src/tools/handlers/canvasToolbar.js +8 -8
  253. package/src/tools/handlers/commandPalette.js +9 -0
  254. package/src/tools/handlers/comments.js +1 -1
  255. package/src/tools/handlers/create.js +1 -1
  256. package/src/tools/handlers/devtools.js +16 -0
  257. package/src/tools/handlers/devtools.test.js +38 -0
  258. package/src/tools/handlers/flows.js +1 -1
  259. package/src/tools/handlers/hideChrome.js +9 -0
  260. package/src/tools/handlers/paletteTheme.js +35 -0
  261. package/src/tools/handlers/theme.js +1 -1
  262. package/src/tools/registry.js +4 -1
  263. package/src/tools/surfaces/commandList.js +3 -3
  264. package/src/tools/surfaces/mainToolbar.js +3 -3
  265. package/src/tools/surfaces/registry.js +4 -4
  266. package/src/ui/design-modes.ts +2 -2
  267. package/src/ui/viewfinder.ts +1 -1
  268. package/src/vite/server-plugin.js +242 -60
  269. package/src/workshop/features/createCanvas/CreateCanvasForm.jsx +260 -0
  270. package/src/workshop/features/createCanvas/index.js +1 -1
  271. package/src/workshop/features/createFlow/CreateFlowForm.jsx +334 -0
  272. package/src/workshop/features/createFlow/index.js +1 -1
  273. package/src/workshop/features/createPage/CreatePageForm.jsx +304 -0
  274. package/src/workshop/features/createPage/index.js +1 -1
  275. package/src/workshop/features/createPrototype/CreatePrototypeForm.jsx +289 -0
  276. package/src/workshop/features/createPrototype/index.js +1 -1
  277. package/src/workshop/features/createPrototype/server.js +98 -0
  278. package/src/workshop/features/createStory/CreateStoryForm.jsx +208 -0
  279. package/src/workshop/features/createStory/index.js +1 -1
  280. package/src/workshop/ui/WorkshopPanel.jsx +98 -0
  281. package/src/workshop/ui/mount.ts +1 -1
  282. package/src/worktree/port.js +48 -0
  283. package/src/worktree/serverRegistry.js +120 -0
  284. package/toolbar.config.json +93 -42
  285. package/widgets.config.json +580 -12
  286. package/src/ActionMenuButton.svelte +0 -119
  287. package/src/AutosyncMenuButton.svelte +0 -397
  288. package/src/CanvasCreateMenu.svelte +0 -295
  289. package/src/CanvasSnap.svelte +0 -87
  290. package/src/CanvasUndoRedo.svelte +0 -108
  291. package/src/CanvasZoomControl.svelte +0 -111
  292. package/src/CanvasZoomToFit.svelte +0 -52
  293. package/src/CommandMenu.svelte +0 -249
  294. package/src/CommandPalette.svelte +0 -33
  295. package/src/CommentsMenuButton.svelte +0 -53
  296. package/src/CoreUIBar.svelte +0 -847
  297. package/src/CreateMenuButton.svelte +0 -133
  298. package/src/DocPanel.svelte +0 -299
  299. package/src/InspectorPanel.svelte +0 -745
  300. package/src/PwaInstallBanner.svelte +0 -124
  301. package/src/SidePanel.svelte +0 -480
  302. package/src/ThemeMenuButton.svelte +0 -132
  303. package/src/comments/ui/AuthModal.svelte +0 -108
  304. package/src/comments/ui/CommentWindow.svelte +0 -333
  305. package/src/comments/ui/CommentsDrawer.svelte +0 -96
  306. package/src/comments/ui/Composer.svelte +0 -65
  307. package/src/lib/components/ui/alert/alert-action.svelte +0 -19
  308. package/src/lib/components/ui/alert/alert-description.svelte +0 -22
  309. package/src/lib/components/ui/alert/alert-title.svelte +0 -22
  310. package/src/lib/components/ui/alert/alert.svelte +0 -38
  311. package/src/lib/components/ui/avatar/avatar-badge.svelte +0 -25
  312. package/src/lib/components/ui/avatar/avatar-fallback.svelte +0 -20
  313. package/src/lib/components/ui/avatar/avatar-group-count.svelte +0 -22
  314. package/src/lib/components/ui/avatar/avatar-group.svelte +0 -22
  315. package/src/lib/components/ui/avatar/avatar-image.svelte +0 -17
  316. package/src/lib/components/ui/avatar/avatar.svelte +0 -24
  317. package/src/lib/components/ui/badge/badge.svelte +0 -44
  318. package/src/lib/components/ui/button/button.svelte +0 -108
  319. package/src/lib/components/ui/card/card-action.svelte +0 -21
  320. package/src/lib/components/ui/card/card-content.svelte +0 -19
  321. package/src/lib/components/ui/card/card-description.svelte +0 -19
  322. package/src/lib/components/ui/card/card-footer.svelte +0 -18
  323. package/src/lib/components/ui/card/card-header.svelte +0 -21
  324. package/src/lib/components/ui/card/card-title.svelte +0 -14
  325. package/src/lib/components/ui/card/card.svelte +0 -21
  326. package/src/lib/components/ui/checkbox/checkbox.svelte +0 -39
  327. package/src/lib/components/ui/collapsible/collapsible-content.svelte +0 -7
  328. package/src/lib/components/ui/collapsible/collapsible-trigger.svelte +0 -7
  329. package/src/lib/components/ui/collapsible/collapsible.svelte +0 -11
  330. package/src/lib/components/ui/dialog/dialog-close.svelte +0 -11
  331. package/src/lib/components/ui/dialog/dialog-content.svelte +0 -42
  332. package/src/lib/components/ui/dialog/dialog-description.svelte +0 -17
  333. package/src/lib/components/ui/dialog/dialog-footer.svelte +0 -29
  334. package/src/lib/components/ui/dialog/dialog-header.svelte +0 -19
  335. package/src/lib/components/ui/dialog/dialog-overlay.svelte +0 -17
  336. package/src/lib/components/ui/dialog/dialog-portal.svelte +0 -7
  337. package/src/lib/components/ui/dialog/dialog-title.svelte +0 -17
  338. package/src/lib/components/ui/dialog/dialog-trigger.svelte +0 -11
  339. package/src/lib/components/ui/dialog/dialog.svelte +0 -7
  340. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.svelte +0 -16
  341. package/src/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.svelte +0 -40
  342. package/src/lib/components/ui/dropdown-menu/dropdown-menu-content.svelte +0 -27
  343. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.svelte +0 -18
  344. package/src/lib/components/ui/dropdown-menu/dropdown-menu-group.svelte +0 -7
  345. package/src/lib/components/ui/dropdown-menu/dropdown-menu-item.svelte +0 -24
  346. package/src/lib/components/ui/dropdown-menu/dropdown-menu-label.svelte +0 -20
  347. package/src/lib/components/ui/dropdown-menu/dropdown-menu-portal.svelte +0 -7
  348. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.svelte +0 -16
  349. package/src/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.svelte +0 -34
  350. package/src/lib/components/ui/dropdown-menu/dropdown-menu-separator.svelte +0 -17
  351. package/src/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.svelte +0 -19
  352. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.svelte +0 -17
  353. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.svelte +0 -27
  354. package/src/lib/components/ui/dropdown-menu/dropdown-menu-sub.svelte +0 -7
  355. package/src/lib/components/ui/dropdown-menu/dropdown-menu-trigger.svelte +0 -7
  356. package/src/lib/components/ui/dropdown-menu/dropdown-menu.svelte +0 -7
  357. package/src/lib/components/ui/input/input.svelte +0 -40
  358. package/src/lib/components/ui/label/label.svelte +0 -20
  359. package/src/lib/components/ui/panel/panel-body.svelte +0 -13
  360. package/src/lib/components/ui/panel/panel-close.svelte +0 -16
  361. package/src/lib/components/ui/panel/panel-content.svelte +0 -33
  362. package/src/lib/components/ui/panel/panel-footer.svelte +0 -13
  363. package/src/lib/components/ui/panel/panel-header.svelte +0 -16
  364. package/src/lib/components/ui/panel/panel-title.svelte +0 -14
  365. package/src/lib/components/ui/panel/panel.svelte +0 -15
  366. package/src/lib/components/ui/popover/popover-close.svelte +0 -7
  367. package/src/lib/components/ui/popover/popover-content.svelte +0 -27
  368. package/src/lib/components/ui/popover/popover-description.svelte +0 -19
  369. package/src/lib/components/ui/popover/popover-header.svelte +0 -19
  370. package/src/lib/components/ui/popover/popover-portal.svelte +0 -7
  371. package/src/lib/components/ui/popover/popover-title.svelte +0 -19
  372. package/src/lib/components/ui/popover/popover-trigger.svelte +0 -17
  373. package/src/lib/components/ui/popover/popover.svelte +0 -7
  374. package/src/lib/components/ui/select/select-content.svelte +0 -40
  375. package/src/lib/components/ui/select/select-group-heading.svelte +0 -19
  376. package/src/lib/components/ui/select/select-group.svelte +0 -17
  377. package/src/lib/components/ui/select/select-item.svelte +0 -38
  378. package/src/lib/components/ui/select/select-label.svelte +0 -18
  379. package/src/lib/components/ui/select/select-portal.svelte +0 -7
  380. package/src/lib/components/ui/select/select-scroll-down-button.svelte +0 -20
  381. package/src/lib/components/ui/select/select-scroll-up-button.svelte +0 -20
  382. package/src/lib/components/ui/select/select-separator.svelte +0 -17
  383. package/src/lib/components/ui/select/select-trigger.svelte +0 -27
  384. package/src/lib/components/ui/select/select.svelte +0 -11
  385. package/src/lib/components/ui/separator/separator.svelte +0 -23
  386. package/src/lib/components/ui/sheet/sheet-close.svelte +0 -7
  387. package/src/lib/components/ui/sheet/sheet-content.svelte +0 -43
  388. package/src/lib/components/ui/sheet/sheet-description.svelte +0 -17
  389. package/src/lib/components/ui/sheet/sheet-footer.svelte +0 -18
  390. package/src/lib/components/ui/sheet/sheet-header.svelte +0 -19
  391. package/src/lib/components/ui/sheet/sheet-overlay.svelte +0 -17
  392. package/src/lib/components/ui/sheet/sheet-portal.svelte +0 -7
  393. package/src/lib/components/ui/sheet/sheet-title.svelte +0 -17
  394. package/src/lib/components/ui/sheet/sheet-trigger.svelte +0 -7
  395. package/src/lib/components/ui/sheet/sheet.svelte +0 -7
  396. package/src/lib/components/ui/textarea/textarea.svelte +0 -21
  397. package/src/lib/components/ui/toggle/toggle.svelte +0 -45
  398. package/src/lib/components/ui/toggle-group/toggle-group-item.svelte +0 -35
  399. package/src/lib/components/ui/toggle-group/toggle-group.svelte +0 -63
  400. package/src/lib/components/ui/tooltip/tooltip-content.svelte +0 -24
  401. package/src/lib/components/ui/tooltip/tooltip-trigger.svelte +0 -27
  402. package/src/lib/components/ui/tooltip/tooltip.svelte +0 -9
  403. package/src/lib/components/ui/trigger-button/trigger-button.svelte +0 -106
  404. package/src/svelte-plugin-ui/components/Icon.svelte +0 -181
  405. package/src/svelte-plugin-ui/components/ModeSwitch.svelte +0 -121
  406. package/src/svelte-plugin-ui/components/ToolbarShell.svelte +0 -150
  407. package/src/svelte-plugin-ui/components/Viewfinder.svelte +0 -1001
  408. package/src/tools/handlers/docs.js +0 -11
  409. package/src/workshop/features/createCanvas/CreateCanvasForm.svelte +0 -139
  410. package/src/workshop/features/createFlow/CreateFlowForm.svelte +0 -314
  411. package/src/workshop/features/createPage/CreatePageForm.svelte +0 -249
  412. package/src/workshop/features/createPrototype/CreatePrototypeForm.svelte +0 -287
  413. package/src/workshop/features/createStory/CreateStoryForm.svelte +0 -161
  414. package/src/workshop/ui/WorkshopPanel.svelte +0 -97
@@ -0,0 +1,512 @@
1
+ /**
2
+ * Viewfinder — prototype index and flow dashboard.
3
+ *
4
+ * Full-page component that lists prototypes as expandable groups,
5
+ * each showing its flows. Global flows (not belonging to any prototype)
6
+ * appear as an "Other flows" group.
7
+ *
8
+ * Mounted via mountViewfinder() from the viewfinder plugin entry point.
9
+ */
10
+
11
+ import React, { useState, useMemo, useEffect, useCallback } from 'react'
12
+ import './Viewfinder.css'
13
+ import { buildPrototypeIndex } from '../../viewfinder.js'
14
+ import { getLocal, setLocal } from '../../localStorage.js'
15
+ import { Icon } from './Icon.jsx'
16
+
17
+ const VIEW_MODE_KEY = 'viewfinder.viewMode'
18
+ const EXPANDED_KEY = 'viewfinder.expanded'
19
+
20
+ function loadExpanded() {
21
+ const raw = getLocal(EXPANDED_KEY)
22
+ if (!raw) return {}
23
+ try { return JSON.parse(raw) } catch { return {} }
24
+ }
25
+
26
+ function formatName(name) {
27
+ return name
28
+ .split('-')
29
+ .map((w) => w.charAt(0).toUpperCase() + w.slice(1))
30
+ .join(' ')
31
+ }
32
+
33
+ function placeholderSvg(name) {
34
+ const h = (function hashStr(s) {
35
+ let v = 0
36
+ for (let i = 0; i < s.length; i++) v = ((v << 5) - v + s.charCodeAt(i)) | 0
37
+ return Math.abs(v)
38
+ })(name)
39
+
40
+ let rects = ''
41
+ for (let i = 0; i < 12; i++) {
42
+ const s = h * (i + 1)
43
+ const x = (s * 7 + i * 31) % 320
44
+ const y = (s * 13 + i * 17) % 200
45
+ const w = 20 + (s * (i + 3)) % 80
46
+ const ht = 8 + (s * (i + 7)) % 40
47
+ const opacity = 0.06 + ((s * (i + 2)) % 20) / 100
48
+ const fill = i % 3 === 0 ? 'var(--sb--placeholder-accent)' : i % 3 === 1 ? 'var(--sb--placeholder-fg)' : 'var(--sb--placeholder-muted)'
49
+ rects += `<rect x="${x}" y="${y}" width="${w}" height="${ht}" rx="2" fill="${fill}" opacity="${opacity}" />`
50
+ }
51
+
52
+ let lines = ''
53
+ for (let i = 0; i < 6; i++) {
54
+ const s = h * (i + 5)
55
+ const y = 10 + (s % 180)
56
+ lines += `<line x1="0" y1="${y}" x2="320" y2="${y}" stroke="var(--sb--placeholder-grid)" stroke-width="0.5" opacity="0.4" />`
57
+ }
58
+ for (let i = 0; i < 8; i++) {
59
+ const s = h * (i + 9)
60
+ const x = 10 + (s % 300)
61
+ lines += `<line x1="${x}" y1="0" x2="${x}" y2="200" stroke="var(--sb--placeholder-grid)" stroke-width="0.5" opacity="0.3" />`
62
+ }
63
+
64
+ return `<svg viewBox="0 0 320 200" xmlns="http://www.w3.org/2000/svg" aria-hidden="true"><rect width="320" height="200" fill="var(--sb--placeholder-bg)" />${lines}${rects}</svg>`
65
+ }
66
+
67
+ /* ── Author block ── */
68
+ function AuthorBlock({ author, gitAuthor }) {
69
+ if (author) {
70
+ const authors = Array.isArray(author) ? author : [author]
71
+ return (
72
+ <div className="author">
73
+ <span className="authorAvatars">
74
+ {authors.map((a) => (
75
+ <img key={a} src={`https://github.com/${a}.png?size=48`} alt={a} className="authorAvatar" />
76
+ ))}
77
+ </span>
78
+ <span className="authorName">{authors.join(', ')}</span>
79
+ </div>
80
+ )
81
+ }
82
+ if (gitAuthor) {
83
+ return <p className="authorPlain">{gitAuthor}</p>
84
+ }
85
+ return null
86
+ }
87
+
88
+ /* ── Proto entry ── */
89
+ function ProtoEntry({ proto, isExpanded, toggle, withBase, showThumbnails }) {
90
+ if (proto.isExternal) {
91
+ return (
92
+ <section className="protoGroup">
93
+ <a className="listItem" href={proto.externalUrl} target="_blank" rel="noopener noreferrer">
94
+ <div className="cardBody">
95
+ <p className="protoName">
96
+ {proto.icon && <span className="protoIcon">{proto.icon}</span>}
97
+ {proto.name}
98
+ <span className="externalBadge">
99
+ <Icon size={12} color="var(--fgColor-muted)" name="primer/link-external" offsetY={-2} />
100
+ external
101
+ </span>
102
+ </p>
103
+ {proto.description && <p className="protoDesc">{proto.description}</p>}
104
+ <AuthorBlock author={proto.author} gitAuthor={proto.gitAuthor} />
105
+ </div>
106
+ </a>
107
+ </section>
108
+ )
109
+ }
110
+
111
+ if (proto.hideFlows && proto.flows.length === 1) {
112
+ return (
113
+ <section className="protoGroup">
114
+ <a className="listItem" href={withBase(proto.flows[0].route)}>
115
+ <div className="cardBody">
116
+ <p className={`protoName${proto.dirName === '__global__' ? ' otherflows' : ''}`}>
117
+ {proto.icon && <span className="protoIcon">{proto.icon}</span>}
118
+ {proto.name}
119
+ </p>
120
+ {proto.description && <p className="protoDesc">{proto.description}</p>}
121
+ <AuthorBlock author={proto.author} gitAuthor={proto.gitAuthor} />
122
+ </div>
123
+ </a>
124
+ </section>
125
+ )
126
+ }
127
+
128
+ if (proto.flows.length > 0) {
129
+ const expanded = isExpanded(proto.dirName)
130
+ return (
131
+ <section className="protoGroup">
132
+ <button
133
+ className="listItem protoHeader"
134
+ onClick={() => toggle(proto.dirName)}
135
+ aria-expanded={expanded}
136
+ >
137
+ <div className="cardBody">
138
+ <p className={`protoName${proto.dirName === '__global__' ? ' otherflows' : ''}`}>
139
+ {proto.icon && <span className="protoIcon">{proto.icon}</span>}
140
+ {proto.name}
141
+ <span className="protoChevron">
142
+ {expanded
143
+ ? <Icon size={12} color="var(--fgColor-disabled)" name="primer/chevron-down" offsetY={-3} offsetX={2} />
144
+ : <Icon size={12} color="var(--fgColor-disabled)" name="primer/chevron-right" offsetY={-3} offsetX={2} />
145
+ }
146
+ </span>
147
+ </p>
148
+ {proto.description && <p className="protoDesc">{proto.description}</p>}
149
+ <AuthorBlock author={proto.author} gitAuthor={proto.gitAuthor} />
150
+ </div>
151
+ </button>
152
+
153
+ {!(proto.hideFlows && proto.flows.length === 1) && expanded && proto.flows.length > 0 && (
154
+ <div className="flowList">
155
+ {proto.flows.map((flow) => (
156
+ <a key={flow.key} href={withBase(flow.route)} className="listItem flowItem">
157
+ {showThumbnails && (
158
+ <div className="thumbnail" dangerouslySetInnerHTML={{ __html: placeholderSvg(flow.key) }} />
159
+ )}
160
+ <div className="cardBody">
161
+ <p className="protoName">{flow.meta?.title || formatName(flow.name)}</p>
162
+ {flow.meta?.description && <p className="flowDesc">{flow.meta.description}</p>}
163
+ </div>
164
+ </a>
165
+ ))}
166
+ </div>
167
+ )}
168
+ </section>
169
+ )
170
+ }
171
+
172
+ // Prototype with no flows — navigates directly
173
+ return (
174
+ <section className="protoGroup">
175
+ <a className="listItem" href={withBase(`/${proto.dirName}`)}>
176
+ <div className="cardBody">
177
+ <p className={`protoName${proto.dirName === '__global__' ? ' otherflows' : ''}`}>
178
+ {proto.icon && <span className="protoIcon">{proto.icon}</span>}
179
+ {proto.name}
180
+ </p>
181
+ {proto.description && <p className="protoDesc">{proto.description}</p>}
182
+ <AuthorBlock author={proto.author} gitAuthor={proto.gitAuthor} />
183
+ </div>
184
+ </a>
185
+ </section>
186
+ )
187
+ }
188
+
189
+ /* ── Canvas entry ── */
190
+ function CanvasEntry({ canvas, withBase }) {
191
+ const authors = canvas.author
192
+ ? (Array.isArray(canvas.author) ? canvas.author : [canvas.author])
193
+ : null
194
+
195
+ return (
196
+ <section className="protoGroup">
197
+ <a className="listItem" href={withBase(canvas.route)}>
198
+ <div className="cardBody">
199
+ <p className="protoName">
200
+ <span className="protoIcon">{canvas.icon || ''}</span>
201
+ {canvas.name}
202
+ </p>
203
+ {canvas.description && <p className="protoDesc">{canvas.description}</p>}
204
+ {authors ? (
205
+ <div className="author">
206
+ <span className="authorAvatars">
207
+ {authors.map((a) => (
208
+ <img key={a} src={`https://github.com/${a}.png?size=48`} alt={a} className="authorAvatar" />
209
+ ))}
210
+ </span>
211
+ <span className="authorName">{authors.join(', ')}</span>
212
+ </div>
213
+ ) : canvas.gitAuthor ? (
214
+ <p className="authorPlain">{canvas.gitAuthor}</p>
215
+ ) : null}
216
+ </div>
217
+ </a>
218
+ </section>
219
+ )
220
+ }
221
+
222
+ /* ── Folder section ── */
223
+ function FolderSection({ folder, isExpanded, toggle, renderItems, itemKey = 'prototypes' }) {
224
+ const key = `folder:${folder.dirName}`
225
+ const expanded = isExpanded(key)
226
+ const items = folder[itemKey] || []
227
+
228
+ return (
229
+ <section className={`folderGroup${expanded ? ' folderGroupOpen' : ''}`}>
230
+ <button
231
+ className="folderHeader"
232
+ onClick={() => toggle(key)}
233
+ aria-expanded={expanded}
234
+ >
235
+ <p className="folderName">
236
+ <span>
237
+ {expanded
238
+ ? <Icon size={20} offsetY={-1.5} name="folder-open" color="#54aeff" />
239
+ : <Icon size={20} offsetY={-1.5} name="folder" color="#54aeff" />
240
+ }
241
+ </span>
242
+ {folder.name}
243
+ </p>
244
+ {folder.description && <p className="folderDesc">{folder.description}</p>}
245
+ </button>
246
+ {expanded && items.length > 0 && (
247
+ <div className="folderContent">
248
+ {renderItems(items)}
249
+ </div>
250
+ )}
251
+ </section>
252
+ )
253
+ }
254
+
255
+ /* ── Main Viewfinder component ── */
256
+ export function Viewfinder({
257
+ title = 'Storyboard',
258
+ subtitle = '',
259
+ basePath = '/',
260
+ knownRoutes = [],
261
+ showThumbnails = false,
262
+ hideDefaultFlow = false,
263
+ }) {
264
+ const prototypeIndex = useMemo(() => buildPrototypeIndex(knownRoutes), [knownRoutes])
265
+
266
+ const globalFlows = useMemo(() => {
267
+ return hideDefaultFlow
268
+ ? prototypeIndex.globalFlows.filter((f) => f.key !== 'default')
269
+ : prototypeIndex.globalFlows
270
+ }, [prototypeIndex, hideDefaultFlow])
271
+
272
+ const ungroupedProtos = prototypeIndex.prototypes
273
+ const folders = prototypeIndex.folders || []
274
+
275
+ const otherFlows = useMemo(() => {
276
+ if (globalFlows.length === 0) return null
277
+ return {
278
+ name: 'Other flows',
279
+ dirName: '__global__',
280
+ description: null,
281
+ author: null,
282
+ gitAuthor: null,
283
+ lastModified: null,
284
+ icon: null,
285
+ team: null,
286
+ tags: null,
287
+ flows: globalFlows,
288
+ }
289
+ }, [globalFlows])
290
+
291
+ const totalProtos = ungroupedProtos.length + folders.reduce((sum, f) => sum + f.prototypes.length, 0)
292
+
293
+ // Sorting
294
+ const [sortBy, setSortBy] = useState('updated')
295
+ const sortedProtos = prototypeIndex.sorted?.[sortBy]?.prototypes ?? ungroupedProtos
296
+ const sortedFolders = prototypeIndex.sorted?.[sortBy]?.folders ?? folders
297
+
298
+ // Canvases
299
+ const ungroupedCanvases = prototypeIndex.canvases || []
300
+ const sortedCanvases = prototypeIndex.sorted?.[sortBy]?.canvases ?? ungroupedCanvases
301
+ const totalCanvases = ungroupedCanvases.length + folders.reduce((sum, f) => sum + (f.canvases?.length || 0), 0)
302
+
303
+ // View mode
304
+ const [viewMode, setViewMode] = useState(() =>
305
+ getLocal(VIEW_MODE_KEY) === 'canvases' ? 'canvases' : 'prototypes'
306
+ )
307
+
308
+ useEffect(() => {
309
+ setLocal(VIEW_MODE_KEY, viewMode)
310
+ }, [viewMode])
311
+
312
+ // Canvas folders
313
+ const canvasFolders = useMemo(() => {
314
+ const src = prototypeIndex.sorted?.[sortBy]?.folders ?? folders
315
+ return src
316
+ .filter((f) => f.canvases && f.canvases.length > 0)
317
+ .map((f) => ({ ...f, prototypes: [], canvases: f.canvases }))
318
+ }, [prototypeIndex, sortBy, folders])
319
+
320
+ // Proto-only folders
321
+ const protoOnlyFolders = useMemo(() => {
322
+ const src = prototypeIndex.sorted?.[sortBy]?.folders ?? folders
323
+ return src
324
+ .filter((f) => f.prototypes.length > 0)
325
+ .map((f) => ({ ...f, canvases: [] }))
326
+ }, [prototypeIndex, sortBy, folders])
327
+
328
+ // Expanded state
329
+ const [expanded, setExpanded] = useState(loadExpanded)
330
+
331
+ const isExpandedFn = useCallback((dirName) => expanded[dirName] ?? false, [expanded])
332
+
333
+ const toggleFn = useCallback((dirName) => {
334
+ setExpanded((prev) => {
335
+ const next = { ...prev, [dirName]: !(prev[dirName] ?? false) }
336
+ setLocal(EXPANDED_KEY, JSON.stringify(next))
337
+ return next
338
+ })
339
+ }, [])
340
+
341
+ // URL helpers
342
+ const withBase = useCallback((route) => {
343
+ const normalizedRoute = route.startsWith('/') ? route : `/${route}`
344
+ const normalizedBase = (basePath || '/').replace(/\/+$/, '')
345
+ if (!normalizedBase || normalizedBase === '/') return normalizedRoute
346
+ return `${normalizedBase}${normalizedRoute}`.replace(/\/+/g, '/')
347
+ }, [basePath])
348
+
349
+ // Branch switching
350
+ const branches = (typeof window !== 'undefined' && Array.isArray(window.__SB_BRANCHES__))
351
+ ? window.__SB_BRANCHES__
352
+ : null
353
+
354
+ const branchBasePath = (basePath || '/storyboard-source/').replace(/\/branch--[^/]*\/$/, '/')
355
+ const currentBranch = useMemo(() => {
356
+ const m = (basePath || '').match(/\/branch--([^/]+)\/?$/)
357
+ return m ? m[1] : 'main'
358
+ }, [basePath])
359
+
360
+ function handleBranchChange(e) {
361
+ const folder = e.target.value
362
+ if (folder) {
363
+ window.location.href = `${branchBasePath}${folder}/`
364
+ }
365
+ }
366
+
367
+ return (
368
+ <div className="container">
369
+ <header className="header">
370
+ <div className="headerTop">
371
+ <div>
372
+ <h1 className="title">{title}</h1>
373
+ {subtitle && <p className="subtitle">{subtitle}</p>}
374
+ </div>
375
+ </div>
376
+ <div className="controlsRow">
377
+ {/* View mode toggle */}
378
+ <div className="sortToggle">
379
+ <button
380
+ className={`sortButton${viewMode === 'prototypes' ? ' sortButtonActive' : ''}`}
381
+ onClick={() => setViewMode('prototypes')}
382
+ >
383
+ Prototypes
384
+ </button>
385
+ <button
386
+ className={`sortButton${viewMode === 'canvases' ? ' sortButtonActive' : ''}`}
387
+ onClick={() => setViewMode('canvases')}
388
+ >
389
+ Canvas
390
+ </button>
391
+ </div>
392
+ {/* Sort toggle — hidden for now */}
393
+ <div className="sortToggle" style={{ display: 'none' }}>
394
+ <button
395
+ className={`sortButton${sortBy === 'updated' ? ' sortButtonActive' : ''}`}
396
+ onClick={() => setSortBy('updated')}
397
+ >
398
+ <Icon name="primer/clock" size={14} color="var(--fgColor-muted)" />
399
+ Last updated
400
+ </button>
401
+ <button
402
+ className={`sortButton${sortBy === 'title' ? ' sortButtonActive' : ''}`}
403
+ onClick={() => setSortBy('title')}
404
+ >
405
+ <Icon name="primer/sort-asc" size={14} color="var(--fgColor-muted)" />
406
+ Title A–Z
407
+ </button>
408
+ </div>
409
+ {branches && branches.length > 0 && (
410
+ <div className="branchDropdown">
411
+ <span className="branchIcon">
412
+ <Icon size={16} color="var(--fgColor-muted)" offsetY={-1} offsetX={2} name="primer/git-branch" />
413
+ </span>
414
+ <select
415
+ className="branchSelect"
416
+ onChange={handleBranchChange}
417
+ aria-label="Switch branch"
418
+ defaultValue=""
419
+ >
420
+ <option value="" disabled>{currentBranch}</option>
421
+ {branches.map((b) => (
422
+ <option key={b.folder} value={b.folder}>{b.branch}</option>
423
+ ))}
424
+ </select>
425
+ </div>
426
+ )}
427
+ </div>
428
+ </header>
429
+
430
+ {viewMode === 'prototypes' && totalProtos === 0 && folders.length === 0 ? (
431
+ <p className="empty">No flows found. Add a <code>*.flow.json</code> file to get started.</p>
432
+ ) : viewMode === 'canvases' && totalCanvases === 0 ? (
433
+ <p className="empty">No canvases found. Add a <code>*.canvas.jsonl</code> file to get started.</p>
434
+ ) : (
435
+ <div className="list">
436
+ {viewMode === 'prototypes' ? (
437
+ <>
438
+ {protoOnlyFolders.map((folder) => (
439
+ <FolderSection
440
+ key={folder.dirName}
441
+ folder={folder}
442
+ isExpanded={isExpandedFn}
443
+ toggle={toggleFn}
444
+ renderItems={(protos) =>
445
+ protos.map((proto) => (
446
+ <ProtoEntry
447
+ key={proto.dirName}
448
+ proto={proto}
449
+ isExpanded={isExpandedFn}
450
+ toggle={toggleFn}
451
+ withBase={withBase}
452
+ showThumbnails={showThumbnails}
453
+ />
454
+ ))
455
+ }
456
+ />
457
+ ))}
458
+
459
+ {sortedProtos.map((proto) => (
460
+ <ProtoEntry
461
+ key={proto.dirName}
462
+ proto={proto}
463
+ isExpanded={isExpandedFn}
464
+ toggle={toggleFn}
465
+ withBase={withBase}
466
+ showThumbnails={showThumbnails}
467
+ />
468
+ ))}
469
+
470
+ {otherFlows && (
471
+ <ProtoEntry
472
+ proto={otherFlows}
473
+ isExpanded={isExpandedFn}
474
+ toggle={toggleFn}
475
+ withBase={withBase}
476
+ showThumbnails={showThumbnails}
477
+ />
478
+ )}
479
+ </>
480
+ ) : (
481
+ <>
482
+ <div className="canvasWarning">
483
+ <Icon size={14} name="primer/alert" color="#9a6700" offsetY={-1} />
484
+ <span>Canvas is an experimental feature. Use with caution.</span>
485
+ </div>
486
+ {canvasFolders.map((folder) => (
487
+ <FolderSection
488
+ key={folder.dirName}
489
+ folder={folder}
490
+ isExpanded={isExpandedFn}
491
+ toggle={toggleFn}
492
+ itemKey="canvases"
493
+ renderItems={(canvases) =>
494
+ canvases.map((canvas) => (
495
+ <CanvasEntry key={canvas.dirName} canvas={canvas} withBase={withBase} />
496
+ ))
497
+ }
498
+ />
499
+ ))}
500
+
501
+ {sortedCanvases.map((canvas) => (
502
+ <CanvasEntry key={canvas.dirName} canvas={canvas} withBase={withBase} />
503
+ ))}
504
+ </>
505
+ )}
506
+ </div>
507
+ )}
508
+ </div>
509
+ )
510
+ }
511
+
512
+ export default Viewfinder
@@ -1,19 +1,20 @@
1
1
  /**
2
- * Generic mount utility for Svelte plugin components.
2
+ * Generic mount utility for React plugin components.
3
3
  *
4
- * Provides a framework-agnostic way to mount Svelte components into any
4
+ * Provides a framework-agnostic way to mount React components into any
5
5
  * DOM target. Handles shared style injection (idempotent) and returns
6
6
  * a destroy handle for cleanup.
7
7
  *
8
8
  * Usage:
9
9
  * import { mountSveltePlugin } from '@dfosco/storyboard-core/svelte-plugin-ui'
10
- * import MyComponent from './MyComponent.svelte'
10
+ * import MyComponent from './MyComponent.jsx'
11
11
  *
12
12
  * const handle = mountSveltePlugin(document.body, MyComponent, { someProp: 'value' })
13
13
  * // later: handle.destroy()
14
14
  */
15
15
 
16
- import { mount, unmount, type Component } from 'svelte'
16
+ import { createElement, type ComponentType } from 'react'
17
+ import { createRoot, type Root } from 'react-dom/client'
17
18
 
18
19
  const STYLE_ID = 'sb-svelte-ui-styles'
19
20
 
@@ -69,28 +70,25 @@ export function injectStyles(): Promise<void> {
69
70
  export interface PluginHandle {
70
71
  /** Remove the component and its wrapper from the DOM */
71
72
  destroy: () => void
72
- /** The wrapper element containing the Svelte component */
73
+ /** The wrapper element containing the React component */
73
74
  element: HTMLElement
74
75
  /** Resolves when all styles are loaded and the component is ready to show */
75
76
  ready: Promise<void>
76
77
  }
77
78
 
78
79
  /**
79
- * Mount a Svelte component into a DOM target.
80
+ * Mount a React component into a DOM target.
80
81
  *
81
82
  * @param target - DOM element to append the component wrapper to
82
- * @param ComponentClass - Svelte component constructor
83
+ * @param ComponentClass - React component
83
84
  * @param props - Props to pass to the component
84
85
  * @returns Handle with destroy() method and a `ready` promise
85
86
  */
86
87
  export function mountSveltePlugin<T extends Record<string, unknown>>(
87
88
  target: HTMLElement,
88
- ComponentClass: Component<T>,
89
+ ComponentClass: ComponentType<T>,
89
90
  props?: T,
90
91
  ): PluginHandle {
91
- // Fire-and-forget — styles are either already present (Vite bundle)
92
- // or will load in parallel. The `ready` promise on PluginHandle can
93
- // be awaited by callers that need to wait for CSS.
94
92
  const stylesReady = injectStyles()
95
93
 
96
94
  const wrapper = document.createElement('div')
@@ -98,16 +96,14 @@ export function mountSveltePlugin<T extends Record<string, unknown>>(
98
96
  wrapper.style.display = 'contents'
99
97
  target.appendChild(wrapper)
100
98
 
101
- const instance = mount(ComponentClass, {
102
- target: wrapper,
103
- props: props ?? ({} as T),
104
- })
99
+ const root: Root = createRoot(wrapper)
100
+ root.render(createElement(ComponentClass, props ?? ({} as T)))
105
101
 
106
102
  return {
107
103
  element: wrapper,
108
104
  ready: stylesReady,
109
105
  destroy() {
110
- unmount(instance)
106
+ root.unmount()
111
107
  wrapper.remove()
112
108
  },
113
109
  }
@@ -2,8 +2,8 @@
2
2
  * Tool Registry — config-driven state management for toolbar tools.
3
3
  *
4
4
  * Every tool is declared in toolbar.config.json under the `tools` key.
5
- * Each tool specifies a `toolbar` target (main-toolbar, secondary-toolbar,
6
- * command-list) and a `render` type (button, menu, sidepanel, submenu, link).
5
+ * Each tool specifies a `toolbar` target (command-toolbar, canvas-toolbar,
6
+ * command-palette) and a `render` type (button, menu, sidepanel, submenu, link).
7
7
  *
8
8
  * Code modules register themselves via registerToolModule() to provide
9
9
  * component, handler, setup, and guard functions.
@@ -58,7 +58,7 @@ export function initToolRegistry(config) {
58
58
  *
59
59
  * @param {string} id - Tool id (matches key in toolbar.config.json tools)
60
60
  * @param {object} mod
61
- * @param {Function} [mod.component] - () => import('./SomeComponent.svelte')
61
+ * @param {Function} [mod.component] - () => import('./SomeComponent.jsx')
62
62
  * @param {object|Function} [mod.handler] - Command action handler
63
63
  * @param {Function} [mod.setup] - async (ctx) => void — called once at mount
64
64
  * @param {Function} [mod.guard] - async (ctx) => boolean — return false to hide
@@ -117,7 +117,7 @@ export function getToolModule(id) {
117
117
  /**
118
118
  * Get tools for a specific toolbar target, filtered by mode and visibility.
119
119
  *
120
- * @param {string} toolbar - "main-toolbar" | "secondary-toolbar" | "command-list"
120
+ * @param {string} toolbar - "command-toolbar" | "canvas-toolbar" | "command-palette"
121
121
  * @param {string} mode - Current mode name
122
122
  * @param {object} [options]
123
123
  * @param {boolean} [options.isLocalDev] - Whether running in local dev
@@ -25,6 +25,9 @@ let _mergedConfig = {}
25
25
  /** @type {Set<Function>} */
26
26
  const _listeners = new Set()
27
27
 
28
+ /** @type {object|null} Client-repo toolbar overrides (set by virtual module before mount) */
29
+ let _clientOverrides = null
30
+
28
31
  let _snapshotVersion = 0
29
32
 
30
33
  // ---------------------------------------------------------------------------
@@ -122,6 +125,32 @@ function _recompute() {
122
125
  }
123
126
  }
124
127
 
128
+ // ---------------------------------------------------------------------------
129
+ // Client overrides (set by Vite data plugin before mountStoryboardCore runs)
130
+ // ---------------------------------------------------------------------------
131
+
132
+ /**
133
+ * Store client-repo toolbar overrides from a root toolbar.config.json.
134
+ * Called from the generated virtual module at import time.
135
+ *
136
+ * @param {object} config - Client toolbar config (tools, surfaces, etc.)
137
+ */
138
+ export function setClientToolbarOverrides(config) {
139
+ _clientOverrides = config
140
+ }
141
+
142
+ /**
143
+ * Consume and clear pending client overrides.
144
+ * Called once by mountStoryboardCore during toolbar config init.
145
+ *
146
+ * @returns {object|null}
147
+ */
148
+ export function consumeClientToolbarOverrides() {
149
+ const overrides = _clientOverrides
150
+ _clientOverrides = null
151
+ return overrides
152
+ }
153
+
125
154
  // ---------------------------------------------------------------------------
126
155
  // Test helpers
127
156
  // ---------------------------------------------------------------------------
@@ -129,6 +158,7 @@ function _recompute() {
129
158
  export function _resetToolbarConfig() {
130
159
  _baseConfig = {}
131
160
  _prototypeConfig = null
161
+ _clientOverrides = null
132
162
  _mergedConfig = {}
133
163
  _listeners.clear()
134
164
  _snapshotVersion = 0
@@ -7,6 +7,6 @@
7
7
  export const id = 'autosync'
8
8
 
9
9
  export async function component() {
10
- const mod = await import('../../AutosyncMenuButton.svelte')
10
+ const mod = await import('../../AutosyncMenuButton.jsx')
11
11
  return mod.default
12
12
  }
@@ -6,6 +6,6 @@
6
6
  export const id = 'canvas-add-widget'
7
7
 
8
8
  export async function component() {
9
- const mod = await import('../../CanvasCreateMenu.svelte')
9
+ const mod = await import('../../CanvasCreateMenu.jsx')
10
10
  return mod.default
11
11
  }