@pixerate/flair 0.24.0 → 0.25.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 +12 -0
- package/dist/catalog/index.js +2 -2
- package/dist/chunk-DBTLCXKY.js +332 -0
- package/dist/chunk-DBTLCXKY.js.map +1 -0
- package/dist/{chunk-VP6IEWIK.js → chunk-H6L67KHI.js} +1 -1
- package/dist/chunk-H6VDFBIO.js +498 -0
- package/dist/chunk-H6VDFBIO.js.map +1 -0
- package/dist/chunk-JL6TI6II.js +724 -0
- package/dist/chunk-JL6TI6II.js.map +1 -0
- package/dist/{chunk-NGKNI3QX.js → chunk-O44ZJTGG.js} +5 -485
- package/dist/chunk-O44ZJTGG.js.map +1 -0
- package/dist/chunk-OKYMKSXK.js +414 -0
- package/dist/chunk-OKYMKSXK.js.map +1 -0
- package/dist/{chunk-OHW7UG6D.js → chunk-ORAFCHX3.js} +26 -2
- package/dist/{chunk-OHW7UG6D.js.map → chunk-ORAFCHX3.js.map} +1 -1
- package/dist/{chunk-OQ4EWZ3B.js → chunk-PYDN5G2P.js} +5 -5
- package/dist/{chunk-ARKC7LDW.js → chunk-RDU63CDO.js} +2 -331
- package/dist/chunk-RDU63CDO.js.map +1 -0
- package/dist/chunk-S2RGHHKZ.js +902 -0
- package/dist/chunk-S2RGHHKZ.js.map +1 -0
- package/dist/{chunk-LVPIIWPP.js → chunk-STKEKXCK.js} +18 -8
- package/dist/chunk-STKEKXCK.js.map +1 -0
- package/dist/chunk-YBGRXVAE.js +407 -0
- package/dist/chunk-YBGRXVAE.js.map +1 -0
- package/dist/cli.js +68 -5
- package/dist/cli.js.map +1 -1
- package/dist/editor/index.d.ts +1 -1
- package/dist/editor/index.js +14 -12
- package/dist/editor/index.js.map +1 -1
- package/dist/effect-26CPF5HS.js +47 -0
- package/dist/embed/index.d.ts +215 -0
- package/dist/embed/index.js +21 -0
- package/dist/embed/index.js.map +1 -0
- package/dist/frames-VEcqa40g.d.ts +161 -0
- package/dist/index.d.ts +6 -163
- package/dist/index.js +86 -78
- package/dist/index.js.map +1 -1
- package/dist/node.d.ts +167 -7
- package/dist/node.js +25 -3
- package/dist/react/index.d.ts +33 -2
- package/dist/react/index.js +54 -9
- package/dist/react/index.js.map +1 -1
- package/dist/recorder-CDPPTJMG.js +31 -0
- package/dist/recorder-CDPPTJMG.js.map +1 -0
- package/dist/{renderer-C2P1qGzP.d.ts → renderer-teaa98RE.d.ts} +1 -1
- package/dist/svelte/index.d.ts +33 -4
- package/dist/svelte/index.js +51 -9
- package/dist/svelte/index.js.map +1 -1
- package/dist/vector/index.d.ts +52 -1
- package/dist/vector/index.js +8 -4
- package/package.json +1 -1
- package/dist/chunk-ARKC7LDW.js.map +0 -1
- package/dist/chunk-LVPIIWPP.js.map +0 -1
- package/dist/chunk-NGKNI3QX.js.map +0 -1
- package/dist/chunk-UP6QQVRS.js +0 -331
- package/dist/chunk-UP6QQVRS.js.map +0 -1
- package/dist/recorder-HKFFHQES.js +0 -10
- /package/dist/{chunk-VP6IEWIK.js.map → chunk-H6L67KHI.js.map} +0 -0
- /package/dist/{chunk-OQ4EWZ3B.js.map → chunk-PYDN5G2P.js.map} +0 -0
- /package/dist/{recorder-HKFFHQES.js.map → effect-26CPF5HS.js.map} +0 -0
package/dist/svelte/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/svelte/index.ts"],"sourcesContent":["/**\n * Svelte 5 bindings for Flair's vector effects, written as plain TypeScript so\n * they need no Svelte compiler: the `vectorEffect` action plays a catalog\n * effect (or any {@link SvgMotion}) in an element, and `vectorEffectStill`\n * gives the markup and style of its still for server rendering.\n *\n * ```svelte\n * <script>\n * import { vectorEffect, vectorEffectStill } from \"@pixerate/flair/svelte\";\n * const params = { id: \"drip-text\", values: { word: \"Slop\" }, loop: false };\n * const still = vectorEffectStill(params);\n * </script>\n *\n * <span use:vectorEffect={params} style={still.style}>{@html still.markup}</span>\n * ```\n *\n * The still is in place from the first paint; the live `SvgPlayer` takes over\n * after mount and is disposed on destroy. Under `prefers-reduced-motion:\n * reduce` the still stays.\n *\n * Needs Svelte 5 (an optional peer dependency of the package); only its types\n * are imported.\n *\n * @packageDocumentation\n */\n\nimport type { ActionReturn } from \"svelte/action\";\nimport { getEffect, effectDefaults } from \"../catalog/index.js\";\nimport { renderVectorEffect, type VectorEffect as VectorEffectDefinition } from \"../catalog/types.js\";\nimport type { ControlValue } from \"../shader/controls.js\";\nimport type { Clock } from \"../time/clock.js\";\nimport type { SvgMotion } from \"../vector/motion.js\";\nimport { svgFrameMarkup, svgInlineLayout, svgViewBox } from \"../vector/static.js\";\nimport { SvgPlayer, type SvgTrigger } from \"../vector/svg.js\";\n\n/** Cap height of a heavy sans, as a share of its font size: what an inline word is framed to. */\nconst CAP_HEIGHT = \"0.72em\";\n\n/** Marks the still's layer, so the action can find it (and hide it while the player runs). */\nconst STILL_ATTR = \"data-flair-still\";\n\nconst LAYER = \"position:absolute;inset:0;display:block\";\n\n/** When to leave the still in place of the animation. */\nexport type ReducedMotion = \"user\" | \"always\" | \"never\";\n\n/** Options shared by an effect by id and a motion of your own. */\nexport interface SvgPlayerParams {\n /** Start again at the end (default `true`); `false` plays once and stays on the last frame. */\n loop?: boolean;\n /** Start playing at once (default `true`). */\n autoplay?: boolean;\n /** Playback speed (default 1); changed without remaking the player. */\n speed?: number;\n /** Ms to rest on the last frame before looping (default 600, or the effect's). */\n hold?: number;\n /** Loop length in ms (default: the picture's own, plus `hold`). */\n duration?: number;\n /** Step start times in ms, for pictures that change on steps. */\n steps?: readonly number[];\n /** Plays in answer to the pointer (see `SvgTrigger`; default the effect's). */\n trigger?: SvgTrigger;\n /** Pause while scrolled out of view. */\n pauseWhenHidden?: boolean;\n /**\n * Wait to start until scrolled into view. Default `true` when it plays once\n * (`loop: false`, no trigger), so a one-shot further down the page does not\n * finish before anyone sees it; `false` plays at mount.\n */\n playOnEnter?: boolean;\n /** Hide the picture while paused or reset. */\n hideWhenPaused?: boolean;\n /** Time source (default animation frames); a `ManualClock` steps frames yourself. */\n clock?: Clock;\n /** Called with the id of the innermost element with an id that is clicked. */\n onPick?: (id: string) => void;\n /** Called with the player once it is made, and `undefined` when it is disposed. */\n onPlayer?: (player: SvgPlayer | undefined) => void;\n /**\n * The still shown before the player starts and instead of it under reduced\n * motion: `\"last\"` (default; the rest frame, `\"first\"` for a hover or press\n * trigger), `\"first\"` or a time in ms.\n */\n poster?: \"first\" | \"last\" | number;\n /**\n * `\"user\"` (default) shows the still when the visitor prefers reduced\n * motion, `\"always\"` always does, `\"never\"` always plays.\n */\n reducedMotion?: ReducedMotion;\n /**\n * Size it as a word in a line of text: `display: inline-block` with the\n * viewBox's aspect ratio and `height` 0.72em (the cap height of a heavy\n * sans; pass a CSS length for another). Default: the effect's `inline`\n * control. Otherwise it is a block as wide as its container with the\n * viewBox's aspect ratio.\n */\n inline?: boolean | string;\n /**\n * With `inline`, keep room for what spills past the word (descenders,\n * outlines, glows, drips): a margin of the picture's `data-overhang` (see\n * `svgInlineLayout`), so the lines around it make space instead of being\n * painted over. Default `false`.\n */\n contain?: boolean;\n}\n\n/** A catalog vector effect by id (or the effect itself), with its values. */\nexport interface VectorEffectByIdParams extends SvgPlayerParams {\n /** A vector effect's catalog id (`\"drip-text\"`), or the effect itself. */\n id: string | VectorEffectDefinition;\n /** Control values; missing ones take the preset's, then the defaults. Compared by content. */\n values?: Record<string, ControlValue>;\n /** A preset's name to start from. */\n preset?: string;\n motion?: never;\n}\n\n/** Any {@link SvgMotion}; a new object restarts the player. */\nexport interface SvgMotionParams extends SvgPlayerParams {\n /** The picture and its animations. */\n motion: SvgMotion;\n id?: never;\n values?: never;\n preset?: never;\n}\n\n/** What `vectorEffect` and `vectorEffectStill` take: an effect by `id`, or a `motion`. */\nexport type VectorEffectParams = VectorEffectByIdParams | SvgMotionParams;\n\n/** A still of the picture, for `{@html markup}` inside an element with `style`. */\nexport interface VectorEffectStill {\n /** The still's layer: safe `<svg>` markup (see `svgFrameMarkup`) in an absolutely placed `<span>`. */\n markup: string;\n /** The host's inline style: its position and size from the viewBox. */\n style: string;\n}\n\ninterface Resolved {\n motion: SvgMotion;\n hold?: number;\n trigger?: SvgTrigger;\n inline?: boolean | string;\n contain?: boolean;\n}\n\n/** Remembers the last motion made from an effect, so values compared by content do not remake it. */\ntype MotionCache = { key: string; effect: VectorEffectDefinition; motion: SvgMotion };\n\nfunction resolve(params: VectorEffectParams, cache?: { current?: MotionCache }): Resolved {\n if (params.motion) return { motion: params.motion, hold: params.hold, trigger: params.trigger, inline: params.inline, contain: params.contain };\n const { id, values, preset } = params as VectorEffectByIdParams;\n const effect = typeof id === \"string\" ? getEffect(id) : id;\n if (!effect || effect.kind !== \"vector\")\n throw new Error(\n `\"${typeof id === \"string\" ? id : (effect?.id ?? id)}\" is not a vector effect; pick one from findEffects({ kind: \"vector\" }), or pass a motion`,\n );\n const key = JSON.stringify([preset ?? null, values ?? {}]);\n let motion: SvgMotion;\n if (cache?.current && cache.current.effect === effect && cache.current.key === key) motion = cache.current.motion;\n else {\n motion = renderVectorEffect(effect, effectDefaults(effect, { preset, values }));\n if (cache) cache.current = { key, effect, motion };\n }\n return {\n motion,\n hold: params.hold ?? effect.hold,\n trigger: params.trigger ?? effect.trigger,\n inline: params.inline ?? values?.inline === true,\n contain: params.contain,\n };\n}\n\n/** The host's sizing from the picture's viewBox, so the still and the player take the same room. */\nfunction hostStyle(svg: string, inline: boolean | string | undefined, contain?: boolean): [string, string][] {\n const box = svgViewBox(svg);\n const style: [string, string][] = [\n [\"position\", \"relative\"],\n [\"display\", inline ? \"inline-block\" : \"block\"],\n ];\n if (inline) style.push([\"height\", typeof inline === \"string\" ? inline : CAP_HEIGHT]);\n if (box) style.push([\"aspect-ratio\", `${box[2]} / ${box[3]}`]);\n const spill = inline && contain ? svgInlineLayout(svg)?.overhang : undefined;\n if (spill) style.push([\"margin\", `${spill.top}em ${spill.right}em ${spill.bottom}em ${spill.left}em`]);\n return style;\n}\n\n/** Whether to wait until scrolled into view: as asked, else when it plays once. */\nconst enters = (r: Resolved, p: SvgPlayerParams) => p.playOnEnter ?? (p.loop === false && !r.trigger);\n\nfunction stillMarkup(r: Resolved, params: SvgPlayerParams): string {\n const at = params.poster ?? (r.trigger === \"hover\" || r.trigger === \"press\" ? \"first\" : \"last\");\n return svgFrameMarkup(r.motion, { at, steps: params.steps }) ?? \"\";\n}\n\n/**\n * The still of an effect or motion, for server rendering: put `markup` in the\n * element that has the `vectorEffect` action, with `style` as its style, so\n * the page shows the picture before the player starts (and instead of it\n * under reduced motion), in the room the player will take.\n * Throws when `id` is not a vector effect.\n */\nexport function vectorEffectStill(params: VectorEffectParams): VectorEffectStill {\n const r = resolve(params);\n return {\n markup: `<span ${STILL_ATTR} aria-hidden=\"true\" style=\"${LAYER}\">${stillMarkup(r, params)}</span>`,\n style: hostStyle(r.motion.svg, r.inline, r.contain)\n .map(([k, v]) => `${k}: ${v}`)\n .join(\"; \"),\n };\n}\n\nfunction prefersReducedMotion(): boolean {\n return typeof matchMedia === \"function\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/** The options whose change remakes the player (`speed` is set on it instead). */\nfunction playerKey(r: Resolved, p: SvgPlayerParams): unknown[] {\n return [\n r.motion,\n p.loop,\n p.autoplay,\n r.hold,\n p.duration,\n p.steps?.join(\",\"),\n r.trigger,\n p.pauseWhenHidden,\n enters(r, p),\n p.hideWhenPaused,\n p.clock,\n p.reducedMotion ?? \"user\",\n ];\n}\n\n/**\n * A Svelte action that plays a vector effect in its element:\n * `<span use:vectorEffect={{ id: \"drip-text\", values: { word: \"Slop\" }, loop: false }} />`.\n *\n * It makes an `SvgPlayer` in a layer of its own, remakes it when the params\n * change (values by content; `speed` without remaking) and disposes it on\n * destroy. A still from {@link vectorEffectStill} in the element is hidden\n * while the player runs and shown again after; without one, the action makes\n * its own (so reduced motion still shows the picture) and sizes the element\n * from the viewBox, leaving alone any of `position`, `display`, `height`,\n * `aspect-ratio` and `margin` the element's style already sets.\n *\n * For an attachment, `{@attach fromAction(vectorEffect, () => params)}`\n * (`fromAction` is from `svelte/attachments`). Throws when `id` is not a\n * vector effect.\n */\nexport function vectorEffect(node: HTMLElement, initial: VectorEffectParams): ActionReturn<VectorEffectParams> {\n const cache: { current?: MotionCache } = {};\n const doc = node.ownerDocument;\n const mount = doc.createElement(\"span\");\n mount.style.cssText = LAYER;\n node.appendChild(mount);\n\n let params = initial;\n let resolved = resolve(params, cache);\n let player: SvgPlayer | undefined;\n let key: unknown[] = [];\n /** The still the action made itself, when the element had none. */\n let ownStill: HTMLElement | undefined;\n /** Sizing properties the action set (the element's own style had them empty). */\n const sized = new Set<string>();\n\n const stills = () => node.querySelectorAll<HTMLElement>(`:scope > [${STILL_ATTR}]`);\n const showStills = (show: boolean) => {\n for (const s of stills()) s.style.display = show ? \"block\" : \"none\";\n };\n // When the params change Svelte replaces a server still (`{@html}`), and when\n // it is the element's only child, by setting `innerHTML`, which takes the\n // player's layer out too: put the layer back, and keep a new still hidden.\n const reattach = () => {\n if (mount.parentNode !== node) node.appendChild(mount);\n if (player) showStills(false);\n };\n const observer = typeof MutationObserver === \"function\" ? new MutationObserver(reattach) : undefined;\n observer?.observe(node, { childList: true });\n\n const size = () => {\n const style = hostStyle(resolved.motion.svg, resolved.inline, resolved.contain);\n for (const [prop, value] of style) {\n if (!sized.has(prop) && node.style.getPropertyValue(prop)) continue;\n node.style.setProperty(prop, value);\n sized.add(prop);\n }\n // A property the new sizing drops (`height` when no longer inline) is cleared.\n for (const prop of sized)\n if (!style.some(([p]) => p === prop)) {\n node.style.removeProperty(prop);\n sized.delete(prop);\n }\n };\n\n if (stills().length === 0) {\n ownStill = doc.createElement(\"span\");\n ownStill.setAttribute(STILL_ATTR, \"\");\n ownStill.setAttribute(\"aria-hidden\", \"true\");\n ownStill.style.cssText = LAYER;\n node.insertBefore(ownStill, mount);\n size();\n }\n\n const stop = () => {\n if (!player) return;\n player.dispose();\n player = undefined;\n showStills(true);\n params.onPlayer?.(undefined);\n };\n\n const start = () => {\n const reduced = params.reducedMotion ?? \"user\";\n if (reduced === \"always\" || (reduced === \"user\" && prefersReducedMotion())) return;\n player = new SvgPlayer(mount, resolved.motion, {\n loop: params.loop,\n autoplay: params.autoplay,\n speed: params.speed,\n hold: resolved.hold,\n duration: params.duration,\n steps: params.steps,\n trigger: resolved.trigger,\n pauseWhenHidden: params.pauseWhenHidden,\n playOnEnter: enters(resolved, params),\n hideWhenPaused: params.hideWhenPaused,\n clock: params.clock,\n // The latest params' callback, without remaking the player.\n onPick: (id) => params.onPick?.(id),\n });\n showStills(false);\n params.onPlayer?.(player);\n };\n\n const apply = () => {\n reattach();\n if (ownStill) {\n ownStill.innerHTML = stillMarkup(resolved, params);\n size();\n }\n const next = playerKey(resolved, params);\n if (player && next.every((v, i) => v === key[i])) {\n player.setSpeed(params.speed ?? 1);\n return;\n }\n key = next;\n stop();\n start();\n };\n\n apply();\n\n return {\n update(next) {\n params = next;\n resolved = resolve(params, cache);\n apply();\n },\n destroy() {\n observer?.disconnect();\n stop();\n mount.remove();\n ownStill?.remove();\n for (const prop of sized) node.style.removeProperty(prop);\n },\n };\n}\n\nexport type { SvgPlayer, SvgMotion, SvgTrigger };\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/svelte/index.ts"],"sourcesContent":["/**\n * Svelte 5 bindings for Flair, written as plain TypeScript so they need no\n * Svelte compiler: the `flairEffect` action runs any catalog effect (shader or\n * vector) applied to a picture, video, SVG or words; the `vectorEffect` action plays a catalog\n * effect (or any {@link SvgMotion}) in an element, and `vectorEffectStill`\n * gives the markup and style of its still for server rendering.\n *\n * ```svelte\n * <script>\n * import { vectorEffect, vectorEffectStill } from \"@pixerate/flair/svelte\";\n * const params = { id: \"drip-text\", values: { word: \"Slop\" }, loop: false };\n * const still = vectorEffectStill(params);\n * </script>\n *\n * <span use:vectorEffect={params} style={still.style}>{@html still.markup}</span>\n * ```\n *\n * The still is in place from the first paint; the live `SvgPlayer` takes over\n * after mount and is disposed on destroy. Under `prefers-reduced-motion:\n * reduce` the still stays.\n *\n * Needs Svelte 5 (an optional peer dependency of the package); only its types\n * are imported.\n *\n * @packageDocumentation\n */\n\nimport type { ActionReturn } from \"svelte/action\";\nimport { getEffect, effectDefaults, type EffectDefinition } from \"../catalog/index.js\";\nimport { mountEffect, type EffectSubject } from \"../embed/index.js\";\nimport { renderVectorEffect, type VectorEffect as VectorEffectDefinition } from \"../catalog/types.js\";\nimport type { ControlValue } from \"../shader/controls.js\";\nimport type { Clock } from \"../time/clock.js\";\nimport type { SvgMotion } from \"../vector/motion.js\";\nimport { svgFrameMarkup, svgInlineLayout, svgViewBox } from \"../vector/static.js\";\nimport { SvgPlayer, type SvgTrigger } from \"../vector/svg.js\";\n\n/** Cap height of a heavy sans, as a share of its font size: what an inline word is framed to. */\nconst CAP_HEIGHT = \"0.72em\";\n\n/** Marks the still's layer, so the action can find it (and hide it while the player runs). */\nconst STILL_ATTR = \"data-flair-still\";\n\nconst LAYER = \"position:absolute;inset:0;display:block\";\n\n/** When to leave the still in place of the animation. */\nexport type ReducedMotion = \"user\" | \"always\" | \"never\";\n\n/** Options shared by an effect by id and a motion of your own. */\nexport interface SvgPlayerParams {\n /** Start again at the end (default `true`); `false` plays once and stays on the last frame. */\n loop?: boolean;\n /** Start playing at once (default `true`). */\n autoplay?: boolean;\n /** Playback speed (default 1); changed without remaking the player. */\n speed?: number;\n /** Ms to rest on the last frame before looping (default 600, or the effect's). */\n hold?: number;\n /** Loop length in ms (default: the picture's own, plus `hold`). */\n duration?: number;\n /** Step start times in ms, for pictures that change on steps. */\n steps?: readonly number[];\n /** Plays in answer to the pointer (see `SvgTrigger`; default the effect's). */\n trigger?: SvgTrigger;\n /** Pause while scrolled out of view. */\n pauseWhenHidden?: boolean;\n /**\n * Wait to start until scrolled into view. Default `true` when it plays once\n * (`loop: false`, no trigger), so a one-shot further down the page does not\n * finish before anyone sees it; `false` plays at mount.\n */\n playOnEnter?: boolean;\n /** Hide the picture while paused or reset. */\n hideWhenPaused?: boolean;\n /** Time source (default animation frames); a `ManualClock` steps frames yourself. */\n clock?: Clock;\n /** Called with the id of the innermost element with an id that is clicked. */\n onPick?: (id: string) => void;\n /** Called with the player once it is made, and `undefined` when it is disposed. */\n onPlayer?: (player: SvgPlayer | undefined) => void;\n /**\n * The still shown before the player starts and instead of it under reduced\n * motion: `\"last\"` (default; the rest frame, `\"first\"` for a hover or press\n * trigger), `\"first\"` or a time in ms.\n */\n poster?: \"first\" | \"last\" | number;\n /**\n * `\"user\"` (default) shows the still when the visitor prefers reduced\n * motion, `\"always\"` always does, `\"never\"` always plays.\n */\n reducedMotion?: ReducedMotion;\n /**\n * Size it as a word in a line of text: `display: inline-block` with the\n * viewBox's aspect ratio and `height` 0.72em (the cap height of a heavy\n * sans; pass a CSS length for another). Default: the effect's `inline`\n * control. Otherwise it is a block as wide as its container with the\n * viewBox's aspect ratio.\n */\n inline?: boolean | string;\n /**\n * With `inline`, keep room for what spills past the word (descenders,\n * outlines, glows, drips): a margin of the picture's `data-overhang` (see\n * `svgInlineLayout`), so the lines around it make space instead of being\n * painted over. Default `false`.\n */\n contain?: boolean;\n}\n\n/** A catalog vector effect by id (or the effect itself), with its values. */\nexport interface VectorEffectByIdParams extends SvgPlayerParams {\n /** A vector effect's catalog id (`\"drip-text\"`), or the effect itself. */\n id: string | VectorEffectDefinition;\n /** Control values; missing ones take the preset's, then the defaults. Compared by content. */\n values?: Record<string, ControlValue>;\n /** A preset's name to start from. */\n preset?: string;\n motion?: never;\n}\n\n/** Any {@link SvgMotion}; a new object restarts the player. */\nexport interface SvgMotionParams extends SvgPlayerParams {\n /** The picture and its animations. */\n motion: SvgMotion;\n id?: never;\n values?: never;\n preset?: never;\n}\n\n/** What `vectorEffect` and `vectorEffectStill` take: an effect by `id`, or a `motion`. */\nexport type VectorEffectParams = VectorEffectByIdParams | SvgMotionParams;\n\n/** A still of the picture, for `{@html markup}` inside an element with `style`. */\nexport interface VectorEffectStill {\n /** The still's layer: safe `<svg>` markup (see `svgFrameMarkup`) in an absolutely placed `<span>`. */\n markup: string;\n /** The host's inline style: its position and size from the viewBox. */\n style: string;\n}\n\ninterface Resolved {\n motion: SvgMotion;\n hold?: number;\n trigger?: SvgTrigger;\n inline?: boolean | string;\n contain?: boolean;\n}\n\n/** Remembers the last motion made from an effect, so values compared by content do not remake it. */\ntype MotionCache = { key: string; effect: VectorEffectDefinition; motion: SvgMotion };\n\nfunction resolve(params: VectorEffectParams, cache?: { current?: MotionCache }): Resolved {\n if (params.motion) return { motion: params.motion, hold: params.hold, trigger: params.trigger, inline: params.inline, contain: params.contain };\n const { id, values, preset } = params as VectorEffectByIdParams;\n const effect = typeof id === \"string\" ? getEffect(id) : id;\n if (!effect || effect.kind !== \"vector\")\n throw new Error(\n `\"${typeof id === \"string\" ? id : (effect?.id ?? id)}\" is not a vector effect; pick one from findEffects({ kind: \"vector\" }), or pass a motion`,\n );\n const key = JSON.stringify([preset ?? null, values ?? {}]);\n let motion: SvgMotion;\n if (cache?.current && cache.current.effect === effect && cache.current.key === key) motion = cache.current.motion;\n else {\n motion = renderVectorEffect(effect, effectDefaults(effect, { preset, values }));\n if (cache) cache.current = { key, effect, motion };\n }\n return {\n motion,\n hold: params.hold ?? effect.hold,\n trigger: params.trigger ?? effect.trigger,\n inline: params.inline ?? values?.inline === true,\n contain: params.contain,\n };\n}\n\n/** The host's sizing from the picture's viewBox, so the still and the player take the same room. */\nfunction hostStyle(svg: string, inline: boolean | string | undefined, contain?: boolean): [string, string][] {\n const box = svgViewBox(svg);\n const style: [string, string][] = [\n [\"position\", \"relative\"],\n [\"display\", inline ? \"inline-block\" : \"block\"],\n ];\n if (inline) style.push([\"height\", typeof inline === \"string\" ? inline : CAP_HEIGHT]);\n if (box) style.push([\"aspect-ratio\", `${box[2]} / ${box[3]}`]);\n const spill = inline && contain ? svgInlineLayout(svg)?.overhang : undefined;\n if (spill) style.push([\"margin\", `${spill.top}em ${spill.right}em ${spill.bottom}em ${spill.left}em`]);\n return style;\n}\n\n/** Whether to wait until scrolled into view: as asked, else when it plays once. */\nconst enters = (r: Resolved, p: SvgPlayerParams) => p.playOnEnter ?? (p.loop === false && !r.trigger);\n\nfunction stillMarkup(r: Resolved, params: SvgPlayerParams): string {\n const at = params.poster ?? (r.trigger === \"hover\" || r.trigger === \"press\" ? \"first\" : \"last\");\n return svgFrameMarkup(r.motion, { at, steps: params.steps }) ?? \"\";\n}\n\n/**\n * The still of an effect or motion, for server rendering: put `markup` in the\n * element that has the `vectorEffect` action, with `style` as its style, so\n * the page shows the picture before the player starts (and instead of it\n * under reduced motion), in the room the player will take.\n * Throws when `id` is not a vector effect.\n */\nexport function vectorEffectStill(params: VectorEffectParams): VectorEffectStill {\n const r = resolve(params);\n return {\n markup: `<span ${STILL_ATTR} aria-hidden=\"true\" style=\"${LAYER}\">${stillMarkup(r, params)}</span>`,\n style: hostStyle(r.motion.svg, r.inline, r.contain)\n .map(([k, v]) => `${k}: ${v}`)\n .join(\"; \"),\n };\n}\n\nfunction prefersReducedMotion(): boolean {\n return typeof matchMedia === \"function\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/** The options whose change remakes the player (`speed` is set on it instead). */\nfunction playerKey(r: Resolved, p: SvgPlayerParams): unknown[] {\n return [\n r.motion,\n p.loop,\n p.autoplay,\n r.hold,\n p.duration,\n p.steps?.join(\",\"),\n r.trigger,\n p.pauseWhenHidden,\n enters(r, p),\n p.hideWhenPaused,\n p.clock,\n p.reducedMotion ?? \"user\",\n ];\n}\n\n/**\n * A Svelte action that plays a vector effect in its element:\n * `<span use:vectorEffect={{ id: \"drip-text\", values: { word: \"Slop\" }, loop: false }} />`.\n *\n * It makes an `SvgPlayer` in a layer of its own, remakes it when the params\n * change (values by content; `speed` without remaking) and disposes it on\n * destroy. A still from {@link vectorEffectStill} in the element is hidden\n * while the player runs and shown again after; without one, the action makes\n * its own (so reduced motion still shows the picture) and sizes the element\n * from the viewBox, leaving alone any of `position`, `display`, `height`,\n * `aspect-ratio` and `margin` the element's style already sets.\n *\n * For an attachment, `{@attach fromAction(vectorEffect, () => params)}`\n * (`fromAction` is from `svelte/attachments`). Throws when `id` is not a\n * vector effect.\n */\nexport function vectorEffect(node: HTMLElement, initial: VectorEffectParams): ActionReturn<VectorEffectParams> {\n const cache: { current?: MotionCache } = {};\n const doc = node.ownerDocument;\n const mount = doc.createElement(\"span\");\n mount.style.cssText = LAYER;\n node.appendChild(mount);\n\n let params = initial;\n let resolved = resolve(params, cache);\n let player: SvgPlayer | undefined;\n let key: unknown[] = [];\n /** The still the action made itself, when the element had none. */\n let ownStill: HTMLElement | undefined;\n /** Sizing properties the action set (the element's own style had them empty). */\n const sized = new Set<string>();\n\n const stills = () => node.querySelectorAll<HTMLElement>(`:scope > [${STILL_ATTR}]`);\n const showStills = (show: boolean) => {\n for (const s of stills()) s.style.display = show ? \"block\" : \"none\";\n };\n // When the params change Svelte replaces a server still (`{@html}`), and when\n // it is the element's only child, by setting `innerHTML`, which takes the\n // player's layer out too: put the layer back, and keep a new still hidden.\n const reattach = () => {\n if (mount.parentNode !== node) node.appendChild(mount);\n if (player) showStills(false);\n };\n const observer = typeof MutationObserver === \"function\" ? new MutationObserver(reattach) : undefined;\n observer?.observe(node, { childList: true });\n\n const size = () => {\n const style = hostStyle(resolved.motion.svg, resolved.inline, resolved.contain);\n for (const [prop, value] of style) {\n if (!sized.has(prop) && node.style.getPropertyValue(prop)) continue;\n node.style.setProperty(prop, value);\n sized.add(prop);\n }\n // A property the new sizing drops (`height` when no longer inline) is cleared.\n for (const prop of sized)\n if (!style.some(([p]) => p === prop)) {\n node.style.removeProperty(prop);\n sized.delete(prop);\n }\n };\n\n if (stills().length === 0) {\n ownStill = doc.createElement(\"span\");\n ownStill.setAttribute(STILL_ATTR, \"\");\n ownStill.setAttribute(\"aria-hidden\", \"true\");\n ownStill.style.cssText = LAYER;\n node.insertBefore(ownStill, mount);\n size();\n }\n\n const stop = () => {\n if (!player) return;\n player.dispose();\n player = undefined;\n showStills(true);\n params.onPlayer?.(undefined);\n };\n\n const start = () => {\n const reduced = params.reducedMotion ?? \"user\";\n if (reduced === \"always\" || (reduced === \"user\" && prefersReducedMotion())) return;\n player = new SvgPlayer(mount, resolved.motion, {\n loop: params.loop,\n autoplay: params.autoplay,\n speed: params.speed,\n hold: resolved.hold,\n duration: params.duration,\n steps: params.steps,\n trigger: resolved.trigger,\n pauseWhenHidden: params.pauseWhenHidden,\n playOnEnter: enters(resolved, params),\n hideWhenPaused: params.hideWhenPaused,\n clock: params.clock,\n // The latest params' callback, without remaking the player.\n onPick: (id) => params.onPick?.(id),\n });\n showStills(false);\n params.onPlayer?.(player);\n };\n\n const apply = () => {\n reattach();\n if (ownStill) {\n ownStill.innerHTML = stillMarkup(resolved, params);\n size();\n }\n const next = playerKey(resolved, params);\n if (player && next.every((v, i) => v === key[i])) {\n player.setSpeed(params.speed ?? 1);\n return;\n }\n key = next;\n stop();\n start();\n };\n\n apply();\n\n return {\n update(next) {\n params = next;\n resolved = resolve(params, cache);\n apply();\n },\n destroy() {\n observer?.disconnect();\n stop();\n mount.remove();\n ownStill?.remove();\n for (const prop of sized) node.style.removeProperty(prop);\n },\n };\n}\n\nexport type { SvgPlayer, SvgMotion, SvgTrigger };\n\n/** What the `flairEffect` action runs: any catalog effect, applied to a subject. */\nexport interface FlairEffectParams {\n /** A catalog effect, by id or definition: shader or vector. */\n effect: string | EffectDefinition;\n /** What to apply it to: a picture, a video, an SVG, words or a path (see `EffectSubject`). */\n subject?: EffectSubject | readonly EffectSubject[];\n preset?: string;\n values?: Record<string, ControlValue>;\n /** Start playing at once (default `true`). */\n autoplay?: boolean;\n /** Pause while scrolled out of view (default `true`). */\n pauseWhenHidden?: boolean;\n}\n\n/**\n * Runs any catalog effect, shader or vector, in an element, applied to a\n * subject (see `mountEffect` in `@pixerate/flair/embed`); it fills the\n * element, so size it with CSS. A new subject or values update the running\n * effect; a new effect, preset or playback option starts it again.\n *\n * ```svelte\n * <div use:flairEffect={{ effect: \"image-duotone\", subject: { image: \"/team.jpg\" } }} style=\"aspect-ratio: 16 / 9\"></div>\n * ```\n */\nexport function flairEffect(node: HTMLElement, initial: FlairEffectParams): ActionReturn<FlairEffectParams> {\n let params = initial;\n if (!node.style.position) node.style.position = \"relative\";\n const start = () => {\n const m = mountEffect(node, params.effect, {\n ...(params.subject ? { subject: params.subject } : {}),\n ...(params.preset ? { preset: params.preset } : {}),\n ...(params.values ? { values: params.values } : {}),\n autoplay: params.autoplay ?? true,\n pauseWhenHidden: params.pauseWhenHidden ?? true,\n });\n m.element.style.display = \"block\";\n m.element.style.width = \"100%\";\n m.element.style.height = \"100%\";\n return m;\n };\n let mounted = start();\n return {\n update(next) {\n const restart =\n next.effect !== params.effect || next.preset !== params.preset || next.autoplay !== params.autoplay || next.pauseWhenHidden !== params.pauseWhenHidden;\n const subjectChanged = next.subject !== params.subject;\n const valuesChanged = JSON.stringify(next.values ?? {}) !== JSON.stringify(params.values ?? {});\n params = next;\n if (restart) {\n mounted.dispose();\n mounted = start();\n return;\n }\n if (subjectChanged && next.subject) mounted.setSubject(next.subject);\n if (valuesChanged && next.values) mounted.setValues(next.values);\n },\n destroy() {\n mounted.dispose();\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/vector/index.d.ts
CHANGED
|
@@ -86,6 +86,57 @@ interface SvgFrameMarkupOptions {
|
|
|
86
86
|
*/
|
|
87
87
|
declare function svgFrameMarkup(motion: SvgMotion, options?: SvgFrameMarkupOptions): string | undefined;
|
|
88
88
|
|
|
89
|
+
/**
|
|
90
|
+
* An {@link SvgMotion} as one self-contained animated `.svg` file, with no
|
|
91
|
+
* DOM and no script: its changes written as SMIL (`<animate>`,
|
|
92
|
+
* `<animateTransform>`, `<animateMotion>`), so it plays on its own wherever
|
|
93
|
+
* an SVG image does (an `<img src>`, a file opened directly, inline markup).
|
|
94
|
+
*/
|
|
95
|
+
|
|
96
|
+
interface AnimatedSvgOptions {
|
|
97
|
+
/** Loop length in ms (default: `svgDuration(motion, steps)` + `hold`). */
|
|
98
|
+
duration?: number;
|
|
99
|
+
/** Ms to rest on the last frame before looping (default 600, like `SvgPlayer`). */
|
|
100
|
+
hold?: number;
|
|
101
|
+
/** Loop forever (default true); false plays once and holds the last frame. */
|
|
102
|
+
loop?: boolean;
|
|
103
|
+
/** Step start times in ms, for pictures that change on steps (like `SvgPlayer`'s `steps`). */
|
|
104
|
+
steps?: readonly number[];
|
|
105
|
+
/**
|
|
106
|
+
* Samples per second for what cannot be written exactly (counts, written
|
|
107
|
+
* text, a change cut short by the next, a `matrix` transform); default 30.
|
|
108
|
+
*/
|
|
109
|
+
fps?: number;
|
|
110
|
+
/**
|
|
111
|
+
* Added to the ids the picture refers to (its gradients, filters, clips,
|
|
112
|
+
* paths followed), so two files inlined in one page each use their own.
|
|
113
|
+
* Default: a hash of the motion, so the same motion gives the same file;
|
|
114
|
+
* `""` keeps ids as written.
|
|
115
|
+
*/
|
|
116
|
+
idSuffix?: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* The {@link SvgMotion} as one animated SVG file that plays and loops on its
|
|
120
|
+
* own, as `SvgPlayer` plays it, with no script: save it as `.svg`, put it in
|
|
121
|
+
* an `<img src>`, or inline it. Each element starts as the motion's first
|
|
122
|
+
* frame, so it still shows that where SMIL does not run.
|
|
123
|
+
*
|
|
124
|
+
* Attribute changes become one `<animate>` per attribute (`<animateTransform>`
|
|
125
|
+
* per function of a `transform`), with the eases written exactly as splines;
|
|
126
|
+
* `draw` animates `stroke-dashoffset`; `along` becomes `<animateMotion>` on
|
|
127
|
+
* the path; `view` animates the root `viewBox` (keeping `data-fixed` and
|
|
128
|
+
* `data-nonscaling` elements as the player does); `solo` toggles `display`.
|
|
129
|
+
* Counts and written text are sampled at `fps`, each text shown in its own
|
|
130
|
+
* `<tspan>` in turn.
|
|
131
|
+
*
|
|
132
|
+
* Limits: a `view` that frames an element by id stays where it is (it needs
|
|
133
|
+
* layout, as in `svgFrameMarkup`); `style` and other attributes SMIL cannot
|
|
134
|
+
* interpolate change in steps; ids are suffixed only where the picture
|
|
135
|
+
* refers to them (CSS `#id` selectors in a `<style>` are left as written).
|
|
136
|
+
* Undefined when `motion.svg` is not an `<svg>`.
|
|
137
|
+
*/
|
|
138
|
+
declare function svgAnimatedMarkup(motion: SvgMotion, options?: AnimatedSvgOptions): string | undefined;
|
|
139
|
+
|
|
89
140
|
type BoxFit = 'fill' | 'contain' | 'cover' | 'none' | 'scale-down';
|
|
90
141
|
type BoxAlignment = 'topLeft' | 'topCenter' | 'topRight' | 'centerLeft' | 'center' | 'centerRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight';
|
|
91
142
|
interface FittedBoxResult {
|
|
@@ -139,4 +190,4 @@ interface FormatUnitOptions {
|
|
|
139
190
|
*/
|
|
140
191
|
declare function formatUnit(value: number, format?: UnitFormat, options?: FormatUnitOptions): string;
|
|
141
192
|
|
|
142
|
-
export { type BoxAlignment, type BoxFit, type FittedBoxResult, type FormatUnitOptions, type MorphOptions, type StackLayoutOptions, SvgBox, type SvgFrameMarkupOptions, type SvgInlineLayout, SvgMotion, type UnitFormat, computeBoxFit, formatUnit, layoutStack, morphPaths, morphSequence, parseViewBox, remap, stepVariant, svgFrameMarkup, svgInlineLayout, svgViewBox };
|
|
193
|
+
export { type AnimatedSvgOptions, type BoxAlignment, type BoxFit, type FittedBoxResult, type FormatUnitOptions, type MorphOptions, type StackLayoutOptions, SvgBox, type SvgFrameMarkupOptions, type SvgInlineLayout, SvgMotion, type UnitFormat, computeBoxFit, formatUnit, layoutStack, morphPaths, morphSequence, parseViewBox, remap, stepVariant, svgAnimatedMarkup, svgFrameMarkup, svgInlineLayout, svgViewBox };
|
package/dist/vector/index.js
CHANGED
|
@@ -4,13 +4,16 @@ import {
|
|
|
4
4
|
layoutStack,
|
|
5
5
|
remap,
|
|
6
6
|
stepVariant
|
|
7
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-H6L67KHI.js";
|
|
8
|
+
import {
|
|
9
|
+
svgAnimatedMarkup
|
|
10
|
+
} from "../chunk-YBGRXVAE.js";
|
|
8
11
|
import {
|
|
9
12
|
parseViewBox,
|
|
10
13
|
svgFrameMarkup,
|
|
11
14
|
svgInlineLayout,
|
|
12
15
|
svgViewBox
|
|
13
|
-
} from "../chunk-
|
|
16
|
+
} from "../chunk-STKEKXCK.js";
|
|
14
17
|
import {
|
|
15
18
|
EASES,
|
|
16
19
|
SCRAMBLE_MS,
|
|
@@ -33,11 +36,11 @@ import {
|
|
|
33
36
|
svgView,
|
|
34
37
|
writtenText
|
|
35
38
|
} from "../chunk-PFGGPIMT.js";
|
|
39
|
+
import "../chunk-WMZQCUFJ.js";
|
|
36
40
|
import {
|
|
37
41
|
morphPaths,
|
|
38
42
|
morphSequence
|
|
39
|
-
} from "../chunk-
|
|
40
|
-
import "../chunk-WMZQCUFJ.js";
|
|
43
|
+
} from "../chunk-ORAFCHX3.js";
|
|
41
44
|
export {
|
|
42
45
|
EASES,
|
|
43
46
|
SCRAMBLE_MS,
|
|
@@ -61,6 +64,7 @@ export {
|
|
|
61
64
|
stepProgress,
|
|
62
65
|
stepStart,
|
|
63
66
|
stepVariant,
|
|
67
|
+
svgAnimatedMarkup,
|
|
64
68
|
svgDuration,
|
|
65
69
|
svgFrame,
|
|
66
70
|
svgFrameMarkup,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pixerate/flair",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "Web visual effects and motion graphics: WebGL2 shader effects, animated vector effects, a catalog of ready-made effects, and a UI-agnostic, agent-ready effect editor.",
|
|
5
5
|
"author": "Pixerate",
|
|
6
6
|
"license": "MIT",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/shader/textures.ts","../src/shader/pointer.ts","../src/shader/program.ts","../src/shader/color.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","/**\n * Perceptual Color Science & Film Grading Engine.\n *\n * Implements:\n * - Oklab & Oklch: Perceptually uniform color spaces that eliminate hue shifts and gray dead zones.\n * - Standard Color Spaces: sRGB, Linear sRGB, Rec.709, Display P3, and ACEScg.\n * - Film Color Grading: ASC CDL (Slope, Offset, Power), Lift/Gamma/Gain, Vibrance (skin tone protection),\n * and White Balance (Kelvin color temperature & tint).\n * - GLSL code generators for real-time WebGL fragment shader execution.\n */\n\nexport type ColorRGB = [number, number, number];\nexport type ColorRGBA = [number, number, number, number];\n\n// -----------------------------------------------------------------------------\n// sRGB <-> Linear Transfer Curves\n// -----------------------------------------------------------------------------\n\nexport function srgbToLinear(c: number): number {\n const v = Math.max(0, c);\n return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);\n}\n\nexport function linearToSrgb(c: number): number {\n const v = Math.max(0, c);\n return v <= 0.0031308 ? v * 12.92 : 1.055 * Math.pow(v, 1.0 / 2.4) - 0.055;\n}\n\nexport function srgbToLinearRgb(rgb: ColorRGB): ColorRGB {\n return [srgbToLinear(rgb[0]), srgbToLinear(rgb[1]), srgbToLinear(rgb[2])];\n}\n\nexport function linearRgbToSrgb(rgb: ColorRGB): ColorRGB {\n return [linearToSrgb(rgb[0]), linearToSrgb(rgb[1]), linearToSrgb(rgb[2])];\n}\n\n// -----------------------------------------------------------------------------\n// Oklab & Oklch Perceptual Color Spaces (Björn Ottosson, 2020)\n// -----------------------------------------------------------------------------\n\nexport function linearSrgbToOklab(rgb: ColorRGB): [number, number, number] {\n const [r, g, b] = rgb;\n\n // Linear sRGB to LMS cone response\n const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);\n const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);\n const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);\n\n // LMS to Oklab (L: lightness [0..1], a: green-red, b: blue-yellow)\n const L = 0.2104542553 * l + 0.793617785 * m - 0.0040720468 * s;\n const a = 1.9779984951 * l - 2.428592205 * m + 0.4505937099 * s;\n const bVal = 0.0259040371 * l + 0.7827717662 * m - 0.808675766 * s;\n\n return [L, a, bVal];\n}\n\nexport function oklabToLinearSrgb(lab: [number, number, number]): ColorRGB {\n const [L, a, b] = lab;\n\n const l_ = L + 0.3963377774 * a + 0.2158037573 * b;\n const m_ = L - 0.1055613458 * a - 0.0638541728 * b;\n const s_ = L - 0.0894841775 * a - 1.291485548 * b;\n\n const l = l_ * l_ * l_;\n const m = m_ * m_ * m_;\n const s = s_ * s_ * s_;\n\n const r = +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;\n const g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;\n const bVal = -0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s;\n\n return [r, g, bVal];\n}\n\nexport function srgbToOklab(rgb: ColorRGB): [number, number, number] {\n return linearSrgbToOklab(srgbToLinearRgb(rgb));\n}\n\nexport function oklabToSrgb(lab: [number, number, number]): ColorRGB {\n const linear = oklabToLinearSrgb(lab);\n return linearRgbToSrgb(linear);\n}\n\nexport function oklabToOklch(lab: [number, number, number]): [number, number, number] {\n const [L, a, b] = lab;\n const C = Math.sqrt(a * a + b * b);\n let h = Math.atan2(b, a);\n if (h < 0) h += 2 * Math.PI;\n return [L, C, h];\n}\n\nexport function oklchToOklab(lch: [number, number, number]): [number, number, number] {\n const [L, C, h] = lch;\n return [L, C * Math.cos(h), C * Math.sin(h)];\n}\n\n/**\n * Perceptually uniform color interpolation using Oklab space.\n * Prevents intermediate grayish dead spots.\n */\nexport function interpolateOklab(c1: ColorRGB, c2: ColorRGB, t: number): ColorRGB {\n const lab1 = srgbToOklab(c1);\n const lab2 = srgbToOklab(c2);\n const clampedT = Math.max(0, Math.min(1, t));\n\n const lab: [number, number, number] = [\n lab1[0] + (lab2[0] - lab1[0]) * clampedT,\n lab1[1] + (lab2[1] - lab1[1]) * clampedT,\n lab1[2] + (lab2[2] - lab1[2]) * clampedT,\n ];\n\n const res = oklabToSrgb(lab);\n return [\n Math.max(0, Math.min(1, res[0])),\n Math.max(0, Math.min(1, res[1])),\n Math.max(0, Math.min(1, res[2])),\n ];\n}\n\n/**\n * Perceptually uniform color interpolation using Oklch cylindrical space.\n * Interpolates along the shortest hue arc for vibrant gradients.\n */\nexport function interpolateOklch(c1: ColorRGB, c2: ColorRGB, t: number): ColorRGB {\n const lch1 = oklabToOklch(srgbToOklab(c1));\n const lch2 = oklabToOklch(srgbToOklab(c2));\n const clampedT = Math.max(0, Math.min(1, t));\n\n const L = lch1[0] + (lch2[0] - lch1[0]) * clampedT;\n const C = lch1[1] + (lch2[1] - lch1[1]) * clampedT;\n\n // Shortest arc hue interpolation\n let dHue = lch2[2] - lch1[2];\n if (dHue > Math.PI) dHue -= 2 * Math.PI;\n if (dHue < -Math.PI) dHue += 2 * Math.PI;\n let h = lch1[2] + dHue * clampedT;\n if (h < 0) h += 2 * Math.PI;\n if (h >= 2 * Math.PI) h -= 2 * Math.PI;\n\n const res = oklabToSrgb(oklchToOklab([L, C, h]));\n return [\n Math.max(0, Math.min(1, res[0])),\n Math.max(0, Math.min(1, res[1])),\n Math.max(0, Math.min(1, res[2])),\n ];\n}\n\n// -----------------------------------------------------------------------------\n// Color Space Transformations (sRGB, Rec.709, Display P3, ACEScg)\n// -----------------------------------------------------------------------------\n\nexport type ColorSpace = 'srgb' | 'linear-srgb' | 'rec709' | 'display-p3' | 'acescg';\n\ntype Matrix3x3 = [\n number, number, number,\n number, number, number,\n number, number, number\n];\n\nfunction mulMat3(m: Matrix3x3, v: ColorRGB): ColorRGB {\n return [\n m[0] * v[0] + m[1] * v[1] + m[2] * v[2],\n m[3] * v[0] + m[4] * v[1] + m[5] * v[2],\n m[6] * v[0] + m[7] * v[1] + m[8] * v[2],\n ];\n}\n\n// Linear sRGB to Display P3 (linear)\nconst MAT_LINEAR_SRGB_TO_P3: Matrix3x3 = [\n 0.822462, 0.177538, 0.000000,\n 0.033194, 0.966806, 0.000000,\n 0.017083, 0.072397, 0.910520,\n];\n\n// Display P3 (linear) to Linear sRGB\nconst MAT_P3_TO_LINEAR_SRGB: Matrix3x3 = [\n 1.224940, -0.224940, 0.000000,\n -0.042057, 1.042057, 0.000000,\n -0.019638, -0.078636, 1.098274,\n];\n\n// Linear sRGB to ACEScg (AP1 primaries with Bradford adaptation to ACES white)\nconst MAT_LINEAR_SRGB_TO_ACESCG: Matrix3x3 = [\n 0.613097, 0.339523, 0.047379,\n 0.070194, 0.916354, 0.013452,\n 0.020616, 0.109570, 0.869815,\n];\n\n// ACEScg to Linear sRGB\nconst MAT_ACESCG_TO_LINEAR_SRGB: Matrix3x3 = [\n 1.704859, -0.621714, -0.083299,\n -0.130078, 1.140735, -0.010560,\n -0.023964, -0.128975, 1.153014,\n];\n\n/**\n * Converts a color between standard imaging color spaces.\n */\nexport function convertColorSpace(color: ColorRGB, from: ColorSpace, to: ColorSpace): ColorRGB {\n if (from === to) return [...color];\n\n // First convert `from` to Linear sRGB\n let lin: ColorRGB;\n switch (from) {\n case 'srgb':\n lin = srgbToLinearRgb(color);\n break;\n case 'linear-srgb':\n lin = [...color];\n break;\n case 'rec709':\n // BT.709 gamma 2.4 EOTF\n lin = [\n Math.pow(Math.max(0, color[0]), 2.4),\n Math.pow(Math.max(0, color[1]), 2.4),\n Math.pow(Math.max(0, color[2]), 2.4),\n ];\n break;\n case 'display-p3': {\n // P3 sRGB transfer to linear P3, then matrix to linear sRGB\n const p3Lin = srgbToLinearRgb(color);\n lin = mulMat3(MAT_P3_TO_LINEAR_SRGB, p3Lin);\n break;\n }\n case 'acescg':\n lin = mulMat3(MAT_ACESCG_TO_LINEAR_SRGB, color);\n break;\n }\n\n // Then convert from Linear sRGB to `to`\n switch (to) {\n case 'linear-srgb':\n return lin;\n case 'srgb':\n return linearRgbToSrgb(lin);\n case 'rec709':\n // BT.709 gamma 1/2.4\n return [\n Math.pow(Math.max(0, lin[0]), 1 / 2.4),\n Math.pow(Math.max(0, lin[1]), 1 / 2.4),\n Math.pow(Math.max(0, lin[2]), 1 / 2.4),\n ];\n case 'display-p3': {\n const p3Lin = mulMat3(MAT_LINEAR_SRGB_TO_P3, lin);\n return linearRgbToSrgb(p3Lin);\n }\n case 'acescg':\n return mulMat3(MAT_LINEAR_SRGB_TO_ACESCG, lin);\n }\n}\n\n// -----------------------------------------------------------------------------\n// Film Color Grading: ASC CDL, Lift/Gamma/Gain, Vibrance, White Balance\n// -----------------------------------------------------------------------------\n\nexport interface AscCdl {\n /** Multiplicative scaling (default [1, 1, 1]) */\n slope?: ColorRGB;\n /** Additive offset (default [0, 0, 0]) */\n offset?: ColorRGB;\n /** Exponential power (default [1, 1, 1]) */\n power?: ColorRGB;\n /** Master saturation (default 1.0) */\n saturation?: number;\n}\n\n/**\n * Standard ASC CDL (American Society of Cinematographers Color Decision List).\n * Formula: out = (in * slope + offset)^power, followed by Rec.709 luma-weighted saturation.\n */\nexport function applyAscCdl(color: ColorRGB, cdl: AscCdl): ColorRGB {\n const slope = cdl.slope ?? [1, 1, 1];\n const offset = cdl.offset ?? [0, 0, 0];\n const power = cdl.power ?? [1, 1, 1];\n const sat = cdl.saturation ?? 1.0;\n\n let r = Math.pow(Math.max(0, color[0] * slope[0] + offset[0]), power[0]);\n let g = Math.pow(Math.max(0, color[1] * slope[1] + offset[1]), power[1]);\n let b = Math.pow(Math.max(0, color[2] * slope[2] + offset[2]), power[2]);\n\n if (sat !== 1.0) {\n const luma = 0.2126 * r + 0.7152 * g + 0.0722 * b;\n r = luma + sat * (r - luma);\n g = luma + sat * (g - luma);\n b = luma + sat * (b - luma);\n }\n\n return [Math.max(0, r), Math.max(0, g), Math.max(0, b)];\n}\n\nexport interface LiftGammaGain {\n /** Shadows adjustment (default [0, 0, 0]) */\n lift?: ColorRGB;\n /** Midtones gamma adjustment (default [1, 1, 1]) */\n gamma?: ColorRGB;\n /** Highlights gain adjustment (default [1, 1, 1]) */\n gain?: ColorRGB;\n}\n\n/**\n * Three-way Lift / Gamma / Gain film color grading.\n * Formula: out = (gain * (in + lift * (1 - in)))^(1 / gamma)\n */\nexport function applyLiftGammaGain(color: ColorRGB, lgg: LiftGammaGain): ColorRGB {\n const lift = lgg.lift ?? [0, 0, 0];\n const gamma = lgg.gamma ?? [1, 1, 1];\n const gain = lgg.gain ?? [1, 1, 1];\n\n const processChannel = (val: number, l: number, gm: number, gn: number): number => {\n const lifted = val + l * (1.0 - val);\n const gained = Math.max(0, lifted * gn);\n const safeGamma = Math.max(1e-4, gm);\n return Math.pow(gained, 1.0 / safeGamma);\n };\n\n return [\n processChannel(color[0], lift[0], gamma[0], gain[0]),\n processChannel(color[1], lift[1], gamma[1], gain[1]),\n processChannel(color[2], lift[2], gamma[2], gain[2]),\n ];\n}\n\n/**\n * Vibrance adjustment with skin tone protection.\n * Selectively boosts muted colors while preventing already saturated colors and skin tones\n * from clipping.\n * @param amount Vibrance delta in [-1..1]\n */\nexport function applyVibrance(color: ColorRGB, amount: number): ColorRGB {\n if (Math.abs(amount) < 1e-4) return [...color];\n\n const [r, g, b] = color;\n const maxC = Math.max(r, g, b);\n const minC = Math.min(r, g, b);\n const sat = maxC > 1e-5 ? (maxC - minC) / maxC : 0;\n\n // Protect warm skin tones (hue around red/orange/yellow: r > g > b)\n let skinProtection = 1.0;\n if (r > g && g > b) {\n const skinFactor = (g - b) / (r - b + 1e-5);\n skinProtection = Math.max(0.2, 1.0 - skinFactor * 0.5);\n }\n\n // Weight inversely proportional to current saturation\n const boost = amount * (1.0 - sat) * skinProtection;\n const luma = 0.2126 * r + 0.7152 * g + 0.0722 * b;\n\n const newR = Math.max(0, Math.min(1, luma + (1 + boost) * (r - luma)));\n const newG = Math.max(0, Math.min(1, luma + (1 + boost) * (g - luma)));\n const newB = Math.max(0, Math.min(1, luma + (1 + boost) * (b - luma)));\n\n return [newR, newG, newB];\n}\n\n/**\n * Calculates RGB multiplier from Kelvin blackbody color temperature and green/magenta tint.\n * @param kelvin Temperature in Kelvin [2000..12000], D65 neutral is 6500K.\n * @param tint Green/magenta shift in [-100..100] (0 = neutral).\n */\nexport function getWhiteBalanceGains(kelvin: number, tint = 0): ColorRGB {\n const k = Math.max(2000, Math.min(12000, kelvin)) / 100.0;\n\n let r: number;\n let g: number;\n let b: number;\n\n if (k <= 66) {\n r = 255;\n g = 99.4708025861 * Math.log(k) - 161.1195681661;\n b = k <= 19 ? 0 : 138.5177312231 * Math.log(k - 10) - 305.0447927307;\n } else {\n r = 329.698727446 * Math.pow(k - 60, -0.1332047592);\n g = 288.1221695283 * Math.pow(k - 60, -0.0755148492);\n b = 255;\n }\n\n // Normalize D65 (6500K) to [1, 1, 1]\n const d65R = 255;\n const d65G = 250.7;\n const d65B = 255;\n\n let gainR = r / d65R;\n let gainG = g / d65G;\n let gainB = b / d65B;\n\n // Tint adjustment (green vs magenta)\n const tintFactor = tint / 100.0;\n gainG *= 1.0 - tintFactor * 0.15;\n gainR *= 1.0 + tintFactor * 0.05;\n gainB *= 1.0 + tintFactor * 0.05;\n\n return [gainR, gainG, gainB];\n}\n\n// -----------------------------------------------------------------------------\n// GLSL Shaders\n// -----------------------------------------------------------------------------\n\n/**\n * Self-contained GLSL functions for fast Oklab <-> Linear sRGB transforms.\n */\nexport function getOklabGLSL(): string {\n return `\n// Oklab <-> Linear sRGB (Björn Ottosson)\nvec3 flair_linear_to_oklab(vec3 c) {\n float l = pow(0.4122214708 * c.r + 0.5363325363 * c.g + 0.0514459929 * c.b, 1.0 / 3.0);\n float m = pow(0.2119034982 * c.r + 0.6806995451 * c.g + 0.1073969566 * c.b, 1.0 / 3.0);\n float s = pow(0.0883024619 * c.r + 0.2817188376 * c.g + 0.6299787005 * c.b, 1.0 / 3.0);\n return vec3(\n 0.2104542553 * l + 0.7936177850 * m - 0.0040720468 * s,\n 1.9779984951 * l - 2.4285922050 * m + 0.4505937099 * s,\n 0.0259040371 * l + 0.7827717662 * m - 0.8086757660 * s\n );\n}\n\nvec3 flair_oklab_to_linear(vec3 lab) {\n float l_ = lab.x + 0.3963377774 * lab.y + 0.2158037573 * lab.z;\n float m_ = lab.x - 0.1055613458 * lab.y - 0.0638541728 * lab.z;\n float s_ = lab.x - 0.0894841775 * lab.y - 1.2914855480 * lab.z;\n float l = l_ * l_ * l_;\n float m = m_ * m_ * m_;\n float s = s_ * s_ * s_;\n return vec3(\n +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s,\n -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s,\n -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s\n );\n}\n`.trim();\n}\n\n/**\n * Self-contained GLSL functions for ASC CDL and Lift/Gamma/Gain grading.\n */\nexport function getColorGradingGLSL(): string {\n return `\n// ASC CDL Grading\nvec3 flair_cdl(vec3 color, vec3 slope, vec3 offset, vec3 power, float sat) {\n vec3 c = pow(max(color * slope + offset, vec3(0.0)), power);\n float luma = dot(c, vec3(0.2126, 0.7152, 0.0722));\n return mix(vec3(luma), c, sat);\n}\n\n// 3-Way Lift / Gamma / Gain Grading\nvec3 flair_lift_gamma_gain(vec3 color, vec3 lift, vec3 gamma, vec3 gain) {\n vec3 lifted = color + lift * (vec3(1.0) - color);\n vec3 gained = max(lifted * gain, vec3(0.0));\n return pow(gained, 1.0 / max(gamma, vec3(0.0001)));\n}\n`.trim();\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vector/static.ts"],"sourcesContent":["/**\n * An {@link SvgMotion}'s frame as markup, with no DOM: for server rendering\n * (a still that hydrates without a blank flash), reduced motion and other\n * places a live player is not wanted.\n */\n\nimport { SVG_PICTURE, svgFrame, type SvgBox, type SvgMotion } from \"./motion.js\";\nimport { svgDuration } from \"./svg.js\";\n\ninterface Node {\n tag: string;\n attrs: [string, string][];\n children: (Node | string)[];\n}\n\n/** Elements dropped with all they hold: they run code or show outside markup. */\nconst DROPPED = new Set([\"script\", \"foreignobject\", \"iframe\", \"object\", \"embed\"]);\nconst ATTR = /([^\\s=/>\"']+)(?:\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)'|([^\\s>\"']+)))?/g;\nconst TOKEN = /<!--[\\s\\S]*?(?:-->|$)|<!\\[CDATA\\[([\\s\\S]*?)(?:\\]\\]>|$)|<[!?][^>]*>|<\\/\\s*([\\w:.-]+)\\s*>|<([\\w:.-]+)((?:\\s+[^\\s=/>\"']+(?:\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s>\"']+))?)*)\\s*(\\/?)>/g;\n\nconst ENTITIES: Record<string, string> = { amp: \"&\", lt: \"<\", gt: \">\", quot: '\"', apos: \"'\", nbsp: \" \" };\nconst decode = (s: string) =>\n s.replace(/&(#x[0-9a-f]+|#\\d+|\\w+);/gi, (match, e: string) => {\n if (e[0] !== \"#\") return ENTITIES[e.toLowerCase()] ?? match;\n const code = e[1] === \"x\" || e[1] === \"X\" ? parseInt(e.slice(2), 16) : parseInt(e.slice(1), 10);\n return code > 0 && code <= 0x10ffff ? String.fromCodePoint(code) : \"\";\n });\nconst escapeText = (s: string) => s.replace(/&/g, \"&\").replace(/</g, \"<\").replace(/>/g, \">\");\nconst escapeAttr = (s: string) => escapeText(s).replace(/\"/g, \""\");\n\n/** Safe as `parseSvg` keeps it: no handlers, and links only within the picture or to data images. */\nfunction safeAttr(name: string, value: string): boolean {\n const n = name.toLowerCase();\n if (n.startsWith(\"on\") || !/^[a-z_][\\w:.-]*$/i.test(n)) return false;\n if (n === \"href\" || n === \"xlink:href\" || n === \"src\") return /^(#|data:image\\/)/i.test(value.trim());\n return true;\n}\n\n/** The `<svg>` in `markup` as a tree, without anything `parseSvg` would remove. */\nfunction parse(markup: string): Node | undefined {\n const root: Node = { tag: \"\", attrs: [], children: [] };\n const stack = [root];\n let dropping = 0;\n let at = 0;\n const text = (s: string) => {\n if (!dropping && s) stack[stack.length - 1]!.children.push(decode(s));\n };\n for (const m of markup.matchAll(TOKEN)) {\n text(markup.slice(at, m.index));\n at = m.index + m[0].length;\n const [, cdata, close, open, attrs = \"\", selfClosing] = m;\n if (cdata !== undefined) {\n if (!dropping) stack[stack.length - 1]!.children.push(cdata);\n } else if (close) {\n const tag = close.toLowerCase();\n if (dropping) {\n if (DROPPED.has(tag)) dropping--;\n continue;\n }\n // Close up to the matching element; a stray closing tag is ignored.\n let i = stack.length - 1;\n while (i > 0 && stack[i]!.tag.toLowerCase() !== tag) i--;\n if (i > 0) stack.length = i;\n } else if (open) {\n if (DROPPED.has(open.toLowerCase())) {\n if (!selfClosing) dropping++;\n continue;\n }\n if (dropping) continue;\n const node: Node = { tag: open, attrs: [], children: [] };\n for (const a of attrs.matchAll(ATTR)) {\n const value = decode(a[2] ?? a[3] ?? a[4] ?? \"\");\n if (safeAttr(a[1]!, value)) node.attrs.push([a[1]!, value]);\n }\n stack[stack.length - 1]!.children.push(node);\n if (!selfClosing) stack.push(node);\n }\n }\n text(markup.slice(at));\n const svg = root.children.find((c): c is Node => typeof c !== \"string\");\n return svg && svg.tag.toLowerCase() === \"svg\" ? svg : undefined;\n}\n\nfunction serialize(node: Node | string): string {\n if (typeof node === \"string\") return escapeText(node);\n const attrs = node.attrs.map(([k, v]) => ` ${k}=\"${escapeAttr(v)}\"`).join(\"\");\n return `<${node.tag}${attrs}>${node.children.map(serialize).join(\"\")}</${node.tag}>`;\n}\n\nfunction setAttr(node: Node, name: string, value: string | undefined) {\n const i = node.attrs.findIndex(([k]) => k === name);\n if (value === undefined) {\n if (i >= 0) node.attrs.splice(i, 1);\n } else if (!safeAttr(name, value)) return;\n else if (i >= 0) node.attrs[i]![1] = value;\n else node.attrs.push([name, value]);\n}\n\nconst getAttr = (node: Node, name: string) => node.attrs.find(([k]) => k === name)?.[1];\n\n/** A `viewBox` attribute's box, or undefined when it has none or it is malformed. */\nexport function parseViewBox(value: string | null | undefined): SvgBox | undefined {\n const box = (value ?? \"\").trim().split(/[\\s,]+/).map(Number);\n return box.length === 4 && box.every(Number.isFinite) && box[2]! > 0 && box[3]! > 0\n ? (box as unknown as SvgBox)\n : undefined;\n}\n\n/** The `viewBox` on an SVG's opening tag (see {@link parseViewBox}). */\nexport function svgViewBox(markup: string): SvgBox | undefined {\n const open = /<svg\\b[^>]*>/i.exec(markup)?.[0] ?? \"\";\n return parseViewBox(/\\sviewBox\\s*=\\s*(?:\"([^\"]*)\"|'([^']*)')/i.exec(open)?.slice(1).find((v) => v !== undefined));\n}\n\n/** How a picture framed for a line of text (a text effect's `inline`) sits in it; see {@link svgInlineLayout}. */\nexport interface SvgInlineLayout {\n /** Its viewBox: x, y, width, height. */\n viewBox: SvgBox;\n /** Width over height, for its host's CSS `aspect-ratio`. */\n aspectRatio: number;\n /**\n * How far it reaches past its box at rest (descenders, outlines, glows,\n * drips), in ems of the font size it is set at; 0 where the picture says\n * nothing (no `data-overhang`).\n */\n overhang: { top: number; right: number; bottom: number; left: number };\n}\n\n/**\n * The box and overhang on an SVG's opening tag: its `viewBox`, and\n * `data-overhang=\"top right bottom left\"` (ems), which text effects write.\n * Set inline (`height: 0.72em`, the cap height they frame), give the host a\n * margin of the overhang to keep room for what spills out:\n * `margin: ${top}em ${right}em ${bottom}em ${left}em`.\n */\nexport function svgInlineLayout(markup: string): SvgInlineLayout | undefined {\n const viewBox = svgViewBox(markup);\n if (!viewBox || !(viewBox[3] > 0)) return undefined;\n const open = /<svg\\b[^>]*>/i.exec(markup)?.[0] ?? \"\";\n const spill = (/\\sdata-overhang\\s*=\\s*\"([^\"]*)\"/i.exec(open)?.[1] ?? \"\").trim().split(/\\s+/).map(Number);\n const [top, right, bottom, left] = [0, 1, 2, 3].map((i) => (Number.isFinite(spill[i]) ? Math.max(0, spill[i]!) : 0));\n return { viewBox, aspectRatio: viewBox[2] / viewBox[3], overhang: { top: top!, right: right!, bottom: bottom!, left: left! } };\n}\n\nexport interface SvgFrameMarkupOptions {\n /**\n * The time shown, in ms: a number, `\"first\"` (0) or `\"last\"` (the end of\n * its last change, see `svgDuration`; the default).\n */\n at?: number | \"first\" | \"last\";\n /** Step start times in ms, as a player's `steps` (default none). */\n steps?: readonly number[];\n}\n\n/**\n * The picture of an {@link SvgMotion} at a moment, as `<svg>` markup made safe\n * the way `parseSvg` makes it (no scripts, handlers, `<foreignObject>` or\n * outside links), with no DOM needed: render it on a server, show it under\n * `prefers-reduced-motion`, or anywhere a still will do. It is sized to fill\n * its container, as `SvgPlayer` draws it.\n *\n * It matches the player's frame except where that needs layout: a change\n * `along` a path, and a `view` that frames an element by id, stay where the\n * markup puts them. Undefined when `motion.svg` is not an `<svg>`.\n */\nexport function svgFrameMarkup(motion: SvgMotion, options: SvgFrameMarkupOptions = {}): string | undefined {\n const svg = parse(motion.svg.trim());\n if (!svg) return undefined;\n const steps = options.steps ?? [];\n const at = options.at ?? \"last\";\n const time = at === \"first\" ? 0 : at === \"last\" ? svgDuration(motion, steps) : at;\n const byId = new Map<string, Node>();\n const index = (node: Node) => {\n const id = getAttr(node, \"id\");\n if (id && !byId.has(id)) byId.set(id, node);\n for (const c of node.children) if (typeof c !== \"string\") index(c);\n };\n index(svg);\n const whole = parseViewBox(getAttr(svg, \"viewBox\"));\n for (const [id, frame] of svgFrame(motion.animate ?? [], steps, time)) {\n if (id === SVG_PICTURE && frame.view) {\n const { from, to, u } = frame.view;\n const a = from === null ? whole : typeof from === \"string\" ? undefined : from;\n const b = typeof to === \"string\" ? undefined : to;\n if (a && b) setAttr(svg, \"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)) setAttr(el, name, value);\n if (frame.draw !== undefined) {\n setAttr(el, \"pathLength\", \"1\");\n setAttr(el, \"stroke-dasharray\", \"1 1\");\n setAttr(el, \"stroke-dashoffset\", String(1 - frame.draw));\n }\n if (frame.text !== undefined) el.children = [frame.text];\n if (frame.solo !== undefined) {\n let i = 0;\n for (const child of el.children)\n if (typeof child !== \"string\") setAttr(child, \"display\", i++ === frame.solo ? undefined : \"none\");\n }\n }\n setAttr(svg, \"width\", \"100%\");\n setAttr(svg, \"height\", \"100%\");\n if (!getAttr(svg, \"xmlns\")) setAttr(svg, \"xmlns\", \"http://www.w3.org/2000/svg\");\n return serialize(svg);\n}\n"],"mappings":"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","names":[]}
|