@pixerate/flair 0.14.0 → 0.15.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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @pixerate/flair
2
2
 
3
+ ## 0.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 61b2ed6: New `@pixerate/flair/react` entry point, with `react` (>= 18) as an optional peer dependency:
8
+
9
+ - `<VectorEffect id="drip-text" values={{ word: "Slop" }} loop={false} />` plays a catalog vector effect; `<SvgPlayerView motion={...} />` plays any `SvgMotion`. Each makes an `SvgPlayer` after mount and disposes it on unmount.
10
+ - Server-renders a still of the last frame, sized from the viewBox, so hydration neither shifts the layout nor flashes blank. The still stays under `prefers-reduced-motion` (`reducedMotion` overrides).
11
+ - `inline` (or an effect's `inline` control, like drip text's) sizes it as a word in a line: `inline-block`, 0.72em high, with the viewBox's aspect ratio.
12
+
13
+ `@pixerate/flair/vector` adds `svgFrameMarkup(motion, { at })`, a frame as safe `<svg>` markup with no DOM (for server rendering and reduced motion), and `svgViewBox` / `parseViewBox`.
14
+
3
15
  ## 0.14.0
4
16
 
5
17
  ### Minor Changes
package/README.md CHANGED
@@ -43,7 +43,8 @@ Flair gives products a library of good-looking, configurable visual effects (her
43
43
  | :--- | :--- | :--- |
44
44
  | `@pixerate/flair` | Shader engine, vector motion, time and easing, colour, blending, transitions, scenes, interchange exporters | None (browser-safe) |
45
45
  | `@pixerate/flair/catalog` | `EFFECTS`, `getEffect`, `findEffects`, `effectDefaults`, `renderVectorEffect`, `vectorControls`, GLSL helpers, sample images, `textImage` | None |
46
- | `@pixerate/flair/vector` | `SvgMotion`, `svgFrame`, `svgView`, `SvgPlayer`, `animateCount`, `formatCount`, `morphPaths`, `morphSequence`, `svgMotionIssues` | None |
46
+ | `@pixerate/flair/vector` | `SvgMotion`, `svgFrame`, `svgView`, `SvgPlayer`, `svgFrameMarkup`, `svgViewBox`, `animateCount`, `formatCount`, `morphPaths`, `morphSequence`, `svgMotionIssues` | None |
47
+ | `@pixerate/flair/react` | `<VectorEffect>`, `<SvgPlayerView>`: vector effects as React components, server-rendered as a still | `react` ≥ 18 (optional peer) |
47
48
  | `@pixerate/flair/editor` | `EffectEditor`, effect documents, keyframe tracks, renderer bindings, parameter-panel binding, agent tools and instructions | `@pixerate/editor` ≥ 0.29 (optional peer; only its dependency-free `/history`, `/commands`, `/tools`, `/animation` and `/parameters` subpaths) |
48
49
  | `@pixerate/flair/node` | `exportMotionGraphic`: renders a shader to GIF/MP4 through headless Chrome and ffmpeg | Node.js |
49
50
 
@@ -149,6 +150,25 @@ Overlay shaders (`category: "overlay"`) have `transparent: true`: they write cov
149
150
 
150
151
  To morph between any two SVG shapes, `morphPaths(from, to)` (from `@pixerate/flair/vector`) returns two paths with one structure, so `attrs: { d: [a, b] }` blends them point by point: curves and arcs are read, pieces are paired by position and size, and a piece with no partner grows from or shrinks to a point (draw them with `fill-rule="evenodd"`). `morphSequence` does the same for three or more shapes. `feature-morph` morphs two photos from five matching points, and `silhouette-morph` morphs any two silhouettes or logos (or words, through `textImage`).
151
152
 
153
+ ### React
154
+
155
+ `@pixerate/flair/react` wraps the player, so a page needs no ref, effect or dispose of its own. `<VectorEffect>` plays a catalog vector effect by id, `<SvgPlayerView>` any `SvgMotion`:
156
+
157
+ ```tsx
158
+ import { VectorEffect } from "@pixerate/flair/react";
159
+
160
+ <h1>
161
+ Stop the <VectorEffect id="drip-text" values={{ word: "Slop", inline: true, font: "inherit" }} loop={false} />
162
+ </h1>;
163
+ ```
164
+
165
+ - **Server rendering**: both render a still of the last frame as markup (`"first"` for hover and press triggers; set `poster` for another), sized from the viewBox, so the page hydrates with the picture in place. The `SvgPlayer` takes over after mount and is disposed on unmount.
166
+ - **Reduced motion**: under `prefers-reduced-motion: reduce` the still stays. `reducedMotion="always"` or `"never"` overrides it.
167
+ - **Size**: a block as wide as its container, with the viewBox's aspect ratio. With `inline` (or an effect whose `inline` control is on, like drip text's) it is an `inline-block` 0.72em high, sitting on the baseline like a capital letter; pass a CSS length to `inline` for another height.
168
+ - **Props**: player options (`loop`, `autoplay`, `speed`, `hold`, `trigger`, `steps`, `pauseWhenHidden`, `playOnEnter`, `clock` …), `values` and `preset` for an effect, `onPlayer` for the player itself, and any `<span>` attribute (`elementId` sets the host's `id` on `<VectorEffect>`). Values are compared by content, so an inline object does not restart it; pass `<SvgPlayerView>` a memoised `motion`.
169
+
170
+ Without React, `svgFrameMarkup(motion, { at: "last" })` (from `@pixerate/flair/vector`) gives the same still as safe `<svg>` markup with no DOM, for any server or framework.
171
+
152
172
  `shader-text` fills letters from a text image: set its `uText` control to `textImage("Your title", { weight: 900 })`, a transparent SVG `data:` URL of any Unicode text.
153
173
 
154
174
  A vector effect declares its controls in its picture, the way a shader declares its uniforms: the first `{{name: type …}}` declares a control (`float`, `int`, `bool`, `color` or `text`, with `@control`'s attributes; quote values with spaces in single quotes), and every `{{name}}` is filled with its value. Declarations can sit in an XML comment, which is dropped when the picture is filled in, and text is escaped, so any words are safe:
@@ -1,7 +1,7 @@
1
1
  import { a as ControlDef, C as ControlValue } from '../controls-Syr6drzO.js';
2
- import { E as EffectDefinition, a as EffectCategory, S as ShaderEffect } from '../types-CGsNkP5U.js';
3
- export { b as EFFECT_CATEGORIES, c as EffectPreset, V as VECTOR_CONTROL_TYPES, d as VectorControl, e as VectorEffect, f as colorControl, n as numberControl, r as renderVectorEffect, v as vectorControlDef, g as vectorControlIssues, h as vectorControls, i as vectorEffectControls } from '../types-CGsNkP5U.js';
4
- import '../svg-C_TWBtEN.js';
2
+ import { E as EffectDefinition, a as EffectCategory, S as ShaderEffect } from '../types-9J6NWaN3.js';
3
+ export { b as EFFECT_CATEGORIES, c as EffectPreset, d as VECTOR_CONTROL_TYPES, e as VectorControl, V as VectorEffect, f as colorControl, n as numberControl, r as renderVectorEffect, v as vectorControlDef, g as vectorControlIssues, h as vectorControls, i as vectorEffectControls } from '../types-9J6NWaN3.js';
4
+ import '../svg-XugR-6Ec.js';
5
5
 
6
6
  /**
7
7
  * Sample pictures for the catalog's image effects: small SVGs as `data:` URLs,
@@ -0,0 +1,137 @@
1
+ import {
2
+ SVG_PICTURE,
3
+ svgDuration,
4
+ svgFrame
5
+ } from "./chunk-4RGHZWQC.js";
6
+
7
+ // src/vector/static.ts
8
+ var DROPPED = /* @__PURE__ */ new Set(["script", "foreignobject", "iframe", "object", "embed"]);
9
+ var ATTR = /([^\s=/>"']+)(?:\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s>"']+)))?/g;
10
+ var TOKEN = /<!--[\s\S]*?(?:-->|$)|<!\[CDATA\[([\s\S]*?)(?:\]\]>|$)|<[!?][^>]*>|<\/\s*([\w:.-]+)\s*>|<([\w:.-]+)((?:\s+[^\s=/>"']+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s>"']+))?)*)\s*(\/?)>/g;
11
+ var ENTITIES = { amp: "&", lt: "<", gt: ">", quot: '"', apos: "'", nbsp: "\xA0" };
12
+ var decode = (s) => s.replace(/&(#x[0-9a-f]+|#\d+|\w+);/gi, (match, e) => {
13
+ if (e[0] !== "#") return ENTITIES[e.toLowerCase()] ?? match;
14
+ const code = e[1] === "x" || e[1] === "X" ? parseInt(e.slice(2), 16) : parseInt(e.slice(1), 10);
15
+ return code > 0 && code <= 1114111 ? String.fromCodePoint(code) : "";
16
+ });
17
+ var escapeText = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
18
+ var escapeAttr = (s) => escapeText(s).replace(/"/g, "&quot;");
19
+ function safeAttr(name, value) {
20
+ const n = name.toLowerCase();
21
+ if (n.startsWith("on") || !/^[a-z_][\w:.-]*$/i.test(n)) return false;
22
+ if (n === "href" || n === "xlink:href" || n === "src") return /^(#|data:image\/)/i.test(value.trim());
23
+ return true;
24
+ }
25
+ function parse(markup) {
26
+ const root = { tag: "", attrs: [], children: [] };
27
+ const stack = [root];
28
+ let dropping = 0;
29
+ let at = 0;
30
+ const text = (s) => {
31
+ if (!dropping && s) stack[stack.length - 1].children.push(decode(s));
32
+ };
33
+ for (const m of markup.matchAll(TOKEN)) {
34
+ text(markup.slice(at, m.index));
35
+ at = m.index + m[0].length;
36
+ const [, cdata, close, open, attrs = "", selfClosing] = m;
37
+ if (cdata !== void 0) {
38
+ if (!dropping) stack[stack.length - 1].children.push(cdata);
39
+ } else if (close) {
40
+ const tag = close.toLowerCase();
41
+ if (dropping) {
42
+ if (DROPPED.has(tag)) dropping--;
43
+ continue;
44
+ }
45
+ let i = stack.length - 1;
46
+ while (i > 0 && stack[i].tag.toLowerCase() !== tag) i--;
47
+ if (i > 0) stack.length = i;
48
+ } else if (open) {
49
+ if (DROPPED.has(open.toLowerCase())) {
50
+ if (!selfClosing) dropping++;
51
+ continue;
52
+ }
53
+ if (dropping) continue;
54
+ const node = { tag: open, attrs: [], children: [] };
55
+ for (const a of attrs.matchAll(ATTR)) {
56
+ const value = decode(a[2] ?? a[3] ?? a[4] ?? "");
57
+ if (safeAttr(a[1], value)) node.attrs.push([a[1], value]);
58
+ }
59
+ stack[stack.length - 1].children.push(node);
60
+ if (!selfClosing) stack.push(node);
61
+ }
62
+ }
63
+ text(markup.slice(at));
64
+ const svg = root.children.find((c) => typeof c !== "string");
65
+ return svg && svg.tag.toLowerCase() === "svg" ? svg : void 0;
66
+ }
67
+ function serialize(node) {
68
+ if (typeof node === "string") return escapeText(node);
69
+ const attrs = node.attrs.map(([k, v]) => ` ${k}="${escapeAttr(v)}"`).join("");
70
+ return `<${node.tag}${attrs}>${node.children.map(serialize).join("")}</${node.tag}>`;
71
+ }
72
+ function setAttr(node, name, value) {
73
+ const i = node.attrs.findIndex(([k]) => k === name);
74
+ if (value === void 0) {
75
+ if (i >= 0) node.attrs.splice(i, 1);
76
+ } else if (!safeAttr(name, value)) return;
77
+ else if (i >= 0) node.attrs[i][1] = value;
78
+ else node.attrs.push([name, value]);
79
+ }
80
+ var getAttr = (node, name) => node.attrs.find(([k]) => k === name)?.[1];
81
+ function parseViewBox(value) {
82
+ const box = (value ?? "").trim().split(/[\s,]+/).map(Number);
83
+ return box.length === 4 && box.every(Number.isFinite) && box[2] > 0 && box[3] > 0 ? box : void 0;
84
+ }
85
+ function svgViewBox(markup) {
86
+ const open = /<svg\b[^>]*>/i.exec(markup)?.[0] ?? "";
87
+ return parseViewBox(/\sviewBox\s*=\s*(?:"([^"]*)"|'([^']*)')/i.exec(open)?.slice(1).find((v) => v !== void 0));
88
+ }
89
+ function svgFrameMarkup(motion, options = {}) {
90
+ const svg = parse(motion.svg.trim());
91
+ if (!svg) return void 0;
92
+ const steps = options.steps ?? [];
93
+ const at = options.at ?? "last";
94
+ const time = at === "first" ? 0 : at === "last" ? svgDuration(motion, steps) : at;
95
+ const byId = /* @__PURE__ */ new Map();
96
+ const index = (node) => {
97
+ const id = getAttr(node, "id");
98
+ if (id && !byId.has(id)) byId.set(id, node);
99
+ for (const c of node.children) if (typeof c !== "string") index(c);
100
+ };
101
+ index(svg);
102
+ const whole = parseViewBox(getAttr(svg, "viewBox"));
103
+ for (const [id, frame] of svgFrame(motion.animate ?? [], steps, time)) {
104
+ if (id === SVG_PICTURE && frame.view) {
105
+ const { from, to, u } = frame.view;
106
+ const a = from === null ? whole : typeof from === "string" ? void 0 : from;
107
+ const b = typeof to === "string" ? void 0 : to;
108
+ if (a && b) setAttr(svg, "viewBox", a.map((n, i) => +(n + (b[i] - n) * u).toFixed(2)).join(" "));
109
+ continue;
110
+ }
111
+ const el = byId.get(id);
112
+ if (!el) continue;
113
+ for (const [name, value] of Object.entries(frame.attrs)) setAttr(el, name, value);
114
+ if (frame.draw !== void 0) {
115
+ setAttr(el, "pathLength", "1");
116
+ setAttr(el, "stroke-dasharray", "1 1");
117
+ setAttr(el, "stroke-dashoffset", String(1 - frame.draw));
118
+ }
119
+ if (frame.text !== void 0) el.children = [frame.text];
120
+ if (frame.solo !== void 0) {
121
+ let i = 0;
122
+ for (const child of el.children)
123
+ if (typeof child !== "string") setAttr(child, "display", i++ === frame.solo ? void 0 : "none");
124
+ }
125
+ }
126
+ setAttr(svg, "width", "100%");
127
+ setAttr(svg, "height", "100%");
128
+ if (!getAttr(svg, "xmlns")) setAttr(svg, "xmlns", "http://www.w3.org/2000/svg");
129
+ return serialize(svg);
130
+ }
131
+
132
+ export {
133
+ parseViewBox,
134
+ svgViewBox,
135
+ svgFrameMarkup
136
+ };
137
+ //# sourceMappingURL=chunk-DVVQRZJ5.js.map
@@ -0,0 +1 @@
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, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\nconst escapeAttr = (s: string) => escapeText(s).replace(/\"/g, \"&quot;\");\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\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":[]}
@@ -13,6 +13,11 @@ import {
13
13
  resetGlCaches,
14
14
  wrapSource
15
15
  } from "./chunk-YLJWC4N2.js";
16
+ import {
17
+ controlValue,
18
+ imageUrls,
19
+ parseControls
20
+ } from "./chunk-WC3VADZC.js";
16
21
  import {
17
22
  CAMERA_MS,
18
23
  CAMERA_STEP_MS,
@@ -22,11 +27,6 @@ import {
22
27
  cameraTrack,
23
28
  sceneStage
24
29
  } from "./chunk-WAMA45G3.js";
25
- import {
26
- controlValue,
27
- imageUrls,
28
- parseControls
29
- } from "./chunk-WC3VADZC.js";
30
30
 
31
31
  // src/shader/renderer.ts
32
32
  var ShaderRenderer = class {
@@ -1617,4 +1617,4 @@ export {
1617
1617
  validateScene,
1618
1618
  standaloneSceneHtml
1619
1619
  };
1620
- //# sourceMappingURL=chunk-KVKJCD6A.js.map
1620
+ //# sourceMappingURL=chunk-SHHAIWUR.js.map
@@ -128,4 +128,4 @@ export {
128
128
  stepVariant,
129
129
  formatUnit
130
130
  };
131
- //# sourceMappingURL=chunk-H355R6U4.js.map
131
+ //# sourceMappingURL=chunk-VP6IEWIK.js.map
package/dist/cli.js CHANGED
@@ -3,16 +3,16 @@ import {
3
3
  standaloneHtml,
4
4
  standaloneSceneHtml,
5
5
  validateScene
6
- } from "./chunk-KVKJCD6A.js";
6
+ } from "./chunk-SHHAIWUR.js";
7
7
  import "./chunk-YLJWC4N2.js";
8
8
  import "./chunk-EHDJ3CPJ.js";
9
+ import {
10
+ parseControls
11
+ } from "./chunk-WC3VADZC.js";
9
12
  import {
10
13
  simulateScene
11
14
  } from "./chunk-WAMA45G3.js";
12
15
  import "./chunk-WMZQCUFJ.js";
13
- import {
14
- parseControls
15
- } from "./chunk-WC3VADZC.js";
16
16
 
17
17
  // src/cli.ts
18
18
  import { Command } from "commander";
@@ -1,6 +1,6 @@
1
- import { d as VectorControl, c as EffectPreset, E as EffectDefinition } from '../types-CGsNkP5U.js';
1
+ import { e as VectorControl, c as EffectPreset, E as EffectDefinition } from '../types-9J6NWaN3.js';
2
2
  import { C as ControlValue, a as ControlDef, b as ControlType } from '../controls-Syr6drzO.js';
3
- import { S as SvgMotion, C as Clock } from '../svg-C_TWBtEN.js';
3
+ import { S as SvgMotion, C as Clock } from '../svg-XugR-6Ec.js';
4
4
  import { AnimationEasingPreset, AnimationEasing, AnimationTrack, AnimationKeyframe, cubicBezierAt as cubicBezierAt$1, evaluateEasing as evaluateEasing$1 } from '@pixerate/editor/animation';
5
5
  export { CubicBezierEasing, SpringEasing } from '@pixerate/editor/animation';
6
6
  import { CommandRegistry, CommandSpec } from '@pixerate/editor/commands';
@@ -16,14 +16,14 @@ import {
16
16
  interpolateOklab
17
17
  } from "../chunk-YLJWC4N2.js";
18
18
  import "../chunk-EHDJ3CPJ.js";
19
- import {
20
- realClock
21
- } from "../chunk-WMZQCUFJ.js";
22
19
  import {
23
20
  checkControlValue,
24
21
  controlValue,
25
22
  parseControls
26
23
  } from "../chunk-WC3VADZC.js";
24
+ import {
25
+ realClock
26
+ } from "../chunk-WMZQCUFJ.js";
27
27
 
28
28
  // src/editor/timeline.ts
29
29
  import {
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { C as ControlValue, a as ControlDef } from './controls-Syr6drzO.js';
2
2
  export { c as ControlCheck, b as ControlType, T as TextureSettings, d as checkControlValue, e as coerceControlValue, f as componentCount, g as controlValue, h as describeValue, i as hexToRgb, j as humanise, k as imageUrls, l as isImageUrl, p as parseControls, r as rgbToHex } from './controls-Syr6drzO.js';
3
3
  export { B as BUILTIN_UNIFORMS, C as CompileError, b as CompileResult, a as CompileStatus, c as CompiledShader, F as FrameState, I as ImageLoadError, R as RendererStats, S as SVG_EDGE, d as ShaderCompileError, e as ShaderRenderer, f as ShaderRendererOptions, T as TextureCache, g as TextureSource, V as VERTEX_SOURCE, h as applyTextureSettings, i as compileShader, j as createContext, k as drawFrame, l as formatCompileError, m as isSvgUrl, n as loadImage, p as parseCompileLog, o as preloadImages, r as releaseImages, q as resetGlCaches, s as sizeSvg, w as wrapSource } from './renderer-SNYZu__R.js';
4
- import { C as Clock } from './svg-C_TWBtEN.js';
5
- export { A as AnimateCountOptions, D as DataKey, E as EASES, b as EaseName, M as ManualClock, c as SCRAMBLE_MS, d as STEP_MS, e as SVG_PICTURE, f as SvgAnimation, g as SvgBox, h as SvgElementFrame, S as SvgMotion, i as SvgPlayer, j as SvgPlayerOptions, a as SvgTrigger, k as SvgView, l as SvgViewOptions, m as animateCount, n as defaultDataKey, o as formatCount, p as jitter, q as lerpAttr, r as lerpData, s as pageHidden, t as parseSvg, u as realClock, v as stepData, w as stepProgress, x as stepStart, y as svgDuration, z as svgFrame, B as svgMotionIssues, F as svgOpeningTag, G as svgView, H as writtenText } from './svg-C_TWBtEN.js';
6
- export { BoxAlignment, BoxFit, FittedBoxResult, FormatUnitOptions, MorphOptions, StackLayoutOptions, UnitFormat, computeBoxFit, formatUnit, layoutStack, morphPaths, morphSequence, remap, stepVariant } from './vector/index.js';
4
+ import { C as Clock } from './svg-XugR-6Ec.js';
5
+ export { A as AnimateCountOptions, D as DataKey, E as EASES, c as EaseName, M as ManualClock, d as SCRAMBLE_MS, e as STEP_MS, f as SVG_PICTURE, g as SvgAnimation, h as SvgBox, i as SvgElementFrame, S as SvgMotion, b as SvgPlayer, j as SvgPlayerOptions, a as SvgTrigger, k as SvgView, l as SvgViewOptions, m as animateCount, n as defaultDataKey, o as formatCount, p as jitter, q as lerpAttr, r as lerpData, s as pageHidden, t as parseSvg, u as realClock, v as stepData, w as stepProgress, x as stepStart, y as svgDuration, z as svgFrame, B as svgMotionIssues, F as svgOpeningTag, G as svgView, H as writtenText } from './svg-XugR-6Ec.js';
6
+ export { BoxAlignment, BoxFit, FittedBoxResult, FormatUnitOptions, MorphOptions, StackLayoutOptions, SvgFrameMarkupOptions, UnitFormat, computeBoxFit, formatUnit, layoutStack, morphPaths, morphSequence, parseViewBox, remap, stepVariant, svgFrameMarkup, svgViewBox } from './vector/index.js';
7
7
 
8
8
  /** Controls a registered thumbnail. */
9
9
  interface ThumbnailHandle {
package/dist/index.js CHANGED
@@ -4,7 +4,12 @@ import {
4
4
  layoutStack,
5
5
  remap,
6
6
  stepVariant
7
- } from "./chunk-H355R6U4.js";
7
+ } from "./chunk-VP6IEWIK.js";
8
+ import {
9
+ parseViewBox,
10
+ svgFrameMarkup,
11
+ svgViewBox
12
+ } from "./chunk-DVVQRZJ5.js";
8
13
  import {
9
14
  EASES,
10
15
  SCRAMBLE_MS,
@@ -44,7 +49,7 @@ import {
44
49
  standaloneHtml,
45
50
  standaloneSceneHtml,
46
51
  validateScene
47
- } from "./chunk-KVKJCD6A.js";
52
+ } from "./chunk-SHHAIWUR.js";
48
53
  import {
49
54
  BUILTIN_UNIFORMS,
50
55
  HOVER_SECONDS,
@@ -95,6 +100,19 @@ import {
95
100
  getTransitionGLSL,
96
101
  sampleTransition
97
102
  } from "./chunk-EHDJ3CPJ.js";
103
+ import {
104
+ checkControlValue,
105
+ coerceControlValue,
106
+ componentCount,
107
+ controlValue,
108
+ describeValue,
109
+ hexToRgb,
110
+ humanise,
111
+ imageUrls,
112
+ isImageUrl,
113
+ parseControls,
114
+ rgbToHex
115
+ } from "./chunk-WC3VADZC.js";
98
116
  import {
99
117
  calculateShotTimings,
100
118
  createLottieEase,
@@ -168,19 +186,6 @@ import {
168
186
  pageHidden,
169
187
  realClock
170
188
  } from "./chunk-WMZQCUFJ.js";
171
- import {
172
- checkControlValue,
173
- coerceControlValue,
174
- componentCount,
175
- controlValue,
176
- describeValue,
177
- hexToRgb,
178
- humanise,
179
- imageUrls,
180
- isImageUrl,
181
- parseControls,
182
- rgbToHex
183
- } from "./chunk-WC3VADZC.js";
184
189
 
185
190
  // src/time/retiming.ts
186
191
  function loopTime(t, duration, start = 0) {
@@ -1303,6 +1308,7 @@ export {
1303
1308
  parseControls,
1304
1309
  parseSvg,
1305
1310
  parseTimecode,
1311
+ parseViewBox,
1306
1312
  pingPongTime,
1307
1313
  playScene,
1308
1314
  preloadImages,
@@ -1343,9 +1349,11 @@ export {
1343
1349
  supportsDropFrame,
1344
1350
  svgDuration,
1345
1351
  svgFrame,
1352
+ svgFrameMarkup,
1346
1353
  svgMotionIssues,
1347
1354
  svgOpeningTag,
1348
1355
  svgView,
1356
+ svgViewBox,
1349
1357
  timecodeToFrames,
1350
1358
  titleBox,
1351
1359
  touchedIds,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/time/retiming.ts","../src/time/keyframe.ts","../src/time/timecode.ts","../src/scene/rig.ts","../src/scene/replicator.ts","../src/scene/motionpath.ts","../src/agent/tools.ts","../src/agent/batch.ts"],"sourcesContent":["/**\n * Retiming math engine inspired by Apple Motion's RetimingMath framework.\n * Provides deterministic time transformation functors for looping, bouncing (ping-pong),\n * freezing (hold), posterizing/stepping (strobe), and non-linear speed ramps.\n */\n\nexport type EasingCurve = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut';\n\n/**\n * Loops time within [start, start + duration).\n * Handles negative time values smoothly.\n */\nexport function loopTime(t: number, duration: number, start = 0): number {\n if (duration <= 0) return start;\n const rel = t - start;\n const mod = ((rel % duration) + duration) % duration;\n return start + mod;\n}\n\n/**\n * Reflects time back and forth (triangle wave) between start and start + duration.\n */\nexport function pingPongTime(t: number, duration: number, start = 0): number {\n if (duration <= 0) return start;\n const period = 2 * duration;\n const rel = t - start;\n const mod = ((rel % period) + period) % period;\n const offset = mod <= duration ? mod : period - mod;\n return start + offset;\n}\n\n/**\n * Freezes time at a specified timestamp.\n */\nexport function holdTime(_t: number, holdAt: number): number {\n return holdAt;\n}\n\n/**\n * Quantizes continuous time into discrete intervals matching a target frame rate (posterize time).\n * @param t Current timestamp.\n * @param fps Target stepped frame rate (e.g. 12 for stop-motion).\n * @param unit 'ms' (default) if t is in milliseconds, or 'sec' if t is in seconds.\n */\nexport function strobeTime(t: number, fps: number, unit: 'ms' | 'sec' = 'ms'): number {\n if (fps <= 0) return t;\n const interval = (unit === 'ms' ? 1000 : 1) / fps;\n return Math.floor(t / interval) * interval;\n}\n\n/**\n * Applies a non-linear speed ramp curve to time progression within an interval [start, start + duration].\n */\nexport function speedRampTime(\n t: number,\n start: number,\n duration: number,\n ease: EasingCurve = 'easeInOut',\n): number {\n if (duration <= 0 || t <= start) return t;\n if (t >= start + duration) return t;\n\n const p = (t - start) / duration;\n let eased: number;\n switch (ease) {\n case 'linear':\n eased = p;\n break;\n case 'easeIn':\n eased = p * p;\n break;\n case 'easeOut':\n eased = p * (2 - p);\n break;\n case 'easeInOut':\n default:\n eased = p < 0.5 ? 2 * p * p : -1 + (4 - 2 * p) * p;\n break;\n }\n\n return start + eased * duration;\n}\n","/**\n * Keyframe velocity and cubic Bezier easing engine matching Adobe After Effects interpolation semantics.\n *\n * Temporal interpolation between two keyframes is characterized by:\n * - Speed (units / second)\n * - Influence (fraction 0..1, corresponding to 0.1%..100% in the Keyframe Velocity dialog)\n *\n * For normalized values going from 0 to 1 over a segment, easeProgress(outSpeedNorm, outInf, inSpeedNorm, inInf, x)\n * solves the monotone cubic Bezier root x(u) = x and computes value y(u).\n */\n\nexport interface KeyframeEase {\n /** Speed in value units per second (or normalized speed if evaluating normalized segment). */\n speed: number;\n /** Influence as a fraction between 0.0 and 1.0 (e.g. 0.3333 for 33.33%). */\n influence: number;\n}\n\n/** Easy Ease preset: 0 speed, 33.333% influence. */\nexport const EASY_EASE: KeyframeEase = {\n speed: 0,\n influence: 1 / 3,\n};\n\n/** Evaluates a 1D cubic Bezier polynomial at parameter u in [0, 1]. */\nexport function bez1d(p0: number, p1: number, p2: number, p3: number, u: number): number {\n const v = 1.0 - u;\n return v * v * v * p0 + 3.0 * v * v * u * p1 + 3.0 * v * u * u * p2 + u * u * u * p3;\n}\n\n/** Evaluates the first derivative of a 1D cubic Bezier polynomial at parameter u. */\nexport function bez1dDerivative(p0: number, p1: number, p2: number, p3: number, u: number): number {\n const v = 1.0 - u;\n return 3.0 * v * v * (p1 - p0) + 6.0 * v * u * (p2 - p1) + 3.0 * u * u * (p3 - p2);\n}\n\n/**\n * Solves bez1d(x0, x1, x2, x3, u) = x for u in [0, 1] assuming x(u) is monotone.\n * Uses closed-form inverse for 100% influence midpoint, Newton-Raphson iteration,\n * and high-precision bisection fallback.\n */\nexport function solveBezierU(x0: number, x1: number, x2: number, x3: number, x: number): number {\n if (x <= x0) return 0.0;\n if (x >= x3) return 1.0;\n\n // Closed-form solution for 100% influence on both sides (x1 === x3 && x2 === x0).\n // x(u) = x0 + (x3 - x0) * (0.5 + 4 * (u - 0.5)^3)\n if (Math.abs(x1 - x3) < 1e-12 && Math.abs(x2 - x0) < 1e-12) {\n const progress = (x - x0) / (x3 - x0);\n return 0.5 + Math.cbrt((progress - 0.5) * 0.25);\n }\n\n // Initial estimate\n let u = (x - x0) / (x3 - x0);\n\n // Up to 8 Newton-Raphson iterations\n for (let iter = 0; iter < 8; iter++) {\n const f = bez1d(x0, x1, x2, x3, u) - x;\n const d = bez1dDerivative(x0, x1, x2, x3, u);\n if (Math.abs(d) < 1e-12) break;\n if (Math.abs(f / d) < 1e-12) return u;\n const nextU = u - f / d;\n if (nextU < 0.0 || nextU > 1.0) break;\n u = nextU;\n }\n\n // Bisection fallback for robustness\n let lo = 0.0;\n let hi = 1.0;\n for (let iter = 0; iter < 60; iter++) {\n const mid = (lo + hi) * 0.5;\n if (bez1d(x0, x1, x2, x3, mid) < x) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n\n return (lo + hi) * 0.5;\n}\n\n/**\n * Fraction of progress 0..1 through a 1D Bezier temporal segment whose value goes from 0 to 1,\n * with normalized out/in speeds (speed * duration / deltaValue) and influences.\n *\n * @param outSpeedNorm Normalized outgoing speed (speed * duration / deltaValue).\n * @param outInfluence Outgoing influence fraction [0, 1].\n * @param inSpeedNorm Normalized incoming speed (speed * duration / deltaValue).\n * @param inInfluence Incoming influence fraction [0, 1].\n * @param x Normalized time progress in segment [0, 1].\n */\nexport function easeProgress(\n outSpeedNorm: number,\n outInfluence: number,\n inSpeedNorm: number,\n inInfluence: number,\n x: number,\n): number {\n const i0 = Math.min(1.0, Math.max(0.0, outInfluence));\n const i1 = Math.min(1.0, Math.max(0.0, inInfluence));\n const u = solveBezierU(0.0, i0, 1.0 - i1, 1.0, x);\n return bez1d(0.0, outSpeedNorm * i0, 1.0 - inSpeedNorm * i1, 1.0, u);\n}\n\n/**\n * Evaluates an interpolated keyframe segment between two values over duration.\n *\n * @param from Starting value at t = 0.\n * @param to Ending value at t = duration.\n * @param duration Duration of the keyframe segment in seconds.\n * @param t Current elapsed time in seconds (0 <= t <= duration).\n * @param outEase Outgoing ease specification at start keyframe.\n * @param inEase Incoming ease specification at end keyframe.\n */\nexport function evaluateKeyframeSegment(\n from: number,\n to: number,\n duration: number,\n t: number,\n outEase: KeyframeEase = EASY_EASE,\n inEase: KeyframeEase = EASY_EASE,\n): number {\n if (duration <= 0 || t <= 0) return from;\n if (t >= duration) return to;\n\n const delta = to - from;\n const x = t / duration;\n\n // Zero delta: maintain from\n if (Math.abs(delta) < 1e-12) {\n return from;\n }\n\n const outSpeedNorm = (outEase.speed * duration) / delta;\n const inSpeedNorm = (inEase.speed * duration) / delta;\n\n const progress = easeProgress(outSpeedNorm, outEase.influence, inSpeedNorm, inEase.influence, x);\n return from + progress * delta;\n}\n","/**\n * SMPTE 12M Timecode engine and broadcast frame-rate converter.\n *\n * Supports non-drop-frame (NDF) and drop-frame (DF) timecode for broadcast standards\n * (23.976, 24, 25, 29.97, 30, 48, 50, 59.94, 60, 120 fps).\n *\n * Drop-frame timecode drops frames 00 and 01 at the start of each minute,\n * except every 10th minute (e.g. 00:01:00;02 instead of 00:01:00;00).\n */\n\nexport interface RationalFrameRate {\n readonly num: number;\n readonly den: number;\n}\n\nexport const COMMON_FRAME_RATES = {\n FPS_23_976: { num: 24000, den: 1001 },\n FPS_24: { num: 24, den: 1 },\n FPS_25: { num: 25, den: 1 },\n FPS_29_97: { num: 30000, den: 1001 },\n FPS_30: { num: 30, den: 1 },\n FPS_48: { num: 48, den: 1 },\n FPS_50: { num: 50, den: 1 },\n FPS_59_94: { num: 60000, den: 1001 },\n FPS_60: { num: 60, den: 1 },\n FPS_120: { num: 120, den: 1 },\n} as const;\n\nexport type StandardFrameRateKey = keyof typeof COMMON_FRAME_RATES;\n\n/** Greatest common divisor helper. */\nfunction gcd(a: number, b: number): number {\n let x = Math.abs(Math.round(a));\n let y = Math.abs(Math.round(b));\n while (y !== 0) {\n const t = y;\n y = x % y;\n x = t;\n }\n return x || 1;\n}\n\n/** Creates a reduced rational frame rate. */\nexport function createFrameRate(num: number, den = 1): RationalFrameRate {\n if (den <= 0 || num <= 0) {\n return { num: 30, den: 1 };\n }\n const g = gcd(num, den);\n return { num: Math.round(num / g), den: Math.round(den / g) };\n}\n\n/** Returns the timecode base (frames counted per second in timecode display). */\nexport function getTimecodeBase(rate: RationalFrameRate): number {\n return Math.ceil(rate.num / rate.den);\n}\n\n/** Whether a given frame rate supports drop-frame counting (29.97, 59.94, etc.). */\nexport function supportsDropFrame(rate: RationalFrameRate): boolean {\n return rate.den === 1001 && getTimecodeBase(rate) % 30 === 0;\n}\n\n/** Number of dropped frames per minute (e.g. 2 for 29.97, 4 for 59.94). */\nexport function getDropFrameCount(rate: RationalFrameRate): number {\n const base = getTimecodeBase(rate);\n return Math.floor(base / 15);\n}\n\nexport interface SMPTEFields {\n negative: boolean;\n hours: number;\n minutes: number;\n seconds: number;\n frames: number;\n}\n\n/**\n * Converts a continuous frame count to SMPTE fields (hours, minutes, seconds, frames).\n */\nexport function framesToSMPTE(\n frame: number,\n rate: RationalFrameRate = COMMON_FRAME_RATES.FPS_30,\n dropFrame = false,\n): SMPTEFields {\n const isDrop = dropFrame && supportsDropFrame(rate);\n const neg = frame < 0;\n let n = Math.abs(Math.round(frame));\n const base = getTimecodeBase(rate);\n const drop = getDropFrameCount(rate);\n\n if (isDrop) {\n const perMinute = base * 60 - drop;\n const per10Minutes = perMinute * 10 + drop;\n const d = Math.floor(n / per10Minutes);\n const m = n % per10Minutes;\n\n n += drop * 9 * d;\n if (m > drop) {\n n += drop * Math.floor((m - drop) / perMinute);\n }\n }\n\n const frames = n % base;\n const seconds = Math.floor(n / base) % 60;\n const minutes = Math.floor(n / (base * 60)) % 60;\n const hours = Math.floor(n / (base * 3600));\n\n return { negative: neg, hours, minutes, seconds, frames };\n}\n\n/**\n * Converts SMPTE fields back to a continuous frame number.\n */\nexport function smpteToFrames(\n fields: { hours: number; minutes: number; seconds: number; frames: number },\n rate: RationalFrameRate = COMMON_FRAME_RATES.FPS_30,\n dropFrame = false,\n): number {\n const isDrop = dropFrame && supportsDropFrame(rate);\n const base = getTimecodeBase(rate);\n const drop = getDropFrameCount(rate);\n\n const totalSecs = fields.hours * 3600 + fields.minutes * 60 + fields.seconds;\n let n = totalSecs * base + fields.frames;\n\n if (isDrop) {\n const totalMinutes = fields.hours * 60 + fields.minutes;\n n -= drop * (totalMinutes - Math.floor(totalMinutes / 10));\n }\n\n return n;\n}\n\n/**\n * Formats a frame number as standard SMPTE timecode (HH:MM:SS:FF or HH;MM;SS;FF).\n */\nexport function formatTimecode(\n frame: number,\n rate: RationalFrameRate = COMMON_FRAME_RATES.FPS_30,\n dropFrame = false,\n): string {\n const isDrop = dropFrame && supportsDropFrame(rate);\n const { negative, hours, minutes, seconds, frames } = framesToSMPTE(frame, rate, isDrop);\n const sep = isDrop ? ';' : ':';\n const base = getTimecodeBase(rate);\n const frameWidth = base >= 100 ? 3 : 2;\n\n const hStr = String(hours).padStart(2, '0');\n const mStr = String(minutes).padStart(2, '0');\n const sStr = String(seconds).padStart(2, '0');\n const fStr = String(frames).padStart(frameWidth, '0');\n\n return `${negative ? '-' : ''}${hStr}${sep}${mStr}${sep}${sStr}${sep}${fStr}`;\n}\n\n/**\n * Parses user or NLE input into a frame number.\n * Supports:\n * - Standard timecodes: `01:00:00:00`, `01;00;00;00`, `00.01.20.15`\n * - Right-aligned numbers: `1000` -> `00:00:10:00`\n * - Relative offsets: `+15` (+15 frames), `-1.00` (-1 second)\n *\n * @param input The timecode string to parse.\n * @param rate Rational frame rate (default: 30 fps).\n * @param dropFrame Whether drop-frame arithmetic applies.\n * @param currentFrame Current playhead position for relative additions.\n */\nexport function parseTimecode(\n input: string,\n rate: RationalFrameRate = COMMON_FRAME_RATES.FPS_30,\n dropFrame = false,\n currentFrame = 0,\n): number {\n const s = input.trim();\n if (!s) {\n throw new Error('Empty timecode string');\n }\n\n let relativeSign: 1 | -1 | null = null;\n let body = s;\n if (s.startsWith('+')) {\n relativeSign = 1;\n body = s.slice(1);\n } else if (s.startsWith('-')) {\n relativeSign = -1;\n body = s.slice(1);\n }\n\n const parts = body.split(/[:;.,]/);\n let parsedFrame = 0;\n\n if (parts.length === 1) {\n const digits = parts[0]!;\n if (!/^\\d+$/.test(digits)) {\n throw new Error(`Invalid timecode: \"${input}\"`);\n }\n\n if (relativeSign !== null) {\n // Relative bare digits are treated as frames\n const count = parseInt(digits, 10);\n return currentFrame + relativeSign * count;\n }\n\n // Right-aligned pairs: e.g. \"1000\" -> HH=0, MM=0, SS=10, FF=0\n const nums: number[] = [];\n let end = digits.length;\n while (end > 0) {\n const start = Math.max(0, end - 2);\n nums.unshift(parseInt(digits.slice(start, end), 10));\n end = start;\n }\n\n const padded = [0, 0, 0, 0];\n const offset = 4 - nums.length;\n for (let i = 0; i < nums.length; i++) {\n padded[offset + i] = nums[i]!;\n }\n const [h, m, sec, fr] = padded;\n parsedFrame = smpteToFrames(\n { hours: h!, minutes: m!, seconds: sec!, frames: fr! },\n rate,\n dropFrame,\n );\n } else {\n if (parts.length > 4) {\n throw new Error(`Too many timecode fields in \"${input}\"`);\n }\n const nums = parts.map((p) => (p.length === 0 ? 0 : parseInt(p, 10)));\n if (nums.some((n) => isNaN(n))) {\n throw new Error(`Invalid number in timecode: \"${input}\"`);\n }\n\n const padded = [0, 0, 0, 0];\n const offset = 4 - nums.length;\n for (let i = 0; i < nums.length; i++) {\n padded[offset + i] = nums[i]!;\n }\n const [h, m, sec, fr] = padded;\n parsedFrame = smpteToFrames(\n { hours: h!, minutes: m!, seconds: sec!, frames: fr! },\n rate,\n dropFrame,\n );\n }\n\n if (relativeSign !== null) {\n return currentFrame + relativeSign * parsedFrame;\n }\n\n return parsedFrame;\n}\n","import type { Scene } from './types.js';\n\nexport interface SliderSnapshot {\n at: number;\n values: Record<string, number | string>;\n}\n\nexport interface SliderWidget {\n type: 'slider';\n name: string;\n value: number;\n snapshots: SliderSnapshot[];\n}\n\nexport interface PopupWidget {\n type: 'popup';\n name: string;\n selected: string;\n options: Record<string, Record<string, number | string>>;\n}\n\nexport interface ToggleWidget {\n type: 'toggle';\n name: string;\n enabled: boolean;\n on: Record<string, number | string>;\n off: Record<string, number | string>;\n}\n\nexport type RigWidget = SliderWidget | PopupWidget | ToggleWidget;\n\nexport interface SceneRig {\n widgets: Record<string, RigWidget>;\n}\n\n/**\n * Updates a widget within a SceneRig and returns the updated SceneRig.\n */\nexport function setRigWidget(\n rig: SceneRig,\n widgetName: string,\n value: number | string | boolean,\n): SceneRig {\n const widget = rig.widgets[widgetName];\n if (!widget) {\n throw new Error(`Rig widget \"${widgetName}\" not found.`);\n }\n\n const updatedWidgets = { ...rig.widgets };\n\n if (widget.type === 'slider') {\n if (typeof value !== 'number') {\n throw new Error(`Slider widget \"${widgetName}\" expects numeric value.`);\n }\n updatedWidgets[widgetName] = { ...widget, value };\n } else if (widget.type === 'popup') {\n if (typeof value !== 'string') {\n throw new Error(`Popup widget \"${widgetName}\" expects string value.`);\n }\n updatedWidgets[widgetName] = { ...widget, selected: value };\n } else if (widget.type === 'toggle') {\n if (typeof value !== 'boolean') {\n throw new Error(`Toggle widget \"${widgetName}\" expects boolean value.`);\n }\n updatedWidgets[widgetName] = { ...widget, enabled: value };\n }\n\n return { widgets: updatedWidgets };\n}\n\n/**\n * Evaluates resolved values for a given widget.\n */\nfunction resolveWidgetValues(widget: RigWidget): Record<string, number | string> {\n if (widget.type === 'popup') {\n return widget.options[widget.selected] ?? {};\n }\n\n if (widget.type === 'toggle') {\n return widget.enabled ? widget.on : widget.off;\n }\n\n if (widget.type === 'slider') {\n const { snapshots, value } = widget;\n if (!snapshots || snapshots.length === 0) return {};\n\n const sorted = [...snapshots].sort((a, b) => a.at - b.at);\n if (value <= sorted[0]!.at) {\n return { ...sorted[0]!.values };\n }\n if (value >= sorted[sorted.length - 1]!.at) {\n return { ...sorted[sorted.length - 1]!.values };\n }\n\n // Find bounding snapshots\n let idx = 0;\n while (idx < sorted.length - 1 && sorted[idx + 1]!.at < value) {\n idx++;\n }\n\n const s0 = sorted[idx]!;\n const s1 = sorted[idx + 1]!;\n const span = s1.at - s0.at;\n const t = span > 0 ? (value - s0.at) / span : 0;\n\n const result: Record<string, number | string> = {};\n const allKeys = new Set([...Object.keys(s0.values), ...Object.keys(s1.values)]);\n\n for (const k of allKeys) {\n const v0 = s0.values[k];\n const v1 = s1.values[k];\n if (typeof v0 === 'number' && typeof v1 === 'number') {\n result[k] = v0 + (v1 - v0) * t;\n } else if (v0 !== undefined && v1 !== undefined) {\n result[k] = t < 0.5 ? v0 : v1;\n } else {\n result[k] = v1 !== undefined ? v1 : (v0 as number | string);\n }\n }\n\n return result;\n }\n\n return {};\n}\n\n/**\n * Propagates rig widget state into the scene's shader uniforms and elements.\n */\nexport function applyRig(rig: SceneRig, scene: Scene): Scene {\n // Deep clone media and shots to prevent mutation\n const nextMedia: Record<string, any> = {};\n if (scene.media) {\n for (const [id, m] of Object.entries(scene.media)) {\n nextMedia[id] = {\n ...m,\n values: { ...(m.values ?? {}) },\n };\n }\n }\n\n const nextShots = scene.shots.map((shot) => {\n if (!shot.run) return { ...shot };\n return {\n ...shot,\n run: shot.run.map((cmd) => {\n if (cmd.type === 'element' && 'element' in cmd && cmd.element) {\n return { ...cmd, element: { ...cmd.element } };\n }\n if (cmd.type === 'update' && 'props' in cmd && (cmd as any).props) {\n return { ...cmd, props: { ...(cmd as any).props } };\n }\n return { ...cmd };\n }),\n };\n });\n\n // Collect all resolved values across all widgets in the rig\n const resolvedAll: Record<string, number | string> = {};\n for (const widget of Object.values(rig.widgets)) {\n Object.assign(resolvedAll, resolveWidgetValues(widget));\n }\n\n // Apply resolved values\n for (const [targetKey, val] of Object.entries(resolvedAll)) {\n if (targetKey.startsWith('media.')) {\n const parts = targetKey.split('.');\n const mediaId = parts[1]!;\n const prop = parts.length > 3 && parts[2] === 'values' ? parts[3]! : parts[2]!;\n if (nextMedia[mediaId]) {\n nextMedia[mediaId].values[prop] = val;\n }\n } else if (targetKey.startsWith('element.')) {\n const parts = targetKey.split('.');\n const elId = parts[1]!;\n const prop = parts[2]!;\n for (const shot of nextShots) {\n if (shot.run) {\n for (const cmd of shot.run) {\n if (cmd.type === 'element' && 'element' in cmd && (cmd as any).element?.id === elId) {\n (cmd.element as any)[prop] = val;\n } else if (cmd.type === 'update' && 'id' in cmd && cmd.id === elId) {\n (cmd as any).props[prop] = val;\n }\n }\n }\n }\n } else {\n // General uniform shorthand: uniforms.<name> or simply <name>\n const uniformName = targetKey.replace(/^uniforms\\./, '');\n for (const m of Object.values(nextMedia)) {\n m.values[uniformName] = val;\n }\n }\n }\n\n return {\n ...scene,\n media: Object.keys(nextMedia).length > 0 ? nextMedia : scene.media,\n shots: nextShots,\n rig,\n };\n}\n","import type { SceneElement } from './geometry.js';\n\nexport type ReplicatorPattern = 'grid' | 'line' | 'circle' | 'spiral';\n\nexport interface ReplicatorSequence {\n /** Property to modulate per item. */\n property?: 'opacity' | 'rotation' | 'scale' | 'x' | 'y';\n /** Incremental offset or delta added per instance. */\n offset?: number;\n /** Milliseconds delay per instance for staggered triggers. */\n delayPerItem?: number;\n}\n\nexport interface ReplicatorConfig {\n pattern: ReplicatorPattern;\n count: number;\n /** Origin point [x, y] to anchor the layout (defaults to prototype.x, prototype.y). */\n origin?: [number, number];\n\n // Grid options\n columns?: number;\n rows?: number;\n columnSpacing?: number;\n rowSpacing?: number;\n\n // Line options\n startPoint?: [number, number];\n endPoint?: [number, number];\n spacing?: number;\n\n // Circle / Spiral options\n radius?: number;\n startAngle?: number; // radians\n spiralTightness?: number; // radius expansion per instance\n\n // Sequence modulation\n sequence?: ReplicatorSequence;\n}\n\n/**\n * Procedurally replicates a prototype SceneElement into an array of positioned\n * and sequenced instances (grid, circular array, line, or spiral).\n */\nexport function expandReplicator(\n prototype: SceneElement,\n config: ReplicatorConfig,\n): SceneElement[] {\n const count = Math.max(0, Math.floor(config.count));\n if (count === 0) return [];\n\n const originX = config.origin ? config.origin[0] : prototype.x;\n const originY = config.origin ? config.origin[1] : prototype.y;\n const elements: SceneElement[] = [];\n\n for (let i = 0; i < count; i++) {\n const el: SceneElement = {\n ...prototype,\n id: `${prototype.id}_${i}`,\n };\n\n let px = originX;\n let py = originY;\n\n switch (config.pattern) {\n case 'grid': {\n const cols = config.columns ?? Math.ceil(Math.sqrt(count));\n const colSpacing = config.columnSpacing ?? (prototype.width + 20);\n const rowSpacing = config.rowSpacing ?? (prototype.height + 20);\n const col = i % cols;\n const row = Math.floor(i / cols);\n px = originX + col * colSpacing;\n py = originY + row * rowSpacing;\n break;\n }\n\n case 'line': {\n if (config.startPoint && config.endPoint) {\n const t = count > 1 ? i / (count - 1) : 0;\n px = config.startPoint[0] + (config.endPoint[0] - config.startPoint[0]) * t;\n py = config.startPoint[1] + (config.endPoint[1] - config.startPoint[1]) * t;\n } else {\n const spacing = config.spacing ?? (prototype.width + 20);\n px = originX + i * spacing;\n py = originY;\n }\n break;\n }\n\n case 'circle': {\n const radius = config.radius ?? 150;\n const angleStep = (2 * Math.PI) / count;\n const angle = (config.startAngle ?? 0) + i * angleStep;\n px = originX + radius * Math.cos(angle);\n py = originY + radius * Math.sin(angle);\n break;\n }\n\n case 'spiral': {\n const baseRadius = config.radius ?? 40;\n const tightness = config.spiralTightness ?? 12;\n const angleStep = Math.PI / 4; // 45 degrees per step\n const angle = (config.startAngle ?? 0) + i * angleStep;\n const r = baseRadius + tightness * i;\n px = originX + r * Math.cos(angle);\n py = originY + r * Math.sin(angle);\n break;\n }\n }\n\n el.x = px;\n el.y = py;\n\n // Apply sequence property modulation\n if (config.sequence && config.sequence.offset !== undefined) {\n const { property, offset } = config.sequence;\n if (property === 'opacity') {\n const base = prototype.opacity ?? 1.0;\n el.opacity = Math.max(0, Math.min(1, base + i * offset));\n } else if (property === 'rotation') {\n const base = (prototype as any).rotation ?? 0;\n (el as any).rotation = base + i * offset;\n } else if (property === 'scale') {\n const factor = 1 + i * offset;\n el.width = Math.max(1, prototype.width * factor);\n el.height = Math.max(1, prototype.height * factor);\n } else if (property === 'x') {\n el.x += i * offset;\n } else if (property === 'y') {\n el.y += i * offset;\n }\n }\n\n elements.push(el);\n }\n\n return elements;\n}\n","/**\n * Constant-Velocity Spatial Motion Paths & Arc-Length Parameterization.\n *\n * Implements multi-segment cubic Bezier spatial trajectories with numerical\n * arc-length integration, ensuring constant pixel-speed traversal, tangent heading,\n * normal vectors, curvature, and seamless combination with temporal AE keyframe easing.\n */\n\nimport { evaluateKeyframeSegment, type KeyframeEase } from '../time/keyframe.js';\n\nexport type Vec2 = [number, number];\nexport type Vec3 = [number, number, number];\n\nexport interface PathWaypoint {\n /** Anchor position in 2D or 3D scene coordinates [x, y] or [x, y, z]. */\n point: Vec2 | Vec3;\n /** In-tangent handle relative to anchor point (vector pointing from handle to anchor or vice-versa). Default: [0, 0, 0] */\n inTangent?: Vec2 | Vec3;\n /** Out-tangent handle relative to anchor point (vector pointing from anchor toward next handle). Default: [0, 0, 0] */\n outTangent?: Vec2 | Vec3;\n}\n\nexport interface SpatialPathSample {\n /** Position on curve [x, y, z]. */\n position: Vec3;\n /** Normalized unit tangent vector [dx, dy, dz]. */\n tangent: Vec3;\n /** 2D heading angle in radians (atan2(dy, dx)). */\n heading: number;\n /** 2D unit normal vector [-dy, dx, 0]. */\n normal: Vec3;\n /** Instantaneous curvature kappa (1 / radius of curvature). */\n curvature: number;\n /** Distance traversed along the path in absolute units. */\n distance: number;\n}\n\ninterface SegmentSample {\n t: number;\n s: number;\n pos: Vec3;\n}\n\ninterface PathSegment {\n p0: Vec3;\n p1: Vec3;\n p2: Vec3;\n p3: Vec3;\n length: number;\n samples: SegmentSample[];\n}\n\nexport interface SpatialMotionPath {\n waypoints: PathWaypoint[];\n closed: boolean;\n totalLength: number;\n segments: PathSegment[];\n}\n\nfunction toVec3(p: Vec2 | Vec3 | undefined): Vec3 {\n if (!p) return [0, 0, 0];\n return [p[0], p[1], p[2] ?? 0];\n}\n\nfunction cubicPos(p0: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, t: number): Vec3 {\n const u = 1 - t;\n const a = u * u * u;\n const b = 3 * u * u * t;\n const c = 3 * u * t * t;\n const d = t * t * t;\n\n return [\n a * p0[0] + b * p1[0] + c * p2[0] + d * p3[0],\n a * p0[1] + b * p1[1] + c * p2[1] + d * p3[1],\n a * p0[2] + b * p1[2] + c * p2[2] + d * p3[2],\n ];\n}\n\nfunction cubicVel(p0: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, t: number): Vec3 {\n const u = 1 - t;\n const a = -3 * u * u;\n const b = 3 * u * u - 6 * u * t;\n const c = 6 * u * t - 3 * t * t;\n const d = 3 * t * t;\n\n return [\n a * p0[0] + b * p1[0] + c * p2[0] + d * p3[0],\n a * p0[1] + b * p1[1] + c * p2[1] + d * p3[1],\n a * p0[2] + b * p1[2] + c * p2[2] + d * p3[2],\n ];\n}\n\nfunction cubicAcc(p0: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, t: number): Vec3 {\n const u = 1 - t;\n const a = 6 * u;\n const b = -12 * u + 6 * t;\n const c = 6 * u - 12 * t;\n const d = 6 * t;\n\n return [\n a * p0[0] + b * p1[0] + c * p2[0] + d * p3[0],\n a * p0[1] + b * p1[1] + c * p2[1] + d * p3[1],\n a * p0[2] + b * p1[2] + c * p2[2] + d * p3[2],\n ];\n}\n\nfunction dist3(a: Vec3, b: Vec3): number {\n const dx = b[0] - a[0];\n const dy = b[1] - a[1];\n const dz = b[2] - a[2];\n return Math.sqrt(dx * dx + dy * dy + dz * dz);\n}\n\n/**\n * Creates and compiles a constant-velocity SpatialMotionPath from a sequence of waypoints.\n * Computes fine-grained arc-length tables along all Bezier segments.\n */\nexport function createMotionPath(\n waypoints: PathWaypoint[],\n options?: { closed?: boolean; resolution?: number }\n): SpatialMotionPath {\n if (waypoints.length < 2) {\n throw new Error('SpatialMotionPath requires at least 2 waypoints.');\n }\n\n const closed = options?.closed ?? false;\n const segmentCount = closed ? waypoints.length : waypoints.length - 1;\n const segments: PathSegment[] = [];\n let totalLength = 0;\n\n for (let i = 0; i < segmentCount; i++) {\n const nextIdx = (i + 1) % waypoints.length;\n const w0 = waypoints[i];\n const w1 = waypoints[nextIdx];\n\n const p0 = toVec3(w0.point);\n const outT = toVec3(w0.outTangent);\n const p1: Vec3 = [p0[0] + outT[0], p0[1] + outT[1], p0[2] + outT[2]];\n\n const p3 = toVec3(w1.point);\n const inT = toVec3(w1.inTangent);\n const p2: Vec3 = [p3[0] + inT[0], p3[1] + inT[1], p3[2] + inT[2]];\n\n // Chord length estimate\n const chord = dist3(p0, p1) + dist3(p1, p2) + dist3(p2, p3);\n const stepCount = Math.max(16, Math.min(256, Math.ceil(chord / (options?.resolution ?? 2))));\n\n const samples: SegmentSample[] = [];\n let segLen = 0;\n let prev = p0;\n samples.push({ t: 0, s: 0, pos: p0 });\n\n for (let k = 1; k <= stepCount; k++) {\n const t = k / stepCount;\n const pos = cubicPos(p0, p1, p2, p3, t);\n segLen += dist3(prev, pos);\n samples.push({ t, s: segLen, pos });\n prev = pos;\n }\n\n segments.push({\n p0,\n p1,\n p2,\n p3,\n length: segLen,\n samples,\n });\n totalLength += segLen;\n }\n\n return {\n waypoints,\n closed,\n totalLength,\n segments,\n };\n}\n\n/**\n * Samples the spatial motion path at a normalized distance fraction [0..1].\n * Guarantees strictly constant pixel speed regardless of control handle asymmetry.\n */\nexport function sampleMotionPath(path: SpatialMotionPath, distanceFraction: number): SpatialPathSample {\n const clampedFraction = Math.max(0, Math.min(1, distanceFraction));\n const targetDistance = clampedFraction * path.totalLength;\n\n if (path.totalLength === 0) {\n const p = toVec3(path.waypoints[0].point);\n return {\n position: p,\n tangent: [1, 0, 0],\n heading: 0,\n normal: [0, 1, 0],\n curvature: 0,\n distance: 0,\n };\n }\n\n // Find target segment\n let accumulated = 0;\n let targetSeg = path.segments[0];\n let segDistance = targetDistance;\n\n for (const seg of path.segments) {\n if (accumulated + seg.length >= targetDistance || seg === path.segments[path.segments.length - 1]) {\n targetSeg = seg;\n segDistance = Math.max(0, Math.min(seg.length, targetDistance - accumulated));\n break;\n }\n accumulated += seg.length;\n }\n\n // Binary search for exact sample in target segment's arc length table\n const samples = targetSeg.samples;\n let low = 0;\n let high = samples.length - 1;\n\n while (low <= high) {\n const mid = (low + high) >> 1;\n if (samples[mid].s < segDistance) {\n low = mid + 1;\n } else {\n high = mid - 1;\n }\n }\n\n const idx = Math.max(0, Math.min(samples.length - 2, high));\n const s0 = samples[idx];\n const s1 = samples[idx + 1];\n\n const segRange = s1.s - s0.s;\n const factor = segRange > 1e-7 ? (segDistance - s0.s) / segRange : 0;\n const t = s0.t + factor * (s1.t - s0.t);\n\n // Evaluate exact position, velocity, acceleration at t\n const pos = cubicPos(targetSeg.p0, targetSeg.p1, targetSeg.p2, targetSeg.p3, t);\n const vel = cubicVel(targetSeg.p0, targetSeg.p1, targetSeg.p2, targetSeg.p3, t);\n const acc = cubicAcc(targetSeg.p0, targetSeg.p1, targetSeg.p2, targetSeg.p3, t);\n\n const speed = Math.sqrt(vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]);\n const safeSpeed = speed > 1e-6 ? speed : 1;\n const tangent: Vec3 = [vel[0] / safeSpeed, vel[1] / safeSpeed, vel[2] / safeSpeed];\n\n const heading = Math.atan2(tangent[1], tangent[0]);\n const normal: Vec3 = [-tangent[1], tangent[0], 0];\n\n // Curvature: kappa = |v x a| / |v|^3\n const cx = vel[1] * acc[2] - vel[2] * acc[1];\n const cy = vel[2] * acc[0] - vel[0] * acc[2];\n const cz = vel[0] * acc[1] - vel[1] * acc[0];\n const crossMag = Math.sqrt(cx * cx + cy * cy + cz * cz);\n const curvature = crossMag / (safeSpeed * safeSpeed * safeSpeed);\n\n return {\n position: pos,\n tangent,\n heading,\n normal,\n curvature,\n distance: targetDistance,\n };\n}\n\n/**\n * Samples a spatial motion path driven by elapsed time and AE keyframe velocity easing.\n * Combines spatial arc-length constancy with temporal speed curves.\n */\nexport function sampleMotionPathAtTime(\n path: SpatialMotionPath,\n time: number,\n duration: number,\n ease?: {\n easeIn?: KeyframeEase;\n easeOut?: KeyframeEase;\n }\n): SpatialPathSample {\n const distanceFraction = evaluateKeyframeSegment(\n 0,\n 1,\n duration,\n time,\n ease?.easeOut,\n ease?.easeIn\n );\n return sampleMotionPath(path, distanceFraction);\n}\n\n","import type { Scene, SceneMedia, Shot } from '../scene/types.js';\nimport { validateScene, type SceneIssue } from '../scene/validate.js';\nimport { simulateScene } from '../scene/player.js';\nimport type { Review } from '../scene/report.js';\nimport { applyRig, setRigWidget } from '../scene/rig.js';\n\nexport interface AgentToolDefinition {\n name: string;\n description: string;\n input_schema: Record<string, unknown>;\n}\n\nexport const FLAIR_AGENT_TOOLS: AgentToolDefinition[] = [\n {\n name: 'get_scene',\n description: 'Returns the current scene JSON (or a concise structural outline) and any static validation issues.',\n input_schema: {\n type: 'object',\n properties: {\n view: {\n type: 'string',\n enum: ['full', 'outline'],\n description:\n 'When \"outline\", returns scene hierarchy, timing, and framing without dense commands or raw media sources.',\n },\n },\n additionalProperties: false,\n },\n },\n {\n name: 'write_scene',\n description: 'Overwrites the entire scene with a new specification and validates it.',\n input_schema: {\n type: 'object',\n properties: {\n scene: {\n type: 'object',\n description:\n 'Full Scene object with name, stage, media, and shots. A shot camera frames a box {x, y, width, height} or elements {frame: [ids]}, and may add tilt, turn, roll (degrees, tilt/turn up to 75), perspective (default 1.2) and motionBlur (0-3, 1 natural); angles persist until changed.',\n },\n },\n required: ['scene'],\n additionalProperties: false,\n },\n },\n {\n name: 'update_shot',\n description: 'Updates fields of a specific shot (1-based index) without rewriting the whole scene.',\n input_schema: {\n type: 'object',\n properties: {\n shot: { type: 'integer', minimum: 1, description: '1-based index of the shot to update.' },\n set: { type: 'object', description: 'Fields to set or replace on this shot.' },\n remove: {\n type: 'array',\n items: { type: 'string' },\n description: 'Field names to delete from this shot.',\n },\n },\n required: ['shot'],\n additionalProperties: false,\n },\n },\n {\n name: 'insert_shots',\n description: 'Inserts one or more shots at a given position.',\n input_schema: {\n type: 'object',\n properties: {\n after: {\n type: 'integer',\n minimum: 0,\n description: '0 to insert at the beginning, or 1-based index of shot to insert after.',\n },\n shots: {\n type: 'array',\n items: { type: 'object' },\n description: 'Array of Shot objects to insert.',\n },\n },\n required: ['after', 'shots'],\n additionalProperties: false,\n },\n },\n {\n name: 'delete_shots',\n description: 'Deletes one or more shots by 1-based index.',\n input_schema: {\n type: 'object',\n properties: {\n shots: {\n type: 'array',\n items: { type: 'integer', minimum: 1 },\n description: '1-based shot numbers to delete.',\n },\n },\n required: ['shots'],\n additionalProperties: false,\n },\n },\n {\n name: 'set_media',\n description: 'Adds, updates, or removes embedded media (e.g. bespoke WebGL shaders) by ID.',\n input_schema: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'Media identifier.' },\n media: {\n type: ['object', 'null'],\n description: 'SceneMedia object (e.g. { type: \"shader\", source: \"...\" }), or null to remove.',\n },\n },\n required: ['id', 'media'],\n additionalProperties: false,\n },\n },\n {\n name: 'preview_scene',\n description: 'Simulates the scene fast and off-screen, returning timing, layout checks, and review report.',\n input_schema: {\n type: 'object',\n properties: {},\n additionalProperties: false,\n },\n },\n {\n name: 'set_rig_widget',\n description: 'Adjusts a high-level creative rig widget (slider, popup, or toggle) and propagates parameters to shaders and elements.',\n input_schema: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Rig widget identifier/name.' },\n value: {\n type: ['number', 'string', 'boolean'],\n description: 'New value (number for slider, string for popup, boolean for toggle).',\n },\n },\n required: ['name', 'value'],\n additionalProperties: false,\n },\n },\n];\n\nexport interface SceneOutlineShot {\n shot: number;\n caption?: string;\n title?: string;\n hold?: number;\n camera?: Shot['camera'];\n commandCount: number;\n effects?: string[];\n}\n\nexport interface SceneOutline {\n name: string;\n title?: string;\n description?: string;\n stage?: Scene['stage'];\n target?: Scene['target'];\n mediaIds: string[];\n shots: SceneOutlineShot[];\n}\n\nexport type SceneToolResult =\n | { ok: true; scene: Scene; outline?: SceneOutline; issues: SceneIssue[]; review?: Review }\n | { ok: false; error: string };\n\n/**\n * Pure state machine that applies tool operations to a Scene.\n */\nexport async function applySceneTool(\n scene: Scene,\n toolName: string,\n input: Record<string, any> = {},\n): Promise<SceneToolResult> {\n switch (toolName) {\n case 'get_scene': {\n const issues = validateScene(scene);\n if (input.view === 'outline') {\n const outline: SceneOutline = {\n name: scene.name,\n title: scene.title,\n description: scene.description,\n stage: scene.stage,\n target: scene.target,\n mediaIds: Object.keys(scene.media || {}),\n shots: scene.shots.map((s, i) => ({\n shot: i + 1,\n caption: s.caption,\n title: s.title,\n hold: s.hold,\n camera: s.camera,\n commandCount: s.run?.length ?? 0,\n effects: s.effects?.map((e) => e.type),\n })),\n };\n return { ok: true, scene, outline, issues };\n }\n return { ok: true, scene, issues };\n }\n\n case 'write_scene': {\n if (!input.scene || typeof input.scene !== 'object') {\n return { ok: false, error: 'Expected scene object in arguments.' };\n }\n const newScene = input.scene as Scene;\n const issues = validateScene(newScene);\n return { ok: true, scene: newScene, issues };\n }\n\n case 'update_shot': {\n const idx = input.shot - 1;\n if (idx < 0 || idx >= scene.shots.length) {\n return { ok: false, error: `Invalid shot number ${input.shot}; scene has ${scene.shots.length} shots.` };\n }\n const existing = scene.shots[idx]!;\n const updated: Record<string, any> = { ...existing, ...(input.set || {}) };\n if (Array.isArray(input.remove)) {\n for (const k of input.remove) {\n delete updated[k];\n }\n }\n const shots = [...scene.shots];\n shots[idx] = updated as Shot;\n const newScene = { ...scene, shots };\n return { ok: true, scene: newScene, issues: validateScene(newScene) };\n }\n\n case 'insert_shots': {\n const after = input.after ?? scene.shots.length;\n if (after < 0 || after > scene.shots.length) {\n return { ok: false, error: `Invalid after index ${after}.` };\n }\n if (!Array.isArray(input.shots) || input.shots.length === 0) {\n return { ok: false, error: 'Expected non-empty shots array to insert.' };\n }\n const shots = [...scene.shots.slice(0, after), ...input.shots, ...scene.shots.slice(after)];\n const newScene = { ...scene, shots };\n return { ok: true, scene: newScene, issues: validateScene(newScene) };\n }\n\n case 'delete_shots': {\n if (!Array.isArray(input.shots) || input.shots.length === 0) {\n return { ok: false, error: 'Expected non-empty shots array to delete.' };\n }\n const toDelete = new Set(input.shots.map((n: number) => n - 1));\n const shots = scene.shots.filter((_, i) => !toDelete.has(i));\n if (shots.length === 0) {\n return { ok: false, error: 'Cannot delete all shots in scene.' };\n }\n const newScene = { ...scene, shots };\n return { ok: true, scene: newScene, issues: validateScene(newScene) };\n }\n\n case 'set_media': {\n if (!input.id || typeof input.id !== 'string') {\n return { ok: false, error: 'Expected string media id.' };\n }\n const media = { ...(scene.media || {}) };\n if (input.media === null) {\n delete media[input.id];\n } else {\n media[input.id] = input.media as SceneMedia;\n }\n const newScene = { ...scene, media };\n return { ok: true, scene: newScene, issues: validateScene(newScene) };\n }\n\n case 'preview_scene': {\n const { review } = await simulateScene(scene);\n return { ok: true, scene, issues: validateScene(scene), review };\n }\n\n case 'set_rig_widget': {\n if (!scene.rig || !scene.rig.widgets || !scene.rig.widgets[input.name]) {\n return { ok: false, error: `Scene does not have a rig widget named \"${input.name}\".` };\n }\n try {\n const updatedRig = setRigWidget(scene.rig, input.name, input.value);\n const newScene = applyRig(updatedRig, scene);\n return { ok: true, scene: newScene, issues: validateScene(newScene) };\n } catch (err: any) {\n return { ok: false, error: err.message || String(err) };\n }\n }\n\n default:\n return { ok: false, error: `Unknown tool name: ${toolName}` };\n }\n}\n","/**\n * Atomic Agent Multi-Tool Batching with Result Variable Substitution.\n * Inspired by EffectCraft's atomic batch execution protocol.\n *\n * Allows AI agents to execute multi-step modifications to a Scene in a single turn,\n * with atomic rollback on failure and cross-step variable substitution ($1.prop, $2.prop).\n */\n\nimport type { Scene } from '../scene/types.js';\nimport { applySceneTool, type SceneToolResult } from './tools.js';\n\nexport interface BatchCommand {\n /** Name of the tool to execute (e.g. 'update_shot', 'insert_shots', 'set_rig_widget'). */\n tool: string;\n /** Parameters for the tool call. */\n params?: Record<string, any>;\n}\n\nexport interface BatchExecutionStepResult {\n step: number;\n tool: string;\n result: SceneToolResult;\n}\n\nexport interface BatchExecutionResult {\n ok: boolean;\n scene: Scene;\n steps: BatchExecutionStepResult[];\n error?: string;\n failedStep?: number;\n}\n\n/**\n * Resolves nested property path on an object (e.g. \"a.b[0].c\").\n */\nfunction getByPath(obj: any, path: string): any {\n if (!obj || typeof obj !== 'object') return undefined;\n const parts = path.replace(/\\[(\\w+)\\]/g, '.$1').split('.');\n let curr = obj;\n for (const part of parts) {\n if (curr === undefined || curr === null) return undefined;\n curr = curr[part];\n }\n return curr;\n}\n\n/**\n * Recursively substitutes `$stepIndex.path` references in parameters using previous step results.\n * E.g., \"$1.scene.shots[0].duration\" -> substituted with the duration value from step 1 result.\n */\nexport function substituteVariables(\n value: any,\n stepResults: Map<number, SceneToolResult>,\n): any {\n if (typeof value === 'string') {\n // Check if the entire string is a substitution reference: \"$1.path.to.prop\"\n const match = /^\\$(\\d+)\\.(.+)$/.exec(value);\n if (match) {\n const stepIdx = parseInt(match[1]!, 10);\n const path = match[2]!;\n const prevResult = stepResults.get(stepIdx);\n if (prevResult) {\n const resolved = getByPath(prevResult, path);\n if (resolved !== undefined) {\n return resolved;\n }\n }\n }\n // Partial template string substitution: \"Hello $1.scene.name\"\n return value.replace(/\\$(\\d+)\\.([a-zA-Z0-9_.[\\]]+)/g, (fullMatch, stepStr, path) => {\n const stepIdx = parseInt(stepStr, 10);\n const prevResult = stepResults.get(stepIdx);\n if (prevResult) {\n const resolved = getByPath(prevResult, path);\n if (resolved !== undefined) {\n return String(resolved);\n }\n }\n return fullMatch;\n });\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => substituteVariables(item, stepResults));\n }\n\n if (value !== null && typeof value === 'object') {\n const copy: Record<string, any> = {};\n for (const [k, v] of Object.entries(value)) {\n copy[k] = substituteVariables(v, stepResults);\n }\n return copy;\n }\n\n return value;\n}\n\n/**\n * Executes an atomic batch of scene tools with transactional rollback.\n * If any step fails, the scene rolls back to the initial state and returns the failure.\n *\n * @param scene Initial scene state before batch.\n * @param commands Ordered array of tool commands to execute.\n */\nexport async function applySceneBatch(\n scene: Scene,\n commands: BatchCommand[],\n): Promise<BatchExecutionResult> {\n let currentScene = scene;\n const stepResults = new Map<number, SceneToolResult>();\n const executedSteps: BatchExecutionStepResult[] = [];\n\n for (let i = 0; i < commands.length; i++) {\n const stepNumber = i + 1; // 1-based indexing for user/agent ergonomics\n const cmd = commands[i]!;\n\n // Perform variable substitution using results of earlier steps\n const resolvedParams = substituteVariables(cmd.params || {}, stepResults);\n\n // Prevent recursive batch execution to avoid cycles\n if (cmd.tool === 'batch_scene_tool') {\n return {\n ok: false,\n scene, // Rollback\n steps: executedSteps,\n error: `Nested batch_scene_tool is not allowed at step ${stepNumber}.`,\n failedStep: stepNumber,\n };\n }\n\n const stepResult = await applySceneTool(currentScene, cmd.tool, resolvedParams);\n stepResults.set(stepNumber, stepResult);\n executedSteps.push({\n step: stepNumber,\n tool: cmd.tool,\n result: stepResult,\n });\n\n if (!stepResult.ok) {\n // Transactional rollback: discard intermediate scenes and return original\n return {\n ok: false,\n scene, // Rollback to initial\n steps: executedSteps,\n error: `Step ${stepNumber} (${cmd.tool}) failed: ${stepResult.error}`,\n failedStep: stepNumber,\n };\n }\n\n currentScene = stepResult.scene;\n }\n\n return {\n ok: true,\n scene: currentScene,\n steps: executedSteps,\n };\n}\n"],"mappings":"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","names":["frame"]}
1
+ {"version":3,"sources":["../src/time/retiming.ts","../src/time/keyframe.ts","../src/time/timecode.ts","../src/scene/rig.ts","../src/scene/replicator.ts","../src/scene/motionpath.ts","../src/agent/tools.ts","../src/agent/batch.ts"],"sourcesContent":["/**\n * Retiming math engine inspired by Apple Motion's RetimingMath framework.\n * Provides deterministic time transformation functors for looping, bouncing (ping-pong),\n * freezing (hold), posterizing/stepping (strobe), and non-linear speed ramps.\n */\n\nexport type EasingCurve = 'linear' | 'easeIn' | 'easeOut' | 'easeInOut';\n\n/**\n * Loops time within [start, start + duration).\n * Handles negative time values smoothly.\n */\nexport function loopTime(t: number, duration: number, start = 0): number {\n if (duration <= 0) return start;\n const rel = t - start;\n const mod = ((rel % duration) + duration) % duration;\n return start + mod;\n}\n\n/**\n * Reflects time back and forth (triangle wave) between start and start + duration.\n */\nexport function pingPongTime(t: number, duration: number, start = 0): number {\n if (duration <= 0) return start;\n const period = 2 * duration;\n const rel = t - start;\n const mod = ((rel % period) + period) % period;\n const offset = mod <= duration ? mod : period - mod;\n return start + offset;\n}\n\n/**\n * Freezes time at a specified timestamp.\n */\nexport function holdTime(_t: number, holdAt: number): number {\n return holdAt;\n}\n\n/**\n * Quantizes continuous time into discrete intervals matching a target frame rate (posterize time).\n * @param t Current timestamp.\n * @param fps Target stepped frame rate (e.g. 12 for stop-motion).\n * @param unit 'ms' (default) if t is in milliseconds, or 'sec' if t is in seconds.\n */\nexport function strobeTime(t: number, fps: number, unit: 'ms' | 'sec' = 'ms'): number {\n if (fps <= 0) return t;\n const interval = (unit === 'ms' ? 1000 : 1) / fps;\n return Math.floor(t / interval) * interval;\n}\n\n/**\n * Applies a non-linear speed ramp curve to time progression within an interval [start, start + duration].\n */\nexport function speedRampTime(\n t: number,\n start: number,\n duration: number,\n ease: EasingCurve = 'easeInOut',\n): number {\n if (duration <= 0 || t <= start) return t;\n if (t >= start + duration) return t;\n\n const p = (t - start) / duration;\n let eased: number;\n switch (ease) {\n case 'linear':\n eased = p;\n break;\n case 'easeIn':\n eased = p * p;\n break;\n case 'easeOut':\n eased = p * (2 - p);\n break;\n case 'easeInOut':\n default:\n eased = p < 0.5 ? 2 * p * p : -1 + (4 - 2 * p) * p;\n break;\n }\n\n return start + eased * duration;\n}\n","/**\n * Keyframe velocity and cubic Bezier easing engine matching Adobe After Effects interpolation semantics.\n *\n * Temporal interpolation between two keyframes is characterized by:\n * - Speed (units / second)\n * - Influence (fraction 0..1, corresponding to 0.1%..100% in the Keyframe Velocity dialog)\n *\n * For normalized values going from 0 to 1 over a segment, easeProgress(outSpeedNorm, outInf, inSpeedNorm, inInf, x)\n * solves the monotone cubic Bezier root x(u) = x and computes value y(u).\n */\n\nexport interface KeyframeEase {\n /** Speed in value units per second (or normalized speed if evaluating normalized segment). */\n speed: number;\n /** Influence as a fraction between 0.0 and 1.0 (e.g. 0.3333 for 33.33%). */\n influence: number;\n}\n\n/** Easy Ease preset: 0 speed, 33.333% influence. */\nexport const EASY_EASE: KeyframeEase = {\n speed: 0,\n influence: 1 / 3,\n};\n\n/** Evaluates a 1D cubic Bezier polynomial at parameter u in [0, 1]. */\nexport function bez1d(p0: number, p1: number, p2: number, p3: number, u: number): number {\n const v = 1.0 - u;\n return v * v * v * p0 + 3.0 * v * v * u * p1 + 3.0 * v * u * u * p2 + u * u * u * p3;\n}\n\n/** Evaluates the first derivative of a 1D cubic Bezier polynomial at parameter u. */\nexport function bez1dDerivative(p0: number, p1: number, p2: number, p3: number, u: number): number {\n const v = 1.0 - u;\n return 3.0 * v * v * (p1 - p0) + 6.0 * v * u * (p2 - p1) + 3.0 * u * u * (p3 - p2);\n}\n\n/**\n * Solves bez1d(x0, x1, x2, x3, u) = x for u in [0, 1] assuming x(u) is monotone.\n * Uses closed-form inverse for 100% influence midpoint, Newton-Raphson iteration,\n * and high-precision bisection fallback.\n */\nexport function solveBezierU(x0: number, x1: number, x2: number, x3: number, x: number): number {\n if (x <= x0) return 0.0;\n if (x >= x3) return 1.0;\n\n // Closed-form solution for 100% influence on both sides (x1 === x3 && x2 === x0).\n // x(u) = x0 + (x3 - x0) * (0.5 + 4 * (u - 0.5)^3)\n if (Math.abs(x1 - x3) < 1e-12 && Math.abs(x2 - x0) < 1e-12) {\n const progress = (x - x0) / (x3 - x0);\n return 0.5 + Math.cbrt((progress - 0.5) * 0.25);\n }\n\n // Initial estimate\n let u = (x - x0) / (x3 - x0);\n\n // Up to 8 Newton-Raphson iterations\n for (let iter = 0; iter < 8; iter++) {\n const f = bez1d(x0, x1, x2, x3, u) - x;\n const d = bez1dDerivative(x0, x1, x2, x3, u);\n if (Math.abs(d) < 1e-12) break;\n if (Math.abs(f / d) < 1e-12) return u;\n const nextU = u - f / d;\n if (nextU < 0.0 || nextU > 1.0) break;\n u = nextU;\n }\n\n // Bisection fallback for robustness\n let lo = 0.0;\n let hi = 1.0;\n for (let iter = 0; iter < 60; iter++) {\n const mid = (lo + hi) * 0.5;\n if (bez1d(x0, x1, x2, x3, mid) < x) {\n lo = mid;\n } else {\n hi = mid;\n }\n }\n\n return (lo + hi) * 0.5;\n}\n\n/**\n * Fraction of progress 0..1 through a 1D Bezier temporal segment whose value goes from 0 to 1,\n * with normalized out/in speeds (speed * duration / deltaValue) and influences.\n *\n * @param outSpeedNorm Normalized outgoing speed (speed * duration / deltaValue).\n * @param outInfluence Outgoing influence fraction [0, 1].\n * @param inSpeedNorm Normalized incoming speed (speed * duration / deltaValue).\n * @param inInfluence Incoming influence fraction [0, 1].\n * @param x Normalized time progress in segment [0, 1].\n */\nexport function easeProgress(\n outSpeedNorm: number,\n outInfluence: number,\n inSpeedNorm: number,\n inInfluence: number,\n x: number,\n): number {\n const i0 = Math.min(1.0, Math.max(0.0, outInfluence));\n const i1 = Math.min(1.0, Math.max(0.0, inInfluence));\n const u = solveBezierU(0.0, i0, 1.0 - i1, 1.0, x);\n return bez1d(0.0, outSpeedNorm * i0, 1.0 - inSpeedNorm * i1, 1.0, u);\n}\n\n/**\n * Evaluates an interpolated keyframe segment between two values over duration.\n *\n * @param from Starting value at t = 0.\n * @param to Ending value at t = duration.\n * @param duration Duration of the keyframe segment in seconds.\n * @param t Current elapsed time in seconds (0 <= t <= duration).\n * @param outEase Outgoing ease specification at start keyframe.\n * @param inEase Incoming ease specification at end keyframe.\n */\nexport function evaluateKeyframeSegment(\n from: number,\n to: number,\n duration: number,\n t: number,\n outEase: KeyframeEase = EASY_EASE,\n inEase: KeyframeEase = EASY_EASE,\n): number {\n if (duration <= 0 || t <= 0) return from;\n if (t >= duration) return to;\n\n const delta = to - from;\n const x = t / duration;\n\n // Zero delta: maintain from\n if (Math.abs(delta) < 1e-12) {\n return from;\n }\n\n const outSpeedNorm = (outEase.speed * duration) / delta;\n const inSpeedNorm = (inEase.speed * duration) / delta;\n\n const progress = easeProgress(outSpeedNorm, outEase.influence, inSpeedNorm, inEase.influence, x);\n return from + progress * delta;\n}\n","/**\n * SMPTE 12M Timecode engine and broadcast frame-rate converter.\n *\n * Supports non-drop-frame (NDF) and drop-frame (DF) timecode for broadcast standards\n * (23.976, 24, 25, 29.97, 30, 48, 50, 59.94, 60, 120 fps).\n *\n * Drop-frame timecode drops frames 00 and 01 at the start of each minute,\n * except every 10th minute (e.g. 00:01:00;02 instead of 00:01:00;00).\n */\n\nexport interface RationalFrameRate {\n readonly num: number;\n readonly den: number;\n}\n\nexport const COMMON_FRAME_RATES = {\n FPS_23_976: { num: 24000, den: 1001 },\n FPS_24: { num: 24, den: 1 },\n FPS_25: { num: 25, den: 1 },\n FPS_29_97: { num: 30000, den: 1001 },\n FPS_30: { num: 30, den: 1 },\n FPS_48: { num: 48, den: 1 },\n FPS_50: { num: 50, den: 1 },\n FPS_59_94: { num: 60000, den: 1001 },\n FPS_60: { num: 60, den: 1 },\n FPS_120: { num: 120, den: 1 },\n} as const;\n\nexport type StandardFrameRateKey = keyof typeof COMMON_FRAME_RATES;\n\n/** Greatest common divisor helper. */\nfunction gcd(a: number, b: number): number {\n let x = Math.abs(Math.round(a));\n let y = Math.abs(Math.round(b));\n while (y !== 0) {\n const t = y;\n y = x % y;\n x = t;\n }\n return x || 1;\n}\n\n/** Creates a reduced rational frame rate. */\nexport function createFrameRate(num: number, den = 1): RationalFrameRate {\n if (den <= 0 || num <= 0) {\n return { num: 30, den: 1 };\n }\n const g = gcd(num, den);\n return { num: Math.round(num / g), den: Math.round(den / g) };\n}\n\n/** Returns the timecode base (frames counted per second in timecode display). */\nexport function getTimecodeBase(rate: RationalFrameRate): number {\n return Math.ceil(rate.num / rate.den);\n}\n\n/** Whether a given frame rate supports drop-frame counting (29.97, 59.94, etc.). */\nexport function supportsDropFrame(rate: RationalFrameRate): boolean {\n return rate.den === 1001 && getTimecodeBase(rate) % 30 === 0;\n}\n\n/** Number of dropped frames per minute (e.g. 2 for 29.97, 4 for 59.94). */\nexport function getDropFrameCount(rate: RationalFrameRate): number {\n const base = getTimecodeBase(rate);\n return Math.floor(base / 15);\n}\n\nexport interface SMPTEFields {\n negative: boolean;\n hours: number;\n minutes: number;\n seconds: number;\n frames: number;\n}\n\n/**\n * Converts a continuous frame count to SMPTE fields (hours, minutes, seconds, frames).\n */\nexport function framesToSMPTE(\n frame: number,\n rate: RationalFrameRate = COMMON_FRAME_RATES.FPS_30,\n dropFrame = false,\n): SMPTEFields {\n const isDrop = dropFrame && supportsDropFrame(rate);\n const neg = frame < 0;\n let n = Math.abs(Math.round(frame));\n const base = getTimecodeBase(rate);\n const drop = getDropFrameCount(rate);\n\n if (isDrop) {\n const perMinute = base * 60 - drop;\n const per10Minutes = perMinute * 10 + drop;\n const d = Math.floor(n / per10Minutes);\n const m = n % per10Minutes;\n\n n += drop * 9 * d;\n if (m > drop) {\n n += drop * Math.floor((m - drop) / perMinute);\n }\n }\n\n const frames = n % base;\n const seconds = Math.floor(n / base) % 60;\n const minutes = Math.floor(n / (base * 60)) % 60;\n const hours = Math.floor(n / (base * 3600));\n\n return { negative: neg, hours, minutes, seconds, frames };\n}\n\n/**\n * Converts SMPTE fields back to a continuous frame number.\n */\nexport function smpteToFrames(\n fields: { hours: number; minutes: number; seconds: number; frames: number },\n rate: RationalFrameRate = COMMON_FRAME_RATES.FPS_30,\n dropFrame = false,\n): number {\n const isDrop = dropFrame && supportsDropFrame(rate);\n const base = getTimecodeBase(rate);\n const drop = getDropFrameCount(rate);\n\n const totalSecs = fields.hours * 3600 + fields.minutes * 60 + fields.seconds;\n let n = totalSecs * base + fields.frames;\n\n if (isDrop) {\n const totalMinutes = fields.hours * 60 + fields.minutes;\n n -= drop * (totalMinutes - Math.floor(totalMinutes / 10));\n }\n\n return n;\n}\n\n/**\n * Formats a frame number as standard SMPTE timecode (HH:MM:SS:FF or HH;MM;SS;FF).\n */\nexport function formatTimecode(\n frame: number,\n rate: RationalFrameRate = COMMON_FRAME_RATES.FPS_30,\n dropFrame = false,\n): string {\n const isDrop = dropFrame && supportsDropFrame(rate);\n const { negative, hours, minutes, seconds, frames } = framesToSMPTE(frame, rate, isDrop);\n const sep = isDrop ? ';' : ':';\n const base = getTimecodeBase(rate);\n const frameWidth = base >= 100 ? 3 : 2;\n\n const hStr = String(hours).padStart(2, '0');\n const mStr = String(minutes).padStart(2, '0');\n const sStr = String(seconds).padStart(2, '0');\n const fStr = String(frames).padStart(frameWidth, '0');\n\n return `${negative ? '-' : ''}${hStr}${sep}${mStr}${sep}${sStr}${sep}${fStr}`;\n}\n\n/**\n * Parses user or NLE input into a frame number.\n * Supports:\n * - Standard timecodes: `01:00:00:00`, `01;00;00;00`, `00.01.20.15`\n * - Right-aligned numbers: `1000` -> `00:00:10:00`\n * - Relative offsets: `+15` (+15 frames), `-1.00` (-1 second)\n *\n * @param input The timecode string to parse.\n * @param rate Rational frame rate (default: 30 fps).\n * @param dropFrame Whether drop-frame arithmetic applies.\n * @param currentFrame Current playhead position for relative additions.\n */\nexport function parseTimecode(\n input: string,\n rate: RationalFrameRate = COMMON_FRAME_RATES.FPS_30,\n dropFrame = false,\n currentFrame = 0,\n): number {\n const s = input.trim();\n if (!s) {\n throw new Error('Empty timecode string');\n }\n\n let relativeSign: 1 | -1 | null = null;\n let body = s;\n if (s.startsWith('+')) {\n relativeSign = 1;\n body = s.slice(1);\n } else if (s.startsWith('-')) {\n relativeSign = -1;\n body = s.slice(1);\n }\n\n const parts = body.split(/[:;.,]/);\n let parsedFrame = 0;\n\n if (parts.length === 1) {\n const digits = parts[0]!;\n if (!/^\\d+$/.test(digits)) {\n throw new Error(`Invalid timecode: \"${input}\"`);\n }\n\n if (relativeSign !== null) {\n // Relative bare digits are treated as frames\n const count = parseInt(digits, 10);\n return currentFrame + relativeSign * count;\n }\n\n // Right-aligned pairs: e.g. \"1000\" -> HH=0, MM=0, SS=10, FF=0\n const nums: number[] = [];\n let end = digits.length;\n while (end > 0) {\n const start = Math.max(0, end - 2);\n nums.unshift(parseInt(digits.slice(start, end), 10));\n end = start;\n }\n\n const padded = [0, 0, 0, 0];\n const offset = 4 - nums.length;\n for (let i = 0; i < nums.length; i++) {\n padded[offset + i] = nums[i]!;\n }\n const [h, m, sec, fr] = padded;\n parsedFrame = smpteToFrames(\n { hours: h!, minutes: m!, seconds: sec!, frames: fr! },\n rate,\n dropFrame,\n );\n } else {\n if (parts.length > 4) {\n throw new Error(`Too many timecode fields in \"${input}\"`);\n }\n const nums = parts.map((p) => (p.length === 0 ? 0 : parseInt(p, 10)));\n if (nums.some((n) => isNaN(n))) {\n throw new Error(`Invalid number in timecode: \"${input}\"`);\n }\n\n const padded = [0, 0, 0, 0];\n const offset = 4 - nums.length;\n for (let i = 0; i < nums.length; i++) {\n padded[offset + i] = nums[i]!;\n }\n const [h, m, sec, fr] = padded;\n parsedFrame = smpteToFrames(\n { hours: h!, minutes: m!, seconds: sec!, frames: fr! },\n rate,\n dropFrame,\n );\n }\n\n if (relativeSign !== null) {\n return currentFrame + relativeSign * parsedFrame;\n }\n\n return parsedFrame;\n}\n","import type { Scene } from './types.js';\n\nexport interface SliderSnapshot {\n at: number;\n values: Record<string, number | string>;\n}\n\nexport interface SliderWidget {\n type: 'slider';\n name: string;\n value: number;\n snapshots: SliderSnapshot[];\n}\n\nexport interface PopupWidget {\n type: 'popup';\n name: string;\n selected: string;\n options: Record<string, Record<string, number | string>>;\n}\n\nexport interface ToggleWidget {\n type: 'toggle';\n name: string;\n enabled: boolean;\n on: Record<string, number | string>;\n off: Record<string, number | string>;\n}\n\nexport type RigWidget = SliderWidget | PopupWidget | ToggleWidget;\n\nexport interface SceneRig {\n widgets: Record<string, RigWidget>;\n}\n\n/**\n * Updates a widget within a SceneRig and returns the updated SceneRig.\n */\nexport function setRigWidget(\n rig: SceneRig,\n widgetName: string,\n value: number | string | boolean,\n): SceneRig {\n const widget = rig.widgets[widgetName];\n if (!widget) {\n throw new Error(`Rig widget \"${widgetName}\" not found.`);\n }\n\n const updatedWidgets = { ...rig.widgets };\n\n if (widget.type === 'slider') {\n if (typeof value !== 'number') {\n throw new Error(`Slider widget \"${widgetName}\" expects numeric value.`);\n }\n updatedWidgets[widgetName] = { ...widget, value };\n } else if (widget.type === 'popup') {\n if (typeof value !== 'string') {\n throw new Error(`Popup widget \"${widgetName}\" expects string value.`);\n }\n updatedWidgets[widgetName] = { ...widget, selected: value };\n } else if (widget.type === 'toggle') {\n if (typeof value !== 'boolean') {\n throw new Error(`Toggle widget \"${widgetName}\" expects boolean value.`);\n }\n updatedWidgets[widgetName] = { ...widget, enabled: value };\n }\n\n return { widgets: updatedWidgets };\n}\n\n/**\n * Evaluates resolved values for a given widget.\n */\nfunction resolveWidgetValues(widget: RigWidget): Record<string, number | string> {\n if (widget.type === 'popup') {\n return widget.options[widget.selected] ?? {};\n }\n\n if (widget.type === 'toggle') {\n return widget.enabled ? widget.on : widget.off;\n }\n\n if (widget.type === 'slider') {\n const { snapshots, value } = widget;\n if (!snapshots || snapshots.length === 0) return {};\n\n const sorted = [...snapshots].sort((a, b) => a.at - b.at);\n if (value <= sorted[0]!.at) {\n return { ...sorted[0]!.values };\n }\n if (value >= sorted[sorted.length - 1]!.at) {\n return { ...sorted[sorted.length - 1]!.values };\n }\n\n // Find bounding snapshots\n let idx = 0;\n while (idx < sorted.length - 1 && sorted[idx + 1]!.at < value) {\n idx++;\n }\n\n const s0 = sorted[idx]!;\n const s1 = sorted[idx + 1]!;\n const span = s1.at - s0.at;\n const t = span > 0 ? (value - s0.at) / span : 0;\n\n const result: Record<string, number | string> = {};\n const allKeys = new Set([...Object.keys(s0.values), ...Object.keys(s1.values)]);\n\n for (const k of allKeys) {\n const v0 = s0.values[k];\n const v1 = s1.values[k];\n if (typeof v0 === 'number' && typeof v1 === 'number') {\n result[k] = v0 + (v1 - v0) * t;\n } else if (v0 !== undefined && v1 !== undefined) {\n result[k] = t < 0.5 ? v0 : v1;\n } else {\n result[k] = v1 !== undefined ? v1 : (v0 as number | string);\n }\n }\n\n return result;\n }\n\n return {};\n}\n\n/**\n * Propagates rig widget state into the scene's shader uniforms and elements.\n */\nexport function applyRig(rig: SceneRig, scene: Scene): Scene {\n // Deep clone media and shots to prevent mutation\n const nextMedia: Record<string, any> = {};\n if (scene.media) {\n for (const [id, m] of Object.entries(scene.media)) {\n nextMedia[id] = {\n ...m,\n values: { ...(m.values ?? {}) },\n };\n }\n }\n\n const nextShots = scene.shots.map((shot) => {\n if (!shot.run) return { ...shot };\n return {\n ...shot,\n run: shot.run.map((cmd) => {\n if (cmd.type === 'element' && 'element' in cmd && cmd.element) {\n return { ...cmd, element: { ...cmd.element } };\n }\n if (cmd.type === 'update' && 'props' in cmd && (cmd as any).props) {\n return { ...cmd, props: { ...(cmd as any).props } };\n }\n return { ...cmd };\n }),\n };\n });\n\n // Collect all resolved values across all widgets in the rig\n const resolvedAll: Record<string, number | string> = {};\n for (const widget of Object.values(rig.widgets)) {\n Object.assign(resolvedAll, resolveWidgetValues(widget));\n }\n\n // Apply resolved values\n for (const [targetKey, val] of Object.entries(resolvedAll)) {\n if (targetKey.startsWith('media.')) {\n const parts = targetKey.split('.');\n const mediaId = parts[1]!;\n const prop = parts.length > 3 && parts[2] === 'values' ? parts[3]! : parts[2]!;\n if (nextMedia[mediaId]) {\n nextMedia[mediaId].values[prop] = val;\n }\n } else if (targetKey.startsWith('element.')) {\n const parts = targetKey.split('.');\n const elId = parts[1]!;\n const prop = parts[2]!;\n for (const shot of nextShots) {\n if (shot.run) {\n for (const cmd of shot.run) {\n if (cmd.type === 'element' && 'element' in cmd && (cmd as any).element?.id === elId) {\n (cmd.element as any)[prop] = val;\n } else if (cmd.type === 'update' && 'id' in cmd && cmd.id === elId) {\n (cmd as any).props[prop] = val;\n }\n }\n }\n }\n } else {\n // General uniform shorthand: uniforms.<name> or simply <name>\n const uniformName = targetKey.replace(/^uniforms\\./, '');\n for (const m of Object.values(nextMedia)) {\n m.values[uniformName] = val;\n }\n }\n }\n\n return {\n ...scene,\n media: Object.keys(nextMedia).length > 0 ? nextMedia : scene.media,\n shots: nextShots,\n rig,\n };\n}\n","import type { SceneElement } from './geometry.js';\n\nexport type ReplicatorPattern = 'grid' | 'line' | 'circle' | 'spiral';\n\nexport interface ReplicatorSequence {\n /** Property to modulate per item. */\n property?: 'opacity' | 'rotation' | 'scale' | 'x' | 'y';\n /** Incremental offset or delta added per instance. */\n offset?: number;\n /** Milliseconds delay per instance for staggered triggers. */\n delayPerItem?: number;\n}\n\nexport interface ReplicatorConfig {\n pattern: ReplicatorPattern;\n count: number;\n /** Origin point [x, y] to anchor the layout (defaults to prototype.x, prototype.y). */\n origin?: [number, number];\n\n // Grid options\n columns?: number;\n rows?: number;\n columnSpacing?: number;\n rowSpacing?: number;\n\n // Line options\n startPoint?: [number, number];\n endPoint?: [number, number];\n spacing?: number;\n\n // Circle / Spiral options\n radius?: number;\n startAngle?: number; // radians\n spiralTightness?: number; // radius expansion per instance\n\n // Sequence modulation\n sequence?: ReplicatorSequence;\n}\n\n/**\n * Procedurally replicates a prototype SceneElement into an array of positioned\n * and sequenced instances (grid, circular array, line, or spiral).\n */\nexport function expandReplicator(\n prototype: SceneElement,\n config: ReplicatorConfig,\n): SceneElement[] {\n const count = Math.max(0, Math.floor(config.count));\n if (count === 0) return [];\n\n const originX = config.origin ? config.origin[0] : prototype.x;\n const originY = config.origin ? config.origin[1] : prototype.y;\n const elements: SceneElement[] = [];\n\n for (let i = 0; i < count; i++) {\n const el: SceneElement = {\n ...prototype,\n id: `${prototype.id}_${i}`,\n };\n\n let px = originX;\n let py = originY;\n\n switch (config.pattern) {\n case 'grid': {\n const cols = config.columns ?? Math.ceil(Math.sqrt(count));\n const colSpacing = config.columnSpacing ?? (prototype.width + 20);\n const rowSpacing = config.rowSpacing ?? (prototype.height + 20);\n const col = i % cols;\n const row = Math.floor(i / cols);\n px = originX + col * colSpacing;\n py = originY + row * rowSpacing;\n break;\n }\n\n case 'line': {\n if (config.startPoint && config.endPoint) {\n const t = count > 1 ? i / (count - 1) : 0;\n px = config.startPoint[0] + (config.endPoint[0] - config.startPoint[0]) * t;\n py = config.startPoint[1] + (config.endPoint[1] - config.startPoint[1]) * t;\n } else {\n const spacing = config.spacing ?? (prototype.width + 20);\n px = originX + i * spacing;\n py = originY;\n }\n break;\n }\n\n case 'circle': {\n const radius = config.radius ?? 150;\n const angleStep = (2 * Math.PI) / count;\n const angle = (config.startAngle ?? 0) + i * angleStep;\n px = originX + radius * Math.cos(angle);\n py = originY + radius * Math.sin(angle);\n break;\n }\n\n case 'spiral': {\n const baseRadius = config.radius ?? 40;\n const tightness = config.spiralTightness ?? 12;\n const angleStep = Math.PI / 4; // 45 degrees per step\n const angle = (config.startAngle ?? 0) + i * angleStep;\n const r = baseRadius + tightness * i;\n px = originX + r * Math.cos(angle);\n py = originY + r * Math.sin(angle);\n break;\n }\n }\n\n el.x = px;\n el.y = py;\n\n // Apply sequence property modulation\n if (config.sequence && config.sequence.offset !== undefined) {\n const { property, offset } = config.sequence;\n if (property === 'opacity') {\n const base = prototype.opacity ?? 1.0;\n el.opacity = Math.max(0, Math.min(1, base + i * offset));\n } else if (property === 'rotation') {\n const base = (prototype as any).rotation ?? 0;\n (el as any).rotation = base + i * offset;\n } else if (property === 'scale') {\n const factor = 1 + i * offset;\n el.width = Math.max(1, prototype.width * factor);\n el.height = Math.max(1, prototype.height * factor);\n } else if (property === 'x') {\n el.x += i * offset;\n } else if (property === 'y') {\n el.y += i * offset;\n }\n }\n\n elements.push(el);\n }\n\n return elements;\n}\n","/**\n * Constant-Velocity Spatial Motion Paths & Arc-Length Parameterization.\n *\n * Implements multi-segment cubic Bezier spatial trajectories with numerical\n * arc-length integration, ensuring constant pixel-speed traversal, tangent heading,\n * normal vectors, curvature, and seamless combination with temporal AE keyframe easing.\n */\n\nimport { evaluateKeyframeSegment, type KeyframeEase } from '../time/keyframe.js';\n\nexport type Vec2 = [number, number];\nexport type Vec3 = [number, number, number];\n\nexport interface PathWaypoint {\n /** Anchor position in 2D or 3D scene coordinates [x, y] or [x, y, z]. */\n point: Vec2 | Vec3;\n /** In-tangent handle relative to anchor point (vector pointing from handle to anchor or vice-versa). Default: [0, 0, 0] */\n inTangent?: Vec2 | Vec3;\n /** Out-tangent handle relative to anchor point (vector pointing from anchor toward next handle). Default: [0, 0, 0] */\n outTangent?: Vec2 | Vec3;\n}\n\nexport interface SpatialPathSample {\n /** Position on curve [x, y, z]. */\n position: Vec3;\n /** Normalized unit tangent vector [dx, dy, dz]. */\n tangent: Vec3;\n /** 2D heading angle in radians (atan2(dy, dx)). */\n heading: number;\n /** 2D unit normal vector [-dy, dx, 0]. */\n normal: Vec3;\n /** Instantaneous curvature kappa (1 / radius of curvature). */\n curvature: number;\n /** Distance traversed along the path in absolute units. */\n distance: number;\n}\n\ninterface SegmentSample {\n t: number;\n s: number;\n pos: Vec3;\n}\n\ninterface PathSegment {\n p0: Vec3;\n p1: Vec3;\n p2: Vec3;\n p3: Vec3;\n length: number;\n samples: SegmentSample[];\n}\n\nexport interface SpatialMotionPath {\n waypoints: PathWaypoint[];\n closed: boolean;\n totalLength: number;\n segments: PathSegment[];\n}\n\nfunction toVec3(p: Vec2 | Vec3 | undefined): Vec3 {\n if (!p) return [0, 0, 0];\n return [p[0], p[1], p[2] ?? 0];\n}\n\nfunction cubicPos(p0: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, t: number): Vec3 {\n const u = 1 - t;\n const a = u * u * u;\n const b = 3 * u * u * t;\n const c = 3 * u * t * t;\n const d = t * t * t;\n\n return [\n a * p0[0] + b * p1[0] + c * p2[0] + d * p3[0],\n a * p0[1] + b * p1[1] + c * p2[1] + d * p3[1],\n a * p0[2] + b * p1[2] + c * p2[2] + d * p3[2],\n ];\n}\n\nfunction cubicVel(p0: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, t: number): Vec3 {\n const u = 1 - t;\n const a = -3 * u * u;\n const b = 3 * u * u - 6 * u * t;\n const c = 6 * u * t - 3 * t * t;\n const d = 3 * t * t;\n\n return [\n a * p0[0] + b * p1[0] + c * p2[0] + d * p3[0],\n a * p0[1] + b * p1[1] + c * p2[1] + d * p3[1],\n a * p0[2] + b * p1[2] + c * p2[2] + d * p3[2],\n ];\n}\n\nfunction cubicAcc(p0: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, t: number): Vec3 {\n const u = 1 - t;\n const a = 6 * u;\n const b = -12 * u + 6 * t;\n const c = 6 * u - 12 * t;\n const d = 6 * t;\n\n return [\n a * p0[0] + b * p1[0] + c * p2[0] + d * p3[0],\n a * p0[1] + b * p1[1] + c * p2[1] + d * p3[1],\n a * p0[2] + b * p1[2] + c * p2[2] + d * p3[2],\n ];\n}\n\nfunction dist3(a: Vec3, b: Vec3): number {\n const dx = b[0] - a[0];\n const dy = b[1] - a[1];\n const dz = b[2] - a[2];\n return Math.sqrt(dx * dx + dy * dy + dz * dz);\n}\n\n/**\n * Creates and compiles a constant-velocity SpatialMotionPath from a sequence of waypoints.\n * Computes fine-grained arc-length tables along all Bezier segments.\n */\nexport function createMotionPath(\n waypoints: PathWaypoint[],\n options?: { closed?: boolean; resolution?: number }\n): SpatialMotionPath {\n if (waypoints.length < 2) {\n throw new Error('SpatialMotionPath requires at least 2 waypoints.');\n }\n\n const closed = options?.closed ?? false;\n const segmentCount = closed ? waypoints.length : waypoints.length - 1;\n const segments: PathSegment[] = [];\n let totalLength = 0;\n\n for (let i = 0; i < segmentCount; i++) {\n const nextIdx = (i + 1) % waypoints.length;\n const w0 = waypoints[i];\n const w1 = waypoints[nextIdx];\n\n const p0 = toVec3(w0.point);\n const outT = toVec3(w0.outTangent);\n const p1: Vec3 = [p0[0] + outT[0], p0[1] + outT[1], p0[2] + outT[2]];\n\n const p3 = toVec3(w1.point);\n const inT = toVec3(w1.inTangent);\n const p2: Vec3 = [p3[0] + inT[0], p3[1] + inT[1], p3[2] + inT[2]];\n\n // Chord length estimate\n const chord = dist3(p0, p1) + dist3(p1, p2) + dist3(p2, p3);\n const stepCount = Math.max(16, Math.min(256, Math.ceil(chord / (options?.resolution ?? 2))));\n\n const samples: SegmentSample[] = [];\n let segLen = 0;\n let prev = p0;\n samples.push({ t: 0, s: 0, pos: p0 });\n\n for (let k = 1; k <= stepCount; k++) {\n const t = k / stepCount;\n const pos = cubicPos(p0, p1, p2, p3, t);\n segLen += dist3(prev, pos);\n samples.push({ t, s: segLen, pos });\n prev = pos;\n }\n\n segments.push({\n p0,\n p1,\n p2,\n p3,\n length: segLen,\n samples,\n });\n totalLength += segLen;\n }\n\n return {\n waypoints,\n closed,\n totalLength,\n segments,\n };\n}\n\n/**\n * Samples the spatial motion path at a normalized distance fraction [0..1].\n * Guarantees strictly constant pixel speed regardless of control handle asymmetry.\n */\nexport function sampleMotionPath(path: SpatialMotionPath, distanceFraction: number): SpatialPathSample {\n const clampedFraction = Math.max(0, Math.min(1, distanceFraction));\n const targetDistance = clampedFraction * path.totalLength;\n\n if (path.totalLength === 0) {\n const p = toVec3(path.waypoints[0].point);\n return {\n position: p,\n tangent: [1, 0, 0],\n heading: 0,\n normal: [0, 1, 0],\n curvature: 0,\n distance: 0,\n };\n }\n\n // Find target segment\n let accumulated = 0;\n let targetSeg = path.segments[0];\n let segDistance = targetDistance;\n\n for (const seg of path.segments) {\n if (accumulated + seg.length >= targetDistance || seg === path.segments[path.segments.length - 1]) {\n targetSeg = seg;\n segDistance = Math.max(0, Math.min(seg.length, targetDistance - accumulated));\n break;\n }\n accumulated += seg.length;\n }\n\n // Binary search for exact sample in target segment's arc length table\n const samples = targetSeg.samples;\n let low = 0;\n let high = samples.length - 1;\n\n while (low <= high) {\n const mid = (low + high) >> 1;\n if (samples[mid].s < segDistance) {\n low = mid + 1;\n } else {\n high = mid - 1;\n }\n }\n\n const idx = Math.max(0, Math.min(samples.length - 2, high));\n const s0 = samples[idx];\n const s1 = samples[idx + 1];\n\n const segRange = s1.s - s0.s;\n const factor = segRange > 1e-7 ? (segDistance - s0.s) / segRange : 0;\n const t = s0.t + factor * (s1.t - s0.t);\n\n // Evaluate exact position, velocity, acceleration at t\n const pos = cubicPos(targetSeg.p0, targetSeg.p1, targetSeg.p2, targetSeg.p3, t);\n const vel = cubicVel(targetSeg.p0, targetSeg.p1, targetSeg.p2, targetSeg.p3, t);\n const acc = cubicAcc(targetSeg.p0, targetSeg.p1, targetSeg.p2, targetSeg.p3, t);\n\n const speed = Math.sqrt(vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2]);\n const safeSpeed = speed > 1e-6 ? speed : 1;\n const tangent: Vec3 = [vel[0] / safeSpeed, vel[1] / safeSpeed, vel[2] / safeSpeed];\n\n const heading = Math.atan2(tangent[1], tangent[0]);\n const normal: Vec3 = [-tangent[1], tangent[0], 0];\n\n // Curvature: kappa = |v x a| / |v|^3\n const cx = vel[1] * acc[2] - vel[2] * acc[1];\n const cy = vel[2] * acc[0] - vel[0] * acc[2];\n const cz = vel[0] * acc[1] - vel[1] * acc[0];\n const crossMag = Math.sqrt(cx * cx + cy * cy + cz * cz);\n const curvature = crossMag / (safeSpeed * safeSpeed * safeSpeed);\n\n return {\n position: pos,\n tangent,\n heading,\n normal,\n curvature,\n distance: targetDistance,\n };\n}\n\n/**\n * Samples a spatial motion path driven by elapsed time and AE keyframe velocity easing.\n * Combines spatial arc-length constancy with temporal speed curves.\n */\nexport function sampleMotionPathAtTime(\n path: SpatialMotionPath,\n time: number,\n duration: number,\n ease?: {\n easeIn?: KeyframeEase;\n easeOut?: KeyframeEase;\n }\n): SpatialPathSample {\n const distanceFraction = evaluateKeyframeSegment(\n 0,\n 1,\n duration,\n time,\n ease?.easeOut,\n ease?.easeIn\n );\n return sampleMotionPath(path, distanceFraction);\n}\n\n","import type { Scene, SceneMedia, Shot } from '../scene/types.js';\nimport { validateScene, type SceneIssue } from '../scene/validate.js';\nimport { simulateScene } from '../scene/player.js';\nimport type { Review } from '../scene/report.js';\nimport { applyRig, setRigWidget } from '../scene/rig.js';\n\nexport interface AgentToolDefinition {\n name: string;\n description: string;\n input_schema: Record<string, unknown>;\n}\n\nexport const FLAIR_AGENT_TOOLS: AgentToolDefinition[] = [\n {\n name: 'get_scene',\n description: 'Returns the current scene JSON (or a concise structural outline) and any static validation issues.',\n input_schema: {\n type: 'object',\n properties: {\n view: {\n type: 'string',\n enum: ['full', 'outline'],\n description:\n 'When \"outline\", returns scene hierarchy, timing, and framing without dense commands or raw media sources.',\n },\n },\n additionalProperties: false,\n },\n },\n {\n name: 'write_scene',\n description: 'Overwrites the entire scene with a new specification and validates it.',\n input_schema: {\n type: 'object',\n properties: {\n scene: {\n type: 'object',\n description:\n 'Full Scene object with name, stage, media, and shots. A shot camera frames a box {x, y, width, height} or elements {frame: [ids]}, and may add tilt, turn, roll (degrees, tilt/turn up to 75), perspective (default 1.2) and motionBlur (0-3, 1 natural); angles persist until changed.',\n },\n },\n required: ['scene'],\n additionalProperties: false,\n },\n },\n {\n name: 'update_shot',\n description: 'Updates fields of a specific shot (1-based index) without rewriting the whole scene.',\n input_schema: {\n type: 'object',\n properties: {\n shot: { type: 'integer', minimum: 1, description: '1-based index of the shot to update.' },\n set: { type: 'object', description: 'Fields to set or replace on this shot.' },\n remove: {\n type: 'array',\n items: { type: 'string' },\n description: 'Field names to delete from this shot.',\n },\n },\n required: ['shot'],\n additionalProperties: false,\n },\n },\n {\n name: 'insert_shots',\n description: 'Inserts one or more shots at a given position.',\n input_schema: {\n type: 'object',\n properties: {\n after: {\n type: 'integer',\n minimum: 0,\n description: '0 to insert at the beginning, or 1-based index of shot to insert after.',\n },\n shots: {\n type: 'array',\n items: { type: 'object' },\n description: 'Array of Shot objects to insert.',\n },\n },\n required: ['after', 'shots'],\n additionalProperties: false,\n },\n },\n {\n name: 'delete_shots',\n description: 'Deletes one or more shots by 1-based index.',\n input_schema: {\n type: 'object',\n properties: {\n shots: {\n type: 'array',\n items: { type: 'integer', minimum: 1 },\n description: '1-based shot numbers to delete.',\n },\n },\n required: ['shots'],\n additionalProperties: false,\n },\n },\n {\n name: 'set_media',\n description: 'Adds, updates, or removes embedded media (e.g. bespoke WebGL shaders) by ID.',\n input_schema: {\n type: 'object',\n properties: {\n id: { type: 'string', description: 'Media identifier.' },\n media: {\n type: ['object', 'null'],\n description: 'SceneMedia object (e.g. { type: \"shader\", source: \"...\" }), or null to remove.',\n },\n },\n required: ['id', 'media'],\n additionalProperties: false,\n },\n },\n {\n name: 'preview_scene',\n description: 'Simulates the scene fast and off-screen, returning timing, layout checks, and review report.',\n input_schema: {\n type: 'object',\n properties: {},\n additionalProperties: false,\n },\n },\n {\n name: 'set_rig_widget',\n description: 'Adjusts a high-level creative rig widget (slider, popup, or toggle) and propagates parameters to shaders and elements.',\n input_schema: {\n type: 'object',\n properties: {\n name: { type: 'string', description: 'Rig widget identifier/name.' },\n value: {\n type: ['number', 'string', 'boolean'],\n description: 'New value (number for slider, string for popup, boolean for toggle).',\n },\n },\n required: ['name', 'value'],\n additionalProperties: false,\n },\n },\n];\n\nexport interface SceneOutlineShot {\n shot: number;\n caption?: string;\n title?: string;\n hold?: number;\n camera?: Shot['camera'];\n commandCount: number;\n effects?: string[];\n}\n\nexport interface SceneOutline {\n name: string;\n title?: string;\n description?: string;\n stage?: Scene['stage'];\n target?: Scene['target'];\n mediaIds: string[];\n shots: SceneOutlineShot[];\n}\n\nexport type SceneToolResult =\n | { ok: true; scene: Scene; outline?: SceneOutline; issues: SceneIssue[]; review?: Review }\n | { ok: false; error: string };\n\n/**\n * Pure state machine that applies tool operations to a Scene.\n */\nexport async function applySceneTool(\n scene: Scene,\n toolName: string,\n input: Record<string, any> = {},\n): Promise<SceneToolResult> {\n switch (toolName) {\n case 'get_scene': {\n const issues = validateScene(scene);\n if (input.view === 'outline') {\n const outline: SceneOutline = {\n name: scene.name,\n title: scene.title,\n description: scene.description,\n stage: scene.stage,\n target: scene.target,\n mediaIds: Object.keys(scene.media || {}),\n shots: scene.shots.map((s, i) => ({\n shot: i + 1,\n caption: s.caption,\n title: s.title,\n hold: s.hold,\n camera: s.camera,\n commandCount: s.run?.length ?? 0,\n effects: s.effects?.map((e) => e.type),\n })),\n };\n return { ok: true, scene, outline, issues };\n }\n return { ok: true, scene, issues };\n }\n\n case 'write_scene': {\n if (!input.scene || typeof input.scene !== 'object') {\n return { ok: false, error: 'Expected scene object in arguments.' };\n }\n const newScene = input.scene as Scene;\n const issues = validateScene(newScene);\n return { ok: true, scene: newScene, issues };\n }\n\n case 'update_shot': {\n const idx = input.shot - 1;\n if (idx < 0 || idx >= scene.shots.length) {\n return { ok: false, error: `Invalid shot number ${input.shot}; scene has ${scene.shots.length} shots.` };\n }\n const existing = scene.shots[idx]!;\n const updated: Record<string, any> = { ...existing, ...(input.set || {}) };\n if (Array.isArray(input.remove)) {\n for (const k of input.remove) {\n delete updated[k];\n }\n }\n const shots = [...scene.shots];\n shots[idx] = updated as Shot;\n const newScene = { ...scene, shots };\n return { ok: true, scene: newScene, issues: validateScene(newScene) };\n }\n\n case 'insert_shots': {\n const after = input.after ?? scene.shots.length;\n if (after < 0 || after > scene.shots.length) {\n return { ok: false, error: `Invalid after index ${after}.` };\n }\n if (!Array.isArray(input.shots) || input.shots.length === 0) {\n return { ok: false, error: 'Expected non-empty shots array to insert.' };\n }\n const shots = [...scene.shots.slice(0, after), ...input.shots, ...scene.shots.slice(after)];\n const newScene = { ...scene, shots };\n return { ok: true, scene: newScene, issues: validateScene(newScene) };\n }\n\n case 'delete_shots': {\n if (!Array.isArray(input.shots) || input.shots.length === 0) {\n return { ok: false, error: 'Expected non-empty shots array to delete.' };\n }\n const toDelete = new Set(input.shots.map((n: number) => n - 1));\n const shots = scene.shots.filter((_, i) => !toDelete.has(i));\n if (shots.length === 0) {\n return { ok: false, error: 'Cannot delete all shots in scene.' };\n }\n const newScene = { ...scene, shots };\n return { ok: true, scene: newScene, issues: validateScene(newScene) };\n }\n\n case 'set_media': {\n if (!input.id || typeof input.id !== 'string') {\n return { ok: false, error: 'Expected string media id.' };\n }\n const media = { ...(scene.media || {}) };\n if (input.media === null) {\n delete media[input.id];\n } else {\n media[input.id] = input.media as SceneMedia;\n }\n const newScene = { ...scene, media };\n return { ok: true, scene: newScene, issues: validateScene(newScene) };\n }\n\n case 'preview_scene': {\n const { review } = await simulateScene(scene);\n return { ok: true, scene, issues: validateScene(scene), review };\n }\n\n case 'set_rig_widget': {\n if (!scene.rig || !scene.rig.widgets || !scene.rig.widgets[input.name]) {\n return { ok: false, error: `Scene does not have a rig widget named \"${input.name}\".` };\n }\n try {\n const updatedRig = setRigWidget(scene.rig, input.name, input.value);\n const newScene = applyRig(updatedRig, scene);\n return { ok: true, scene: newScene, issues: validateScene(newScene) };\n } catch (err: any) {\n return { ok: false, error: err.message || String(err) };\n }\n }\n\n default:\n return { ok: false, error: `Unknown tool name: ${toolName}` };\n }\n}\n","/**\n * Atomic Agent Multi-Tool Batching with Result Variable Substitution.\n * Inspired by EffectCraft's atomic batch execution protocol.\n *\n * Allows AI agents to execute multi-step modifications to a Scene in a single turn,\n * with atomic rollback on failure and cross-step variable substitution ($1.prop, $2.prop).\n */\n\nimport type { Scene } from '../scene/types.js';\nimport { applySceneTool, type SceneToolResult } from './tools.js';\n\nexport interface BatchCommand {\n /** Name of the tool to execute (e.g. 'update_shot', 'insert_shots', 'set_rig_widget'). */\n tool: string;\n /** Parameters for the tool call. */\n params?: Record<string, any>;\n}\n\nexport interface BatchExecutionStepResult {\n step: number;\n tool: string;\n result: SceneToolResult;\n}\n\nexport interface BatchExecutionResult {\n ok: boolean;\n scene: Scene;\n steps: BatchExecutionStepResult[];\n error?: string;\n failedStep?: number;\n}\n\n/**\n * Resolves nested property path on an object (e.g. \"a.b[0].c\").\n */\nfunction getByPath(obj: any, path: string): any {\n if (!obj || typeof obj !== 'object') return undefined;\n const parts = path.replace(/\\[(\\w+)\\]/g, '.$1').split('.');\n let curr = obj;\n for (const part of parts) {\n if (curr === undefined || curr === null) return undefined;\n curr = curr[part];\n }\n return curr;\n}\n\n/**\n * Recursively substitutes `$stepIndex.path` references in parameters using previous step results.\n * E.g., \"$1.scene.shots[0].duration\" -> substituted with the duration value from step 1 result.\n */\nexport function substituteVariables(\n value: any,\n stepResults: Map<number, SceneToolResult>,\n): any {\n if (typeof value === 'string') {\n // Check if the entire string is a substitution reference: \"$1.path.to.prop\"\n const match = /^\\$(\\d+)\\.(.+)$/.exec(value);\n if (match) {\n const stepIdx = parseInt(match[1]!, 10);\n const path = match[2]!;\n const prevResult = stepResults.get(stepIdx);\n if (prevResult) {\n const resolved = getByPath(prevResult, path);\n if (resolved !== undefined) {\n return resolved;\n }\n }\n }\n // Partial template string substitution: \"Hello $1.scene.name\"\n return value.replace(/\\$(\\d+)\\.([a-zA-Z0-9_.[\\]]+)/g, (fullMatch, stepStr, path) => {\n const stepIdx = parseInt(stepStr, 10);\n const prevResult = stepResults.get(stepIdx);\n if (prevResult) {\n const resolved = getByPath(prevResult, path);\n if (resolved !== undefined) {\n return String(resolved);\n }\n }\n return fullMatch;\n });\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => substituteVariables(item, stepResults));\n }\n\n if (value !== null && typeof value === 'object') {\n const copy: Record<string, any> = {};\n for (const [k, v] of Object.entries(value)) {\n copy[k] = substituteVariables(v, stepResults);\n }\n return copy;\n }\n\n return value;\n}\n\n/**\n * Executes an atomic batch of scene tools with transactional rollback.\n * If any step fails, the scene rolls back to the initial state and returns the failure.\n *\n * @param scene Initial scene state before batch.\n * @param commands Ordered array of tool commands to execute.\n */\nexport async function applySceneBatch(\n scene: Scene,\n commands: BatchCommand[],\n): Promise<BatchExecutionResult> {\n let currentScene = scene;\n const stepResults = new Map<number, SceneToolResult>();\n const executedSteps: BatchExecutionStepResult[] = [];\n\n for (let i = 0; i < commands.length; i++) {\n const stepNumber = i + 1; // 1-based indexing for user/agent ergonomics\n const cmd = commands[i]!;\n\n // Perform variable substitution using results of earlier steps\n const resolvedParams = substituteVariables(cmd.params || {}, stepResults);\n\n // Prevent recursive batch execution to avoid cycles\n if (cmd.tool === 'batch_scene_tool') {\n return {\n ok: false,\n scene, // Rollback\n steps: executedSteps,\n error: `Nested batch_scene_tool is not allowed at step ${stepNumber}.`,\n failedStep: stepNumber,\n };\n }\n\n const stepResult = await applySceneTool(currentScene, cmd.tool, resolvedParams);\n stepResults.set(stepNumber, stepResult);\n executedSteps.push({\n step: stepNumber,\n tool: cmd.tool,\n result: stepResult,\n });\n\n if (!stepResult.ok) {\n // Transactional rollback: discard intermediate scenes and return original\n return {\n ok: false,\n scene, // Rollback to initial\n steps: executedSteps,\n error: `Step ${stepNumber} (${cmd.tool}) failed: ${stepResult.error}`,\n failedStep: stepNumber,\n };\n }\n\n currentScene = stepResult.scene;\n }\n\n return {\n ok: true,\n scene: currentScene,\n steps: executedSteps,\n };\n}\n"],"mappings":"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","names":["frame"]}
@@ -0,0 +1,82 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes } from 'react';
3
+ import { V as VectorEffect$1 } from '../types-9J6NWaN3.js';
4
+ import { C as ControlValue } from '../controls-Syr6drzO.js';
5
+ import { S as SvgMotion, a as SvgTrigger, C as Clock, b as SvgPlayer } from '../svg-XugR-6Ec.js';
6
+
7
+ /** When to leave the still in place of the animation. */
8
+ type ReducedMotion = "user" | "always" | "never";
9
+ interface SvgPlayerViewProps extends Omit<HTMLAttributes<HTMLSpanElement>, "children"> {
10
+ /** The picture and its animations. */
11
+ motion: SvgMotion;
12
+ /** Start again at the end (default `true`); `false` plays once and stays on the last frame. */
13
+ loop?: boolean;
14
+ /** Start playing at once (default `true`). */
15
+ autoplay?: boolean;
16
+ /** Playback speed (default 1). */
17
+ speed?: number;
18
+ /** Ms to rest on the last frame before looping (default 600). */
19
+ hold?: number;
20
+ /** Loop length in ms (default: the picture's own, plus `hold`). */
21
+ duration?: number;
22
+ /** Step start times in ms, for pictures that change on steps. */
23
+ steps?: readonly number[];
24
+ /** Plays in answer to the pointer (see `SvgTrigger`). */
25
+ trigger?: SvgTrigger;
26
+ /** Pause while scrolled out of view. */
27
+ pauseWhenHidden?: boolean;
28
+ /** Wait to start until scrolled into view. */
29
+ playOnEnter?: boolean;
30
+ /** Hide the picture while paused or reset. */
31
+ hideWhenPaused?: boolean;
32
+ /** Time source (default animation frames); a `ManualClock` steps frames yourself. */
33
+ clock?: Clock;
34
+ /** Called with the id of the innermost element with an id that is clicked. */
35
+ onPick?: (id: string) => void;
36
+ /** Called with the player once it is made, and `undefined` when it is disposed. */
37
+ onPlayer?: (player: SvgPlayer | undefined) => void;
38
+ /**
39
+ * The still shown before the player starts (server render, hydration) and
40
+ * instead of it under reduced motion: `"last"` (default; the rest frame,
41
+ * `"first"` for a hover or press trigger), `"first"` or a time in ms.
42
+ */
43
+ poster?: "first" | "last" | number;
44
+ /**
45
+ * `"user"` (default) shows the still when the visitor prefers reduced
46
+ * motion, `"always"` always does, `"never"` always plays.
47
+ */
48
+ reducedMotion?: ReducedMotion;
49
+ /**
50
+ * Size it as a word in a line of text: `display: inline-block` with the
51
+ * viewBox's aspect ratio and `height` 0.72em (the cap height of a heavy
52
+ * sans; pass a CSS length for another). Meant for pictures framed from cap
53
+ * height to baseline, like drip text's `inline`. Otherwise it is a block
54
+ * as wide as its container with the viewBox's aspect ratio.
55
+ */
56
+ inline?: boolean | string;
57
+ }
58
+ /**
59
+ * Plays an {@link SvgMotion}: a still on the server and before mount, then
60
+ * an `SvgPlayer` (remade when the motion or its options change, disposed on
61
+ * unmount). Pass a memoised `motion`: a new object each render restarts it.
62
+ */
63
+ declare function SvgPlayerView(props: SvgPlayerViewProps): react.JSX.Element;
64
+ interface VectorEffectProps extends Omit<SvgPlayerViewProps, "motion" | "id"> {
65
+ /** A vector effect's catalog id (`"drip-text"`), or the effect itself. */
66
+ id: string | VectorEffect$1;
67
+ /** Control values; missing ones take the preset's, then the defaults. */
68
+ values?: Record<string, ControlValue>;
69
+ /** A preset's name to start from. */
70
+ preset?: string;
71
+ /** The host element's own `id`. */
72
+ elementId?: string;
73
+ }
74
+ /**
75
+ * Plays a catalog vector effect: `<VectorEffect id="drip-text" values={{ word: "Slop" }} loop={false} />`.
76
+ * Its `hold` and `trigger` are used unless given. With an `inline` control
77
+ * set (drip text's), it is sized as a word in the line (see `inline`).
78
+ * Throws when `id` is not a vector effect.
79
+ */
80
+ declare function VectorEffect(props: VectorEffectProps): react.JSX.Element;
81
+
82
+ export { type ReducedMotion, SvgMotion, SvgPlayer, SvgPlayerView, type SvgPlayerViewProps, SvgTrigger, VectorEffect, type VectorEffectProps };
@@ -0,0 +1,132 @@
1
+ import {
2
+ effectDefaults,
3
+ getEffect,
4
+ renderVectorEffect
5
+ } from "../chunk-KWNFZ5NC.js";
6
+ import {
7
+ svgFrameMarkup,
8
+ svgViewBox
9
+ } from "../chunk-DVVQRZJ5.js";
10
+ import {
11
+ SvgPlayer
12
+ } from "../chunk-4RGHZWQC.js";
13
+ import "../chunk-OHW7UG6D.js";
14
+ import "../chunk-EHDJ3CPJ.js";
15
+ import "../chunk-WC3VADZC.js";
16
+ import "../chunk-WMZQCUFJ.js";
17
+
18
+ // src/react/index.tsx
19
+ import {
20
+ useEffect,
21
+ useLayoutEffect,
22
+ useMemo,
23
+ useRef
24
+ } from "react";
25
+ import { jsx, jsxs } from "react/jsx-runtime";
26
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
27
+ var CAP_HEIGHT = "0.72em";
28
+ function prefersReducedMotion() {
29
+ return typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
30
+ }
31
+ function hostStyle(svg, inline, style) {
32
+ const box = svgViewBox(svg);
33
+ const aspectRatio = box ? `${box[2]} / ${box[3]}` : void 0;
34
+ const base = inline ? { display: "inline-block", height: typeof inline === "string" ? inline : CAP_HEIGHT, aspectRatio } : { display: "block", aspectRatio };
35
+ return { position: "relative", ...base, ...style };
36
+ }
37
+ var LAYER = { position: "absolute", inset: 0, display: "block" };
38
+ function SvgPlayerView(props) {
39
+ const {
40
+ motion,
41
+ loop,
42
+ autoplay,
43
+ speed,
44
+ hold,
45
+ duration,
46
+ steps,
47
+ trigger,
48
+ pauseWhenHidden,
49
+ playOnEnter,
50
+ hideWhenPaused,
51
+ clock,
52
+ onPick,
53
+ onPlayer,
54
+ poster,
55
+ reducedMotion = "user",
56
+ inline,
57
+ style,
58
+ ...rest
59
+ } = props;
60
+ const still = useRef(null);
61
+ const mount = useRef(null);
62
+ const player = useRef(void 0);
63
+ const callbacks = useRef({ onPick, onPlayer });
64
+ callbacks.current = { onPick, onPlayer };
65
+ const at = poster ?? (trigger === "hover" || trigger === "press" ? "first" : "last");
66
+ const markup = useMemo(() => svgFrameMarkup(motion, { at, steps }) ?? "", [motion, at, steps]);
67
+ const stepsKey = steps?.join(",");
68
+ useIsomorphicLayoutEffect(() => {
69
+ const host = mount.current;
70
+ if (!host) return;
71
+ if (reducedMotion === "always" || reducedMotion === "user" && prefersReducedMotion()) return;
72
+ const p = new SvgPlayer(host, motion, {
73
+ loop,
74
+ autoplay,
75
+ speed,
76
+ hold,
77
+ duration,
78
+ steps,
79
+ trigger,
80
+ pauseWhenHidden,
81
+ playOnEnter,
82
+ hideWhenPaused,
83
+ clock,
84
+ onPick: (id) => callbacks.current.onPick?.(id)
85
+ });
86
+ player.current = p;
87
+ if (still.current) still.current.style.display = "none";
88
+ callbacks.current.onPlayer?.(p);
89
+ return () => {
90
+ p.dispose();
91
+ player.current = void 0;
92
+ if (still.current) still.current.style.display = "block";
93
+ callbacks.current.onPlayer?.(void 0);
94
+ };
95
+ }, [motion, loop, autoplay, hold, duration, stepsKey, trigger, pauseWhenHidden, playOnEnter, hideWhenPaused, clock, reducedMotion]);
96
+ useEffect(() => {
97
+ player.current?.setSpeed(speed ?? 1);
98
+ }, [speed]);
99
+ return /* @__PURE__ */ jsxs("span", { ...rest, style: hostStyle(motion.svg, inline, style), children: [
100
+ /* @__PURE__ */ jsx("span", { ref: still, "aria-hidden": "true", style: LAYER, dangerouslySetInnerHTML: { __html: markup } }),
101
+ /* @__PURE__ */ jsx("span", { ref: mount, style: LAYER })
102
+ ] });
103
+ }
104
+ function VectorEffect(props) {
105
+ const { id, values, preset, elementId, ...rest } = props;
106
+ const effect = typeof id === "string" ? getEffect(id) : id;
107
+ if (!effect || effect.kind !== "vector")
108
+ throw new Error(`"${typeof id === "string" ? id : effect?.id}" is not a vector effect; pick one from findEffects({ kind: "vector" })`);
109
+ const valuesKey = JSON.stringify(values ?? {});
110
+ const motion = useMemo(
111
+ () => renderVectorEffect(effect, effectDefaults(effect, { preset, values })),
112
+ // Values by content, so an inline object literal does not restart it.
113
+ // eslint-disable-next-line react-hooks/exhaustive-deps
114
+ [effect, preset, valuesKey]
115
+ );
116
+ return /* @__PURE__ */ jsx(
117
+ SvgPlayerView,
118
+ {
119
+ id: elementId,
120
+ motion,
121
+ hold: effect.hold,
122
+ trigger: effect.trigger,
123
+ inline: values?.inline === true,
124
+ ...rest
125
+ }
126
+ );
127
+ }
128
+ export {
129
+ SvgPlayerView,
130
+ VectorEffect
131
+ };
132
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/react/index.tsx"],"sourcesContent":["/**\n * React components for Flair's vector effects: `<VectorEffect>` plays a\n * catalog effect by id, `<SvgPlayerView>` plays any {@link SvgMotion}.\n *\n * Both render a still of the picture on the server (its last frame, by\n * default), so a page hydrates with the picture in place rather than a blank\n * box that jumps; the live `SvgPlayer` takes over after mount and is disposed\n * on unmount. Under `prefers-reduced-motion: reduce` the still stays.\n *\n * Needs React 18 or later (an optional peer dependency of the package).\n *\n * @packageDocumentation\n */\n\nimport {\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n type CSSProperties,\n type HTMLAttributes,\n} from \"react\";\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, svgViewBox } from \"../vector/static.js\";\nimport { SvgPlayer, type SvgTrigger } from \"../vector/svg.js\";\n\n// Layout effects swap the still for the player before paint; on a server neither runs.\nconst useIsomorphicLayoutEffect = typeof window === \"undefined\" ? useEffect : useLayoutEffect;\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/** When to leave the still in place of the animation. */\nexport type ReducedMotion = \"user\" | \"always\" | \"never\";\n\nexport interface SvgPlayerViewProps extends Omit<HTMLAttributes<HTMLSpanElement>, \"children\"> {\n /** The picture and its animations. */\n motion: SvgMotion;\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). */\n speed?: number;\n /** Ms to rest on the last frame before looping (default 600). */\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`). */\n trigger?: SvgTrigger;\n /** Pause while scrolled out of view. */\n pauseWhenHidden?: boolean;\n /** Wait to start until scrolled into view. */\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 (server render, hydration) and\n * instead of it under reduced motion: `\"last\"` (default; the rest frame,\n * `\"first\"` for a hover or press 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). Meant for pictures framed from cap\n * height to baseline, like drip text's `inline`. Otherwise it is a block\n * as wide as its container with the viewBox's aspect ratio.\n */\n inline?: boolean | string;\n}\n\nfunction prefersReducedMotion(): boolean {\n return typeof matchMedia === \"function\" && matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\n/** The host's size from the picture's viewBox, so the still and the player take the same room. */\nfunction hostStyle(svg: string, inline: boolean | string | undefined, style?: CSSProperties): CSSProperties {\n const box = svgViewBox(svg);\n const aspectRatio = box ? `${box[2]} / ${box[3]}` : undefined;\n const base: CSSProperties = inline\n ? { display: \"inline-block\", height: typeof inline === \"string\" ? inline : CAP_HEIGHT, aspectRatio }\n : { display: \"block\", aspectRatio };\n return { position: \"relative\", ...base, ...style };\n}\n\nconst LAYER: CSSProperties = { position: \"absolute\", inset: 0, display: \"block\" };\n\n/**\n * Plays an {@link SvgMotion}: a still on the server and before mount, then\n * an `SvgPlayer` (remade when the motion or its options change, disposed on\n * unmount). Pass a memoised `motion`: a new object each render restarts it.\n */\nexport function SvgPlayerView(props: SvgPlayerViewProps) {\n const {\n motion,\n loop,\n autoplay,\n speed,\n hold,\n duration,\n steps,\n trigger,\n pauseWhenHidden,\n playOnEnter,\n hideWhenPaused,\n clock,\n onPick,\n onPlayer,\n poster,\n reducedMotion = \"user\",\n inline,\n style,\n ...rest\n } = props;\n const still = useRef<HTMLSpanElement>(null);\n const mount = useRef<HTMLSpanElement>(null);\n const player = useRef<SvgPlayer | undefined>(undefined);\n // Callbacks change every render; the player calls the latest without being remade.\n const callbacks = useRef({ onPick, onPlayer });\n callbacks.current = { onPick, onPlayer };\n\n const at = poster ?? (trigger === \"hover\" || trigger === \"press\" ? \"first\" : \"last\");\n const markup = useMemo(() => svgFrameMarkup(motion, { at, steps }) ?? \"\", [motion, at, steps]);\n const stepsKey = steps?.join(\",\");\n\n useIsomorphicLayoutEffect(() => {\n const host = mount.current;\n if (!host) return;\n if (reducedMotion === \"always\" || (reducedMotion === \"user\" && prefersReducedMotion())) return;\n const p = new SvgPlayer(host, motion, {\n loop,\n autoplay,\n speed,\n hold,\n duration,\n steps,\n trigger,\n pauseWhenHidden,\n playOnEnter,\n hideWhenPaused,\n clock,\n onPick: (id) => callbacks.current.onPick?.(id),\n });\n player.current = p;\n // Set directly, not through props, so React leaves it be on later renders.\n if (still.current) still.current.style.display = \"none\";\n callbacks.current.onPlayer?.(p);\n return () => {\n p.dispose();\n player.current = undefined;\n if (still.current) still.current.style.display = \"block\";\n callbacks.current.onPlayer?.(undefined);\n };\n // `speed` is applied below without remaking; `steps` by value.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [motion, loop, autoplay, hold, duration, stepsKey, trigger, pauseWhenHidden, playOnEnter, hideWhenPaused, clock, reducedMotion]);\n\n useEffect(() => {\n player.current?.setSpeed(speed ?? 1);\n }, [speed]);\n\n return (\n <span {...rest} style={hostStyle(motion.svg, inline, style)}>\n <span ref={still} aria-hidden=\"true\" style={LAYER} dangerouslySetInnerHTML={{ __html: markup }} />\n <span ref={mount} style={LAYER} />\n </span>\n );\n}\n\nexport interface VectorEffectProps extends Omit<SvgPlayerViewProps, \"motion\" | \"id\"> {\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. */\n values?: Record<string, ControlValue>;\n /** A preset's name to start from. */\n preset?: string;\n /** The host element's own `id`. */\n elementId?: string;\n}\n\n/**\n * Plays a catalog vector effect: `<VectorEffect id=\"drip-text\" values={{ word: \"Slop\" }} loop={false} />`.\n * Its `hold` and `trigger` are used unless given. With an `inline` control\n * set (drip text's), it is sized as a word in the line (see `inline`).\n * Throws when `id` is not a vector effect.\n */\nexport function VectorEffect(props: VectorEffectProps) {\n const { id, values, preset, elementId, ...rest } = props;\n const effect = typeof id === \"string\" ? getEffect(id) : id;\n if (!effect || effect.kind !== \"vector\")\n throw new Error(`\"${typeof id === \"string\" ? id : effect?.id}\" is not a vector effect; pick one from findEffects({ kind: \"vector\" })`);\n const valuesKey = JSON.stringify(values ?? {});\n const motion = useMemo(\n () => renderVectorEffect(effect, effectDefaults(effect, { preset, values })),\n // Values by content, so an inline object literal does not restart it.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [effect, preset, valuesKey],\n );\n return (\n <SvgPlayerView\n id={elementId}\n motion={motion}\n hold={effect.hold}\n trigger={effect.trigger}\n inline={values?.inline === true}\n {...rest}\n />\n );\n}\n\nexport type { SvgPlayer, SvgMotion, SvgTrigger };\n"],"mappings":"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","names":[]}
@@ -382,4 +382,4 @@ interface AnimateCountOptions {
382
382
  */
383
383
  declare function animateCount(options: AnimateCountOptions): () => void;
384
384
 
385
- export { type AnimateCountOptions as A, svgMotionIssues as B, type Clock as C, type DataKey as D, EASES as E, svgOpeningTag as F, svgView as G, writtenText as H, ManualClock as M, type SvgMotion as S, type SvgTrigger as a, type EaseName as b, SCRAMBLE_MS as c, STEP_MS as d, SVG_PICTURE as e, type SvgAnimation as f, type SvgBox as g, type SvgElementFrame as h, SvgPlayer as i, type SvgPlayerOptions as j, type SvgView as k, type SvgViewOptions as l, animateCount as m, defaultDataKey as n, formatCount as o, jitter as p, lerpAttr as q, lerpData as r, pageHidden as s, parseSvg as t, realClock as u, stepData as v, stepProgress as w, stepStart as x, svgDuration as y, svgFrame as z };
385
+ export { type AnimateCountOptions as A, svgMotionIssues as B, type Clock as C, type DataKey as D, EASES as E, svgOpeningTag as F, svgView as G, writtenText as H, ManualClock as M, type SvgMotion as S, type SvgTrigger as a, SvgPlayer as b, type EaseName as c, SCRAMBLE_MS as d, STEP_MS as e, SVG_PICTURE as f, type SvgAnimation as g, type SvgBox as h, type SvgElementFrame as i, type SvgPlayerOptions as j, type SvgView as k, type SvgViewOptions as l, animateCount as m, defaultDataKey as n, formatCount as o, jitter as p, lerpAttr as q, lerpData as r, pageHidden as s, parseSvg as t, realClock as u, stepData as v, stepProgress as w, stepStart as x, svgDuration as y, svgFrame as z };
@@ -1,5 +1,5 @@
1
1
  import { C as ControlValue, a as ControlDef } from './controls-Syr6drzO.js';
2
- import { S as SvgMotion, a as SvgTrigger } from './svg-C_TWBtEN.js';
2
+ import { S as SvgMotion, a as SvgTrigger } from './svg-XugR-6Ec.js';
3
3
 
4
4
  /** What an effect is for, used to group the catalog. */
5
5
  type EffectCategory = "gradient" | "organic" | "pattern" | "light" | "space" | "retro" | "image" | "overlay" | "text" | "morph" | "interaction" | "pyrotechnics" | "timewarp" | "melt" | "electric" | "transition" | "loader" | "data" | "icon";
@@ -111,4 +111,4 @@ declare function colorControl(name: string, hex: string, label?: string): Vector
111
111
  /** A number control for vector effects. */
112
112
  declare function numberControl(name: string, value: number, min: number, max: number, label?: string, step?: number): VectorControl;
113
113
 
114
- export { type EffectDefinition as E, type ShaderEffect as S, VECTOR_CONTROL_TYPES as V, type EffectCategory as a, EFFECT_CATEGORIES as b, type EffectPreset as c, type VectorControl as d, type VectorEffect as e, colorControl as f, vectorControlIssues as g, vectorControls as h, vectorEffectControls as i, numberControl as n, renderVectorEffect as r, vectorControlDef as v };
114
+ export { type EffectDefinition as E, type ShaderEffect as S, type VectorEffect as V, type EffectCategory as a, EFFECT_CATEGORIES as b, type EffectPreset as c, VECTOR_CONTROL_TYPES as d, type VectorControl as e, colorControl as f, vectorControlIssues as g, vectorControls as h, vectorEffectControls as i, numberControl as n, renderVectorEffect as r, vectorControlDef as v };
@@ -1,5 +1,5 @@
1
- import { g as SvgBox } from '../svg-C_TWBtEN.js';
2
- export { A as AnimateCountOptions, D as DataKey, E as EASES, b as EaseName, c as SCRAMBLE_MS, d as STEP_MS, e as SVG_PICTURE, f as SvgAnimation, h as SvgElementFrame, S as SvgMotion, i as SvgPlayer, j as SvgPlayerOptions, a as SvgTrigger, k as SvgView, l as SvgViewOptions, m as animateCount, n as defaultDataKey, o as formatCount, q as lerpAttr, r as lerpData, t as parseSvg, v as stepData, w as stepProgress, x as stepStart, y as svgDuration, z as svgFrame, B as svgMotionIssues, F as svgOpeningTag, G as svgView, H as writtenText } from '../svg-C_TWBtEN.js';
1
+ import { h as SvgBox, S as SvgMotion } from '../svg-XugR-6Ec.js';
2
+ export { A as AnimateCountOptions, D as DataKey, E as EASES, c as EaseName, d as SCRAMBLE_MS, e as STEP_MS, f as SVG_PICTURE, g as SvgAnimation, i as SvgElementFrame, b as SvgPlayer, j as SvgPlayerOptions, a as SvgTrigger, k as SvgView, l as SvgViewOptions, m as animateCount, n as defaultDataKey, o as formatCount, q as lerpAttr, r as lerpData, t as parseSvg, v as stepData, w as stepProgress, x as stepStart, y as svgDuration, z as svgFrame, B as svgMotionIssues, F as svgOpeningTag, G as svgView, H as writtenText } from '../svg-XugR-6Ec.js';
3
3
 
4
4
  /**
5
5
  * Shape morphing: any SVG paths turned into paths with the same structure, so
@@ -28,6 +28,38 @@ declare function morphSequence(paths: readonly string[], options?: MorphOptions)
28
28
  */
29
29
  declare function morphPaths(from: string, to: string, options?: MorphOptions): [string, string];
30
30
 
31
+ /**
32
+ * An {@link SvgMotion}'s frame as markup, with no DOM: for server rendering
33
+ * (a still that hydrates without a blank flash), reduced motion and other
34
+ * places a live player is not wanted.
35
+ */
36
+
37
+ /** A `viewBox` attribute's box, or undefined when it has none or it is malformed. */
38
+ declare function parseViewBox(value: string | null | undefined): SvgBox | undefined;
39
+ /** The `viewBox` on an SVG's opening tag (see {@link parseViewBox}). */
40
+ declare function svgViewBox(markup: string): SvgBox | undefined;
41
+ interface SvgFrameMarkupOptions {
42
+ /**
43
+ * The time shown, in ms: a number, `"first"` (0) or `"last"` (the end of
44
+ * its last change, see `svgDuration`; the default).
45
+ */
46
+ at?: number | "first" | "last";
47
+ /** Step start times in ms, as a player's `steps` (default none). */
48
+ steps?: readonly number[];
49
+ }
50
+ /**
51
+ * The picture of an {@link SvgMotion} at a moment, as `<svg>` markup made safe
52
+ * the way `parseSvg` makes it (no scripts, handlers, `<foreignObject>` or
53
+ * outside links), with no DOM needed: render it on a server, show it under
54
+ * `prefers-reduced-motion`, or anywhere a still will do. It is sized to fill
55
+ * its container, as `SvgPlayer` draws it.
56
+ *
57
+ * It matches the player's frame except where that needs layout: a change
58
+ * `along` a path, and a `view` that frames an element by id, stay where the
59
+ * markup puts them. Undefined when `motion.svg` is not an `<svg>`.
60
+ */
61
+ declare function svgFrameMarkup(motion: SvgMotion, options?: SvgFrameMarkupOptions): string | undefined;
62
+
31
63
  type BoxFit = 'fill' | 'contain' | 'cover' | 'none' | 'scale-down';
32
64
  type BoxAlignment = 'topLeft' | 'topCenter' | 'topRight' | 'centerLeft' | 'center' | 'centerRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight';
33
65
  interface FittedBoxResult {
@@ -81,4 +113,4 @@ interface FormatUnitOptions {
81
113
  */
82
114
  declare function formatUnit(value: number, format?: UnitFormat, options?: FormatUnitOptions): string;
83
115
 
84
- export { type BoxAlignment, type BoxFit, type FittedBoxResult, type FormatUnitOptions, type MorphOptions, type StackLayoutOptions, SvgBox, type UnitFormat, computeBoxFit, formatUnit, layoutStack, morphPaths, morphSequence, remap, stepVariant };
116
+ export { type BoxAlignment, type BoxFit, type FittedBoxResult, type FormatUnitOptions, type MorphOptions, type StackLayoutOptions, SvgBox, type SvgFrameMarkupOptions, SvgMotion, type UnitFormat, computeBoxFit, formatUnit, layoutStack, morphPaths, morphSequence, parseViewBox, remap, stepVariant, svgFrameMarkup, svgViewBox };
@@ -4,7 +4,12 @@ import {
4
4
  layoutStack,
5
5
  remap,
6
6
  stepVariant
7
- } from "../chunk-H355R6U4.js";
7
+ } from "../chunk-VP6IEWIK.js";
8
+ import {
9
+ parseViewBox,
10
+ svgFrameMarkup,
11
+ svgViewBox
12
+ } from "../chunk-DVVQRZJ5.js";
8
13
  import {
9
14
  EASES,
10
15
  SCRAMBLE_MS,
@@ -49,6 +54,7 @@ export {
49
54
  morphPaths,
50
55
  morphSequence,
51
56
  parseSvg,
57
+ parseViewBox,
52
58
  remap,
53
59
  stepData,
54
60
  stepProgress,
@@ -56,9 +62,11 @@ export {
56
62
  stepVariant,
57
63
  svgDuration,
58
64
  svgFrame,
65
+ svgFrameMarkup,
59
66
  svgMotionIssues,
60
67
  svgOpeningTag,
61
68
  svgView,
69
+ svgViewBox,
62
70
  writtenText
63
71
  };
64
72
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pixerate/flair",
3
- "version": "0.14.0",
3
+ "version": "0.15.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",
@@ -38,6 +38,10 @@
38
38
  "types": "./dist/vector/index.d.ts",
39
39
  "import": "./dist/vector/index.js"
40
40
  },
41
+ "./react": {
42
+ "types": "./dist/react/index.d.ts",
43
+ "import": "./dist/react/index.js"
44
+ },
41
45
  "./node": {
42
46
  "types": "./dist/node.d.ts",
43
47
  "import": "./dist/node.js"
@@ -57,25 +61,34 @@
57
61
  "effects",
58
62
  "generative",
59
63
  "editor",
60
- "ai-agents"
64
+ "ai-agents",
65
+ "react"
61
66
  ],
62
67
  "dependencies": {
63
68
  "commander": "^12.0.0",
64
69
  "gifenc": "^1.0.3"
65
70
  },
66
71
  "peerDependencies": {
67
- "@pixerate/editor": ">=0.29.0 <1"
72
+ "@pixerate/editor": ">=0.29.0 <1",
73
+ "react": ">=18"
68
74
  },
69
75
  "peerDependenciesMeta": {
70
76
  "@pixerate/editor": {
71
77
  "optional": true
78
+ },
79
+ "react": {
80
+ "optional": true
72
81
  }
73
82
  },
74
83
  "devDependencies": {
75
84
  "@changesets/cli": "^2.27.12",
76
85
  "@pixerate/editor": "^0.29.0",
77
86
  "@types/node": "^24.19.2",
87
+ "@types/react": "^19.3.0",
88
+ "@types/react-dom": "^19.3.0",
78
89
  "jsdom": "^30.1.3",
90
+ "react": "^19.3.1",
91
+ "react-dom": "^19.3.1",
79
92
  "tsup": "^8.5",
80
93
  "typescript": "^5.9",
81
94
  "vitest": "^4.1.11"