@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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
.embed {
|
|
2
2
|
position: relative;
|
|
3
3
|
overflow: hidden;
|
|
4
|
-
background: var(--
|
|
5
|
-
border: 3px solid var(--
|
|
4
|
+
background: var(--color-background, #ffffff);
|
|
5
|
+
border: 3px solid var(--color-border, #d0d7de);
|
|
6
6
|
border-radius: 12px;
|
|
7
7
|
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
|
8
8
|
}
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
padding: 10px 10px;
|
|
15
15
|
font-size: 12px;
|
|
16
16
|
font-weight: 500;
|
|
17
|
-
color: var(--
|
|
18
|
-
background: var(--
|
|
19
|
-
border-bottom: 1px solid var(--
|
|
17
|
+
color: var(--color-foreground-muted, #656d76);
|
|
18
|
+
background: var(--color-background-muted, #f6f8fa);
|
|
19
|
+
border-bottom: 1px solid var(--color-border-muted, #d8dee4);
|
|
20
20
|
white-space: nowrap;
|
|
21
21
|
overflow: hidden;
|
|
22
22
|
text-overflow: ellipsis;
|
|
@@ -48,8 +48,10 @@
|
|
|
48
48
|
align-items: center;
|
|
49
49
|
justify-content: center;
|
|
50
50
|
gap: 8px;
|
|
51
|
-
|
|
51
|
+
background: var(--color-background-muted, #f6f8fa);
|
|
52
|
+
color: var(--color-foreground-muted, #656d76);
|
|
52
53
|
text-align: center;
|
|
54
|
+
z-index: 2;
|
|
53
55
|
}
|
|
54
56
|
|
|
55
57
|
.placeholderIcon {
|
|
@@ -63,10 +65,10 @@
|
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
.spinner {
|
|
66
|
-
width:
|
|
67
|
-
height:
|
|
68
|
-
border: 3px solid var(--
|
|
69
|
-
border-top-color: var(--
|
|
68
|
+
width: 40px;
|
|
69
|
+
height: 40px;
|
|
70
|
+
border: 3px solid var(--color-border-muted, #d0d7de);
|
|
71
|
+
border-top-color: var(--color-foreground-accent, #2f81f7);
|
|
70
72
|
border-radius: 50%;
|
|
71
73
|
animation: spin 0.8s linear infinite;
|
|
72
74
|
}
|
|
@@ -100,7 +102,7 @@
|
|
|
100
102
|
align-items: center;
|
|
101
103
|
justify-content: center;
|
|
102
104
|
height: 100%;
|
|
103
|
-
color: var(--
|
|
105
|
+
color: var(--color-foreground-muted, #656d76);
|
|
104
106
|
font-size: 14px;
|
|
105
107
|
font-style: italic;
|
|
106
108
|
cursor: pointer;
|
|
@@ -122,9 +124,9 @@
|
|
|
122
124
|
align-items: center;
|
|
123
125
|
justify-content: center;
|
|
124
126
|
border-radius: 6px;
|
|
125
|
-
background: var(--
|
|
126
|
-
border: 1px solid var(--
|
|
127
|
-
color: var(--
|
|
127
|
+
background: var(--color-background, rgba(255, 255, 255, 0.92));
|
|
128
|
+
border: 1px solid var(--color-border, rgba(0, 0, 0, 0.12));
|
|
129
|
+
color: var(--color-foreground, #1f2328);
|
|
128
130
|
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.15);
|
|
129
131
|
font-size: 14px;
|
|
130
132
|
opacity: 0;
|
|
@@ -137,7 +139,7 @@
|
|
|
137
139
|
}
|
|
138
140
|
|
|
139
141
|
.editBtn:hover {
|
|
140
|
-
background: var(--
|
|
142
|
+
background: var(--color-background-muted, rgba(255, 255, 255, 0.98));
|
|
141
143
|
}
|
|
142
144
|
|
|
143
145
|
.urlForm {
|
|
@@ -170,14 +172,14 @@
|
|
|
170
172
|
margin: 8px 16px;
|
|
171
173
|
padding: 6px 10px;
|
|
172
174
|
font-size: 13px;
|
|
173
|
-
border: 1px solid var(--
|
|
175
|
+
border: 1px solid var(--color-border, #d0d7de);
|
|
174
176
|
border-radius: 6px;
|
|
175
|
-
background: var(--
|
|
176
|
-
color: var(--
|
|
177
|
+
background: var(--color-background, #ffffff);
|
|
178
|
+
color: var(--color-foreground, #1f2328);
|
|
177
179
|
}
|
|
178
180
|
|
|
179
181
|
.filterInput:focus {
|
|
180
|
-
border-color: var(--
|
|
182
|
+
border-color: var(--color-background-accent-emphasis, #2f81f7);
|
|
181
183
|
box-shadow: 0 0 0 2px rgba(47, 129, 247, 0.3);
|
|
182
184
|
}
|
|
183
185
|
|
|
@@ -195,7 +197,7 @@
|
|
|
195
197
|
padding: 6px 8px 2px;
|
|
196
198
|
font-size: 11px;
|
|
197
199
|
font-weight: 600;
|
|
198
|
-
color: var(--
|
|
200
|
+
color: var(--color-foreground-muted, #656d76);
|
|
199
201
|
text-transform: uppercase;
|
|
200
202
|
letter-spacing: 0.5px;
|
|
201
203
|
}
|
|
@@ -207,7 +209,7 @@
|
|
|
207
209
|
box-sizing: border-box;
|
|
208
210
|
padding: 6px 12px;
|
|
209
211
|
font-size: 13px;
|
|
210
|
-
color: var(--
|
|
212
|
+
color: var(--color-foreground, #1f2328);
|
|
211
213
|
border-radius: 6px;
|
|
212
214
|
cursor: pointer;
|
|
213
215
|
white-space: nowrap;
|
|
@@ -216,18 +218,18 @@
|
|
|
216
218
|
}
|
|
217
219
|
|
|
218
220
|
.pickerItem:hover {
|
|
219
|
-
background: var(--
|
|
221
|
+
background: var(--color-background-neutral-muted, #eaeef2);
|
|
220
222
|
}
|
|
221
223
|
|
|
222
224
|
.pickerItem:focus-visible {
|
|
223
|
-
outline: 4px solid var(--
|
|
225
|
+
outline: 4px solid var(--color-background-accent-emphasis, #2f81f7);
|
|
224
226
|
outline-offset: -2px;
|
|
225
227
|
}
|
|
226
228
|
|
|
227
229
|
.pickerEmpty {
|
|
228
230
|
padding: 12px;
|
|
229
231
|
font-size: 13px;
|
|
230
|
-
color: var(--
|
|
232
|
+
color: var(--color-foreground-muted, #656d76);
|
|
231
233
|
font-style: italic;
|
|
232
234
|
text-align: center;
|
|
233
235
|
}
|
|
@@ -235,7 +237,7 @@
|
|
|
235
237
|
.pickerDivider {
|
|
236
238
|
height: 1px;
|
|
237
239
|
margin: 4px 16px;
|
|
238
|
-
background: var(--
|
|
240
|
+
background: var(--color-border-muted, #d8dee4);
|
|
239
241
|
}
|
|
240
242
|
|
|
241
243
|
.customUrlSection {
|
|
@@ -248,7 +250,7 @@
|
|
|
248
250
|
.urlLabel {
|
|
249
251
|
font-size: 12px;
|
|
250
252
|
font-weight: 600;
|
|
251
|
-
color: var(--
|
|
253
|
+
color: var(--color-foreground-muted, #656d76);
|
|
252
254
|
text-transform: uppercase;
|
|
253
255
|
letter-spacing: 0.5px;
|
|
254
256
|
}
|
|
@@ -258,14 +260,14 @@
|
|
|
258
260
|
padding: 8px 10px;
|
|
259
261
|
font-size: 14px;
|
|
260
262
|
font-family: ui-monospace, SFMono-Regular, monospace;
|
|
261
|
-
border: 1px solid var(--
|
|
263
|
+
border: 1px solid var(--color-border, #d0d7de);
|
|
262
264
|
border-radius: 6px;
|
|
263
|
-
background: var(--
|
|
264
|
-
color: var(--
|
|
265
|
+
background: var(--color-background, #ffffff);
|
|
266
|
+
color: var(--color-foreground, #1f2328);
|
|
265
267
|
}
|
|
266
268
|
|
|
267
269
|
.urlInput:focus {
|
|
268
|
-
border-color: var(--
|
|
270
|
+
border-color: var(--color-background-accent-emphasis, #2f81f7);
|
|
269
271
|
box-shadow: 0 0 0 2px rgba(47, 129, 247, 0.3);
|
|
270
272
|
}
|
|
271
273
|
|
|
@@ -286,21 +288,21 @@
|
|
|
286
288
|
}
|
|
287
289
|
|
|
288
290
|
.urlSave {
|
|
289
|
-
background: var(--
|
|
290
|
-
color: var(--
|
|
291
|
+
background: var(--color-background-accent-emphasis, #2f81f7);
|
|
292
|
+
color: var(--color-foreground-on-emphasis, #ffffff);
|
|
291
293
|
}
|
|
292
294
|
|
|
293
295
|
.urlSave:hover {
|
|
294
|
-
background: var(--
|
|
296
|
+
background: var(--color-background-accent-emphasis, #388bfd);
|
|
295
297
|
}
|
|
296
298
|
|
|
297
299
|
.urlCancel {
|
|
298
|
-
color: var(--
|
|
300
|
+
color: var(--color-foreground-muted, #656d76);
|
|
299
301
|
}
|
|
300
302
|
|
|
301
303
|
.urlCancel:hover {
|
|
302
|
-
color: var(--
|
|
303
|
-
background: var(--
|
|
304
|
+
color: var(--color-foreground, #1f2328);
|
|
305
|
+
background: var(--color-background-muted, #f6f8fa);
|
|
304
306
|
}
|
|
305
307
|
|
|
306
308
|
.resizeHandle {
|
|
@@ -313,12 +315,12 @@
|
|
|
313
315
|
background: linear-gradient(
|
|
314
316
|
135deg,
|
|
315
317
|
transparent 40%,
|
|
316
|
-
var(--
|
|
317
|
-
var(--
|
|
318
|
+
var(--color-border-muted, rgba(0, 0, 0, 0.15)) 40%,
|
|
319
|
+
var(--color-border-muted, rgba(0, 0, 0, 0.15)) 50%,
|
|
318
320
|
transparent 50%,
|
|
319
321
|
transparent 65%,
|
|
320
|
-
var(--
|
|
321
|
-
var(--
|
|
322
|
+
var(--color-border-muted, rgba(0, 0, 0, 0.15)) 65%,
|
|
323
|
+
var(--color-border-muted, rgba(0, 0, 0, 0.15)) 75%,
|
|
322
324
|
transparent 75%
|
|
323
325
|
);
|
|
324
326
|
opacity: 0;
|
|
@@ -339,8 +341,8 @@
|
|
|
339
341
|
display: flex;
|
|
340
342
|
align-items: center;
|
|
341
343
|
border-radius: 10px;
|
|
342
|
-
border: 1.5px solid var(--trigger-border, var(--
|
|
343
|
-
background: var(--trigger-bg, var(--
|
|
344
|
+
border: 1.5px solid var(--trigger-border, var(--color-border-muted, #d0d7de));
|
|
345
|
+
background: var(--trigger-bg, var(--color-background-muted, #f6f8fa));
|
|
344
346
|
opacity: 0;
|
|
345
347
|
transition: opacity 150ms;
|
|
346
348
|
z-index: 3;
|
|
@@ -360,7 +362,7 @@
|
|
|
360
362
|
justify-content: center;
|
|
361
363
|
font-size: 16px;
|
|
362
364
|
font-weight: 600;
|
|
363
|
-
color: var(--trigger-text, var(--
|
|
365
|
+
color: var(--trigger-text, var(--color-foreground, #1f2328));
|
|
364
366
|
transition: background 120ms;
|
|
365
367
|
}
|
|
366
368
|
|
|
@@ -373,7 +375,7 @@
|
|
|
373
375
|
}
|
|
374
376
|
|
|
375
377
|
.zoomBtn:hover:not(:disabled) {
|
|
376
|
-
background: var(--trigger-bg-hover, var(--
|
|
378
|
+
background: var(--trigger-bg-hover, var(--color-background-neutral-muted, #eaeef2));
|
|
377
379
|
}
|
|
378
380
|
|
|
379
381
|
.zoomBtn:disabled {
|
|
@@ -391,9 +393,9 @@
|
|
|
391
393
|
font-size: 11px;
|
|
392
394
|
font-weight: 600;
|
|
393
395
|
font-variant-numeric: tabular-nums;
|
|
394
|
-
color: var(--trigger-text, var(--
|
|
395
|
-
border-left: 1.5px solid var(--trigger-border, var(--
|
|
396
|
-
border-right: 1.5px solid var(--trigger-border, var(--
|
|
396
|
+
color: var(--trigger-text, var(--color-foreground, #1f2328));
|
|
397
|
+
border-left: 1.5px solid var(--trigger-border, var(--color-border-muted, #d0d7de));
|
|
398
|
+
border-right: 1.5px solid var(--trigger-border, var(--color-border-muted, #d0d7de));
|
|
397
399
|
user-select: none;
|
|
398
400
|
}
|
|
399
401
|
|
|
@@ -420,7 +422,7 @@
|
|
|
420
422
|
position: relative;
|
|
421
423
|
border-radius: 12px;
|
|
422
424
|
overflow: hidden;
|
|
423
|
-
background: var(--
|
|
425
|
+
background: var(--color-background, #ffffff);
|
|
424
426
|
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.4);
|
|
425
427
|
animation: expandScaleIn 0.2s ease;
|
|
426
428
|
}
|
|
@@ -469,7 +471,7 @@
|
|
|
469
471
|
height: 100%;
|
|
470
472
|
position: relative;
|
|
471
473
|
overflow: hidden;
|
|
472
|
-
background: var(--
|
|
474
|
+
background: var(--color-background, #ffffff);
|
|
473
475
|
}
|
|
474
476
|
|
|
475
477
|
.expandContainerSplit .expandIframe {
|
|
@@ -499,7 +501,7 @@
|
|
|
499
501
|
min-width: 0;
|
|
500
502
|
height: 100%;
|
|
501
503
|
overflow: hidden;
|
|
502
|
-
border-right: 1px solid var(--
|
|
504
|
+
border-right: 1px solid var(--color-border-muted, #d8dee4);
|
|
503
505
|
}
|
|
504
506
|
|
|
505
507
|
.expandSplitRight {
|
|
@@ -513,7 +515,7 @@
|
|
|
513
515
|
width: 100%;
|
|
514
516
|
height: 100%;
|
|
515
517
|
overflow: auto;
|
|
516
|
-
background: var(--
|
|
518
|
+
background: var(--color-background, #ffffff);
|
|
517
519
|
}
|
|
518
520
|
|
|
519
521
|
.expandSecondary iframe {
|
|
@@ -533,13 +535,13 @@
|
|
|
533
535
|
padding: 32px 40px;
|
|
534
536
|
font-size: 15px;
|
|
535
537
|
line-height: 1.7;
|
|
536
|
-
color: var(--
|
|
538
|
+
color: var(--color-foreground, #1f2328);
|
|
537
539
|
max-width: 800px;
|
|
538
540
|
margin: 0 auto;
|
|
539
541
|
}
|
|
540
542
|
|
|
541
543
|
.expandMarkdownContent * { pointer-events: auto; }
|
|
542
|
-
.expandMarkdownContent a { color: var(--
|
|
544
|
+
.expandMarkdownContent a { color: var(--color-foreground-accent, #0969da); text-decoration: none; }
|
|
543
545
|
.expandMarkdownContent a:hover { text-decoration: underline; }
|
|
544
546
|
.expandMarkdownContent img { max-width: 100%; height: auto; border-radius: 6px; margin: 8px 0; display: block; }
|
|
545
547
|
|
|
@@ -547,14 +549,14 @@
|
|
|
547
549
|
height: 100%;
|
|
548
550
|
display: flex;
|
|
549
551
|
flex-direction: column;
|
|
550
|
-
background: var(--
|
|
552
|
+
background: var(--color-background, #ffffff);
|
|
551
553
|
}
|
|
552
554
|
|
|
553
555
|
.expandGithubHeader {
|
|
554
556
|
padding: 16px 24px;
|
|
555
557
|
font-size: 18px;
|
|
556
558
|
font-weight: 600;
|
|
557
|
-
border-bottom: 1px solid var(--
|
|
559
|
+
border-bottom: 1px solid var(--color-border-muted, #d8dee4);
|
|
558
560
|
}
|
|
559
561
|
|
|
560
562
|
.expandGithubBody {
|
|
@@ -566,7 +568,7 @@
|
|
|
566
568
|
}
|
|
567
569
|
|
|
568
570
|
.expandGithubBody * { pointer-events: auto; }
|
|
569
|
-
.expandGithubBody a { color: var(--
|
|
571
|
+
.expandGithubBody a { color: var(--color-foreground-accent, #0969da); }
|
|
570
572
|
|
|
571
573
|
.expandLinkCard {
|
|
572
574
|
padding: 32px 40px;
|
|
@@ -1,10 +1,124 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest'
|
|
2
2
|
import { getEmbedChromeVars } from './embedTheme.js'
|
|
3
|
+
import { normalizeLegacyEmbedSrc } from './normalizeLegacyEmbedSrc.js'
|
|
3
4
|
|
|
4
5
|
describe('getEmbedChromeVars', () => {
|
|
5
|
-
it('
|
|
6
|
-
expect(getEmbedChromeVars('light')
|
|
7
|
-
expect(getEmbedChromeVars('dark')
|
|
8
|
-
expect(getEmbedChromeVars('dark_dimmed')
|
|
6
|
+
it('returns an empty object — color tokens now cascade from data-sb-canvas-theme via tailwind.css', () => {
|
|
7
|
+
expect(getEmbedChromeVars('light')).toEqual({})
|
|
8
|
+
expect(getEmbedChromeVars('dark')).toEqual({})
|
|
9
|
+
expect(getEmbedChromeVars('dark_dimmed')).toEqual({})
|
|
10
|
+
})
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
describe('normalizeLegacyEmbedSrc', () => {
|
|
14
|
+
it('passes through clean canvas-app routes unchanged', () => {
|
|
15
|
+
expect(normalizeLegacyEmbedSrc('/cq-org-enablement')).toBe('/cq-org-enablement')
|
|
16
|
+
expect(normalizeLegacyEmbedSrc('/MyProto/SignupForm')).toBe('/MyProto/SignupForm')
|
|
17
|
+
expect(normalizeLegacyEmbedSrc('/cq-org-enablement#x=1')).toBe('/cq-org-enablement#x=1')
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('passes through external http(s) URLs unchanged', () => {
|
|
21
|
+
expect(normalizeLegacyEmbedSrc('https://example.com/foo')).toBe('https://example.com/foo')
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('passes through empty/falsy values', () => {
|
|
25
|
+
expect(normalizeLegacyEmbedSrc('')).toBe('')
|
|
26
|
+
expect(normalizeLegacyEmbedSrc(null)).toBe(null)
|
|
27
|
+
expect(normalizeLegacyEmbedSrc(undefined)).toBe(undefined)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
describe('legacy hash-form: /prototypes.html#/<route>', () => {
|
|
31
|
+
it('strips loader prefix and keeps inner route', () => {
|
|
32
|
+
expect(normalizeLegacyEmbedSrc('/prototypes.html#/cq-org-enablement')).toBe('/cq-org-enablement')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('keeps query strings inside inner', () => {
|
|
36
|
+
expect(normalizeLegacyEmbedSrc('/prototypes.html#/cq-org-enablement?cqConfirmOpen=true'))
|
|
37
|
+
.toBe('/cq-org-enablement?cqConfirmOpen=true')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('handles non-root basePath', () => {
|
|
41
|
+
expect(normalizeLegacyEmbedSrc('/storyboard/prototypes.html#/MyProto')).toBe('/MyProto')
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('returns "/" for empty inner', () => {
|
|
45
|
+
expect(normalizeLegacyEmbedSrc('/prototypes.html#')).toBe('/')
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
it('prefixes "/" if inner missing leading slash', () => {
|
|
49
|
+
expect(normalizeLegacyEmbedSrc('/prototypes.html#MyProto')).toBe('/MyProto')
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
describe('legacy URLSearchParams-clobbered form (real-world 0.6.13/0.6.14 bug)', () => {
|
|
54
|
+
// Real bug: storyboard's session.writeHash did URLSearchParams.toString()
|
|
55
|
+
// on the entire hash, which URL-encoded the route slash to %2F and turned
|
|
56
|
+
// /MyProto into a key with an empty value. Real persisted srcs from the
|
|
57
|
+
// wild look like /prototypes.html#%2Fcq-org-enablement=&cqConfirmOpen=true
|
|
58
|
+
it('recovers route from URLSearchParams-mangled hash', () => {
|
|
59
|
+
expect(
|
|
60
|
+
normalizeLegacyEmbedSrc('/prototypes.html#%2Fcq-org-enablement=&cqConfirmOpen=true'),
|
|
61
|
+
).toBe('/cq-org-enablement#cqConfirmOpen=true')
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it('recovers route with no surviving storyboard state', () => {
|
|
65
|
+
expect(normalizeLegacyEmbedSrc('/prototypes.html#%2Fcq-org-enablement=')).toBe('/cq-org-enablement')
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('recovers route with multiple storyboard params', () => {
|
|
69
|
+
expect(
|
|
70
|
+
normalizeLegacyEmbedSrc(
|
|
71
|
+
'/prototypes.html#%2Fcq-org-enablement=&cqEnabled=null&cqFlashDismissed=null&cqConfirmOpen=true',
|
|
72
|
+
),
|
|
73
|
+
).toBe('/cq-org-enablement#cqEnabled=null&cqFlashDismissed=null&cqConfirmOpen=true')
|
|
74
|
+
})
|
|
75
|
+
|
|
76
|
+
it('recovers nested route', () => {
|
|
77
|
+
expect(
|
|
78
|
+
normalizeLegacyEmbedSrc('/prototypes.html#%2FMyProto%2FSignupForm=&x=1'),
|
|
79
|
+
).toBe('/MyProto/SignupForm#x=1')
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
it('handles non-root basePath', () => {
|
|
83
|
+
expect(
|
|
84
|
+
normalizeLegacyEmbedSrc('/storyboard/prototypes.html#%2FMyProto=&x=1'),
|
|
85
|
+
).toBe('/MyProto#x=1')
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
describe('defensive path-form: /prototypes.html/<route>', () => {
|
|
90
|
+
it('strips loader prefix', () => {
|
|
91
|
+
expect(normalizeLegacyEmbedSrc('/prototypes.html/MyProto')).toBe('/MyProto')
|
|
92
|
+
})
|
|
93
|
+
|
|
94
|
+
it('handles nested routes', () => {
|
|
95
|
+
expect(normalizeLegacyEmbedSrc('/prototypes.html/MyProto/SignupForm')).toBe('/MyProto/SignupForm')
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('handles non-root basePath', () => {
|
|
99
|
+
expect(normalizeLegacyEmbedSrc('/storyboard/prototypes.html/MyProto')).toBe('/MyProto')
|
|
100
|
+
})
|
|
101
|
+
})
|
|
102
|
+
|
|
103
|
+
describe('all-encompassing regression — no legacy shape can produce a /prototypes.html src', () => {
|
|
104
|
+
const cases = [
|
|
105
|
+
'/prototypes.html#/foo',
|
|
106
|
+
'/prototypes.html#/foo?bar=1',
|
|
107
|
+
'/prototypes.html#',
|
|
108
|
+
'/prototypes.html#%2Ffoo=&bar=1',
|
|
109
|
+
'/prototypes.html#%2Ffoo%2Fbar=&x=1',
|
|
110
|
+
'/prototypes.html/foo',
|
|
111
|
+
'/prototypes.html/foo/bar',
|
|
112
|
+
'/storyboard/prototypes.html#/foo',
|
|
113
|
+
'/storyboard/prototypes.html#%2Ffoo=&x=1',
|
|
114
|
+
'/storyboard/prototypes.html/foo',
|
|
115
|
+
]
|
|
116
|
+
for (const input of cases) {
|
|
117
|
+
it(`recovers ${input}`, () => {
|
|
118
|
+
const result = normalizeLegacyEmbedSrc(input)
|
|
119
|
+
expect(result).not.toMatch(/prototypes\.html/)
|
|
120
|
+
expect(result.startsWith('/')).toBe(true)
|
|
121
|
+
})
|
|
122
|
+
}
|
|
9
123
|
})
|
|
10
124
|
})
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
background: linear-gradient(
|
|
9
9
|
135deg,
|
|
10
10
|
transparent 40%,
|
|
11
|
-
var(--
|
|
12
|
-
var(--
|
|
11
|
+
var(--color-border-muted, rgba(0, 0, 0, 0.15)) 40%,
|
|
12
|
+
var(--color-border-muted, rgba(0, 0, 0, 0.15)) 50%,
|
|
13
13
|
transparent 50%,
|
|
14
14
|
transparent 65%,
|
|
15
|
-
var(--
|
|
16
|
-
var(--
|
|
15
|
+
var(--color-border-muted, rgba(0, 0, 0, 0.15)) 65%,
|
|
16
|
+
var(--color-border-muted, rgba(0, 0, 0, 0.15)) 75%,
|
|
17
17
|
transparent 75%
|
|
18
18
|
);
|
|
19
19
|
opacity: 0;
|
|
@@ -20,7 +20,6 @@ import ExpandedPane from './ExpandedPane.jsx'
|
|
|
20
20
|
import { buildSecondaryIframeUrl, getSplitPaneLabel } from './expandUtils.js'
|
|
21
21
|
import { useExpandOverride } from './useExpandOverride.js'
|
|
22
22
|
import { useIframeDevLogs } from './iframeDevLogs.js'
|
|
23
|
-
import styles from './StorySetWidget.module.css'
|
|
24
23
|
import overlayStyles from './embedOverlay.module.css'
|
|
25
24
|
|
|
26
25
|
function GridIcon({ size = 16 }) {
|
|
@@ -31,18 +30,28 @@ function resolveStorySetUrl(storyId, layout, selected, density, theme) {
|
|
|
31
30
|
const story = getStoryData(storyId)
|
|
32
31
|
if (!story?._storyModule) return ''
|
|
33
32
|
const base = (import.meta.env.BASE_URL || '/').replace(/\/$/, '')
|
|
33
|
+
|
|
34
|
+
// Route through the shared iframe-isolation entry in dev so a broken
|
|
35
|
+
// .story.jsx can't poison the canvas SPA's module graph. The real story
|
|
36
|
+
// route handles it in prod (no isolation middleware in deployed builds).
|
|
34
37
|
const params = new URLSearchParams()
|
|
35
|
-
// Route via the real story page (works in dev AND prod). The dev-only
|
|
36
|
-
// `_storyboard/canvas/isolate-set` middleware doesn't exist in deployed
|
|
37
|
-
// builds, so we mount ComponentSetPage at the story's route with
|
|
38
|
-
// `_sb_component_set` instead. `_sb_embed` keeps the canvas chrome off.
|
|
39
38
|
params.set('_sb_embed', '')
|
|
40
39
|
params.set('_sb_component_set', '')
|
|
40
|
+
// Force the prototype surface inside the iframe to follow the global
|
|
41
|
+
// theme. themeBootstrap only writes a theme's companion attrs
|
|
42
|
+
// (data-color-mode, data-light-theme, data-dark-theme) to <html> for
|
|
43
|
+
// the prototype surface — so any other target would leave Primer
|
|
44
|
+
// components rendering in light mode regardless of the canvas theme.
|
|
45
|
+
params.set('_sb_theme_target', 'prototype')
|
|
41
46
|
if (layout) params.set('layout', layout)
|
|
42
47
|
if (selected) params.set('selected', selected)
|
|
43
48
|
if (density) params.set('density', density)
|
|
44
49
|
if (theme) params.set('theme', theme)
|
|
50
|
+
|
|
45
51
|
const route = story._route || `/components/${storyId}`
|
|
52
|
+
if (import.meta.env.DEV) {
|
|
53
|
+
return `${base}/stories.html${route}?${params}`
|
|
54
|
+
}
|
|
46
55
|
return `${base}${route}?${params}`
|
|
47
56
|
}
|
|
48
57
|
|
|
@@ -61,6 +70,10 @@ export default forwardRef(function StorySetWidget({ id: widgetId, props, onUpdat
|
|
|
61
70
|
const contentSizeRef = useRef({ width: 0, height: 0 })
|
|
62
71
|
const [snapping, setSnapping] = useState(false)
|
|
63
72
|
const [interactive, setInteractive] = useState(false)
|
|
73
|
+
// Track which src URL has fired its onLoad callback so we can overlay a
|
|
74
|
+
// spinner while a new iframe is fetching. Stored as the URL itself so
|
|
75
|
+
// changing src naturally invalidates the loaded state without an effect.
|
|
76
|
+
const [loadedSrc, setLoadedSrc] = useState(null)
|
|
64
77
|
const [storyIndexKey, setStoryIndexKey] = useState(0)
|
|
65
78
|
const [expandedMode, setExpandedMode] = useExpandOverride('storyset', widgetId)
|
|
66
79
|
const expanded = expandedMode === '1' || expandedMode === 'immersive'
|
|
@@ -193,10 +206,13 @@ export default forwardRef(function StorySetWidget({ id: widgetId, props, onUpdat
|
|
|
193
206
|
if (!storyId) {
|
|
194
207
|
return (
|
|
195
208
|
<WidgetWrapper>
|
|
196
|
-
<div
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
209
|
+
<div
|
|
210
|
+
ref={containerRef}
|
|
211
|
+
className="relative overflow-hidden min-w-[200px] min-h-[120px] w-full h-full rounded-lg bg-background shadow-[0_4px_16px_rgba(0,0,0,0.08)]"
|
|
212
|
+
>
|
|
213
|
+
<div className="flex items-center gap-2 p-4 text-sm leading-snug font-[system-ui,-apple-system,sans-serif] text-foreground-danger">
|
|
214
|
+
<span className="text-xl flex-shrink-0"><GridIcon size={20} /></span>
|
|
215
|
+
<span className="break-words">Missing story ID</span>
|
|
200
216
|
</div>
|
|
201
217
|
</div>
|
|
202
218
|
</WidgetWrapper>
|
|
@@ -206,10 +222,13 @@ export default forwardRef(function StorySetWidget({ id: widgetId, props, onUpdat
|
|
|
206
222
|
if (!iframeSrc) {
|
|
207
223
|
return (
|
|
208
224
|
<WidgetWrapper>
|
|
209
|
-
<div
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
225
|
+
<div
|
|
226
|
+
ref={containerRef}
|
|
227
|
+
className="relative overflow-hidden min-w-[200px] min-h-[120px] w-full h-full rounded-lg bg-background shadow-[0_4px_16px_rgba(0,0,0,0.08)]"
|
|
228
|
+
>
|
|
229
|
+
<div className="flex items-center gap-2 p-4 text-sm leading-snug font-[system-ui,-apple-system,sans-serif] text-foreground-danger">
|
|
230
|
+
<span className="text-xl flex-shrink-0"><GridIcon size={20} /></span>
|
|
231
|
+
<span className="break-words">Story “{storyId}” not found or has no route</span>
|
|
213
232
|
</div>
|
|
214
233
|
</div>
|
|
215
234
|
</WidgetWrapper>
|
|
@@ -224,25 +243,34 @@ export default forwardRef(function StorySetWidget({ id: widgetId, props, onUpdat
|
|
|
224
243
|
return (
|
|
225
244
|
<>
|
|
226
245
|
<WidgetWrapper>
|
|
227
|
-
<div
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
246
|
+
<div
|
|
247
|
+
ref={containerRef}
|
|
248
|
+
className="relative overflow-hidden min-w-[200px] min-h-[120px] w-full h-full rounded-lg bg-background shadow-[0_4px_16px_rgba(0,0,0,0.08)]"
|
|
249
|
+
style={sizeStyle}
|
|
250
|
+
>
|
|
251
|
+
<div className="flex items-center gap-1.5 px-2.5 py-2.5 text-xs font-medium whitespace-nowrap overflow-hidden text-ellipsis select-none border-b border-border-muted bg-background-muted text-foreground-muted">
|
|
252
|
+
<span className="inline-flex flex-shrink-0"><GridIcon size={16} /></span>
|
|
253
|
+
<span className="overflow-hidden text-ellipsis">{displayName}</span>
|
|
231
254
|
{selected && (
|
|
232
|
-
<span className=
|
|
255
|
+
<span className="font-semibold flex-shrink-0 text-foreground-accent">· {selected}</span>
|
|
233
256
|
)}
|
|
234
|
-
<span className={styles.headerLayout} title={`Layout: ${layout}`}>
|
|
235
|
-
{layout === 'wide' ? '▭' : layout === 'tall' ? '▯' : '▦'}
|
|
236
|
-
</span>
|
|
237
257
|
</div>
|
|
238
|
-
<div className=
|
|
258
|
+
<div className="relative w-full h-[calc(100%-37px)]">
|
|
239
259
|
<iframe
|
|
240
260
|
ref={iframeRef}
|
|
241
261
|
src={iframeSrc}
|
|
242
|
-
className=
|
|
262
|
+
className="absolute inset-0 block w-full h-full border-0 z-[1]"
|
|
243
263
|
title={`${displayName} component set`}
|
|
244
|
-
onLoad={(e) => e.target.blur()}
|
|
264
|
+
onLoad={(e) => { e.target.blur(); setLoadedSrc(iframeSrc) }}
|
|
245
265
|
/>
|
|
266
|
+
{loadedSrc !== iframeSrc && (
|
|
267
|
+
<div
|
|
268
|
+
className="absolute inset-0 z-[2] flex flex-col items-center justify-center gap-2 text-center bg-background-muted text-foreground-muted"
|
|
269
|
+
aria-hidden="true"
|
|
270
|
+
>
|
|
271
|
+
<div className="w-10 h-10 rounded-full animate-spin border-t-foreground-accent" />
|
|
272
|
+
</div>
|
|
273
|
+
)}
|
|
246
274
|
</div>
|
|
247
275
|
{!interactive && (
|
|
248
276
|
<div
|
|
@@ -299,7 +327,7 @@ function ComponentSetExpandPane({ widgetId, storyId, layout, selected, immersive
|
|
|
299
327
|
kind: 'react',
|
|
300
328
|
render: () => url
|
|
301
329
|
? <iframe src={url} style={{ border: 'none', width: '100%', height: '100%', display: 'block' }} title={storyId} onLoad={(e) => e.target.blur()} />
|
|
302
|
-
: <div style={{ padding: 32, color: 'var(--
|
|
330
|
+
: <div style={{ padding: 32, color: 'var(--color-foreground-muted)' }}>Story "{storyId}" not found</div>,
|
|
303
331
|
}), [widgetId, label, url, storyId])
|
|
304
332
|
|
|
305
333
|
return (
|