@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,47 @@
|
|
|
1
|
+
// The status bar's word on the selection's panes: `regeneration failed` while
|
|
2
|
+
// the scenario editor's last regeneration failed, `regenerating` while one
|
|
3
|
+
// runs, `render error` with the targets whose story threw, `loading` while a
|
|
4
|
+
// pane loads, and `ready` once every pane shows its story. The messages behind
|
|
5
|
+
// a failure open as a hint over it (Hint), from the pointer or the keyboard.
|
|
6
|
+
// Styled in its index.css.
|
|
7
|
+
import { usePreviewState } from '../../controller-context';
|
|
8
|
+
import { Hint } from '../Hint';
|
|
9
|
+
import './index.css';
|
|
10
|
+
|
|
11
|
+
export function PaneStatus() {
|
|
12
|
+
const regeneration = usePreviewState((state) => state.regeneration);
|
|
13
|
+
const frames = usePreviewState((state) => state.frames);
|
|
14
|
+
const errors = usePreviewState((state) => state.frameErrors);
|
|
15
|
+
const failing = Object.entries(errors).filter((entry): entry is [string, string] => entry[1] !== undefined);
|
|
16
|
+
const loading = Object.values(frames).includes('loading');
|
|
17
|
+
const [word, detail, failed] =
|
|
18
|
+
regeneration.status === 'error'
|
|
19
|
+
? ['regeneration failed', regeneration.message, true]
|
|
20
|
+
: regeneration.status === 'pending'
|
|
21
|
+
? ['regenerating…', undefined, false]
|
|
22
|
+
: failing.length > 0
|
|
23
|
+
? [
|
|
24
|
+
`render error · ${failing.map(([target]) => target).join(', ')}`,
|
|
25
|
+
failing.map(([target, message]) => `${target}: ${message}`).join('\n'),
|
|
26
|
+
true,
|
|
27
|
+
]
|
|
28
|
+
: loading
|
|
29
|
+
? ['loading…', undefined, false]
|
|
30
|
+
: ['ready', undefined, false];
|
|
31
|
+
return (
|
|
32
|
+
<Hint text={detail}>
|
|
33
|
+
{(hint) => (
|
|
34
|
+
// With messages behind it, the word takes focus, so the keyboard
|
|
35
|
+
// opens them as the pointer does.
|
|
36
|
+
<span
|
|
37
|
+
{...hint}
|
|
38
|
+
className={`PaneStatus${failed ? ' PaneStatus--failed' : ''}`}
|
|
39
|
+
role="status"
|
|
40
|
+
tabIndex={detail ? 0 : undefined}
|
|
41
|
+
>
|
|
42
|
+
{word}
|
|
43
|
+
</span>
|
|
44
|
+
)}
|
|
45
|
+
</Hint>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// The output's `width` select, among the output's options with the kit's
|
|
2
|
+
// own (ViewControls): `fit`, the panes sharing the stage's width, or one of
|
|
3
|
+
// the catalog's pane widths, such as `medium 768`, which lays every story
|
|
4
|
+
// pane out that wide so a component that responds to its width shows as it
|
|
5
|
+
// does on such a screen. The output stacks its panes as rows while the width
|
|
6
|
+
// is wider than a column would be (PreviewGrid), and a row still narrower
|
|
7
|
+
// scrolls across (PreviewPane). A width a link names that is not among them
|
|
8
|
+
// shows as its number. The controller keeps the choice, and the address with
|
|
9
|
+
// it (`width=768`). With no pane widths in the catalog and none chosen there
|
|
10
|
+
// is nothing to pick, and no select.
|
|
11
|
+
import { usePreviewController, usePreviewState } from '../../controller-context';
|
|
12
|
+
import { Select, type SelectOption } from '../Select';
|
|
13
|
+
|
|
14
|
+
/** The select's value while the panes fit the stage. */
|
|
15
|
+
const FIT = 'fit';
|
|
16
|
+
|
|
17
|
+
/** Whether there is a width to pick: the catalog offers some, or one is
|
|
18
|
+
* chosen. */
|
|
19
|
+
export function usePaneWidthShown(): boolean {
|
|
20
|
+
const controller = usePreviewController();
|
|
21
|
+
const paneWidth = usePreviewState((state) => state.paneWidth);
|
|
22
|
+
return controller.catalog.paneWidths.length > 0 || paneWidth !== undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function PaneWidth() {
|
|
26
|
+
const controller = usePreviewController();
|
|
27
|
+
const paneWidth = usePreviewState((state) => state.paneWidth);
|
|
28
|
+
const paneWidths = controller.catalog.paneWidths;
|
|
29
|
+
if (paneWidths.length === 0 && paneWidth === undefined) return null;
|
|
30
|
+
const options: SelectOption[] = [
|
|
31
|
+
{ value: FIT, label: FIT },
|
|
32
|
+
...paneWidths.map(({ label, width }) => ({ value: String(width), label: `${label} ${width}` })),
|
|
33
|
+
];
|
|
34
|
+
if (paneWidth !== undefined && !paneWidths.some(({ width }) => width === paneWidth))
|
|
35
|
+
options.push({ value: String(paneWidth), label: String(paneWidth) });
|
|
36
|
+
return (
|
|
37
|
+
<Select
|
|
38
|
+
label="width"
|
|
39
|
+
testId="select-pane-width"
|
|
40
|
+
value={paneWidth === undefined ? FIT : String(paneWidth)}
|
|
41
|
+
onChange={(value) => controller.actions.setPaneWidth(value === FIT ? undefined : Number(value))}
|
|
42
|
+
options={options}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
@layer charcell.components {
|
|
2
|
+
/* The panes: the targets' preview and code panes in a charcell SplitGrid
|
|
3
|
+
that fills the grid's place (charcell's `fill`). The frames float on the
|
|
4
|
+
canvas: the stage's side cells their breathing room to the lines beside
|
|
5
|
+
them, the invisible-at-rest handles the gaps. No vertical padding: the
|
|
6
|
+
frames' own ring rows are the breathing room, and their strokes land
|
|
7
|
+
centered in whole grid rows. */
|
|
8
|
+
.PreviewGrid {
|
|
9
|
+
flex: 1;
|
|
10
|
+
display: flex;
|
|
11
|
+
min-width: 0;
|
|
12
|
+
min-height: 0;
|
|
13
|
+
}
|
|
14
|
+
/* The rows' box: the grid's height, or, stacked, at least the rows' least
|
|
15
|
+
(`--preview-grid-least-rows`, in rows), the grid then scrolling down
|
|
16
|
+
past the stage rather than squeezing a row. */
|
|
17
|
+
.PreviewGrid__rows {
|
|
18
|
+
flex: 1 1 0;
|
|
19
|
+
display: flex;
|
|
20
|
+
min-width: 0;
|
|
21
|
+
min-height: 0;
|
|
22
|
+
}
|
|
23
|
+
.PreviewGrid[data-stacked] {
|
|
24
|
+
overflow-y: auto;
|
|
25
|
+
overscroll-behavior: contain;
|
|
26
|
+
}
|
|
27
|
+
.PreviewGrid[data-stacked] > .PreviewGrid__rows {
|
|
28
|
+
min-height: calc(var(--preview-grid-least-rows) * var(--charcell-row));
|
|
29
|
+
}
|
|
30
|
+
/* Under stacked output rows, the code row holds each target's code pane
|
|
31
|
+
side by side, a cell apart. */
|
|
32
|
+
.PreviewGrid__codes {
|
|
33
|
+
flex: 1;
|
|
34
|
+
display: flex;
|
|
35
|
+
gap: 1ch;
|
|
36
|
+
min-width: 0;
|
|
37
|
+
min-height: 0;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
// The component stage's grid: a column per pane showing (a target's, and
|
|
2
|
+
// the html one where the kit builds html), and a row per view showing of the
|
|
3
|
+
// two the grid holds - the output row, a preview pane in each column, and the
|
|
4
|
+
// code row, that target's code pane under it (CodePane). charcell's
|
|
5
|
+
// SplitGridDriver + SplitGridVisual composed with its SplitGridCell and
|
|
6
|
+
// SplitGridHandle parts: a handle between two columns runs down every row, the
|
|
7
|
+
// handle between the rows across every column, and a press where they cross
|
|
8
|
+
// drags both, each boundary a whole column or row at a time (the driver's own
|
|
9
|
+
// snapping). The handle between the rows draws one grip, in its middle, and
|
|
10
|
+
// carries the code view's heading at its start and the wrap toggle
|
|
11
|
+
// (WrapToggle) at its end. The code row starts at about two fifths of the height and keeps
|
|
12
|
+
// at least eight rows - its ring, the copy row and a few rows of source - and
|
|
13
|
+
// the output row at least three; the columns share the width equally to
|
|
14
|
+
// start. A new set of columns or rows starts over from those sizes. The
|
|
15
|
+
// preview cells are keyed by their target and come first, and stay in the
|
|
16
|
+
// grid while the output row is hidden, laid out nowhere, so the panes keep
|
|
17
|
+
// their place in the tree, and their frames, while either row opens and
|
|
18
|
+
// closes and while a target is turned on or off.
|
|
19
|
+
//
|
|
20
|
+
// While the story panes are laid out at a width (`paneWidth`) wider than a
|
|
21
|
+
// column would be, the output stacks instead: a row per target, each at the
|
|
22
|
+
// grid's full width, the handles between them dragging a row at a time, and
|
|
23
|
+
// the code row under them holding each target's code pane side by side. Each
|
|
24
|
+
// row starts at its story's height, or, when the stories don't fit, at an
|
|
25
|
+
// equal share (stackedRowCells), once every story has reported its height.
|
|
26
|
+
// Each keeps a least: ten rows, its ring and scrollbar rows and about seven
|
|
27
|
+
// rows of story, or its whole story and pane when they take fewer. The grid
|
|
28
|
+
// is tall enough for every row's least and the code row's, so the stage
|
|
29
|
+
// scrolls down only when those don't fit, rather than squeezing a row. The
|
|
30
|
+
// rows follow the stories' heights and the stage's until the reader drags a
|
|
31
|
+
// handle between them or steps it with a key. A story still wider than its row
|
|
32
|
+
// scrolls across, and a taller one down (PreviewPane). The preview cells keep
|
|
33
|
+
// their keys, so the panes keep their frames as the grid stacks and unstacks.
|
|
34
|
+
//
|
|
35
|
+
// A target turned off gives its columns to the others in proportion to their
|
|
36
|
+
// widths, and one turned back on comes back at the width it had, the others
|
|
37
|
+
// giving way in proportion (the driver's `redistribute: 'proportional'`); the
|
|
38
|
+
// stacked rows and the code row share their rows the same way. A double-click
|
|
39
|
+
// on a handle, or Enter while it holds the focus (split-reset.ts), puts its
|
|
40
|
+
// split back where it started: the columns at equal widths, the output and
|
|
41
|
+
// code rows at their starting heights, and stacked rows at their stories'
|
|
42
|
+
// heights again, following the stories as before a handle was moved.
|
|
43
|
+
import { useLayoutEffect, useMemo, useRef, useState, type CSSProperties, type RefObject } from 'react';
|
|
44
|
+
import {
|
|
45
|
+
SplitGridCell,
|
|
46
|
+
SplitGridDriver,
|
|
47
|
+
SplitGridHandle,
|
|
48
|
+
SplitGridHandleRow,
|
|
49
|
+
SplitGridVisual,
|
|
50
|
+
type SplitGridScope,
|
|
51
|
+
} from 'charcell/react/unlinked';
|
|
52
|
+
import type { PreviewTarget } from '../../../../../src/shell';
|
|
53
|
+
import { usePreviewState } from '../../controller-context';
|
|
54
|
+
import { withResetGesture } from '../../split-reset';
|
|
55
|
+
import { stackedLeastCells, stackedRowCells, type StackedCodeRow } from '../../stacked-rows';
|
|
56
|
+
import { CodePane } from '../CodePane';
|
|
57
|
+
import { PreviewPane } from '../PreviewPane';
|
|
58
|
+
import { ViewControls } from '../ViewControls';
|
|
59
|
+
import { ViewHeading } from '../ViewHeading';
|
|
60
|
+
import { WrapToggle } from '../WrapToggle';
|
|
61
|
+
import './index.css';
|
|
62
|
+
|
|
63
|
+
/** The fewest rows the code row keeps, so its copy row and some source still show. */
|
|
64
|
+
const CODE_ROWS = 8;
|
|
65
|
+
|
|
66
|
+
/** The fewest rows the output row keeps. */
|
|
67
|
+
const OUTPUT_ROWS = 3;
|
|
68
|
+
|
|
69
|
+
/** The fewest columns a pane keeps, so its title and some of its story still show. */
|
|
70
|
+
const PANE_COLUMNS = 12;
|
|
71
|
+
|
|
72
|
+
/** The output row's and the code row's starting shares, in percent, while both show. */
|
|
73
|
+
const BOTH_ROWS_SIZE = [60, 40];
|
|
74
|
+
|
|
75
|
+
/** The one row's share while only one shows. */
|
|
76
|
+
const ONE_ROW_SIZE = [100];
|
|
77
|
+
|
|
78
|
+
/** The code row's starting share under stacked output rows, in percent. */
|
|
79
|
+
const STACKED_CODE_SIZE = 30;
|
|
80
|
+
|
|
81
|
+
/** The fewest rows a stacked output row keeps, unless its story and pane
|
|
82
|
+
* take fewer: its ring and scrollbar rows and about seven rows of story. */
|
|
83
|
+
const STACKED_ROWS = 10;
|
|
84
|
+
|
|
85
|
+
/** The keys that step a handle. */
|
|
86
|
+
const STEP_KEYS = new Set(['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'PageUp', 'PageDown']);
|
|
87
|
+
|
|
88
|
+
/** The one column of a stacked grid. */
|
|
89
|
+
const STACK_COLUMN = 'stack';
|
|
90
|
+
|
|
91
|
+
/** The grid's own size, as it changes. */
|
|
92
|
+
function useSize(element: RefObject<HTMLDivElement | null>): {
|
|
93
|
+
width: number;
|
|
94
|
+
height: number;
|
|
95
|
+
} {
|
|
96
|
+
const [size, setSize] = useState({ width: 0, height: 0 });
|
|
97
|
+
useLayoutEffect(() => {
|
|
98
|
+
const current = element.current;
|
|
99
|
+
if (!current) return;
|
|
100
|
+
const { width, height } = current.getBoundingClientRect();
|
|
101
|
+
setSize({ width, height });
|
|
102
|
+
const observer = new ResizeObserver(([entry]) =>
|
|
103
|
+
setSize({
|
|
104
|
+
width: entry.contentRect.width,
|
|
105
|
+
height: entry.contentRect.height,
|
|
106
|
+
}),
|
|
107
|
+
);
|
|
108
|
+
observer.observe(current);
|
|
109
|
+
return () => observer.disconnect();
|
|
110
|
+
}, [element]);
|
|
111
|
+
return size;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function PreviewGrid({ targets, output, code }: { targets: PreviewTarget[]; output: boolean; code: boolean }) {
|
|
115
|
+
const element = useRef<HTMLDivElement>(null);
|
|
116
|
+
const { width, height } = useSize(element);
|
|
117
|
+
const paneWidth = usePreviewState((state) => state.paneWidth);
|
|
118
|
+
// The stories' heights, as one value that changes when any of them does.
|
|
119
|
+
const storyHeights = usePreviewState((state) =>
|
|
120
|
+
targets.map((target) => state.frameSizes[target]?.height ?? '').join(','),
|
|
121
|
+
);
|
|
122
|
+
// Stacked while the output shows and a picked width is wider than a column would be.
|
|
123
|
+
const stacked =
|
|
124
|
+
output && targets.length > 1 && paneWidth !== undefined && width > 0 && paneWidth > width / targets.length;
|
|
125
|
+
const columns = useMemo(
|
|
126
|
+
() =>
|
|
127
|
+
stacked
|
|
128
|
+
? [{ id: STACK_COLUMN, minimumCells: PANE_COLUMNS }]
|
|
129
|
+
: targets.map((target) => ({ id: target, minimumCells: PANE_COLUMNS })),
|
|
130
|
+
[targets, stacked],
|
|
131
|
+
);
|
|
132
|
+
// With neither row showing the grid is hidden whole (StageSplit),
|
|
133
|
+
// and keeps the output row for its panes.
|
|
134
|
+
const rows = useMemo(
|
|
135
|
+
() =>
|
|
136
|
+
stacked
|
|
137
|
+
? [
|
|
138
|
+
// Each target's row starts at its story's height (below).
|
|
139
|
+
...targets.map((target) => ({
|
|
140
|
+
id: `output:${target}`,
|
|
141
|
+
minimumCells: OUTPUT_ROWS,
|
|
142
|
+
})),
|
|
143
|
+
...(code ? [{ id: 'code', minimumCells: CODE_ROWS }] : []),
|
|
144
|
+
]
|
|
145
|
+
: [
|
|
146
|
+
// Beside the code row, the output row starts at its panes' content.
|
|
147
|
+
...(output || !code
|
|
148
|
+
? [
|
|
149
|
+
{
|
|
150
|
+
id: 'output',
|
|
151
|
+
minimumCells: OUTPUT_ROWS,
|
|
152
|
+
...(code && output ? { defaultCells: 'content' as const } : {}),
|
|
153
|
+
},
|
|
154
|
+
]
|
|
155
|
+
: []),
|
|
156
|
+
...(code ? [{ id: 'code', minimumCells: CODE_ROWS }] : []),
|
|
157
|
+
],
|
|
158
|
+
[targets, output, code, stacked],
|
|
159
|
+
);
|
|
160
|
+
const defaultColumnSize = useMemo(() => columns.map(() => 100 / columns.length), [columns]);
|
|
161
|
+
const defaultRowSize = useMemo(() => {
|
|
162
|
+
if (!stacked) return rows.length === 2 ? BOTH_ROWS_SIZE : ONE_ROW_SIZE;
|
|
163
|
+
const outputShare = (100 - (code ? STACKED_CODE_SIZE : 0)) / targets.length;
|
|
164
|
+
return [...targets.map(() => outputShare), ...(code ? [STACKED_CODE_SIZE] : [])];
|
|
165
|
+
}, [stacked, rows, code, targets]);
|
|
166
|
+
// The code row is the last; the handle above it carries its heading.
|
|
167
|
+
const codeRow = rows.length - 1;
|
|
168
|
+
const codeRowLimits: StackedCodeRow | undefined = code ? { least: CODE_ROWS, share: STACKED_CODE_SIZE } : undefined;
|
|
169
|
+
|
|
170
|
+
// The grid's parts as the driver last handed them, for the stacked rows' start.
|
|
171
|
+
const scope = useRef<SplitGridScope | null>(null);
|
|
172
|
+
// Whether the reader has moved a handle between the rows since they last
|
|
173
|
+
// stacked: dragged it, or stepped it with a key.
|
|
174
|
+
const moved = useRef(false);
|
|
175
|
+
// A press on a handle, until it ends: a drag while it lasts is the reader's.
|
|
176
|
+
const pressed = useRef(false);
|
|
177
|
+
const layout = `${stacked}:${code}:${targets.join(',')}`;
|
|
178
|
+
useLayoutEffect(() => {
|
|
179
|
+
moved.current = false;
|
|
180
|
+
}, [layout]);
|
|
181
|
+
// The cells the stacked grid needs at least, once the stories report.
|
|
182
|
+
const [leastCells, setLeastCells] = useState(0);
|
|
183
|
+
// A count of the resets of the rows, so a reset of stacked rows lays them
|
|
184
|
+
// out at their stories again.
|
|
185
|
+
const [rowResets, setRowResets] = useState(0);
|
|
186
|
+
// A charcell whose split has no `resetSizes` leaves the split where it is,
|
|
187
|
+
// and shares a leaving track's cells by its own default, whatever
|
|
188
|
+
// `redistribute` says: a reset there does nothing but re-lay stacked rows
|
|
189
|
+
// at their stories.
|
|
190
|
+
const resetColumns = () => scope.current?.columnsApi.resetSizes?.();
|
|
191
|
+
const resetRows = () => {
|
|
192
|
+
scope.current?.rowsApi.resetSizes?.();
|
|
193
|
+
if (!stacked) return;
|
|
194
|
+
moved.current = false;
|
|
195
|
+
setRowResets((count) => count + 1);
|
|
196
|
+
};
|
|
197
|
+
// Stacked, each row starts at its story's height, or an equal share where
|
|
198
|
+
// the stories don't fit, once every story has reported its height, and
|
|
199
|
+
// follows the stories and the stage until the reader moves a handle.
|
|
200
|
+
useLayoutEffect(() => {
|
|
201
|
+
const grid = scope.current;
|
|
202
|
+
if (!stacked || moved.current || !grid) return;
|
|
203
|
+
const gridElement = document.getElementById(String(grid.gridProps.id));
|
|
204
|
+
if (!gridElement) return;
|
|
205
|
+
const cell = parseFloat(getComputedStyle(gridElement).lineHeight);
|
|
206
|
+
if (!(cell > 0)) return;
|
|
207
|
+
const heights = storyHeights.split(',').map(Number);
|
|
208
|
+
if (heights.some((story) => !(story > 0))) return;
|
|
209
|
+
const wanted = targets.map((_, index) => {
|
|
210
|
+
const cellElement = document.getElementById(String(grid.cellProps(0, index).id));
|
|
211
|
+
const viewport = cellElement?.querySelector('[role="region"]');
|
|
212
|
+
if (!cellElement || !viewport) return undefined;
|
|
213
|
+
// The pane around the story: its ring and any scrollbar row.
|
|
214
|
+
const chrome = cellElement.getBoundingClientRect().height - viewport.clientHeight;
|
|
215
|
+
return (heights[index] + chrome) / cell;
|
|
216
|
+
});
|
|
217
|
+
const least = stackedLeastCells(wanted, STACKED_ROWS, codeRowLimits);
|
|
218
|
+
if (least !== leastCells) {
|
|
219
|
+
// The grid grows to it first; this runs again at its new height.
|
|
220
|
+
setLeastCells(least);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const total = (gridElement.getBoundingClientRect().height - (grid.rows.length - 1) * cell) / cell;
|
|
224
|
+
if (!(total > 0)) return;
|
|
225
|
+
const cells = stackedRowCells({ wanted, total, least: STACKED_ROWS, code: codeRowLimits });
|
|
226
|
+
// A frame later, once the split has taken in a new set of rows.
|
|
227
|
+
const frame = requestAnimationFrame(() =>
|
|
228
|
+
scope.current?.rowsApi.setSizes(cells.map((length) => (length / total) * 100)),
|
|
229
|
+
);
|
|
230
|
+
return () => cancelAnimationFrame(frame);
|
|
231
|
+
// The layout and stories it follows, the grid's least, the stage's size
|
|
232
|
+
// and a reset of the rows.
|
|
233
|
+
}, [stacked, layout, storyHeights, leastCells, height, width, rowResets]);
|
|
234
|
+
const onHandle = (target: EventTarget) => (target as Element).closest('[data-part="resize-trigger"]') !== null;
|
|
235
|
+
return (
|
|
236
|
+
<div
|
|
237
|
+
ref={element}
|
|
238
|
+
className="PreviewGrid"
|
|
239
|
+
data-stacked={stacked || undefined}
|
|
240
|
+
style={{ '--preview-grid-least-rows': stacked ? leastCells : 0 } as CSSProperties}
|
|
241
|
+
// A drag or a step key on a handle between the rows is the reader's:
|
|
242
|
+
// the rows stay where they leave them. A plain click or a tab to it is not.
|
|
243
|
+
onPointerDownCapture={(event) => {
|
|
244
|
+
pressed.current = onHandle(event.target);
|
|
245
|
+
}}
|
|
246
|
+
onPointerMoveCapture={(event) => {
|
|
247
|
+
if (pressed.current && event.buttons !== 0) moved.current = true;
|
|
248
|
+
}}
|
|
249
|
+
onPointerUpCapture={() => {
|
|
250
|
+
pressed.current = false;
|
|
251
|
+
}}
|
|
252
|
+
onKeyDownCapture={(event) => {
|
|
253
|
+
if (STEP_KEYS.has(event.key) && onHandle(event.target)) moved.current = true;
|
|
254
|
+
}}
|
|
255
|
+
>
|
|
256
|
+
<div className="PreviewGrid__rows">
|
|
257
|
+
<SplitGridDriver
|
|
258
|
+
columns={columns}
|
|
259
|
+
rows={rows}
|
|
260
|
+
defaultColumnSize={defaultColumnSize}
|
|
261
|
+
defaultRowSize={defaultRowSize}
|
|
262
|
+
redistribute="proportional"
|
|
263
|
+
>
|
|
264
|
+
{({ grid }) => {
|
|
265
|
+
scope.current = grid;
|
|
266
|
+
return (
|
|
267
|
+
<SplitGridVisual fill rowGrips="one" {...grid.rootProps} gridProps={grid.gridProps}>
|
|
268
|
+
{targets.map((target, index) => (
|
|
269
|
+
<SplitGridCell
|
|
270
|
+
key={`output:${target}`}
|
|
271
|
+
{...(!output ? { hidden: true } : stacked ? grid.cellProps(0, index) : grid.cellProps(index, 0))}
|
|
272
|
+
>
|
|
273
|
+
<PreviewPane title={target} target={target} />
|
|
274
|
+
</SplitGridCell>
|
|
275
|
+
))}
|
|
276
|
+
{code &&
|
|
277
|
+
!stacked &&
|
|
278
|
+
targets.map((target, columnIndex) => (
|
|
279
|
+
<SplitGridCell key={`code:${target}`} {...grid.cellProps(columnIndex, codeRow)}>
|
|
280
|
+
<CodePane target={target} />
|
|
281
|
+
</SplitGridCell>
|
|
282
|
+
))}
|
|
283
|
+
{code && stacked && (
|
|
284
|
+
<SplitGridCell key="code:stack" {...grid.cellProps(0, codeRow)}>
|
|
285
|
+
<div className="PreviewGrid__codes">
|
|
286
|
+
{targets.map((target) => (
|
|
287
|
+
<CodePane key={target} target={target} />
|
|
288
|
+
))}
|
|
289
|
+
</div>
|
|
290
|
+
</SplitGridCell>
|
|
291
|
+
)}
|
|
292
|
+
{!stacked &&
|
|
293
|
+
targets
|
|
294
|
+
.slice(1)
|
|
295
|
+
.map((target, index) => (
|
|
296
|
+
<SplitGridHandle
|
|
297
|
+
key={`handle:${target}`}
|
|
298
|
+
{...withResetGesture(grid.columnHandleProps(index), resetColumns)}
|
|
299
|
+
axis="column"
|
|
300
|
+
crosses={grid.rows}
|
|
301
|
+
label={`resize ${targets[index]} and ${target}`}
|
|
302
|
+
/>
|
|
303
|
+
))}
|
|
304
|
+
{stacked &&
|
|
305
|
+
targets
|
|
306
|
+
.slice(1)
|
|
307
|
+
.map((target, index) => (
|
|
308
|
+
<SplitGridHandle
|
|
309
|
+
key={`row-handle:${target}`}
|
|
310
|
+
{...withResetGesture(grid.rowHandleProps(index), resetRows)}
|
|
311
|
+
axis="row"
|
|
312
|
+
crosses={grid.columns}
|
|
313
|
+
label={`resize ${targets[index]} and ${target}`}
|
|
314
|
+
/>
|
|
315
|
+
))}
|
|
316
|
+
{code && rows.length > 1 && (
|
|
317
|
+
<SplitGridHandle
|
|
318
|
+
key="handle:code"
|
|
319
|
+
{...withResetGesture(grid.rowHandleProps(codeRow - 1), resetRows)}
|
|
320
|
+
axis="row"
|
|
321
|
+
crosses={grid.columns}
|
|
322
|
+
label="resize panes and code"
|
|
323
|
+
/>
|
|
324
|
+
)}
|
|
325
|
+
{code && rows.length > 1 && (
|
|
326
|
+
<SplitGridHandleRow
|
|
327
|
+
key="handle-row:code"
|
|
328
|
+
{...grid.rowHandleRowProps(codeRow - 1)}
|
|
329
|
+
start={<ViewHeading>code</ViewHeading>}
|
|
330
|
+
end={
|
|
331
|
+
<ViewControls view="code">
|
|
332
|
+
<WrapToggle />
|
|
333
|
+
</ViewControls>
|
|
334
|
+
}
|
|
335
|
+
/>
|
|
336
|
+
)}
|
|
337
|
+
</SplitGridVisual>
|
|
338
|
+
);
|
|
339
|
+
}}
|
|
340
|
+
</SplitGridDriver>
|
|
341
|
+
</div>
|
|
342
|
+
</div>
|
|
343
|
+
);
|
|
344
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
@layer charcell.components {
|
|
2
|
+
/* One pane: the element the controller mounts the iframe
|
|
3
|
+
in, inside a charcell Frame that fills the pane's place in the row. It fills
|
|
4
|
+
the Frame's body, which is not a flex container, so the iframe's own flex
|
|
5
|
+
sizing has a box to fill. */
|
|
6
|
+
.PreviewPane {
|
|
7
|
+
position: relative;
|
|
8
|
+
height: 100%;
|
|
9
|
+
min-height: 0;
|
|
10
|
+
display: flex;
|
|
11
|
+
flex-direction: column;
|
|
12
|
+
}
|
|
13
|
+
/* While its iframe loads, hidden by the controller until it shows its
|
|
14
|
+
content, the pane says so in the mid gray, its dots counting up - after
|
|
15
|
+
300ms, so a quick load shows nothing but the ground. The note sits on a
|
|
16
|
+
whole cell counted from the pane's corner, the one nearest the middle. */
|
|
17
|
+
.PreviewPane:has(> iframe:not([data-preview-shown]))::after {
|
|
18
|
+
content: 'loading';
|
|
19
|
+
position: absolute;
|
|
20
|
+
left: round(down, calc((100% - 10ch) / 2), 1ch);
|
|
21
|
+
top: round(
|
|
22
|
+
down,
|
|
23
|
+
calc((100% - var(--charcell-row)) / 2),
|
|
24
|
+
var(--charcell-row)
|
|
25
|
+
);
|
|
26
|
+
white-space: pre;
|
|
27
|
+
color: var(--charcell-mid);
|
|
28
|
+
visibility: hidden;
|
|
29
|
+
animation:
|
|
30
|
+
PreviewPane-loading 0s 300ms forwards,
|
|
31
|
+
PreviewPane-dots 1.2s 300ms steps(1, end) infinite;
|
|
32
|
+
}
|
|
33
|
+
@keyframes PreviewPane-loading {
|
|
34
|
+
to {
|
|
35
|
+
visibility: visible;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/* The dots count up, one a step; spaces hold the dots' place, so the
|
|
39
|
+
word stays put in the monospace face. */
|
|
40
|
+
@keyframes PreviewPane-dots {
|
|
41
|
+
0% {
|
|
42
|
+
content: 'loading\00a0\00a0\00a0';
|
|
43
|
+
}
|
|
44
|
+
25% {
|
|
45
|
+
content: 'loading.\00a0\00a0';
|
|
46
|
+
}
|
|
47
|
+
50% {
|
|
48
|
+
content: 'loading..\00a0';
|
|
49
|
+
}
|
|
50
|
+
75%,
|
|
51
|
+
100% {
|
|
52
|
+
content: 'loading...';
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
@media (prefers-reduced-motion: reduce) {
|
|
56
|
+
.PreviewPane:has(> iframe:not([data-preview-shown]))::after {
|
|
57
|
+
animation: PreviewPane-loading 0s 300ms forwards;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/* The controller's iframe, the pane's one child: based on the height its
|
|
61
|
+
story reports (the iframe's own 150px until it does), so a row measuring
|
|
62
|
+
its content fits the story, and growing to fill a taller pane or
|
|
63
|
+
shrinking with a shorter one. */
|
|
64
|
+
.PreviewPane > iframe {
|
|
65
|
+
display: block;
|
|
66
|
+
flex: 1 1 var(--preview-pane-content, 150px);
|
|
67
|
+
min-height: 0;
|
|
68
|
+
width: 100%;
|
|
69
|
+
border: 0;
|
|
70
|
+
}
|
|
71
|
+
/* At a width the reader picked, inside a scroll area: the iframe is that
|
|
72
|
+
wide and as tall as its story, centered while the pane is wider. The
|
|
73
|
+
scroll area's bars take rows and columns of their own, so a bar never
|
|
74
|
+
covers the story, and a row sized to its content makes room for one. */
|
|
75
|
+
.PreviewPane--fixed {
|
|
76
|
+
display: block;
|
|
77
|
+
height: auto;
|
|
78
|
+
}
|
|
79
|
+
.PreviewPane--fixed > iframe {
|
|
80
|
+
width: var(--preview-pane-width);
|
|
81
|
+
height: var(--preview-pane-content, 150px);
|
|
82
|
+
margin-inline: auto;
|
|
83
|
+
}
|
|
84
|
+
/* Why the html pane has no html, over the pane's own note in the kit's
|
|
85
|
+
canvas: in the mid gray on the shell's ground, centered, as the
|
|
86
|
+
loading note and the code pane's reason are. */
|
|
87
|
+
.PreviewPane__note {
|
|
88
|
+
position: absolute;
|
|
89
|
+
inset: 0;
|
|
90
|
+
margin: 0;
|
|
91
|
+
padding: 0 1ch;
|
|
92
|
+
display: grid;
|
|
93
|
+
place-items: center;
|
|
94
|
+
text-align: center;
|
|
95
|
+
color: var(--charcell-mid);
|
|
96
|
+
background: var(--charcell-background);
|
|
97
|
+
}
|
|
98
|
+
/* What the Frame fills, and takes the pane's whole width from; the cell,
|
|
99
|
+
nothing to see, is the width the labels are cut against. */
|
|
100
|
+
.PreviewPane__frame {
|
|
101
|
+
position: relative;
|
|
102
|
+
flex: 1 1 auto;
|
|
103
|
+
width: 100%;
|
|
104
|
+
height: 100%;
|
|
105
|
+
min-width: 0;
|
|
106
|
+
min-height: 0;
|
|
107
|
+
display: grid;
|
|
108
|
+
grid-template: minmax(0, 1fr) / minmax(0, 1fr);
|
|
109
|
+
}
|
|
110
|
+
.PreviewPane__cell {
|
|
111
|
+
position: absolute;
|
|
112
|
+
width: 1ch;
|
|
113
|
+
visibility: hidden;
|
|
114
|
+
}
|
|
115
|
+
/* The actions at the end of the top row, side by side: each button's own
|
|
116
|
+
padding is the cells between them. */
|
|
117
|
+
.PreviewPane__actions {
|
|
118
|
+
display: flex;
|
|
119
|
+
}
|
|
120
|
+
/* How many warnings the html pane's markup has, first in its legend at
|
|
121
|
+
the foreground, so a part left out at rest is not mistaken for one the
|
|
122
|
+
story does not show; the count opens the warnings (HtmlWarnings). */
|
|
123
|
+
.PreviewPane__warnings {
|
|
124
|
+
white-space: nowrap;
|
|
125
|
+
color: var(--charcell-foreground);
|
|
126
|
+
}
|
|
127
|
+
}
|