@pixerate/flair 0.28.0 → 0.29.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/CHANGELOG.md +13 -0
- package/README.md +48 -6
- package/dist/catalog/index.d.ts +11 -6
- package/dist/catalog/index.js +1 -1
- package/dist/{chunk-4LKAPRFM.js → chunk-6GFOLHCT.js} +920 -34
- package/dist/chunk-6GFOLHCT.js.map +1 -0
- package/dist/{chunk-JL6TI6II.js → chunk-7KYQ4R76.js} +2 -2
- package/dist/chunk-7KYQ4R76.js.map +1 -0
- package/dist/{chunk-STKEKXCK.js → chunk-AUH3PEFW.js} +2 -2
- package/dist/{chunk-PFGGPIMT.js → chunk-DA4UUSDO.js} +58 -3
- package/dist/chunk-DA4UUSDO.js.map +1 -0
- package/dist/{chunk-RDU63CDO.js → chunk-HDYBY3PQ.js} +380 -1
- package/dist/chunk-HDYBY3PQ.js.map +1 -0
- package/dist/{chunk-VLQLRKGW.js → chunk-KZYZX3V5.js} +260 -33
- package/dist/chunk-KZYZX3V5.js.map +1 -0
- package/dist/{chunk-GXP4YLAP.js → chunk-MBKNTXQX.js} +9 -9
- package/dist/chunk-MBKNTXQX.js.map +1 -0
- package/dist/{chunk-H6VDFBIO.js → chunk-SMR2MJXB.js} +156 -5
- package/dist/chunk-SMR2MJXB.js.map +1 -0
- package/dist/{chunk-YBGRXVAE.js → chunk-X3C2VFTM.js} +3 -3
- package/dist/{chunk-CK6EV37I.js → chunk-ZULFHADW.js} +69 -6
- package/dist/chunk-ZULFHADW.js.map +1 -0
- package/dist/cli.js +6 -6
- package/dist/editor/index.d.ts +3 -3
- package/dist/editor/index.js +3 -3
- package/dist/{effect-GGP66JI6.js → effect-YBWDNIYG.js} +10 -10
- package/dist/embed/index.d.ts +36 -8
- package/dist/embed/index.js +5 -5
- package/dist/{frames-VEcqa40g.d.ts → frames-CGJudAbu.d.ts} +11 -1
- package/dist/index.d.ts +69 -6
- package/dist/index.js +35 -7
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +4 -4
- package/dist/node.js +9 -9
- package/dist/react/index.d.ts +4 -4
- package/dist/react/index.js +7 -7
- package/dist/react/index.js.map +1 -1
- package/dist/{recorder-CDPPTJMG.js → recorder-TYMEZHOT.js} +3 -3
- package/dist/{renderer-teaa98RE.d.ts → renderer-tk1nbVkW.d.ts} +252 -2
- package/dist/svelte/index.d.ts +4 -4
- package/dist/svelte/index.js +7 -7
- package/dist/svelte/index.js.map +1 -1
- package/dist/{svg-BhRboN9q.d.ts → svg-DaKRPA9v.d.ts} +39 -7
- package/dist/{types-DUOMxZaq.d.ts → types-wh28fXW4.d.ts} +2 -2
- package/dist/vector/index.d.ts +2 -2
- package/dist/vector/index.js +5 -3
- package/package.json +1 -1
- package/dist/chunk-4LKAPRFM.js.map +0 -1
- package/dist/chunk-CK6EV37I.js.map +0 -1
- package/dist/chunk-GXP4YLAP.js.map +0 -1
- package/dist/chunk-H6VDFBIO.js.map +0 -1
- package/dist/chunk-JL6TI6II.js.map +0 -1
- package/dist/chunk-PFGGPIMT.js.map +0 -1
- package/dist/chunk-RDU63CDO.js.map +0 -1
- package/dist/chunk-VLQLRKGW.js.map +0 -1
- /package/dist/{chunk-STKEKXCK.js.map → chunk-AUH3PEFW.js.map} +0 -0
- /package/dist/{chunk-YBGRXVAE.js.map → chunk-X3C2VFTM.js.map} +0 -0
- /package/dist/{effect-GGP66JI6.js.map → effect-YBWDNIYG.js.map} +0 -0
- /package/dist/{recorder-CDPPTJMG.js.map → recorder-TYMEZHOT.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vector/motion.ts","../src/vector/svg.ts"],"sourcesContent":["/**\n * Vector motion: animated SVG pictures described as data. A picture changes in\n * steps (step 0 when it starts, step n at `steps[n - 1]` ms), and everything\n * here is a pure function of its arguments, so a frame comes out the same\n * however it is reached (played, stepped for a recording, or seeked).\n */\n\n/** Easing curves by name. */\nexport const EASES = {\n linear: (t: number) => t,\n \"in-out\": (t: number) => (t < 0.5 ? 4 * t * t * t : 1 - (-2 * t + 2) ** 3 / 2),\n out: (t: number) => 1 - (1 - t) ** 3,\n} as const;\n\nexport type EaseName = keyof typeof EASES;\n\n/** How long a change takes by default, in ms. */\nexport const STEP_MS = 800;\n\nconst clamp01 = (t: number) => (t < 0 ? 0 : t > 1 ? 1 : t);\n\n/**\n * When `step` starts, in ms since the media started (step 0 at 0, step n at\n * `steps[n - 1]`), or undefined if it has not started yet.\n */\nexport function stepStart(steps: readonly number[], step: number): number | undefined {\n if (step <= 0) return 0;\n return steps[step - 1];\n}\n\n/**\n * How far a change that plays on `step` (after `delay` ms, over `ms`) has\n * got at `timeMs`, eased: 0 before it starts, 1 once it is over.\n */\nexport function stepProgress(\n steps: readonly number[],\n timeMs: number,\n step: number,\n options: { delay?: number; ms?: number; ease?: EaseName } = {},\n): number {\n const start = stepStart(steps, step);\n if (start === undefined) return 0;\n const from = start + (options.delay ?? 0);\n const ms = options.ms ?? STEP_MS;\n const t = ms > 0 ? clamp01((timeMs - from) / ms) : timeMs >= from ? 1 : 0;\n return EASES[options.ease ?? \"in-out\"](t);\n}\n\n/** The key an item in a list of data keeps from one state to the next. */\nexport type DataKey = (item: unknown, index: number) => string;\n\n/**\n * Keys items by their `id`, `key`, `name` or `label` (or a link's `source`\n * and `target`), else by position.\n */\nexport const defaultDataKey: DataKey = (item, index) => {\n if (item && typeof item === \"object\") {\n const o = item as Record<string, unknown>;\n if (o.source !== undefined && o.target !== undefined)\n return `${String(o.source)}→${String(o.target)}`;\n for (const k of [\"id\", \"key\", \"name\", \"label\"])\n if (typeof o[k] === \"string\" || typeof o[k] === \"number\") return String(o[k]);\n }\n return String(index);\n};\n\n/** Every number in `value` times `k`, so an item can grow from or shrink to nothing. */\nfunction scaled(value: unknown, k: number): unknown {\n if (typeof value === \"number\") return value * k;\n if (Array.isArray(value)) return value.map((v) => scaled(v, k));\n if (value && typeof value === \"object\")\n return Object.fromEntries(Object.entries(value).map(([key, v]) => [key, scaled(v, k)]));\n return value;\n}\n\n/**\n * Data between two states, `u` of the way from `a` to `b`. Numbers blend;\n * lists match their items by key (`keyOf`), so each keeps its identity and\n * moves rather than jumping, with items only in `b` growing from nothing and\n * items only in `a` shrinking away; objects blend field by field; anything\n * else changes halfway.\n */\nexport function lerpData<D>(a: D, b: D, u: number, keyOf: DataKey = defaultDataKey): D {\n if (u <= 0) return a;\n if (u >= 1) return b;\n return blend(a, b, u, keyOf) as D;\n}\n\nfunction blend(a: unknown, b: unknown, u: number, keyOf: DataKey): unknown {\n if (typeof a === \"number\" && typeof b === \"number\") return a + (b - a) * u;\n if (Array.isArray(a) && Array.isArray(b)) {\n const before = new Map(a.map((item, i) => [keyOf(item, i), item]));\n const after = new Set(b.map((item, i) => keyOf(item, i)));\n const out: unknown[] = b.map((item, i) => {\n const key = keyOf(item, i);\n return before.has(key) ? blend(before.get(key), item, u, keyOf) : scaled(item, u);\n });\n a.forEach((item, i) => {\n if (!after.has(keyOf(item, i))) out.push(scaled(item, 1 - u));\n });\n return out;\n }\n if (a && b && typeof a === \"object\" && typeof b === \"object\") {\n const ao = a as Record<string, unknown>;\n const bo = b as Record<string, unknown>;\n return Object.fromEntries(\n [...new Set([...Object.keys(ao), ...Object.keys(bo)])].map((k) => [\n k,\n k in ao && k in bo\n ? blend(ao[k], bo[k], u, keyOf)\n : k in bo\n ? scaled(bo[k], u)\n : scaled(ao[k], 1 - u),\n ]),\n );\n }\n return u < 0.5 ? a : b;\n}\n\n/**\n * The data to show at `timeMs`, for media whose data has a state per step:\n * `states[n]` is shown from step n (the last one stays), reached by moving\n * from the state before it over `ms`.\n */\nexport function stepData<D>(\n states: readonly D[],\n steps: readonly number[],\n timeMs: number,\n options: { ms?: number; ease?: EaseName; keyOf?: DataKey } = {},\n): D {\n const last = Math.min(steps.length, states.length - 1);\n const to = states[last]!;\n if (last === 0) return to;\n const u = stepProgress(steps, timeMs, last, options);\n return lerpData(states[last - 1]!, to, u, options.keyOf);\n}\n\n// ── SVG media ──────────────────────────────────────────────────────────\n\n/**\n * An animated SVG picture: markup plus changes to its elements. Draw it with\n * `SvgPlayer` (or `svgView`), or compute frames yourself with `svgFrame`.\n */\nexport interface SvgMotion {\n /** One self-contained `<svg>` with a `viewBox`: no scripts, no outside links. */\n svg: string;\n /** Changes to its elements, each on a step. */\n animate?: SvgAnimation[];\n}\n\n/** A box in an SVG's `viewBox` units: `[x, y, width, height]`. */\nexport type SvgBox = readonly [number, number, number, number];\n\n/** A change to one element of an {@link SvgMotion}, or (with `view`) to the whole picture. */\nexport interface SvgAnimation {\n /** The element's `id` in the SVG (not needed for `view`). */\n id?: string;\n /** The step it plays on: 0 (default) when the media starts, 1 with the next shot, and so on. */\n step?: number;\n /** Ms after the step starts. */\n delay?: number;\n /** How long it takes, in ms (default {@link STEP_MS}). */\n ms?: number;\n ease?: EaseName;\n /**\n * Attributes from one value to another: numbers, colours (`#rrggbb`), or\n * strings whose numbers change while the rest stays the same (a path's\n * `d`, a `transform`, `points`).\n */\n attrs?: Record<string, readonly [string | number, string | number]>;\n /** Draws a line or outline on along its length, from 0 to 1 (or between two fractions). */\n draw?: boolean | readonly [number, number];\n /**\n * Zooms and pans the whole picture to frame a box (`[x, y, width, height]`\n * in the `viewBox`'s units) or an element by id (with a margin round it),\n * from where the last `view` left it (at first, the whole `viewBox`).\n */\n view?: SvgBox | string;\n /**\n * Moves the element along a path (by id) from its start to its end, or\n * between the fractions in `at`; draw the element round (0, 0), like a\n * circle at `cx=\"0\" cy=\"0\"`.\n */\n along?: string;\n /** How far along the path `along` moves the element, from and to (default [0, 1]). */\n at?: readonly [number, number];\n /**\n * Sets the active child index in a solo container (data-solo group or element with multiple children).\n * Hides all siblings except the one at this index (0-based).\n */\n solo?: number;\n /** Counts the element's text from one number to the other. */\n count?: readonly [number, number];\n /** How a count is written: `{n}` stands for the number (\"{n}%\", \"$ {n}M\"). */\n format?: string;\n /** Decimals in a count (default 0). */\n decimals?: number;\n /**\n * Writes this text into the element letter by letter: none of it when the\n * change starts, all of it when it ends (a typewriter).\n */\n write?: string;\n /**\n * With `write`: letters not yet written show characters picked from this\n * string, changing every {@link SCRAMBLE_MS} ms, so the text decodes\n * rather than types. The same time always picks the same characters.\n */\n scramble?: string;\n /** With `write`: shown after the written letters while it writes (\"▌\", \"|\"). */\n caret?: string;\n}\n\n/** How often scrambled letters change, in ms (see `SvgAnimation.scramble`). */\nexport const SCRAMBLE_MS = 50;\n\n/**\n * `text` with `u` (0–1) of its letters written (see `SvgAnimation.write`):\n * the rest scrambled from `scramble` (picked by `timeMs`) or left off, then\n * the caret while it is unfinished. Letters are code points, so emoji and\n * accents are never split.\n */\nexport function writtenText(\n text: string,\n u: number,\n options: { scramble?: string; caret?: string; timeMs?: number } = {},\n): string {\n const letters = Array.from(text);\n const shown = Math.round(clamp01(u) * letters.length);\n let out = letters.slice(0, shown).join(\"\");\n const pool = Array.from(options.scramble ?? \"\");\n if (pool.length) {\n const tick = Math.floor((options.timeMs ?? 0) / SCRAMBLE_MS);\n for (let i = shown; i < letters.length; i++)\n out += /\\s/.test(letters[i]!) ? letters[i] : pool[Math.floor(noise(i, tick) * pool.length)];\n }\n return shown < letters.length && options.caret ? out + options.caret : out;\n}\n\n/** A repeatable 0–1 number for a letter at a tick. */\nfunction noise(i: number, tick: number): number {\n const x = Math.sin(i * 127.1 + tick * 311.7) * 43758.5453;\n return x - Math.floor(x);\n}\n\n/** What one element of an animated SVG shows at a time. */\nexport interface SvgElementFrame {\n attrs: Record<string, string>;\n /** How much of its length is drawn, 0–1. */\n draw?: number;\n text?: string;\n /** Active child index when targeting a solo container. */\n solo?: number;\n /** Where it is along a path: the path's id and the fraction of its length. */\n along?: { path: string; at: number };\n /**\n * The whole picture's framing (on the frame for {@link SVG_PICTURE}): `u`\n * of the way from one view to the next, `null` being the whole `viewBox`.\n */\n view?: { from: SvgBox | string | null; to: SvgBox | string; u: number };\n}\n\n/** The key of the whole picture's frame in {@link svgFrame}'s result (for `view`). */\nexport const SVG_PICTURE = \"\";\n\nconst NUMBER = /-?(?:\\d+\\.?\\d*|\\.\\d+)(?:e[-+]?\\d+)?/gi;\nconst HEX = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i;\n\nfunction rgb(hex: string): [number, number, number] {\n let h = hex.slice(1);\n if (h.length === 3) h = [...h].map((c) => c + c).join(\"\");\n return [0, 2, 4].map((i) => parseInt(h.slice(i, i + 2), 16)) as [number, number, number];\n}\n\nconst round = (n: number) => Math.round(n * 1000) / 1000;\n\n/** A value `u` of the way between two attribute values (see `SvgAnimation.attrs`). */\nexport function lerpAttr(a: string | number, b: string | number, u: number): string {\n if (typeof a === \"number\" && typeof b === \"number\") return String(round(a + (b - a) * u));\n const sa = String(a);\n const sb = String(b);\n if (HEX.test(sa) && HEX.test(sb)) {\n const [ca, cb] = [rgb(sa), rgb(sb)];\n return `#${ca\n .map((c, i) =>\n Math.round(c + (cb[i]! - c) * u)\n .toString(16)\n .padStart(2, \"0\"),\n )\n .join(\"\")}`;\n }\n const na = sa.match(NUMBER) ?? [];\n const nb = sb.match(NUMBER) ?? [];\n if (na.length && na.length === nb.length && sa.replace(NUMBER, \"#\") === sb.replace(NUMBER, \"#\")) {\n let i = 0;\n return sa.replace(NUMBER, () => {\n const v = Number(na[i]) + (Number(nb[i]) - Number(na[i])) * u;\n i++;\n return String(round(v));\n });\n }\n return u < 0.5 ? sa : sb;\n}\n\n/** Formats a number for a count animation (`{n}` stands for the rounded number). */\nexport function formatCount(\n value: number,\n options: { decimals?: number; format?: string } = {},\n): string {\n const n = value.toFixed(options.decimals ?? 0);\n return (options.format ?? \"{n}\").replace(\"{n}\", n);\n}\n\nconst startOf = (a: SvgAnimation, steps: readonly number[]) => {\n const s = stepStart(steps, a.step ?? 0);\n return s === undefined ? Infinity : s + (a.delay ?? 0);\n};\n\n/**\n * What each animated element shows at `timeMs`. For each attribute (or\n * line, count or writing) the latest change to have started wins; before the first\n * one starts, the element shows that change's starting value, so something\n * that grows in later is hidden until then.\n */\nexport function svgFrame(\n animations: readonly SvgAnimation[],\n steps: readonly number[],\n timeMs: number,\n): Map<string, SvgElementFrame> {\n // Each property's changes in the order they start (ties: list order).\n const tracks = new Map<string, { anim: SvgAnimation; start: number; index: number }[]>();\n const add = (prop: string, anim: SvgAnimation, index: number) => {\n const key = `${prop === \"view\" ? SVG_PICTURE : anim.id}\\u0000${prop}`;\n const list = tracks.get(key) ?? [];\n list.push({ anim, start: startOf(anim, steps), index });\n tracks.set(key, list);\n };\n animations.forEach((a, i) => {\n for (const name of Object.keys(a.attrs ?? {})) add(`@${name}`, a, i);\n if (a.draw) add(\"draw\", a, i);\n if (a.count) add(\"count\", a, i);\n if (a.write !== undefined) add(\"count\", a, i);\n if (a.solo !== undefined) add(\"solo\", a, i);\n if (a.view !== undefined) add(\"view\", a, i);\n if (a.along) add(\"along\", a, i);\n });\n const frames = new Map<string, SvgElementFrame>();\n for (const [key, list] of tracks) {\n list.sort((x, y) => x.start - y.start || x.index - y.index);\n const [id, prop] = key.split(\"\\u0000\") as [string, string];\n const started = list.filter((c) => c.start <= timeMs);\n const current = started[started.length - 1];\n const anim = (current ?? list[0]!).anim;\n const u = current\n ? stepProgress(steps, timeMs, anim.step ?? 0, {\n delay: anim.delay,\n ms: anim.ms,\n ease: anim.ease,\n })\n : 0;\n const frame = frames.get(id) ?? { attrs: {} };\n if (prop === \"view\") {\n // From where the change before it left the picture.\n const before = current ? list[list.indexOf(current) - 1] : undefined;\n frame.view = { from: before?.anim.view ?? null, to: anim.view!, u };\n } else if (prop === \"along\") {\n const [a, b] = anim.at ?? [0, 1];\n frame.along = { path: anim.along!, at: a + (b - a) * u };\n } else if (prop === \"solo\") {\n frame.solo = anim.solo;\n } else if (prop.startsWith(\"@\")) {\n const [a, b] = anim.attrs![prop.slice(1)]!;\n frame.attrs[prop.slice(1)] = lerpAttr(a, b, u);\n } else if (prop === \"draw\") {\n const [a, b] = anim.draw === true ? [0, 1] : (anim.draw as readonly [number, number]);\n frame.draw = a + (b - a) * u;\n } else if (anim.write !== undefined) {\n frame.text = writtenText(anim.write, u, { scramble: anim.scramble, caret: anim.caret, timeMs });\n } else {\n const [a, b] = anim.count!;\n frame.text = formatCount(a + (b - a) * u, anim);\n }\n frames.set(id, frame);\n }\n return frames;\n}\n\n/**\n * The opening tag of the root element at the start of `markup` (up to its\n * first `>`), cut out without a regular expression, so checks on it stay\n * linear however long or odd the markup is.\n */\nexport function svgOpeningTag(markup: string): string {\n const end = markup.indexOf(\">\");\n return end < 0 ? markup : markup.slice(0, end + 1);\n}\n\n/** Problems with an {@link SvgMotion}, as sentences; none when it can be drawn. */\nexport function svgMotionIssues(motion: unknown): string[] {\n const issues: string[] = [];\n const m = (motion ?? {}) as Partial<SvgMotion>;\n const svg = typeof m.svg === \"string\" ? m.svg.trim() : \"\";\n if (!svg) return [\"`svg` needs the picture's markup: one <svg> element\"];\n if (!/^<svg[\\s>]/i.test(svg) || !svg.toLowerCase().endsWith(\"</svg>\"))\n issues.push(\"`svg` must be one <svg>…</svg> element\");\n if (!/\\sviewBox\\s*=/i.test(svgOpeningTag(svg)))\n issues.push(\"the <svg> needs a `viewBox`, so it scales to where it is placed\");\n if (/<script|<foreignObject|\\son\\w+\\s*=/i.test(svg))\n issues.push(\"`svg` cannot have scripts, event handlers or <foreignObject>\");\n if (/<(animate|animateTransform|animateMotion|set)[\\s/>]/i.test(svg))\n issues.push(\n \"`svg` cannot animate itself (<animate>, <animateTransform>, <animateMotion>, <set>): give changes in `animate`, so every frame is a function of time\",\n );\n if (/(?:href|src)\\s*=\\s*[\"'](?!#|data:image\\/)/i.test(svg))\n issues.push(\"`svg` cannot link outside itself (only #ids and data:image URLs)\");\n const ids = new Set([...svg.matchAll(/\\sid\\s*=\\s*[\"']([^\"']+)[\"']/g)].map((x) => x[1]));\n if (m.animate !== undefined && !Array.isArray(m.animate)) issues.push(\"`animate` must be a list\");\n (Array.isArray(m.animate) ? m.animate : []).forEach((a, i) => {\n const where = `animate[${i}]`;\n if (!a || typeof a !== \"object\") return void issues.push(`${where} is not an animation`);\n if (typeof a.id !== \"string\") {\n if (a.view === undefined) return void issues.push(`${where} needs an \\`id\\``);\n } else if (!ids.has(a.id))\n issues.push(`${where}: there is no element with id \"${a.id}\" in the SVG`);\n if (a.step !== undefined && !(Number.isInteger(a.step) && a.step >= 0))\n issues.push(`${where}: \\`step\\` is a whole number, 0 or more`);\n if (a.ms !== undefined && !(a.ms >= 0)) issues.push(`${where}: \\`ms\\` must be 0 or more`);\n if (a.delay !== undefined && !(a.delay >= 0))\n issues.push(`${where}: \\`delay\\` must be 0 or more`);\n if (a.ease !== undefined && !(a.ease in EASES))\n issues.push(`${where}: \\`ease\\` is one of ${Object.keys(EASES).join(\", \")}`);\n if (!a.attrs && !a.draw && !a.count && a.write === undefined && a.view === undefined && !a.along && a.solo === undefined)\n issues.push(\n `${where} changes nothing: give \\`attrs\\`, \\`draw\\`, \\`count\\`, \\`write\\`, \\`view\\`, \\`along\\` or \\`solo\\``,\n );\n if (a.solo !== undefined && !(Number.isInteger(a.solo) && a.solo >= 0))\n issues.push(`${where}: \\`solo\\` is an index (whole number, 0 or more)`);\n if (a.view !== undefined) {\n const box = a.view as unknown;\n if (typeof box === \"string\") {\n if (!ids.has(box))\n issues.push(`${where}: \\`view\\` frames \"${box}\", which is not an id in the SVG`);\n } else if (\n !Array.isArray(box) ||\n box.length !== 4 ||\n !box.every((n) => Number.isFinite(n)) ||\n !(box[2] > 0 && box[3] > 0)\n )\n issues.push(\n `${where}: \\`view\\` is [x, y, width, height] (width and height above 0) or an element's id`,\n );\n }\n if (a.along !== undefined) {\n if (typeof a.along !== \"string\" || !ids.has(a.along))\n issues.push(`${where}: \\`along\\` is the id of a path in the SVG`);\n if (typeof a.id !== \"string\")\n issues.push(`${where}: \\`along\\` moves an element: give its \\`id\\``);\n }\n if (\n a.at !== undefined &&\n !(Array.isArray(a.at) && a.at.length === 2 && a.at.every((v) => v >= 0 && v <= 1))\n )\n issues.push(`${where}: \\`at\\` is [from, to] between 0 and 1`);\n for (const [name, pair] of Object.entries(a.attrs ?? {}))\n if (!Array.isArray(pair) || pair.length !== 2)\n issues.push(`${where}: \\`attrs.${name}\\` is [from, to]`);\n if (Array.isArray(a.draw) && a.draw.some((v) => !(v >= 0 && v <= 1)))\n issues.push(`${where}: \\`draw\\` is true or [from, to] between 0 and 1`);\n if (a.count !== undefined && !(Array.isArray(a.count) && a.count.length === 2))\n issues.push(`${where}: \\`count\\` is [from, to]`);\n if (a.write !== undefined && typeof a.write !== \"string\")\n issues.push(`${where}: \\`write\\` is the text to write`);\n if ((a.scramble !== undefined || a.caret !== undefined) && a.write === undefined)\n issues.push(`${where}: \\`scramble\\` and \\`caret\\` go with \\`write\\``);\n });\n return issues;\n}\n","/**\n * Drawing animated SVG pictures (see `SvgMotion`) in the DOM: a sanitising\n * parser, a view that applies frames, and a player that runs on a `Clock`.\n */\n\nimport { realClock, type Clock } from \"../time/clock.js\";\nimport {\n EASES,\n formatCount,\n STEP_MS,\n SVG_PICTURE,\n svgFrame,\n svgOpeningTag,\n type EaseName,\n type SvgBox,\n type SvgMotion,\n} from \"./motion.js\";\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\n\n/**\n * The `<svg>` in `markup`, parsed and made safe to show: no scripts, event\n * handlers, `<foreignObject>` or links outside itself. Undefined when it is\n * not an SVG.\n */\nexport function parseSvg(markup: string): SVGSVGElement | undefined {\n // Parsed as XML, an <svg> without its namespace is not an SVG at all.\n let source = markup.trim();\n const open = svgOpeningTag(source);\n if (!/\\sxmlns\\s*=/i.test(open)) source = source.replace(/^<svg/i, `<svg xmlns=\"${SVG_NS}\"`);\n if (/xlink:/.test(source) && !/\\sxmlns:xlink\\s*=/i.test(open))\n source = source.replace(/^<svg/i, '<svg xmlns:xlink=\"http://www.w3.org/1999/xlink\"');\n const doc = new DOMParser().parseFromString(source, \"image/svg+xml\");\n const svg = doc.documentElement;\n if (svg.namespaceURI !== SVG_NS || svg.localName !== \"svg\" || doc.querySelector(\"parsererror\"))\n return undefined;\n for (const bad of svg.querySelectorAll(\"script, foreignObject\")) bad.remove();\n for (const el of [svg, ...svg.querySelectorAll(\"*\")]) {\n for (const attr of [...el.attributes]) {\n const name = attr.name.toLowerCase();\n const link = name === \"href\" || name === \"xlink:href\" || name === \"src\";\n if (name.startsWith(\"on\") || (link && !/^(#|data:image\\/)/i.test(attr.value.trim())))\n el.removeAttribute(attr.name);\n }\n }\n return document.importNode(svg, true) as unknown as SVGSVGElement;\n}\n\n/** Live views made so far, for ids unique on the page (see {@link scopeIds}). */\nlet views = 0;\n\nconst URL_REF = /url\\(\\s*(['\"]?)#([^'\")\\s]+)\\1\\s*\\)/g;\n\n/**\n * Gives the ids a live picture refers to (by `url(#…)` in attributes and\n * styles, or `href=\"#…\"`: its gradients, filters, clips, masks, `<use>`d\n * shapes) `suffix`, and points the references at the new ids, so two\n * pictures on one page that both define `id=\"glow\"` each use their own.\n * Other ids stay as written. The original id is kept in `data-flair-id`;\n * returns how ids map.\n */\nfunction scopeIds(svg: Element, suffix: string): Map<string, string> {\n const all = [svg, ...svg.querySelectorAll(\"*\")];\n const referred = new Set<string>();\n for (const el of all) {\n const texts = [...el.attributes].map((a) => [a.name.toLowerCase(), a.value] as const);\n if (el.localName === \"style\") texts.push([\"\", el.textContent ?? \"\"]);\n for (const [name, value] of texts) {\n if ((name === \"href\" || name === \"xlink:href\") && value.startsWith(\"#\")) referred.add(value.slice(1));\n for (const m of value.matchAll(URL_REF)) referred.add(m[2]!);\n }\n }\n const ids = new Map<string, string>();\n for (const el of all) {\n if (!el.id || !referred.has(el.id) || ids.has(el.id)) continue;\n ids.set(el.id, `${el.id}-${suffix}`);\n el.setAttribute(\"data-flair-id\", el.id);\n el.id = `${el.id}-${suffix}`;\n }\n if (ids.size)\n for (const el of [svg, ...svg.querySelectorAll(\"*\")]) {\n for (const attr of [...el.attributes]) {\n const scoped = scopedRefs(attr.value, ids, attr.name);\n if (scoped !== attr.value) attr.value = scoped;\n }\n if (el.localName === \"style\" && el.textContent) el.textContent = scopedRefs(el.textContent, ids);\n }\n return ids;\n}\n\n/** `value` with its references to ids in `ids` pointed at their scoped ids. */\nfunction scopedRefs(value: string, ids: ReadonlyMap<string, string>, attr = \"\"): string {\n const name = attr.toLowerCase();\n if (name === \"href\" || name === \"xlink:href\") {\n const to = value.startsWith(\"#\") ? ids.get(value.slice(1)) : undefined;\n return to ? `#${to}` : value;\n }\n if (!value.includes(\"url(\")) return value;\n return value.replace(URL_REF, (whole, quote: string, id: string) => {\n const to = ids.get(id);\n return to ? `url(${quote}#${to}${quote})` : whole;\n });\n}\n\n/** Share of an element's size left round it when a `view` frames it. */\nconst VIEW_MARGIN = 0.12;\n\n/**\n * The box a `view` frames, in viewBox units: a box as given, an element's\n * box with a margin, widened to the picture's shape so the zoom does not\n * skew, or the whole picture for `null`.\n */\nfunction viewBox(view: SvgBox | string | null, whole: SvgBox, byId: Map<string, Element>): SvgBox {\n if (view === null) return whole;\n if (typeof view !== \"string\") return view;\n const el = byId.get(view) as SVGGraphicsElement | undefined;\n let box: DOMRect | undefined;\n try {\n box = el?.getBBox?.();\n } catch {\n // Not laid out (or not drawable): keep the whole picture.\n }\n if (!box || !(box.width > 0 || box.height > 0)) return whole;\n // In the picture's own units: through the element's transforms (a point\n // placed with one), which its box leaves out.\n try {\n const svg = el!.ownerSVGElement;\n const m = svg?.getScreenCTM()?.inverse().multiply(el!.getScreenCTM()!);\n if (m) {\n const corners = [\n [box.x, box.y],\n [box.x + box.width, box.y],\n [box.x, box.y + box.height],\n [box.x + box.width, box.y + box.height],\n ].map(([x, y]) => new DOMPoint(x, y).matrixTransform(m));\n const xs = corners.map((p) => p.x);\n const ys = corners.map((p) => p.y);\n box = new DOMRect(\n Math.min(...xs),\n Math.min(...ys),\n Math.max(...xs) - Math.min(...xs),\n Math.max(...ys) - Math.min(...ys),\n );\n }\n } catch {\n // Not laid out: keep its own box.\n }\n const aspect = whole[2] / whole[3];\n let w = box.width * (1 + 2 * VIEW_MARGIN);\n let h = box.height * (1 + 2 * VIEW_MARGIN);\n if (w / h > aspect) h = w / aspect;\n else w = h * aspect;\n return [box.x + box.width / 2 - w / 2, box.y + box.height / 2 - h / 2, w, h];\n}\n\n/**\n * Keeps the picture's `data-nonscaling` elements (a map's pins and labels)\n * the same size on screen as a `view` zooms: each is scaled round its own\n * origin by how far the picture is zoomed (so draw it round (0, 0) inside a\n * group that places it).\n */\nfunction keepSize(svg: SVGSVGElement, whole: SvgBox, nonscaling: Element[]) {\n if (!nonscaling.length) return;\n const width = Number((svg.getAttribute(\"viewBox\") ?? \"\").trim().split(/[\\s,]+/)[2]);\n const zoom = width > 0 ? width / whole[2] : 1;\n const transform = Math.abs(zoom - 1) < 1e-4 ? \"\" : `scale(${+zoom.toFixed(4)})`;\n for (const el of nonscaling)\n if ((el.getAttribute(\"transform\") ?? \"\") !== transform)\n if (transform) el.setAttribute(\"transform\", transform);\n else el.removeAttribute(\"transform\");\n}\n\n/** Applies a frame of the media's animations to `svg`. */\nfunction apply(\n svg: SVGSVGElement,\n whole: SvgBox,\n byId: Map<string, Element>,\n motion: SvgMotion,\n timeMs: number,\n steps: readonly number[],\n ids: ReadonlyMap<string, string> = new Map(),\n) {\n for (const [id, frame] of svgFrame(motion.animate ?? [], steps, timeMs)) {\n if (id === SVG_PICTURE && frame.view) {\n const a = viewBox(frame.view.from, whole, byId);\n const b = viewBox(frame.view.to, whole, byId);\n const u = frame.view.u;\n svg.setAttribute(\"viewBox\", a.map((n, i) => +(n + (b[i]! - n) * u).toFixed(2)).join(\" \"));\n continue;\n }\n const el = byId.get(id);\n if (!el) continue;\n for (const [name, value] of Object.entries(frame.attrs)) el.setAttribute(name, scopedRefs(value, ids, name));\n if (frame.draw !== undefined) {\n // A path length of 1 lets the dash be a fraction, with nothing measured.\n el.setAttribute(\"pathLength\", \"1\");\n el.setAttribute(\"stroke-dasharray\", \"1 1\");\n el.setAttribute(\"stroke-dashoffset\", String(1 - frame.draw));\n }\n if (frame.text !== undefined) el.textContent = frame.text;\n if (frame.solo !== undefined) {\n const children = Array.from(el.children);\n children.forEach((child, idx) => {\n if (child instanceof SVGElement || child instanceof HTMLElement) {\n if (idx === frame.solo) {\n child.removeAttribute(\"display\");\n } else {\n child.setAttribute(\"display\", \"none\");\n }\n }\n });\n }\n if (frame.along) {\n const path = byId.get(frame.along.path) as SVGGeometryElement | undefined;\n try {\n const length = path?.getTotalLength?.();\n if (path && length !== undefined) {\n const p = path.getPointAtLength(frame.along.at * length);\n el.setAttribute(\"transform\", `translate(${+p.x.toFixed(2)} ${+p.y.toFixed(2)})`);\n }\n } catch {\n // Not laid out: leave it where it is.\n }\n }\n }\n}\n\nconst VAR = /var\\(\\s*(--[\\w-]+)\\s*(?:,\\s*([^()]*(?:\\([^()]*\\)[^()]*)*))?\\)/g;\n\n/**\n * `copy` with the CSS variables in its attributes and styles replaced by\n * their values on `live` (its original, in the page), or their fallbacks:\n * an image of the SVG is drawn on its own, where the page's variables (a\n * host's palette) mean nothing.\n */\nfunction resolveVariables(live: SVGSVGElement, copy: SVGSVGElement) {\n const originals = [live, ...live.querySelectorAll(\"*\")];\n const copies = [copy, ...copy.querySelectorAll(\"*\")];\n copies.forEach((el, i) => {\n let style: CSSStyleDeclaration | undefined;\n for (const attr of [...el.attributes]) {\n if (!attr.value.includes(\"var(\")) continue;\n style ??= getComputedStyle(originals[i] ?? live);\n el.setAttribute(\n attr.name,\n attr.value.replace(\n VAR,\n (_, name: string, fallback?: string) =>\n style!.getPropertyValue(name).trim() || fallback?.trim() || \"\",\n ),\n );\n }\n });\n}\n\n/** An image of the picture as drawn now (its layers in order), at `pixels`. */\nasync function rasterize(layers: SVGSVGElement[], pixels: { width: number; height: number }): Promise<HTMLCanvasElement> {\n const canvas = document.createElement(\"canvas\");\n canvas.width = pixels.width;\n canvas.height = pixels.height;\n const defs = layers[0]?.querySelector(\"defs\");\n for (const [i, svg] of layers.entries()) {\n const copy = svg.cloneNode(true) as SVGSVGElement;\n resolveVariables(svg, copy);\n // A fixed layer's gradients and markers live in the picture's <defs>.\n if (i > 0 && defs) copy.prepend(defs.cloneNode(true));\n copy.setAttribute(\"xmlns\", SVG_NS);\n copy.setAttribute(\"width\", String(pixels.width));\n copy.setAttribute(\"height\", String(pixels.height));\n const url = URL.createObjectURL(\n new Blob([new XMLSerializer().serializeToString(copy)], { type: \"image/svg+xml\" }),\n );\n try {\n const image = new Image();\n image.src = url;\n await image.decode();\n canvas.getContext(\"2d\")!.drawImage(image, 0, 0, pixels.width, pixels.height);\n } finally {\n URL.revokeObjectURL(url);\n }\n }\n return canvas;\n}\n\n/**\n * Moves the picture's `data-fixed` elements (titles, legends, notes) into a\n * layer over it that keeps the original `viewBox`, so a `view` zooms the\n * picture under them while they stay put. Undefined when it has none.\n */\nfunction fixedLayer(svg: SVGSVGElement): SVGSVGElement | undefined {\n const fixed = [...svg.querySelectorAll(\"[data-fixed]\")].filter(\n (el) => !el.parentElement?.closest(\"[data-fixed]\"),\n );\n if (!fixed.length) return undefined;\n // The picture's own attributes (viewBox, fonts, fills) without its id.\n const layer = svg.cloneNode(false) as SVGSVGElement;\n layer.removeAttribute(\"id\");\n layer.setAttribute(\"aria-hidden\", \"true\");\n layer.style.cssText = \"position:absolute;inset:0;overflow:visible\";\n for (const el of fixed) layer.appendChild(el);\n return layer;\n}\n\nexport interface SvgViewOptions {\n /**\n * Called with the id of the innermost element with an id that is clicked:\n * its id in the motion's markup (in the page, ids carry a suffix that keeps\n * them unique, so several pictures can use the same ones).\n */\n onPick?: (id: string) => void;\n}\n\n/** An {@link SvgMotion} drawn into an element; call `draw` with a time to show it then. */\nexport interface SvgView {\n /** A `div` filled by the picture; put it anywhere. */\n readonly element: HTMLDivElement;\n /** Shows the picture at `timeMs`, with steps starting at `steps` (ms). */\n draw(timeMs: number, steps?: readonly number[]): void;\n /** An image of the picture as drawn now. */\n capture(pixels: { width: number; height: number }): Promise<HTMLCanvasElement | undefined>;\n}\n\n/** Shows an {@link SvgMotion} as a live view; with `onPick`, clicks report the id of the element clicked. */\nexport function svgView(motion: SvgMotion, options: SvgViewOptions = {}): SvgView {\n const element = document.createElement(\"div\");\n element.style.width = \"100%\";\n element.style.height = \"100%\";\n const { onPick } = options;\n if (onPick)\n element.addEventListener(\"click\", (event) => {\n // The innermost element with an id, up to the picture itself.\n for (let el = event.target as Element | null; el && el !== element; el = el.parentElement)\n if (el.id && el.localName !== \"svg\") return onPick(el.getAttribute(\"data-flair-id\") ?? el.id);\n });\n let svg: SVGSVGElement | undefined | null = null;\n let fixed: SVGSVGElement | undefined;\n let nonscaling: Element[] = [];\n let whole: SvgBox = [0, 0, 100, 100];\n const byId = new Map<string, Element>();\n let ids: ReadonlyMap<string, string> = new Map();\n const suffix = `f${++views}`;\n return {\n element,\n draw(timeMs, steps = []) {\n if (svg === null) {\n // Parsed on first use, so a view made and dropped costs nothing.\n svg = parseSvg(motion.svg);\n if (svg) {\n ids = scopeIds(svg, suffix);\n svg.setAttribute(\"width\", \"100%\");\n svg.setAttribute(\"height\", \"100%\");\n element.appendChild(svg);\n fixed = fixedLayer(svg);\n if (fixed) {\n element.style.position = \"relative\";\n element.appendChild(fixed);\n }\n for (const layer of [svg, fixed])\n for (const el of layer?.querySelectorAll(\"[id]\") ?? [])\n byId.set(el.getAttribute(\"data-flair-id\") ?? el.id, el);\n nonscaling = [...svg.querySelectorAll(\"[data-nonscaling]\")];\n const box = (svg.getAttribute(\"viewBox\") ?? \"\")\n .trim()\n .split(/[\\s,]+/)\n .map(Number);\n if (box.length === 4 && box.every(Number.isFinite)) whole = box as unknown as SvgBox;\n }\n }\n if (svg) {\n apply(svg, whole, byId, motion, timeMs, steps, ids);\n keepSize(svg, whole, nonscaling);\n }\n },\n capture: async (pixels) => (svg ? rasterize(fixed ? [svg, fixed] : [svg], pixels) : undefined),\n };\n}\n\n/** How long an {@link SvgMotion} runs: its last change's end, in ms (at least 1). */\nexport function svgDuration(motion: SvgMotion, steps: readonly number[] = []): number {\n let end = 0;\n for (const a of motion.animate ?? []) {\n const step = a.step ?? 0;\n const start = step <= 0 ? 0 : steps[step - 1];\n if (start === undefined) continue;\n end = Math.max(end, start + (a.delay ?? 0) + (a.ms ?? 800));\n }\n return Math.max(1, end);\n}\n\nexport interface SvgPlayerOptions extends SvgViewOptions {\n /** Time source (default: animation frames). Pass a `ManualClock` to step frames yourself. */\n clock?: Clock;\n /** Start playing at once (default `true`). */\n autoplay?: boolean;\n /**\n * Start again at the end (default `true`). When `false` it plays once and\n * stays on the last frame (hidden instead with `hideWhenPaused`).\n */\n loop?: boolean;\n /** Loop length in ms (default: the picture's own, see {@link svgDuration}, plus `hold`). */\n duration?: number;\n /** Ms to rest on the last frame before looping (default 600). */\n hold?: number;\n /** Playback speed (default 1). */\n speed?: number;\n /** Step start times in ms, for pictures that change on steps (default none). */\n steps?: readonly number[];\n /** Pause the animation loop when scrolled out of view via IntersectionObserver (default false). */\n pauseWhenHidden?: boolean;\n /** Wait to start playing until the element enters the viewport via IntersectionObserver (default false). When true, autoplay is deferred until first visible. */\n playOnEnter?: boolean;\n /** Hide the view (`visibility: hidden`) whenever playback is paused or reset (default false). */\n hideWhenPaused?: boolean;\n /**\n * Plays in answer to the pointer instead of on its own (see {@link SvgTrigger}):\n * `\"hover\"` and `\"press\"` play to the end while hovered or held and back to\n * the start after; `\"click\"` plays the next step on each click, starting\n * over after the last. `autoplay`, `loop` and `steps` are ignored.\n */\n trigger?: SvgTrigger;\n /** The element whose pointer events trigger it (default the container). */\n triggerTarget?: HTMLElement;\n}\n\n/** What makes a triggered {@link SvgPlayer} play. */\nexport type SvgTrigger = \"hover\" | \"press\" | \"click\";\n\n/**\n * Plays an {@link SvgMotion} inside `container`: loops by default, and can be\n * paused, sought and sped up. Dispose it to stop and remove the picture.\n */\nexport class SvgPlayer {\n readonly view: SvgView;\n private readonly clock: Clock;\n private steps: readonly number[];\n private readonly loop: boolean;\n private length: number;\n private readonly motion: SvgMotion;\n private readonly trigger?: SvgTrigger;\n private readonly triggerTarget?: HTMLElement;\n /** With a hover or press trigger: 1 playing to the end, -1 back to the start. */\n private direction = 1;\n /** With a click trigger: when each click came, in ms of playback. */\n private clicks: number[] = [];\n private readonly hideWhenPaused: boolean;\n private speed: number;\n private time = 0;\n private last = 0;\n private playing = false;\n private disposed = false;\n private wasPlayingBeforeHidden = false;\n private hasEnteredViewport = false;\n private intersectionObserver?: IntersectionObserver;\n\n constructor(\n private readonly container: HTMLElement,\n motion: SvgMotion,\n options: SvgPlayerOptions = {},\n ) {\n this.clock = options.clock ?? realClock;\n this.motion = motion;\n this.trigger = options.trigger;\n this.steps = this.trigger ? [] : (options.steps ?? []);\n this.loop = this.trigger ? false : (options.loop ?? true);\n this.speed = options.speed ?? 1;\n this.hideWhenPaused = Boolean(options.hideWhenPaused);\n this.length = options.duration ?? svgDuration(motion, this.steps) + (options.hold ?? 600);\n this.view = svgView(motion, options);\n container.appendChild(this.view.element);\n this.view.draw(0, this.steps);\n\n const needsObserver =\n (options.pauseWhenHidden || options.playOnEnter) && typeof IntersectionObserver !== \"undefined\";\n\n if (needsObserver) {\n this.intersectionObserver = new IntersectionObserver(([entry]) => {\n if (!entry) return;\n if (entry.isIntersecting) {\n if (options.playOnEnter && !this.hasEnteredViewport) {\n this.hasEnteredViewport = true;\n if (options.autoplay ?? true) {\n this.play();\n }\n } else if (this.wasPlayingBeforeHidden) {\n this.wasPlayingBeforeHidden = false;\n this.play();\n }\n } else {\n if (this.playing && options.pauseWhenHidden) {\n this.wasPlayingBeforeHidden = true;\n this.pause();\n }\n }\n });\n this.intersectionObserver.observe(this.view.element);\n }\n\n if (this.trigger) {\n // A click-triggered picture runs until its latest step is over, however many clicks.\n // Hovers and presses run to the last change and back, with no rest to wait through.\n this.length = this.trigger === \"click\" ? Infinity : (options.duration ?? svgDuration(motion));\n this.triggerTarget = options.triggerTarget ?? container;\n this.listen(true);\n return;\n }\n\n // Without IntersectionObserver (a server, a test), nothing would say it entered: play at once.\n const shouldAutoplay = (options.autoplay ?? true) && !(options.playOnEnter && needsObserver);\n if (shouldAutoplay) {\n this.play();\n } else if (this.hideWhenPaused) {\n this.view.element.style.visibility = \"hidden\";\n }\n }\n\n /** The loop length in ms. */\n get duration(): number {\n return this.length;\n }\n\n /** The time shown, in ms. */\n get currentTime(): number {\n return this.time;\n }\n\n get isPlaying(): boolean {\n return this.playing;\n }\n\n play(): void {\n if (this.playing || this.disposed) return;\n this.playing = true;\n if (this.hideWhenPaused) this.view.element.style.visibility = \"visible\";\n this.last = this.clock.now();\n void this.run();\n }\n\n pause(): void {\n this.playing = false;\n if (this.hideWhenPaused) this.view.element.style.visibility = \"hidden\";\n }\n\n /** Stops playback, rewinds to `0 ms`, and hides the view if `hideWhenPaused` is enabled. */\n reset(): void {\n this.playing = false;\n this.wasPlayingBeforeHidden = false;\n this.seek(0);\n if (this.hideWhenPaused) this.view.element.style.visibility = \"hidden\";\n }\n\n /** Shows the picture at `ms` (wrapped into the loop when looping). */\n seek(ms: number): void {\n this.time = this.loop\n ? ((ms % this.length) + this.length) % this.length\n : Math.min(Math.max(ms, 0), this.length);\n this.view.draw(this.time, this.steps);\n }\n\n setSpeed(speed: number): void {\n this.speed = speed;\n }\n\n /**\n * Plays to the end (`true`) or back to the start (`false`) from wherever it\n * is: what a hover or press trigger does, for hosts that drive it themselves\n * (a hovered card, a focused button).\n */\n setActive(active: boolean): void {\n this.direction = active ? 1 : -1;\n this.play();\n }\n\n /**\n * Plays the picture's next step (what a click trigger does): steps 1, 2, …\n * in turn, then step 1 again, so a picture whose last step leads back to\n * how it started toggles; one with no steps plays again from the start.\n */\n advance(): void {\n const last = Math.max(0, ...(this.motion.animate ?? []).map((a) => a.step ?? 0));\n if (last === 0) {\n this.clicks = [];\n this.time = 0;\n } else {\n this.clicks.push(this.time);\n // Only the clicks of the current round count, so each round starts from how the last ended.\n this.steps = this.clicks.slice(Math.floor((this.clicks.length - 1) / last) * last);\n }\n this.view.draw(this.time, this.steps);\n this.play();\n }\n\n dispose(): void {\n this.disposed = true;\n this.playing = false;\n if (this.trigger) this.listen(false);\n this.intersectionObserver?.disconnect();\n this.view.element.remove();\n }\n\n private onEnter = () => this.setActive(true);\n private onLeave = () => this.setActive(false);\n private onClick = () => this.advance();\n\n private listen(on: boolean) {\n const target = this.triggerTarget!;\n const method = on ? \"addEventListener\" : \"removeEventListener\";\n if (this.trigger === \"hover\") {\n target[method](\"pointerenter\", this.onEnter);\n target[method](\"pointerleave\", this.onLeave);\n } else if (this.trigger === \"press\") {\n target[method](\"pointerdown\", this.onEnter);\n window[method](\"pointerup\", this.onLeave);\n window[method](\"pointercancel\", this.onLeave);\n } else target[method](\"click\", this.onClick);\n }\n\n private async run(): Promise<void> {\n while (this.playing && !this.disposed) {\n await this.clock.frame();\n if (!this.playing || this.disposed) return;\n const now = this.clock.now();\n const dt = (now - this.last) * this.speed;\n this.last = now;\n if (this.trigger === \"click\") {\n // Rest once the latest step is over, until the next click.\n const end = svgDuration(this.motion, this.steps);\n this.time = Math.min(this.time + dt, Math.max(end, this.time));\n this.view.draw(this.time, this.steps);\n if (this.time >= end) this.playing = false;\n continue;\n }\n if (this.trigger) {\n const next = Math.min(Math.max(this.time + dt * this.direction, 0), this.length);\n this.seek(next);\n if (next === 0 || next === this.length) this.playing = false;\n continue;\n }\n const next = this.time + dt;\n if (!this.loop && next >= this.length) {\n this.seek(this.length);\n this.playing = false;\n if (this.hideWhenPaused) this.view.element.style.visibility = \"hidden\";\n return;\n }\n this.seek(next);\n }\n }\n}\n\nexport interface AnimateCountOptions {\n /** Starting number. */\n from: number;\n /** Ending number. */\n to: number;\n /** Duration in ms (default {@link STEP_MS}). */\n ms?: number;\n /** Delay before starting in ms (default 0). */\n delay?: number;\n /** Easing curve (default `\"out\"`). */\n ease?: EaseName;\n /** Number of decimal places (default 0). */\n decimals?: number;\n /** Format template where `{n}` is replaced by the formatted number (default `\"{n}\"`). */\n format?: string;\n /** Time source (default: animation frames). */\n clock?: Clock;\n /** Called with each formatted text frame (and raw numeric value). */\n onUpdate: (text: string, value: number) => void;\n}\n\n/**\n * Counts a number from `from` to `to` over `ms` using Flair's easing curves\n * and `Clock`, calling `onUpdate` with the formatted string on each frame.\n * Returns a cancel function that stops the animation.\n */\nexport function animateCount(options: AnimateCountOptions): () => void {\n const clock = options.clock ?? realClock;\n const ms = options.ms ?? STEP_MS;\n const delay = options.delay ?? 0;\n const ease = EASES[options.ease ?? \"out\"];\n const start = clock.now();\n let stopped = false;\n\n const emit = (u: number) => {\n const v = options.from + (options.to - options.from) * ease(u);\n options.onUpdate(formatCount(v, options), v);\n };\n\n emit(ms <= 0 && delay <= 0 ? 1 : 0);\n if (ms <= 0 && delay <= 0) return () => {};\n\n void (async () => {\n while (!stopped) {\n await clock.frame();\n if (stopped) return;\n const elapsed = clock.now() - start - delay;\n if (elapsed < 0) continue;\n if (ms <= 0 || elapsed >= ms) {\n emit(1);\n return;\n }\n emit(elapsed / ms);\n }\n })();\n\n return () => {\n stopped = true;\n };\n}\n"],"mappings":"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","names":["next"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shader/textures.ts","../src/shader/pointer.ts","../src/shader/program.ts"],"sourcesContent":["import type { TextureSettings } from \"./controls.js\";\n\n/** Why an image control's URL could not be shown. */\nexport class ImageLoadError extends Error {\n readonly url: string;\n\n constructor(url: string, cause?: unknown, message?: string) {\n super(\n message ??\n `Could not load the image at ${shortUrl(url)}. If it is on another site, that site must allow cross-origin use (CORS).`,\n { cause },\n );\n this.name = \"ImageLoadError\";\n this.url = url;\n }\n}\n\n/** A URL short enough for a message: a data URL is cut after its type. */\nexport function shortUrl(url: string): string {\n if (url.startsWith(\"data:\")) return `${url.slice(0, Math.min(url.indexOf(\",\") + 1 || 40, 40))}…`;\n return url.length > 120 ? `${url.slice(0, 119)}…` : url;\n}\n\n/**\n * The long edge, in pixels, SVG images are rasterised at. WebGL2 guarantees\n * textures this large on every device.\n */\nexport const SVG_EDGE = 2048;\n\nconst SVG_TYPE = \"image/svg+xml\";\n\n/** Whether `url` is an SVG: a `data:image/svg+xml` URL, or a path ending in `.svg`. */\nexport function isSvgUrl(url: string): boolean {\n return /^data:image\\/svg\\+xml[;,]/i.test(url) || /^(?!data:)[^?#]*\\.svg([?#]|$)/i.test(url);\n}\n\n/** A length attribute in user units, or undefined for a percentage, `auto` or nothing. */\nfunction svgLength(value: string | null): number | undefined {\n const match = value?.trim().match(/^([\\d.]+)(px)?$/);\n const n = match ? Number(match[1]) : NaN;\n return n > 0 ? n : undefined;\n}\n\n/**\n * An SVG's markup with `width` and `height` set so its long edge is `edge`\n * pixels, keeping its aspect ratio. An image decodes an SVG at its own size\n * (often icon-sized, or 300 × 150 when it has none), so it would make a\n * small, blurry texture; at this size it is rasterised crisply. A `viewBox`\n * is added where missing, so the drawing scales with the new size rather\n * than staying in the corner. Throws for markup that is not an SVG.\n */\nexport function sizeSvg(markup: string, edge: number): string {\n const doc = new DOMParser().parseFromString(markup, SVG_TYPE);\n const svg = doc.documentElement;\n if (svg.localName !== \"svg\" || doc.getElementsByTagName(\"parsererror\").length) {\n throw new Error(\"Not an SVG document.\");\n }\n const box = (svg.getAttribute(\"viewBox\") ?? \"\")\n .trim()\n .split(/[\\s,]+/)\n .map(Number);\n const hasBox = box.length === 4 && box[2]! > 0 && box[3]! > 0;\n const width = svgLength(svg.getAttribute(\"width\")) ?? (hasBox ? box[2]! : 300);\n const height = svgLength(svg.getAttribute(\"height\")) ?? (hasBox ? box[3]! : 150);\n if (!hasBox) svg.setAttribute(\"viewBox\", `0 0 ${width} ${height}`);\n const scale = edge / Math.max(width, height);\n svg.setAttribute(\"width\", String(Math.max(1, Math.round(width * scale))));\n svg.setAttribute(\"height\", String(Math.max(1, Math.round(height * scale))));\n return new XMLSerializer().serializeToString(svg);\n}\n\n/**\n * Loads and decodes an image for WebGL. Images from other origins are\n * requested with CORS (`crossOrigin = \"anonymous\"`): WebGL refuses pixels a\n * page is not allowed to read. SVGs (see {@link isSvgUrl}) are fetched, also\n * with CORS, and sized to {@link SVG_EDGE} pixels on their long edge before\n * they are decoded, so they stay sharp however small they were drawn.\n */\nexport async function loadImage(url: string): Promise<HTMLImageElement> {\n if (isSvgUrl(url)) return loadSvg(url);\n return decode(url, url, !/^(data|blob):/i.test(url));\n}\n\nasync function loadSvg(url: string): Promise<HTMLImageElement> {\n let markup: string;\n try {\n const response = await fetch(url);\n if (!response.ok) throw new Error(`HTTP ${response.status}`);\n markup = sizeSvg(await response.text(), SVG_EDGE);\n } catch (e) {\n throw new ImageLoadError(url, e);\n }\n const sized = URL.createObjectURL(new Blob([markup], { type: SVG_TYPE }));\n try {\n return await decode(sized, url, false);\n } finally {\n URL.revokeObjectURL(sized);\n }\n}\n\nasync function decode(src: string, url: string, cors: boolean): Promise<HTMLImageElement> {\n const image = new Image();\n if (cors) image.crossOrigin = \"anonymous\";\n image.src = src;\n try {\n await image.decode();\n } catch (e) {\n throw new ImageLoadError(url, e);\n }\n return image;\n}\n\n/** Images decoded by {@link preloadImages}, by URL, for every context on the page. */\nconst preloaded = new Map<string, Promise<HTMLImageElement>>();\nconst decoded = new Map<string, HTMLImageElement>();\n\n/**\n * Loads and decodes images ahead of time, for every WebGL context on the\n * page: a texture cache that meets one of them afterwards (in a\n * `ShaderRenderer`, `ShaderFrames` or thumbnail) uploads it at once, so even\n * its first frame shows the image. Otherwise an image arrives a moment after\n * the first frame, which is black where it goes. Use it before drawing frames\n * that cannot wait, such as a video player asking a new `ShaderFrames` for\n * frame _n_.\n *\n * Each URL loads once, however often it is preloaded. Rejects with the first\n * {@link ImageLoadError}; the other images still load. Preloaded images stay\n * in memory until {@link releaseImages}.\n */\nexport async function preloadImages(urls: Iterable<string>): Promise<void> {\n const loads = [...new Set(urls)].filter(Boolean).map((url) => {\n let load = preloaded.get(url);\n if (!load) {\n load = loadImage(url).then(\n (image) => {\n if (preloaded.get(url) === load) decoded.set(url, image);\n return image;\n },\n (e: unknown) => {\n if (preloaded.get(url) === load) preloaded.delete(url);\n throw e;\n },\n );\n preloaded.set(url, load);\n }\n return load;\n });\n const results = await Promise.allSettled(loads);\n const failed = results.find((r) => r.status === \"rejected\");\n if (failed) throw failed.reason;\n}\n\n/** Forgets preloaded images (all of them without `urls`). Textures already made from them stay. */\nexport function releaseImages(urls?: Iterable<string>) {\n for (const url of urls ?? [...preloaded.keys()]) {\n preloaded.delete(url);\n decoded.delete(url);\n }\n}\n\n/** Something that hands `drawFrame` a texture for an image URL. */\nexport interface TextureSource {\n /** The texture for `url`: the image once loaded, a 1 × 1 opaque black placeholder until then. */\n texture(url: string): WebGLTexture | null;\n /**\n * The texture of the live source set for the image control `name` (see\n * {@link TextureCache.setLive}), with its current frame; undefined when\n * the control has none, so its URL is drawn instead.\n */\n liveTexture?(name: string): WebGLTexture | null | undefined;\n}\n\n/**\n * A picture that changes while it is shown, for an image control: a playing\n * `<video>`, or a canvas something else draws on. Videos re-upload when\n * their frame changes; canvases on every frame drawn.\n */\nexport type LiveSource = HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas;\n\ninterface Live {\n source: LiveSource;\n texture: WebGLTexture | null;\n /** The video time last uploaded (NaN before the first upload). */\n uploaded: number;\n /** Set once the source could not be uploaded: it shows black, and is not tried again. */\n error: ImageLoadError | null;\n}\n\n/** Whether `source` is a video element (without touching `HTMLVideoElement`, which tests and workers lack). */\nfunction isVideo(source: LiveSource): source is HTMLVideoElement {\n return \"readyState\" in source && \"currentTime\" in source;\n}\n\n/** `HAVE_CURRENT_DATA`: a video has a frame to show. */\nconst HAVE_CURRENT_DATA = 2;\n\n/** A name for a live source in messages: its video URL, or the control's name. */\nfunction liveName(name: string, source: LiveSource): string {\n return (isVideo(source) && (source.currentSrc || source.src)) || name;\n}\n\n/**\n * Seeks a video to `time` seconds and settles once the frame there can be\n * drawn, for stepping a video in time with `ShaderFrames`: `await\n * seekVideo(video, t); frames.render(t)`. Pause the video first, or it\n * moves on. The time is clamped to the video's length.\n */\nexport async function seekVideo(video: HTMLVideoElement, time: number): Promise<void> {\n if (video.readyState < 1) {\n await new Promise<void>((resolve, reject) => {\n video.addEventListener(\"loadedmetadata\", () => resolve(), { once: true });\n video.addEventListener(\"error\", () => reject(new Error(`Could not load the video ${shortUrl(video.currentSrc || video.src)}.`)), { once: true });\n });\n }\n const target = Math.max(0, Math.min(time, Number.isFinite(video.duration) ? video.duration : time));\n if (Math.abs(video.currentTime - target) < 1e-6 && video.readyState >= HAVE_CURRENT_DATA && !video.seeking) return;\n await new Promise<void>((resolve) => {\n video.addEventListener(\"seeked\", () => resolve(), { once: true });\n video.currentTime = target;\n });\n}\n\ninterface Entry {\n texture: WebGLTexture | null;\n /** Settles when the image is uploaded or has failed. */\n loaded: Promise<void>;\n error: ImageLoadError | null;\n}\n\n/**\n * The textures of one WebGL context, by image URL. A URL starts loading the\n * first time it is asked for; until it arrives the placeholder is drawn, and\n * `onLoad` hears when it does (or fails) so the owner can redraw. An image\n * already decoded by {@link preloadImages} is uploaded at once instead. Images are\n * uploaded upright (`fragCoord / iResolution` samples them the right way up)\n * with mipmaps.\n */\nexport class TextureCache implements TextureSource {\n private readonly gl: WebGL2RenderingContext;\n private readonly entries = new Map<string, Entry>();\n private readonly live = new Map<string, Live>();\n private readonly onLoad: (url: string, error: ImageLoadError | null) => void;\n private readonly load: (url: string) => Promise<TexImageSource>;\n private placeholder: WebGLTexture | null = null;\n private disposed = false;\n\n constructor(\n gl: WebGL2RenderingContext,\n onLoad: (url: string, error: ImageLoadError | null) => void = () => {},\n load: (url: string) => Promise<TexImageSource> = loadImage,\n ) {\n this.gl = gl;\n this.onLoad = onLoad;\n this.load = load;\n }\n\n texture(url: string): WebGLTexture | null {\n return (url && this.entry(url).texture) || this.blank();\n }\n\n /** Starts loading `url` if it is new. */\n request(url: string) {\n if (url) this.entry(url);\n }\n\n private entry(url: string): Entry {\n const existing = this.entries.get(url);\n if (existing) return existing;\n const created: Entry = { texture: null, loaded: Promise.resolve(), error: null };\n const ready = decoded.get(url);\n if (ready && !this.gl.isContextLost()) {\n created.texture = this.upload(ready);\n this.entries.set(url, created);\n return created;\n }\n created.loaded = this.load(url).then(\n (image) => {\n if (this.entries.get(url) !== created || this.disposed || this.gl.isContextLost()) return;\n created.texture = this.upload(image);\n this.onLoad(url, null);\n },\n (e: unknown) => {\n if (this.entries.get(url) !== created || this.disposed) return;\n created.error = e instanceof ImageLoadError ? e : new ImageLoadError(url, e);\n this.onLoad(url, created.error);\n },\n );\n this.entries.set(url, created);\n return created;\n }\n\n /**\n * Shows `source` in the image control `name` instead of its URL, frame by\n * frame (`null` goes back to the URL). Its texture is uploaded as it is\n * drawn: a video's whenever it has moved to another frame, a canvas's on\n * every frame. Until a video has a frame it shows black. A video from\n * another site needs CORS (`crossOrigin = \"anonymous\"` and the site's\n * consent); without it the upload fails, `onLoad` hears an\n * {@link ImageLoadError}, and the control shows black.\n */\n setLive(name: string, source: LiveSource | null) {\n const existing = this.live.get(name);\n if (existing?.source === source) return;\n if (existing?.texture) this.gl.deleteTexture(existing.texture);\n this.live.delete(name);\n if (source) this.live.set(name, { source, texture: null, uploaded: NaN, error: null });\n }\n\n liveTexture(name: string): WebGLTexture | null | undefined {\n const live = this.live.get(name);\n if (!live) return undefined;\n if (live.error || this.gl.isContextLost()) return this.blank();\n const { source } = live;\n if (isVideo(source)) {\n if (source.readyState < HAVE_CURRENT_DATA) return live.texture ?? this.blank();\n if (live.texture && live.uploaded === source.currentTime) return live.texture;\n live.uploaded = source.currentTime;\n }\n const gl = this.gl;\n live.texture ??= gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, live.texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);\n try {\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);\n } catch (e) {\n const url = liveName(name, source);\n live.error = new ImageLoadError(\n url,\n e,\n `Could not draw the video at ${shortUrl(url)}. If it is on another site, set crossOrigin = \"anonymous\" on the <video> and make sure that site allows cross-origin use (CORS).`,\n );\n this.onLoad(url, live.error);\n return this.blank();\n } finally {\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\n }\n gl.generateMipmap(gl.TEXTURE_2D);\n return live.texture;\n }\n\n /**\n * Whether a live video has moved to a frame not yet drawn (or has its\n * first frame ready), so a paused preview knows to draw again.\n */\n liveChanged(): boolean {\n for (const live of this.live.values()) {\n const { source } = live;\n if (live.error || !isVideo(source) || source.readyState < HAVE_CURRENT_DATA) continue;\n if (!live.texture || live.uploaded !== source.currentTime) return true;\n }\n return false;\n }\n\n /**\n * Settles once every live video has a frame to show. Rejects with an\n * {@link ImageLoadError} when one fails to load.\n */\n async liveReady(): Promise<void> {\n await Promise.all(\n [...this.live.entries()].map(([name, { source }]) => {\n if (!isVideo(source) || source.readyState >= HAVE_CURRENT_DATA) return undefined;\n return new Promise<void>((resolve, reject) => {\n source.addEventListener(\"loadeddata\", () => resolve(), { once: true });\n source.addEventListener(\n \"error\",\n () => reject(new ImageLoadError(liveName(name, source), source.error, `Could not load the video at ${shortUrl(liveName(name, source))}.`)),\n { once: true },\n );\n });\n }),\n );\n }\n\n /** The error for `url`, if it failed to load. */\n error(url: string): ImageLoadError | null {\n return this.entries.get(url)?.error ?? null;\n }\n\n /**\n * Settles once every one of `urls` has loaded or failed (starting any that\n * are new). Rejects with the first {@link ImageLoadError}.\n */\n async ready(urls: Iterable<string>): Promise<void> {\n const entries = [...urls].filter(Boolean).map((url) => this.entry(url));\n await Promise.all(entries.map((e) => e.loaded));\n const failed = entries.find((e) => e.error);\n if (failed) throw failed.error;\n }\n\n /** Deletes the textures of every URL not in `urls`; a later request loads them again. */\n retain(urls: Iterable<string>) {\n const keep = new Set(urls);\n for (const [url, entry] of this.entries) {\n if (keep.has(url)) continue;\n if (entry.texture) this.gl.deleteTexture(entry.texture);\n this.entries.delete(url);\n }\n }\n\n /** Deletes every texture; loads still in flight are dropped. */\n dispose() {\n this.retain([]);\n for (const name of [...this.live.keys()]) this.setLive(name, null);\n if (this.placeholder) this.gl.deleteTexture(this.placeholder);\n this.placeholder = null;\n this.disposed = true;\n }\n\n private blank(): WebGLTexture | null {\n if (this.placeholder) return this.placeholder;\n const gl = this.gl;\n this.placeholder = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, this.placeholder);\n const black = new Uint8Array([0, 0, 0, 255]);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, black);\n return this.placeholder;\n }\n\n private upload(image: TexImageSource): WebGLTexture | null {\n const gl = this.gl;\n const texture = gl.createTexture();\n gl.bindTexture(gl.TEXTURE_2D, texture);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);\n gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);\n gl.generateMipmap(gl.TEXTURE_2D);\n return texture;\n }\n}\n\n/** Sets the bound `TEXTURE_2D`'s filter and wrap. */\nexport function applyTextureSettings(gl: WebGL2RenderingContext, settings: TextureSettings) {\n const min = { mipmap: gl.LINEAR_MIPMAP_LINEAR, linear: gl.LINEAR, nearest: gl.NEAREST }[\n settings.filter\n ];\n const wrap = { repeat: gl.REPEAT, clamp: gl.CLAMP_TO_EDGE, mirror: gl.MIRRORED_REPEAT }[\n settings.wrap\n ];\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, min);\n gl.texParameteri(\n gl.TEXTURE_2D,\n gl.TEXTURE_MAG_FILTER,\n settings.filter === \"nearest\" ? gl.NEAREST : gl.LINEAR,\n );\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrap);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrap);\n}\n","/**\n * The pointer as shaders see it, beyond Shadertoy's `iMouse`: where it is\n * while it is over the canvas, how hovered the canvas is (eased in and out),\n * how long it has been pressed, the last few clicks, and where it has just\n * been (its trail), so effects can answer hovers, presses, taps and moves.\n * Times are in `iTime` seconds, so a recording can script them (see\n * `ShaderFrames`' `pointer`, `clicks` and `trail`).\n */\n\n/** How many clicks `iClicks` holds; older ones drop off. */\nexport const MAX_CLICKS = 8;\n\n/** How many of the pointer's recent positions `iTrail` holds; older ones drop off. */\nexport const MAX_TRAIL = 32;\n\n/**\n * The least time between two positions in the trail, in seconds: moves in\n * between update the newest. With {@link MAX_TRAIL}, about a second of path.\n */\nexport const TRAIL_SECONDS = 1 / 30;\n\n/** How long hovering eases in or out, in seconds. */\nexport const HOVER_SECONDS = 0.25;\n\n/** A click, or a point of the trail: where (pixels from the bottom left, like `iMouse`) and when (`iTime` seconds). */\nexport interface ShaderClick {\n x: number;\n y: number;\n time: number;\n}\n\nconst smooth = (t: number) => (t <= 0 ? 0 : t >= 1 ? 1 : t * t * (3 - 2 * t));\n\n/**\n * `iClicks` from a list of clicks, newest first: `vec4(x, y, time, 1)` for\n * each click at or before `time`, zeros for the rest.\n */\nexport function clicksUniform(clicks: readonly ShaderClick[], time: number): Float32Array {\n return latest(clicks, time, MAX_CLICKS);\n}\n\n/**\n * `iTrail` from the pointer's positions, oldest first in the list: the\n * newest {@link MAX_TRAIL} at or before `time`, newest first, as\n * `vec4(x, y, time, 1)`, zeros for the rest.\n */\nexport function trailUniform(trail: readonly ShaderClick[], time: number): Float32Array {\n return latest(trail, time, MAX_TRAIL);\n}\n\nfunction latest(events: readonly ShaderClick[], time: number, max: number): Float32Array {\n const out = new Float32Array(max * 4);\n let i = 0;\n for (let k = events.length - 1; k >= 0 && i < max; k--) {\n const c = events[k]!;\n if (c.time > time) continue;\n out.set([c.x, c.y, c.time, 1], i * 4);\n i++;\n }\n return out;\n}\n\n/**\n * Follows one canvas's pointer for `iPointer` and `iClicks`: feed it pointer\n * events with the `iTime` they happen at, and read the uniforms for a frame.\n */\nexport class PointerTracker {\n private x = 0;\n private y = 0;\n private over = false;\n private hoverFrom = 0;\n private changedAt = -Infinity;\n private pressedAt: number | null = null;\n private releasedAt: number | null = null;\n private clicks: ShaderClick[] = [];\n private trail: ShaderClick[] = [];\n\n /**\n * The pointer moved to (x, y), in pixels from the bottom left. With a\n * `time`, the move joins the trail: a new point at most every\n * {@link TRAIL_SECONDS}, the newest point following the pointer between.\n */\n move(x: number, y: number, time?: number) {\n this.x = x;\n this.y = y;\n if (time === undefined) return;\n const last = this.trail[this.trail.length - 1];\n if (last && time >= last.time && time - last.time < TRAIL_SECONDS) {\n last.x = x;\n last.y = y;\n return;\n }\n this.trail.push({ x, y, time });\n if (this.trail.length > MAX_TRAIL) this.trail.shift();\n }\n\n /** The pointer came over the canvas (`true`) or left it. */\n hover(over: boolean, time: number) {\n if (over === this.over) return;\n this.hoverFrom = this.hovered(time);\n this.changedAt = time;\n this.over = over;\n }\n\n /** A press at (x, y): counts as a click. */\n down(x: number, y: number, time: number) {\n this.move(x, y);\n this.pressedAt = time;\n this.clicks.push({ x, y, time });\n if (this.clicks.length > MAX_CLICKS) this.clicks.shift();\n }\n\n up(time: number) {\n if (this.pressedAt !== null) this.releasedAt = time;\n this.pressedAt = null;\n }\n\n /** Forgets clicks, presses and the trail (when time jumps back, say). */\n clear() {\n this.clicks = [];\n this.trail = [];\n this.pressedAt = null;\n this.releasedAt = null;\n }\n\n /** How hovered the canvas is at `time`, 0–1, eased. */\n hovered(time: number): number {\n const t = smooth((time - this.changedAt) / HOVER_SECONDS);\n return this.hoverFrom + ((this.over ? 1 : 0) - this.hoverFrom) * t;\n }\n\n /**\n * `iPointer` at `time`: x, y, how hovered (0–1), and the press: seconds\n * held while pressed, minus the seconds since it was let go after, 0\n * before the first press.\n */\n pointer(time: number): [number, number, number, number] {\n let press = 0;\n if (this.pressedAt !== null) press = Math.max(0, time - this.pressedAt);\n else if (this.releasedAt !== null) press = -Math.max(1e-3, time - this.releasedAt);\n return [this.x, this.y, this.hovered(time), press];\n }\n\n /** `iClicks` at `time` (see {@link clicksUniform}). */\n clicksAt(time: number): Float32Array {\n return clicksUniform(this.clicks, time);\n }\n\n /** `iTrail` at `time` (see {@link trailUniform}). */\n trailAt(time: number): Float32Array {\n return trailUniform(this.trail, time);\n }\n}\n","import { controlValue, type ControlDef, type ControlValue } from \"./controls.js\";\nimport { MAX_CLICKS, MAX_TRAIL } from \"./pointer.js\";\nimport { applyTextureSettings, type TextureSource } from \"./textures.js\";\n\n/**\n * Shaders are written Shadertoy-style: the source defines\n * `void mainImage(out vec4 fragColor, in vec2 fragCoord)` and may use the\n * built-in uniforms below. It is compiled as GLSL ES 3.00 (WebGL2) inside a\n * small wrapper; `#line 1` keeps compiler line numbers matching the source.\n */\nexport const BUILTIN_UNIFORMS = [\n { name: \"iResolution\", type: \"vec3\", doc: \"viewport size in pixels (z = 1)\" },\n { name: \"iTime\", type: \"float\", doc: \"seconds since the shader started\" },\n { name: \"iTimeDelta\", type: \"float\", doc: \"seconds since the previous frame\" },\n { name: \"iFrame\", type: \"int\", doc: \"frame number\" },\n {\n name: \"iMouse\",\n type: \"vec4\",\n doc: \"xy = pointer while pressed (pixels), zw = press position (negative once released)\",\n },\n {\n name: \"iPointer\",\n type: \"vec4\",\n doc: \"xy = pointer while over the canvas (pixels), z = how hovered (0–1, eased), w = seconds held while pressed, minus seconds since release after (0 before any press)\",\n },\n {\n name: \"iClicks\",\n type: \"vec4\",\n size: MAX_CLICKS,\n doc: \"the latest clicks, newest first: xy = where (pixels), z = when (iTime seconds), w = 1 for a click, 0 for an empty slot\",\n },\n {\n name: \"iTrail\",\n type: \"vec4\",\n size: MAX_TRAIL,\n doc: \"where the pointer has just been over the canvas, newest first (about 30 points a second, so a second of path): xy = where (pixels), z = when (iTime seconds), w = 1 for a point, 0 for an empty slot\",\n },\n] as const;\n\nconst PRELUDE = `#version 300 es\nprecision highp float;\nprecision highp int;\nuniform vec3 iResolution;\nuniform float iTime;\nuniform float iTimeDelta;\nuniform int iFrame;\nuniform vec4 iMouse;\nuniform vec4 iPointer;\nuniform vec4 iClicks[${MAX_CLICKS}];\nuniform vec4 iTrail[${MAX_TRAIL}];\nout vec4 flair_FragColor;\n`;\n\nconst EPILOGUE = `\nvoid main() {\n vec4 flair_color = vec4(0.0, 0.0, 0.0, 1.0);\n mainImage(flair_color, gl_FragCoord.xy);\n flair_FragColor = vec4(flair_color.rgb, clamp(flair_color.a, 0.0, 1.0));\n}\n`;\n\n/** A full-screen triangle from `gl_VertexID` alone: no buffers or attributes. */\nexport const VERTEX_SOURCE = `#version 300 es\nvoid main() {\n vec2 p = vec2(float((gl_VertexID << 1) & 2), float(gl_VertexID & 2));\n gl_Position = vec4(p * 2.0 - 1.0, 0.0, 1.0);\n}\n`;\n\n/** One compiler message, mapped back to the user's source. */\nexport interface CompileError {\n /** 1-based line in the user's source (0 when the driver gave none, or it is outside the source). */\n line: number;\n message: string;\n}\n\n/** A linked program and the uniform locations `drawFrame` sets. */\nexport interface CompiledShader {\n program: WebGLProgram;\n builtins: Record<string, WebGLUniformLocation | null>;\n uniforms: Map<string, WebGLUniformLocation | null>;\n}\n\nexport type CompileResult =\n { ok: true; shader: CompiledShader } | { ok: false; errors: CompileError[] };\n\n/** Thrown by the APIs that cannot carry on without a program (`ShaderFrames`, `recordGif`). */\nexport class ShaderCompileError extends Error {\n readonly errors: CompileError[];\n\n constructor(errors: CompileError[]) {\n super(formatCompileError(errors));\n this.name = \"ShaderCompileError\";\n this.errors = errors;\n }\n}\n\n/** \"The shader does not compile (line 3): 'x' : undeclared identifier\", from the first error. */\nexport function formatCompileError(errors: CompileError[]): string {\n const first = errors[0];\n return `The shader does not compile${first?.line ? ` (line ${first.line})` : \"\"}: ${first?.message ?? \"unknown error\"}`;\n}\n\n/** The complete GLSL ES 3.00 fragment shader for a `mainImage` source. */\nexport function wrapSource(source: string): string {\n // `#line 1` must follow the prelude; drop a user `#version` (the wrapper owns it).\n return `${PRELUDE}#line 1\\n${source.replace(/^\\s*#version[^\\n]*/m, \"\")}\\n${EPILOGUE}`;\n}\n\n/** Turns a driver log (\"ERROR: 0:12: 'foo' : undeclared identifier\") into line-numbered errors. */\nexport function parseCompileLog(log: string, lineCount: number): CompileError[] {\n const errors: CompileError[] = [];\n for (const raw of log.split(\"\\n\")) {\n const text = raw.trim();\n if (!text) continue;\n const m = /^(?:ERROR|WARNING):\\s*\\d+:(\\d+):\\s*(.*)$/.exec(text);\n if (m) {\n const line = Number(m[1]);\n errors.push({ line: line >= 1 && line <= lineCount ? line : 0, message: m[2]!.trim() });\n } else if (!/^\\W*$/.test(text)) {\n errors.push({ line: 0, message: text.replace(/^ERROR:\\s*/, \"\") });\n }\n }\n if (!errors.length) errors.push({ line: 0, message: \"The shader did not compile.\" });\n // Drivers often repeat the same error.\n const seen = new Set<string>();\n return errors.filter((e) => {\n const key = `${e.line}:${e.message}`;\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n}\n\nlet vertexCache = new WeakMap<WebGL2RenderingContext, WebGLShader>();\n\nfunction vertexShader(gl: WebGL2RenderingContext): WebGLShader {\n let vs = vertexCache.get(gl);\n if (!vs) {\n vs = gl.createShader(gl.VERTEX_SHADER)!;\n gl.shaderSource(vs, VERTEX_SOURCE);\n gl.compileShader(vs);\n vertexCache.set(gl, vs);\n }\n return vs;\n}\n\n/** Forgets cached GL objects. Call it after a context loss, before compiling on the restored context. */\nexport function resetGlCaches() {\n vertexCache = new WeakMap();\n}\n\n/**\n * Compiles and links a `mainImage` source. Errors come back with lines in\n * the user's source, never thrown. `controls` (from `parseControls`) says\n * which uniform locations to look up.\n */\nexport function compileShader(\n gl: WebGL2RenderingContext,\n source: string,\n controls: ControlDef[],\n): CompileResult {\n const lineCount = source.split(\"\\n\").length;\n if (gl.isContextLost()) {\n return {\n ok: false,\n errors: [\n {\n line: 0,\n message:\n \"The graphics context was lost; reload the page if the preview does not come back.\",\n },\n ],\n };\n }\n if (!/\\bmainImage\\s*\\(/.test(source)) {\n return {\n ok: false,\n errors: [\n { line: 0, message: \"Define void mainImage(out vec4 fragColor, in vec2 fragCoord).\" },\n ],\n };\n }\n const fs = gl.createShader(gl.FRAGMENT_SHADER);\n if (!fs) {\n return {\n ok: false,\n errors: [{ line: 0, message: \"WebGL could not create a shader (the context may be lost).\" }],\n };\n }\n gl.shaderSource(fs, wrapSource(source));\n gl.compileShader(fs);\n if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {\n const errors = parseCompileLog(gl.getShaderInfoLog(fs) ?? \"\", lineCount);\n gl.deleteShader(fs);\n return { ok: false, errors };\n }\n const program = gl.createProgram()!;\n gl.attachShader(program, vertexShader(gl));\n gl.attachShader(program, fs);\n gl.linkProgram(program);\n gl.deleteShader(fs);\n if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {\n const errors = parseCompileLog(gl.getProgramInfoLog(program) ?? \"\", lineCount);\n gl.deleteProgram(program);\n return { ok: false, errors };\n }\n const builtins: CompiledShader[\"builtins\"] = {};\n for (const u of BUILTIN_UNIFORMS) builtins[u.name] = gl.getUniformLocation(program, u.name);\n const uniforms = new Map(\n controls.map((c) => [c.name, gl.getUniformLocation(program, c.name)] as const),\n );\n return { ok: true, shader: { program, builtins, uniforms } };\n}\n\nconst NO_CLICKS = new Float32Array(MAX_CLICKS * 4);\nconst NO_TRAIL = new Float32Array(MAX_TRAIL * 4);\n\n/** What one frame shows: its size in pixels, its time and the pointer. */\nexport interface FrameState {\n width: number;\n height: number;\n /** `iTime`, in seconds. */\n time: number;\n /** `iTimeDelta`, in seconds. */\n delta: number;\n /** `iFrame`. */\n frame: number;\n /** `iMouse`, Shadertoy semantics. */\n mouse: [number, number, number, number];\n /** `iPointer` (default all zero: nobody is pointing). */\n pointer?: readonly [number, number, number, number];\n /** `iClicks`: {@link MAX_CLICKS} × (x, y, time, 1), newest first (default none; see `clicksUniform`). */\n clicks?: Float32Array;\n /** `iTrail`: {@link MAX_TRAIL} × (x, y, time, 1), newest first (default none; see `trailUniform`). */\n trail?: Float32Array;\n}\n\n/**\n * Draws one frame of a compiled shader into the bound framebuffer, from (0, 0).\n * Image controls are bound to texture units 0, 1, … in source order, with\n * textures from `textures` (a {@link TextureCache} for the same context): a\n * control's live source when it has one, else its URL's image. Without\n * `textures` they sample nothing.\n */\nexport function drawFrame(\n gl: WebGL2RenderingContext,\n shader: CompiledShader,\n controls: ControlDef[],\n values: Record<string, ControlValue> | undefined,\n state: FrameState,\n textures?: TextureSource,\n) {\n gl.viewport(0, 0, state.width, state.height);\n gl.useProgram(shader.program);\n const b = shader.builtins;\n if (b.iResolution) gl.uniform3f(b.iResolution, state.width, state.height, 1);\n if (b.iTime) gl.uniform1f(b.iTime, state.time);\n if (b.iTimeDelta) gl.uniform1f(b.iTimeDelta, state.delta);\n if (b.iFrame) gl.uniform1i(b.iFrame, state.frame);\n if (b.iMouse) gl.uniform4f(b.iMouse, ...state.mouse);\n if (b.iPointer) gl.uniform4f(b.iPointer, ...(state.pointer ?? [0, 0, 0, 0]));\n if (b.iClicks) gl.uniform4fv(b.iClicks, state.clicks ?? NO_CLICKS);\n if (b.iTrail) gl.uniform4fv(b.iTrail, state.trail ?? NO_TRAIL);\n let unit = 0;\n for (const control of controls) {\n const loc = shader.uniforms.get(control.name);\n if (!loc) continue;\n const v = controlValue(control, values);\n switch (control.type) {\n case \"float\":\n gl.uniform1f(loc, v as number);\n break;\n case \"int\":\n gl.uniform1i(loc, Math.round(v as number));\n break;\n case \"bool\":\n gl.uniform1i(loc, v ? 1 : 0);\n break;\n case \"vec2\":\n gl.uniform2fv(loc, v as number[]);\n break;\n case \"vec3\":\n gl.uniform3fv(loc, v as number[]);\n break;\n case \"vec4\":\n gl.uniform4fv(loc, v as number[]);\n break;\n case \"sampler2D\": {\n gl.activeTexture(gl.TEXTURE0 + unit);\n const live = textures?.liveTexture?.(control.name);\n const texture = (live === undefined ? textures?.texture(v as string) : live) ?? null;\n gl.bindTexture(gl.TEXTURE_2D, texture);\n if (texture && control.texture) applyTextureSettings(gl, control.texture);\n gl.uniform1i(loc, unit++);\n break;\n }\n }\n }\n gl.drawArrays(gl.TRIANGLES, 0, 3);\n}\n\n/**\n * A WebGL2 context set up for full-screen fragment shaders: opaque by default,\n * no depth, stencil or antialiasing. `preserveDrawingBuffer` keeps the last\n * frame readable after the task that drew it (for captures). `alpha` enables a\n * transparent drawing buffer for overlay shaders. Null without WebGL2.\n */\nexport function createContext(\n canvas: HTMLCanvasElement | OffscreenCanvas,\n preserveDrawingBuffer = false,\n alpha = false,\n): WebGL2RenderingContext | null {\n return canvas.getContext(\"webgl2\", {\n alpha,\n antialias: false,\n depth: false,\n stencil: false,\n premultipliedAlpha: false,\n preserveDrawingBuffer,\n powerPreference: \"high-performance\",\n }) as WebGL2RenderingContext | null;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/export/mp4mux.ts","../src/export/webmmux.ts","../src/export/zip.ts","../src/embed/record.ts","../src/embed/index.ts"],"sourcesContent":["/**\n * A small MP4 (ISO BMFF) writer for one H.264 video track, with no\n * dependencies, for video encoded in the browser (WebCodecs' `VideoEncoder`\n * with `avc: { format: \"avc\" }`).\n *\n * The file is \"faststart\": `ftyp`, then `moov` (the index), then one `mdat`\n * holding every sample in a single chunk, so a page can start playing it\n * before it has all arrived. Samples are in presentation order (browser\n * encoders make no B-frames), so there is no `ctts`.\n */\n\n/** One encoded frame: its bytes (length-prefixed NAL units), when it shows, and whether it is a keyframe. */\nexport interface Mp4Sample {\n data: Uint8Array;\n /** Presentation time in microseconds (WebCodecs' `timestamp`). */\n timestamp: number;\n /** How long it shows, in microseconds (default: until the next sample, or the one before's). */\n duration?: number;\n key: boolean;\n}\n\nexport interface Mp4Options {\n width: number;\n height: number;\n /** The `avcC` record: the encoder's `decoderConfig.description`. */\n avcC: Uint8Array;\n samples: readonly Mp4Sample[];\n /** Ticks per second of the track's times (default 90000, as for broadcast video). */\n timescale?: number;\n}\n\nconst MOVIE_TIMESCALE = 1000;\nconst UINT32 = 0x1_0000_0000;\n\nconst ascii = (s: string) => Uint8Array.from(s, (c) => c.charCodeAt(0));\n\n/** Big-endian fields, written into a growing list of parts. */\nclass Writer {\n parts: Uint8Array[] = [];\n size = 0;\n bytes(b: Uint8Array) {\n this.parts.push(b);\n this.size += b.length;\n return this;\n }\n u8(n: number) {\n return this.bytes(Uint8Array.of(n & 0xff));\n }\n u16(n: number) {\n return this.bytes(Uint8Array.of((n >>> 8) & 0xff, n & 0xff));\n }\n u32(n: number) {\n const b = new Uint8Array(4);\n new DataView(b.buffer).setUint32(0, n >>> 0);\n return this.bytes(b);\n }\n u64(n: number) {\n return this.u32(Math.floor(n / UINT32)).u32(n % UINT32);\n }\n zeros(n: number) {\n return this.bytes(new Uint8Array(n));\n }\n done(): Uint8Array {\n const out = new Uint8Array(this.size);\n let at = 0;\n for (const p of this.parts) {\n out.set(p, at);\n at += p.length;\n }\n return out;\n }\n}\n\n/** A box: size, type, then its fields and children. */\nfunction box(type: string, ...content: Uint8Array[]): Uint8Array {\n const w = new Writer();\n const size = 8 + content.reduce((n, c) => n + c.length, 0);\n w.u32(size).bytes(ascii(type));\n for (const c of content) w.bytes(c);\n return w.done();\n}\n\n/** A full box: a box whose fields start with a version and flags. */\nfunction fullBox(type: string, version: number, flags: number, ...content: Uint8Array[]): Uint8Array {\n return box(type, Uint8Array.of(version, (flags >> 16) & 0xff, (flags >> 8) & 0xff, flags & 0xff), ...content);\n}\n\nconst fields = (fill: (w: Writer) => unknown) => {\n const w = new Writer();\n fill(w);\n return w.done();\n};\n\n/** The identity transform, as `tkhd` and `mvhd` write it (16.16 and 2.30 fixed point). */\nconst MATRIX = fields((w) => [0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000].forEach((n) => w.u32(n)));\n\n/**\n * Each sample's duration in track ticks, from the gaps between timestamps\n * (the last keeps its own duration, or the gap before it).\n */\nfunction sampleTicks(samples: readonly Mp4Sample[], timescale: number): number[] {\n const tick = (us: number) => Math.round((us * timescale) / 1e6);\n return samples.map((s, i) => {\n const next = samples[i + 1];\n if (next) return Math.max(1, tick(next.timestamp) - tick(s.timestamp));\n if (s.duration) return Math.max(1, tick(s.duration));\n const prev = samples[i - 1];\n return prev ? Math.max(1, tick(s.timestamp) - tick(prev.timestamp)) : Math.max(1, tick(1e6 / 30));\n });\n}\n\n/** `stts`: the durations, run-length coded. */\nfunction stts(ticks: number[]): Uint8Array {\n const runs: [number, number][] = [];\n for (const t of ticks) {\n const last = runs[runs.length - 1];\n if (last && last[1] === t) last[0]++;\n else runs.push([1, t]);\n }\n return fullBox(\"stts\", 0, 0, fields((w) => {\n w.u32(runs.length);\n for (const [count, delta] of runs) w.u32(count).u32(delta);\n }));\n}\n\nfunction moov(options: Mp4Options, ticks: number[], dataOffset: number, wide: boolean): Uint8Array {\n const { width, height, avcC, samples } = options;\n const timescale = options.timescale ?? 90000;\n const trackTicks = ticks.reduce((a, b) => a + b, 0);\n const movieTicks = Math.round((trackTicks * MOVIE_TIMESCALE) / timescale);\n\n const mvhd = fullBox(\"mvhd\", 0, 0, fields((w) =>\n w.u32(0).u32(0).u32(MOVIE_TIMESCALE).u32(movieTicks)\n .u32(0x00010000).u16(0x0100).zeros(10) // rate 1.0, volume 1.0, reserved\n .bytes(MATRIX).zeros(24).u32(2), // pre_defined, next track id\n ));\n const tkhd = fullBox(\"tkhd\", 0, 3, fields((w) => // enabled, in the movie\n w.u32(0).u32(0).u32(1).u32(0).u32(movieTicks)\n .zeros(8).u16(0).u16(0).u16(0).u16(0) // reserved, layer, group, volume (none for video), reserved\n .bytes(MATRIX).u32(width * 0x10000).u32(height * 0x10000),\n ));\n const mdhd = fullBox(\"mdhd\", 0, 0, fields((w) => w.u32(0).u32(0).u32(timescale).u32(trackTicks).u16(0x55c4).u16(0))); // \"und\"\n const hdlr = fullBox(\"hdlr\", 0, 0, fields((w) => w.u32(0).bytes(ascii(\"vide\")).zeros(12).bytes(ascii(\"VideoHandler\\0\"))));\n const vmhd = fullBox(\"vmhd\", 0, 1, new Uint8Array(8));\n const dinf = box(\"dinf\", fullBox(\"dref\", 0, 0, fields((w) => w.u32(1)), fullBox(\"url \", 0, 1)));\n\n const avc1 = box(\n \"avc1\",\n fields((w) =>\n w.zeros(6).u16(1) // reserved, data reference index\n .zeros(16).u16(width).u16(height)\n .u32(0x00480000).u32(0x00480000).u32(0).u16(1) // 72 dpi, reserved, one frame per sample\n .zeros(32).u16(0x0018).u16(0xffff), // compressor name, depth, pre_defined\n ),\n box(\"avcC\", avcC),\n );\n const stsd = fullBox(\"stsd\", 0, 0, fields((w) => w.u32(1)), avc1);\n const keys = samples.flatMap((s, i) => (s.key ? [i + 1] : []));\n // Every sample a keyframe: leave stss out, which says so.\n const stss = keys.length === samples.length ? [] : [fullBox(\"stss\", 0, 0, fields((w) => {\n w.u32(keys.length);\n for (const k of keys) w.u32(k);\n }))];\n const stsz = fullBox(\"stsz\", 0, 0, fields((w) => {\n w.u32(0).u32(samples.length);\n for (const s of samples) w.u32(s.data.length);\n }));\n // One chunk with every sample, starting at the mdat's data.\n const stsc = fullBox(\"stsc\", 0, 0, fields((w) => (samples.length ? w.u32(1).u32(1).u32(samples.length).u32(1) : w.u32(0))));\n const stco = wide\n ? fullBox(\"co64\", 0, 0, fields((w) => w.u32(1).u64(dataOffset)))\n : fullBox(\"stco\", 0, 0, fields((w) => w.u32(1).u32(dataOffset)));\n const stbl = box(\"stbl\", stsd, stts(ticks), ...stss, stsz, stsc, stco);\n const minf = box(\"minf\", vmhd, dinf, stbl);\n const trak = box(\"trak\", tkhd, box(\"mdia\", mdhd, hdlr, minf));\n return box(\"moov\", mvhd, trak);\n}\n\n/**\n * An MP4 file of one H.264 track: `ftyp`, `moov`, then the samples in one\n * `mdat`. Throws when there are no samples or the first is not a keyframe.\n */\nexport function muxMp4(options: Mp4Options): Uint8Array {\n const { samples } = options;\n if (!samples.length) throw new Error(\"An MP4 needs at least one frame.\");\n if (!samples[0]!.key) throw new Error(\"An MP4's first frame must be a keyframe.\");\n const ftyp = box(\"ftyp\", ascii(\"isom\"), fields((w) => w.u32(0x200)), ascii(\"isomiso2avc1mp41\"));\n const ticks = sampleTicks(samples, options.timescale ?? 90000);\n const payload = samples.reduce((n, s) => n + s.data.length, 0);\n const large = payload + 8 >= UINT32;\n const mdatHeader = large ? 16 : 8;\n // The index's size does not depend on the offset it holds, so measure it once and write it again.\n const wide = ftyp.length + moov(options, ticks, 0, large).length + mdatHeader + payload >= UINT32;\n const index = moov(options, ticks, 0, wide);\n const dataOffset = ftyp.length + index.length + mdatHeader;\n const head = fields((w) => {\n w.bytes(ftyp).bytes(moov(options, ticks, dataOffset, wide));\n if (large) w.u32(1).bytes(ascii(\"mdat\")).u64(payload + 16);\n else w.u32(payload + 8).bytes(ascii(\"mdat\"));\n });\n const out = new Uint8Array(head.length + payload);\n out.set(head);\n let at = head.length;\n for (const s of samples) {\n out.set(s.data, at);\n at += s.data.length;\n }\n return out;\n}\n","/**\n * A small WebM (Matroska) writer for one VP8 or VP9 video track, with no\n * dependencies, for video encoded in the browser (WebCodecs' `VideoEncoder`).\n *\n * The file is an EBML header and one Segment of known size: `Info` (with the\n * duration), `Tracks`, then `Cluster`s of `SimpleBlock`s, a new cluster at\n * each keyframe. There are no `Cues`, so a player seeks by scanning, which\n * is quick for short clips. Frames with an alpha plane (VP9 or VP8 encoded\n * with `alpha: \"keep\"`) go in `BlockGroup`s with the alpha as a\n * `BlockAdditional` (id 1), and the track says `AlphaMode` 1, as Chrome's\n * own recordings do.\n */\n\n/** One encoded frame. */\nexport interface WebmFrame {\n data: Uint8Array;\n /** Presentation time in microseconds (WebCodecs' `timestamp`). */\n timestamp: number;\n key: boolean;\n /** The frame's alpha plane, encoded (WebCodecs' `metadata.alphaSideData`). */\n alpha?: Uint8Array;\n}\n\nexport interface WebmOptions {\n codec: \"vp8\" | \"vp9\";\n width: number;\n height: number;\n frames: readonly WebmFrame[];\n /** The length in microseconds (default: the last frame's time plus one frame). */\n duration?: number;\n /** Frames per second, written as the track's default frame duration. */\n fps?: number;\n /** `WritingApp` (default \"flair\"). */\n app?: string;\n}\n\n/** Element ids (their own leading-bits coding is part of the id). */\nconst ID = {\n EBML: 0x1a45dfa3,\n EBMLVersion: 0x4286,\n EBMLReadVersion: 0x42f7,\n EBMLMaxIDLength: 0x42f2,\n EBMLMaxSizeLength: 0x42f3,\n DocType: 0x4282,\n DocTypeVersion: 0x4287,\n DocTypeReadVersion: 0x4285,\n Segment: 0x18538067,\n Info: 0x1549a966,\n TimestampScale: 0x2ad7b1,\n Duration: 0x4489,\n MuxingApp: 0x4d80,\n WritingApp: 0x5741,\n Tracks: 0x1654ae6b,\n TrackEntry: 0xae,\n TrackNumber: 0xd7,\n TrackUID: 0x73c5,\n TrackType: 0x83,\n FlagLacing: 0x9c,\n CodecID: 0x86,\n DefaultDuration: 0x23e383,\n MaxBlockAdditionID: 0x55ee,\n Video: 0xe0,\n PixelWidth: 0xb0,\n PixelHeight: 0xba,\n AlphaMode: 0x53c0,\n Cluster: 0x1f43b675,\n Timestamp: 0xe7,\n SimpleBlock: 0xa3,\n BlockGroup: 0xa0,\n Block: 0xa1,\n ReferenceBlock: 0xfb,\n BlockAdditions: 0x75a1,\n BlockMore: 0xa6,\n BlockAddID: 0xee,\n BlockAdditional: 0xa5,\n} as const;\n\n/** Timestamps count milliseconds (TimestampScale 1 000 000 ns). */\nconst SCALE_NS = 1_000_000;\n/** A block's time is a signed 16-bit offset from its cluster's. */\nconst MAX_OFFSET = 32767;\n\nconst concat = (parts: readonly Uint8Array[]) => {\n const out = new Uint8Array(parts.reduce((n, p) => n + p.length, 0));\n let at = 0;\n for (const p of parts) {\n out.set(p, at);\n at += p.length;\n }\n return out;\n};\n\n/** An element id's bytes (ids already carry their length marker). */\nfunction idBytes(id: number): Uint8Array {\n const out: number[] = [];\n for (let n = id; n > 0; n = Math.floor(n / 256)) out.unshift(n & 0xff);\n return Uint8Array.from(out);\n}\n\n/** A size as an EBML variable-length integer, in the fewest bytes (1–8). */\nexport function vint(n: number): Uint8Array {\n for (let len = 1; len <= 8; len++) {\n // All ones is reserved for \"unknown size\".\n if (n < 2 ** (7 * len) - 1) {\n const out = new Uint8Array(len);\n let v = n;\n for (let i = len - 1; i >= 0; i--) {\n out[i] = v % 256;\n v = Math.floor(v / 256);\n }\n out[0]! |= 1 << (8 - len);\n return out;\n }\n }\n throw new RangeError(`An EBML size cannot be ${n}.`);\n}\n\nconst el = (id: number, ...content: Uint8Array[]) => {\n const body = concat(content);\n return concat([idBytes(id), vint(body.length), body]);\n};\n\nconst uint = (id: number, n: number) => {\n const out: number[] = [];\n for (let v = n; v > 0 || out.length === 0; v = Math.floor(v / 256)) out.unshift(v % 256);\n return el(id, Uint8Array.from(out));\n};\n\nconst float = (id: number, n: number) => {\n const b = new Uint8Array(8);\n new DataView(b.buffer).setFloat64(0, n);\n return el(id, b);\n};\n\nconst str = (id: number, s: string) => el(id, new TextEncoder().encode(s));\n\n/** A block's header: track 1, its time from the cluster's, its flags. */\nfunction blockHeader(offset: number, flags: number): Uint8Array {\n const b = new Uint8Array(4);\n b[0] = 0x81;\n new DataView(b.buffer).setInt16(1, offset);\n b[3] = flags;\n return b;\n}\n\n/**\n * A WebM file of one VP8 or VP9 track. Throws when there are no frames or\n * the first is not a keyframe.\n */\nexport function muxWebm(options: WebmOptions): Uint8Array {\n const { codec, width, height, frames, fps } = options;\n if (!frames.length) throw new Error(\"A WebM needs at least one frame.\");\n if (!frames[0]!.key) throw new Error(\"A WebM's first frame must be a keyframe.\");\n const alpha = frames.some((f) => f.alpha);\n const ms = (us: number) => Math.round(us / 1000);\n const last = frames[frames.length - 1]!;\n const frameUs = fps ? 1e6 / fps : frames.length > 1 ? (last.timestamp - frames[0]!.timestamp) / (frames.length - 1) : 1e6 / 30;\n const durationUs = options.duration ?? last.timestamp + frameUs;\n\n const header = el(\n ID.EBML,\n uint(ID.EBMLVersion, 1),\n uint(ID.EBMLReadVersion, 1),\n uint(ID.EBMLMaxIDLength, 4),\n uint(ID.EBMLMaxSizeLength, 8),\n str(ID.DocType, \"webm\"),\n // BlockAdditions came in version 4.\n uint(ID.DocTypeVersion, alpha ? 4 : 2),\n uint(ID.DocTypeReadVersion, 2),\n );\n const info = el(\n ID.Info,\n uint(ID.TimestampScale, SCALE_NS),\n float(ID.Duration, durationUs / 1000),\n str(ID.MuxingApp, \"flair\"),\n str(ID.WritingApp, options.app ?? \"flair\"),\n );\n const tracks = el(\n ID.Tracks,\n el(\n ID.TrackEntry,\n uint(ID.TrackNumber, 1),\n uint(ID.TrackUID, 1),\n uint(ID.TrackType, 1), // video\n uint(ID.FlagLacing, 0),\n str(ID.CodecID, codec === \"vp9\" ? \"V_VP9\" : \"V_VP8\"),\n ...(fps ? [uint(ID.DefaultDuration, Math.round(1e9 / fps))] : []),\n ...(alpha ? [uint(ID.MaxBlockAdditionID, 1)] : []),\n el(ID.Video, uint(ID.PixelWidth, width), uint(ID.PixelHeight, height), ...(alpha ? [uint(ID.AlphaMode, 1)] : [])),\n ),\n );\n\n const clusters: Uint8Array[] = [];\n let blocks: Uint8Array[] = [];\n let clusterMs = 0;\n let previousMs = 0;\n const close = () => {\n if (blocks.length) clusters.push(el(ID.Cluster, uint(ID.Timestamp, clusterMs), ...blocks));\n blocks = [];\n };\n frames.forEach((frame, i) => {\n const at = ms(frame.timestamp);\n if (i === 0 || frame.key || at - clusterMs > MAX_OFFSET) {\n close();\n clusterMs = at;\n }\n const offset = at - clusterMs;\n if (frame.alpha) {\n blocks.push(\n el(\n ID.BlockGroup,\n el(ID.Block, blockHeader(offset, 0), frame.data),\n el(ID.BlockAdditions, el(ID.BlockMore, uint(ID.BlockAddID, 1), el(ID.BlockAdditional, frame.alpha))),\n // A group without a reference is a keyframe; point delta frames at the one before.\n ...(frame.key ? [] : [el(ID.ReferenceBlock, signed(previousMs - at))]),\n ),\n );\n } else {\n blocks.push(el(ID.SimpleBlock, blockHeader(offset, frame.key ? 0x80 : 0), frame.data));\n }\n previousMs = at;\n });\n close();\n\n const segment = el(ID.Segment, info, tracks, ...clusters);\n return concat([header, segment]);\n}\n\n/** A signed integer's bytes, big-endian, in the fewest bytes (ReferenceBlock is signed). */\nfunction signed(n: number): Uint8Array {\n for (let len = 1; len <= 8; len++) {\n if (n >= -(2 ** (8 * len - 1)) && n < 2 ** (8 * len - 1)) {\n const out = new Uint8Array(len);\n let v = n < 0 ? 2 ** (8 * len) + n : n;\n for (let i = len - 1; i >= 0; i--) {\n out[i] = v % 256;\n v = Math.floor(v / 256);\n }\n return out;\n }\n }\n throw new RangeError(`${n} is out of range.`);\n}\n","/**\n * A store-only ZIP writer (no compression, no dependencies), for handing\n * over many already-compressed files at once: a PNG sequence, say.\n */\n\nexport interface ZipEntry {\n name: string;\n data: Uint8Array;\n}\n\nlet table: Uint32Array | undefined;\n\n/** CRC-32 (IEEE), as ZIP wants it. */\nexport function crc32(data: Uint8Array): number {\n table ??= Uint32Array.from({ length: 256 }, (_, n) => {\n let c = n;\n for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;\n return c >>> 0;\n });\n let crc = 0xffffffff;\n for (let i = 0; i < data.length; i++) crc = table[(crc ^ data[i]!) & 0xff]! ^ (crc >>> 8);\n return (crc ^ 0xffffffff) >>> 0;\n}\n\n/** 1 January 1980, the earliest time a ZIP can hold, so the same frames make the same file. */\nconst DOS_DATE = (0 << 9) | (1 << 5) | 1;\n\n/**\n * A ZIP holding `entries` as they are (method 0, \"stored\"). Names are UTF-8.\n * Each file and the whole must stay under 4 GB (no ZIP64).\n */\nexport function zipStore(entries: readonly ZipEntry[]): Uint8Array {\n const encoder = new TextEncoder();\n const locals: Uint8Array[] = [];\n const centrals: Uint8Array[] = [];\n let offset = 0;\n for (const { name, data } of entries) {\n const nameBytes = encoder.encode(name);\n const crc = crc32(data);\n const local = new Uint8Array(30 + nameBytes.length);\n const l = new DataView(local.buffer);\n l.setUint32(0, 0x04034b50, true);\n l.setUint16(4, 20, true); // version needed: 2.0\n l.setUint16(6, 0x0800, true); // UTF-8 names\n l.setUint16(8, 0, true); // stored\n l.setUint16(10, 0, true); // time\n l.setUint16(12, DOS_DATE, true);\n l.setUint32(14, crc, true);\n l.setUint32(18, data.length, true);\n l.setUint32(22, data.length, true);\n l.setUint16(26, nameBytes.length, true);\n local.set(nameBytes, 30);\n\n const central = new Uint8Array(46 + nameBytes.length);\n const c = new DataView(central.buffer);\n c.setUint32(0, 0x02014b50, true);\n c.setUint16(4, 20, true); // made by\n c.setUint16(6, 20, true); // needed\n c.setUint16(8, 0x0800, true);\n c.setUint16(10, 0, true);\n c.setUint16(12, 0, true);\n c.setUint16(14, DOS_DATE, true);\n c.setUint32(16, crc, true);\n c.setUint32(20, data.length, true);\n c.setUint32(24, data.length, true);\n c.setUint16(28, nameBytes.length, true);\n c.setUint32(42, offset, true);\n central.set(nameBytes, 46);\n\n locals.push(local, data);\n centrals.push(central);\n offset += local.length + data.length;\n }\n const centralSize = centrals.reduce((n, c) => n + c.length, 0);\n const end = new Uint8Array(22);\n const e = new DataView(end.buffer);\n e.setUint32(0, 0x06054b50, true);\n e.setUint16(8, entries.length, true);\n e.setUint16(10, entries.length, true);\n e.setUint32(12, centralSize, true);\n e.setUint32(16, offset, true);\n\n const out = new Uint8Array(offset + centralSize + 22);\n let at = 0;\n for (const part of [...locals, ...centrals, end]) {\n out.set(part, at);\n at += part.length;\n }\n return out;\n}\n","// gifenc ships without types. The reference (not an import) brings them along when a host\n// type-checks these sources through the `workspace` condition.\n// eslint-disable-next-line @typescript-eslint/triple-slash-reference\n/// <reference path=\"../shader/gifenc.d.ts\" />\nimport { effectDefaults, getEffect, type EffectDefinition } from \"../catalog/index.js\";\nimport { renderVectorEffect } from \"../catalog/types.js\";\nimport { muxMp4 } from \"../export/mp4mux.js\";\nimport { muxWebm, type WebmFrame } from \"../export/webmmux.js\";\nimport { zipStore, type ZipEntry } from \"../export/zip.js\";\nimport { parseColor, type ControlValue } from \"../shader/controls.js\";\nimport { ShaderFrames, type RenderOptions } from \"../shader/frames.js\";\nimport { seekVideo, type LiveSource } from \"../shader/textures.js\";\nimport { svgDuration, svgView } from \"../vector/svg.js\";\nimport { subjectValues, type EffectSubject } from \"./index.js\";\n\n/** What {@link recordEffect} makes: a video (`mp4`, `webm`), an animated `gif`, or `png` frames in a ZIP. */\nexport type RecordFormat = \"mp4\" | \"webm\" | \"gif\" | \"png\";\n\n/** The pointer for one frame of a shader: `iPointer`, `iMouse`, and clicks and trail so far (times in seconds). */\nexport type RecordPointer = Pick<RenderOptions, \"pointer\" | \"mouse\" | \"clicks\" | \"trail\">;\n\nexport interface RecordOptions {\n /** What to apply the effect to (see {@link EffectSubject}); several fill several controls in order. */\n subject?: EffectSubject | readonly EffectSubject[];\n /** A preset by name, then these values, over the effect's defaults. */\n preset?: string;\n values?: Record<string, ControlValue>;\n /**\n * The file to make (default `mp4` where the browser encodes H.264, else\n * `webm`; `webm` when `alpha` is on).\n */\n format?: RecordFormat;\n /** Pixels (default 1280 × 720). Videos round them up to even numbers, as their encoders need. */\n width?: number;\n height?: number;\n /** Frames per second (default 30). GIF delays are whole hundredths of a second, so 10, 20, 25 and 50 play back exactly there. */\n fps?: number;\n /**\n * Seconds to record (default: a shader's `loop`, or a vector effect's\n * picture plus its `hold`, else 4).\n */\n duration?: number;\n /** The time of the first frame, in seconds (default 0). */\n start?: number;\n /** Bits per second for `mp4` and `webm` (default `width × height × fps × 0.15`). */\n bitrate?: number;\n /**\n * Keep transparency (default: the effect's `transparent`): `webm` (VP9\n * or VP8 with an alpha channel, which Chrome, Edge and Firefox play),\n * `png`, and `gif` (one see-through colour). `mp4` cannot, so it lays the\n * picture over `background` unless `alpha: true` was asked for. Without\n * it, transparent pixels are laid over `background`.\n */\n alpha?: boolean;\n /** A CSS colour under the picture when `alpha` is off (default black for shaders, white for vector effects). */\n background?: string;\n /**\n * The pointer, for shaders that answer it: the same every frame, or a\n * function of the frame's time in seconds. Without it, interactive\n * effects play their idle demos, as on a page nobody has touched.\n *\n * ```ts\n * pointer: { clicks: [{ x: 640, y: 360, time: 0.5 }] }\n * pointer: (t) => ({ pointer: [640 + 200 * Math.sin(t), 360, 1, 0] })\n * ```\n */\n pointer?: RecordPointer | ((time: number) => RecordPointer);\n /** A vector effect's step start times in ms, for pictures that change on steps (default none). */\n steps?: readonly number[];\n /**\n * Called before each frame is drawn, with its time in seconds: draw a\n * canvas subject for that time here. (A `<video>` subject is paused and\n * sought to each frame's time for you.)\n */\n beforeFrame?: (time: number, index: number) => void | Promise<void>;\n /** Called after each frame with the share done, 0–1. */\n onProgress?: (fraction: number) => void;\n /** Aborting rejects with an `AbortError` `DOMException`. */\n signal?: AbortSignal;\n}\n\n/** What a recording will be, worked out from the options before any frame is drawn (see {@link recordingPlan}). */\nexport interface RecordingPlan {\n effect: EffectDefinition;\n format: RecordFormat;\n width: number;\n height: number;\n fps: number;\n duration: number;\n start: number;\n frames: number;\n alpha: boolean;\n /** For `mp4` and `webm`: the encoder's settings. */\n encoder?: VideoEncoderConfig;\n}\n\nconst DEFAULT_SECONDS = 4;\n\n/** Lets the page repaint between frames so progress shows and Cancel works. */\nconst yieldToBrowser = () => new Promise<void>((resolve) => setTimeout(resolve, 0));\n\nconst formats = (list: RecordFormat[]) => list.map((f) => `\"${f}\"`).join(\", \").replace(/, ([^,]*)$/, \" or $1\");\n\n/** H.264 levels by the most macroblocks a frame and a second may hold, for the codec string. */\nconst AVC_LEVELS: [level: number, frame: number, second: number][] = [\n [0x1f, 3600, 108000], // 3.1\n [0x28, 8192, 245760], // 4.0\n [0x2a, 8704, 522240], // 4.2\n [0x32, 22080, 589824], // 5.0\n [0x33, 36864, 983040], // 5.1\n [0x34, 36864, 2073600], // 5.2\n [0x3c, 139264, 4177920], // 6.0\n];\n\n/** H.264 codec strings to try, High profile first, at the lowest level that holds the picture. */\nfunction avcCodecs(width: number, height: number, fps: number): string[] {\n const mbs = Math.ceil(width / 16) * Math.ceil(height / 16);\n const level = (AVC_LEVELS.find(([, f, s]) => mbs <= f && mbs * fps <= s) ?? AVC_LEVELS[AVC_LEVELS.length - 1]!)[0];\n const hex = level.toString(16).toUpperCase().padStart(2, \"0\");\n return [\"avc1.6400\", \"avc1.4D00\", \"avc1.42E0\"].map((p) => p + hex);\n}\n\n/** The first of `codecs` the browser encodes with these settings, as a config; undefined when none. */\nasync function supported(codecs: string[], base: Omit<VideoEncoderConfig, \"codec\">): Promise<VideoEncoderConfig | undefined> {\n for (const codec of codecs) {\n const config: VideoEncoderConfig = { ...base, codec };\n try {\n const answer = await VideoEncoder.isConfigSupported(config);\n if (answer.supported) return config;\n } catch {\n // A codec string the browser does not know: try the next.\n }\n }\n return undefined;\n}\n\nconst hasWebCodecs = () => typeof VideoEncoder !== \"undefined\" && typeof VideoFrame !== \"undefined\";\n\n/** A video's encoder config, or undefined when the browser cannot encode it. */\nasync function videoConfig(format: \"mp4\" | \"webm\", width: number, height: number, fps: number, bitrate: number) {\n const base: Omit<VideoEncoderConfig, \"codec\"> = {\n width,\n height,\n bitrate,\n framerate: fps,\n latencyMode: \"quality\",\n ...(format === \"mp4\" ? { avc: { format: \"avc\" as const } } : {}),\n };\n return supported(format === \"mp4\" ? avcCodecs(width, height, fps) : [\"vp09.00.10.08\", \"vp8\"], base);\n}\n\nconst resolveEffect = (effect: EffectDefinition | string) => {\n const def = typeof effect === \"string\" ? getEffect(effect) : effect;\n if (!def) throw new Error(`There is no effect \"${String(effect)}\" in the catalog; findEffects() lists them.`);\n return def;\n};\n\n/** A positive number option, or a sentence saying what it should be. */\nfunction positive(name: string, value: number | undefined, fallback: number): number {\n const n = value ?? fallback;\n if (!Number.isFinite(n) || n <= 0) throw new Error(`${name} must be a number above 0 (it was ${String(value)}).`);\n return n;\n}\n\nconst even = (n: number) => Math.max(2, Math.ceil(n / 2) * 2);\n\n/**\n * What {@link recordEffect} would make of these options, without drawing a\n * frame: the format (after falling back where the browser cannot encode\n * one), size, length, frame count, whether it keeps transparency, and the\n * encoder settings. Rejects with a sentence when the effect is unknown, an\n * option is out of range, or the browser cannot make the format asked for.\n */\nexport async function recordingPlan(effect: EffectDefinition | string, options: RecordOptions = {}): Promise<RecordingPlan> {\n const def = resolveEffect(effect);\n if (options.preset && !def.presets?.some((p) => p.name === options.preset)) {\n const names = def.presets?.map((p) => `\"${p.name}\"`).join(\", \");\n throw new Error(`\"${def.id}\" has no preset \"${options.preset}\"${names ? `; it has ${names}` : \"\"}.`);\n }\n const fps = positive(\"fps\", options.fps, 30);\n const start = options.start ?? 0;\n if (!Number.isFinite(start) || start < 0) throw new Error(`start must be 0 or more seconds (it was ${String(options.start)}).`);\n const duration = positive(\"duration\", options.duration, defaultDuration(def, options));\n let width = Math.round(positive(\"width\", options.width, 1280));\n let height = Math.round(positive(\"height\", options.height, 720));\n const explicitAlpha = options.alpha === true;\n let alpha = options.alpha ?? (def.kind === \"shader\" && Boolean(def.transparent));\n let format = options.format;\n if (format && ![\"mp4\", \"webm\", \"gif\", \"png\"].includes(format)) throw new Error(`format is one of \"mp4\", \"webm\", \"gif\" or \"png\" (it was \"${format}\").`);\n if (format === \"mp4\" && alpha) {\n if (explicitAlpha) throw new Error(`An mp4 (H.264) cannot keep transparency; record ${formats([\"webm\", \"png\", \"gif\"])} to keep it, or pass alpha: false.`);\n alpha = false;\n }\n\n let encoder: VideoEncoderConfig | undefined;\n if (format !== \"gif\" && format !== \"png\") {\n if (!hasWebCodecs())\n throw new Error(`This browser cannot encode video (it has no WebCodecs VideoEncoder), so it cannot record ${format ?? \"a video\"}; record ${formats([\"gif\", \"png\"])} instead.`);\n const w = even(width);\n const h = even(height);\n const bitrate = Math.round(positive(\"bitrate\", options.bitrate, w * h * fps * 0.15));\n const tryFormat = (f: \"mp4\" | \"webm\") => videoConfig(f, w, h, fps, bitrate);\n // Transparency needs webm; mp4 is the first choice otherwise, as it plays everywhere.\n const choices: (\"mp4\" | \"webm\")[] = format ? [format] : alpha ? [\"webm\"] : [\"mp4\", \"webm\"];\n for (const f of choices) {\n encoder = await tryFormat(f);\n if (encoder) {\n format = f;\n break;\n }\n }\n if (!encoder && !format && alpha && !explicitAlpha) {\n // Transparency was only the effect's default: an opaque mp4 will do.\n encoder = await tryFormat(\"mp4\");\n if (encoder) {\n format = \"mp4\";\n alpha = false;\n }\n }\n if (!encoder) {\n const asked = format ?? (alpha ? \"webm\" : \"mp4\");\n const other = asked === \"mp4\" ? \"webm\" : \"mp4\";\n if (alpha && asked === \"webm\") throw new Error(`This browser cannot encode VP8 or VP9, so it cannot record a webm with transparency; record ${formats([\"png\", \"gif\"])} to keep it, or pass alpha: false.`);\n const otherWorks = format && (await tryFormat(other));\n const codec = asked === \"mp4\" ? \"H.264\" : \"VP8 or VP9\";\n throw new Error(\n format\n ? `This browser cannot encode ${codec} at ${w} × ${h}, so it cannot record ${asked}; record ${formats(otherWorks ? [other, \"gif\", \"png\"] : [\"gif\", \"png\"])} instead.`\n : `This browser cannot encode H.264, VP8 or VP9 at ${w} × ${h}; record ${formats([\"gif\", \"png\"])} instead.`,\n );\n }\n width = w;\n height = h;\n }\n return { effect: def, format: format!, width, height, fps, duration, start, frames: Math.max(1, Math.round(duration * fps)), alpha, ...(encoder ? { encoder } : {}) };\n}\n\n/** A shader's loop, or a vector effect's picture plus its hold, else 4 seconds. */\nfunction defaultDuration(def: EffectDefinition, options: RecordOptions): number {\n if (def.kind === \"shader\") return def.loop ?? DEFAULT_SECONDS;\n const motion = renderVectorEffect(def, effectValues(def, options).values);\n return (svgDuration(motion, options.steps ?? []) + (def.hold ?? 600)) / 1000;\n}\n\nfunction effectValues(def: EffectDefinition, options: RecordOptions) {\n const values = effectDefaults(def, { ...(options.preset ? { preset: options.preset } : {}), ...(options.values ? { values: options.values } : {}) });\n if (!options.subject) return { values, live: {} as Record<string, LiveSource> };\n const s = subjectValues(def, options.subject);\n return { values: { ...values, ...s.values }, live: s.live };\n}\n\n/** RGBA bytes of one frame. */\ntype Pixels = Uint8ClampedArray<ArrayBuffer>;\n\n/** Draws frames as straight (not premultiplied) RGBA, rows top down. */\ninterface FrameSource {\n frame(time: number, index: number, out: Pixels): Promise<void>;\n dispose(): void;\n}\n\nfunction shaderSource(plan: RecordingPlan, values: Record<string, ControlValue>, live: Record<string, LiveSource>, options: RecordOptions): FrameSource {\n const def = plan.effect as Extract<EffectDefinition, { kind: \"shader\" }>;\n // A transparent effect is drawn with its alpha even when it is not kept, to be laid over the background.\n const frames = new ShaderFrames({ source: def.source, values, width: plan.width, height: plan.height, alpha: plan.alpha || Boolean(def.transparent) });\n const videos: { video: HTMLVideoElement; time: number; paused: boolean }[] = [];\n for (const [name, source] of Object.entries(live)) {\n frames.setLiveSource(name, source);\n if (typeof HTMLVideoElement !== \"undefined\" && source instanceof HTMLVideoElement) {\n videos.push({ video: source, time: source.currentTime, paused: source.paused });\n source.pause();\n }\n }\n const script = options.pointer;\n return {\n async frame(time, index, out) {\n for (const { video } of videos) await seekVideo(video, time);\n await options.beforeFrame?.(time, index);\n await frames.ready();\n const pointer = typeof script === \"function\" ? script(time) : script;\n frames.render(time, { frame: index, delta: 1 / plan.fps, ...pointer });\n frames.readPixels(out);\n },\n dispose() {\n frames.dispose();\n for (const { video, time, paused } of videos) {\n video.currentTime = time;\n if (!paused) void video.play().catch(() => undefined);\n }\n },\n };\n}\n\nfunction vectorSource(plan: RecordingPlan, values: Record<string, ControlValue>, options: RecordOptions): FrameSource {\n const def = plan.effect as Extract<EffectDefinition, { kind: \"vector\" }>;\n const view = svgView(renderVectorEffect(def, values));\n // In the page (out of sight) so its fonts, sizes and colours resolve as they would on screen.\n const host = document.createElement(\"div\");\n host.setAttribute(\"aria-hidden\", \"true\");\n host.style.cssText = `position:fixed;left:-100000px;top:0;width:${plan.width}px;height:${plan.height}px;pointer-events:none;`;\n host.appendChild(view.element);\n document.body.appendChild(host);\n const steps = options.steps ?? [];\n return {\n async frame(time, index, out) {\n await options.beforeFrame?.(time, index);\n view.draw(time * 1000, steps);\n const canvas = await view.capture({ width: plan.width, height: plan.height });\n if (!canvas) throw new Error(`\"${def.id}\" has no picture to record: its SVG does not parse.`);\n out.set(canvas.getContext(\"2d\")!.getImageData(0, 0, plan.width, plan.height).data);\n },\n dispose: () => host.remove(),\n };\n}\n\n/** Lays straight-alpha pixels over an opaque colour, in place. */\nfunction flatten(rgba: Pixels, background: [number, number, number]) {\n const [br, bg, bb] = background;\n for (let i = 0; i < rgba.length; i += 4) {\n const a = rgba[i + 3]!;\n if (a === 255) continue;\n const k = a / 255;\n rgba[i] = rgba[i]! * k + br * (1 - k);\n rgba[i + 1] = rgba[i + 1]! * k + bg * (1 - k);\n rgba[i + 2] = rgba[i + 2]! * k + bb * (1 - k);\n rgba[i + 3] = 255;\n }\n}\n\n/** Turns frames into a file, one at a time. */\ninterface Encoder {\n add(rgba: Pixels, index: number): Promise<void>;\n finish(): Promise<Blob>;\n close(): void;\n}\n\nasync function gifEncoder(plan: RecordingPlan): Promise<Encoder> {\n const { GIFEncoder, quantize, applyPalette } = await import(\"gifenc\");\n const gif = GIFEncoder();\n const delay = 1000 / plan.fps;\n return {\n async add(rgba, i) {\n const repeat = i === 0 ? { repeat: 0 } : {};\n if (!plan.alpha) {\n const palette = quantize(rgba, 256);\n gif.writeFrame(applyPalette(rgba, palette), plan.width, plan.height, { palette, delay, ...repeat });\n return;\n }\n // One colour is see-through: pixels at most half covered. Each frame replaces the last (dispose 2).\n const palette = quantize(rgba, 256, { format: \"rgba4444\", oneBitAlpha: true });\n const transparentIndex = palette.findIndex((c) => c[3] === 0);\n gif.writeFrame(applyPalette(rgba, palette, \"rgba4444\"), plan.width, plan.height, {\n palette,\n delay,\n dispose: 2,\n ...(transparentIndex >= 0 ? { transparent: true, transparentIndex } : {}),\n ...repeat,\n });\n },\n async finish() {\n gif.finish();\n return new Blob([gif.bytes()], { type: \"image/gif\" });\n },\n close() {},\n };\n}\n\nfunction pngEncoder(plan: RecordingPlan): Encoder {\n const canvas = document.createElement(\"canvas\");\n canvas.width = plan.width;\n canvas.height = plan.height;\n const context = canvas.getContext(\"2d\");\n if (!context) throw new Error(\"This browser cannot draw on a canvas, so it cannot make PNG frames.\");\n const entries: ZipEntry[] = [];\n const digits = Math.max(4, String(plan.frames).length);\n return {\n async add(rgba, i) {\n context.putImageData(new ImageData(rgba, plan.width, plan.height), 0, 0);\n const blob = await new Promise<Blob | null>((resolve) => canvas.toBlob(resolve, \"image/png\"));\n if (!blob) throw new Error(\"The browser could not encode a PNG frame.\");\n entries.push({ name: `frame-${String(i + 1).padStart(digits, \"0\")}.png`, data: new Uint8Array(await blob.arrayBuffer()) });\n },\n async finish() {\n return new Blob([zipStore(entries) as Uint8Array<ArrayBuffer>], { type: \"application/zip\" });\n },\n close() {},\n };\n}\n\nconst bytesOf = (source: AllowSharedBufferSource) =>\n source instanceof ArrayBuffer || (typeof SharedArrayBuffer !== \"undefined\" && source instanceof SharedArrayBuffer)\n ? new Uint8Array(source.slice(0))\n : new Uint8Array((source as ArrayBufferView).buffer.slice((source as ArrayBufferView).byteOffset, (source as ArrayBufferView).byteOffset + (source as ArrayBufferView).byteLength));\n\n/** A WebCodecs encoder whose chunks are collected, with the first decoder description it gives. */\nfunction collector(config: VideoEncoderConfig, fail: (e: Error) => void) {\n const chunks: { data: Uint8Array; timestamp: number; duration?: number; key: boolean }[] = [];\n const out = { chunks, description: undefined as Uint8Array | undefined, encoder: undefined as unknown as VideoEncoder };\n out.encoder = new VideoEncoder({\n output(chunk, metadata) {\n const data = new Uint8Array(chunk.byteLength);\n chunk.copyTo(data);\n const desc = metadata?.decoderConfig?.description;\n if (desc && !out.description) out.description = bytesOf(desc);\n chunks.push({ data, timestamp: chunk.timestamp, ...(chunk.duration ? { duration: chunk.duration } : {}), key: chunk.type === \"key\" });\n },\n error: (e) => fail(new Error(`The video encoder failed: ${e.message}`, { cause: e })),\n });\n out.encoder.configure(config);\n return out;\n}\n\n/**\n * Encodes with WebCodecs and muxes into mp4 or webm. With `alpha`, a second\n * encoder (same codec) takes the alpha as a greyscale picture, and each\n * frame's alpha goes beside it in the webm, as Chrome's own recordings do:\n * browsers' encoders do not keep alpha themselves.\n */\nfunction videoEncoder(plan: RecordingPlan): Encoder {\n const config = plan.encoder!;\n let failure: Error | undefined;\n const fail = (e: Error) => (failure ??= e);\n const color = collector(config, fail);\n const alpha = plan.alpha ? collector(config, fail) : undefined;\n const encoders = [color.encoder, ...(alpha ? [alpha.encoder] : [])];\n const frameUs = 1e6 / plan.fps;\n // A keyframe every two seconds, so players can seek.\n const keyEvery = Math.max(1, Math.round(plan.fps * 2));\n const { width, height } = plan;\n // I420: the alpha as luma, with neutral chroma.\n const plane = alpha ? new Uint8Array(width * height * 1.5).fill(128) : undefined;\n const check = () => {\n if (failure) throw failure;\n };\n const encode = (encoder: VideoEncoder, frame: VideoFrame, key: boolean) => {\n try {\n encoder.encode(frame, { keyFrame: key });\n } finally {\n frame.close();\n }\n };\n return {\n async add(rgba, i) {\n check();\n const timing = { codedWidth: width, codedHeight: height, timestamp: Math.round(i * frameUs), duration: Math.round(frameUs) };\n const key = i % keyEvery === 0;\n encode(color.encoder, new VideoFrame(rgba, { format: \"RGBX\", ...timing }), key);\n if (alpha && plane) {\n for (let p = 0, q = 3; p < width * height; p++, q += 4) plane[p] = rgba[q]!;\n encode(alpha.encoder, new VideoFrame(plane, { format: \"I420\", ...timing }), key);\n }\n // Hold back while an encoder is behind, so frames don't pile up in memory.\n while (encoders.some((e) => e.encodeQueueSize > 4) && !failure) await new Promise((resolve) => setTimeout(resolve, 1));\n },\n async finish() {\n await Promise.all(encoders.map((e) => e.flush()));\n check();\n for (const e of encoders) e.close();\n const byTime = (a: { timestamp: number }, b: { timestamp: number }) => a.timestamp - b.timestamp;\n const chunks = color.chunks.sort(byTime);\n if (plan.format === \"mp4\") {\n if (!color.description) throw new Error(\"The H.264 encoder gave no decoder configuration (avcC), so the mp4 cannot be written.\");\n const file = muxMp4({ width, height, avcC: color.description, samples: chunks });\n return new Blob([file as Uint8Array<ArrayBuffer>], { type: \"video/mp4\" });\n }\n const alphas = new Map(alpha?.chunks.map((c) => [c.timestamp, c.data]));\n const frames: WebmFrame[] = chunks.map((c) => {\n const a = alphas.get(c.timestamp);\n if (alpha && !a) throw new Error(`The alpha encoder dropped the frame at ${c.timestamp / 1e6} s, so the webm cannot keep transparency; record \"png\" or \"gif\" instead.`);\n return { ...c, ...(a ? { alpha: a } : {}) };\n });\n const codec = config.codec.startsWith(\"vp8\") ? \"vp8\" : \"vp9\";\n const file = muxWebm({ codec, width, height, frames, duration: plan.frames * frameUs, fps: plan.fps });\n return new Blob([file as Uint8Array<ArrayBuffer>], { type: \"video/webm\" });\n },\n close() {\n for (const e of encoders) if (e.state !== \"closed\") e.close();\n },\n };\n}\n\n/**\n * Records a catalog effect (by id or definition), applied to `subject`, to a\n * file in the browser: an `mp4` or `webm` video (WebCodecs, muxed here with\n * no dependencies), an animated `gif`, or `png` frames.\n *\n * Frames are drawn off screen at exact times (`start + i / fps`), so the\n * result is smooth whatever the page's frame rate, and the same on every\n * machine. Shaders render with `ShaderFrames` (a `<video>` subject is paused\n * and sought to each frame, and put back after); vector effects are drawn\n * with `svgView` and rasterised. Shaders that answer the pointer play their\n * idle demos unless `pointer` scripts it.\n *\n * `png` resolves to a ZIP of numbered frames (`frame-0001.png`, …), so every\n * format is one `Blob` to save or upload.\n *\n * Rejects with a sentence when the effect is unknown, takes no such\n * subject, or the browser cannot make the format (naming the formats that\n * would work); with a `ShaderCompileError` or `ImageLoadError` as\n * `ShaderFrames` does; and with an `AbortError` when `signal` aborts.\n *\n * ```ts\n * const mp4 = await recordEffect(\"image-duotone\", { subject: { image: \"/team.jpg\" }, preset: \"Spotify\" });\n * const gif = await recordEffect(\"typewriter\", { subject: { text: \"Hello\" }, format: \"gif\", width: 640, height: 360, fps: 25 });\n * const webm = await recordEffect(\"click-ripple\", { format: \"webm\", alpha: true, pointer: { clicks: [{ x: 640, y: 360, time: 0.2 }] } });\n * ```\n */\nexport async function recordEffect(effect: EffectDefinition | string, options: RecordOptions = {}): Promise<Blob> {\n const plan = await recordingPlan(effect, options);\n const { signal, onProgress } = options;\n const { values, live } = effectValues(plan.effect, options);\n const background = (parseColor(options.background ?? (plan.effect.kind === \"shader\" ? \"#000000\" : \"#ffffff\")) ?? [0, 0, 0]).map((c) => Math.round(c * 255)) as [number, number, number];\n\n const source = plan.effect.kind === \"shader\" ? shaderSource(plan, values, live, options) : vectorSource(plan, values, options);\n let encoder: Encoder | undefined;\n try {\n encoder = plan.format === \"gif\" ? await gifEncoder(plan) : plan.format === \"png\" ? pngEncoder(plan) : videoEncoder(plan);\n const rgba = new Uint8ClampedArray(plan.width * plan.height * 4);\n for (let i = 0; i < plan.frames; i++) {\n if (signal?.aborted) throw new DOMException(\"Cancelled\", \"AbortError\");\n await source.frame(plan.start + i / plan.fps, i, rgba);\n if (!plan.alpha) flatten(rgba, background);\n await encoder.add(rgba, i);\n onProgress?.((i + 1) / plan.frames);\n if (i % 2 === 1) await yieldToBrowser();\n }\n if (signal?.aborted) throw new DOMException(\"Cancelled\", \"AbortError\");\n return await encoder.finish();\n } finally {\n encoder?.close();\n source.dispose();\n }\n}\n","/**\n * Catalog effects on a page in one call: pick an effect, give it what it\n * takes (a picture, a video, an SVG, words or a path) and get it running.\n *\n * - Pairing: `subjectValues` turns a subject into the control values (and\n * live sources) an effect needs, using `effectInputs`.\n * - Embedding: `mountEffect` runs a shader effect (`ShaderRenderer`) or a\n * vector effect (`SvgPlayer`) in an element, with its subject.\n *\n * @packageDocumentation\n */\n\nimport { effectDefaults, effectInputs, getEffect, textImage, type EffectDefinition, type ImageSlot, type TextSlot } from \"../catalog/index.js\";\nimport { renderVectorEffect } from \"../catalog/types.js\";\nimport type { ControlValue } from \"../shader/controls.js\";\nimport { ShaderRenderer } from \"../shader/renderer.js\";\nimport type { LiveSource } from \"../shader/textures.js\";\nimport { SvgPlayer } from \"../vector/svg.js\";\n\nexport { recordEffect, recordingPlan, type RecordFormat, type RecordOptions, type RecordPointer, type RecordingPlan } from \"./record.js\";\n\n/**\n * What an effect is applied to:\n * - `{ image }`: a picture's URL (or `data:` URL).\n * - `{ video }`: a playing `<video>` (or a canvas), shown live.\n * - `{ svg }`: an SVG, as markup (`\"<svg …>\"`) or a URL; drawn as a picture, keeping its transparency.\n * - `{ text }`: words, for a vector effect's text, or drawn with `textImage` for a shader's text or mask.\n * - `{ path }`: SVG path data (`d`), for a shape control.\n */\nexport type EffectSubject =\n | { image: string }\n | { video: LiveSource }\n | { svg: string }\n | { text: string; font?: string; weight?: number | string }\n | { path: string };\n\n/** What a subject becomes for an effect: control values, and live sources by image control. */\nexport interface SubjectValues {\n values: Record<string, ControlValue>;\n live: Record<string, LiveSource>;\n}\n\nconst kindOf = (subject: EffectSubject) => Object.keys(subject).find((k) => k !== \"font\" && k !== \"weight\") as \"image\" | \"video\" | \"svg\" | \"text\" | \"path\";\n\n/** An SVG as a URL: markup becomes a UTF-8 `data:` URL; a URL stays as it is. */\nfunction svgUrl(svg: string): string {\n const markup = svg.trim();\n if (!markup.startsWith(\"<\")) return svg;\n const withNs = /\\sxmlns\\s*=/.test(markup.slice(0, markup.indexOf(\">\") + 1)) ? markup : markup.replace(/^<svg/i, '<svg xmlns=\"http://www.w3.org/2000/svg\"');\n return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(withNs)}`;\n}\n\nfunction pick<T extends { name: string }>(slots: T[], wanted: (s: T) => boolean, name: string | undefined, effect: EffectDefinition, what: string): T {\n const slot = name ? slots.find((s) => s.name === name) : slots.find(wanted);\n if (!slot) {\n const names = slots.map((s) => s.name).join(\", \");\n throw new Error(\n name\n ? `\"${effect.id}\" has no control \"${name}\" for ${what}${names ? `; it has ${names}` : \"\"}.`\n : `\"${effect.id}\" takes no ${what}; see effectInputs(effect).accepts, or findEffects({ accepts: [...] }) for effects that do.`,\n );\n }\n return slot;\n}\n\n/**\n * The control values (and live sources) that put `subject` in `effect`,\n * into the control named `slot` or the first that suits it: a picture or\n * SVG into an image control, a video into a picture control as a live\n * source, words into a vector effect's text or (drawn by `textImage`) a\n * shader's text or mask control, path data into a shape control. Several\n * subjects fill several controls in order (a transition's from and to).\n * Throws a sentence when the effect takes no such thing.\n */\nexport function subjectValues(effect: EffectDefinition, subject: EffectSubject | readonly EffectSubject[], slot?: string): SubjectValues {\n const out: SubjectValues = { values: {}, live: {} };\n const inputs = effectInputs(effect);\n const used = new Set<string>();\n for (const s of Array.isArray(subject) ? subject : [subject as EffectSubject]) {\n const kind = kindOf(s);\n const free = <T extends { name: string }>(slots: T[]) => slots.filter((x) => !used.has(x.name));\n if (kind === \"path\" || (kind === \"text\" && effect.kind === \"vector\")) {\n const holds = kind === \"path\" ? \"path\" : \"copy\";\n const text = pick<TextSlot>(free(inputs.texts), (t) => t.holds === holds, slot, effect, kind === \"path\" ? \"path data\" : \"text\");\n out.values[text.name] = kind === \"path\" ? (s as { path: string }).path : (s as { text: string }).text;\n used.add(text.name);\n continue;\n }\n if (effect.kind === \"vector\")\n throw new Error(`\"${effect.id}\" is a vector effect: it draws its own picture and takes words or path data (${inputs.accepts.join(\", \") || \"nothing\"}), not ${{ svg: \"an SVG\", image: \"an image\", video: \"a video\" }[kind as \"svg\" | \"image\" | \"video\"]}.`);\n const wanted = (x: ImageSlot) =>\n kind === \"text\" ? x.wants !== \"picture\" : kind === \"video\" ? x.wants === \"picture\" : true;\n const image = pick<ImageSlot>(free(inputs.images), wanted, slot, effect, kind === \"text\" ? \"text\" : `${kind === \"svg\" ? \"SVG\" : kind}`);\n used.add(image.name);\n if (kind === \"video\") {\n if (!inputs.accepts.includes(\"video\")) throw new Error(`\"${effect.id}\" is not made for video (video: \"${inputs.video}\"); give it a picture.`);\n out.live[image.name] = (s as { video: LiveSource }).video;\n } else if (kind === \"text\") {\n const t = s as { text: string; font?: string; weight?: number | string };\n out.values[image.name] = textImage(t.text, { ...(t.font ? { font: t.font } : {}), ...(t.weight !== undefined ? { weight: t.weight } : {}) });\n } else out.values[image.name] = kind === \"svg\" ? svgUrl((s as { svg: string }).svg) : (s as { image: string }).image;\n }\n return out;\n}\n\nexport interface MountOptions {\n /** What to apply the effect to (see {@link EffectSubject}); several fill several controls in order. */\n subject?: EffectSubject | readonly EffectSubject[];\n /** A preset by name, then these values, over the effect's defaults. */\n preset?: string;\n values?: Record<string, ControlValue>;\n /** Start playing at once (default true). */\n autoplay?: boolean;\n /** Class for the canvas (shaders) or the player's element (vector effects). */\n className?: string;\n /** Pause while scrolled out of view (default true). */\n pauseWhenHidden?: boolean;\n}\n\n/** A running effect, from {@link mountEffect}. */\nexport interface MountedEffect {\n readonly effect: EffectDefinition;\n /** What it draws into: the shader's canvas, or the vector player's element. */\n readonly element: HTMLElement;\n /** The shader renderer, for a shader effect. */\n readonly renderer?: ShaderRenderer;\n /** The vector player, for a vector effect (replaced when values change). */\n readonly player?: SvgPlayer;\n /** Applies it to something else. */\n setSubject(subject: EffectSubject | readonly EffectSubject[]): void;\n /** Changes control values (merged over the current ones). */\n setValues(values: Record<string, ControlValue>): void;\n play(): void;\n pause(): void;\n /** Stops it and removes what it drew. */\n dispose(): void;\n}\n\n/**\n * Runs a catalog effect (by id or definition) in `host`, applied to\n * `subject`: a shader on a canvas (transparent for overlays, so it lays over\n * the page), or a vector effect in an SVG player that answers its trigger\n * (hover, press, click). Throws a sentence when the effect is unknown or\n * takes no such subject.\n *\n * ```ts\n * mountEffect(el, \"image-duotone\", { subject: { image: \"/team.jpg\" }, preset: \"Spotify\" });\n * mountEffect(el, \"crt\", { subject: { video: videoElement } });\n * mountEffect(el, \"typewriter\", { subject: { text: \"Hello there\" } });\n * mountEffect(el, \"neon-outline\", { subject: { svg: logoMarkup } });\n * ```\n */\nexport function mountEffect(host: HTMLElement, effect: EffectDefinition | string, options: MountOptions = {}): MountedEffect {\n const def = typeof effect === \"string\" ? getEffect(effect) : effect;\n if (!def) throw new Error(`There is no effect \"${String(effect)}\" in the catalog; findEffects() lists them.`);\n let values: Record<string, ControlValue> = { ...effectDefaults(def, { ...(options.preset ? { preset: options.preset } : {}), ...(options.values ? { values: options.values } : {}) }) };\n let live: Record<string, LiveSource> = {};\n const apply = (subject: EffectSubject | readonly EffectSubject[] | undefined) => {\n if (!subject) return;\n const s = subjectValues(def, subject);\n values = { ...values, ...s.values };\n live = s.live;\n };\n apply(options.subject);\n\n if (def.kind === \"shader\") {\n const renderer = new ShaderRenderer(host, {\n alpha: Boolean(def.transparent),\n autoplay: options.autoplay ?? true,\n pauseWhenHidden: options.pauseWhenHidden ?? true,\n ...(options.className ? { className: options.className } : {}),\n });\n renderer.setSource(def.source);\n renderer.setValues(values);\n const setLive = (previous: Record<string, LiveSource>) => {\n for (const name of Object.keys(previous)) if (!(name in live)) renderer.setLiveSource(name, null);\n for (const [name, source] of Object.entries(live)) renderer.setLiveSource(name, source);\n };\n setLive({});\n return {\n effect: def,\n element: renderer.canvas,\n renderer,\n setSubject(subject) {\n const before = live;\n apply(subject);\n renderer.setValues(values);\n setLive(before);\n },\n setValues(next) {\n values = { ...values, ...next };\n renderer.setValues(values);\n },\n play: () => renderer.play(),\n pause: () => renderer.pause(),\n dispose: () => renderer.dispose(),\n };\n }\n\n let player: SvgPlayer;\n const build = () => {\n player?.dispose();\n player = new SvgPlayer(host, renderVectorEffect(def, values), {\n hold: def.hold,\n ...(def.trigger ? { trigger: def.trigger } : {}),\n autoplay: options.autoplay ?? true,\n pauseWhenHidden: options.pauseWhenHidden ?? true,\n });\n if (options.className) player.view.element.className = options.className;\n };\n build();\n return {\n effect: def,\n get element() {\n return player.view.element;\n },\n get player() {\n return player;\n },\n setSubject(subject) {\n apply(subject);\n build();\n },\n setValues(next) {\n values = { ...values, ...next };\n build();\n },\n play: () => player.play(),\n pause: () => player.pause(),\n dispose: () => player.dispose(),\n };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AA+BA,IAAM,kBAAkB;AACxB,IAAM,SAAS;AAEf,IAAM,QAAQ,CAAC,MAAc,WAAW,KAAK,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAGtE,IAAM,SAAN,MAAa;AAAA,EACX,QAAsB,CAAC;AAAA,EACvB,OAAO;AAAA,EACP,MAAM,GAAe;AACnB,SAAK,MAAM,KAAK,CAAC;AACjB,SAAK,QAAQ,EAAE;AACf,WAAO;AAAA,EACT;AAAA,EACA,GAAG,GAAW;AACZ,WAAO,KAAK,MAAM,WAAW,GAAG,IAAI,GAAI,CAAC;AAAA,EAC3C;AAAA,EACA,IAAI,GAAW;AACb,WAAO,KAAK,MAAM,WAAW,GAAI,MAAM,IAAK,KAAM,IAAI,GAAI,CAAC;AAAA,EAC7D;AAAA,EACA,IAAI,GAAW;AACb,UAAM,IAAI,IAAI,WAAW,CAAC;AAC1B,QAAI,SAAS,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC;AAC3C,WAAO,KAAK,MAAM,CAAC;AAAA,EACrB;AAAA,EACA,IAAI,GAAW;AACb,WAAO,KAAK,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,EAAE,IAAI,IAAI,MAAM;AAAA,EACxD;AAAA,EACA,MAAM,GAAW;AACf,WAAO,KAAK,MAAM,IAAI,WAAW,CAAC,CAAC;AAAA,EACrC;AAAA,EACA,OAAmB;AACjB,UAAM,MAAM,IAAI,WAAW,KAAK,IAAI;AACpC,QAAI,KAAK;AACT,eAAW,KAAK,KAAK,OAAO;AAC1B,UAAI,IAAI,GAAG,EAAE;AACb,YAAM,EAAE;AAAA,IACV;AACA,WAAO;AAAA,EACT;AACF;AAGA,SAAS,IAAI,SAAiB,SAAmC;AAC/D,QAAM,IAAI,IAAI,OAAO;AACrB,QAAM,OAAO,IAAI,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AACzD,IAAE,IAAI,IAAI,EAAE,MAAM,MAAM,IAAI,CAAC;AAC7B,aAAW,KAAK,QAAS,GAAE,MAAM,CAAC;AAClC,SAAO,EAAE,KAAK;AAChB;AAGA,SAAS,QAAQ,MAAc,SAAiB,UAAkB,SAAmC;AACnG,SAAO,IAAI,MAAM,WAAW,GAAG,SAAU,SAAS,KAAM,KAAO,SAAS,IAAK,KAAM,QAAQ,GAAI,GAAG,GAAG,OAAO;AAC9G;AAEA,IAAM,SAAS,CAAC,SAAiC;AAC/C,QAAM,IAAI,IAAI,OAAO;AACrB,OAAK,CAAC;AACN,SAAO,EAAE,KAAK;AAChB;AAGA,IAAM,SAAS,OAAO,CAAC,MAAM,CAAC,OAAS,GAAG,GAAG,GAAG,OAAS,GAAG,GAAG,GAAG,UAAU,EAAE,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,CAAC;AAMtG,SAAS,YAAY,SAA+B,WAA6B;AAC/E,QAAM,OAAO,CAAC,OAAe,KAAK,MAAO,KAAK,YAAa,GAAG;AAC9D,SAAO,QAAQ,IAAI,CAAC,GAAG,MAAM;AAC3B,UAAM,OAAO,QAAQ,IAAI,CAAC;AAC1B,QAAI,KAAM,QAAO,KAAK,IAAI,GAAG,KAAK,KAAK,SAAS,IAAI,KAAK,EAAE,SAAS,CAAC;AACrE,QAAI,EAAE,SAAU,QAAO,KAAK,IAAI,GAAG,KAAK,EAAE,QAAQ,CAAC;AACnD,UAAM,OAAO,QAAQ,IAAI,CAAC;AAC1B,WAAO,OAAO,KAAK,IAAI,GAAG,KAAK,EAAE,SAAS,IAAI,KAAK,KAAK,SAAS,CAAC,IAAI,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;AAAA,EAClG,CAAC;AACH;AAGA,SAAS,KAAK,OAA6B;AACzC,QAAM,OAA2B,CAAC;AAClC,aAAW,KAAK,OAAO;AACrB,UAAM,OAAO,KAAK,KAAK,SAAS,CAAC;AACjC,QAAI,QAAQ,KAAK,CAAC,MAAM,EAAG,MAAK,CAAC;AAAA,QAC5B,MAAK,KAAK,CAAC,GAAG,CAAC,CAAC;AAAA,EACvB;AACA,SAAO,QAAQ,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAM;AACzC,MAAE,IAAI,KAAK,MAAM;AACjB,eAAW,CAAC,OAAO,KAAK,KAAK,KAAM,GAAE,IAAI,KAAK,EAAE,IAAI,KAAK;AAAA,EAC3D,CAAC,CAAC;AACJ;AAEA,SAAS,KAAK,SAAqB,OAAiB,YAAoB,MAA2B;AACjG,QAAM,EAAE,OAAO,QAAQ,MAAM,QAAQ,IAAI;AACzC,QAAM,YAAY,QAAQ,aAAa;AACvC,QAAM,aAAa,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC;AAClD,QAAM,aAAa,KAAK,MAAO,aAAa,kBAAmB,SAAS;AAExE,QAAM,OAAO,QAAQ,QAAQ,GAAG,GAAG;AAAA,IAAO,CAAC,MACzC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,eAAe,EAAE,IAAI,UAAU,EAChD,IAAI,KAAU,EAAE,IAAI,GAAM,EAAE,MAAM,EAAE,EACpC,MAAM,MAAM,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC;AAAA;AAAA,EAClC,CAAC;AACD,QAAM,OAAO,QAAQ,QAAQ,GAAG,GAAG;AAAA,IAAO,CAAC;AAAA;AAAA,MACzC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,UAAU,EACzC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EACnC,MAAM,MAAM,EAAE,IAAI,QAAQ,KAAO,EAAE,IAAI,SAAS,KAAO;AAAA;AAAA,EAC5D,CAAC;AACD,QAAM,OAAO,QAAQ,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,SAAS,EAAE,IAAI,UAAU,EAAE,IAAI,KAAM,EAAE,IAAI,CAAC,CAAC,CAAC;AACnH,QAAM,OAAO,QAAQ,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,MAAM,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,MAAM,MAAM,gBAAgB,CAAC,CAAC,CAAC;AACxH,QAAM,OAAO,QAAQ,QAAQ,GAAG,GAAG,IAAI,WAAW,CAAC,CAAC;AACpD,QAAM,OAAO,IAAI,QAAQ,QAAQ,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,QAAQ,QAAQ,GAAG,CAAC,CAAC,CAAC;AAE9F,QAAM,OAAO;AAAA,IACX;AAAA,IACA;AAAA,MAAO,CAAC,MACN,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,EACb,MAAM,EAAE,EAAE,IAAI,KAAK,EAAE,IAAI,MAAM,EAC/B,IAAI,OAAU,EAAE,IAAI,OAAU,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAC5C,MAAM,EAAE,EAAE,IAAI,EAAM,EAAE,IAAI,KAAM;AAAA;AAAA,IACrC;AAAA,IACA,IAAI,QAAQ,IAAI;AAAA,EAClB;AACA,QAAM,OAAO,QAAQ,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI;AAChE,QAAM,OAAO,QAAQ,QAAQ,CAAC,GAAG,MAAO,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAE;AAE7D,QAAM,OAAO,KAAK,WAAW,QAAQ,SAAS,CAAC,IAAI,CAAC,QAAQ,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAM;AACtF,MAAE,IAAI,KAAK,MAAM;AACjB,eAAW,KAAK,KAAM,GAAE,IAAI,CAAC;AAAA,EAC/B,CAAC,CAAC,CAAC;AACH,QAAM,OAAO,QAAQ,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAM;AAC/C,MAAE,IAAI,CAAC,EAAE,IAAI,QAAQ,MAAM;AAC3B,eAAW,KAAK,QAAS,GAAE,IAAI,EAAE,KAAK,MAAM;AAAA,EAC9C,CAAC,CAAC;AAEF,QAAM,OAAO,QAAQ,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAO,QAAQ,SAAS,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI,QAAQ,MAAM,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAE,CAAC;AAC1H,QAAM,OAAO,OACT,QAAQ,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,UAAU,CAAC,CAAC,IAC7D,QAAQ,QAAQ,GAAG,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,UAAU,CAAC,CAAC;AACjE,QAAM,OAAO,IAAI,QAAQ,MAAM,KAAK,KAAK,GAAG,GAAG,MAAM,MAAM,MAAM,IAAI;AACrE,QAAM,OAAO,IAAI,QAAQ,MAAM,MAAM,IAAI;AACzC,QAAM,OAAO,IAAI,QAAQ,MAAM,IAAI,QAAQ,MAAM,MAAM,IAAI,CAAC;AAC5D,SAAO,IAAI,QAAQ,MAAM,IAAI;AAC/B;AAMO,SAAS,OAAO,SAAiC;AACtD,QAAM,EAAE,QAAQ,IAAI;AACpB,MAAI,CAAC,QAAQ,OAAQ,OAAM,IAAI,MAAM,kCAAkC;AACvE,MAAI,CAAC,QAAQ,CAAC,EAAG,IAAK,OAAM,IAAI,MAAM,0CAA0C;AAChF,QAAM,OAAO,IAAI,QAAQ,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,IAAI,GAAK,CAAC,GAAG,MAAM,kBAAkB,CAAC;AAC9F,QAAM,QAAQ,YAAY,SAAS,QAAQ,aAAa,GAAK;AAC7D,QAAM,UAAU,QAAQ,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,KAAK,QAAQ,CAAC;AAC7D,QAAM,QAAQ,UAAU,KAAK;AAC7B,QAAM,aAAa,QAAQ,KAAK;AAEhC,QAAM,OAAO,KAAK,SAAS,KAAK,SAAS,OAAO,GAAG,KAAK,EAAE,SAAS,aAAa,WAAW;AAC3F,QAAM,QAAQ,KAAK,SAAS,OAAO,GAAG,IAAI;AAC1C,QAAM,aAAa,KAAK,SAAS,MAAM,SAAS;AAChD,QAAM,OAAO,OAAO,CAAC,MAAM;AACzB,MAAE,MAAM,IAAI,EAAE,MAAM,KAAK,SAAS,OAAO,YAAY,IAAI,CAAC;AAC1D,QAAI,MAAO,GAAE,IAAI,CAAC,EAAE,MAAM,MAAM,MAAM,CAAC,EAAE,IAAI,UAAU,EAAE;AAAA,QACpD,GAAE,IAAI,UAAU,CAAC,EAAE,MAAM,MAAM,MAAM,CAAC;AAAA,EAC7C,CAAC;AACD,QAAM,MAAM,IAAI,WAAW,KAAK,SAAS,OAAO;AAChD,MAAI,IAAI,IAAI;AACZ,MAAI,KAAK,KAAK;AACd,aAAW,KAAK,SAAS;AACvB,QAAI,IAAI,EAAE,MAAM,EAAE;AAClB,UAAM,EAAE,KAAK;AAAA,EACf;AACA,SAAO;AACT;;;AC3KA,IAAM,KAAK;AAAA,EACT,MAAM;AAAA,EACN,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,SAAS;AAAA,EACT,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,SAAS;AAAA,EACT,MAAM;AAAA,EACN,gBAAgB;AAAA,EAChB,UAAU;AAAA,EACV,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,QAAQ;AAAA,EACR,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,UAAU;AAAA,EACV,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,SAAS;AAAA,EACT,iBAAiB;AAAA,EACjB,oBAAoB;AAAA,EACpB,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,WAAW;AAAA,EACX,SAAS;AAAA,EACT,WAAW;AAAA,EACX,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,OAAO;AAAA,EACP,gBAAgB;AAAA,EAChB,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,iBAAiB;AACnB;AAGA,IAAM,WAAW;AAEjB,IAAM,aAAa;AAEnB,IAAM,SAAS,CAAC,UAAiC;AAC/C,QAAM,MAAM,IAAI,WAAW,MAAM,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC,CAAC;AAClE,MAAI,KAAK;AACT,aAAW,KAAK,OAAO;AACrB,QAAI,IAAI,GAAG,EAAE;AACb,UAAM,EAAE;AAAA,EACV;AACA,SAAO;AACT;AAGA,SAAS,QAAQ,IAAwB;AACvC,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,IAAI,IAAI,GAAG,IAAI,KAAK,MAAM,IAAI,GAAG,EAAG,KAAI,QAAQ,IAAI,GAAI;AACrE,SAAO,WAAW,KAAK,GAAG;AAC5B;AAGO,SAAS,KAAK,GAAuB;AAC1C,WAAS,MAAM,GAAG,OAAO,GAAG,OAAO;AAEjC,QAAI,IAAI,MAAM,IAAI,OAAO,GAAG;AAC1B,YAAM,MAAM,IAAI,WAAW,GAAG;AAC9B,UAAI,IAAI;AACR,eAAS,IAAI,MAAM,GAAG,KAAK,GAAG,KAAK;AACjC,YAAI,CAAC,IAAI,IAAI;AACb,YAAI,KAAK,MAAM,IAAI,GAAG;AAAA,MACxB;AACA,UAAI,CAAC,KAAM,KAAM,IAAI;AACrB,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,IAAI,WAAW,0BAA0B,CAAC,GAAG;AACrD;AAEA,IAAM,KAAK,CAAC,OAAe,YAA0B;AACnD,QAAM,OAAO,OAAO,OAAO;AAC3B,SAAO,OAAO,CAAC,QAAQ,EAAE,GAAG,KAAK,KAAK,MAAM,GAAG,IAAI,CAAC;AACtD;AAEA,IAAM,OAAO,CAAC,IAAY,MAAc;AACtC,QAAM,MAAgB,CAAC;AACvB,WAAS,IAAI,GAAG,IAAI,KAAK,IAAI,WAAW,GAAG,IAAI,KAAK,MAAM,IAAI,GAAG,EAAG,KAAI,QAAQ,IAAI,GAAG;AACvF,SAAO,GAAG,IAAI,WAAW,KAAK,GAAG,CAAC;AACpC;AAEA,IAAM,QAAQ,CAAC,IAAY,MAAc;AACvC,QAAM,IAAI,IAAI,WAAW,CAAC;AAC1B,MAAI,SAAS,EAAE,MAAM,EAAE,WAAW,GAAG,CAAC;AACtC,SAAO,GAAG,IAAI,CAAC;AACjB;AAEA,IAAM,MAAM,CAAC,IAAY,MAAc,GAAG,IAAI,IAAI,YAAY,EAAE,OAAO,CAAC,CAAC;AAGzE,SAAS,YAAY,QAAgB,OAA2B;AAC9D,QAAM,IAAI,IAAI,WAAW,CAAC;AAC1B,IAAE,CAAC,IAAI;AACP,MAAI,SAAS,EAAE,MAAM,EAAE,SAAS,GAAG,MAAM;AACzC,IAAE,CAAC,IAAI;AACP,SAAO;AACT;AAMO,SAAS,QAAQ,SAAkC;AACxD,QAAM,EAAE,OAAO,OAAO,QAAQ,QAAQ,IAAI,IAAI;AAC9C,MAAI,CAAC,OAAO,OAAQ,OAAM,IAAI,MAAM,kCAAkC;AACtE,MAAI,CAAC,OAAO,CAAC,EAAG,IAAK,OAAM,IAAI,MAAM,0CAA0C;AAC/E,QAAM,QAAQ,OAAO,KAAK,CAAC,MAAM,EAAE,KAAK;AACxC,QAAM,KAAK,CAAC,OAAe,KAAK,MAAM,KAAK,GAAI;AAC/C,QAAM,OAAO,OAAO,OAAO,SAAS,CAAC;AACrC,QAAM,UAAU,MAAM,MAAM,MAAM,OAAO,SAAS,KAAK,KAAK,YAAY,OAAO,CAAC,EAAG,cAAc,OAAO,SAAS,KAAK,MAAM;AAC5H,QAAM,aAAa,QAAQ,YAAY,KAAK,YAAY;AAExD,QAAM,SAAS;AAAA,IACb,GAAG;AAAA,IACH,KAAK,GAAG,aAAa,CAAC;AAAA,IACtB,KAAK,GAAG,iBAAiB,CAAC;AAAA,IAC1B,KAAK,GAAG,iBAAiB,CAAC;AAAA,IAC1B,KAAK,GAAG,mBAAmB,CAAC;AAAA,IAC5B,IAAI,GAAG,SAAS,MAAM;AAAA;AAAA,IAEtB,KAAK,GAAG,gBAAgB,QAAQ,IAAI,CAAC;AAAA,IACrC,KAAK,GAAG,oBAAoB,CAAC;AAAA,EAC/B;AACA,QAAM,OAAO;AAAA,IACX,GAAG;AAAA,IACH,KAAK,GAAG,gBAAgB,QAAQ;AAAA,IAChC,MAAM,GAAG,UAAU,aAAa,GAAI;AAAA,IACpC,IAAI,GAAG,WAAW,OAAO;AAAA,IACzB,IAAI,GAAG,YAAY,QAAQ,OAAO,OAAO;AAAA,EAC3C;AACA,QAAM,SAAS;AAAA,IACb,GAAG;AAAA,IACH;AAAA,MACE,GAAG;AAAA,MACH,KAAK,GAAG,aAAa,CAAC;AAAA,MACtB,KAAK,GAAG,UAAU,CAAC;AAAA,MACnB,KAAK,GAAG,WAAW,CAAC;AAAA;AAAA,MACpB,KAAK,GAAG,YAAY,CAAC;AAAA,MACrB,IAAI,GAAG,SAAS,UAAU,QAAQ,UAAU,OAAO;AAAA,MACnD,GAAI,MAAM,CAAC,KAAK,GAAG,iBAAiB,KAAK,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC;AAAA,MAC/D,GAAI,QAAQ,CAAC,KAAK,GAAG,oBAAoB,CAAC,CAAC,IAAI,CAAC;AAAA,MAChD,GAAG,GAAG,OAAO,KAAK,GAAG,YAAY,KAAK,GAAG,KAAK,GAAG,aAAa,MAAM,GAAG,GAAI,QAAQ,CAAC,KAAK,GAAG,WAAW,CAAC,CAAC,IAAI,CAAC,CAAE;AAAA,IAClH;AAAA,EACF;AAEA,QAAM,WAAyB,CAAC;AAChC,MAAI,SAAuB,CAAC;AAC5B,MAAI,YAAY;AAChB,MAAI,aAAa;AACjB,QAAM,QAAQ,MAAM;AAClB,QAAI,OAAO,OAAQ,UAAS,KAAK,GAAG,GAAG,SAAS,KAAK,GAAG,WAAW,SAAS,GAAG,GAAG,MAAM,CAAC;AACzF,aAAS,CAAC;AAAA,EACZ;AACA,SAAO,QAAQ,CAAC,OAAO,MAAM;AAC3B,UAAM,KAAK,GAAG,MAAM,SAAS;AAC7B,QAAI,MAAM,KAAK,MAAM,OAAO,KAAK,YAAY,YAAY;AACvD,YAAM;AACN,kBAAY;AAAA,IACd;AACA,UAAM,SAAS,KAAK;AACpB,QAAI,MAAM,OAAO;AACf,aAAO;AAAA,QACL;AAAA,UACE,GAAG;AAAA,UACH,GAAG,GAAG,OAAO,YAAY,QAAQ,CAAC,GAAG,MAAM,IAAI;AAAA,UAC/C,GAAG,GAAG,gBAAgB,GAAG,GAAG,WAAW,KAAK,GAAG,YAAY,CAAC,GAAG,GAAG,GAAG,iBAAiB,MAAM,KAAK,CAAC,CAAC;AAAA,UAEnG,GAAI,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,GAAG,gBAAgB,OAAO,aAAa,EAAE,CAAC,CAAC;AAAA,QACtE;AAAA,MACF;AAAA,IACF,OAAO;AACL,aAAO,KAAK,GAAG,GAAG,aAAa,YAAY,QAAQ,MAAM,MAAM,MAAO,CAAC,GAAG,MAAM,IAAI,CAAC;AAAA,IACvF;AACA,iBAAa;AAAA,EACf,CAAC;AACD,QAAM;AAEN,QAAM,UAAU,GAAG,GAAG,SAAS,MAAM,QAAQ,GAAG,QAAQ;AACxD,SAAO,OAAO,CAAC,QAAQ,OAAO,CAAC;AACjC;AAGA,SAAS,OAAO,GAAuB;AACrC,WAAS,MAAM,GAAG,OAAO,GAAG,OAAO;AACjC,QAAI,KAAK,EAAE,MAAM,IAAI,MAAM,OAAO,IAAI,MAAM,IAAI,MAAM,IAAI;AACxD,YAAM,MAAM,IAAI,WAAW,GAAG;AAC9B,UAAI,IAAI,IAAI,IAAI,MAAM,IAAI,OAAO,IAAI;AACrC,eAAS,IAAI,MAAM,GAAG,KAAK,GAAG,KAAK;AACjC,YAAI,CAAC,IAAI,IAAI;AACb,YAAI,KAAK,MAAM,IAAI,GAAG;AAAA,MACxB;AACA,aAAO;AAAA,IACT;AAAA,EACF;AACA,QAAM,IAAI,WAAW,GAAG,CAAC,mBAAmB;AAC9C;;;ACxOA,IAAI;AAGG,SAAS,MAAM,MAA0B;AAC9C,YAAU,YAAY,KAAK,EAAE,QAAQ,IAAI,GAAG,CAAC,GAAG,MAAM;AACpD,QAAI,IAAI;AACR,aAAS,IAAI,GAAG,IAAI,GAAG,IAAK,KAAI,IAAI,IAAI,aAAc,MAAM,IAAK,MAAM;AACvE,WAAO,MAAM;AAAA,EACf,CAAC;AACD,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,IAAK,OAAM,OAAO,MAAM,KAAK,CAAC,KAAM,GAAI,IAAM,QAAQ;AACvF,UAAQ,MAAM,gBAAgB;AAChC;AAGA,IAAM,WAAY,KAAK,IAAM,KAAK,IAAK;AAMhC,SAAS,SAAS,SAA0C;AACjE,QAAM,UAAU,IAAI,YAAY;AAChC,QAAM,SAAuB,CAAC;AAC9B,QAAM,WAAyB,CAAC;AAChC,MAAI,SAAS;AACb,aAAW,EAAE,MAAM,KAAK,KAAK,SAAS;AACpC,UAAM,YAAY,QAAQ,OAAO,IAAI;AACrC,UAAM,MAAM,MAAM,IAAI;AACtB,UAAM,QAAQ,IAAI,WAAW,KAAK,UAAU,MAAM;AAClD,UAAM,IAAI,IAAI,SAAS,MAAM,MAAM;AACnC,MAAE,UAAU,GAAG,UAAY,IAAI;AAC/B,MAAE,UAAU,GAAG,IAAI,IAAI;AACvB,MAAE,UAAU,GAAG,MAAQ,IAAI;AAC3B,MAAE,UAAU,GAAG,GAAG,IAAI;AACtB,MAAE,UAAU,IAAI,GAAG,IAAI;AACvB,MAAE,UAAU,IAAI,UAAU,IAAI;AAC9B,MAAE,UAAU,IAAI,KAAK,IAAI;AACzB,MAAE,UAAU,IAAI,KAAK,QAAQ,IAAI;AACjC,MAAE,UAAU,IAAI,KAAK,QAAQ,IAAI;AACjC,MAAE,UAAU,IAAI,UAAU,QAAQ,IAAI;AACtC,UAAM,IAAI,WAAW,EAAE;AAEvB,UAAM,UAAU,IAAI,WAAW,KAAK,UAAU,MAAM;AACpD,UAAM,IAAI,IAAI,SAAS,QAAQ,MAAM;AACrC,MAAE,UAAU,GAAG,UAAY,IAAI;AAC/B,MAAE,UAAU,GAAG,IAAI,IAAI;AACvB,MAAE,UAAU,GAAG,IAAI,IAAI;AACvB,MAAE,UAAU,GAAG,MAAQ,IAAI;AAC3B,MAAE,UAAU,IAAI,GAAG,IAAI;AACvB,MAAE,UAAU,IAAI,GAAG,IAAI;AACvB,MAAE,UAAU,IAAI,UAAU,IAAI;AAC9B,MAAE,UAAU,IAAI,KAAK,IAAI;AACzB,MAAE,UAAU,IAAI,KAAK,QAAQ,IAAI;AACjC,MAAE,UAAU,IAAI,KAAK,QAAQ,IAAI;AACjC,MAAE,UAAU,IAAI,UAAU,QAAQ,IAAI;AACtC,MAAE,UAAU,IAAI,QAAQ,IAAI;AAC5B,YAAQ,IAAI,WAAW,EAAE;AAEzB,WAAO,KAAK,OAAO,IAAI;AACvB,aAAS,KAAK,OAAO;AACrB,cAAU,MAAM,SAAS,KAAK;AAAA,EAChC;AACA,QAAM,cAAc,SAAS,OAAO,CAAC,GAAG,MAAM,IAAI,EAAE,QAAQ,CAAC;AAC7D,QAAM,MAAM,IAAI,WAAW,EAAE;AAC7B,QAAM,IAAI,IAAI,SAAS,IAAI,MAAM;AACjC,IAAE,UAAU,GAAG,WAAY,IAAI;AAC/B,IAAE,UAAU,GAAG,QAAQ,QAAQ,IAAI;AACnC,IAAE,UAAU,IAAI,QAAQ,QAAQ,IAAI;AACpC,IAAE,UAAU,IAAI,aAAa,IAAI;AACjC,IAAE,UAAU,IAAI,QAAQ,IAAI;AAE5B,QAAM,MAAM,IAAI,WAAW,SAAS,cAAc,EAAE;AACpD,MAAI,KAAK;AACT,aAAW,QAAQ,CAAC,GAAG,QAAQ,GAAG,UAAU,GAAG,GAAG;AAChD,QAAI,IAAI,MAAM,EAAE;AAChB,UAAM,KAAK;AAAA,EACb;AACA,SAAO;AACT;;;ACOA,IAAM,kBAAkB;AAGxB,IAAM,iBAAiB,MAAM,IAAI,QAAc,CAAC,YAAY,WAAW,SAAS,CAAC,CAAC;AAElF,IAAM,UAAU,CAAC,SAAyB,KAAK,IAAI,CAAC,MAAM,IAAI,CAAC,GAAG,EAAE,KAAK,IAAI,EAAE,QAAQ,cAAc,QAAQ;AAG7G,IAAM,aAA+D;AAAA,EACnE,CAAC,IAAM,MAAM,KAAM;AAAA;AAAA,EACnB,CAAC,IAAM,MAAM,MAAM;AAAA;AAAA,EACnB,CAAC,IAAM,MAAM,MAAM;AAAA;AAAA,EACnB,CAAC,IAAM,OAAO,MAAM;AAAA;AAAA,EACpB,CAAC,IAAM,OAAO,MAAM;AAAA;AAAA,EACpB,CAAC,IAAM,OAAO,OAAO;AAAA;AAAA,EACrB,CAAC,IAAM,QAAQ,OAAO;AAAA;AACxB;AAGA,SAAS,UAAU,OAAe,QAAgB,KAAuB;AACvE,QAAM,MAAM,KAAK,KAAK,QAAQ,EAAE,IAAI,KAAK,KAAK,SAAS,EAAE;AACzD,QAAM,SAAS,WAAW,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,OAAO,KAAK,MAAM,OAAO,CAAC,KAAK,WAAW,WAAW,SAAS,CAAC,GAAI,CAAC;AACjH,QAAM,MAAM,MAAM,SAAS,EAAE,EAAE,YAAY,EAAE,SAAS,GAAG,GAAG;AAC5D,SAAO,CAAC,aAAa,aAAa,WAAW,EAAE,IAAI,CAAC,MAAM,IAAI,GAAG;AACnE;AAGA,eAAe,UAAU,QAAkB,MAAkF;AAC3H,aAAW,SAAS,QAAQ;AAC1B,UAAM,SAA6B,EAAE,GAAG,MAAM,MAAM;AACpD,QAAI;AACF,YAAM,SAAS,MAAM,aAAa,kBAAkB,MAAM;AAC1D,UAAI,OAAO,UAAW,QAAO;AAAA,IAC/B,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,eAAe,MAAM,OAAO,iBAAiB,eAAe,OAAO,eAAe;AAGxF,eAAe,YAAY,QAAwB,OAAe,QAAgB,KAAa,SAAiB;AAC9G,QAAM,OAA0C;AAAA,IAC9C;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,aAAa;AAAA,IACb,GAAI,WAAW,QAAQ,EAAE,KAAK,EAAE,QAAQ,MAAe,EAAE,IAAI,CAAC;AAAA,EAChE;AACA,SAAO,UAAU,WAAW,QAAQ,UAAU,OAAO,QAAQ,GAAG,IAAI,CAAC,iBAAiB,KAAK,GAAG,IAAI;AACpG;AAEA,IAAM,gBAAgB,CAAC,WAAsC;AAC3D,QAAM,MAAM,OAAO,WAAW,WAAW,UAAU,MAAM,IAAI;AAC7D,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,uBAAuB,OAAO,MAAM,CAAC,6CAA6C;AAC5G,SAAO;AACT;AAGA,SAAS,SAAS,MAAc,OAA2B,UAA0B;AACnF,QAAM,IAAI,SAAS;AACnB,MAAI,CAAC,OAAO,SAAS,CAAC,KAAK,KAAK,EAAG,OAAM,IAAI,MAAM,GAAG,IAAI,qCAAqC,OAAO,KAAK,CAAC,IAAI;AAChH,SAAO;AACT;AAEA,IAAM,OAAO,CAAC,MAAc,KAAK,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,IAAI,CAAC;AAS5D,eAAsB,cAAc,QAAmC,UAAyB,CAAC,GAA2B;AAC1H,QAAM,MAAM,cAAc,MAAM;AAChC,MAAI,QAAQ,UAAU,CAAC,IAAI,SAAS,KAAK,CAAC,MAAM,EAAE,SAAS,QAAQ,MAAM,GAAG;AAC1E,UAAM,QAAQ,IAAI,SAAS,IAAI,CAAC,MAAM,IAAI,EAAE,IAAI,GAAG,EAAE,KAAK,IAAI;AAC9D,UAAM,IAAI,MAAM,IAAI,IAAI,EAAE,oBAAoB,QAAQ,MAAM,IAAI,QAAQ,YAAY,KAAK,KAAK,EAAE,GAAG;AAAA,EACrG;AACA,QAAM,MAAM,SAAS,OAAO,QAAQ,KAAK,EAAE;AAC3C,QAAM,QAAQ,QAAQ,SAAS;AAC/B,MAAI,CAAC,OAAO,SAAS,KAAK,KAAK,QAAQ,EAAG,OAAM,IAAI,MAAM,2CAA2C,OAAO,QAAQ,KAAK,CAAC,IAAI;AAC9H,QAAM,WAAW,SAAS,YAAY,QAAQ,UAAU,gBAAgB,KAAK,OAAO,CAAC;AACrF,MAAI,QAAQ,KAAK,MAAM,SAAS,SAAS,QAAQ,OAAO,IAAI,CAAC;AAC7D,MAAI,SAAS,KAAK,MAAM,SAAS,UAAU,QAAQ,QAAQ,GAAG,CAAC;AAC/D,QAAM,gBAAgB,QAAQ,UAAU;AACxC,MAAI,QAAQ,QAAQ,UAAU,IAAI,SAAS,YAAY,QAAQ,IAAI,WAAW;AAC9E,MAAI,SAAS,QAAQ;AACrB,MAAI,UAAU,CAAC,CAAC,OAAO,QAAQ,OAAO,KAAK,EAAE,SAAS,MAAM,EAAG,OAAM,IAAI,MAAM,2DAA2D,MAAM,KAAK;AACrJ,MAAI,WAAW,SAAS,OAAO;AAC7B,QAAI,cAAe,OAAM,IAAI,MAAM,mDAAmD,QAAQ,CAAC,QAAQ,OAAO,KAAK,CAAC,CAAC,oCAAoC;AACzJ,YAAQ;AAAA,EACV;AAEA,MAAI;AACJ,MAAI,WAAW,SAAS,WAAW,OAAO;AACxC,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI,MAAM,4FAA4F,UAAU,SAAS,YAAY,QAAQ,CAAC,OAAO,KAAK,CAAC,CAAC,WAAW;AAC/K,UAAM,IAAI,KAAK,KAAK;AACpB,UAAM,IAAI,KAAK,MAAM;AACrB,UAAM,UAAU,KAAK,MAAM,SAAS,WAAW,QAAQ,SAAS,IAAI,IAAI,MAAM,IAAI,CAAC;AACnF,UAAM,YAAY,CAAC,MAAsB,YAAY,GAAG,GAAG,GAAG,KAAK,OAAO;AAE1E,UAAM,UAA8B,SAAS,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,IAAI,CAAC,OAAO,MAAM;AACzF,eAAW,KAAK,SAAS;AACvB,gBAAU,MAAM,UAAU,CAAC;AAC3B,UAAI,SAAS;AACX,iBAAS;AACT;AAAA,MACF;AAAA,IACF;AACA,QAAI,CAAC,WAAW,CAAC,UAAU,SAAS,CAAC,eAAe;AAElD,gBAAU,MAAM,UAAU,KAAK;AAC/B,UAAI,SAAS;AACX,iBAAS;AACT,gBAAQ;AAAA,MACV;AAAA,IACF;AACA,QAAI,CAAC,SAAS;AACZ,YAAM,QAAQ,WAAW,QAAQ,SAAS;AAC1C,YAAM,QAAQ,UAAU,QAAQ,SAAS;AACzC,UAAI,SAAS,UAAU,OAAQ,OAAM,IAAI,MAAM,+FAA+F,QAAQ,CAAC,OAAO,KAAK,CAAC,CAAC,oCAAoC;AACzM,YAAM,aAAa,UAAW,MAAM,UAAU,KAAK;AACnD,YAAM,QAAQ,UAAU,QAAQ,UAAU;AAC1C,YAAM,IAAI;AAAA,QACR,SACI,8BAA8B,KAAK,OAAO,CAAC,SAAM,CAAC,yBAAyB,KAAK,YAAY,QAAQ,aAAa,CAAC,OAAO,OAAO,KAAK,IAAI,CAAC,OAAO,KAAK,CAAC,CAAC,cACxJ,mDAAmD,CAAC,SAAM,CAAC,YAAY,QAAQ,CAAC,OAAO,KAAK,CAAC,CAAC;AAAA,MACpG;AAAA,IACF;AACA,YAAQ;AACR,aAAS;AAAA,EACX;AACA,SAAO,EAAE,QAAQ,KAAK,QAAiB,OAAO,QAAQ,KAAK,UAAU,OAAO,QAAQ,KAAK,IAAI,GAAG,KAAK,MAAM,WAAW,GAAG,CAAC,GAAG,OAAO,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC,EAAG;AACtK;AAGA,SAAS,gBAAgB,KAAuB,SAAgC;AAC9E,MAAI,IAAI,SAAS,SAAU,QAAO,IAAI,QAAQ;AAC9C,QAAM,SAAS,mBAAmB,KAAK,aAAa,KAAK,OAAO,EAAE,MAAM;AACxE,UAAQ,YAAY,QAAQ,QAAQ,SAAS,CAAC,CAAC,KAAK,IAAI,QAAQ,QAAQ;AAC1E;AAEA,SAAS,aAAa,KAAuB,SAAwB;AACnE,QAAM,SAAS,eAAe,KAAK,EAAE,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC,GAAI,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC,EAAG,CAAC;AACnJ,MAAI,CAAC,QAAQ,QAAS,QAAO,EAAE,QAAQ,MAAM,CAAC,EAAgC;AAC9E,QAAM,IAAI,cAAc,KAAK,QAAQ,OAAO;AAC5C,SAAO,EAAE,QAAQ,EAAE,GAAG,QAAQ,GAAG,EAAE,OAAO,GAAG,MAAM,EAAE,KAAK;AAC5D;AAWA,SAAS,aAAa,MAAqB,QAAsC,MAAkC,SAAqC;AACtJ,QAAM,MAAM,KAAK;AAEjB,QAAM,SAAS,IAAI,aAAa,EAAE,QAAQ,IAAI,QAAQ,QAAQ,OAAO,KAAK,OAAO,QAAQ,KAAK,QAAQ,OAAO,KAAK,SAAS,QAAQ,IAAI,WAAW,EAAE,CAAC;AACrJ,QAAM,SAAuE,CAAC;AAC9E,aAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,IAAI,GAAG;AACjD,WAAO,cAAc,MAAM,MAAM;AACjC,QAAI,OAAO,qBAAqB,eAAe,kBAAkB,kBAAkB;AACjF,aAAO,KAAK,EAAE,OAAO,QAAQ,MAAM,OAAO,aAAa,QAAQ,OAAO,OAAO,CAAC;AAC9E,aAAO,MAAM;AAAA,IACf;AAAA,EACF;AACA,QAAM,SAAS,QAAQ;AACvB,SAAO;AAAA,IACL,MAAM,MAAM,MAAM,OAAO,KAAK;AAC5B,iBAAW,EAAE,MAAM,KAAK,OAAQ,OAAM,UAAU,OAAO,IAAI;AAC3D,YAAM,QAAQ,cAAc,MAAM,KAAK;AACvC,YAAM,OAAO,MAAM;AACnB,YAAM,UAAU,OAAO,WAAW,aAAa,OAAO,IAAI,IAAI;AAC9D,aAAO,OAAO,MAAM,EAAE,OAAO,OAAO,OAAO,IAAI,KAAK,KAAK,GAAG,QAAQ,CAAC;AACrE,aAAO,WAAW,GAAG;AAAA,IACvB;AAAA,IACA,UAAU;AACR,aAAO,QAAQ;AACf,iBAAW,EAAE,OAAO,MAAM,OAAO,KAAK,QAAQ;AAC5C,cAAM,cAAc;AACpB,YAAI,CAAC,OAAQ,MAAK,MAAM,KAAK,EAAE,MAAM,MAAM,MAAS;AAAA,MACtD;AAAA,IACF;AAAA,EACF;AACF;AAEA,SAAS,aAAa,MAAqB,QAAsC,SAAqC;AACpH,QAAM,MAAM,KAAK;AACjB,QAAM,OAAO,QAAQ,mBAAmB,KAAK,MAAM,CAAC;AAEpD,QAAM,OAAO,SAAS,cAAc,KAAK;AACzC,OAAK,aAAa,eAAe,MAAM;AACvC,OAAK,MAAM,UAAU,6CAA6C,KAAK,KAAK,aAAa,KAAK,MAAM;AACpG,OAAK,YAAY,KAAK,OAAO;AAC7B,WAAS,KAAK,YAAY,IAAI;AAC9B,QAAM,QAAQ,QAAQ,SAAS,CAAC;AAChC,SAAO;AAAA,IACL,MAAM,MAAM,MAAM,OAAO,KAAK;AAC5B,YAAM,QAAQ,cAAc,MAAM,KAAK;AACvC,WAAK,KAAK,OAAO,KAAM,KAAK;AAC5B,YAAM,SAAS,MAAM,KAAK,QAAQ,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO,CAAC;AAC5E,UAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,IAAI,IAAI,EAAE,qDAAqD;AAC5F,UAAI,IAAI,OAAO,WAAW,IAAI,EAAG,aAAa,GAAG,GAAG,KAAK,OAAO,KAAK,MAAM,EAAE,IAAI;AAAA,IACnF;AAAA,IACA,SAAS,MAAM,KAAK,OAAO;AAAA,EAC7B;AACF;AAGA,SAAS,QAAQ,MAAc,YAAsC;AACnE,QAAM,CAAC,IAAI,IAAI,EAAE,IAAI;AACrB,WAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK,GAAG;AACvC,UAAM,IAAI,KAAK,IAAI,CAAC;AACpB,QAAI,MAAM,IAAK;AACf,UAAM,IAAI,IAAI;AACd,SAAK,CAAC,IAAI,KAAK,CAAC,IAAK,IAAI,MAAM,IAAI;AACnC,SAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAK,IAAI,MAAM,IAAI;AAC3C,SAAK,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,IAAK,IAAI,MAAM,IAAI;AAC3C,SAAK,IAAI,CAAC,IAAI;AAAA,EAChB;AACF;AASA,eAAe,WAAW,MAAuC;AAC/D,QAAM,EAAE,YAAY,UAAU,aAAa,IAAI,MAAM,OAAO,QAAQ;AACpE,QAAM,MAAM,WAAW;AACvB,QAAM,QAAQ,MAAO,KAAK;AAC1B,SAAO;AAAA,IACL,MAAM,IAAI,MAAM,GAAG;AACjB,YAAM,SAAS,MAAM,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC;AAC1C,UAAI,CAAC,KAAK,OAAO;AACf,cAAMA,WAAU,SAAS,MAAM,GAAG;AAClC,YAAI,WAAW,aAAa,MAAMA,QAAO,GAAG,KAAK,OAAO,KAAK,QAAQ,EAAE,SAAAA,UAAS,OAAO,GAAG,OAAO,CAAC;AAClG;AAAA,MACF;AAEA,YAAM,UAAU,SAAS,MAAM,KAAK,EAAE,QAAQ,YAAY,aAAa,KAAK,CAAC;AAC7E,YAAM,mBAAmB,QAAQ,UAAU,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC;AAC5D,UAAI,WAAW,aAAa,MAAM,SAAS,UAAU,GAAG,KAAK,OAAO,KAAK,QAAQ;AAAA,QAC/E;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT,GAAI,oBAAoB,IAAI,EAAE,aAAa,MAAM,iBAAiB,IAAI,CAAC;AAAA,QACvE,GAAG;AAAA,MACL,CAAC;AAAA,IACH;AAAA,IACA,MAAM,SAAS;AACb,UAAI,OAAO;AACX,aAAO,IAAI,KAAK,CAAC,IAAI,MAAM,CAAC,GAAG,EAAE,MAAM,YAAY,CAAC;AAAA,IACtD;AAAA,IACA,QAAQ;AAAA,IAAC;AAAA,EACX;AACF;AAEA,SAAS,WAAW,MAA8B;AAChD,QAAM,SAAS,SAAS,cAAc,QAAQ;AAC9C,SAAO,QAAQ,KAAK;AACpB,SAAO,SAAS,KAAK;AACrB,QAAM,UAAU,OAAO,WAAW,IAAI;AACtC,MAAI,CAAC,QAAS,OAAM,IAAI,MAAM,qEAAqE;AACnG,QAAM,UAAsB,CAAC;AAC7B,QAAM,SAAS,KAAK,IAAI,GAAG,OAAO,KAAK,MAAM,EAAE,MAAM;AACrD,SAAO;AAAA,IACL,MAAM,IAAI,MAAM,GAAG;AACjB,cAAQ,aAAa,IAAI,UAAU,MAAM,KAAK,OAAO,KAAK,MAAM,GAAG,GAAG,CAAC;AACvE,YAAM,OAAO,MAAM,IAAI,QAAqB,CAAC,YAAY,OAAO,OAAO,SAAS,WAAW,CAAC;AAC5F,UAAI,CAAC,KAAM,OAAM,IAAI,MAAM,2CAA2C;AACtE,cAAQ,KAAK,EAAE,MAAM,SAAS,OAAO,IAAI,CAAC,EAAE,SAAS,QAAQ,GAAG,CAAC,QAAQ,MAAM,IAAI,WAAW,MAAM,KAAK,YAAY,CAAC,EAAE,CAAC;AAAA,IAC3H;AAAA,IACA,MAAM,SAAS;AACb,aAAO,IAAI,KAAK,CAAC,SAAS,OAAO,CAA4B,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAAA,IAC7F;AAAA,IACA,QAAQ;AAAA,IAAC;AAAA,EACX;AACF;AAEA,IAAM,UAAU,CAAC,WACf,kBAAkB,eAAgB,OAAO,sBAAsB,eAAe,kBAAkB,oBAC5F,IAAI,WAAW,OAAO,MAAM,CAAC,CAAC,IAC9B,IAAI,WAAY,OAA2B,OAAO,MAAO,OAA2B,YAAa,OAA2B,aAAc,OAA2B,UAAU,CAAC;AAGtL,SAAS,UAAU,QAA4B,MAA0B;AACvE,QAAM,SAAqF,CAAC;AAC5F,QAAM,MAAM,EAAE,QAAQ,aAAa,QAAqC,SAAS,OAAqC;AACtH,MAAI,UAAU,IAAI,aAAa;AAAA,IAC7B,OAAO,OAAO,UAAU;AACtB,YAAM,OAAO,IAAI,WAAW,MAAM,UAAU;AAC5C,YAAM,OAAO,IAAI;AACjB,YAAM,OAAO,UAAU,eAAe;AACtC,UAAI,QAAQ,CAAC,IAAI,YAAa,KAAI,cAAc,QAAQ,IAAI;AAC5D,aAAO,KAAK,EAAE,MAAM,WAAW,MAAM,WAAW,GAAI,MAAM,WAAW,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC,GAAI,KAAK,MAAM,SAAS,MAAM,CAAC;AAAA,IACtI;AAAA,IACA,OAAO,CAAC,MAAM,KAAK,IAAI,MAAM,6BAA6B,EAAE,OAAO,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAAA,EACtF,CAAC;AACD,MAAI,QAAQ,UAAU,MAAM;AAC5B,SAAO;AACT;AAQA,SAAS,aAAa,MAA8B;AAClD,QAAM,SAAS,KAAK;AACpB,MAAI;AACJ,QAAM,OAAO,CAAC,MAAc,YAAY;AACxC,QAAM,QAAQ,UAAU,QAAQ,IAAI;AACpC,QAAM,QAAQ,KAAK,QAAQ,UAAU,QAAQ,IAAI,IAAI;AACrD,QAAM,WAAW,CAAC,MAAM,SAAS,GAAI,QAAQ,CAAC,MAAM,OAAO,IAAI,CAAC,CAAE;AAClE,QAAM,UAAU,MAAM,KAAK;AAE3B,QAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC;AACrD,QAAM,EAAE,OAAO,OAAO,IAAI;AAE1B,QAAM,QAAQ,QAAQ,IAAI,WAAW,QAAQ,SAAS,GAAG,EAAE,KAAK,GAAG,IAAI;AACvE,QAAM,QAAQ,MAAM;AAClB,QAAI,QAAS,OAAM;AAAA,EACrB;AACA,QAAM,SAAS,CAAC,SAAuB,OAAmB,QAAiB;AACzE,QAAI;AACF,cAAQ,OAAO,OAAO,EAAE,UAAU,IAAI,CAAC;AAAA,IACzC,UAAE;AACA,YAAM,MAAM;AAAA,IACd;AAAA,EACF;AACA,SAAO;AAAA,IACL,MAAM,IAAI,MAAM,GAAG;AACjB,YAAM;AACN,YAAM,SAAS,EAAE,YAAY,OAAO,aAAa,QAAQ,WAAW,KAAK,MAAM,IAAI,OAAO,GAAG,UAAU,KAAK,MAAM,OAAO,EAAE;AAC3H,YAAM,MAAM,IAAI,aAAa;AAC7B,aAAO,MAAM,SAAS,IAAI,WAAW,MAAM,EAAE,QAAQ,QAAQ,GAAG,OAAO,CAAC,GAAG,GAAG;AAC9E,UAAI,SAAS,OAAO;AAClB,iBAAS,IAAI,GAAG,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,KAAK,EAAG,OAAM,CAAC,IAAI,KAAK,CAAC;AACzE,eAAO,MAAM,SAAS,IAAI,WAAW,OAAO,EAAE,QAAQ,QAAQ,GAAG,OAAO,CAAC,GAAG,GAAG;AAAA,MACjF;AAEA,aAAO,SAAS,KAAK,CAAC,MAAM,EAAE,kBAAkB,CAAC,KAAK,CAAC,QAAS,OAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,CAAC,CAAC;AAAA,IACvH;AAAA,IACA,MAAM,SAAS;AACb,YAAM,QAAQ,IAAI,SAAS,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAChD,YAAM;AACN,iBAAW,KAAK,SAAU,GAAE,MAAM;AAClC,YAAM,SAAS,CAAC,GAA0B,MAA6B,EAAE,YAAY,EAAE;AACvF,YAAM,SAAS,MAAM,OAAO,KAAK,MAAM;AACvC,UAAI,KAAK,WAAW,OAAO;AACzB,YAAI,CAAC,MAAM,YAAa,OAAM,IAAI,MAAM,uFAAuF;AAC/H,cAAMC,QAAO,OAAO,EAAE,OAAO,QAAQ,MAAM,MAAM,aAAa,SAAS,OAAO,CAAC;AAC/E,eAAO,IAAI,KAAK,CAACA,KAA+B,GAAG,EAAE,MAAM,YAAY,CAAC;AAAA,MAC1E;AACA,YAAM,SAAS,IAAI,IAAI,OAAO,OAAO,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,IAAI,CAAC,CAAC;AACtE,YAAM,SAAsB,OAAO,IAAI,CAAC,MAAM;AAC5C,cAAM,IAAI,OAAO,IAAI,EAAE,SAAS;AAChC,YAAI,SAAS,CAAC,EAAG,OAAM,IAAI,MAAM,0CAA0C,EAAE,YAAY,GAAG,0EAA0E;AACtK,eAAO,EAAE,GAAG,GAAG,GAAI,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,EAAG;AAAA,MAC5C,CAAC;AACD,YAAM,QAAQ,OAAO,MAAM,WAAW,KAAK,IAAI,QAAQ;AACvD,YAAM,OAAO,QAAQ,EAAE,OAAO,OAAO,QAAQ,QAAQ,UAAU,KAAK,SAAS,SAAS,KAAK,KAAK,IAAI,CAAC;AACrG,aAAO,IAAI,KAAK,CAAC,IAA+B,GAAG,EAAE,MAAM,aAAa,CAAC;AAAA,IAC3E;AAAA,IACA,QAAQ;AACN,iBAAW,KAAK,SAAU,KAAI,EAAE,UAAU,SAAU,GAAE,MAAM;AAAA,IAC9D;AAAA,EACF;AACF;AA4BA,eAAsB,aAAa,QAAmC,UAAyB,CAAC,GAAkB;AAChH,QAAM,OAAO,MAAM,cAAc,QAAQ,OAAO;AAChD,QAAM,EAAE,QAAQ,WAAW,IAAI;AAC/B,QAAM,EAAE,QAAQ,KAAK,IAAI,aAAa,KAAK,QAAQ,OAAO;AAC1D,QAAM,cAAc,WAAW,QAAQ,eAAe,KAAK,OAAO,SAAS,WAAW,YAAY,UAAU,KAAK,CAAC,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC;AAE1J,QAAM,SAAS,KAAK,OAAO,SAAS,WAAW,aAAa,MAAM,QAAQ,MAAM,OAAO,IAAI,aAAa,MAAM,QAAQ,OAAO;AAC7H,MAAI;AACJ,MAAI;AACF,cAAU,KAAK,WAAW,QAAQ,MAAM,WAAW,IAAI,IAAI,KAAK,WAAW,QAAQ,WAAW,IAAI,IAAI,aAAa,IAAI;AACvH,UAAM,OAAO,IAAI,kBAAkB,KAAK,QAAQ,KAAK,SAAS,CAAC;AAC/D,aAAS,IAAI,GAAG,IAAI,KAAK,QAAQ,KAAK;AACpC,UAAI,QAAQ,QAAS,OAAM,IAAI,aAAa,aAAa,YAAY;AACrE,YAAM,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,KAAK,GAAG,IAAI;AACrD,UAAI,CAAC,KAAK,MAAO,SAAQ,MAAM,UAAU;AACzC,YAAM,QAAQ,IAAI,MAAM,CAAC;AACzB,oBAAc,IAAI,KAAK,KAAK,MAAM;AAClC,UAAI,IAAI,MAAM,EAAG,OAAM,eAAe;AAAA,IACxC;AACA,QAAI,QAAQ,QAAS,OAAM,IAAI,aAAa,aAAa,YAAY;AACrE,WAAO,MAAM,QAAQ,OAAO;AAAA,EAC9B,UAAE;AACA,aAAS,MAAM;AACf,WAAO,QAAQ;AAAA,EACjB;AACF;;;ACzeA,IAAM,SAAS,CAAC,YAA2B,OAAO,KAAK,OAAO,EAAE,KAAK,CAAC,MAAM,MAAM,UAAU,MAAM,QAAQ;AAG1G,SAAS,OAAO,KAAqB;AACnC,QAAM,SAAS,IAAI,KAAK;AACxB,MAAI,CAAC,OAAO,WAAW,GAAG,EAAG,QAAO;AACpC,QAAM,SAAS,cAAc,KAAK,OAAO,MAAM,GAAG,OAAO,QAAQ,GAAG,IAAI,CAAC,CAAC,IAAI,SAAS,OAAO,QAAQ,UAAU,yCAAyC;AACzJ,SAAO,oCAAoC,mBAAmB,MAAM,CAAC;AACvE;AAEA,SAAS,KAAiC,OAAY,QAA2B,MAA0B,QAA0B,MAAiB;AACpJ,QAAM,OAAO,OAAO,MAAM,KAAK,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI,MAAM,KAAK,MAAM;AAC1E,MAAI,CAAC,MAAM;AACT,UAAM,QAAQ,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,KAAK,IAAI;AAChD,UAAM,IAAI;AAAA,MACR,OACI,IAAI,OAAO,EAAE,qBAAqB,IAAI,SAAS,IAAI,GAAG,QAAQ,YAAY,KAAK,KAAK,EAAE,MACtF,IAAI,OAAO,EAAE,cAAc,IAAI;AAAA,IACrC;AAAA,EACF;AACA,SAAO;AACT;AAWO,SAAS,cAAc,QAA0B,SAAmD,MAA8B;AACvI,QAAM,MAAqB,EAAE,QAAQ,CAAC,GAAG,MAAM,CAAC,EAAE;AAClD,QAAM,SAAS,aAAa,MAAM;AAClC,QAAM,OAAO,oBAAI,IAAY;AAC7B,aAAW,KAAK,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAwB,GAAG;AAC7E,UAAM,OAAO,OAAO,CAAC;AACrB,UAAM,OAAO,CAA6B,UAAe,MAAM,OAAO,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,IAAI,CAAC;AAC9F,QAAI,SAAS,UAAW,SAAS,UAAU,OAAO,SAAS,UAAW;AACpE,YAAM,QAAQ,SAAS,SAAS,SAAS;AACzC,YAAM,OAAO,KAAe,KAAK,OAAO,KAAK,GAAG,CAAC,MAAM,EAAE,UAAU,OAAO,MAAM,QAAQ,SAAS,SAAS,cAAc,MAAM;AAC9H,UAAI,OAAO,KAAK,IAAI,IAAI,SAAS,SAAU,EAAuB,OAAQ,EAAuB;AACjG,WAAK,IAAI,KAAK,IAAI;AAClB;AAAA,IACF;AACA,QAAI,OAAO,SAAS;AAClB,YAAM,IAAI,MAAM,IAAI,OAAO,EAAE,gFAAgF,OAAO,QAAQ,KAAK,IAAI,KAAK,SAAS,UAAU,EAAE,KAAK,UAAU,OAAO,YAAY,OAAO,UAAU,EAAE,IAAiC,CAAC,GAAG;AAC3P,UAAM,SAAS,CAAC,MACd,SAAS,SAAS,EAAE,UAAU,YAAY,SAAS,UAAU,EAAE,UAAU,YAAY;AACvF,UAAM,QAAQ,KAAgB,KAAK,OAAO,MAAM,GAAG,QAAQ,MAAM,QAAQ,SAAS,SAAS,SAAS,GAAG,SAAS,QAAQ,QAAQ,IAAI,EAAE;AACtI,SAAK,IAAI,MAAM,IAAI;AACnB,QAAI,SAAS,SAAS;AACpB,UAAI,CAAC,OAAO,QAAQ,SAAS,OAAO,EAAG,OAAM,IAAI,MAAM,IAAI,OAAO,EAAE,oCAAoC,OAAO,KAAK,wBAAwB;AAC5I,UAAI,KAAK,MAAM,IAAI,IAAK,EAA4B;AAAA,IACtD,WAAW,SAAS,QAAQ;AAC1B,YAAM,IAAI;AACV,UAAI,OAAO,MAAM,IAAI,IAAI,UAAU,EAAE,MAAM,EAAE,GAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,GAAI,GAAI,EAAE,WAAW,SAAY,EAAE,QAAQ,EAAE,OAAO,IAAI,CAAC,EAAG,CAAC;AAAA,IAC7I,MAAO,KAAI,OAAO,MAAM,IAAI,IAAI,SAAS,QAAQ,OAAQ,EAAsB,GAAG,IAAK,EAAwB;AAAA,EACjH;AACA,SAAO;AACT;AAiDO,SAAS,YAAY,MAAmB,QAAmC,UAAwB,CAAC,GAAkB;AAC3H,QAAM,MAAM,OAAO,WAAW,WAAW,UAAU,MAAM,IAAI;AAC7D,MAAI,CAAC,IAAK,OAAM,IAAI,MAAM,uBAAuB,OAAO,MAAM,CAAC,6CAA6C;AAC5G,MAAI,SAAuC,EAAE,GAAG,eAAe,KAAK,EAAE,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC,GAAI,GAAI,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC,EAAG,CAAC,EAAE;AACtL,MAAI,OAAmC,CAAC;AACxC,QAAM,QAAQ,CAAC,YAAkE;AAC/E,QAAI,CAAC,QAAS;AACd,UAAM,IAAI,cAAc,KAAK,OAAO;AACpC,aAAS,EAAE,GAAG,QAAQ,GAAG,EAAE,OAAO;AAClC,WAAO,EAAE;AAAA,EACX;AACA,QAAM,QAAQ,OAAO;AAErB,MAAI,IAAI,SAAS,UAAU;AACzB,UAAM,WAAW,IAAI,eAAe,MAAM;AAAA,MACxC,OAAO,QAAQ,IAAI,WAAW;AAAA,MAC9B,UAAU,QAAQ,YAAY;AAAA,MAC9B,iBAAiB,QAAQ,mBAAmB;AAAA,MAC5C,GAAI,QAAQ,YAAY,EAAE,WAAW,QAAQ,UAAU,IAAI,CAAC;AAAA,IAC9D,CAAC;AACD,aAAS,UAAU,IAAI,MAAM;AAC7B,aAAS,UAAU,MAAM;AACzB,UAAM,UAAU,CAAC,aAAyC;AACxD,iBAAW,QAAQ,OAAO,KAAK,QAAQ,EAAG,KAAI,EAAE,QAAQ,MAAO,UAAS,cAAc,MAAM,IAAI;AAChG,iBAAW,CAAC,MAAM,MAAM,KAAK,OAAO,QAAQ,IAAI,EAAG,UAAS,cAAc,MAAM,MAAM;AAAA,IACxF;AACA,YAAQ,CAAC,CAAC;AACV,WAAO;AAAA,MACL,QAAQ;AAAA,MACR,SAAS,SAAS;AAAA,MAClB;AAAA,MACA,WAAW,SAAS;AAClB,cAAM,SAAS;AACf,cAAM,OAAO;AACb,iBAAS,UAAU,MAAM;AACzB,gBAAQ,MAAM;AAAA,MAChB;AAAA,MACA,UAAU,MAAM;AACd,iBAAS,EAAE,GAAG,QAAQ,GAAG,KAAK;AAC9B,iBAAS,UAAU,MAAM;AAAA,MAC3B;AAAA,MACA,MAAM,MAAM,SAAS,KAAK;AAAA,MAC1B,OAAO,MAAM,SAAS,MAAM;AAAA,MAC5B,SAAS,MAAM,SAAS,QAAQ;AAAA,IAClC;AAAA,EACF;AAEA,MAAI;AACJ,QAAM,QAAQ,MAAM;AAClB,YAAQ,QAAQ;AAChB,aAAS,IAAI,UAAU,MAAM,mBAAmB,KAAK,MAAM,GAAG;AAAA,MAC5D,MAAM,IAAI;AAAA,MACV,GAAI,IAAI,UAAU,EAAE,SAAS,IAAI,QAAQ,IAAI,CAAC;AAAA,MAC9C,UAAU,QAAQ,YAAY;AAAA,MAC9B,iBAAiB,QAAQ,mBAAmB;AAAA,IAC9C,CAAC;AACD,QAAI,QAAQ,UAAW,QAAO,KAAK,QAAQ,YAAY,QAAQ;AAAA,EACjE;AACA,QAAM;AACN,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,IAAI,UAAU;AACZ,aAAO,OAAO,KAAK;AAAA,IACrB;AAAA,IACA,IAAI,SAAS;AACX,aAAO;AAAA,IACT;AAAA,IACA,WAAW,SAAS;AAClB,YAAM,OAAO;AACb,YAAM;AAAA,IACR;AAAA,IACA,UAAU,MAAM;AACd,eAAS,EAAE,GAAG,QAAQ,GAAG,KAAK;AAC9B,YAAM;AAAA,IACR;AAAA,IACA,MAAM,MAAM,OAAO,KAAK;AAAA,IACxB,OAAO,MAAM,OAAO,MAAM;AAAA,IAC1B,SAAS,MAAM,OAAO,QAAQ;AAAA,EAChC;AACF;","names":["palette","file"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|