@weasel-js/forge 1.9.3 → 1.10.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.
- package/README.md +34 -4
- package/dist/{FrameController-CpcY0DNB.d.ts → FrameController-UeTY7ubF.d.ts} +26 -36
- package/dist/{chunk-Q2EZXJFE.js → chunk-4NM3RTYK.js} +70 -56
- package/dist/chunk-4NM3RTYK.js.map +1 -0
- package/dist/chunk-5DXUNLV2.js +6 -0
- package/dist/chunk-5DXUNLV2.js.map +1 -0
- package/dist/{chunk-GZPQMGXJ.js → chunk-DFKCLZKS.js} +5 -4
- package/dist/chunk-DFKCLZKS.js.map +1 -0
- package/dist/{chunk-CJX3W5HY.js → chunk-DKWHGSBZ.js} +4 -3
- package/dist/chunk-DKWHGSBZ.js.map +1 -0
- package/dist/{chunk-BGOHALHO.js → chunk-ENXU34PI.js} +23 -111
- package/dist/chunk-ENXU34PI.js.map +1 -0
- package/dist/chunk-FL2MUPUL.js +10 -0
- package/dist/chunk-FL2MUPUL.js.map +1 -0
- package/dist/{chunk-MGQWCPYE.js → chunk-GB6PRJET.js} +4 -5
- package/dist/chunk-GB6PRJET.js.map +1 -0
- package/dist/{chunk-JVRHBI3V.js → chunk-V4RI7GWD.js} +53 -59
- package/dist/chunk-V4RI7GWD.js.map +1 -0
- package/dist/{chunk-HRGPFQBW.js → chunk-ZAWXMUGZ.js} +6 -3
- package/dist/chunk-ZAWXMUGZ.js.map +1 -0
- package/dist/{config-BfsYw5lg.d.ts → config-Cz7ZyGF-.d.ts} +28 -5
- package/dist/csf/preview-api.d.ts +5 -2
- package/dist/csf/preview-api.js +2 -2
- package/dist/csf/preview-api.js.map +1 -1
- package/dist/frame/index.css +19 -2
- package/dist/frame/index.css.map +1 -1
- package/dist/frame/index.d.ts +2 -2
- package/dist/frame/index.js +7 -41
- package/dist/frame/index.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/shell/index.css +93 -62
- package/dist/shell/index.css.map +1 -1
- package/dist/shell/index.d.ts +10 -17
- package/dist/shell/index.js +724 -587
- package/dist/shell/index.js.map +1 -1
- package/dist/test/index.d.ts +4 -2
- package/dist/test/index.js +8 -8
- package/dist/test/index.js.map +1 -1
- package/dist/test/play.d.ts +2 -4
- package/dist/test/play.js.map +1 -1
- package/dist/vite/index.d.ts +19 -2
- package/dist/vite/index.js +751 -162
- package/dist/vite/index.js.map +1 -1
- package/package.json +10 -5
- package/dist/chunk-BGOHALHO.js.map +0 -1
- package/dist/chunk-CJX3W5HY.js.map +0 -1
- package/dist/chunk-GZPQMGXJ.js.map +0 -1
- package/dist/chunk-HRGPFQBW.js.map +0 -1
- package/dist/chunk-JVRHBI3V.js.map +0 -1
- package/dist/chunk-KJGXJD3U.js +0 -15
- package/dist/chunk-KJGXJD3U.js.map +0 -1
- package/dist/chunk-MGQWCPYE.js.map +0 -1
- package/dist/chunk-Q2EZXJFE.js.map +0 -1
package/README.md
CHANGED
|
@@ -7,6 +7,19 @@ component can be compared side by side.
|
|
|
7
7
|
|
|
8
8
|
Direction: `docs/superpowers/specs/2026-09-13-forge-design.md`.
|
|
9
9
|
|
|
10
|
+
## What the index reads
|
|
11
|
+
|
|
12
|
+
The story list is read from each file's source without running it, and a
|
|
13
|
+
loaded story takes its title from that list. So a meta's `title` has to be
|
|
14
|
+
readable there: a string, a template with no expression, or a `const` of the
|
|
15
|
+
same file holding one. Any other title, such as an imported constant, is
|
|
16
|
+
passed over for the title the file's path gives it. In a file whose meta is
|
|
17
|
+
forge's `meta`, a story is an export that calls `story`, directly or through
|
|
18
|
+
a function that returns the call, and an import or a re-export is followed to
|
|
19
|
+
its declaration to see whether it is one. Anything else the file exports, such
|
|
20
|
+
as `export const rows = makeRows()` or a constant from another module, is not
|
|
21
|
+
listed.
|
|
22
|
+
|
|
10
23
|
## Where a story renders
|
|
11
24
|
|
|
12
25
|
A story renders inside a host element in the workshop document. The host
|
|
@@ -23,13 +36,13 @@ export const Interactive = story({ isolate: 'asserts placement against the windo
|
|
|
23
36
|
// CSF: parameters: { forge: { isolate: 'asserts placement against the window edge' } }
|
|
24
37
|
```
|
|
25
38
|
|
|
26
|
-
It then renders in an iframe
|
|
27
|
-
|
|
39
|
+
It then renders in an iframe. The frame path
|
|
40
|
+
gets no new features; `npm run check:forge-isolate`
|
|
28
41
|
lists the isolated stories and fails when their number goes above the one the
|
|
29
42
|
script holds, so the count only goes down. The value is read from the source
|
|
30
43
|
without running it, and must be a string literal.
|
|
31
44
|
|
|
32
|
-
|
|
45
|
+
If the count ever reaches
|
|
33
46
|
zero, the frame side goes: `FrameView`, `framePool`, `trialFrames`,
|
|
34
47
|
`answers`, `readyKey`, `labHarness`, `mountFrame`, `protocol/*`, the frame
|
|
35
48
|
entry, `frame.html`, `html.ts`, the frame page in `build.ts`, the `./frame`
|
|
@@ -52,11 +65,20 @@ The vite plugin takes two optional config modules:
|
|
|
52
65
|
renderers, and global declarations. Only the workshop page imports it.
|
|
53
66
|
`title` names the workshop in its header and as the document title
|
|
54
67
|
(default `weaselforge`), and `cssVars: false` leaves out the CSS Vars panel.
|
|
68
|
+
`libraries` names the project's libraries, each a stretch of file path, a
|
|
69
|
+
label and an optional badge tone: `{ path: '/packages/ui/', label: 'ui' }`.
|
|
70
|
+
The tree's package filter, index pages, and Get Info show the label; a
|
|
71
|
+
story under none of them takes its title's first segment.
|
|
55
72
|
|
|
56
73
|
```ts
|
|
57
74
|
forge({ stories: ['src/**/*.stories.tsx'], frameConfig: 'forge.frame.tsx', shellConfig: 'forge.shell.tsx' });
|
|
58
75
|
```
|
|
59
76
|
|
|
77
|
+
The workshop page imports the frame config too, so a stylesheet it imports
|
|
78
|
+
styles the workshop as well. CSS meant for frame documents alone, such as a
|
|
79
|
+
page background on `html, body`, goes in `frameStyles`, a list of stylesheet
|
|
80
|
+
paths that only the frame document loads.
|
|
81
|
+
|
|
60
82
|
Editing a story file reloads that story in every trial showing it, with the
|
|
61
83
|
trial's config and state kept; the page itself stays.
|
|
62
84
|
|
|
@@ -179,6 +201,14 @@ export default meta({
|
|
|
179
201
|
A custom page gets the list as `Dependencies`, and `gallery` says whether the
|
|
180
202
|
component is one.
|
|
181
203
|
|
|
204
|
+
Above the list the page says which release the component first shipped in and
|
|
205
|
+
when its source file was created and last changed. All three come from git:
|
|
206
|
+
the dates are the file's first and latest commits, followed back through
|
|
207
|
+
renames, and the release is the nearest tag after the first, taken from the
|
|
208
|
+
file's own package's tags (`@scope/pkg@1.2.0`) and unscoped ones (`v1.2.0`).
|
|
209
|
+
A file not yet in a tagged release reads `Unreleased`, and a file git has
|
|
210
|
+
never committed shows nothing. A custom page gets it as `History`.
|
|
211
|
+
|
|
182
212
|
## Galleries
|
|
183
213
|
|
|
184
214
|
A story file that catalogs many components, or every permutation of one, tags
|
|
@@ -201,6 +231,6 @@ appear as a user of everything.
|
|
|
201
231
|
|
|
202
232
|
`forgeTest` from `@weasel-js/forge/vite` runs every story as a vitest browser
|
|
203
233
|
test: each story renders in the test page through the same host the workshop
|
|
204
|
-
uses, with its defaults, plays, and fails on any fault. Pass it the same `frameConfig`. It needs vitest 4 in browser mode with a provider, such as
|
|
234
|
+
uses, with its defaults, plays, and fails on any fault. Pass it the same `frameConfig`. It needs vitest 4 or 5 in browser mode with a provider, such as
|
|
205
235
|
`@vitest/browser-playwright`. This repo runs it with
|
|
206
236
|
`npm run test:stories:forge`, not in CI.
|
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { BranchAnnotations, Annotations, ConfigSchema } from '@weasel-js/labkit/config';
|
|
2
2
|
import { ReactNode, ComponentType } from 'react';
|
|
3
3
|
|
|
4
|
+
/** One end of a two-way message link: sends `Out`, hears `In`. */
|
|
4
5
|
interface Channel<In, Out> {
|
|
5
6
|
send(msg: Out): void;
|
|
6
7
|
on(fn: (msg: In) => void): () => void;
|
|
7
8
|
close(): void;
|
|
8
9
|
}
|
|
9
10
|
|
|
11
|
+
/** The section a described entry sits in, as structured-clone data. */
|
|
10
12
|
interface SectionDescription {
|
|
11
13
|
label: string;
|
|
12
14
|
collapsed?: boolean;
|
|
13
15
|
}
|
|
16
|
+
/** One key of a described shape: a leaf, or a branch holding more. */
|
|
14
17
|
type DescribedEntry = {
|
|
15
18
|
branch: true;
|
|
16
19
|
annotations: BranchAnnotations;
|
|
@@ -28,6 +31,7 @@ type DescribedEntry = {
|
|
|
28
31
|
/** The node draws its own row with `.render`, which stays in the frame. */
|
|
29
32
|
customControl: boolean;
|
|
30
33
|
};
|
|
34
|
+
/** A config shape as structured-clone data: each key's entry, described. */
|
|
31
35
|
type DescribedShape = {
|
|
32
36
|
[key: string]: DescribedEntry;
|
|
33
37
|
};
|
|
@@ -36,13 +40,17 @@ interface SchemaDescription {
|
|
|
36
40
|
nodes: DescribedShape;
|
|
37
41
|
}
|
|
38
42
|
|
|
43
|
+
/** The workshop's toolbar globals as a story reads them, by name. */
|
|
39
44
|
type Globals = Readonly<Record<string, unknown>>;
|
|
45
|
+
/** How a story sits in its frame. */
|
|
40
46
|
type Layout = 'centered' | 'padded' | 'fullscreen';
|
|
47
|
+
/** A frame size a story asks for, in CSS pixels. */
|
|
41
48
|
interface Viewport {
|
|
42
49
|
width: number;
|
|
43
50
|
height: number;
|
|
44
51
|
}
|
|
45
|
-
|
|
52
|
+
/** Where a frame's fault happened: loading the story, rendering it, or reading a message. */
|
|
53
|
+
type FaultPhase = 'import' | 'render' | 'protocol';
|
|
46
54
|
/** One custom property as the frame found it. */
|
|
47
55
|
interface CssVarReport {
|
|
48
56
|
name: string;
|
|
@@ -81,15 +89,7 @@ interface A11yReport {
|
|
|
81
89
|
passes: number;
|
|
82
90
|
inapplicable: number;
|
|
83
91
|
}
|
|
84
|
-
/** A
|
|
85
|
-
* which no structured clone carries. */
|
|
86
|
-
type CapturedPicture = {
|
|
87
|
-
kind: 'svg';
|
|
88
|
-
markup: string;
|
|
89
|
-
} | {
|
|
90
|
-
kind: 'image';
|
|
91
|
-
src: string;
|
|
92
|
-
};
|
|
92
|
+
/** A message the workshop sends a story's frame. */
|
|
93
93
|
type ToFrame = {
|
|
94
94
|
type: 'init';
|
|
95
95
|
config: unknown;
|
|
@@ -108,19 +108,13 @@ type ToFrame = {
|
|
|
108
108
|
type: 'vars.set';
|
|
109
109
|
name: string;
|
|
110
110
|
value: string | null;
|
|
111
|
-
} | {
|
|
112
|
-
type: 'play';
|
|
113
111
|
}
|
|
114
112
|
/** Run axe over the story's own subtree. Answered by `a11y` carrying the same `id`. */
|
|
115
113
|
| {
|
|
116
114
|
type: 'a11y.run';
|
|
117
115
|
id: string;
|
|
118
|
-
}
|
|
119
|
-
/** Serialize the story's own subtree as a picture. Answered by `capture` carrying the same `id`. */
|
|
120
|
-
| {
|
|
121
|
-
type: 'capture.run';
|
|
122
|
-
id: string;
|
|
123
116
|
};
|
|
117
|
+
/** A message a story's frame sends the workshop. */
|
|
124
118
|
type FromFrame = {
|
|
125
119
|
type: 'ready';
|
|
126
120
|
schema: SchemaDescription;
|
|
@@ -140,10 +134,6 @@ type FromFrame = {
|
|
|
140
134
|
} | {
|
|
141
135
|
type: 'setState';
|
|
142
136
|
state: unknown;
|
|
143
|
-
} | {
|
|
144
|
-
type: 'size';
|
|
145
|
-
width: number;
|
|
146
|
-
height: number;
|
|
147
137
|
} | {
|
|
148
138
|
type: 'vars';
|
|
149
139
|
vars: CssVarReport[];
|
|
@@ -152,10 +142,6 @@ type FromFrame = {
|
|
|
152
142
|
| {
|
|
153
143
|
type: 'open';
|
|
154
144
|
id: string;
|
|
155
|
-
} | {
|
|
156
|
-
type: 'played';
|
|
157
|
-
ok: boolean;
|
|
158
|
-
message?: string;
|
|
159
145
|
} | {
|
|
160
146
|
type: 'a11y';
|
|
161
147
|
id: string;
|
|
@@ -166,16 +152,6 @@ type FromFrame = {
|
|
|
166
152
|
id: string;
|
|
167
153
|
ok: false;
|
|
168
154
|
message: string;
|
|
169
|
-
} | {
|
|
170
|
-
type: 'capture';
|
|
171
|
-
id: string;
|
|
172
|
-
ok: true;
|
|
173
|
-
picture: CapturedPicture;
|
|
174
|
-
} | {
|
|
175
|
-
type: 'capture';
|
|
176
|
-
id: string;
|
|
177
|
-
ok: false;
|
|
178
|
-
message: string;
|
|
179
155
|
}
|
|
180
156
|
/** `seq`, on a render fault only: how many `init`/`config`/`state`/`globals` messages the frame had received. */
|
|
181
157
|
| {
|
|
@@ -266,6 +242,9 @@ interface IndexContext {
|
|
|
266
242
|
DefaultIndex: ComponentType;
|
|
267
243
|
/** The listed components this one uses and those that use it, as the generated page shows them. */
|
|
268
244
|
Dependencies: ComponentType;
|
|
245
|
+
/** The release the component first shipped in and when its source was created and last changed, as the generated
|
|
246
|
+
* page shows them. */
|
|
247
|
+
History: ComponentType;
|
|
269
248
|
/** Whether the meta is tagged `gallery`. */
|
|
270
249
|
gallery: boolean;
|
|
271
250
|
/** Shows story `id` in this page's trial in its place. */
|
|
@@ -339,6 +318,15 @@ interface IndexEntry {
|
|
|
339
318
|
* story of its component carries. */
|
|
340
319
|
tags?: string[];
|
|
341
320
|
}
|
|
321
|
+
/** When a component's source file was written and released, read from git. */
|
|
322
|
+
interface ComponentHistory {
|
|
323
|
+
/** When the file was first committed, as an ISO date. A rename does not reset it. */
|
|
324
|
+
created: string;
|
|
325
|
+
/** When the file was last committed, as an ISO date. */
|
|
326
|
+
modified: string;
|
|
327
|
+
/** The first release holding the file, from the nearest tag after it was added; null while no release does. */
|
|
328
|
+
introduced: string | null;
|
|
329
|
+
}
|
|
342
330
|
/** One component's place in the component graph. Every list holds story titles, sorted. */
|
|
343
331
|
interface ComponentDeps {
|
|
344
332
|
/** The file declaring the component, relative to the vite root; null when forge could not find one. */
|
|
@@ -347,6 +335,8 @@ interface ComponentDeps {
|
|
|
347
335
|
uses: string[];
|
|
348
336
|
/** The listed components whose own source imports it. */
|
|
349
337
|
usedBy: string[];
|
|
338
|
+
/** Absent for a source file git has never committed, and outside a repository. */
|
|
339
|
+
history?: ComponentHistory;
|
|
350
340
|
}
|
|
351
341
|
/** The component graph the vite plugin derives from source, by story title. A gallery has no entry. */
|
|
352
342
|
type DepGraph = Record<string, ComponentDeps>;
|
|
@@ -393,4 +383,4 @@ declare function startFrame({ story, channel, container, setup }: StartFrameOpti
|
|
|
393
383
|
/** Reports an import failure — there is no story to start. */
|
|
394
384
|
declare function reportImportFault(channel: Channel<ToFrame, FromFrame>, error: unknown): void;
|
|
395
385
|
|
|
396
|
-
export { type A11yFinding as A, type ClockState as C, type Decorator as D, type FrameSetup as F, type Globals as G, type IndexContext as I, type LoadedStory as L, type MetaSpec as M, type PlayContext as P, type StorySpec as S, type TimelineSpec as T, type Viewport as V, type SpanOverride as a, type A11yNode as b, type A11yReport as c, type ComponentDeps as d, type
|
|
386
|
+
export { type A11yFinding as A, type ClockState as C, type Decorator as D, type FrameSetup as F, type Globals as G, type IndexContext as I, type LoadedStory as L, type MetaSpec as M, type PlayContext as P, type StorySpec as S, type TimelineSpec as T, type Viewport as V, type SpanOverride as a, type A11yNode as b, type A11yReport as c, type ComponentDeps as d, type ComponentHistory as e, type DepGraph as f, type GlobalsTarget as g, type IndexRender as h, type IndexStoryProps as i, type StoryContext as j, type Layout as k, type Span as l, type IndexEntry as m, type FromFrame as n, type ToFrame as o, type CssVarReport as p, type DescribedEntry as q, type DescribedShape as r, type SchemaDescription as s, type SectionDescription as t, type Channel as u, type ConfigAnswers as v, type FaultPhase as w, type StartFrameOptions as x, reportImportFault as y, startFrame as z };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { isNative, ClockContext } from './chunk-L5XM5VKB.js';
|
|
2
|
-
import { storyNameFromExport, storyId } from './chunk-
|
|
3
|
-
import { portSafePart, appliedLocal, withUnsent, coverOf, ArgsContext } from './chunk-
|
|
4
|
-
import { isPlainObject } from '
|
|
5
|
-
import { useVisibleRaf, useLatest } from '@weasel-js/core';
|
|
2
|
+
import { storyNameFromExport, storyId, PROP_ARG_TYPES_EXPORT } from './chunk-ZAWXMUGZ.js';
|
|
3
|
+
import { portSafePart, appliedLocal, withUnsent, coverOf, ArgsContext } from './chunk-GB6PRJET.js';
|
|
4
|
+
import { useVisibleRaf, useLatest, isPlainObject } from '@weasel-js/core';
|
|
6
5
|
import { createContext, useSyncExternalStore, useRef, useEffect, useState, Component, useContext, createElement } from 'react';
|
|
6
|
+
import { createEmitter } from '@weasel-js/registry';
|
|
7
7
|
import { jsx } from 'react/jsx-runtime';
|
|
8
8
|
import { f } from '@weasel-js/labkit/config';
|
|
9
9
|
|
|
@@ -40,10 +40,14 @@ var PAGE_RULES = [
|
|
|
40
40
|
"page-has-heading-one",
|
|
41
41
|
"region"
|
|
42
42
|
];
|
|
43
|
+
var last = Promise.resolve();
|
|
43
44
|
async function runAxe(element, { page = true } = {}) {
|
|
44
45
|
const axe = await loadAxe();
|
|
45
46
|
const rules = page ? void 0 : Object.fromEntries(PAGE_RULES.map((id) => [id, { enabled: false }]));
|
|
46
|
-
const
|
|
47
|
+
const run = () => axe.run(element, rules ? { rules } : void 0);
|
|
48
|
+
const running = last.then(run, run);
|
|
49
|
+
last = running;
|
|
50
|
+
const result = await running;
|
|
47
51
|
return {
|
|
48
52
|
violations: result.violations.map(finding),
|
|
49
53
|
incomplete: result.incomplete.map(finding),
|
|
@@ -142,37 +146,6 @@ ${decls.join("\n")}
|
|
|
142
146
|
};
|
|
143
147
|
}
|
|
144
148
|
|
|
145
|
-
// src/frame/capture.ts
|
|
146
|
-
var SVG_NS = "http://www.w3.org/2000/svg";
|
|
147
|
-
function documentCss(doc) {
|
|
148
|
-
const out = [];
|
|
149
|
-
for (const sheet of Array.from(doc.styleSheets)) {
|
|
150
|
-
try {
|
|
151
|
-
for (const rule of Array.from(sheet.cssRules)) out.push(rule.cssText);
|
|
152
|
-
} catch {
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
return out.join("\n");
|
|
156
|
-
}
|
|
157
|
-
function captureElement(element) {
|
|
158
|
-
const doc = element.ownerDocument;
|
|
159
|
-
const rect = element.getBoundingClientRect();
|
|
160
|
-
const w = Math.max(1, Math.ceil(rect.width));
|
|
161
|
-
const h = Math.max(1, Math.ceil(rect.height));
|
|
162
|
-
const root = doc.createElement("div");
|
|
163
|
-
root.setAttribute("data-fg-capture", "");
|
|
164
|
-
const tokens = scanCssVars(doc).filter((v) => v.value).map((v) => `${v.name}: ${v.value};`).join("");
|
|
165
|
-
const style = doc.createElement("style");
|
|
166
|
-
style.textContent = `${documentCss(doc)}
|
|
167
|
-
[data-fg-capture]{${tokens}}`;
|
|
168
|
-
root.append(style, element.cloneNode(true));
|
|
169
|
-
const inner = new XMLSerializer().serializeToString(root);
|
|
170
|
-
return {
|
|
171
|
-
kind: "svg",
|
|
172
|
-
markup: `<svg xmlns="${SVG_NS}" width="${w}" height="${h}" viewBox="0 0 ${w} ${h}"><foreignObject x="0" y="0" width="${w}" height="${h}">${inner}</foreignObject></svg>`
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
|
|
176
149
|
// src/frame/globalsTarget.ts
|
|
177
150
|
function createGlobalsTarget(root, scope) {
|
|
178
151
|
const doc = root.ownerDocument;
|
|
@@ -199,31 +172,29 @@ var NEVER = () => () => {
|
|
|
199
172
|
var notPlaying = () => false;
|
|
200
173
|
function useClockLoop(clock, target) {
|
|
201
174
|
const playing = useSyncExternalStore(clock?.subscribe ?? NEVER, clock ? () => clock.get().playing : notPlaying);
|
|
202
|
-
const
|
|
175
|
+
const last2 = useRef(null);
|
|
203
176
|
const raf = useVisibleRaf(
|
|
204
177
|
(now) => {
|
|
205
178
|
if (!clock) return;
|
|
206
|
-
const prev =
|
|
207
|
-
|
|
179
|
+
const prev = last2.current;
|
|
180
|
+
last2.current = now;
|
|
208
181
|
if (prev !== null) clock.tick(now - prev);
|
|
209
182
|
if (clock.get().playing) raf.request();
|
|
210
183
|
},
|
|
211
184
|
{
|
|
212
185
|
...target ? { target } : {},
|
|
213
186
|
onResume: () => {
|
|
214
|
-
|
|
187
|
+
last2.current = null;
|
|
215
188
|
}
|
|
216
189
|
}
|
|
217
190
|
);
|
|
218
191
|
useEffect(() => {
|
|
219
192
|
if (!playing) return;
|
|
220
|
-
|
|
193
|
+
last2.current = null;
|
|
221
194
|
raf.request();
|
|
222
195
|
return () => raf.cancel();
|
|
223
196
|
}, [playing, raf]);
|
|
224
197
|
}
|
|
225
|
-
|
|
226
|
-
// src/timeline/clock.ts
|
|
227
198
|
function spanOf(spec) {
|
|
228
199
|
const start = Number.isFinite(spec.start) ? spec.start : 0;
|
|
229
200
|
const duration = Number.isFinite(spec.duration) && spec.duration > 0 ? spec.duration : 0;
|
|
@@ -256,7 +227,7 @@ function createClock(spec, initial) {
|
|
|
256
227
|
rate: validRate(spec.rate) ? spec.rate : 1,
|
|
257
228
|
span: declared
|
|
258
229
|
};
|
|
259
|
-
const
|
|
230
|
+
const changed = createEmitter();
|
|
260
231
|
const pendingIn = (at) => requested && requested.time !== null && requested.time !== at.time ? requested.time : null;
|
|
261
232
|
let pending = pendingIn(state);
|
|
262
233
|
const set = (next) => {
|
|
@@ -265,7 +236,7 @@ function createClock(spec, initial) {
|
|
|
265
236
|
return;
|
|
266
237
|
state = next;
|
|
267
238
|
pending = nextPending;
|
|
268
|
-
|
|
239
|
+
changed.emit();
|
|
269
240
|
};
|
|
270
241
|
const moved = (next) => {
|
|
271
242
|
requested = null;
|
|
@@ -277,10 +248,7 @@ function createClock(spec, initial) {
|
|
|
277
248
|
};
|
|
278
249
|
return {
|
|
279
250
|
get: () => state,
|
|
280
|
-
subscribe
|
|
281
|
-
listeners.add(listener);
|
|
282
|
-
return () => listeners.delete(listener);
|
|
283
|
-
},
|
|
251
|
+
subscribe: changed.subscribe,
|
|
284
252
|
play() {
|
|
285
253
|
if (state.playing) return;
|
|
286
254
|
moved({ ...state, playing: true, time: state.time >= state.span.end ? state.span.start : state.time });
|
|
@@ -532,11 +500,12 @@ function Scoped({
|
|
|
532
500
|
createElement(ArgsContext.Provider, { value: scope }, createElement(Call, { fn: () => fn(context) }))
|
|
533
501
|
);
|
|
534
502
|
}
|
|
535
|
-
function loadCsfModule(mod,
|
|
503
|
+
function loadCsfModule(mod, title, projectParameters = {}) {
|
|
536
504
|
const meta = isPlainObject(mod.default) ? mod.default : {};
|
|
537
|
-
const title = meta.title ?? autoTitle;
|
|
538
505
|
const stories = [];
|
|
506
|
+
const propArgTypes = isPlainObject(mod[PROP_ARG_TYPES_EXPORT]) ? mod[PROP_ARG_TYPES_EXPORT] : void 0;
|
|
539
507
|
for (const [exportName, value] of Object.entries(mod)) {
|
|
508
|
+
if (exportName === PROP_ARG_TYPES_EXPORT) continue;
|
|
540
509
|
if (exportName === "default" || exportName === "__namedExportsOrder" || exportName === "__esModule") continue;
|
|
541
510
|
if (meta.includeStories && !matches(exportName, meta.includeStories)) continue;
|
|
542
511
|
if (meta.excludeStories && matches(exportName, meta.excludeStories)) continue;
|
|
@@ -547,15 +516,17 @@ function loadCsfModule(mod, autoTitle, projectParameters = {}) {
|
|
|
547
516
|
const args = { ...meta.args, ...spec.args };
|
|
548
517
|
const parameters = combineParameters(projectParameters, meta.parameters, spec.parameters);
|
|
549
518
|
const matchers = parameters.controls?.matchers;
|
|
519
|
+
const render = spec.render ?? meta.render;
|
|
520
|
+
const fromProps = render === void 0 || render.length > 0 ? propArgTypes : void 0;
|
|
550
521
|
const config = argsToSchema(
|
|
551
522
|
args,
|
|
552
|
-
combineParameters(meta.argTypes, spec.argTypes),
|
|
523
|
+
combineParameters(fromProps, meta.argTypes, spec.argTypes),
|
|
553
524
|
isPlainObject(matchers) ? matchers : {}
|
|
554
525
|
);
|
|
555
526
|
const defaults = config.defaults();
|
|
556
527
|
const storyGlobals = { ...meta.globals, ...spec.globals };
|
|
557
528
|
const component = meta.component;
|
|
558
|
-
const renderFn =
|
|
529
|
+
const renderFn = render ?? (component ? (a) => createElement(component, a) : void 0);
|
|
559
530
|
const withArgs = (config2) => Object.fromEntries(
|
|
560
531
|
Object.entries(withoutUndefined(config2)).map(([key, value2]) => [key, key in args ? withUnsent(value2, args[key]) : value2])
|
|
561
532
|
);
|
|
@@ -648,7 +619,50 @@ function indexRenderOf(mod) {
|
|
|
648
619
|
const render = isNative(meta, "meta") ? meta?.index : meta?.parameters?.forge?.index;
|
|
649
620
|
return typeof render === "function" ? render : null;
|
|
650
621
|
}
|
|
622
|
+
var IN_VIEW_MARGIN = "50%";
|
|
623
|
+
function useNearViewport(ref, margin, initial = true) {
|
|
624
|
+
const [near, setNear] = useState(() => initial || typeof IntersectionObserver === "undefined");
|
|
625
|
+
useEffect(() => {
|
|
626
|
+
const el = ref.current;
|
|
627
|
+
if (!el || typeof IntersectionObserver === "undefined") return;
|
|
628
|
+
const recheck = () => {
|
|
629
|
+
observer.unobserve(el);
|
|
630
|
+
observer.observe(el);
|
|
631
|
+
};
|
|
632
|
+
let watching = false;
|
|
633
|
+
const watch = (on) => {
|
|
634
|
+
if (on === watching) return;
|
|
635
|
+
watching = on;
|
|
636
|
+
if (on) {
|
|
637
|
+
document.addEventListener("scroll", recheck, { capture: true, passive: true });
|
|
638
|
+
window.addEventListener("resize", recheck);
|
|
639
|
+
} else {
|
|
640
|
+
document.removeEventListener("scroll", recheck, { capture: true });
|
|
641
|
+
window.removeEventListener("resize", recheck);
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
const observer = new IntersectionObserver(
|
|
645
|
+
(entries) => {
|
|
646
|
+
const last2 = entries.at(-1);
|
|
647
|
+
if (!last2) return;
|
|
648
|
+
const root = last2.rootBounds;
|
|
649
|
+
const box = last2.boundingClientRect;
|
|
650
|
+
setNear(
|
|
651
|
+
root ? box.bottom >= root.top && box.top <= root.bottom && box.right >= root.left && box.left <= root.right : last2.isIntersecting
|
|
652
|
+
);
|
|
653
|
+
watch(Boolean(root) && !last2.isIntersecting);
|
|
654
|
+
},
|
|
655
|
+
{ root: document, rootMargin: margin }
|
|
656
|
+
);
|
|
657
|
+
observer.observe(el);
|
|
658
|
+
return () => {
|
|
659
|
+
observer.disconnect();
|
|
660
|
+
watch(false);
|
|
661
|
+
};
|
|
662
|
+
}, [ref, margin]);
|
|
663
|
+
return near;
|
|
664
|
+
}
|
|
651
665
|
|
|
652
|
-
export {
|
|
653
|
-
//# sourceMappingURL=chunk-
|
|
654
|
-
//# sourceMappingURL=chunk-
|
|
666
|
+
export { IN_VIEW_MARGIN, StoryHost, createGlobalsTarget, createOverrides, indexRenderOf, loadStories, resolveCssVar, runAxe, scanCssVars, useClockLoop, useNearViewport, useStoryClock };
|
|
667
|
+
//# sourceMappingURL=chunk-4NM3RTYK.js.map
|
|
668
|
+
//# sourceMappingURL=chunk-4NM3RTYK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/frame/a11y.ts","../src/frame/cssVars.ts","../src/frame/globalsTarget.ts","../src/timeline/useClockLoop.ts","../src/timeline/clock.ts","../src/timeline/StoryClock.tsx","../src/frame/StoryHost.tsx","../src/csf/argsToSchema.ts","../src/timeline/declare.ts","../src/csf/loadCsfModule.tsx","../src/story/native.ts","../src/story/load.ts","../src/frame/useNearViewport.ts"],"names":["last","useEffect","jsx","value","isPlainObject","useContext","useState","config","f"],"mappings":"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","file":"chunk-4NM3RTYK.js","sourcesContent":["import type { A11yFinding, A11yReport } from '../protocol/messages';\n\n/** The shape of `axe.run`'s answer this module reads. */\ninterface AxeResult {\n violations: readonly AxeFinding[];\n incomplete: readonly AxeFinding[];\n passes: readonly unknown[];\n inapplicable: readonly unknown[];\n}\ninterface AxeFinding {\n id: string;\n impact?: string | null;\n help: string;\n helpUrl: string;\n description: string;\n nodes: readonly { target: readonly unknown[]; html: string; failureSummary?: string }[];\n}\ninterface AxeModule {\n run(context: Element, options?: unknown): Promise<AxeResult>;\n}\n\nconst IMPACTS = new Set(['minor', 'moderate', 'serious', 'critical']);\n\nfunction finding(from: AxeFinding): A11yFinding {\n const impact = from.impact ?? '';\n return {\n id: from.id,\n impact: IMPACTS.has(impact) ? (impact as A11yFinding['impact']) : null,\n help: from.help,\n helpUrl: from.helpUrl,\n description: from.description,\n nodes: from.nodes.map((node) => ({\n // An axe target entry is a selector, or an array of them for an element inside a shadow root.\n target: node.target.map((part) => (Array.isArray(part) ? part.join(' ') : String(part))),\n html: node.html,\n ...(node.failureSummary === undefined ? {} : { failureSummary: node.failureSummary }),\n })),\n };\n}\n\nlet loading: Promise<AxeModule> | null = null;\n\n/** axe is ~500 KB, so a frame that is never audited never pays for it. */\nfunction loadAxe(): Promise<AxeModule> {\n loading ??= import('axe-core').then((mod) => (mod as unknown as { default?: AxeModule }).default ?? (mod as unknown as AxeModule));\n return loading;\n}\n\n/** Rules that judge the page rather than the element audited; off when the element is one story on a page of many. */\nexport const PAGE_RULES: readonly string[] = [\n 'bypass',\n 'document-title',\n 'html-has-lang',\n 'html-lang-valid',\n 'html-xml-lang-mismatch',\n 'landmark-one-main',\n 'page-has-heading-one',\n 'region',\n];\n\nexport interface RunAxeOptions {\n /** Whether `element` stands for the whole page. False leaves `PAGE_RULES` out. Default true. */\n page?: boolean;\n}\n\n// axe refuses a run while another is under way in the same document, and the workshop page holds every story.\nlet last: Promise<unknown> = Promise.resolve();\n\n/** Runs axe over `element` and reduces its answer to what crosses the frame's channel. A run waits for the one before it. */\nexport async function runAxe(element: Element, { page = true }: RunAxeOptions = {}): Promise<A11yReport> {\n const axe = await loadAxe();\n const rules = page ? undefined : Object.fromEntries(PAGE_RULES.map((id) => [id, { enabled: false }]));\n const run = () => axe.run(element, rules ? { rules } : undefined);\n const running = last.then(run, run);\n last = running;\n const result = await running;\n return {\n violations: result.violations.map(finding),\n incomplete: result.incomplete.map(finding),\n passes: result.passes.length,\n inapplicable: result.inapplicable.length,\n };\n}\n","import type { CssVarReport } from '../protocol/messages';\n\nconst VAR_REF = /var\\(\\s*(--[\\w-]+)/g;\n\nfunction collect(text: string, names: Set<string>): void {\n if (!text.includes('var(')) return;\n for (const [, name] of text.matchAll(VAR_REF)) names.add(name!);\n}\n\n/** A grouping rule's text holds its children's; an `@import` holds only its URL, so its sheet is read too. */\nfunction walkRules(sheet: CSSStyleSheet, names: Set<string>): void {\n let rules: CSSRuleList;\n try {\n rules = sheet.cssRules;\n } catch {\n // A cross-origin sheet refuses to be read.\n return;\n }\n for (const rule of Array.from(rules)) {\n const imported = (rule as CSSRule & { styleSheet?: CSSStyleSheet | null }).styleSheet;\n if (imported) walkRules(imported, names);\n else collect(rule.cssText, names);\n }\n}\n\n/**\n * Every custom property the document references with `var()`, from inline styles and stylesheet rules — computed\n * styles have already substituted the reference away. Values resolve on `root`, the document's by default, or else\n * on the first element under it that declares one.\n */\nexport function scanCssVars(\n doc: Document,\n overridden: (name: string) => boolean = () => false,\n root: Element = doc.documentElement,\n): CssVarReport[] {\n const names = new Set<string>();\n for (const el of Array.from(doc.querySelectorAll('[style]'))) collect(el.getAttribute('style') ?? '', names);\n for (const sheet of Array.from(doc.styleSheets)) walkRules(sheet, names);\n\n const values = resolveValues(doc, names, root);\n return [...names]\n .sort()\n .map((name) => ({ name, value: values.get(name) ?? '', overridden: overridden(name) }));\n}\n\nfunction resolveValues(doc: Document, names: Iterable<string>, root: Element): Map<string, string> {\n const view = doc.defaultView;\n const values = new Map<string, string>();\n if (!view) return values;\n const own = view.getComputedStyle(root);\n const missing: string[] = [];\n for (const name of names) {\n const value = own.getPropertyValue(name).trim();\n if (value) values.set(name, value);\n else missing.push(name);\n }\n const under = root === doc.documentElement ? (doc.body ?? root) : root;\n for (const el of missing.length > 0 ? Array.from(under.querySelectorAll('*')) : []) {\n const style = view.getComputedStyle(el);\n for (let i = missing.length - 1; i >= 0; i--) {\n const value = style.getPropertyValue(missing[i]!).trim();\n if (!value) continue;\n values.set(missing[i]!, value);\n missing.splice(i, 1);\n }\n if (missing.length === 0) break;\n }\n return values;\n}\n\n/** One custom property's value, resolved the way `scanCssVars` resolves each. */\nexport function resolveCssVar(doc: Document, name: string, root: Element = doc.documentElement): string {\n return resolveValues(doc, [name], root).get(name) ?? '';\n}\n\nexport interface Overrides {\n set(name: string, value: string | null): void;\n has(name: string): boolean;\n /** Whether `node` is the override style element or inside it. */\n owns(node: Node): boolean;\n dispose(): void;\n}\n\n/**\n * Custom property overrides as one rule on `scope`, kept last in `<head>`. `:not(#fg-overrides)` adds an ID's weight\n * without `!important`, so the rule outranks a theme's attribute selectors; a stylesheet that lands after it sends\n * the element back to the end.\n */\nexport function createOverrides(doc: Document, scope = ':root'): Overrides {\n const values = new Map<string, string>();\n const style = doc.createElement('style');\n style.setAttribute('data-fg-overrides', '');\n\n // Another instance's style counts as last place too, or two instances would take turns moving forever.\n const keepLast = () => {\n if (style.parentNode === doc.head) {\n let next = style.nextElementSibling;\n while (next?.hasAttribute('data-fg-overrides')) next = next.nextElementSibling;\n if (next === null) return;\n }\n doc.head.append(style);\n };\n const write = () => {\n const decls = [...values].map(([name, value]) => ` ${name}: ${value};`);\n style.textContent = decls.length > 0 ? `:is(${scope}):not(#fg-overrides) {\\n${decls.join('\\n')}\\n}\\n` : '';\n };\n\n keepLast();\n const observer = typeof MutationObserver === 'undefined' ? null : new MutationObserver(keepLast);\n observer?.observe(doc.head, { childList: true });\n\n return {\n set(name, value) {\n if (value === null) values.delete(name);\n else values.set(name, value);\n write();\n },\n has: (name) => values.has(name),\n owns: (node) => style.contains(node),\n dispose() {\n observer?.disconnect();\n style.remove();\n },\n };\n}\n","/** What a setup's `applyGlobals` is handed: the element the globals apply to, and a way to style it alone. */\nexport interface GlobalsTarget {\n /** A frame document's root, or one story's host in the workshop document. */\n root: HTMLElement;\n /** A selector matching `root` and nothing else, so a rule written under it reaches only this target. */\n scope: string;\n /** Replaces the CSS forge keeps for this target. */\n style: (css: string) => void;\n}\n\n/** A target over `root`, owning one `<style>` in the document's head; `dispose` removes it. */\nexport function createGlobalsTarget(root: HTMLElement, scope: string): GlobalsTarget & { dispose: () => void } {\n const doc = root.ownerDocument;\n let style: HTMLStyleElement | null = null;\n return {\n root,\n scope,\n style(css) {\n if (!style) {\n style = doc.createElement('style');\n style.setAttribute('data-fg-globals', scope);\n doc.head.append(style);\n }\n style.textContent = css;\n },\n dispose() {\n style?.remove();\n style = null;\n },\n };\n}\n","import { useVisibleRaf, type VisibleRafTarget } from '@weasel-js/core';\nimport { useEffect, useRef, useSyncExternalStore } from 'react';\nimport type { Clock } from './clock';\n\nconst NEVER = () => () => {};\nconst notPlaying = () => false;\n\n/** Drives `clock` from frames while it plays. Frames stop while the page or `target` is out of sight, and the time\n * spent there is dropped rather than arriving as one long frame. */\nexport function useClockLoop(clock: Clock | null, target?: VisibleRafTarget): void {\n const playing = useSyncExternalStore(clock?.subscribe ?? NEVER, clock ? () => clock.get().playing : notPlaying);\n const last = useRef<number | null>(null);\n const raf = useVisibleRaf(\n (now) => {\n if (!clock) return;\n const prev = last.current;\n last.current = now;\n if (prev !== null) clock.tick(now - prev);\n if (clock.get().playing) raf.request();\n },\n {\n ...(target ? { target } : {}),\n onResume: () => {\n last.current = null;\n },\n },\n );\n useEffect(() => {\n if (!playing) return;\n last.current = null;\n raf.request();\n return () => raf.cancel();\n }, [playing, raf]);\n}\n","import { createEmitter } from '@weasel-js/registry';\n\n/** What a story declares to get a playhead. Times are in ms, as `@weasel-js/ui`'s timeline components take them. */\nexport interface TimelineSpec {\n /** How long the span runs. */\n duration: number;\n /** Where the span begins; below zero gives a lead-in before the story's zero. A fresh trial opens here. Default 0. */\n start?: number;\n /** Whether playing past the end wraps back to `start`. Default true. */\n loop?: boolean;\n /** Playback speed multiplier. Default 1. */\n rate?: number;\n}\n\n/** The span a playhead may stand in, in ms. */\nexport interface Span {\n start: number;\n end: number;\n}\n\n/** Everything a clock holds. */\nexport interface ClockState {\n /** The playhead, in ms, always inside `span`. */\n time: number;\n playing: boolean;\n loop: boolean;\n rate: number;\n span: Span;\n}\n\n/** A span replacing the declared one at runtime, as `StoryTimeline.setSpan` takes it. */\nexport type SpanOverride = Pick<TimelineSpec, 'duration' | 'start'>;\n\nexport function spanOf(spec: SpanOverride): Span {\n const start = Number.isFinite(spec.start) ? (spec.start as number) : 0;\n const duration = Number.isFinite(spec.duration) && spec.duration > 0 ? spec.duration : 0;\n return { start, end: start + duration };\n}\n\nexport function clampTime(span: Span, t: number): number {\n if (Number.isNaN(t)) return span.start;\n return Math.min(span.end, Math.max(span.start, t));\n}\n\n/** `state` after `elapsed` ms of wall time. Past the end it wraps when looping, and otherwise stops there, paused. */\nexport function advance(state: ClockState, elapsed: number): ClockState {\n if (!state.playing) return state;\n const { start, end } = state.span;\n const length = end - start;\n if (length <= 0) return { ...state, time: start, playing: false };\n const next = state.time + elapsed * state.rate;\n if (next <= end) return { ...state, time: next };\n if (!state.loop) return { ...state, time: end, playing: false };\n return { ...state, time: start + ((next - start) % length) };\n}\n\nconst validRate = (rate: number | undefined): rate is number => typeof rate === 'number' && Number.isFinite(rate) && rate > 0;\n\n/** A story's clock: its state as an external store, and the moves the transport and the story make on it. */\nexport interface Clock {\n get(): ClockState;\n subscribe(listener: () => void): () => void;\n play(): void;\n pause(): void;\n seek(time: number): void;\n /**\n * Pauses at `time`, asked for from outside the story — a URL, a persisted value — and keeps asking: every span\n * change clamps it afresh, so a span that only arrives later can still hold it, until play, a seek or another\n * request moves the playhead. Null asks for the span's start, wherever it ends up.\n */\n request(time: number | null): void;\n /** The requested time while the span cannot hold it yet, or null. Whatever echoes the playhead outward waits on it. */\n pending(): number | null;\n setLoop(loop: boolean): void;\n setRate(rate: number): void;\n /** Replaces the declared span until called with null. */\n setSpan(span: SpanOverride | null): void;\n /** The story's declaration changed, as after an edit or a new config. Only its span is taken up. */\n declare(spec: TimelineSpec): void;\n /** Advances a playing clock by `elapsed` ms of wall time. */\n tick(elapsed: number): void;\n}\n\n/** Where a request puts the playhead in `span`; null asks for its start. */\nconst placed = (span: Span, requested: number | null): number =>\n requested === null ? span.start : clampTime(span, requested);\n\n/** A clock for `spec`, paused at a request for `initial`, which is the span start when none is given. */\nexport function createClock(spec: TimelineSpec, initial?: number | null): Clock {\n let declared = spanOf(spec);\n let override: Span | null = null;\n // Until something moves the playhead it stands where it was asked to, re-placed in every new span, so a span set\n // after mount still opens at the start — or at a URL's time beyond the span declared before it.\n let requested: { time: number | null } | null = { time: initial ?? null };\n let state: ClockState = {\n time: placed(declared, requested.time),\n playing: false,\n loop: spec.loop ?? true,\n rate: validRate(spec.rate) ? spec.rate : 1,\n span: declared,\n };\n const changed = createEmitter();\n const pendingIn = (at: ClockState): number | null =>\n requested && requested.time !== null && requested.time !== at.time ? requested.time : null;\n // What echoes the playhead outward waits on a pending request, so its coming and going notifies as a move does.\n let pending = pendingIn(state);\n\n const set = (next: ClockState): void => {\n const nextPending = pendingIn(next);\n if (\n nextPending === pending &&\n next.time === state.time &&\n next.playing === state.playing &&\n next.loop === state.loop &&\n next.rate === state.rate &&\n next.span.start === state.span.start &&\n next.span.end === state.span.end\n )\n return;\n state = next;\n pending = nextPending;\n changed.emit();\n };\n const moved = (next: ClockState): void => {\n requested = null;\n set(next);\n };\n const respan = (): void => {\n const span = override ?? declared;\n set({ ...state, span, time: requested ? placed(span, requested.time) : clampTime(span, state.time) });\n };\n\n return {\n get: () => state,\n subscribe: changed.subscribe,\n play() {\n if (state.playing) return;\n // Playing from the end starts over, as a player's play button does.\n moved({ ...state, playing: true, time: state.time >= state.span.end ? state.span.start : state.time });\n },\n pause: () => set({ ...state, playing: false }),\n seek: (time) => moved({ ...state, time: clampTime(state.span, time) }),\n request(time) {\n requested = { time: Number.isNaN(time) ? null : time };\n set({ ...state, playing: false, time: placed(state.span, requested.time) });\n },\n pending: () => pending,\n setLoop: (loop) => set({ ...state, loop }),\n setRate(rate) {\n if (validRate(rate)) set({ ...state, rate });\n },\n setSpan(span) {\n override = span ? spanOf(span) : null;\n respan();\n },\n declare(next) {\n declared = spanOf(next);\n respan();\n },\n tick(elapsed) {\n if (state.playing) moved(advance(state, elapsed));\n },\n };\n}\n","import { useLatest } from '@weasel-js/core';\nimport { type ReactNode, useContext, useEffect, useState } from 'react';\nimport type { LoadedStory } from '../story/types';\nimport { type Clock, createClock, type TimelineSpec } from './clock';\nimport { ClockContext } from './context';\nimport { useClockLoop } from './useClockLoop';\n\n/**\n * A clock for a story declaring `spec`, kept across renders and redeclared when the span it declares changes. It is\n * made when a declaration appears and dropped when it goes, as an edit can do either. `initial` is read only when\n * the clock is made.\n */\nexport function useStoryClock(spec: TimelineSpec | null, initial: () => number | null): Clock | null {\n const [clock, setClock] = useState(() => (spec ? createClock(spec, initial()) : null));\n let current = clock;\n if (spec && !clock) {\n current = createClock(spec, initial());\n setClock(current);\n } else if (!spec && clock) {\n current = null;\n setClock(null);\n }\n const latest = useLatest(spec);\n const spanKey = spec ? `${spec.start ?? 0}:${spec.duration}` : null;\n useEffect(() => {\n if (current && latest.current) current.declare(latest.current);\n }, [current, spanKey, latest]);\n return current;\n}\n\nconst NO_INITIAL = () => null;\n\nfunction OwnClock({ spec, children }: { spec: TimelineSpec; children: ReactNode }) {\n const clock = useStoryClock(spec, NO_INITIAL);\n useClockLoop(clock);\n return <ClockContext.Provider value={clock}>{children}</ClockContext.Provider>;\n}\n\n/**\n * Gives a story declaring a timeline a clock of its own where nothing above supplies one — an index page, a frame, a\n * story test. It stands paused at the span's start, with no transport, until the story moves it.\n */\nexport function WithStoryClock({ story, config, children }: { story: LoadedStory; config: unknown; children: ReactNode }) {\n const outer = useContext(ClockContext);\n if (outer || !story.timeline) return children;\n return <OwnClock spec={story.timeline(config)}>{children}</OwnClock>;\n}\n","import { Component, type ReactNode } from 'react';\nimport type { Decorator, LoadedStory, StoryContext } from '../story/types';\nimport { WithStoryClock } from '../timeline/StoryClock';\n\nexport interface StoryHostProps {\n story: LoadedStory;\n ctx: StoryContext;\n /** Outermost decorators, from the frame setup. */\n decorators: readonly Decorator[];\n /** A change clears a caught error, so new input retries the render. */\n resetKey: number;\n onError: (error: unknown) => void;\n}\n\nfunction RenderStory({ story, ctx }: { story: LoadedStory; ctx: StoryContext }): ReactNode {\n return story.render(ctx);\n}\n\nfunction Decorated({ story, ctx, decorators }: Omit<StoryHostProps, 'resetKey' | 'onError'>): ReactNode {\n let inner: () => ReactNode = () => <RenderStory story={story} ctx={ctx} />;\n for (const decorate of [...story.decorators, ...decorators]) {\n const wrapped = inner;\n inner = () => decorate(wrapped, ctx);\n }\n return inner();\n}\n\ninterface BoundaryState {\n error: unknown;\n failed: boolean;\n resetKey: number;\n}\n\nexport class StoryHost extends Component<StoryHostProps, BoundaryState> {\n override state: BoundaryState = { error: null, failed: false, resetKey: this.props.resetKey };\n\n static getDerivedStateFromProps(props: StoryHostProps, state: BoundaryState): Partial<BoundaryState> | null {\n return props.resetKey === state.resetKey ? null : { error: null, failed: false, resetKey: props.resetKey };\n }\n\n static getDerivedStateFromError(error: unknown): Partial<BoundaryState> {\n return { error, failed: true };\n }\n\n override componentDidCatch(error: unknown): void {\n this.props.onError(error);\n }\n\n override render(): ReactNode {\n if (this.state.failed) {\n const { error } = this.state;\n return <pre className=\"fg-frame__fault\">{error instanceof Error ? error.message : String(error)}</pre>;\n }\n const { story, ctx, decorators } = this.props;\n return (\n <WithStoryClock story={story} config={ctx.config}>\n <Decorated story={story} ctx={ctx} decorators={decorators} />\n </WithStoryClock>\n );\n }\n}\n","import { type ConfigNode, type ConfigSchema, type ConfigShape, f } from '@weasel-js/labkit/config';\nimport { isPlainObject } from '@weasel-js/core';\nimport { portSafePart } from './portSafe';\n\n/** Storybook's conditional control: shown only while an arg, or a global, meets the test. */\nexport type ArgCondition = ({ arg: string } | { global: string }) & {\n truthy?: boolean;\n exists?: boolean;\n eq?: unknown;\n neq?: unknown;\n};\n\n/** A CSF `argTypes` entry, as far as forge reads it. */\nexport interface ArgType {\n name?: string;\n description?: string;\n control?:\n | string\n | false\n | {\n type?: string;\n min?: number;\n max?: number;\n step?: number;\n /** forge's own: an icon (weasel-ui `IconName`) per option, drawn in place of its label. */\n icons?: Readonly<Record<string, string>>;\n };\n options?: readonly unknown[];\n table?: { disable?: boolean };\n if?: ArgCondition;\n}\n\ninterface Leaf extends ConfigNode<unknown> {\n hidden(): Leaf;\n describe(description: string): Leaf;\n label(name: string): Leaf;\n showIf(predicate: (config: Record<string, unknown>) => boolean): Leaf;\n}\n\ninterface Control {\n type: string | undefined;\n min?: number;\n max?: number;\n step?: number;\n icons?: Readonly<Record<string, string>>;\n}\n\nfunction controlOf(argType: ArgType): Control | false {\n const { control } = argType;\n if (control === false) return false;\n if (typeof control === 'string') return { type: control };\n return { type: control?.type, min: control?.min, max: control?.max, step: control?.step, icons: control?.icons };\n}\n\nfunction stringOptions(argType: ArgType): string[] | null {\n const opts = argType.options;\n return opts && opts.length > 0 && opts.every((o) => typeof o === 'string') ? (opts as string[]) : null;\n}\n\nfunction inferred(value: unknown): Leaf | null {\n switch (typeof value) {\n case 'number':\n return f.number(value);\n case 'boolean':\n return f.boolean(value);\n case 'string':\n return f.string(value);\n default:\n return Array.isArray(value) || isPlainObject(value) ? f.custom('json', value) : null;\n }\n}\n\nfunction bounded(node: ReturnType<typeof f.number>, control: Control) {\n let out = node;\n if (control.min !== undefined && control.max !== undefined) out = out.range(control.min, control.max);\n if (control.step !== undefined) out = out.step(control.step);\n return out;\n}\n\nfunction controlled(control: Control, argType: ArgType, has: boolean, value: unknown): Leaf | null {\n const options = stringOptions(argType);\n // Storybook passes an argTypes-only key as undefined, so the component's own default applies.\n const def = <T>() => (has ? value : undefined) as T;\n switch (control.type) {\n case 'number': {\n const node = bounded(f.number(def()), control);\n return control.min !== undefined && control.max !== undefined ? node.input() : node;\n }\n case 'range':\n case 'slider':\n return has ? bounded(f.number(def()), control).slider() : null;\n case 'boolean':\n return f.boolean(def());\n case 'switch':\n return f.boolean(def()).toggle();\n case 'text':\n case 'textarea':\n return f.string(def());\n case 'select':\n case 'radio':\n case 'inline-radio':\n case undefined: {\n if (!options) return control.type === undefined && has ? inferred(value) : null;\n const { icons } = control;\n const node = f.enum(\n def<string>(),\n icons ? options.map((value) => ({ value, label: value, ...(icons[value] ? { icon: icons[value] } : {}) })) : options,\n );\n return control.type === 'radio' || control.type === 'inline-radio' ? node.radio() : node;\n }\n case 'object':\n return has ? f.custom('json', value) : null;\n default:\n return has ? inferred(value) : null;\n }\n}\n\n/** The config predicate for an `if`; null for a condition on a global, which a story's config does not hold. */\nfunction conditionOf(condition: ArgCondition): ((config: Record<string, unknown>) => boolean) | null {\n if (!('arg' in condition)) return null;\n const { arg } = condition;\n return (config) => {\n const value = config[arg];\n if (condition.exists !== undefined) return (value !== undefined) === condition.exists;\n if ('eq' in condition) return Object.is(value, condition.eq);\n if ('neq' in condition) return !Object.is(value, condition.neq);\n return Boolean(value) === (condition.truthy ?? true);\n };\n}\n\n/** `parameters.controls.matchers`: arg names that pick a control when the arg's argType names none. */\nexport interface ControlMatchers {\n color?: RegExp;\n /** labkit has no date leaf, so a date match keeps the leaf its value infers. */\n date?: RegExp;\n}\n\n/** Storybook's rule: a string arg with no control or options whose name matches `color` gets a color picker. */\nfunction matched(key: string, value: unknown, argType: ArgType | undefined, matchers: ControlMatchers): Leaf | null {\n if (typeof value !== 'string' || argType?.control !== undefined || stringOptions(argType ?? {})) return null;\n return matchers.color?.test(key) ? f.color(value) : null;\n}\n\n/** A labkit schema for a CSF story's args, refined by its `argTypes`. */\nexport function argsToSchema(\n args: Readonly<Record<string, unknown>>,\n argTypes: Readonly<Record<string, ArgType | undefined>>,\n matchers: ControlMatchers = {},\n): ConfigSchema<unknown> {\n const nodes: Record<string, Leaf> = {};\n for (const key of new Set([...Object.keys(args), ...Object.keys(argTypes)])) {\n const has = key in args;\n // A control carries only what crosses the port; the frame puts the rest back from `args` (`withUnsent`).\n const part = has ? portSafePart(args[key]) : null;\n if (has && !part) continue;\n const value = part?.value;\n const argType = argTypes[key];\n const control = argType ? controlOf(argType) : false;\n\n let node: Leaf | null =\n (has ? matched(key, value, argType, matchers) : null) ??\n (control ? controlled(control, argType ?? {}, has, value) : has ? inferred(value) : null);\n if (!node) continue;\n if (argType && (argType.control === false || argType.table?.disable)) node = node.hidden();\n if (argType?.description) node = node.describe(argType.description);\n if (argType?.name) node = node.label(argType.name);\n const shownWhen = argType?.if ? conditionOf(argType.if) : null;\n if (shownWhen) node = node.showIf(shownWhen);\n nodes[key] = node;\n }\n return f.schema(nodes as ConfigShape);\n}\n","import type { TimelineSpec } from './clock';\n\nconst isSpec = (value: unknown): value is TimelineSpec =>\n !!value && typeof value === 'object' && typeof (value as { duration?: unknown }).duration === 'number';\n\n/** A declared timeline as a function of config: a spec stands for itself at every config, a function is called with\n * the config. Anything else declares none. `adapt` turns the trial's config into what the function is handed. */\nexport function timelineOf(\n value: unknown,\n adapt: (config: unknown) => unknown = (config) => config,\n): ((config: unknown) => TimelineSpec) | null {\n if (isSpec(value)) return () => value;\n if (typeof value === 'function') return (config) => (value as (input: unknown) => TimelineSpec)(adapt(config));\n return null;\n}\n","import {\n type ComponentType,\n createContext,\n createElement,\n type Dispatch,\n type ReactNode,\n type SetStateAction,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport type { Globals, Layout, Viewport } from '../protocol/messages';\nimport { storyId, storyNameFromExport } from '../story/ids';\nimport type { Decorator, LoadedStory, PlayContext, StoryContext } from '../story/types';\nimport { type ArgsScope, ArgsContext, appliedLocal, coverOf, type LocalArgs } from './argsContext';\nimport { type ArgType, argsToSchema, type ControlMatchers } from './argsToSchema';\nimport { isPlainObject } from '@weasel-js/core';\nimport { withUnsent } from './portSafe';\nimport { PROP_ARG_TYPES_EXPORT } from './propArgTypes';\nimport { timelineOf } from '../timeline/declare';\n\ntype Args = Record<string, unknown>;\ntype CsfContext = {\n args: Args;\n globals: Globals;\n parameters: Record<string, unknown>;\n title: string;\n name: string;\n id: string;\n viewMode: 'story';\n};\ntype CsfRender = (args: Args, context: CsfContext) => ReactNode;\ntype CsfDecorator = (Story: ComponentType, context: CsfContext) => ReactNode;\ntype CsfPlay = (context: CsfContext & { canvasElement: HTMLElement; step: CsfStep }) => void | Promise<void>;\ntype CsfStep = (label: string, fn: () => void | Promise<void>) => Promise<void>;\n\ninterface Annotations {\n title?: string;\n name?: string;\n storyName?: string;\n component?: ComponentType<Args>;\n args?: Args;\n argTypes?: Record<string, ArgType>;\n parameters?: Record<string, unknown>;\n globals?: Record<string, unknown>;\n decorators?: CsfDecorator | CsfDecorator[];\n render?: CsfRender;\n play?: CsfPlay;\n includeStories?: string[] | RegExp;\n excludeStories?: string[] | RegExp;\n}\n\nconst LAYOUTS: readonly Layout[] = ['centered', 'padded', 'fullscreen'];\n\nconst asArray = <T,>(value: T | T[] | undefined): T[] => (value === undefined ? [] : Array.isArray(value) ? value : [value]);\n\n/** Storybook's `deleteUndefined`, which its args store applies after every update. */\nconst withoutUndefined = (args: Args): Args =>\n Object.fromEntries(Object.entries(args).filter(([, value]) => value !== undefined));\n\n/** Storybook's `matches` from `isExportStory`. */\nconst matches = (key: string, filter: string[] | RegExp) =>\n Array.isArray(filter) ? filter.includes(key) : key.match(filter) !== null;\n\n/** Storybook's `combineParameters`: plain objects merge deeply, anything else is replaced. */\nfunction combineParameters(...sources: (Record<string, unknown> | undefined)[]): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const source of sources) {\n for (const [key, value] of Object.entries(source ?? {})) {\n if (value === undefined) continue;\n out[key] = isPlainObject(value) && isPlainObject(out[key]) ? combineParameters(out[key], value) : value;\n }\n }\n return out;\n}\n\nfunction resolveViewport(parameters: Record<string, unknown>, globals: Record<string, unknown>): Viewport | null {\n const selected = globals.viewport as { value?: string; isRotated?: boolean } | undefined;\n const options = (parameters.viewport as { options?: Record<string, { styles?: { width?: string; height?: string } }> } | undefined)\n ?.options;\n const styles = selected?.value ? options?.[selected.value]?.styles : undefined;\n const px = (v: string | undefined) => (v && /^\\d+(\\.\\d+)?px$/.test(v) ? Number.parseFloat(v) : Number.NaN);\n const width = px(styles?.width);\n const height = px(styles?.height);\n if (Number.isNaN(width) || Number.isNaN(height)) return null;\n return selected?.isRotated ? { width: height, height: width } : { width, height };\n}\n\nconst InnerStory = createContext<(() => ReactNode) | null>(null);\n\nfunction Story(): ReactNode {\n return useContext(InnerStory)?.() ?? null;\n}\n\nfunction Call({ fn }: { fn: () => ReactNode }): ReactNode {\n return fn();\n}\n\ninterface StoryLocals {\n story: string;\n local: LocalArgs;\n setLocal: Dispatch<SetStateAction<LocalArgs>>;\n}\n\nconst LocalArgsContext = createContext<StoryLocals | null>(null);\n\n/** The outermost scope of a story holds its frame-local args, so its decorators and render share them. */\nfunction Scoped({\n id,\n build,\n fn,\n}: {\n id: string;\n build: (local: StoryLocals) => [ArgsScope, CsfContext];\n fn: (context: CsfContext) => ReactNode;\n}): ReactNode {\n const outer = useContext(LocalArgsContext);\n const [local, setLocal] = useState<LocalArgs>({});\n const shared = outer?.story === id ? outer : { story: id, local, setLocal };\n const [scope, context] = build(shared);\n const { config } = scope;\n const prune = shared.setLocal;\n // An entry config has moved past must not come back if config later returns to the value it covered.\n useEffect(() => {\n prune((prev) => {\n const kept = Object.entries(prev).filter(([key, entry]) => coverOf(config[key]) === entry.over);\n return kept.length === Object.keys(prev).length ? prev : Object.fromEntries(kept);\n });\n }, [config, prune]);\n return createElement(\n LocalArgsContext.Provider,\n { value: shared },\n createElement(ArgsContext.Provider, { value: scope }, createElement(Call, { fn: () => fn(context) })),\n );\n}\n\n/**\n * Normalizes a Component Story Format module. `title` is the index entry's, which wins over the meta's own: the\n * index reads the meta without running it and falls back to the auto title for one it cannot read, so taking the\n * meta's here would give one story two ids. `parameters` are the project's, under the meta's and each story's.\n */\nexport function loadCsfModule(\n mod: Record<string, unknown>,\n title: string,\n projectParameters: Record<string, unknown> = {},\n): LoadedStory[] {\n const meta = (isPlainObject(mod.default) ? mod.default : {}) as Annotations;\n const stories: LoadedStory[] = [];\n const propArgTypes = isPlainObject(mod[PROP_ARG_TYPES_EXPORT]) ? (mod[PROP_ARG_TYPES_EXPORT] as Record<string, ArgType>) : undefined;\n\n for (const [exportName, value] of Object.entries(mod)) {\n if (exportName === PROP_ARG_TYPES_EXPORT) continue;\n if (exportName === 'default' || exportName === '__namedExportsOrder' || exportName === '__esModule') continue;\n if (meta.includeStories && !matches(exportName, meta.includeStories)) continue;\n if (meta.excludeStories && matches(exportName, meta.excludeStories)) continue;\n if (!value || (typeof value !== 'object' && typeof value !== 'function')) continue;\n\n // A CSF 2 function export hoists its annotations onto itself.\n const spec: Annotations = typeof value === 'function' ? { ...value, render: value as CsfRender } : (value as Annotations);\n const id = storyId(title, exportName);\n const name = spec.name || spec.storyName || storyNameFromExport(exportName);\n const args = { ...meta.args, ...spec.args };\n const parameters = combineParameters(projectParameters, meta.parameters, spec.parameters);\n const matchers = (parameters.controls as { matchers?: ControlMatchers } | undefined)?.matchers;\n const render = spec.render ?? meta.render;\n // A render that takes no args draws the same thing whatever a prop's control says.\n const fromProps = render === undefined || render.length > 0 ? propArgTypes : undefined;\n const config = argsToSchema(\n args,\n combineParameters(fromProps, meta.argTypes, spec.argTypes) as Record<string, ArgType>,\n isPlainObject(matchers) ? matchers : {},\n );\n const defaults = config.defaults() as Args;\n const storyGlobals = { ...meta.globals, ...spec.globals };\n const component = meta.component;\n const renderFn: CsfRender | undefined =\n render ?? (component ? (a) => createElement(component, a) : undefined);\n\n const withArgs = (config: Args): Args =>\n Object.fromEntries(\n Object.entries(withoutUndefined(config)).map(([key, value]) => [key, key in args ? withUnsent(value, args[key]) : value]),\n );\n const csfContext = (config: unknown, globals: Globals, local: LocalArgs = {}): CsfContext => ({\n args: withoutUndefined({ ...args, ...withArgs(config as Args), ...appliedLocal(local, config as Args) }),\n globals,\n parameters,\n title,\n name,\n id,\n viewMode: 'story',\n });\n const scoped = (ctx: StoryContext, fn: (context: CsfContext) => ReactNode): ReactNode =>\n createElement(Scoped, {\n id,\n build: ({ local, setLocal }: StoryLocals): [ArgsScope, CsfContext] => {\n const context = csfContext(ctx.config, ctx.globals, local);\n const scope: ArgsScope = {\n args: context.args,\n config: ctx.config as Args,\n defaults,\n original: args,\n setConfig: ctx.setConfig,\n setLocal,\n };\n return [scope, context];\n },\n fn,\n });\n\n const adapt =\n (decorator: CsfDecorator): Decorator =>\n (inner, ctx) =>\n createElement(\n InnerStory.Provider,\n { value: inner },\n scoped(ctx, (context) => decorator(Story, context)),\n );\n\n const layout = parameters.layout as Layout | undefined;\n const forgeParams = parameters.forge as { isolate?: unknown; timeline?: unknown } | undefined;\n const isolate = forgeParams?.isolate;\n const play = spec.play ?? meta.play;\n\n stories.push({\n id,\n title,\n name,\n exportName,\n config,\n initialState: null,\n render: (ctx) => {\n if (!renderFn) return null;\n return scoped(ctx, (context) => renderFn(context.args, context));\n },\n decorators: [...asArray(spec.decorators), ...asArray(meta.decorators)].map(adapt),\n layout: layout && LAYOUTS.includes(layout) ? layout : 'padded',\n viewport: resolveViewport(parameters, storyGlobals),\n isolate: typeof isolate === 'string' ? isolate : null,\n play: play\n ? ({ canvasElement, config, globals }: PlayContext) =>\n play({ ...csfContext(config, globals), canvasElement, step: async (_label, fn) => fn() })\n : null,\n timeline: timelineOf(forgeParams?.timeline, (config) => csfContext(config, {}).args),\n });\n }\n return stories;\n}\n","import { f } from '@weasel-js/labkit/config';\nimport { isNative } from './define';\nimport { storyId, storyNameFromExport } from './ids';\nimport { timelineOf } from '../timeline/declare';\nimport type { LoadedStory, MetaSpec, StorySpec } from './types';\n\n/**\n * Normalizes a module written with `meta` and `story`; exports that are not stories are skipped. `title` is the index\n * entry's, which wins over the meta's own: the index reads the meta without running it and can miss it, so taking\n * the meta's here would give one story two titles.\n */\nexport function loadNativeModule(mod: Record<string, unknown>, title: string): LoadedStory[] {\n const metaSpec: MetaSpec = isNative(mod.default, 'meta') ? (mod.default as MetaSpec) : {};\n const stories: LoadedStory[] = [];\n for (const [exportName, value] of Object.entries(mod)) {\n if (exportName === 'default' || !isNative(value, 'story')) continue;\n const spec = value as StorySpec<unknown, unknown>;\n stories.push({\n id: storyId(title, exportName),\n title,\n name: spec.name ?? storyNameFromExport(exportName),\n exportName,\n config: spec.config ?? f.schema({}),\n initialState: spec.state ?? null,\n render: spec.render,\n decorators: [...(spec.decorators ?? []), ...(metaSpec.decorators ?? [])],\n layout: spec.layout ?? metaSpec.layout ?? 'centered',\n viewport: spec.viewport ?? null,\n isolate: spec.isolate ?? metaSpec.isolate ?? null,\n play: spec.play ?? null,\n timeline: timelineOf(spec.timeline ?? metaSpec.timeline),\n });\n }\n return stories;\n}\n","import { loadCsfModule } from '../csf/loadCsfModule';\nimport { isNative } from './define';\nimport { loadNativeModule } from './native';\nimport type { IndexRender, LoadedStory } from './types';\n\n/**\n * A story module's stories: a module whose default export is a forge `meta` is native, anything else is CSF under\n * `parameters`. `title` is the module's index entry title, which every story takes as given.\n */\nexport function loadStories(\n mod: Record<string, unknown>,\n title: string,\n parameters?: Record<string, unknown>,\n): LoadedStory[] {\n return isNative(mod.default, 'meta')\n ? loadNativeModule(mod, title)\n : loadCsfModule(mod, title, parameters);\n}\n\n/** A module's own index page: a native meta's `index`, or a CSF meta's `parameters.forge.index`. */\nexport function indexRenderOf(mod: Record<string, unknown>): IndexRender | null {\n const meta = mod.default as { index?: unknown; parameters?: { forge?: { index?: unknown } } } | undefined;\n const render = isNative(meta, 'meta') ? meta?.index : meta?.parameters?.forge?.index;\n return typeof render === 'function' ? (render as IndexRender) : null;\n}\n","import { type RefObject, useEffect, useState } from 'react';\n\n/** How far past the viewport a trial's story stays mounted, so a small scroll back does not reload it. */\nexport const IN_VIEW_MARGIN = '50%';\n\n/**\n * Whether `ref`'s element lies within `margin` of its document's viewport; true where the browser cannot say.\n * Decided by where the element is, not by whether any of it shows: `isIntersecting` is false too for an element an\n * `overflow` ancestor clips away, as a narrow lab tile does to its content while the tiling changes. `initial` is\n * the answer before the browser has given one: false for content too costly to mount everywhere at once.\n */\nexport function useNearViewport(ref: RefObject<Element | null>, margin: string, initial = true): boolean {\n const [near, setNear] = useState(() => initial || typeof IntersectionObserver === 'undefined');\n useEffect(() => {\n const el = ref.current;\n if (!el || typeof IntersectionObserver === 'undefined') return;\n // A fresh observe always reports, wherever the element is.\n const recheck = () => {\n observer.unobserve(el);\n observer.observe(el);\n };\n let watching = false;\n const watch = (on: boolean) => {\n if (on === watching) return;\n watching = on;\n if (on) {\n document.addEventListener('scroll', recheck, { capture: true, passive: true });\n window.addEventListener('resize', recheck);\n } else {\n document.removeEventListener('scroll', recheck, { capture: true });\n window.removeEventListener('resize', recheck);\n }\n };\n const observer = new IntersectionObserver(\n (entries) => {\n const last = entries.at(-1);\n if (!last) return;\n const root = last.rootBounds;\n const box = last.boundingClientRect;\n setNear(\n root\n ? box.bottom >= root.top && box.top <= root.bottom && box.right >= root.left && box.left <= root.right\n : last.isIntersecting,\n );\n // While nothing of it intersects, a clip can hide every move from the observer, so ask again on each scroll.\n watch(Boolean(root) && !last.isIntersecting);\n },\n { root: document, rootMargin: margin },\n );\n observer.observe(el);\n return () => {\n observer.disconnect();\n watch(false);\n };\n }, [ref, margin]);\n return near;\n}\n"]}
|