@weasel-js/forge 1.10.1 → 1.11.1
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/README.md +2 -1
- package/dist/{FrameController-UeTY7ubF.d.ts → FrameController-Cj_i-Rdk.d.ts} +23 -10
- package/dist/{chunk-DFKCLZKS.js → chunk-7BQPHMA2.js} +2 -2
- package/dist/chunk-7BQPHMA2.js.map +1 -0
- package/dist/{chunk-BIAEGWGJ.js → chunk-BKPDKUDN.js} +26 -15
- package/dist/chunk-BKPDKUDN.js.map +1 -0
- package/dist/{chunk-E2FHBDNQ.js → chunk-FZNABWJC.js} +13 -16
- package/dist/chunk-FZNABWJC.js.map +1 -0
- package/dist/{chunk-FL2MUPUL.js → chunk-GH5RE5X5.js} +2 -2
- package/dist/chunk-GH5RE5X5.js.map +1 -0
- package/dist/{chunk-AP3DRQLI.js → chunk-JTCUIJPZ.js} +170 -10
- package/dist/chunk-JTCUIJPZ.js.map +1 -0
- package/dist/{chunk-GB6PRJET.js → chunk-KEQBGDUZ.js} +3 -3
- package/dist/{chunk-GB6PRJET.js.map → chunk-KEQBGDUZ.js.map} +1 -1
- package/dist/{chunk-DKWHGSBZ.js → chunk-LTTEILXY.js} +3 -3
- package/dist/{chunk-DKWHGSBZ.js.map → chunk-LTTEILXY.js.map} +1 -1
- package/dist/{config-Cz7ZyGF-.d.ts → config-DN6IaNf6.d.ts} +6 -5
- package/dist/csf/preview-api.js +2 -2
- package/dist/frame/index.css +1 -0
- package/dist/frame/index.css.map +1 -1
- package/dist/frame/index.d.ts +3 -2
- package/dist/frame/index.js +13 -15
- package/dist/frame/index.js.map +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/shell/index.css +18 -6
- package/dist/shell/index.css.map +1 -1
- package/dist/shell/index.d.ts +6 -13
- package/dist/shell/index.js +235 -92
- package/dist/shell/index.js.map +1 -1
- package/dist/test/index.d.ts +3 -4
- package/dist/test/index.js +10 -12
- package/dist/test/index.js.map +1 -1
- package/dist/vite/index.d.ts +1 -1
- package/dist/vite/index.js +14 -5
- package/dist/vite/index.js.map +1 -1
- package/package.json +8 -6
- package/dist/chunk-AP3DRQLI.js.map +0 -1
- package/dist/chunk-BIAEGWGJ.js.map +0 -1
- package/dist/chunk-DFKCLZKS.js.map +0 -1
- package/dist/chunk-E2FHBDNQ.js.map +0 -1
- package/dist/chunk-FL2MUPUL.js.map +0 -1
package/dist/shell/index.js
CHANGED
|
@@ -1,38 +1,55 @@
|
|
|
1
|
-
import { parseRoute, formatRoute, paramsToKnobs, knobPaths, sameKnob, knobsToParams, PLAYHEAD_PARAM, reservedParams } from '../chunk-
|
|
1
|
+
import { parseRoute, formatRoute, paramsToKnobs, knobPaths, sameKnob, knobsToParams, PLAYHEAD_PARAM, reservedParams } from '../chunk-LTTEILXY.js';
|
|
2
2
|
import { DEFAULT_TITLE } from '../chunk-5DXUNLV2.js';
|
|
3
|
-
import { TITLE_LIBRARIES, isIndexId, indexId, indexEntries, librariesFrom, LibrariesContext, schemaFromDescription, LibraryBadge, openChannel, IndexPage } from '../chunk-
|
|
3
|
+
import { TITLE_LIBRARIES, isIndexId, indexId, indexEntries, librariesFrom, LibrariesContext, createKitRoot, schemaFromDescription, LibraryBadge, openChannel, IndexPage } from '../chunk-BKPDKUDN.js';
|
|
4
4
|
import { isGallery } from '../chunk-WEQSLPKT.js';
|
|
5
|
-
import { useTrialFrame, createTrialFrames, createTrialClocks, StoryGlobalsContext, TrialFramesContext, TrialClocksContext, StoryTrial, useCssOverrides, useTrialClock, TrialHost } from '../chunk-
|
|
6
|
-
export { StoryGlobalsContext, StoryTrial, TrialFramesContext, TrialHost, useTrialFrame } from '../chunk-
|
|
7
|
-
import { labGlobals, withGlobals, followApp, storyConfig, GLOBALS_KEY, effectiveGlobals, PLAYHEAD_KEY, labOptions, isGlobalsPath } from '../chunk-
|
|
8
|
-
import { loadStories, indexRenderOf, useNearViewport, IN_VIEW_MARGIN } from '../chunk-
|
|
5
|
+
import { useTrialFrame, createTrialFrames, createTrialClocks, StoryGlobalsContext, TrialFramesContext, TrialClocksContext, StoryTrial, useCssOverrides, useTrialClock, TrialHost } from '../chunk-FZNABWJC.js';
|
|
6
|
+
export { StoryGlobalsContext, StoryTrial, TrialFramesContext, TrialHost, useTrialFrame } from '../chunk-FZNABWJC.js';
|
|
7
|
+
import { labGlobals, withGlobals, followApp, storyConfig, GLOBALS_KEY, effectiveGlobals, PLAYHEAD_KEY, labOptions, isGlobalsPath } from '../chunk-7BQPHMA2.js';
|
|
8
|
+
import { loadStories, indexRenderOf, useNearViewport, IN_VIEW_MARGIN } from '../chunk-JTCUIJPZ.js';
|
|
9
9
|
import '../chunk-L5XM5VKB.js';
|
|
10
10
|
import '../chunk-ZAWXMUGZ.js';
|
|
11
|
-
import '../chunk-
|
|
12
|
-
import { stableStringify, PORT_HANDOFF, FRAME_HELLO, PROTOCOL_VERSION } from '../chunk-
|
|
13
|
-
import { useTrialId, Button, Lab, useLabContext, TrialIdContext, usePersistedState, Select, useTrialState,
|
|
11
|
+
import '../chunk-KEQBGDUZ.js';
|
|
12
|
+
import { stableStringify, PORT_HANDOFF, FRAME_HELLO, PROTOCOL_VERSION } from '../chunk-GH5RE5X5.js';
|
|
13
|
+
import { useTrialId, Button, Lab, useLabContext, TrialIdContext, usePersistedState, Select, useTrialState, ToggleBar as ToggleBar$1, Input, TokenPanel, inferTokenType, refitScale } from '@weasel-js/labkit';
|
|
14
14
|
import num from '@weasel-js/theme/numeric.module.css';
|
|
15
15
|
import { createContext, useState, useRef, useCallback, useEffect, useMemo, useLayoutEffect, useId, useContext, Fragment as Fragment$1, useSyncExternalStore } from 'react';
|
|
16
16
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
17
|
-
import { createRoot } from 'react-dom/client';
|
|
18
17
|
import { createEmitter } from '@weasel-js/registry';
|
|
19
18
|
import { f, valueAtPath, isConfigBranch } from '@weasel-js/labkit/config';
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
19
|
+
import { Slider } from '@weasel-js/ui/components/Slider';
|
|
20
|
+
import { Transport } from '@weasel-js/ui/components/Timeline';
|
|
21
|
+
import { TOKEN_MANIFEST, themeAxes, weaselTheme, THEME_SOURCES, resolveTheme, isColorModePreference, isByAxis } from '@weasel-js/theme';
|
|
22
22
|
import { scale, httpThemeApi } from '@weasel-js/theme/engine';
|
|
23
23
|
import { useLatest, historyKey, createHistory, swapOp, isPlainObject } from '@weasel-js/core';
|
|
24
|
+
import { Button as Button$1 } from '@weasel-js/ui/components/Button';
|
|
25
|
+
import { Checkbox } from '@weasel-js/ui/components/Checkbox';
|
|
26
|
+
import { Icon } from '@weasel-js/ui/components/Icon';
|
|
27
|
+
import { ToggleBar } from '@weasel-js/ui/components/ToggleBar';
|
|
28
|
+
import { TOKEN_CATEGORIES } from '@weasel-js/ui/components/TokenPanel';
|
|
24
29
|
import { useResolvedColorMode } from '@weasel-js/theme/react';
|
|
30
|
+
import { formatShortcut } from '@weasel-js/ui/components/ToolPalette';
|
|
31
|
+
import { Dialog } from '@weasel-js/ui/components/Dialog';
|
|
32
|
+
import { Callout } from '@weasel-js/ui/components/Callout';
|
|
33
|
+
import { pref } from '@weasel-js/prefs';
|
|
34
|
+
import { DisclosureMark } from '@weasel-js/ui/components/Disclosure';
|
|
25
35
|
|
|
26
|
-
function
|
|
27
|
-
|
|
36
|
+
function pointAt(point, nodes) {
|
|
37
|
+
const enter = (event) => {
|
|
38
|
+
event.stopPropagation();
|
|
39
|
+
point(nodes);
|
|
40
|
+
};
|
|
41
|
+
return { onMouseOver: enter, onFocus: enter, onMouseLeave: () => point(null), onBlur: () => point(null) };
|
|
42
|
+
}
|
|
43
|
+
function Finding({ finding, point }) {
|
|
44
|
+
return /* @__PURE__ */ jsxs("li", { className: "fg-a11y__finding", ...pointAt(point, finding.nodes), children: [
|
|
28
45
|
/* @__PURE__ */ jsxs("p", { className: "fg-a11y__help", children: [
|
|
29
46
|
/* @__PURE__ */ jsx("a", { href: finding.helpUrl, target: "_blank", rel: "noreferrer", children: finding.help }),
|
|
30
47
|
finding.impact ? /* @__PURE__ */ jsx("span", { className: "fg-a11y__impact", "data-impact": finding.impact, children: finding.impact }) : null
|
|
31
48
|
] }),
|
|
32
|
-
/* @__PURE__ */ jsx("ul", { className: "fg-a11y__nodes", children: finding.nodes.map((node) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("code", { children: node.target.join(" ") }) }, `${finding.id}:${node.target.join(",")}`)) })
|
|
49
|
+
/* @__PURE__ */ jsx("ul", { className: "fg-a11y__nodes", children: finding.nodes.map((node) => /* @__PURE__ */ jsx("li", { ...pointAt(point, [node]), children: /* @__PURE__ */ jsx("code", { children: node.target.join(" ") }) }, `${finding.id}:${node.target.join(",")}`)) })
|
|
33
50
|
] });
|
|
34
51
|
}
|
|
35
|
-
function Findings({ title, findings }) {
|
|
52
|
+
function Findings({ title, findings, point }) {
|
|
36
53
|
if (findings.length === 0) return null;
|
|
37
54
|
return /* @__PURE__ */ jsxs("section", { className: "fg-a11y__group", children: [
|
|
38
55
|
/* @__PURE__ */ jsxs("h3", { className: `fg-a11y__group-title ${num.numeric}`, children: [
|
|
@@ -41,7 +58,7 @@ function Findings({ title, findings }) {
|
|
|
41
58
|
findings.length,
|
|
42
59
|
")"
|
|
43
60
|
] }),
|
|
44
|
-
/* @__PURE__ */ jsx("ul", { className: "fg-a11y__findings", children: findings.map((finding) => /* @__PURE__ */ jsx(Finding, { finding }, finding.id)) })
|
|
61
|
+
/* @__PURE__ */ jsx("ul", { className: "fg-a11y__findings", children: findings.map((finding) => /* @__PURE__ */ jsx(Finding, { finding, point }, finding.id)) })
|
|
45
62
|
] });
|
|
46
63
|
}
|
|
47
64
|
function A11yPanel() {
|
|
@@ -60,6 +77,13 @@ function A11yPanel() {
|
|
|
60
77
|
ran.current = audit;
|
|
61
78
|
start(audit);
|
|
62
79
|
}, [audit, start]);
|
|
80
|
+
const send = frame.send;
|
|
81
|
+
const [pointed, setPointed] = useState(null);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
if (!send || !pointed) return;
|
|
84
|
+
send({ type: "a11y.highlight", targets: pointed.map((node) => node.target) });
|
|
85
|
+
return () => send({ type: "a11y.highlight", targets: [] });
|
|
86
|
+
}, [send, pointed]);
|
|
63
87
|
const rerun = () => {
|
|
64
88
|
if (audit) start(audit);
|
|
65
89
|
};
|
|
@@ -82,8 +106,8 @@ function A11yPanel() {
|
|
|
82
106
|
outcome.report.passes,
|
|
83
107
|
" passes"
|
|
84
108
|
] }),
|
|
85
|
-
/* @__PURE__ */ jsx(Findings, { title: "Violations", findings: outcome.report.violations }),
|
|
86
|
-
/* @__PURE__ */ jsx(Findings, { title: "Needs review", findings: outcome.report.incomplete })
|
|
109
|
+
/* @__PURE__ */ jsx(Findings, { title: "Violations", findings: outcome.report.violations, point: setPointed }),
|
|
110
|
+
/* @__PURE__ */ jsx(Findings, { title: "Needs review", findings: outcome.report.incomplete, point: setPointed })
|
|
87
111
|
] }) : null
|
|
88
112
|
] });
|
|
89
113
|
}
|
|
@@ -340,12 +364,30 @@ function missingInstrument(id, globals = {}) {
|
|
|
340
364
|
};
|
|
341
365
|
}
|
|
342
366
|
var ICONS = {
|
|
343
|
-
color:
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
367
|
+
color: (
|
|
368
|
+
/* @icon */
|
|
369
|
+
"ui:drop"
|
|
370
|
+
),
|
|
371
|
+
type: (
|
|
372
|
+
/* @icon */
|
|
373
|
+
"ui:type"
|
|
374
|
+
),
|
|
375
|
+
size: (
|
|
376
|
+
/* @icon */
|
|
377
|
+
"core:measure"
|
|
378
|
+
),
|
|
379
|
+
motion: (
|
|
380
|
+
/* @icon */
|
|
381
|
+
"ui:curveEaseInOut"
|
|
382
|
+
),
|
|
383
|
+
depth: (
|
|
384
|
+
/* @icon */
|
|
385
|
+
"ui:layers"
|
|
386
|
+
),
|
|
387
|
+
other: (
|
|
388
|
+
/* @icon */
|
|
389
|
+
"ui:more"
|
|
390
|
+
)
|
|
349
391
|
};
|
|
350
392
|
var PANEL = ".fg-css-vars";
|
|
351
393
|
var HOST = ".lk-sidebar-section, .lk-panel-tile";
|
|
@@ -636,6 +678,24 @@ function useThemeSave({ trialId, globals, themeApi, scales, overrides, history:
|
|
|
636
678
|
save
|
|
637
679
|
};
|
|
638
680
|
}
|
|
681
|
+
var MANIFEST = new Map(TOKEN_MANIFEST.map((token) => [token.name, token]));
|
|
682
|
+
function groupOf(name) {
|
|
683
|
+
const segments = name.replace(/^--/, "").split("-");
|
|
684
|
+
return segments.length > 1 ? segments.slice(0, -1).join("-") : name.replace(/^--/, "");
|
|
685
|
+
}
|
|
686
|
+
function useStoryTokens(vars) {
|
|
687
|
+
const [showUnused, setShowUnused] = usePersistedState("fg-css-vars-unused", false, { scope: "lab" });
|
|
688
|
+
const tokens = useMemo(
|
|
689
|
+
() => vars.flatMap(({ name, value, used }) => {
|
|
690
|
+
if (!used && !showUnused) return [];
|
|
691
|
+
const known = MANIFEST.get(name);
|
|
692
|
+
return [{ name, type: known?.type ?? inferTokenType(value), group: known?.group ?? groupOf(name), value }];
|
|
693
|
+
}),
|
|
694
|
+
[vars, showUnused]
|
|
695
|
+
);
|
|
696
|
+
const emptyText = vars.length > 0 && !showUnused ? "The story uses no variables." : "The story\u2019s frame has reported no variables.";
|
|
697
|
+
return { tokens, showUnused, setShowUnused, emptyText };
|
|
698
|
+
}
|
|
639
699
|
var AXES = themeAxes(weaselTheme);
|
|
640
700
|
function useThemeTokens(globals, vars) {
|
|
641
701
|
const selection = useTrialSelection(AXES, globals);
|
|
@@ -714,13 +774,13 @@ var TABS = [
|
|
|
714
774
|
{ value: "theme", label: "Theme" },
|
|
715
775
|
{ value: "story", label: "Story" }
|
|
716
776
|
];
|
|
717
|
-
var
|
|
777
|
+
var MANIFEST2 = new Map(TOKEN_MANIFEST.map((token) => [token.name, token]));
|
|
718
778
|
var literal = (v) => typeof v === "number";
|
|
719
779
|
var SCALE_SOURCES = Object.entries(THEME_SOURCES[THEME_NAME]?.scales ?? {}).flatMap(([name, def]) => {
|
|
720
780
|
if (!Array.isArray(def.steps)) return [];
|
|
721
781
|
const steps = def.steps;
|
|
722
782
|
const tokens = steps.map((step) => `${TOKEN_PREFIX}${name}-${step}`);
|
|
723
|
-
const group =
|
|
783
|
+
const group = MANIFEST2.get(tokens[0] ?? "")?.group;
|
|
724
784
|
if (!group) return [];
|
|
725
785
|
const factors = Array.isArray(def.factors) && def.factors.every(literal) ? def.factors : null;
|
|
726
786
|
const rule = def.factors !== void 0 ? factors ? { kind: "factors", factors } : "factors" : def.ratio !== void 0 ? literal(def.ratio) ? { kind: "ratio", ratio: def.ratio } : "ratio" : literal(def.step) ? { kind: "step", step: def.step } : "step";
|
|
@@ -750,10 +810,6 @@ function standingScale(source, amounts) {
|
|
|
750
810
|
const base = (amounts[at] ?? 0) / (rule.factors[at] ?? 1);
|
|
751
811
|
return { ...seed, base: Math.round(base * 100) / 100, rule };
|
|
752
812
|
}
|
|
753
|
-
function groupOf(name) {
|
|
754
|
-
const segments = name.replace(/^--/, "").split("-");
|
|
755
|
-
return segments.length > 1 ? segments.slice(0, -1).join("-") : name.replace(/^--/, "");
|
|
756
|
-
}
|
|
757
813
|
var NO_GLOBALS = {};
|
|
758
814
|
function CssVarsPanel({ globals = NO_GLOBALS, themeApi } = {}) {
|
|
759
815
|
const trialId = useTrialId();
|
|
@@ -768,13 +824,8 @@ function CssVarsPanel({ globals = NO_GLOBALS, themeApi } = {}) {
|
|
|
768
824
|
const [tab, setTab] = useState("theme");
|
|
769
825
|
const [filter, setFilter] = useState("");
|
|
770
826
|
const themeTokens = useThemeTokens(globals, frame.vars);
|
|
771
|
-
const
|
|
772
|
-
|
|
773
|
-
return frame.vars.map(({ name, value }) => {
|
|
774
|
-
const known = MANIFEST.get(name);
|
|
775
|
-
return { name, type: known?.type ?? inferTokenType(value), group: known?.group ?? groupOf(name), value };
|
|
776
|
-
});
|
|
777
|
-
}, [tab, frame.vars, themeTokens]);
|
|
827
|
+
const story = useStoryTokens(frame.vars);
|
|
828
|
+
const tokens = tab === "theme" ? themeTokens : story.tokens;
|
|
778
829
|
const query = filter.trim().toLowerCase();
|
|
779
830
|
const shown = tokens.map((token) => {
|
|
780
831
|
const override = overrides[token.name];
|
|
@@ -866,27 +917,27 @@ function CssVarsPanel({ globals = NO_GLOBALS, themeApi } = {}) {
|
|
|
866
917
|
placeholder: "Filter",
|
|
867
918
|
value: filter,
|
|
868
919
|
onChange: setFilter,
|
|
869
|
-
leadingAdornment: /* @__PURE__ */ jsx(
|
|
920
|
+
leadingAdornment: /* @__PURE__ */ jsx(Icon, { name: (
|
|
921
|
+
/* @icon */
|
|
922
|
+
"ui:search"
|
|
923
|
+
), size: 12 })
|
|
870
924
|
}
|
|
871
925
|
),
|
|
872
926
|
/* @__PURE__ */ jsxs("div", { className: "fg-css-vars__steps", role: "group", "aria-label": "History", children: [
|
|
873
|
-
/* @__PURE__ */ jsx(Button$1, { iconOnly: true, ariaLabel: "Undo", variant: "ghost", size: "sm", disabled: !history2.canUndo, onClick: () => history2.step("undo"), children: /* @__PURE__ */ jsx(Icon, { name:
|
|
874
|
-
|
|
927
|
+
/* @__PURE__ */ jsx(Button$1, { iconOnly: true, ariaLabel: "Undo", variant: "ghost", size: "sm", disabled: !history2.canUndo, onClick: () => history2.step("undo"), children: /* @__PURE__ */ jsx(Icon, { name: (
|
|
928
|
+
/* @icon */
|
|
929
|
+
"core:undo"
|
|
930
|
+
), size: 14 }) }),
|
|
931
|
+
/* @__PURE__ */ jsx(Button$1, { iconOnly: true, ariaLabel: "Redo", variant: "ghost", size: "sm", disabled: !history2.canRedo, onClick: () => history2.step("redo"), children: /* @__PURE__ */ jsx(Icon, { name: (
|
|
932
|
+
/* @icon */
|
|
933
|
+
"core:redo"
|
|
934
|
+
), size: 14 }) })
|
|
875
935
|
] })
|
|
876
936
|
] }),
|
|
877
|
-
tab === "
|
|
878
|
-
|
|
879
|
-
notice ? /* @__PURE__ */ jsx(
|
|
880
|
-
"p",
|
|
881
|
-
{
|
|
882
|
-
className: `fg-css-vars__notice fg-css-vars__notice--${notice.tone}`,
|
|
883
|
-
role: notice.tone === "error" ? "alert" : "status",
|
|
884
|
-
children: notice.text
|
|
885
|
-
}
|
|
886
|
-
) : null
|
|
887
|
-
] }) : null
|
|
937
|
+
tab === "story" ? /* @__PURE__ */ jsx(Checkbox, { className: "fg-css-vars__unused", isSelected: story.showUnused, onChange: story.setShowUnused, children: "Show variables the story doesn\u2019t use" }) : null,
|
|
938
|
+
tab === "theme" ? /* @__PURE__ */ jsx(SaveRow, { pending, saving, notice, onSave: () => void save() }) : null
|
|
888
939
|
] }),
|
|
889
|
-
shown.length === 0 ? /* @__PURE__ */ jsx("p", { className: "fg-css-vars__empty", children: tokens.length
|
|
940
|
+
shown.length === 0 ? /* @__PURE__ */ jsx("p", { className: "fg-css-vars__empty", children: tokens.length > 0 ? "No variables match." : tab === "story" ? story.emptyText : "The story\u2019s frame has reported no variables." }) : /* @__PURE__ */ jsx("div", { className: "fg-css-vars__list", children: /* @__PURE__ */ jsx(
|
|
890
941
|
TokenPanel,
|
|
891
942
|
{
|
|
892
943
|
tokens: shown,
|
|
@@ -903,6 +954,13 @@ function CssVarsPanel({ globals = NO_GLOBALS, themeApi } = {}) {
|
|
|
903
954
|
)
|
|
904
955
|
);
|
|
905
956
|
}
|
|
957
|
+
function SaveRow({ pending, saving, notice, onSave }) {
|
|
958
|
+
if (!pending && !notice) return null;
|
|
959
|
+
return /* @__PURE__ */ jsxs("div", { className: "fg-css-vars__save", children: [
|
|
960
|
+
pending ? /* @__PURE__ */ jsx(Button$1, { variant: "primary", size: "sm", loading: saving, disabled: saving, onClick: onSave, children: "Save to theme" }) : null,
|
|
961
|
+
notice ? /* @__PURE__ */ jsx("p", { className: `fg-css-vars__notice fg-css-vars__notice--${notice.tone}`, role: notice.tone === "error" ? "alert" : "status", children: notice.text }) : null
|
|
962
|
+
] });
|
|
963
|
+
}
|
|
906
964
|
function FocusedCssVars() {
|
|
907
965
|
const { focusedTrialId, trials, instruments } = useLabContext();
|
|
908
966
|
const labGlobals2 = useContext(StoryGlobalsContext);
|
|
@@ -920,6 +978,42 @@ var CSS_VARS_SECTION = {
|
|
|
920
978
|
region: "aside",
|
|
921
979
|
item: { title: "CSS Vars", actions: /* @__PURE__ */ jsx(SectionJump, {}), fill: true, body: /* @__PURE__ */ jsx(FocusedCssVars, {}) }
|
|
922
980
|
};
|
|
981
|
+
|
|
982
|
+
// src/shell/cssVars/cssVarsChrome.ts
|
|
983
|
+
var RECORD = "fg-css-vars-shown";
|
|
984
|
+
function cssVarsChrome(shown, toggle) {
|
|
985
|
+
return [
|
|
986
|
+
{
|
|
987
|
+
id: "fg-css-vars-toggle",
|
|
988
|
+
region: "header",
|
|
989
|
+
group: "story",
|
|
990
|
+
item: { icon: (
|
|
991
|
+
/* @icon */
|
|
992
|
+
"ui:typeBraces"
|
|
993
|
+
), label: "CSS Vars panel", pressed: shown, onActivate: toggle }
|
|
994
|
+
},
|
|
995
|
+
...shown ? [CSS_VARS_SECTION] : []
|
|
996
|
+
];
|
|
997
|
+
}
|
|
998
|
+
function CssVarsChrome({ onChrome }) {
|
|
999
|
+
const [shown, setShown] = usePersistedState(RECORD, false, { scope: "lab" });
|
|
1000
|
+
const chrome = useMemo(() => cssVarsChrome(shown, () => setShown((was) => !was)), [shown, setShown]);
|
|
1001
|
+
useEffect(() => onChrome(chrome), [chrome, onChrome]);
|
|
1002
|
+
return null;
|
|
1003
|
+
}
|
|
1004
|
+
var KEYS = { kind: "key", key: "i", mods: { mod: true } };
|
|
1005
|
+
function infoItem(open) {
|
|
1006
|
+
return {
|
|
1007
|
+
icon: (
|
|
1008
|
+
/* @icon */
|
|
1009
|
+
"ui:info"
|
|
1010
|
+
),
|
|
1011
|
+
label: "Info",
|
|
1012
|
+
shortcut: formatShortcut({ key: KEYS.key, mod: KEYS.mods.mod }),
|
|
1013
|
+
keys: KEYS,
|
|
1014
|
+
onActivate: open
|
|
1015
|
+
};
|
|
1016
|
+
}
|
|
923
1017
|
var GLOBALS = "$globals";
|
|
924
1018
|
function leaves(shape, prefix = "") {
|
|
925
1019
|
const out = [];
|
|
@@ -1159,9 +1253,9 @@ function RoutePlayhead() {
|
|
|
1159
1253
|
if (!trial || route === null) return null;
|
|
1160
1254
|
return /* @__PURE__ */ jsx(PlayheadSync, { trialId: trial.id, route, appliedRef: applied }, `${trial.id} ${route}`);
|
|
1161
1255
|
}
|
|
1162
|
-
var
|
|
1256
|
+
var RECORD2 = "fg-globals";
|
|
1163
1257
|
function useLabGlobals(declarations) {
|
|
1164
|
-
const [stored, setStored] = usePersistedState(
|
|
1258
|
+
const [stored, setStored] = usePersistedState(RECORD2, null, { scope: "lab" });
|
|
1165
1259
|
const values = useMemo(() => labGlobals(declarations, stored), [declarations, stored]);
|
|
1166
1260
|
const set = useCallback(
|
|
1167
1261
|
(key, value) => setStored((prev) => ({ ...labGlobals(declarations, prev), [key]: value })),
|
|
@@ -1193,7 +1287,8 @@ function GlobalsToolbar({ declarations }) {
|
|
|
1193
1287
|
NestedGlobals,
|
|
1194
1288
|
{
|
|
1195
1289
|
label: declaration.label,
|
|
1196
|
-
icon: declaration.icon ??
|
|
1290
|
+
icon: declaration.icon ?? /* @icon */
|
|
1291
|
+
"core:tune",
|
|
1197
1292
|
nested,
|
|
1198
1293
|
values,
|
|
1199
1294
|
set
|
|
@@ -1251,6 +1346,41 @@ function LabGlobals({
|
|
|
1251
1346
|
useEffect(() => onChange(resolved), [resolved, onChange]);
|
|
1252
1347
|
return null;
|
|
1253
1348
|
}
|
|
1349
|
+
var leafPath = (n) => `globals.d${n}.v`;
|
|
1350
|
+
function globalsMenu(declarations, values, set) {
|
|
1351
|
+
const entries = Object.entries(declarations);
|
|
1352
|
+
if (entries.length === 0) return void 0;
|
|
1353
|
+
const submenus = {};
|
|
1354
|
+
const current = {};
|
|
1355
|
+
const keys = /* @__PURE__ */ new Map();
|
|
1356
|
+
entries.forEach(([key, declaration], n) => {
|
|
1357
|
+
const options = labOptions(declaration, values);
|
|
1358
|
+
submenus[`d${n}`] = pref.group(
|
|
1359
|
+
declaration.label,
|
|
1360
|
+
{ v: pref.enum(declaration.label, declaration.default, options) },
|
|
1361
|
+
{ as: "menu" }
|
|
1362
|
+
);
|
|
1363
|
+
current[leafPath(n)] = values[key];
|
|
1364
|
+
keys.set(leafPath(n), key);
|
|
1365
|
+
});
|
|
1366
|
+
return {
|
|
1367
|
+
schema: pref.group("", { globals: pref.group("Globals", submenus, { as: "menu" }) }),
|
|
1368
|
+
values: current,
|
|
1369
|
+
onChange: (path, value) => {
|
|
1370
|
+
const key = keys.get(path);
|
|
1371
|
+
if (key !== void 0 && typeof value === "string") set(key, value);
|
|
1372
|
+
}
|
|
1373
|
+
};
|
|
1374
|
+
}
|
|
1375
|
+
function GlobalsMenus({
|
|
1376
|
+
declarations,
|
|
1377
|
+
onMenus
|
|
1378
|
+
}) {
|
|
1379
|
+
const [values, set] = useLabGlobals(declarations);
|
|
1380
|
+
const menus = useMemo(() => globalsMenu(declarations, values, set), [declarations, values, set]);
|
|
1381
|
+
useEffect(() => onMenus(menus), [menus, onMenus]);
|
|
1382
|
+
return null;
|
|
1383
|
+
}
|
|
1254
1384
|
function KnobSync({ schema, config }) {
|
|
1255
1385
|
const { setConfig } = useTrialState();
|
|
1256
1386
|
const reading = useRef(true);
|
|
@@ -1427,14 +1557,27 @@ function filterComponents(rows, query) {
|
|
|
1427
1557
|
}
|
|
1428
1558
|
return out;
|
|
1429
1559
|
}
|
|
1560
|
+
function parentOf(row, byPath) {
|
|
1561
|
+
const segments = row.path.split("/");
|
|
1562
|
+
for (let take = segments.length - 1; take > 0; take--) {
|
|
1563
|
+
const parent = byPath.get(segments.slice(0, take).join("/"));
|
|
1564
|
+
if (parent && parent.library === row.library) return parent;
|
|
1565
|
+
}
|
|
1566
|
+
return void 0;
|
|
1567
|
+
}
|
|
1430
1568
|
function componentNodes(rows) {
|
|
1431
1569
|
const root = [];
|
|
1432
1570
|
const folders = /* @__PURE__ */ new Map();
|
|
1571
|
+
const byPath = new Map(rows.map((row) => [row.path, row]));
|
|
1572
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
1573
|
+
const subs = /* @__PURE__ */ new Map();
|
|
1574
|
+
for (const row of rows) subs.set(row.path, []);
|
|
1433
1575
|
for (const row of rows) {
|
|
1434
|
-
const
|
|
1576
|
+
const parent = parentOf(row, byPath);
|
|
1435
1577
|
const title = row.path.split("/");
|
|
1436
|
-
|
|
1437
|
-
let
|
|
1578
|
+
const labels = parent ? title.slice(parent.path.split("/").length) : row.label.split("/");
|
|
1579
|
+
let siblings = parent ? subs.get(parent.path) : root;
|
|
1580
|
+
let tag = parent ? void 0 : row.library;
|
|
1438
1581
|
for (let i = 0; i < labels.length - 1; i++) {
|
|
1439
1582
|
const path = title.slice(0, title.length - labels.length + i + 1).join("/");
|
|
1440
1583
|
let folder = folders.get(path);
|
|
@@ -1446,14 +1589,22 @@ function componentNodes(rows) {
|
|
|
1446
1589
|
siblings = folder.children;
|
|
1447
1590
|
tag = void 0;
|
|
1448
1591
|
}
|
|
1449
|
-
|
|
1592
|
+
const node = {
|
|
1450
1593
|
kind: "folder",
|
|
1451
1594
|
label: labels[labels.length - 1],
|
|
1452
1595
|
path: row.path,
|
|
1453
1596
|
tag,
|
|
1454
1597
|
...row.index ? { index: row.index } : {},
|
|
1455
|
-
children:
|
|
1456
|
-
}
|
|
1598
|
+
children: []
|
|
1599
|
+
};
|
|
1600
|
+
nodes.set(row.path, node);
|
|
1601
|
+
siblings.push(node);
|
|
1602
|
+
}
|
|
1603
|
+
for (const row of rows) {
|
|
1604
|
+
nodes.get(row.path).children = [
|
|
1605
|
+
...subs.get(row.path),
|
|
1606
|
+
...row.entries.map((entry) => ({ kind: "story", entry }))
|
|
1607
|
+
];
|
|
1457
1608
|
}
|
|
1458
1609
|
return foldGalleries(root);
|
|
1459
1610
|
}
|
|
@@ -2303,26 +2454,21 @@ function RouteOpener() {
|
|
|
2303
2454
|
}, [route, lab]);
|
|
2304
2455
|
return null;
|
|
2305
2456
|
}
|
|
2306
|
-
function
|
|
2457
|
+
function useDocumentTitle(title) {
|
|
2307
2458
|
useEffect(() => {
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
window.addEventListener("keydown", onKeyDown);
|
|
2317
|
-
return () => window.removeEventListener("keydown", onKeyDown);
|
|
2318
|
-
}, [open]);
|
|
2459
|
+
document.title = title;
|
|
2460
|
+
}, [title]);
|
|
2461
|
+
}
|
|
2462
|
+
function NoStories({ stories }) {
|
|
2463
|
+
return /* @__PURE__ */ jsxs("div", { className: "fg-empty", children: [
|
|
2464
|
+
/* @__PURE__ */ jsx("p", { className: "fg-empty__title", children: "No stories found" }),
|
|
2465
|
+
stories.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "fg-empty__globs", "aria-label": "Story globs", children: stories.map((glob) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("code", { children: glob }) }, glob)) }) : null
|
|
2466
|
+
] });
|
|
2319
2467
|
}
|
|
2320
2468
|
function Workshop({ index, frameUrl, importers, setup, changes, config, stories = [], storageKey, storage, dependencies }) {
|
|
2321
2469
|
const declarations = config?.globals ?? NO_DECLARATIONS;
|
|
2322
2470
|
const title = config?.title ?? DEFAULT_TITLE;
|
|
2323
|
-
|
|
2324
|
-
document.title = title;
|
|
2325
|
-
}, [title]);
|
|
2471
|
+
useDocumentTitle(title);
|
|
2326
2472
|
const [frames] = useState(createTrialFrames);
|
|
2327
2473
|
const [clocks] = useState(createTrialClocks);
|
|
2328
2474
|
const [pool, setPool] = useState(null);
|
|
@@ -2358,33 +2504,27 @@ function Workshop({ index, frameUrl, importers, setup, changes, config, stories
|
|
|
2358
2504
|
const themeFor = config?.labTheme;
|
|
2359
2505
|
const labTheme = useMemo(() => themeFor?.(labValues), [themeFor, labValues]);
|
|
2360
2506
|
const [infoOpen, setInfoOpen] = useState(false);
|
|
2361
|
-
useInfoShortcut(setInfoOpen);
|
|
2362
2507
|
const reportLabValues = useCallback(
|
|
2363
2508
|
(next) => setLabValues((prev) => stableStringify(prev) === stableStringify(next) ? prev : next),
|
|
2364
2509
|
[]
|
|
2365
2510
|
);
|
|
2366
|
-
const infoCommand = useMemo(
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
);
|
|
2511
|
+
const infoCommand = useMemo(() => infoItem(() => setInfoOpen(true)), []);
|
|
2512
|
+
const showsCssVars = config?.cssVars !== false;
|
|
2513
|
+
const [cssVarsChrome2, setCssVarsChrome] = useState([]);
|
|
2370
2514
|
const labChrome = useMemo(
|
|
2371
2515
|
() => [
|
|
2372
2516
|
{ id: "fg-stories", region: "sidebar", render: (ctx) => /* @__PURE__ */ jsx(StoryTree, { ctx, index }) },
|
|
2373
|
-
...
|
|
2517
|
+
...showsCssVars ? cssVarsChrome2 : [],
|
|
2374
2518
|
A11Y_SECTION,
|
|
2375
2519
|
...Object.keys(declarations).length > 0 ? [{ id: "fg-globals", region: "header", render: () => /* @__PURE__ */ jsx(GlobalsToolbar, { declarations }) }] : [],
|
|
2376
2520
|
{ id: "fg-info", region: "header", group: "story", item: infoCommand },
|
|
2377
2521
|
...config?.labChrome ?? []
|
|
2378
2522
|
],
|
|
2379
|
-
[index, infoCommand, declarations,
|
|
2523
|
+
[index, infoCommand, declarations, showsCssVars, cssVarsChrome2, config?.labChrome]
|
|
2380
2524
|
);
|
|
2525
|
+
const [menus, setMenus] = useState();
|
|
2381
2526
|
const first = index[0];
|
|
2382
|
-
if (!first) {
|
|
2383
|
-
return /* @__PURE__ */ jsxs("div", { className: "fg-empty", children: [
|
|
2384
|
-
/* @__PURE__ */ jsx("p", { className: "fg-empty__title", children: "No stories found" }),
|
|
2385
|
-
stories.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "fg-empty__globs", "aria-label": "Story globs", children: stories.map((glob) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("code", { children: glob }) }, glob)) }) : null
|
|
2386
|
-
] });
|
|
2387
|
-
}
|
|
2527
|
+
if (!first) return /* @__PURE__ */ jsx(NoStories, { stories });
|
|
2388
2528
|
return /* @__PURE__ */ jsx(LibrariesContext.Provider, { value: libraries, children: /* @__PURE__ */ jsx(StoryGlobalsContext.Provider, { value: labValues, children: /* @__PURE__ */ jsx(DependenciesContext.Provider, { value: dependencies ?? null, children: /* @__PURE__ */ jsx(FramePoolContext.Provider, { value: pool, children: /* @__PURE__ */ jsx(TrialFramesContext.Provider, { value: frames, children: /* @__PURE__ */ jsx(TrialClocksContext.Provider, { value: clocks, children: /* @__PURE__ */ jsxs(
|
|
2389
2529
|
Lab,
|
|
2390
2530
|
{
|
|
@@ -2397,6 +2537,7 @@ function Workshop({ index, frameUrl, importers, setup, changes, config, stories
|
|
|
2397
2537
|
...storage ? { storage } : {},
|
|
2398
2538
|
labChrome,
|
|
2399
2539
|
addTrial: false,
|
|
2540
|
+
...menus ? { menus } : {},
|
|
2400
2541
|
...config?.controls ? { controls: config.controls } : {},
|
|
2401
2542
|
...config?.pages ? { pages: config.pages } : {},
|
|
2402
2543
|
...config?.path !== void 0 ? { path: config.path } : {},
|
|
@@ -2413,7 +2554,9 @@ function Workshop({ index, frameUrl, importers, setup, changes, config, stories
|
|
|
2413
2554
|
onOpenChange: setInfoOpen
|
|
2414
2555
|
}
|
|
2415
2556
|
),
|
|
2416
|
-
/* @__PURE__ */ jsx(LabGlobals, { declarations, onChange: reportLabValues })
|
|
2557
|
+
/* @__PURE__ */ jsx(LabGlobals, { declarations, onChange: reportLabValues }),
|
|
2558
|
+
/* @__PURE__ */ jsx(GlobalsMenus, { declarations, onMenus: setMenus }),
|
|
2559
|
+
showsCssVars ? /* @__PURE__ */ jsx(CssVarsChrome, { onChrome: setCssVarsChrome }) : null
|
|
2417
2560
|
]
|
|
2418
2561
|
}
|
|
2419
2562
|
) }) }) }) }) }) });
|
|
@@ -2421,7 +2564,7 @@ function Workshop({ index, frameUrl, importers, setup, changes, config, stories
|
|
|
2421
2564
|
function mountWorkshop({ container, ...props }) {
|
|
2422
2565
|
const target = container ?? document.getElementById("root");
|
|
2423
2566
|
if (!target) throw new Error("mountWorkshop: no container given and no #root element");
|
|
2424
|
-
const root =
|
|
2567
|
+
const root = createKitRoot(target, props.setup?.icons);
|
|
2425
2568
|
const changes = createStoryChanges();
|
|
2426
2569
|
let current = { ...props, changes };
|
|
2427
2570
|
root.render(/* @__PURE__ */ jsx(Workshop, { ...current }));
|