procedural-paper 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +205 -2
- package/THIRD_PARTY_NOTICES.md +51 -0
- package/dist/cards.d.ts +42 -0
- package/dist/color.d.ts +5 -0
- package/dist/composition/assets.d.ts +7 -0
- package/dist/composition/cords.d.ts +43 -0
- package/dist/composition/filters.d.ts +1 -0
- package/dist/composition/fit.d.ts +58 -0
- package/dist/composition/index.d.ts +27 -0
- package/dist/composition/index.js +1247 -0
- package/dist/composition/index.js.map +1 -0
- package/dist/composition/model.d.ts +72 -0
- package/dist/composition/motion-spec.d.ts +98 -0
- package/dist/composition/motion.d.ts +36 -0
- package/dist/composition/motion.js +291 -0
- package/dist/composition/motion.js.map +1 -0
- package/dist/composition/nodes.d.ts +7 -0
- package/dist/composition/pen.d.ts +6 -0
- package/dist/composition/photos.d.ts +41 -0
- package/dist/composition/props.d.ts +32 -0
- package/dist/composition/react.d.ts +10 -0
- package/dist/composition/react.js +22 -0
- package/dist/composition/react.js.map +1 -0
- package/dist/composition/renderer.d.ts +77 -0
- package/dist/composition/rng.d.ts +11 -0
- package/dist/composition/scene.d.ts +77 -0
- package/dist/composition/unrotate.d.ts +3 -0
- package/dist/composition.css +78 -0
- package/dist/cpu/compose.d.ts +7 -0
- package/dist/cpu/field.d.ts +10 -0
- package/dist/cpu/noise.d.ts +7 -0
- package/dist/cpu/overlays.d.ts +12 -0
- package/dist/cpu/renderer.d.ts +16 -0
- package/dist/cpu/strands.d.ts +33 -0
- package/dist/dom.d.ts +110 -0
- package/dist/dom.js +65 -0
- package/dist/dom.js.map +1 -0
- package/dist/export.d.ts +20 -0
- package/dist/gl/renderer.d.ts +61 -0
- package/dist/gl/shaders.d.ts +10 -0
- package/dist/gl/sheet-shader.d.ts +1 -0
- package/dist/hash.d.ts +12 -0
- package/dist/index.d.ts +73 -0
- package/dist/index.js +2415 -0
- package/dist/index.js.map +1 -0
- package/dist/params.d.ts +169 -0
- package/dist/presets.d.ts +11 -0
- package/dist/react.d.ts +20 -0
- package/dist/react.js +50 -0
- package/dist/react.js.map +1 -0
- package/dist/resolve.d.ts +125 -0
- package/dist/sheet.d.ts +167 -0
- package/dist/stocks.d.ts +12 -0
- package/dist/styles.css +13 -0
- package/licenses/Apache-2.0.txt +201 -0
- package/package.json +116 -4
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
import { builtinEngine as T, flushReveals as F, annotate as A } from "brushmark";
|
|
2
|
+
const S = /* @__PURE__ */ new WeakMap(), k = /* @__PURE__ */ new WeakMap(), D = (s) => k.get(s) ?? s.style.transform;
|
|
3
|
+
function $(s, t, o = []) {
|
|
4
|
+
if ((S.get(s) ?? 0) > 0) return t();
|
|
5
|
+
S.set(s, 1);
|
|
6
|
+
const a = /* @__PURE__ */ new Set([s]);
|
|
7
|
+
for (const e of o)
|
|
8
|
+
for (let l = e; l && l !== s; l = l.parentElement)
|
|
9
|
+
(l.style.transform || l.style.rotate || l.style.scale) && a.add(l);
|
|
10
|
+
const n = [...a].map((e) => ({ el: e, transition: e.style.transition, transform: e.style.transform, rotate: e.style.rotate, scale: e.style.scale }));
|
|
11
|
+
for (const e of n)
|
|
12
|
+
k.set(e.el, e.transform), e.el.style.transition = "none", e.el.style.transform = "none", e.rotate && (e.el.style.rotate = "none"), e.scale && (e.el.style.scale = "none");
|
|
13
|
+
s.style.setProperty("scale", "1", "important");
|
|
14
|
+
try {
|
|
15
|
+
return t();
|
|
16
|
+
} finally {
|
|
17
|
+
for (const e of n)
|
|
18
|
+
e.el.style.transform = e.transform, e.rotate && (e.el.style.rotate = e.rotate), e.scale && (e.el.style.scale = e.scale);
|
|
19
|
+
s.style.removeProperty("scale"), s.offsetWidth;
|
|
20
|
+
for (const e of n)
|
|
21
|
+
e.el.style.transition = e.transition, k.delete(e.el);
|
|
22
|
+
S.set(s, 0);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
const N = { "‘": "'", "’": "'", "…": "..." }, C = (s, t) => s.replace(/[‘’…]/g, (o) => o in t.glyphData ? o : N[o]), _ = () => matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
26
|
+
class I {
|
|
27
|
+
constructor(t) {
|
|
28
|
+
this.el = t, this.base = D(t), this.saved = { transform: this.base, opacity: t.style.opacity, clipPath: t.style.clipPath }, this.o0 = parseFloat(getComputedStyle(t).opacity) || 1, t.dataset.mv = "";
|
|
29
|
+
}
|
|
30
|
+
x = 0;
|
|
31
|
+
y = 0;
|
|
32
|
+
s = 1;
|
|
33
|
+
o = 1;
|
|
34
|
+
/** Percent hidden from the right / bottom (clip sweeps). */
|
|
35
|
+
cx = 0;
|
|
36
|
+
cy = 0;
|
|
37
|
+
base;
|
|
38
|
+
o0;
|
|
39
|
+
saved;
|
|
40
|
+
flush() {
|
|
41
|
+
const t = this.el.style, o = this.x || this.y || this.s !== 1;
|
|
42
|
+
t.transform = o ? `${this.base} translate(${this.x.toFixed(2)}px, ${this.y.toFixed(2)}px) scale(${this.s.toFixed(4)})`.trim() : this.base, t.opacity = this.o >= 1 ? this.saved.opacity : `${(this.o0 * this.o).toFixed(3)}`, t.clipPath = this.cx > 0 ? `inset(0 ${this.cx.toFixed(2)}% 0 0)` : this.cy > 0 ? `inset(0 0 ${this.cy.toFixed(2)}% 0)` : this.saved.clipPath;
|
|
43
|
+
}
|
|
44
|
+
restore() {
|
|
45
|
+
Object.assign(this.el.style, this.saved), delete this.el.dataset.mv;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const E = (s, t, o) => s.duration ?? (t.duration || o), R = {
|
|
49
|
+
prepare(s, t, o) {
|
|
50
|
+
const { kind: a, target: n, at: e, priority: l, ...d } = t, h = s.map(
|
|
51
|
+
(r) => A(r, {
|
|
52
|
+
...d,
|
|
53
|
+
duration: t.duration ?? (o.duration || d.duration),
|
|
54
|
+
observe: !1,
|
|
55
|
+
measure: (p) => $(o.card, p, [r]),
|
|
56
|
+
seed: d.seed ?? o.rng.int(1, 1e9)
|
|
57
|
+
})
|
|
58
|
+
);
|
|
59
|
+
for (const r of h) r.prepare();
|
|
60
|
+
return {
|
|
61
|
+
build(r) {
|
|
62
|
+
h.forEach((p, i) => r.add(p.timeline, i === 0 ? 0 : ">-0.1"));
|
|
63
|
+
},
|
|
64
|
+
dispose: () => h.forEach((r) => r.remove())
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}, q = {
|
|
68
|
+
prepare(s, t, o) {
|
|
69
|
+
const a = s.flatMap((r) => r instanceof SVGPathElement ? [r] : [...r.querySelectorAll("path")]);
|
|
70
|
+
if (!a.length) return null;
|
|
71
|
+
const n = a.map((r) => {
|
|
72
|
+
const p = r.getTotalLength(), i = { dasharray: r.style.strokeDasharray, dashoffset: r.style.strokeDashoffset, opacity: r.style.opacity };
|
|
73
|
+
r.style.strokeDasharray = `${p}`;
|
|
74
|
+
const c = {
|
|
75
|
+
t: 0,
|
|
76
|
+
flush() {
|
|
77
|
+
r.style.strokeDashoffset = `${(p * (1 - c.t)).toFixed(2)}`, r.style.opacity = c.t > 0 ? i.opacity : "0";
|
|
78
|
+
},
|
|
79
|
+
restore: () => Object.assign(r.style, { strokeDasharray: i.dasharray, strokeDashoffset: i.dashoffset, opacity: i.opacity })
|
|
80
|
+
};
|
|
81
|
+
return c.flush(), c;
|
|
82
|
+
}), e = E(t, o, 1.2), l = t.stagger ?? 0, d = a.map((r) => r.getTotalLength()), h = d.reduce((r, p) => r + p, 0) || 1;
|
|
83
|
+
return {
|
|
84
|
+
build(r) {
|
|
85
|
+
let p = 0;
|
|
86
|
+
n.forEach((i, c) => {
|
|
87
|
+
const f = Math.max(0.05, e * d[c] / h);
|
|
88
|
+
r.to(i, { t: 1, duration: f, ease: t.ease ?? "power1.inOut", onUpdate: () => o.mark(i) }, p), p += f + l;
|
|
89
|
+
});
|
|
90
|
+
},
|
|
91
|
+
dispose: () => n.forEach((r) => r.restore())
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}, H = /* @__PURE__ */ new Set(["SPAN", "B", "I", "EM", "STRONG", "S", "U", "SMALL", "SUB", "SUP", "BR"]);
|
|
95
|
+
function P(s) {
|
|
96
|
+
const t = [...s.children];
|
|
97
|
+
return t.every((o) => H.has(o.tagName) && !o.querySelector(":not(span,b,i,em,strong,s,u,small,sub,sup,br)")) ? s.textContent?.trim() ? [s] : [] : t.flatMap(P);
|
|
98
|
+
}
|
|
99
|
+
const O = 1.6, W = 8;
|
|
100
|
+
function B(s, t, o) {
|
|
101
|
+
const a = o.pen?.Engine, n = P(s), e = n.map((i) => o.pen?.bundleFor(getComputedStyle(i).fontFamily));
|
|
102
|
+
if (!a || !n.length || e.some((i) => !i)) return null;
|
|
103
|
+
const l = n.map((i, c) => {
|
|
104
|
+
const f = C(i.innerText.trim(), e[c]), b = i.innerHTML;
|
|
105
|
+
i.textContent = "";
|
|
106
|
+
const m = document.createElement("span");
|
|
107
|
+
m.className = "pen", i.appendChild(m);
|
|
108
|
+
const y = new a(m, { font: e[c], text: f, time: { mode: "controlled", value: 0 }, seed: o.rng.int(0, 1e6) });
|
|
109
|
+
return { leaf: i, html: b, engine: y, len: y.duration || f.length * 0.12, t: -1 };
|
|
110
|
+
}), d = l.reduce((i, c) => i + c.len, 0), h = Math.min(W, Math.max(d / O, t.duration ?? 0)), r = d / h, p = {
|
|
111
|
+
t: 0,
|
|
112
|
+
flush() {
|
|
113
|
+
let i = p.t * r;
|
|
114
|
+
for (const c of l) {
|
|
115
|
+
const f = Math.min(c.len, Math.max(0, i));
|
|
116
|
+
f !== c.t && c.engine.update({ time: { mode: "controlled", value: c.t = f } }), i -= c.len;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
return p.flush(), {
|
|
121
|
+
build: (i) => i.to(p, { t: h, duration: h, ease: "none", onUpdate: () => o.mark(p) }, 0),
|
|
122
|
+
dispose: () => l.forEach((i) => {
|
|
123
|
+
i.engine.destroy(), i.leaf.innerHTML = i.html;
|
|
124
|
+
})
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
const G = {
|
|
128
|
+
prepare(s, t, o) {
|
|
129
|
+
const a = [];
|
|
130
|
+
for (const n of s) {
|
|
131
|
+
const e = [...n.querySelectorAll(".w > span")];
|
|
132
|
+
let l = t.mode ?? "auto";
|
|
133
|
+
if ((l === "auto" || l === "pen") && !e.length && o.pen) {
|
|
134
|
+
const d = B(n, t, o);
|
|
135
|
+
if (d) {
|
|
136
|
+
a.push(d);
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
if (l === "pen" && (l = "auto"), l === "auto" && (l = e.length ? "glyph" : n.offsetHeight > 1.6 * parseFloat(getComputedStyle(n).fontSize) ? "sweep-y" : "sweep-x"), l === "glyph") {
|
|
141
|
+
if (!e.length) continue;
|
|
142
|
+
const d = e.map((c) => c.style.opacity);
|
|
143
|
+
for (const c of e) c.style.opacity = "0";
|
|
144
|
+
let h = 0;
|
|
145
|
+
const r = {
|
|
146
|
+
n: 0,
|
|
147
|
+
flush() {
|
|
148
|
+
const c = Math.min(e.length, Math.max(0, Math.floor(r.n)));
|
|
149
|
+
for (let f = h; f < c; f++) e[f].style.opacity = d[f];
|
|
150
|
+
for (let f = c; f < h; f++) e[f].style.opacity = "0";
|
|
151
|
+
h = c;
|
|
152
|
+
}
|
|
153
|
+
}, p = t.rate ?? 28, i = t.duration ?? e.length / p;
|
|
154
|
+
a.push({
|
|
155
|
+
build: (c) => c.to(r, { n: e.length, duration: i, ease: "none", onUpdate: () => o.mark(r) }, 0),
|
|
156
|
+
dispose: () => e.forEach((c, f) => c.style.opacity = d[f])
|
|
157
|
+
});
|
|
158
|
+
} else {
|
|
159
|
+
const d = o.pose(n), h = l === "sweep-x" ? "cx" : "cy";
|
|
160
|
+
d[h] = 100, d.flush(), a.push({
|
|
161
|
+
build: (r) => r.to(d, { [h]: 0, duration: E(t, o, 1), ease: t.ease ?? "none", onUpdate: () => o.mark(d) }, 0),
|
|
162
|
+
dispose: () => d.restore()
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return a.length ? { build: (n) => a.forEach((e) => e.build(n)), dispose: () => a.forEach((n) => n.dispose()) } : null;
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
function w(s, t) {
|
|
170
|
+
return {
|
|
171
|
+
prepare(o, a, n) {
|
|
172
|
+
const e = o.map((l) => {
|
|
173
|
+
const d = n.pose(l);
|
|
174
|
+
return s(d, a), d.flush(), d;
|
|
175
|
+
});
|
|
176
|
+
return {
|
|
177
|
+
build: (l) => e.forEach((d) => t(l, d, a, E(a, n, 0.4), () => n.mark(d))),
|
|
178
|
+
dispose: () => e.forEach((l) => l.restore())
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
const j = w(
|
|
184
|
+
(s, t) => s.o = t.from ?? 0,
|
|
185
|
+
(s, t, o, a, n) => s.to(t, { o: 1, duration: a, ease: o.ease ?? "power1.out", onUpdate: n }, 0)
|
|
186
|
+
), z = w(
|
|
187
|
+
(s, t) => (s.o = 0, s.y = t.dy ?? 6),
|
|
188
|
+
(s, t, o, a, n) => s.to(t, { o: 1, y: 0, duration: a, ease: o.ease ?? "power2.out", onUpdate: n }, 0)
|
|
189
|
+
), K = w(
|
|
190
|
+
(s, t) => (s.o = 0, s.s = t.from ?? 1.6),
|
|
191
|
+
(s, t, o, a, n) => {
|
|
192
|
+
s.to(t, { s: 1, duration: a, ease: o.ease ?? "back.out", onUpdate: n }, 0), s.to(t, { o: 1, duration: a * 0.4, ease: "power2.out", onUpdate: n }, 0);
|
|
193
|
+
}
|
|
194
|
+
), V = {
|
|
195
|
+
prepare(s, t, o) {
|
|
196
|
+
const a = s.map((n) => {
|
|
197
|
+
const e = { v: 1, flush: () => void (n.style.opacity = e.v.toFixed(3)) };
|
|
198
|
+
return e.flush(), e;
|
|
199
|
+
});
|
|
200
|
+
return {
|
|
201
|
+
build: (n) => a.forEach((e) => n.to(e, { v: 0, duration: E(t, o, 2.6), ease: t.ease ?? "power1.in", onUpdate: () => o.mark(e) }, 0)),
|
|
202
|
+
dispose: () => s.forEach((n) => n.style.opacity = "")
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
}, X = { brush: R, draw: q, write: G, fade: j, rise: z, stamp: K, develop: V };
|
|
206
|
+
function J(s, t) {
|
|
207
|
+
if (!t) return s;
|
|
208
|
+
if (typeof s == "number") return s + t;
|
|
209
|
+
const o = /^>([+-]?\d*\.?\d+)?$/.exec(s);
|
|
210
|
+
if (o) return `>${(parseFloat(o[1] ?? "0") + t).toFixed(3)}`;
|
|
211
|
+
const a = /^([+-])=(\d*\.?\d+)$/.exec(s);
|
|
212
|
+
if (a) {
|
|
213
|
+
const n = (a[1] === "-" ? -1 : 1) * parseFloat(a[2]) + t;
|
|
214
|
+
return `${n < 0 ? "-" : "+"}=${Math.abs(n).toFixed(3)}`;
|
|
215
|
+
}
|
|
216
|
+
return s;
|
|
217
|
+
}
|
|
218
|
+
function Q(s, t) {
|
|
219
|
+
return typeof t.target == "string" ? [...s.querySelectorAll(t.target)] : s.contains(t.target) ? [t.target] : [];
|
|
220
|
+
}
|
|
221
|
+
function Z(s, t, o, a) {
|
|
222
|
+
const n = s.motion, e = s.ink;
|
|
223
|
+
if (!n?.steps.length || !e) return null;
|
|
224
|
+
const l = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Map(), h = () => {
|
|
225
|
+
for (const u of l) u.flush();
|
|
226
|
+
l.clear();
|
|
227
|
+
}, r = t.el, p = T.createTimeline({ paused: !0, onUpdate: h, onComplete: () => r.classList.remove("motion") }), i = {
|
|
228
|
+
card: r,
|
|
229
|
+
pen: a,
|
|
230
|
+
ink: e,
|
|
231
|
+
rng: o,
|
|
232
|
+
duration: n.duration ?? 0,
|
|
233
|
+
pose: (u) => d.get(u) ?? (d.set(u, new I(u)), d.get(u)),
|
|
234
|
+
mark: (u) => l.add(u),
|
|
235
|
+
child: () => T.createTimeline({ paused: !0 })
|
|
236
|
+
}, c = n.steps.map((u) => ({ step: u, targets: Q(e, u) })).filter((u) => u.targets.length);
|
|
237
|
+
if (!c.length) return null;
|
|
238
|
+
const f = $(
|
|
239
|
+
r,
|
|
240
|
+
() => c.map(({ step: u, targets: g }) => ({ step: u, p: X[u.kind].prepare(g, u, i) })),
|
|
241
|
+
c.flatMap((u) => u.targets)
|
|
242
|
+
).filter((u) => !!u.p);
|
|
243
|
+
if (!f.length) return null;
|
|
244
|
+
const b = n.stagger ?? 0;
|
|
245
|
+
f.forEach(({ step: u, p: g }, U) => {
|
|
246
|
+
const L = u.at ?? (U === 0 ? n.delay ?? 0 : b === 0 ? ">" : `>${b}`), x = i.child();
|
|
247
|
+
g.build(x), p.add(x, J(L, u.delay ?? 0));
|
|
248
|
+
}), h();
|
|
249
|
+
let m = !1, y = 0;
|
|
250
|
+
const v = _();
|
|
251
|
+
v && (p.progress(1), F());
|
|
252
|
+
const M = () => {
|
|
253
|
+
m || v || (r.classList.add("motion"), p.play(0));
|
|
254
|
+
};
|
|
255
|
+
return {
|
|
256
|
+
timeline: p,
|
|
257
|
+
pause() {
|
|
258
|
+
clearTimeout(y), p.pause();
|
|
259
|
+
},
|
|
260
|
+
resume() {
|
|
261
|
+
!m && !v && (r.classList.add("motion"), p.play());
|
|
262
|
+
},
|
|
263
|
+
play() {
|
|
264
|
+
if (m || v) return;
|
|
265
|
+
const u = r.getAnimations().find((g) => g instanceof CSSAnimation && g.animationName === "drop");
|
|
266
|
+
u ? u.finished.then(M, () => {
|
|
267
|
+
}) : M();
|
|
268
|
+
},
|
|
269
|
+
replay(u = 0) {
|
|
270
|
+
m || v || (clearTimeout(y), p.pause(0), y = window.setTimeout(M, u));
|
|
271
|
+
},
|
|
272
|
+
seek(u) {
|
|
273
|
+
m || (clearTimeout(y), p.pause(), p.progress(Math.min(1, Math.max(0, u))));
|
|
274
|
+
},
|
|
275
|
+
finish() {
|
|
276
|
+
m || (clearTimeout(y), p.pause(), p.progress(1), F(), r.classList.remove("motion"));
|
|
277
|
+
},
|
|
278
|
+
dispose() {
|
|
279
|
+
if (!m) {
|
|
280
|
+
m = !0, clearTimeout(y), p.kill();
|
|
281
|
+
for (const { p: u } of f) u.dispose();
|
|
282
|
+
r.classList.remove("motion");
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
export {
|
|
288
|
+
_ as prefersReducedMotion,
|
|
289
|
+
Z as prepareMotion
|
|
290
|
+
};
|
|
291
|
+
//# sourceMappingURL=motion.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"motion.js","sources":["../../src/composition/unrotate.ts","../../src/composition/pen.ts","../../src/composition/motion.ts"],"sourcesContent":["/**\n * Run a layout measurement with a card in its untransformed frame.\n *\n * Brushmark (and anything else using Range / getBoundingClientRect) measures\n * in viewport px, but every card is rotated with a CSS transform and some ink\n * elements carry their own inline rotate. Inside `fn` the card, and every\n * inline-transformed ancestor of the `within` elements up to the card, are\n * flattened, so measured rects are in the card's own frame.\n *\n * Nothing is painted: it all happens synchronously in one task. The card's\n * 0.7 s transform transition does not fire either: transforms are restored\n * while `transition` is still `none`, style is flushed, then transitions come\n * back (the same trick peel.ts uses when it bakes a rest pose).\n *\n * Re-entrant: nested calls on the same card just run `fn`.\n */\nconst depth = new WeakMap<HTMLElement, number>();\n/** Inline transforms as they were before the current flattened span (so code running inside can still read them). */\nconst originals = new WeakMap<HTMLElement, string>();\n\n/** The element's inline `transform` as it is outside any withUnrotated span. */\nexport const inlineTransform = (el: HTMLElement) => originals.get(el) ?? el.style.transform;\n\nexport function withUnrotated<T>(card: HTMLElement, fn: () => T, within: HTMLElement[] = []): T {\n if ((depth.get(card) ?? 0) > 0) return fn();\n depth.set(card, 1);\n\n // the card plus any inline-transformed element between the targets and the card\n const els = new Set<HTMLElement>([card]);\n for (const t of within) {\n for (let e: HTMLElement | null = t; e && e !== card; e = e.parentElement) {\n if (e.style.transform || e.style.rotate || e.style.scale) els.add(e);\n }\n }\n const saved = [...els].map((el) => ({ el, transition: el.style.transition, transform: el.style.transform, rotate: el.style.rotate, scale: el.style.scale }));\n for (const s of saved) {\n originals.set(s.el, s.transform);\n s.el.style.transition = 'none';\n s.el.style.transform = 'none';\n if (s.rotate) s.el.style.rotate = 'none';\n if (s.scale) s.el.style.scale = 'none';\n }\n // the `drop` keyframe scales the card for 0.45 s after it appears: an !important\n // declaration outranks the animation without restarting it\n card.style.setProperty('scale', '1', 'important');\n try {\n return fn();\n } finally {\n for (const s of saved) {\n s.el.style.transform = s.transform;\n if (s.rotate) s.el.style.rotate = s.rotate;\n if (s.scale) s.el.style.scale = s.scale;\n }\n card.style.removeProperty('scale');\n void card.offsetWidth;\n for (const s of saved) {\n s.el.style.transition = s.transition;\n originals.delete(s.el);\n }\n depth.set(card, 0);\n }\n}\n","import type { TegakiBundle, TegakiEngine } from 'tegaki/core';\nexport interface PenContext {\n Engine: typeof TegakiEngine;\n bundleFor(family: string): TegakiBundle | undefined;\n}\nconst STRAIGHT: Record<string, string> = { '‘': \"'\", '’': \"'\", '…': '...' };\nexport const penText = (s: string, bundle: TegakiBundle) => s.replace(/[‘’…]/g, c => c in bundle.glyphData ? c : STRAIGHT[c]);\n","/**\n * Runs a card's MotionSpec: one paused Brushmark timeline per card, with\n * annotation timelines nested as children and native steps (draw, write,\n * fade, rise, stamp) as tweens on plain numbers.\n *\n * Performance rules:\n * - layout is read only in `prepare`, inside withUnrotated, once per card;\n * - tweens write numbers; the master timeline's onUpdate flushes one batched\n * style write per dirty element (transform / opacity / clip-path, plus\n * stroke-dashoffset for the one small doodle SVG);\n * - every card ticks on Brushmark's single rAF ticker, which stops when\n * nothing is playing; Brushmark repaints only dirty overlays;\n * - annotations are built one card per frame by the render queue, and the\n * brush budget caps GL paints per card and per desk.\n */\nimport { annotate, builtinEngine, flushReveals, type BrushAnnotation, type BrushTimeline } from 'brushmark';\nimport type { CardPlan } from './scene';\nimport type { BuiltCard } from './renderer';\nimport type { Rng } from './rng';\nimport type { At, BrushStep, DevelopStep, DrawStep, FadeStep, MotionSpec, MotionStep, RiseStep, StampStep, WriteStep } from './motion-spec';\nimport { inlineTransform, withUnrotated } from './unrotate';\nimport type { PenContext } from './pen';\nimport { penText } from './pen';\n\nexport interface CardMotion {\n timeline: BrushTimeline;\n /** Start after the card's drop animation (right away if it already ran). */\n play(): void;\n pause(): void;\n resume(): void;\n /** Restart from the beginning after `delayMs`. */\n replay(delayMs?: number): void;\n /** Pause and show the state at progress 0..1 (debug scrubber). */\n seek(p: number): void;\n /** Jump to the end state, painted right now (grab, reduced motion). */\n finish(): void;\n dispose(): void;\n}\n\nexport const prefersReducedMotion = () => matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n// ---------------------------------------------------------------- per-card state\n\ninterface Flushable {\n flush(): void;\n}\n\n/** Compositor-only state of one element; written in one go when dirty. */\nclass Pose implements Flushable {\n x = 0;\n y = 0;\n s = 1;\n o = 1;\n /** Percent hidden from the right / bottom (clip sweeps). */\n cx = 0;\n cy = 0;\n private readonly base: string;\n private readonly o0: number;\n private readonly saved: { transform: string; opacity: string; clipPath: string };\n constructor(readonly el: HTMLElement) {\n // poses are made inside withUnrotated, where inline transforms are flattened: read the real one\n this.base = inlineTransform(el);\n this.saved = { transform: this.base, opacity: el.style.opacity, clipPath: el.style.clipPath };\n this.o0 = parseFloat(getComputedStyle(el).opacity) || 1;\n el.dataset.mv = '';\n }\n flush() {\n const st = this.el.style;\n const moved = this.x || this.y || this.s !== 1;\n st.transform = moved ? `${this.base} translate(${this.x.toFixed(2)}px, ${this.y.toFixed(2)}px) scale(${this.s.toFixed(4)})`.trim() : this.base;\n st.opacity = this.o >= 1 ? this.saved.opacity : `${(this.o0 * this.o).toFixed(3)}`;\n st.clipPath = this.cx > 0 ? `inset(0 ${this.cx.toFixed(2)}% 0 0)` : this.cy > 0 ? `inset(0 0 ${this.cy.toFixed(2)}% 0)` : this.saved.clipPath;\n }\n restore() {\n Object.assign(this.el.style, this.saved);\n delete this.el.dataset.mv;\n }\n}\n\ninterface StepCtx {\n pen?: PenContext;\n card: HTMLElement;\n ink: HTMLElement;\n rng: Rng;\n /** Spec-level default duration. */\n duration: number;\n pose(el: HTMLElement): Pose;\n /** Flush `f` on the next master update. */\n mark(f: Flushable): void;\n /** A paused child timeline, to be added to the master at the step's position. */\n child(): BrushTimeline;\n}\n\ninterface Prepared {\n /** Fill the child timeline (tweens start at 0 within it). */\n build(tl: BrushTimeline): void;\n dispose(): void;\n}\n\ninterface StepImpl<S extends MotionStep> {\n /** May read layout (runs inside withUnrotated). Null when there is nothing to do. */\n prepare(targets: HTMLElement[], step: S, ctx: StepCtx): Prepared | null;\n}\n\nconst dur = (step: MotionStep, ctx: StepCtx, fallback: number) => step.duration ?? (ctx.duration || fallback);\n\n// ---------------------------------------------------------------- steps\n\nconst brush: StepImpl<BrushStep> = {\n prepare(targets, step, ctx) {\n const { kind: _k, target: _t, at: _a, priority: _p, ...cfg } = step;\n const annos: BrushAnnotation[] = targets.map((el) =>\n annotate(el, {\n ...cfg,\n duration: step.duration ?? (ctx.duration || cfg.duration),\n observe: false,\n measure: (run) => withUnrotated(ctx.card, run, [el]),\n seed: cfg.seed ?? ctx.rng.int(1, 1e9),\n }),\n );\n for (const a of annos) a.prepare();\n return {\n build(tl) {\n annos.forEach((a, i) => tl.add(a.timeline, i === 0 ? 0 : '>-0.1'));\n },\n dispose: () => annos.forEach((a) => a.remove()),\n };\n },\n};\n\nconst draw: StepImpl<DrawStep> = {\n prepare(targets, step, ctx) {\n const paths = targets.flatMap((t) => (t instanceof SVGPathElement ? [t] : [...t.querySelectorAll('path')]));\n if (!paths.length) return null;\n const items = paths.map((p) => {\n const len = p.getTotalLength();\n const saved = { dasharray: p.style.strokeDasharray, dashoffset: p.style.strokeDashoffset, opacity: p.style.opacity };\n p.style.strokeDasharray = `${len}`;\n const it = {\n t: 0,\n flush() {\n p.style.strokeDashoffset = `${(len * (1 - it.t)).toFixed(2)}`;\n // a zero-length dash still shows a round-cap dot: hide until the stroke starts\n p.style.opacity = it.t > 0 ? saved.opacity : '0';\n },\n restore: () => Object.assign(p.style, { strokeDasharray: saved.dasharray, strokeDashoffset: saved.dashoffset, opacity: saved.opacity }),\n };\n it.flush();\n return it;\n });\n const total = dur(step, ctx, 1.2);\n const stagger = step.stagger ?? 0;\n // each path gets time in proportion to its length, laid end to end\n const lens = paths.map((p) => p.getTotalLength());\n const sum = lens.reduce((a, b) => a + b, 0) || 1;\n return {\n build(tl) {\n let pos = 0;\n items.forEach((it, i) => {\n const d = Math.max(0.05, (total * lens[i]) / sum);\n tl.to(it, { t: 1, duration: d, ease: step.ease ?? 'power1.inOut', onUpdate: () => ctx.mark(it) }, pos);\n pos += d + stagger;\n });\n },\n dispose: () => items.forEach((it) => it.restore()),\n };\n },\n};\n\n/** Text-bearing elements under `el`, in reading order: elements whose children are only text, <br> or inline phrasing. */\nconst INLINE = new Set(['SPAN', 'B', 'I', 'EM', 'STRONG', 'S', 'U', 'SMALL', 'SUB', 'SUP', 'BR']);\nfunction textLeaves(el: HTMLElement): HTMLElement[] {\n const kids = [...el.children] as HTMLElement[];\n if (kids.every((k) => INLINE.has(k.tagName) && !k.querySelector(':not(span,b,i,em,strong,s,u,small,sub,sup,br)'))) return el.textContent?.trim() ? [el] : [];\n return kids.flatMap(textLeaves);\n}\n\n/** Seconds of pen time per second on the desk, and the longest a block may take: real stroke timing is slow for long text. */\nconst PEN_SPEED = 1.6;\nconst PEN_MAX = 8;\n\n/** Tegaki pen strokes (handwriting.ts), one engine per text block, written one after another. Null when any block has no pen font. */\nfunction penWrite(el: HTMLElement, step: WriteStep, ctx: StepCtx): Prepared | null {\n const Engine = ctx.pen?.Engine;\n const leaves = textLeaves(el);\n const fonts = leaves.map((l) => ctx.pen?.bundleFor(getComputedStyle(l).fontFamily));\n if (!Engine || !leaves.length || fonts.some((f) => !f)) return null;\n const blocks = leaves.map((leaf, i) => {\n const text = penText(leaf.innerText.trim(), fonts[i]!);\n const html = leaf.innerHTML;\n // the engine keeps the text as transparent DOM in the same flow, so the block keeps its size and its text stays selectable\n leaf.textContent = '';\n const host = document.createElement('span');\n host.className = 'pen';\n leaf.appendChild(host);\n const engine = new Engine(host, { font: fonts[i]!, text, time: { mode: 'controlled', value: 0 }, seed: ctx.rng.int(0, 1e6) });\n return { leaf, html, engine, len: engine.duration || text.length * 0.12, t: -1 };\n });\n const natural = blocks.reduce((a, b) => a + b.len, 0);\n const d = Math.min(PEN_MAX, Math.max(natural / PEN_SPEED, step.duration ?? 0));\n const k = natural / d;\n const st = {\n t: 0,\n flush() {\n let at = st.t * k;\n for (const b of blocks) {\n const t = Math.min(b.len, Math.max(0, at));\n if (t !== b.t) b.engine.update({ time: { mode: 'controlled', value: (b.t = t) } });\n at -= b.len;\n }\n },\n };\n st.flush();\n return {\n build: (tl) => tl.to(st, { t: d, duration: d, ease: 'none', onUpdate: () => ctx.mark(st) }, 0),\n dispose: () =>\n blocks.forEach((b) => {\n b.engine.destroy();\n b.leaf.innerHTML = b.html;\n }),\n };\n}\n\nconst write: StepImpl<WriteStep> = {\n prepare(targets, step, ctx) {\n const prepared: Prepared[] = [];\n for (const el of targets) {\n const glyphs = [...el.querySelectorAll<HTMLElement>('.w > span')];\n let mode = step.mode ?? 'auto';\n if ((mode === 'auto' || mode === 'pen') && !glyphs.length && ctx.pen) {\n const p = penWrite(el, step, ctx);\n if (p) {\n prepared.push(p);\n continue;\n }\n }\n if (mode === 'pen') mode = 'auto';\n if (mode === 'auto') mode = glyphs.length ? 'glyph' : el.offsetHeight > 1.6 * parseFloat(getComputedStyle(el).fontSize) ? 'sweep-y' : 'sweep-x';\n if (mode === 'glyph') {\n if (!glyphs.length) continue;\n // typed() already gave every glyph its own ink density: hide them all, then reveal in order\n const saved = glyphs.map((g) => g.style.opacity);\n for (const g of glyphs) g.style.opacity = '0';\n let applied = 0;\n const st = {\n n: 0,\n flush() {\n const want = Math.min(glyphs.length, Math.max(0, Math.floor(st.n)));\n for (let i = applied; i < want; i++) glyphs[i].style.opacity = saved[i];\n for (let i = want; i < applied; i++) glyphs[i].style.opacity = '0';\n applied = want;\n },\n };\n const rate = step.rate ?? 28;\n const d = step.duration ?? glyphs.length / rate;\n prepared.push({\n build: (tl) => tl.to(st, { n: glyphs.length, duration: d, ease: 'none', onUpdate: () => ctx.mark(st) }, 0),\n dispose: () => glyphs.forEach((g, i) => (g.style.opacity = saved[i])),\n });\n } else {\n const pose = ctx.pose(el);\n const key = mode === 'sweep-x' ? 'cx' : 'cy';\n pose[key] = 100;\n pose.flush();\n prepared.push({\n build: (tl) => tl.to(pose, { [key]: 0, duration: dur(step, ctx, 1), ease: step.ease ?? 'none', onUpdate: () => ctx.mark(pose) }, 0),\n dispose: () => pose.restore(),\n });\n }\n }\n if (!prepared.length) return null;\n return { build: (tl) => prepared.forEach((p) => p.build(tl)), dispose: () => prepared.forEach((p) => p.dispose()) };\n },\n};\n\n/** Pose tweens shared by fade / rise / stamp: set the start pose, tween to rest. */\nfunction poseStep<S extends FadeStep | RiseStep | StampStep>(start: (p: Pose, s: S) => void, tween: (tl: BrushTimeline, p: Pose, s: S, d: number, mark: () => void) => void): StepImpl<S> {\n return {\n prepare(targets, step, ctx) {\n const poses = targets.map((el) => {\n const p = ctx.pose(el);\n start(p, step);\n p.flush();\n return p;\n });\n return {\n build: (tl) => poses.forEach((p) => tween(tl, p, step, dur(step, ctx, 0.4), () => ctx.mark(p))),\n dispose: () => poses.forEach((p) => p.restore()),\n };\n },\n };\n}\n\nconst fade = poseStep<FadeStep>(\n (p, s) => (p.o = s.from ?? 0),\n (tl, p, s, d, mark) => tl.to(p, { o: 1, duration: d, ease: s.ease ?? 'power1.out', onUpdate: mark }, 0),\n);\n\nconst rise = poseStep<RiseStep>(\n (p, s) => ((p.o = 0), (p.y = s.dy ?? 6)),\n (tl, p, s, d, mark) => tl.to(p, { o: 1, y: 0, duration: d, ease: s.ease ?? 'power2.out', onUpdate: mark }, 0),\n);\n\nconst stamp = poseStep<StampStep>(\n (p, s) => ((p.o = 0), (p.s = s.from ?? 1.6)),\n (tl, p, s, d, mark) => {\n tl.to(p, { s: 1, duration: d, ease: s.ease ?? 'back.out', onUpdate: mark }, 0);\n tl.to(p, { o: 1, duration: d * 0.4, ease: 'power2.out', onUpdate: mark }, 0);\n },\n);\n\n/** Opacity 1 -> 0 on an element that is invisible at rest (opacity: 0 in CSS), so motion-off shows the clear photo. */\nconst develop: StepImpl<DevelopStep> = {\n prepare(targets, step, ctx) {\n const states = targets.map((el) => {\n const st = { v: 1, flush: () => void (el.style.opacity = st.v.toFixed(3)) };\n st.flush();\n return st;\n });\n return {\n build: (tl) => states.forEach((st) => tl.to(st, { v: 0, duration: dur(step, ctx, 2.6), ease: step.ease ?? 'power1.in', onUpdate: () => ctx.mark(st) }, 0)),\n dispose: () => targets.forEach((el) => (el.style.opacity = '')),\n };\n },\n};\n\nconst STEP_KINDS: { [K in MotionStep['kind']]: StepImpl<Extract<MotionStep, { kind: K }>> } = { brush, draw, write, fade, rise, stamp, develop };\n\n// ---------------------------------------------------------------- orchestration\n\n/** Fold a step's own delay into its timeline position (`>`, `>+n`, `>-n`, `+=n`, `-=n` or seconds). */\nfunction withDelay(at: At, delay: number): At {\n if (!delay) return at;\n if (typeof at === 'number') return at + delay;\n const rel = /^>([+-]?\\d*\\.?\\d+)?$/.exec(at);\n if (rel) return `>${(parseFloat(rel[1] ?? '0') + delay).toFixed(3)}`;\n const off = /^([+-])=(\\d*\\.?\\d+)$/.exec(at);\n if (off) {\n const n = (off[1] === '-' ? -1 : 1) * parseFloat(off[2]) + delay;\n return `${n < 0 ? '-' : '+'}=${Math.abs(n).toFixed(3)}`;\n }\n return at;\n}\n\nfunction resolveTargets(ink: HTMLElement, step: MotionStep): HTMLElement[] {\n if (typeof step.target === 'string') return [...ink.querySelectorAll<HTMLElement>(step.target)];\n return ink.contains(step.target) ? [step.target] : [];\n}\n\nexport function prepareMotion(plan: CardPlan, built: BuiltCard, rng: Rng, pen?: PenContext): CardMotion | null {\n const spec: MotionSpec | undefined = plan.motion;\n const ink = plan.ink;\n if (!spec?.steps.length || !ink) return null;\n\n const dirty = new Set<Flushable>();\n const poses = new Map<HTMLElement, Pose>();\n const flushAll = () => {\n for (const f of dirty) f.flush();\n dirty.clear();\n };\n const card = built.el;\n const master = builtinEngine.createTimeline({ paused: true, onUpdate: flushAll, onComplete: () => card.classList.remove('motion') });\n const ctx: StepCtx = {\n card,\n pen,\n ink,\n rng,\n duration: spec.duration ?? 0,\n pose: (el) => poses.get(el) ?? (poses.set(el, new Pose(el)), poses.get(el)!),\n mark: (f) => dirty.add(f),\n child: () => builtinEngine.createTimeline({ paused: true }),\n };\n\n const steps = spec.steps.map((step) => ({ step, targets: resolveTargets(ink, step) })).filter((x) => x.targets.length);\n if (!steps.length) return null;\n\n // one unrotated span per card: every step measures in the card's own frame\n const prepared = withUnrotated(\n card,\n () => steps.map(({ step, targets }) => ({ step, p: (STEP_KINDS[step.kind] as StepImpl<MotionStep>).prepare(targets, step, ctx) })),\n steps.flatMap((x) => x.targets),\n ).filter((x): x is { step: MotionStep; p: Prepared } => !!x.p);\n if (!prepared.length) return null;\n\n const gap = spec.stagger ?? 0;\n prepared.forEach(({ step, p }, i) => {\n const at: At = step.at ?? (i === 0 ? (spec.delay ?? 0) : gap === 0 ? '>' : `>${gap}`);\n const child = ctx.child();\n p.build(child);\n master.add(child, withDelay(at, step.delay ?? 0));\n });\n flushAll();\n\n let disposed = false;\n let timer = 0;\n const reduced = prefersReducedMotion();\n if (reduced) {\n master.progress(1);\n flushReveals();\n }\n\n const start = () => {\n if (disposed || reduced) return;\n card.classList.add('motion');\n master.play(0);\n };\n return {\n timeline: master,\n pause() { clearTimeout(timer); master.pause(); },\n resume() { if (!disposed && !reduced) { card.classList.add('motion'); master.play(); } },\n play() {\n if (disposed || reduced) return;\n const drop = card.getAnimations().find((a) => a instanceof CSSAnimation && a.animationName === 'drop');\n if (drop) drop.finished.then(start, () => {});\n else start();\n },\n replay(delayMs = 0) {\n if (disposed || reduced) return;\n clearTimeout(timer);\n master.pause(0);\n timer = window.setTimeout(start, delayMs);\n },\n seek(p) {\n if (disposed) return;\n clearTimeout(timer);\n master.pause();\n master.progress(Math.min(1, Math.max(0, p)));\n },\n finish() {\n if (disposed) return;\n clearTimeout(timer);\n master.pause();\n master.progress(1);\n flushReveals();\n card.classList.remove('motion');\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n clearTimeout(timer);\n master.kill();\n for (const { p } of prepared) p.dispose();\n card.classList.remove('motion');\n },\n };\n}\n"],"names":["depth","originals","inlineTransform","el","withUnrotated","card","fn","within","els","t","e","saved","s","STRAIGHT","penText","bundle","c","prefersReducedMotion","Pose","st","moved","dur","step","ctx","fallback","brush","targets","_k","_t","_a","_p","cfg","annos","annotate","run","a","tl","draw","paths","items","p","len","it","total","stagger","lens","sum","b","pos","i","d","INLINE","textLeaves","kids","k","PEN_SPEED","PEN_MAX","penWrite","Engine","leaves","fonts","l","f","blocks","leaf","text","html","host","engine","natural","at","write","prepared","glyphs","mode","g","applied","want","rate","pose","key","poseStep","start","tween","poses","fade","mark","rise","stamp","develop","states","STEP_KINDS","withDelay","delay","rel","off","resolveTargets","ink","prepareMotion","plan","built","rng","pen","spec","dirty","flushAll","master","builtinEngine","steps","x","gap","child","disposed","timer","reduced","flushReveals","drop","delayMs"],"mappings":";AAgBA,MAAMA,wBAAY,QAAA,GAEZC,wBAAgB,QAAA,GAGTC,IAAkB,CAACC,MAAoBF,EAAU,IAAIE,CAAE,KAAKA,EAAG,MAAM;AAE3E,SAASC,EAAiBC,GAAmBC,GAAaC,IAAwB,CAAA,GAAO;AAC9F,OAAKP,EAAM,IAAIK,CAAI,KAAK,KAAK,UAAUC,EAAA;AACvC,EAAAN,EAAM,IAAIK,GAAM,CAAC;AAGjB,QAAMG,IAAM,oBAAI,IAAiB,CAACH,CAAI,CAAC;AACvC,aAAWI,KAAKF;AACd,aAASG,IAAwBD,GAAGC,KAAKA,MAAML,GAAMK,IAAIA,EAAE;AACzD,OAAIA,EAAE,MAAM,aAAaA,EAAE,MAAM,UAAUA,EAAE,MAAM,UAAOF,EAAI,IAAIE,CAAC;AAGvE,QAAMC,IAAQ,CAAC,GAAGH,CAAG,EAAE,IAAI,CAACL,OAAQ,EAAE,IAAAA,GAAI,YAAYA,EAAG,MAAM,YAAY,WAAWA,EAAG,MAAM,WAAW,QAAQA,EAAG,MAAM,QAAQ,OAAOA,EAAG,MAAM,MAAA,EAAQ;AAC3J,aAAWS,KAAKD;AACd,IAAAV,EAAU,IAAIW,EAAE,IAAIA,EAAE,SAAS,GAC/BA,EAAE,GAAG,MAAM,aAAa,QACxBA,EAAE,GAAG,MAAM,YAAY,QACnBA,EAAE,WAAQA,EAAE,GAAG,MAAM,SAAS,SAC9BA,EAAE,UAAOA,EAAE,GAAG,MAAM,QAAQ;AAIlC,EAAAP,EAAK,MAAM,YAAY,SAAS,KAAK,WAAW;AAChD,MAAI;AACF,WAAOC,EAAA;AAAA,EACT,UAAA;AACE,eAAWM,KAAKD;AACd,MAAAC,EAAE,GAAG,MAAM,YAAYA,EAAE,WACrBA,EAAE,WAAQA,EAAE,GAAG,MAAM,SAASA,EAAE,SAChCA,EAAE,UAAOA,EAAE,GAAG,MAAM,QAAQA,EAAE;AAEpC,IAAAP,EAAK,MAAM,eAAe,OAAO,GAC5BA,EAAK;AACV,eAAWO,KAAKD;AACd,MAAAC,EAAE,GAAG,MAAM,aAAaA,EAAE,YAC1BX,EAAU,OAAOW,EAAE,EAAE;AAEvB,IAAAZ,EAAM,IAAIK,GAAM,CAAC;AAAA,EACnB;AACF;ACxDA,MAAMQ,IAAmC,EAAE,KAAK,KAAK,KAAK,KAAK,KAAK,MAAA,GACvDC,IAAU,CAAC,GAAWC,MAAyB,EAAE,QAAQ,UAAU,CAAAC,MAAKA,KAAKD,EAAO,YAAYC,IAAIH,EAASG,CAAC,CAAC,GCiC/GC,IAAuB,MAAM,WAAW,kCAAkC,EAAE;AASzF,MAAMC,EAA0B;AAAA,EAW9B,YAAqBf,GAAiB;AAAjB,SAAA,KAAAA,GAEnB,KAAK,OAAOD,EAAgBC,CAAE,GAC9B,KAAK,QAAQ,EAAE,WAAW,KAAK,MAAM,SAASA,EAAG,MAAM,SAAS,UAAUA,EAAG,MAAM,SAAA,GACnF,KAAK,KAAK,WAAW,iBAAiBA,CAAE,EAAE,OAAO,KAAK,GACtDA,EAAG,QAAQ,KAAK;AAAA,EAClB;AAAA,EAhBA,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA,EACJ,IAAI;AAAA;AAAA,EAEJ,KAAK;AAAA,EACL,KAAK;AAAA,EACY;AAAA,EACA;AAAA,EACA;AAAA,EAQjB,QAAQ;AACN,UAAMgB,IAAK,KAAK,GAAG,OACbC,IAAQ,KAAK,KAAK,KAAK,KAAK,KAAK,MAAM;AAC7C,IAAAD,EAAG,YAAYC,IAAQ,GAAG,KAAK,IAAI,cAAc,KAAK,EAAE,QAAQ,CAAC,CAAC,OAAO,KAAK,EAAE,QAAQ,CAAC,CAAC,aAAa,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,KAAA,IAAS,KAAK,MAC1ID,EAAG,UAAU,KAAK,KAAK,IAAI,KAAK,MAAM,UAAU,IAAI,KAAK,KAAK,KAAK,GAAG,QAAQ,CAAC,CAAC,IAChFA,EAAG,WAAW,KAAK,KAAK,IAAI,WAAW,KAAK,GAAG,QAAQ,CAAC,CAAC,WAAW,KAAK,KAAK,IAAI,aAAa,KAAK,GAAG,QAAQ,CAAC,CAAC,SAAS,KAAK,MAAM;AAAA,EACvI;AAAA,EACA,UAAU;AACR,WAAO,OAAO,KAAK,GAAG,OAAO,KAAK,KAAK,GACvC,OAAO,KAAK,GAAG,QAAQ;AAAA,EACzB;AACF;AA2BA,MAAME,IAAM,CAACC,GAAkBC,GAAcC,MAAqBF,EAAK,aAAaC,EAAI,YAAYC,IAI9FC,IAA6B;AAAA,EACjC,QAAQC,GAASJ,GAAMC,GAAK;AAC1B,UAAM,EAAE,MAAMI,GAAI,QAAQC,GAAI,IAAIC,GAAI,UAAUC,GAAI,GAAGC,EAAA,IAAQT,GACzDU,IAA2BN,EAAQ;AAAA,MAAI,CAACvB,MAC5C8B,EAAS9B,GAAI;AAAA,QACX,GAAG4B;AAAA,QACH,UAAUT,EAAK,aAAaC,EAAI,YAAYQ,EAAI;AAAA,QAChD,SAAS;AAAA,QACT,SAAS,CAACG,MAAQ9B,EAAcmB,EAAI,MAAMW,GAAK,CAAC/B,CAAE,CAAC;AAAA,QACnD,MAAM4B,EAAI,QAAQR,EAAI,IAAI,IAAI,GAAG,GAAG;AAAA,MAAA,CACrC;AAAA,IAAA;AAEH,eAAWY,KAAKH,EAAO,CAAAG,EAAE,QAAA;AACzB,WAAO;AAAA,MACL,MAAMC,GAAI;AACR,QAAAJ,EAAM,QAAQ,CAACG,GAAG,MAAMC,EAAG,IAAID,EAAE,UAAU,MAAM,IAAI,IAAI,OAAO,CAAC;AAAA,MACnE;AAAA,MACA,SAAS,MAAMH,EAAM,QAAQ,CAACG,MAAMA,EAAE,QAAQ;AAAA,IAAA;AAAA,EAElD;AACF,GAEME,IAA2B;AAAA,EAC/B,QAAQX,GAASJ,GAAMC,GAAK;AAC1B,UAAMe,IAAQZ,EAAQ,QAAQ,CAACjB,MAAOA,aAAa,iBAAiB,CAACA,CAAC,IAAI,CAAC,GAAGA,EAAE,iBAAiB,MAAM,CAAC,CAAE;AAC1G,QAAI,CAAC6B,EAAM,OAAQ,QAAO;AAC1B,UAAMC,IAAQD,EAAM,IAAI,CAACE,MAAM;AAC7B,YAAMC,IAAMD,EAAE,eAAA,GACR7B,IAAQ,EAAE,WAAW6B,EAAE,MAAM,iBAAiB,YAAYA,EAAE,MAAM,kBAAkB,SAASA,EAAE,MAAM,QAAA;AAC3G,MAAAA,EAAE,MAAM,kBAAkB,GAAGC,CAAG;AAChC,YAAMC,IAAK;AAAA,QACT,GAAG;AAAA,QACH,QAAQ;AACN,UAAAF,EAAE,MAAM,mBAAmB,IAAIC,KAAO,IAAIC,EAAG,IAAI,QAAQ,CAAC,CAAC,IAE3DF,EAAE,MAAM,UAAUE,EAAG,IAAI,IAAI/B,EAAM,UAAU;AAAA,QAC/C;AAAA,QACA,SAAS,MAAM,OAAO,OAAO6B,EAAE,OAAO,EAAE,iBAAiB7B,EAAM,WAAW,kBAAkBA,EAAM,YAAY,SAASA,EAAM,SAAS;AAAA,MAAA;AAExI,aAAA+B,EAAG,MAAA,GACIA;AAAA,IACT,CAAC,GACKC,IAAQtB,EAAIC,GAAMC,GAAK,GAAG,GAC1BqB,IAAUtB,EAAK,WAAW,GAE1BuB,IAAOP,EAAM,IAAI,CAACE,MAAMA,EAAE,gBAAgB,GAC1CM,IAAMD,EAAK,OAAO,CAACV,GAAGY,MAAMZ,IAAIY,GAAG,CAAC,KAAK;AAC/C,WAAO;AAAA,MACL,MAAMX,GAAI;AACR,YAAIY,IAAM;AACV,QAAAT,EAAM,QAAQ,CAACG,GAAIO,MAAM;AACvB,gBAAMC,IAAI,KAAK,IAAI,MAAOP,IAAQE,EAAKI,CAAC,IAAKH,CAAG;AAChD,UAAAV,EAAG,GAAGM,GAAI,EAAE,GAAG,GAAG,UAAUQ,GAAG,MAAM5B,EAAK,QAAQ,gBAAgB,UAAU,MAAMC,EAAI,KAAKmB,CAAE,EAAA,GAAKM,CAAG,GACrGA,KAAOE,IAAIN;AAAA,QACb,CAAC;AAAA,MACH;AAAA,MACA,SAAS,MAAML,EAAM,QAAQ,CAACG,MAAOA,EAAG,SAAS;AAAA,IAAA;AAAA,EAErD;AACF,GAGMS,IAAS,oBAAI,IAAI,CAAC,QAAQ,KAAK,KAAK,MAAM,UAAU,KAAK,KAAK,SAAS,OAAO,OAAO,IAAI,CAAC;AAChG,SAASC,EAAWjD,GAAgC;AAClD,QAAMkD,IAAO,CAAC,GAAGlD,EAAG,QAAQ;AAC5B,SAAIkD,EAAK,MAAM,CAACC,MAAMH,EAAO,IAAIG,EAAE,OAAO,KAAK,CAACA,EAAE,cAAc,+CAA+C,CAAC,IAAUnD,EAAG,aAAa,SAAS,CAACA,CAAE,IAAI,CAAA,IACnJkD,EAAK,QAAQD,CAAU;AAChC;AAGA,MAAMG,IAAY,KACZC,IAAU;AAGhB,SAASC,EAAStD,GAAiBmB,GAAiBC,GAA+B;AACjF,QAAMmC,IAASnC,EAAI,KAAK,QAClBoC,IAASP,EAAWjD,CAAE,GACtByD,IAAQD,EAAO,IAAI,CAACE,MAAMtC,EAAI,KAAK,UAAU,iBAAiBsC,CAAC,EAAE,UAAU,CAAC;AAClF,MAAI,CAACH,KAAU,CAACC,EAAO,UAAUC,EAAM,KAAK,CAACE,MAAM,CAACA,CAAC,EAAG,QAAO;AAC/D,QAAMC,IAASJ,EAAO,IAAI,CAACK,GAAMf,MAAM;AACrC,UAAMgB,IAAOnD,EAAQkD,EAAK,UAAU,QAAQJ,EAAMX,CAAC,CAAE,GAC/CiB,IAAOF,EAAK;AAElB,IAAAA,EAAK,cAAc;AACnB,UAAMG,IAAO,SAAS,cAAc,MAAM;AAC1C,IAAAA,EAAK,YAAY,OACjBH,EAAK,YAAYG,CAAI;AACrB,UAAMC,IAAS,IAAIV,EAAOS,GAAM,EAAE,MAAMP,EAAMX,CAAC,GAAI,MAAAgB,GAAM,MAAM,EAAE,MAAM,cAAc,OAAO,EAAA,GAAK,MAAM1C,EAAI,IAAI,IAAI,GAAG,GAAG,GAAG;AAC5H,WAAO,EAAE,MAAAyC,GAAM,MAAAE,GAAM,QAAAE,GAAQ,KAAKA,EAAO,YAAYH,EAAK,SAAS,MAAM,GAAG,GAAA;AAAA,EAC9E,CAAC,GACKI,IAAUN,EAAO,OAAO,CAAC5B,GAAGY,MAAMZ,IAAIY,EAAE,KAAK,CAAC,GAC9CG,IAAI,KAAK,IAAIM,GAAS,KAAK,IAAIa,IAAUd,GAAWjC,EAAK,YAAY,CAAC,CAAC,GACvEgC,IAAIe,IAAUnB,GACd/B,IAAK;AAAA,IACT,GAAG;AAAA,IACH,QAAQ;AACN,UAAImD,IAAKnD,EAAG,IAAImC;AAChB,iBAAWP,KAAKgB,GAAQ;AACtB,cAAMtD,IAAI,KAAK,IAAIsC,EAAE,KAAK,KAAK,IAAI,GAAGuB,CAAE,CAAC;AACzC,QAAI7D,MAAMsC,EAAE,KAAGA,EAAE,OAAO,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,OAAQA,EAAE,IAAItC,EAAA,GAAM,GACjF6D,KAAMvB,EAAE;AAAA,MACV;AAAA,IACF;AAAA,EAAA;AAEF,SAAA5B,EAAG,MAAA,GACI;AAAA,IACL,OAAO,CAACiB,MAAOA,EAAG,GAAGjB,GAAI,EAAE,GAAG+B,GAAG,UAAUA,GAAG,MAAM,QAAQ,UAAU,MAAM3B,EAAI,KAAKJ,CAAE,EAAA,GAAK,CAAC;AAAA,IAC7F,SAAS,MACP4C,EAAO,QAAQ,CAAChB,MAAM;AACpB,MAAAA,EAAE,OAAO,QAAA,GACTA,EAAE,KAAK,YAAYA,EAAE;AAAA,IACvB,CAAC;AAAA,EAAA;AAEP;AAEA,MAAMwB,IAA6B;AAAA,EACjC,QAAQ7C,GAASJ,GAAMC,GAAK;AAC1B,UAAMiD,IAAuB,CAAA;AAC7B,eAAWrE,KAAMuB,GAAS;AACxB,YAAM+C,IAAS,CAAC,GAAGtE,EAAG,iBAA8B,WAAW,CAAC;AAChE,UAAIuE,IAAOpD,EAAK,QAAQ;AACxB,WAAKoD,MAAS,UAAUA,MAAS,UAAU,CAACD,EAAO,UAAUlD,EAAI,KAAK;AACpE,cAAMiB,IAAIiB,EAAStD,GAAImB,GAAMC,CAAG;AAChC,YAAIiB,GAAG;AACL,UAAAgC,EAAS,KAAKhC,CAAC;AACf;AAAA,QACF;AAAA,MACF;AAGA,UAFIkC,MAAS,UAAOA,IAAO,SACvBA,MAAS,WAAQA,IAAOD,EAAO,SAAS,UAAUtE,EAAG,eAAe,MAAM,WAAW,iBAAiBA,CAAE,EAAE,QAAQ,IAAI,YAAY,YAClIuE,MAAS,SAAS;AACpB,YAAI,CAACD,EAAO,OAAQ;AAEpB,cAAM9D,IAAQ8D,EAAO,IAAI,CAACE,MAAMA,EAAE,MAAM,OAAO;AAC/C,mBAAWA,KAAKF,EAAQ,CAAAE,EAAE,MAAM,UAAU;AAC1C,YAAIC,IAAU;AACd,cAAMzD,IAAK;AAAA,UACT,GAAG;AAAA,UACH,QAAQ;AACN,kBAAM0D,IAAO,KAAK,IAAIJ,EAAO,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAMtD,EAAG,CAAC,CAAC,CAAC;AAClE,qBAAS8B,IAAI2B,GAAS3B,IAAI4B,GAAM5B,IAAK,CAAAwB,EAAOxB,CAAC,EAAE,MAAM,UAAUtC,EAAMsC,CAAC;AACtE,qBAASA,IAAI4B,GAAM5B,IAAI2B,GAAS3B,IAAK,CAAAwB,EAAOxB,CAAC,EAAE,MAAM,UAAU;AAC/D,YAAA2B,IAAUC;AAAA,UACZ;AAAA,QAAA,GAEIC,IAAOxD,EAAK,QAAQ,IACpB4B,IAAI5B,EAAK,YAAYmD,EAAO,SAASK;AAC3C,QAAAN,EAAS,KAAK;AAAA,UACZ,OAAO,CAACpC,MAAOA,EAAG,GAAGjB,GAAI,EAAE,GAAGsD,EAAO,QAAQ,UAAUvB,GAAG,MAAM,QAAQ,UAAU,MAAM3B,EAAI,KAAKJ,CAAE,EAAA,GAAK,CAAC;AAAA,UACzG,SAAS,MAAMsD,EAAO,QAAQ,CAACE,GAAG1B,MAAO0B,EAAE,MAAM,UAAUhE,EAAMsC,CAAC,CAAE;AAAA,QAAA,CACrE;AAAA,MACH,OAAO;AACL,cAAM8B,IAAOxD,EAAI,KAAKpB,CAAE,GAClB6E,IAAMN,MAAS,YAAY,OAAO;AACxC,QAAAK,EAAKC,CAAG,IAAI,KACZD,EAAK,MAAA,GACLP,EAAS,KAAK;AAAA,UACZ,OAAO,CAACpC,MAAOA,EAAG,GAAG2C,GAAM,EAAE,CAACC,CAAG,GAAG,GAAG,UAAU3D,EAAIC,GAAMC,GAAK,CAAC,GAAG,MAAMD,EAAK,QAAQ,QAAQ,UAAU,MAAMC,EAAI,KAAKwD,CAAI,EAAA,GAAK,CAAC;AAAA,UAClI,SAAS,MAAMA,EAAK,QAAA;AAAA,QAAQ,CAC7B;AAAA,MACH;AAAA,IACF;AACA,WAAKP,EAAS,SACP,EAAE,OAAO,CAACpC,MAAOoC,EAAS,QAAQ,CAAChC,MAAMA,EAAE,MAAMJ,CAAE,CAAC,GAAG,SAAS,MAAMoC,EAAS,QAAQ,CAAChC,MAAMA,EAAE,QAAA,CAAS,EAAA,IADnF;AAAA,EAE/B;AACF;AAGA,SAASyC,EAAoDC,GAAgCC,GAA6F;AACxL,SAAO;AAAA,IACL,QAAQzD,GAASJ,GAAMC,GAAK;AAC1B,YAAM6D,IAAQ1D,EAAQ,IAAI,CAACvB,MAAO;AAChC,cAAMqC,IAAIjB,EAAI,KAAKpB,CAAE;AACrB,eAAA+E,EAAM1C,GAAGlB,CAAI,GACbkB,EAAE,MAAA,GACKA;AAAA,MACT,CAAC;AACD,aAAO;AAAA,QACL,OAAO,CAACJ,MAAOgD,EAAM,QAAQ,CAAC5C,MAAM2C,EAAM/C,GAAII,GAAGlB,GAAMD,EAAIC,GAAMC,GAAK,GAAG,GAAG,MAAMA,EAAI,KAAKiB,CAAC,CAAC,CAAC;AAAA,QAC9F,SAAS,MAAM4C,EAAM,QAAQ,CAAC5C,MAAMA,EAAE,SAAS;AAAA,MAAA;AAAA,IAEnD;AAAA,EAAA;AAEJ;AAEA,MAAM6C,IAAOJ;AAAA,EACX,CAACzC,GAAG5B,MAAO4B,EAAE,IAAI5B,EAAE,QAAQ;AAAA,EAC3B,CAACwB,GAAII,GAAG5B,GAAGsC,GAAGoC,MAASlD,EAAG,GAAGI,GAAG,EAAE,GAAG,GAAG,UAAUU,GAAG,MAAMtC,EAAE,QAAQ,cAAc,UAAU0E,EAAA,GAAQ,CAAC;AACxG,GAEMC,IAAON;AAAA,EACX,CAACzC,GAAG5B,OAAQ4B,EAAE,IAAI,GAAKA,EAAE,IAAI5B,EAAE,MAAM;AAAA,EACrC,CAACwB,GAAII,GAAG5B,GAAGsC,GAAGoC,MAASlD,EAAG,GAAGI,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,UAAUU,GAAG,MAAMtC,EAAE,QAAQ,cAAc,UAAU0E,EAAA,GAAQ,CAAC;AAC9G,GAEME,IAAQP;AAAA,EACZ,CAACzC,GAAG5B,OAAQ4B,EAAE,IAAI,GAAKA,EAAE,IAAI5B,EAAE,QAAQ;AAAA,EACvC,CAACwB,GAAII,GAAG5B,GAAGsC,GAAGoC,MAAS;AACrB,IAAAlD,EAAG,GAAGI,GAAG,EAAE,GAAG,GAAG,UAAUU,GAAG,MAAMtC,EAAE,QAAQ,YAAY,UAAU0E,EAAA,GAAQ,CAAC,GAC7ElD,EAAG,GAAGI,GAAG,EAAE,GAAG,GAAG,UAAUU,IAAI,KAAK,MAAM,cAAc,UAAUoC,EAAA,GAAQ,CAAC;AAAA,EAC7E;AACF,GAGMG,IAAiC;AAAA,EACrC,QAAQ/D,GAASJ,GAAMC,GAAK;AAC1B,UAAMmE,IAAShE,EAAQ,IAAI,CAACvB,MAAO;AACjC,YAAMgB,IAAK,EAAE,GAAG,GAAG,OAAO,MAAM,MAAMhB,EAAG,MAAM,UAAUgB,EAAG,EAAE,QAAQ,CAAC,GAAA;AACvE,aAAAA,EAAG,MAAA,GACIA;AAAA,IACT,CAAC;AACD,WAAO;AAAA,MACL,OAAO,CAACiB,MAAOsD,EAAO,QAAQ,CAACvE,MAAOiB,EAAG,GAAGjB,GAAI,EAAE,GAAG,GAAG,UAAUE,EAAIC,GAAMC,GAAK,GAAG,GAAG,MAAMD,EAAK,QAAQ,aAAa,UAAU,MAAMC,EAAI,KAAKJ,CAAE,EAAA,GAAK,CAAC,CAAC;AAAA,MACzJ,SAAS,MAAMO,EAAQ,QAAQ,CAACvB,MAAQA,EAAG,MAAM,UAAU,EAAG;AAAA,IAAA;AAAA,EAElE;AACF,GAEMwF,IAAwF,EAAE,OAAAlE,GAAO,MAAAY,GAAM,OAAAkC,GAAO,MAAAc,GAAM,MAAAE,GAAM,OAAAC,GAAO,SAAAC,EAAA;AAKvI,SAASG,EAAUtB,GAAQuB,GAAmB;AAC5C,MAAI,CAACA,EAAO,QAAOvB;AACnB,MAAI,OAAOA,KAAO,SAAU,QAAOA,IAAKuB;AACxC,QAAMC,IAAM,uBAAuB,KAAKxB,CAAE;AAC1C,MAAIwB,EAAK,QAAO,KAAK,WAAWA,EAAI,CAAC,KAAK,GAAG,IAAID,GAAO,QAAQ,CAAC,CAAC;AAClE,QAAME,IAAM,uBAAuB,KAAKzB,CAAE;AAC1C,MAAIyB,GAAK;AACP,UAAM,KAAKA,EAAI,CAAC,MAAM,MAAM,KAAK,KAAK,WAAWA,EAAI,CAAC,CAAC,IAAIF;AAC3D,WAAO,GAAG,IAAI,IAAI,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EACvD;AACA,SAAOvB;AACT;AAEA,SAAS0B,EAAeC,GAAkB3E,GAAiC;AACzE,SAAI,OAAOA,EAAK,UAAW,WAAiB,CAAC,GAAG2E,EAAI,iBAA8B3E,EAAK,MAAM,CAAC,IACvF2E,EAAI,SAAS3E,EAAK,MAAM,IAAI,CAACA,EAAK,MAAM,IAAI,CAAA;AACrD;AAEO,SAAS4E,EAAcC,GAAgBC,GAAkBC,GAAUC,GAAqC;AAC7G,QAAMC,IAA+BJ,EAAK,QACpCF,IAAME,EAAK;AACjB,MAAI,CAACI,GAAM,MAAM,UAAU,CAACN,EAAK,QAAO;AAExC,QAAMO,wBAAY,IAAA,GACZpB,wBAAY,IAAA,GACZqB,IAAW,MAAM;AACrB,eAAW3C,KAAK0C,EAAO,CAAA1C,EAAE,MAAA;AACzB,IAAA0C,EAAM,MAAA;AAAA,EACR,GACMnG,IAAO+F,EAAM,IACbM,IAASC,EAAc,eAAe,EAAE,QAAQ,IAAM,UAAUF,GAAU,YAAY,MAAMpG,EAAK,UAAU,OAAO,QAAQ,GAAG,GAC7HkB,IAAe;AAAA,IACnB,MAAAlB;AAAA,IACA,KAAAiG;AAAA,IACA,KAAAL;AAAA,IACA,KAAAI;AAAA,IACA,UAAUE,EAAK,YAAY;AAAA,IAC3B,MAAM,CAACpG,MAAOiF,EAAM,IAAIjF,CAAE,MAAMiF,EAAM,IAAIjF,GAAI,IAAIe,EAAKf,CAAE,CAAC,GAAGiF,EAAM,IAAIjF,CAAE;AAAA,IACzE,MAAM,CAAC2D,MAAM0C,EAAM,IAAI1C,CAAC;AAAA,IACxB,OAAO,MAAM6C,EAAc,eAAe,EAAE,QAAQ,IAAM;AAAA,EAAA,GAGtDC,IAAQL,EAAK,MAAM,IAAI,CAACjF,OAAU,EAAE,MAAAA,GAAM,SAAS0E,EAAeC,GAAK3E,CAAI,EAAA,EAAI,EAAE,OAAO,CAACuF,MAAMA,EAAE,QAAQ,MAAM;AACrH,MAAI,CAACD,EAAM,OAAQ,QAAO;AAG1B,QAAMpC,IAAWpE;AAAA,IACfC;AAAA,IACA,MAAMuG,EAAM,IAAI,CAAC,EAAE,MAAAtF,GAAM,SAAAI,EAAA,OAAe,EAAE,MAAAJ,GAAM,GAAIqE,EAAWrE,EAAK,IAAI,EAA2B,QAAQI,GAASJ,GAAMC,CAAG,IAAI;AAAA,IACjIqF,EAAM,QAAQ,CAACC,MAAMA,EAAE,OAAO;AAAA,EAAA,EAC9B,OAAO,CAACA,MAA8C,CAAC,CAACA,EAAE,CAAC;AAC7D,MAAI,CAACrC,EAAS,OAAQ,QAAO;AAE7B,QAAMsC,IAAMP,EAAK,WAAW;AAC5B,EAAA/B,EAAS,QAAQ,CAAC,EAAE,MAAAlD,GAAM,GAAAkB,EAAA,GAAKS,MAAM;AACnC,UAAMqB,IAAShD,EAAK,OAAO2B,MAAM,IAAKsD,EAAK,SAAS,IAAKO,MAAQ,IAAI,MAAM,IAAIA,CAAG,KAC5EC,IAAQxF,EAAI,MAAA;AAClB,IAAAiB,EAAE,MAAMuE,CAAK,GACbL,EAAO,IAAIK,GAAOnB,EAAUtB,GAAIhD,EAAK,SAAS,CAAC,CAAC;AAAA,EAClD,CAAC,GACDmF,EAAA;AAEA,MAAIO,IAAW,IACXC,IAAQ;AACZ,QAAMC,IAAUjG,EAAA;AAChB,EAAIiG,MACFR,EAAO,SAAS,CAAC,GACjBS,EAAA;AAGF,QAAMjC,IAAQ,MAAM;AAClB,IAAI8B,KAAYE,MAChB7G,EAAK,UAAU,IAAI,QAAQ,GAC3BqG,EAAO,KAAK,CAAC;AAAA,EACf;AACA,SAAO;AAAA,IACL,UAAUA;AAAA,IACV,QAAQ;AAAE,mBAAaO,CAAK,GAAGP,EAAO,MAAA;AAAA,IAAS;AAAA,IAC/C,SAAS;AAAE,MAAI,CAACM,KAAY,CAACE,MAAW7G,EAAK,UAAU,IAAI,QAAQ,GAAGqG,EAAO,KAAA;AAAA,IAAU;AAAA,IACvF,OAAO;AACL,UAAIM,KAAYE,EAAS;AACzB,YAAME,IAAO/G,EAAK,cAAA,EAAgB,KAAK,CAAC8B,MAAMA,aAAa,gBAAgBA,EAAE,kBAAkB,MAAM;AACrG,MAAIiF,IAAMA,EAAK,SAAS,KAAKlC,GAAO,MAAM;AAAA,MAAC,CAAC,IACvCA,EAAA;AAAA,IACP;AAAA,IACA,OAAOmC,IAAU,GAAG;AAClB,MAAIL,KAAYE,MAChB,aAAaD,CAAK,GAClBP,EAAO,MAAM,CAAC,GACdO,IAAQ,OAAO,WAAW/B,GAAOmC,CAAO;AAAA,IAC1C;AAAA,IACA,KAAK7E,GAAG;AACN,MAAIwE,MACJ,aAAaC,CAAK,GAClBP,EAAO,MAAA,GACPA,EAAO,SAAS,KAAK,IAAI,GAAG,KAAK,IAAI,GAAGlE,CAAC,CAAC,CAAC;AAAA,IAC7C;AAAA,IACA,SAAS;AACP,MAAIwE,MACJ,aAAaC,CAAK,GAClBP,EAAO,MAAA,GACPA,EAAO,SAAS,CAAC,GACjBS,EAAA,GACA9G,EAAK,UAAU,OAAO,QAAQ;AAAA,IAChC;AAAA,IACA,UAAU;AACR,UAAI,CAAA2G,GACJ;AAAA,QAAAA,IAAW,IACX,aAAaC,CAAK,GAClBP,EAAO,KAAA;AACP,mBAAW,EAAE,GAAAlE,EAAA,KAAOgC,KAAY,QAAA;AAChC,QAAAnE,EAAK,UAAU,OAAO,QAAQ;AAAA;AAAA,IAChC;AAAA,EAAA;AAEJ;"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { CompositionNode } from './model';
|
|
2
|
+
export declare function safeAttributes(attributes?: Record<string, string>): Record<string, string>;
|
|
3
|
+
/** Capture generator output before motion; not a snapshot of an animated card. */
|
|
4
|
+
export declare function describeNode(node: Node, prefix?: string, counter?: {
|
|
5
|
+
n: number;
|
|
6
|
+
}): CompositionNode;
|
|
7
|
+
export declare function materializeNode(node: CompositionNode, scope: string): Node;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface PhotoMeta {
|
|
2
|
+
id: string;
|
|
3
|
+
w: number;
|
|
4
|
+
h: number;
|
|
5
|
+
/** Crop focus, 0..1 of the image. */
|
|
6
|
+
focus: [number, number];
|
|
7
|
+
captions: string[];
|
|
8
|
+
}
|
|
9
|
+
export type Grade = 'none' | 'bw' | 'sepia' | 'faded' | 'instant' | 'warm' | 'expired';
|
|
10
|
+
export interface PhotoSpec {
|
|
11
|
+
id: string;
|
|
12
|
+
grade?: Grade;
|
|
13
|
+
/** 0..1 */
|
|
14
|
+
vignette?: number;
|
|
15
|
+
/** 0..1 */
|
|
16
|
+
grain?: number;
|
|
17
|
+
/** Light leak from one edge. */
|
|
18
|
+
leak?: boolean;
|
|
19
|
+
/** Orange LCD date stamp in the corner ("'98 7 14"). */
|
|
20
|
+
stamp?: string;
|
|
21
|
+
/** Colour halftone screen (newsprint, magazines). */
|
|
22
|
+
halftone?: boolean;
|
|
23
|
+
/** Extra crop zoom (>= 1). */
|
|
24
|
+
zoom?: number;
|
|
25
|
+
seed?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface Box {
|
|
28
|
+
x: number;
|
|
29
|
+
y: number;
|
|
30
|
+
w: number;
|
|
31
|
+
h: number;
|
|
32
|
+
}
|
|
33
|
+
export declare const photoSpecs: WeakMap<HTMLCanvasElement, PhotoSpec>;
|
|
34
|
+
export declare function photoLater(spec: PhotoSpec, box: Box, cls?: string, style?: string): HTMLCanvasElement;
|
|
35
|
+
export declare function createPhotoRenderer(metadata: (id: string) => Pick<PhotoMeta, 'focus'>, url: (id: string) => string | Promise<string>, ratio?: () => number): {
|
|
36
|
+
renderPhoto: (spec: PhotoSpec, w: number, h: number, k: number) => HTMLCanvasElement;
|
|
37
|
+
preloadPhotos: (specs: PhotoSpec[]) => Promise<void>;
|
|
38
|
+
runPhotos: (root: HTMLElement) => Promise<void>;
|
|
39
|
+
loadPhoto: (id: string) => Promise<HTMLImageElement>;
|
|
40
|
+
dispose(): void;
|
|
41
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type PropKind = 'pushpin' | 'mappin' | 'thumbtack' | 'magnet' | 'magnet-neo' | 'magnet-bar' | 'binder' | 'paperclip' | 'staple' | 'pencil' | 'ruler' | 'eraser' | 'tape-roll' | 'mug' | 'knife' | 'washi-roll' | 'eyelet';
|
|
2
|
+
/** [footprint radius, max height] in CSS px. */
|
|
3
|
+
export declare const EXTENT: Record<PropKind, [number, number]>;
|
|
4
|
+
export interface PropSpec {
|
|
5
|
+
kind: PropKind;
|
|
6
|
+
color?: string;
|
|
7
|
+
color2?: string;
|
|
8
|
+
/** Rotation in degrees (clockwise on screen). */
|
|
9
|
+
angle?: number;
|
|
10
|
+
/** Paper clip: 'front' = the loop on top of the paper, 'back' = the rest. */
|
|
11
|
+
part?: 'all' | 'front' | 'back';
|
|
12
|
+
/** Light direction in the sprite's frame (degrees, same convention as paper `lighting.azimuth`). */
|
|
13
|
+
azimuth?: number;
|
|
14
|
+
elevation?: number;
|
|
15
|
+
seed?: number;
|
|
16
|
+
/** Pencil / ruler / knife length (CSS px). */
|
|
17
|
+
length?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface Sprite {
|
|
20
|
+
canvas: HTMLCanvasElement;
|
|
21
|
+
/** CSS size of the sprite. */
|
|
22
|
+
w: number;
|
|
23
|
+
h: number;
|
|
24
|
+
/** Where the prop's origin sits inside the sprite (CSS px). */
|
|
25
|
+
ox: number;
|
|
26
|
+
oy: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function createPropRenderer(): {
|
|
29
|
+
renderProp: (spec: PropSpec, dpr: number) => Sprite;
|
|
30
|
+
dispose(): void;
|
|
31
|
+
};
|
|
32
|
+
export declare const renderProp: ReturnType<typeof createPropRenderer>['renderProp'];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type CSSProperties } from 'react';
|
|
2
|
+
import { type CompositionHandle, type CompositionOptions } from './index';
|
|
3
|
+
export interface PaperCompositionProps extends CompositionOptions {
|
|
4
|
+
className?: string;
|
|
5
|
+
style?: CSSProperties;
|
|
6
|
+
onReady?: () => void;
|
|
7
|
+
onError?: (error: unknown) => void;
|
|
8
|
+
}
|
|
9
|
+
export type PaperCompositionRef = Pick<CompositionHandle, 'play' | 'pause' | 'replay' | 'seek'>;
|
|
10
|
+
export declare const PaperComposition: import("react").ForwardRefExoticComponent<PaperCompositionProps & import("react").RefAttributes<PaperCompositionRef>>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { forwardRef as l, useRef as o, useImperativeHandle as s, useEffect as m, createElement as f } from "react";
|
|
3
|
+
import { createPaperComposition as d } from "./index.js";
|
|
4
|
+
const p = l(function(e, i) {
|
|
5
|
+
const c = o(null), t = o(void 0), n = o(e);
|
|
6
|
+
return n.current = e, s(i, () => ({ play: () => t.current?.play(), pause: () => t.current?.pause(), replay: () => t.current?.replay(), seek: (r) => t.current?.seek(r) }), []), m(() => {
|
|
7
|
+
const r = d(e);
|
|
8
|
+
t.current = r, c.current.append(r.element);
|
|
9
|
+
let a = !0;
|
|
10
|
+
return r.ready.then(() => {
|
|
11
|
+
a && n.current.onReady?.();
|
|
12
|
+
}, (u) => {
|
|
13
|
+
a && n.current.onError?.(u);
|
|
14
|
+
}), () => {
|
|
15
|
+
a = !1, r.dispose(), t.current = void 0;
|
|
16
|
+
};
|
|
17
|
+
}, [e.composition, e.resolveAsset, e.autoplay, e.fit, e.renderer]), f("div", { ref: c, className: e.className, style: e.style, "aria-label": e.composition.info.kind });
|
|
18
|
+
});
|
|
19
|
+
export {
|
|
20
|
+
p as PaperComposition
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=react.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"react.js","sources":["../../src/composition/react.ts"],"sourcesContent":["// The build preserves this entry as a client boundary.\nimport { createElement, forwardRef, useEffect, useImperativeHandle, useRef, type CSSProperties } from 'react';\nimport { createPaperComposition, type CompositionHandle, type CompositionOptions } from './index';\nexport interface PaperCompositionProps extends CompositionOptions {\n className?: string; style?: CSSProperties; onReady?: () => void; onError?: (error: unknown) => void;\n}\nexport type PaperCompositionRef = Pick<CompositionHandle, 'play' | 'pause' | 'replay' | 'seek'>;\nexport const PaperComposition = forwardRef<PaperCompositionRef, PaperCompositionProps>(function PaperComposition(props, ref) {\n const host = useRef<HTMLDivElement>(null), component = useRef<CompositionHandle | undefined>(undefined);\n const callbacks = useRef(props); callbacks.current = props;\n useImperativeHandle(ref, () => ({ play: () => component.current?.play(), pause: () => component.current?.pause(), replay: () => component.current?.replay(), seek: p => component.current?.seek(p) }), []);\n useEffect(() => {\n const value = createPaperComposition(props); component.current = value; host.current!.append(value.element);\n let mounted = true;\n value.ready.then(() => { if (mounted) callbacks.current.onReady?.(); }, error => { if (mounted) callbacks.current.onError?.(error); });\n return () => { mounted = false; value.dispose(); component.current = undefined; };\n }, [props.composition, props.resolveAsset, props.autoplay, props.fit, props.renderer]);\n return createElement('div', { ref: host, className: props.className, style: props.style, 'aria-label': props.composition.info.kind });\n});\n"],"names":["PaperComposition","forwardRef","props","ref","host","useRef","component","callbacks","useImperativeHandle","p","useEffect","value","createPaperComposition","mounted","error","createElement"],"mappings":";;;AAOO,MAAMA,IAAmBC,EAAuD,SAA0BC,GAAOC,GAAK;AAC3H,QAAMC,IAAOC,EAAuB,IAAI,GAAGC,IAAYD,EAAsC,MAAS,GAChGE,IAAYF,EAAOH,CAAK;AAAG,SAAAK,EAAU,UAAUL,GACrDM,EAAoBL,GAAK,OAAO,EAAE,MAAM,MAAMG,EAAU,SAAS,KAAA,GAAQ,OAAO,MAAMA,EAAU,SAAS,MAAA,GAAS,QAAQ,MAAMA,EAAU,SAAS,OAAA,GAAU,MAAM,CAAAG,MAAKH,EAAU,SAAS,KAAKG,CAAC,EAAA,IAAM,CAAA,CAAE,GACzMC,EAAU,MAAM;AACd,UAAMC,IAAQC,EAAuBV,CAAK;AAAG,IAAAI,EAAU,UAAUK,GAAOP,EAAK,QAAS,OAAOO,EAAM,OAAO;AAC1G,QAAIE,IAAU;AACd,WAAAF,EAAM,MAAM,KAAK,MAAM;AAAE,MAAIE,KAASN,EAAU,QAAQ,UAAA;AAAA,IAAa,GAAG,CAAAO,MAAS;AAAE,MAAID,KAASN,EAAU,QAAQ,UAAUO,CAAK;AAAA,IAAG,CAAC,GAC9H,MAAM;AAAE,MAAAD,IAAU,IAAOF,EAAM,QAAA,GAAWL,EAAU,UAAU;AAAA,IAAW;AAAA,EAClF,GAAG,CAACJ,EAAM,aAAaA,EAAM,cAAcA,EAAM,UAAUA,EAAM,KAAKA,EAAM,QAAQ,CAAC,GAC9Ea,EAAc,OAAO,EAAE,KAAKX,GAAM,WAAWF,EAAM,WAAW,OAAOA,EAAM,OAAO,cAAcA,EAAM,YAAY,KAAK,MAAM;AACtI,CAAC;"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turns card plans into DOM + pixels. Every sheet and prop is rendered with
|
|
3
|
+
* the light expressed in its own (rotated) frame, so after CSS rotation all
|
|
4
|
+
* shadows on the desk fall the same way.
|
|
5
|
+
*
|
|
6
|
+
* .card positioned + rotated (peel.ts owns the transform)
|
|
7
|
+
* .shadow cast shadow: contact canvas + pre-blurred lifted canvas
|
|
8
|
+
* .back attachments under the paper (paper-clip loop, tag string)
|
|
9
|
+
* .paper (isolated) base canvas · ink (masked to the sheet) · shade canvas (hard-light) · sheen
|
|
10
|
+
* .front pins, magnets, tape, clips
|
|
11
|
+
*/
|
|
12
|
+
import { mergeParams, type PaperParams } from '../index';
|
|
13
|
+
import type { CardPlan } from './scene';
|
|
14
|
+
import { PaperRenderer } from '../index';
|
|
15
|
+
import { type PropSpec } from './props';
|
|
16
|
+
import type { createPhotoRenderer } from './photos';
|
|
17
|
+
export type HolderKind = 'free' | 'adhesive' | 'taped' | 'pinned' | 'magnetic' | 'hung';
|
|
18
|
+
export interface HolderPoint {
|
|
19
|
+
/** Card-local position (px). */
|
|
20
|
+
x: number;
|
|
21
|
+
y: number;
|
|
22
|
+
/** The attachment's sprite, if it has one of its own. */
|
|
23
|
+
el?: HTMLElement;
|
|
24
|
+
/** Tape: on-card angle and length. */
|
|
25
|
+
angle?: number;
|
|
26
|
+
len?: number;
|
|
27
|
+
}
|
|
28
|
+
export interface Holder {
|
|
29
|
+
kind: HolderKind;
|
|
30
|
+
points: HolderPoint[];
|
|
31
|
+
}
|
|
32
|
+
export type Thickness = 'thin' | 'normal' | 'thick';
|
|
33
|
+
export interface BuiltCard {
|
|
34
|
+
el: HTMLElement;
|
|
35
|
+
paper: HTMLElement;
|
|
36
|
+
/** Cast shadow layer (moves on its own when the card is lifted). */
|
|
37
|
+
shadow: HTMLElement;
|
|
38
|
+
/** Highlight gradient for the peel curl (opacity 0 at rest). */
|
|
39
|
+
sheen: HTMLElement;
|
|
40
|
+
holder: Holder;
|
|
41
|
+
thickness: Thickness;
|
|
42
|
+
/** Bendable copy of the layers for the pickup curl (built on first grab, dropped on re-render). */
|
|
43
|
+
copy: Promise<HTMLElement> | null;
|
|
44
|
+
/** On-screen rotation the pixels were lit for (null until rendered). */
|
|
45
|
+
litFor: number | null;
|
|
46
|
+
/** Render (or re-render) for an on-screen rotation; defaults to the plan's. */
|
|
47
|
+
render(angle?: number): Promise<void>;
|
|
48
|
+
}
|
|
49
|
+
export interface BuiltProp {
|
|
50
|
+
el: HTMLElement;
|
|
51
|
+
ox: number;
|
|
52
|
+
oy: number;
|
|
53
|
+
w: number;
|
|
54
|
+
h: number;
|
|
55
|
+
/** Soft shadow for when the prop is lifted (hidden at rest). */
|
|
56
|
+
shadow: HTMLElement;
|
|
57
|
+
/** Physical height (CSS px): how far it has to be lifted, how heavy it feels. */
|
|
58
|
+
height: number;
|
|
59
|
+
}
|
|
60
|
+
export declare function createSceneRenderer(options: {
|
|
61
|
+
renderer: PaperRenderer;
|
|
62
|
+
light: {
|
|
63
|
+
azimuth: number;
|
|
64
|
+
elevation: number;
|
|
65
|
+
};
|
|
66
|
+
grain: () => number;
|
|
67
|
+
photos: ReturnType<typeof createPhotoRenderer>;
|
|
68
|
+
pixelRatio?: () => number;
|
|
69
|
+
onPrepared?: (plan: CardPlan, built: BuiltCard, angle: number) => void;
|
|
70
|
+
}): {
|
|
71
|
+
buildCard: (plan: CardPlan) => BuiltCard;
|
|
72
|
+
buildProp: (spec: PropSpec) => BuiltProp;
|
|
73
|
+
shadowDir: () => [number, number];
|
|
74
|
+
grainParams: (key: string, overrides?: Parameters<typeof mergeParams>[1]) => PaperParams;
|
|
75
|
+
dpr: () => number;
|
|
76
|
+
dispose(): void;
|
|
77
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Small seeded PRNG (mulberry32) with helpers. */
|
|
2
|
+
export interface Rng {
|
|
3
|
+
(): number;
|
|
4
|
+
range(a: number, b: number): number;
|
|
5
|
+
int(a: number, b: number): number;
|
|
6
|
+
pick<T>(a: readonly T[]): T;
|
|
7
|
+
chance(p: number): boolean;
|
|
8
|
+
weighted<T>(items: readonly T[], weight: (t: T) => number): T;
|
|
9
|
+
fork(): Rng;
|
|
10
|
+
}
|
|
11
|
+
export declare function makeRng(seed: number): Rng;
|