@weasel-js/forge 1.13.0-rc.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 (40) hide show
  1. package/dist/{FrameController-Tv3jrHyT.d.ts → FrameController-DgfVaENb.d.ts} +13 -1
  2. package/dist/{chunk-GH5RE5X5.js → chunk-2ZBZRBHI.js} +2 -2
  3. package/dist/{chunk-GH5RE5X5.js.map → chunk-2ZBZRBHI.js.map} +1 -1
  4. package/dist/{chunk-KEQBGDUZ.js → chunk-7XJNVJB5.js} +3 -3
  5. package/dist/{chunk-KEQBGDUZ.js.map → chunk-7XJNVJB5.js.map} +1 -1
  6. package/dist/{chunk-LTTEILXY.js → chunk-COT4I347.js} +3 -3
  7. package/dist/{chunk-LTTEILXY.js.map → chunk-COT4I347.js.map} +1 -1
  8. package/dist/{chunk-35DOPXHZ.js → chunk-GHPMNT2A.js} +13 -10
  9. package/dist/chunk-GHPMNT2A.js.map +1 -0
  10. package/dist/{chunk-STF6NQ5N.js → chunk-RVJHUY7W.js} +2 -2
  11. package/dist/chunk-RVJHUY7W.js.map +1 -0
  12. package/dist/{chunk-BUXUWAI4.js → chunk-WFT5IOHX.js} +61 -8
  13. package/dist/chunk-WFT5IOHX.js.map +1 -0
  14. package/dist/{chunk-RKQ277P5.js → chunk-XIBKYSRU.js} +5 -4
  15. package/dist/chunk-XIBKYSRU.js.map +1 -0
  16. package/dist/{config-Bd6FVlh7.d.ts → config-6fWf87Tt.d.ts} +3 -21
  17. package/dist/csf/preview-api.js +2 -2
  18. package/dist/frame/index.d.ts +14 -8
  19. package/dist/frame/index.js +109 -77
  20. package/dist/frame/index.js.map +1 -1
  21. package/dist/index.d.ts +4 -3
  22. package/dist/index.js +2 -2
  23. package/dist/library-CdTj-hFp.d.ts +21 -0
  24. package/dist/{mountFrame-FdJDb3TB.d.ts → mountFrame-Bs7u1ro-.d.ts} +1 -1
  25. package/dist/shell/index.css +2 -3
  26. package/dist/shell/index.css.map +1 -1
  27. package/dist/shell/index.d.ts +5 -4
  28. package/dist/shell/index.js +150 -94
  29. package/dist/shell/index.js.map +1 -1
  30. package/dist/test/index.css +2 -3
  31. package/dist/test/index.css.map +1 -1
  32. package/dist/test/index.d.ts +1 -1
  33. package/dist/test/index.js +4 -4
  34. package/dist/vite/index.js +9 -2
  35. package/dist/vite/index.js.map +1 -1
  36. package/package.json +9 -9
  37. package/dist/chunk-35DOPXHZ.js.map +0 -1
  38. package/dist/chunk-BUXUWAI4.js.map +0 -1
  39. package/dist/chunk-RKQ277P5.js.map +0 -1
  40. package/dist/chunk-STF6NQ5N.js.map +0 -1
@@ -1,20 +1,43 @@
1
- import { describeSchema, createKitRoot, openChannel, TITLE_LIBRARIES, LAB_DENSITY, answerSchema, IndexPage } from '../chunk-BUXUWAI4.js';
2
- import { isIndexId, indexId } from '../chunk-STF6NQ5N.js';
3
- import { taggedIds, isGallery } from '../chunk-VUPN73JP.js';
4
- import { createOverrides, createGlobalsTarget, createA11yHighlighter, loadStories, indexRenderOf, scanCssVars, auditElement, runAxe, useHostConditions, useStoryClock, StoryHost, resolveCssVar } from '../chunk-35DOPXHZ.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';
5
5
  import { ClockContext } from '../chunk-L5XM5VKB.js';
6
6
  import '../chunk-5WS67HMU.js';
7
- import '../chunk-KEQBGDUZ.js';
8
- 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';
9
9
  import { flushSync } from 'react-dom';
10
10
  import { jsx } from 'react/jsx-runtime';
11
11
  import { f } from '@weasel-js/labkit/config';
12
- import { Component, useState, useMemo, useLayoutEffect, useRef, useEffect } from 'react';
12
+ import { Component, useState, useLayoutEffect, useRef, useEffect, useMemo } from 'react';
13
13
  import { useLatest, useVisibleRaf } from '@weasel-js/core';
14
14
  import { interstellarTheme, LabRoot } from '@weasel-js/labkit';
15
15
  import { ThemeProvider } from '@weasel-js/theme/react';
16
16
  import { OverlayPortalProvider } from '@weasel-js/ui/portal-host';
17
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
+ }
18
41
  var VARS_SETTLE_MS = 100;
19
42
  function fault(phase, error, seq) {
20
43
  return {
@@ -25,6 +48,15 @@ function fault(phase, error, seq) {
25
48
  ...seq === void 0 ? {} : { seq }
26
49
  };
27
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
+ }
28
60
  function startFrame({ story, channel, container, setup = {} }) {
29
61
  const { send } = channel;
30
62
  send({ type: "ready", schema: describeSchema(story.config), layout: story.layout, viewport: story.viewport });
@@ -102,19 +134,11 @@ function startFrame({ story, channel, container, setup = {} }) {
102
134
  }
103
135
  if (!rendered) {
104
136
  rendered = true;
105
- announceRendered();
137
+ announceRendered(send);
106
138
  }
107
139
  reportVars();
108
140
  };
109
- const announceRendered = () => {
110
- const { fonts } = document;
111
- if (!fonts) {
112
- send({ type: "rendered" });
113
- return;
114
- }
115
- const afterPaint = () => requestAnimationFrame(() => send({ type: "rendered" }));
116
- void fonts.ready.then(afterPaint, afterPaint);
117
- };
141
+ const scroll = followDocumentScroll(document, send);
118
142
  const audit = async (id) => send({ type: "a11y", id, ...await auditElement(wrapper) });
119
143
  const off = channel.on((msg) => {
120
144
  switch (msg.type) {
@@ -162,10 +186,14 @@ function startFrame({ story, channel, container, setup = {} }) {
162
186
  case "a11y.highlight":
163
187
  highlighter.show(msg.targets);
164
188
  break;
189
+ case "scroll":
190
+ scroll.apply(msg);
191
+ break;
165
192
  }
166
193
  });
167
194
  return () => {
168
195
  off();
196
+ scroll.dispose();
169
197
  mutations?.disconnect();
170
198
  clearTimeout(settleTimer);
171
199
  overrides.dispose();
@@ -204,23 +232,14 @@ function startIndex(options) {
204
232
  let announced = false;
205
233
  const render = () => {
206
234
  if (!globals) return;
207
- const env = {
208
- title: options.title,
209
- ...options.library === void 0 ? {} : { library: options.library },
210
- ...options.description === void 0 ? {} : { description: options.description },
211
- stories: options.stories,
212
- descriptions: options.descriptions,
213
- gallery: options.gallery ?? false,
214
- galleries: options.galleries ?? [],
215
- labs: options.labs ?? [],
235
+ const env = indexEnvOf(options.bundle, {
236
+ graph: null,
216
237
  globals,
217
238
  decorators: setup.decorators ?? [],
218
- open: (id) => send({ type: "open", id }),
219
- // A story that throws shows its error in its own cell; the rest of the page is still worth reading.
220
- onError: (error) => console.error(error)
221
- };
239
+ open: (id) => send({ type: "open", id })
240
+ });
222
241
  root.render(
223
- /* @__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 }) })
224
243
  );
225
244
  };
226
245
  const announce = () => {
@@ -299,33 +318,10 @@ async function mountFrame(options) {
299
318
  const container = document.getElementById("root") ?? document.body;
300
319
  try {
301
320
  if (isIndexId(id)) {
302
- const entries = entriesOf(id);
303
- const title = entries[0]?.title;
304
- if (title === void 0) throw new Error(`No component with index "${id}"`);
305
- const files = [...new Set(entries.map((e) => e.file))];
306
- const mods = await Promise.all(files.map(importOf));
307
- const loaded = files.map((file, i) => ({
308
- file,
309
- stories: (options.load ?? loadStories)(mods[i] ?? {}, title, options.setup?.parameters)
310
- }));
311
- const stories2 = entries.flatMap(
312
- (e) => loaded.find((l) => l.file === e.file)?.stories.find((s) => s.exportName === e.exportName) ?? []
313
- );
314
- for (const story2 of stories2) await options.setup?.prepare?.(story2);
315
- startIndex({
316
- title,
317
- ...entries[0]?.componentDescription === void 0 ? {} : { description: entries[0].componentDescription },
318
- // The project's library table is the shell config's, which a frame document does not load.
319
- library: TITLE_LIBRARIES.of({ file: entries[0]?.file ?? "", title }),
320
- gallery: entries.every(isGallery),
321
- ...taggedIds(entries),
322
- stories: stories2,
323
- descriptions: Object.fromEntries(entries.flatMap((e) => e.description ? [[e.id, e.description]] : [])),
324
- render: mods.map(indexRenderOf).find((render) => render !== null) ?? null,
325
- channel,
326
- container,
327
- ...options.setup ? { setup: options.setup } : {}
328
- });
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 } : {} });
329
325
  return;
330
326
  }
331
327
  const entry = options.index.find((e) => e.id === id);
@@ -345,14 +341,12 @@ var NO_WRITE = () => {
345
341
  };
346
342
  var boxStyle = ({ width, height }) => ({ ["--fg-capture-w"]: `${width}px`, ["--fg-capture-h"]: `${height}px` });
347
343
  function scrollTo(host, { left, top }) {
348
- const scroller = host?.querySelector(":scope > .fg-story__scroll");
344
+ const scroller = host?.querySelector(":scope > .fg-story__scroll") ?? host;
349
345
  if (!scroller) return;
350
346
  scroller.scrollLeft = left;
351
347
  scroller.scrollTop = top;
352
348
  }
353
- function CaptureView({ story, payload, setup, labTheme, onRendered }) {
354
- const [host, setHost] = useState(null);
355
- useHostConditions(host, { hostId: HOST_ID, globals: payload.globals, overrides: payload.overrides, setup });
349
+ function CapturedStory({ story, payload, setup }) {
356
350
  const spec = useMemo(() => story.timeline?.(payload.config) ?? null, [story, payload.config]);
357
351
  const clock = useStoryClock(spec, () => payload.playhead);
358
352
  const state = useMemo(
@@ -368,6 +362,11 @@ function CaptureView({ story, payload, setup, labTheme, onRendered }) {
368
362
  title: story.title,
369
363
  name: story.name
370
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 });
371
370
  const latest = useLatest({ onRendered, host, scroll: payload.scroll });
372
371
  useLayoutEffect(() => scrollTo(host, payload.scroll), [host, payload.scroll]);
373
372
  const ticks = useRef(0);
@@ -394,7 +393,13 @@ function CaptureView({ story, payload, setup, labTheme, onRendered }) {
394
393
  raf.cancel();
395
394
  };
396
395
  }, [host, raf]);
397
- 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
+ );
398
403
  const box = /* @__PURE__ */ jsx(
399
404
  "div",
400
405
  {
@@ -429,36 +434,63 @@ var CaptureBoundary = class extends Component {
429
434
  return this.state.failed ? null : this.props.children;
430
435
  }
431
436
  };
432
- function mountCapture({ index, importers, setup, labTheme }) {
437
+ function mountCapture(options) {
438
+ const { index, importers, setup, labTheme } = options;
439
+ const libraries = librariesFrom(options.libraries);
433
440
  const container = document.getElementById("root") ?? document.body;
434
441
  const root = createKitRoot(container, setup.icons);
435
442
  const prepared = /* @__PURE__ */ new Map();
443
+ let graph = null;
436
444
  let renders = 0;
437
- 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) => {
438
464
  let loading = prepared.get(id);
439
465
  if (!loading) {
440
- loading = (async () => {
441
- const entry = index.find((e) => e.id === id);
442
- if (!entry) throw new Error(`No story with id "${id}"`);
443
- const importer = importers[entry.file];
444
- if (!importer) throw new Error(`No importer for ${entry.file}`);
445
- const story = loadStories(await importer(), entry.title, setup.parameters).find((s) => s.exportName === entry.exportName);
446
- if (!story) throw new Error(`${entry.file} has no story export "${entry.exportName}"`);
447
- await setup.prepare?.(story);
448
- return story;
449
- })();
466
+ loading = isIndexId(id) ? loadIndex(id) : loadStory(id);
450
467
  prepared.set(id, loading);
451
468
  loading.catch(() => prepared.delete(id));
452
469
  }
453
470
  return loading;
454
471
  };
472
+ const graphOf = () => {
473
+ graph ??= options.dependencies ? options.dependencies().catch(() => null) : Promise.resolve(null);
474
+ return graph;
475
+ };
455
476
  window.__forgeCapture = {
456
477
  async render(payload) {
457
- const story = await storyOf(payload.story);
478
+ const subject = await subjectOf(payload.story);
479
+ const deps = subject.kind === "index" ? await graphOf() : null;
458
480
  renders += 1;
459
481
  await new Promise((resolve, reject) => {
460
482
  root.render(
461
- /* @__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)
462
494
  );
463
495
  });
464
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 /** The ids of the stories tagged `lab`. */\n labs?: 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 labs: options.labs ?? [],\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, taggedIds } 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 ...taggedIds(entries),\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":";;;;;;;;;;;;;;;;;;AAYO,SAAS,oBAAA,CAAqB,KAAe,IAAA,EAAgD;AAClG,EAAA,MAAM,QAAA,GAAW,GAAA,CAAI,gBAAA,IAAoB,GAAA,CAAI,eAAA;AAC7C,EAAA,MAAM,OAAO,GAAA,CAAI,WAAA;AACjB,EAAA,IAAI,QAAA,GAA0B,IAAA;AAC9B,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,MAAM,OAAO,QAAA,CAAS,UAAA;AACtB,IAAA,MAAM,MAAM,QAAA,CAAS,SAAA;AACrB,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,GAAG,CAAA,CAAA;AAC1B,IAAA,IAAI,QAAQ,QAAA,EAAU;AACtB,IAAA,QAAA,GAAW,GAAA;AACX,IAAA,IAAA,CAAK,EAAE,IAAA,EAAM,QAAA,EAAU,IAAA,EAAM,KAAK,CAAA;AAAA,EACpC,CAAA;AACA,EAAA,MAAA,EAAO;AACP,EAAA,IAAA,EAAM,iBAAiB,QAAA,EAAU,MAAA,EAAQ,EAAE,OAAA,EAAS,MAAM,CAAA;AAC1D,EAAA,OAAO;AAAA,IACL,KAAA,CAAM,EAAE,IAAA,EAAM,GAAA,EAAI,EAAG;AACnB,MAAA,QAAA,CAAS,UAAA,GAAa,IAAA;AACtB,MAAA,QAAA,CAAS,SAAA,GAAY,GAAA;AAAA,IACvB,CAAA;AAAA,IACA,OAAA,EAAS,MAAM,IAAA,EAAM,mBAAA,CAAoB,UAAU,MAAM;AAAA,GAC3D;AACF;ACmBA,IAAM,cAAA,GAAiB,GAAA;AAEvB,SAAS,KAAA,CAAM,KAAA,EAAmB,KAAA,EAAgB,GAAA,EAAyB;AACzE,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,OAAA;AAAA,IACN,KAAA;AAAA,IACA,SAAS,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAAA,IAC9D,GAAI,KAAA,YAAiB,KAAA,IAAS,KAAA,CAAM,KAAA,GAAQ,EAAE,KAAA,EAAO,KAAA,CAAM,KAAA,EAAM,GAAI,EAAC;AAAA,IACtE,GAAI,GAAA,KAAQ,MAAA,GAAY,EAAC,GAAI,EAAE,GAAA;AAAI,GACrC;AACF;AAWA,SAAS,iBAAiB,IAAA,EAAsC;AAC9D,EAAA,MAAM,EAAE,OAAM,GAAI,QAAA;AAClB,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,IAAA,CAAK,EAAE,IAAA,EAAM,UAAA,EAAY,CAAA;AACzB,IAAA;AAAA,EACF;AACA,EAAA,MAAM,UAAA,GAAa,MAAM,qBAAA,CAAsB,MAAM,KAAK,EAAE,IAAA,EAAM,UAAA,EAAY,CAAC,CAAA;AAC/E,EAAA,KAAK,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,UAAA,EAAY,UAAU,CAAA;AAC9C;AAGO,SAAS,UAAA,CAAW,EAAE,KAAA,EAAO,OAAA,EAAS,WAAW,KAAA,GAAQ,IAAG,EAAkC;AACnG,EAAA,MAAM,EAAE,MAAK,GAAI,OAAA;AACjB,EAAA,IAAA,CAAK,EAAE,IAAA,EAAM,OAAA,EAAS,MAAA,EAAQ,eAAe,KAAA,CAAM,MAAM,CAAA,EAAG,MAAA,EAAQ,KAAA,CAAM,MAAA,EAAQ,QAAA,EAAU,KAAA,CAAM,UAAU,CAAA;AAE5G,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC5C,EAAA,OAAA,CAAQ,SAAA,GAAY,CAAA,mBAAA,EAAsB,KAAA,CAAM,MAAM,CAAA,CAAA;AACtD,EAAA,SAAA,CAAU,OAAO,OAAO,CAAA;AACxB,EAAA,MAAM,IAAA,GAAO,aAAA,CAAc,OAAA,EAAS,KAAA,CAAM,KAAK,CAAA;AAC/C,EAAA,MAAM,UAAA,GAAa,KAAA,CAAM,UAAA,IAAc,EAAC;AAExC,EAAA,IAAI,WAAA,GAAc,KAAA;AAClB,EAAA,IAAI,QAAA,GAAW,KAAA;AACf,EAAA,IAAI,MAAA;AACJ,EAAA,IAAI,KAAA,GAAiB,IAAA;AACrB,EAAA,IAAI,UAAmB,EAAC;AACxB,EAAA,IAAI,WAAA,GAA6B,IAAA;AACjC,EAAA,IAAI,QAAA,GAAW,CAAA;AACf,EAAA,IAAI,GAAA,GAAM,CAAA;AAEV,EAAA,MAAM,SAAA,GAAY,eAAA,CAAgB,QAAA,EAAU,KAAA,CAAM,YAAY,CAAA;AAC9D,EAAA,MAAM,aAAA,GAAgB,mBAAA,CAAoB,QAAA,CAAS,eAAA,EAAiB,OAAO,CAAA;AAC3E,EAAA,MAAM,WAAA,GAAc,sBAAsB,QAAQ,CAAA;AAClD,EAAA,IAAI,QAAA,GAAkC,IAAA;AACtC,EAAA,IAAI,QAAA,GAA0B,IAAA;AAC9B,EAAA,MAAM,WAAA,GAAc,CAAC,IAAA,KAAyB;AAC5C,IAAA,QAAA,GAAW,IAAA;AACX,IAAA,MAAM,GAAA,GAAM,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA;AAC/B,IAAA,IAAI,QAAQ,QAAA,EAAU;AACtB,IAAA,QAAA,GAAW,GAAA;AACX,IAAA,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,CAAA;AAAA,EAC7B,CAAA;AACA,EAAA,MAAM,aAAa,MAAM,WAAA,CAAY,YAAY,QAAA,EAAU,SAAA,CAAU,GAAG,CAAC,CAAA;AACzE,EAAA,MAAM,WAAA,GAAc,CAAC,MAAA,KACnB,SAAA,CAAU,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA,IAC3B,MAAA,CAAO,IAAA,KAAS,WAAA,IACf,CAAC,GAAG,MAAA,CAAO,UAAA,EAAY,GAAG,MAAA,CAAO,YAAY,CAAA,CAAE,MAAA,GAAS,CAAA,IACxD,CAAC,GAAG,MAAA,CAAO,UAAA,EAAY,GAAG,MAAA,CAAO,YAAY,CAAA,CAAE,KAAA,CAAM,UAAU,IAAI,CAAA;AACvE,EAAA,IAAI,WAAA;AACJ,EAAA,MAAM,SAAA,GACJ,OAAO,gBAAA,KAAqB,WAAA,GACxB,OACA,IAAI,gBAAA,CAAiB,CAAC,OAAA,KAAY;AAChC,IAAA,IAAI,OAAA,CAAQ,KAAA,CAAM,WAAW,CAAA,EAAG;AAChC,IAAA,YAAA,CAAa,WAAW,CAAA;AACxB,IAAA,WAAA,GAAc,UAAA,CAAW,YAAY,cAAc,CAAA;AAAA,EACrD,CAAC,CAAA;AAEP,EAAA,SAAA,EAAW,OAAA,CAAQ,QAAA,CAAS,eAAA,EAAiB,EAAE,OAAA,EAAS,IAAA,EAAM,SAAA,EAAW,IAAA,EAAM,aAAA,EAAe,IAAA,EAAM,UAAA,EAAY,IAAA,EAAM,CAAA;AAEtH,EAAA,MAAM,SAAA,GAAY,CAAC,IAAA,EAAc,KAAA,KAAmB,IAAA,CAAK,EAAE,IAAA,EAAM,WAAA,EAAa,IAAA,EAAM,KAAA,EAAO,CAAA;AAC3F,EAAA,MAAM,QAAA,GAAW,CAAC,IAAA,KAAkB;AAClC,IAAA,KAAA,GAAQ,OAAO,IAAA,KAAS,UAAA,GAAc,IAAA,CAAoC,KAAK,CAAA,GAAI,IAAA;AACnF,IAAA,IAAA,CAAK,EAAE,IAAA,EAAM,UAAA,EAAY,KAAA,EAAO,CAAA;AAChC,IAAA,MAAA,EAAO;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,SAAS,MAAM;AACnB,IAAA,MAAM,GAAA,GAAoB,EAAE,MAAA,EAAQ,SAAA,EAAW,KAAA,EAAO,QAAA,EAAU,OAAA,EAAS,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,IAAA,EAAM,KAAA,CAAM,IAAA,EAAK;AAC9G,IAAA,MAAM,EAAA,GAAK,GAAA;AACX,IAAA,IAAA,CAAK,MAAA;AAAA,sBACH,GAAA;AAAA,QAAC,SAAA;AAAA,QAAA;AAAA,UACC,KAAA;AAAA,UACA,GAAA;AAAA,UACA,UAAA;AAAA,UACA,QAAA;AAAA,UACA,OAAA,EAAS,CAAC,KAAA,KAAU,IAAA,CAAK,MAAM,QAAA,EAAU,KAAA,EAAO,EAAE,CAAC;AAAA;AAAA;AACrD,KACF;AACA,IAAA,MAAM,GAAA,GAAM,gBAAgB,MAAM,CAAA;AAClC,IAAA,IAAI,QAAQ,WAAA,EAAa;AACvB,MAAA,WAAA,GAAc,GAAA;AACd,MAAA,IAAA,CAAK,EAAE,IAAA,EAAM,SAAA,EAAW,OAAA,EAAS,EAAE,SAAA,EAAW,GAAA,EAAK,GAAG,YAAA,CAAa,KAAA,CAAM,MAAA,EAAQ,MAAM,CAAA,IAAK,CAAA;AAAA,IAC9F;AAAA,EACF,CAAA;AAIA,EAAA,MAAM,KAAA,GAAQ,CAAC,KAAA,KAAsB;AACnC,IAAA,GAAA,IAAO,CAAA;AACP,IAAA,IAAI;AACF,MAAA,KAAA,EAAM;AACN,MAAA,IAAI,CAAC,WAAA,EAAa;AAClB,MAAA,QAAA,IAAY,CAAA;AACZ,MAAA,SAAA,CAAU,MAAM,CAAA;AAAA,IAClB,SAAS,KAAA,EAAO;AACd,MAAA,IAAA,CAAK,KAAA,CAAM,QAAA,EAAU,KAAA,EAAO,GAAG,CAAC,CAAA;AAChC,MAAA;AAAA,IACF;AACA,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,gBAAA,CAAiB,IAAI,CAAA;AAAA,IACvB;AACA,IAAA,UAAA,EAAW;AAAA,EACb,CAAA;AAEA,EAAA,MAAM,MAAA,GAAS,oBAAA,CAAqB,QAAA,EAAU,IAAI,CAAA;AAElD,EAAA,MAAM,KAAA,GAAQ,OAAO,EAAA,KAAe,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,EAAA,EAAI,GAAI,MAAM,YAAA,CAAa,OAAO,GAAI,CAAA;AAE/F,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,EAAA,CAAG,CAAC,GAAA,KAAQ;AAC9B,IAAA,QAAQ,IAAI,IAAA;AAAM,MAChB,KAAK,MAAA;AACH,QAAA,KAAA,CAAM,MAAM;AACV,UAAA,WAAA,GAAc,IAAA;AACd,UAAA,MAAA,GAAS,GAAA,CAAI,MAAA;AACb,UAAA,OAAA,GAAU,GAAA,CAAI,OAAA;AACd,UAAA,KAAA,GAAQ,GAAA,CAAI,KAAA;AACZ,UAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,CAAM,YAAA,EAAc;AACxC,YAAA,KAAA,GAAQ,KAAA,CAAM,aAAa,MAAM,CAAA;AACjC,YAAA,IAAA,CAAK,EAAE,IAAA,EAAM,UAAA,EAAY,KAAA,EAAO,CAAA;AAAA,UAClC;AACA,UAAA,KAAA,CAAM,YAAA,GAAe,SAAS,aAAa,CAAA;AAAA,QAC7C,CAAC,CAAA;AACD,QAAA;AAAA,MACF,KAAK,QAAA;AACH,QAAA,KAAA,CAAM,MAAM;AACV,UAAA,MAAA,GAAS,GAAA,CAAI,MAAA;AAAA,QACf,CAAC,CAAA;AACD,QAAA;AAAA,MACF,KAAK,OAAA;AACH,QAAA,KAAA,CAAM,MAAM;AACV,UAAA,KAAA,GAAQ,GAAA,CAAI,KAAA;AAAA,QACd,CAAC,CAAA;AACD,QAAA;AAAA,MACF,KAAK,SAAA;AACH,QAAA,KAAA,CAAM,MAAM;AACV,UAAA,OAAA,GAAU,GAAA,CAAI,OAAA;AACd,UAAA,KAAA,CAAM,YAAA,GAAe,SAAS,aAAa,CAAA;AAAA,QAC7C,CAAC,CAAA;AACD,QAAA;AAAA,MACF,KAAK,UAAA,EAAY;AACf,QAAA,SAAA,CAAU,GAAA,CAAI,GAAA,CAAI,IAAA,EAAM,GAAA,CAAI,KAAK,CAAA;AACjC,QAAA,MAAM,EAAA,GAAK,UAAU,SAAA,CAAU,CAAC,MAAM,CAAA,CAAE,IAAA,KAAS,GAAA,CAAI,IAAI,CAAA,IAAK,EAAA;AAC9D,QAAA,IAAI,CAAC,QAAA,IAAY,EAAA,GAAK,CAAA,EAAG;AACzB,QAAA,MAAM,IAAA,GAAO,SAAS,KAAA,EAAM;AAC5B,QAAA,IAAA,CAAK,EAAE,CAAA,GAAI,EAAE,GAAG,IAAA,CAAK,EAAE,GAAI,KAAA,EAAO,aAAA,CAAc,QAAA,EAAU,GAAA,CAAI,IAAI,CAAA,EAAG,UAAA,EAAY,UAAU,GAAA,CAAI,GAAA,CAAI,IAAI,CAAA,EAAE;AACzG,QAAA,WAAA,CAAY,IAAI,CAAA;AAChB,QAAA;AAAA,MACF;AAAA,MACA,KAAK,UAAA;AACH,QAAA,KAAK,KAAA,CAAM,IAAI,EAAE,CAAA;AACjB,QAAA;AAAA,MACF,KAAK,gBAAA;AACH,QAAA,WAAA,CAAY,IAAA,CAAK,IAAI,OAAO,CAAA;AAC5B,QAAA;AAAA,MACF,KAAK,QAAA;AACH,QAAA,MAAA,CAAO,MAAM,GAAG,CAAA;AAChB,QAAA;AAAA;AACJ,EACF,CAAC,CAAA;AAED,EAAA,OAAO,MAAM;AACX,IAAA,GAAA,EAAI;AACJ,IAAA,MAAA,CAAO,OAAA,EAAQ;AACf,IAAA,SAAA,EAAW,UAAA,EAAW;AACtB,IAAA,YAAA,CAAa,WAAW,CAAA;AACxB,IAAA,SAAA,CAAU,OAAA,EAAQ;AAClB,IAAA,aAAA,CAAc,OAAA,EAAQ;AACtB,IAAA,WAAA,CAAY,OAAA,EAAQ;AACpB,IAAA,IAAA,CAAK,OAAA,EAAQ;AACb,IAAA,OAAA,CAAQ,MAAA,EAAO;AAAA,EACjB,CAAA;AACF;AAGO,SAAS,iBAAA,CAAkB,SAAsC,KAAA,EAAsB;AAC5F,EAAA,OAAA,CAAQ,IAAA,CAAK,KAAA,CAAM,QAAA,EAAU,KAAK,CAAC,CAAA;AACrC;ACtOA,IAAM,OAAA,GAAU,CAAC,KAAA,KAA4B,KAAA,YAAiB,QAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAGlG,IAAM,YAAA,GAAN,cAA2B,SAAA,CAA2F;AAAA,EAC3G,KAAA,GAAQ,EAAE,MAAA,EAAQ,IAAA,EAAgB;AAAA,EAE3C,OAAO,yBAAyB,KAAA,EAAgB;AAC9C,IAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,IAAS,IAAI,KAAA,CAAM,mBAAmB,CAAA,EAAE;AAAA,EAC3D;AAAA,EAES,kBAAkB,KAAA,EAAsB;AAC/C,IAAA,IAAA,CAAK,KAAA,CAAM,QAAQ,KAAK,CAAA;AAAA,EAC1B;AAAA,EAES,MAAA,GAAoB;AAC3B,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,IAAA,GAAO,KAAK,KAAA,CAAM,QAAA;AAAA,EAC/C;AACF,CAAA;AAMO,SAAS,WAAW,OAAA,EAAwC;AACjE,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,KAAA,GAAQ,IAAG,GAAI,OAAA;AAC3C,EAAA,MAAM,EAAE,MAAK,GAAI,OAAA;AACjB,EAAA,IAAA,CAAK,EAAE,IAAA,EAAM,OAAA,EAAS,MAAA,EAAQ,eAAe,CAAA,CAAE,MAAA,CAAO,EAAE,CAAC,CAAA,EAAG,MAAA,EAAQ,YAAA,EAAc,QAAA,EAAU,MAAM,CAAA;AAElG,EAAA,MAAM,OAAA,GAAU,QAAA,CAAS,aAAA,CAAc,KAAK,CAAA;AAC5C,EAAA,OAAA,CAAQ,SAAA,GAAY,+BAAA;AACpB,EAAA,SAAA,CAAU,OAAO,OAAO,CAAA;AACxB,EAAA,MAAM,IAAA,GAAO,aAAA,CAAc,OAAA,EAAS,KAAA,CAAM,KAAK,CAAA;AAC/C,EAAA,MAAM,aAAA,GAAgB,mBAAA,CAAoB,QAAA,CAAS,eAAA,EAAiB,OAAO,CAAA;AAC3E,EAAA,IAAI,OAAA,GAA0B,IAAA;AAC9B,EAAA,IAAI,SAAA,GAAY,KAAA;AAEhB,EAAA,MAAM,SAAS,MAAY;AACzB,IAAA,IAAI,CAAC,OAAA,EAAS;AACd,IAAA,MAAM,GAAA,GAAM,UAAA,CAAW,OAAA,CAAQ,MAAA,EAAQ;AAAA,MACrC,KAAA,EAAO,IAAA;AAAA,MACP,OAAA;AAAA,MACA,UAAA,EAAY,KAAA,CAAM,UAAA,IAAc,EAAC;AAAA,MACjC,IAAA,EAAM,CAAC,EAAA,KAAO,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAI;AAAA,KACxC,CAAA;AACD,IAAA,IAAA,CAAK,MAAA;AAAA,sBACHA,GAAAA,CAAC,YAAA,EAAA,EAAa,OAAA,EAAS,CAAC,KAAA,KAAU,IAAA,CAAK,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,QAAA,EAAU,OAAA,EAAS,QAAQ,KAAK,CAAA,EAAG,CAAA,EAChG,QAAA,kBAAAA,GAAAA,CAAC,SAAA,EAAA,EAAU,GAAA,EAAU,MAAA,EAAQ,OAAA,CAAQ,MAAA,CAAO,MAAA,EAAQ,CAAA,EACtD;AAAA,KACF;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,WAAW,MAAY;AAC3B,IAAA,IAAI,SAAA,EAAW;AACf,IAAA,SAAA,GAAY,IAAA;AACZ,IAAA,MAAM,EAAE,OAAM,GAAI,QAAA;AAClB,IAAA,IAAI,CAAC,KAAA,EAAO;AACV,MAAA,IAAA,CAAK,EAAE,IAAA,EAAM,UAAA,EAAY,CAAA;AACzB,MAAA;AAAA,IACF;AACA,IAAA,MAAM,UAAA,GAAa,MAAM,qBAAA,CAAsB,MAAM,KAAK,EAAE,IAAA,EAAM,UAAA,EAAY,CAAC,CAAA;AAC/E,IAAA,KAAK,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,UAAA,EAAY,UAAU,CAAA;AAAA,EAC9C,CAAA;AAEA,EAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,EAAA,CAAG,CAAC,GAAA,KAAQ;AAC9B,IAAA,QAAQ,IAAI,IAAA;AAAM,MAChB,KAAK,MAAA;AAAA,MACL,KAAK,SAAA;AACH,QAAA,OAAA,GAAU,GAAA,CAAI,OAAA;AACd,QAAA,KAAA,CAAM,YAAA,GAAe,SAAS,aAAa,CAAA;AAC3C,QAAAC,UAAU,MAAM,CAAA;AAChB,QAAA,QAAA,EAAS;AACT,QAAA;AAAA,MACF,KAAK,UAAA;AACH,QAAA,MAAA,CAAO,OAAO,CAAA,CAAE,IAAA;AAAA,UACd,CAAC,MAAA,KAAW,IAAA,CAAK,EAAE,IAAA,EAAM,MAAA,EAAQ,EAAA,EAAI,GAAA,CAAI,EAAA,EAAI,EAAA,EAAI,IAAA,EAAM,MAAA,EAAQ,CAAA;AAAA,UAC/D,CAAC,KAAA,KAAmB,IAAA,CAAK,EAAE,MAAM,MAAA,EAAQ,EAAA,EAAI,GAAA,CAAI,EAAA,EAAI,IAAI,KAAA,EAAO,OAAA,EAAS,OAAA,CAAQ,KAAK,GAAG;AAAA,SAC3F;AACA,QAAA;AAEA;AACJ,EACF,CAAC,CAAA;AAED,EAAA,OAAO,MAAM;AACX,IAAA,GAAA,EAAI;AACJ,IAAA,aAAA,CAAc,OAAA,EAAQ;AACtB,IAAA,IAAA,CAAK,OAAA,EAAQ;AACb,IAAA,OAAA,CAAQ,MAAA,EAAO;AAAA,EACjB,CAAA;AACF;;;ACvEA,SAAS,cAAA,GAAmE;AAC1E,EAAA,OAAO,IAAI,OAAA,CAAQ,CAAC,OAAA,KAAY;AAC9B,IAAA,MAAM,SAAA,GAAY,CAAC,KAAA,KAAwB;AACzC,MAAA,MAAM,OAAO,KAAA,CAAM,IAAA;AACnB,MAAA,MAAM,IAAA,GAAO,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA;AAC1B,MAAA,IAAI,MAAM,MAAA,KAAW,QAAA,CAAS,UAAU,KAAA,CAAM,MAAA,KAAW,OAAO,MAAA,EAAQ;AACxE,MAAA,IAAI,OAAO,SAAS,QAAA,IAAY,IAAA,KAAS,QAAQ,IAAA,CAAK,IAAA,KAAS,YAAA,IAAgB,CAAC,IAAA,EAAM;AACtF,MAAA,MAAA,CAAO,mBAAA,CAAoB,WAAW,SAAS,CAAA;AAC/C,MAAA,OAAA,CAAQ,EAAE,IAAA,EAAM,EAAA,EAAI,OAAO,IAAA,CAAK,OAAO,QAAA,GAAW,IAAA,CAAK,EAAA,GAAK,IAAA,EAAM,CAAA;AAAA,IACpE,CAAA;AACA,IAAA,MAAA,CAAO,gBAAA,CAAiB,WAAW,SAAS,CAAA;AAAA,EAC9C,CAAC,CAAA;AACH;AAMA,eAAsB,WAAW,OAAA,EAA2C;AAC1E,EAAA,MAAM,OAAA,uBAAc,GAAA,EAA8C;AAClE,EAAA,MAAM,QAAA,GAAW,CAAC,IAAA,KAAmD;AACnE,IAAA,IAAI,OAAA,GAAU,OAAA,CAAQ,GAAA,CAAI,IAAI,CAAA;AAC9B,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,SAAA,CAAU,IAAI,CAAA;AACvC,MAAA,IAAI,CAAC,QAAA,EAAU,MAAM,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,IAAI,CAAA,CAAE,CAAA;AACxD,MAAA,OAAA,GAAU,QAAA,EAAS;AACnB,MAAA,OAAA,CAAQ,GAAA,CAAI,MAAM,OAAO,CAAA;AAAA,IAC3B;AACA,IAAA,OAAO,OAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,SAAA,GAAY,CAACC,GAAAA,KACjB,SAAA,CAAUA,GAAE,IACR,OAAA,CAAQ,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA,KAAM,OAAA,CAAQ,EAAE,KAAK,CAAA,KAAMA,GAAE,CAAA,GACnD,OAAA,CAAQ,KAAA,CAAM,OAAO,CAAC,CAAA,KAAM,CAAA,CAAE,EAAA,KAAOA,GAAE,CAAA;AAC7C,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,IAAK,IAAA;AAExC,EAAA,KAAA,MAAW,QAAQ,IAAI,GAAA,CAAI,KAAA,KAAU,IAAA,GAAO,EAAC,GAAI,SAAA,CAAU,KAAK,CAAA,CAAE,IAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAA,EAAG;AACrF,IAAA,IAAI,OAAA,CAAQ,UAAU,IAAI,CAAA,WAAY,IAAI,CAAA,CAAE,MAAM,MAAM;AAAA,IAAC,CAAC,CAAA;AAAA,EAC5D;AAEA,EAAA,MAAM,UAAU,cAAA,EAAe;AAC/B,EAAA,MAAA,CAAO,OAAO,WAAA,CAAY,EAAE,MAAM,WAAA,EAAY,EAAG,SAAS,MAAM,CAAA;AAChE,EAAA,MAAM,EAAE,IAAA,EAAM,EAAA,EAAI,MAAA,KAAW,MAAM,OAAA;AACnC,EAAA,MAAM,OAAA,GAAU,YAAgC,IAAI,CAAA;AACpD,EAAA,MAAM,EAAA,GAAK,UAAU,KAAA,IAAS,EAAA;AAC9B,EAAA,MAAM,SAAA,GAAY,QAAA,CAAS,cAAA,CAAe,MAAM,KAAK,QAAA,CAAS,IAAA;AAC9D,EAAA,IAAI;AACF,IAAA,IAAI,SAAA,CAAU,EAAE,CAAA,EAAG;AACjB,MAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,OAAA;AACxB,MAAA,MAAM,MAAA,GAAS,EAAE,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,QAAA,EAAU,IAAA,EAAM,UAAA,EAAY,KAAA,EAAO,UAAA,EAAY,OAAA,EAAS,KAAA,EAAO,OAAA,EAAQ;AAE9G,MAAA,MAAM,MAAA,GAAS,MAAM,eAAA,CAAgB,EAAA,EAAI,MAAM,CAAA;AAC/C,MAAA,UAAA,CAAW,EAAE,MAAA,EAAQ,OAAA,EAAS,SAAA,EAAW,GAAI,KAAA,GAAQ,EAAE,KAAA,EAAM,GAAI,EAAC,EAAI,CAAA;AACtE,MAAA;AAAA,IACF;AACA,IAAA,MAAM,KAAA,GAAQ,QAAQ,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AACnD,IAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,EAAE,CAAA,CAAA,CAAG,CAAA;AACtD,IAAA,MAAM,GAAA,GAAM,MAAM,QAAA,CAAS,KAAA,CAAM,IAAI,CAAA;AACrC,IAAA,MAAM,OAAA,GAAA,CAAW,QAAQ,IAAA,IAAQ,WAAA,EAAa,KAAK,KAAA,CAAM,KAAA,EAAO,OAAA,CAAQ,KAAA,EAAO,UAAU,CAAA;AACzF,IAAA,MAAM,KAAA,GAAQ,QAAQ,IAAA,CAAK,CAAC,MAAM,CAAA,CAAE,UAAA,KAAe,MAAM,UAAU,CAAA;AACnE,IAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,sBAAA,EAAyB,KAAA,CAAM,UAAU,CAAA,CAAA,CAAG,CAAA;AACrF,IAAA,MAAM,OAAA,CAAQ,KAAA,EAAO,OAAA,GAAU,KAAK,CAAA;AACpC,IAAA,UAAA,CAAW,EAAE,KAAA,EAAO,OAAA,EAAS,WAAW,KAAA,EAAO,OAAA,CAAQ,OAAO,CAAA;AAAA,EAChE,SAAS,KAAA,EAAO;AACd,IAAA,iBAAA,CAAkB,SAAS,KAAK,CAAA;AAAA,EAClC;AACF;ACxEA,IAAM,OAAA,GAAU,SAAA;AAChB,IAAM,WAAW,MAAM;AAAC,CAAA;AAGxB,IAAM,WAAW,CAAC,EAAE,OAAO,MAAA,EAAO,MAC/B,EAAE,CAAC,gBAA0B,GAAG,CAAA,EAAG,KAAK,CAAA,EAAA,CAAA,EAAM,CAAC,gBAA0B,GAAG,CAAA,EAAG,MAAM,CAAA,EAAA,CAAA,EAAK,CAAA;AAM7F,SAAS,QAAA,CAAS,IAAA,EAA0B,EAAE,IAAA,EAAM,KAAI,EAA6B;AACnF,EAAA,MAAM,QAAA,GAAW,IAAA,EAAM,aAAA,CAA2B,4BAA4B,CAAA,IAAK,IAAA;AACnF,EAAA,IAAI,CAAC,QAAA,EAAU;AACf,EAAA,QAAA,CAAS,UAAA,GAAa,IAAA;AACtB,EAAA,QAAA,CAAS,SAAA,GAAY,GAAA;AACvB;AAGA,SAAS,aAAA,CAAc,EAAE,KAAA,EAAO,OAAA,EAAS,OAAM,EAAuE;AACpH,EAAA,MAAM,IAAA,GAAO,OAAA,CAAQ,MAAM,KAAA,CAAM,QAAA,GAAW,OAAA,CAAQ,MAAM,CAAA,IAAK,IAAA,EAAM,CAAC,KAAA,EAAO,OAAA,CAAQ,MAAM,CAAC,CAAA;AAC5F,EAAA,MAAM,KAAA,GAAQ,aAAA,CAAc,IAAA,EAAM,MAAM,QAAQ,QAAQ,CAAA;AAExD,EAAA,MAAM,KAAA,GAAQ,OAAA;AAAA,IACZ,MAAO,OAAA,CAAQ,KAAA,KAAU,IAAA,IAAQ,KAAA,CAAM,YAAA,GAAe,KAAA,CAAM,YAAA,CAAa,OAAA,CAAQ,MAAM,CAAA,GAAI,OAAA,CAAQ,KAAA;AAAA,IACnG,CAAC,OAAA,CAAQ,KAAA,EAAO,OAAA,CAAQ,QAAQ,KAAK;AAAA,GACvC;AACA,EAAA,MAAM,GAAA,GAAoB;AAAA,IACxB,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,SAAA,EAAW,QAAA;AAAA,IACX,KAAA;AAAA,IACA,QAAA,EAAU,QAAA;AAAA,IACV,SAAS,OAAA,CAAQ,OAAA;AAAA,IACjB,OAAO,KAAA,CAAM,KAAA;AAAA,IACb,MAAM,KAAA,CAAM;AAAA,GACd;AACA,EAAA,uBACEF,IAAC,YAAA,CAAa,QAAA,EAAb,EAAsB,KAAA,EAAO,KAAA,EAC5B,0BAAAA,GAAAA,CAAC,SAAA,EAAA,EAAU,OAAc,GAAA,EAAU,UAAA,EAAY,MAAM,UAAA,IAAc,IAAI,QAAA,EAAU,CAAA,EAAG,OAAA,EAAS,QAAA,EAAU,CAAA,EACzG,CAAA;AAEJ;AAQO,SAAS,WAAA,CAAY,EAAE,OAAA,EAAS,KAAA,GAAQ,MAAM,OAAA,EAAS,KAAA,EAAO,QAAA,EAAU,UAAA,EAAW,EAAqB;AAC7G,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAI,SAAgC,IAAI,CAAA;AAC5D,EAAA,iBAAA,CAAkB,IAAA,EAAM,EAAE,MAAA,EAAQ,OAAA,EAAS,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAS,SAAA,EAAW,OAAA,CAAQ,SAAA,EAAW,KAAA,EAAO,CAAA;AAE1G,EAAA,MAAM,MAAA,GAAS,UAAU,EAAE,UAAA,EAAY,MAAM,MAAA,EAAQ,OAAA,CAAQ,QAAQ,CAAA;AACrE,EAAA,eAAA,CAAgB,MAAM,QAAA,CAAS,IAAA,EAAM,OAAA,CAAQ,MAAM,GAAG,CAAC,IAAA,EAAM,OAAA,CAAQ,MAAM,CAAC,CAAA;AAC5E,EAAA,MAAM,KAAA,GAAQ,OAAO,CAAC,CAAA;AAEtB,EAAA,MAAM,GAAA,GAAM,aAAA;AAAA,IACV,CAAC,MAAM,IAAA,KAAS;AACd,MAAA,KAAA,CAAM,OAAA,IAAW,CAAA;AACjB,MAAA,QAAA,CAAS,MAAA,CAAO,OAAA,CAAQ,IAAA,EAAM,MAAA,CAAO,QAAQ,MAAM,CAAA;AACnD,MAAA,IAAI,KAAA,CAAM,OAAA,GAAU,CAAA,EAAG,IAAA,CAAK,OAAA,EAAQ;AAAA,WAC/B,MAAA,CAAO,QAAQ,UAAA,EAAW;AAAA,IACjC,CAAA;AAAA,IACA,EAAE,0BAA0B,IAAA;AAAK,GACnC;AACA,EAAA,SAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,IAAI,QAAA,GAAW,KAAA;AACf,IAAA,MAAM,QAAQ,MAAM;AAClB,MAAA,IAAI,CAAC,QAAA,EAAU,GAAA,CAAI,OAAA,EAAQ;AAAA,IAC7B,CAAA;AACA,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,IAAA,CAAK,aAAA;AACvB,IAAA,IAAI,OAAO,KAAK,KAAA,CAAM,KAAA,CAAM,IAAA,CAAK,OAAO,KAAK,CAAA;AAAA,SACxC,KAAA,EAAM;AACX,IAAA,OAAO,MAAM;AACX,MAAA,QAAA,GAAW,IAAA;AACX,MAAA,GAAA,CAAI,MAAA,EAAO;AAAA,IACb,CAAA;AAAA,EACF,CAAA,EAAG,CAAC,IAAA,EAAM,GAAG,CAAC,CAAA;AAEd,EAAA,MAAM,UAAqB,CAAC,IAAA,GAAO,IAAA,GAAO,OAAA,CAAQ,SAAS,OAAA,mBACzDA,GAAAA,CAAC,aAAA,EAAA,EAAc,OAAO,OAAA,CAAQ,KAAA,EAAO,OAAA,EAAkB,KAAA,EAAc,oBAErEA,GAAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,KAAK,UAAA,CAAW,OAAA,CAAQ,MAAA,EAAQ,EAAE,OAAO,OAAA,EAAS,OAAA,CAAQ,OAAA,EAAS,UAAA,EAAY,MAAM,UAAA,IAAc,EAAC,EAAG,IAAA,EAAM,UAAU,CAAA;AAAA,MACvH,MAAA,EAAQ,QAAQ,MAAA,CAAO;AAAA;AAAA,GACzB;AAGF,EAAA,MAAM,sBACJA,GAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,GAAA,EAAK,OAAA;AAAA,MACL,SAAA,EAAU,UAAA;AAAA,MACV,cAAA,EAAc,OAAA;AAAA,MACd,iBAAA,EAAgB,EAAA;AAAA,MAChB,kBAAgB,OAAA,CAAQ,MAAA;AAAA,MACxB,KAAA,EAAO,QAAA,CAAS,OAAA,CAAQ,GAAG,CAAA;AAAA,MAE1B,QAAA,EAAA,OAAA,CAAQ,OAAA,mBACPA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,CAAA,mBAAA,EAAsB,OAAA,CAAQ,MAAM,CAAA,CAAA,EAAK,QAAA,EAAA,OAAA,EAAQ,CAAA,mBAEjEA,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kBAAA,EACZ,QAAA,EAAA,IAAA,mBACCA,GAAAA,CAAC,qBAAA,EAAA,EAAsB,SAAA,EAAW,IAAA,EAAM,SAAA,EAAS,IAAA,EAC9C,QAAA,EAAA,OAAA,EACH,CAAA,GACE,IAAA,EACN;AAAA;AAAA,GAEJ;AAEF,EAAA,IAAI,OAAA,CAAQ,SAAS,OAAO,GAAA;AAC5B,EAAA,uBACEA,GAAAA;AAAA,IAAC,aAAA;AAAA,IAAA;AAAA,MACC,KAAA,EAAO,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,OAAO,CAAA,IAAK,iBAAA;AAAA,MAC1C,WAAW,EAAE,IAAA,EAAM,QAAQ,GAAA,CAAI,IAAA,EAAM,SAAS,WAAA,EAAY;AAAA,MAE1D,QAAA,kBAAAA,GAAAA,CAAC,OAAA,EAAA,EAAS,QAAA,EAAA,GAAA,EAAI;AAAA;AAAA,GAChB;AAEJ;ACvHA,IAAM,eAAA,GAAN,cAA8BG,SAAAA,CAA2F;AAAA,EAC9G,KAAA,GAAQ,EAAE,MAAA,EAAQ,KAAA,EAAM;AAAA,EAEjC,OAAO,wBAAA,GAAgD;AACrD,IAAA,OAAO,EAAE,QAAQ,IAAA,EAAK;AAAA,EACxB;AAAA,EAES,kBAAkB,KAAA,EAAsB;AAC/C,IAAA,IAAA,CAAK,KAAA,CAAM,QAAQ,KAAK,CAAA;AAAA,EAC1B;AAAA,EAES,MAAA,GAAoB;AAC3B,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,MAAA,GAAS,IAAA,GAAO,KAAK,KAAA,CAAM,QAAA;AAAA,EAC/C;AACF,CAAA;AAOO,SAAS,aAAa,OAAA,EAAoC;AAC/D,EAAA,MAAM,EAAE,KAAA,EAAO,SAAA,EAAW,KAAA,EAAO,UAAS,GAAI,OAAA;AAC9C,EAAA,MAAM,SAAA,GAAY,aAAA,CAAc,OAAA,CAAQ,SAAS,CAAA;AACjD,EAAA,MAAM,SAAA,GAAY,QAAA,CAAS,cAAA,CAAe,MAAM,KAAK,QAAA,CAAS,IAAA;AAC9D,EAAA,MAAM,IAAA,GAAO,aAAA,CAAc,SAAA,EAAW,KAAA,CAAM,KAAK,CAAA;AACjD,EAAA,MAAM,QAAA,uBAAe,GAAA,EAA6B;AAClD,EAAA,IAAI,KAAA,GAAyC,IAAA;AAC7C,EAAA,IAAI,OAAA,GAAU,CAAA;AAEd,EAAA,MAAM,QAAA,GAAW,CAAC,IAAA,KAAmD;AACnE,IAAA,MAAM,QAAA,GAAW,UAAU,IAAI,CAAA;AAC/B,IAAA,OAAO,QAAA,GAAW,QAAA,EAAS,GAAI,OAAA,CAAQ,MAAA,CAAO,IAAI,KAAA,CAAM,CAAA,gBAAA,EAAmB,IAAI,CAAA,CAAE,CAAC,CAAA;AAAA,EACpF,CAAA;AACA,EAAA,MAAM,SAAA,GAAY,OAAO,EAAA,KAAgC;AACvD,IAAA,MAAM,QAAQ,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,EAAE,CAAA;AAC3C,IAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,CAAA,kBAAA,EAAqB,EAAE,CAAA,CAAA,CAAG,CAAA;AACtD,IAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,MAAM,QAAA,CAAS,KAAA,CAAM,IAAI,CAAA,EAAG,KAAA,CAAM,KAAA,EAAO,KAAA,CAAM,UAAU,CAAA,CAAE,IAAA;AAAA,MACnF,CAAC,CAAA,KAAM,CAAA,CAAE,UAAA,KAAe,KAAA,CAAM;AAAA,KAChC;AACA,IAAA,IAAI,CAAC,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,CAAA,EAAG,KAAA,CAAM,IAAI,CAAA,sBAAA,EAAyB,KAAA,CAAM,UAAU,CAAA,CAAA,CAAG,CAAA;AACrF,IAAA,MAAM,KAAA,CAAM,UAAU,KAAK,CAAA;AAC3B,IAAA,OAAO,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAM;AAAA,EAChC,CAAA;AACA,EAAA,MAAM,SAAA,GAAY,OAAO,EAAA,KAAgC;AACvD,IAAA,MAAM,MAAA,GAAS,EAAE,KAAA,EAAO,QAAA,EAAU,UAAA,EAAY,MAAM,UAAA,EAAY,OAAA,EAAS,KAAA,CAAM,OAAA,EAAS,SAAA,EAAU;AAClG,IAAA,OAAO,EAAE,MAAM,OAAA,EAAS,MAAA,EAAQ,MAAM,eAAA,CAAgB,EAAA,EAAI,MAAM,CAAA,EAAE;AAAA,EACpE,CAAA;AACA,EAAA,MAAM,SAAA,GAAY,CAAC,EAAA,KAAgC;AACjD,IAAA,IAAI,OAAA,GAAU,QAAA,CAAS,GAAA,CAAI,EAAE,CAAA;AAC7B,IAAA,IAAI,CAAC,OAAA,EAAS;AACZ,MAAA,OAAA,GAAU,UAAU,EAAE,CAAA,GAAI,UAAU,EAAE,CAAA,GAAI,UAAU,EAAE,CAAA;AACtD,MAAA,QAAA,CAAS,GAAA,CAAI,IAAI,OAAO,CAAA;AACxB,MAAA,OAAA,CAAQ,KAAA,CAAM,MAAM,QAAA,CAAS,MAAA,CAAO,EAAE,CAAC,CAAA;AAAA,IACzC;AACA,IAAA,OAAO,OAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,UAAU,MAAgC;AAC9C,IAAA,KAAA,KAAU,OAAA,CAAQ,YAAA,GAAe,OAAA,CAAQ,YAAA,EAAa,CAAE,KAAA,CAAM,MAAM,IAAI,CAAA,GAAI,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA;AAChG,IAAA,OAAO,KAAA;AAAA,EACT,CAAA;AAEA,EAAA,MAAA,CAAO,cAAA,GAAiB;AAAA,IACtB,MAAM,OAAO,OAAA,EAAS;AACpB,MAAA,MAAM,OAAA,GAAU,MAAM,SAAA,CAAU,OAAA,CAAQ,KAAK,CAAA;AAC7C,MAAA,MAAM,OAAO,OAAA,CAAQ,IAAA,KAAS,OAAA,GAAU,MAAM,SAAQ,GAAI,IAAA;AAC1D,MAAA,OAAA,IAAW,CAAA;AACX,MAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,EAAS,MAAA,KAAW;AAE3C,QAAA,IAAA,CAAK,MAAA;AAAA,0BACHH,GAAAA,CAAC,eAAA,EAAA,EAA8B,OAAA,EAAS,MAAA,EACtC,QAAA,kBAAAA,GAAAA,CAAC,gBAAA,CAAiB,QAAA,EAAjB,EAA0B,KAAA,EAAO,SAAA,EAChC,QAAA,kBAAAA,GAAAA;AAAA,YAAC,WAAA;AAAA,YAAA;AAAA,cACC,OAAA;AAAA,cACA,KAAA,EAAO,IAAA;AAAA,cACP,OAAA;AAAA,cACA,KAAA;AAAA,cACA,QAAA;AAAA,cACA,UAAA,EAAY;AAAA;AAAA,WACd,EACF,KAVoB,OAWtB;AAAA,SACF;AAAA,MACF,CAAC,CAAA;AAAA,IACH;AAAA,GACF;AACF","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,9 +1,10 @@
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-Bd6FVlh7.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-Tv3jrHyT.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-Tv3jrHyT.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';
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';
1
+ export { RESERVED_PARAMS, decodeKnob, encodeKnob, formatRoute, knobParams, knobPaths, knobsToParams, paramsToKnobs, parseRoute, reservedParams, storyHref } from './chunk-COT4I347.js';
2
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
@@ -0,0 +1,21 @@
1
+ import { AppearanceProps } from '@weasel-js/ui/appearance';
2
+
3
+ /** One library of a project: the story files under `path` carry `label`. */
4
+ interface Library {
5
+ /** A stretch of path every story file of the library has, with forward slashes: `/packages/ui/`. */
6
+ path: string;
7
+ label: string;
8
+ /** The tint of the library's badge, as a `<Badge>` takes one. Default: the badge's own low emphasis. */
9
+ tint?: AppearanceProps['tint'];
10
+ }
11
+ /** A project's libraries, as the tree's package filter, the index page header, and Get Info ask about them. */
12
+ interface Libraries {
13
+ /** The label of the first library whose `path` the story's file holds, else its title's first segment. */
14
+ of(entry: {
15
+ file: string;
16
+ title: string;
17
+ }): string;
18
+ tintOf(label: string): AppearanceProps['tint'];
19
+ }
20
+
21
+ export type { Library as L, Libraries as a };
@@ -1,4 +1,4 @@
1
- import { F as FrameSetup, p as LoadedStory } from './FrameController-Tv3jrHyT.js';
1
+ import { F as FrameSetup, p as LoadedStory } from './FrameController-DgfVaENb.js';
2
2
 
3
3
  /** Story modules by file path, each loaded on first use. */
4
4
  interface FrameImporters {
@@ -707,9 +707,8 @@
707
707
  transform-origin: 0 0;
708
708
  transform: translate(var(--fg-lens-copy-x), var(--fg-lens-copy-y)) scale(var(--fg-lens-copy-f));
709
709
  }
710
- .fg-lens-copy > .fg-story,
711
710
  .fg-lens-copy > .fg-frame-host {
712
- background: var(--wzl-bg);
711
+ background: var(--wzl-surface);
713
712
  }
714
713
  .fg-lens-pixels {
715
714
  position: absolute;
@@ -728,7 +727,7 @@
728
727
  text-align: center;
729
728
  font-size: 11px;
730
729
  color: var(--wzl-fg-muted);
731
- background: var(--wzl-bg);
730
+ background: var(--wzl-surface);
732
731
  }
733
732
  .fg-lens-empty[hidden] {
734
733
  display: none;