@scaffold-ui-kit/preview 0.0.0-stage → 2.3.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/LICENSE +21 -0
- package/README.md +1868 -2
- package/application/host/bootstrap.ts +43 -0
- package/application/host/main.ts +31 -0
- package/application/host/shell-host.ts +47 -0
- package/application/index.html +12 -0
- package/application/lib/base-url.ts +15 -0
- package/application/lib/no-code-block.ts +7 -0
- package/application/lib/no-setup.ts +3 -0
- package/application/lib/no-views.ts +6 -0
- package/application/preview/code/code.html +12 -0
- package/application/preview/code/main.ts +89 -0
- package/application/preview/globals.ts +254 -0
- package/application/preview/html/main.ts +93 -0
- package/application/preview/html/preview.html +12 -0
- package/application/preview/react/main.tsx +146 -0
- package/application/preview/react/preview.html +12 -0
- package/application/preview/svelte/Preview.svelte +104 -0
- package/application/preview/svelte/main.ts +13 -0
- package/application/preview/svelte/preview.html +12 -0
- package/application/preview/svelte/story-props.ts +172 -0
- package/application/preview/view/main.ts +124 -0
- package/application/preview/view/view.html +12 -0
- package/application/preview/vue/main.ts +145 -0
- package/application/preview/vue/preview.html +12 -0
- package/application/shells/charcell/components/Application/index.css +37 -0
- package/application/shells/charcell/components/Application/index.tsx +65 -0
- package/application/shells/charcell/components/Bar/index.css +68 -0
- package/application/shells/charcell/components/Bar/index.tsx +60 -0
- package/application/shells/charcell/components/CodePane/index.css +60 -0
- package/application/shells/charcell/components/CodePane/index.tsx +113 -0
- package/application/shells/charcell/components/ComponentStage/index.css +26 -0
- package/application/shells/charcell/components/ComponentStage/index.tsx +110 -0
- package/application/shells/charcell/components/Control/index.css +20 -0
- package/application/shells/charcell/components/Control/index.tsx +118 -0
- package/application/shells/charcell/components/CopyLink/index.tsx +35 -0
- package/application/shells/charcell/components/Description/index.css +6 -0
- package/application/shells/charcell/components/Description/index.tsx +24 -0
- package/application/shells/charcell/components/EditorAddDialog/index.css +9 -0
- package/application/shells/charcell/components/EditorAddDialog/index.tsx +158 -0
- package/application/shells/charcell/components/EditorPanel/index.css +48 -0
- package/application/shells/charcell/components/EditorPanel/index.tsx +496 -0
- package/application/shells/charcell/components/EventsRow/index.css +42 -0
- package/application/shells/charcell/components/EventsRow/index.tsx +68 -0
- package/application/shells/charcell/components/HeadingRow/index.css +11 -0
- package/application/shells/charcell/components/HeadingRow/index.tsx +16 -0
- package/application/shells/charcell/components/Hint/index.css +16 -0
- package/application/shells/charcell/components/Hint/index.tsx +81 -0
- package/application/shells/charcell/components/HtmlWarnings/index.tsx +45 -0
- package/application/shells/charcell/components/KeyHints/index.css +27 -0
- package/application/shells/charcell/components/KeyHints/index.tsx +106 -0
- package/application/shells/charcell/components/KitCodeBlock/index.css +55 -0
- package/application/shells/charcell/components/KitCodeBlock/index.tsx +18 -0
- package/application/shells/charcell/components/Markdown/index.tsx +16 -0
- package/application/shells/charcell/components/Navigation/index.css +13 -0
- package/application/shells/charcell/components/Navigation/index.tsx +98 -0
- package/application/shells/charcell/components/NavigationSplit/index.css +16 -0
- package/application/shells/charcell/components/NavigationSplit/index.tsx +82 -0
- package/application/shells/charcell/components/OptionControls/index.tsx +93 -0
- package/application/shells/charcell/components/PaneStatus/index.css +7 -0
- package/application/shells/charcell/components/PaneStatus/index.tsx +47 -0
- package/application/shells/charcell/components/PaneWidth/index.tsx +45 -0
- package/application/shells/charcell/components/PreviewGrid/index.css +39 -0
- package/application/shells/charcell/components/PreviewGrid/index.tsx +344 -0
- package/application/shells/charcell/components/PreviewPane/index.css +127 -0
- package/application/shells/charcell/components/PreviewPane/index.tsx +182 -0
- package/application/shells/charcell/components/PromptBar/index.tsx +133 -0
- package/application/shells/charcell/components/ScenarioRow/index.css +36 -0
- package/application/shells/charcell/components/ScenarioRow/index.tsx +71 -0
- package/application/shells/charcell/components/Select/index.tsx +48 -0
- package/application/shells/charcell/components/SlotOutlet/index.css +7 -0
- package/application/shells/charcell/components/SlotOutlet/index.tsx +25 -0
- package/application/shells/charcell/components/StageBar/index.css +7 -0
- package/application/shells/charcell/components/StageBar/index.tsx +109 -0
- package/application/shells/charcell/components/StageSplit/index.css +11 -0
- package/application/shells/charcell/components/StageSplit/index.tsx +99 -0
- package/application/shells/charcell/components/StatusBar/index.tsx +30 -0
- package/application/shells/charcell/components/ViewControls/index.css +15 -0
- package/application/shells/charcell/components/ViewControls/index.tsx +58 -0
- package/application/shells/charcell/components/ViewHeading/index.css +13 -0
- package/application/shells/charcell/components/ViewHeading/index.tsx +8 -0
- package/application/shells/charcell/components/ViewStage/index.css +9 -0
- package/application/shells/charcell/components/ViewStage/index.tsx +25 -0
- package/application/shells/charcell/components/WrapToggle/index.tsx +27 -0
- package/application/shells/charcell/configuration.ts +45 -0
- package/application/shells/charcell/controller-context.ts +27 -0
- package/application/shells/charcell/fit-labels.ts +42 -0
- package/application/shells/charcell/html-warnings.ts +18 -0
- package/application/shells/charcell/index.tsx +82 -0
- package/application/shells/charcell/page-loading.html +57 -0
- package/application/shells/charcell/placement.ts +24 -0
- package/application/shells/charcell/shell-options.ts +23 -0
- package/application/shells/charcell/shell.css +37 -0
- package/application/shells/charcell/shell.tsx +25 -0
- package/application/shells/charcell/split-reset.ts +47 -0
- package/application/shells/charcell/stacked-rows.ts +117 -0
- package/application/shells/charcell/stage-toggles.ts +93 -0
- package/application/types/manifest.d.ts +6 -0
- package/application/types/preview-configuration.d.ts +10 -0
- package/application/types/preview-shell.d.ts +7 -0
- package/application/types/react-registry.d.ts +15 -0
- package/application/types/vue-registry.d.ts +6 -0
- package/dist/build.d.ts +24 -0
- package/dist/build.js +34 -0
- package/dist/check.d.ts +48 -0
- package/dist/check.js +781 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +88 -0
- package/dist/context.d.ts +179 -0
- package/dist/context.js +783 -0
- package/dist/controller/catalog.d.ts +339 -0
- package/dist/controller/catalog.js +367 -0
- package/dist/controller/create-preview-controller.d.ts +532 -0
- package/dist/controller/create-preview-controller.js +1707 -0
- package/dist/controller/editor-tree.d.ts +161 -0
- package/dist/controller/editor-tree.js +373 -0
- package/dist/controller/html-source.d.ts +62 -0
- package/dist/controller/html-source.js +61 -0
- package/dist/controller/index.d.ts +9 -0
- package/dist/controller/index.js +12 -0
- package/dist/controller/persistence.d.ts +191 -0
- package/dist/controller/persistence.js +315 -0
- package/dist/controller/regeneration.d.ts +30 -0
- package/dist/controller/regeneration.js +27 -0
- package/dist/controller/source.d.ts +80 -0
- package/dist/controller/source.js +236 -0
- package/dist/controller/store.d.ts +27 -0
- package/dist/controller/store.js +40 -0
- package/dist/declarations/application/shells/charcell/components/Application/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/Bar/index.d.ts +11 -0
- package/dist/declarations/application/shells/charcell/components/CodePane/index.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/components/ComponentStage/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/Control/index.d.ts +9 -0
- package/dist/declarations/application/shells/charcell/components/CopyLink/index.d.ts +1 -0
- package/dist/declarations/application/shells/charcell/components/Description/index.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/components/EditorAddDialog/index.d.ts +6 -0
- package/dist/declarations/application/shells/charcell/components/EditorPanel/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/EventsRow/index.d.ts +4 -0
- package/dist/declarations/application/shells/charcell/components/HeadingRow/index.d.ts +6 -0
- package/dist/declarations/application/shells/charcell/components/Hint/index.d.ts +11 -0
- package/dist/declarations/application/shells/charcell/components/HtmlWarnings/index.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/components/KeyHints/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/KitCodeBlock/index.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/components/Markdown/index.d.ts +3 -0
- package/dist/declarations/application/shells/charcell/components/Navigation/index.d.ts +8 -0
- package/dist/declarations/application/shells/charcell/components/NavigationSplit/index.d.ts +7 -0
- package/dist/declarations/application/shells/charcell/components/OptionControls/index.d.ts +7 -0
- package/dist/declarations/application/shells/charcell/components/PaneStatus/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/PaneWidth/index.d.ts +4 -0
- package/dist/declarations/application/shells/charcell/components/PreviewGrid/index.d.ts +7 -0
- package/dist/declarations/application/shells/charcell/components/PreviewPane/index.d.ts +9 -0
- package/dist/declarations/application/shells/charcell/components/PromptBar/index.d.ts +1 -0
- package/dist/declarations/application/shells/charcell/components/ScenarioRow/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/Select/index.d.ts +16 -0
- package/dist/declarations/application/shells/charcell/components/SlotOutlet/index.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/components/StageBar/index.d.ts +2 -0
- package/dist/declarations/application/shells/charcell/components/StageSplit/index.d.ts +17 -0
- package/dist/declarations/application/shells/charcell/components/StatusBar/index.d.ts +1 -0
- package/dist/declarations/application/shells/charcell/components/ViewControls/index.d.ts +9 -0
- package/dist/declarations/application/shells/charcell/components/ViewHeading/index.d.ts +4 -0
- package/dist/declarations/application/shells/charcell/components/ViewStage/index.d.ts +4 -0
- package/dist/declarations/application/shells/charcell/components/WrapToggle/index.d.ts +1 -0
- package/dist/declarations/application/shells/charcell/configuration.d.ts +31 -0
- package/dist/declarations/application/shells/charcell/controller-context.d.ts +9 -0
- package/dist/declarations/application/shells/charcell/fit-labels.d.ts +18 -0
- package/dist/declarations/application/shells/charcell/html-warnings.d.ts +5 -0
- package/dist/declarations/application/shells/charcell/index.d.ts +39 -0
- package/dist/declarations/application/shells/charcell/placement.d.ts +7 -0
- package/dist/declarations/application/shells/charcell/shell-options.d.ts +15 -0
- package/dist/declarations/application/shells/charcell/shell.d.ts +9 -0
- package/dist/declarations/application/shells/charcell/split-reset.d.ts +30 -0
- package/dist/declarations/application/shells/charcell/stacked-rows.d.ts +58 -0
- package/dist/declarations/application/shells/charcell/stage-toggles.d.ts +28 -0
- package/dist/declarations/src/controller/catalog.d.ts +339 -0
- package/dist/declarations/src/controller/create-preview-controller.d.ts +532 -0
- package/dist/declarations/src/controller/editor-tree.d.ts +161 -0
- package/dist/declarations/src/controller/html-source.d.ts +62 -0
- package/dist/declarations/src/controller/index.d.ts +9 -0
- package/dist/declarations/src/controller/persistence.d.ts +191 -0
- package/dist/declarations/src/controller/regeneration.d.ts +30 -0
- package/dist/declarations/src/controller/source.d.ts +80 -0
- package/dist/declarations/src/controller/store.d.ts +27 -0
- package/dist/declarations/src/emit/common.d.ts +103 -0
- package/dist/declarations/src/emit/manifest.d.ts +138 -0
- package/dist/declarations/src/emit/source.d.ts +87 -0
- package/dist/declarations/src/lib/jsx-roots.d.ts +22 -0
- package/dist/declarations/src/lib/module-of-source.d.ts +18 -0
- package/dist/declarations/src/lib/naming.d.ts +29 -0
- package/dist/declarations/src/lib/react-spelling.d.ts +68 -0
- package/dist/declarations/src/lib/scenario-story.d.ts +41 -0
- package/dist/declarations/src/lib/slot-fill.d.ts +15 -0
- package/dist/declarations/src/lib/types.d.ts +741 -0
- package/dist/declarations/src/options.d.ts +224 -0
- package/dist/declarations/src/protocol.d.ts +541 -0
- package/dist/declarations/src/react-view.d.ts +22 -0
- package/dist/declarations/src/react.d.ts +17 -0
- package/dist/declarations/src/shell.d.ts +99 -0
- package/dist/declarations/src/views.d.ts +152 -0
- package/dist/development-server.d.ts +121 -0
- package/dist/development-server.js +331 -0
- package/dist/emit/common.d.ts +103 -0
- package/dist/emit/common.js +170 -0
- package/dist/emit/html-source.d.ts +46 -0
- package/dist/emit/html-source.js +322 -0
- package/dist/emit/manifest.d.ts +138 -0
- package/dist/emit/manifest.js +74 -0
- package/dist/emit/react.d.ts +16 -0
- package/dist/emit/react.js +210 -0
- package/dist/emit/scratch.d.ts +40 -0
- package/dist/emit/scratch.js +116 -0
- package/dist/emit/source.d.ts +87 -0
- package/dist/emit/source.js +789 -0
- package/dist/emit/svelte.d.ts +9 -0
- package/dist/emit/svelte.js +177 -0
- package/dist/emit/vue.d.ts +2 -0
- package/dist/emit/vue.js +152 -0
- package/dist/enumerate.d.ts +2 -0
- package/dist/enumerate.js +162 -0
- package/dist/generate.d.ts +43 -0
- package/dist/generate.js +302 -0
- package/dist/html-stylesheet.d.ts +43 -0
- package/dist/html-stylesheet.js +145 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +21 -0
- package/dist/landing.d.ts +16 -0
- package/dist/landing.js +45 -0
- package/dist/lib/exported-types.d.ts +42 -0
- package/dist/lib/exported-types.js +86 -0
- package/dist/lib/html-attributes.d.ts +2 -0
- package/dist/lib/html-attributes.js +111 -0
- package/dist/lib/html-warnings.d.ts +19 -0
- package/dist/lib/html-warnings.js +79 -0
- package/dist/lib/jsx-roots.d.ts +22 -0
- package/dist/lib/jsx-roots.js +243 -0
- package/dist/lib/module-of-source.d.ts +18 -0
- package/dist/lib/module-of-source.js +24 -0
- package/dist/lib/naming.d.ts +29 -0
- package/dist/lib/naming.js +56 -0
- package/dist/lib/parse-type.d.ts +32 -0
- package/dist/lib/parse-type.js +103 -0
- package/dist/lib/react-spelling.d.ts +68 -0
- package/dist/lib/react-spelling.js +197 -0
- package/dist/lib/scenario-story.d.ts +41 -0
- package/dist/lib/scenario-story.js +84 -0
- package/dist/lib/slot-fill.d.ts +15 -0
- package/dist/lib/slot-fill.js +92 -0
- package/dist/lib/template-files.d.ts +14 -0
- package/dist/lib/template-files.js +25 -0
- package/dist/lib/types.d.ts +741 -0
- package/dist/lib/types.js +13 -0
- package/dist/lib/void-elements.d.ts +7 -0
- package/dist/lib/void-elements.js +13 -0
- package/dist/load.d.ts +37 -0
- package/dist/load.js +82 -0
- package/dist/model.d.ts +44 -0
- package/dist/model.js +464 -0
- package/dist/options.d.ts +224 -0
- package/dist/options.js +223 -0
- package/dist/prop-types.d.ts +26 -0
- package/dist/prop-types.js +102 -0
- package/dist/props-from.d.ts +84 -0
- package/dist/props-from.js +510 -0
- package/dist/protocol.d.ts +541 -0
- package/dist/protocol.js +819 -0
- package/dist/react-view.d.ts +22 -0
- package/dist/react-view.js +36 -0
- package/dist/react.d.ts +17 -0
- package/dist/react.js +23 -0
- package/dist/sass-importers.d.ts +26 -0
- package/dist/sass-importers.js +32 -0
- package/dist/shell-acceptance.d.ts +21 -0
- package/dist/shell-acceptance.js +37 -0
- package/dist/shell-page.d.ts +36 -0
- package/dist/shell-page.js +90 -0
- package/dist/shell-peers.d.ts +38 -0
- package/dist/shell-peers.js +61 -0
- package/dist/shell.d.ts +99 -0
- package/dist/shell.js +52 -0
- package/dist/shells/charcell/page.d.ts +8 -0
- package/dist/shells/charcell/page.js +69 -0
- package/dist/story-source.d.ts +113 -0
- package/dist/story-source.js +271 -0
- package/dist/story.d.ts +5 -0
- package/dist/story.js +28 -0
- package/dist/testing.d.ts +218 -0
- package/dist/testing.js +284 -0
- package/dist/views.d.ts +152 -0
- package/dist/views.js +7 -0
- package/dist/vite-configuration.d.ts +114 -0
- package/dist/vite-configuration.js +578 -0
- package/package.json +123 -3
- package/src/build.ts +51 -0
- package/src/check.ts +1062 -0
- package/src/cli.ts +123 -0
- package/src/context.ts +1168 -0
- package/src/controller/catalog.ts +719 -0
- package/src/controller/create-preview-controller.ts +2683 -0
- package/src/controller/editor-tree.ts +530 -0
- package/src/controller/html-source.ts +114 -0
- package/src/controller/index.ts +105 -0
- package/src/controller/persistence.ts +403 -0
- package/src/controller/regeneration.ts +55 -0
- package/src/controller/source.ts +333 -0
- package/src/controller/store.ts +55 -0
- package/src/development-server.ts +442 -0
- package/src/emit/common.ts +201 -0
- package/src/emit/html-source.ts +402 -0
- package/src/emit/manifest.ts +241 -0
- package/src/emit/react.ts +263 -0
- package/src/emit/scratch.ts +175 -0
- package/src/emit/source.ts +1094 -0
- package/src/emit/svelte.ts +230 -0
- package/src/emit/vue.ts +194 -0
- package/src/enumerate.ts +220 -0
- package/src/generate.ts +443 -0
- package/src/html-stylesheet.ts +173 -0
- package/src/index.ts +60 -0
- package/src/landing.ts +58 -0
- package/src/lib/exported-types.ts +114 -0
- package/src/lib/html-attributes.ts +113 -0
- package/src/lib/html-warnings.ts +81 -0
- package/src/lib/jsx-roots.ts +238 -0
- package/src/lib/module-of-source.ts +26 -0
- package/src/lib/naming.ts +65 -0
- package/src/lib/parse-type.ts +143 -0
- package/src/lib/react-spelling.ts +235 -0
- package/src/lib/scenario-story.ts +97 -0
- package/src/lib/slot-fill.ts +102 -0
- package/src/lib/template-files.ts +31 -0
- package/src/lib/types.ts +778 -0
- package/src/lib/void-elements.ts +15 -0
- package/src/load.ts +144 -0
- package/src/model.ts +568 -0
- package/src/options.ts +435 -0
- package/src/prop-types.ts +133 -0
- package/src/props-from.ts +678 -0
- package/src/protocol.ts +1135 -0
- package/src/react-view.ts +45 -0
- package/src/react.ts +34 -0
- package/src/sass-importers.ts +45 -0
- package/src/shell-acceptance.ts +45 -0
- package/src/shell-page.ts +133 -0
- package/src/shell-peers.ts +70 -0
- package/src/shell.ts +194 -0
- package/src/shells/charcell/page.ts +82 -0
- package/src/story-source.ts +391 -0
- package/src/story.ts +42 -0
- package/src/testing.ts +497 -0
- package/src/views.ts +183 -0
- package/src/vite-configuration.ts +675 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
// A story's source printed in the browser from the catalog: the code a
|
|
2
|
+
// consumer writes per target, importing from the kit's package entries,
|
|
3
|
+
// with the props a person sets and the slot content the story or the editor's
|
|
4
|
+
// tree holds. The printers are pure, so the source follows every change
|
|
5
|
+
// without a round trip; the html source, which renders the kit's templates,
|
|
6
|
+
// is the server's (html-source.ts). Browser-safe.
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
inDeclarationOrder,
|
|
10
|
+
SOURCE_PRINTERS,
|
|
11
|
+
type SourceBinding,
|
|
12
|
+
type SourceStory,
|
|
13
|
+
} from '../emit/source.js';
|
|
14
|
+
import { collectSlotComponents } from '../lib/slot-fill.js';
|
|
15
|
+
import { moduleOfSource } from '../lib/module-of-source.js';
|
|
16
|
+
import type { JsonValue, SlotFill, StoryAround } from '../lib/types.js';
|
|
17
|
+
import type { PreviewScriptedTarget } from '../protocol.js';
|
|
18
|
+
import {
|
|
19
|
+
defaultScenarioId,
|
|
20
|
+
type PreviewCatalog,
|
|
21
|
+
type PreviewComponent,
|
|
22
|
+
type PreviewScenario,
|
|
23
|
+
type PreviewStoryReference,
|
|
24
|
+
} from './catalog.js';
|
|
25
|
+
import { cleanRecord, toPayload, type EditorState } from './editor-tree.js';
|
|
26
|
+
|
|
27
|
+
/** A story's source, by scripted target: what a consumer writes. */
|
|
28
|
+
export type PreviewTargetCode = Partial<Record<PreviewScriptedTarget, string>>;
|
|
29
|
+
|
|
30
|
+
/** A story resolved for printing: its component, the props to print and its
|
|
31
|
+
* slot content. */
|
|
32
|
+
export interface ResolvedSourceStory {
|
|
33
|
+
/** The root component's name. */
|
|
34
|
+
component: string;
|
|
35
|
+
/** The props a consumer writes: those that differ from what the component
|
|
36
|
+
* and the preview start from. */
|
|
37
|
+
props: Record<string, JsonValue>;
|
|
38
|
+
/** Default-slot content. */
|
|
39
|
+
children?: SlotFill;
|
|
40
|
+
/** Named-slot content, by slot name. */
|
|
41
|
+
named: Record<string, SlotFill>;
|
|
42
|
+
/** The content beside the component, as its siblings. */
|
|
43
|
+
around?: StoryAround;
|
|
44
|
+
/** The two-way props the story gives, which the printed source binds to
|
|
45
|
+
* state of its own. Absent when it gives none. */
|
|
46
|
+
bindings?: SourceBinding[];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The catalog fields the printing reads. */
|
|
50
|
+
export type SourceCatalog = Pick<
|
|
51
|
+
PreviewCatalog,
|
|
52
|
+
'imports' | 'sources' | 'kitName'
|
|
53
|
+
> &
|
|
54
|
+
Partial<Pick<PreviewCatalog, 'svelteMode' | 'reactAttributeNames'>>;
|
|
55
|
+
|
|
56
|
+
function withoutUndefined(
|
|
57
|
+
props: Record<string, unknown>
|
|
58
|
+
): Record<string, JsonValue> {
|
|
59
|
+
const out: Record<string, JsonValue> = {};
|
|
60
|
+
for (const [name, value] of Object.entries(props))
|
|
61
|
+
if (value !== undefined) out[name] = value as JsonValue;
|
|
62
|
+
return out;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Whether a story's default-slot text is the component's name the preview
|
|
67
|
+
* shows in a default slot the story leaves unfilled, which a consumer never
|
|
68
|
+
* writes: the preview's own starting text, while the scenario does not give
|
|
69
|
+
* `children` itself.
|
|
70
|
+
*/
|
|
71
|
+
export function isPlaceholder(
|
|
72
|
+
component: PreviewComponent,
|
|
73
|
+
text: string,
|
|
74
|
+
input: { scenario?: PreviewScenario }
|
|
75
|
+
): boolean {
|
|
76
|
+
return (
|
|
77
|
+
component.previewDefaults.children === text &&
|
|
78
|
+
!('children' in (input.scenario?.props ?? {}))
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Resolve what a story's source prints. Without a tree, the slot content is
|
|
84
|
+
* the story's own and a string `children` is its default-slot text; with the
|
|
85
|
+
* editor's tree, the root's props and content are the tree's. A prop is left
|
|
86
|
+
* out while it holds the component's declared default, or the preview's own
|
|
87
|
+
* starting value that the scenario does not set, as is the component's name
|
|
88
|
+
* the preview shows in a default slot the story leaves unfilled.
|
|
89
|
+
*/
|
|
90
|
+
export function resolveSourceStory(
|
|
91
|
+
component: PreviewComponent,
|
|
92
|
+
input: {
|
|
93
|
+
props: Record<string, unknown>;
|
|
94
|
+
scenario?: PreviewScenario;
|
|
95
|
+
tree?: EditorState;
|
|
96
|
+
}
|
|
97
|
+
): ResolvedSourceStory {
|
|
98
|
+
let props: Record<string, JsonValue>;
|
|
99
|
+
let children: SlotFill | undefined;
|
|
100
|
+
let named: Record<string, SlotFill>;
|
|
101
|
+
if (input.tree) {
|
|
102
|
+
const payload = toPayload(input.tree);
|
|
103
|
+
const { children: _children, ...rootProps } = input.props;
|
|
104
|
+
props = cleanRecord(rootProps);
|
|
105
|
+
children = payload.slots?.default;
|
|
106
|
+
named = payload.slots?.named ?? {};
|
|
107
|
+
} else {
|
|
108
|
+
const { children: text, ...rest } = input.props;
|
|
109
|
+
props = withoutUndefined(rest);
|
|
110
|
+
// A scenario with content of its own shows that in place of the story's.
|
|
111
|
+
const content = input.scenario?.content ?? component.content;
|
|
112
|
+
children =
|
|
113
|
+
content?.default ??
|
|
114
|
+
(typeof text === 'string' && !isPlaceholder(component, text, input)
|
|
115
|
+
? { kind: 'text', value: text }
|
|
116
|
+
: undefined);
|
|
117
|
+
named = content?.named ?? {};
|
|
118
|
+
}
|
|
119
|
+
const declared = new Map(
|
|
120
|
+
component.propTypes.map((propType) => [propType.name, propType])
|
|
121
|
+
);
|
|
122
|
+
const scenarioProps = input.scenario?.props ?? {};
|
|
123
|
+
for (const [name, value] of Object.entries(props)) {
|
|
124
|
+
const declaredDefault = declared.get(name)?.declaredDefault;
|
|
125
|
+
const previewDefault = component.previewDefaults[name];
|
|
126
|
+
if (
|
|
127
|
+
(declaredDefault !== undefined &&
|
|
128
|
+
JSON.stringify(declaredDefault) === JSON.stringify(value)) ||
|
|
129
|
+
(previewDefault !== undefined &&
|
|
130
|
+
!(name in scenarioProps) &&
|
|
131
|
+
JSON.stringify(previewDefault) === JSON.stringify(value))
|
|
132
|
+
)
|
|
133
|
+
delete props[name];
|
|
134
|
+
}
|
|
135
|
+
props = inDeclarationOrder(
|
|
136
|
+
props,
|
|
137
|
+
component.propTypes.map((propType) => propType.name)
|
|
138
|
+
);
|
|
139
|
+
// A two-way prop the story gives is controlled: its source binds it.
|
|
140
|
+
const bindings = (component.bindings ?? [])
|
|
141
|
+
.filter((binding) => binding.prop in props)
|
|
142
|
+
.map((binding) => {
|
|
143
|
+
const declaredType = declared.get(binding.prop)?.declaredType;
|
|
144
|
+
return {
|
|
145
|
+
prop: binding.prop,
|
|
146
|
+
...(binding.changeProp !== undefined
|
|
147
|
+
? { changeProp: binding.changeProp }
|
|
148
|
+
: {}),
|
|
149
|
+
...(binding.defaultProp !== undefined
|
|
150
|
+
? { defaultProp: binding.defaultProp }
|
|
151
|
+
: {}),
|
|
152
|
+
...(binding.vueModel ? { vueModel: true } : {}),
|
|
153
|
+
...(binding.generic ? { generic: true } : {}),
|
|
154
|
+
...(declaredType !== undefined ? { declaredType } : {}),
|
|
155
|
+
};
|
|
156
|
+
});
|
|
157
|
+
// The content beside the component is the story's, with or without the
|
|
158
|
+
// editor's tree: no edit reaches it.
|
|
159
|
+
const around = component.around;
|
|
160
|
+
return {
|
|
161
|
+
component: component.name,
|
|
162
|
+
props,
|
|
163
|
+
...(children ? { children } : {}),
|
|
164
|
+
named,
|
|
165
|
+
...(around ? { around } : {}),
|
|
166
|
+
...(bindings.length > 0 ? { bindings } : {}),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** The import of each component a story names, for one target: its root,
|
|
171
|
+
* then what its slot content holds, in order. */
|
|
172
|
+
function importsFor(
|
|
173
|
+
catalog: SourceCatalog,
|
|
174
|
+
story: ResolvedSourceStory,
|
|
175
|
+
target: PreviewScriptedTarget
|
|
176
|
+
): SourceStory['imports'] {
|
|
177
|
+
const names = new Set<string>();
|
|
178
|
+
collectSlotComponents(story.children, names);
|
|
179
|
+
for (const fill of [
|
|
180
|
+
...Object.values(story.named),
|
|
181
|
+
story.around?.before,
|
|
182
|
+
story.around?.after,
|
|
183
|
+
])
|
|
184
|
+
collectSlotComponents(fill, names);
|
|
185
|
+
const base = catalog.sources[0]?.moduleBase ?? catalog.kitName;
|
|
186
|
+
const imports: SourceStory['imports'] = new Map();
|
|
187
|
+
for (const name of [story.component, ...names]) {
|
|
188
|
+
if (imports.has(name)) continue;
|
|
189
|
+
const known = catalog.imports[name];
|
|
190
|
+
imports.set(name, {
|
|
191
|
+
module: known?.modules[target] ?? moduleOfSource(base, target),
|
|
192
|
+
exported: known?.exportName ?? name,
|
|
193
|
+
...(known?.declaredAttributes
|
|
194
|
+
? { declaredAttributes: known.declaredAttributes }
|
|
195
|
+
: {}),
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
return imports;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** The type names the kit's components' modules export, for one target,
|
|
202
|
+
* each with the module a consumer imports it from: the story's own
|
|
203
|
+
* component's, then the first other component's to export it. A name a
|
|
204
|
+
* component is imported under is a value, never a type here. */
|
|
205
|
+
function exportedTypesFor(
|
|
206
|
+
catalog: SourceCatalog,
|
|
207
|
+
target: PreviewScriptedTarget,
|
|
208
|
+
component: string
|
|
209
|
+
): Map<string, string> {
|
|
210
|
+
const base = catalog.sources[0]?.moduleBase ?? catalog.kitName;
|
|
211
|
+
// A component's own name, or the name it is exported under, is a value.
|
|
212
|
+
const values = new Set(
|
|
213
|
+
Object.entries(catalog.imports).flatMap(([name, known]) => [
|
|
214
|
+
name,
|
|
215
|
+
known.exportName,
|
|
216
|
+
])
|
|
217
|
+
);
|
|
218
|
+
const types = new Map<string, string>();
|
|
219
|
+
// The story's own component first, so its type wins a name another
|
|
220
|
+
// component's module exports too.
|
|
221
|
+
const own = catalog.imports[component];
|
|
222
|
+
const entries = [
|
|
223
|
+
...(own ? [own] : []),
|
|
224
|
+
...Object.entries(catalog.imports)
|
|
225
|
+
.filter(([name]) => name !== component)
|
|
226
|
+
.map(([, known]) => known),
|
|
227
|
+
];
|
|
228
|
+
for (const known of entries)
|
|
229
|
+
for (const type of known.types?.[target] ?? [])
|
|
230
|
+
if (!types.has(type) && !values.has(type))
|
|
231
|
+
types.set(type, known.modules[target] ?? moduleOfSource(base, target));
|
|
232
|
+
return types;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Print a resolved story in each of `targets`: a two-way prop it gives
|
|
237
|
+
* bound to state of the source's own, in the catalog's Svelte mode.
|
|
238
|
+
*
|
|
239
|
+
* @param catalog - The catalog the components' imports are read from.
|
|
240
|
+
* @param story - The story, resolved.
|
|
241
|
+
* @param targets - The targets to print.
|
|
242
|
+
* @returns The source per target.
|
|
243
|
+
*/
|
|
244
|
+
export function printSourceStory(
|
|
245
|
+
catalog: SourceCatalog,
|
|
246
|
+
story: ResolvedSourceStory,
|
|
247
|
+
targets: readonly PreviewScriptedTarget[]
|
|
248
|
+
): PreviewTargetCode {
|
|
249
|
+
const sources: PreviewTargetCode = {};
|
|
250
|
+
for (const target of targets) {
|
|
251
|
+
sources[target] = SOURCE_PRINTERS[target]({
|
|
252
|
+
component: story.component,
|
|
253
|
+
props: story.props,
|
|
254
|
+
...(story.children ? { children: story.children } : {}),
|
|
255
|
+
named: story.named,
|
|
256
|
+
...(story.around ? { around: story.around } : {}),
|
|
257
|
+
imports: importsFor(catalog, story, target),
|
|
258
|
+
...(story.bindings ? { bindings: story.bindings } : {}),
|
|
259
|
+
...(catalog.svelteMode ? { svelteMode: catalog.svelteMode } : {}),
|
|
260
|
+
...(catalog.reactAttributeNames
|
|
261
|
+
? { reactAttributeNames: catalog.reactAttributeNames }
|
|
262
|
+
: {}),
|
|
263
|
+
exportedTypes: exportedTypesFor(catalog, target, story.component),
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
return sources;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Print any story of the catalog as the source a consumer writes, per
|
|
271
|
+
* target the component renders in: the component with the props of the
|
|
272
|
+
* scenario over its defaults and `props` over those, its slot content, and
|
|
273
|
+
* imports from the kit's package entry for each target. A prop is left
|
|
274
|
+
* out while it holds the component's declared default. It takes the story
|
|
275
|
+
* reference `frames.mountStory` takes, so a shell can show the code beside a
|
|
276
|
+
* detached pane. The html source is the preview's own (`state.code.html`)
|
|
277
|
+
* and is not printed here.
|
|
278
|
+
*
|
|
279
|
+
* @param catalog - The controller's catalog.
|
|
280
|
+
* @param story - The story: a component's id, a scenario (omitted, the one
|
|
281
|
+
* the story starts on; `''`, the anonymous default) and props over its own.
|
|
282
|
+
* @returns The source per target, in the component's targets.
|
|
283
|
+
* @throws When the component or the scenario is unknown.
|
|
284
|
+
* @example
|
|
285
|
+
* ```ts
|
|
286
|
+
* const { react } = printStorySource(controller.catalog, { component: 'components-button', scenario: 'ghost' });
|
|
287
|
+
* ```
|
|
288
|
+
*/
|
|
289
|
+
export function printStorySource(
|
|
290
|
+
catalog: PreviewCatalog,
|
|
291
|
+
story: PreviewStoryReference
|
|
292
|
+
): PreviewTargetCode {
|
|
293
|
+
const component = catalog.components.find(
|
|
294
|
+
(candidate) => candidate.id === story.component
|
|
295
|
+
);
|
|
296
|
+
if (!component)
|
|
297
|
+
throw new Error(
|
|
298
|
+
`The catalog has no component "${story.component}" to print.`
|
|
299
|
+
);
|
|
300
|
+
const scenarioId = story.scenario ?? defaultScenarioId(component);
|
|
301
|
+
const scenario = component.scenarios.find(
|
|
302
|
+
(candidate) => candidate.id === scenarioId
|
|
303
|
+
);
|
|
304
|
+
if (scenarioId !== '' && !scenario)
|
|
305
|
+
throw new Error(
|
|
306
|
+
`The story "${component.id}" has no scenario "${scenarioId}".`
|
|
307
|
+
);
|
|
308
|
+
const seeded = { ...component.defaultProps, ...(scenario?.props ?? {}) };
|
|
309
|
+
// The Empty scenario is the story's props with no slot content.
|
|
310
|
+
const props = {
|
|
311
|
+
...(scenario?.empty ? withoutChildren(seeded) : seeded),
|
|
312
|
+
...withoutUndefined(story.props ?? {}),
|
|
313
|
+
};
|
|
314
|
+
const resolved = scenario?.empty
|
|
315
|
+
? resolveSourceStory(component, {
|
|
316
|
+
props,
|
|
317
|
+
scenario,
|
|
318
|
+
tree: {
|
|
319
|
+
root: component.name,
|
|
320
|
+
props: withoutChildren(props),
|
|
321
|
+
slots: {},
|
|
322
|
+
},
|
|
323
|
+
})
|
|
324
|
+
: resolveSourceStory(component, { props, scenario });
|
|
325
|
+
return printSourceStory(catalog, resolved, component.targets);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function withoutChildren(
|
|
329
|
+
props: Record<string, unknown>
|
|
330
|
+
): Record<string, unknown> {
|
|
331
|
+
const { children: _children, ...rest } = props;
|
|
332
|
+
return rest;
|
|
333
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// A store view of the preview controller: an object with one `subscribe`
|
|
2
|
+
// method that calls its listener with the current value at once and again
|
|
3
|
+
// whenever the value changes. That is the Svelte store contract, so a Svelte
|
|
4
|
+
// shell reads it with `$store` or `fromStore`, and it suits any other
|
|
5
|
+
// store-shaped consumer. Framework-neutral and browser-safe.
|
|
6
|
+
|
|
7
|
+
import type {
|
|
8
|
+
PreviewController,
|
|
9
|
+
PreviewState,
|
|
10
|
+
} from './create-preview-controller.js';
|
|
11
|
+
|
|
12
|
+
/** A readable store: `subscribe` calls `listener` with the current value
|
|
13
|
+
* immediately, then with each new value, until the returned function is called. */
|
|
14
|
+
export interface PreviewStore<Value> {
|
|
15
|
+
subscribe(listener: (value: Value) => void): () => void;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* A store of the controller's state, or of a slice of it. Each subscriber is
|
|
20
|
+
* called with the current slice when it subscribes, and again only when the
|
|
21
|
+
* slice changes by identity, so `selector` returns a field of the state (or a
|
|
22
|
+
* primitive derived from it) rather than a fresh object or array.
|
|
23
|
+
*
|
|
24
|
+
* @param controller - The controller to read.
|
|
25
|
+
* @param selector - Picks the slice; the whole state when omitted.
|
|
26
|
+
* @returns The store.
|
|
27
|
+
* @example
|
|
28
|
+
* ```svelte
|
|
29
|
+
* <script lang="ts">
|
|
30
|
+
* import { previewStore } from '@scaffold-ui-kit/preview/shell';
|
|
31
|
+
* const preview = previewStore(controller);
|
|
32
|
+
* const scenario = previewStore(controller, (state) => state.scenario);
|
|
33
|
+
* </script>
|
|
34
|
+
*
|
|
35
|
+
* <p>{$preview.selection.id}: {$scenario}</p>
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export function previewStore<Selected = PreviewState>(
|
|
39
|
+
controller: Pick<PreviewController, 'getState' | 'subscribe'>,
|
|
40
|
+
selector: (state: PreviewState) => Selected = (state) =>
|
|
41
|
+
state as unknown as Selected
|
|
42
|
+
): PreviewStore<Selected> {
|
|
43
|
+
return {
|
|
44
|
+
subscribe(listener) {
|
|
45
|
+
let current = selector(controller.getState());
|
|
46
|
+
listener(current);
|
|
47
|
+
return controller.subscribe((state) => {
|
|
48
|
+
const next = selector(state);
|
|
49
|
+
if (Object.is(next, current)) return;
|
|
50
|
+
current = next;
|
|
51
|
+
listener(next);
|
|
52
|
+
});
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|