@pixerate/editor 0.266.2 → 0.267.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.
Files changed (111) hide show
  1. package/dist/agent/index.cjs +2 -2
  2. package/dist/agent/index.js +1 -1
  3. package/dist/animation-editor/controller.d.cts +8 -0
  4. package/dist/animation-editor/controller.d.ts +8 -0
  5. package/dist/animation-editor/effect-tools.d.cts +1 -1
  6. package/dist/animation-editor/effect-tools.d.ts +1 -1
  7. package/dist/animation-editor/index.cjs +172 -105
  8. package/dist/animation-editor/index.js +91 -24
  9. package/dist/brushes/index.cjs +59 -59
  10. package/dist/brushes/index.js +5 -5
  11. package/dist/brushes/profiles.d.cts +6 -1
  12. package/dist/brushes/profiles.d.ts +6 -1
  13. package/dist/{brushstrokeRender-FSUWXUZY.cjs → brushstrokeRender-L7JYRR2R.cjs} +16 -16
  14. package/dist/{brushstrokeRender-KD453OBX.js → brushstrokeRender-NLFPEBGI.js} +4 -4
  15. package/dist/canvas/brushTypes.d.cts +12 -0
  16. package/dist/canvas/brushTypes.d.ts +12 -0
  17. package/dist/canvas/brushstroke.d.cts +1 -1
  18. package/dist/canvas/brushstroke.d.ts +1 -1
  19. package/dist/canvas/drawController.d.cts +19 -4
  20. package/dist/canvas/drawController.d.ts +19 -4
  21. package/dist/canvas/index.cjs +144 -105
  22. package/dist/canvas/index.js +46 -7
  23. package/dist/{chunk-XORJ7UZO.cjs → chunk-3VHH6V67.cjs} +13 -12
  24. package/dist/{chunk-T2LDTEXK.js → chunk-4IDUYB45.js} +2217 -56
  25. package/dist/chunk-7UKFXXWL.js +802 -0
  26. package/dist/chunk-ADMRNWR7.js +340 -0
  27. package/dist/{chunk-CIJBSUM5.js → chunk-AGNUD5BI.js} +2 -2
  28. package/dist/{chunk-WLUVZKVD.cjs → chunk-DT4YQUGT.cjs} +32 -32
  29. package/dist/{chunk-DXYHQ2VN.js → chunk-EF7LZAXQ.js} +1 -1
  30. package/dist/chunk-EXB2EGBE.cjs +802 -0
  31. package/dist/{chunk-4ODRXQRW.js → chunk-EYSHTYLG.js} +1 -1
  32. package/dist/{chunk-R44Y3EFS.js → chunk-FGJHJIMN.js} +8 -336
  33. package/dist/{chunk-AQZQWXEU.cjs → chunk-G7NHE2VD.cjs} +35 -35
  34. package/dist/{chunk-XC6DPRYI.js → chunk-GSTSZPSR.js} +154 -949
  35. package/dist/{chunk-VRK322ZC.cjs → chunk-HIO6E7LC.cjs} +2 -2
  36. package/dist/{chunk-TOID45I2.cjs → chunk-J2TNIZ55.cjs} +1 -1
  37. package/dist/{chunk-YHDHFJUC.cjs → chunk-J5VQYK7T.cjs} +217 -1012
  38. package/dist/{chunk-3C33YTNN.js → chunk-JGWVZPT6.js} +2 -2
  39. package/dist/{chunk-ACFSFUQH.js → chunk-JL6YH5WD.js} +4 -0
  40. package/dist/{chunk-3SBLVGOM.cjs → chunk-LA5Y4ETA.cjs} +23 -23
  41. package/dist/{chunk-MVUQSK5J.cjs → chunk-LHPEG5AU.cjs} +107 -435
  42. package/dist/{chunk-DOZ6F2K2.js → chunk-NSETJI74.js} +3 -2
  43. package/dist/{chunk-XRXFVRGY.cjs → chunk-OKHKA43L.cjs} +2364 -203
  44. package/dist/{chunk-LK4SXL3V.js → chunk-OSEXT7JL.js} +1 -1
  45. package/dist/{chunk-PE6YJMQT.cjs → chunk-PFHJS4HE.cjs} +20 -19
  46. package/dist/{chunk-7KNW3WXZ.cjs → chunk-QEVLRLUN.cjs} +63 -0
  47. package/dist/{chunk-OTN6VB5S.cjs → chunk-RDFHWAHL.cjs} +5 -1
  48. package/dist/{chunk-6JL2D5SG.js → chunk-VE6UKYQ2.js} +3 -2
  49. package/dist/{chunk-RFJZGTHA.cjs → chunk-XVOP3CGQ.cjs} +9 -9
  50. package/dist/{chunk-EZOJBP4D.js → chunk-YIC6MAJ2.js} +1 -1
  51. package/dist/chunk-YZWM6ZIP.cjs +340 -0
  52. package/dist/{chunk-472INMWH.js → chunk-ZA7L5YJB.js} +63 -0
  53. package/dist/commands/builtins.d.cts +12 -1
  54. package/dist/commands/builtins.d.ts +12 -1
  55. package/dist/commands/index.cjs +2 -2
  56. package/dist/commands/index.js +1 -1
  57. package/dist/image-editor/controller.d.cts +1 -1
  58. package/dist/image-editor/controller.d.ts +1 -1
  59. package/dist/image-editor/index.cjs +837 -833
  60. package/dist/image-editor/index.js +105 -101
  61. package/dist/paint/index.cjs +5 -3
  62. package/dist/paint/index.js +46 -44
  63. package/dist/paint-editor/controller.d.cts +5 -3
  64. package/dist/paint-editor/controller.d.ts +5 -3
  65. package/dist/paint-editor/index.cjs +832 -2295
  66. package/dist/paint-editor/index.js +285 -1748
  67. package/dist/paint-editor/path-samples.d.cts +2 -0
  68. package/dist/paint-editor/path-samples.d.ts +2 -0
  69. package/dist/paint-editor/presence.d.cts +20 -1
  70. package/dist/paint-editor/presence.d.ts +20 -1
  71. package/dist/stickers/helpers.d.cts +2 -0
  72. package/dist/stickers/helpers.d.ts +2 -0
  73. package/dist/stickers/index.cjs +41 -35
  74. package/dist/stickers/index.js +22 -16
  75. package/dist/stickers/types.d.cts +4 -2
  76. package/dist/stickers/types.d.ts +4 -2
  77. package/dist/vector/backdrop.d.cts +13 -0
  78. package/dist/vector/backdrop.d.ts +13 -0
  79. package/dist/vector/brushstroke.d.cts +54 -7
  80. package/dist/vector/brushstroke.d.ts +54 -7
  81. package/dist/vector/brushstrokeMedia.d.cts +96 -0
  82. package/dist/vector/brushstrokeMedia.d.ts +96 -0
  83. package/dist/vector/controller.d.cts +17 -3
  84. package/dist/vector/controller.d.ts +17 -3
  85. package/dist/vector/index.cjs +1846 -1386
  86. package/dist/vector/index.d.cts +2 -0
  87. package/dist/vector/index.d.ts +2 -0
  88. package/dist/vector/index.js +517 -57
  89. package/dist/vector/render.d.cts +6 -0
  90. package/dist/vector/render.d.ts +6 -0
  91. package/dist/vector/types.d.cts +14 -0
  92. package/dist/vector/types.d.ts +14 -0
  93. package/package.json +1 -1
  94. package/skills/pixerate-animation-editor/SKILL.md +1 -0
  95. package/skills/pixerate-brushes/SKILL.md +2 -2
  96. package/skills/pixerate-brushes-design/SKILL.md +7 -4
  97. package/skills/pixerate-brushes-design/evals/port-to-vector.json +8 -8
  98. package/skills/pixerate-canvas/SKILL.md +11 -1
  99. package/skills/pixerate-image-editor/SKILL.md +19 -64
  100. package/skills/pixerate-image-editor/references/color-management.md +2 -1
  101. package/skills/pixerate-image-editor/references/free-transform.md +12 -0
  102. package/skills/pixerate-image-editor/references/layer-effects.md +10 -0
  103. package/skills/pixerate-image-editor/references/painting.md +17 -0
  104. package/skills/pixerate-image-editor/references/photoshop-files.md +1 -1
  105. package/skills/pixerate-image-editor/references/shapes-and-type.md +14 -0
  106. package/skills/pixerate-image-editor/references/smart-objects.md +10 -0
  107. package/skills/pixerate-paint-editor/SKILL.md +8 -4
  108. package/skills/pixerate-paint-editor/references/wet-media.md +9 -0
  109. package/skills/pixerate-vector/SKILL.md +16 -6
  110. package/skills/pixerate-vector/references/best-practices.md +1 -0
  111. package/skills/pixerate-vector/references/commands.md +19 -0
@@ -1,6 +1,6 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2;
2
2
 
3
- var _chunkAQZQWXEUcjs = require('../chunk-AQZQWXEU.cjs');
3
+ var _chunkG7NHE2VDcjs = require('../chunk-G7NHE2VD.cjs');
4
4
 
5
5
 
6
6
 
@@ -39,9 +39,9 @@ var _chunk557BDWKOcjs = require('../chunk-557BDWKO.cjs');
39
39
 
40
40
 
41
41
 
42
- var _chunkXRXFVRGYcjs = require('../chunk-XRXFVRGY.cjs');
43
- require('../chunk-RFJZGTHA.cjs');
44
- require('../chunk-OTN6VB5S.cjs');
42
+ var _chunkOKHKA43Lcjs = require('../chunk-OKHKA43L.cjs');
43
+ require('../chunk-XVOP3CGQ.cjs');
44
+ require('../chunk-RDFHWAHL.cjs');
45
45
  require('../chunk-CVFAAZXE.cjs');
46
46
 
47
47
 
@@ -74,6 +74,7 @@ var _chunkPY4GWSE2cjs = require('../chunk-PY4GWSE2.cjs');
74
74
 
75
75
  var _chunkL2JTLW6Bcjs = require('../chunk-L2JTLW6B.cjs');
76
76
  require('../chunk-WOFXZ3XU.cjs');
77
+ require('../chunk-J5VQYK7T.cjs');
77
78
  require('../chunk-PXDIAYB6.cjs');
78
79
  require('../chunk-FQPUF2W2.cjs');
79
80
  require('../chunk-3K6HWEXZ.cjs');
@@ -705,7 +706,7 @@ function smoothMotionTimes(points, start, duration, pacing = "even") {
705
706
  function motionTextLayout(nodes, id) {
706
707
  const group = _optionalChain([nodes, 'access', _5 => _5.get, 'call', _6 => _6(id), 'optionalAccess', _7 => _7.node]);
707
708
  if (!group || group.type !== "group") return null;
708
- const letters = _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, group).map((p) => ({ id: p.id, b: _optionalChain([nodes, 'access', _8 => _8.get, 'call', _9 => _9(p.id), 'optionalAccess', _10 => _10.bounds]) })).filter((l) => !!l.b && l.b.width + l.b.height > 0);
709
+ const letters = _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, group).map((p) => ({ id: p.id, b: _optionalChain([nodes, 'access', _8 => _8.get, 'call', _9 => _9(p.id), 'optionalAccess', _10 => _10.bounds]) })).filter((l) => !!l.b && l.b.width + l.b.height > 0);
709
710
  if (!letters.length) return null;
710
711
  const lines = [];
711
712
  for (const l of [...letters].sort((a, c) => a.b.y + a.b.height / 2 - (c.b.y + c.b.height / 2))) {
@@ -790,21 +791,21 @@ function indexMotionNodes(nodes) {
790
791
  const out = /* @__PURE__ */ new Map();
791
792
  const walk = (list, parentWorld, ancestors) => {
792
793
  for (const node of list) {
793
- const local = _chunkXRXFVRGYcjs.vectorNodeBounds.call(void 0, node);
794
- const bounds = _chunkXRXFVRGYcjs.vectorNodeBounds.call(void 0, node, parentWorld);
794
+ const local = _chunkOKHKA43Lcjs.vectorNodeBounds.call(void 0, node);
795
+ const bounds = _chunkOKHKA43Lcjs.vectorNodeBounds.call(void 0, node, parentWorld);
795
796
  const center = local ? { x: local.x + local.width / 2, y: local.y + local.height / 2 } : { x: 0, y: 0 };
796
797
  if (!out.has(node.id)) out.set(node.id, { node, ancestors, parentWorld, center, bounds, box: local });
797
- if (node.type === "group") walk(node.children, _chunkXRXFVRGYcjs.multiplyMatrices.call(void 0, _chunkXRXFVRGYcjs.nodeMatrix.call(void 0, node), parentWorld), [...ancestors, node.id]);
798
+ if (node.type === "group") walk(node.children, _chunkOKHKA43Lcjs.multiplyMatrices.call(void 0, _chunkOKHKA43Lcjs.nodeMatrix.call(void 0, node), parentWorld), [...ancestors, node.id]);
798
799
  }
799
800
  };
800
- walk(nodes, _chunkXRXFVRGYcjs.IDENTITY_MATRIX, []);
801
+ walk(nodes, _chunkOKHKA43Lcjs.IDENTITY_MATRIX, []);
801
802
  indexCache.set(nodes, out);
802
803
  return out;
803
804
  }
804
805
  var solid = (paint) => typeof paint === "string" && paint !== "none" ? paint : void 0;
805
806
  function firstPaint(node, key) {
806
807
  if (node.type === "path") return solid(node[key]);
807
- for (const p of _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, node)) {
808
+ for (const p of _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, node)) {
808
809
  const s = solid(p[key]);
809
810
  if (s) return s;
810
811
  }
@@ -812,7 +813,7 @@ function firstPaint(node, key) {
812
813
  }
813
814
  function strokeReach(node) {
814
815
  let reach = 0;
815
- for (const p of node.type === "path" ? [node] : _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, node)) {
816
+ for (const p of node.type === "path" ? [node] : _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, node)) {
816
817
  if (p.stroke == null || p.stroke === "none") continue;
817
818
  const width = _nullishCoalesce(p.strokeWidth, () => ( 1));
818
819
  reach = Math.max(reach, p.strokeAlign === "outside" ? width : p.strokeAlign === "inside" ? 0 : width / 2);
@@ -882,7 +883,7 @@ function motionRestValue(entry, property, artwork) {
882
883
  case "stroke":
883
884
  return _nullishCoalesce((node && firstPaint(node, property)), () => ( "transparent"));
884
885
  case "strokeWidth": {
885
- const path = _optionalChain([node, 'optionalAccess', _13 => _13.type]) === "path" ? node : node ? _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, node)[0] : void 0;
886
+ const path = _optionalChain([node, 'optionalAccess', _13 => _13.type]) === "path" ? node : node ? _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, node)[0] : void 0;
886
887
  return _nullishCoalesce(_optionalChain([path, 'optionalAccess', _14 => _14.strokeWidth]), () => ( 1));
887
888
  }
888
889
  case "shape":
@@ -993,12 +994,12 @@ function resolveMotionCamera(camera, scene) {
993
994
  const r = camera;
994
995
  return { x: r.x, y: r.y, width: r.width, height: r.height };
995
996
  }
996
- function motionPathLength(node, parentWorld = _chunkXRXFVRGYcjs.IDENTITY_MATRIX) {
997
+ function motionPathLength(node, parentWorld = _chunkOKHKA43Lcjs.IDENTITY_MATRIX) {
997
998
  let longest = 0;
998
- const paths = node.type === "path" ? [node] : _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, node);
999
+ const paths = node.type === "path" ? [node] : _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, node);
999
1000
  for (const p of paths) {
1000
1001
  try {
1001
- longest = Math.max(longest, _chunkGF2RBSDMcjs.bezierPathLength.call(void 0, _chunkXRXFVRGYcjs.vectorPathWorldBezier.call(void 0, p, parentWorld, { effects: false })));
1002
+ longest = Math.max(longest, _chunkGF2RBSDMcjs.bezierPathLength.call(void 0, _chunkOKHKA43Lcjs.vectorPathWorldBezier.call(void 0, p, parentWorld, { effects: false })));
1002
1003
  } catch (e2) {
1003
1004
  }
1004
1005
  }
@@ -1274,12 +1275,12 @@ function compileMotionScene(scene) {
1274
1275
  const order2 = _nullishCoalesce(o.order, () => ( "together"));
1275
1276
  const pace = _nullishCoalesce(o.pace, () => ( "time"));
1276
1277
  if (order2 === "together" && pace === "time") return null;
1277
- const paths = entry.node.type === "path" ? [entry.node] : _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, entry.node);
1278
+ const paths = entry.node.type === "path" ? [entry.node] : _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, entry.node);
1278
1279
  let list = paths.map((p) => {
1279
1280
  const at = nodes.get(p.id);
1280
1281
  let first = { x: 0, y: 0 };
1281
1282
  try {
1282
- const m = _chunkXRXFVRGYcjs.vectorPathWorldBezier.call(void 0, p, _nullishCoalesce(_optionalChain([at, 'optionalAccess', _42 => _42.parentWorld]), () => ( _chunkXRXFVRGYcjs.IDENTITY_MATRIX)), { effects: false })[0];
1283
+ const m = _chunkOKHKA43Lcjs.vectorPathWorldBezier.call(void 0, p, _nullishCoalesce(_optionalChain([at, 'optionalAccess', _42 => _42.parentWorld]), () => ( _chunkOKHKA43Lcjs.IDENTITY_MATRIX)), { effects: false })[0];
1283
1284
  if (m && m.type === "M") first = { x: m.x, y: m.y };
1284
1285
  } catch (e3) {
1285
1286
  }
@@ -1391,17 +1392,17 @@ function compileMotionScene(scene) {
1391
1392
  let dx = _nullishCoalesce(_optionalChain([command3, 'access', _45 => _45.by, 'optionalAccess', _46 => _46.x]), () => ( 0));
1392
1393
  let dy = _nullishCoalesce(_optionalChain([command3, 'access', _47 => _47.by, 'optionalAccess', _48 => _48.y]), () => ( 0));
1393
1394
  if (command3.to) {
1394
- const inv = _chunkXRXFVRGYcjs.invertMatrix.call(void 0, entry.parentWorld);
1395
- const target = _chunkXRXFVRGYcjs.applyMatrix.call(void 0, inv, command3.to);
1395
+ const inv = _chunkOKHKA43Lcjs.invertMatrix.call(void 0, entry.parentWorld);
1396
+ const target = _chunkOKHKA43Lcjs.applyMatrix.call(void 0, inv, command3.to);
1396
1397
  dx = target.x - (entry.center.x + num2("x"));
1397
1398
  dy = target.y - (entry.center.y + num2("y"));
1398
1399
  }
1399
1400
  if (_optionalChain([command3, 'access', _49 => _49.via, 'optionalAccess', _50 => _50.length])) {
1400
- const inv = _chunkXRXFVRGYcjs.invertMatrix.call(void 0, entry.parentWorld);
1401
+ const inv = _chunkOKHKA43Lcjs.invertMatrix.call(void 0, entry.parentWorld);
1401
1402
  const x0 = num2("x");
1402
1403
  const y0 = num2("y");
1403
1404
  const add = command3.blend === "add";
1404
- const offsets = [{ x: 0, y: 0 }, ...command3.via.map((p) => _chunkXRXFVRGYcjs.applyMatrix.call(void 0, inv, p)).map((p) => ({ x: p.x - entry.center.x - x0, y: p.y - entry.center.y - y0 })), { x: dx, y: dy }];
1405
+ const offsets = [{ x: 0, y: 0 }, ...command3.via.map((p) => _chunkOKHKA43Lcjs.applyMatrix.call(void 0, inv, p)).map((p) => ({ x: p.x - entry.center.x - x0, y: p.y - entry.center.y - y0 })), { x: dx, y: dy }];
1405
1406
  const times = _optionalChain([command3, 'access', _51 => _51.times, 'optionalAccess', _52 => _52.length]) === command3.via.length ? [start, ...command3.times.map((f) => start + f * (end - start)), end] : smoothMotionTimes(offsets, start, end - start, _nullishCoalesce(command3.pacing, () => ( "even")));
1406
1407
  for (const axis of ["x", "y"]) {
1407
1408
  const base = add ? 0 : axis === "x" ? x0 : y0;
@@ -2024,13 +2025,13 @@ function morphBetween(a, b) {
2024
2025
  let inner = morphCache.get(a);
2025
2026
  if (!inner) morphCache.set(a, inner = /* @__PURE__ */ new WeakMap());
2026
2027
  let morph = inner.get(b);
2027
- if (!morph) inner.set(b, morph = _chunkAQZQWXEUcjs.createVectorMorph.call(void 0, a, b, { id: a.id }));
2028
+ if (!morph) inner.set(b, morph = _chunkG7NHE2VDcjs.createVectorMorph.call(void 0, a, b, { id: a.id }));
2028
2029
  return morph;
2029
2030
  }
2030
2031
  function shapeIn(entry, shape) {
2031
2032
  if (shape === entry) return entry.node;
2032
- const m = _chunkXRXFVRGYcjs.multiplyMatrices.call(void 0, _chunkXRXFVRGYcjs.multiplyMatrices.call(void 0, _chunkXRXFVRGYcjs.nodeMatrix.call(void 0, shape.node), shape.parentWorld), _chunkXRXFVRGYcjs.invertMatrix.call(void 0, entry.parentWorld));
2033
- return { ...shape.node, ..._chunkXRXFVRGYcjs.isIdentityMatrix.call(void 0, m) ? { transform: void 0 } : { transform: m } };
2033
+ const m = _chunkOKHKA43Lcjs.multiplyMatrices.call(void 0, _chunkOKHKA43Lcjs.multiplyMatrices.call(void 0, _chunkOKHKA43Lcjs.nodeMatrix.call(void 0, shape.node), shape.parentWorld), _chunkOKHKA43Lcjs.invertMatrix.call(void 0, entry.parentWorld));
2034
+ return { ...shape.node, ..._chunkOKHKA43Lcjs.isIdentityMatrix.call(void 0, m) ? { transform: void 0 } : { transform: m } };
2034
2035
  }
2035
2036
  function shapeAt(entry, timeline, nodes, time) {
2036
2037
  const track = timeline.tracks.get(motionTrackKey(entry.node.id, "shape"));
@@ -2050,7 +2051,7 @@ function shapeAt(entry, timeline, nodes, time) {
2050
2051
  function motionFollowRoute(entry, path) {
2051
2052
  if (!path || path.node.type !== "path") return null;
2052
2053
  try {
2053
- return _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkXRXFVRGYcjs.vectorPathWorldBezier.call(void 0, path.node, path.parentWorld, { effects: false }), _chunkXRXFVRGYcjs.invertMatrix.call(void 0, entry.parentWorld));
2054
+ return _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkOKHKA43Lcjs.vectorPathWorldBezier.call(void 0, path.node, path.parentWorld, { effects: false }), _chunkOKHKA43Lcjs.invertMatrix.call(void 0, entry.parentWorld));
2054
2055
  } catch (e6) {
2055
2056
  return null;
2056
2057
  }
@@ -2084,9 +2085,9 @@ function motionNodeOffset(entry, timeline, time, nodes = indexMotionNodes([entry
2084
2085
  const scaleX = read("scaleX", 1);
2085
2086
  const scaleY = read("scaleY", 1);
2086
2087
  const c = entry.center;
2087
- let matrix = _chunkXRXFVRGYcjs.multiplyMatrices.call(void 0, _chunkXRXFVRGYcjs.multiplyMatrices.call(void 0, _chunkXRXFVRGYcjs.scaleMatrix.call(void 0, scaleX, scaleY, c), _chunkXRXFVRGYcjs.rotateMatrix.call(void 0, rotation, c)), _chunkXRXFVRGYcjs.translateMatrix.call(void 0, dx, dy));
2088
+ let matrix = _chunkOKHKA43Lcjs.multiplyMatrices.call(void 0, _chunkOKHKA43Lcjs.multiplyMatrices.call(void 0, _chunkOKHKA43Lcjs.scaleMatrix.call(void 0, scaleX, scaleY, c), _chunkOKHKA43Lcjs.rotateMatrix.call(void 0, rotation, c)), _chunkOKHKA43Lcjs.translateMatrix.call(void 0, dx, dy));
2088
2089
  const along = follow ? followAt(entry, timeline, nodes, time) : null;
2089
- if (along) matrix = _chunkXRXFVRGYcjs.multiplyMatrices.call(void 0, matrix, _chunkXRXFVRGYcjs.multiplyMatrices.call(void 0, _chunkXRXFVRGYcjs.multiplyMatrices.call(void 0, _chunkXRXFVRGYcjs.translateMatrix.call(void 0, -c.x, -c.y), _chunkXRXFVRGYcjs.rotateMatrix.call(void 0, along.angle)), _chunkXRXFVRGYcjs.translateMatrix.call(void 0, along.x, along.y)));
2090
+ if (along) matrix = _chunkOKHKA43Lcjs.multiplyMatrices.call(void 0, matrix, _chunkOKHKA43Lcjs.multiplyMatrices.call(void 0, _chunkOKHKA43Lcjs.multiplyMatrices.call(void 0, _chunkOKHKA43Lcjs.translateMatrix.call(void 0, -c.x, -c.y), _chunkOKHKA43Lcjs.rotateMatrix.call(void 0, along.angle)), _chunkOKHKA43Lcjs.translateMatrix.call(void 0, along.x, along.y)));
2090
2091
  return { matrix, dx, dy, rotation, scaleX, scaleY, follow: along };
2091
2092
  }
2092
2093
  function motionNodeClips(id, timeline, time) {
@@ -2153,7 +2154,7 @@ function motionFrameAt(scene, time, options = {}) {
2153
2154
  const start = Math.min(1, Math.max(0, typeof drawStart === "number" ? drawStart : 0));
2154
2155
  const end = Math.min(1, Math.max(0, typeof drawEnd === "number" ? drawEnd : 1));
2155
2156
  if (start > 0 || end < 1) {
2156
- const trim = _chunkXRXFVRGYcjs.createVectorEffect.call(void 0, "trim", MOTION_DRAW_EFFECT_ID, { start: tidy(start * 100), end: tidy(end * 100) });
2157
+ const trim = _chunkOKHKA43Lcjs.createVectorEffect.call(void 0, "trim", MOTION_DRAW_EFFECT_ID, { start: tidy(start * 100), end: tidy(end * 100) });
2157
2158
  p = { ...p, effects: [trim, ...(_nullishCoalesce(p.effects, () => ( []))).filter((e) => e.id !== MOTION_DRAW_EFFECT_ID)] };
2158
2159
  }
2159
2160
  }
@@ -2167,8 +2168,8 @@ function motionFrameAt(scene, time, options = {}) {
2167
2168
  if (o >= 1) delete out.opacity;
2168
2169
  }
2169
2170
  const offset = options.offsets === false ? null : motionNodeOffset(entry, timeline, time, nodes);
2170
- if (offset && !_chunkXRXFVRGYcjs.isIdentityMatrix.call(void 0, offset.matrix)) {
2171
- const m = _chunkXRXFVRGYcjs.multiplyMatrices.call(void 0, _chunkXRXFVRGYcjs.nodeMatrix.call(void 0, out), offset.matrix).map(tidy);
2171
+ if (offset && !_chunkOKHKA43Lcjs.isIdentityMatrix.call(void 0, offset.matrix)) {
2172
+ const m = _chunkOKHKA43Lcjs.multiplyMatrices.call(void 0, _chunkOKHKA43Lcjs.nodeMatrix.call(void 0, out), offset.matrix).map(tidy);
2172
2173
  out = { ...out, transform: m };
2173
2174
  }
2174
2175
  return out;
@@ -2189,8 +2190,8 @@ function motionFrameToSvg(scene, time, options = {}) {
2189
2190
  const wrap = { ...options.wrap };
2190
2191
  for (const [id, clips] of Object.entries(frame.clips))
2191
2192
  wrap[id] = [..._nullishCoalesce(wrap[id], () => ( [])), ...clips.map((clip, i) => ({ clip: { id: `${prefix}reveal-${id}-${i}`, shape: clip.shape, attrs: motionClipAttrs(clip) } }))];
2192
- if (!motionSceneHasLayers(scene)) return withCameraViewEffects(withViewBox(_chunkXRXFVRGYcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap }), frame.camera), frame.view, frame.camera, prefix);
2193
- const art = _chunkXRXFVRGYcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap, background: false });
2193
+ if (!motionSceneHasLayers(scene)) return withCameraViewEffects(withViewBox(_chunkOKHKA43Lcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap }), frame.camera), frame.view, frame.camera, prefix);
2194
+ const art = _chunkOKHKA43Lcjs.vectorDocumentToSvg.call(void 0, frame.document, { ...options, wrap, background: false });
2194
2195
  let svg = withViewBox(withMotionShotLayers(art, scene, time, frame.camera, options.layers, options.background !== false), frame.camera);
2195
2196
  const transition = options.transitions === false ? null : motionTransitionAt(scene, time);
2196
2197
  if (transition) {
@@ -2381,8 +2382,8 @@ function visibleAt(timeline, id, time, node) {
2381
2382
  if (Array.isArray(rect) && (rect[2] <= 1e-4 || rect[3] <= 1e-4)) return false;
2382
2383
  const circle = clip("clipCircle");
2383
2384
  if (Array.isArray(circle) && circle[2] <= 1e-4) return false;
2384
- const hasFill = node.type === "path" ? !!node.fill && node.fill !== "none" : _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, node).some((p) => p.fill && p.fill !== "none");
2385
- const drawn = num2("drawEnd", 1) > 0.01 && (node.type === "path" || _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, node).length === 0 || _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, node).some((p) => {
2385
+ const hasFill = node.type === "path" ? !!node.fill && node.fill !== "none" : _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, node).some((p) => p.fill && p.fill !== "none");
2386
+ const drawn = num2("drawEnd", 1) > 0.01 && (node.type === "path" || _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, node).length === 0 || _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, node).some((p) => {
2386
2387
  const v = trackValue(timeline.tracks.get(motionTrackKey(p.id, "drawEnd")), time);
2387
2388
  return typeof v !== "number" || v > 0.01;
2388
2389
  }));
@@ -2469,7 +2470,7 @@ function checkMotionScene(scene) {
2469
2470
  }
2470
2471
  for (const id of targets) {
2471
2472
  const node = nodes.get(id).node;
2472
- const paths = node.type === "path" ? [node] : _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, node);
2473
+ const paths = node.type === "path" ? [node] : _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, node);
2473
2474
  if (paths.some((p) => p[key] !== void 0 && p[key] !== null && typeof p[key] !== "string"))
2474
2475
  issues.push(_chunkDGWOGQJ5cjs.motionIssue.call(void 0, "paint-not-color", `"${id}" has a gradient ${key}; it switches to ${color} at the end instead of blending.`, { ...where, ids: [id] }));
2475
2476
  }
@@ -2482,7 +2483,7 @@ function checkMotionScene(scene) {
2482
2483
  else
2483
2484
  for (const id of targets) {
2484
2485
  const node = nodes.get(id).node;
2485
- const paths = node.type === "path" ? [node] : _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, node);
2486
+ const paths = node.type === "path" ? [node] : _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, node);
2486
2487
  if (paths.some((p) => typeof p[key] !== "string"))
2487
2488
  issues.push(_chunkDGWOGQJ5cjs.motionIssue.call(void 0, "paint-not-color", `"${id}" has a gradient or no ${key}, so a colour pulse cannot tint it; give it a solid ${key} or pulse the ${key === "fill" ? "stroke" : "fill"}.`, { ...where, ids: [id] }));
2488
2489
  }
@@ -2927,7 +2928,7 @@ function motionNodePose(scene, id, time) {
2927
2928
  if (!entry) throw new Error(`There is no element ${_chunkDGWOGQJ5cjs.namedWithSuggestion.call(void 0, id, [...indexMotionNodes(scene.artwork.nodes).keys()])} in the artwork.`);
2928
2929
  const timeline = compileMotionScene(scene);
2929
2930
  const drawn = indexMotionNodes(motionFrameAt(scene, time).document.nodes).get(id);
2930
- const centre = _chunkXRXFVRGYcjs.applyMatrix.call(void 0, entry.parentWorld, { x: entry.center.x + motionPropertyValue(timeline, id, "x", time), y: entry.center.y + motionPropertyValue(timeline, id, "y", time) });
2931
+ const centre = _chunkOKHKA43Lcjs.applyMatrix.call(void 0, entry.parentWorld, { x: entry.center.x + motionPropertyValue(timeline, id, "x", time), y: entry.center.y + motionPropertyValue(timeline, id, "y", time) });
2931
2932
  const paint = (property) => _nullishCoalesce(trackValue(timeline.tracks.get(motionTrackKey(id, property)), time), () => ( motionRestValue(entry, property, scene.artwork)));
2932
2933
  const fill = paint("fill");
2933
2934
  const stroke = paint("stroke");
@@ -3274,7 +3275,7 @@ function toFlairSvgMotion(scene, options = {}) {
3274
3275
  raw: (t) => transformAt(t, true)
3275
3276
  });
3276
3277
  }
3277
- const paths = node.type === "path" ? [node] : _chunkXRXFVRGYcjs.collectPathNodes.call(void 0, node);
3278
+ const paths = node.type === "path" ? [node] : _chunkOKHKA43Lcjs.collectPathNodes.call(void 0, node);
3278
3279
  for (const path of paths) {
3279
3280
  if (pathsSeen.has(path.id)) continue;
3280
3281
  pathsSeen.add(path.id);
@@ -3296,7 +3297,7 @@ function toFlairSvgMotion(scene, options = {}) {
3296
3297
  if (shapeSegments.length) {
3297
3298
  if (node.type !== "path") notes.push(`"${id}" is a group: its morph or effect animation is not exported (Flair tweens one path's "d").`);
3298
3299
  else {
3299
- const inverse = _chunkXRXFVRGYcjs.invertMatrix.call(void 0, _chunkXRXFVRGYcjs.nodeMatrix.call(void 0, node));
3300
+ const inverse = _chunkOKHKA43Lcjs.invertMatrix.call(void 0, _chunkOKHKA43Lcjs.nodeMatrix.call(void 0, node));
3300
3301
  channels.push({
3301
3302
  id,
3302
3303
  kind: "attr",
@@ -3305,9 +3306,9 @@ function toFlairSvgMotion(scene, options = {}) {
3305
3306
  exact: () => false,
3306
3307
  value: (t) => {
3307
3308
  const frame = motionFrameAt(scene, t, { draw: false, offsets: false });
3308
- const now = _chunkXRXFVRGYcjs.expandVectorAppearance.call(void 0, _optionalChain([indexMotionNodes, 'call', _151 => _151(frame.document.nodes), 'access', _152 => _152.get, 'call', _153 => _153(id), 'optionalAccess', _154 => _154.node]));
3309
+ const now = _chunkOKHKA43Lcjs.expandVectorAppearance.call(void 0, _optionalChain([indexMotionNodes, 'call', _151 => _151(frame.document.nodes), 'access', _152 => _152.get, 'call', _153 => _153(id), 'optionalAccess', _154 => _154.node]));
3309
3310
  if (!now || now.type !== "path") return "";
3310
- const bezier = _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkXRXFVRGYcjs.vectorPathWorldBezier.call(void 0, now, _chunkXRXFVRGYcjs.IDENTITY_MATRIX, { effects: false }), inverse);
3311
+ const bezier = _chunkGF2RBSDMcjs.transformBezierPath.call(void 0, _chunkOKHKA43Lcjs.vectorPathWorldBezier.call(void 0, now, _chunkOKHKA43Lcjs.IDENTITY_MATRIX, { effects: false }), inverse);
3311
3312
  return _chunkGF2RBSDMcjs.bezierPathToSvg.call(void 0, bezier, { precision: Math.min(precision, 2) });
3312
3313
  }
3313
3314
  });
@@ -3447,7 +3448,7 @@ function toFlairSvgMotion(scene, options = {}) {
3447
3448
  }
3448
3449
  if (scene.motionBlur) notes.push("Motion blur is drawn on the stage only; Flair plays the scene sharp.");
3449
3450
  if (trigger && (_nullishCoalesce(scene.loop, () => ( "none"))) !== "none") notes.push(`The scene plays on ${trigger}, so its loop does not apply in Flair.`);
3450
- let svg = _chunkXRXFVRGYcjs.vectorDocumentToSvg.call(void 0, { ...scene.artwork, nodes: _chunkXRXFVRGYcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) }, { pretty: false, precision, wrap });
3451
+ let svg = _chunkOKHKA43Lcjs.vectorDocumentToSvg.call(void 0, { ...scene.artwork, nodes: _chunkOKHKA43Lcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) }, { pretty: false, precision, wrap });
3451
3452
  if (routes.length) svg = svg.replace(/^(<svg[^>]*>)/, `$1<defs>${routes.join("")}</defs>`);
3452
3453
  let motion = { svg, animate };
3453
3454
  if (_optionalChain([scene, 'access', _160 => _160.controls, 'optionalAccess', _161 => _161.length])) {
@@ -3545,14 +3546,14 @@ function easingOf(ease, fallback) {
3545
3546
  return fallback;
3546
3547
  }
3547
3548
  function poseOf(value, entry) {
3548
- const t = _chunkXRXFVRGYcjs.parseSvgTransform.call(void 0, String(value));
3549
- const o = _chunkXRXFVRGYcjs.multiplyMatrices.call(void 0, _nullishCoalesce(_chunkXRXFVRGYcjs.invertMatrix.call(void 0, _chunkXRXFVRGYcjs.nodeMatrix.call(void 0, entry.node)), () => ( [1, 0, 0, 1, 0, 0])), t);
3549
+ const t = _chunkOKHKA43Lcjs.parseSvgTransform.call(void 0, String(value));
3550
+ const o = _chunkOKHKA43Lcjs.multiplyMatrices.call(void 0, _nullishCoalesce(_chunkOKHKA43Lcjs.invertMatrix.call(void 0, _chunkOKHKA43Lcjs.nodeMatrix.call(void 0, entry.node)), () => ( [1, 0, 0, 1, 0, 0])), t);
3550
3551
  const sx = Math.hypot(o[0], o[1]);
3551
3552
  if (!(sx > 1e-9)) return null;
3552
3553
  const sy = (o[0] * o[3] - o[1] * o[2]) / sx;
3553
3554
  if (Math.abs(o[2] + o[1] / sx * sy) > 1e-6 || Math.abs(o[3] - o[0] / sx * sy) > 1e-6) return null;
3554
3555
  const c = entry.center;
3555
- const moved = _chunkXRXFVRGYcjs.applyMatrix.call(void 0, o, c);
3556
+ const moved = _chunkOKHKA43Lcjs.applyMatrix.call(void 0, o, c);
3556
3557
  return { dx: moved.x - c.x, dy: moved.y - c.y, rotation: Math.atan2(o[1], o[0]) * 180 / Math.PI, sx, sy };
3557
3558
  }
3558
3559
  var near = (a, b, eps = 1e-6) => Math.abs(a - b) < eps;
@@ -3637,7 +3638,7 @@ function fromFlairSvgMotion(input, options = {}) {
3637
3638
  const notes = [];
3638
3639
  if (!input || typeof input.svg !== "string") throw new Error('Give a Flair SvgMotion: { svg: "<svg \u2026>", animate: [ \u2026 ] }.');
3639
3640
  const { motion, controls } = resolvePlaceholders(input, notes);
3640
- const artwork = _chunkXRXFVRGYcjs.parseVectorSvg.call(void 0, motion.svg);
3641
+ const artwork = _chunkOKHKA43Lcjs.parseVectorSvg.call(void 0, motion.svg);
3641
3642
  const nodes = indexMotionNodes(artwork.nodes);
3642
3643
  const byStep = /* @__PURE__ */ new Map();
3643
3644
  for (const anim of _nullishCoalesce(motion.animate, () => ( []))) {
@@ -3884,9 +3885,9 @@ function toLottie(scene, options = {}) {
3884
3885
  const items = [];
3885
3886
  const shapeSegments = [...timeline.tracks.entries()].filter(([k]) => k.startsWith(`${path.id}\0`) && (k.endsWith("\0shape") || k.includes("\0effect:"))).flatMap(([, v]) => v);
3886
3887
  const geometryAt = (t) => {
3887
- if (!shapeSegments.length) return _chunkXRXFVRGYcjs.vectorPathWorldBezier.call(void 0, path);
3888
+ if (!shapeSegments.length) return _chunkOKHKA43Lcjs.vectorPathWorldBezier.call(void 0, path);
3888
3889
  const now = _optionalChain([indexMotionNodes, 'call', _170 => _170(motionFrameAt(scene, t, { draw: false, offsets: false }).document.nodes), 'access', _171 => _171.get, 'call', _172 => _172(path.id), 'optionalAccess', _173 => _173.node]);
3889
- return now && now.type === "path" ? _chunkXRXFVRGYcjs.vectorPathWorldBezier.call(void 0, _chunkXRXFVRGYcjs.expandVectorAppearances.call(void 0, [now])[0]) : _chunkXRXFVRGYcjs.vectorPathWorldBezier.call(void 0, path);
3890
+ return now && now.type === "path" ? _chunkOKHKA43Lcjs.vectorPathWorldBezier.call(void 0, _chunkOKHKA43Lcjs.expandVectorAppearances.call(void 0, [now])[0]) : _chunkOKHKA43Lcjs.vectorPathWorldBezier.call(void 0, path);
3890
3891
  };
3891
3892
  const rest = lottieContours(_chunkGF2RBSDMcjs.toBezierPath.call(void 0, geometryAt(0)), round4);
3892
3893
  rest.forEach((contour, n2) => {
@@ -3959,13 +3960,13 @@ function toLottie(scene, options = {}) {
3959
3960
  const innerTr = STATIC_TR();
3960
3961
  if (node.type === "path") inner = [...pathShapes(node)];
3961
3962
  else if (node.type === "text" || node.type === "instance") {
3962
- const drawn = _chunkXRXFVRGYcjs.expandVectorAppearance.call(void 0, node);
3963
+ const drawn = _chunkOKHKA43Lcjs.expandVectorAppearance.call(void 0, node);
3963
3964
  inner = drawn.type === "path" ? [...pathShapes(drawn)] : drawn.children.filter((c) => c.type === "path").reverse().flatMap((c) => [...pathShapes(c)]);
3964
- notes.push(`"${node.id}": text is exported as its outlines${_chunkXRXFVRGYcjs.vectorTextHasOutlines.call(void 0, ) ? "" : " (glyph boxes: set an outline text shaper for real glyphs)"}.`);
3965
+ notes.push(`"${node.id}": text is exported as its outlines${_chunkOKHKA43Lcjs.vectorTextHasOutlines.call(void 0, ) ? "" : " (glyph boxes: set an outline text shaper for real glyphs)"}.`);
3965
3966
  } else {
3966
3967
  inner = shown(node.children).reverse().map(nodeGroup);
3967
- const m = _chunkXRXFVRGYcjs.nodeMatrix.call(void 0, node);
3968
- if (m !== _chunkXRXFVRGYcjs.IDENTITY_MATRIX) {
3968
+ const m = _chunkOKHKA43Lcjs.nodeMatrix.call(void 0, node);
3969
+ if (m !== _chunkOKHKA43Lcjs.IDENTITY_MATRIX) {
3969
3970
  const parts = staticParts(m);
3970
3971
  if (!parts) notes.push(`"${node.id}": its transform skews, which is not exported; it is drawn without the skew.`);
3971
3972
  else {
@@ -3978,7 +3979,7 @@ function toLottie(scene, options = {}) {
3978
3979
  const body = { ty: "gr", nm: `${node.id} (own)`, it: [...inner, innerTr] };
3979
3980
  return { ty: "gr", nm: _nullishCoalesce(node.name, () => ( node.id)), it: [body, poseTransform(entry)] };
3980
3981
  };
3981
- const artwork = { ...scene.artwork, nodes: _chunkXRXFVRGYcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) };
3982
+ const artwork = { ...scene.artwork, nodes: _chunkOKHKA43Lcjs.expandVectorAppearances.call(void 0, scene.artwork.nodes) };
3982
3983
  const content = shown(artwork.nodes).reverse().map(nodeGroup);
3983
3984
  if (artwork.background && rgba(artwork.background))
3984
3985
  content.push({ ty: "gr", nm: "Background", it: [{ ty: "rc", nm: "Background", p: { a: 0, k: [artwork.width / 2, artwork.height / 2] }, s: { a: 0, k: [artwork.width, artwork.height] }, r: { a: 0, k: 0 } }, { ty: "fl", c: { a: 0, k: rgba(artwork.background).map(round4) }, o: { a: 0, k: 100 }, r: 1 }, STATIC_TR()] });
@@ -4077,11 +4078,11 @@ function preset(prst, w, h) {
4077
4078
  const poly = (pts) => [{ closed: true, anchors: pts.map(([x, y]) => ({ x, y })) }];
4078
4079
  switch (prst) {
4079
4080
  case "rect":
4080
- return [_chunkXRXFVRGYcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4081
+ return [_chunkOKHKA43Lcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4081
4082
  case "roundRect":
4082
- return [_chunkXRXFVRGYcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h }, Math.min(w, h) * 0.16667)];
4083
+ return [_chunkOKHKA43Lcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h }, Math.min(w, h) * 0.16667)];
4083
4084
  case "ellipse":
4084
- return [_chunkXRXFVRGYcjs.ellipseSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4085
+ return [_chunkOKHKA43Lcjs.ellipseSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4085
4086
  case "triangle":
4086
4087
  return poly([[w / 2, 0], [w, h], [0, h]]);
4087
4088
  case "rtTriangle":
@@ -4189,7 +4190,7 @@ function shapes(ctx, tree, map) {
4189
4190
  let subpaths = cust ? custom(cust, w, h) : prst ? preset(prst, w, h) : null;
4190
4191
  if (!subpaths) {
4191
4192
  if (prst) ctx.notes.push(`"${name}" is a ${prst}, drawn as its bounding rectangle.`);
4192
- subpaths = [_chunkXRXFVRGYcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4193
+ subpaths = [_chunkOKHKA43Lcjs.rectSubpath.call(void 0, { x: 0, y: 0, width: w, height: h })];
4193
4194
  }
4194
4195
  const style = kid(el, "style");
4195
4196
  const fill = kid(spPr, "noFill") ? null : _nullishCoalesce(colour(ctx, kid(spPr, "solidFill")), () => ( (el.localName === "cxnSp" ? null : colour(ctx, kid(style, "fillRef")))));
@@ -4578,7 +4579,7 @@ function nextMotionEffectInstance(scene) {
4578
4579
  walk(scene.artwork.nodes);
4579
4580
  for (let i = 1; ; i++) if (!used.has(`fx${i}`)) return `fx${i}`;
4580
4581
  }
4581
- var motionArtworkSvg = (artwork) => _chunkXRXFVRGYcjs.vectorDocumentToSvg.call(void 0, artwork);
4582
+ var motionArtworkSvg = (artwork) => _chunkOKHKA43Lcjs.vectorDocumentToSvg.call(void 0, artwork);
4582
4583
  var tag = (commands, source) => commands.map((c) => c.type === "wait" ? c : { ...c, source });
4583
4584
  function motionCommandsFromEffect(artwork, motion, source) {
4584
4585
  const imported = fromFlairSvgMotion({ svg: motionArtworkSvg(artwork), animate: [..._nullishCoalesce(motion.animate, () => ( []))] });
@@ -4901,6 +4902,25 @@ var AnimationEditorController = (_class2 = class {
4901
4902
  return { scene: { ...this.scene, shots }, label: `Apply ${d.name}`, instance, notes };
4902
4903
  });
4903
4904
  }
4905
+ async resolveVectorPath(artwork, d, path, controlName) {
4906
+ const controls = _chunkL2JTLW6Bcjs.pathControlsOf.call(void 0, d);
4907
+ if (!controls.length) throw new Error(`"${d.id}" does not draw along a path. Find one that does with search_effects accepts ["path"] (kind vector).`);
4908
+ const control = _nullishCoalesce(controlName, () => ( (controls.length === 1 ? controls[0] : void 0)));
4909
+ if (!control) throw new Error(`"${d.id}" has several path controls (${controls.join(", ")}); pass control.`);
4910
+ if (!controls.includes(control)) throw new Error(`"${control}" is not a path control of "${d.id}"; its path controls are ${controls.join(", ")}.`);
4911
+ if ("node" in path) {
4912
+ const entry = indexMotionNodes(artwork.nodes).get(path.node);
4913
+ if (!entry) throw new Error(`There is no node "${path.node}"; find_animation_elements lists the artwork's nodes.`);
4914
+ if (entry.node.type !== "path") throw new Error(`Node "${path.node}" is a ${entry.node.type}, not a path; pass a path node (find_animation_elements shows each node's type).`);
4915
+ const value2 = _chunkGF2RBSDMcjs.bezierPathToSvg.call(void 0, _chunkOKHKA43Lcjs.vectorPathWorldBezier.call(void 0, entry.node, entry.parentWorld, { effects: false }));
4916
+ return { control, value: value2, place: "viewBox" };
4917
+ }
4918
+ const provider = this.effects.require();
4919
+ if (!provider.pathFromText) throw new Error(`The effects provider "${provider.id}" cannot write words as a path; pass a path node instead.`);
4920
+ if (typeof path.text !== "string" || !path.text.trim()) throw new Error("text is empty; pass the words to write.");
4921
+ const value = await provider.pathFromText(path.text, { ...path.font ? { font: path.font } : {}, ...path.align ? { align: path.align } : {} });
4922
+ return { control, value };
4923
+ }
4904
4924
  /**
4905
4925
  * Adds a provider vector effect (one with its own picture: a lower third, a loader): its SVG as
4906
4926
  * an artwork group (id: the instance) fitted into `box` (default the whole artwork), and its
@@ -4912,25 +4932,9 @@ var AnimationEditorController = (_class2 = class {
4912
4932
  let given = options.values;
4913
4933
  let place = options.box;
4914
4934
  if (options.path) {
4915
- const controls = _chunkL2JTLW6Bcjs.pathControlsOf.call(void 0, d);
4916
- if (!controls.length) throw new Error(`"${d.id}" does not draw along a path. Find one that does with search_effects accepts ["path"] (kind vector).`);
4917
- const control = _nullishCoalesce(options.control, () => ( (controls.length === 1 ? controls[0] : void 0)));
4918
- if (!control) throw new Error(`"${d.id}" has several path controls (${controls.join(", ")}); pass control.`);
4919
- if (!controls.includes(control)) throw new Error(`"${control}" is not a path control of "${d.id}"; its path controls are ${controls.join(", ")}.`);
4920
- let value;
4921
- if ("node" in options.path) {
4922
- const entry = indexMotionNodes(this.scene.artwork.nodes).get(options.path.node);
4923
- if (!entry) throw new Error(`There is no node "${options.path.node}"; find_animation_elements lists the artwork's nodes.`);
4924
- if (entry.node.type !== "path") throw new Error(`Node "${options.path.node}" is a ${entry.node.type}, not a path; pass a path node (find_animation_elements shows each node's type).`);
4925
- value = _chunkGF2RBSDMcjs.bezierPathToSvg.call(void 0, _chunkXRXFVRGYcjs.vectorPathWorldBezier.call(void 0, entry.node, entry.parentWorld, { effects: false }));
4926
- place ??= "viewBox";
4927
- } else {
4928
- const provider = this.effects.require();
4929
- if (!provider.pathFromText) throw new Error(`The effects provider "${provider.id}" cannot write words as a path; pass a path node instead.`);
4930
- if (typeof options.path.text !== "string" || !options.path.text.trim()) throw new Error("text is empty; pass the words to write.");
4931
- value = await provider.pathFromText(options.path.text, { ...options.path.font ? { font: options.path.font } : {}, ...options.path.align ? { align: options.path.align } : {} });
4932
- }
4933
- given = { ..._nullishCoalesce(given, () => ( {})), [control]: value };
4935
+ const resolved = await this.resolveVectorPath(this.scene.artwork, d, options.path, options.control);
4936
+ if (resolved.place) place ??= resolved.place;
4937
+ given = { ..._nullishCoalesce(given, () => ( {})), [resolved.control]: resolved.value };
4934
4938
  }
4935
4939
  const values = _chunkL2JTLW6Bcjs.resolveEffectValues.call(void 0, d, given);
4936
4940
  const instance = _nullishCoalesce(options.instance, () => ( nextMotionEffectInstance(this.scene)));
@@ -4940,6 +4944,33 @@ var AnimationEditorController = (_class2 = class {
4940
4944
  return { scene: { ...this.scene, artwork: { ...this.scene.artwork, nodes: [...this.scene.artwork.nodes, group] }, shots: [...this.scene.shots, ...shots] }, label: `Add ${d.name}`, instance, notes };
4941
4945
  });
4942
4946
  }
4947
+ /**
4948
+ * Sets an applied vector effect's path from a path node in the artwork (landing on the node at
4949
+ * scale 1) or words written by the provider (keeping where the picture was placed). One undo step.
4950
+ */
4951
+ setVectorEffectPath(instance, path, options = {}) {
4952
+ return this.effectEdit(async () => {
4953
+ const was = motionSceneEffects(this.scene).find((e) => e.instance === instance);
4954
+ if (!was) throw new Error(`There is no applied effect "${instance}"; list_applied_effects lists them.`);
4955
+ if (was.kind !== "vector") throw new Error(`"${instance}" is a motion effect, not a vector effect.`);
4956
+ const d = await this.describeFor(was.effect, ["vector"]);
4957
+ const { scene: bare } = withoutMotionEffect(this.scene, instance);
4958
+ const { control, value, place } = await this.resolveVectorPath(bare.artwork, d, path, options.control);
4959
+ const merged = { ...was.values, [control]: value };
4960
+ const provider = this.effects.require();
4961
+ const source = { instance, effect: d.id, provider: provider.id, name: d.name, values: merged };
4962
+ const motion = await provider.applyVectorEffect(d.id, motionArtworkSvg(bare.artwork), merged);
4963
+ const { group, shots, notes } = motionPartsFromVectorEffect(bare.artwork, motion, source, place);
4964
+ const old = this.scene.artwork.nodes.find((n2) => n2.id === instance);
4965
+ const index = this.scene.artwork.nodes.findIndex((n2) => n2.id === instance);
4966
+ const nodes = [...bare.artwork.nodes];
4967
+ nodes.splice(Math.max(0, index), 0, !place && _optionalChain([old, 'optionalAccess', _230 => _230.transform]) ? { ...group, transform: old.transform } : group);
4968
+ const at = this.scene.shots.findIndex((s) => was.shots.includes(s.id));
4969
+ const kept = bare.shots;
4970
+ const nextShots = [...kept.slice(0, Math.max(0, at)), ...shots, ...kept.slice(Math.max(0, at))];
4971
+ return { scene: { ...bare, artwork: { ...bare.artwork, nodes }, shots: nextShots }, label: `Set ${d.name} path`, instance, notes };
4972
+ });
4973
+ }
4943
4974
  /**
4944
4975
  * Makes an applied effect again with new `values` (merged over its own; `null` resets a
4945
4976
  * control), in the same place. One undo step.
@@ -4966,7 +4997,7 @@ var AnimationEditorController = (_class2 = class {
4966
4997
  const { group, shots: shots2, notes: notes2 } = motionPartsFromVectorEffect(bare.artwork, motion2, source);
4967
4998
  const index = this.scene.artwork.nodes.findIndex((n2) => n2.id === instance);
4968
4999
  const nodes = [...bare.artwork.nodes];
4969
- nodes.splice(Math.max(0, index), 0, _optionalChain([old, 'optionalAccess', _230 => _230.transform]) ? { ...group, transform: old.transform } : group);
5000
+ nodes.splice(Math.max(0, index), 0, _optionalChain([old, 'optionalAccess', _231 => _231.transform]) ? { ...group, transform: old.transform } : group);
4970
5001
  const at = this.scene.shots.findIndex((s) => was.shots.includes(s.id));
4971
5002
  const kept = bare.shots;
4972
5003
  const nextShots = [...kept.slice(0, Math.max(0, at)), ...shots2, ...kept.slice(Math.max(0, at))];
@@ -4977,7 +5008,7 @@ var AnimationEditorController = (_class2 = class {
4977
5008
  let shots = bare.shots;
4978
5009
  if (place && shots.some((s) => s.id === place.shot)) shots = shots.map((s) => s.id === place.shot ? { ...s, run: [...s.run.slice(0, place.index), ...commands, ...s.run.slice(place.index)] } : s);
4979
5010
  else {
4980
- const at = this.scene.shots.findIndex((s) => s.id === _optionalChain([place, 'optionalAccess', _231 => _231.shot]));
5011
+ const at = this.scene.shots.findIndex((s) => s.id === _optionalChain([place, 'optionalAccess', _232 => _232.shot]));
4981
5012
  shots = [...shots.slice(0, Math.max(0, at)), { id: instance, label: d.name, run: commands }, ...shots.slice(Math.max(0, at))];
4982
5013
  }
4983
5014
  return { scene: { ...bare, shots }, label: `Change ${d.name}`, instance, notes };
@@ -5031,7 +5062,7 @@ var AnimationEditorController = (_class2 = class {
5031
5062
  const found = this.scene.shots.find((s) => s.id === shot);
5032
5063
  if (!found) return this.refuse(`There is no shot "${shot}"; the shots are ${this.scene.shots.map((s) => `"${s.id}"`).join(", ") || "none yet"}.`);
5033
5064
  const field = _chunkL2JTLW6Bcjs.cameraMoveField.call(void 0, role);
5034
- if (_optionalChain([found, 'access', _232 => _232.camera, 'optionalAccess', _233 => _233[field]]) === void 0) return this.refuse(`Shot "${shot}" has no camera "${field}" move to clear${_optionalChain([found, 'access', _234 => _234.camera, 'optionalAccess', _235 => _235[field === "in" ? "during" : "in"]]) !== void 0 ? `; it has a "${field === "in" ? "during" : "in"}" move (role ${role === "hold" ? "transition" : "hold"})` : ""}.`);
5065
+ if (_optionalChain([found, 'access', _233 => _233.camera, 'optionalAccess', _234 => _234[field]]) === void 0) return this.refuse(`Shot "${shot}" has no camera "${field}" move to clear${_optionalChain([found, 'access', _235 => _235.camera, 'optionalAccess', _236 => _236[field === "in" ? "during" : "in"]]) !== void 0 ? `; it has a "${field === "in" ? "during" : "in"}" move (role ${role === "hold" ? "transition" : "hold"})` : ""}.`);
5035
5066
  const rest = { ...found.camera };
5036
5067
  delete rest[field];
5037
5068
  const keep = motionCameraFramed(rest) || rest.in !== void 0 || rest.during !== void 0;
@@ -5041,7 +5072,7 @@ var AnimationEditorController = (_class2 = class {
5041
5072
  }
5042
5073
  cameraMoveResult(shot, role, move) {
5043
5074
  const timing = compileMotionScene(this.scene).shots.find((s) => s.id === shot);
5044
- const camera = _nullishCoalesce(_optionalChain([this, 'access', _236 => _236.scene, 'access', _237 => _237.shots, 'access', _238 => _238.find, 'call', _239 => _239((s) => s.id === shot), 'optionalAccess', _240 => _240.camera]), () => ( null));
5075
+ const camera = _nullishCoalesce(_optionalChain([this, 'access', _237 => _237.scene, 'access', _238 => _238.shots, 'access', _239 => _239.find, 'call', _240 => _240((s) => s.id === shot), 'optionalAccess', _241 => _241.camera]), () => ( null));
5045
5076
  const window = role === "transition" ? { start: timing.start, end: timing.commandsStart } : { start: timing.commandsEnd, end: timing.end };
5046
5077
  const notes = [];
5047
5078
  if (move && role === "transition" && timing.index === 0) notes.push('This is the first shot, which cuts to its framing, so its "in" move does not play; it plays from the second shot on.');
@@ -5112,7 +5143,7 @@ var AnimationEditorController = (_class2 = class {
5112
5143
  viewScene() {
5113
5144
  const r = this.recording;
5114
5145
  if (!r) return this.scene;
5115
- if (_optionalChain([r, 'access', _241 => _241.preview, 'optionalAccess', _242 => _242.count]) === r.samples.length) return r.preview.scene;
5146
+ if (_optionalChain([r, 'access', _242 => _242.preview, 'optionalAccess', _243 => _243.count]) === r.samples.length) return r.preview.scene;
5116
5147
  let scene = this.scene;
5117
5148
  if (r.samples.length) {
5118
5149
  try {
@@ -5261,7 +5292,7 @@ var AnimationEditorController = (_class2 = class {
5261
5292
  const r = this.apply({ op: "update_shot", shot, set: { transition: resolved } }, `Transition ${_nullishCoalesce(resolved.name, () => ( resolved.effect))}`, { merge: options.merge });
5262
5293
  if (!r.ok) return r;
5263
5294
  const camera = this.scene.shots.find((s) => s.id === shot).camera;
5264
- return this.layerResult(shot, void 0, _optionalChain([camera, 'optionalAccess', _243 => _243.in]) === void 0 ? ["With no camera move in, the camera cuts to this shot's framing and the transition does the move."] : []);
5295
+ return this.layerResult(shot, void 0, _optionalChain([camera, 'optionalAccess', _244 => _244.in]) === void 0 ? ["With no camera move in, the camera cuts to this shot's framing and the transition does the move."] : []);
5265
5296
  }
5266
5297
  /** Removes a shot's transition. One undo step. Works without a provider. */
5267
5298
  clearShotTransition(shot) {
@@ -5375,13 +5406,13 @@ var AnimationEditorController = (_class2 = class {
5375
5406
  }
5376
5407
  /** Records the drag's pose with the pointer at `point` (document units). */
5377
5408
  updateRecordGesture(point) {
5378
- const g = _optionalChain([this, 'access', _244 => _244.recording, 'optionalAccess', _245 => _245.gesture]);
5409
+ const g = _optionalChain([this, 'access', _245 => _245.recording, 'optionalAccess', _246 => _246.gesture]);
5379
5410
  if (g) this.recordGesture(g.pose, point);
5380
5411
  }
5381
5412
  /** Ends the stage drag (the take keeps recording). */
5382
5413
  endRecordGesture() {
5383
5414
  const r = this.recording;
5384
- if (!_optionalChain([r, 'optionalAccess', _246 => _246.gesture])) return;
5415
+ if (!_optionalChain([r, 'optionalAccess', _247 => _247.gesture])) return;
5385
5416
  r.gesture = null;
5386
5417
  this.notify();
5387
5418
  }
@@ -5395,7 +5426,7 @@ var AnimationEditorController = (_class2 = class {
5395
5426
  this.recordSample(g.node, { scaleX: Math.max(0.01, pose.scaleX * f), scaleY: Math.max(0.01, pose.scaleY * f) });
5396
5427
  } else {
5397
5428
  const turn = (Math.atan2(point.y - c.y, point.x - c.x) - Math.atan2(g.from.y - c.y, g.from.x - c.x)) * (180 / Math.PI);
5398
- const was = _nullishCoalesce(_optionalChain([this, 'access', _247 => _247.recording, 'access', _248 => _248.samples, 'access', _249 => _249.filter, 'call', _250 => _250((s) => s.node === g.node && s.rotation !== void 0), 'access', _251 => _251.at, 'call', _252 => _252(-1), 'optionalAccess', _253 => _253.rotation]), () => ( pose.rotation));
5429
+ const was = _nullishCoalesce(_optionalChain([this, 'access', _248 => _248.recording, 'access', _249 => _249.samples, 'access', _250 => _250.filter, 'call', _251 => _251((s) => s.node === g.node && s.rotation !== void 0), 'access', _252 => _252.at, 'call', _253 => _253(-1), 'optionalAccess', _254 => _254.rotation]), () => ( pose.rotation));
5399
5430
  let next = pose.rotation + turn;
5400
5431
  next += 360 * Math.round((was - next) / 360);
5401
5432
  this.recordSample(g.node, { rotation: next });
@@ -5489,7 +5520,7 @@ function elementsOf(args) {
5489
5520
  if (Array.isArray(args.ops)) {
5490
5521
  for (const op of args.ops) {
5491
5522
  fromShot(op);
5492
- if (Array.isArray(_optionalChain([op, 'optionalAccess', _254 => _254.shots]))) op.shots.forEach(fromShot);
5523
+ if (Array.isArray(_optionalChain([op, 'optionalAccess', _255 => _255.shots]))) op.shots.forEach(fromShot);
5493
5524
  }
5494
5525
  }
5495
5526
  return out.slice(0, 4);
@@ -5671,7 +5702,7 @@ var MOTION_COMMAND_SCHEMA = {
5671
5702
  oneOf: MOTION_COMMAND_TYPES.map((type) => MOTION_COMMAND_TYPE_SCHEMAS[type])
5672
5703
  };
5673
5704
  var REF2 = (name, description) => ({ $ref: `#/$defs/${name}`, ...description ? { description } : {} });
5674
- var firstSentence = (text) => _nullishCoalesce(_optionalChain([/^.*?[.;](?=\s|$)/, 'access', _255 => _255.exec, 'call', _256 => _256(text), 'optionalAccess', _257 => _257[0]]), () => ( text));
5705
+ var firstSentence = (text) => _nullishCoalesce(_optionalChain([/^.*?[.;](?=\s|$)/, 'access', _256 => _256.exec, 'call', _257 => _257(text), 'optionalAccess', _258 => _258[0]]), () => ( text));
5675
5706
  var COMMAND_TYPE_LINES = MOTION_COMMAND_TYPES.map((type) => `${type}: ${firstSentence(_nullishCoalesce(MOTION_COMMAND_TYPE_SCHEMAS[type].description, () => ( "")))}`);
5676
5707
  var EASE_COMPACT = {
5677
5708
  description: `Easing: a preset, or a curve { "type": "cubic-bezier", x1, y1, x2, y2 }, { "type": "spring", stiffness, damping, mass, velocity } (spring presets are Figma's; with no "duration" it lasts until it settles) or { "type": "elastic", amplitude, period, mode }. Default: ease-out for entrances, ease-in-out for moves.`,
@@ -6080,9 +6111,9 @@ function createAnimationEditorToolProvider(controller, options = {}) {
6080
6111
  handler: ({ from = 0, to, limit = 200 }) => {
6081
6112
  const s = scene();
6082
6113
  const timeline = compileMotionScene(s);
6083
- const words = _nullishCoalesce(_optionalChain([s, 'access', _258 => _258.narration, 'optionalAccess', _259 => _259.words]), () => ( []));
6114
+ const words = _nullishCoalesce(_optionalChain([s, 'access', _259 => _259.narration, 'optionalAccess', _260 => _260.words]), () => ( []));
6084
6115
  const end = _nullishCoalesce(to, () => ( Math.max(timeline.duration, words.length ? _nullishCoalesce(words[words.length - 1].end, () => ( words[words.length - 1].start)) : 0)));
6085
- const shotAt = (ms2) => _optionalChain([timeline, 'access', _260 => _260.shots, 'access', _261 => _261.find, 'call', _262 => _262((x) => ms2 >= x.start && ms2 < x.end), 'optionalAccess', _263 => _263.id]);
6116
+ const shotAt = (ms2) => _optionalChain([timeline, 'access', _261 => _261.shots, 'access', _262 => _262.find, 'call', _263 => _263((x) => ms2 >= x.start && ms2 < x.end), 'optionalAccess', _264 => _264.id]);
6086
6117
  const beats = [];
6087
6118
  if (s.beat && s.beat.bpm > 0) {
6088
6119
  const first = Math.max(0, Math.ceil(motionBeatAt(s.beat, from).beat - 1e-9));
@@ -6183,7 +6214,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
6183
6214
  handler: ({ svg }) => {
6184
6215
  let artwork;
6185
6216
  try {
6186
- artwork = _chunkXRXFVRGYcjs.parseVectorSvg.call(void 0, svg);
6217
+ artwork = _chunkOKHKA43Lcjs.parseVectorSvg.call(void 0, svg);
6187
6218
  } catch (error) {
6188
6219
  throw new Error(`The SVG could not be read: ${error.message}. Nothing was changed.`);
6189
6220
  }
@@ -6458,7 +6489,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
6458
6489
  inputSchema: object({ shot: SHOT_ID, commands: { type: "array", items: REF2("command"), minItems: 1, description: "Commands to add." }, at: { type: "integer", minimum: 0, description: "Index in the run (default: the end)." } }, ["shot", "commands"]),
6459
6490
  annotations: { title: "Add commands to a shot", ...WRITE },
6460
6491
  handler: ({ shot, commands, at }) => {
6461
- const before = _nullishCoalesce(_optionalChain([scene, 'call', _264 => _264(), 'access', _265 => _265.shots, 'access', _266 => _266.find, 'call', _267 => _267((s) => s.id === shot), 'optionalAccess', _268 => _268.run, 'access', _269 => _269.length]), () => ( 0));
6492
+ const before = _nullishCoalesce(_optionalChain([scene, 'call', _265 => _265(), 'access', _266 => _266.shots, 'access', _267 => _267.find, 'call', _268 => _268((s) => s.id === shot), 'optionalAccess', _269 => _269.run, 'access', _270 => _270.length]), () => ( 0));
6462
6493
  const first = _nullishCoalesce(at, () => ( before));
6463
6494
  return apply({ op: "add_commands", shot, commands, at }, "Add commands", (s) => {
6464
6495
  const shots = describeMotionShots(s);
@@ -6659,7 +6690,7 @@ var TIMING = /* @__PURE__ */ new Set(["duration", "delay", "stagger", "with", "e
6659
6690
  var COLORS = /* @__PURE__ */ new Set(["fill", "stroke", "color"]);
6660
6691
  var NODES = /* @__PURE__ */ new Set(["into", "path"]);
6661
6692
  function branch(type) {
6662
- return (_nullishCoalesce(MOTION_COMMAND_SCHEMA.oneOf, () => ( []))).find((b) => _optionalChain([b, 'access', _270 => _270.properties, 'optionalAccess', _271 => _271.type, 'optionalAccess', _272 => _272.const]) === type);
6693
+ return (_nullishCoalesce(MOTION_COMMAND_SCHEMA.oneOf, () => ( []))).find((b) => _optionalChain([b, 'access', _271 => _271.properties, 'optionalAccess', _272 => _272.type, 'optionalAccess', _273 => _273.const]) === type);
6663
6694
  }
6664
6695
  function unitOf(type, name) {
6665
6696
  if (name === "duration" || name === "delay" || name === "stagger") return "ms";
@@ -6694,7 +6725,7 @@ function kindOf(name, schema) {
6694
6725
  }
6695
6726
  function motionCommandFields(type) {
6696
6727
  const schema = branch(type);
6697
- if (!_optionalChain([schema, 'optionalAccess', _273 => _273.properties])) return [];
6728
+ if (!_optionalChain([schema, 'optionalAccess', _274 => _274.properties])) return [];
6698
6729
  const required = new Set(_nullishCoalesce(schema.required, () => ( [])));
6699
6730
  const fields2 = Object.entries(schema.properties).filter(([name]) => name !== "type").map(([name, s]) => {
6700
6731
  const kind = kindOf(name, s);
@@ -6751,7 +6782,7 @@ function defaultMotionCommand(type, targets, scene) {
6751
6782
  if (type === "wait") return { type: "wait", duration: 500 };
6752
6783
  if (!targets.length) return { error: "Pick a target first: click an element on the stage." };
6753
6784
  const nodes = [...indexMotionNodes(scene.artwork.nodes).values()];
6754
- const other = (pred) => _optionalChain([nodes, 'access', _274 => _274.find, 'call', _275 => _275((e) => !targets.includes(e.node.id) && pred(e)), 'optionalAccess', _276 => _276.node, 'access', _277 => _277.id]);
6785
+ const other = (pred) => _optionalChain([nodes, 'access', _275 => _275.find, 'call', _276 => _276((e) => !targets.includes(e.node.id) && pred(e)), 'optionalAccess', _277 => _277.node, 'access', _278 => _278.id]);
6755
6786
  const base = { targets: [...targets] };
6756
6787
  switch (type) {
6757
6788
  case "scale":
@@ -6782,8 +6813,8 @@ function defaultMotionCommand(type, targets, scene) {
6782
6813
  }
6783
6814
  case "effect": {
6784
6815
  for (const id of targets) {
6785
- const node = _optionalChain([nodes, 'access', _278 => _278.find, 'call', _279 => _279((e) => e.node.id === id), 'optionalAccess', _280 => _280.node]);
6786
- for (const effect of _nullishCoalesce(_optionalChain([node, 'optionalAccess', _281 => _281.effects]), () => ( []))) {
6816
+ const node = _optionalChain([nodes, 'access', _279 => _279.find, 'call', _280 => _280((e) => e.node.id === id), 'optionalAccess', _281 => _281.node]);
6817
+ for (const effect of _nullishCoalesce(_optionalChain([node, 'optionalAccess', _282 => _282.effects]), () => ( []))) {
6787
6818
  const param = Object.entries(effect.params).find(([, v]) => typeof v === "number");
6788
6819
  if (param) return { type, ...base, effect: effect.id, param: param[0], to: param[1] + 1 };
6789
6820
  }
@@ -6808,11 +6839,11 @@ function motionCommandRows(scene, shotId) {
6808
6839
  return scene.shots[index].run.map((command3, i) => {
6809
6840
  const t = timeline.commands.find((c) => c.shotIndex === index && c.command === i);
6810
6841
  const primitive = motionFlairPrimitive(command3);
6811
- return { index: i, command: command3, summary: motionCommandSummary(command3), start: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _282 => _282.start]), () => ( 0)), end: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _283 => _283.end]), () => ( 0)), ...primitive ? { flairPrimitive: primitive } : {} };
6842
+ return { index: i, command: command3, summary: motionCommandSummary(command3), start: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _283 => _283.start]), () => ( 0)), end: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _284 => _284.end]), () => ( 0)), ...primitive ? { flairPrimitive: primitive } : {} };
6812
6843
  });
6813
6844
  }
6814
6845
  function duplicateMotionCommandEdit(scene, shot, command3) {
6815
- const run = _nullishCoalesce(_optionalChain([scene, 'access', _284 => _284.shots, 'access', _285 => _285.find, 'call', _286 => _286((s) => s.id === shot), 'optionalAccess', _287 => _287.run]), () => ( []));
6846
+ const run = _nullishCoalesce(_optionalChain([scene, 'access', _285 => _285.shots, 'access', _286 => _286.find, 'call', _287 => _287((s) => s.id === shot), 'optionalAccess', _288 => _288.run]), () => ( []));
6816
6847
  return { op: "add_commands", shot, commands: run[command3] ? [structuredClone(run[command3])] : [], at: command3 + 1 };
6817
6848
  }
6818
6849
  var MOTION_EASE_CHOICES = [
@@ -6897,7 +6928,7 @@ function motionCueFromKey(key) {
6897
6928
  function motionCueChoices(scene, limit = 256) {
6898
6929
  const choices = [];
6899
6930
  const s = (ms2) => `${(ms2 / 1e3).toFixed(2)} s`;
6900
- const end = Math.max(compileMotionScene(scene).duration, ..._nullishCoalesce(_optionalChain([scene, 'access', _288 => _288.narration, 'optionalAccess', _289 => _289.words, 'access', _290 => _290.map, 'call', _291 => _291((w) => _nullishCoalesce(w.end, () => ( w.start)))]), () => ( [0]))) + 2e3;
6931
+ const end = Math.max(compileMotionScene(scene).duration, ..._nullishCoalesce(_optionalChain([scene, 'access', _289 => _289.narration, 'optionalAccess', _290 => _290.words, 'access', _291 => _291.map, 'call', _292 => _292((w) => _nullishCoalesce(w.end, () => ( w.start)))]), () => ( [0]))) + 2e3;
6901
6932
  if (scene.beat && scene.beat.bpm > 0) {
6902
6933
  for (let beat = 0; choices.length < limit; beat++) {
6903
6934
  const time = motionBeatTime(scene.beat, beat);
@@ -6907,7 +6938,7 @@ function motionCueChoices(scene, limit = 256) {
6907
6938
  choices.push({ value: `beat:${beat}`, label: `Beat ${beat} (bar ${at.bar}.${at.beatInBar}) \xB7 ${s(time)}`, time });
6908
6939
  }
6909
6940
  }
6910
- _optionalChain([scene, 'access', _292 => _292.narration, 'optionalAccess', _293 => _293.words, 'access', _294 => _294.forEach, 'call', _295 => _295((w, i) => {
6941
+ _optionalChain([scene, 'access', _293 => _293.narration, 'optionalAccess', _294 => _294.words, 'access', _295 => _295.forEach, 'call', _296 => _296((w, i) => {
6911
6942
  if (choices.length < limit * 2) choices.push({ value: `word:${i}`, label: `Word ${i} \u201C${w.text}\u201D \xB7 ${s(w.start)}`, time: w.start });
6912
6943
  })]);
6913
6944
  return choices;
@@ -6916,7 +6947,7 @@ function motionShotCueTime(scene, cue) {
6916
6947
  return cue ? motionCueTime(scene, cue) : void 0;
6917
6948
  }
6918
6949
  function formatMotionNarration(narration) {
6919
- return (_nullishCoalesce(_optionalChain([narration, 'optionalAccess', _296 => _296.words]), () => ( []))).map((w) => `${w.start} ${w.text}`).join("\n");
6950
+ return (_nullishCoalesce(_optionalChain([narration, 'optionalAccess', _297 => _297.words]), () => ( []))).map((w) => `${w.start} ${w.text}`).join("\n");
6920
6951
  }
6921
6952
  function parseMotionNarration(text) {
6922
6953
  const lines = text.split("\n").map((l) => l.trim()).filter(Boolean);
@@ -6959,7 +6990,7 @@ var ROLE = {
6959
6990
  enum: ["transition", "hold"],
6960
6991
  description: `transition: the move the camera gets into the shot with (its camera "in": a glide, whip pan, punch zoom, cut). hold: the move it makes while the shot holds (its camera "during": a Ken Burns drift, a crash zoom), played across the shot's hold.`
6961
6992
  };
6962
- var summary = (e) => ({ id: e.id, name: e.name, role: e.camera.role, durationMs: e.camera.durationMs, ...e.camera.cut !== void 0 ? { cut: e.camera.cut } : {}, ...e.description ? { description: e.description } : {}, ..._optionalChain([e, 'access', _297 => _297.tags, 'optionalAccess', _298 => _298.length]) ? { tags: e.tags } : {} });
6993
+ var summary = (e) => ({ id: e.id, name: e.name, role: e.camera.role, durationMs: e.camera.durationMs, ...e.camera.cut !== void 0 ? { cut: e.camera.cut } : {}, ...e.description ? { description: e.description } : {}, ..._optionalChain([e, 'access', _298 => _298.tags, 'optionalAccess', _299 => _299.length]) ? { tags: e.tags } : {} });
6963
6994
  var done = (r) => {
6964
6995
  if (!r.ok) throw new Error(r.error);
6965
6996
  return { shot: r.shot, camera: r.camera, ...r.window ? { window: r.window } : {}, ...r.notes.length ? { notes: r.notes } : {} };
@@ -7239,7 +7270,7 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
7239
7270
  {
7240
7271
  name: "add_vector_effect",
7241
7272
  title: "Add a vector effect",
7242
- description: 'Adds a provider vector effect that brings its own picture (search_effects with kind vector: lower thirds, loaders, stickers): its SVG becomes an artwork group, fitted into box (default the whole artwork), and its motion becomes shots after the last one. For an effect that draws along a path (search_effects accepts ["path"]: a signature, a route), pass path: { node } to run it along a path node (its outline with every transform applied; the picture then lands on the node at scale 1 unless box is given) or { text } for words the provider writes. Use it instead of follow or draw-on when the effect itself should trace the path. The path is copied when added; add it again after reshaping the node. Change it with update_effect (target and effect: the returned instance) or remove it with remove_effect. One undo step. Returns the instance, the group id and any notes on what could not be carried over.',
7273
+ description: 'Adds a provider vector effect that brings its own picture (search_effects with kind vector: lower thirds, loaders, stickers): its SVG becomes an artwork group, fitted into box (default the whole artwork), and its motion becomes shots after the last one. For an effect that draws along a path (search_effects accepts ["path"]: a signature, a route), pass path: { node } to run it along a path node (its outline with every transform applied; the picture then lands on the node at scale 1 unless box is given) or { text } for words the provider writes. Use it instead of follow or draw-on when the effect itself should trace the path. The path is copied when added; after reshaping the node, give it the path again with set_vector_effect_path. Change it with update_effect (target and effect: the returned instance) or remove it with remove_effect. One undo step. Returns the instance, the group id and any notes on what could not be carried over.',
7243
7274
  inputSchema: {
7244
7275
  type: "object",
7245
7276
  properties: {
@@ -7283,6 +7314,42 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
7283
7314
  if (!r.ok) throw new Error(r.error);
7284
7315
  return { instance: r.effect.instance, group: r.effect.group, effect: info(r.effect), ...r.notes.length ? { notes: r.notes } : {} };
7285
7316
  }
7317
+ },
7318
+ {
7319
+ name: "set_vector_effect_path",
7320
+ title: "Run a vector effect along a path",
7321
+ description: 'Gives a vector effect already added with add_vector_effect (instance: its id from add_vector_effect or list_applied_effects) a new path to draw along, in place: path: { node } runs it along a path node (its outline with every transform applied) and lands the picture on the node at scale 1; { text } writes words with the provider and keeps the picture where it was. Use it after reshaping the node the effect was run along, or to switch between a node and words. To clear the path, call update_effect with the path control set to "". Refuses a motion effect, an effect without a path control, an unknown or non-path node, and a provider that cannot write words, saying what to pass. One undo step. Returns the instance, the control set, its new path data and any notes.',
7322
+ inputSchema: {
7323
+ type: "object",
7324
+ properties: {
7325
+ instance: { type: "string", minLength: 1, description: "The applied vector effect id (add_vector_effect instance, or list_applied_effects)." },
7326
+ path: {
7327
+ type: "object",
7328
+ description: "The path the effect draws along: { node } or { text }.",
7329
+ properties: {
7330
+ node: { type: "string", minLength: 1, description: "A path node id (find_animation_elements)." },
7331
+ text: { type: "string", minLength: 1, description: "Words the provider writes as a single-stroke path." },
7332
+ font: { type: "string", minLength: 1, description: "With text: a single-stroke font the provider offers (default its first)." },
7333
+ align: { type: "string", enum: ["start", "middle", "end"], description: "With text: where the line sits (default start)." }
7334
+ },
7335
+ oneOf: [{ required: ["node"] }, { required: ["text"] }],
7336
+ additionalProperties: false
7337
+ },
7338
+ control: { type: "string", minLength: 1, description: "Which path control takes the path (default the effect's only one; describe_effect pathControls lists them)." }
7339
+ },
7340
+ required: ["instance", "path"],
7341
+ additionalProperties: false
7342
+ },
7343
+ annotations: { title: "Run a vector effect along a path", ...ctx.annotations.write, idempotentHint: true },
7344
+ handler: async (args) => {
7345
+ ctx.requireProvider();
7346
+ if (args.path.node !== void 0 && args.path.text !== void 0) throw new Error("Pass path as { node } or { text }, not both.");
7347
+ const path = args.path.node !== void 0 ? { node: args.path.node } : { text: args.path.text, font: args.path.font, align: args.path.align };
7348
+ const r = await controller.setVectorEffectPath(args.instance, path, { control: args.control });
7349
+ if (!r.ok) throw new Error(r.error);
7350
+ const control = await _asyncNullishCoalesce(args.control, async () => ( _chunkL2JTLW6Bcjs.pathControlsOf.call(void 0, await controller.effectsProvider.describe(r.effect.effect))[0]));
7351
+ return { instance: r.effect.instance, group: r.effect.group, control, value: r.effect.values[control], effect: info(r.effect), ...r.notes.length ? { notes: r.notes } : {} };
7352
+ }
7286
7353
  }
7287
7354
  ]
7288
7355
  }), options.playbackSurface);