@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,224 @@
|
|
|
1
|
+
/** An option's runtime value: a string (a choice) or a boolean. */
|
|
2
|
+
export type OptionValue = string | boolean;
|
|
3
|
+
/** One value a choice option offers. */
|
|
4
|
+
export interface OptionChoice {
|
|
5
|
+
value: string;
|
|
6
|
+
label: string;
|
|
7
|
+
}
|
|
8
|
+
/** What kind of value an option holds: one of its `values`, or a boolean. */
|
|
9
|
+
export type OptionKind = 'choice' | 'boolean';
|
|
10
|
+
/** The group of the kit's own settings, such as its theme: what sets up the
|
|
11
|
+
* kit as a whole rather than the setting a component is shown in. */
|
|
12
|
+
export declare const KIT_OPTION_GROUP = "kit";
|
|
13
|
+
/** The group of the options that set what a component is shown in, such as a
|
|
14
|
+
* color mode, a surface or the padding around it. An option without a group
|
|
15
|
+
* belongs to it. */
|
|
16
|
+
export declare const CONTEXT_OPTION_GROUP = "context";
|
|
17
|
+
/** The prefix of a shell option's id in the preview's state, address and
|
|
18
|
+
* storage: a shell's `mode` is `shell.mode`, so it cannot collide with a kit
|
|
19
|
+
* option of the same name. */
|
|
20
|
+
export declare const SHELL_OPTION_PREFIX = "shell.";
|
|
21
|
+
/** Which element an apply targets. `'root'` is the preview `<html>` (the
|
|
22
|
+
* default), `'body'` is `<body>`, and `{ ref }` is a named node in the
|
|
23
|
+
* kit's `mount` wrapper (resolved against the ref map). */
|
|
24
|
+
export type ApplyTarget = 'root' | 'body' | {
|
|
25
|
+
ref: string;
|
|
26
|
+
};
|
|
27
|
+
/** How an option affects the preview canvas. The union is open by design - a
|
|
28
|
+
* new strategy slots in without touching the registry. `root-attribute` /
|
|
29
|
+
* `class` / `css-var` may carry a `target` to hit a `mount` wrapper
|
|
30
|
+
* node instead of the document root. */
|
|
31
|
+
export type OptionApply =
|
|
32
|
+
/** Set `<attribute>="<value>"` on the target element (default the preview
|
|
33
|
+
* `<html>`); `false` or an empty value removes it. With `omitAtDefault`,
|
|
34
|
+
* the option's default value removes it too, for a kit whose default
|
|
35
|
+
* renders with no attribute, such as a default color mode. */
|
|
36
|
+
{
|
|
37
|
+
type: 'root-attribute';
|
|
38
|
+
attribute: string;
|
|
39
|
+
target?: ApplyTarget;
|
|
40
|
+
omitAtDefault?: boolean;
|
|
41
|
+
}
|
|
42
|
+
/** Swap the active theme stylesheet by value (`themes/<id>/theme.css`
|
|
43
|
+
* under the URL the preview is served from). */
|
|
44
|
+
| {
|
|
45
|
+
type: 'stylesheet';
|
|
46
|
+
}
|
|
47
|
+
/** Toggle `className` on the target by the value's truth; without
|
|
48
|
+
* `className`, set the value as the target's `data-<namePrefix>-preview-class`
|
|
49
|
+
* attribute for the kit's CSS to key off, `false` or an empty value removing
|
|
50
|
+
* it. `on` names `'root'` or `'body'`; `target` names either as well, or
|
|
51
|
+
* a wrapper node, and wins where both are given. */
|
|
52
|
+
| {
|
|
53
|
+
type: 'class';
|
|
54
|
+
on?: 'root' | 'body';
|
|
55
|
+
className?: string;
|
|
56
|
+
target?: ApplyTarget;
|
|
57
|
+
}
|
|
58
|
+
/** Set a CSS custom property to the value on the target element; `false` or
|
|
59
|
+
* an empty value removes it. */
|
|
60
|
+
| {
|
|
61
|
+
type: 'css-var';
|
|
62
|
+
var: string;
|
|
63
|
+
target?: ApplyTarget;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* One preview option: what it means, never where or how it is shown. Its kind
|
|
67
|
+
* follows from its fields - an option with `values` is a choice among them
|
|
68
|
+
* with a string `default`, and one without is a boolean with a boolean
|
|
69
|
+
* `default` - and the preview's interface picks the widget for that kind.
|
|
70
|
+
*/
|
|
71
|
+
export interface PreviewOption {
|
|
72
|
+
/** Stable key - the message payload key and the manifest per-story override key. */
|
|
73
|
+
id: string;
|
|
74
|
+
/** The option's name, as its control is labeled. */
|
|
75
|
+
label: string;
|
|
76
|
+
/** A longer description, such as a control's tooltip; markdown allowed. */
|
|
77
|
+
title?: string;
|
|
78
|
+
/** The values of a choice option. Omitted, the option is a boolean. */
|
|
79
|
+
values?: OptionChoice[];
|
|
80
|
+
/** The starting value: one of `values` for a choice, a boolean otherwise. */
|
|
81
|
+
default: OptionValue;
|
|
82
|
+
/** A free-form hint for where the option belongs: `'context'` (the
|
|
83
|
+
* default) for the setting a component is shown in, such as its color
|
|
84
|
+
* mode or the padding around it; `'kit'` for the kit's own settings, such
|
|
85
|
+
* as its theme; or a name of the kit's choosing for a set that belongs
|
|
86
|
+
* together, such as canvas settings. An interface places a group it does
|
|
87
|
+
* not know in a default place. */
|
|
88
|
+
group?: string;
|
|
89
|
+
/** `global` = one value for the whole session; `story` = a value per
|
|
90
|
+
* selected story, seeded from its story file, that lasts until another story
|
|
91
|
+
* is selected. */
|
|
92
|
+
scope: 'global' | 'story';
|
|
93
|
+
/** How the value hits the canvas. */
|
|
94
|
+
apply: OptionApply;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* An option a shell declares for itself, such as its own color mode or
|
|
98
|
+
* density: a {@link PreviewOption} without `apply` or `scope`. Its value
|
|
99
|
+
* never reaches the kit's iframes; the shell reads it from the preview's
|
|
100
|
+
* state under the id {@link shellOptionId} gives it, and it is global.
|
|
101
|
+
*/
|
|
102
|
+
export type PreviewShellOption = Omit<PreviewOption, 'apply' | 'scope'>;
|
|
103
|
+
/**
|
|
104
|
+
* The id a shell option has in the preview's state, address and storage.
|
|
105
|
+
*
|
|
106
|
+
* @param id - The option's id as the shell declares it.
|
|
107
|
+
* @returns The id prefixed with `shell.`.
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* shellOptionId('mode'); // 'shell.mode'
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export declare function shellOptionId(id: string): string;
|
|
114
|
+
/** The kit-authored canvas styling: what the preview page paints with. The
|
|
115
|
+
* preview's canvas stylesheet is a generic template over these values - the
|
|
116
|
+
* kit's token vocabulary lives HERE, never in the preview. Any wrapper
|
|
117
|
+
* geometry (surface fills, insets, padding) a kit wants lives in `extraCss`,
|
|
118
|
+
* keyed off the nodes it declares in `mount`. Values are raw CSS. */
|
|
119
|
+
export interface PreviewCanvasConfiguration {
|
|
120
|
+
/** Prefix for every preview-owned DOM name - injected element ids, the
|
|
121
|
+
* class-apply data attribute (`data-<prefix>-preview-class`). */
|
|
122
|
+
namePrefix: string;
|
|
123
|
+
/** Canvas page background, painted on `<body>`. Optional: a kit whose
|
|
124
|
+
* stylesheet already states its page canvas (the kit's own `html`/`body`
|
|
125
|
+
* rules, loaded with the theme) omits it, and the preview paints nothing -
|
|
126
|
+
* the preview document *is* the kit's page, and what the page is stays
|
|
127
|
+
* the kit's (and the theme's) call rather than a value restated here. */
|
|
128
|
+
pageBackground?: string;
|
|
129
|
+
/** Extra kit-authored CSS appended to the canvas stylesheet - where a kit
|
|
130
|
+
* styles its `mount` wrapper nodes and any option-driven geometry. */
|
|
131
|
+
extraCss?: string;
|
|
132
|
+
}
|
|
133
|
+
/** The canvas of a custom view's iframe, which shows a kit-authored view
|
|
134
|
+
* rather than a mounted component: no `mount` wrapper, so none of the
|
|
135
|
+
* component frame's geometry applies. A kit sets it as `viewCanvas`;
|
|
136
|
+
* without it a view gets `canvas.pageBackground` and nothing else. The
|
|
137
|
+
* name prefix stays `canvas.namePrefix`. Options still apply to a view,
|
|
138
|
+
* except one targeting a `mount` node by `ref`, which a view lacks. */
|
|
139
|
+
export interface PreviewViewCanvasConfiguration {
|
|
140
|
+
/** The view page's background, painted on `<body>`. */
|
|
141
|
+
pageBackground?: string;
|
|
142
|
+
/** Extra kit-authored CSS for the view page. */
|
|
143
|
+
extraCss?: string;
|
|
144
|
+
}
|
|
145
|
+
/** A node in a kit's `mount` wrapper tree - plain, framework-agnostic
|
|
146
|
+
* DOM rendered around the `#app` mount, identical across every preview iframe.
|
|
147
|
+
* The preview knows nothing of what these nodes mean; the kit styles them via
|
|
148
|
+
* `canvas.extraCss` and targets options at them by `ref`. */
|
|
149
|
+
export interface PreviewMountNode {
|
|
150
|
+
/** Element tag. Defaults to `'div'`. */
|
|
151
|
+
tag?: string;
|
|
152
|
+
/** Static attributes rendered on the element (e.g. a surface-cascade attribute). */
|
|
153
|
+
attributes?: Record<string, string>;
|
|
154
|
+
/** Static class names. */
|
|
155
|
+
classes?: string[];
|
|
156
|
+
/** Inline `style` text. */
|
|
157
|
+
style?: string;
|
|
158
|
+
/** Name for the ref map - the handle `apply.target = { ref }` resolves to,
|
|
159
|
+
* and how kit CSS and option targeting address this node. */
|
|
160
|
+
ref?: string;
|
|
161
|
+
/** Child nodes, rendered in order. */
|
|
162
|
+
children?: PreviewMountNode[];
|
|
163
|
+
/** Marks the node the `#app` mount is reparented into. Exactly one node in
|
|
164
|
+
* the tree sets this. */
|
|
165
|
+
mount?: boolean;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* The kind of an option: a choice when it has `values`, a boolean otherwise.
|
|
169
|
+
*
|
|
170
|
+
* @param option - The option.
|
|
171
|
+
* @returns `'choice'` or `'boolean'`.
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* optionKind({ values: [{ value: 'light', label: 'light' }] }); // 'choice'
|
|
175
|
+
* optionKind({}); // 'boolean'
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
export declare function optionKind(option: Pick<PreviewOption, 'values'>): OptionKind;
|
|
179
|
+
/**
|
|
180
|
+
* The group an option belongs to: its `group`, or `'context'` without one.
|
|
181
|
+
*
|
|
182
|
+
* @param option - The option.
|
|
183
|
+
* @returns The group name.
|
|
184
|
+
* @example
|
|
185
|
+
* ```ts
|
|
186
|
+
* optionGroup({ group: 'kit' }); // 'kit'
|
|
187
|
+
* optionGroup({}); // 'context'
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
export declare function optionGroup(option: Pick<PreviewOption, 'group'>): string;
|
|
191
|
+
/**
|
|
192
|
+
* Whether `value` is a value `option` can hold: one of its values for a
|
|
193
|
+
* choice, a boolean for a boolean.
|
|
194
|
+
*
|
|
195
|
+
* @param option - The option.
|
|
196
|
+
* @param value - The candidate value.
|
|
197
|
+
* @returns Whether the option accepts it.
|
|
198
|
+
*/
|
|
199
|
+
export declare function acceptsOptionValue(option: Pick<PreviewOption, 'values'>, value: unknown): value is OptionValue;
|
|
200
|
+
/**
|
|
201
|
+
* The problems with a kit's options, each naming the option: a missing or
|
|
202
|
+
* repeated id, a scope other than `global` or `story`, an option whose
|
|
203
|
+
* kind is ambiguous - a choice needs `values` and a string `default` among
|
|
204
|
+
* them, a boolean no `values` and a boolean `default` - and a key the
|
|
205
|
+
* option, one of its values or its `apply` does not take. Empty when every
|
|
206
|
+
* option is sound.
|
|
207
|
+
*
|
|
208
|
+
* @param options - The preview block's `options`.
|
|
209
|
+
* @returns One message per problem.
|
|
210
|
+
*/
|
|
211
|
+
export declare function optionProblems(options: unknown): string[];
|
|
212
|
+
/** The option registry keyed by id - O(1) lookup when applying a payload. */
|
|
213
|
+
export declare function optionsById(options: PreviewOption[]): Record<string, PreviewOption>;
|
|
214
|
+
/** Default values for the options in a scope (or all scopes). */
|
|
215
|
+
export declare function optionDefaults(options: Array<Pick<PreviewOption, 'id' | 'default' | 'scope'>>, scope?: 'global' | 'story'): Record<string, OptionValue>;
|
|
216
|
+
/**
|
|
217
|
+
* The served URL of a theme's stylesheet (the generator copies it there).
|
|
218
|
+
*
|
|
219
|
+
* @param themeId - The theme's id.
|
|
220
|
+
* @param baseUrl - The URL the preview is served under, ending in `/`; the
|
|
221
|
+
* root of the origin, `/`, by default.
|
|
222
|
+
* @returns The stylesheet's URL, such as `/themes/light/theme.css`.
|
|
223
|
+
*/
|
|
224
|
+
export declare function themeHref(themeId: string, baseUrl?: string): string;
|
package/dist/options.js
ADDED
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
// The composable preview-options contract: the preview block's `options`,
|
|
2
|
+
// `canvas`, `mount` and `viewCanvas`, and the derived helpers the host +
|
|
3
|
+
// iframes share. Browser-safe - no node imports; both the Vite app and the
|
|
4
|
+
// kit's configuration type against this file.
|
|
5
|
+
/** The group of the kit's own settings, such as its theme: what sets up the
|
|
6
|
+
* kit as a whole rather than the setting a component is shown in. */
|
|
7
|
+
export const KIT_OPTION_GROUP = 'kit';
|
|
8
|
+
/** The group of the options that set what a component is shown in, such as a
|
|
9
|
+
* color mode, a surface or the padding around it. An option without a group
|
|
10
|
+
* belongs to it. */
|
|
11
|
+
export const CONTEXT_OPTION_GROUP = 'context';
|
|
12
|
+
/** The prefix of a shell option's id in the preview's state, address and
|
|
13
|
+
* storage: a shell's `mode` is `shell.mode`, so it cannot collide with a kit
|
|
14
|
+
* option of the same name. */
|
|
15
|
+
export const SHELL_OPTION_PREFIX = 'shell.';
|
|
16
|
+
/**
|
|
17
|
+
* The id a shell option has in the preview's state, address and storage.
|
|
18
|
+
*
|
|
19
|
+
* @param id - The option's id as the shell declares it.
|
|
20
|
+
* @returns The id prefixed with `shell.`.
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* shellOptionId('mode'); // 'shell.mode'
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function shellOptionId(id) {
|
|
27
|
+
return `${SHELL_OPTION_PREFIX}${id}`;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The kind of an option: a choice when it has `values`, a boolean otherwise.
|
|
31
|
+
*
|
|
32
|
+
* @param option - The option.
|
|
33
|
+
* @returns `'choice'` or `'boolean'`.
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* optionKind({ values: [{ value: 'light', label: 'light' }] }); // 'choice'
|
|
37
|
+
* optionKind({}); // 'boolean'
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export function optionKind(option) {
|
|
41
|
+
return option.values !== undefined ? 'choice' : 'boolean';
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The group an option belongs to: its `group`, or `'context'` without one.
|
|
45
|
+
*
|
|
46
|
+
* @param option - The option.
|
|
47
|
+
* @returns The group name.
|
|
48
|
+
* @example
|
|
49
|
+
* ```ts
|
|
50
|
+
* optionGroup({ group: 'kit' }); // 'kit'
|
|
51
|
+
* optionGroup({}); // 'context'
|
|
52
|
+
* ```
|
|
53
|
+
*/
|
|
54
|
+
export function optionGroup(option) {
|
|
55
|
+
return option.group ?? CONTEXT_OPTION_GROUP;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Whether `value` is a value `option` can hold: one of its values for a
|
|
59
|
+
* choice, a boolean for a boolean.
|
|
60
|
+
*
|
|
61
|
+
* @param option - The option.
|
|
62
|
+
* @param value - The candidate value.
|
|
63
|
+
* @returns Whether the option accepts it.
|
|
64
|
+
*/
|
|
65
|
+
export function acceptsOptionValue(option, value) {
|
|
66
|
+
if (optionKind(option) === 'boolean')
|
|
67
|
+
return typeof value === 'boolean';
|
|
68
|
+
return (typeof value === 'string' &&
|
|
69
|
+
(option.values ?? []).some((choice) => choice.value === value));
|
|
70
|
+
}
|
|
71
|
+
/** The keys an option takes. */
|
|
72
|
+
const OPTION_KEYS = Object.keys({
|
|
73
|
+
id: true,
|
|
74
|
+
label: true,
|
|
75
|
+
title: true,
|
|
76
|
+
values: true,
|
|
77
|
+
default: true,
|
|
78
|
+
group: true,
|
|
79
|
+
scope: true,
|
|
80
|
+
apply: true,
|
|
81
|
+
});
|
|
82
|
+
/** The keys a choice option's value takes. */
|
|
83
|
+
const CHOICE_KEYS = Object.keys({
|
|
84
|
+
value: true,
|
|
85
|
+
label: true,
|
|
86
|
+
});
|
|
87
|
+
/** The keys each apply strategy takes, by its type: one entry per member of
|
|
88
|
+
* `OptionApply`, listing every key of that member. A strategy of a type
|
|
89
|
+
* the preview does not know is not checked. */
|
|
90
|
+
const APPLY_KEY_SETS = {
|
|
91
|
+
'root-attribute': {
|
|
92
|
+
type: true,
|
|
93
|
+
attribute: true,
|
|
94
|
+
target: true,
|
|
95
|
+
omitAtDefault: true,
|
|
96
|
+
},
|
|
97
|
+
stylesheet: { type: true },
|
|
98
|
+
class: { type: true, on: true, className: true, target: true },
|
|
99
|
+
'css-var': { type: true, var: true, target: true },
|
|
100
|
+
};
|
|
101
|
+
const APPLY_KEYS = Object.fromEntries(Object.entries(APPLY_KEY_SETS).map(([type, keys]) => [
|
|
102
|
+
type,
|
|
103
|
+
Object.keys(keys),
|
|
104
|
+
]));
|
|
105
|
+
/** The keys of `value` that are not among `allowed`, `skipped` aside. A
|
|
106
|
+
* key set to `undefined` is absent. */
|
|
107
|
+
function unknownKeys(value, allowed, skipped = []) {
|
|
108
|
+
return Object.entries(value)
|
|
109
|
+
.filter(([key, entry]) => entry !== undefined && !allowed.includes(key) && !skipped.includes(key))
|
|
110
|
+
.map(([key]) => key);
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The problems with a kit's options, each naming the option: a missing or
|
|
114
|
+
* repeated id, a scope other than `global` or `story`, an option whose
|
|
115
|
+
* kind is ambiguous - a choice needs `values` and a string `default` among
|
|
116
|
+
* them, a boolean no `values` and a boolean `default` - and a key the
|
|
117
|
+
* option, one of its values or its `apply` does not take. Empty when every
|
|
118
|
+
* option is sound.
|
|
119
|
+
*
|
|
120
|
+
* @param options - The preview block's `options`.
|
|
121
|
+
* @returns One message per problem.
|
|
122
|
+
*/
|
|
123
|
+
export function optionProblems(options) {
|
|
124
|
+
if (!Array.isArray(options))
|
|
125
|
+
return ['preview.options must be an array'];
|
|
126
|
+
const problems = [];
|
|
127
|
+
const seen = new Set();
|
|
128
|
+
options.forEach((candidate, index) => {
|
|
129
|
+
const option = candidate;
|
|
130
|
+
if (!option || typeof option !== 'object') {
|
|
131
|
+
problems.push(`preview.options[${index}] must be an object`);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const name = typeof option.id === 'string' && option.id
|
|
135
|
+
? `preview.options[${index}] ('${option.id}')`
|
|
136
|
+
: `preview.options[${index}]`;
|
|
137
|
+
if (typeof option.id !== 'string' || !option.id) {
|
|
138
|
+
problems.push(`${name}: id must be a non-empty string`);
|
|
139
|
+
}
|
|
140
|
+
else if (seen.has(option.id)) {
|
|
141
|
+
problems.push(`${name}: another option has the id '${option.id}'`);
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
seen.add(option.id);
|
|
145
|
+
}
|
|
146
|
+
if (typeof option.label !== 'string')
|
|
147
|
+
problems.push(`${name}: label must be a string`);
|
|
148
|
+
if (option.scope !== 'global' && option.scope !== 'story')
|
|
149
|
+
problems.push(`${name}: scope must be 'global' or 'story'`);
|
|
150
|
+
if (option.group !== undefined &&
|
|
151
|
+
(typeof option.group !== 'string' || !option.group))
|
|
152
|
+
problems.push(`${name}: group must be a non-empty string`);
|
|
153
|
+
if ('slot' in option)
|
|
154
|
+
problems.push(`${name}: slot is not an option field - an option says where it belongs with group`);
|
|
155
|
+
if ('control' in option)
|
|
156
|
+
problems.push(`${name}: control is not an option field - an option with values is a choice, one with a boolean default a boolean`);
|
|
157
|
+
// `slot` and `control` are named above with where their meaning went.
|
|
158
|
+
for (const key of unknownKeys(option, OPTION_KEYS, ['slot', 'control']))
|
|
159
|
+
problems.push(`${name}: unknown key '${key}'; an option takes ${OPTION_KEYS.join(', ')}`);
|
|
160
|
+
if (option.values !== undefined) {
|
|
161
|
+
const values = option.values;
|
|
162
|
+
if (!Array.isArray(values) ||
|
|
163
|
+
values.length === 0 ||
|
|
164
|
+
values.some((choice) => !choice ||
|
|
165
|
+
typeof choice.value !== 'string' ||
|
|
166
|
+
typeof choice.label !== 'string')) {
|
|
167
|
+
problems.push(`${name}: values must be a non-empty list of { value, label } strings`);
|
|
168
|
+
}
|
|
169
|
+
else if (typeof option.default !== 'string') {
|
|
170
|
+
problems.push(`${name}: a choice option (one with values) needs a string default`);
|
|
171
|
+
}
|
|
172
|
+
else if (!values.some((choice) => choice.value === option.default)) {
|
|
173
|
+
problems.push(`${name}: default '${option.default}' is not one of its values`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else if (typeof option.default !== 'boolean') {
|
|
177
|
+
problems.push(`${name}: an option without values is a boolean and needs a boolean default; a choice lists its values`);
|
|
178
|
+
}
|
|
179
|
+
if (Array.isArray(option.values))
|
|
180
|
+
option.values.forEach((choice, choiceIndex) => {
|
|
181
|
+
if (!choice || typeof choice !== 'object')
|
|
182
|
+
return;
|
|
183
|
+
for (const key of unknownKeys(choice, CHOICE_KEYS))
|
|
184
|
+
problems.push(`${name}: unknown key 'values[${choiceIndex}].${key}'; a value takes ${CHOICE_KEYS.join(', ')}`);
|
|
185
|
+
});
|
|
186
|
+
if (!option.apply || typeof option.apply !== 'object') {
|
|
187
|
+
problems.push(`${name}: apply must describe how the value hits the canvas`);
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
const type = option.apply.type;
|
|
191
|
+
if (typeof type === 'string' && Object.hasOwn(APPLY_KEYS, type)) {
|
|
192
|
+
const allowed = APPLY_KEYS[type];
|
|
193
|
+
for (const key of unknownKeys(option.apply, allowed))
|
|
194
|
+
problems.push(`${name}: unknown key 'apply.${key}'; a '${type}' apply takes ${allowed.join(', ')}`);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
return problems;
|
|
199
|
+
}
|
|
200
|
+
/** The option registry keyed by id - O(1) lookup when applying a payload. */
|
|
201
|
+
export function optionsById(options) {
|
|
202
|
+
return Object.fromEntries(options.map((option) => [option.id, option]));
|
|
203
|
+
}
|
|
204
|
+
/** Default values for the options in a scope (or all scopes). */
|
|
205
|
+
export function optionDefaults(options, scope) {
|
|
206
|
+
const out = {};
|
|
207
|
+
for (const option of options) {
|
|
208
|
+
if (!scope || option.scope === scope)
|
|
209
|
+
out[option.id] = option.default;
|
|
210
|
+
}
|
|
211
|
+
return out;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* The served URL of a theme's stylesheet (the generator copies it there).
|
|
215
|
+
*
|
|
216
|
+
* @param themeId - The theme's id.
|
|
217
|
+
* @param baseUrl - The URL the preview is served under, ending in `/`; the
|
|
218
|
+
* root of the origin, `/`, by default.
|
|
219
|
+
* @returns The stylesheet's URL, such as `/themes/light/theme.css`.
|
|
220
|
+
*/
|
|
221
|
+
export function themeHref(themeId, baseUrl = '/') {
|
|
222
|
+
return `${baseUrl}themes/${themeId}/theme.css`;
|
|
223
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { PreviewControlHints, PropTypeSpecification, JsonValue } from './lib/types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The control a prop gets in the controls panel, from its declared type. A
|
|
4
|
+
* prop whose name ends in `color`, in any case (`color`, `borderColor`), and
|
|
5
|
+
* whose type is string-like gets the
|
|
6
|
+
* color select, offering the kit's color tokens, when the kit gives any;
|
|
7
|
+
* otherwise it is treated by its declared type like any other prop.
|
|
8
|
+
*
|
|
9
|
+
* @param componentName - The component the prop belongs to.
|
|
10
|
+
* @param propName - The prop's name.
|
|
11
|
+
* @param def - The prop's declared type, resolved type and default.
|
|
12
|
+
* @param hints - The kit's control hints; their `colorTokens` turn on the
|
|
13
|
+
* color select.
|
|
14
|
+
* @returns The prop's control specification.
|
|
15
|
+
*/
|
|
16
|
+
export declare function propTypeForProp(componentName: string, propName: string, def: {
|
|
17
|
+
type: string;
|
|
18
|
+
resolvedType?: string;
|
|
19
|
+
default?: JsonValue;
|
|
20
|
+
}, hints?: PreviewControlHints): PropTypeSpecification;
|
|
21
|
+
/** Suggested default prop value from the template default (and the kit's
|
|
22
|
+
* component-size hint, when it supplies one). */
|
|
23
|
+
export declare function defaultPropForProp(componentName: string, propName: string, def: {
|
|
24
|
+
type: string;
|
|
25
|
+
default?: JsonValue;
|
|
26
|
+
}, hints: PreviewControlHints): JsonValue | undefined;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
// Map one component prop → a control spec for the host's controls panel. Pure
|
|
2
|
+
// function of the prop (name, parsed type, default) plus the kit's control
|
|
3
|
+
// hints (its token-config hook - see PreviewControlHints).
|
|
4
|
+
import { parseType } from './lib/parse-type.js';
|
|
5
|
+
function isColorProp(name) {
|
|
6
|
+
return name === 'color' || /color$/i.test(name);
|
|
7
|
+
}
|
|
8
|
+
/** Whether the kit gives color tokens for a color select to offer. */
|
|
9
|
+
function hasColorTokens(hints) {
|
|
10
|
+
return (hints.colorTokens ?? []).some((token) => token != null);
|
|
11
|
+
}
|
|
12
|
+
/** A union of string literals, template literal types (`` `accent-${string}` ``),
|
|
13
|
+
* `string`, or named types - the shapes a color-token type takes, which the
|
|
14
|
+
* color select can offer from the kit's token list whatever they expand to. */
|
|
15
|
+
const NON_STRING_KEYWORDS = new Set([
|
|
16
|
+
'boolean',
|
|
17
|
+
'number',
|
|
18
|
+
'bigint',
|
|
19
|
+
'object',
|
|
20
|
+
'symbol',
|
|
21
|
+
'unknown',
|
|
22
|
+
'any',
|
|
23
|
+
'never',
|
|
24
|
+
'null',
|
|
25
|
+
'void',
|
|
26
|
+
]);
|
|
27
|
+
function isStringLikeType(type) {
|
|
28
|
+
return type
|
|
29
|
+
.split('|')
|
|
30
|
+
.map((part) => part.trim())
|
|
31
|
+
.every((part) => part === 'string' ||
|
|
32
|
+
part === 'undefined' ||
|
|
33
|
+
/^'[^']*'$/.test(part) ||
|
|
34
|
+
/^"[^"]*"$/.test(part) ||
|
|
35
|
+
/^`[^`]*`$/.test(part) ||
|
|
36
|
+
(!NON_STRING_KEYWORDS.has(part) &&
|
|
37
|
+
/^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*)*$/.test(part)));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* The control a prop gets in the controls panel, from its declared type. A
|
|
41
|
+
* prop whose name ends in `color`, in any case (`color`, `borderColor`), and
|
|
42
|
+
* whose type is string-like gets the
|
|
43
|
+
* color select, offering the kit's color tokens, when the kit gives any;
|
|
44
|
+
* otherwise it is treated by its declared type like any other prop.
|
|
45
|
+
*
|
|
46
|
+
* @param componentName - The component the prop belongs to.
|
|
47
|
+
* @param propName - The prop's name.
|
|
48
|
+
* @param def - The prop's declared type, resolved type and default.
|
|
49
|
+
* @param hints - The kit's control hints; their `colorTokens` turn on the
|
|
50
|
+
* color select.
|
|
51
|
+
* @returns The prop's control specification.
|
|
52
|
+
*/
|
|
53
|
+
export function propTypeForProp(componentName, propName, def, hints = {}) {
|
|
54
|
+
const parsed = parseType(def.resolvedType ?? def.type);
|
|
55
|
+
const hasDefault = def.default !== undefined;
|
|
56
|
+
if (hasColorTokens(hints) &&
|
|
57
|
+
isColorProp(propName) &&
|
|
58
|
+
(parsed.kind === 'string' ||
|
|
59
|
+
(parsed.kind === 'enum' &&
|
|
60
|
+
parsed.options.every((option) => typeof option === 'string')) ||
|
|
61
|
+
isStringLikeType(def.type))) {
|
|
62
|
+
return { name: propName, control: 'color-select', include: true };
|
|
63
|
+
}
|
|
64
|
+
switch (parsed.kind) {
|
|
65
|
+
case 'boolean':
|
|
66
|
+
return { name: propName, control: 'boolean', include: true };
|
|
67
|
+
case 'number': {
|
|
68
|
+
if (propName === 'size') {
|
|
69
|
+
return {
|
|
70
|
+
name: propName,
|
|
71
|
+
control: 'number',
|
|
72
|
+
number: { min: 0.25, max: 4, step: 0.05 },
|
|
73
|
+
include: true,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
return { name: propName, control: 'number', include: true };
|
|
77
|
+
}
|
|
78
|
+
case 'enum': {
|
|
79
|
+
const options = [...parsed.options];
|
|
80
|
+
if (!hasDefault)
|
|
81
|
+
options.unshift(undefined);
|
|
82
|
+
return { name: propName, control: 'select', options, include: true };
|
|
83
|
+
}
|
|
84
|
+
case 'string':
|
|
85
|
+
case 'stringOrNumber':
|
|
86
|
+
return { name: propName, control: 'text', include: true };
|
|
87
|
+
case 'complex':
|
|
88
|
+
// Record<...>, X[], injected interfaces - driver-internal or too complex
|
|
89
|
+
// for a control. Omit; a story file can supply a default prop if required.
|
|
90
|
+
return { name: propName, control: 'text', include: false };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/** Suggested default prop value from the template default (and the kit's
|
|
94
|
+
* component-size hint, when it supplies one). */
|
|
95
|
+
export function defaultPropForProp(componentName, propName, def, hints) {
|
|
96
|
+
if (def.default !== undefined)
|
|
97
|
+
return def.default;
|
|
98
|
+
if (propName === 'size' && parseType(def.type).kind === 'number') {
|
|
99
|
+
return hints.componentSizeRem?.(componentName);
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import type { EnumeratedComponent, ManualComponentSpecification } from './lib/types.js';
|
|
3
|
+
/** The props read from one `propsFrom` interface. */
|
|
4
|
+
export interface PropsFromResult {
|
|
5
|
+
props: EnumeratedComponent['props'];
|
|
6
|
+
/** Whether the interface declares a non-function `children` (the default slot;
|
|
7
|
+
* a render-function `children` is a scoped slot instead). */
|
|
8
|
+
hasChildren: boolean;
|
|
9
|
+
/** Whether that default slot exposes values to its content (a scoped
|
|
10
|
+
* slot): a template component's whose default slot does, read through
|
|
11
|
+
* `ComponentProps<typeof X>`. */
|
|
12
|
+
childrenScoped: boolean;
|
|
13
|
+
/** Members whose type is not a control. */
|
|
14
|
+
hiddenProps: string[];
|
|
15
|
+
/** Every own member name, `children` included. */
|
|
16
|
+
memberNames: string[];
|
|
17
|
+
}
|
|
18
|
+
/** A type declaration found by name: an interface or a type alias, in its file. */
|
|
19
|
+
type Declaration = {
|
|
20
|
+
kind: 'interface';
|
|
21
|
+
node: ts.InterfaceDeclaration;
|
|
22
|
+
file: ts.SourceFile;
|
|
23
|
+
} | {
|
|
24
|
+
kind: 'alias';
|
|
25
|
+
node: ts.TypeAliasDeclaration;
|
|
26
|
+
file: ts.SourceFile;
|
|
27
|
+
};
|
|
28
|
+
/** Finds type declarations by name across a kit's source files, following
|
|
29
|
+
* imports and re-exports with TypeScript's module resolution and the kit's
|
|
30
|
+
* tsconfig. Parses each file once. */
|
|
31
|
+
export declare class DeclarationResolver {
|
|
32
|
+
private readonly files;
|
|
33
|
+
private readonly options;
|
|
34
|
+
constructor(kitRoot: string);
|
|
35
|
+
/** Parses source that is not on disk, as if it were the file at `path`, so
|
|
36
|
+
* its imports resolve from there. Not cached. */
|
|
37
|
+
virtual(path: string, text: string): ts.SourceFile;
|
|
38
|
+
file(path: string): ts.SourceFile;
|
|
39
|
+
private resolveModule;
|
|
40
|
+
/** The declaration `name` refers to inside `file`: declared there, or imported. */
|
|
41
|
+
find(name: string, file: ts.SourceFile, seen?: Set<string>): Declaration | undefined;
|
|
42
|
+
/** The declaration a module exports as `name`, through re-exports. */
|
|
43
|
+
private findExport;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Reads the own members of the interface (or object type alias, or intersection
|
|
47
|
+
* of them) `propsFrom` names into preview prop definitions.
|
|
48
|
+
*
|
|
49
|
+
* @param reference - `'<file relative to the kit root>#<InterfaceName>'`
|
|
50
|
+
* @param kitRoot - The kit root the file resolves against
|
|
51
|
+
* @param templates - The kit's template components, which a
|
|
52
|
+
* `ComponentProps<typeof X>` in the type can name
|
|
53
|
+
* @returns The props, the default-slot flag, and the hidden and member names
|
|
54
|
+
*/
|
|
55
|
+
export declare function readPropsFrom(reference: string, kitRoot: string, templates?: readonly EnumeratedComponent[]): PropsFromResult;
|
|
56
|
+
/**
|
|
57
|
+
* A template prop's type with the named types it uses expanded, read through
|
|
58
|
+
* the template's own import statements: an alias becomes its members (a
|
|
59
|
+
* generic one with its arguments in place), an interface reads as an object
|
|
60
|
+
* form, and a union is flattened. `undefined` when the type names nothing to
|
|
61
|
+
* expand, or expands to the same text.
|
|
62
|
+
*
|
|
63
|
+
* @param type - The prop's type as the template writes it
|
|
64
|
+
* @param templatePath - The template file, which its imports resolve from
|
|
65
|
+
* @param imports - The template's import statements
|
|
66
|
+
* @param resolver - The declaration resolver to read through
|
|
67
|
+
* @returns The expanded type, or `undefined`
|
|
68
|
+
* @example
|
|
69
|
+
* // With `import type { StackAlign } from '@acme/kit/scripts';`
|
|
70
|
+
* resolveNamedType('StackAlign', templatePath, imports, resolver);
|
|
71
|
+
* // "'start' | 'center' | 'end'"
|
|
72
|
+
*/
|
|
73
|
+
export declare function resolveNamedType(type: string, templatePath: string, imports: readonly string[], resolver: DeclarationResolver): string | undefined;
|
|
74
|
+
/**
|
|
75
|
+
* Resolves a manual spec into an EnumeratedComponent, reading `propsFrom` when set.
|
|
76
|
+
*
|
|
77
|
+
* @param specification - The manual component's specification
|
|
78
|
+
* @param kitRoot - The kit root `propsFrom` resolves against
|
|
79
|
+
* @param templates - The kit's template components, which a
|
|
80
|
+
* `ComponentProps<typeof X>` in the props type can name
|
|
81
|
+
* @returns The component, with its props read from `propsFrom` or given inline
|
|
82
|
+
*/
|
|
83
|
+
export declare function resolveManualComponent(specification: ManualComponentSpecification, kitRoot: string, templates?: readonly EnumeratedComponent[]): EnumeratedComponent;
|
|
84
|
+
export {};
|