@dfosco/storyboard 0.7.1 → 0.9.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 (323) hide show
  1. package/dist/storyboard-ui.css +1 -1
  2. package/dist/storyboard-ui.js +14128 -10953
  3. package/dist/storyboard-ui.js.map +1 -1
  4. package/dist/tailwind.css +1 -1
  5. package/dist/tiny-canvas.css +1 -1
  6. package/package.json +138 -128
  7. package/scaffold/AGENTS.md +9 -7
  8. package/scaffold/README.md +18 -0
  9. package/scaffold/deploy.yml +21 -0
  10. package/scaffold/gitignore +8 -14
  11. package/scaffold/preview.yml +40 -0
  12. package/scaffold/{manifest.json → scaffold.config.json} +73 -3
  13. package/scaffold/scripts/aggregate-artifacts.mjs +257 -0
  14. package/scaffold/skills/canvas/SKILL.md +1 -1
  15. package/scaffold/skills/migrate-0.5.0/SKILL.md +1 -1
  16. package/scaffold/skills/ship/SKILL.md +2 -2
  17. package/scaffold/skills/worktree/SKILL.md +1 -1
  18. package/scaffold/src/_prototype.jsx +17 -0
  19. package/scaffold/src/_story.jsx +13 -0
  20. package/scaffold/src/library/README.md +34 -0
  21. package/scaffold/src/library/_app.jsx +41 -0
  22. package/scaffold/src/library/_app.module.css +2 -0
  23. package/scaffold/src/library/create.jsx +10 -0
  24. package/scaffold/src/library/index.jsx +14 -0
  25. package/scaffold/src/library/mount.jsx +51 -0
  26. package/scaffold/src/library/prototypes-entry.jsx +57 -0
  27. package/scaffold/src/library/routes.jsx +205 -0
  28. package/scaffold/src/library/viewfinder.jsx +13 -0
  29. package/scaffold/src/library/workspace.jsx +17 -0
  30. package/scripts/aggregate-artifacts.mjs +257 -0
  31. package/src/canvas/style.css +16 -16
  32. package/src/core/artifact/operations.js +54 -15
  33. package/src/core/artifact/schemas/canvas.schema.json +7 -1
  34. package/src/core/autosync/server.test.js +1 -1
  35. package/src/core/canvas/hot-pool.js +21 -33
  36. package/src/core/canvas/materializer.js +39 -13
  37. package/src/core/canvas/selectedWidgets.js +1 -1
  38. package/src/core/canvas/server.js +376 -100
  39. package/src/core/canvas/server.test.js +472 -2
  40. package/src/core/canvas/terminal-server.js +144 -57
  41. package/src/core/canvas/undoRedo.js +174 -0
  42. package/src/core/canvas/undoRedo.test.js +250 -0
  43. package/src/core/cli/artifact.js +2 -0
  44. package/src/core/cli/buildManifest.js +34 -0
  45. package/src/core/cli/canvasRedo.js +44 -0
  46. package/src/core/cli/canvasUndo.js +40 -0
  47. package/src/core/cli/create.js +151 -23
  48. package/src/core/cli/dev.js +23 -35
  49. package/src/core/cli/index.js +21 -0
  50. package/src/core/cli/schemas.js +8 -4
  51. package/src/core/cli/serverUrl.js +24 -0
  52. package/src/core/cli/setup.js +14 -25
  53. package/src/core/cli/terminal-welcome.js +12 -6
  54. package/src/core/cli/updateVersion.js +42 -2
  55. package/src/core/cli/workleaf.js +140 -0
  56. package/src/core/comments/api.js +1 -1
  57. package/src/core/comments/queries.js +3 -0
  58. package/src/core/comments/ui/CommentWindow.jsx +3 -2
  59. package/src/core/comments/ui/comment-layout.css +14 -14
  60. package/src/core/data/artifactIndex.js +235 -0
  61. package/src/core/data/artifactIndex.test.js +203 -0
  62. package/src/core/data/artifactManifest.js +290 -0
  63. package/src/core/data/artifactManifest.test.js +207 -0
  64. package/src/core/data/viewfinder.js +47 -7
  65. package/src/core/index.js +24 -1
  66. package/src/core/inspector/highlighter.js +1 -1
  67. package/src/core/inspector/mouseMode.js +2 -2
  68. package/src/core/lib/components/ui/avatar/avatar-fallback.jsx +2 -2
  69. package/src/core/lib/components/ui/avatar/avatar-image.jsx +2 -2
  70. package/src/core/lib/components/ui/avatar/avatar.jsx +2 -2
  71. package/src/core/lib/components/ui/checkbox/checkbox.jsx +12 -9
  72. package/src/core/lib/components/ui/dialog/dialog-content.jsx +45 -31
  73. package/src/core/lib/components/ui/dialog/dialog-trigger.jsx +9 -5
  74. package/src/core/lib/components/ui/dialog/dialog.jsx +12 -3
  75. package/src/core/lib/components/ui/dialog/dialog.module.css +118 -0
  76. package/src/core/lib/components/ui/dialog/index.js +4 -34
  77. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +3 -3
  78. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +19 -9
  79. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +8 -8
  80. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +2 -2
  81. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +2 -2
  82. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +15 -4
  83. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +2 -2
  84. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +2 -2
  85. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +14 -7
  86. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +2 -2
  87. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +8 -4
  88. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +4 -4
  89. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +2 -2
  90. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +8 -2
  91. package/src/core/lib/components/ui/dropdown-menu/dropdown-menu.jsx +2 -2
  92. package/src/core/lib/components/ui/label/label.jsx +1 -2
  93. package/src/core/lib/components/ui/panel/panel-close.jsx +7 -4
  94. package/src/core/lib/components/ui/panel/panel-content.jsx +7 -9
  95. package/src/core/lib/components/ui/panel/panel-title.jsx +3 -3
  96. package/src/core/lib/components/ui/panel/panel.jsx +11 -2
  97. package/src/core/lib/components/ui/separator/separator.jsx +6 -4
  98. package/src/core/lib/components/ui/tooltip/tooltip-content.jsx +7 -6
  99. package/src/core/lib/components/ui/tooltip/tooltip-trigger.jsx +13 -6
  100. package/src/core/lib/components/ui/tooltip/tooltip.jsx +5 -5
  101. package/src/core/modes/modes.css +4 -4
  102. package/src/core/mountStoryboardCore.js +287 -83
  103. package/src/core/mountStoryboardCore.test.js +198 -0
  104. package/src/core/rename-watcher/config.json +1 -1
  105. package/src/core/rename-watcher/watcher.js +330 -37
  106. package/src/core/rename-watcher/watcher.test.js +253 -0
  107. package/src/core/scaffold/fragments.js +287 -0
  108. package/src/core/scaffold/fragments.test.js +401 -0
  109. package/src/core/scaffold/index.js +291 -0
  110. package/src/core/scaffold/migrateLegacyGitignore.js +157 -0
  111. package/src/core/scaffold/scaffold-integration.test.js +247 -0
  112. package/src/core/scaffold.js +4 -97
  113. package/src/core/stores/canvasInteractionStore.js +120 -0
  114. package/src/core/stores/canvasInteractionStore.test.js +126 -0
  115. package/src/core/stores/configSchema.js +64 -8
  116. package/src/core/stores/configSchema.test.js +3 -0
  117. package/src/core/stores/customerModeConfig.js +24 -3
  118. package/src/core/stores/customerModeConfig.test.js +46 -0
  119. package/src/core/stores/presentationStore.js +118 -0
  120. package/src/core/stores/presentationStore.test.js +114 -0
  121. package/src/core/stores/recentArtifacts.js +49 -2
  122. package/src/core/stores/recentArtifacts.test.js +59 -6
  123. package/src/core/stores/themeBootstrap.js +264 -0
  124. package/src/core/stores/themeBootstrap.test.js +211 -0
  125. package/src/core/stores/themeStore.test.js +154 -0
  126. package/src/core/stores/themeStore.ts +235 -220
  127. package/src/core/stores/uiConfig.js +10 -2
  128. package/src/core/styles/generateThemesCss.js +63 -0
  129. package/src/core/styles/tailwind.css +150 -94
  130. package/src/core/styles/workspace-chrome.css +13 -0
  131. package/src/core/tools/handlers/paletteTheme.js +11 -8
  132. package/src/core/ui/ActionMenuButton.jsx +2 -1
  133. package/src/core/ui/AutosyncMenuButton.css +7 -7
  134. package/src/core/ui/BranchSelect.module.css +5 -5
  135. package/src/core/ui/CanvasCreateMenu.jsx +1 -19
  136. package/src/core/ui/ChromeSlot.jsx +92 -0
  137. package/src/core/ui/ChromeSlot.test.jsx +140 -0
  138. package/src/core/ui/CoreUIBar.css +5 -5
  139. package/src/core/ui/CoreUIBar.jsx +170 -142
  140. package/src/core/ui/InspectorPanel.css +5 -5
  141. package/src/core/ui/InspectorPanel.jsx +9 -9
  142. package/src/core/ui/PwaInstallBanner.css +5 -5
  143. package/src/core/ui/PwaInstallBanner.jsx +5 -5
  144. package/src/core/ui/ThemeMenuButton.jsx +45 -30
  145. package/src/core/ui/core-ui-colors.css +28 -66
  146. package/src/core/ui/sidepanel.css +12 -12
  147. package/src/core/vite/server-plugin.js +13 -0
  148. package/src/core/workleaf/cleanup.js +102 -0
  149. package/src/core/workleaf/create.js +199 -0
  150. package/src/core/workleaf/delete.js +101 -0
  151. package/src/core/workleaf/list.js +57 -0
  152. package/src/core/workleaf/merge.js +238 -0
  153. package/src/core/workleaf/paths.js +146 -0
  154. package/src/core/workleaf/paths.test.js +230 -0
  155. package/src/core/workshop/features/createCanvas/CreateCanvasForm.jsx +130 -34
  156. package/src/core/workshop/features/createFlow/server.js +5 -1
  157. package/src/core/workshop/features/createPrototype/server.js +5 -1
  158. package/src/core/workshop/features/templateIndex.js +28 -1
  159. package/src/core/worktree/port.js +48 -5
  160. package/src/core/worktree/port.test.js +42 -0
  161. package/src/internals/ArtifactForm/ArtifactForm.jsx +173 -112
  162. package/src/internals/ArtifactForm/ArtifactForm.module.css +51 -69
  163. package/src/internals/ArtifactForm/artifactSchemas.js +40 -5
  164. package/src/internals/AuthModal/AuthModal.module.css +34 -34
  165. package/src/internals/BaseUiForm/BaseUiForm.jsx +293 -0
  166. package/src/internals/BaseUiForm/BaseUiForm.module.css +542 -0
  167. package/src/internals/BranchBar/BranchBar.module.css +4 -4
  168. package/src/internals/BranchesDropdown/BranchesDropdown.jsx +69 -0
  169. package/src/internals/BranchesDropdown/BranchesDropdown.module.css +84 -0
  170. package/src/internals/CommandPalette/CommandPalette.jsx +41 -29
  171. package/src/internals/CommandPalette/CreateArtifactForm.jsx +150 -0
  172. package/src/internals/CommandPalette/CreateDialog.jsx +20 -110
  173. package/src/internals/CommandPalette/WidgetArtifactDialog.css +16 -16
  174. package/src/internals/CommandPalette/WidgetArtifactDialog.jsx +1 -1
  175. package/src/internals/CommandPalette/command-palette.css +14 -14
  176. package/src/internals/CommandPalette/createHelpers.js +30 -0
  177. package/src/internals/CreatePage/CreatePage.jsx +57 -0
  178. package/src/internals/CreatePage/CreatePage.module.css +34 -0
  179. package/src/internals/Dialog.jsx +51 -0
  180. package/src/internals/FlowError.module.css +5 -5
  181. package/src/internals/PrototypeErrorBoundary.module.css +15 -15
  182. package/src/internals/SimpleWorkspace/SimpleWorkspace.jsx +534 -0
  183. package/src/internals/SimpleWorkspace/SimpleWorkspace.module.css +323 -0
  184. package/src/internals/Tooltip.jsx +39 -0
  185. package/src/internals/Viewfinder.jsx +229 -64
  186. package/src/internals/Viewfinder.module.css +253 -182
  187. package/src/internals/canvas/CanvasControls.module.css +11 -11
  188. package/src/internals/canvas/CanvasPage.bridge.test.jsx +11 -37
  189. package/src/internals/canvas/CanvasPage.jsx +358 -217
  190. package/src/internals/canvas/CanvasPage.module.css +20 -19
  191. package/src/internals/canvas/CanvasPage.multiselect.test.jsx +39 -26
  192. package/src/internals/canvas/CanvasToolbar.module.css +11 -11
  193. package/src/internals/canvas/ConnectorLayer.jsx +39 -2
  194. package/src/internals/canvas/ConnectorLayer.module.css +10 -10
  195. package/src/internals/canvas/PageSelector.jsx +15 -1
  196. package/src/internals/canvas/PageSelector.module.css +41 -27
  197. package/src/internals/canvas/canvasApi.js +40 -5
  198. package/src/internals/canvas/canvasTheme.js +22 -111
  199. package/src/internals/canvas/isolation/createIsolationMiddleware.js +68 -0
  200. package/src/internals/canvas/isolation/mountIsolationApp.jsx +88 -0
  201. package/src/internals/canvas/isolation/prototypeRoutes.jsx +140 -0
  202. package/src/internals/canvas/isolation/prototypesEntry.jsx +28 -0
  203. package/src/internals/canvas/isolation/storiesEntry.jsx +20 -0
  204. package/src/internals/canvas/isolation/storyRoutes.jsx +55 -0
  205. package/src/internals/canvas/useUndoRedo.js +75 -60
  206. package/src/internals/canvas/useUndoRedo.test.js +46 -178
  207. package/src/internals/canvas/widgets/CodePenEmbed.jsx +16 -36
  208. package/src/internals/canvas/widgets/CodePenEmbed.module.css +12 -12
  209. package/src/internals/canvas/widgets/CropOverlay.module.css +23 -23
  210. package/src/internals/canvas/widgets/ExpandedPane.module.css +8 -8
  211. package/src/internals/canvas/widgets/ExpandedPaneTopBar.jsx +1 -1
  212. package/src/internals/canvas/widgets/FigmaEmbed.jsx +15 -36
  213. package/src/internals/canvas/widgets/FigmaEmbed.module.css +15 -15
  214. package/src/internals/canvas/widgets/FrozenTerminalOverlay.jsx +30 -21
  215. package/src/internals/canvas/widgets/FrozenTerminalOverlay.module.css +5 -5
  216. package/src/internals/canvas/widgets/ImageWidget.jsx +7 -2
  217. package/src/internals/canvas/widgets/ImageWidget.module.css +3 -3
  218. package/src/internals/canvas/widgets/LinkPreview.module.css +79 -80
  219. package/src/internals/canvas/widgets/MarkdownBlock.module.css +31 -31
  220. package/src/internals/canvas/widgets/PromptWidget.jsx +2 -16
  221. package/src/internals/canvas/widgets/PromptWidget.module.css +33 -33
  222. package/src/internals/canvas/widgets/PrototypeEmbed.jsx +92 -17
  223. package/src/internals/canvas/widgets/PrototypeEmbed.module.css +58 -56
  224. package/src/internals/canvas/widgets/PrototypeEmbed.test.jsx +118 -4
  225. package/src/internals/canvas/widgets/ResizeHandle.module.css +4 -4
  226. package/src/internals/canvas/widgets/StorySetWidget.jsx +53 -25
  227. package/src/internals/canvas/widgets/StoryWidget.jsx +71 -56
  228. package/src/internals/canvas/widgets/StoryWidget.module.css +22 -20
  229. package/src/internals/canvas/widgets/TerminalReadWidget.jsx +13 -15
  230. package/src/internals/canvas/widgets/TerminalReadWidget.module.css +4 -4
  231. package/src/internals/canvas/widgets/TerminalWidget.jsx +56 -45
  232. package/src/internals/canvas/widgets/TerminalWidget.module.css +10 -10
  233. package/src/internals/canvas/widgets/TilesWidget.module.css +17 -17
  234. package/src/internals/canvas/widgets/WidgetChrome.jsx +1 -1
  235. package/src/internals/canvas/widgets/WidgetChrome.module.css +76 -61
  236. package/src/internals/canvas/widgets/WidgetWrapper.module.css +2 -2
  237. package/src/internals/canvas/widgets/embedOverlay.module.css +14 -4
  238. package/src/internals/canvas/widgets/embedTheme.js +12 -104
  239. package/src/internals/canvas/widgets/expandUtils.js +19 -19
  240. package/src/internals/canvas/widgets/normalizeLegacyEmbedSrc.js +74 -0
  241. package/src/internals/canvas/widgets/widgetConfig.js +5 -5
  242. package/src/internals/context.jsx +22 -1
  243. package/src/internals/context.test.jsx +47 -0
  244. package/src/internals/hooks/useArtifactIndex.js +31 -0
  245. package/src/internals/hooks/useArtifactIndex.test.js +45 -0
  246. package/src/internals/hooks/usePrototypeReloadGuard.js +14 -8
  247. package/src/internals/index.js +6 -0
  248. package/src/internals/loadConsumerWrapper.js +60 -0
  249. package/src/internals/story/ComponentSetPage.jsx +75 -34
  250. package/src/internals/story/ComponentSetPage.module.css +14 -14
  251. package/src/internals/story/StoryPage.jsx +16 -25
  252. package/src/internals/story/StoryPage.module.css +2 -2
  253. package/src/internals/vite/data-plugin.js +317 -149
  254. package/src/internals/vite/data-plugin.test.js +11 -11
  255. package/{scaffold/storyboard.config.json → storyboard.config.json} +25 -0
  256. package/terminal.config.json +1 -1
  257. package/src/core/lib/components/ui/card/card-action.jsx +0 -11
  258. package/src/core/lib/components/ui/card/card-content.jsx +0 -11
  259. package/src/core/lib/components/ui/card/card-description.jsx +0 -11
  260. package/src/core/lib/components/ui/card/card-footer.jsx +0 -11
  261. package/src/core/lib/components/ui/card/card-header.jsx +0 -19
  262. package/src/core/lib/components/ui/card/card-title.jsx +0 -11
  263. package/src/core/lib/components/ui/card/card.jsx +0 -17
  264. package/src/core/lib/components/ui/card/index.js +0 -25
  265. package/src/core/lib/components/ui/collapsible/collapsible-content.jsx +0 -7
  266. package/src/core/lib/components/ui/collapsible/collapsible-trigger.jsx +0 -7
  267. package/src/core/lib/components/ui/collapsible/collapsible.jsx +0 -7
  268. package/src/core/lib/components/ui/collapsible/index.js +0 -13
  269. package/src/core/lib/components/ui/dialog/dialog-close.jsx +0 -7
  270. package/src/core/lib/components/ui/dialog/dialog-description.jsx +0 -15
  271. package/src/core/lib/components/ui/dialog/dialog-footer.jsx +0 -23
  272. package/src/core/lib/components/ui/dialog/dialog-header.jsx +0 -11
  273. package/src/core/lib/components/ui/dialog/dialog-overlay.jsx +0 -15
  274. package/src/core/lib/components/ui/dialog/dialog-portal.jsx +0 -4
  275. package/src/core/lib/components/ui/dialog/dialog-title.jsx +0 -15
  276. package/src/core/lib/components/ui/popover/index.js +0 -28
  277. package/src/core/lib/components/ui/popover/popover-close.jsx +0 -7
  278. package/src/core/lib/components/ui/popover/popover-content.jsx +0 -22
  279. package/src/core/lib/components/ui/popover/popover-description.jsx +0 -11
  280. package/src/core/lib/components/ui/popover/popover-header.jsx +0 -11
  281. package/src/core/lib/components/ui/popover/popover-portal.jsx +0 -4
  282. package/src/core/lib/components/ui/popover/popover-title.jsx +0 -11
  283. package/src/core/lib/components/ui/popover/popover-trigger.jsx +0 -8
  284. package/src/core/lib/components/ui/popover/popover.jsx +0 -4
  285. package/src/core/lib/components/ui/select/index.js +0 -37
  286. package/src/core/lib/components/ui/select/select-content.jsx +0 -30
  287. package/src/core/lib/components/ui/select/select-group-heading.jsx +0 -17
  288. package/src/core/lib/components/ui/select/select-group.jsx +0 -15
  289. package/src/core/lib/components/ui/select/select-item.jsx +0 -26
  290. package/src/core/lib/components/ui/select/select-label.jsx +0 -11
  291. package/src/core/lib/components/ui/select/select-portal.jsx +0 -4
  292. package/src/core/lib/components/ui/select/select-scroll-down-button.jsx +0 -18
  293. package/src/core/lib/components/ui/select/select-scroll-up-button.jsx +0 -18
  294. package/src/core/lib/components/ui/select/select-separator.jsx +0 -15
  295. package/src/core/lib/components/ui/select/select-trigger.jsx +0 -25
  296. package/src/core/lib/components/ui/select/select.jsx +0 -4
  297. package/src/core/lib/components/ui/sheet/index.js +0 -34
  298. package/src/core/lib/components/ui/sheet/sheet-close.jsx +0 -7
  299. package/src/core/lib/components/ui/sheet/sheet-content.jsx +0 -35
  300. package/src/core/lib/components/ui/sheet/sheet-description.jsx +0 -15
  301. package/src/core/lib/components/ui/sheet/sheet-footer.jsx +0 -11
  302. package/src/core/lib/components/ui/sheet/sheet-header.jsx +0 -11
  303. package/src/core/lib/components/ui/sheet/sheet-overlay.jsx +0 -15
  304. package/src/core/lib/components/ui/sheet/sheet-portal.jsx +0 -4
  305. package/src/core/lib/components/ui/sheet/sheet-title.jsx +0 -15
  306. package/src/core/lib/components/ui/sheet/sheet-trigger.jsx +0 -7
  307. package/src/core/lib/components/ui/sheet/sheet.jsx +0 -4
  308. package/src/core/lib/components/ui/toggle/index.js +0 -8
  309. package/src/core/lib/components/ui/toggle/toggle.jsx +0 -36
  310. package/src/core/lib/components/ui/toggle-group/index.js +0 -10
  311. package/src/core/lib/components/ui/toggle-group/toggle-group-item.jsx +0 -29
  312. package/src/core/lib/components/ui/toggle-group/toggle-group.jsx +0 -43
  313. package/src/internals/canvas/StoryErrorBoundary.jsx +0 -47
  314. package/src/internals/canvas/WebGLContextPool.jsx +0 -291
  315. package/src/internals/canvas/WebGLContextPool.test.jsx +0 -165
  316. package/src/internals/canvas/componentIsolate.jsx +0 -144
  317. package/src/internals/canvas/componentSetIsolate.jsx +0 -300
  318. package/src/internals/canvas/widgets/ComponentSetWidget.module.css +0 -89
  319. package/src/internals/canvas/widgets/InlineStoryRenderer.jsx +0 -129
  320. package/src/internals/canvas/widgets/InlineStoryRenderer.test.jsx +0 -68
  321. package/src/internals/canvas/widgets/StorySetWidget.module.css +0 -89
  322. package/src/primer/ThemeSync.jsx +0 -73
  323. package/src/primer/index.js +0 -1
@@ -94,7 +94,7 @@ function ItemIcon({ type, toolIcon, toolMeta }) {
94
94
  const entry = toolIcon || icons[type] || icons.fallback || 'feather/hexagon'
95
95
  const iconName = typeof entry === 'object' ? entry.name : entry
96
96
  const meta = toolMeta || (typeof entry === 'object' ? entry.meta : undefined)
97
- return <Icon name={iconName} size={ICON_SIZE} color="var(--fgColor-muted, #656d76)" {...(meta || {})} />
97
+ return <Icon name={iconName} size={ICON_SIZE} color="var(--color-foreground-muted, #656d76)" {...(meta || {})} />
98
98
  }
99
99
 
100
100
  function AvatarIcon({ username }) {
@@ -433,11 +433,17 @@ function buildDynamicSection(section, prefix, onNavigateToPage, onCreateAction)
433
433
  if (section.source === 'create') {
434
434
  const isLocalDev = typeof window !== 'undefined' && window.__SB_LOCAL_DEV__ === true
435
435
  if (!isLocalDev) return null
436
+ // Same workshop.features.create<X> flags that control the workspace
437
+ // Create-Artifact menu. Default true; set to false in
438
+ // storyboard.config.json to hide that artifact type here too.
439
+ const features = getConfig('workshop')?.features || {}
440
+ const isEnabled = (flag) => features[flag] !== false
436
441
  const createItems = [
437
- { id: 'create:canvas', children: 'Canvas', keywords: ['create', 'canvas', 'new', 'board'], itemType: 'create', onClick: () => onCreateAction?.('Canvas') },
438
- { id: 'create:prototype', children: 'Prototype', keywords: ['create', 'prototype', 'new', 'page'], itemType: 'create', onClick: () => onCreateAction?.('Prototype') },
439
- { id: 'create:component', children: 'Component', keywords: ['create', 'component', 'new', 'story'], itemType: 'create', onClick: () => onCreateAction?.('Component') },
440
- ]
442
+ { id: 'create:canvas', children: 'Canvas', keywords: ['create', 'canvas', 'new', 'board'], itemType: 'create', flag: 'createCanvas', onClick: () => onCreateAction?.('Canvas') },
443
+ { id: 'create:prototype', children: 'Prototype', keywords: ['create', 'prototype', 'new', 'page'], itemType: 'create', flag: 'createPrototype', onClick: () => onCreateAction?.('Prototype') },
444
+ { id: 'create:component', children: 'Component', keywords: ['create', 'component', 'new', 'story'], itemType: 'create', flag: 'createComponent', onClick: () => onCreateAction?.('Component') },
445
+ ].filter(it => isEnabled(it.flag))
446
+ if (createItems.length === 0) return null
441
447
  return { group: { heading: section.title, id: `cfg:${section.id}`, items: createItems } }
442
448
  }
443
449
 
@@ -447,25 +453,31 @@ function buildDynamicSection(section, prefix, onNavigateToPage, onCreateAction)
447
453
  if (!isLocalDev) return null
448
454
  const isCanvasRoute = typeof window !== 'undefined' && window.location.pathname.includes('/canvas/')
449
455
  if (!isCanvasRoute) return null
450
- // Note: 'story' is intentionally NOT hidden here it now has a proper
451
- // artifact picker dialog (see WIDGET_TYPES_WITH_PICKER below). The
452
- // deprecated 'component' widget type is hidden in favor of 'story'.
453
- const hiddenTypes = new Set(['link-preview', 'image', 'figma-embed', 'codepen-embed', 'component', 'terminal-read', 'agent'])
454
- const items = Object.entries(widgetTypes).filter(([type]) => !hiddenTypes.has(type)).map(([type, def]) => ({
455
- id: `create-widget:${type}`,
456
- children: def.label,
457
- index_tags: [`Add ${def.label}`],
458
- keywords: ['add', 'widget', 'create', type, def.label.toLowerCase()],
459
- itemType: type,
460
- onClick: () => {
461
- if (WIDGET_TYPES_WITH_PICKER.has(type)) {
462
- // Open the artifact picker dialog instead of creating an empty widget.
463
- document.dispatchEvent(new CustomEvent('storyboard:open-widget-artifact-dialog', { detail: { type } }))
464
- } else {
465
- document.dispatchEvent(new CustomEvent('storyboard:canvas:add-widget', { detail: { type } }))
466
- }
467
- },
468
- }))
456
+ // 'story' is shown as "Component"the StoryPicker auto-upgrades
457
+ // multi-export stories to a component-set widget, so we expose a single
458
+ // unified "Component" entry instead of separate Story / Component Set items.
459
+ // The deprecated 'component' widget type and the raw 'component-set' entry
460
+ // are both hidden in favor of this consolidated flow.
461
+ const hiddenTypes = new Set(['link-preview', 'image', 'figma-embed', 'codepen-embed', 'component', 'component-set', 'terminal-read', 'agent'])
462
+ const labelOverrides = { story: 'Component' }
463
+ const items = Object.entries(widgetTypes).filter(([type]) => !hiddenTypes.has(type)).map(([type, def]) => {
464
+ const label = labelOverrides[type] || def.label
465
+ return {
466
+ id: `create-widget:${type}`,
467
+ children: label,
468
+ index_tags: [`Add ${label}`],
469
+ keywords: ['add', 'widget', 'create', type, label.toLowerCase(), def.label.toLowerCase()],
470
+ itemType: type === 'story' ? 'component' : type,
471
+ onClick: () => {
472
+ if (WIDGET_TYPES_WITH_PICKER.has(type)) {
473
+ // Open the artifact picker dialog instead of creating an empty widget.
474
+ document.dispatchEvent(new CustomEvent('storyboard:open-widget-artifact-dialog', { detail: { type } }))
475
+ } else {
476
+ document.dispatchEvent(new CustomEvent('storyboard:canvas:add-widget', { detail: { type } }))
477
+ }
478
+ },
479
+ }
480
+ })
469
481
 
470
482
  // Build agent submenu from canvas.agents config
471
483
  const subPages = []
@@ -1289,8 +1301,8 @@ export default function StoryboardCommandPalette({ basePath }) {
1289
1301
  Object.assign(el.style, {
1290
1302
  position: 'fixed', top: '50%', left: '50%', transform: 'translate(-50%, -50%)',
1291
1303
  zIndex: '10000', padding: '0.625rem 1rem', borderRadius: '0.5rem',
1292
- background: 'var(--bgColor-emphasis, #1f2328)', color: 'var(--fgColor-onEmphasis, #fff)',
1293
- fontSize: '0.8125rem', fontFamily: 'var(--fontStack-sansSerif, system-ui)',
1304
+ background: 'var(--color-background-emphasis, #1f2328)', color: 'var(--color-foreground-on-emphasis, #fff)',
1305
+ fontSize: '0.8125rem', fontFamily: 'var(--font-sans, system-ui)',
1294
1306
  opacity: '0', transition: 'opacity 0.15s ease',
1295
1307
  pointerEvents: 'none',
1296
1308
  })
@@ -1367,7 +1379,7 @@ export default function StoryboardCommandPalette({ basePath }) {
1367
1379
  value={itemValue(item)}
1368
1380
  onSelect={item.onSelect}
1369
1381
  >
1370
- {item.icon && <Icon name={item.icon} size={ICON_SIZE} color="var(--fgColor-muted, #656d76)" />}
1382
+ {item.icon && <Icon name={item.icon} size={ICON_SIZE} color="var(--color-foreground-muted, #656d76)" />}
1371
1383
  <span style={{ display: 'flex', width: '100%', justifyContent: 'space-between', alignItems: 'center' }}>
1372
1384
  <span>{item.label}</span>
1373
1385
  {(item.isActiveToggle || item.isActiveTheme) && <span>✓</span>}
@@ -1446,7 +1458,7 @@ export default function StoryboardCommandPalette({ basePath }) {
1446
1458
  <AvatarIcon username={group.author} />
1447
1459
  <span style={{ display: 'flex', width: '100%', justifyContent: 'space-between', alignItems: 'center' }}>
1448
1460
  <span>{item.label}</span>
1449
- <span style={{ fontSize: '12px', color: 'var(--fgColor-muted, #999)' }}>{item.type}</span>
1461
+ <span style={{ fontSize: '12px', color: 'var(--color-foreground-muted, #999)' }}>{item.type}</span>
1450
1462
  </span>
1451
1463
  </Command.Item>
1452
1464
  ))}
@@ -1473,7 +1485,7 @@ export default function StoryboardCommandPalette({ basePath }) {
1473
1485
  setActivePage('root')
1474
1486
  }}
1475
1487
  >
1476
- {opt.icon && <Icon name={opt.icon} size={ICON_SIZE} color="var(--fgColor-muted, #656d76)" />}
1488
+ {opt.icon && <Icon name={opt.icon} size={ICON_SIZE} color="var(--color-foreground-muted, #656d76)" />}
1477
1489
  {opt.toolHandler === 'core:theme' && opt.value === currentTheme
1478
1490
  ? <span style={{ display: 'flex', width: '100%', justifyContent: 'space-between', alignItems: 'center' }}><span>{opt.label}</span><span>✓</span></span>
1479
1491
  : opt.label}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * CreateArtifactForm — shared form body for the artifact create UI.
3
+ *
4
+ * Wraps `ArtifactForm` with the data-loading, gh-author prefill, payload
5
+ * shaping, and post-submit navigation logic. Used by both the in-app
6
+ * modal (`CreateDialog`) and the standalone full-page route
7
+ * (`CreatePage`). Picker mode (no `type`) is supported — ArtifactForm
8
+ * renders its TypeSelector and the submit handler resolves the schema
9
+ * from the form callback.
10
+ */
11
+ import { useState, useEffect, useMemo } from 'react'
12
+ import ArtifactForm, { ARTIFACT_SCHEMAS, isFieldVisible } from '../ArtifactForm/ArtifactForm.jsx'
13
+ import { resolveSchemaKey, withBase } from './createHelpers.js'
14
+
15
+ export default function CreateArtifactForm({
16
+ type,
17
+ basePath,
18
+ onClose,
19
+ hideHeader = true,
20
+ }) {
21
+ const schemaKey = resolveSchemaKey(type)
22
+ const isPicker = schemaKey === null
23
+ const fixedSchema = schemaKey ? ARTIFACT_SCHEMAS[schemaKey] : null
24
+
25
+ const [prototypes, setPrototypes] = useState([])
26
+ const [partials, setPartials] = useState([])
27
+ const [ghLogin, setGhLogin] = useState(null)
28
+
29
+ // In picker mode we don't yet know the schema, so load everything that
30
+ // any schema might need. For a fixed type we only load what's required.
31
+ const needsPrototypes = useMemo(() => {
32
+ if (isPicker) return true
33
+ return fixedSchema?.fields.some(f => f.dynamic === 'prototypes') || false
34
+ }, [isPicker, fixedSchema])
35
+
36
+ const needsPartials = useMemo(() => {
37
+ if (isPicker) return true
38
+ return fixedSchema?.fields.some(f => f.dynamic === 'partials') || false
39
+ }, [isPicker, fixedSchema])
40
+
41
+ const needsAuthor = useMemo(() => {
42
+ if (isPicker) return true
43
+ return fixedSchema?.fields.some(f => f.name === 'author') || false
44
+ }, [isPicker, fixedSchema])
45
+
46
+ useEffect(() => {
47
+ if (!needsPrototypes) return
48
+ const apiBase = (basePath || '/').replace(/\/+$/, '')
49
+ fetch(`${apiBase}/_storyboard/artifact/list?type=prototype`)
50
+ .then(r => (r.ok ? r.json() : null))
51
+ .then(data => { if (data?.items) setPrototypes(data.items.map(p => p.name)) })
52
+ .catch(() => {})
53
+ }, [needsPrototypes, basePath])
54
+
55
+ useEffect(() => {
56
+ if (!needsPartials) return
57
+ const apiBase = (basePath || '/').replace(/\/+$/, '')
58
+ fetch(`${apiBase}/_storyboard/workshop/prototypes`)
59
+ .then(r => (r.ok ? r.json() : null))
60
+ .then(data => {
61
+ if (!data?.partials) return
62
+ // Group by scope+kind: "Templates" / "Recipes" for global, "<proto> / Templates" etc. for local.
63
+ const opts = data.partials.map(p => {
64
+ const kindLabel = p.kind === 'recipe' ? 'Recipes' : 'Templates'
65
+ const group = p.scope === 'global'
66
+ ? kindLabel
67
+ : `${p.folder ? p.folder + ' / ' : ''}${p.prototype || 'local'} / ${kindLabel}`
68
+ return { value: p.id, label: p.name, group }
69
+ })
70
+ setPartials(opts)
71
+ })
72
+ .catch(() => {})
73
+ }, [needsPartials, basePath])
74
+
75
+ useEffect(() => {
76
+ if (!needsAuthor) return
77
+ const apiBase = (basePath || '/').replace(/\/+$/, '')
78
+ fetch(`${apiBase}/_storyboard/git-user`)
79
+ .then(r => (r.ok ? r.json() : null))
80
+ .then(data => { if (data?.login) setGhLogin(data.login) })
81
+ .catch(() => {})
82
+ }, [needsAuthor, basePath])
83
+
84
+ // Late-arriving gh login is merged into empty fields inside ArtifactForm.
85
+ const initialValues = useMemo(() => {
86
+ if (!needsAuthor || !ghLogin) return undefined
87
+ return { author: ghLogin }
88
+ }, [needsAuthor, ghLogin])
89
+
90
+ if (!isPicker && !fixedSchema) return null
91
+
92
+ async function handleSubmit({ type: t, values }) {
93
+ const apiBase = (basePath || '/').replace(/\/+$/, '')
94
+ const endpoint = `${apiBase}/_storyboard/artifact/`
95
+
96
+ // In picker mode the schema is decided by the form; resolve it now.
97
+ const submittedSchema = ARTIFACT_SCHEMAS[t] || fixedSchema
98
+ if (!submittedSchema) throw new Error(`Unknown artifact type: ${t}`)
99
+
100
+ const payload = { type: t }
101
+ for (const field of submittedSchema.fields) {
102
+ // Skip UI-only fields (e.g. the `external` toggle on prototype —
103
+ // the server infers external mode from the presence of `url`).
104
+ if (field.uiOnly) continue
105
+ // Skip fields hidden by `showIf` so we never send a stale value
106
+ // for a field the user can't see (e.g. `url` when external is off).
107
+ if (!isFieldVisible(field, values)) continue
108
+ const val = values[field.name]
109
+ if (field.type === 'checkbox') {
110
+ if (val) payload[field.name] = true
111
+ } else if (typeof val === 'string') {
112
+ const trimmed = val.trim()
113
+ if (trimmed) payload[field.name] = trimmed
114
+ } else if (val != null) {
115
+ payload[field.name] = val
116
+ }
117
+ }
118
+
119
+ const res = await fetch(endpoint, {
120
+ method: 'POST',
121
+ headers: { 'Content-Type': 'application/json' },
122
+ body: JSON.stringify(payload),
123
+ })
124
+ if (!res.ok) {
125
+ const data = await res.json().catch(() => null)
126
+ throw new Error(data?.error || `Request failed (${res.status})`)
127
+ }
128
+ const data = await res.json().catch(() => ({}))
129
+ // Navigate only if the server gave us an explicit route. Types without
130
+ // a route (object/record/component) just close the form.
131
+ if (data.route) {
132
+ window.location.href = withBase(basePath, data.route)
133
+ } else {
134
+ onClose?.()
135
+ }
136
+ }
137
+
138
+ return (
139
+ <ArtifactForm
140
+ type={isPicker ? undefined : schemaKey}
141
+ onSubmit={handleSubmit}
142
+ onCancel={onClose}
143
+ dynamicOptions={{ prototypes, partials }}
144
+ initialValues={initialValues}
145
+ hideHeader={hideHeader}
146
+ />
147
+ )
148
+ }
149
+
150
+ export { ARTIFACT_SCHEMAS }
@@ -1,125 +1,35 @@
1
1
  /**
2
- * CreateDialog — Primer Dialog wrapper around the unified ArtifactForm.
2
+ * CreateDialog — Primer Dialog wrapper around CreateArtifactForm.
3
3
  *
4
- * The form, fields, and validation are entirely schema-driven via
5
- * ARTIFACT_SCHEMAS. This component supplies modal chrome (Primer Dialog),
6
- * fetches dynamic select options (e.g. prototype list), POSTs to the
7
- * artifact API, and navigates to the resulting route on success.
4
+ * The form, fields, validation, data-loading, and submission live in
5
+ * `CreateArtifactForm`. This component just supplies the modal chrome.
8
6
  */
9
- import { useState, useEffect, useMemo } from 'react'
10
- import { Dialog } from '@primer/react/experimental'
11
- import ArtifactForm, { ARTIFACT_SCHEMAS } from '../ArtifactForm/ArtifactForm.jsx'
12
-
13
- // Map UI command-palette type ids (PascalCase) to schema keys (lowercase)
14
- const TYPE_KEY_MAP = {
15
- Prototype: 'prototype', Canvas: 'canvas', Component: 'component',
16
- Flow: 'flow', Object: 'object', Record: 'record', Page: 'page',
17
- }
18
-
19
- function withBase(base, route) {
20
- const b = (base || '/').replace(/\/+$/, '')
21
- const r = route?.startsWith('/') ? route : `/${route || ''}`
22
- return b === '' || b === '/' ? r : `${b}${r}`
23
- }
7
+ import Dialog from '../Dialog.jsx'
8
+ import CreateArtifactForm, { ARTIFACT_SCHEMAS } from './CreateArtifactForm.jsx'
9
+ import { resolveSchemaKey, TYPE_KEY_MAP } from './createHelpers.js'
24
10
 
25
11
  export default function CreateDialog({ type, basePath, onClose }) {
26
- const schemaKey = type ? (TYPE_KEY_MAP[type] || String(type).toLowerCase()) : null
27
- const schema = schemaKey ? ARTIFACT_SCHEMAS[schemaKey] : null
28
- const [prototypes, setPrototypes] = useState([])
29
- const [partials, setPartials] = useState([])
30
-
31
- const needsPrototypes = useMemo(() => {
32
- if (!schema) return false
33
- return schema.fields.some(f => f.dynamic === 'prototypes')
34
- }, [schema])
12
+ // `type === null`/`undefined` means "no dialog requested" render nothing.
13
+ // Explicit `'Any'` (or empty string) means picker mode.
14
+ if (type == null) return null
35
15
 
36
- const needsPartials = useMemo(() => {
37
- if (!schema) return false
38
- return schema.fields.some(f => f.dynamic === 'partials')
39
- }, [schema])
40
-
41
- useEffect(() => {
42
- if (!needsPrototypes || !schemaKey) return
43
- const apiBase = (basePath || '/').replace(/\/+$/, '')
44
- fetch(`${apiBase}/_storyboard/artifact/list?type=prototype`)
45
- .then(r => (r.ok ? r.json() : null))
46
- .then(data => { if (data?.items) setPrototypes(data.items.map(p => p.name)) })
47
- .catch(() => {})
48
- }, [needsPrototypes, schemaKey, basePath])
49
-
50
- useEffect(() => {
51
- if (!needsPartials || !schemaKey) return
52
- const apiBase = (basePath || '/').replace(/\/+$/, '')
53
- fetch(`${apiBase}/_storyboard/workshop/prototypes`)
54
- .then(r => (r.ok ? r.json() : null))
55
- .then(data => {
56
- if (!data?.partials) return
57
- // Map workshop format → grouped select options.
58
- // Group by scope+kind: "Templates" / "Recipes" for global, "<proto> / Templates" etc. for local.
59
- const opts = data.partials.map(p => {
60
- const kindLabel = p.kind === 'recipe' ? 'Recipes' : 'Templates'
61
- const group = p.scope === 'global'
62
- ? kindLabel
63
- : `${p.folder ? p.folder + ' / ' : ''}${p.prototype || 'local'} / ${kindLabel}`
64
- return { value: p.id, label: p.name, group }
65
- })
66
- setPartials(opts)
67
- })
68
- .catch(() => {})
69
- }, [needsPartials, schemaKey, basePath])
70
-
71
- if (!schemaKey || !schema) return null
72
-
73
- async function handleSubmit({ type: t, values }) {
74
- const apiBase = (basePath || '/').replace(/\/+$/, '')
75
- const endpoint = `${apiBase}/_storyboard/artifact/`
76
-
77
- // Build payload — include checkboxes that are true, trimmed strings, raw selects
78
- const payload = { type: t }
79
- for (const field of schema.fields) {
80
- const val = values[field.name]
81
- if (field.type === 'checkbox') {
82
- if (val) payload[field.name] = true
83
- } else if (typeof val === 'string') {
84
- const trimmed = val.trim()
85
- if (trimmed) payload[field.name] = trimmed
86
- } else if (val != null) {
87
- payload[field.name] = val
88
- }
89
- }
16
+ const schemaKey = resolveSchemaKey(type)
17
+ const isPicker = schemaKey === null
18
+ const schema = schemaKey ? ARTIFACT_SCHEMAS[schemaKey] : null
90
19
 
91
- const res = await fetch(endpoint, {
92
- method: 'POST',
93
- headers: { 'Content-Type': 'application/json' },
94
- body: JSON.stringify(payload),
95
- })
96
- if (!res.ok) {
97
- const data = await res.json().catch(() => null)
98
- throw new Error(data?.error || `Request failed (${res.status})`)
99
- }
100
- const data = await res.json().catch(() => ({}))
101
- // Only navigate when the server gives us an explicit route. Falling back
102
- // to data.path here is wrong — that's a filesystem path (e.g. "src/canvas"),
103
- // not a URL route. Types without a route (object/record/component) just close.
104
- if (data.route) {
105
- window.location.href = withBase(basePath, data.route)
106
- } else {
107
- onClose?.()
108
- }
109
- }
20
+ if (!isPicker && !schema) return null
110
21
 
111
22
  return (
112
23
  <Dialog
113
- title={`New ${schema.label}`}
114
- subtitle={schema.description}
24
+ title={isPicker ? 'New artifact' : `New ${schema.label}`}
25
+ subtitle={isPicker ? 'Pick an artifact type to create.' : schema.description}
115
26
  onClose={onClose}
116
27
  width="large"
117
28
  >
118
- <ArtifactForm
119
- type={schemaKey}
120
- onSubmit={handleSubmit}
121
- onCancel={onClose}
122
- dynamicOptions={{ prototypes, partials }}
29
+ <CreateArtifactForm
30
+ type={type}
31
+ basePath={basePath}
32
+ onClose={onClose}
123
33
  hideHeader
124
34
  />
125
35
  </Dialog>
@@ -127,4 +37,4 @@ export default function CreateDialog({ type, basePath, onClose }) {
127
37
  }
128
38
 
129
39
  // Re-export for canvas/workspace integrations
130
- export { ARTIFACT_SCHEMAS as CREATE_SCHEMAS }
40
+ export { ARTIFACT_SCHEMAS as CREATE_SCHEMAS, TYPE_KEY_MAP }
@@ -12,24 +12,24 @@
12
12
  width: 100%;
13
13
  padding: 8px 10px;
14
14
  font: inherit;
15
- color: var(--fgColor-default);
16
- background: var(--bgColor-inset, var(--color-canvas-inset));
17
- border: 1px solid var(--borderColor-default, var(--color-border-default));
15
+ color: var(--color-foreground);
16
+ background: var(--color-background-inset, var(--color-background-inset));
17
+ border: 1px solid var(--color-border, var(--color-border));
18
18
  border-radius: 6px;
19
19
  outline: none;
20
20
  }
21
21
 
22
22
  .sb-wad-filter:focus,
23
23
  .sb-wad-custom-input:focus {
24
- border-color: var(--borderColor-accent-emphasis, var(--color-accent-emphasis));
25
- box-shadow: 0 0 0 3px var(--bgColor-accent-muted, rgba(9, 105, 218, 0.2));
24
+ border-color: var(--color-border-accent-emphasis, var(--color-background-accent-emphasis));
25
+ box-shadow: 0 0 0 3px var(--color-background-accent-muted, rgba(9, 105, 218, 0.2));
26
26
  }
27
27
 
28
28
  .sb-wad-list {
29
29
  flex: 1 1 auto;
30
30
  min-height: 0;
31
31
  overflow-y: auto;
32
- border: 1px solid var(--borderColor-muted, var(--color-border-muted));
32
+ border: 1px solid var(--color-border-muted, var(--color-border-muted));
33
33
  border-radius: 6px;
34
34
  padding: 4px;
35
35
  }
@@ -44,7 +44,7 @@
44
44
  font-weight: 600;
45
45
  text-transform: uppercase;
46
46
  letter-spacing: 0.04em;
47
- color: var(--fgColor-muted);
47
+ color: var(--color-foreground-muted);
48
48
  }
49
49
 
50
50
  .sb-wad-item {
@@ -56,7 +56,7 @@
56
56
  padding: 8px 10px;
57
57
  text-align: left;
58
58
  font: inherit;
59
- color: var(--fgColor-default);
59
+ color: var(--color-foreground);
60
60
  background: transparent;
61
61
  border: 0;
62
62
  border-radius: 4px;
@@ -69,7 +69,7 @@
69
69
 
70
70
  .sb-wad-item:hover,
71
71
  .sb-wad-item:focus-visible {
72
- background: var(--bgColor-neutral-muted, var(--color-neutral-subtle));
72
+ background: var(--color-background-neutral-muted, var(--color-background-neutral-muted));
73
73
  outline: none;
74
74
  }
75
75
 
@@ -84,13 +84,13 @@
84
84
  .sb-wad-item-hint {
85
85
  flex: 0 0 auto;
86
86
  font-size: 12px;
87
- color: var(--fgColor-muted);
88
- font-family: var(--fontStack-monospace, ui-monospace, monospace);
87
+ color: var(--color-foreground-muted);
88
+ font-family: var(--font-mono, ui-monospace, monospace);
89
89
  }
90
90
 
91
91
  .sb-wad-empty {
92
92
  padding: 16px;
93
- color: var(--fgColor-muted);
93
+ color: var(--color-foreground-muted);
94
94
  text-align: center;
95
95
  font-size: 13px;
96
96
  }
@@ -99,7 +99,7 @@
99
99
  display: flex;
100
100
  flex-direction: column;
101
101
  gap: 6px;
102
- border-top: 1px solid var(--borderColor-muted, var(--color-border-muted));
102
+ border-top: 1px solid var(--color-border-muted, var(--color-border-muted));
103
103
  padding-top: 12px;
104
104
  }
105
105
 
@@ -108,7 +108,7 @@
108
108
  font-weight: 600;
109
109
  text-transform: uppercase;
110
110
  letter-spacing: 0.04em;
111
- color: var(--fgColor-muted);
111
+ color: var(--color-foreground-muted);
112
112
  }
113
113
 
114
114
  .sb-wad-custom-row {
@@ -119,8 +119,8 @@
119
119
  .sb-wad-submit {
120
120
  padding: 8px 14px;
121
121
  font: inherit;
122
- color: var(--fgColor-onEmphasis, white);
123
- background: var(--bgColor-accent-emphasis, var(--color-accent-emphasis));
122
+ color: var(--color-foreground-on-emphasis, white);
123
+ background: var(--color-background-accent-emphasis, var(--color-background-accent-emphasis));
124
124
  border: 0;
125
125
  border-radius: 6px;
126
126
  cursor: pointer;
@@ -8,7 +8,7 @@
8
8
  * `storyboard:canvas:add-widget` with full props.
9
9
  */
10
10
  import { useState, useMemo, useEffect, useRef } from 'react'
11
- import { Dialog } from '@primer/react/experimental'
11
+ import Dialog from '../Dialog.jsx'
12
12
  import { buildPrototypeIndex, listStories, getStoryData } from '../../core/index.js'
13
13
  import './WidgetArtifactDialog.css'
14
14
 
@@ -25,9 +25,9 @@
25
25
  border-radius: 12px;
26
26
  overflow: hidden;
27
27
  box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
28
- background: var(--bgColor-default, #ffffff);
29
- color: var(--fgColor-default, #1f2328);
30
- border: 1px solid var(--borderColor-muted, #d1d9e0);
28
+ background: var(--color-background, #ffffff);
29
+ color: var(--color-foreground, #1f2328);
30
+ border: 1px solid var(--color-border-muted, #d1d9e0);
31
31
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
32
32
  outline: none;
33
33
  animation: cmdk-dialog-in 120ms ease-out;
@@ -49,15 +49,15 @@
49
49
  padding: 14px 16px;
50
50
  font-size: 15px;
51
51
  border: none;
52
- border-bottom: 1px solid var(--borderColor-muted, #d1d9e0);
52
+ border-bottom: 1px solid var(--color-border-muted, #d1d9e0);
53
53
  outline: none;
54
54
  background: transparent;
55
- color: var(--fgColor-default, #1f2328);
55
+ color: var(--color-foreground, #1f2328);
56
56
  font-family: inherit;
57
57
  }
58
58
 
59
59
  [cmdk-input]::placeholder {
60
- color: var(--fgColor-muted, #656d76);
60
+ color: var(--color-foreground-muted, #656d76);
61
61
  }
62
62
 
63
63
  /* ─── List ─── */
@@ -73,7 +73,7 @@
73
73
  font-weight: 600;
74
74
  text-transform: uppercase;
75
75
  letter-spacing: 0.05em;
76
- color: var(--fgColor-muted, #656d76);
76
+ color: var(--color-foreground-muted, #656d76);
77
77
  padding: 8px 8px 4px;
78
78
  user-select: none;
79
79
  }
@@ -89,16 +89,16 @@
89
89
  /* font-weight: 500; */
90
90
  cursor: pointer;
91
91
  user-select: none;
92
- color: var(--fgColor-default, #1f2328);
92
+ color: var(--color-foreground, #1f2328);
93
93
  transition: background 0.1s;
94
94
  }
95
95
 
96
96
  [cmdk-item][data-selected="true"] {
97
- background: var(--bgColor-neutral-muted, rgba(175, 184, 193, 0.2));
97
+ background: var(--color-background-neutral-muted, rgba(175, 184, 193, 0.2));
98
98
  }
99
99
 
100
100
  [cmdk-item]:active {
101
- background: var(--bgColor-neutral-muted, rgba(175, 184, 193, 0.3));
101
+ background: var(--color-background-neutral-muted, rgba(175, 184, 193, 0.3));
102
102
  }
103
103
 
104
104
  /* ─── Item tag (background badge) ─── */
@@ -106,8 +106,8 @@
106
106
  font-size: 11px;
107
107
  padding: 2px 6px;
108
108
  border-radius: 999px;
109
- background: var(--bgColor-neutral-muted, rgba(175, 184, 193, 0.2));
110
- color: var(--fgColor-muted, #656d76);
109
+ background: var(--color-background-neutral-muted, rgba(175, 184, 193, 0.2));
110
+ color: var(--color-foreground-muted, #656d76);
111
111
  white-space: nowrap;
112
112
  flex-shrink: 0;
113
113
  }
@@ -116,14 +116,14 @@
116
116
  [cmdk-separator] {
117
117
  height: 1px;
118
118
  margin: 4px 14px;
119
- background: var(--borderColor-muted, #d1d9e0);
119
+ background: var(--color-border-muted, #d1d9e0);
120
120
  }
121
121
 
122
122
  /* ─── Empty state ─── */
123
123
  [cmdk-empty] {
124
124
  padding: 2rem;
125
125
  text-align: center;
126
- color: var(--fgColor-muted, #656d76);
126
+ color: var(--color-foreground-muted, #656d76);
127
127
  font-size: 14px;
128
128
  }
129
129
 
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Map UI command-palette type ids (PascalCase) to schema keys (lowercase),
3
+ * and normalise consumer-supplied `type` values to a schema key.
4
+ *
5
+ * Kept in its own file so React Fast Refresh stays happy in
6
+ * `CreateArtifactForm.jsx` and `CreateDialog.jsx` (component-only modules).
7
+ */
8
+ export const TYPE_KEY_MAP = {
9
+ Prototype: 'prototype', Canvas: 'canvas', Component: 'component',
10
+ Flow: 'flow', Object: 'object', Record: 'record', Page: 'page',
11
+ }
12
+
13
+ /**
14
+ * Returns the schema key (lowercase) for a consumer-supplied type, or
15
+ * `null` when no fixed type was requested (picker mode).
16
+ */
17
+ export function resolveSchemaKey(type) {
18
+ if (!type || type === 'Any' || String(type).toLowerCase() === 'any') return null
19
+ return TYPE_KEY_MAP[type] || String(type).toLowerCase()
20
+ }
21
+
22
+ /**
23
+ * Prepend `base` (e.g. `/storyboard/`) to an artifact route. Used by the
24
+ * post-create navigation in `CreateArtifactForm`.
25
+ */
26
+ export function withBase(base, route) {
27
+ const b = (base || '/').replace(/\/+$/, '')
28
+ const r = route?.startsWith('/') ? route : `/${route || ''}`
29
+ return b === '' || b === '/' ? r : `${b}${r}`
30
+ }