@weasel-js/forge 1.13.0-rc.0 → 1.14.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 +1 -1
- package/dist/{FrameController-Tv3jrHyT.d.ts → FrameController-BM6xuEfY.d.ts} +18 -10
- package/dist/{chunk-KEQBGDUZ.js → chunk-B26DWEYT.js} +3 -3
- package/dist/{chunk-KEQBGDUZ.js.map → chunk-B26DWEYT.js.map} +1 -1
- package/dist/{chunk-3BAM6M26.js → chunk-FPF2JSWB.js} +3 -3
- package/dist/chunk-FPF2JSWB.js.map +1 -0
- package/dist/{chunk-ORMMZ5PV.js → chunk-MRYXJTDO.js} +7 -3
- package/dist/chunk-MRYXJTDO.js.map +1 -0
- package/dist/{chunk-35DOPXHZ.js → chunk-PGLOYXDP.js} +193 -190
- package/dist/chunk-PGLOYXDP.js.map +1 -0
- package/dist/{chunk-BUXUWAI4.js → chunk-PPB7VP6R.js} +62 -8
- package/dist/chunk-PPB7VP6R.js.map +1 -0
- package/dist/{chunk-STF6NQ5N.js → chunk-RVJHUY7W.js} +2 -2
- package/dist/chunk-RVJHUY7W.js.map +1 -0
- package/dist/{chunk-LTTEILXY.js → chunk-SFKDHXVE.js} +26 -4
- package/dist/chunk-SFKDHXVE.js.map +1 -0
- package/dist/chunk-STK2AZH2.js +11 -0
- package/dist/chunk-STK2AZH2.js.map +1 -0
- package/dist/chunk-TT4ZOYB6.js +143 -0
- package/dist/chunk-TT4ZOYB6.js.map +1 -0
- package/dist/{chunk-RKQ277P5.js → chunk-UDEUT7AG.js} +125 -80
- package/dist/chunk-UDEUT7AG.js.map +1 -0
- package/dist/{config-Bd6FVlh7.d.ts → config-DOjWyIui.d.ts} +3 -21
- package/dist/csf/preview-api.js +2 -2
- package/dist/frame/index.css +0 -2
- package/dist/frame/index.css.map +1 -1
- package/dist/frame/index.d.ts +14 -8
- package/dist/frame/index.js +114 -79
- package/dist/frame/index.js.map +1 -1
- package/dist/index.d.ts +12 -5
- package/dist/index.js +4 -4
- package/dist/library-CdTj-hFp.d.ts +21 -0
- package/dist/{mountFrame-FdJDb3TB.d.ts → mountFrame-CRPAjg1M.d.ts} +1 -1
- package/dist/shell/index.css +166 -150
- package/dist/shell/index.css.map +1 -1
- package/dist/shell/index.d.ts +24 -5
- package/dist/shell/index.js +594 -402
- package/dist/shell/index.js.map +1 -1
- package/dist/test/index.css +2 -3
- package/dist/test/index.css.map +1 -1
- package/dist/test/index.d.ts +1 -1
- package/dist/test/index.js +8 -10
- package/dist/test/index.js.map +1 -1
- package/dist/vite/index.js +127 -32
- package/dist/vite/index.js.map +1 -1
- package/package.json +11 -9
- package/dist/chunk-35DOPXHZ.js.map +0 -1
- package/dist/chunk-3BAM6M26.js.map +0 -1
- package/dist/chunk-BUXUWAI4.js.map +0 -1
- package/dist/chunk-GH5RE5X5.js +0 -10
- package/dist/chunk-GH5RE5X5.js.map +0 -1
- package/dist/chunk-L5XM5VKB.js +0 -47
- package/dist/chunk-L5XM5VKB.js.map +0 -1
- package/dist/chunk-LTTEILXY.js.map +0 -1
- package/dist/chunk-ORMMZ5PV.js.map +0 -1
- package/dist/chunk-RKQ277P5.js.map +0 -1
- package/dist/chunk-STF6NQ5N.js.map +0 -1
|
@@ -1,28 +1,145 @@
|
|
|
1
|
-
import { isNative, ClockContext } from './chunk-
|
|
1
|
+
import { clockSpecOf, isNative, ClockContext } from './chunk-TT4ZOYB6.js';
|
|
2
2
|
import { isSafeOverride, storyNameFromExport, storyId, PROP_ARG_TYPES_EXPORT } from './chunk-5WS67HMU.js';
|
|
3
|
-
import { portSafePart, appliedLocal, withUnsent, coverOf, ArgsContext } from './chunk-
|
|
4
|
-
import {
|
|
5
|
-
import { createContext,
|
|
6
|
-
import {
|
|
3
|
+
import { portSafePart, appliedLocal, withUnsent, coverOf, ArgsContext } from './chunk-B26DWEYT.js';
|
|
4
|
+
import { DEFAULT_LAYOUT } from './chunk-STK2AZH2.js';
|
|
5
|
+
import { createContext, useState, useRef, useEffect, Component, useLayoutEffect, useContext, createElement } from 'react';
|
|
6
|
+
import { createClock, createClockRegistry } from '@weasel-js/clock';
|
|
7
|
+
import { useClockLoop } from '@weasel-js/clock/react';
|
|
8
|
+
import { useLatest, isPlainObject } from '@weasel-js/core';
|
|
7
9
|
import { jsx } from 'react/jsx-runtime';
|
|
8
10
|
import { f, UnionNode, ObjectNode } from '@weasel-js/labkit/config';
|
|
9
11
|
import { iconFromData } from '@weasel-js/ui/components/Icon';
|
|
10
12
|
|
|
13
|
+
// src/frame/a11yContrast.ts
|
|
14
|
+
var RECHECKED = /* @__PURE__ */ new Set(["bgOverlap", "pseudoContent", "elmPartiallyObscured", "elmPartiallyObscuring"]);
|
|
15
|
+
var undecided = (key) => ({ decided: false, key });
|
|
16
|
+
function pseudoArea(el, which) {
|
|
17
|
+
const style = getComputedStyle(el, which);
|
|
18
|
+
if (style.content === "none" || style.display === "none" || style.visibility === "hidden" || style.position !== "absolute") return 0;
|
|
19
|
+
if (style.backgroundColor === "rgba(0, 0, 0, 0)" && style.backgroundImage === "none") return 0;
|
|
20
|
+
const width = parseFloat(style.width);
|
|
21
|
+
const height = parseFloat(style.height);
|
|
22
|
+
if (!style.width.endsWith("px") || !style.height.endsWith("px")) return width === 0 || height === 0 ? 0 : Infinity;
|
|
23
|
+
return width * height;
|
|
24
|
+
}
|
|
25
|
+
function hasPseudoBackdrop(node, root) {
|
|
26
|
+
const rect = node.getBoundingClientRect();
|
|
27
|
+
const minimum = rect.width * rect.height * 0.25;
|
|
28
|
+
for (let el = node; el; el = el.parentElement) {
|
|
29
|
+
if (pseudoArea(el, "::before") + pseudoArea(el, "::after") > minimum) return true;
|
|
30
|
+
if (el === root) return false;
|
|
31
|
+
}
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
function hasCompositing(node) {
|
|
35
|
+
for (let el = node; el; el = el.parentElement) {
|
|
36
|
+
const style = getComputedStyle(el);
|
|
37
|
+
if (Number(style.opacity) < 1 || style.filter !== "none" || style.mixBlendMode !== "normal") return true;
|
|
38
|
+
if (style.backdropFilter && style.backdropFilter !== "none") return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
var isChrome = (el, root) => !root.contains(el) && !el.contains(root);
|
|
43
|
+
var paints = (style) => style.backgroundImage !== "none" || style.backgroundColor !== "rgba(0, 0, 0, 0)";
|
|
44
|
+
function stacksWithoutChrome(axe, node, root) {
|
|
45
|
+
const stacks = [];
|
|
46
|
+
for (const stack of axe.commons.dom.getTextElementStack(node)) {
|
|
47
|
+
const at = stack.indexOf(node);
|
|
48
|
+
const above = at < 0 ? stack : stack.slice(0, at);
|
|
49
|
+
if (above.some((el) => isChrome(el, root) && paints(getComputedStyle(el)))) return null;
|
|
50
|
+
const kept = [...above.filter((el) => !isChrome(el, root)), ...at < 0 ? [] : stack.slice(at)];
|
|
51
|
+
stacks.push(axe.commons.dom.reduceToElementsBelowFloating(kept, node));
|
|
52
|
+
}
|
|
53
|
+
return stacks;
|
|
54
|
+
}
|
|
55
|
+
function covers(el, style, rects) {
|
|
56
|
+
const box = el.getBoundingClientRect();
|
|
57
|
+
const scrolls = ["scroll", "auto"].includes(style.overflow);
|
|
58
|
+
const right = scrolls ? box.left + el.scrollWidth : box.right;
|
|
59
|
+
const bottom = scrolls ? box.top + el.scrollHeight : box.bottom;
|
|
60
|
+
return rects.every((r) => r.top >= box.top && r.bottom <= bottom && r.left >= box.left && r.right <= right);
|
|
61
|
+
}
|
|
62
|
+
function ownText(node) {
|
|
63
|
+
let text = "";
|
|
64
|
+
for (const child of node.childNodes) if (child.nodeType === Node.TEXT_NODE) text += child.textContent ?? "";
|
|
65
|
+
return text.trim();
|
|
66
|
+
}
|
|
67
|
+
function textRects(node) {
|
|
68
|
+
const range = document.createRange();
|
|
69
|
+
const rects = [];
|
|
70
|
+
for (const child of node.childNodes) {
|
|
71
|
+
if (child.nodeType !== Node.TEXT_NODE || !child.textContent?.trim()) continue;
|
|
72
|
+
range.selectNodeContents(child);
|
|
73
|
+
rects.push(...range.getClientRects());
|
|
74
|
+
}
|
|
75
|
+
return rects;
|
|
76
|
+
}
|
|
77
|
+
function judgeContrast(axe, node, root) {
|
|
78
|
+
const { Color, flattenColors, hasValidContrastRatio } = axe.commons.color;
|
|
79
|
+
const style = getComputedStyle(node);
|
|
80
|
+
if (hasPseudoBackdrop(node, root)) return undecided("pseudoContent");
|
|
81
|
+
if (style.textShadow !== "none") return undecided("complexTextShadows");
|
|
82
|
+
if (hasCompositing(node) || parseFloat(style.getPropertyValue("-webkit-text-stroke-width")) > 0) return undecided("blended");
|
|
83
|
+
const stacks = stacksWithoutChrome(axe, node, root);
|
|
84
|
+
if (!stacks?.length) return undecided("bgOverlap");
|
|
85
|
+
for (const stack of stacks) {
|
|
86
|
+
if (stack[0] !== node) return undecided("bgOverlap");
|
|
87
|
+
if (stack.length !== stacks[0].length || stack.some((el, i) => el !== stacks[0][i])) return undecided("elmPartiallyObscuring");
|
|
88
|
+
}
|
|
89
|
+
const rects = textRects(node);
|
|
90
|
+
const layers = [];
|
|
91
|
+
for (const el of stacks[0]) {
|
|
92
|
+
const elStyle = getComputedStyle(el);
|
|
93
|
+
if (elStyle.backgroundImage !== "none") return undecided(elStyle.backgroundImage.includes("gradient") ? "bgGradient" : "bgImage");
|
|
94
|
+
if (el instanceof HTMLImageElement || el instanceof HTMLCanvasElement || el instanceof SVGElement) return undecided("imgNode");
|
|
95
|
+
const color = new Color().parseString(elStyle.backgroundColor);
|
|
96
|
+
if (color.alpha === 0) continue;
|
|
97
|
+
if (elStyle.display !== "inline" && !covers(el, elStyle, rects)) return undecided("elmPartiallyObscured");
|
|
98
|
+
layers.push(color);
|
|
99
|
+
if (color.alpha === 1) break;
|
|
100
|
+
}
|
|
101
|
+
const white = new Color().parseString("#fff");
|
|
102
|
+
const bg = layers.reduceRight((backdrop, layer) => flattenColors(layer, backdrop), white);
|
|
103
|
+
const fg = new Color().parseString(style.getPropertyValue("-webkit-text-fill-color") || style.color);
|
|
104
|
+
const bold = parseFloat(style.fontWeight) >= 700 || style.fontWeight === "bold";
|
|
105
|
+
const verdict = hasValidContrastRatio(bg, fg, parseFloat(style.fontSize), bold);
|
|
106
|
+
if (Math.floor(verdict.contrastRatio * 100) === 100) return undecided("equalRatio");
|
|
107
|
+
if (!verdict.isValid && ownText(node).length === 1) return undecided("shortTextContent");
|
|
108
|
+
return {
|
|
109
|
+
decided: true,
|
|
110
|
+
isValid: verdict.isValid,
|
|
111
|
+
ratio: verdict.contrastRatio,
|
|
112
|
+
expected: verdict.expectedContrastRatio,
|
|
113
|
+
fg: fg.toHexString(),
|
|
114
|
+
bg: bg.toHexString()
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
11
118
|
// src/frame/a11y.ts
|
|
12
119
|
var IMPACTS = /* @__PURE__ */ new Set(["minor", "moderate", "serious", "critical"]);
|
|
13
|
-
function
|
|
120
|
+
function reasonOf(node) {
|
|
121
|
+
if (node.reason) return node.reason;
|
|
122
|
+
const checks = [...node.any ?? [], ...node.all ?? [], ...node.none ?? []];
|
|
123
|
+
const said = checks.find((c) => c.data?.messageKey) ?? checks.find((c) => c.message);
|
|
124
|
+
if (!said) return void 0;
|
|
125
|
+
const key = said.data?.messageKey;
|
|
126
|
+
return { ...key ? { key } : {}, ...said.message ? { message: said.message } : {} };
|
|
127
|
+
}
|
|
128
|
+
function finding(from, withReasons = false) {
|
|
14
129
|
const impact = from.impact ?? "";
|
|
130
|
+
const reasons = withReasons ? from.nodes.map(reasonOf) : [];
|
|
15
131
|
return {
|
|
16
132
|
id: from.id,
|
|
17
133
|
impact: IMPACTS.has(impact) ? impact : null,
|
|
18
134
|
help: from.help,
|
|
19
135
|
helpUrl: from.helpUrl,
|
|
20
136
|
description: from.description,
|
|
21
|
-
nodes: from.nodes.map((node) => ({
|
|
137
|
+
nodes: from.nodes.map((node, i) => ({
|
|
22
138
|
// An axe target entry is a selector, or an array of them for an element inside a shadow root.
|
|
23
139
|
target: node.target.map((part) => Array.isArray(part) ? part.join(" ") : String(part)),
|
|
24
140
|
html: node.html,
|
|
25
|
-
...node.failureSummary === void 0 ? {} : { failureSummary: node.failureSummary }
|
|
141
|
+
...node.failureSummary === void 0 ? {} : { failureSummary: node.failureSummary },
|
|
142
|
+
...reasons[i] ? { reason: reasons[i] } : {}
|
|
26
143
|
}))
|
|
27
144
|
};
|
|
28
145
|
}
|
|
@@ -45,17 +162,49 @@ var last = Promise.resolve();
|
|
|
45
162
|
async function runAxe(element, { page = true } = {}) {
|
|
46
163
|
const axe = await loadAxe();
|
|
47
164
|
const rules = page ? void 0 : Object.fromEntries(PAGE_RULES.map((id) => [id, { enabled: false }]));
|
|
48
|
-
const run = () => axe.run(element, rules ? { rules } :
|
|
165
|
+
const run = async () => recheckContrast(axe, element, await axe.run(element, { elementRef: true, ...rules ? { rules } : {} }));
|
|
49
166
|
const running = last.then(run, run);
|
|
50
167
|
last = running;
|
|
51
168
|
const result = await running;
|
|
52
169
|
return {
|
|
53
|
-
violations: result.violations.map(finding),
|
|
54
|
-
incomplete: result.incomplete.map(finding),
|
|
170
|
+
violations: result.violations.map((f3) => finding(f3)),
|
|
171
|
+
incomplete: result.incomplete.map((f3) => finding(f3, true)),
|
|
55
172
|
passes: result.passes.length,
|
|
56
173
|
inapplicable: result.inapplicable.length
|
|
57
174
|
};
|
|
58
175
|
}
|
|
176
|
+
function recheckContrast(axe, root, result) {
|
|
177
|
+
const review = result.incomplete.find((f3) => f3.id === "color-contrast");
|
|
178
|
+
const rechecked = (n) => n.element !== void 0 && RECHECKED.has(reasonOf(n)?.key ?? "");
|
|
179
|
+
if (!review?.nodes.some(rechecked)) return result;
|
|
180
|
+
const kept = [];
|
|
181
|
+
const failed = [];
|
|
182
|
+
let passed = false;
|
|
183
|
+
axe.setup(document);
|
|
184
|
+
try {
|
|
185
|
+
for (const node of review.nodes) {
|
|
186
|
+
const verdict = rechecked(node) ? judgeContrast(axe, node.element, root) : null;
|
|
187
|
+
if (!verdict) kept.push(node);
|
|
188
|
+
else if (!verdict.decided) kept.push({ ...node, failureSummary: void 0, reason: { key: verdict.key } });
|
|
189
|
+
else if (verdict.isValid) passed = true;
|
|
190
|
+
else {
|
|
191
|
+
const summary = `Contrast is ${verdict.ratio.toFixed(2)}:1 (foreground ${verdict.fg}, background ${verdict.bg}); ${verdict.expected}:1 is needed.`;
|
|
192
|
+
failed.push({ ...node, failureSummary: summary });
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
} finally {
|
|
196
|
+
axe.teardown();
|
|
197
|
+
}
|
|
198
|
+
const others = (list) => list.filter((f3) => f3.id !== "color-contrast");
|
|
199
|
+
const failing = result.violations.find((f3) => f3.id === "color-contrast");
|
|
200
|
+
const violations = failed.length === 0 ? result.violations : [
|
|
201
|
+
...others(result.violations),
|
|
202
|
+
{ ...review, impact: "serious", ...failing, nodes: [...failing?.nodes ?? [], ...failed] }
|
|
203
|
+
];
|
|
204
|
+
const incomplete = kept.length === 0 ? others(result.incomplete) : result.incomplete.map((f3) => f3 === review ? { ...f3, nodes: kept } : f3);
|
|
205
|
+
const passes = passed && !result.passes.some((p) => p.id === "color-contrast") ? [...result.passes, { id: "color-contrast" }] : result.passes;
|
|
206
|
+
return { ...result, violations, incomplete, passes };
|
|
207
|
+
}
|
|
59
208
|
async function auditElement(element, options) {
|
|
60
209
|
try {
|
|
61
210
|
return { ok: true, report: await runAxe(element, options) };
|
|
@@ -332,138 +481,32 @@ function createGlobalsTarget(root, scope) {
|
|
|
332
481
|
}
|
|
333
482
|
};
|
|
334
483
|
}
|
|
335
|
-
var
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
if (!clock) return;
|
|
344
|
-
const prev = last2.current;
|
|
345
|
-
last2.current = now;
|
|
346
|
-
if (prev !== null) clock.tick(now - prev);
|
|
347
|
-
if (clock.get().playing) raf2.request();
|
|
348
|
-
},
|
|
349
|
-
{
|
|
350
|
-
...target ? { target } : {},
|
|
351
|
-
onResume: () => {
|
|
352
|
-
last2.current = null;
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
);
|
|
356
|
-
useEffect(() => {
|
|
357
|
-
if (!playing) return;
|
|
358
|
-
last2.current = null;
|
|
359
|
-
raf.request();
|
|
360
|
-
return () => raf.cancel();
|
|
361
|
-
}, [playing, raf]);
|
|
362
|
-
}
|
|
363
|
-
function spanOf(spec) {
|
|
364
|
-
const start = Number.isFinite(spec.start) ? spec.start : 0;
|
|
365
|
-
const duration = Number.isFinite(spec.duration) && spec.duration > 0 ? spec.duration : 0;
|
|
366
|
-
return { start, end: start + duration };
|
|
367
|
-
}
|
|
368
|
-
function clampTime(span, t) {
|
|
369
|
-
if (Number.isNaN(t)) return span.start;
|
|
370
|
-
return Math.min(span.end, Math.max(span.start, t));
|
|
371
|
-
}
|
|
372
|
-
function advance(state, elapsed) {
|
|
373
|
-
if (!state.playing) return state;
|
|
374
|
-
const { start, end } = state.span;
|
|
375
|
-
const length = end - start;
|
|
376
|
-
if (length <= 0) return { ...state, time: start, playing: false };
|
|
377
|
-
const next = state.time + elapsed * state.rate;
|
|
378
|
-
if (next <= end) return { ...state, time: next };
|
|
379
|
-
if (!state.loop) return { ...state, time: end, playing: false };
|
|
380
|
-
return { ...state, time: start + (next - start) % length };
|
|
381
|
-
}
|
|
382
|
-
var validRate = (rate) => typeof rate === "number" && Number.isFinite(rate) && rate > 0;
|
|
383
|
-
var placed = (span, requested) => requested === null ? span.start : clampTime(span, requested);
|
|
384
|
-
function createClock(spec, initial) {
|
|
385
|
-
let declared = spanOf(spec);
|
|
386
|
-
let override = null;
|
|
387
|
-
let requested = { time: initial ?? null };
|
|
388
|
-
let state = {
|
|
389
|
-
time: placed(declared, requested.time),
|
|
390
|
-
playing: false,
|
|
391
|
-
loop: spec.loop ?? true,
|
|
392
|
-
rate: validRate(spec.rate) ? spec.rate : 1,
|
|
393
|
-
span: declared
|
|
394
|
-
};
|
|
395
|
-
const changed = createEmitter();
|
|
396
|
-
const pendingIn = (at) => requested && requested.time !== null && requested.time !== at.time ? requested.time : null;
|
|
397
|
-
let pending = pendingIn(state);
|
|
398
|
-
const set = (next) => {
|
|
399
|
-
const nextPending = pendingIn(next);
|
|
400
|
-
if (nextPending === pending && next.time === state.time && next.playing === state.playing && next.loop === state.loop && next.rate === state.rate && next.span.start === state.span.start && next.span.end === state.span.end)
|
|
401
|
-
return;
|
|
402
|
-
state = next;
|
|
403
|
-
pending = nextPending;
|
|
404
|
-
changed.emit();
|
|
405
|
-
};
|
|
406
|
-
const moved = (next) => {
|
|
407
|
-
requested = null;
|
|
408
|
-
set(next);
|
|
409
|
-
};
|
|
410
|
-
const respan = () => {
|
|
411
|
-
const span = override ?? declared;
|
|
412
|
-
set({ ...state, span, time: requested ? placed(span, requested.time) : clampTime(span, state.time) });
|
|
413
|
-
};
|
|
414
|
-
return {
|
|
415
|
-
get: () => state,
|
|
416
|
-
subscribe: changed.subscribe,
|
|
417
|
-
play() {
|
|
418
|
-
if (state.playing) return;
|
|
419
|
-
moved({ ...state, playing: true, time: state.time >= state.span.end ? state.span.start : state.time });
|
|
420
|
-
},
|
|
421
|
-
pause: () => set({ ...state, playing: false }),
|
|
422
|
-
seek: (time) => moved({ ...state, time: clampTime(state.span, time) }),
|
|
423
|
-
request(time) {
|
|
424
|
-
requested = { time: Number.isNaN(time) ? null : time };
|
|
425
|
-
set({ ...state, playing: false, time: placed(state.span, requested.time) });
|
|
426
|
-
},
|
|
427
|
-
pending: () => pending,
|
|
428
|
-
setLoop: (loop) => set({ ...state, loop }),
|
|
429
|
-
setRate(rate) {
|
|
430
|
-
if (validRate(rate)) set({ ...state, rate });
|
|
431
|
-
},
|
|
432
|
-
setSpan(span) {
|
|
433
|
-
override = span ? spanOf(span) : null;
|
|
434
|
-
respan();
|
|
435
|
-
},
|
|
436
|
-
declare(next) {
|
|
437
|
-
declared = spanOf(next);
|
|
438
|
-
respan();
|
|
439
|
-
},
|
|
440
|
-
tick(elapsed) {
|
|
441
|
-
if (state.playing) moved(advance(state, elapsed));
|
|
442
|
-
}
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
function useStoryClock(spec, initial) {
|
|
446
|
-
const [clock, setClock] = useState(() => spec ? createClock(spec, initial()) : null);
|
|
447
|
-
let current = clock;
|
|
448
|
-
if (spec && !clock) {
|
|
449
|
-
current = createClock(spec, initial());
|
|
450
|
-
setClock(current);
|
|
451
|
-
} else if (!spec && clock) {
|
|
484
|
+
var keyOf = (spec) => spec ? `${spec.start ?? 0}|${spec.duration}|${spec.loop ?? true}|${spec.rate ?? 1}` : null;
|
|
485
|
+
function useOwnClock(spec) {
|
|
486
|
+
const [handle, setHandle] = useState(() => spec ? createClock(clockSpecOf(spec)) : null);
|
|
487
|
+
let current = handle;
|
|
488
|
+
if (spec && !handle) {
|
|
489
|
+
current = createClock(clockSpecOf(spec));
|
|
490
|
+
setHandle(current);
|
|
491
|
+
} else if (!spec && handle) {
|
|
452
492
|
current = null;
|
|
453
|
-
|
|
493
|
+
setHandle(null);
|
|
454
494
|
}
|
|
455
495
|
const latest = useLatest(spec);
|
|
456
|
-
const
|
|
496
|
+
const key = keyOf(spec);
|
|
497
|
+
const declared = useRef(key);
|
|
457
498
|
useEffect(() => {
|
|
458
|
-
if (current
|
|
459
|
-
|
|
499
|
+
if (!current || !latest.current || key === declared.current) return;
|
|
500
|
+
declared.current = key;
|
|
501
|
+
current.declare(clockSpecOf(latest.current));
|
|
502
|
+
}, [current, key, latest]);
|
|
460
503
|
return current;
|
|
461
504
|
}
|
|
462
|
-
var NO_INITIAL = () => null;
|
|
463
505
|
function OwnClock({ spec, children }) {
|
|
464
|
-
const
|
|
465
|
-
|
|
466
|
-
|
|
506
|
+
const handle = useOwnClock(spec);
|
|
507
|
+
const [registry] = useState(() => createClockRegistry(handle));
|
|
508
|
+
useClockLoop(registry);
|
|
509
|
+
return /* @__PURE__ */ jsx(ClockContext.Provider, { value: handle, children });
|
|
467
510
|
}
|
|
468
511
|
function WithStoryClock({ story, config, children }) {
|
|
469
512
|
const outer = useContext(ClockContext);
|
|
@@ -811,7 +854,7 @@ function loadCsfModule(mod, title, projectParameters = {}) {
|
|
|
811
854
|
return scoped(ctx, (context) => renderFn(context.args, context));
|
|
812
855
|
},
|
|
813
856
|
decorators: [...asArray(spec.decorators), ...asArray(meta.decorators)].map(adapt),
|
|
814
|
-
layout: layout && LAYOUTS.includes(layout) ? layout :
|
|
857
|
+
layout: layout && LAYOUTS.includes(layout) ? layout : DEFAULT_LAYOUT,
|
|
815
858
|
viewport: resolveViewport(parameters, storyGlobals),
|
|
816
859
|
isolate: typeof isolate === "string" ? isolate : null,
|
|
817
860
|
play: play ? ({ canvasElement, config: config2, globals }) => play({ ...csfContext(config2, globals), canvasElement, step: async (_label, fn) => fn() }) : null,
|
|
@@ -835,7 +878,7 @@ function loadNativeModule(mod, title) {
|
|
|
835
878
|
initialState: spec.state ?? null,
|
|
836
879
|
render: spec.render,
|
|
837
880
|
decorators: [...spec.decorators ?? [], ...metaSpec.decorators ?? []],
|
|
838
|
-
layout: spec.layout ?? metaSpec.layout ??
|
|
881
|
+
layout: spec.layout ?? metaSpec.layout ?? DEFAULT_LAYOUT,
|
|
839
882
|
viewport: spec.viewport ?? null,
|
|
840
883
|
isolate: spec.isolate ?? metaSpec.isolate ?? null,
|
|
841
884
|
play: spec.play ?? null,
|
|
@@ -854,50 +897,12 @@ function indexRenderOf(mod) {
|
|
|
854
897
|
const render = isNative(meta, "meta") ? meta?.index : meta?.parameters?.forge?.index;
|
|
855
898
|
return typeof render === "function" ? render : null;
|
|
856
899
|
}
|
|
857
|
-
var IN_VIEW_MARGIN = "50%";
|
|
858
|
-
function useNearViewport(ref, margin, initial = true) {
|
|
859
|
-
const [near, setNear] = useState(() => initial || typeof IntersectionObserver === "undefined");
|
|
860
|
-
useEffect(() => {
|
|
861
|
-
const el = ref.current;
|
|
862
|
-
if (!el || typeof IntersectionObserver === "undefined") return;
|
|
863
|
-
const recheck = () => {
|
|
864
|
-
observer.unobserve(el);
|
|
865
|
-
observer.observe(el);
|
|
866
|
-
};
|
|
867
|
-
let watching = false;
|
|
868
|
-
const watch = (on) => {
|
|
869
|
-
if (on === watching) return;
|
|
870
|
-
watching = on;
|
|
871
|
-
if (on) {
|
|
872
|
-
document.addEventListener("scroll", recheck, { capture: true, passive: true });
|
|
873
|
-
window.addEventListener("resize", recheck);
|
|
874
|
-
} else {
|
|
875
|
-
document.removeEventListener("scroll", recheck, { capture: true });
|
|
876
|
-
window.removeEventListener("resize", recheck);
|
|
877
|
-
}
|
|
878
|
-
};
|
|
879
|
-
const observer = new IntersectionObserver(
|
|
880
|
-
(entries) => {
|
|
881
|
-
const last2 = entries.at(-1);
|
|
882
|
-
if (!last2) return;
|
|
883
|
-
const root = last2.rootBounds;
|
|
884
|
-
const box = last2.boundingClientRect;
|
|
885
|
-
setNear(
|
|
886
|
-
root ? box.bottom >= root.top && box.top <= root.bottom && box.right >= root.left && box.left <= root.right : last2.isIntersecting
|
|
887
|
-
);
|
|
888
|
-
watch(Boolean(root) && !last2.isIntersecting);
|
|
889
|
-
},
|
|
890
|
-
{ root: document, rootMargin: margin }
|
|
891
|
-
);
|
|
892
|
-
observer.observe(el);
|
|
893
|
-
return () => {
|
|
894
|
-
observer.disconnect();
|
|
895
|
-
watch(false);
|
|
896
|
-
};
|
|
897
|
-
}, [ref, margin]);
|
|
898
|
-
return near;
|
|
899
|
-
}
|
|
900
900
|
var scopeOf = (id) => `[data-fg-host="${id}"]`;
|
|
901
|
+
function applyGlobalsTo(host, hostId, globals, setup) {
|
|
902
|
+
const target = createGlobalsTarget(host, scopeOf(hostId));
|
|
903
|
+
setup.applyGlobals?.(globals, target);
|
|
904
|
+
return () => target.dispose();
|
|
905
|
+
}
|
|
901
906
|
function useHostConditions(host, opts) {
|
|
902
907
|
const { hostId, globals, overrides: persisted, setup } = opts;
|
|
903
908
|
const latest = useLatest({ setup });
|
|
@@ -923,15 +928,13 @@ function useHostConditions(host, opts) {
|
|
|
923
928
|
for (const [name, value] of Object.entries(persisted)) overrides.set(name, value);
|
|
924
929
|
applied.current = { ...persisted };
|
|
925
930
|
}, [host, hostId, persisted]);
|
|
926
|
-
useLayoutEffect(
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
return () => target.dispose();
|
|
931
|
-
}, [host, hostId, globals, latest]);
|
|
931
|
+
useLayoutEffect(
|
|
932
|
+
() => host ? applyGlobalsTo(host, hostId, globals, latest.current.setup) : void 0,
|
|
933
|
+
[host, hostId, globals, latest]
|
|
934
|
+
);
|
|
932
935
|
return overridesRef;
|
|
933
936
|
}
|
|
934
937
|
|
|
935
|
-
export {
|
|
936
|
-
//# sourceMappingURL=chunk-
|
|
937
|
-
//# sourceMappingURL=chunk-
|
|
938
|
+
export { StoryHost, applyGlobalsTo, auditElement, createA11yHighlighter, createGlobalsTarget, createOverrides, cssRulesOf, indexRenderOf, loadStories, resolveCssVar, runAxe, scanCssVars, useHostConditions, useOwnClock, varRefs };
|
|
939
|
+
//# sourceMappingURL=chunk-PGLOYXDP.js.map
|
|
940
|
+
//# sourceMappingURL=chunk-PGLOYXDP.js.map
|