@weasel-js/forge 1.12.0 → 1.13.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.
Files changed (46) hide show
  1. package/README.md +20 -5
  2. package/dist/{FrameController-CdnaIo4C.d.ts → FrameController-DgfVaENb.d.ts} +15 -3
  3. package/dist/{chunk-GH5RE5X5.js → chunk-2ZBZRBHI.js} +2 -2
  4. package/dist/{chunk-GH5RE5X5.js.map → chunk-2ZBZRBHI.js.map} +1 -1
  5. package/dist/{chunk-KEQBGDUZ.js → chunk-7XJNVJB5.js} +3 -3
  6. package/dist/{chunk-KEQBGDUZ.js.map → chunk-7XJNVJB5.js.map} +1 -1
  7. package/dist/{chunk-LTTEILXY.js → chunk-COT4I347.js} +3 -3
  8. package/dist/{chunk-LTTEILXY.js.map → chunk-COT4I347.js.map} +1 -1
  9. package/dist/{chunk-WMGEO5M6.js → chunk-GHPMNT2A.js} +83 -13
  10. package/dist/chunk-GHPMNT2A.js.map +1 -0
  11. package/dist/chunk-RVJHUY7W.js +60 -0
  12. package/dist/chunk-RVJHUY7W.js.map +1 -0
  13. package/dist/chunk-VUPN73JP.js +16 -0
  14. package/dist/chunk-VUPN73JP.js.map +1 -0
  15. package/dist/{chunk-ATI7FYJ7.js → chunk-WFT5IOHX.js} +98 -63
  16. package/dist/chunk-WFT5IOHX.js.map +1 -0
  17. package/dist/{chunk-YDLRSEUN.js → chunk-XIBKYSRU.js} +5 -4
  18. package/dist/chunk-XIBKYSRU.js.map +1 -0
  19. package/dist/{config-Mg05Ja9r.d.ts → config-6fWf87Tt.d.ts} +3 -21
  20. package/dist/csf/preview-api.js +2 -2
  21. package/dist/frame/index.css +26 -0
  22. package/dist/frame/index.css.map +1 -1
  23. package/dist/frame/index.d.ts +14 -8
  24. package/dist/frame/index.js +109 -75
  25. package/dist/frame/index.js.map +1 -1
  26. package/dist/index.d.ts +29 -5
  27. package/dist/index.js +3 -3
  28. package/dist/library-CdTj-hFp.d.ts +21 -0
  29. package/dist/{mountFrame-Ds3QLnBF.d.ts → mountFrame-Bs7u1ro-.d.ts} +1 -1
  30. package/dist/shell/index.css +33 -5
  31. package/dist/shell/index.css.map +1 -1
  32. package/dist/shell/index.d.ts +6 -5
  33. package/dist/shell/index.js +190 -108
  34. package/dist/shell/index.js.map +1 -1
  35. package/dist/test/index.css +2 -3
  36. package/dist/test/index.css.map +1 -1
  37. package/dist/test/index.d.ts +1 -1
  38. package/dist/test/index.js +4 -4
  39. package/dist/vite/index.js +78 -16
  40. package/dist/vite/index.js.map +1 -1
  41. package/package.json +9 -9
  42. package/dist/chunk-ATI7FYJ7.js.map +0 -1
  43. package/dist/chunk-WEQSLPKT.js +0 -9
  44. package/dist/chunk-WEQSLPKT.js.map +0 -1
  45. package/dist/chunk-WMGEO5M6.js.map +0 -1
  46. package/dist/chunk-YDLRSEUN.js.map +0 -1
@@ -1,19 +1,43 @@
1
- import { describeSchema, createKitRoot, openChannel, isIndexId, TITLE_LIBRARIES, indexId, LAB_DENSITY, answerSchema, IndexPage } from '../chunk-ATI7FYJ7.js';
2
- import { isGallery } from '../chunk-WEQSLPKT.js';
3
- import { createOverrides, createGlobalsTarget, createA11yHighlighter, loadStories, indexRenderOf, scanCssVars, auditElement, runAxe, useHostConditions, useStoryClock, StoryHost, resolveCssVar } from '../chunk-WMGEO5M6.js';
1
+ import { describeSchema, createKitRoot, openChannel, loadIndexBundle, librariesFrom, LibrariesContext, IndexPage, indexEnvOf, LAB_DENSITY, answerSchema } from '../chunk-WFT5IOHX.js';
2
+ import { isIndexId, indexId } from '../chunk-RVJHUY7W.js';
3
+ import '../chunk-VUPN73JP.js';
4
+ import { createOverrides, createGlobalsTarget, createA11yHighlighter, loadStories, scanCssVars, auditElement, runAxe, useHostConditions, StoryHost, useStoryClock, resolveCssVar } from '../chunk-GHPMNT2A.js';
4
5
  import { ClockContext } from '../chunk-L5XM5VKB.js';
5
6
  import '../chunk-5WS67HMU.js';
6
- import '../chunk-KEQBGDUZ.js';
7
- import { FRAME_HELLO, stableStringify, PORT_HANDOFF } from '../chunk-GH5RE5X5.js';
7
+ import '../chunk-7XJNVJB5.js';
8
+ import { FRAME_HELLO, stableStringify, PORT_HANDOFF } from '../chunk-2ZBZRBHI.js';
8
9
  import { flushSync } from 'react-dom';
9
10
  import { jsx } from 'react/jsx-runtime';
10
11
  import { f } from '@weasel-js/labkit/config';
11
- import { Component, useState, useMemo, useLayoutEffect, useRef, useEffect } from 'react';
12
+ import { Component, useState, useLayoutEffect, useRef, useEffect, useMemo } from 'react';
12
13
  import { useLatest, useVisibleRaf } from '@weasel-js/core';
13
14
  import { interstellarTheme, LabRoot } from '@weasel-js/labkit';
14
15
  import { ThemeProvider } from '@weasel-js/theme/react';
15
16
  import { OverlayPortalProvider } from '@weasel-js/ui/portal-host';
16
17
 
18
+ // src/frame/documentScroll.ts
19
+ function followDocumentScroll(doc, send) {
20
+ const scroller = doc.scrollingElement ?? doc.documentElement;
21
+ const view = doc.defaultView;
22
+ let reported = null;
23
+ const report = () => {
24
+ const left = scroller.scrollLeft;
25
+ const top = scroller.scrollTop;
26
+ const key = `${left} ${top}`;
27
+ if (key === reported) return;
28
+ reported = key;
29
+ send({ type: "scroll", left, top });
30
+ };
31
+ report();
32
+ view?.addEventListener("scroll", report, { passive: true });
33
+ return {
34
+ apply({ left, top }) {
35
+ scroller.scrollLeft = left;
36
+ scroller.scrollTop = top;
37
+ },
38
+ dispose: () => view?.removeEventListener("scroll", report)
39
+ };
40
+ }
17
41
  var VARS_SETTLE_MS = 100;
18
42
  function fault(phase, error, seq) {
19
43
  return {
@@ -24,6 +48,15 @@ function fault(phase, error, seq) {
24
48
  ...seq === void 0 ? {} : { seq }
25
49
  };
26
50
  }
51
+ function announceRendered(send) {
52
+ const { fonts } = document;
53
+ if (!fonts) {
54
+ send({ type: "rendered" });
55
+ return;
56
+ }
57
+ const afterPaint = () => requestAnimationFrame(() => send({ type: "rendered" }));
58
+ void fonts.ready.then(afterPaint, afterPaint);
59
+ }
27
60
  function startFrame({ story, channel, container, setup = {} }) {
28
61
  const { send } = channel;
29
62
  send({ type: "ready", schema: describeSchema(story.config), layout: story.layout, viewport: story.viewport });
@@ -101,19 +134,11 @@ function startFrame({ story, channel, container, setup = {} }) {
101
134
  }
102
135
  if (!rendered) {
103
136
  rendered = true;
104
- announceRendered();
137
+ announceRendered(send);
105
138
  }
106
139
  reportVars();
107
140
  };
108
- const announceRendered = () => {
109
- const { fonts } = document;
110
- if (!fonts) {
111
- send({ type: "rendered" });
112
- return;
113
- }
114
- const afterPaint = () => requestAnimationFrame(() => send({ type: "rendered" }));
115
- void fonts.ready.then(afterPaint, afterPaint);
116
- };
141
+ const scroll = followDocumentScroll(document, send);
117
142
  const audit = async (id) => send({ type: "a11y", id, ...await auditElement(wrapper) });
118
143
  const off = channel.on((msg) => {
119
144
  switch (msg.type) {
@@ -161,10 +186,14 @@ function startFrame({ story, channel, container, setup = {} }) {
161
186
  case "a11y.highlight":
162
187
  highlighter.show(msg.targets);
163
188
  break;
189
+ case "scroll":
190
+ scroll.apply(msg);
191
+ break;
164
192
  }
165
193
  });
166
194
  return () => {
167
195
  off();
196
+ scroll.dispose();
168
197
  mutations?.disconnect();
169
198
  clearTimeout(settleTimer);
170
199
  overrides.dispose();
@@ -203,22 +232,14 @@ function startIndex(options) {
203
232
  let announced = false;
204
233
  const render = () => {
205
234
  if (!globals) return;
206
- const env = {
207
- title: options.title,
208
- ...options.library === void 0 ? {} : { library: options.library },
209
- ...options.description === void 0 ? {} : { description: options.description },
210
- stories: options.stories,
211
- descriptions: options.descriptions,
212
- gallery: options.gallery ?? false,
213
- galleries: options.galleries ?? [],
235
+ const env = indexEnvOf(options.bundle, {
236
+ graph: null,
214
237
  globals,
215
238
  decorators: setup.decorators ?? [],
216
- open: (id) => send({ type: "open", id }),
217
- // A story that throws shows its error in its own cell; the rest of the page is still worth reading.
218
- onError: (error) => console.error(error)
219
- };
239
+ open: (id) => send({ type: "open", id })
240
+ });
220
241
  root.render(
221
- /* @__PURE__ */ jsx(PageBoundary, { onError: (error) => send({ type: "fault", phase: "render", message: message(error) }), children: /* @__PURE__ */ jsx(IndexPage, { env, render: options.render }) })
242
+ /* @__PURE__ */ jsx(PageBoundary, { onError: (error) => send({ type: "fault", phase: "render", message: message(error) }), children: /* @__PURE__ */ jsx(IndexPage, { env, render: options.bundle.render }) })
222
243
  );
223
244
  };
224
245
  const announce = () => {
@@ -297,33 +318,10 @@ async function mountFrame(options) {
297
318
  const container = document.getElementById("root") ?? document.body;
298
319
  try {
299
320
  if (isIndexId(id)) {
300
- const entries = entriesOf(id);
301
- const title = entries[0]?.title;
302
- if (title === void 0) throw new Error(`No component with index "${id}"`);
303
- const files = [...new Set(entries.map((e) => e.file))];
304
- const mods = await Promise.all(files.map(importOf));
305
- const loaded = files.map((file, i) => ({
306
- file,
307
- stories: (options.load ?? loadStories)(mods[i] ?? {}, title, options.setup?.parameters)
308
- }));
309
- const stories2 = entries.flatMap(
310
- (e) => loaded.find((l) => l.file === e.file)?.stories.find((s) => s.exportName === e.exportName) ?? []
311
- );
312
- for (const story2 of stories2) await options.setup?.prepare?.(story2);
313
- startIndex({
314
- title,
315
- ...entries[0]?.componentDescription === void 0 ? {} : { description: entries[0].componentDescription },
316
- // The project's library table is the shell config's, which a frame document does not load.
317
- library: TITLE_LIBRARIES.of({ file: entries[0]?.file ?? "", title }),
318
- gallery: entries.every(isGallery),
319
- galleries: entries.filter(isGallery).map((e) => e.id),
320
- stories: stories2,
321
- descriptions: Object.fromEntries(entries.flatMap((e) => e.description ? [[e.id, e.description]] : [])),
322
- render: mods.map(indexRenderOf).find((render) => render !== null) ?? null,
323
- channel,
324
- container,
325
- ...options.setup ? { setup: options.setup } : {}
326
- });
321
+ const { load, setup } = options;
322
+ const source = { index: options.index, importOf, load, parameters: setup?.parameters, prepare: setup?.prepare };
323
+ const bundle = await loadIndexBundle(id, source);
324
+ startIndex({ bundle, channel, container, ...setup ? { setup } : {} });
327
325
  return;
328
326
  }
329
327
  const entry = options.index.find((e) => e.id === id);
@@ -343,14 +341,12 @@ var NO_WRITE = () => {
343
341
  };
344
342
  var boxStyle = ({ width, height }) => ({ ["--fg-capture-w"]: `${width}px`, ["--fg-capture-h"]: `${height}px` });
345
343
  function scrollTo(host, { left, top }) {
346
- const scroller = host?.querySelector(":scope > .fg-story__scroll");
344
+ const scroller = host?.querySelector(":scope > .fg-story__scroll") ?? host;
347
345
  if (!scroller) return;
348
346
  scroller.scrollLeft = left;
349
347
  scroller.scrollTop = top;
350
348
  }
351
- function CaptureView({ story, payload, setup, labTheme, onRendered }) {
352
- const [host, setHost] = useState(null);
353
- useHostConditions(host, { hostId: HOST_ID, globals: payload.globals, overrides: payload.overrides, setup });
349
+ function CapturedStory({ story, payload, setup }) {
354
350
  const spec = useMemo(() => story.timeline?.(payload.config) ?? null, [story, payload.config]);
355
351
  const clock = useStoryClock(spec, () => payload.playhead);
356
352
  const state = useMemo(
@@ -366,6 +362,11 @@ function CaptureView({ story, payload, setup, labTheme, onRendered }) {
366
362
  title: story.title,
367
363
  name: story.name
368
364
  };
365
+ return /* @__PURE__ */ jsx(ClockContext.Provider, { value: clock, children: /* @__PURE__ */ jsx(StoryHost, { story, ctx, decorators: setup.decorators ?? [], resetKey: 0, onError: NO_WRITE }) });
366
+ }
367
+ function CaptureView({ subject, graph = null, payload, setup, labTheme, onRendered }) {
368
+ const [host, setHost] = useState(null);
369
+ useHostConditions(host, { hostId: HOST_ID, globals: payload.globals, overrides: payload.overrides, setup });
369
370
  const latest = useLatest({ onRendered, host, scroll: payload.scroll });
370
371
  useLayoutEffect(() => scrollTo(host, payload.scroll), [host, payload.scroll]);
371
372
  const ticks = useRef(0);
@@ -392,7 +393,13 @@ function CaptureView({ story, payload, setup, labTheme, onRendered }) {
392
393
  raf.cancel();
393
394
  };
394
395
  }, [host, raf]);
395
- const content = host ? /* @__PURE__ */ jsx(ClockContext.Provider, { value: clock, children: /* @__PURE__ */ jsx(StoryHost, { story, ctx, decorators: setup.decorators ?? [], resetKey: 0, onError: NO_WRITE }) }) : null;
396
+ const content = !host ? null : subject.kind === "story" ? /* @__PURE__ */ jsx(CapturedStory, { story: subject.story, payload, setup }) : /* @__PURE__ */ jsx(
397
+ IndexPage,
398
+ {
399
+ env: indexEnvOf(subject.bundle, { graph, globals: payload.globals, decorators: setup.decorators ?? [], open: NO_WRITE }),
400
+ render: subject.bundle.render
401
+ }
402
+ );
396
403
  const box = /* @__PURE__ */ jsx(
397
404
  "div",
398
405
  {
@@ -427,36 +434,63 @@ var CaptureBoundary = class extends Component {
427
434
  return this.state.failed ? null : this.props.children;
428
435
  }
429
436
  };
430
- function mountCapture({ index, importers, setup, labTheme }) {
437
+ function mountCapture(options) {
438
+ const { index, importers, setup, labTheme } = options;
439
+ const libraries = librariesFrom(options.libraries);
431
440
  const container = document.getElementById("root") ?? document.body;
432
441
  const root = createKitRoot(container, setup.icons);
433
442
  const prepared = /* @__PURE__ */ new Map();
443
+ let graph = null;
434
444
  let renders = 0;
435
- const storyOf = (id) => {
445
+ const importOf = (file) => {
446
+ const importer = importers[file];
447
+ return importer ? importer() : Promise.reject(new Error(`No importer for ${file}`));
448
+ };
449
+ const loadStory = async (id) => {
450
+ const entry = index.find((e) => e.id === id);
451
+ if (!entry) throw new Error(`No story with id "${id}"`);
452
+ const story = loadStories(await importOf(entry.file), entry.title, setup.parameters).find(
453
+ (s) => s.exportName === entry.exportName
454
+ );
455
+ if (!story) throw new Error(`${entry.file} has no story export "${entry.exportName}"`);
456
+ await setup.prepare?.(story);
457
+ return { kind: "story", story };
458
+ };
459
+ const loadIndex = async (id) => {
460
+ const source = { index, importOf, parameters: setup.parameters, prepare: setup.prepare, libraries };
461
+ return { kind: "index", bundle: await loadIndexBundle(id, source) };
462
+ };
463
+ const subjectOf = (id) => {
436
464
  let loading = prepared.get(id);
437
465
  if (!loading) {
438
- loading = (async () => {
439
- const entry = index.find((e) => e.id === id);
440
- if (!entry) throw new Error(`No story with id "${id}"`);
441
- const importer = importers[entry.file];
442
- if (!importer) throw new Error(`No importer for ${entry.file}`);
443
- const story = loadStories(await importer(), entry.title, setup.parameters).find((s) => s.exportName === entry.exportName);
444
- if (!story) throw new Error(`${entry.file} has no story export "${entry.exportName}"`);
445
- await setup.prepare?.(story);
446
- return story;
447
- })();
466
+ loading = isIndexId(id) ? loadIndex(id) : loadStory(id);
448
467
  prepared.set(id, loading);
449
468
  loading.catch(() => prepared.delete(id));
450
469
  }
451
470
  return loading;
452
471
  };
472
+ const graphOf = () => {
473
+ graph ??= options.dependencies ? options.dependencies().catch(() => null) : Promise.resolve(null);
474
+ return graph;
475
+ };
453
476
  window.__forgeCapture = {
454
477
  async render(payload) {
455
- const story = await storyOf(payload.story);
478
+ const subject = await subjectOf(payload.story);
479
+ const deps = subject.kind === "index" ? await graphOf() : null;
456
480
  renders += 1;
457
481
  await new Promise((resolve, reject) => {
458
482
  root.render(
459
- /* @__PURE__ */ jsx(CaptureBoundary, { onError: reject, children: /* @__PURE__ */ jsx(CaptureView, { story, payload, setup, labTheme, onRendered: resolve }) }, renders)
483
+ /* @__PURE__ */ jsx(CaptureBoundary, { onError: reject, children: /* @__PURE__ */ jsx(LibrariesContext.Provider, { value: libraries, children: /* @__PURE__ */ jsx(
484
+ CaptureView,
485
+ {
486
+ subject,
487
+ graph: deps,
488
+ payload,
489
+ setup,
490
+ labTheme,
491
+ onRendered: resolve
492
+ }
493
+ ) }) }, renders)
460
494
  );
461
495
  });
462
496
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/frame/FrameController.tsx","../../src/frame/index/startIndex.tsx","../../src/frame/mountFrame.tsx","../../src/frame/capture/CaptureView.tsx","../../src/frame/capture/mountCapture.tsx"],"names":["jsx","flushSync","id","stories","story","Component"],"mappings":"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","file":"index.js","sourcesContent":["import { flushSync } from 'react-dom';\nimport type { IconTable } from '@weasel-js/icons';\nimport { createKitRoot } from '../kitIcons';\nimport type { Channel } from '../protocol/channel';\nimport {\n type CssVarReport,\n type FaultPhase,\n type FromFrame,\n type Globals,\n stableStringify,\n type ToFrame,\n} from '../protocol/messages';\nimport { answerSchema, describeSchema } from '../protocol/schema';\nimport type { Decorator, LoadedStory, StoryContext } from '../story/types';\nimport { auditElement } from './a11y';\nimport { createA11yHighlighter } from './a11yHighlight';\nimport { createOverrides, resolveCssVar, scanCssVars } from './cssVars';\nimport { createGlobalsTarget, type GlobalsTarget } from './globalsTarget';\nimport { StoryHost } from './StoryHost';\n\n/** The frame config: what `defineFrameConfig` returns and the `frameConfig` module default-exports. */\nexport interface FrameSetup {\n /** Wraps every story, outermost; receives the globals. From the frame config (`frameConfig`). */\n decorators?: Decorator[];\n /** Applies globals to a target: theme mode, fonts. The target is a frame document's root, or one story's host in\n * the workshop document, so a rule the setup writes goes through `target.style` under `target.scope`. */\n applyGlobals?: (globals: Globals, target: GlobalsTarget) => void;\n /**\n * The elements a CSS variable override is declared on; `:root` by default. An override has to be declared on\n * whichever element declares the token itself — a theme wrapper, say — or that element's own value wins.\n */\n cssVarsScope?: string;\n /** Project-wide CSF parameters, Storybook's preview `parameters`: under each meta's and story's. */\n parameters?: Record<string, unknown>;\n /**\n * Awaited once a story is loaded and before it first renders — the place to import what only some stories\n * need, so the rest never load it.\n */\n prepare?: (story: LoadedStory) => void | Promise<void>;\n /** Icon tables registered beside the kit's in every frame: an app's own, for its stories' glyphs. */\n icons?: readonly IconTable[];\n}\n\n/** Inputs to `startFrame`: the story, the channel to the shell, and the element to render into. */\nexport interface StartFrameOptions {\n story: LoadedStory;\n channel: Channel<ToFrame, FromFrame>;\n container: HTMLElement;\n setup?: FrameSetup;\n}\n\nconst VARS_SETTLE_MS = 100;\n\nfunction fault(phase: FaultPhase, error: unknown, seq?: number): FromFrame {\n return {\n type: 'fault',\n phase,\n message: error instanceof Error ? error.message : String(error),\n ...(error instanceof Error && error.stack ? { stack: error.stack } : {}),\n ...(seq === undefined ? {} : { seq }),\n };\n}\n\n/** Sends `ready`, then renders the story on `init` and keeps it in step. Returns a stop function. */\nexport function startFrame({ story, channel, container, setup = {} }: StartFrameOptions): () => void {\n const { send } = channel;\n send({ type: 'ready', schema: describeSchema(story.config), layout: story.layout, viewport: story.viewport });\n\n const wrapper = document.createElement('div');\n wrapper.className = `fg-frame fg-frame--${story.layout}`;\n container.append(wrapper);\n const root = createKitRoot(wrapper, setup.icons);\n const decorators = setup.decorators ?? [];\n\n let initialized = false;\n let rendered = false;\n let config: unknown;\n let state: unknown = null;\n let globals: Globals = {};\n let answeredKey: string | null = null;\n let resetKey = 0;\n let seq = 0;\n\n const overrides = createOverrides(document, setup.cssVarsScope);\n const globalsTarget = createGlobalsTarget(document.documentElement, ':root');\n const highlighter = createA11yHighlighter(document);\n let lastVars: CssVarReport[] | null = null;\n let reported: string | null = null;\n const publishVars = (vars: CssVarReport[]) => {\n lastVars = vars;\n const key = JSON.stringify(vars);\n if (key === reported) return;\n reported = key;\n send({ type: 'vars', vars });\n };\n const reportVars = () => publishVars(scanCssVars(document, overrides.has));\n const ownMutation = (record: MutationRecord) =>\n overrides.owns(record.target) ||\n (record.type === 'childList' &&\n [...record.addedNodes, ...record.removedNodes].length > 0 &&\n [...record.addedNodes, ...record.removedNodes].every(overrides.owns));\n let settleTimer: ReturnType<typeof setTimeout> | undefined;\n const mutations =\n typeof MutationObserver === 'undefined'\n ? null\n : new MutationObserver((records) => {\n if (records.every(ownMutation)) return;\n clearTimeout(settleTimer);\n settleTimer = setTimeout(reportVars, VARS_SETTLE_MS);\n });\n // Every attribute, not just style and class: a stylesheet can select on any of them, `[data-wzl-mode]` included.\n mutations?.observe(document.documentElement, { subtree: true, childList: true, characterData: true, attributes: true });\n\n const setConfig = (path: string, value: unknown) => send({ type: 'setConfig', path, value });\n const setState = (next: unknown) => {\n state = typeof next === 'function' ? (next as (prev: unknown) => unknown)(state) : next;\n send({ type: 'setState', state });\n render();\n };\n\n const render = () => {\n const ctx: StoryContext = { config, setConfig, state, setState, globals, title: story.title, name: story.name };\n const at = seq;\n root.render(\n <StoryHost\n story={story}\n ctx={ctx}\n decorators={decorators}\n resetKey={resetKey}\n onError={(error) => send(fault('render', error, at))}\n />,\n );\n const key = stableStringify(config);\n if (key !== answeredKey) {\n answeredKey = key;\n send({ type: 'answers', answers: { configKey: key, ...answerSchema(story.config, config) } });\n }\n };\n\n // Input from the trial commits synchronously, so `rendered` and the vars report describe the story it produced. A\n // throw while applying it faults like a render would; otherwise the trial would wait on a frame that never answers.\n const input = (apply: () => void) => {\n seq += 1;\n try {\n apply();\n if (!initialized) return;\n resetKey += 1;\n flushSync(render);\n } catch (error) {\n send(fault('render', error, seq));\n return;\n }\n if (!rendered) {\n rendered = true;\n announceRendered();\n }\n reportVars();\n };\n\n /**\n * The shell unhides the frame on `rendered` and fades it in, so a webfont\n * swapping in after that message reads as the story gliding. Waiting for the\n * fonts and then one painted frame means the story the shell reveals is the\n * settled one.\n *\n * `document.fonts` is absent in jsdom, so the message stays synchronous\n * there; the deferral is only exercised in a browser.\n */\n const announceRendered = () => {\n const { fonts } = document;\n if (!fonts) {\n send({ type: 'rendered' });\n return;\n }\n const afterPaint = () => requestAnimationFrame(() => send({ type: 'rendered' }));\n void fonts.ready.then(afterPaint, afterPaint);\n };\n\n const audit = async (id: string) => send({ type: 'a11y', id, ...(await auditElement(wrapper)) });\n\n const off = channel.on((msg) => {\n switch (msg.type) {\n case 'init':\n input(() => {\n initialized = true;\n config = msg.config;\n globals = msg.globals;\n state = msg.state;\n if (state === null && story.initialState) {\n state = story.initialState(config);\n send({ type: 'setState', state });\n }\n setup.applyGlobals?.(globals, globalsTarget);\n });\n break;\n case 'config':\n input(() => {\n config = msg.config;\n });\n break;\n case 'state':\n input(() => {\n state = msg.state;\n });\n break;\n case 'globals':\n input(() => {\n globals = msg.globals;\n setup.applyGlobals?.(globals, globalsTarget);\n });\n break;\n case 'vars.set': {\n overrides.set(msg.name, msg.value);\n const at = lastVars?.findIndex((v) => v.name === msg.name) ?? -1;\n if (!lastVars || at < 0) break;\n const vars = lastVars.slice();\n vars[at] = { ...vars[at]!, value: resolveCssVar(document, msg.name), overridden: overrides.has(msg.name) };\n publishVars(vars);\n break;\n }\n case 'a11y.run':\n void audit(msg.id);\n break;\n case 'a11y.highlight':\n highlighter.show(msg.targets);\n break;\n }\n });\n\n return () => {\n off();\n mutations?.disconnect();\n clearTimeout(settleTimer);\n overrides.dispose();\n globalsTarget.dispose();\n highlighter.dispose();\n root.unmount();\n wrapper.remove();\n };\n}\n\n/** Reports an import failure — there is no story to start. */\nexport function reportImportFault(channel: Channel<ToFrame, FromFrame>, error: unknown): void {\n channel.send(fault('import', error));\n}\n","import { f } from '@weasel-js/labkit/config';\nimport { Component, type ReactNode } from 'react';\nimport { flushSync } from 'react-dom';\nimport { createKitRoot } from '../../kitIcons';\nimport type { Channel } from '../../protocol/channel';\nimport type { FromFrame, Globals, ToFrame } from '../../protocol/messages';\nimport { describeSchema } from '../../protocol/schema';\nimport type { IndexRender, LoadedStory } from '../../story/types';\nimport { runAxe } from '../a11y';\nimport type { FrameSetup } from '../FrameController';\nimport { createGlobalsTarget } from '../globalsTarget';\nimport { type IndexEnv, IndexPage } from './IndexPage';\n\nexport interface StartIndexOptions {\n title: string;\n /** The package the component ships in. */\n library?: string;\n description?: string;\n /** Whether the component is a gallery. */\n gallery?: boolean;\n /** The ids of the stories tagged `gallery`. */\n galleries?: readonly string[];\n /** In file order. */\n stories: readonly LoadedStory[];\n descriptions: Readonly<Record<string, string>>;\n /** The component's own page; null for the generated one. */\n render: IndexRender | null;\n channel: Channel<ToFrame, FromFrame>;\n container: HTMLElement;\n setup?: FrameSetup;\n}\n\nconst message = (error: unknown): string => (error instanceof Error ? error.message : String(error));\n\n/** Faults the frame when the page itself throws. A single story's throw stays in its own cell. */\nclass PageBoundary extends Component<{ onError: (error: unknown) => void; children: ReactNode }, { failed: unknown }> {\n override state = { failed: null as unknown };\n\n static getDerivedStateFromError(error: unknown) {\n return { failed: error ?? new Error('Index page failed') };\n }\n\n override componentDidCatch(error: unknown): void {\n this.props.onError(error);\n }\n\n override render(): ReactNode {\n return this.state.failed ? null : this.props.children;\n }\n}\n\n/**\n * Sends `ready` for a page with no controls, then renders the component's index on `init` and follows the lab's\n * globals. Returns a stop function.\n */\nexport function startIndex(options: StartIndexOptions): () => void {\n const { channel, container, setup = {} } = options;\n const { send } = channel;\n send({ type: 'ready', schema: describeSchema(f.schema({})), layout: 'fullscreen', viewport: null });\n\n const wrapper = document.createElement('div');\n wrapper.className = 'fg-frame fg-frame--fullscreen';\n container.append(wrapper);\n const root = createKitRoot(wrapper, setup.icons);\n const globalsTarget = createGlobalsTarget(document.documentElement, ':root');\n let globals: Globals | null = null;\n let announced = false;\n\n const render = (): void => {\n if (!globals) return;\n const env: IndexEnv = {\n title: options.title,\n ...(options.library === undefined ? {} : { library: options.library }),\n ...(options.description === undefined ? {} : { description: options.description }),\n stories: options.stories,\n descriptions: options.descriptions,\n gallery: options.gallery ?? false,\n galleries: options.galleries ?? [],\n globals,\n decorators: setup.decorators ?? [],\n open: (id) => send({ type: 'open', id }),\n // A story that throws shows its error in its own cell; the rest of the page is still worth reading.\n onError: (error) => console.error(error),\n };\n root.render(\n <PageBoundary onError={(error) => send({ type: 'fault', phase: 'render', message: message(error) })}>\n <IndexPage env={env} render={options.render} />\n </PageBoundary>,\n );\n };\n\n const announce = (): void => {\n if (announced) return;\n announced = true;\n const { fonts } = document;\n if (!fonts) {\n send({ type: 'rendered' });\n return;\n }\n const afterPaint = () => requestAnimationFrame(() => send({ type: 'rendered' }));\n void fonts.ready.then(afterPaint, afterPaint);\n };\n\n const off = channel.on((msg) => {\n switch (msg.type) {\n case 'init':\n case 'globals':\n globals = msg.globals;\n setup.applyGlobals?.(globals, globalsTarget);\n flushSync(render);\n announce();\n break;\n case 'a11y.run':\n runAxe(wrapper).then(\n (report) => send({ type: 'a11y', id: msg.id, ok: true, report }),\n (error: unknown) => send({ type: 'a11y', id: msg.id, ok: false, message: message(error) }),\n );\n break;\n default:\n break;\n }\n });\n\n return () => {\n off();\n globalsTarget.dispose();\n root.unmount();\n wrapper.remove();\n };\n}\n","import { openChannel } from '../protocol/channel';\nimport { FRAME_HELLO, type FromFrame, PORT_HANDOFF, type ToFrame } from '../protocol/messages';\nimport { indexId, isIndexId } from '../story/indexPages';\nimport { TITLE_LIBRARIES } from '../story/library';\nimport { isGallery } from '../story/tags';\nimport { indexRenderOf, loadStories } from '../story/load';\nimport type { LoadedStory } from '../story/types';\nimport { type FrameSetup, reportImportFault, startFrame } from './FrameController';\nimport { startIndex } from './index/startIndex';\n\n/** Story modules by file path, each loaded on first use. */\nexport interface FrameImporters {\n [file: string]: () => Promise<Record<string, unknown>>;\n}\n\n/** One story as a frame document needs to find it, before its module is loaded. */\nexport interface FrameIndexEntry {\n id: string;\n /** The story's title as indexed, which titles the file's stories when its meta names none. */\n title: string;\n file: string;\n exportName: string;\n /** The JSDoc above the story's export, which its index page shows. */\n description?: string;\n /** The JSDoc above the file's meta, which heads the index page. */\n componentDescription?: string;\n /** The meta's `tags`. */\n tags?: readonly string[];\n}\n\n/** Inputs to `mountFrame`. `load` replaces the default module loader, `loadStories`. */\nexport interface MountFrameOptions {\n index: readonly FrameIndexEntry[];\n importers: FrameImporters;\n setup?: FrameSetup;\n load?: (mod: Record<string, unknown>, title: string, parameters?: Record<string, unknown>) => LoadedStory[];\n}\n\nexport { indexRenderOf, loadStories } from '../story/load';\n\nfunction waitForHandoff():Promise<{ port: MessagePort; id: string | null }> {\n return new Promise((resolve) => {\n const onMessage = (event: MessageEvent) => {\n const data = event.data as { type?: unknown; id?: unknown } | null;\n const port = event.ports[0];\n if (event.origin !== location.origin || event.source !== window.parent) return;\n if (typeof data !== 'object' || data === null || data.type !== PORT_HANDOFF || !port) return;\n window.removeEventListener('message', onMessage);\n resolve({ port, id: typeof data.id === 'string' ? data.id : null });\n };\n window.addEventListener('message', onMessage);\n });\n}\n\n/**\n * The frame document's entry: asks its parent for a port and shows what the handoff names, or, from a shell that\n * names nothing, what the hash does. The hash is read at once, so its module loads during the handshake.\n */\nexport async function mountFrame(options: MountFrameOptions): Promise<void> {\n const imports = new Map<string, Promise<Record<string, unknown>>>();\n const importOf = (file: string): Promise<Record<string, unknown>> => {\n let loading = imports.get(file);\n if (!loading) {\n const importer = options.importers[file];\n if (!importer) throw new Error(`No importer for ${file}`);\n loading = importer();\n imports.set(file, loading);\n }\n return loading;\n };\n /** The entries `id` shows: one story, or every story of the component an index id names. */\n const entriesOf = (id: string): FrameIndexEntry[] =>\n isIndexId(id)\n ? options.index.filter((e) => indexId(e.title) === id)\n : options.index.filter((e) => e.id === id);\n const early = location.hash.slice(1) || null;\n // Only starts the fetch; whoever awaits the import later sees its outcome.\n for (const file of new Set(early === null ? [] : entriesOf(early).map((e) => e.file))) {\n if (options.importers[file]) importOf(file).catch(() => {});\n }\n\n const handoff = waitForHandoff();\n window.parent.postMessage({ type: FRAME_HELLO }, location.origin);\n const { port, id: handed } = await handoff;\n const channel = openChannel<ToFrame, FromFrame>(port);\n const id = handed ?? early ?? '';\n const container = document.getElementById('root') ?? document.body;\n try {\n if (isIndexId(id)) {\n const entries = entriesOf(id);\n const title = entries[0]?.title;\n if (title === undefined) throw new Error(`No component with index \"${id}\"`);\n const files = [...new Set(entries.map((e) => e.file))];\n const mods = await Promise.all(files.map(importOf));\n const loaded = files.map((file, i) => ({\n file,\n stories: (options.load ?? loadStories)(mods[i] ?? {}, title, options.setup?.parameters),\n }));\n const stories = entries.flatMap(\n (e) => loaded.find((l) => l.file === e.file)?.stories.find((s) => s.exportName === e.exportName) ?? [],\n );\n for (const story of stories) await options.setup?.prepare?.(story);\n startIndex({\n title,\n ...(entries[0]?.componentDescription === undefined ? {} : { description: entries[0].componentDescription }),\n // The project's library table is the shell config's, which a frame document does not load.\n library: TITLE_LIBRARIES.of({ file: entries[0]?.file ?? '', title }),\n gallery: entries.every(isGallery),\n galleries: entries.filter(isGallery).map((e) => e.id),\n stories,\n descriptions: Object.fromEntries(entries.flatMap((e) => (e.description ? [[e.id, e.description]] : []))),\n render: mods.map(indexRenderOf).find((render) => render !== null) ?? null,\n channel,\n container,\n ...(options.setup ? { setup: options.setup } : {}),\n });\n return;\n }\n const entry = options.index.find((e) => e.id === id);\n if (!entry) throw new Error(`No story with id \"${id}\"`);\n const mod = await importOf(entry.file);\n const stories = (options.load ?? loadStories)(mod, entry.title, options.setup?.parameters);\n const story = stories.find((s) => s.exportName === entry.exportName);\n if (!story) throw new Error(`${entry.file} has no story export \"${entry.exportName}\"`);\n await options.setup?.prepare?.(story);\n startFrame({ story, channel, container, setup: options.setup });\n } catch (error) {\n reportImportFault(channel, error);\n }\n}\n","import './capture.css';\nimport { useLatest, useVisibleRaf } from '@weasel-js/core';\nimport { interstellarTheme, LabRoot } from '@weasel-js/labkit';\nimport type { Theme } from '@weasel-js/theme';\nimport { ThemeProvider } from '@weasel-js/theme/react';\nimport { OverlayPortalProvider } from '@weasel-js/ui/portal-host';\nimport { type CSSProperties, type ReactNode, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { useHostConditions } from '../../shell/hostConditions';\nimport { LAB_DENSITY } from '../../shell/labDensity';\nimport type { Globals } from '../../protocol/messages';\nimport type { LoadedStory, StoryContext } from '../../story/types';\nimport { ClockContext } from '../../timeline/context';\nimport { useStoryClock } from '../../timeline/StoryClock';\nimport type { CapturePayload } from '../../vite/capture/payload';\nimport type { FrameSetup } from '../FrameController';\nimport { StoryHost } from '../StoryHost';\n\n/** Props for `CaptureView`. */\nexport interface CaptureViewProps {\n story: LoadedStory;\n payload: CapturePayload;\n setup: FrameSetup;\n /** The shell config's `labTheme`, which the workshop's lab is themed by. */\n labTheme?: ((globals: Globals) => Theme) | undefined;\n /** Called once the story has painted with its fonts, so a screenshot taken then shows it settled. */\n onRendered: () => void;\n}\n\nconst HOST_ID = 'capture';\nconst NO_WRITE = () => {};\n\n/** Sizes the box through custom properties, which capture.css reads. */\nconst boxStyle = ({ width, height }: CapturePayload['box']): CSSProperties =>\n ({ ['--fg-capture-w' as string]: `${width}px`, ['--fg-capture-h' as string]: `${height}px` }) as CSSProperties;\n\n/** Scrolls the story's scroller to where the screen's stood; a story still growing is scrolled again before the shot. */\nfunction scrollTo(host: HTMLElement | null, { left, top }: CapturePayload['scroll']) {\n const scroller = host?.querySelector<HTMLElement>(':scope > .fg-story__scroll');\n if (!scroller) return;\n scroller.scrollLeft = left;\n scroller.scrollTop = top;\n}\n\n/**\n * One story rendered from a capture payload, still: its clock stands at the payload's playhead and nothing plays\n * it, and nothing it writes to its config or state goes anywhere. A story that would be in the workshop document\n * sits under a lab root themed as the lab is, as it does there; an isolated one sits in the frame document's own\n * wrapper.\n */\nexport function CaptureView({ story, payload, setup, labTheme, onRendered }: CaptureViewProps) {\n const [host, setHost] = useState<HTMLDivElement | null>(null);\n useHostConditions(host, { hostId: HOST_ID, globals: payload.globals, overrides: payload.overrides, setup });\n\n const spec = useMemo(() => story.timeline?.(payload.config) ?? null, [story, payload.config]);\n const clock = useStoryClock(spec, () => payload.playhead);\n\n const state = useMemo(\n () => (payload.state === null && story.initialState ? story.initialState(payload.config) : payload.state),\n [payload.state, payload.config, story],\n );\n const ctx: StoryContext = {\n config: payload.config,\n setConfig: NO_WRITE,\n state,\n setState: NO_WRITE,\n globals: payload.globals,\n title: story.title,\n name: story.name,\n };\n\n const latest = useLatest({ onRendered, host, scroll: payload.scroll });\n useLayoutEffect(() => scrollTo(host, payload.scroll), [host, payload.scroll]);\n const ticks = useRef(0);\n // A capture page is never looked at, and a headless page can count as hidden.\n const raf = useVisibleRaf(\n (_now, loop) => {\n ticks.current += 1;\n scrollTo(latest.current.host, latest.current.scroll);\n if (ticks.current < 2) loop.request();\n else latest.current.onRendered();\n },\n { dangerouslyRunWhenHidden: true },\n );\n useEffect(() => {\n if (!host) return;\n let canceled = false;\n const start = () => {\n if (!canceled) raf.request();\n };\n const { fonts } = host.ownerDocument;\n if (fonts) void fonts.ready.then(start, start);\n else start();\n return () => {\n canceled = true;\n raf.cancel();\n };\n }, [host, raf]);\n\n const content: ReactNode = host ? (\n <ClockContext.Provider value={clock}>\n <StoryHost story={story} ctx={ctx} decorators={setup.decorators ?? []} resetKey={0} onError={NO_WRITE} />\n </ClockContext.Provider>\n ) : null;\n\n const box = (\n <div\n ref={setHost}\n className=\"fg-story\"\n data-fg-host={HOST_ID}\n data-fg-capture=\"\"\n data-fg-layout={payload.layout}\n style={boxStyle(payload.box)}\n >\n {payload.isolate ? (\n <div className={`fg-frame fg-frame--${payload.layout}`}>{content}</div>\n ) : (\n <div className=\"fg-story__scroll\">\n {host ? (\n <OverlayPortalProvider container={host} contained>\n {content}\n </OverlayPortalProvider>\n ) : null}\n </div>\n )}\n </div>\n );\n if (payload.isolate) return box;\n return (\n <ThemeProvider\n theme={labTheme?.(payload.lab.globals) ?? interstellarTheme}\n selection={{ mode: payload.lab.mode, density: LAB_DENSITY }}\n >\n <LabRoot>{box}</LabRoot>\n </ThemeProvider>\n );\n}\n","import type { Theme } from '@weasel-js/theme';\nimport { Component, type ReactNode } from 'react';\nimport { createKitRoot } from '../../kitIcons';\nimport type { Globals } from '../../protocol/messages';\nimport { loadStories } from '../../story/load';\nimport type { IndexEntry, LoadedStory } from '../../story/types';\nimport type { CapturePayload } from '../../vite/capture/payload';\nimport type { FrameSetup } from '../FrameController';\nimport type { FrameImporters } from '../mountFrame';\nimport { CaptureView } from './CaptureView';\n\n/** Inputs to `mountCapture`, as a capture page's entry module passes them. */\nexport interface MountCaptureOptions {\n index: readonly IndexEntry[];\n importers: FrameImporters;\n setup: FrameSetup;\n /** The shell config's `labTheme`; only the shell's capture page has one. */\n labTheme?: ((globals: Globals) => Theme) | undefined;\n}\n\ndeclare global {\n interface Window {\n /** Set by `mountCapture`: renders one payload and resolves once it has painted. */\n __forgeCapture?: { render(payload: CapturePayload): Promise<void> };\n }\n}\n\n/** Catches what throws outside the story's own boundary, which would otherwise unmount the root and leave the\n * render waiting forever. */\nclass CaptureBoundary extends Component<{ onError: (error: unknown) => void; children: ReactNode }, { failed: boolean }> {\n override state = { failed: false };\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n override componentDidCatch(error: unknown): void {\n this.props.onError(error);\n }\n\n override render(): ReactNode {\n return this.state.failed ? null : this.props.children;\n }\n}\n\n/**\n * A capture page's entry: exposes `window.__forgeCapture.render(payload)`, which loads the payload's story, renders\n * it afresh into `#root`, and resolves once it has painted. Rejects for a story the index does not hold, and with\n * whatever throws outside the story's own error boundary.\n */\nexport function mountCapture({ index, importers, setup, labTheme }: MountCaptureOptions): void {\n const container = document.getElementById('root') ?? document.body;\n const root = createKitRoot(container, setup.icons);\n const prepared = new Map<string, Promise<LoadedStory>>();\n let renders = 0;\n\n const storyOf = (id: string): Promise<LoadedStory> => {\n let loading = prepared.get(id);\n if (!loading) {\n loading = (async () => {\n const entry = index.find((e) => e.id === id);\n if (!entry) throw new Error(`No story with id \"${id}\"`);\n const importer = importers[entry.file];\n if (!importer) throw new Error(`No importer for ${entry.file}`);\n const story = loadStories(await importer(), entry.title, setup.parameters).find((s) => s.exportName === entry.exportName);\n if (!story) throw new Error(`${entry.file} has no story export \"${entry.exportName}\"`);\n await setup.prepare?.(story);\n return story;\n })();\n prepared.set(id, loading);\n loading.catch(() => prepared.delete(id));\n }\n return loading;\n };\n\n window.__forgeCapture = {\n async render(payload) {\n const story = await storyOf(payload.story);\n renders += 1;\n await new Promise<void>((resolve, reject) => {\n // Keyed per render, so a payload never inherits the last one's clock or state.\n root.render(\n <CaptureBoundary key={renders} onError={reject}>\n <CaptureView story={story} payload={payload} setup={setup} labTheme={labTheme} onRendered={resolve} />\n </CaptureBoundary>,\n );\n });\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/frame/documentScroll.ts","../../src/frame/FrameController.tsx","../../src/frame/index/startIndex.tsx","../../src/frame/mountFrame.tsx","../../src/frame/capture/CaptureView.tsx","../../src/frame/capture/mountCapture.tsx"],"names":["jsx","flushSync","id","Component"],"mappings":"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","file":"index.js","sourcesContent":["import type { FromFrame } from '../protocol/messages';\n\n/** Where a frame document stands, kept in step with the shell. */\nexport interface DocumentScroll {\n apply(to: { left: number; top: number }): void;\n dispose(): void;\n}\n\n/**\n * Reports where `doc` stands, now and on each scroll, and scrolls it where the shell says: the story scrolls the\n * frame document itself, and the shell keeps a lens's copy and a capture on the same patch.\n */\nexport function followDocumentScroll(doc: Document, send: (msg: FromFrame) => void): DocumentScroll {\n const scroller = doc.scrollingElement ?? doc.documentElement;\n const view = doc.defaultView;\n let reported: string | null = null;\n const report = () => {\n const left = scroller.scrollLeft;\n const top = scroller.scrollTop;\n const key = `${left} ${top}`;\n if (key === reported) return;\n reported = key;\n send({ type: 'scroll', left, top });\n };\n report();\n view?.addEventListener('scroll', report, { passive: true });\n return {\n apply({ left, top }) {\n scroller.scrollLeft = left;\n scroller.scrollTop = top;\n },\n dispose: () => view?.removeEventListener('scroll', report),\n };\n}\n","import { flushSync } from 'react-dom';\nimport type { IconTable } from '@weasel-js/icons';\nimport { createKitRoot } from '../kitIcons';\nimport type { Channel } from '../protocol/channel';\nimport {\n type CssVarReport,\n type FaultPhase,\n type FromFrame,\n type Globals,\n stableStringify,\n type ToFrame,\n} from '../protocol/messages';\nimport { answerSchema, describeSchema } from '../protocol/schema';\nimport type { Decorator, LoadedStory, StoryContext } from '../story/types';\nimport { auditElement } from './a11y';\nimport { createA11yHighlighter } from './a11yHighlight';\nimport { createOverrides, resolveCssVar, scanCssVars } from './cssVars';\nimport { followDocumentScroll } from './documentScroll';\nimport { createGlobalsTarget, type GlobalsTarget } from './globalsTarget';\nimport { StoryHost } from './StoryHost';\n\n/** The frame config: what `defineFrameConfig` returns and the `frameConfig` module default-exports. */\nexport interface FrameSetup {\n /** Wraps every story, outermost; receives the globals. From the frame config (`frameConfig`). */\n decorators?: Decorator[];\n /** Applies globals to a target: theme mode, fonts. The target is a frame document's root, or one story's host in\n * the workshop document, so a rule the setup writes goes through `target.style` under `target.scope`. */\n applyGlobals?: (globals: Globals, target: GlobalsTarget) => void;\n /**\n * The elements a CSS variable override is declared on; `:root` by default. An override has to be declared on\n * whichever element declares the token itself — a theme wrapper, say — or that element's own value wins.\n */\n cssVarsScope?: string;\n /** Project-wide CSF parameters, Storybook's preview `parameters`: under each meta's and story's. */\n parameters?: Record<string, unknown>;\n /**\n * Awaited once a story is loaded and before it first renders — the place to import what only some stories\n * need, so the rest never load it.\n */\n prepare?: (story: LoadedStory) => void | Promise<void>;\n /** Icon tables registered beside the kit's in every frame: an app's own, for its stories' glyphs. */\n icons?: readonly IconTable[];\n}\n\n/** Inputs to `startFrame`: the story, the channel to the shell, and the element to render into. */\nexport interface StartFrameOptions {\n story: LoadedStory;\n channel: Channel<ToFrame, FromFrame>;\n container: HTMLElement;\n setup?: FrameSetup;\n}\n\nconst VARS_SETTLE_MS = 100;\n\nfunction fault(phase: FaultPhase, error: unknown, seq?: number): FromFrame {\n return {\n type: 'fault',\n phase,\n message: error instanceof Error ? error.message : String(error),\n ...(error instanceof Error && error.stack ? { stack: error.stack } : {}),\n ...(seq === undefined ? {} : { seq }),\n };\n}\n\n/**\n * The shell unhides the frame on `rendered` and fades it in, so a webfont\n * swapping in after that message reads as the story gliding. Waiting for the\n * fonts and then one painted frame means the story the shell reveals is the\n * settled one.\n *\n * `document.fonts` is absent in jsdom, so the message stays synchronous\n * there; the deferral is only exercised in a browser.\n */\nfunction announceRendered(send: (msg: FromFrame) => void): void {\n const { fonts } = document;\n if (!fonts) {\n send({ type: 'rendered' });\n return;\n }\n const afterPaint = () => requestAnimationFrame(() => send({ type: 'rendered' }));\n void fonts.ready.then(afterPaint, afterPaint);\n}\n\n/** Sends `ready`, then renders the story on `init` and keeps it in step. Returns a stop function. */\nexport function startFrame({ story, channel, container, setup = {} }: StartFrameOptions): () => void {\n const { send } = channel;\n send({ type: 'ready', schema: describeSchema(story.config), layout: story.layout, viewport: story.viewport });\n\n const wrapper = document.createElement('div');\n wrapper.className = `fg-frame fg-frame--${story.layout}`;\n container.append(wrapper);\n const root = createKitRoot(wrapper, setup.icons);\n const decorators = setup.decorators ?? [];\n\n let initialized = false;\n let rendered = false;\n let config: unknown;\n let state: unknown = null;\n let globals: Globals = {};\n let answeredKey: string | null = null;\n let resetKey = 0;\n let seq = 0;\n\n const overrides = createOverrides(document, setup.cssVarsScope);\n const globalsTarget = createGlobalsTarget(document.documentElement, ':root');\n const highlighter = createA11yHighlighter(document);\n let lastVars: CssVarReport[] | null = null;\n let reported: string | null = null;\n const publishVars = (vars: CssVarReport[]) => {\n lastVars = vars;\n const key = JSON.stringify(vars);\n if (key === reported) return;\n reported = key;\n send({ type: 'vars', vars });\n };\n const reportVars = () => publishVars(scanCssVars(document, overrides.has));\n const ownMutation = (record: MutationRecord) =>\n overrides.owns(record.target) ||\n (record.type === 'childList' &&\n [...record.addedNodes, ...record.removedNodes].length > 0 &&\n [...record.addedNodes, ...record.removedNodes].every(overrides.owns));\n let settleTimer: ReturnType<typeof setTimeout> | undefined;\n const mutations =\n typeof MutationObserver === 'undefined'\n ? null\n : new MutationObserver((records) => {\n if (records.every(ownMutation)) return;\n clearTimeout(settleTimer);\n settleTimer = setTimeout(reportVars, VARS_SETTLE_MS);\n });\n // Every attribute, not just style and class: a stylesheet can select on any of them, `[data-wzl-mode]` included.\n mutations?.observe(document.documentElement, { subtree: true, childList: true, characterData: true, attributes: true });\n\n const setConfig = (path: string, value: unknown) => send({ type: 'setConfig', path, value });\n const setState = (next: unknown) => {\n state = typeof next === 'function' ? (next as (prev: unknown) => unknown)(state) : next;\n send({ type: 'setState', state });\n render();\n };\n\n const render = () => {\n const ctx: StoryContext = { config, setConfig, state, setState, globals, title: story.title, name: story.name };\n const at = seq;\n root.render(\n <StoryHost\n story={story}\n ctx={ctx}\n decorators={decorators}\n resetKey={resetKey}\n onError={(error) => send(fault('render', error, at))}\n />,\n );\n const key = stableStringify(config);\n if (key !== answeredKey) {\n answeredKey = key;\n send({ type: 'answers', answers: { configKey: key, ...answerSchema(story.config, config) } });\n }\n };\n\n // Input from the trial commits synchronously, so `rendered` and the vars report describe the story it produced. A\n // throw while applying it faults like a render would; otherwise the trial would wait on a frame that never answers.\n const input = (apply: () => void) => {\n seq += 1;\n try {\n apply();\n if (!initialized) return;\n resetKey += 1;\n flushSync(render);\n } catch (error) {\n send(fault('render', error, seq));\n return;\n }\n if (!rendered) {\n rendered = true;\n announceRendered(send);\n }\n reportVars();\n };\n\n const scroll = followDocumentScroll(document, send);\n\n const audit = async (id: string) => send({ type: 'a11y', id, ...(await auditElement(wrapper)) });\n\n const off = channel.on((msg) => {\n switch (msg.type) {\n case 'init':\n input(() => {\n initialized = true;\n config = msg.config;\n globals = msg.globals;\n state = msg.state;\n if (state === null && story.initialState) {\n state = story.initialState(config);\n send({ type: 'setState', state });\n }\n setup.applyGlobals?.(globals, globalsTarget);\n });\n break;\n case 'config':\n input(() => {\n config = msg.config;\n });\n break;\n case 'state':\n input(() => {\n state = msg.state;\n });\n break;\n case 'globals':\n input(() => {\n globals = msg.globals;\n setup.applyGlobals?.(globals, globalsTarget);\n });\n break;\n case 'vars.set': {\n overrides.set(msg.name, msg.value);\n const at = lastVars?.findIndex((v) => v.name === msg.name) ?? -1;\n if (!lastVars || at < 0) break;\n const vars = lastVars.slice();\n vars[at] = { ...vars[at]!, value: resolveCssVar(document, msg.name), overridden: overrides.has(msg.name) };\n publishVars(vars);\n break;\n }\n case 'a11y.run':\n void audit(msg.id);\n break;\n case 'a11y.highlight':\n highlighter.show(msg.targets);\n break;\n case 'scroll':\n scroll.apply(msg);\n break;\n }\n });\n\n return () => {\n off();\n scroll.dispose();\n mutations?.disconnect();\n clearTimeout(settleTimer);\n overrides.dispose();\n globalsTarget.dispose();\n highlighter.dispose();\n root.unmount();\n wrapper.remove();\n };\n}\n\n/** Reports an import failure — there is no story to start. */\nexport function reportImportFault(channel: Channel<ToFrame, FromFrame>, error: unknown): void {\n channel.send(fault('import', error));\n}\n","import { f } from '@weasel-js/labkit/config';\nimport { Component, type ReactNode } from 'react';\nimport { flushSync } from 'react-dom';\nimport { createKitRoot } from '../../kitIcons';\nimport type { Channel } from '../../protocol/channel';\nimport type { FromFrame, Globals, ToFrame } from '../../protocol/messages';\nimport { describeSchema } from '../../protocol/schema';\nimport type { IndexBundle } from '../../story/indexBundle';\nimport { runAxe } from '../a11y';\nimport type { FrameSetup } from '../FrameController';\nimport { createGlobalsTarget } from '../globalsTarget';\nimport { indexEnvOf } from './indexEnv';\nimport { IndexPage } from './IndexPage';\n\nexport interface StartIndexOptions {\n bundle: IndexBundle;\n channel: Channel<ToFrame, FromFrame>;\n container: HTMLElement;\n setup?: FrameSetup;\n}\n\nconst message = (error: unknown): string => (error instanceof Error ? error.message : String(error));\n\n/** Faults the frame when the page itself throws. A single story's throw stays in its own cell. */\nclass PageBoundary extends Component<{ onError: (error: unknown) => void; children: ReactNode }, { failed: unknown }> {\n override state = { failed: null as unknown };\n\n static getDerivedStateFromError(error: unknown) {\n return { failed: error ?? new Error('Index page failed') };\n }\n\n override componentDidCatch(error: unknown): void {\n this.props.onError(error);\n }\n\n override render(): ReactNode {\n return this.state.failed ? null : this.props.children;\n }\n}\n\n/**\n * Sends `ready` for a page with no controls, then renders the component's index on `init` and follows the lab's\n * globals. Returns a stop function.\n */\nexport function startIndex(options: StartIndexOptions): () => void {\n const { channel, container, setup = {} } = options;\n const { send } = channel;\n send({ type: 'ready', schema: describeSchema(f.schema({})), layout: 'fullscreen', viewport: null });\n\n const wrapper = document.createElement('div');\n wrapper.className = 'fg-frame fg-frame--fullscreen';\n container.append(wrapper);\n const root = createKitRoot(wrapper, setup.icons);\n const globalsTarget = createGlobalsTarget(document.documentElement, ':root');\n let globals: Globals | null = null;\n let announced = false;\n\n const render = (): void => {\n if (!globals) return;\n const env = indexEnvOf(options.bundle, {\n graph: null,\n globals,\n decorators: setup.decorators ?? [],\n open: (id) => send({ type: 'open', id }),\n });\n root.render(\n <PageBoundary onError={(error) => send({ type: 'fault', phase: 'render', message: message(error) })}>\n <IndexPage env={env} render={options.bundle.render} />\n </PageBoundary>,\n );\n };\n\n const announce = (): void => {\n if (announced) return;\n announced = true;\n const { fonts } = document;\n if (!fonts) {\n send({ type: 'rendered' });\n return;\n }\n const afterPaint = () => requestAnimationFrame(() => send({ type: 'rendered' }));\n void fonts.ready.then(afterPaint, afterPaint);\n };\n\n const off = channel.on((msg) => {\n switch (msg.type) {\n case 'init':\n case 'globals':\n globals = msg.globals;\n setup.applyGlobals?.(globals, globalsTarget);\n flushSync(render);\n announce();\n break;\n case 'a11y.run':\n runAxe(wrapper).then(\n (report) => send({ type: 'a11y', id: msg.id, ok: true, report }),\n (error: unknown) => send({ type: 'a11y', id: msg.id, ok: false, message: message(error) }),\n );\n break;\n default:\n break;\n }\n });\n\n return () => {\n off();\n globalsTarget.dispose();\n root.unmount();\n wrapper.remove();\n };\n}\n","import { openChannel } from '../protocol/channel';\nimport { FRAME_HELLO, type FromFrame, PORT_HANDOFF, type ToFrame } from '../protocol/messages';\nimport { indexId, isIndexId } from '../story/indexPages';\nimport { loadIndexBundle } from '../story/indexBundle';\nimport { loadStories } from '../story/load';\nimport type { LoadedStory } from '../story/types';\nimport { type FrameSetup, reportImportFault, startFrame } from './FrameController';\nimport { startIndex } from './index/startIndex';\n\n/** Story modules by file path, each loaded on first use. */\nexport interface FrameImporters {\n [file: string]: () => Promise<Record<string, unknown>>;\n}\n\n/** One story as a frame document needs to find it, before its module is loaded. */\nexport interface FrameIndexEntry {\n id: string;\n /** The story's title as indexed, which titles the file's stories when its meta names none. */\n title: string;\n file: string;\n exportName: string;\n /** The JSDoc above the story's export, which its index page shows. */\n description?: string;\n /** The JSDoc above the file's meta, which heads the index page. */\n componentDescription?: string;\n /** The meta's `tags`. */\n tags?: readonly string[];\n}\n\n/** Inputs to `mountFrame`. `load` replaces the default module loader, `loadStories`. */\nexport interface MountFrameOptions {\n index: readonly FrameIndexEntry[];\n importers: FrameImporters;\n setup?: FrameSetup;\n load?: (mod: Record<string, unknown>, title: string, parameters?: Record<string, unknown>) => LoadedStory[];\n}\n\nexport { indexRenderOf, loadStories } from '../story/load';\n\nfunction waitForHandoff():Promise<{ port: MessagePort; id: string | null }> {\n return new Promise((resolve) => {\n const onMessage = (event: MessageEvent) => {\n const data = event.data as { type?: unknown; id?: unknown } | null;\n const port = event.ports[0];\n if (event.origin !== location.origin || event.source !== window.parent) return;\n if (typeof data !== 'object' || data === null || data.type !== PORT_HANDOFF || !port) return;\n window.removeEventListener('message', onMessage);\n resolve({ port, id: typeof data.id === 'string' ? data.id : null });\n };\n window.addEventListener('message', onMessage);\n });\n}\n\n/**\n * The frame document's entry: asks its parent for a port and shows what the handoff names, or, from a shell that\n * names nothing, what the hash does. The hash is read at once, so its module loads during the handshake.\n */\nexport async function mountFrame(options: MountFrameOptions): Promise<void> {\n const imports = new Map<string, Promise<Record<string, unknown>>>();\n const importOf = (file: string): Promise<Record<string, unknown>> => {\n let loading = imports.get(file);\n if (!loading) {\n const importer = options.importers[file];\n if (!importer) throw new Error(`No importer for ${file}`);\n loading = importer();\n imports.set(file, loading);\n }\n return loading;\n };\n /** The entries `id` shows: one story, or every story of the component an index id names. */\n const entriesOf = (id: string): FrameIndexEntry[] =>\n isIndexId(id)\n ? options.index.filter((e) => indexId(e.title) === id)\n : options.index.filter((e) => e.id === id);\n const early = location.hash.slice(1) || null;\n // Only starts the fetch; whoever awaits the import later sees its outcome.\n for (const file of new Set(early === null ? [] : entriesOf(early).map((e) => e.file))) {\n if (options.importers[file]) importOf(file).catch(() => {});\n }\n\n const handoff = waitForHandoff();\n window.parent.postMessage({ type: FRAME_HELLO }, location.origin);\n const { port, id: handed } = await handoff;\n const channel = openChannel<ToFrame, FromFrame>(port);\n const id = handed ?? early ?? '';\n const container = document.getElementById('root') ?? document.body;\n try {\n if (isIndexId(id)) {\n const { load, setup } = options;\n const source = { index: options.index, importOf, load, parameters: setup?.parameters, prepare: setup?.prepare };\n // The project's library table is the shell config's, which a frame document does not load.\n const bundle = await loadIndexBundle(id, source);\n startIndex({ bundle, channel, container, ...(setup ? { setup } : {}) });\n return;\n }\n const entry = options.index.find((e) => e.id === id);\n if (!entry) throw new Error(`No story with id \"${id}\"`);\n const mod = await importOf(entry.file);\n const stories = (options.load ?? loadStories)(mod, entry.title, options.setup?.parameters);\n const story = stories.find((s) => s.exportName === entry.exportName);\n if (!story) throw new Error(`${entry.file} has no story export \"${entry.exportName}\"`);\n await options.setup?.prepare?.(story);\n startFrame({ story, channel, container, setup: options.setup });\n } catch (error) {\n reportImportFault(channel, error);\n }\n}\n","import './capture.css';\nimport { useLatest, useVisibleRaf } from '@weasel-js/core';\nimport { interstellarTheme, LabRoot } from '@weasel-js/labkit';\nimport type { Theme } from '@weasel-js/theme';\nimport { ThemeProvider } from '@weasel-js/theme/react';\nimport { OverlayPortalProvider } from '@weasel-js/ui/portal-host';\nimport { type CSSProperties, type ReactNode, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\nimport { useHostConditions } from '../../shell/hostConditions';\nimport { LAB_DENSITY } from '../../shell/labDensity';\nimport type { Globals } from '../../protocol/messages';\nimport type { Loaded } from '../../story/indexBundle';\nimport type { DepGraph, LoadedStory, StoryContext } from '../../story/types';\nimport { ClockContext } from '../../timeline/context';\nimport { useStoryClock } from '../../timeline/StoryClock';\nimport type { CapturePayload } from '../../vite/capture/payload';\nimport type { FrameSetup } from '../FrameController';\nimport { indexEnvOf } from '../index/indexEnv';\nimport { IndexPage } from '../index/IndexPage';\nimport { StoryHost } from '../StoryHost';\n\n/** Props for `CaptureView`. */\nexport interface CaptureViewProps {\n /** What the payload's id names: one story, or a component's index page. */\n subject: Loaded;\n /** The component graph an index page lists dependencies and history from. */\n graph?: DepGraph | null | undefined;\n payload: CapturePayload;\n setup: FrameSetup;\n /** The shell config's `labTheme`, which the workshop's lab is themed by. */\n labTheme?: ((globals: Globals) => Theme) | undefined;\n /** Called once the story has painted with its fonts, so a screenshot taken then shows it settled. */\n onRendered: () => void;\n}\n\nconst HOST_ID = 'capture';\nconst NO_WRITE = () => {};\n\n/** Sizes the box through custom properties, which capture.css reads. */\nconst boxStyle = ({ width, height }: CapturePayload['box']): CSSProperties =>\n ({ ['--fg-capture-w' as string]: `${width}px`, ['--fg-capture-h' as string]: `${height}px` }) as CSSProperties;\n\n/**\n * Scrolls the story's scroller to where the screen's stood; a story still growing is scrolled again before the shot.\n * An isolated story scrolls its frame's document on screen, which the box itself stands in for here.\n */\nfunction scrollTo(host: HTMLElement | null, { left, top }: CapturePayload['scroll']) {\n const scroller = host?.querySelector<HTMLElement>(':scope > .fg-story__scroll') ?? host;\n if (!scroller) return;\n scroller.scrollLeft = left;\n scroller.scrollTop = top;\n}\n\n/** One story at the payload's playhead, config and state, writing nowhere. */\nfunction CapturedStory({ story, payload, setup }: { story: LoadedStory; payload: CapturePayload; setup: FrameSetup }) {\n const spec = useMemo(() => story.timeline?.(payload.config) ?? null, [story, payload.config]);\n const clock = useStoryClock(spec, () => payload.playhead);\n\n const state = useMemo(\n () => (payload.state === null && story.initialState ? story.initialState(payload.config) : payload.state),\n [payload.state, payload.config, story],\n );\n const ctx: StoryContext = {\n config: payload.config,\n setConfig: NO_WRITE,\n state,\n setState: NO_WRITE,\n globals: payload.globals,\n title: story.title,\n name: story.name,\n };\n return (\n <ClockContext.Provider value={clock}>\n <StoryHost story={story} ctx={ctx} decorators={setup.decorators ?? []} resetKey={0} onError={NO_WRITE} />\n </ClockContext.Provider>\n );\n}\n\n/**\n * One story, or a component's index page, rendered from a capture payload, still: a story's clock stands at the\n * payload's playhead and nothing plays it, and nothing it writes to its config or state goes anywhere. A story that would be in the workshop document\n * sits under a lab root themed as the lab is, as it does there; an isolated one sits in the frame document's own\n * wrapper.\n */\nexport function CaptureView({ subject, graph = null, payload, setup, labTheme, onRendered }: CaptureViewProps) {\n const [host, setHost] = useState<HTMLDivElement | null>(null);\n useHostConditions(host, { hostId: HOST_ID, globals: payload.globals, overrides: payload.overrides, setup });\n\n const latest = useLatest({ onRendered, host, scroll: payload.scroll });\n useLayoutEffect(() => scrollTo(host, payload.scroll), [host, payload.scroll]);\n const ticks = useRef(0);\n // A capture page is never looked at, and a headless page can count as hidden.\n const raf = useVisibleRaf(\n (_now, loop) => {\n ticks.current += 1;\n scrollTo(latest.current.host, latest.current.scroll);\n if (ticks.current < 2) loop.request();\n else latest.current.onRendered();\n },\n { dangerouslyRunWhenHidden: true },\n );\n useEffect(() => {\n if (!host) return;\n let canceled = false;\n const start = () => {\n if (!canceled) raf.request();\n };\n const { fonts } = host.ownerDocument;\n if (fonts) void fonts.ready.then(start, start);\n else start();\n return () => {\n canceled = true;\n raf.cancel();\n };\n }, [host, raf]);\n\n const content: ReactNode = !host ? null : subject.kind === 'story' ? (\n <CapturedStory story={subject.story} payload={payload} setup={setup} />\n ) : (\n <IndexPage\n env={indexEnvOf(subject.bundle, { graph, globals: payload.globals, decorators: setup.decorators ?? [], open: NO_WRITE })}\n render={subject.bundle.render}\n />\n );\n\n const box = (\n <div\n ref={setHost}\n className=\"fg-story\"\n data-fg-host={HOST_ID}\n data-fg-capture=\"\"\n data-fg-layout={payload.layout}\n style={boxStyle(payload.box)}\n >\n {payload.isolate ? (\n <div className={`fg-frame fg-frame--${payload.layout}`}>{content}</div>\n ) : (\n <div className=\"fg-story__scroll\">\n {host ? (\n <OverlayPortalProvider container={host} contained>\n {content}\n </OverlayPortalProvider>\n ) : null}\n </div>\n )}\n </div>\n );\n if (payload.isolate) return box;\n return (\n <ThemeProvider\n theme={labTheme?.(payload.lab.globals) ?? interstellarTheme}\n selection={{ mode: payload.lab.mode, density: LAB_DENSITY }}\n >\n <LabRoot>{box}</LabRoot>\n </ThemeProvider>\n );\n}\n","import type { Theme } from '@weasel-js/theme';\nimport { Component, type ReactNode } from 'react';\nimport { createKitRoot } from '../../kitIcons';\nimport type { Globals } from '../../protocol/messages';\nimport { loadIndexBundle, type Loaded } from '../../story/indexBundle';\nimport { isIndexId } from '../../story/indexPages';\nimport { LibrariesContext, type Library, librariesFrom } from '../../story/library';\nimport { loadStories } from '../../story/load';\nimport type { DepGraph, IndexEntry } from '../../story/types';\nimport type { CapturePayload } from '../../vite/capture/payload';\nimport type { FrameSetup } from '../FrameController';\nimport type { FrameImporters } from '../mountFrame';\nimport { CaptureView } from './CaptureView';\n\n/** Inputs to `mountCapture`, as a capture page's entry module passes them. */\nexport interface MountCaptureOptions {\n index: readonly IndexEntry[];\n importers: FrameImporters;\n setup: FrameSetup;\n /** The shell config's `labTheme`; only the shell's capture page has one. */\n labTheme?: ((globals: Globals) => Theme) | undefined;\n /** The shell config's `libraries`, which an index page's header names and tints. */\n libraries?: readonly Library[] | undefined;\n /** The component graph an index page reads its dependencies and history from, asked for at its first capture. */\n dependencies?: (() => Promise<DepGraph>) | undefined;\n}\n\ndeclare global {\n interface Window {\n /** Set by `mountCapture`: renders one payload and resolves once it has painted. */\n __forgeCapture?: { render(payload: CapturePayload): Promise<void> };\n }\n}\n\n/** Catches what throws outside the story's own boundary, which would otherwise unmount the root and leave the\n * render waiting forever. */\nclass CaptureBoundary extends Component<{ onError: (error: unknown) => void; children: ReactNode }, { failed: boolean }> {\n override state = { failed: false };\n\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true };\n }\n\n override componentDidCatch(error: unknown): void {\n this.props.onError(error);\n }\n\n override render(): ReactNode {\n return this.state.failed ? null : this.props.children;\n }\n}\n\n/**\n * A capture page's entry: exposes `window.__forgeCapture.render(payload)`, which loads the payload's story, or the\n * index page its index id names, renders it afresh into `#root`, and resolves once it has painted. Rejects for an id\n * the index does not hold, and with whatever throws outside the story's own error boundary.\n */\nexport function mountCapture(options: MountCaptureOptions): void {\n const { index, importers, setup, labTheme } = options;\n const libraries = librariesFrom(options.libraries);\n const container = document.getElementById('root') ?? document.body;\n const root = createKitRoot(container, setup.icons);\n const prepared = new Map<string, Promise<Loaded>>();\n let graph: Promise<DepGraph | null> | null = null;\n let renders = 0;\n\n const importOf = (file: string): Promise<Record<string, unknown>> => {\n const importer = importers[file];\n return importer ? importer() : Promise.reject(new Error(`No importer for ${file}`));\n };\n const loadStory = async (id: string): Promise<Loaded> => {\n const entry = index.find((e) => e.id === id);\n if (!entry) throw new Error(`No story with id \"${id}\"`);\n const story = loadStories(await importOf(entry.file), entry.title, setup.parameters).find(\n (s) => s.exportName === entry.exportName,\n );\n if (!story) throw new Error(`${entry.file} has no story export \"${entry.exportName}\"`);\n await setup.prepare?.(story);\n return { kind: 'story', story };\n };\n const loadIndex = async (id: string): Promise<Loaded> => {\n const source = { index, importOf, parameters: setup.parameters, prepare: setup.prepare, libraries };\n return { kind: 'index', bundle: await loadIndexBundle(id, source) };\n };\n const subjectOf = (id: string): Promise<Loaded> => {\n let loading = prepared.get(id);\n if (!loading) {\n loading = isIndexId(id) ? loadIndex(id) : loadStory(id);\n prepared.set(id, loading);\n loading.catch(() => prepared.delete(id));\n }\n return loading;\n };\n // An index page without its graph still shows its stories; the screen shows it the same way until the graph lands.\n const graphOf = (): Promise<DepGraph | null> => {\n graph ??= options.dependencies ? options.dependencies().catch(() => null) : Promise.resolve(null);\n return graph;\n };\n\n window.__forgeCapture = {\n async render(payload) {\n const subject = await subjectOf(payload.story);\n const deps = subject.kind === 'index' ? await graphOf() : null;\n renders += 1;\n await new Promise<void>((resolve, reject) => {\n // Keyed per render, so a payload never inherits the last one's clock or state.\n root.render(\n <CaptureBoundary key={renders} onError={reject}>\n <LibrariesContext.Provider value={libraries}>\n <CaptureView\n subject={subject}\n graph={deps}\n payload={payload}\n setup={setup}\n labTheme={labTheme}\n onRendered={resolve}\n />\n </LibrariesContext.Provider>\n </CaptureBoundary>,\n );\n });\n },\n };\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  import { ConfigSchema } from '@weasel-js/labkit/config';
2
2
  export { f } from '@weasel-js/labkit/config';
3
- export { F as FOLLOW_APP, G as GlobalDeclaration, a as GlobalDeclarations, L as LabChrome, b as Library, S as ShellConfig, d as defineFrameConfig, c as defineShellConfig } from './config-Mg05Ja9r.js';
3
+ export { F as FOLLOW_APP, G as GlobalDeclaration, a as GlobalDeclarations, L as LabChrome, S as ShellConfig, d as defineFrameConfig, b as defineShellConfig } from './config-6fWf87Tt.js';
4
4
  import { ComponentType, ReactNode } from 'react';
5
- import { G as Globals, M as MetaSpec, d as StorySpec, e as ClockState, f as SpanOverride } from './FrameController-CdnaIo4C.js';
6
- export { A as A11yFinding, g as A11yNode, h as A11yReport, i as ComponentDeps, j as ComponentHistory, D as Decorator, k as DepGraph, F as FrameSetup, l as GlobalsTarget, m as IndexContext, n as IndexRender, o as IndexStoryProps, p as LoadedStory, P as PlayContext, q as StoryContext, L as StoryLayout, V as StoryViewport, t as TimelineSpan, u as TimelineSpec } from './FrameController-CdnaIo4C.js';
5
+ import { G as Globals, M as MetaSpec, d as StorySpec, e as ClockState, f as SpanOverride } from './FrameController-DgfVaENb.js';
6
+ export { A as A11yFinding, g as A11yNode, h as A11yReport, i as ComponentDeps, j as ComponentHistory, k as Decorator, D as DepGraph, F as FrameSetup, l as GlobalsTarget, m as IndexContext, n as IndexRender, o as IndexStoryProps, p as LoadedStory, P as PlayContext, q as StoryContext, L as StoryLayout, V as StoryViewport, t as TimelineSpan, u as TimelineSpec } from './FrameController-DgfVaENb.js';
7
+ export { L as Library } from './library-CdTj-hFp.js';
7
8
  import '@weasel-js/labkit';
8
9
  import '@weasel-js/theme';
9
10
  import '@weasel-js/icons';
10
- import '@weasel-js/ui/stance';
11
+ import '@weasel-js/ui/appearance';
11
12
 
12
13
  /** Storybook's conditional control: shown only while an arg, or a global, meets the test. */
13
14
  type ArgCondition = ({
@@ -20,10 +21,31 @@ type ArgCondition = ({
20
21
  eq?: unknown;
21
22
  neq?: unknown;
22
23
  };
24
+ /**
25
+ * Storybook's `SBType`, as far as forge reads it: the shape of an arg's value. A control is built from the parts of
26
+ * an array, an object or a union, and a union of objects that each pin one field to a string is edited as a choice
27
+ * of that string, with the chosen object's own fields under it.
28
+ */
29
+ type ArgShape = {
30
+ name: 'boolean' | 'string' | 'number';
31
+ } | {
32
+ name: 'enum';
33
+ value: readonly string[];
34
+ } | {
35
+ name: 'array';
36
+ value: ArgShape;
37
+ } | {
38
+ name: 'object';
39
+ value: Readonly<Record<string, ArgShape>>;
40
+ } | {
41
+ name: 'union';
42
+ value: readonly ArgShape[];
43
+ };
23
44
  /** A CSF `argTypes` entry, as far as forge reads it. */
24
45
  interface ArgType {
25
46
  name?: string;
26
47
  description?: string;
48
+ type?: ArgShape;
27
49
  control?: string | false | {
28
50
  type?: string;
29
51
  min?: number;
@@ -187,5 +209,7 @@ declare function useTimeline(): StoryTimeline;
187
209
 
188
210
  /** The meta tag marking a story file as a gallery: a catalog of many components, or of every permutation of one. */
189
211
  declare const GALLERY_TAG = "gallery";
212
+ /** The meta tag marking a story file as a lab: a whole screen for exercising a component, not a specimen of it. */
213
+ declare const LAB_TAG = "lab";
190
214
 
191
- export { type ArgCondition, type ArgType, type ArgsOf, type CsfDecorator, type CsfPlayContext, type CsfStep, type CsfStoryContext, type ForgeRoute, GALLERY_TAG, type KnobLeaf, type KnobPath, type Meta, MetaSpec, RESERVED_PARAMS, SpanOverride, Globals as StoryGlobals, type StoryObj, StorySpec, type StoryTimeline, decodeKnob, encodeKnob, formatRoute, knobParams, knobPaths, knobsToParams, meta, paramsToKnobs, parseRoute, reservedParams, story, storyHref, usePlayhead, useTimeline };
215
+ export { type ArgCondition, type ArgShape, type ArgType, type ArgsOf, type CsfDecorator, type CsfPlayContext, type CsfStep, type CsfStoryContext, type ForgeRoute, GALLERY_TAG, type KnobLeaf, type KnobPath, LAB_TAG, type Meta, MetaSpec, RESERVED_PARAMS, SpanOverride, Globals as StoryGlobals, type StoryObj, StorySpec, type StoryTimeline, decodeKnob, encodeKnob, formatRoute, knobParams, knobPaths, knobsToParams, meta, paramsToKnobs, parseRoute, reservedParams, story, storyHref, usePlayhead, useTimeline };
package/dist/index.js CHANGED
@@ -1,8 +1,8 @@
1
- export { RESERVED_PARAMS, decodeKnob, encodeKnob, formatRoute, knobParams, knobPaths, knobsToParams, paramsToKnobs, parseRoute, reservedParams, storyHref } from './chunk-LTTEILXY.js';
2
- export { GALLERY_TAG } from './chunk-WEQSLPKT.js';
1
+ export { RESERVED_PARAMS, decodeKnob, encodeKnob, formatRoute, knobParams, knobPaths, knobsToParams, paramsToKnobs, parseRoute, reservedParams, storyHref } from './chunk-COT4I347.js';
2
+ export { GALLERY_TAG, LAB_TAG } from './chunk-VUPN73JP.js';
3
3
  export { FOLLOW_APP } from './chunk-3BAM6M26.js';
4
4
  export { meta, story, usePlayhead, useTimeline } from './chunk-L5XM5VKB.js';
5
- import './chunk-GH5RE5X5.js';
5
+ import './chunk-2ZBZRBHI.js';
6
6
  export { f } from '@weasel-js/labkit/config';
7
7
 
8
8
  // src/config.ts