@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.
- package/dist/storyboard-ui.css +1 -1
- package/dist/storyboard-ui.js +14128 -10953
- package/dist/storyboard-ui.js.map +1 -1
- package/dist/tailwind.css +1 -1
- package/dist/tiny-canvas.css +1 -1
- package/package.json +138 -128
- package/scaffold/AGENTS.md +9 -7
- package/scaffold/README.md +18 -0
- package/scaffold/deploy.yml +21 -0
- package/scaffold/gitignore +8 -14
- package/scaffold/preview.yml +40 -0
- package/scaffold/{manifest.json → scaffold.config.json} +73 -3
- package/scaffold/scripts/aggregate-artifacts.mjs +257 -0
- package/scaffold/skills/canvas/SKILL.md +1 -1
- package/scaffold/skills/migrate-0.5.0/SKILL.md +1 -1
- package/scaffold/skills/ship/SKILL.md +2 -2
- package/scaffold/skills/worktree/SKILL.md +1 -1
- package/scaffold/src/_prototype.jsx +17 -0
- package/scaffold/src/_story.jsx +13 -0
- package/scaffold/src/library/README.md +34 -0
- package/scaffold/src/library/_app.jsx +41 -0
- package/scaffold/src/library/_app.module.css +2 -0
- package/scaffold/src/library/create.jsx +10 -0
- package/scaffold/src/library/index.jsx +14 -0
- package/scaffold/src/library/mount.jsx +51 -0
- package/scaffold/src/library/prototypes-entry.jsx +57 -0
- package/scaffold/src/library/routes.jsx +205 -0
- package/scaffold/src/library/viewfinder.jsx +13 -0
- package/scaffold/src/library/workspace.jsx +17 -0
- package/scripts/aggregate-artifacts.mjs +257 -0
- package/src/canvas/style.css +16 -16
- package/src/core/artifact/operations.js +54 -15
- package/src/core/artifact/schemas/canvas.schema.json +7 -1
- package/src/core/autosync/server.test.js +1 -1
- package/src/core/canvas/hot-pool.js +21 -33
- package/src/core/canvas/materializer.js +39 -13
- package/src/core/canvas/selectedWidgets.js +1 -1
- package/src/core/canvas/server.js +376 -100
- package/src/core/canvas/server.test.js +472 -2
- package/src/core/canvas/terminal-server.js +144 -57
- package/src/core/canvas/undoRedo.js +174 -0
- package/src/core/canvas/undoRedo.test.js +250 -0
- package/src/core/cli/artifact.js +2 -0
- package/src/core/cli/buildManifest.js +34 -0
- package/src/core/cli/canvasRedo.js +44 -0
- package/src/core/cli/canvasUndo.js +40 -0
- package/src/core/cli/create.js +151 -23
- package/src/core/cli/dev.js +23 -35
- package/src/core/cli/index.js +21 -0
- package/src/core/cli/schemas.js +8 -4
- package/src/core/cli/serverUrl.js +24 -0
- package/src/core/cli/setup.js +14 -25
- package/src/core/cli/terminal-welcome.js +12 -6
- package/src/core/cli/updateVersion.js +42 -2
- package/src/core/cli/workleaf.js +140 -0
- package/src/core/comments/api.js +1 -1
- package/src/core/comments/queries.js +3 -0
- package/src/core/comments/ui/CommentWindow.jsx +3 -2
- package/src/core/comments/ui/comment-layout.css +14 -14
- package/src/core/data/artifactIndex.js +235 -0
- package/src/core/data/artifactIndex.test.js +203 -0
- package/src/core/data/artifactManifest.js +290 -0
- package/src/core/data/artifactManifest.test.js +207 -0
- package/src/core/data/viewfinder.js +47 -7
- package/src/core/index.js +24 -1
- package/src/core/inspector/highlighter.js +1 -1
- package/src/core/inspector/mouseMode.js +2 -2
- package/src/core/lib/components/ui/avatar/avatar-fallback.jsx +2 -2
- package/src/core/lib/components/ui/avatar/avatar-image.jsx +2 -2
- package/src/core/lib/components/ui/avatar/avatar.jsx +2 -2
- package/src/core/lib/components/ui/checkbox/checkbox.jsx +12 -9
- package/src/core/lib/components/ui/dialog/dialog-content.jsx +45 -31
- package/src/core/lib/components/ui/dialog/dialog-trigger.jsx +9 -5
- package/src/core/lib/components/ui/dialog/dialog.jsx +12 -3
- package/src/core/lib/components/ui/dialog/dialog.module.css +118 -0
- package/src/core/lib/components/ui/dialog/index.js +4 -34
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-group.jsx +3 -3
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-checkbox-item.jsx +19 -9
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-content.jsx +8 -8
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group-heading.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-group.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-item.jsx +15 -4
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-portal.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-group.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-radio-item.jsx +14 -7
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-separator.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-content.jsx +8 -4
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub-trigger.jsx +4 -4
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-sub.jsx +2 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu-trigger.jsx +8 -2
- package/src/core/lib/components/ui/dropdown-menu/dropdown-menu.jsx +2 -2
- package/src/core/lib/components/ui/label/label.jsx +1 -2
- package/src/core/lib/components/ui/panel/panel-close.jsx +7 -4
- package/src/core/lib/components/ui/panel/panel-content.jsx +7 -9
- package/src/core/lib/components/ui/panel/panel-title.jsx +3 -3
- package/src/core/lib/components/ui/panel/panel.jsx +11 -2
- package/src/core/lib/components/ui/separator/separator.jsx +6 -4
- package/src/core/lib/components/ui/tooltip/tooltip-content.jsx +7 -6
- package/src/core/lib/components/ui/tooltip/tooltip-trigger.jsx +13 -6
- package/src/core/lib/components/ui/tooltip/tooltip.jsx +5 -5
- package/src/core/modes/modes.css +4 -4
- package/src/core/mountStoryboardCore.js +287 -83
- package/src/core/mountStoryboardCore.test.js +198 -0
- package/src/core/rename-watcher/config.json +1 -1
- package/src/core/rename-watcher/watcher.js +330 -37
- package/src/core/rename-watcher/watcher.test.js +253 -0
- package/src/core/scaffold/fragments.js +287 -0
- package/src/core/scaffold/fragments.test.js +401 -0
- package/src/core/scaffold/index.js +291 -0
- package/src/core/scaffold/migrateLegacyGitignore.js +157 -0
- package/src/core/scaffold/scaffold-integration.test.js +247 -0
- package/src/core/scaffold.js +4 -97
- package/src/core/stores/canvasInteractionStore.js +120 -0
- package/src/core/stores/canvasInteractionStore.test.js +126 -0
- package/src/core/stores/configSchema.js +64 -8
- package/src/core/stores/configSchema.test.js +3 -0
- package/src/core/stores/customerModeConfig.js +24 -3
- package/src/core/stores/customerModeConfig.test.js +46 -0
- package/src/core/stores/presentationStore.js +118 -0
- package/src/core/stores/presentationStore.test.js +114 -0
- package/src/core/stores/recentArtifacts.js +49 -2
- package/src/core/stores/recentArtifacts.test.js +59 -6
- package/src/core/stores/themeBootstrap.js +264 -0
- package/src/core/stores/themeBootstrap.test.js +211 -0
- package/src/core/stores/themeStore.test.js +154 -0
- package/src/core/stores/themeStore.ts +235 -220
- package/src/core/stores/uiConfig.js +10 -2
- package/src/core/styles/generateThemesCss.js +63 -0
- package/src/core/styles/tailwind.css +150 -94
- package/src/core/styles/workspace-chrome.css +13 -0
- package/src/core/tools/handlers/paletteTheme.js +11 -8
- package/src/core/ui/ActionMenuButton.jsx +2 -1
- package/src/core/ui/AutosyncMenuButton.css +7 -7
- package/src/core/ui/BranchSelect.module.css +5 -5
- package/src/core/ui/CanvasCreateMenu.jsx +1 -19
- package/src/core/ui/ChromeSlot.jsx +92 -0
- package/src/core/ui/ChromeSlot.test.jsx +140 -0
- package/src/core/ui/CoreUIBar.css +5 -5
- package/src/core/ui/CoreUIBar.jsx +170 -142
- package/src/core/ui/InspectorPanel.css +5 -5
- package/src/core/ui/InspectorPanel.jsx +9 -9
- package/src/core/ui/PwaInstallBanner.css +5 -5
- package/src/core/ui/PwaInstallBanner.jsx +5 -5
- package/src/core/ui/ThemeMenuButton.jsx +45 -30
- package/src/core/ui/core-ui-colors.css +28 -66
- package/src/core/ui/sidepanel.css +12 -12
- package/src/core/vite/server-plugin.js +13 -0
- package/src/core/workleaf/cleanup.js +102 -0
- package/src/core/workleaf/create.js +199 -0
- package/src/core/workleaf/delete.js +101 -0
- package/src/core/workleaf/list.js +57 -0
- package/src/core/workleaf/merge.js +238 -0
- package/src/core/workleaf/paths.js +146 -0
- package/src/core/workleaf/paths.test.js +230 -0
- package/src/core/workshop/features/createCanvas/CreateCanvasForm.jsx +130 -34
- package/src/core/workshop/features/createFlow/server.js +5 -1
- package/src/core/workshop/features/createPrototype/server.js +5 -1
- package/src/core/workshop/features/templateIndex.js +28 -1
- package/src/core/worktree/port.js +48 -5
- package/src/core/worktree/port.test.js +42 -0
- package/src/internals/ArtifactForm/ArtifactForm.jsx +173 -112
- package/src/internals/ArtifactForm/ArtifactForm.module.css +51 -69
- package/src/internals/ArtifactForm/artifactSchemas.js +40 -5
- package/src/internals/AuthModal/AuthModal.module.css +34 -34
- package/src/internals/BaseUiForm/BaseUiForm.jsx +293 -0
- package/src/internals/BaseUiForm/BaseUiForm.module.css +542 -0
- package/src/internals/BranchBar/BranchBar.module.css +4 -4
- package/src/internals/BranchesDropdown/BranchesDropdown.jsx +69 -0
- package/src/internals/BranchesDropdown/BranchesDropdown.module.css +84 -0
- package/src/internals/CommandPalette/CommandPalette.jsx +41 -29
- package/src/internals/CommandPalette/CreateArtifactForm.jsx +150 -0
- package/src/internals/CommandPalette/CreateDialog.jsx +20 -110
- package/src/internals/CommandPalette/WidgetArtifactDialog.css +16 -16
- package/src/internals/CommandPalette/WidgetArtifactDialog.jsx +1 -1
- package/src/internals/CommandPalette/command-palette.css +14 -14
- package/src/internals/CommandPalette/createHelpers.js +30 -0
- package/src/internals/CreatePage/CreatePage.jsx +57 -0
- package/src/internals/CreatePage/CreatePage.module.css +34 -0
- package/src/internals/Dialog.jsx +51 -0
- package/src/internals/FlowError.module.css +5 -5
- package/src/internals/PrototypeErrorBoundary.module.css +15 -15
- package/src/internals/SimpleWorkspace/SimpleWorkspace.jsx +534 -0
- package/src/internals/SimpleWorkspace/SimpleWorkspace.module.css +323 -0
- package/src/internals/Tooltip.jsx +39 -0
- package/src/internals/Viewfinder.jsx +229 -64
- package/src/internals/Viewfinder.module.css +253 -182
- package/src/internals/canvas/CanvasControls.module.css +11 -11
- package/src/internals/canvas/CanvasPage.bridge.test.jsx +11 -37
- package/src/internals/canvas/CanvasPage.jsx +358 -217
- package/src/internals/canvas/CanvasPage.module.css +20 -19
- package/src/internals/canvas/CanvasPage.multiselect.test.jsx +39 -26
- package/src/internals/canvas/CanvasToolbar.module.css +11 -11
- package/src/internals/canvas/ConnectorLayer.jsx +39 -2
- package/src/internals/canvas/ConnectorLayer.module.css +10 -10
- package/src/internals/canvas/PageSelector.jsx +15 -1
- package/src/internals/canvas/PageSelector.module.css +41 -27
- package/src/internals/canvas/canvasApi.js +40 -5
- package/src/internals/canvas/canvasTheme.js +22 -111
- package/src/internals/canvas/isolation/createIsolationMiddleware.js +68 -0
- package/src/internals/canvas/isolation/mountIsolationApp.jsx +88 -0
- package/src/internals/canvas/isolation/prototypeRoutes.jsx +140 -0
- package/src/internals/canvas/isolation/prototypesEntry.jsx +28 -0
- package/src/internals/canvas/isolation/storiesEntry.jsx +20 -0
- package/src/internals/canvas/isolation/storyRoutes.jsx +55 -0
- package/src/internals/canvas/useUndoRedo.js +75 -60
- package/src/internals/canvas/useUndoRedo.test.js +46 -178
- package/src/internals/canvas/widgets/CodePenEmbed.jsx +16 -36
- package/src/internals/canvas/widgets/CodePenEmbed.module.css +12 -12
- package/src/internals/canvas/widgets/CropOverlay.module.css +23 -23
- package/src/internals/canvas/widgets/ExpandedPane.module.css +8 -8
- package/src/internals/canvas/widgets/ExpandedPaneTopBar.jsx +1 -1
- package/src/internals/canvas/widgets/FigmaEmbed.jsx +15 -36
- package/src/internals/canvas/widgets/FigmaEmbed.module.css +15 -15
- package/src/internals/canvas/widgets/FrozenTerminalOverlay.jsx +30 -21
- package/src/internals/canvas/widgets/FrozenTerminalOverlay.module.css +5 -5
- package/src/internals/canvas/widgets/ImageWidget.jsx +7 -2
- package/src/internals/canvas/widgets/ImageWidget.module.css +3 -3
- package/src/internals/canvas/widgets/LinkPreview.module.css +79 -80
- package/src/internals/canvas/widgets/MarkdownBlock.module.css +31 -31
- package/src/internals/canvas/widgets/PromptWidget.jsx +2 -16
- package/src/internals/canvas/widgets/PromptWidget.module.css +33 -33
- package/src/internals/canvas/widgets/PrototypeEmbed.jsx +92 -17
- package/src/internals/canvas/widgets/PrototypeEmbed.module.css +58 -56
- package/src/internals/canvas/widgets/PrototypeEmbed.test.jsx +118 -4
- package/src/internals/canvas/widgets/ResizeHandle.module.css +4 -4
- package/src/internals/canvas/widgets/StorySetWidget.jsx +53 -25
- package/src/internals/canvas/widgets/StoryWidget.jsx +71 -56
- package/src/internals/canvas/widgets/StoryWidget.module.css +22 -20
- package/src/internals/canvas/widgets/TerminalReadWidget.jsx +13 -15
- package/src/internals/canvas/widgets/TerminalReadWidget.module.css +4 -4
- package/src/internals/canvas/widgets/TerminalWidget.jsx +56 -45
- package/src/internals/canvas/widgets/TerminalWidget.module.css +10 -10
- package/src/internals/canvas/widgets/TilesWidget.module.css +17 -17
- package/src/internals/canvas/widgets/WidgetChrome.jsx +1 -1
- package/src/internals/canvas/widgets/WidgetChrome.module.css +76 -61
- package/src/internals/canvas/widgets/WidgetWrapper.module.css +2 -2
- package/src/internals/canvas/widgets/embedOverlay.module.css +14 -4
- package/src/internals/canvas/widgets/embedTheme.js +12 -104
- package/src/internals/canvas/widgets/expandUtils.js +19 -19
- package/src/internals/canvas/widgets/normalizeLegacyEmbedSrc.js +74 -0
- package/src/internals/canvas/widgets/widgetConfig.js +5 -5
- package/src/internals/context.jsx +22 -1
- package/src/internals/context.test.jsx +47 -0
- package/src/internals/hooks/useArtifactIndex.js +31 -0
- package/src/internals/hooks/useArtifactIndex.test.js +45 -0
- package/src/internals/hooks/usePrototypeReloadGuard.js +14 -8
- package/src/internals/index.js +6 -0
- package/src/internals/loadConsumerWrapper.js +60 -0
- package/src/internals/story/ComponentSetPage.jsx +75 -34
- package/src/internals/story/ComponentSetPage.module.css +14 -14
- package/src/internals/story/StoryPage.jsx +16 -25
- package/src/internals/story/StoryPage.module.css +2 -2
- package/src/internals/vite/data-plugin.js +317 -149
- package/src/internals/vite/data-plugin.test.js +11 -11
- package/{scaffold/storyboard.config.json → storyboard.config.json} +25 -0
- package/terminal.config.json +1 -1
- package/src/core/lib/components/ui/card/card-action.jsx +0 -11
- package/src/core/lib/components/ui/card/card-content.jsx +0 -11
- package/src/core/lib/components/ui/card/card-description.jsx +0 -11
- package/src/core/lib/components/ui/card/card-footer.jsx +0 -11
- package/src/core/lib/components/ui/card/card-header.jsx +0 -19
- package/src/core/lib/components/ui/card/card-title.jsx +0 -11
- package/src/core/lib/components/ui/card/card.jsx +0 -17
- package/src/core/lib/components/ui/card/index.js +0 -25
- package/src/core/lib/components/ui/collapsible/collapsible-content.jsx +0 -7
- package/src/core/lib/components/ui/collapsible/collapsible-trigger.jsx +0 -7
- package/src/core/lib/components/ui/collapsible/collapsible.jsx +0 -7
- package/src/core/lib/components/ui/collapsible/index.js +0 -13
- package/src/core/lib/components/ui/dialog/dialog-close.jsx +0 -7
- package/src/core/lib/components/ui/dialog/dialog-description.jsx +0 -15
- package/src/core/lib/components/ui/dialog/dialog-footer.jsx +0 -23
- package/src/core/lib/components/ui/dialog/dialog-header.jsx +0 -11
- package/src/core/lib/components/ui/dialog/dialog-overlay.jsx +0 -15
- package/src/core/lib/components/ui/dialog/dialog-portal.jsx +0 -4
- package/src/core/lib/components/ui/dialog/dialog-title.jsx +0 -15
- package/src/core/lib/components/ui/popover/index.js +0 -28
- package/src/core/lib/components/ui/popover/popover-close.jsx +0 -7
- package/src/core/lib/components/ui/popover/popover-content.jsx +0 -22
- package/src/core/lib/components/ui/popover/popover-description.jsx +0 -11
- package/src/core/lib/components/ui/popover/popover-header.jsx +0 -11
- package/src/core/lib/components/ui/popover/popover-portal.jsx +0 -4
- package/src/core/lib/components/ui/popover/popover-title.jsx +0 -11
- package/src/core/lib/components/ui/popover/popover-trigger.jsx +0 -8
- package/src/core/lib/components/ui/popover/popover.jsx +0 -4
- package/src/core/lib/components/ui/select/index.js +0 -37
- package/src/core/lib/components/ui/select/select-content.jsx +0 -30
- package/src/core/lib/components/ui/select/select-group-heading.jsx +0 -17
- package/src/core/lib/components/ui/select/select-group.jsx +0 -15
- package/src/core/lib/components/ui/select/select-item.jsx +0 -26
- package/src/core/lib/components/ui/select/select-label.jsx +0 -11
- package/src/core/lib/components/ui/select/select-portal.jsx +0 -4
- package/src/core/lib/components/ui/select/select-scroll-down-button.jsx +0 -18
- package/src/core/lib/components/ui/select/select-scroll-up-button.jsx +0 -18
- package/src/core/lib/components/ui/select/select-separator.jsx +0 -15
- package/src/core/lib/components/ui/select/select-trigger.jsx +0 -25
- package/src/core/lib/components/ui/select/select.jsx +0 -4
- package/src/core/lib/components/ui/sheet/index.js +0 -34
- package/src/core/lib/components/ui/sheet/sheet-close.jsx +0 -7
- package/src/core/lib/components/ui/sheet/sheet-content.jsx +0 -35
- package/src/core/lib/components/ui/sheet/sheet-description.jsx +0 -15
- package/src/core/lib/components/ui/sheet/sheet-footer.jsx +0 -11
- package/src/core/lib/components/ui/sheet/sheet-header.jsx +0 -11
- package/src/core/lib/components/ui/sheet/sheet-overlay.jsx +0 -15
- package/src/core/lib/components/ui/sheet/sheet-portal.jsx +0 -4
- package/src/core/lib/components/ui/sheet/sheet-title.jsx +0 -15
- package/src/core/lib/components/ui/sheet/sheet-trigger.jsx +0 -7
- package/src/core/lib/components/ui/sheet/sheet.jsx +0 -4
- package/src/core/lib/components/ui/toggle/index.js +0 -8
- package/src/core/lib/components/ui/toggle/toggle.jsx +0 -36
- package/src/core/lib/components/ui/toggle-group/index.js +0 -10
- package/src/core/lib/components/ui/toggle-group/toggle-group-item.jsx +0 -29
- package/src/core/lib/components/ui/toggle-group/toggle-group.jsx +0 -43
- package/src/internals/canvas/StoryErrorBoundary.jsx +0 -47
- package/src/internals/canvas/WebGLContextPool.jsx +0 -291
- package/src/internals/canvas/WebGLContextPool.test.jsx +0 -165
- package/src/internals/canvas/componentIsolate.jsx +0 -144
- package/src/internals/canvas/componentSetIsolate.jsx +0 -300
- package/src/internals/canvas/widgets/ComponentSetWidget.module.css +0 -89
- package/src/internals/canvas/widgets/InlineStoryRenderer.jsx +0 -129
- package/src/internals/canvas/widgets/InlineStoryRenderer.test.jsx +0 -68
- package/src/internals/canvas/widgets/StorySetWidget.module.css +0 -89
- package/src/primer/ThemeSync.jsx +0 -73
- 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(--
|
|
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',
|
|
438
|
-
{ id: 'create:prototype', children: 'Prototype', keywords: ['create', 'prototype', 'new', 'page'],
|
|
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
|
-
//
|
|
451
|
-
//
|
|
452
|
-
//
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
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(--
|
|
1293
|
-
fontSize: '0.8125rem', fontFamily: 'var(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
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
|
|
2
|
+
* CreateDialog — Primer Dialog wrapper around CreateArtifactForm.
|
|
3
3
|
*
|
|
4
|
-
* The form, fields,
|
|
5
|
-
*
|
|
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
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
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
|
-
<
|
|
119
|
-
type={
|
|
120
|
-
|
|
121
|
-
|
|
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(--
|
|
16
|
-
background: var(--
|
|
17
|
-
border: 1px solid var(--
|
|
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(--
|
|
25
|
-
box-shadow: 0 0 0 3px var(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
88
|
-
font-family: var(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
123
|
-
background: var(--
|
|
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
|
|
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(--
|
|
29
|
-
color: var(--
|
|
30
|
-
border: 1px solid var(--
|
|
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(--
|
|
52
|
+
border-bottom: 1px solid var(--color-border-muted, #d1d9e0);
|
|
53
53
|
outline: none;
|
|
54
54
|
background: transparent;
|
|
55
|
-
color: var(--
|
|
55
|
+
color: var(--color-foreground, #1f2328);
|
|
56
56
|
font-family: inherit;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
[cmdk-input]::placeholder {
|
|
60
|
-
color: var(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
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(--
|
|
110
|
-
color: var(--
|
|
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(--
|
|
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(--
|
|
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
|
+
}
|