@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,13 +1,14 @@
1
1
  /**
2
- * Comment window — Svelte popup that shows a comment thread with replies and reactions.
2
+ * Comment window — React popup that shows a comment thread with replies and reactions.
3
3
  *
4
4
  * Opens when clicking a comment pin. Shows comment body, author, replies,
5
5
  * reply input, reactions, and supports drag-to-move.
6
6
  * Styled with Tachyons + sb-* custom classes for light/dark mode support.
7
7
  */
8
8
 
9
- import { mount, unmount } from 'svelte'
10
- import CommentWindowComponent from './CommentWindow.svelte'
9
+ import { createElement } from 'react'
10
+ import { createRoot } from 'react-dom/client'
11
+ import CommentWindowComponent from './CommentWindow.jsx'
11
12
  import { getCachedUser } from '../auth.js'
12
13
  import { saveDraft, replyDraftKey } from '../commentDrafts.js'
13
14
  import './comment-layout.css'
@@ -50,17 +51,17 @@ export function showCommentWindow(container, comment, discussion, callbacks = {}
50
51
 
51
52
  container.appendChild(win)
52
53
 
53
- let instance = null
54
+ let root = null
54
55
 
55
56
  function destroy() {
56
- // Save reply draft from DOM before Svelte unmounts
57
+ // Save reply draft from DOM before React unmounts
57
58
  const textarea = win.querySelector('textarea[placeholder="Reply…"]')
58
59
  const val = textarea?.value?.trim()
59
60
  if (val) {
60
61
  saveDraft(replyDraftKey(comment.id), { type: 'reply', text: textarea.value })
61
62
  }
62
63
 
63
- if (instance) { unmount(instance); instance = null }
64
+ if (root) { root.unmount(); root = null }
64
65
  win.remove()
65
66
  if (activeWindow?.el === win) activeWindow = null
66
67
  const currentUrl = new URL(window.location.href)
@@ -69,17 +70,15 @@ export function showCommentWindow(container, comment, discussion, callbacks = {}
69
70
  callbacks.onClose?.()
70
71
  }
71
72
 
72
- instance = mount(CommentWindowComponent, {
73
- target: win,
74
- props: {
75
- comment,
76
- discussion,
77
- user,
78
- winEl: win,
79
- onClose: destroy,
80
- onMove: () => callbacks.onMove?.(),
81
- },
82
- })
73
+ root = createRoot(win)
74
+ root.render(createElement(CommentWindowComponent, {
75
+ comment,
76
+ discussion,
77
+ user,
78
+ winEl: win,
79
+ onClose: destroy,
80
+ onMove: () => callbacks.onMove?.(),
81
+ }))
83
82
 
84
83
  // Adjust position to keep window within viewport
85
84
  requestAnimationFrame(() => {
@@ -1,13 +1,14 @@
1
1
  /**
2
- * Comments drawer — Svelte right-side panel listing all comments across all routes.
2
+ * Comments drawer — React right-side panel listing all comments across all routes.
3
3
  *
4
4
  * Opened from the DevTools "See all comments" menu item.
5
5
  * Clicking a comment navigates to its route and opens it.
6
6
  * Styled with Tachyons + sb-* custom classes for light/dark mode support.
7
7
  */
8
8
 
9
- import { mount, unmount } from 'svelte'
10
- import CommentsDrawerComponent from './CommentsDrawer.svelte'
9
+ import { createElement } from 'react'
10
+ import { createRoot } from 'react-dom/client'
11
+ import CommentsDrawerComponent from './CommentsDrawer.jsx'
11
12
  import { isAuthenticated } from '../auth.js'
12
13
  import { setCommentMode } from '../commentMode.js'
13
14
  import './comment-layout.css'
@@ -32,7 +33,7 @@ export async function openCommentsDrawer() {
32
33
  document.body.appendChild(backdrop)
33
34
  document.body.appendChild(drawer)
34
35
 
35
- let instance = null
36
+ let root = null
36
37
 
37
38
  function onKeyDown(e) {
38
39
  if (e.key === 'Escape') {
@@ -44,28 +45,26 @@ export async function openCommentsDrawer() {
44
45
  }
45
46
  window.addEventListener('keydown', onKeyDown, true)
46
47
 
47
- instance = mount(CommentsDrawerComponent, {
48
- target: drawer,
49
- props: {
50
- onClose: closeCommentsDrawer,
51
- onNavigate: (route, commentId) => {
52
- closeCommentsDrawer()
53
- if (window.location.pathname !== route) {
54
- const navUrl = new URL(window.location.href)
55
- navUrl.pathname = route
56
- navUrl.searchParams.set('comment', commentId)
57
- window.location.href = navUrl.toString()
58
- } else {
59
- const navUrl = new URL(window.location.href)
60
- navUrl.searchParams.set('comment', commentId)
61
- window.history.replaceState(null, '', navUrl.toString())
62
- setCommentMode(true)
63
- }
64
- },
48
+ root = createRoot(drawer)
49
+ root.render(createElement(CommentsDrawerComponent, {
50
+ onClose: closeCommentsDrawer,
51
+ onNavigate: (route, commentId) => {
52
+ closeCommentsDrawer()
53
+ if (window.location.pathname !== route) {
54
+ const navUrl = new URL(window.location.href)
55
+ navUrl.pathname = route
56
+ navUrl.searchParams.set('comment', commentId)
57
+ window.location.href = navUrl.toString()
58
+ } else {
59
+ const navUrl = new URL(window.location.href)
60
+ navUrl.searchParams.set('comment', commentId)
61
+ window.history.replaceState(null, '', navUrl.toString())
62
+ setCommentMode(true)
63
+ }
65
64
  },
66
- })
65
+ }))
67
66
 
68
- activeDrawer = { backdrop, drawer, instance, onKeyDown }
67
+ activeDrawer = { backdrop, drawer, root, onKeyDown }
69
68
  }
70
69
 
71
70
  /**
@@ -76,8 +75,8 @@ export function closeCommentsDrawer() {
76
75
  if (activeDrawer.onKeyDown) {
77
76
  window.removeEventListener('keydown', activeDrawer.onKeyDown, true)
78
77
  }
79
- if (activeDrawer.instance) {
80
- unmount(activeDrawer.instance)
78
+ if (activeDrawer.root) {
79
+ activeDrawer.root.unmount()
81
80
  }
82
81
  activeDrawer.backdrop.remove()
83
82
  activeDrawer.drawer.remove()
@@ -1,12 +1,13 @@
1
1
  /**
2
- * Comment composer — Svelte inline text input that appears at click position.
2
+ * Comment composer — React inline text input that appears at click position.
3
3
  *
4
4
  * Positioned absolutely within the comment overlay. Submits to the comments API.
5
5
  * Styled with Tachyons + sb-* custom classes for light/dark mode support.
6
6
  */
7
7
 
8
- import { mount, unmount } from 'svelte'
9
- import ComposerComponent from './Composer.svelte'
8
+ import { createElement } from 'react'
9
+ import { createRoot } from 'react-dom/client'
10
+ import ComposerComponent from './Composer.jsx'
10
11
  import { getCachedUser } from '../auth.js'
11
12
  import { saveDraft, clearDraft, composerDraftKey } from '../commentDrafts.js'
12
13
  import './comment-layout.css'
@@ -36,7 +37,7 @@ export function showComposer(container, xPct, yPct, route, callbacks = {}) {
36
37
  // Stop click from propagating (prevents placing another composer)
37
38
  composer.addEventListener('click', (e) => e.stopPropagation())
38
39
 
39
- let instance = null
40
+ let root = null
40
41
  let skipDraftSave = false
41
42
  const draftKey = composerDraftKey(route)
42
43
 
@@ -84,7 +85,7 @@ export function showComposer(container, xPct, yPct, route, callbacks = {}) {
84
85
  }
85
86
 
86
87
  function destroy() {
87
- // Save draft from DOM before Svelte unmounts (reactive state is unreliable after unmount)
88
+ // Save draft from DOM before React unmounts
88
89
  if (!skipDraftSave) {
89
90
  const textarea = composer.querySelector('textarea')
90
91
  const val = textarea?.value?.trim()
@@ -94,7 +95,7 @@ export function showComposer(container, xPct, yPct, route, callbacks = {}) {
94
95
  }
95
96
 
96
97
  window.removeEventListener('keydown', onEscape, true)
97
- if (instance) { unmount(instance); instance = null }
98
+ if (root) { root.unmount(); root = null }
98
99
  composer.remove()
99
100
  }
100
101
 
@@ -109,25 +110,23 @@ export function showComposer(container, xPct, yPct, route, callbacks = {}) {
109
110
  }
110
111
  window.addEventListener('keydown', onEscape, true)
111
112
 
112
- instance = mount(ComposerComponent, {
113
- target: composer,
114
- props: {
115
- user,
116
- route,
117
- onCancel: () => {
118
- clearDraft(draftKey)
119
- skipDraftSave = true
120
- destroy()
121
- callbacks.onCancel?.()
122
- },
123
- onSubmit: (text) => {
124
- clearDraft(draftKey)
125
- skipDraftSave = true
126
- destroy()
127
- callbacks.onSubmitOptimistic?.(text, pos.x, pos.y)
128
- },
113
+ root = createRoot(composer)
114
+ root.render(createElement(ComposerComponent, {
115
+ user,
116
+ route,
117
+ onCancel: () => {
118
+ clearDraft(draftKey)
119
+ skipDraftSave = true
120
+ destroy()
121
+ callbacks.onCancel?.()
122
+ },
123
+ onSubmit: (text) => {
124
+ clearDraft(draftKey)
125
+ skipDraftSave = true
126
+ destroy()
127
+ callbacks.onSubmitOptimistic?.(text, pos.x, pos.y)
129
128
  },
130
- })
129
+ }))
131
130
 
132
131
  applyPosition()
133
132
  // Auto-focus textarea after DOM is ready
@@ -1,8 +1,7 @@
1
1
  /**
2
- * Svelte UI exports for the comments system.
2
+ * React UI exports for the comments system.
3
3
  *
4
- * These require a Svelte peer dependency (^5.0.0).
5
- * Import from '@dfosco/storyboard-core/comments/svelte'.
4
+ * Import from '@dfosco/storyboard-core/comments/ui'.
6
5
  */
7
6
 
8
7
  // Mount
@@ -15,10 +15,57 @@
15
15
  * @property {Record<string, string>} [propsMap] — static props merged into widget props
16
16
  */
17
17
 
18
+ /**
19
+ * @typedef {object} CanvasTerminalConfig
20
+ * @property {boolean} [resizable] — whether terminal widgets can be resized (default false)
21
+ * @property {number} [defaultWidth] — default width for new terminal widgets
22
+ * @property {number} [defaultHeight] — default height for new terminal widgets
23
+ * @property {number} [fontSize] — terminal font size
24
+ * @property {string} [fontFamily] — terminal font family
25
+ * @property {string} [prompt] — shell prompt string
26
+ * @property {string|null} [startupCommand] — skip welcome screen: "copilot", "shell", or a custom command. null shows welcome.
27
+ * @property {object|null} [defaultStartupSequence] — sequence of steps to run after terminal opens
28
+ */
29
+
30
+ /**
31
+ * @typedef {object} CanvasZoomConfig
32
+ * @property {number} min — minimum zoom percentage (default 10)
33
+ * @property {number} max — maximum zoom percentage (default 250)
34
+ * @property {number} step — zoom increment/decrement step (default 10)
35
+ */
36
+
18
37
  /**
19
38
  * @typedef {object} CanvasConfig
20
39
  * @property {PasteRule[]} pasteRules — URL→widget conversion rules (evaluated in order, first match wins)
21
40
  * @property {{ embedBehavior: string, ghGuard: string }} github — GitHub-specific embed settings
41
+ * @property {CanvasTerminalConfig} [terminal] — terminal widget settings
42
+ * @property {Record<string, CanvasAgentConfig>} [agents] — per-agent overrides
43
+ * @property {CanvasZoomConfig} [zoom] — zoom min/max/step settings
44
+ */
45
+
46
+ /**
47
+ * @typedef {object} CanvasAgentConfig
48
+ * @property {string} [label] — display label
49
+ * @property {string} [icon] — icon name
50
+ * @property {string} [startupCommand] — command to run on startup
51
+ * @property {string} [resumeCommand] — command to browse/resume existing sessions (e.g. "copilot --resume")
52
+ * @property {string} [postStartup] — command sent after agent readiness (e.g. "/allow-all on")
53
+ * @property {string} [readinessSignal] — tmux pane text that signals the agent is ready (fragile, prefer readinessFile)
54
+ * @property {boolean} [readinessFile] — use a file-based SessionStart hook for readiness (writes --settings with hook, polls for signal file)
55
+ * @property {boolean} [resizable] — override terminal resizability for this agent
56
+ * @property {number} [defaultWidth] — override default width
57
+ * @property {number} [defaultHeight] — override default height
58
+ */
59
+
60
+ /**
61
+ * @typedef {object} HotPoolConfig
62
+ * @property {boolean} [enabled] — enable/disable all pools (default: true)
63
+ * @property {boolean} [verbose] — log to Vite terminal (default: false)
64
+ * @property {number} [default_pool_size] — default baseline per pool (default: 1)
65
+ * @property {number} [default_max_pool_size] — default surge cap per pool (default: 3)
66
+ * @property {boolean} [load_balancer] — enable auto-scaling (default: true)
67
+ * @property {number} [load_balancer_cooldown_mins] — minutes idle before scale-down (default: 10)
68
+ * @property {Record<string, { pool_size?: number, max_pool_size?: number }>} [pools] — per-pool overrides (terminal, prompt, copilot, claude, codex)
22
69
  */
23
70
 
24
71
  /**
@@ -63,7 +110,7 @@
63
110
  * @property {boolean} enabled — master toggle for customer mode
64
111
  * @property {boolean} hideChrome — hides all toolbars (except canvas tools), branchbar, cmd+k, cmd+.
65
112
  * @property {boolean} hideHomepage — removes the storyboard homepage (leaves empty page)
66
- * @property {string} protoHomepage — internal /path that replaces homepage; redirects from / and /viewfinder
113
+ * @property {string} protoHomepage — internal /path that replaces homepage; redirects from / and /workspace
67
114
  */
68
115
 
69
116
  /**
@@ -79,6 +126,7 @@
79
126
  * @property {{ hide?: string[] }} [ui]
80
127
  * @property {object} [toolbar]
81
128
  * @property {CanvasConfig} [canvas]
129
+ * @property {HotPoolConfig} [hotPool]
82
130
  * @property {CommandPaletteConfig} [commandPalette]
83
131
  * @property {CustomerModeConfig} [customerMode]
84
132
  */
@@ -114,6 +162,16 @@ export const configDefaults = {
114
162
  embedBehavior: 'link-preview', // "link-preview" | "rich-embed"
115
163
  ghGuard: 'copy', // "copy" | "link" | "off"
116
164
  },
165
+ zoom: {
166
+ min: 10,
167
+ max: 250,
168
+ step: 10,
169
+ },
170
+ terminal: {
171
+ resizable: false,
172
+ defaultWidth: 800,
173
+ defaultHeight: 450,
174
+ },
117
175
  },
118
176
  commandPalette: {
119
177
  providers: ['prototypes', 'flows', 'canvases', 'pages'],
@@ -0,0 +1,161 @@
1
+ /**
2
+ * Unified Config Store — single source of truth for all storyboard configuration.
3
+ *
4
+ * Replaces the scattered init/store pattern with one reactive config object.
5
+ * Domain-specific stores (toolbarConfigStore, canvasConfig, etc.) become thin
6
+ * wrappers that delegate here — zero consumer changes needed.
7
+ *
8
+ * Override priority (lowest → highest):
9
+ * core defaults → widgets → paste → toolbar → commandPalette → storyboard.config.json → prototype
10
+ *
11
+ * Framework-agnostic (zero npm dependencies).
12
+ */
13
+
14
+ import { deepMerge } from './loader.js'
15
+
16
+ // ---------------------------------------------------------------------------
17
+ // Internal state
18
+ // ---------------------------------------------------------------------------
19
+
20
+ /** @type {object} Full merged config (set once at startup) */
21
+ let _baseConfig = {}
22
+
23
+ /** @type {Record<string, object>} Domain → prototype-level overrides */
24
+ let _prototypeOverrides = {}
25
+
26
+ /** @type {object} Final merged config (base + prototype overrides) */
27
+ let _mergedConfig = {}
28
+
29
+ /** @type {Set<Function>} */
30
+ const _listeners = new Set()
31
+
32
+ let _snapshotVersion = 0
33
+
34
+ // ---------------------------------------------------------------------------
35
+ // Initialization
36
+ // ---------------------------------------------------------------------------
37
+
38
+ /**
39
+ * Seed the unified config with the pre-merged config object.
40
+ * Called once at app startup (from the virtual module or mountStoryboardCore).
41
+ *
42
+ * @param {object} config - The unified config with all domains
43
+ */
44
+ export function initConfig(config) {
45
+ _baseConfig = config || {}
46
+ _prototypeOverrides = {}
47
+ _recompute()
48
+ }
49
+
50
+ // ---------------------------------------------------------------------------
51
+ // Domain access
52
+ // ---------------------------------------------------------------------------
53
+
54
+ /**
55
+ * Get the full merged config or a specific domain slice.
56
+ *
57
+ * @param {string} [domain] - Optional domain key (e.g. 'toolbar', 'canvas')
58
+ * @returns {object}
59
+ */
60
+ export function getConfig(domain) {
61
+ if (!domain) return _mergedConfig
62
+ return _mergedConfig[domain] || {}
63
+ }
64
+
65
+ // ---------------------------------------------------------------------------
66
+ // Prototype overrides
67
+ // ---------------------------------------------------------------------------
68
+
69
+ /**
70
+ * Set overrides for a specific domain from a prototype-local config file.
71
+ * Called on route change when entering a prototype with local config.
72
+ *
73
+ * @param {string} domain - Config domain (e.g. 'toolbar', 'widgets')
74
+ * @param {object} overrides - Prototype-level overrides to deep-merge
75
+ */
76
+ export function setOverrides(domain, overrides) {
77
+ if (!overrides) return
78
+ _prototypeOverrides[domain] = overrides
79
+ _recompute()
80
+ }
81
+
82
+ /**
83
+ * Clear overrides for a specific domain.
84
+ *
85
+ * @param {string} domain
86
+ */
87
+ export function clearOverrides(domain) {
88
+ if (!_prototypeOverrides[domain]) return
89
+ delete _prototypeOverrides[domain]
90
+ _recompute()
91
+ }
92
+
93
+ /**
94
+ * Clear all prototype overrides (e.g. when leaving a prototype).
95
+ */
96
+ export function clearAllOverrides() {
97
+ if (Object.keys(_prototypeOverrides).length === 0) return
98
+ _prototypeOverrides = {}
99
+ _recompute()
100
+ }
101
+
102
+ // ---------------------------------------------------------------------------
103
+ // Reactivity
104
+ // ---------------------------------------------------------------------------
105
+
106
+ /**
107
+ * Subscribe to config changes. Compatible with Svelte stores.
108
+ *
109
+ * @param {Function} callback - Called with the full merged config
110
+ * @returns {Function} Unsubscribe
111
+ */
112
+ export function subscribeToConfig(callback) {
113
+ _listeners.add(callback)
114
+ callback(_mergedConfig)
115
+ return () => _listeners.delete(callback)
116
+ }
117
+
118
+ /**
119
+ * Snapshot version for useSyncExternalStore.
120
+ *
121
+ * @returns {string}
122
+ */
123
+ export function getConfigSnapshot() {
124
+ return String(_snapshotVersion)
125
+ }
126
+
127
+ // ---------------------------------------------------------------------------
128
+ // Internal
129
+ // ---------------------------------------------------------------------------
130
+
131
+ function _recompute() {
132
+ if (Object.keys(_prototypeOverrides).length === 0) {
133
+ _mergedConfig = _baseConfig
134
+ } else {
135
+ const result = { ..._baseConfig }
136
+ for (const [domain, overrides] of Object.entries(_prototypeOverrides)) {
137
+ result[domain] = result[domain]
138
+ ? deepMerge(result[domain], overrides)
139
+ : overrides
140
+ }
141
+ _mergedConfig = result
142
+ }
143
+ _snapshotVersion++
144
+ for (const cb of _listeners) {
145
+ try { cb(_mergedConfig) } catch (err) {
146
+ console.error('[storyboard] Error in config subscriber:', err)
147
+ }
148
+ }
149
+ }
150
+
151
+ // ---------------------------------------------------------------------------
152
+ // Test helpers
153
+ // ---------------------------------------------------------------------------
154
+
155
+ export function _resetConfig() {
156
+ _baseConfig = {}
157
+ _prototypeOverrides = {}
158
+ _mergedConfig = {}
159
+ _listeners.clear()
160
+ _snapshotVersion = 0
161
+ }
@@ -64,6 +64,12 @@
64
64
  --fgColor-muted: #656d76;
65
65
  --borderColor-default: #d1d9e0;
66
66
  --bgColor-neutral-muted: rgba(175, 184, 193, 0.2);
67
+
68
+ /* Slate palette tokens — used by trigger buttons and canvas toolbar */
69
+ --color-slate-100: oklch(96.8% .007 247.896);
70
+ --color-slate-300: oklch(86.9% .022 252.894);
71
+ --color-slate-400: oklch(70.4% .04 256.788);
72
+ --color-slate-600: oklch(44.6% .043 257.281);
67
73
  }
68
74
 
69
75
  /* Dark tokens — applied when toolbar syncs with a dark theme.
@@ -114,4 +120,10 @@
114
120
  --fgColor-muted: #8b949e;
115
121
  --borderColor-default: #30363d;
116
122
  --bgColor-neutral-muted: rgba(110, 118, 129, 0.2);
123
+
124
+ /* Slate palette tokens — dark equivalents */
125
+ --color-slate-100: oklch(20.8% .042 265.755);
126
+ --color-slate-300: oklch(29.3% .042 264.531);
127
+ --color-slate-400: oklch(44.6% .043 257.281);
128
+ --color-slate-600: oklch(70.4% .04 256.788);
117
129
  }
package/src/devtools.js CHANGED
@@ -1,17 +1,17 @@
1
1
  /**
2
- * Storyboard Core UI Bar — Svelte-based floating toolbar.
2
+ * Storyboard Core UI Bar — React-based floating toolbar.
3
3
  *
4
- * Mounts the CoreUIBar Svelte component into the DOM.
4
+ * Mounts the CoreUIBar React component into the DOM.
5
5
  * Contains the command menu and mode-specific buttons (workshop, etc.).
6
- * Uses dynamic import() for the Svelte component to avoid
7
- * breaking non-Svelte test environments.
6
+ * Uses dynamic import() for the React component to avoid
7
+ * breaking non-React test environments.
8
8
  *
9
9
  * Usage:
10
10
  * import { mountDevTools } from '@dfosco/storyboard-core'
11
11
  * mountDevTools() // call once at app startup
12
12
  */
13
13
 
14
- let instance = null
14
+ let root = null
15
15
  let wrapper = null
16
16
  let skipLink = null
17
17
 
@@ -35,8 +35,9 @@ export async function mountDevTools(options = {}) {
35
35
  // Skip mounting entirely when loaded inside a prototype embed iframe
36
36
  if (typeof window !== 'undefined' && new URLSearchParams(window.location.search).has('_sb_embed')) return
37
37
 
38
- const { mount } = await import('svelte')
39
- const { default: CoreUIBar } = await import('./CoreUIBar.svelte')
38
+ const { createElement } = await import('react')
39
+ const { createRoot } = await import('react-dom/client')
40
+ const { default: CoreUIBar } = await import('./CoreUIBar.jsx')
40
41
 
41
42
  // Inject skip link as the first child of <body> so it is the
42
43
  // first element in the tab order, regardless of where CoreUIBar
@@ -108,24 +109,21 @@ export async function mountDevTools(options = {}) {
108
109
  wrapper.id = 'sb-core-ui'
109
110
  container.appendChild(wrapper)
110
111
 
111
- instance = mount(CoreUIBar, {
112
- target: wrapper,
113
- props: {
114
- basePath,
115
- toolbarConfig: options.toolbarConfig,
116
- customHandlers: options.customHandlers,
117
- },
118
- })
112
+ root = createRoot(wrapper)
113
+ root.render(createElement(CoreUIBar, {
114
+ basePath,
115
+ toolbarConfig: options.toolbarConfig,
116
+ customHandlers: options.customHandlers,
117
+ }))
119
118
  }
120
119
 
121
120
  /**
122
121
  * Remove the Core UI Bar from the DOM.
123
122
  */
124
123
  export async function unmountDevTools() {
125
- if (instance) {
126
- const { unmount } = await import('svelte')
127
- unmount(instance)
128
- instance = null
124
+ if (root) {
125
+ root.unmount()
126
+ root = null
129
127
  }
130
128
  if (wrapper) { wrapper.remove(); wrapper = null }
131
129
  if (skipLink) { skipLink.remove(); skipLink = null }
@@ -1,16 +1,23 @@
1
1
  /**
2
2
  * Tests for devtools.js — command menu mount lifecycle.
3
- * Mocks the Svelte component to avoid jsdom lifecycle issues.
3
+ * Mocks the React component to avoid jsdom lifecycle issues.
4
4
  */
5
5
 
6
6
  import { vi } from 'vitest'
7
7
 
8
- vi.mock('svelte', () => ({
9
- mount: vi.fn(() => ({})),
10
- unmount: vi.fn(),
8
+ const mockRender = vi.fn()
9
+ const mockUnmount = vi.fn()
10
+ const mockCreateRoot = vi.fn(() => ({ render: mockRender, unmount: mockUnmount }))
11
+
12
+ vi.mock('react', () => ({
13
+ createElement: vi.fn((comp, props) => ({ comp, props })),
14
+ }))
15
+
16
+ vi.mock('react-dom/client', () => ({
17
+ createRoot: mockCreateRoot,
11
18
  }))
12
19
 
13
- vi.mock('./CommandMenu.svelte', () => ({ default: {} }))
20
+ vi.mock('./CommandMenu.jsx', () => ({ default: () => null }))
14
21
 
15
22
  describe('mountDevTools', () => {
16
23
  let mountDevTools, unmountDevTools
@@ -19,11 +26,13 @@ describe('mountDevTools', () => {
19
26
  document.body.innerHTML = ''
20
27
  vi.resetModules()
21
28
 
22
- vi.doMock('svelte', () => ({
23
- mount: vi.fn(() => ({})),
24
- unmount: vi.fn(),
29
+ vi.doMock('react', () => ({
30
+ createElement: vi.fn((comp, props) => ({ comp, props })),
31
+ }))
32
+ vi.doMock('react-dom/client', () => ({
33
+ createRoot: vi.fn(() => ({ render: vi.fn(), unmount: vi.fn() })),
25
34
  }))
26
- vi.doMock('./CommandMenu.svelte', () => ({ default: {} }))
35
+ vi.doMock('./CommandMenu.jsx', () => ({ default: () => null }))
27
36
 
28
37
  const mod = await import('./devtools.js')
29
38
  mountDevTools = mod.mountDevTools