@pixerate/editor 0.139.1 → 0.140.1

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 (152) hide show
  1. package/README.md +25 -4
  2. package/dist/agent/formatTools.d.cts +15 -0
  3. package/dist/agent/formatTools.d.ts +15 -0
  4. package/dist/agent/index.cjs +408 -49
  5. package/dist/agent/index.js +375 -16
  6. package/dist/agent/providers.d.cts +5 -3
  7. package/dist/agent/providers.d.ts +5 -3
  8. package/dist/animation-editor/effect-tools.d.cts +1 -1
  9. package/dist/animation-editor/effect-tools.d.ts +1 -1
  10. package/dist/animation-editor/index.cjs +250 -116
  11. package/dist/animation-editor/index.js +228 -94
  12. package/dist/animation-editor/instructions.d.cts +1 -1
  13. package/dist/animation-editor/instructions.d.ts +1 -1
  14. package/dist/animation-editor/parse.d.cts +3 -1
  15. package/dist/animation-editor/parse.d.ts +3 -1
  16. package/dist/animation-editor/tools.d.cts +8 -3
  17. package/dist/animation-editor/tools.d.ts +8 -3
  18. package/dist/bridge/cli.cjs +4 -3
  19. package/dist/bridge/cli.js +3 -2
  20. package/dist/bridge/index.cjs +8 -3
  21. package/dist/bridge/index.d.cts +7 -0
  22. package/dist/bridge/index.d.ts +7 -0
  23. package/dist/bridge/index.js +9 -4
  24. package/dist/bridge/skills.d.cts +9 -0
  25. package/dist/bridge/skills.d.ts +9 -0
  26. package/dist/canvas/effect-tools.d.cts +1 -1
  27. package/dist/canvas/effect-tools.d.ts +1 -1
  28. package/dist/canvas/index.cjs +22 -17
  29. package/dist/canvas/index.js +8 -3
  30. package/dist/chart/file-tools.d.cts +1 -1
  31. package/dist/chart/file-tools.d.ts +1 -1
  32. package/dist/chart/index.cjs +7 -1
  33. package/dist/chart/index.js +7 -1
  34. package/dist/chart/tools.d.cts +1 -1
  35. package/dist/chart/tools.d.ts +1 -1
  36. package/dist/chunk-2BSBFBOA.cjs +46 -0
  37. package/dist/{chunk-SWZTQWY7.js → chunk-2INPJDNY.js} +1 -1
  38. package/dist/{chunk-CCKP4XAN.cjs → chunk-34RQAGWI.cjs} +27 -7
  39. package/dist/{chunk-HXCBQ7A6.cjs → chunk-3AJMR7EG.cjs} +7 -4
  40. package/dist/{chunk-BKMU3V6K.js → chunk-5ED73EC6.js} +8 -1
  41. package/dist/{chunk-NKBUVQJW.cjs → chunk-5WOY52O6.cjs} +15 -15
  42. package/dist/{chunk-VRIR53SW.js → chunk-6GAYGQDC.js} +10 -8
  43. package/dist/{chunk-HZZXBTLB.js → chunk-6IN474P4.js} +25 -5
  44. package/dist/{chunk-KHMVB3SJ.js → chunk-7KWJEYIK.js} +4 -1
  45. package/dist/{chunk-R47NQICB.cjs → chunk-AGCD3EHB.cjs} +47 -10
  46. package/dist/{chunk-6I63VZ45.js → chunk-CXXKJBQZ.js} +5 -1
  47. package/dist/{chunk-6NXVDJDR.cjs → chunk-G43MNQ4C.cjs} +5 -5
  48. package/dist/chunk-HDK3T2QS.cjs +1159 -0
  49. package/dist/chunk-HF5QZS7Z.js +46 -0
  50. package/dist/{chunk-S7I3RI5Z.cjs → chunk-HMGWFXEC.cjs} +27 -24
  51. package/dist/{chunk-6NCBFBXA.js → chunk-IQ6KKXOU.js} +1 -1
  52. package/dist/{chunk-T6Y5FV7G.cjs → chunk-L434J57V.cjs} +10 -8
  53. package/dist/{chunk-UCRL6JEV.cjs → chunk-L5OWG2NA.cjs} +8 -3
  54. package/dist/{chunk-CZRWP6IW.cjs → chunk-N2FGYZ4Q.cjs} +8 -1
  55. package/dist/{chunk-GUPQ5BNA.cjs → chunk-PUR6BZFA.cjs} +112 -111
  56. package/dist/chunk-RB62U6MS.js +1159 -0
  57. package/dist/{chunk-3V746PF4.cjs → chunk-RUZQMYXH.cjs} +4 -1
  58. package/dist/{chunk-HGHXGCKG.cjs → chunk-SVFEVKLF.cjs} +1 -1
  59. package/dist/{chunk-PCNCT4ZY.js → chunk-UMS6YFA6.js} +40 -3
  60. package/dist/{chunk-4LGWAJDI.js → chunk-V5OOP74P.js} +5 -2
  61. package/dist/{chunk-BWT4IWLK.cjs → chunk-VKF3PWKR.cjs} +7 -7
  62. package/dist/{chunk-PQMADRCI.js → chunk-WBJ6BG4R.js} +23 -22
  63. package/dist/{chunk-WIYAOZZU.js → chunk-WHKNYFM2.js} +7 -2
  64. package/dist/{chunk-TBSPPVTT.js → chunk-XCK7QK5D.js} +1 -1
  65. package/dist/{chunk-F652BKMS.cjs → chunk-YN6JKAUE.cjs} +6 -2
  66. package/dist/{chunk-YTGF4TJR.js → chunk-ZLZKGHSZ.js} +5 -2
  67. package/dist/{chunk-USU2FL3N.js → chunk-ZNHB5RG6.js} +1 -1
  68. package/dist/commands/agentTools.d.cts +1 -1
  69. package/dist/commands/agentTools.d.ts +1 -1
  70. package/dist/commands/index.cjs +3 -0
  71. package/dist/commands/index.js +3 -0
  72. package/dist/compare/index.cjs +4 -3
  73. package/dist/compare/index.js +3 -2
  74. package/dist/diagram/index.cjs +3 -0
  75. package/dist/diagram/index.js +3 -0
  76. package/dist/diagram/tools.d.cts +1 -1
  77. package/dist/diagram/tools.d.ts +1 -1
  78. package/dist/effects/index.cjs +32 -32
  79. package/dist/effects/index.js +1 -1
  80. package/dist/effects/tools.d.cts +5 -1
  81. package/dist/effects/tools.d.ts +5 -1
  82. package/dist/export/index.cjs +4 -3
  83. package/dist/export/index.js +3 -2
  84. package/dist/extensions/index.cjs +11 -8
  85. package/dist/extensions/index.d.cts +1 -0
  86. package/dist/extensions/index.d.ts +1 -0
  87. package/dist/extensions/index.js +10 -7
  88. package/dist/extensions/safe-merge-attributes.d.cts +10 -0
  89. package/dist/extensions/safe-merge-attributes.d.ts +10 -0
  90. package/dist/generation/index.cjs +7 -1
  91. package/dist/generation/index.js +7 -1
  92. package/dist/image-editor/index.cjs +25 -18
  93. package/dist/image-editor/index.js +10 -3
  94. package/dist/image-editor/provider-effect-tools.d.cts +1 -1
  95. package/dist/image-editor/provider-effect-tools.d.ts +1 -1
  96. package/dist/image-editor/tools.d.cts +1 -1
  97. package/dist/image-editor/tools.d.ts +1 -1
  98. package/dist/index.cjs +42 -29
  99. package/dist/index.d.cts +1 -0
  100. package/dist/index.d.ts +1 -0
  101. package/dist/index.js +22 -9
  102. package/dist/paint-editor/effect-tools.d.cts +1 -1
  103. package/dist/paint-editor/effect-tools.d.ts +1 -1
  104. package/dist/paint-editor/index.cjs +18 -8
  105. package/dist/paint-editor/index.js +13 -3
  106. package/dist/paint-editor/tools.d.cts +1 -1
  107. package/dist/paint-editor/tools.d.ts +1 -1
  108. package/dist/persistence/index.cjs +3 -2
  109. package/dist/persistence/index.js +2 -1
  110. package/dist/serializers/index.cjs +5 -4
  111. package/dist/serializers/index.js +4 -3
  112. package/dist/tools/bridge-client.d.cts +3 -3
  113. package/dist/tools/bridge-client.d.ts +3 -3
  114. package/dist/tools/capture.d.cts +5 -1
  115. package/dist/tools/capture.d.ts +5 -1
  116. package/dist/tools/definitions.d.cts +2 -2
  117. package/dist/tools/definitions.d.ts +2 -2
  118. package/dist/tools/index.cjs +39 -5
  119. package/dist/tools/index.d.cts +4 -0
  120. package/dist/tools/index.d.ts +4 -0
  121. package/dist/tools/index.js +39 -5
  122. package/dist/tools/mcp-server.d.cts +24 -6
  123. package/dist/tools/mcp-server.d.ts +24 -6
  124. package/dist/tools/registry.d.cts +81 -6
  125. package/dist/tools/registry.d.ts +81 -6
  126. package/dist/tools/safe-json.d.cts +27 -0
  127. package/dist/tools/safe-json.d.ts +27 -0
  128. package/dist/tools/search.d.cts +30 -0
  129. package/dist/tools/search.d.ts +30 -0
  130. package/dist/tools/skills.d.cts +26 -0
  131. package/dist/tools/skills.d.ts +26 -0
  132. package/dist/tools/view.d.cts +95 -0
  133. package/dist/tools/view.d.ts +95 -0
  134. package/dist/vector/effect-tools.d.cts +1 -1
  135. package/dist/vector/effect-tools.d.ts +1 -1
  136. package/dist/vector/index.cjs +13 -7
  137. package/dist/vector/index.js +8 -2
  138. package/dist/video-editor/effect-tools.d.cts +1 -1
  139. package/dist/video-editor/effect-tools.d.ts +1 -1
  140. package/dist/video-editor/index.cjs +275 -269
  141. package/dist/video-editor/index.js +8 -2
  142. package/dist/video-editor/tools.d.cts +1 -1
  143. package/dist/video-editor/tools.d.ts +1 -1
  144. package/package.json +31 -29
  145. package/skills/README.md +8 -3
  146. package/skills/pixerate-agent-tools/SKILL.md +33 -7
  147. package/skills/pixerate-animation-editor/SKILL.md +7 -0
  148. package/skills/pixerate-rich-text/SKILL.md +18 -4
  149. package/dist/chunk-5RRYDFU2.js +0 -466
  150. package/dist/chunk-SPVIXXIB.cjs +0 -466
  151. /package/dist/{chunk-SMJK5HBJ.js → chunk-K73HMKQP.js} +0 -0
  152. /package/dist/{chunk-DDF6WQ62.cjs → chunk-LACYURUW.cjs} +0 -0
@@ -48,7 +48,7 @@ require('../chunk-NM3G4VQT.cjs');
48
48
 
49
49
 
50
50
 
51
- var _chunk3V746PF4cjs = require('../chunk-3V746PF4.cjs');
51
+ var _chunkRUZQMYXHcjs = require('../chunk-RUZQMYXH.cjs');
52
52
  require('../chunk-WOFXZ3XU.cjs');
53
53
  require('../chunk-LRRCMRSL.cjs');
54
54
  require('../chunk-YQGCPL5X.cjs');
@@ -206,6 +206,7 @@ var COMMAND_KEYS = {
206
206
  effect: [...BASE_KEYS, "effect", "param", "to"],
207
207
  wait: ["type", "duration", "with", "note"]
208
208
  };
209
+ var MOTION_COMMAND_FIELDS = COMMAND_KEYS;
209
210
  var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
210
211
  var isNum = (v) => typeof v === "number" && Number.isFinite(v);
211
212
  var isPoint = (v) => isObject(v) && isNum(v.x) && isNum(v.y);
@@ -3601,7 +3602,7 @@ var AnimationEditorController = (_class = class {
3601
3602
 
3602
3603
 
3603
3604
  /** The effects provider slot (see `setEffectsProvider`). */
3604
- __init() {this.effects = new (0, _chunk3V746PF4cjs.EffectsSlot)()}
3605
+ __init() {this.effects = new (0, _chunkRUZQMYXHcjs.EffectsSlot)()}
3605
3606
 
3606
3607
 
3607
3608
  __init2() {this.selection = null}
@@ -3776,7 +3777,7 @@ var AnimationEditorController = (_class = class {
3776
3777
  try {
3777
3778
  plan = await work();
3778
3779
  } catch (error) {
3779
- if (_chunk3V746PF4cjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
3780
+ if (_chunkRUZQMYXHcjs.isEffectError.call(void 0, error) || error instanceof Error) return this.refuse(error.message);
3780
3781
  throw error;
3781
3782
  }
3782
3783
  const r = this.apply({ op: "replace_scene", scene: plan.scene }, plan.label, { merge });
@@ -3787,11 +3788,11 @@ var AnimationEditorController = (_class = class {
3787
3788
  }
3788
3789
  async describeFor(effect, kinds) {
3789
3790
  const provider = this.effects.require();
3790
- if (!provider.applyVectorEffect) throw new (0, _chunk3V746PF4cjs.EffectUnsupportedError)(`${provider.name} has no vector or motion effects.`);
3791
+ if (!provider.applyVectorEffect) throw new (0, _chunkRUZQMYXHcjs.EffectUnsupportedError)(`${provider.name} has no vector or motion effects.`);
3791
3792
  const d = await provider.describe(effect);
3792
3793
  if (!kinds.includes(d.kind)) {
3793
3794
  const hint = d.kind === "motion" ? "apply it to nodes with apply_effect" : d.kind === "vector" ? "add it with add_vector_effect" : "it draws pixels, which scenes cannot hold";
3794
- throw new (0, _chunk3V746PF4cjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is a ${d.kind} effect: ${hint}.`, d.id);
3795
+ throw new (0, _chunkRUZQMYXHcjs.EffectUnsupportedError)(`"${d.id}" (${d.name}) is a ${d.kind} effect: ${hint}.`, d.id);
3795
3796
  }
3796
3797
  return d;
3797
3798
  }
@@ -3812,7 +3813,7 @@ var AnimationEditorController = (_class = class {
3812
3813
  return this.effectEdit(async () => {
3813
3814
  this.knownNodes(targets);
3814
3815
  const d = await this.describeFor(effect, ["motion"]);
3815
- const values = _chunk3V746PF4cjs.resolveEffectValues.call(void 0, d, options.values);
3816
+ const values = _chunkRUZQMYXHcjs.resolveEffectValues.call(void 0, d, options.values);
3816
3817
  const instance = _nullishCoalesce(options.instance, () => ( nextMotionEffectInstance(this.scene)));
3817
3818
  const motion = await this.effects.require().applyVectorEffect(d.id, { svg: motionArtworkSvg(this.scene.artwork), nodeIds: [...targets] }, values);
3818
3819
  const source = { instance, effect: d.id, provider: this.effects.require().id, name: d.name, values };
@@ -3834,7 +3835,7 @@ var AnimationEditorController = (_class = class {
3834
3835
  addVectorEffect(effect, options = {}) {
3835
3836
  return this.effectEdit(async () => {
3836
3837
  const d = await this.describeFor(effect, ["vector"]);
3837
- const values = _chunk3V746PF4cjs.resolveEffectValues.call(void 0, d, options.values);
3838
+ const values = _chunkRUZQMYXHcjs.resolveEffectValues.call(void 0, d, options.values);
3838
3839
  const instance = _nullishCoalesce(options.instance, () => ( nextMotionEffectInstance(this.scene)));
3839
3840
  const motion = await this.effects.require().applyVectorEffect(d.id, motionArtworkSvg(this.scene.artwork), values);
3840
3841
  const source = { instance, effect: d.id, provider: this.effects.require().id, name: d.name, values };
@@ -3858,7 +3859,7 @@ var AnimationEditorController = (_class = class {
3858
3859
  else if (k in d.controls.properties) base[k] = d.defaults[k];
3859
3860
  else throw new Error(`"${k}" is not a control of "${d.id}"; its controls are ${Object.keys(d.controls.properties).join(", ")}.`);
3860
3861
  }
3861
- const merged = { ...base, ..._chunk3V746PF4cjs.resolveEffectValues.call(void 0, { ...d, defaults: base }, given) };
3862
+ const merged = { ...base, ..._chunkRUZQMYXHcjs.resolveEffectValues.call(void 0, { ...d, defaults: base }, given) };
3862
3863
  const { scene: bare, place } = withoutMotionEffect(this.scene, instance);
3863
3864
  const provider = this.effects.require();
3864
3865
  const source = { instance, effect: d.id, provider: provider.id, name: d.name, values: merged };
@@ -4041,106 +4042,194 @@ var DRAW_ORDER = {
4041
4042
  origin: object({ x: { type: "number", description: "Document units." }, y: { type: "number", description: "Document units." } }, ["x", "y"], "With sortBy distance: where strokes are drawn out from (default the target's centre).")
4042
4043
  };
4043
4044
  var command2 = (type, description, extra = {}, required = []) => object({ type: { const: type, description }, ...BASE, ...extra }, ["type", "targets", ...required], description);
4045
+ var MOTION_COMMAND_TYPE_SCHEMAS = {
4046
+ enter: command2("enter", "Brings hidden targets in; they are hidden before this shot.", {
4047
+ ...DRAW_ORDER,
4048
+ style: {
4049
+ type: "string",
4050
+ enum: [...MOTION_ENTER_STYLES],
4051
+ description: "fade (default), pop (scales up past full size and settles), grow (from nothing), slide, draw (outline drawn on, then the fill fades in), zoom (settles from larger), rise (rises a short way, overshooting a touch), or a reveal through a clip over the target's box: wipe (behind a travelling edge), iris (from the centre outwards) or split (from a line through the middle). Reveals need a box with a width and a height (not a lone straight line)."
4052
+ },
4053
+ direction: { type: "string", enum: [...MOTION_DIRECTIONS], description: "For slide: direction of travel (default up). For wipe: the way the edge travels (default right, revealing from the left)." },
4054
+ distance: { type: "number", description: "For slide (default 40) and rise (default 20): document units." },
4055
+ scale: { type: "number", minimum: 0, description: "For pop (default 0.5) and zoom (default 1.6): the starting scale (1 = rest size)." },
4056
+ shape: { type: "string", enum: [...MOTION_IRIS_SHAPES], description: "For iris: open through a circle (default; an ellipse on a box that is not square) or a box." },
4057
+ orientation: { type: "string", enum: [...MOTION_SPLIT_ORIENTATIONS], description: "For split: horizontal (default) opens up and down from a horizontal line through the middle; vertical opens left and right." }
4058
+ }),
4059
+ exit: command2("exit", "Takes targets out.", {
4060
+ ...DRAW_ORDER,
4061
+ style: { type: "string", enum: [...MOTION_EXIT_STYLES], description: "fade (default), shrink, slide, undraw, or wipe (hides behind a travelling edge through a clip over the target's box: a wipe in, reversed)." },
4062
+ direction: { type: "string", enum: [...MOTION_DIRECTIONS], description: "For slide: direction of travel (default down). For wipe: the way the edge travels (default right, hiding from the left)." },
4063
+ distance: { type: "number", description: "For slide: document units (default 40)." }
4064
+ }),
4065
+ draw: command2("draw", "Draws strokes on (or off) to a fraction of their length.", { ...DRAW_ORDER, comet: FRACTION("A travelling stroke this fraction of the length long: it runs along the path and off the end (leave out from and to)."), to: FRACTION("Fraction drawn at the end (default 1)."), from: FRACTION("Fraction drawn at the start (default: what is drawn now).") }),
4066
+ move: command2("move", "Moves targets by an offset or so their centre lands on a point.", { via: { type: "array", items: POINT("A point the centre passes through."), minItems: 1, maxItems: 64, description: 'Waypoints (document units) the centre passes through on the way to "to" or "by", smoothly (velocity carries through each) and without overshooting any. Default length 700 ms + 400 per waypoint.' }, pacing: { type: "string", enum: ["even", "equal"], description: "With via: even (default) keeps the speed steady along the path; equal gives each stretch the same time." }, blend: BLEND("replace"), by: POINT("Offset in document units."), to: POINT("Point (document coordinates) for the centre.") }),
4067
+ rotate: command2("rotate", "Turns targets about their centre (degrees, clockwise).", { blend: BLEND("replace"), by: { type: "number", description: "Degrees to turn by." }, to: { type: "number", description: "Angle to turn to, in degrees from rest." } }),
4068
+ scale: command2("scale", "Scales targets about their centre (1 = rest size).", { blend: BLEND("replace"), to: { description: "A factor, or { x, y } factors.", anyOf: [{ type: "number" }, POINT("Factors per axis.")] }, geometric: { type: "boolean", description: "Grow by a steady factor, which reads as an even zoom (default false)." } }, ["to"]),
4069
+ fade: command2("fade", "Changes opacity.", { to: FRACTION("Opacity at the end (0\u20131).") }, ["to"]),
4070
+ style: command2("style", "Blends solid fill / stroke colours (in OKLab) and stroke width. On a group it changes every path in it.", {
4071
+ fill: { type: "string", description: "CSS colour (hex, rgb(), rgba())." },
4072
+ stroke: { type: "string", description: "CSS colour (hex, rgb(), rgba())." },
4073
+ strokeWidth: { type: "number", minimum: 0, description: "Document units." }
4074
+ }),
4075
+ play: object(
4076
+ {
4077
+ type: { const: "play", description: 'Plays a clip (set_animation_clip) on the targets: its commands, with "$" standing for each target, timed as in a shot.' },
4078
+ targets: NODE_IDS,
4079
+ clip: { type: "string", minLength: 1, description: "The clip's name (get_animation lists them)." },
4080
+ speed: { type: "number", minimum: 0.05, maximum: 20, description: "Play it this many times as fast (default 1)." },
4081
+ delay: BASE.delay,
4082
+ stagger: BASE.stagger,
4083
+ with: BASE.with,
4084
+ note: BASE.note
4085
+ },
4086
+ ["type", "targets", "clip"],
4087
+ "Plays a clip on the targets."
4088
+ ),
4089
+ match: command2("match", `Smart Animate: tweens a group into another group (usually hidden), part by part. Parts pair by name, then by id with the group ids taken out (card-a-title \u2194 card-b-title), then by kind in order; each takes its partner's shape, paint and place. Unpaired parts fade out; parts of "into" with no partner do not appear (check_animation lists them).`, { into: { type: "string", minLength: 1, description: "Id of the group to become." } }, ["into"]),
4090
+ morph: command2("morph", "Morphs each target into the shape (and paint) of another node, which usually stays hidden.", { into: { type: "string", minLength: 1, description: "Id of the node whose shape to take." } }, ["into"]),
4091
+ follow: command2("follow", "Moves targets along a path node, centre on the path.", {
4092
+ path: { type: "string", minLength: 1, description: "Id of a path node (it can be hidden)." },
4093
+ rotate: { type: "boolean", description: "Turn with the path (default false); moves and shakes made meanwhile turn with it too." },
4094
+ from: FRACTION("Where to start along the path (default 0)."),
4095
+ to: FRACTION("Where to end along the path (default 1).")
4096
+ }, ["path"]),
4097
+ pulse: command2("pulse", "Scales up and back to draw the eye.", { blend: BLEND("add"), amount: { type: "number", description: "Extra scale at the peak (default 0.15)." }, count: { type: "integer", minimum: 1, description: "Pulses (default 1)." } }),
4098
+ shake: command2("shake", "Shakes side to side (or up and down), settling.", {
4099
+ blend: BLEND("add"),
4100
+ amount: { type: "number", description: "Document units (default 8)." },
4101
+ count: { type: "integer", minimum: 1, description: "Shakes (default 3)." },
4102
+ axis: { type: "string", enum: ["horizontal", "vertical"], description: "Default horizontal." }
4103
+ }),
4104
+ teeter: command2("teeter", "Rocks about the centre either way, settling.", { blend: BLEND("add"), angle: { type: "number", description: "Degrees either way (default 8)." }, count: { type: "integer", minimum: 1, description: "Rocks (default 3)." } }),
4105
+ wave: command2("wave", "Bobs up and down without settling, like something floating (default 1000 ms).", { blend: BLEND("add"), amount: { type: "number", description: "Height in document units (default 6)." }, count: { type: "integer", minimum: 1, description: "Bobs (default 2)." } }),
4106
+ wiggle: command2("wiggle", "Wanders about its place as smooth seeded noise, easing out of and back to rest (default 1500 ms). The same seed always wanders the same way.", {
4107
+ blend: BLEND("add"),
4108
+ amount: { type: "number", description: "Up to about this far, in document units (default 6)." },
4109
+ frequency: { type: "number", exclusiveMinimum: 0, description: "Wanders per second, in Hz (default 3)." },
4110
+ octaves: { type: "integer", minimum: 1, maximum: 8, description: "Layers of finer detail (default 2)." },
4111
+ rotate: { type: "number", description: "Also turns about the centre by up to about this many degrees (default 0)." },
4112
+ seed: { type: "integer", minimum: 0, description: "Default: one picked from the target id, so each target wanders its own way." }
4113
+ }),
4114
+ "color-pulse": command2("color-pulse", "Tints solid paint toward a colour and back (mixed in OKLab). On a group it tints every path in it.", {
4115
+ color: { type: "string", description: 'The tint, a CSS colour (default "#f59e0b").' },
4116
+ paint: { type: "string", enum: ["fill", "stroke"], description: "Which paint (default fill)." },
4117
+ count: { type: "integer", minimum: 1, description: "Pulses (default 1)." }
4118
+ }),
4119
+ effect: command2("effect", "Tweens a numeric parameter of a live path effect on the targets (twist angle, wiggle time, zig zag size, trim offset\u2026).", {
4120
+ effect: { type: "string", minLength: 1, description: `Effect id from get_animation's element "effects".` },
4121
+ param: { type: "string", minLength: 1, description: "A numeric parameter of that effect (listed with it)." },
4122
+ to: { type: "number", description: "Value at the end." }
4123
+ }, ["effect", "param", "to"]),
4124
+ wait: object(
4125
+ { type: { const: "wait", description: "Waits." }, duration: MS("How long"), with: BASE.with, note: BASE.note },
4126
+ ["type", "duration"],
4127
+ "Waits before the next command."
4128
+ )
4129
+ };
4044
4130
  var MOTION_COMMAND_SCHEMA = {
4045
4131
  description: `A command (one of ${MOTION_COMMAND_TYPES.join(", ")}). Commands in a shot play one after another unless "with": "previous".`,
4046
- oneOf: [
4047
- command2("enter", "Brings hidden targets in; they are hidden before this shot.", {
4048
- ...DRAW_ORDER,
4049
- style: {
4050
- type: "string",
4051
- enum: [...MOTION_ENTER_STYLES],
4052
- description: "fade (default), pop (scales up past full size and settles), grow (from nothing), slide, draw (outline drawn on, then the fill fades in), zoom (settles from larger), rise (rises a short way, overshooting a touch), or a reveal through a clip over the target's box: wipe (behind a travelling edge), iris (from the centre outwards) or split (from a line through the middle). Reveals need a box with a width and a height (not a lone straight line)."
4053
- },
4054
- direction: { type: "string", enum: [...MOTION_DIRECTIONS], description: "For slide: direction of travel (default up). For wipe: the way the edge travels (default right, revealing from the left)." },
4055
- distance: { type: "number", description: "For slide (default 40) and rise (default 20): document units." },
4056
- scale: { type: "number", minimum: 0, description: "For pop (default 0.5) and zoom (default 1.6): the starting scale (1 = rest size)." },
4057
- shape: { type: "string", enum: [...MOTION_IRIS_SHAPES], description: "For iris: open through a circle (default; an ellipse on a box that is not square) or a box." },
4058
- orientation: { type: "string", enum: [...MOTION_SPLIT_ORIENTATIONS], description: "For split: horizontal (default) opens up and down from a horizontal line through the middle; vertical opens left and right." }
4059
- }),
4060
- command2("exit", "Takes targets out.", {
4061
- ...DRAW_ORDER,
4062
- style: { type: "string", enum: [...MOTION_EXIT_STYLES], description: "fade (default), shrink, slide, undraw, or wipe (hides behind a travelling edge through a clip over the target's box: a wipe in, reversed)." },
4063
- direction: { type: "string", enum: [...MOTION_DIRECTIONS], description: "For slide: direction of travel (default down). For wipe: the way the edge travels (default right, hiding from the left)." },
4064
- distance: { type: "number", description: "For slide: document units (default 40)." }
4065
- }),
4066
- command2("draw", "Draws strokes on (or off) to a fraction of their length.", { ...DRAW_ORDER, comet: FRACTION("A travelling stroke this fraction of the length long: it runs along the path and off the end (leave out from and to)."), to: FRACTION("Fraction drawn at the end (default 1)."), from: FRACTION("Fraction drawn at the start (default: what is drawn now).") }),
4067
- command2("move", "Moves targets by an offset or so their centre lands on a point.", { via: { type: "array", items: POINT("A point the centre passes through."), minItems: 1, maxItems: 64, description: 'Waypoints (document units) the centre passes through on the way to "to" or "by", smoothly (velocity carries through each) and without overshooting any. Default length 700 ms + 400 per waypoint.' }, pacing: { type: "string", enum: ["even", "equal"], description: "With via: even (default) keeps the speed steady along the path; equal gives each stretch the same time." }, blend: BLEND("replace"), by: POINT("Offset in document units."), to: POINT("Point (document coordinates) for the centre.") }),
4068
- command2("rotate", "Turns targets about their centre (degrees, clockwise).", { blend: BLEND("replace"), by: { type: "number", description: "Degrees to turn by." }, to: { type: "number", description: "Angle to turn to, in degrees from rest." } }),
4069
- command2("scale", "Scales targets about their centre (1 = rest size).", { blend: BLEND("replace"), to: { description: "A factor, or { x, y } factors.", anyOf: [{ type: "number" }, POINT("Factors per axis.")] }, geometric: { type: "boolean", description: "Grow by a steady factor, which reads as an even zoom (default false)." } }, ["to"]),
4070
- command2("fade", "Changes opacity.", { to: FRACTION("Opacity at the end (0\u20131).") }, ["to"]),
4071
- command2("style", "Blends solid fill / stroke colours (in OKLab) and stroke width. On a group it changes every path in it.", {
4072
- fill: { type: "string", description: "CSS colour (hex, rgb(), rgba())." },
4073
- stroke: { type: "string", description: "CSS colour (hex, rgb(), rgba())." },
4074
- strokeWidth: { type: "number", minimum: 0, description: "Document units." }
4075
- }),
4132
+ oneOf: MOTION_COMMAND_TYPES.map((type) => MOTION_COMMAND_TYPE_SCHEMAS[type])
4133
+ };
4134
+ var REF2 = (name, description) => ({ $ref: `#/$defs/${name}`, ...description ? { description } : {} });
4135
+ var firstSentence = (text) => _nullishCoalesce(_optionalChain([/^.*?[.;](?=\s|$)/, 'access', _160 => _160.exec, 'call', _161 => _161(text), 'optionalAccess', _162 => _162[0]]), () => ( text));
4136
+ var COMMAND_TYPE_LINES = MOTION_COMMAND_TYPES.map((type) => `${type}: ${firstSentence(_nullishCoalesce(MOTION_COMMAND_TYPE_SCHEMAS[type].description, () => ( "")))}`);
4137
+ var EASE_COMPACT = {
4138
+ 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.`,
4139
+ anyOf: [
4140
+ { type: "string", enum: [..._chunkDWJJI6RTcjs.ANIMATION_EASING_PRESETS] },
4076
4141
  object(
4077
4142
  {
4078
- type: { const: "play", description: 'Plays a clip (set_animation_clip) on the targets: its commands, with "$" standing for each target, timed as in a shot.' },
4079
- targets: NODE_IDS,
4080
- clip: { type: "string", minLength: 1, description: "The clip's name (get_animation lists them)." },
4081
- speed: { type: "number", minimum: 0.05, maximum: 20, description: "Play it this many times as fast (default 1)." },
4082
- delay: BASE.delay,
4083
- stagger: BASE.stagger,
4084
- with: BASE.with,
4085
- note: BASE.note
4143
+ type: { type: "string", enum: ["cubic-bezier", "spring", "elastic"], description: "Curve kind." },
4144
+ x1: { type: "number", description: "cubic-bezier: out handle x (0\u20131)." },
4145
+ y1: { type: "number", description: "cubic-bezier: out handle y." },
4146
+ x2: { type: "number", description: "cubic-bezier: in handle x (0\u20131)." },
4147
+ y2: { type: "number", description: "cubic-bezier: in handle y." },
4148
+ stiffness: { type: "number", exclusiveMinimum: 0, description: "spring: default 170." },
4149
+ damping: { type: "number", minimum: 0, description: "spring: default 26, lower bounces more." },
4150
+ mass: { type: "number", exclusiveMinimum: 0, description: "spring: default 1." },
4151
+ velocity: { type: "number", description: "spring: starting speed (default 0)." },
4152
+ amplitude: { type: "number", minimum: 0, description: "elastic: overshoot (default 1)." },
4153
+ period: { type: "number", exclusiveMinimum: 0, description: "elastic: fraction of the length (default 0.3)." },
4154
+ mode: { type: "string", enum: ["out", "in", "in-out"], description: "elastic: default out." }
4086
4155
  },
4087
- ["type", "targets", "clip"],
4088
- "Plays a clip on the targets."
4089
- ),
4090
- command2("match", `Smart Animate: tweens a group into another group (usually hidden), part by part. Parts pair by name, then by id with the group ids taken out (card-a-title \u2194 card-b-title), then by kind in order; each takes its partner's shape, paint and place. Unpaired parts fade out; parts of "into" with no partner do not appear (check_animation lists them).`, { into: { type: "string", minLength: 1, description: "Id of the group to become." } }, ["into"]),
4091
- command2("morph", "Morphs each target into the shape (and paint) of another node, which usually stays hidden.", { into: { type: "string", minLength: 1, description: "Id of the node whose shape to take." } }, ["into"]),
4092
- command2("follow", "Moves targets along a path node, centre on the path.", {
4093
- path: { type: "string", minLength: 1, description: "Id of a path node (it can be hidden)." },
4094
- rotate: { type: "boolean", description: "Turn with the path (default false); moves and shakes made meanwhile turn with it too." },
4095
- from: FRACTION("Where to start along the path (default 0)."),
4096
- to: FRACTION("Where to end along the path (default 1).")
4097
- }, ["path"]),
4098
- command2("pulse", "Scales up and back to draw the eye.", { blend: BLEND("add"), amount: { type: "number", description: "Extra scale at the peak (default 0.15)." }, count: { type: "integer", minimum: 1, description: "Pulses (default 1)." } }),
4099
- command2("shake", "Shakes side to side (or up and down), settling.", {
4100
- blend: BLEND("add"),
4101
- amount: { type: "number", description: "Document units (default 8)." },
4102
- count: { type: "integer", minimum: 1, description: "Shakes (default 3)." },
4103
- axis: { type: "string", enum: ["horizontal", "vertical"], description: "Default horizontal." }
4104
- }),
4105
- command2("teeter", "Rocks about the centre either way, settling.", { blend: BLEND("add"), angle: { type: "number", description: "Degrees either way (default 8)." }, count: { type: "integer", minimum: 1, description: "Rocks (default 3)." } }),
4106
- command2("wave", "Bobs up and down without settling, like something floating (default 1000 ms).", { blend: BLEND("add"), amount: { type: "number", description: "Height in document units (default 6)." }, count: { type: "integer", minimum: 1, description: "Bobs (default 2)." } }),
4107
- command2("wiggle", "Wanders about its place as smooth seeded noise, easing out of and back to rest (default 1500 ms). The same seed always wanders the same way.", {
4108
- blend: BLEND("add"),
4109
- amount: { type: "number", description: "Up to about this far, in document units (default 6)." },
4110
- frequency: { type: "number", exclusiveMinimum: 0, description: "Wanders per second, in Hz (default 3)." },
4111
- octaves: { type: "integer", minimum: 1, maximum: 8, description: "Layers of finer detail (default 2)." },
4112
- rotate: { type: "number", description: "Also turns about the centre by up to about this many degrees (default 0)." },
4113
- seed: { type: "integer", minimum: 0, description: "Default: one picked from the target id, so each target wanders its own way." }
4114
- }),
4115
- command2("color-pulse", "Tints solid paint toward a colour and back (mixed in OKLab). On a group it tints every path in it.", {
4116
- color: { type: "string", description: 'The tint, a CSS colour (default "#f59e0b").' },
4117
- paint: { type: "string", enum: ["fill", "stroke"], description: "Which paint (default fill)." },
4118
- count: { type: "integer", minimum: 1, description: "Pulses (default 1)." }
4119
- }),
4120
- command2("effect", "Tweens a numeric parameter of a live path effect on the targets (twist angle, wiggle time, zig zag size, trim offset\u2026).", {
4121
- effect: { type: "string", minLength: 1, description: `Effect id from get_animation's element "effects".` },
4122
- param: { type: "string", minLength: 1, description: "A numeric parameter of that effect (listed with it)." },
4123
- to: { type: "number", description: "Value at the end." }
4124
- }, ["effect", "param", "to"]),
4125
- object(
4126
- { type: { const: "wait", description: "Waits." }, duration: MS("How long"), with: BASE.with, note: BASE.note },
4127
- ["type", "duration"],
4128
- "Waits before the next command."
4156
+ ["type"]
4129
4157
  )
4130
4158
  ]
4131
4159
  };
4160
+ var COMMAND = object(
4161
+ {
4162
+ type: {
4163
+ type: "string",
4164
+ enum: [...MOTION_COMMAND_TYPES],
4165
+ description: `${COMMAND_TYPE_LINES.join(" ")} The fields from blend on say which types take them; play takes no duration, ease, split, cascade, repeat or steps, and wait only duration, with and note. describe_animation_command gives a type's full schema.`
4166
+ },
4167
+ targets: { ...NODE_IDS, description: `Node ids from get_animation's "elements" (a group animates as one; "$" in a clip). Required except for wait.` },
4168
+ duration: MS("Length for each target (each type has a default; draw follows the path length)"),
4169
+ delay: MS("Wait before starting (default 0)"),
4170
+ stagger: MS("Start each further target this much later (default 0)"),
4171
+ with: BASE.with,
4172
+ ease: REF2("ease", "Easing (default ease-out for entrances, ease-in-out for moves)."),
4173
+ note: BASE.note,
4174
+ split: { type: "string", enum: ["letter", "word", "line"], description: "Outlined text (a group of letter paths): animate a letter, word or line at a time, staggered. get_text_layout shows the units." },
4175
+ cascade: { type: "string", enum: ["forward", "backward", "center", "edges", "random"], description: "With split: the order units go in (default forward)." },
4176
+ repeat: { type: "integer", minimum: 1, maximum: 1e3, description: 'Play it this many times (default 1); "duration" is one cycle. Not for enter or exit.' },
4177
+ repeatMode: { type: "string", enum: [...MOTION_REPEAT_MODES], description: "With repeat: loop (default), mirror (every other cycle backwards) or offset (carry on from where the last ended)." },
4178
+ steps: { type: "number", exclusiveMinimum: 0, maximum: 120, description: `Stepped time, frames per second to hold on (12 = "on twos"). Default: the scene's steps, else smooth.` },
4179
+ blend: { type: "string", enum: [...MOTION_BLENDS], description: 'move, rotate, scale, emphasis: "replace" is a change the next takes over from (default for move, rotate, scale), "add" a layer over the pose (default for emphasis).' },
4180
+ style: { type: "string", enum: [.../* @__PURE__ */ new Set([...MOTION_ENTER_STYLES, ...MOTION_EXIT_STYLES])], description: `enter: ${MOTION_ENTER_STYLES.join(", ")} (default fade). exit: ${MOTION_EXIT_STYLES.join(", ")} (default fade).` },
4181
+ direction: { type: "string", enum: [...MOTION_DIRECTIONS], description: "enter / exit slide or wipe: the way it travels (default up for enter slide, down for exit slide, right for wipe)." },
4182
+ distance: { type: "number", description: "enter / exit slide (default 40), enter rise (default 20): document units." },
4183
+ scale: { type: "number", minimum: 0, description: "enter pop (default 0.5) or zoom (default 1.6): the starting scale." },
4184
+ shape: { type: "string", enum: [...MOTION_IRIS_SHAPES], description: "enter iris: open through a circle (default) or a box." },
4185
+ orientation: { type: "string", enum: [...MOTION_SPLIT_ORIENTATIONS], description: "enter split: the line it opens from (default horizontal)." },
4186
+ order: { type: "string", enum: ["together", "sequence"], description: "draw, enter draw, exit undraw on several strokes: together (default) or sequence (one after another)." },
4187
+ pace: { type: "string", enum: ["time", "speed"], description: "With order together: every stroke takes the whole time (default) or all go at one speed." },
4188
+ align: { type: "string", enum: ["start", "end"], description: "With pace speed: start together (default) or finish together." },
4189
+ sortBy: { type: "string", enum: ["document", "distance"], description: "With order sequence: stacking order (default) or distance from origin." },
4190
+ origin: REF2("point", "With sortBy distance: where strokes are drawn out from (default the target's centre)."),
4191
+ from: FRACTION("draw: fraction drawn at the start (default: what is drawn now). follow: where to start along the path (default 0)."),
4192
+ to: { anyOf: [{ type: "number" }, REF2("point")], description: "move: point for the centre. rotate: angle in degrees. scale: factor or { x, y } factors (required). fade: opacity 0\u20131 (required). draw: fraction drawn (default 1). follow: where to end on the path (default 1). effect: the value (required)." },
4193
+ by: { anyOf: [{ type: "number" }, REF2("point")], description: "move: offset { x, y } in document units. rotate: degrees to turn by." },
4194
+ comet: FRACTION("draw: a travelling stroke this fraction of the length long (leave out from and to)."),
4195
+ via: { type: "array", items: REF2("point"), minItems: 1, maxItems: 64, description: 'move: waypoints the centre passes through smoothly on the way to "to" or "by".' },
4196
+ pacing: { type: "string", enum: ["even", "equal"], description: "move with via: steady speed (even, default) or the same time per stretch (equal)." },
4197
+ geometric: { type: "boolean", description: "scale: grow by a steady factor, an even zoom (default false)." },
4198
+ fill: { type: "string", description: "style: fill colour, CSS (hex, rgb(), rgba())." },
4199
+ stroke: { type: "string", description: "style: stroke colour, CSS." },
4200
+ strokeWidth: { type: "number", minimum: 0, description: "style: stroke width, document units." },
4201
+ clip: { type: "string", minLength: 1, description: "play: the clip's name (required)." },
4202
+ speed: { type: "number", minimum: 0.05, maximum: 20, description: "play: this many times as fast (default 1)." },
4203
+ into: { type: "string", minLength: 1, description: "match: id of the group to become. morph: id of the node whose shape to take (required)." },
4204
+ path: { type: "string", minLength: 1, description: "follow: id of a path node (required; it can be hidden)." },
4205
+ rotate: { type: ["boolean", "number"], description: "follow: turn with the path (boolean, default false). wiggle: also turn by up to this many degrees (default 0)." },
4206
+ amount: { type: "number", description: "pulse: extra scale at the peak (default 0.15). shake (8), wave (6), wiggle (6): document units." },
4207
+ count: { type: "integer", minimum: 1, description: "pulse, shake, teeter, wave, color-pulse: how many times." },
4208
+ axis: { type: "string", enum: ["horizontal", "vertical"], description: "shake: default horizontal." },
4209
+ angle: { type: "number", description: "teeter: degrees either way (default 8)." },
4210
+ frequency: { type: "number", exclusiveMinimum: 0, description: "wiggle: wanders per second, Hz (default 3)." },
4211
+ octaves: { type: "integer", minimum: 1, maximum: 8, description: "wiggle: layers of finer detail (default 2)." },
4212
+ seed: { type: "integer", minimum: 0, description: "wiggle: noise seed (default: from the target id)." },
4213
+ color: { type: "string", description: 'color-pulse: the tint, a CSS colour (default "#f59e0b").' },
4214
+ paint: { type: "string", enum: ["fill", "stroke"], description: "color-pulse: which paint (default fill)." },
4215
+ effect: { type: "string", minLength: 1, description: `effect: effect id from get_animation's element "effects" (required).` },
4216
+ param: { type: "string", minLength: 1, description: "effect: a numeric parameter of that effect (required)." }
4217
+ },
4218
+ ["type"],
4219
+ 'A command. Commands in a shot play one after another unless "with": "previous".'
4220
+ );
4132
4221
  var GEOMETRIC_CAMERA = { type: "boolean", description: "Zoom at a steady rate, so a big zoom does not rush at the start (default false)." };
4133
4222
  var CAMERA = {
4134
4223
  description: `Where the camera looks: a rectangle { x, y, width, height } in document units, or { frame: "<node id>", padding } to frame a node (fitted to the artwork's shape). It eases there over "ms" (default 1000); the first shot cuts.`,
4135
4224
  anyOf: [
4136
- object({ x: { type: "number", description: "Left." }, y: { type: "number", description: "Top." }, width: { type: "number", exclusiveMinimum: 0, description: "Width." }, height: { type: "number", exclusiveMinimum: 0, description: "Height." }, ease: EASE, ms: MS("Camera move length"), geometric: GEOMETRIC_CAMERA }, ["x", "y", "width", "height"]),
4137
- object({ frame: { type: "string", minLength: 1, description: "Node id to frame." }, padding: { type: "number", description: "Margin around it (default 24)." }, ease: EASE, ms: MS("Camera move length"), geometric: GEOMETRIC_CAMERA }, ["frame"])
4225
+ object({ x: { type: "number", description: "Left." }, y: { type: "number", description: "Top." }, width: { type: "number", exclusiveMinimum: 0, description: "Width." }, height: { type: "number", exclusiveMinimum: 0, description: "Height." }, ease: REF2("ease"), ms: MS("Camera move length"), geometric: GEOMETRIC_CAMERA }, ["x", "y", "width", "height"]),
4226
+ object({ frame: { type: "string", minLength: 1, description: "Node id to frame." }, padding: { type: "number", description: "Margin around it (default 24)." }, ease: REF2("ease"), ms: MS("Camera move length"), geometric: GEOMETRIC_CAMERA }, ["frame"])
4138
4227
  ]
4139
4228
  };
4140
4229
  var SHOT_FIELDS = {
4141
4230
  label: { type: "string", description: "What happens, in a few words." },
4142
- camera: CAMERA,
4143
- run: { type: "array", items: MOTION_COMMAND_SCHEMA, description: "Commands, in order." },
4231
+ camera: REF2("camera"),
4232
+ run: { type: "array", items: REF2("command"), description: "Commands, in order." },
4144
4233
  hold: MS("Hold after the commands (default 600)"),
4145
4234
  speed: { type: "number", minimum: 0.05, maximum: 20, description: "Play the whole shot this many times as fast (default 1; 0.5 is half speed). fit_animation sets it." },
4146
4235
  at: object(
@@ -4161,6 +4250,26 @@ var CONTROL = object(
4161
4250
  "A colour parameter of the Flair effect made from the scene."
4162
4251
  );
4163
4252
  var PRESET = object({ name: { type: "string", minLength: 1, description: "Preset name." }, values: { type: "object", additionalProperties: { type: "string" }, description: "Control name \u2192 colour." } }, ["name", "values"], "Named control values.");
4253
+ var DEFS = {
4254
+ point: POINT("A point (or offset) in document units."),
4255
+ ease: EASE_COMPACT,
4256
+ command: COMMAND,
4257
+ camera: CAMERA,
4258
+ shot: SHOT
4259
+ };
4260
+ function withDefs(schema) {
4261
+ const used = /* @__PURE__ */ new Set();
4262
+ const visit = (value) => {
4263
+ for (const [, name] of JSON.stringify(value).matchAll(/"#\/\$defs\/(\w+)"/g)) {
4264
+ if (used.has(name)) continue;
4265
+ used.add(name);
4266
+ visit(DEFS[name]);
4267
+ }
4268
+ };
4269
+ visit(schema);
4270
+ if (!used.size) return schema;
4271
+ return { ...schema, $defs: Object.fromEntries(Object.keys(DEFS).filter((n) => used.has(n)).map((n) => [n, DEFS[n]])) };
4272
+ }
4164
4273
  var SETTINGS = {
4165
4274
  name: { type: "string", minLength: 1, description: 'Short name, e.g. "logo-reveal".' },
4166
4275
  description: { type: ["string", "null"], description: "What it shows; null clears." },
@@ -4195,11 +4304,11 @@ var EDIT_OP = {
4195
4304
  description: `One edit (${MOTION_EDIT_OPS.filter((o) => o !== "replace_scene" && o !== "set_artwork").join(", ")}), shaped like the tool of the same name with an "op" field.`,
4196
4305
  oneOf: [
4197
4306
  object({ op: { const: "set_settings", description: "Like set_animation_settings." }, ...SETTINGS }, ["op"]),
4198
- object({ op: { const: "insert_shots", description: "Like insert_shots." }, shots: { type: "array", items: SHOT, minItems: 1, description: "Shots to add." }, at: { type: "integer", minimum: 0, description: "Position (default: the end)." } }, ["op", "shots"]),
4307
+ object({ op: { const: "insert_shots", description: "Like insert_shots." }, shots: { type: "array", items: REF2("shot"), minItems: 1, description: "Shots to add." }, at: { type: "integer", minimum: 0, description: "Position (default: the end)." } }, ["op", "shots"]),
4199
4308
  object({ op: { const: "update_shot", description: "Like update_shot." }, shot: SHOT_ID, set: object({ id: SHOT.properties.id, ...SHOT_FIELDS }, [], "Fields to replace."), remove: { type: "array", items: { type: "string", enum: ["label", "camera", "hold", "speed", "at"] }, description: "Fields to clear." } }, ["op", "shot"]),
4200
4309
  object({ op: { const: "delete_shots", description: "Like delete_shots." }, shots: { type: "array", items: SHOT_ID, minItems: 1, description: "Shot ids." } }, ["op", "shots"]),
4201
4310
  object({ op: { const: "move_shot", description: "Like move_shot." }, shot: SHOT_ID, to: { type: "integer", minimum: 0, description: "New position (0 = first)." } }, ["op", "shot", "to"]),
4202
- object({ op: { const: "add_commands", description: "Like add_commands." }, shot: SHOT_ID, commands: { type: "array", items: MOTION_COMMAND_SCHEMA, minItems: 1, description: "Commands to add." }, at: { type: "integer", minimum: 0, description: "Index in the shot's run (default: the end)." } }, ["op", "shot", "commands"]),
4311
+ object({ op: { const: "add_commands", description: "Like add_commands." }, shot: SHOT_ID, commands: { type: "array", items: REF2("command"), minItems: 1, description: "Commands to add." }, at: { type: "integer", minimum: 0, description: "Index in the shot's run (default: the end)." } }, ["op", "shot", "commands"]),
4203
4312
  object({ op: { const: "update_command", description: "Like update_command." }, shot: SHOT_ID, command: { anyOf: [{ type: "integer", minimum: 0 }, { type: "string", pattern: "^\\$(\\d+|last)[.\\[]" }], description: `Index in the shot's run, or a reference to an earlier op's outcome such as "$0.indexes[0]".` }, set: { type: "object", description: "Command fields to replace." }, remove: { type: "array", items: { type: "string" }, description: "Command fields to clear." } }, ["op", "shot", "command"]),
4204
4313
  object({ op: { const: "move_command", description: "Like move_command." }, shot: SHOT_ID, command: { anyOf: [{ type: "integer", minimum: 0 }, { type: "string", pattern: "^\\$(\\d+|last)[.\\[]" }], description: `Index in the shot's run, or a reference to an earlier op's outcome such as "$0.indexes[0]".` }, to: { type: "integer", minimum: 0, description: "New index in the run (0 = first)." } }, ["op", "shot", "command", "to"]),
4205
4314
  object({ op: { const: "delete_commands", description: "Like delete_commands." }, shot: SHOT_ID, commands: { type: "array", items: { anyOf: [{ type: "integer", minimum: 0 }, { type: "string", pattern: "^\\$(\\d+|last)[.\\[]" }], description: `An index, or a reference to an earlier op's outcome such as "$0.indexes[0]".` }, minItems: 1, description: "Indexes in the shot's run." } }, ["op", "shot", "commands"]),
@@ -4309,6 +4418,21 @@ function createAnimationEditorToolProvider(controller, options = {}) {
4309
4418
  };
4310
4419
  }
4311
4420
  };
4421
+ const describeCommand = {
4422
+ name: "describe_animation_command",
4423
+ title: "Describe command types",
4424
+ description: "Returns the full JSON Schema of each given command type: every field it takes with its type, range, default and meaning, and which are required. The write tools list every field once in short; call this before writing a type you have not used yet or when a write rejects a field. Returns { commands: [{ type, schema }] }.",
4425
+ inputSchema: object(
4426
+ { types: { type: "array", items: { type: "string", enum: [...MOTION_COMMAND_TYPES] }, minItems: 1, uniqueItems: true, description: `Command types, e.g. ["enter", "move"] (any of ${MOTION_COMMAND_TYPES.join(", ")}).` } },
4427
+ ["types"]
4428
+ ),
4429
+ annotations: { title: "Describe command types", ...READ },
4430
+ handler: ({ types }) => {
4431
+ for (const type of types)
4432
+ if (!MOTION_COMMAND_TYPES.includes(type)) throw new Error(`There is no command type ${_chunkEBDZWIOPcjs.namedWithSuggestion.call(void 0, type, MOTION_COMMAND_TYPES)}; use one of ${MOTION_COMMAND_TYPES.join(", ")}.`);
4433
+ return { commands: types.map((type) => ({ type, schema: MOTION_COMMAND_TYPE_SCHEMAS[type] })) };
4434
+ }
4435
+ };
4312
4436
  const getShot = {
4313
4437
  name: "get_shot",
4314
4438
  title: "Read one shot",
@@ -4416,9 +4540,9 @@ function createAnimationEditorToolProvider(controller, options = {}) {
4416
4540
  handler: ({ from = 0, to, limit = 200 }) => {
4417
4541
  const s = scene();
4418
4542
  const timeline = compileMotionScene(s);
4419
- const words = _nullishCoalesce(_optionalChain([s, 'access', _160 => _160.narration, 'optionalAccess', _161 => _161.words]), () => ( []));
4543
+ const words = _nullishCoalesce(_optionalChain([s, 'access', _163 => _163.narration, 'optionalAccess', _164 => _164.words]), () => ( []));
4420
4544
  const end = _nullishCoalesce(to, () => ( Math.max(timeline.duration, words.length ? _nullishCoalesce(words[words.length - 1].end, () => ( words[words.length - 1].start)) : 0)));
4421
- const shotAt = (ms) => _optionalChain([timeline, 'access', _162 => _162.shots, 'access', _163 => _163.find, 'call', _164 => _164((x) => ms >= x.start && ms < x.end), 'optionalAccess', _165 => _165.id]);
4545
+ const shotAt = (ms) => _optionalChain([timeline, 'access', _165 => _165.shots, 'access', _166 => _166.find, 'call', _167 => _167((x) => ms >= x.start && ms < x.end), 'optionalAccess', _168 => _168.id]);
4422
4546
  const beats = [];
4423
4547
  if (s.beat && s.beat.bpm > 0) {
4424
4548
  const first = Math.max(0, Math.ceil(motionBeatAt(s.beat, from).beat - 1e-9));
@@ -4640,7 +4764,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
4640
4764
  {
4641
4765
  name: { type: "string", pattern: "^[A-Za-z_][\\w-]*$", description: 'Clip name, e.g. "pop-settle".' },
4642
4766
  clip: {
4643
- anyOf: [object({ description: { type: "string", description: "What it does, in a few words." }, run: { type: "array", items: MOTION_COMMAND_SCHEMA, minItems: 1, description: 'Commands, timed as in a shot; target "$" for the node it is played on. Clips cannot play clips.' } }, ["run"]), { type: "null" }],
4767
+ anyOf: [object({ description: { type: "string", description: "What it does, in a few words." }, run: { type: "array", items: REF2("command"), minItems: 1, description: 'Commands, timed as in a shot; target "$" for the node it is played on. Clips cannot play clips.' } }, ["run"]), { type: "null" }],
4644
4768
  description: "The clip, or null to delete it (refused while a play command uses it)."
4645
4769
  }
4646
4770
  },
@@ -4698,7 +4822,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
4698
4822
  name: "insert_shots",
4699
4823
  title: "Add shots",
4700
4824
  description: "Adds shots (one undo step) at a position (default: the end). Returns every shot's new timing and any issues.",
4701
- inputSchema: object({ shots: { type: "array", items: SHOT, minItems: 1, description: "Shots to add." }, at: { type: "integer", minimum: 0, description: "Position, 0 = first (default: the end)." } }, ["shots"]),
4825
+ inputSchema: object({ shots: { type: "array", items: REF2("shot"), minItems: 1, description: "Shots to add." }, at: { type: "integer", minimum: 0, description: "Position, 0 = first (default: the end)." } }, ["shots"]),
4702
4826
  annotations: { title: "Add shots", ...WRITE },
4703
4827
  handler: ({ shots, at }) => apply({ op: "insert_shots", shots, at }, "Add shots", () => ({ added: shots.map((s) => s.id) }))
4704
4828
  };
@@ -4737,10 +4861,10 @@ function createAnimationEditorToolProvider(controller, options = {}) {
4737
4861
  name: "add_commands",
4738
4862
  title: "Add commands to a shot",
4739
4863
  description: "Adds commands to a shot's run (one undo step), at an index (default: the end). Returns the indexes they got, their timing and any issues.",
4740
- inputSchema: object({ shot: SHOT_ID, commands: { type: "array", items: MOTION_COMMAND_SCHEMA, minItems: 1, description: "Commands to add." }, at: { type: "integer", minimum: 0, description: "Index in the run (default: the end)." } }, ["shot", "commands"]),
4864
+ 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"]),
4741
4865
  annotations: { title: "Add commands to a shot", ...WRITE },
4742
4866
  handler: ({ shot, commands, at }) => {
4743
- const before = _nullishCoalesce(_optionalChain([scene, 'call', _166 => _166(), 'access', _167 => _167.shots, 'access', _168 => _168.find, 'call', _169 => _169((s) => s.id === shot), 'optionalAccess', _170 => _170.run, 'access', _171 => _171.length]), () => ( 0));
4867
+ const before = _nullishCoalesce(_optionalChain([scene, 'call', _169 => _169(), 'access', _170 => _170.shots, 'access', _171 => _171.find, 'call', _172 => _172((s) => s.id === shot), 'optionalAccess', _173 => _173.run, 'access', _174 => _174.length]), () => ( 0));
4744
4868
  const first = _nullishCoalesce(at, () => ( before));
4745
4869
  return apply({ op: "add_commands", shot, commands, at }, "Add commands", (s) => {
4746
4870
  const shots = describeMotionShots(s);
@@ -4757,7 +4881,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
4757
4881
  {
4758
4882
  shot: SHOT_ID,
4759
4883
  command: { type: "integer", minimum: 0, description: "Index in the shot's run (from get_animation)." },
4760
- set: { type: "object", description: "Command fields to replace (see add_commands for each type's fields)." },
4884
+ set: { type: "object", description: "Command fields to replace (describe_animation_command lists each type's fields)." },
4761
4885
  remove: { type: "array", items: { type: "string" }, description: 'Optional fields to clear (e.g. "delay").' }
4762
4886
  },
4763
4887
  ["shot", "command"]
@@ -4821,7 +4945,7 @@ function createAnimationEditorToolProvider(controller, options = {}) {
4821
4945
  name: "write_animation",
4822
4946
  title: "Replace the animation's shots",
4823
4947
  description: "Replaces every shot (and optionally the settings and controls), keeping the artwork, as one undo step. For small changes prefer the per-operation tools. Returns the timing and issues.",
4824
- inputSchema: object({ shots: { type: "array", items: SHOT, description: "All shots, in order." }, ...SETTINGS, controls: { type: "array", items: CONTROL, description: "Colour controls." }, presets: { type: "array", items: PRESET, description: "Presets." } }, ["shots"]),
4948
+ inputSchema: object({ shots: { type: "array", items: REF2("shot"), description: "All shots, in order." }, ...SETTINGS, controls: { type: "array", items: CONTROL, description: "Colour controls." }, presets: { type: "array", items: PRESET, description: "Presets." } }, ["shots"]),
4825
4949
  annotations: { title: "Replace the animation's shots", ...DESTRUCTIVE },
4826
4950
  handler: ({ shots, controls, presets, ...settings }) => {
4827
4951
  const current = scene();
@@ -4871,11 +4995,15 @@ function createAnimationEditorToolProvider(controller, options = {}) {
4871
4995
  return { redone, ...redone ? { label } : {} };
4872
4996
  }
4873
4997
  };
4874
- const reads = [getAnimation, getShot, findElements, getTextLayout, getMotionPath, getTimingGrid, checkAnimation, renderFrame, exportFlairMotion, exportFlairEffect, exportLottie, seekAnimation];
4875
- const writes = [setArtworkSvg, importPptx, setDrivers, setClip, copyAnimation, fitAnimation, importFlairEffect, insertShots, updateShot, deleteShots, moveShot, addCommands, updateCommand, deleteCommands, moveCommand, setSettings, setControls, editAnimation, writeAnimation, undo, redo];
4998
+ const finish = (tools) => tools.map((tool) => ({ ...tool, inputSchema: withDefs(tool.inputSchema) }));
4999
+ const reads = finish([getAnimation, getShot, describeCommand, findElements, getTextLayout, getMotionPath, getTimingGrid, checkAnimation, renderFrame, exportFlairMotion, exportFlairEffect, exportLottie, seekAnimation]);
5000
+ const writes = finish([setArtworkSvg, importPptx, setDrivers, setClip, copyAnimation, fitAnimation, importFlairEffect, insertShots, updateShot, deleteShots, moveShot, addCommands, updateCommand, deleteCommands, moveCommand, setSettings, setControls, editAnimation, writeAnimation, undo, redo]);
4876
5001
  return {
4877
5002
  id: _nullishCoalesce(options.id, () => ( "animation")),
4878
5003
  namespace: options.namespace,
5004
+ title: "Animation editor",
5005
+ description: "Vector animation: artwork, shots, animation commands and their timing, Flair and Lottie import and export, PowerPoint import.",
5006
+ skill: "pixerate-animation-editor",
4879
5007
  tools: () => readOnlyReason() ? reads : [...reads, ...writes],
4880
5008
  subscribe: (notify) => {
4881
5009
  let last = readOnlyReason();
@@ -4924,6 +5052,7 @@ Commands
4924
5052
  Working method
4925
5053
  1. get_animation to learn the element ids (set_animation_artwork_svg first if there is no artwork: give every element you will animate an id; or import_flair_effect / import_pptx_animation to start from a Flair effect or a PowerPoint slide).
4926
5054
  2. Plan a few shots, each one idea. Add them with insert_shots (add_commands, update_command, move_command and delete_commands refine a shot), or edit_animation to make several edits as one step (dry_run first when unsure).
5055
+ - The write tools list each command field once, saying which types take it; describe_animation_command gives a type's exact fields before you write one you have not used.
4927
5056
  - In edit_animation, a later op can use what an earlier one made: "$0.indexes[0]" (the first command op 1 added), "$last.shot".
4928
5057
  3. To hit a length, fit_animation (keep the shots whose pace matters). check_animation and fix every error and warning; render_animation_frame (shot + "end") to look at the result, or with "times" for a contact sheet of several moments; add onion_skin or motion_paths to see the motion in one picture, or get_motion_path for the numbers.
4929
5058
  - For something the viewer plays (a button, a toggle, a step-by-step explainer), set "trigger" with set_animation_settings: click plays the next shot on each click and then starts over (make the last shot put things back for a toggle), hover or press plays and rewinds, scroll scrubs.
@@ -4936,7 +5065,7 @@ var TIMING = /* @__PURE__ */ new Set(["duration", "delay", "stagger", "with", "e
4936
5065
  var COLORS = /* @__PURE__ */ new Set(["fill", "stroke", "color"]);
4937
5066
  var NODES = /* @__PURE__ */ new Set(["into", "path"]);
4938
5067
  function branch(type) {
4939
- return (_nullishCoalesce(MOTION_COMMAND_SCHEMA.oneOf, () => ( []))).find((b) => _optionalChain([b, 'access', _172 => _172.properties, 'optionalAccess', _173 => _173.type, 'optionalAccess', _174 => _174.const]) === type);
5068
+ return (_nullishCoalesce(MOTION_COMMAND_SCHEMA.oneOf, () => ( []))).find((b) => _optionalChain([b, 'access', _175 => _175.properties, 'optionalAccess', _176 => _176.type, 'optionalAccess', _177 => _177.const]) === type);
4940
5069
  }
4941
5070
  function unitOf(type, name) {
4942
5071
  if (name === "duration" || name === "delay" || name === "stagger") return "ms";
@@ -4971,7 +5100,7 @@ function kindOf(name, schema) {
4971
5100
  }
4972
5101
  function motionCommandFields(type) {
4973
5102
  const schema = branch(type);
4974
- if (!_optionalChain([schema, 'optionalAccess', _175 => _175.properties])) return [];
5103
+ if (!_optionalChain([schema, 'optionalAccess', _178 => _178.properties])) return [];
4975
5104
  const required = new Set(_nullishCoalesce(schema.required, () => ( [])));
4976
5105
  const fields = Object.entries(schema.properties).filter(([name]) => name !== "type").map(([name, s]) => {
4977
5106
  const kind = kindOf(name, s);
@@ -5028,7 +5157,7 @@ function defaultMotionCommand(type, targets, scene) {
5028
5157
  if (type === "wait") return { type: "wait", duration: 500 };
5029
5158
  if (!targets.length) return { error: "Pick a target first: click an element on the stage." };
5030
5159
  const nodes = [...indexMotionNodes(scene.artwork.nodes).values()];
5031
- const other = (pred) => _optionalChain([nodes, 'access', _176 => _176.find, 'call', _177 => _177((e) => !targets.includes(e.node.id) && pred(e)), 'optionalAccess', _178 => _178.node, 'access', _179 => _179.id]);
5160
+ const other = (pred) => _optionalChain([nodes, 'access', _179 => _179.find, 'call', _180 => _180((e) => !targets.includes(e.node.id) && pred(e)), 'optionalAccess', _181 => _181.node, 'access', _182 => _182.id]);
5032
5161
  const base = { targets: [...targets] };
5033
5162
  switch (type) {
5034
5163
  case "scale":
@@ -5059,8 +5188,8 @@ function defaultMotionCommand(type, targets, scene) {
5059
5188
  }
5060
5189
  case "effect": {
5061
5190
  for (const id of targets) {
5062
- const node = _optionalChain([nodes, 'access', _180 => _180.find, 'call', _181 => _181((e) => e.node.id === id), 'optionalAccess', _182 => _182.node]);
5063
- for (const effect of _nullishCoalesce(_optionalChain([node, 'optionalAccess', _183 => _183.effects]), () => ( []))) {
5191
+ const node = _optionalChain([nodes, 'access', _183 => _183.find, 'call', _184 => _184((e) => e.node.id === id), 'optionalAccess', _185 => _185.node]);
5192
+ for (const effect of _nullishCoalesce(_optionalChain([node, 'optionalAccess', _186 => _186.effects]), () => ( []))) {
5064
5193
  const param = Object.entries(effect.params).find(([, v]) => typeof v === "number");
5065
5194
  if (param) return { type, ...base, effect: effect.id, param: param[0], to: param[1] + 1 };
5066
5195
  }
@@ -5085,11 +5214,11 @@ function motionCommandRows(scene, shotId) {
5085
5214
  return scene.shots[index].run.map((command3, i) => {
5086
5215
  const t = timeline.commands.find((c) => c.shotIndex === index && c.command === i);
5087
5216
  const primitive = motionFlairPrimitive(command3);
5088
- return { index: i, command: command3, summary: motionCommandSummary(command3), start: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _184 => _184.start]), () => ( 0)), end: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _185 => _185.end]), () => ( 0)), ...primitive ? { flairPrimitive: primitive } : {} };
5217
+ return { index: i, command: command3, summary: motionCommandSummary(command3), start: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _187 => _187.start]), () => ( 0)), end: _nullishCoalesce(_optionalChain([t, 'optionalAccess', _188 => _188.end]), () => ( 0)), ...primitive ? { flairPrimitive: primitive } : {} };
5089
5218
  });
5090
5219
  }
5091
5220
  function duplicateMotionCommandEdit(scene, shot, command3) {
5092
- const run = _nullishCoalesce(_optionalChain([scene, 'access', _186 => _186.shots, 'access', _187 => _187.find, 'call', _188 => _188((s) => s.id === shot), 'optionalAccess', _189 => _189.run]), () => ( []));
5221
+ const run = _nullishCoalesce(_optionalChain([scene, 'access', _189 => _189.shots, 'access', _190 => _190.find, 'call', _191 => _191((s) => s.id === shot), 'optionalAccess', _192 => _192.run]), () => ( []));
5093
5222
  return { op: "add_commands", shot, commands: run[command3] ? [structuredClone(run[command3])] : [], at: command3 + 1 };
5094
5223
  }
5095
5224
  var MOTION_EASE_CHOICES = [
@@ -5174,7 +5303,7 @@ function motionCueFromKey(key) {
5174
5303
  function motionCueChoices(scene, limit = 256) {
5175
5304
  const choices = [];
5176
5305
  const s = (ms) => `${(ms / 1e3).toFixed(2)} s`;
5177
- const end = Math.max(compileMotionScene(scene).duration, ..._nullishCoalesce(_optionalChain([scene, 'access', _190 => _190.narration, 'optionalAccess', _191 => _191.words, 'access', _192 => _192.map, 'call', _193 => _193((w) => _nullishCoalesce(w.end, () => ( w.start)))]), () => ( [0]))) + 2e3;
5306
+ const end = Math.max(compileMotionScene(scene).duration, ..._nullishCoalesce(_optionalChain([scene, 'access', _193 => _193.narration, 'optionalAccess', _194 => _194.words, 'access', _195 => _195.map, 'call', _196 => _196((w) => _nullishCoalesce(w.end, () => ( w.start)))]), () => ( [0]))) + 2e3;
5178
5307
  if (scene.beat && scene.beat.bpm > 0) {
5179
5308
  for (let beat = 0; choices.length < limit; beat++) {
5180
5309
  const time = motionBeatTime(scene.beat, beat);
@@ -5184,7 +5313,7 @@ function motionCueChoices(scene, limit = 256) {
5184
5313
  choices.push({ value: `beat:${beat}`, label: `Beat ${beat} (bar ${at.bar}.${at.beatInBar}) \xB7 ${s(time)}`, time });
5185
5314
  }
5186
5315
  }
5187
- _optionalChain([scene, 'access', _194 => _194.narration, 'optionalAccess', _195 => _195.words, 'access', _196 => _196.forEach, 'call', _197 => _197((w, i) => {
5316
+ _optionalChain([scene, 'access', _197 => _197.narration, 'optionalAccess', _198 => _198.words, 'access', _199 => _199.forEach, 'call', _200 => _200((w, i) => {
5188
5317
  if (choices.length < limit * 2) choices.push({ value: `word:${i}`, label: `Word ${i} \u201C${w.text}\u201D \xB7 ${s(w.start)}`, time: w.start });
5189
5318
  })]);
5190
5319
  return choices;
@@ -5193,7 +5322,7 @@ function motionShotCueTime(scene, cue) {
5193
5322
  return cue ? motionCueTime(scene, cue) : void 0;
5194
5323
  }
5195
5324
  function formatMotionNarration(narration) {
5196
- return (_nullishCoalesce(_optionalChain([narration, 'optionalAccess', _198 => _198.words]), () => ( []))).map((w) => `${w.start} ${w.text}`).join("\n");
5325
+ return (_nullishCoalesce(_optionalChain([narration, 'optionalAccess', _201 => _201.words]), () => ( []))).map((w) => `${w.start} ${w.text}`).join("\n");
5197
5326
  }
5198
5327
  function parseMotionNarration(text) {
5199
5328
  const lines = text.split("\n").map((l) => l.trim()).filter(Boolean);
@@ -5242,9 +5371,12 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
5242
5371
  if (!r.ok) throw new Error(r.error);
5243
5372
  return { target, effect: info(r.effect), effects: controller.appliedEffects().filter((e) => e.targets.includes(target)).map(info), ...r.notes.length ? { notes: r.notes } : {} };
5244
5373
  };
5245
- return _chunk3V746PF4cjs.createEffectToolProvider.call(void 0, {
5374
+ return _chunkRUZQMYXHcjs.createEffectToolProvider.call(void 0, {
5246
5375
  id: _nullishCoalesce(options.id, () => ( "animation-effects")),
5247
5376
  namespace: options.namespace,
5377
+ title: "Animation effects",
5378
+ description: "Provider motion effects on nodes of the animation artwork.",
5379
+ skill: "pixerate-animation-editor",
5248
5380
  target: { noun: "node", id: "A node id of the artwork from get_animation (a group animates as one)." },
5249
5381
  applyUses: ["motion"],
5250
5382
  applyDetails: "The provider animates the node and its changes become ordinary commands (enter, fade, move, pulse\u2026), in a new shot after the last one, tagged with the effect so it can be changed or removed as a whole. They preview, play and export to Flair like any command. Vector effects with their own picture go through add_vector_effect. index, enabled and opacity do not apply here.",
@@ -5459,4 +5591,6 @@ function createAnimationEffectsToolProvider(controller, options = {}) {
5459
5591
 
5460
5592
 
5461
5593
 
5462
- exports.ANIMATION_EDITOR_AGENT_INSTRUCTIONS = ANIMATION_EDITOR_AGENT_INSTRUCTIONS; exports.AnimationEditorController = AnimationEditorController; exports.FLAIR_EASES = FLAIR_EASES; exports.FLAIR_EXPORT_VERSION = FLAIR_EXPORT_VERSION; exports.MOTION_ADDITIVE_PROPERTIES = MOTION_ADDITIVE_PROPERTIES; exports.MOTION_BLENDS = MOTION_BLENDS; exports.MOTION_CAMERA_MS = MOTION_CAMERA_MS; exports.MOTION_CASCADES = MOTION_CASCADES; exports.MOTION_CLIP_TARGET = MOTION_CLIP_TARGET; exports.MOTION_COMMAND_SCHEMA = MOTION_COMMAND_SCHEMA; exports.MOTION_COMMAND_TYPES = MOTION_COMMAND_TYPES; exports.MOTION_DEFAULT_DURATIONS = MOTION_DEFAULT_DURATIONS; exports.MOTION_DEFAULT_HOLD = MOTION_DEFAULT_HOLD; exports.MOTION_DIRECTIONS = MOTION_DIRECTIONS; exports.MOTION_DRAW_EFFECT_ID = MOTION_DRAW_EFFECT_ID; exports.MOTION_DRAW_MS_PER_UNIT = MOTION_DRAW_MS_PER_UNIT; exports.MOTION_DRAW_RANGE = MOTION_DRAW_RANGE; exports.MOTION_DRIVEN_PROPERTIES = MOTION_DRIVEN_PROPERTIES; exports.MOTION_EASE_CHOICES = MOTION_EASE_CHOICES; exports.MOTION_EASE_IN_OUT = MOTION_EASE_IN_OUT; exports.MOTION_EASE_OUT = MOTION_EASE_OUT; exports.MOTION_EDIT_OPS = MOTION_EDIT_OPS; exports.MOTION_ENTER_STYLES = MOTION_ENTER_STYLES; exports.MOTION_EXIT_STYLES = MOTION_EXIT_STYLES; exports.MOTION_IRIS_SHAPES = MOTION_IRIS_SHAPES; exports.MOTION_ISSUE_CODES = _chunkEBDZWIOPcjs.MOTION_ISSUE_CODES; exports.MOTION_MIN_CHANGE_MS = MOTION_MIN_CHANGE_MS; exports.MOTION_REPEAT_MODES = MOTION_REPEAT_MODES; exports.MOTION_SPEED_RANGE = MOTION_SPEED_RANGE; exports.MOTION_SPLIT_ORIENTATIONS = MOTION_SPLIT_ORIENTATIONS; exports.MOTION_TEXT_STAGGER = MOTION_TEXT_STAGGER; exports.MOTION_TEXT_UNITS = MOTION_TEXT_UNITS; exports.MOTION_TRIGGERS = MOTION_TRIGGERS; exports.MotionSceneFormatError = MotionSceneFormatError; exports.activeSegment = activeSegment; exports.applyMotionControlValues = applyMotionControlValues; exports.applyMotionDrivers = applyMotionDrivers; exports.applyMotionEdits = applyMotionEdits; exports.checkMotionScene = checkMotionScene; exports.clipsShapeProblems = clipsShapeProblems; exports.commandShapeProblems = commandShapeProblems; exports.compileMotionScene = compileMotionScene; exports.createAnimationEditorToolProvider = createAnimationEditorToolProvider; exports.createAnimationEffectsToolProvider = createAnimationEffectsToolProvider; exports.createMotionScene = createMotionScene; exports.defaultMotionCommand = defaultMotionCommand; exports.describeMotionElements = describeMotionElements; exports.describeMotionShots = describeMotionShots; exports.driversShapeProblems = driversShapeProblems; exports.duplicateMotionCommandEdit = duplicateMotionCommandEdit; exports.fitMotionRect = fitMotionRect; exports.fitMotionScene = fitMotionScene; exports.fitMotionSceneEdits = fitMotionSceneEdits; exports.flairAtLeast = flairAtLeast; exports.flairCurveFor = flairCurveFor; exports.flairEaseFor = flairEaseFor; exports.formatMotionDrivers = formatMotionDrivers; exports.formatMotionNarration = formatMotionNarration; exports.freshShotId = freshShotId; exports.fromFlairSvgMotion = fromFlairSvgMotion; exports.fromFlairVectorEffect = fromFlairVectorEffect; exports.fromPptxAnimation = fromPptxAnimation; exports.highlightMotionSvg = highlightMotionSvg; exports.indexMotionNodes = indexMotionNodes; exports.interpolateMotionValue = interpolateMotionValue; exports.isMotionCommand = isMotionCommand; exports.isMotionShot = isMotionShot; exports.matchMotionNodes = matchMotionNodes; exports.motionAddTrackKey = motionAddTrackKey; exports.motionArtworkSvg = motionArtworkSvg; exports.motionBeatAt = motionBeatAt; exports.motionBeatTime = motionBeatTime; exports.motionBlurTimes = motionBlurTimes; exports.motionCascade = motionCascade; exports.motionClipAttrs = motionClipAttrs; exports.motionClipLayout = motionClipLayout; exports.motionCommandDuration = motionCommandDuration; exports.motionCommandFields = motionCommandFields; exports.motionCommandRepeat = motionCommandRepeat; exports.motionCommandRows = motionCommandRows; exports.motionCommandSlots = motionCommandSlots; exports.motionCommandSummary = motionCommandSummary; exports.motionCommandsFromEffect = motionCommandsFromEffect; exports.motionContactSheetSvg = motionContactSheetSvg; exports.motionCueChoices = motionCueChoices; exports.motionCueFromKey = motionCueFromKey; exports.motionCueKey = motionCueKey; exports.motionCueTime = motionCueTime; exports.motionCycleDuration = motionCycleDuration; exports.motionDrivenNodes = motionDrivenNodes; exports.motionDriverSources = motionDriverSources; exports.motionEaseKey = motionEaseKey; exports.motionEasingCurve = motionEasingCurve; exports.motionEasingGuides = motionEasingGuides; exports.motionEasingPath = motionEasingPath; exports.motionFieldEdit = motionFieldEdit; exports.motionFieldLabel = motionFieldLabel; exports.motionFlairPrimitive = motionFlairPrimitive; exports.motionFollowRoute = motionFollowRoute; exports.motionFrameAt = motionFrameAt; exports.motionFrameToSvg = motionFrameToSvg; exports.motionGhosts = motionGhosts; exports.motionIssue = _chunkEBDZWIOPcjs.motionIssue; exports.motionIssueKey = _chunkEBDZWIOPcjs.motionIssueKey; exports.motionIssueLine = _chunkEBDZWIOPcjs.motionIssueLine; exports.motionMovingIds = motionMovingIds; exports.motionNodeAtElement = motionNodeAtElement; exports.motionNodeClips = motionNodeClips; exports.motionNodeOffset = motionNodeOffset; exports.motionPartsFromVectorEffect = motionPartsFromVectorEffect; exports.motionPath = motionPath; exports.motionPathLength = motionPathLength; exports.motionPathsSvg = motionPathsSvg; exports.motionPropertyValue = motionPropertyValue; exports.motionRestValue = motionRestValue; exports.motionRevealClip = motionRevealClip; exports.motionRevealPadding = motionRevealPadding; exports.motionRulerTicks = motionRulerTicks; exports.motionSceneEffects = motionSceneEffects; exports.motionSceneShapeProblems = motionSceneShapeProblems; exports.motionSceneToJson = motionSceneToJson; exports.motionShotAt = motionShotAt; exports.motionShotCueTime = motionShotCueTime; exports.motionShotTimeScale = motionShotTimeScale; exports.motionStageSvg = motionStageSvg; exports.motionTextLayout = motionTextLayout; exports.motionTextUnits = motionTextUnits; exports.motionTrackKey = motionTrackKey; exports.namedWithSuggestion = _chunkEBDZWIOPcjs.namedWithSuggestion; exports.nextMotionEffectInstance = nextMotionEffectInstance; exports.parseMotionDrivers = parseMotionDrivers; exports.parseMotionFieldInput = parseMotionFieldInput; exports.parseMotionNarration = parseMotionNarration; exports.parseMotionScene = parseMotionScene; exports.resolveMotionCamera = resolveMotionCamera; exports.resolveMotionEditRefs = resolveMotionEditRefs; exports.segmentProgress = segmentProgress; exports.segmentValue = segmentValue; exports.shotShapeProblems = shotShapeProblems; exports.smoothMotionLegs = smoothMotionLegs; exports.smoothMotionTimes = smoothMotionTimes; exports.suggestName = _chunkEBDZWIOPcjs.suggestName; exports.toFlairEffectDocument = toFlairEffectDocument; exports.toFlairSvgMotion = toFlairSvgMotion; exports.toFlairVectorEffect = toFlairVectorEffect; exports.toLottie = toLottie; exports.trackValue = trackValue; exports.withMotionLayers = withMotionLayers; exports.withViewBox = withViewBox; exports.withoutMotionEffect = withoutMotionEffect;
5594
+
5595
+
5596
+ exports.ANIMATION_EDITOR_AGENT_INSTRUCTIONS = ANIMATION_EDITOR_AGENT_INSTRUCTIONS; exports.AnimationEditorController = AnimationEditorController; exports.FLAIR_EASES = FLAIR_EASES; exports.FLAIR_EXPORT_VERSION = FLAIR_EXPORT_VERSION; exports.MOTION_ADDITIVE_PROPERTIES = MOTION_ADDITIVE_PROPERTIES; exports.MOTION_BLENDS = MOTION_BLENDS; exports.MOTION_CAMERA_MS = MOTION_CAMERA_MS; exports.MOTION_CASCADES = MOTION_CASCADES; exports.MOTION_CLIP_TARGET = MOTION_CLIP_TARGET; exports.MOTION_COMMAND_FIELDS = MOTION_COMMAND_FIELDS; exports.MOTION_COMMAND_SCHEMA = MOTION_COMMAND_SCHEMA; exports.MOTION_COMMAND_TYPES = MOTION_COMMAND_TYPES; exports.MOTION_COMMAND_TYPE_SCHEMAS = MOTION_COMMAND_TYPE_SCHEMAS; exports.MOTION_DEFAULT_DURATIONS = MOTION_DEFAULT_DURATIONS; exports.MOTION_DEFAULT_HOLD = MOTION_DEFAULT_HOLD; exports.MOTION_DIRECTIONS = MOTION_DIRECTIONS; exports.MOTION_DRAW_EFFECT_ID = MOTION_DRAW_EFFECT_ID; exports.MOTION_DRAW_MS_PER_UNIT = MOTION_DRAW_MS_PER_UNIT; exports.MOTION_DRAW_RANGE = MOTION_DRAW_RANGE; exports.MOTION_DRIVEN_PROPERTIES = MOTION_DRIVEN_PROPERTIES; exports.MOTION_EASE_CHOICES = MOTION_EASE_CHOICES; exports.MOTION_EASE_IN_OUT = MOTION_EASE_IN_OUT; exports.MOTION_EASE_OUT = MOTION_EASE_OUT; exports.MOTION_EDIT_OPS = MOTION_EDIT_OPS; exports.MOTION_ENTER_STYLES = MOTION_ENTER_STYLES; exports.MOTION_EXIT_STYLES = MOTION_EXIT_STYLES; exports.MOTION_IRIS_SHAPES = MOTION_IRIS_SHAPES; exports.MOTION_ISSUE_CODES = _chunkEBDZWIOPcjs.MOTION_ISSUE_CODES; exports.MOTION_MIN_CHANGE_MS = MOTION_MIN_CHANGE_MS; exports.MOTION_REPEAT_MODES = MOTION_REPEAT_MODES; exports.MOTION_SPEED_RANGE = MOTION_SPEED_RANGE; exports.MOTION_SPLIT_ORIENTATIONS = MOTION_SPLIT_ORIENTATIONS; exports.MOTION_TEXT_STAGGER = MOTION_TEXT_STAGGER; exports.MOTION_TEXT_UNITS = MOTION_TEXT_UNITS; exports.MOTION_TRIGGERS = MOTION_TRIGGERS; exports.MotionSceneFormatError = MotionSceneFormatError; exports.activeSegment = activeSegment; exports.applyMotionControlValues = applyMotionControlValues; exports.applyMotionDrivers = applyMotionDrivers; exports.applyMotionEdits = applyMotionEdits; exports.checkMotionScene = checkMotionScene; exports.clipsShapeProblems = clipsShapeProblems; exports.commandShapeProblems = commandShapeProblems; exports.compileMotionScene = compileMotionScene; exports.createAnimationEditorToolProvider = createAnimationEditorToolProvider; exports.createAnimationEffectsToolProvider = createAnimationEffectsToolProvider; exports.createMotionScene = createMotionScene; exports.defaultMotionCommand = defaultMotionCommand; exports.describeMotionElements = describeMotionElements; exports.describeMotionShots = describeMotionShots; exports.driversShapeProblems = driversShapeProblems; exports.duplicateMotionCommandEdit = duplicateMotionCommandEdit; exports.fitMotionRect = fitMotionRect; exports.fitMotionScene = fitMotionScene; exports.fitMotionSceneEdits = fitMotionSceneEdits; exports.flairAtLeast = flairAtLeast; exports.flairCurveFor = flairCurveFor; exports.flairEaseFor = flairEaseFor; exports.formatMotionDrivers = formatMotionDrivers; exports.formatMotionNarration = formatMotionNarration; exports.freshShotId = freshShotId; exports.fromFlairSvgMotion = fromFlairSvgMotion; exports.fromFlairVectorEffect = fromFlairVectorEffect; exports.fromPptxAnimation = fromPptxAnimation; exports.highlightMotionSvg = highlightMotionSvg; exports.indexMotionNodes = indexMotionNodes; exports.interpolateMotionValue = interpolateMotionValue; exports.isMotionCommand = isMotionCommand; exports.isMotionShot = isMotionShot; exports.matchMotionNodes = matchMotionNodes; exports.motionAddTrackKey = motionAddTrackKey; exports.motionArtworkSvg = motionArtworkSvg; exports.motionBeatAt = motionBeatAt; exports.motionBeatTime = motionBeatTime; exports.motionBlurTimes = motionBlurTimes; exports.motionCascade = motionCascade; exports.motionClipAttrs = motionClipAttrs; exports.motionClipLayout = motionClipLayout; exports.motionCommandDuration = motionCommandDuration; exports.motionCommandFields = motionCommandFields; exports.motionCommandRepeat = motionCommandRepeat; exports.motionCommandRows = motionCommandRows; exports.motionCommandSlots = motionCommandSlots; exports.motionCommandSummary = motionCommandSummary; exports.motionCommandsFromEffect = motionCommandsFromEffect; exports.motionContactSheetSvg = motionContactSheetSvg; exports.motionCueChoices = motionCueChoices; exports.motionCueFromKey = motionCueFromKey; exports.motionCueKey = motionCueKey; exports.motionCueTime = motionCueTime; exports.motionCycleDuration = motionCycleDuration; exports.motionDrivenNodes = motionDrivenNodes; exports.motionDriverSources = motionDriverSources; exports.motionEaseKey = motionEaseKey; exports.motionEasingCurve = motionEasingCurve; exports.motionEasingGuides = motionEasingGuides; exports.motionEasingPath = motionEasingPath; exports.motionFieldEdit = motionFieldEdit; exports.motionFieldLabel = motionFieldLabel; exports.motionFlairPrimitive = motionFlairPrimitive; exports.motionFollowRoute = motionFollowRoute; exports.motionFrameAt = motionFrameAt; exports.motionFrameToSvg = motionFrameToSvg; exports.motionGhosts = motionGhosts; exports.motionIssue = _chunkEBDZWIOPcjs.motionIssue; exports.motionIssueKey = _chunkEBDZWIOPcjs.motionIssueKey; exports.motionIssueLine = _chunkEBDZWIOPcjs.motionIssueLine; exports.motionMovingIds = motionMovingIds; exports.motionNodeAtElement = motionNodeAtElement; exports.motionNodeClips = motionNodeClips; exports.motionNodeOffset = motionNodeOffset; exports.motionPartsFromVectorEffect = motionPartsFromVectorEffect; exports.motionPath = motionPath; exports.motionPathLength = motionPathLength; exports.motionPathsSvg = motionPathsSvg; exports.motionPropertyValue = motionPropertyValue; exports.motionRestValue = motionRestValue; exports.motionRevealClip = motionRevealClip; exports.motionRevealPadding = motionRevealPadding; exports.motionRulerTicks = motionRulerTicks; exports.motionSceneEffects = motionSceneEffects; exports.motionSceneShapeProblems = motionSceneShapeProblems; exports.motionSceneToJson = motionSceneToJson; exports.motionShotAt = motionShotAt; exports.motionShotCueTime = motionShotCueTime; exports.motionShotTimeScale = motionShotTimeScale; exports.motionStageSvg = motionStageSvg; exports.motionTextLayout = motionTextLayout; exports.motionTextUnits = motionTextUnits; exports.motionTrackKey = motionTrackKey; exports.namedWithSuggestion = _chunkEBDZWIOPcjs.namedWithSuggestion; exports.nextMotionEffectInstance = nextMotionEffectInstance; exports.parseMotionDrivers = parseMotionDrivers; exports.parseMotionFieldInput = parseMotionFieldInput; exports.parseMotionNarration = parseMotionNarration; exports.parseMotionScene = parseMotionScene; exports.resolveMotionCamera = resolveMotionCamera; exports.resolveMotionEditRefs = resolveMotionEditRefs; exports.segmentProgress = segmentProgress; exports.segmentValue = segmentValue; exports.shotShapeProblems = shotShapeProblems; exports.smoothMotionLegs = smoothMotionLegs; exports.smoothMotionTimes = smoothMotionTimes; exports.suggestName = _chunkEBDZWIOPcjs.suggestName; exports.toFlairEffectDocument = toFlairEffectDocument; exports.toFlairSvgMotion = toFlairSvgMotion; exports.toFlairVectorEffect = toFlairVectorEffect; exports.toLottie = toLottie; exports.trackValue = trackValue; exports.withMotionLayers = withMotionLayers; exports.withViewBox = withViewBox; exports.withoutMotionEffect = withoutMotionEffect;