@dfosco/storyboard 0.5.0-alpha.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 (592) hide show
  1. package/commandpalette.config.json +152 -0
  2. package/dist/storyboard-ui.css +1 -0
  3. package/dist/storyboard-ui.js +21328 -0
  4. package/dist/storyboard-ui.js.map +1 -0
  5. package/dist/tailwind.css +2 -0
  6. package/dist/tiny-canvas.css +1 -0
  7. package/dist/tiny-canvas.js +389 -0
  8. package/package.json +121 -0
  9. package/paste.config.json +67 -0
  10. package/scaffold/AGENTS.md +432 -0
  11. package/scaffold/agents/prompt-agent.agent.md +181 -0
  12. package/scaffold/agents/terminal-agent.agent.md +351 -0
  13. package/scaffold/codex/config.toml +246 -0
  14. package/scaffold/deploy.yml +103 -0
  15. package/scaffold/githooks/pre-push +114 -0
  16. package/scaffold/gitignore +64 -0
  17. package/scaffold/manifest.json +56 -0
  18. package/scaffold/preview.yml +181 -0
  19. package/scaffold/scripts/link.sh +26 -0
  20. package/scaffold/scripts/unlink.sh +10 -0
  21. package/scaffold/skills/agent-browser/SKILL.md +260 -0
  22. package/scaffold/skills/canvas/SKILL.md +364 -0
  23. package/scaffold/skills/create/SKILL.md +501 -0
  24. package/scaffold/skills/ship/SKILL.md +237 -0
  25. package/scaffold/skills/storyboard/SKILL.md +360 -0
  26. package/scaffold/skills/update-storyboard/SKILL.md +16 -0
  27. package/scaffold/skills/update-storyboard/update-storyboard-packages.sh +26 -0
  28. package/scaffold/skills/vitest/GENERATION.md +5 -0
  29. package/scaffold/skills/vitest/SKILL.md +52 -0
  30. package/scaffold/skills/vitest/references/advanced-environments.md +264 -0
  31. package/scaffold/skills/vitest/references/advanced-projects.md +300 -0
  32. package/scaffold/skills/vitest/references/advanced-type-testing.md +237 -0
  33. package/scaffold/skills/vitest/references/advanced-vi.md +249 -0
  34. package/scaffold/skills/vitest/references/core-cli.md +166 -0
  35. package/scaffold/skills/vitest/references/core-config.md +174 -0
  36. package/scaffold/skills/vitest/references/core-describe.md +193 -0
  37. package/scaffold/skills/vitest/references/core-expect.md +219 -0
  38. package/scaffold/skills/vitest/references/core-hooks.md +244 -0
  39. package/scaffold/skills/vitest/references/core-test-api.md +233 -0
  40. package/scaffold/skills/vitest/references/features-concurrency.md +250 -0
  41. package/scaffold/skills/vitest/references/features-context.md +238 -0
  42. package/scaffold/skills/vitest/references/features-coverage.md +207 -0
  43. package/scaffold/skills/vitest/references/features-filtering.md +211 -0
  44. package/scaffold/skills/vitest/references/features-mocking.md +265 -0
  45. package/scaffold/skills/vitest/references/features-snapshots.md +207 -0
  46. package/scaffold/skills/worktree/SKILL.md +93 -0
  47. package/scaffold/storyboard.config.json +44 -0
  48. package/src/canvas/Canvas.jsx +78 -0
  49. package/src/canvas/Draggable.jsx +235 -0
  50. package/src/canvas/index.d.ts +41 -0
  51. package/src/canvas/index.js +6 -0
  52. package/src/canvas/style.css +118 -0
  53. package/src/canvas/useResetCanvas.js +17 -0
  54. package/src/canvas/utils.js +136 -0
  55. package/src/core/assets/fonts/IoskeleyMono-Bold.woff2 +0 -0
  56. package/src/core/assets/fonts/IoskeleyMono-Italic.woff2 +0 -0
  57. package/src/core/assets/fonts/IoskeleyMono-Medium.woff2 +0 -0
  58. package/src/core/assets/fonts/IoskeleyMono-Regular.woff2 +0 -0
  59. package/src/core/assets/fonts/IoskeleyMono-SemiBold.woff2 +0 -0
  60. package/src/core/autosync/server.js +714 -0
  61. package/src/core/autosync/server.test.js +158 -0
  62. package/src/core/canvas/__tests__/agent-integration.test.js +596 -0
  63. package/src/core/canvas/__tests__/helpers/browser.js +95 -0
  64. package/src/core/canvas/__tests__/helpers/canvas-api.js +129 -0
  65. package/src/core/canvas/__tests__/helpers/perf.js +118 -0
  66. package/src/core/canvas/__tests__/helpers/setup.js +176 -0
  67. package/src/core/canvas/__tests__/helpers/tmux.js +130 -0
  68. package/src/core/canvas/__tests__/helpers/transcript.js +132 -0
  69. package/src/core/canvas/__tests__/terminal-integration.test.js +177 -0
  70. package/src/core/canvas/collision.js +292 -0
  71. package/src/core/canvas/collision.test.js +371 -0
  72. package/src/core/canvas/compact.js +83 -0
  73. package/src/core/canvas/deriveCanvasId.test.js +40 -0
  74. package/src/core/canvas/githubEmbeds.js +527 -0
  75. package/src/core/canvas/githubEmbeds.test.js +302 -0
  76. package/src/core/canvas/hot-pool.js +766 -0
  77. package/src/core/canvas/identity.js +107 -0
  78. package/src/core/canvas/identity.test.js +100 -0
  79. package/src/core/canvas/materializer.js +259 -0
  80. package/src/core/canvas/materializer.test.js +356 -0
  81. package/src/core/canvas/selectedWidgets.js +270 -0
  82. package/src/core/canvas/selectedWidgets.test.js +321 -0
  83. package/src/core/canvas/server.js +3134 -0
  84. package/src/core/canvas/server.test.js +379 -0
  85. package/src/core/canvas/terminal-config.js +330 -0
  86. package/src/core/canvas/terminal-registry.js +465 -0
  87. package/src/core/canvas/terminal-server.js +1436 -0
  88. package/src/core/canvas/writeGuard.js +53 -0
  89. package/src/core/cli/agent.js +85 -0
  90. package/src/core/cli/branch.js +386 -0
  91. package/src/core/cli/canvasAdd.js +241 -0
  92. package/src/core/cli/canvasBatch.js +98 -0
  93. package/src/core/cli/canvasBounds.js +160 -0
  94. package/src/core/cli/canvasRead.js +236 -0
  95. package/src/core/cli/canvasUpdate.js +179 -0
  96. package/src/core/cli/code.js +67 -0
  97. package/src/core/cli/compact.js +62 -0
  98. package/src/core/cli/create.js +674 -0
  99. package/src/core/cli/dev-helpers.js +53 -0
  100. package/src/core/cli/dev-helpers.test.js +53 -0
  101. package/src/core/cli/dev.js +430 -0
  102. package/src/core/cli/exit.js +38 -0
  103. package/src/core/cli/flags.js +174 -0
  104. package/src/core/cli/flags.test.js +155 -0
  105. package/src/core/cli/index.js +233 -0
  106. package/src/core/cli/intro.js +37 -0
  107. package/src/core/cli/proxy.js +319 -0
  108. package/src/core/cli/proxy.test.js +63 -0
  109. package/src/core/cli/schemas.js +223 -0
  110. package/src/core/cli/server.js +192 -0
  111. package/src/core/cli/serverUrl.js +61 -0
  112. package/src/core/cli/sessions.js +459 -0
  113. package/src/core/cli/setup.js +404 -0
  114. package/src/core/cli/terminal-commands.js +287 -0
  115. package/src/core/cli/terminal-messaging.js +231 -0
  116. package/src/core/cli/terminal-welcome.js +515 -0
  117. package/src/core/cli/updateVersion.js +124 -0
  118. package/src/core/comments/api.js +284 -0
  119. package/src/core/comments/api.test.js +282 -0
  120. package/src/core/comments/auth.js +151 -0
  121. package/src/core/comments/auth.test.js +167 -0
  122. package/src/core/comments/commentCache.js +109 -0
  123. package/src/core/comments/commentCache.test.js +48 -0
  124. package/src/core/comments/commentDrafts.js +68 -0
  125. package/src/core/comments/commentMode.js +63 -0
  126. package/src/core/comments/commentMode.test.js +90 -0
  127. package/src/core/comments/config.js +47 -0
  128. package/src/core/comments/config.test.js +77 -0
  129. package/src/core/comments/graphql.js +65 -0
  130. package/src/core/comments/graphql.test.js +95 -0
  131. package/src/core/comments/index.js +42 -0
  132. package/src/core/comments/metadata.js +52 -0
  133. package/src/core/comments/metadata.test.js +110 -0
  134. package/src/core/comments/queries.js +245 -0
  135. package/src/core/comments/ui/AuthModal.jsx +114 -0
  136. package/src/core/comments/ui/CommentOverlay.js +52 -0
  137. package/src/core/comments/ui/CommentWindow.jsx +329 -0
  138. package/src/core/comments/ui/CommentsDrawer.jsx +102 -0
  139. package/src/core/comments/ui/Composer.jsx +64 -0
  140. package/src/core/comments/ui/authModal.js +66 -0
  141. package/src/core/comments/ui/authModal.test.js +76 -0
  142. package/src/core/comments/ui/comment-cursor-dark.svg +1 -0
  143. package/src/core/comments/ui/comment-cursor.svg +1 -0
  144. package/src/core/comments/ui/comment-layout.css +142 -0
  145. package/src/core/comments/ui/commentWindow.js +121 -0
  146. package/src/core/comments/ui/comments.css +242 -0
  147. package/src/core/comments/ui/commentsDrawer.js +84 -0
  148. package/src/core/comments/ui/composer.js +136 -0
  149. package/src/core/comments/ui/index.js +14 -0
  150. package/src/core/comments/ui/mount.js +687 -0
  151. package/src/core/comments/ui/mount.test.js +336 -0
  152. package/src/core/data/dotPath.js +53 -0
  153. package/src/core/data/dotPath.test.js +114 -0
  154. package/src/core/data/loader.js +409 -0
  155. package/src/core/data/loader.test.js +599 -0
  156. package/src/core/data/viewfinder.js +363 -0
  157. package/src/core/data/viewfinder.test.js +456 -0
  158. package/src/core/devtools/devtools-consumer.js +28 -0
  159. package/src/core/devtools/devtools.js +144 -0
  160. package/src/core/devtools/devtools.test.js +75 -0
  161. package/src/core/devtools/sceneDebug.js +112 -0
  162. package/src/core/devtools/sceneDebug.test.js +141 -0
  163. package/src/core/index.js +124 -0
  164. package/src/core/inspector/fiberWalker.js +239 -0
  165. package/src/core/inspector/highlighter.js +275 -0
  166. package/src/core/inspector/mouseMode.js +259 -0
  167. package/src/core/lib/components/ui/alert/alert-action.jsx +11 -0
  168. package/src/core/lib/components/ui/alert/alert-description.jsx +11 -0
  169. package/src/core/lib/components/ui/alert/alert-title.jsx +11 -0
  170. package/src/core/lib/components/ui/alert/alert.jsx +25 -0
  171. package/src/core/lib/components/ui/alert/index.js +17 -0
  172. package/src/core/lib/components/ui/avatar/avatar-badge.jsx +22 -0
  173. package/src/core/lib/components/ui/avatar/avatar-fallback.jsx +18 -0
  174. package/src/core/lib/components/ui/avatar/avatar-group-count.jsx +19 -0
  175. package/src/core/lib/components/ui/avatar/avatar-group.jsx +19 -0
  176. package/src/core/lib/components/ui/avatar/avatar-image.jsx +15 -0
  177. package/src/core/lib/components/ui/avatar/avatar.jsx +19 -0
  178. package/src/core/lib/components/ui/avatar/index.js +22 -0
  179. package/src/core/lib/components/ui/badge/badge.jsx +31 -0
  180. package/src/core/lib/components/ui/badge/index.js +2 -0
  181. package/src/core/lib/components/ui/button/button.jsx +100 -0
  182. package/src/core/lib/components/ui/button/index.js +12 -0
  183. package/src/core/lib/components/ui/card/card-action.jsx +11 -0
  184. package/src/core/lib/components/ui/card/card-content.jsx +11 -0
  185. package/src/core/lib/components/ui/card/card-description.jsx +11 -0
  186. package/src/core/lib/components/ui/card/card-footer.jsx +11 -0
  187. package/src/core/lib/components/ui/card/card-header.jsx +19 -0
  188. package/src/core/lib/components/ui/card/card-title.jsx +11 -0
  189. package/src/core/lib/components/ui/card/card.jsx +17 -0
  190. package/src/core/lib/components/ui/card/index.js +25 -0
  191. package/src/core/lib/components/ui/checkbox/checkbox.jsx +29 -0
  192. package/src/core/lib/components/ui/checkbox/index.js +6 -0
  193. package/src/core/lib/components/ui/collapsible/collapsible-content.jsx +7 -0
  194. package/src/core/lib/components/ui/collapsible/collapsible-trigger.jsx +7 -0
  195. package/src/core/lib/components/ui/collapsible/collapsible.jsx +7 -0
  196. package/src/core/lib/components/ui/collapsible/index.js +13 -0
  197. package/src/core/lib/components/ui/dialog/dialog-close.jsx +7 -0
  198. package/src/core/lib/components/ui/dialog/dialog-content.jsx +34 -0
  199. package/src/core/lib/components/ui/dialog/dialog-description.jsx +15 -0
  200. package/src/core/lib/components/ui/dialog/dialog-footer.jsx +23 -0
  201. package/src/core/lib/components/ui/dialog/dialog-header.jsx +11 -0
  202. package/src/core/lib/components/ui/dialog/dialog-overlay.jsx +15 -0
  203. package/src/core/lib/components/ui/dialog/dialog-portal.jsx +4 -0
  204. package/src/core/lib/components/ui/dialog/dialog-title.jsx +15 -0
  205. package/src/core/lib/components/ui/dialog/dialog-trigger.jsx +7 -0
  206. package/src/core/lib/components/ui/dialog/dialog.jsx +4 -0
  207. package/src/core/lib/components/ui/dialog/index.js +34 -0
  208. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +8 -0
  209. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +30 -0
  210. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +22 -0
  211. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +16 -0
  212. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +7 -0
  213. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +20 -0
  214. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-label.jsx +17 -0
  215. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +4 -0
  216. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +7 -0
  217. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +29 -0
  218. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +15 -0
  219. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-shortcut.jsx +16 -0
  220. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +15 -0
  221. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +23 -0
  222. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +4 -0
  223. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +7 -0
  224. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu.jsx +4 -0
  225. package/src/core/lib/components/ui/dropdown-menu/index.js +54 -0
  226. package/src/core/lib/components/ui/input/index.js +7 -0
  227. package/src/core/lib/components/ui/input/input.jsx +19 -0
  228. package/src/core/lib/components/ui/label/index.js +7 -0
  229. package/src/core/lib/components/ui/label/label.jsx +19 -0
  230. package/src/core/lib/components/ui/panel/index.js +24 -0
  231. package/src/core/lib/components/ui/panel/panel-body.jsx +11 -0
  232. package/src/core/lib/components/ui/panel/panel-close.jsx +16 -0
  233. package/src/core/lib/components/ui/panel/panel-content.jsx +29 -0
  234. package/src/core/lib/components/ui/panel/panel-footer.jsx +11 -0
  235. package/src/core/lib/components/ui/panel/panel-header.jsx +11 -0
  236. package/src/core/lib/components/ui/panel/panel-title.jsx +12 -0
  237. package/src/core/lib/components/ui/panel/panel.jsx +4 -0
  238. package/src/core/lib/components/ui/popover/index.js +28 -0
  239. package/src/core/lib/components/ui/popover/popover-close.jsx +7 -0
  240. package/src/core/lib/components/ui/popover/popover-content.jsx +22 -0
  241. package/src/core/lib/components/ui/popover/popover-description.jsx +11 -0
  242. package/src/core/lib/components/ui/popover/popover-header.jsx +11 -0
  243. package/src/core/lib/components/ui/popover/popover-portal.jsx +4 -0
  244. package/src/core/lib/components/ui/popover/popover-title.jsx +11 -0
  245. package/src/core/lib/components/ui/popover/popover-trigger.jsx +8 -0
  246. package/src/core/lib/components/ui/popover/popover.jsx +4 -0
  247. package/src/core/lib/components/ui/searchable-list.jsx +160 -0
  248. package/src/core/lib/components/ui/select/index.js +37 -0
  249. package/src/core/lib/components/ui/select/select-content.jsx +30 -0
  250. package/src/core/lib/components/ui/select/select-group-heading.jsx +17 -0
  251. package/src/core/lib/components/ui/select/select-group.jsx +15 -0
  252. package/src/core/lib/components/ui/select/select-item.jsx +26 -0
  253. package/src/core/lib/components/ui/select/select-label.jsx +11 -0
  254. package/src/core/lib/components/ui/select/select-portal.jsx +4 -0
  255. package/src/core/lib/components/ui/select/select-scroll-down-button.jsx +18 -0
  256. package/src/core/lib/components/ui/select/select-scroll-up-button.jsx +18 -0
  257. package/src/core/lib/components/ui/select/select-separator.jsx +15 -0
  258. package/src/core/lib/components/ui/select/select-trigger.jsx +25 -0
  259. package/src/core/lib/components/ui/select/select.jsx +4 -0
  260. package/src/core/lib/components/ui/separator/index.js +7 -0
  261. package/src/core/lib/components/ui/separator/separator.jsx +22 -0
  262. package/src/core/lib/components/ui/sheet/index.js +34 -0
  263. package/src/core/lib/components/ui/sheet/sheet-close.jsx +7 -0
  264. package/src/core/lib/components/ui/sheet/sheet-content.jsx +35 -0
  265. package/src/core/lib/components/ui/sheet/sheet-description.jsx +15 -0
  266. package/src/core/lib/components/ui/sheet/sheet-footer.jsx +11 -0
  267. package/src/core/lib/components/ui/sheet/sheet-header.jsx +11 -0
  268. package/src/core/lib/components/ui/sheet/sheet-overlay.jsx +15 -0
  269. package/src/core/lib/components/ui/sheet/sheet-portal.jsx +4 -0
  270. package/src/core/lib/components/ui/sheet/sheet-title.jsx +15 -0
  271. package/src/core/lib/components/ui/sheet/sheet-trigger.jsx +7 -0
  272. package/src/core/lib/components/ui/sheet/sheet.jsx +4 -0
  273. package/src/core/lib/components/ui/textarea/index.js +7 -0
  274. package/src/core/lib/components/ui/textarea/textarea.jsx +18 -0
  275. package/src/core/lib/components/ui/toggle/index.js +8 -0
  276. package/src/core/lib/components/ui/toggle/toggle.jsx +36 -0
  277. package/src/core/lib/components/ui/toggle-group/index.js +10 -0
  278. package/src/core/lib/components/ui/toggle-group/toggle-group-item.jsx +29 -0
  279. package/src/core/lib/components/ui/toggle-group/toggle-group.jsx +43 -0
  280. package/src/core/lib/components/ui/tooltip/index.js +3 -0
  281. package/src/core/lib/components/ui/tooltip/tooltip-content.jsx +21 -0
  282. package/src/core/lib/components/ui/tooltip/tooltip-trigger.jsx +23 -0
  283. package/src/core/lib/components/ui/tooltip/tooltip.jsx +11 -0
  284. package/src/core/lib/components/ui/trigger-button/index.js +6 -0
  285. package/src/core/lib/components/ui/trigger-button/trigger-button.css +38 -0
  286. package/src/core/lib/components/ui/trigger-button/trigger-button.jsx +63 -0
  287. package/src/core/lib/utils/index.js +6 -0
  288. package/src/core/logger/devLogger.js +238 -0
  289. package/src/core/logger/devLogger.test.js +193 -0
  290. package/src/core/modes/modes.css +98 -0
  291. package/src/core/modes/modes.js +492 -0
  292. package/src/core/modes/modes.test.js +562 -0
  293. package/src/core/mountStoryboardCore.js +478 -0
  294. package/src/core/rename-watcher/config.json +23 -0
  295. package/src/core/rename-watcher/watcher.js +531 -0
  296. package/src/core/scaffold.js +100 -0
  297. package/src/core/server/index.js +391 -0
  298. package/src/core/session/bodyClasses.js +128 -0
  299. package/src/core/session/bodyClasses.test.js +192 -0
  300. package/src/core/session/hashSubscribe.js +19 -0
  301. package/src/core/session/hashSubscribe.test.js +62 -0
  302. package/src/core/session/hideMode.js +424 -0
  303. package/src/core/session/hideMode.test.js +268 -0
  304. package/src/core/session/interceptHideParams.js +35 -0
  305. package/src/core/session/interceptHideParams.test.js +90 -0
  306. package/src/core/session/localStorage.js +134 -0
  307. package/src/core/session/localStorage.test.js +148 -0
  308. package/src/core/session/session.js +76 -0
  309. package/src/core/session/session.test.js +91 -0
  310. package/src/core/stores/canvasConfig.js +134 -0
  311. package/src/core/stores/canvasConfig.test.js +120 -0
  312. package/src/core/stores/commandActions.js +284 -0
  313. package/src/core/stores/commandPaletteConfig.js +31 -0
  314. package/src/core/stores/configSchema.js +232 -0
  315. package/src/core/stores/configSchema.test.js +72 -0
  316. package/src/core/stores/configStore.js +161 -0
  317. package/src/core/stores/customerModeConfig.js +30 -0
  318. package/src/core/stores/featureFlags.js +127 -0
  319. package/src/core/stores/paletteProviders.js +360 -0
  320. package/src/core/stores/paletteProviders.test.js +186 -0
  321. package/src/core/stores/plugins.js +40 -0
  322. package/src/core/stores/plugins.test.js +68 -0
  323. package/src/core/stores/recentArtifacts.js +68 -0
  324. package/src/core/stores/recentArtifacts.test.js +71 -0
  325. package/src/core/stores/sidePanelStore.ts +143 -0
  326. package/src/core/stores/themeStore.ts +291 -0
  327. package/src/core/stores/toolRegistry.js +227 -0
  328. package/src/core/stores/toolStateStore.js +183 -0
  329. package/src/core/stores/toolStateStore.test.js +220 -0
  330. package/src/core/stores/toolbarConfigStore.js +165 -0
  331. package/src/core/stores/uiConfig.js +64 -0
  332. package/src/core/stores/uiConfig.test.js +63 -0
  333. package/src/core/styles/tailwind.css +204 -0
  334. package/src/core/tools/handlers/autosync.js +12 -0
  335. package/src/core/tools/handlers/canvasAddWidget.js +11 -0
  336. package/src/core/tools/handlers/canvasAgents.js +20 -0
  337. package/src/core/tools/handlers/canvasToolbar.js +56 -0
  338. package/src/core/tools/handlers/commandPalette.js +9 -0
  339. package/src/core/tools/handlers/comments.js +16 -0
  340. package/src/core/tools/handlers/create.js +39 -0
  341. package/src/core/tools/handlers/devtools.js +122 -0
  342. package/src/core/tools/handlers/devtools.test.js +87 -0
  343. package/src/core/tools/handlers/featureFlags.js +21 -0
  344. package/src/core/tools/handlers/flows.js +68 -0
  345. package/src/core/tools/handlers/hideChrome.js +9 -0
  346. package/src/core/tools/handlers/hideToolbars.js +25 -0
  347. package/src/core/tools/handlers/inspector.js +19 -0
  348. package/src/core/tools/handlers/paletteTheme.js +35 -0
  349. package/src/core/tools/handlers/theme.js +9 -0
  350. package/src/core/tools/registry.js +26 -0
  351. package/src/core/tools/surfaces/canvasToolbar.js +10 -0
  352. package/src/core/tools/surfaces/commandList.js +10 -0
  353. package/src/core/tools/surfaces/mainToolbar.js +11 -0
  354. package/src/core/tools/surfaces/registry.js +19 -0
  355. package/src/core/ui/ActionMenuButton.jsx +114 -0
  356. package/src/core/ui/AutosyncMenuButton.css +67 -0
  357. package/src/core/ui/AutosyncMenuButton.jsx +242 -0
  358. package/src/core/ui/BranchSelect.jsx +29 -0
  359. package/src/core/ui/BranchSelect.module.css +30 -0
  360. package/src/core/ui/CanvasAgentsMenu.jsx +89 -0
  361. package/src/core/ui/CanvasCreateMenu.jsx +611 -0
  362. package/src/core/ui/CanvasSnap.css +27 -0
  363. package/src/core/ui/CanvasSnap.jsx +51 -0
  364. package/src/core/ui/CanvasUndoRedo.css +36 -0
  365. package/src/core/ui/CanvasUndoRedo.jsx +62 -0
  366. package/src/core/ui/CanvasZoomControl.css +53 -0
  367. package/src/core/ui/CanvasZoomControl.jsx +49 -0
  368. package/src/core/ui/CanvasZoomToFit.css +18 -0
  369. package/src/core/ui/CanvasZoomToFit.jsx +26 -0
  370. package/src/core/ui/CommandMenu.css +8 -0
  371. package/src/core/ui/CommandMenu.jsx +287 -0
  372. package/src/core/ui/CommandPalette.jsx +35 -0
  373. package/src/core/ui/CommandPaletteTrigger.jsx +25 -0
  374. package/src/core/ui/CommentsMenuButton.jsx +40 -0
  375. package/src/core/ui/CoreUIBar.css +47 -0
  376. package/src/core/ui/CoreUIBar.jsx +905 -0
  377. package/src/core/ui/CreateMenuButton.jsx +117 -0
  378. package/src/core/ui/HideChromeTrigger.jsx +48 -0
  379. package/src/core/ui/Icon.jsx +279 -0
  380. package/src/core/ui/InspectorPanel.css +109 -0
  381. package/src/core/ui/InspectorPanel.jsx +632 -0
  382. package/src/core/ui/PwaInstallBanner.css +42 -0
  383. package/src/core/ui/PwaInstallBanner.jsx +124 -0
  384. package/src/core/ui/SidePanel.jsx +261 -0
  385. package/src/core/ui/ThemeMenuButton.jsx +139 -0
  386. package/src/core/ui/core-ui-colors.css +129 -0
  387. package/src/core/ui/design-modes.ts +7 -0
  388. package/src/core/ui/sidepanel.css +301 -0
  389. package/src/core/ui/viewfinder.ts +7 -0
  390. package/src/core/ui-entry.js +30 -0
  391. package/src/core/utils/fuzzySearch.js +117 -0
  392. package/src/core/utils/fuzzySearch.test.js +119 -0
  393. package/src/core/utils/mobileViewport.js +57 -0
  394. package/src/core/utils/mobileViewport.test.js +68 -0
  395. package/src/core/utils/prodMode.js +38 -0
  396. package/src/core/utils/smoothCorners.js +20 -0
  397. package/src/core/vite/docs-handler.js +155 -0
  398. package/src/core/vite/server-plugin.js +797 -0
  399. package/src/core/workshop/features/createCanvas/CreateCanvasForm.jsx +260 -0
  400. package/src/core/workshop/features/createCanvas/index.js +14 -0
  401. package/src/core/workshop/features/createFlow/CreateFlowForm.jsx +334 -0
  402. package/src/core/workshop/features/createFlow/index.js +19 -0
  403. package/src/core/workshop/features/createFlow/server.js +663 -0
  404. package/src/core/workshop/features/createPage/CreatePageForm.jsx +304 -0
  405. package/src/core/workshop/features/createPage/index.js +11 -0
  406. package/src/core/workshop/features/createPrototype/CreatePrototypeForm.jsx +289 -0
  407. package/src/core/workshop/features/createPrototype/index.js +19 -0
  408. package/src/core/workshop/features/createPrototype/server.js +433 -0
  409. package/src/core/workshop/features/createStory/CreateStoryForm.jsx +208 -0
  410. package/src/core/workshop/features/createStory/index.js +14 -0
  411. package/src/core/workshop/features/registry-server.js +22 -0
  412. package/src/core/workshop/features/registry.js +28 -0
  413. package/src/core/workshop/features/templateIndex.js +155 -0
  414. package/src/core/workshop/ui/WorkshopPanel.jsx +98 -0
  415. package/src/core/workshop/ui/mount.ts +6 -0
  416. package/src/core/worktree/port.js +268 -0
  417. package/src/core/worktree/port.test.js +222 -0
  418. package/src/core/worktree/serverRegistry.js +120 -0
  419. package/src/internals/AuthModal/AuthModal.jsx +132 -0
  420. package/src/internals/AuthModal/AuthModal.module.css +221 -0
  421. package/src/internals/BranchBar/BranchBar.jsx +87 -0
  422. package/src/internals/BranchBar/BranchBar.module.css +247 -0
  423. package/src/internals/BranchBar/useBranches.js +93 -0
  424. package/src/internals/BranchBar/useBranches.test.js +68 -0
  425. package/src/internals/CommandPalette/CommandPalette.jsx +1361 -0
  426. package/src/internals/CommandPalette/CreateDialog.jsx +219 -0
  427. package/src/internals/CommandPalette/command-palette.css +180 -0
  428. package/src/internals/FlowError.module.css +30 -0
  429. package/src/internals/Icon.jsx +279 -0
  430. package/src/internals/StoryboardContext.js +3 -0
  431. package/src/internals/Viewfinder.jsx +1479 -0
  432. package/src/internals/Viewfinder.module.css +1540 -0
  433. package/src/internals/Workspace.jsx +7 -0
  434. package/src/internals/__mocks__/virtual-storyboard-data-index.js +4 -0
  435. package/src/internals/canvas/CanvasControls.jsx +112 -0
  436. package/src/internals/canvas/CanvasControls.module.css +135 -0
  437. package/src/internals/canvas/CanvasPage.bridge.test.jsx +387 -0
  438. package/src/internals/canvas/CanvasPage.dragdrop.test.jsx +350 -0
  439. package/src/internals/canvas/CanvasPage.jsx +3092 -0
  440. package/src/internals/canvas/CanvasPage.module.css +187 -0
  441. package/src/internals/canvas/CanvasPage.multiselect.test.jsx +358 -0
  442. package/src/internals/canvas/CanvasToolbar.jsx +73 -0
  443. package/src/internals/canvas/CanvasToolbar.module.css +92 -0
  444. package/src/internals/canvas/ComponentErrorBoundary.jsx +50 -0
  445. package/src/internals/canvas/ConnectorLayer.jsx +208 -0
  446. package/src/internals/canvas/ConnectorLayer.module.css +129 -0
  447. package/src/internals/canvas/MarqueeOverlay.jsx +20 -0
  448. package/src/internals/canvas/PageSelector.jsx +587 -0
  449. package/src/internals/canvas/PageSelector.module.css +261 -0
  450. package/src/internals/canvas/PageSelector.test.jsx +113 -0
  451. package/src/internals/canvas/WebGLContextPool.jsx +292 -0
  452. package/src/internals/canvas/WebGLContextPool.test.jsx +165 -0
  453. package/src/internals/canvas/canvasApi.js +164 -0
  454. package/src/internals/canvas/canvasReloadGuard.js +37 -0
  455. package/src/internals/canvas/canvasReloadGuard.test.js +27 -0
  456. package/src/internals/canvas/canvasTheme.js +118 -0
  457. package/src/internals/canvas/componentIsolate.jsx +165 -0
  458. package/src/internals/canvas/componentSetIsolate.jsx +257 -0
  459. package/src/internals/canvas/computeCanvasBounds.test.js +121 -0
  460. package/src/internals/canvas/connectorGeometry.js +132 -0
  461. package/src/internals/canvas/hotPoolDevLogs.js +25 -0
  462. package/src/internals/canvas/textSelection.js +10 -0
  463. package/src/internals/canvas/textSelection.test.js +26 -0
  464. package/src/internals/canvas/useCanvas.js +126 -0
  465. package/src/internals/canvas/useCanvas.test.js +26 -0
  466. package/src/internals/canvas/useMarqueeSelect.js +213 -0
  467. package/src/internals/canvas/useMarqueeSelect.test.js +78 -0
  468. package/src/internals/canvas/useUndoRedo.js +86 -0
  469. package/src/internals/canvas/useUndoRedo.test.js +231 -0
  470. package/src/internals/canvas/widgets/CodePenEmbed.jsx +293 -0
  471. package/src/internals/canvas/widgets/CodePenEmbed.module.css +161 -0
  472. package/src/internals/canvas/widgets/ComponentSetWidget.jsx +2 -0
  473. package/src/internals/canvas/widgets/ComponentSetWidget.module.css +89 -0
  474. package/src/internals/canvas/widgets/ComponentWidget.jsx +14 -0
  475. package/src/internals/canvas/widgets/ComponentWidget.module.css +0 -0
  476. package/src/internals/canvas/widgets/CropOverlay.jsx +179 -0
  477. package/src/internals/canvas/widgets/CropOverlay.module.css +154 -0
  478. package/src/internals/canvas/widgets/ExpandedPane.jsx +474 -0
  479. package/src/internals/canvas/widgets/ExpandedPane.module.css +179 -0
  480. package/src/internals/canvas/widgets/ExpandedPane.test.jsx +240 -0
  481. package/src/internals/canvas/widgets/ExpandedPaneTopBar.jsx +111 -0
  482. package/src/internals/canvas/widgets/ExpandedPaneTopBar.module.css +59 -0
  483. package/src/internals/canvas/widgets/ExpandedPaneTopBar.test.jsx +45 -0
  484. package/src/internals/canvas/widgets/FigmaEmbed.jsx +296 -0
  485. package/src/internals/canvas/widgets/FigmaEmbed.module.css +222 -0
  486. package/src/internals/canvas/widgets/FrozenTerminalOverlay.jsx +151 -0
  487. package/src/internals/canvas/widgets/FrozenTerminalOverlay.module.css +83 -0
  488. package/src/internals/canvas/widgets/ImageWidget.jsx +287 -0
  489. package/src/internals/canvas/widgets/ImageWidget.module.css +81 -0
  490. package/src/internals/canvas/widgets/LinkPreview.jsx +439 -0
  491. package/src/internals/canvas/widgets/LinkPreview.module.css +585 -0
  492. package/src/internals/canvas/widgets/LinkPreview.test.jsx +193 -0
  493. package/src/internals/canvas/widgets/MarkdownBlock.jsx +354 -0
  494. package/src/internals/canvas/widgets/MarkdownBlock.module.css +377 -0
  495. package/src/internals/canvas/widgets/MarkdownBlock.test.jsx +92 -0
  496. package/src/internals/canvas/widgets/PromptWidget.jsx +428 -0
  497. package/src/internals/canvas/widgets/PromptWidget.module.css +273 -0
  498. package/src/internals/canvas/widgets/PrototypeEmbed.jsx +463 -0
  499. package/src/internals/canvas/widgets/PrototypeEmbed.module.css +579 -0
  500. package/src/internals/canvas/widgets/PrototypeEmbed.test.jsx +10 -0
  501. package/src/internals/canvas/widgets/ResizeHandle.jsx +67 -0
  502. package/src/internals/canvas/widgets/ResizeHandle.module.css +29 -0
  503. package/src/internals/canvas/widgets/StickyNote.jsx +92 -0
  504. package/src/internals/canvas/widgets/StickyNote.module.css +70 -0
  505. package/src/internals/canvas/widgets/StickyNote.test.jsx +116 -0
  506. package/src/internals/canvas/widgets/StorySetWidget.jsx +208 -0
  507. package/src/internals/canvas/widgets/StorySetWidget.module.css +89 -0
  508. package/src/internals/canvas/widgets/StoryWidget.jsx +334 -0
  509. package/src/internals/canvas/widgets/StoryWidget.module.css +211 -0
  510. package/src/internals/canvas/widgets/TerminalReadWidget.jsx +146 -0
  511. package/src/internals/canvas/widgets/TerminalReadWidget.module.css +94 -0
  512. package/src/internals/canvas/widgets/TerminalWidget.jsx +704 -0
  513. package/src/internals/canvas/widgets/TerminalWidget.module.css +444 -0
  514. package/src/internals/canvas/widgets/TilesWidget.jsx +300 -0
  515. package/src/internals/canvas/widgets/TilesWidget.module.css +133 -0
  516. package/src/internals/canvas/widgets/WidgetChrome.jsx +580 -0
  517. package/src/internals/canvas/widgets/WidgetChrome.module.css +421 -0
  518. package/src/internals/canvas/widgets/WidgetWrapper.jsx +15 -0
  519. package/src/internals/canvas/widgets/WidgetWrapper.module.css +25 -0
  520. package/src/internals/canvas/widgets/codepenUrl.js +75 -0
  521. package/src/internals/canvas/widgets/codepenUrl.test.js +76 -0
  522. package/src/internals/canvas/widgets/embedInteraction.test.jsx +173 -0
  523. package/src/internals/canvas/widgets/embedOverlay.module.css +35 -0
  524. package/src/internals/canvas/widgets/embedTheme.js +148 -0
  525. package/src/internals/canvas/widgets/expandUtils.js +559 -0
  526. package/src/internals/canvas/widgets/expandUtils.test.js +155 -0
  527. package/src/internals/canvas/widgets/figmaUrl.js +118 -0
  528. package/src/internals/canvas/widgets/figmaUrl.test.js +139 -0
  529. package/src/internals/canvas/widgets/githubUrl.js +82 -0
  530. package/src/internals/canvas/widgets/githubUrl.test.js +74 -0
  531. package/src/internals/canvas/widgets/iframeDevLogs.js +49 -0
  532. package/src/internals/canvas/widgets/iframeDevLogs.test.jsx +81 -0
  533. package/src/internals/canvas/widgets/index.js +42 -0
  534. package/src/internals/canvas/widgets/pasteRules.js +295 -0
  535. package/src/internals/canvas/widgets/pasteRules.test.js +474 -0
  536. package/src/internals/canvas/widgets/snapshotDisplay.test.jsx +211 -0
  537. package/src/internals/canvas/widgets/tilePool.js +23 -0
  538. package/src/internals/canvas/widgets/tiles/diagonal-bl.png +0 -0
  539. package/src/internals/canvas/widgets/tiles/diagonal-br.png +0 -0
  540. package/src/internals/canvas/widgets/tiles/diagonal-tl.png +0 -0
  541. package/src/internals/canvas/widgets/tiles/leaf.png +0 -0
  542. package/src/internals/canvas/widgets/tiles/quarter-tl.png +0 -0
  543. package/src/internals/canvas/widgets/tiles/quarter-tr.png +0 -0
  544. package/src/internals/canvas/widgets/tiles/solid-a.png +0 -0
  545. package/src/internals/canvas/widgets/tiles/solid-b.png +0 -0
  546. package/src/internals/canvas/widgets/widgetConfig.js +291 -0
  547. package/src/internals/canvas/widgets/widgetConfig.test.js +68 -0
  548. package/src/internals/canvas/widgets/widgetIcons.jsx +190 -0
  549. package/src/internals/canvas/widgets/widgetProps.js +133 -0
  550. package/src/internals/context/FormContext.js +13 -0
  551. package/src/internals/context/FormContext.test.js +48 -0
  552. package/src/internals/context.jsx +481 -0
  553. package/src/internals/context.test.jsx +296 -0
  554. package/src/internals/hashPreserver.js +73 -0
  555. package/src/internals/hashPreserver.test.js +107 -0
  556. package/src/internals/hooks/useConfig.js +14 -0
  557. package/src/internals/hooks/useFeatureFlag.js +14 -0
  558. package/src/internals/hooks/useFlows.js +50 -0
  559. package/src/internals/hooks/useFlows.test.js +134 -0
  560. package/src/internals/hooks/useHideMode.js +31 -0
  561. package/src/internals/hooks/useHideMode.test.js +43 -0
  562. package/src/internals/hooks/useLocalStorage.js +57 -0
  563. package/src/internals/hooks/useLocalStorage.test.js +75 -0
  564. package/src/internals/hooks/useMode.js +43 -0
  565. package/src/internals/hooks/useObject.js +101 -0
  566. package/src/internals/hooks/useObject.test.js +74 -0
  567. package/src/internals/hooks/useOverride.js +84 -0
  568. package/src/internals/hooks/useOverride.test.js +71 -0
  569. package/src/internals/hooks/usePrototypeReloadGuard.js +64 -0
  570. package/src/internals/hooks/useRecord.js +158 -0
  571. package/src/internals/hooks/useRecord.test.js +221 -0
  572. package/src/internals/hooks/useScene.js +38 -0
  573. package/src/internals/hooks/useScene.test.js +66 -0
  574. package/src/internals/hooks/useSceneData.js +108 -0
  575. package/src/internals/hooks/useSceneData.test.js +136 -0
  576. package/src/internals/hooks/useSession.js +4 -0
  577. package/src/internals/hooks/useSession.test.js +8 -0
  578. package/src/internals/hooks/useThemeState.js +61 -0
  579. package/src/internals/hooks/useThemeState.test.js +66 -0
  580. package/src/internals/hooks/useUndoRedo.js +28 -0
  581. package/src/internals/hooks/useUndoRedo.test.js +64 -0
  582. package/src/internals/index.js +58 -0
  583. package/src/internals/story/ComponentSetPage.jsx +198 -0
  584. package/src/internals/story/ComponentSetPage.module.css +129 -0
  585. package/src/internals/story/StoryPage.jsx +147 -0
  586. package/src/internals/story/StoryPage.module.css +18 -0
  587. package/src/internals/test-utils.js +45 -0
  588. package/src/internals/vite/data-plugin.js +1508 -0
  589. package/src/internals/vite/data-plugin.test.js +1223 -0
  590. package/src/test-utils.js +44 -0
  591. package/toolbar.config.json +271 -0
  592. package/widgets.config.json +1537 -0
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Command Palette Config — runtime store for commandPalette config.
3
+ * Framework-agnostic (zero npm dependencies).
4
+ */
5
+
6
+ import { getConfig } from './configStore.js'
7
+
8
+ let _config = { sections: [] }
9
+
10
+ /**
11
+ * Initialize the command palette config.
12
+ * @param {object} config - The commandPalette object from storyboard.config.json
13
+ */
14
+ export function initCommandPaletteConfig(config) {
15
+ _config = { sections: [], ...config }
16
+ }
17
+
18
+ /**
19
+ * Get the current command palette config.
20
+ * Falls back to the unified config store if the legacy store wasn't initialized.
21
+ * @returns {{ sections: Array }}
22
+ */
23
+ export function getCommandPaletteConfig() {
24
+ if (_config.sections.length === 0) {
25
+ const uc = getConfig('commandPalette')
26
+ if (uc?.sections?.length > 0) {
27
+ _config = { sections: [], ...uc }
28
+ }
29
+ }
30
+ return _config
31
+ }
@@ -0,0 +1,232 @@
1
+ /**
2
+ * Config Schema — canonical shape and defaults for storyboard.config.json.
3
+ *
4
+ * Every consumer of storyboard.config.json should import `getConfig()` to get
5
+ * a fully defaulted, validated config object. New keys added here are safe for
6
+ * existing projects — they always have defaults.
7
+ *
8
+ * @module configSchema
9
+ */
10
+
11
+ /**
12
+ * @typedef {object} PasteRule
13
+ * @property {string} match — regex string tested against pasted URLs
14
+ * @property {string} widget — widget type to create (e.g. "figma-embed", "link-preview")
15
+ * @property {Record<string, string>} [propsMap] — static props merged into widget props
16
+ */
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
+
37
+ /**
38
+ * @typedef {object} CanvasConfig
39
+ * @property {PasteRule[]} pasteRules — URL→widget conversion rules (evaluated in order, first match wins)
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, webgl_ready_slots?: number }>} [pools] — per-pool overrides (terminal, prompt, copilot, claude, codex). webgl_ready_slots: how many front-of-queue sessions should start with PINNED WebGL priority (default: 0)
69
+ */
70
+
71
+ /**
72
+ * @typedef {object} CommandPaletteConfig
73
+ * @property {string[]} providers — provider IDs to enable
74
+ * @property {string} ranking — result ranking strategy
75
+ * @property {CommandPaletteSection[]} [sections] — declarative palette sections
76
+ */
77
+
78
+ /**
79
+ * @typedef {object} CommandPaletteSection
80
+ * @property {string} id — unique section identifier
81
+ * @property {string} [title] — section heading in the palette
82
+ * @property {string} [type] — "tool-menu" for sub-page entries
83
+ * @property {string} [label] — display label (for tool-menu entries)
84
+ * @property {string[]} [keywords] — search keywords
85
+ * @property {CommandPaletteSectionItem[]} [items] — static entries
86
+ * @property {string} [source] — dynamic data source: "canvases" | "prototypes" | "stories"
87
+ * @property {string} [order] — ordering: "recent" | "alphabetical" | "recent-changes"
88
+ * @property {number} [limit] — max items from dynamic source
89
+ * @property {CommandPaletteOption[]} [options] — sub-page options (for tool-menu type)
90
+ */
91
+
92
+ /**
93
+ * @typedef {object} CommandPaletteSectionItem
94
+ * @property {string} type — "link" | "action"
95
+ * @property {string} label — display text
96
+ * @property {string} [url] — navigation URL (for links)
97
+ * @property {string} [action] — command action ID (for actions)
98
+ * @property {string[]} [keywords] — search keywords
99
+ */
100
+
101
+ /**
102
+ * @typedef {object} CommandPaletteOption
103
+ * @property {string} label — display text
104
+ * @property {string} action — command action ID
105
+ * @property {*} [value] — action payload
106
+ */
107
+
108
+ /**
109
+ * @typedef {object} CustomerModeConfig
110
+ * @property {boolean} enabled — master toggle for customer mode
111
+ * @property {boolean} hideChrome — hides all toolbars (except canvas tools), branchbar, cmd+k, cmd+.
112
+ * @property {boolean} hideHomepage — removes the storyboard homepage (leaves empty page)
113
+ * @property {string} protoHomepage — internal /path that replaces homepage; redirects from / and /workspace
114
+ */
115
+
116
+ /**
117
+ * @typedef {object} StoryboardConfig
118
+ * @property {string} [customDomain]
119
+ * @property {string} [devDomain]
120
+ * @property {string} [devDomainColor] — CSS color for the BranchBar in local dev (default: blue)
121
+ * @property {{ owner: string, name: string }} [repository]
122
+ * @property {{ enabled: boolean }} [modes]
123
+ * @property {{ discussions: { category: string } }} [comments]
124
+ * @property {Record<string, boolean>} [plugins]
125
+ * @property {{ enabled?: boolean, features?: Record<string, boolean>, partials?: Array }} [workshop]
126
+ * @property {Record<string, boolean>} [featureFlags]
127
+ * @property {{ hide?: string[] }} [ui]
128
+ * @property {object} [toolbar]
129
+ * @property {CanvasConfig} [canvas]
130
+ * @property {HotPoolConfig} [hotPool]
131
+ * @property {CommandPaletteConfig} [commandPalette]
132
+ * @property {CustomerModeConfig} [customerMode]
133
+ */
134
+
135
+ /** Built-in paste rules shipped with storyboard. */
136
+ export const builtinPasteRules = [
137
+ {
138
+ id: 'figma',
139
+ match: 'https?://(?:www\\.)?figma\\.com/',
140
+ widget: 'figma-embed',
141
+ propsMap: { width: 800, height: 450 },
142
+ },
143
+ ]
144
+
145
+ /** Default config values. Every key here is safe to access without null checks. */
146
+ export const configDefaults = {
147
+ customDomain: '',
148
+ devDomain: '',
149
+ devDomainColor: '',
150
+ repository: { owner: '', name: '' },
151
+ modes: { enabled: false },
152
+ comments: { discussions: { category: 'Comments' } },
153
+ plugins: {},
154
+ workshop: {
155
+ enabled: false,
156
+ features: { createPrototype: true, createFlow: true, createCanvas: true },
157
+ },
158
+ featureFlags: {},
159
+ ui: {},
160
+ toolbar: {},
161
+ canvas: {
162
+ pasteRules: builtinPasteRules,
163
+ github: {
164
+ embedBehavior: 'link-preview', // "link-preview" | "rich-embed"
165
+ ghGuard: 'copy', // "copy" | "link" | "off"
166
+ },
167
+ zoom: {
168
+ min: 10,
169
+ max: 250,
170
+ step: 10,
171
+ },
172
+ terminal: {
173
+ resizable: false,
174
+ defaultWidth: 800,
175
+ defaultHeight: 450,
176
+ },
177
+ },
178
+ commandPalette: {
179
+ providers: ['prototypes', 'flows', 'canvases', 'pages'],
180
+ ranking: 'frecency',
181
+ sections: [],
182
+ },
183
+ customerMode: {
184
+ enabled: false,
185
+ hideChrome: false,
186
+ hideHomepage: false,
187
+ protoHomepage: '',
188
+ },
189
+ }
190
+
191
+ /**
192
+ * Deep-merge helper that replaces arrays instead of concatenating.
193
+ * Objects are recursively merged; all other values are overwritten.
194
+ */
195
+ function mergeConfig(defaults, overrides) {
196
+ if (!overrides || typeof overrides !== 'object' || Array.isArray(overrides)) {
197
+ return overrides ?? defaults
198
+ }
199
+ const result = { ...defaults }
200
+ for (const key of Object.keys(overrides)) {
201
+ const val = overrides[key]
202
+ if (val === undefined) continue
203
+ if (Array.isArray(val)) {
204
+ // Arrays replace (e.g. pasteRules, providers) — no concat
205
+ result[key] = val
206
+ } else if (val && typeof val === 'object' && !Array.isArray(val) && typeof defaults[key] === 'object' && !Array.isArray(defaults[key])) {
207
+ result[key] = mergeConfig(defaults[key], val)
208
+ } else {
209
+ result[key] = val
210
+ }
211
+ }
212
+ return result
213
+ }
214
+
215
+ /**
216
+ * Return a fully defaulted config by merging user-provided values over defaults.
217
+ * Safe to call with an empty object or undefined — returns full defaults.
218
+ *
219
+ * @param {Partial<StoryboardConfig>} [raw={}]
220
+ * @returns {StoryboardConfig}
221
+ */
222
+ export function getConfig(raw = {}) {
223
+ return mergeConfig(configDefaults, raw)
224
+ }
225
+
226
+ /**
227
+ * Return a copy of the bare defaults (no user overrides).
228
+ * @returns {StoryboardConfig}
229
+ */
230
+ export function getConfigDefaults() {
231
+ return JSON.parse(JSON.stringify(configDefaults))
232
+ }
@@ -0,0 +1,72 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { getConfig, getConfigDefaults, configDefaults, builtinPasteRules } from './configSchema.js'
3
+
4
+ describe('configSchema', () => {
5
+ describe('getConfigDefaults', () => {
6
+ it('returns a full defaults object', () => {
7
+ const d = getConfigDefaults()
8
+ expect(d.canvas).toBeDefined()
9
+ expect(d.commandPalette).toBeDefined()
10
+ expect(d.repository).toEqual({ owner: '', name: '' })
11
+ })
12
+
13
+ it('returns a fresh copy each time', () => {
14
+ const a = getConfigDefaults()
15
+ const b = getConfigDefaults()
16
+ expect(a).not.toBe(b)
17
+ expect(a).toEqual(b)
18
+ })
19
+ })
20
+
21
+ describe('getConfig', () => {
22
+ it('returns full defaults when called with empty object', () => {
23
+ const c = getConfig({})
24
+ expect(c.canvas.pasteRules).toEqual(builtinPasteRules)
25
+ expect(c.canvas.github.embedBehavior).toBe('link-preview')
26
+ expect(c.canvas.github.ghGuard).toBe('copy')
27
+ expect(c.commandPalette.providers).toEqual(['prototypes', 'flows', 'canvases', 'pages'])
28
+ expect(c.commandPalette.ranking).toBe('frecency')
29
+ expect(c.customerMode.enabled).toBe(false)
30
+ expect(c.customerMode.hideChrome).toBe(false)
31
+ expect(c.customerMode.hideHomepage).toBe(false)
32
+ expect(c.customerMode.protoHomepage).toBe('')
33
+ })
34
+
35
+ it('returns full defaults when called with undefined', () => {
36
+ const c = getConfig()
37
+ expect(c.canvas).toBeDefined()
38
+ expect(c.commandPalette).toBeDefined()
39
+ })
40
+
41
+ it('merges user config over defaults', () => {
42
+ const c = getConfig({
43
+ repository: { owner: 'test', name: 'repo' },
44
+ canvas: { github: { ghGuard: 'link' } },
45
+ })
46
+ expect(c.repository).toEqual({ owner: 'test', name: 'repo' })
47
+ expect(c.canvas.github.ghGuard).toBe('link')
48
+ // Other defaults preserved
49
+ expect(c.canvas.github.embedBehavior).toBe('link-preview')
50
+ expect(c.canvas.pasteRules).toEqual(builtinPasteRules)
51
+ })
52
+
53
+ it('replaces arrays instead of concatenating', () => {
54
+ const customRules = [{ id: 'custom', match: 'https://example.com', widget: 'link-preview' }]
55
+ const c = getConfig({ canvas: { pasteRules: customRules } })
56
+ expect(c.canvas.pasteRules).toEqual(customRules)
57
+ expect(c.canvas.pasteRules).not.toContainEqual(builtinPasteRules[0])
58
+ })
59
+
60
+ it('preserves existing keys not in defaults', () => {
61
+ const c = getConfig({ devDomain: 'my-project', featureFlags: { 'show-banner': true } })
62
+ expect(c.devDomain).toBe('my-project')
63
+ expect(c.featureFlags['show-banner']).toBe(true)
64
+ })
65
+
66
+ it('does not mutate configDefaults', () => {
67
+ const before = JSON.stringify(configDefaults)
68
+ getConfig({ canvas: { github: { ghGuard: 'off' } } })
69
+ expect(JSON.stringify(configDefaults)).toBe(before)
70
+ })
71
+ })
72
+ })
@@ -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 '../data/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 external 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
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Customer Mode Config — runtime store for customerMode config.
3
+ * Framework-agnostic (zero npm dependencies).
4
+ */
5
+
6
+ let _config = { enabled: false, hideChrome: false, hideHomepage: false, protoHomepage: '' }
7
+
8
+ /**
9
+ * Initialize customer mode config.
10
+ * @param {object} config - The customerMode object from storyboard.config.json
11
+ */
12
+ export function initCustomerModeConfig(config) {
13
+ _config = { enabled: false, hideChrome: false, hideHomepage: false, protoHomepage: '', ...config }
14
+ }
15
+
16
+ /**
17
+ * Get the current customer mode config.
18
+ * @returns {{ enabled: boolean, hideChrome: boolean, hideHomepage: boolean, protoHomepage: string }}
19
+ */
20
+ export function getCustomerModeConfig() {
21
+ return _config
22
+ }
23
+
24
+ /**
25
+ * Check if customer mode is enabled.
26
+ * @returns {boolean}
27
+ */
28
+ export function isCustomerMode() {
29
+ return _config.enabled
30
+ }
@@ -0,0 +1,127 @@
1
+ /**
2
+ * Feature flag system for Storyboard.
3
+ *
4
+ * Flags are defined in storyboard.config.json under "featureFlags" and
5
+ * initialized at app startup via the Vite data plugin.
6
+ *
7
+ * Read priority: localStorage → config defaults
8
+ * Write target: localStorage (persistent per-browser)
9
+ *
10
+ * All flag keys in localStorage are prefixed with "flag." to avoid
11
+ * collisions with scene overrides.
12
+ */
13
+
14
+ import { getLocal, setLocal, removeLocal, getAllLocal } from '../session/localStorage.js'
15
+
16
+ const FLAG_PREFIX = 'flag.'
17
+ const BODY_CLASS_PREFIX = 'sb-ff-'
18
+
19
+ /** Built-in feature flag defaults — always available even if initFeatureFlags is never called. */
20
+ const BUILTIN_DEFAULTS = {
21
+ 'canvas-auto-reload': false,
22
+ 'prototype-auto-reload': true,
23
+ }
24
+
25
+ /** Module-level storage for config defaults */
26
+ let _defaults = {}
27
+
28
+ /**
29
+ * Sync body classes for active feature flags.
30
+ * Adds `sb-ff-{name}` for every flag that resolves to true,
31
+ * removes it for every flag that resolves to false.
32
+ */
33
+ export function syncFlagBodyClasses() {
34
+ if (typeof document === 'undefined') return
35
+ for (const key of Object.keys(_defaults)) {
36
+ const cls = BODY_CLASS_PREFIX + key
37
+ if (getFlag(key)) {
38
+ document.body.classList.add(cls)
39
+ } else {
40
+ document.body.classList.remove(cls)
41
+ }
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Initialize the feature flag system with config defaults.
47
+ * Only writes a default to localStorage when no user override exists yet,
48
+ * so toggled values survive across reloads.
49
+ * @param {Record<string, boolean>} defaults - Flag key → default value
50
+ */
51
+ export function initFeatureFlags(defaults = {}) {
52
+ _defaults = { ...BUILTIN_DEFAULTS, ...defaults }
53
+ for (const [key, value] of Object.entries(_defaults)) {
54
+ if (getLocal(FLAG_PREFIX + key) === null) {
55
+ setLocal(FLAG_PREFIX + key, String(value))
56
+ }
57
+ }
58
+ syncFlagBodyClasses()
59
+ }
60
+
61
+ /**
62
+ * Read a flag value. Priority: localStorage → config default.
63
+ * @param {string} key - Flag key (without prefix)
64
+ * @returns {boolean}
65
+ */
66
+ export function getFlag(key) {
67
+ const localVal = getLocal(FLAG_PREFIX + key)
68
+ if (localVal !== null) return localVal === 'true'
69
+
70
+ return _defaults[key] ?? BUILTIN_DEFAULTS[key] ?? false
71
+ }
72
+
73
+ /**
74
+ * Set a flag value. Writes to localStorage for persistence.
75
+ * @param {string} key - Flag key (without prefix)
76
+ * @param {boolean} value
77
+ */
78
+ export function setFlag(key, value) {
79
+ setLocal(FLAG_PREFIX + key, String(value))
80
+ syncFlagBodyClasses()
81
+ }
82
+
83
+ /**
84
+ * Toggle a flag. Reads current value, writes opposite to localStorage.
85
+ * @param {string} key - Flag key (without prefix)
86
+ */
87
+ export function toggleFlag(key) {
88
+ setFlag(key, !getFlag(key))
89
+ }
90
+
91
+ /**
92
+ * Get all flags with their default and current (resolved) values.
93
+ * @returns {Record<string, { default: boolean, current: boolean }>}
94
+ */
95
+ export function getAllFlags() {
96
+ const allKeys = new Set([...Object.keys(BUILTIN_DEFAULTS), ...Object.keys(_defaults)])
97
+ const result = {}
98
+ for (const key of allKeys) {
99
+ result[key] = {
100
+ default: _defaults[key] ?? BUILTIN_DEFAULTS[key] ?? false,
101
+ current: getFlag(key),
102
+ }
103
+ }
104
+ return result
105
+ }
106
+
107
+ /**
108
+ * Reset all flags — removes localStorage overrides.
109
+ * Flags revert to config defaults.
110
+ */
111
+ export function resetFlags() {
112
+ const allLocal = getAllLocal()
113
+ for (const localKey of Object.keys(allLocal)) {
114
+ if (localKey.startsWith(FLAG_PREFIX)) {
115
+ removeLocal(localKey)
116
+ }
117
+ }
118
+ syncFlagBodyClasses()
119
+ }
120
+
121
+ /**
122
+ * Get all registered flag keys.
123
+ * @returns {string[]}
124
+ */
125
+ export function getFlagKeys() {
126
+ return [...new Set([...Object.keys(BUILTIN_DEFAULTS), ...Object.keys(_defaults)])]
127
+ }