@weasel-js/forge 1.7.3 → 1.8.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 +78 -0
- package/dist/{FrameController-RdGggdGA.d.ts → FrameController-BH8xJHZ8.d.ts} +36 -1
- package/dist/{chunk-NYBMOSSR.js → chunk-5N4YP5HS.js} +166 -10
- package/dist/chunk-5N4YP5HS.js.map +1 -0
- package/dist/chunk-CJX3W5HY.js +151 -0
- package/dist/chunk-CJX3W5HY.js.map +1 -0
- package/dist/{chunk-SEK6EKHO.js → chunk-GHTVXHNJ.js} +72 -10
- package/dist/chunk-GHTVXHNJ.js.map +1 -0
- package/dist/{chunk-KIFCYY4F.js → chunk-JQD3MVUQ.js} +4 -4
- package/dist/{chunk-KIFCYY4F.js.map → chunk-JQD3MVUQ.js.map} +1 -1
- package/dist/chunk-KJGXJD3U.js +15 -0
- package/dist/chunk-KJGXJD3U.js.map +1 -0
- package/dist/chunk-L5XM5VKB.js +47 -0
- package/dist/chunk-L5XM5VKB.js.map +1 -0
- package/dist/{chunk-YKN3IAEX.js → chunk-MGQWCPYE.js} +4 -24
- package/dist/chunk-MGQWCPYE.js.map +1 -0
- package/dist/{chunk-JNJGIUYU.js → chunk-NI5FYQHW.js} +8 -5
- package/dist/chunk-NI5FYQHW.js.map +1 -0
- package/dist/{config-BJIgUhiI.d.ts → config-DoLWwEb2.d.ts} +5 -1
- package/dist/csf/preview-api.js +2 -1
- package/dist/csf/preview-api.js.map +1 -1
- package/dist/frame/index.css +1 -0
- package/dist/frame/index.css.map +1 -1
- package/dist/frame/index.d.ts +2 -2
- package/dist/frame/index.js +5 -4
- package/dist/frame/index.js.map +1 -1
- package/dist/index.d.ts +79 -4
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/shell/index.css +14 -0
- package/dist/shell/index.css.map +1 -1
- package/dist/shell/index.d.ts +2 -2
- package/dist/shell/index.js +225 -56
- package/dist/shell/index.js.map +1 -1
- package/dist/test/index.d.ts +1 -1
- package/dist/test/index.js +6 -5
- package/dist/test/index.js.map +1 -1
- package/dist/vite/index.js +160 -16
- package/dist/vite/index.js.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-JNJGIUYU.js.map +0 -1
- package/dist/chunk-NYBMOSSR.js.map +0 -1
- package/dist/chunk-SEK6EKHO.js.map +0 -1
- package/dist/chunk-Y3WZ2EWR.js +0 -15
- package/dist/chunk-Y3WZ2EWR.js.map +0 -1
- package/dist/chunk-YKN3IAEX.js.map +0 -1
package/dist/shell/index.js
CHANGED
|
@@ -1,18 +1,20 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseRoute, paramsToKnobs, knobPaths, sameKnob, knobsToParams, formatRoute, PLAYHEAD_PARAM, reservedParams } from '../chunk-CJX3W5HY.js';
|
|
2
|
+
import { isIndexId, indexId, libraryOf, indexEntries, schemaFromDescription, LibraryBadge, openChannel, IndexPage } from '../chunk-JQD3MVUQ.js';
|
|
2
3
|
import { isGallery } from '../chunk-WEQSLPKT.js';
|
|
3
|
-
import { useTrialFrame, createTrialFrames, StoryGlobalsContext, TrialFramesContext, StoryTrial, useCssOverrides, TrialHost } from '../chunk-
|
|
4
|
-
export { StoryGlobalsContext, StoryTrial, TrialFramesContext, TrialHost, useTrialFrame } from '../chunk-
|
|
5
|
-
import { labGlobals, withGlobals, followApp, storyConfig, GLOBALS_KEY, effectiveGlobals, labOptions, isGlobalsPath } from '../chunk-
|
|
6
|
-
import { loadStories, indexRenderOf } from '../chunk-
|
|
7
|
-
import '../chunk-
|
|
4
|
+
import { useTrialFrame, createTrialFrames, createTrialClocks, StoryGlobalsContext, TrialFramesContext, TrialClocksContext, StoryTrial, useCssOverrides, useTrialClock, TrialHost } from '../chunk-GHTVXHNJ.js';
|
|
5
|
+
export { StoryGlobalsContext, StoryTrial, TrialFramesContext, TrialHost, useTrialFrame } from '../chunk-GHTVXHNJ.js';
|
|
6
|
+
import { labGlobals, withGlobals, followApp, storyConfig, GLOBALS_KEY, effectiveGlobals, PLAYHEAD_KEY, labOptions, isGlobalsPath } from '../chunk-NI5FYQHW.js';
|
|
7
|
+
import { loadStories, indexRenderOf } from '../chunk-5N4YP5HS.js';
|
|
8
|
+
import '../chunk-L5XM5VKB.js';
|
|
8
9
|
import '../chunk-HRGPFQBW.js';
|
|
9
|
-
import
|
|
10
|
-
import {
|
|
10
|
+
import '../chunk-MGQWCPYE.js';
|
|
11
|
+
import { stableStringify, PORT_HANDOFF, FRAME_HELLO, PROTOCOL_VERSION } from '../chunk-KJGXJD3U.js';
|
|
12
|
+
import { useTrialId, Button, Lab, useLabContext, TrialIdContext, usePersistedState, Select, useTrialState, inferTokenType, ToggleBar as ToggleBar$1, Input, TokenPanel, refitScale } from '@weasel-js/labkit';
|
|
11
13
|
import num from '@weasel-js/theme/numeric.module.css';
|
|
12
|
-
import { createContext, useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect, useId, useContext } from 'react';
|
|
14
|
+
import { createContext, useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect, useId, useContext, useSyncExternalStore } from 'react';
|
|
13
15
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
14
16
|
import { createRoot } from 'react-dom/client';
|
|
15
|
-
import { InfoIcon, ToggleBar, Checkbox, Dialog, DisclosureMark, Button as Button$1, TuneIcon, Callout } from '@weasel-js/ui';
|
|
17
|
+
import { InfoIcon, ToggleBar, Checkbox, Dialog, DisclosureMark, Button as Button$1, TuneIcon, Callout, Slider, Transport } from '@weasel-js/ui';
|
|
16
18
|
import { TOKEN_MANIFEST, THEME_SOURCES, isByAxis } from '@weasel-js/theme';
|
|
17
19
|
import { scale, httpThemeApi } from '@weasel-js/theme/engine';
|
|
18
20
|
import { f, valueAtPath, isConfigBranch } from '@weasel-js/labkit/config';
|
|
@@ -625,6 +627,120 @@ function createFramePool(frameUrl, size = 2) {
|
|
|
625
627
|
};
|
|
626
628
|
}
|
|
627
629
|
var FramePoolContext = createContext(null);
|
|
630
|
+
|
|
631
|
+
// src/shell/routedTrial.ts
|
|
632
|
+
function routedTrial(trials, focusedTrialId, route) {
|
|
633
|
+
return trials.find((t) => t.id === focusedTrialId && t.instrumentName === route) ?? trials.find((t) => t.instrumentName === route);
|
|
634
|
+
}
|
|
635
|
+
function readRoute() {
|
|
636
|
+
return parseRoute(location.hash).story;
|
|
637
|
+
}
|
|
638
|
+
function readRouteParams() {
|
|
639
|
+
return { ...parseRoute(location.hash).params };
|
|
640
|
+
}
|
|
641
|
+
function replaceRouteParams(update) {
|
|
642
|
+
const { story, params } = parseRoute(location.hash);
|
|
643
|
+
if (story === null) return;
|
|
644
|
+
const next = formatRoute({ story, params: update({ ...params }) });
|
|
645
|
+
if (next !== location.hash) history.replaceState(history.state, "", next);
|
|
646
|
+
}
|
|
647
|
+
function readRouteEntry() {
|
|
648
|
+
const state = history.state;
|
|
649
|
+
const entry = state?.forgeRoute;
|
|
650
|
+
return typeof entry?.step === "number" ? entry : null;
|
|
651
|
+
}
|
|
652
|
+
function crossesInPlace(from, to) {
|
|
653
|
+
if (!from || !to || from.step === to.step) return false;
|
|
654
|
+
return to.step < from.step ? from.inPlace : to.inPlace;
|
|
655
|
+
}
|
|
656
|
+
function stamp(entry, hash) {
|
|
657
|
+
history.replaceState({ ...history.state ?? {}, forgeRoute: entry }, "", hash);
|
|
658
|
+
}
|
|
659
|
+
function setRoute(id, options = {}) {
|
|
660
|
+
if (readRoute() === id) {
|
|
661
|
+
history.replaceState(history.state, "", formatRoute({ story: id, params: readRouteParams() }));
|
|
662
|
+
return;
|
|
663
|
+
}
|
|
664
|
+
const hash = formatRoute({ story: id, params: {} });
|
|
665
|
+
const from = readRouteEntry() ?? { step: 0, inPlace: false };
|
|
666
|
+
stamp(from, location.hash);
|
|
667
|
+
location.hash = hash;
|
|
668
|
+
stamp({ step: from.step + 1, inPlace: options.inPlace ?? false }, hash);
|
|
669
|
+
}
|
|
670
|
+
function useRoute() {
|
|
671
|
+
const [route, setCurrent] = useState(readRoute);
|
|
672
|
+
useEffect(() => {
|
|
673
|
+
const sync = () => setCurrent(readRoute());
|
|
674
|
+
window.addEventListener("hashchange", sync);
|
|
675
|
+
sync();
|
|
676
|
+
return () => window.removeEventListener("hashchange", sync);
|
|
677
|
+
}, []);
|
|
678
|
+
return [route, setRoute];
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
// src/timeline/playheadUrl.ts
|
|
682
|
+
function formatSeconds(ms) {
|
|
683
|
+
const rounded = Math.round(ms) / 1e3;
|
|
684
|
+
return String(rounded === 0 ? 0 : rounded);
|
|
685
|
+
}
|
|
686
|
+
function parseSeconds(text) {
|
|
687
|
+
if (text == null || !/^\s*-?(\d+\.?\d*|\.\d+)\s*$/.test(text)) return null;
|
|
688
|
+
return Math.round(Number(text) * 1e3);
|
|
689
|
+
}
|
|
690
|
+
function readPlayheadParam() {
|
|
691
|
+
return parseSeconds(readRouteParams()[PLAYHEAD_PARAM]);
|
|
692
|
+
}
|
|
693
|
+
function writePlayheadParam(ms) {
|
|
694
|
+
replaceRouteParams(
|
|
695
|
+
({ [PLAYHEAD_PARAM]: _held, ...rest }) => ms === null ? rest : { ...rest, [PLAYHEAD_PARAM]: formatSeconds(ms) }
|
|
696
|
+
);
|
|
697
|
+
}
|
|
698
|
+
function PlayheadSync({ trialId, route, applied }) {
|
|
699
|
+
const clock = useTrialClock(trialId);
|
|
700
|
+
useEffect(() => {
|
|
701
|
+
if (!clock) return;
|
|
702
|
+
const fromUrl = () => {
|
|
703
|
+
const t = readPlayheadParam();
|
|
704
|
+
if (t === null || t === clock.get().time) return;
|
|
705
|
+
clock.request(t);
|
|
706
|
+
};
|
|
707
|
+
let held;
|
|
708
|
+
const toUrl = () => {
|
|
709
|
+
if (clock.pending() !== null) return;
|
|
710
|
+
const { playing, time, span } = clock.get();
|
|
711
|
+
const next = playing || time === span.start ? null : time;
|
|
712
|
+
if (next === held) return;
|
|
713
|
+
held = next;
|
|
714
|
+
writePlayheadParam(next);
|
|
715
|
+
};
|
|
716
|
+
if (applied.current !== route) {
|
|
717
|
+
applied.current = route;
|
|
718
|
+
fromUrl();
|
|
719
|
+
}
|
|
720
|
+
toUrl();
|
|
721
|
+
const off = clock.subscribe(toUrl);
|
|
722
|
+
const onHashChange = () => {
|
|
723
|
+
if (readRoute() !== route) return;
|
|
724
|
+
held = void 0;
|
|
725
|
+
fromUrl();
|
|
726
|
+
toUrl();
|
|
727
|
+
};
|
|
728
|
+
window.addEventListener("hashchange", onHashChange);
|
|
729
|
+
return () => {
|
|
730
|
+
off();
|
|
731
|
+
window.removeEventListener("hashchange", onHashChange);
|
|
732
|
+
};
|
|
733
|
+
}, [clock, route, applied]);
|
|
734
|
+
return null;
|
|
735
|
+
}
|
|
736
|
+
function RoutePlayhead() {
|
|
737
|
+
const lab = useLabContext();
|
|
738
|
+
const [route] = useRoute();
|
|
739
|
+
const applied = useRef(null);
|
|
740
|
+
const trial = route === null ? void 0 : routedTrial(lab.trials, lab.focusedTrialId, route);
|
|
741
|
+
if (!trial || route === null) return null;
|
|
742
|
+
return /* @__PURE__ */ jsx(PlayheadSync, { trialId: trial.id, route, applied }, `${trial.id} ${route}`);
|
|
743
|
+
}
|
|
628
744
|
var RECORD = "fg-globals";
|
|
629
745
|
function useLabGlobals(declarations) {
|
|
630
746
|
const [stored, setStored] = usePersistedState(RECORD, null, { scope: "lab" });
|
|
@@ -706,6 +822,46 @@ function LabGlobals({
|
|
|
706
822
|
useEffect(() => onChange(resolved), [resolved, onChange]);
|
|
707
823
|
return null;
|
|
708
824
|
}
|
|
825
|
+
function KnobSync({ schema, config }) {
|
|
826
|
+
const { setConfig } = useTrialState();
|
|
827
|
+
const reading = useRef(true);
|
|
828
|
+
const [typed, setTyped] = useState(0);
|
|
829
|
+
useEffect(() => {
|
|
830
|
+
const onHashChange = () => {
|
|
831
|
+
reading.current = true;
|
|
832
|
+
setTyped((n) => n + 1);
|
|
833
|
+
};
|
|
834
|
+
window.addEventListener("hashchange", onHashChange);
|
|
835
|
+
return () => window.removeEventListener("hashchange", onHashChange);
|
|
836
|
+
}, []);
|
|
837
|
+
useEffect(() => {
|
|
838
|
+
if (reading.current) {
|
|
839
|
+
reading.current = false;
|
|
840
|
+
const knobs2 = paramsToKnobs(schema, readRouteParams());
|
|
841
|
+
let wrote = false;
|
|
842
|
+
for (const { path, leaf } of knobPaths(schema)) {
|
|
843
|
+
const target = path in knobs2 ? knobs2[path] : leaf.default;
|
|
844
|
+
const current = valueAtPath(config, path);
|
|
845
|
+
if (sameKnob(current === void 0 ? leaf.default : current, target)) continue;
|
|
846
|
+
setConfig(path, target);
|
|
847
|
+
wrote = true;
|
|
848
|
+
}
|
|
849
|
+
if (wrote) return;
|
|
850
|
+
}
|
|
851
|
+
const knobs = knobsToParams(schema, config);
|
|
852
|
+
replaceRouteParams((params) => ({ ...knobs, ...reservedParams(params) }));
|
|
853
|
+
}, [schema, config, setConfig, typed]);
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
function RouteKnobs({ instruments, isReady }) {
|
|
857
|
+
const lab = useLabContext();
|
|
858
|
+
const [route] = useRoute();
|
|
859
|
+
if (route === null || !isReady(route)) return null;
|
|
860
|
+
const trial = routedTrial(lab.trials, lab.focusedTrialId, route);
|
|
861
|
+
const schema = instruments.find((instrument) => instrument.name === route)?.config;
|
|
862
|
+
if (!trial || !schema) return null;
|
|
863
|
+
return /* @__PURE__ */ jsx(TrialIdContext.Provider, { value: trial.id, children: /* @__PURE__ */ jsx(KnobSync, { schema, config: trial.config }, `${trial.id} ${route}`) });
|
|
864
|
+
}
|
|
709
865
|
|
|
710
866
|
// src/shell/revealTrial.ts
|
|
711
867
|
var FLASH_MS = 600;
|
|
@@ -727,44 +883,6 @@ function revealTrial(trialId, root = document) {
|
|
|
727
883
|
);
|
|
728
884
|
return true;
|
|
729
885
|
}
|
|
730
|
-
function readRoute() {
|
|
731
|
-
const { hash } = location;
|
|
732
|
-
if (!hash.startsWith("#/")) return null;
|
|
733
|
-
return decodeURIComponent(hash.slice(2)) || null;
|
|
734
|
-
}
|
|
735
|
-
function readRouteEntry() {
|
|
736
|
-
const state = history.state;
|
|
737
|
-
const entry = state?.forgeRoute;
|
|
738
|
-
return typeof entry?.step === "number" ? entry : null;
|
|
739
|
-
}
|
|
740
|
-
function crossesInPlace(from, to) {
|
|
741
|
-
if (!from || !to || from.step === to.step) return false;
|
|
742
|
-
return to.step < from.step ? from.inPlace : to.inPlace;
|
|
743
|
-
}
|
|
744
|
-
function stamp(entry, hash) {
|
|
745
|
-
history.replaceState({ ...history.state ?? {}, forgeRoute: entry }, "", hash);
|
|
746
|
-
}
|
|
747
|
-
function setRoute(id, options = {}) {
|
|
748
|
-
const hash = `#/${encodeURIComponent(id)}`;
|
|
749
|
-
if (readRoute() === id) {
|
|
750
|
-
history.replaceState(history.state, "", hash);
|
|
751
|
-
return;
|
|
752
|
-
}
|
|
753
|
-
const from = readRouteEntry() ?? { step: 0, inPlace: false };
|
|
754
|
-
stamp(from, location.hash);
|
|
755
|
-
location.hash = hash;
|
|
756
|
-
stamp({ step: from.step + 1, inPlace: options.inPlace ?? false }, hash);
|
|
757
|
-
}
|
|
758
|
-
function useRoute() {
|
|
759
|
-
const [route, setCurrent] = useState(readRoute);
|
|
760
|
-
useEffect(() => {
|
|
761
|
-
const sync = () => setCurrent(readRoute());
|
|
762
|
-
window.addEventListener("hashchange", sync);
|
|
763
|
-
sync();
|
|
764
|
-
return () => window.removeEventListener("hashchange", sync);
|
|
765
|
-
}, []);
|
|
766
|
-
return [route, setRoute];
|
|
767
|
-
}
|
|
768
886
|
|
|
769
887
|
// src/shell/tree/buildTree.ts
|
|
770
888
|
function sortFolder(nodes) {
|
|
@@ -1212,6 +1330,44 @@ function createAnswerBook() {
|
|
|
1212
1330
|
}
|
|
1213
1331
|
};
|
|
1214
1332
|
}
|
|
1333
|
+
function TransportBar({ clock }) {
|
|
1334
|
+
const { time, playing, loop, rate, span } = useSyncExternalStore(clock.subscribe, clock.get);
|
|
1335
|
+
return /* @__PURE__ */ jsxs("div", { className: "fg-transport", children: [
|
|
1336
|
+
/* @__PURE__ */ jsx(
|
|
1337
|
+
Slider,
|
|
1338
|
+
{
|
|
1339
|
+
className: "fg-transport__scrub",
|
|
1340
|
+
ariaLabel: "Scrub",
|
|
1341
|
+
density: "slim",
|
|
1342
|
+
readoutPlacement: "none",
|
|
1343
|
+
min: span.start,
|
|
1344
|
+
max: span.end > span.start ? span.end : span.start + 1,
|
|
1345
|
+
thumbs: [{ value: time, valueText: `${formatSeconds(time)} seconds` }],
|
|
1346
|
+
onInput: ([thumb]) => {
|
|
1347
|
+
if (thumb) clock.seek(thumb.value);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
),
|
|
1351
|
+
/* @__PURE__ */ jsx(
|
|
1352
|
+
Transport,
|
|
1353
|
+
{
|
|
1354
|
+
paused: !playing,
|
|
1355
|
+
loop,
|
|
1356
|
+
rate,
|
|
1357
|
+
playhead: time,
|
|
1358
|
+
duration: span.end,
|
|
1359
|
+
onPlay: clock.play,
|
|
1360
|
+
onPause: clock.pause,
|
|
1361
|
+
onLoopChange: (next) => clock.setLoop(next !== false && next !== 0),
|
|
1362
|
+
onRateChange: clock.setRate
|
|
1363
|
+
}
|
|
1364
|
+
)
|
|
1365
|
+
] });
|
|
1366
|
+
}
|
|
1367
|
+
function TrialTransport({ trialId }) {
|
|
1368
|
+
const clock = useTrialClock(trialId);
|
|
1369
|
+
return clock ? /* @__PURE__ */ jsx(TransportBar, { clock }) : null;
|
|
1370
|
+
}
|
|
1215
1371
|
function IndexTrial({ bundle, setup, config }) {
|
|
1216
1372
|
const lab = useLabContext();
|
|
1217
1373
|
const trialId = useContext(TrialIdContext);
|
|
@@ -1243,10 +1399,14 @@ function IndexTrial({ bundle, setup, config }) {
|
|
|
1243
1399
|
};
|
|
1244
1400
|
return /* @__PURE__ */ jsx(TrialHost, { layout: "fullscreen", setup, config, children: render });
|
|
1245
1401
|
}
|
|
1402
|
+
function withPlayhead(schema) {
|
|
1403
|
+
return f.schema({ ...schema.nodes, [PLAYHEAD_KEY]: f.custom("forge-playhead", null).hidden() });
|
|
1404
|
+
}
|
|
1246
1405
|
function documentInstrument(options) {
|
|
1247
1406
|
const { entry, loaded, setup, globals = {} } = options;
|
|
1248
1407
|
const schema = loaded.kind === "story" ? loaded.story.config : f.schema({});
|
|
1249
|
-
const
|
|
1408
|
+
const timed = loaded.kind === "story" && loaded.story.timeline !== null;
|
|
1409
|
+
const config = withGlobals(timed ? withPlayhead(schema) : schema, globals);
|
|
1250
1410
|
const initialState = loaded.kind === "story" ? loaded.story.initialState : null;
|
|
1251
1411
|
return {
|
|
1252
1412
|
name: entry.id,
|
|
@@ -1254,8 +1414,9 @@ function documentInstrument(options) {
|
|
|
1254
1414
|
config,
|
|
1255
1415
|
defaultConfig: () => config.defaults(),
|
|
1256
1416
|
initialState: (c) => initialState?.(c) ?? null,
|
|
1257
|
-
render: (ctx) => loaded.kind === "story" ? /* @__PURE__ */ jsx(StoryTrial, { story: loaded.story, setup, ctx }) : /* @__PURE__ */ jsx(IndexTrial, { bundle: loaded.bundle, setup, config: ctx.config }),
|
|
1258
|
-
...loaded.kind === "story" && loaded.story.viewport ? { stage: { size: { width: loaded.story.viewport.width, height: loaded.story.viewport.height } } } : {}
|
|
1417
|
+
render: (ctx) => loaded.kind === "story" ? /* @__PURE__ */ jsx(StoryTrial, { story: loaded.story, setup, ctx }, loaded.story.id) : /* @__PURE__ */ jsx(IndexTrial, { bundle: loaded.bundle, setup, config: ctx.config }),
|
|
1418
|
+
...loaded.kind === "story" && loaded.story.viewport ? { stage: { size: { width: loaded.story.viewport.width, height: loaded.story.viewport.height } } } : {},
|
|
1419
|
+
...timed ? { chrome: [{ id: "fg-transport", region: "status", render: (c) => /* @__PURE__ */ jsx(TrialTransport, { trialId: c.trialId }) }] } : {}
|
|
1259
1420
|
};
|
|
1260
1421
|
}
|
|
1261
1422
|
function StoryLoad({ entry, load, fault }) {
|
|
@@ -1747,6 +1908,7 @@ function useStoryRegistry(index, options) {
|
|
|
1747
1908
|
return { instruments: cache.list, isReady, onReady, reload };
|
|
1748
1909
|
}
|
|
1749
1910
|
var NO_DECLARATIONS = {};
|
|
1911
|
+
var DEFAULT_TITLE = "weaselforge";
|
|
1750
1912
|
function initialStory(entries, fallback) {
|
|
1751
1913
|
const route = readRoute();
|
|
1752
1914
|
return route !== null && entries.some((entry) => entry.id === route) ? route : fallback;
|
|
@@ -1785,7 +1947,12 @@ function useInfoShortcut(open) {
|
|
|
1785
1947
|
}
|
|
1786
1948
|
function Workshop({ index, frameUrl, importers, setup, changes, config, stories = [], storageKey, storage, dependencies }) {
|
|
1787
1949
|
const declarations = config?.globals ?? NO_DECLARATIONS;
|
|
1950
|
+
const title = config?.title ?? DEFAULT_TITLE;
|
|
1951
|
+
useEffect(() => {
|
|
1952
|
+
document.title = title;
|
|
1953
|
+
}, [title]);
|
|
1788
1954
|
const [frames] = useState(createTrialFrames);
|
|
1955
|
+
const [clocks] = useState(createTrialClocks);
|
|
1789
1956
|
const [pool, setPool] = useState(null);
|
|
1790
1957
|
const framed = importers === void 0 || index.some((entry) => entry.isolate !== void 0);
|
|
1791
1958
|
useEffect(() => {
|
|
@@ -1823,12 +1990,12 @@ function Workshop({ index, frameUrl, importers, setup, changes, config, stories
|
|
|
1823
1990
|
region: "palette",
|
|
1824
1991
|
item: { icon: InfoIcon, label: "Info", shortcut: "\u2318I", onActivate: () => setInfoOpen(true) }
|
|
1825
1992
|
},
|
|
1826
|
-
CSS_VARS_SECTION,
|
|
1993
|
+
...config?.cssVars === false ? [] : [CSS_VARS_SECTION],
|
|
1827
1994
|
A11Y_SECTION,
|
|
1828
1995
|
...Object.keys(declarations).length > 0 ? [{ id: "fg-globals", region: "header", render: () => /* @__PURE__ */ jsx(GlobalsToolbar, { declarations }) }] : [],
|
|
1829
1996
|
...config?.labChrome ?? []
|
|
1830
1997
|
],
|
|
1831
|
-
[index, declarations, config?.labChrome]
|
|
1998
|
+
[index, declarations, config?.cssVars, config?.labChrome]
|
|
1832
1999
|
);
|
|
1833
2000
|
const first = index[0];
|
|
1834
2001
|
if (!first) {
|
|
@@ -1837,10 +2004,10 @@ function Workshop({ index, frameUrl, importers, setup, changes, config, stories
|
|
|
1837
2004
|
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
|
|
1838
2005
|
] });
|
|
1839
2006
|
}
|
|
1840
|
-
return /* @__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__ */ jsxs(
|
|
2007
|
+
return /* @__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(
|
|
1841
2008
|
Lab,
|
|
1842
2009
|
{
|
|
1843
|
-
title
|
|
2010
|
+
title,
|
|
1844
2011
|
density: "roomy",
|
|
1845
2012
|
...labTheme ? { theme: labTheme } : {},
|
|
1846
2013
|
instruments: registry.instruments,
|
|
@@ -1854,6 +2021,8 @@ function Workshop({ index, frameUrl, importers, setup, changes, config, stories
|
|
|
1854
2021
|
...config?.path !== void 0 ? { path: config.path } : {},
|
|
1855
2022
|
children: [
|
|
1856
2023
|
/* @__PURE__ */ jsx(RouteOpener, { index: entries }),
|
|
2024
|
+
/* @__PURE__ */ jsx(RouteKnobs, { instruments: registry.instruments, isReady: registry.isReady }),
|
|
2025
|
+
/* @__PURE__ */ jsx(RoutePlayhead, {}),
|
|
1857
2026
|
/* @__PURE__ */ jsx(
|
|
1858
2027
|
StoryInfoDialog,
|
|
1859
2028
|
{
|
|
@@ -1866,7 +2035,7 @@ function Workshop({ index, frameUrl, importers, setup, changes, config, stories
|
|
|
1866
2035
|
/* @__PURE__ */ jsx(LabGlobals, { declarations, onChange: reportLabValues })
|
|
1867
2036
|
]
|
|
1868
2037
|
}
|
|
1869
|
-
) }) }) }) });
|
|
2038
|
+
) }) }) }) }) });
|
|
1870
2039
|
}
|
|
1871
2040
|
function mountWorkshop({ container, ...props }) {
|
|
1872
2041
|
const target = container ?? document.getElementById("root");
|