@weasel-js/forge 1.9.1 → 1.9.2
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/dist/{chunk-QN3HJQXZ.js → chunk-BGOHALHO.js} +3 -3
- package/dist/{chunk-QN3HJQXZ.js.map → chunk-BGOHALHO.js.map} +1 -1
- package/dist/{chunk-NI5FYQHW.js → chunk-GZPQMGXJ.js} +2 -2
- package/dist/chunk-GZPQMGXJ.js.map +1 -0
- package/dist/{config-jK7q7JuF.d.ts → config-BfsYw5lg.d.ts} +3 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/shell/index.css +97 -52
- package/dist/shell/index.css.map +1 -1
- package/dist/shell/index.d.ts +2 -1
- package/dist/shell/index.js +212 -34
- package/dist/shell/index.js.map +1 -1
- package/dist/test/index.js +2 -2
- package/package.json +5 -5
- package/dist/chunk-NI5FYQHW.js.map +0 -1
package/dist/shell/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { parseRoute, paramsToKnobs, knobPaths, sameKnob, knobsToParams, formatRoute, PLAYHEAD_PARAM, reservedParams } from '../chunk-CJX3W5HY.js';
|
|
2
2
|
import { isIndexId, indexId, libraryOf, indexEntries, schemaFromDescription, LibraryBadge, openChannel, IndexPage } from '../chunk-JVRHBI3V.js';
|
|
3
3
|
import { isGallery } from '../chunk-WEQSLPKT.js';
|
|
4
|
-
import { useTrialFrame, createTrialFrames, createTrialClocks, StoryGlobalsContext, TrialFramesContext, TrialClocksContext, StoryTrial, useCssOverrides, useNearViewport, IN_VIEW_MARGIN, useTrialClock, TrialHost } from '../chunk-
|
|
5
|
-
export { StoryGlobalsContext, StoryTrial, TrialFramesContext, TrialHost, useTrialFrame } from '../chunk-
|
|
6
|
-
import { labGlobals, withGlobals, followApp, storyConfig, GLOBALS_KEY, effectiveGlobals, PLAYHEAD_KEY, labOptions, isGlobalsPath } from '../chunk-
|
|
4
|
+
import { useTrialFrame, createTrialFrames, createTrialClocks, StoryGlobalsContext, TrialFramesContext, TrialClocksContext, StoryTrial, useCssOverrides, useNearViewport, IN_VIEW_MARGIN, useTrialClock, TrialHost } from '../chunk-BGOHALHO.js';
|
|
5
|
+
export { StoryGlobalsContext, StoryTrial, TrialFramesContext, TrialHost, useTrialFrame } from '../chunk-BGOHALHO.js';
|
|
6
|
+
import { labGlobals, withGlobals, followApp, storyConfig, GLOBALS_KEY, effectiveGlobals, PLAYHEAD_KEY, labOptions, isGlobalsPath } from '../chunk-GZPQMGXJ.js';
|
|
7
7
|
import { loadStories, indexRenderOf } from '../chunk-Q2EZXJFE.js';
|
|
8
8
|
import '../chunk-L5XM5VKB.js';
|
|
9
9
|
import '../chunk-HRGPFQBW.js';
|
|
@@ -11,10 +11,10 @@ import '../chunk-MGQWCPYE.js';
|
|
|
11
11
|
import { stableStringify, PORT_HANDOFF, FRAME_HELLO, PROTOCOL_VERSION } from '../chunk-KJGXJD3U.js';
|
|
12
12
|
import { useTrialId, Button, Lab, useLabContext, TrialIdContext, usePersistedState, Select, useTrialState, inferTokenType, ToggleBar as ToggleBar$1, Input, TokenPanel, refitScale } from '@weasel-js/labkit';
|
|
13
13
|
import num from '@weasel-js/theme/numeric.module.css';
|
|
14
|
-
import { createContext, useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect, useId, useContext, useSyncExternalStore } from 'react';
|
|
14
|
+
import { createContext, useState, useRef, useEffect, useCallback, useMemo, useLayoutEffect, useId, useContext, Fragment as Fragment$1, useSyncExternalStore } from 'react';
|
|
15
15
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
16
16
|
import { createRoot } from 'react-dom/client';
|
|
17
|
-
import { InfoIcon, ToggleBar, Checkbox, Dialog, DisclosureMark, Button as Button$1,
|
|
17
|
+
import { InfoIcon, ToggleBar, Checkbox, Dialog, TOKEN_CATEGORIES, Icon, DisclosureMark, Button as Button$1, Callout, Slider, Transport, SearchIcon } from '@weasel-js/ui';
|
|
18
18
|
import { TOKEN_MANIFEST, THEME_SOURCES, isByAxis } from '@weasel-js/theme';
|
|
19
19
|
import { scale, httpThemeApi } from '@weasel-js/theme/engine';
|
|
20
20
|
import { f, valueAtPath, isConfigBranch } from '@weasel-js/labkit/config';
|
|
@@ -100,14 +100,14 @@ var A11Y_SECTION = {
|
|
|
100
100
|
|
|
101
101
|
// src/shell/storyChanges.ts
|
|
102
102
|
function createStoryChanges() {
|
|
103
|
-
const
|
|
103
|
+
const listeners2 = /* @__PURE__ */ new Set();
|
|
104
104
|
return {
|
|
105
105
|
subscribe(listener) {
|
|
106
|
-
|
|
107
|
-
return () =>
|
|
106
|
+
listeners2.add(listener);
|
|
107
|
+
return () => listeners2.delete(listener);
|
|
108
108
|
},
|
|
109
109
|
emit(file) {
|
|
110
|
-
for (const listener of [...
|
|
110
|
+
for (const listener of [...listeners2]) listener(file);
|
|
111
111
|
}
|
|
112
112
|
};
|
|
113
113
|
}
|
|
@@ -221,6 +221,79 @@ function applyScaleEdits(definition, edits, selection) {
|
|
|
221
221
|
for (const [holder, byKey] of writes) for (const [key, value] of byKey) holder[key] = value;
|
|
222
222
|
return { ok: true, definition: root };
|
|
223
223
|
}
|
|
224
|
+
var ICONS = {
|
|
225
|
+
color: "drop",
|
|
226
|
+
type: "type",
|
|
227
|
+
size: "measure",
|
|
228
|
+
motion: "curveEaseInOut",
|
|
229
|
+
depth: "layers",
|
|
230
|
+
other: "more"
|
|
231
|
+
};
|
|
232
|
+
var PANEL = ".fg-css-vars";
|
|
233
|
+
var HOST = ".lk-sidebar-section, .lk-panel-tile";
|
|
234
|
+
var MANUAL = ["wheel", "touchmove", "keydown"];
|
|
235
|
+
function scrollerOf(el) {
|
|
236
|
+
for (let at = el.parentElement; at; at = at.parentElement) {
|
|
237
|
+
const { overflowY } = getComputedStyle(at);
|
|
238
|
+
if ((overflowY === "auto" || overflowY === "scroll") && at.scrollHeight > at.clientHeight) return at;
|
|
239
|
+
}
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
function readLine(panel) {
|
|
243
|
+
return panel.querySelector(".fg-css-vars__controls")?.getBoundingClientRect().bottom ?? panel.getBoundingClientRect().top;
|
|
244
|
+
}
|
|
245
|
+
function sectionsOf(panel) {
|
|
246
|
+
return [...panel.querySelectorAll("[data-token-category]")];
|
|
247
|
+
}
|
|
248
|
+
function SectionJump() {
|
|
249
|
+
const ref = useRef(null);
|
|
250
|
+
const [present, setPresent] = useState([]);
|
|
251
|
+
const [current, setCurrent] = useState(null);
|
|
252
|
+
const held = useRef(false);
|
|
253
|
+
useEffect(() => {
|
|
254
|
+
const root = ref.current?.closest(HOST) ?? document.body;
|
|
255
|
+
const read = () => {
|
|
256
|
+
const panel = root.querySelector(PANEL);
|
|
257
|
+
const sections = panel ? sectionsOf(panel) : [];
|
|
258
|
+
setPresent(sections.map((s) => s.dataset.tokenCategory));
|
|
259
|
+
if (!panel || held.current) return;
|
|
260
|
+
const line = readLine(panel) + 1;
|
|
261
|
+
let top = sections[0]?.dataset.tokenCategory;
|
|
262
|
+
for (const s of sections) if (s.getBoundingClientRect().top <= line) top = s.dataset.tokenCategory;
|
|
263
|
+
setCurrent(top ?? null);
|
|
264
|
+
};
|
|
265
|
+
const release = () => {
|
|
266
|
+
held.current = false;
|
|
267
|
+
};
|
|
268
|
+
read();
|
|
269
|
+
const observer = new MutationObserver(read);
|
|
270
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
271
|
+
document.addEventListener("scroll", read, { capture: true, passive: true });
|
|
272
|
+
for (const type of MANUAL) document.addEventListener(type, release, { capture: true, passive: true });
|
|
273
|
+
return () => {
|
|
274
|
+
observer.disconnect();
|
|
275
|
+
document.removeEventListener("scroll", read, { capture: true });
|
|
276
|
+
for (const type of MANUAL) document.removeEventListener(type, release, { capture: true });
|
|
277
|
+
};
|
|
278
|
+
}, []);
|
|
279
|
+
const items = TOKEN_CATEGORIES.map(({ id, title }) => ({
|
|
280
|
+
value: id,
|
|
281
|
+
label: /* @__PURE__ */ jsx(Icon, { name: ICONS[id], size: 14 }),
|
|
282
|
+
ariaLabel: title,
|
|
283
|
+
tooltip: title,
|
|
284
|
+
disabled: !present.includes(id)
|
|
285
|
+
}));
|
|
286
|
+
const jump = (next) => {
|
|
287
|
+
const panel = ref.current?.closest(HOST)?.querySelector(PANEL);
|
|
288
|
+
const target = next && panel?.querySelector(`[data-token-category="${next}"]`);
|
|
289
|
+
const scroller = panel && scrollerOf(panel);
|
|
290
|
+
if (!panel || !target || !scroller) return;
|
|
291
|
+
held.current = true;
|
|
292
|
+
setCurrent(next);
|
|
293
|
+
scroller.scrollTop += target.getBoundingClientRect().top - readLine(panel);
|
|
294
|
+
};
|
|
295
|
+
return /* @__PURE__ */ jsx("div", { ref, className: "fg-css-vars__jump", children: /* @__PURE__ */ jsx(ToggleBar, { ariaLabel: "Jump to section", variant: "flat", size: "sm", items, value: current, onChange: jump }) });
|
|
296
|
+
}
|
|
224
297
|
var TABS = [
|
|
225
298
|
{ value: "theme", label: "Theme" },
|
|
226
299
|
{ value: "story", label: "Story" }
|
|
@@ -391,19 +464,32 @@ function CssVarsPanel({ globals = NO_GLOBALS, themeApi } = {}) {
|
|
|
391
464
|
);
|
|
392
465
|
return /* @__PURE__ */ jsxs("div", { className: "fg-css-vars", children: [
|
|
393
466
|
/* @__PURE__ */ jsxs("div", { className: "fg-css-vars__controls", children: [
|
|
394
|
-
/* @__PURE__ */
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
467
|
+
/* @__PURE__ */ jsxs("div", { className: "fg-css-vars__bar", children: [
|
|
468
|
+
/* @__PURE__ */ jsx(
|
|
469
|
+
ToggleBar$1,
|
|
470
|
+
{
|
|
471
|
+
ariaLabel: "Variables",
|
|
472
|
+
variant: "flat",
|
|
473
|
+
size: "sm",
|
|
474
|
+
items: TABS,
|
|
475
|
+
value: tab,
|
|
476
|
+
onChange: (next) => {
|
|
477
|
+
if (next) setTab(next);
|
|
478
|
+
}
|
|
403
479
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
480
|
+
),
|
|
481
|
+
/* @__PURE__ */ jsx(
|
|
482
|
+
Input,
|
|
483
|
+
{
|
|
484
|
+
className: "fg-css-vars__filter",
|
|
485
|
+
"aria-label": "Filter",
|
|
486
|
+
placeholder: "Filter",
|
|
487
|
+
value: filter,
|
|
488
|
+
onChange: setFilter,
|
|
489
|
+
leadingAdornment: /* @__PURE__ */ jsx(SearchIcon, { size: 12 })
|
|
490
|
+
}
|
|
491
|
+
)
|
|
492
|
+
] }),
|
|
407
493
|
tab === "theme" && (unsaved.length > 0 || notice) ? /* @__PURE__ */ jsxs("div", { className: "fg-css-vars__save", children: [
|
|
408
494
|
unsaved.length > 0 ? /* @__PURE__ */ jsx(Button$1, { variant: "primary", size: "sm", loading: saving, disabled: saving, onClick: () => void save(), children: "Save scales to theme" }) : null,
|
|
409
495
|
notice ? /* @__PURE__ */ jsx(
|
|
@@ -420,6 +506,7 @@ function CssVarsPanel({ globals = NO_GLOBALS, themeApi } = {}) {
|
|
|
420
506
|
TokenPanel,
|
|
421
507
|
{
|
|
422
508
|
tokens: shown,
|
|
509
|
+
namePrefix: "--wzl-",
|
|
423
510
|
onChange: write,
|
|
424
511
|
scales,
|
|
425
512
|
onScaleChange,
|
|
@@ -444,13 +531,18 @@ function FocusedCssVars() {
|
|
|
444
531
|
var CSS_VARS_SECTION = {
|
|
445
532
|
id: "fg-css-vars",
|
|
446
533
|
region: "aside",
|
|
447
|
-
item: { title: "CSS Vars", body: /* @__PURE__ */ jsx(FocusedCssVars, {}) }
|
|
534
|
+
item: { title: "CSS Vars", actions: /* @__PURE__ */ jsx(SectionJump, {}), body: /* @__PURE__ */ jsx(FocusedCssVars, {}) }
|
|
448
535
|
};
|
|
449
536
|
|
|
450
537
|
// src/shell/breadcrumb.ts
|
|
538
|
+
function crumbs(title, name) {
|
|
539
|
+
const segments = title.split("/");
|
|
540
|
+
const steps = segments.map((label, i) => ({ label, path: segments.slice(0, i + 1).join("/") }));
|
|
541
|
+
steps.push({ label: name, path: null });
|
|
542
|
+
return steps.filter((step, i) => i === 0 || step.label.toLowerCase() !== "index");
|
|
543
|
+
}
|
|
451
544
|
function breadcrumb(title, name) {
|
|
452
|
-
|
|
453
|
-
return segments.join(" > ");
|
|
545
|
+
return crumbs(title, name).map((step) => step.label).join(" > ");
|
|
454
546
|
}
|
|
455
547
|
var GLOBALS = "$globals";
|
|
456
548
|
function leaves(shape, prefix = "") {
|
|
@@ -771,12 +863,23 @@ function GlobalsToolbar({ declarations }) {
|
|
|
771
863
|
top.map(([key, declaration]) => /* @__PURE__ */ jsx("div", { className: "fg-globals__item", children: /* @__PURE__ */ jsx(GlobalSelect, { name: key, declaration, values, set }) }, key)),
|
|
772
864
|
top.map(([key, declaration]) => {
|
|
773
865
|
const nested = entries.filter(([, other]) => other.under === key);
|
|
774
|
-
return nested.length > 0 ? /* @__PURE__ */ jsx(
|
|
866
|
+
return nested.length > 0 ? /* @__PURE__ */ jsx(
|
|
867
|
+
NestedGlobals,
|
|
868
|
+
{
|
|
869
|
+
label: declaration.label,
|
|
870
|
+
icon: declaration.icon ?? "tune",
|
|
871
|
+
nested,
|
|
872
|
+
values,
|
|
873
|
+
set
|
|
874
|
+
},
|
|
875
|
+
key
|
|
876
|
+
) : null;
|
|
775
877
|
})
|
|
776
878
|
] });
|
|
777
879
|
}
|
|
778
880
|
function NestedGlobals({
|
|
779
881
|
label,
|
|
882
|
+
icon,
|
|
780
883
|
nested,
|
|
781
884
|
values,
|
|
782
885
|
set
|
|
@@ -794,7 +897,7 @@ function NestedGlobals({
|
|
|
794
897
|
ariaLabel: `More ${label} settings`,
|
|
795
898
|
pressed: open,
|
|
796
899
|
onClick: () => setOpen((was) => !was),
|
|
797
|
-
children: /* @__PURE__ */ jsx(
|
|
900
|
+
children: /* @__PURE__ */ jsx(Icon, { name: icon, size: 16 })
|
|
798
901
|
}
|
|
799
902
|
),
|
|
800
903
|
/* @__PURE__ */ jsx(
|
|
@@ -884,6 +987,18 @@ function revealTrial(trialId, root = document) {
|
|
|
884
987
|
return true;
|
|
885
988
|
}
|
|
886
989
|
|
|
990
|
+
// src/shell/treeReveal.ts
|
|
991
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
992
|
+
function revealInTree(path) {
|
|
993
|
+
for (const listener of listeners) listener(path);
|
|
994
|
+
}
|
|
995
|
+
function onRevealInTree(listener) {
|
|
996
|
+
listeners.add(listener);
|
|
997
|
+
return () => {
|
|
998
|
+
listeners.delete(listener);
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
|
|
887
1002
|
// src/shell/tree/buildTree.ts
|
|
888
1003
|
function sortFolder(nodes) {
|
|
889
1004
|
const folders = nodes.filter((n) => n.kind === "folder");
|
|
@@ -1124,6 +1239,43 @@ function StoryTree({ ctx, index }) {
|
|
|
1124
1239
|
}
|
|
1125
1240
|
activate(node.index, another);
|
|
1126
1241
|
};
|
|
1242
|
+
const scrollTo = useRef(null);
|
|
1243
|
+
const reveal = (path) => {
|
|
1244
|
+
const find = (nodes, at) => {
|
|
1245
|
+
for (const node2 of nodes) {
|
|
1246
|
+
if (node2.kind !== "folder") continue;
|
|
1247
|
+
if (node2.path === at) return node2;
|
|
1248
|
+
const inner = find(node2.children, at);
|
|
1249
|
+
if (inner) return inner;
|
|
1250
|
+
}
|
|
1251
|
+
return void 0;
|
|
1252
|
+
};
|
|
1253
|
+
const nodesOf = (v) => v === "tree" ? tree : componentNodes(v === "gallery" ? galleries : components);
|
|
1254
|
+
const order = [view, ...VIEWS.map((item) => item.value).filter((v) => v !== view && enabled(v))];
|
|
1255
|
+
let node;
|
|
1256
|
+
let where = view;
|
|
1257
|
+
for (let at = path; at && !node; at = at.includes("/") ? at.slice(0, at.lastIndexOf("/")) : "") {
|
|
1258
|
+
for (const v of order) {
|
|
1259
|
+
node = find(nodesOf(v), at);
|
|
1260
|
+
if (node) {
|
|
1261
|
+
where = v;
|
|
1262
|
+
break;
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
}
|
|
1266
|
+
const found = node;
|
|
1267
|
+
if (!found) return;
|
|
1268
|
+
if (where !== view) setView(where);
|
|
1269
|
+
setQuery("");
|
|
1270
|
+
const segments = found.path.split("/");
|
|
1271
|
+
const above = segments.slice(0, -1).map((_, i) => segments.slice(0, i + 1).join("/"));
|
|
1272
|
+
setFolds((prev) => ({ ...prev, ...Object.fromEntries(above.map((p) => [p, true])) }));
|
|
1273
|
+
setFocusKey(keyOf(found));
|
|
1274
|
+
scrollTo.current = keyOf(found);
|
|
1275
|
+
if (found.index) openFolder(found, false);
|
|
1276
|
+
else setFolds((prev) => ({ ...prev, [found.path]: true }));
|
|
1277
|
+
};
|
|
1278
|
+
useEffect(() => onRevealInTree(reveal));
|
|
1127
1279
|
const onKeyDown = (event) => {
|
|
1128
1280
|
const at = rows.findIndex((row2) => row2.key === active);
|
|
1129
1281
|
const row = rows[at];
|
|
@@ -1170,6 +1322,10 @@ function StoryTree({ ctx, index }) {
|
|
|
1170
1322
|
ref: (el) => {
|
|
1171
1323
|
if (el) items.current.set(key, el);
|
|
1172
1324
|
else items.current.delete(key);
|
|
1325
|
+
if (el && scrollTo.current === key) {
|
|
1326
|
+
scrollTo.current = null;
|
|
1327
|
+
el.scrollIntoView({ block: "nearest" });
|
|
1328
|
+
}
|
|
1173
1329
|
},
|
|
1174
1330
|
// A folder item contains its children, so their focus bubbles through it.
|
|
1175
1331
|
onFocus: (event) => {
|
|
@@ -1254,6 +1410,7 @@ function StoryTree({ ctx, index }) {
|
|
|
1254
1410
|
{
|
|
1255
1411
|
ariaLabel: "Sidebar view",
|
|
1256
1412
|
variant: "flat",
|
|
1413
|
+
size: "sm",
|
|
1257
1414
|
items: views,
|
|
1258
1415
|
value: view,
|
|
1259
1416
|
onChange: (next) => {
|
|
@@ -1268,7 +1425,7 @@ function StoryTree({ ctx, index }) {
|
|
|
1268
1425
|
{
|
|
1269
1426
|
isSelected: !hidden[library],
|
|
1270
1427
|
onChange: (on) => setHidden((prev) => ({ ...prev, [library]: !on })),
|
|
1271
|
-
children: /* @__PURE__ */ jsx(LibraryBadge2, { library })
|
|
1428
|
+
children: /* @__PURE__ */ jsx("span", { className: "fg-tree__library", children: /* @__PURE__ */ jsx(LibraryBadge2, { library }) })
|
|
1272
1429
|
},
|
|
1273
1430
|
library
|
|
1274
1431
|
))
|
|
@@ -1292,7 +1449,7 @@ var KEPT_CONFIGS = 50;
|
|
|
1292
1449
|
var UNANSWERED = stableStringify({ hidden: [], errors: {} });
|
|
1293
1450
|
function createAnswerBook() {
|
|
1294
1451
|
const byConfig = /* @__PURE__ */ new Map();
|
|
1295
|
-
const
|
|
1452
|
+
const listeners2 = /* @__PURE__ */ new Set();
|
|
1296
1453
|
const held = /* @__PURE__ */ new Map();
|
|
1297
1454
|
const keyOf2 = (config) => stableStringify(storyConfig(config));
|
|
1298
1455
|
const answerFor = (config) => byConfig.get(keyOf2(config));
|
|
@@ -1306,7 +1463,7 @@ function createAnswerBook() {
|
|
|
1306
1463
|
const oldest = byConfig.keys().next().value;
|
|
1307
1464
|
if (oldest !== void 0) byConfig.delete(oldest);
|
|
1308
1465
|
}
|
|
1309
|
-
if (changed && held.has(answers.configKey)) for (const fn of
|
|
1466
|
+
if (changed && held.has(answers.configKey)) for (const fn of listeners2) fn();
|
|
1310
1467
|
},
|
|
1311
1468
|
hold(config) {
|
|
1312
1469
|
const key = keyOf2(config);
|
|
@@ -1323,9 +1480,9 @@ function createAnswerBook() {
|
|
|
1323
1480
|
},
|
|
1324
1481
|
errors: (path, config) => answerFor(config)?.errors[path] ?? [],
|
|
1325
1482
|
subscribe(fn) {
|
|
1326
|
-
|
|
1483
|
+
listeners2.add(fn);
|
|
1327
1484
|
return () => {
|
|
1328
|
-
|
|
1485
|
+
listeners2.delete(fn);
|
|
1329
1486
|
};
|
|
1330
1487
|
}
|
|
1331
1488
|
};
|
|
@@ -1368,6 +1525,27 @@ function TrialTransport({ trialId }) {
|
|
|
1368
1525
|
const clock = useTrialClock(trialId);
|
|
1369
1526
|
return clock ? /* @__PURE__ */ jsx(TransportBar, { clock }) : null;
|
|
1370
1527
|
}
|
|
1528
|
+
function Crumbs({ entry }) {
|
|
1529
|
+
const steps = crumbs(entry.title, entry.name);
|
|
1530
|
+
return /* @__PURE__ */ jsx("span", { className: "fg-crumbs", children: steps.map((step, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1531
|
+
i > 0 ? /* @__PURE__ */ jsx("span", { className: "fg-crumbs__sep", "aria-hidden": "true", children: "\u203A" }) : null,
|
|
1532
|
+
step.path === null ? /* @__PURE__ */ jsx("span", { className: "fg-crumbs__here", children: step.label }) : /* @__PURE__ */ jsx(
|
|
1533
|
+
"button",
|
|
1534
|
+
{
|
|
1535
|
+
type: "button",
|
|
1536
|
+
className: "fg-crumbs__step",
|
|
1537
|
+
title: `Show ${step.label} in the story tree`,
|
|
1538
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
1539
|
+
onClick: () => revealInTree(step.path),
|
|
1540
|
+
children: step.label
|
|
1541
|
+
}
|
|
1542
|
+
)
|
|
1543
|
+
] }, step.path ?? `${step.label}:${i}`)) });
|
|
1544
|
+
}
|
|
1545
|
+
function crumbTitle(entry) {
|
|
1546
|
+
const title = breadcrumb(entry.title, entry.name);
|
|
1547
|
+
return { title, renderTitle: (shown) => shown === title ? /* @__PURE__ */ jsx(Crumbs, { entry }) : shown };
|
|
1548
|
+
}
|
|
1371
1549
|
function IndexTrial({ bundle, setup, config }) {
|
|
1372
1550
|
const lab = useLabContext();
|
|
1373
1551
|
const trialId = useContext(TrialIdContext);
|
|
@@ -1410,7 +1588,7 @@ function documentInstrument(options) {
|
|
|
1410
1588
|
const initialState = loaded.kind === "story" ? loaded.story.initialState : null;
|
|
1411
1589
|
return {
|
|
1412
1590
|
name: entry.id,
|
|
1413
|
-
|
|
1591
|
+
...crumbTitle(entry),
|
|
1414
1592
|
config,
|
|
1415
1593
|
defaultConfig: () => config.defaults(),
|
|
1416
1594
|
initialState: (c) => initialState?.(c) ?? null,
|
|
@@ -1433,7 +1611,7 @@ function pendingInstrument(options) {
|
|
|
1433
1611
|
const config = withGlobals(f.schema({}), globals);
|
|
1434
1612
|
return {
|
|
1435
1613
|
name: entry.id,
|
|
1436
|
-
|
|
1614
|
+
...crumbTitle(entry),
|
|
1437
1615
|
config,
|
|
1438
1616
|
defaultConfig: () => config.defaults(),
|
|
1439
1617
|
initialState: () => null,
|
|
@@ -1711,7 +1889,7 @@ function storyInstrument(options) {
|
|
|
1711
1889
|
const viewport = ready ? ready.viewport : entry.viewport;
|
|
1712
1890
|
return {
|
|
1713
1891
|
name: entry.id,
|
|
1714
|
-
|
|
1892
|
+
...crumbTitle(entry),
|
|
1715
1893
|
config,
|
|
1716
1894
|
defaultConfig: () => config.defaults(),
|
|
1717
1895
|
initialState: () => null,
|