@pixerate/editor 0.60.0 → 0.62.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.
@@ -75,6 +75,11 @@ interface MotionShot {
75
75
  run: MotionCommand[];
76
76
  /** Milliseconds to hold after the commands finish (default 600). */
77
77
  hold?: number;
78
+ /**
79
+ * Plays the whole shot this many times as fast (default 1): its camera move, delays,
80
+ * durations, staggers and hold all scale by 1 / speed. `fit_animation` sets it to fit a length.
81
+ */
82
+ speed?: number;
78
83
  }
79
84
  /** Fields every command takes. */
80
85
  interface MotionCommandBase {
@@ -223,6 +228,17 @@ interface MotionMorphCommand extends MotionCommandBase {
223
228
  type: 'morph';
224
229
  into: string;
225
230
  }
231
+ /**
232
+ * Smart Animate: tweens a group into another group (`into`, usually hidden), part by part. Each
233
+ * part of the target takes the shape, paint and place of its partner in `into`, paired by name,
234
+ * then by id (`card-a-title` ↔ `card-b-title`), then by kind in order. Parts with no partner fade
235
+ * out; parts of `into` with no partner do not appear (`check` lists them).
236
+ */
237
+ interface MotionMatchCommand extends MotionCommandBase {
238
+ type: 'match';
239
+ /** Id of the group (or node) to become. */
240
+ into: string;
241
+ }
226
242
  /** Moves targets along a path node, centre on the path. */
227
243
  interface MotionFollowCommand extends MotionCommandBase {
228
244
  type: 'follow';
@@ -346,7 +362,7 @@ interface MotionWaitCommand {
346
362
  with?: 'after' | 'previous';
347
363
  note?: string;
348
364
  }
349
- type MotionCommand = MotionEnterCommand | MotionExitCommand | MotionDrawCommand | MotionMoveCommand | MotionRotateCommand | MotionScaleCommand | MotionFadeCommand | MotionStyleCommand | MotionMorphCommand | MotionFollowCommand | MotionPulseCommand | MotionShakeCommand | MotionTeeterCommand | MotionWaveCommand | MotionWiggleCommand | MotionColorPulseCommand | MotionEffectCommand | MotionWaitCommand;
365
+ type MotionCommand = MotionEnterCommand | MotionExitCommand | MotionDrawCommand | MotionMoveCommand | MotionRotateCommand | MotionScaleCommand | MotionFadeCommand | MotionStyleCommand | MotionMorphCommand | MotionMatchCommand | MotionFollowCommand | MotionPulseCommand | MotionShakeCommand | MotionTeeterCommand | MotionWaveCommand | MotionWiggleCommand | MotionColorPulseCommand | MotionEffectCommand | MotionWaitCommand;
350
366
  type MotionCommandType = MotionCommand['type'];
351
367
  declare const MOTION_COMMAND_TYPES: readonly MotionCommandType[];
352
368
  declare const MOTION_ENTER_STYLES: readonly MotionEnterStyle[];
@@ -425,6 +441,14 @@ declare const MOTION_ISSUE_CODES: {
425
441
  readonly severity: "error";
426
442
  readonly wording: "A morph names a shape the artwork does not have.";
427
443
  };
444
+ readonly 'match-self': {
445
+ readonly severity: "error";
446
+ readonly wording: "A match turns a group into itself or into a group it holds (or that holds it).";
447
+ };
448
+ readonly 'match-unpaired': {
449
+ readonly severity: "note";
450
+ readonly wording: "Parts of a match's \"into\" group have no partner in the target, so they do not appear.";
451
+ };
428
452
  readonly 'unknown-effect': {
429
453
  readonly severity: "error";
430
454
  readonly wording: "An effect command names an effect the node does not have.";
@@ -711,6 +735,8 @@ declare function fitMotionRect(rect: MotionRect, aspect: number): MotionRect;
711
735
  declare function resolveMotionCamera(camera: MotionCamera, scene: MotionScene): MotionRect | null;
712
736
  /** Length of a node's outline (its longest path for a group), in document units. */
713
737
  declare function motionPathLength(node: VectorNode, parentWorld?: AffineMatrix): number;
738
+ /** How much a shot's `speed` stretches its time (1 / speed; 1 when unset or not above 0). */
739
+ declare function motionShotTimeScale(shot: MotionShot): number;
714
740
  /** How many times a command plays (1 for `enter`, `exit` and `wait`, which do not repeat). */
715
741
  declare function motionCommandRepeat(command: MotionCommand): number;
716
742
  /** How long one target of a command takes (ms), every repeat included. */
@@ -730,6 +756,23 @@ declare function compileMotionScene(scene: MotionScene): MotionTimeline;
730
756
  /** The shot playing at `time` (the last one at the end). */
731
757
  declare function motionShotAt(timeline: MotionTimeline, time: number): MotionShotTiming | undefined;
732
758
 
759
+ /** How the parts of one node pair with the parts of another for a `match` (Smart Animate). */
760
+ interface MotionMatch {
761
+ /** `[from id, into id]`: each part of the target and the part of `into` it becomes. */
762
+ pairs: [string, string][];
763
+ /** Parts of the target with no partner (they fade out). */
764
+ unpairedFrom: string[];
765
+ /** Parts of `into` with no partner (they cannot appear). */
766
+ unpairedInto: string[];
767
+ }
768
+ /**
769
+ * Pairs the parts of `from` with the parts of `into`, each part used once, in passes: the same
770
+ * `name`, then the same id once each group's own id is taken out, then the same kind in order.
771
+ * Paired groups pair their own parts the same way, so a part pairs with a part, never a group
772
+ * with a path. Two paths (or a path and a group with no children) pair whole.
773
+ */
774
+ declare function matchMotionNodes(from: VectorNode, into: VectorNode): MotionMatch;
775
+
733
776
  /**
734
777
  * A reveal clip (`wipe`, `iris`, `split`) in the units of the node's own box: 0–1 across it,
735
778
  * as SVG's `clipPathUnits="objectBoundingBox"` and Flair's clip reveals are.
@@ -841,7 +884,7 @@ type MotionEdit = {
841
884
  op: 'update_shot';
842
885
  shot: string;
843
886
  set?: Partial<MotionShot>;
844
- remove?: ('label' | 'camera' | 'hold')[];
887
+ remove?: ('label' | 'camera' | 'hold' | 'speed')[];
845
888
  } | {
846
889
  op: 'delete_shots';
847
890
  shots: string[];
@@ -895,6 +938,27 @@ declare function applyMotionEdits(scene: MotionScene, edits: MotionEdit | readon
895
938
  /** An empty scene over `artwork`. */
896
939
  declare function createMotionScene(artwork: VectorDocument, init?: Partial<Omit<MotionScene, 'artwork' | 'version'>>): MotionScene;
897
940
 
941
+ interface MotionFitOptions {
942
+ /** Shot ids that keep their pace (a logo hold, a line of narration); the others absorb the change. */
943
+ keep?: readonly string[];
944
+ }
945
+ interface MotionFit {
946
+ scene: MotionScene;
947
+ /** The length after fitting, ms (within a few ms of the target: speeds are rounded). */
948
+ duration: number;
949
+ /** The new `speed` of every shot that changed. */
950
+ speeds: Record<string, number>;
951
+ }
952
+ /** Speeds are kept within this range. */
953
+ declare const MOTION_SPEED_RANGE: readonly [number, number];
954
+ /**
955
+ * Fits a scene to `ms` by setting its shots' `speed`: the shots in `keep` play as they are and
956
+ * the rest stretch or squeeze by the same factor, so their timing keeps its proportions (the
957
+ * responsive time of After Effects' protected regions). Throws, changing nothing, when the
958
+ * kept shots alone outlast the target or a speed would leave `MOTION_SPEED_RANGE`.
959
+ */
960
+ declare function fitMotionScene(scene: MotionScene, ms: number, options?: MotionFitOptions): MotionFit;
961
+
898
962
  /**
899
963
  * Export to Flair (`@pixerate/flair`): a scene becomes an `SvgMotion` (one SVG plus a list of
900
964
  * from → to changes on its elements), a catalog `VectorEffect`, or an `EffectDocument` for
@@ -1435,6 +1499,23 @@ declare function describeMotionShots(scene: MotionScene): {
1435
1499
  repeatMode?: "loop" | "mirror" | "offset";
1436
1500
  steps?: number;
1437
1501
  index: number;
1502
+ } | {
1503
+ flairPrimitive?: string | undefined;
1504
+ start: number;
1505
+ end: number;
1506
+ type: "match";
1507
+ into: string;
1508
+ targets: string[];
1509
+ duration?: number;
1510
+ delay?: number;
1511
+ stagger?: number;
1512
+ with?: "after" | "previous";
1513
+ ease?: AnimationEasing;
1514
+ note?: string;
1515
+ repeat?: number;
1516
+ repeatMode?: "loop" | "mirror" | "offset";
1517
+ steps?: number;
1518
+ index: number;
1438
1519
  } | {
1439
1520
  flairPrimitive?: string | undefined;
1440
1521
  start: number;
@@ -1622,6 +1703,6 @@ declare function createAnimationEditorToolProvider(controller: AnimationEditorCo
1622
1703
  * A short authoring guide for a model writing vector animations with the animation editor's
1623
1704
  * tools. Static, so it caches well as part of a system prompt.
1624
1705
  */
1625
- declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. 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 to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots, or edit_animation to make several edits as one step (dry_run first when unsure).\n3. check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
1706
+ declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. 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 to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots, or edit_animation to make several edits as one step (dry_run first when unsure).\n3. 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.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
1626
1707
 
1627
- export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPLIT_ORIENTATIONS, type MotionCamera, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionControl, type MotionDirection, type MotionDrawCommand, type MotionEdit, type MotionEditOp, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMorphCommand, type MotionMoveCommand, type MotionNodeEntry, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, describeMotionElements, describeMotionShots, fitMotionRect, flairAtLeast, flairCurveFor, flairEaseFor, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, motionAddTrackKey, motionClipAttrs, motionCommandDuration, motionCommandRepeat, motionCycleDuration, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionIssue, motionIssueKey, motionIssueLine, motionNodeClips, motionNodeOffset, motionPathLength, motionRestValue, motionRevealClip, motionRevealPadding, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionTrackKey, namedWithSuggestion, parseMotionScene, resolveMotionCamera, segmentProgress, segmentValue, shotShapeProblems, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, trackValue, withMotionLayers, withViewBox };
1708
+ export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPEED_RANGE, MOTION_SPLIT_ORIENTATIONS, type MotionCamera, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionControl, type MotionDirection, type MotionDrawCommand, type MotionEdit, type MotionEditOp, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFit, type MotionFitOptions, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMatch, type MotionMatchCommand, type MotionMorphCommand, type MotionMoveCommand, type MotionNodeEntry, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, describeMotionElements, describeMotionShots, fitMotionRect, fitMotionScene, flairAtLeast, flairCurveFor, flairEaseFor, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, matchMotionNodes, motionAddTrackKey, motionClipAttrs, motionCommandDuration, motionCommandRepeat, motionCycleDuration, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionIssue, motionIssueKey, motionIssueLine, motionNodeClips, motionNodeOffset, motionPathLength, motionRestValue, motionRevealClip, motionRevealPadding, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionShotTimeScale, motionTrackKey, namedWithSuggestion, parseMotionScene, resolveMotionCamera, segmentProgress, segmentValue, shotShapeProblems, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, trackValue, withMotionLayers, withViewBox };
@@ -75,6 +75,11 @@ interface MotionShot {
75
75
  run: MotionCommand[];
76
76
  /** Milliseconds to hold after the commands finish (default 600). */
77
77
  hold?: number;
78
+ /**
79
+ * Plays the whole shot this many times as fast (default 1): its camera move, delays,
80
+ * durations, staggers and hold all scale by 1 / speed. `fit_animation` sets it to fit a length.
81
+ */
82
+ speed?: number;
78
83
  }
79
84
  /** Fields every command takes. */
80
85
  interface MotionCommandBase {
@@ -223,6 +228,17 @@ interface MotionMorphCommand extends MotionCommandBase {
223
228
  type: 'morph';
224
229
  into: string;
225
230
  }
231
+ /**
232
+ * Smart Animate: tweens a group into another group (`into`, usually hidden), part by part. Each
233
+ * part of the target takes the shape, paint and place of its partner in `into`, paired by name,
234
+ * then by id (`card-a-title` ↔ `card-b-title`), then by kind in order. Parts with no partner fade
235
+ * out; parts of `into` with no partner do not appear (`check` lists them).
236
+ */
237
+ interface MotionMatchCommand extends MotionCommandBase {
238
+ type: 'match';
239
+ /** Id of the group (or node) to become. */
240
+ into: string;
241
+ }
226
242
  /** Moves targets along a path node, centre on the path. */
227
243
  interface MotionFollowCommand extends MotionCommandBase {
228
244
  type: 'follow';
@@ -346,7 +362,7 @@ interface MotionWaitCommand {
346
362
  with?: 'after' | 'previous';
347
363
  note?: string;
348
364
  }
349
- type MotionCommand = MotionEnterCommand | MotionExitCommand | MotionDrawCommand | MotionMoveCommand | MotionRotateCommand | MotionScaleCommand | MotionFadeCommand | MotionStyleCommand | MotionMorphCommand | MotionFollowCommand | MotionPulseCommand | MotionShakeCommand | MotionTeeterCommand | MotionWaveCommand | MotionWiggleCommand | MotionColorPulseCommand | MotionEffectCommand | MotionWaitCommand;
365
+ type MotionCommand = MotionEnterCommand | MotionExitCommand | MotionDrawCommand | MotionMoveCommand | MotionRotateCommand | MotionScaleCommand | MotionFadeCommand | MotionStyleCommand | MotionMorphCommand | MotionMatchCommand | MotionFollowCommand | MotionPulseCommand | MotionShakeCommand | MotionTeeterCommand | MotionWaveCommand | MotionWiggleCommand | MotionColorPulseCommand | MotionEffectCommand | MotionWaitCommand;
350
366
  type MotionCommandType = MotionCommand['type'];
351
367
  declare const MOTION_COMMAND_TYPES: readonly MotionCommandType[];
352
368
  declare const MOTION_ENTER_STYLES: readonly MotionEnterStyle[];
@@ -425,6 +441,14 @@ declare const MOTION_ISSUE_CODES: {
425
441
  readonly severity: "error";
426
442
  readonly wording: "A morph names a shape the artwork does not have.";
427
443
  };
444
+ readonly 'match-self': {
445
+ readonly severity: "error";
446
+ readonly wording: "A match turns a group into itself or into a group it holds (or that holds it).";
447
+ };
448
+ readonly 'match-unpaired': {
449
+ readonly severity: "note";
450
+ readonly wording: "Parts of a match's \"into\" group have no partner in the target, so they do not appear.";
451
+ };
428
452
  readonly 'unknown-effect': {
429
453
  readonly severity: "error";
430
454
  readonly wording: "An effect command names an effect the node does not have.";
@@ -711,6 +735,8 @@ declare function fitMotionRect(rect: MotionRect, aspect: number): MotionRect;
711
735
  declare function resolveMotionCamera(camera: MotionCamera, scene: MotionScene): MotionRect | null;
712
736
  /** Length of a node's outline (its longest path for a group), in document units. */
713
737
  declare function motionPathLength(node: VectorNode, parentWorld?: AffineMatrix): number;
738
+ /** How much a shot's `speed` stretches its time (1 / speed; 1 when unset or not above 0). */
739
+ declare function motionShotTimeScale(shot: MotionShot): number;
714
740
  /** How many times a command plays (1 for `enter`, `exit` and `wait`, which do not repeat). */
715
741
  declare function motionCommandRepeat(command: MotionCommand): number;
716
742
  /** How long one target of a command takes (ms), every repeat included. */
@@ -730,6 +756,23 @@ declare function compileMotionScene(scene: MotionScene): MotionTimeline;
730
756
  /** The shot playing at `time` (the last one at the end). */
731
757
  declare function motionShotAt(timeline: MotionTimeline, time: number): MotionShotTiming | undefined;
732
758
 
759
+ /** How the parts of one node pair with the parts of another for a `match` (Smart Animate). */
760
+ interface MotionMatch {
761
+ /** `[from id, into id]`: each part of the target and the part of `into` it becomes. */
762
+ pairs: [string, string][];
763
+ /** Parts of the target with no partner (they fade out). */
764
+ unpairedFrom: string[];
765
+ /** Parts of `into` with no partner (they cannot appear). */
766
+ unpairedInto: string[];
767
+ }
768
+ /**
769
+ * Pairs the parts of `from` with the parts of `into`, each part used once, in passes: the same
770
+ * `name`, then the same id once each group's own id is taken out, then the same kind in order.
771
+ * Paired groups pair their own parts the same way, so a part pairs with a part, never a group
772
+ * with a path. Two paths (or a path and a group with no children) pair whole.
773
+ */
774
+ declare function matchMotionNodes(from: VectorNode, into: VectorNode): MotionMatch;
775
+
733
776
  /**
734
777
  * A reveal clip (`wipe`, `iris`, `split`) in the units of the node's own box: 0–1 across it,
735
778
  * as SVG's `clipPathUnits="objectBoundingBox"` and Flair's clip reveals are.
@@ -841,7 +884,7 @@ type MotionEdit = {
841
884
  op: 'update_shot';
842
885
  shot: string;
843
886
  set?: Partial<MotionShot>;
844
- remove?: ('label' | 'camera' | 'hold')[];
887
+ remove?: ('label' | 'camera' | 'hold' | 'speed')[];
845
888
  } | {
846
889
  op: 'delete_shots';
847
890
  shots: string[];
@@ -895,6 +938,27 @@ declare function applyMotionEdits(scene: MotionScene, edits: MotionEdit | readon
895
938
  /** An empty scene over `artwork`. */
896
939
  declare function createMotionScene(artwork: VectorDocument, init?: Partial<Omit<MotionScene, 'artwork' | 'version'>>): MotionScene;
897
940
 
941
+ interface MotionFitOptions {
942
+ /** Shot ids that keep their pace (a logo hold, a line of narration); the others absorb the change. */
943
+ keep?: readonly string[];
944
+ }
945
+ interface MotionFit {
946
+ scene: MotionScene;
947
+ /** The length after fitting, ms (within a few ms of the target: speeds are rounded). */
948
+ duration: number;
949
+ /** The new `speed` of every shot that changed. */
950
+ speeds: Record<string, number>;
951
+ }
952
+ /** Speeds are kept within this range. */
953
+ declare const MOTION_SPEED_RANGE: readonly [number, number];
954
+ /**
955
+ * Fits a scene to `ms` by setting its shots' `speed`: the shots in `keep` play as they are and
956
+ * the rest stretch or squeeze by the same factor, so their timing keeps its proportions (the
957
+ * responsive time of After Effects' protected regions). Throws, changing nothing, when the
958
+ * kept shots alone outlast the target or a speed would leave `MOTION_SPEED_RANGE`.
959
+ */
960
+ declare function fitMotionScene(scene: MotionScene, ms: number, options?: MotionFitOptions): MotionFit;
961
+
898
962
  /**
899
963
  * Export to Flair (`@pixerate/flair`): a scene becomes an `SvgMotion` (one SVG plus a list of
900
964
  * from → to changes on its elements), a catalog `VectorEffect`, or an `EffectDocument` for
@@ -1435,6 +1499,23 @@ declare function describeMotionShots(scene: MotionScene): {
1435
1499
  repeatMode?: "loop" | "mirror" | "offset";
1436
1500
  steps?: number;
1437
1501
  index: number;
1502
+ } | {
1503
+ flairPrimitive?: string | undefined;
1504
+ start: number;
1505
+ end: number;
1506
+ type: "match";
1507
+ into: string;
1508
+ targets: string[];
1509
+ duration?: number;
1510
+ delay?: number;
1511
+ stagger?: number;
1512
+ with?: "after" | "previous";
1513
+ ease?: AnimationEasing;
1514
+ note?: string;
1515
+ repeat?: number;
1516
+ repeatMode?: "loop" | "mirror" | "offset";
1517
+ steps?: number;
1518
+ index: number;
1438
1519
  } | {
1439
1520
  flairPrimitive?: string | undefined;
1440
1521
  start: number;
@@ -1622,6 +1703,6 @@ declare function createAnimationEditorToolProvider(controller: AnimationEditorCo
1622
1703
  * A short authoring guide for a model writing vector animations with the animation editor's
1623
1704
  * tools. Static, so it caches well as part of a system prompt.
1624
1705
  */
1625
- declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. 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 to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots, or edit_animation to make several edits as one step (dry_run first when unsure).\n3. check_animation and fix every error and warning; render_animation_frame (shot + \"end\") to look at the result.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
1706
+ declare const ANIMATION_EDITOR_AGENT_INSTRUCTIONS = "You animate vector artwork. A scene is artwork (vector paths and groups, each with an id) plus shots.\n\nHow it plays\n- Shots play in order. A shot optionally moves the camera, plays its commands, then holds (default 600 ms).\n- Commands in a shot play one after another; give \"with\": \"previous\" to start one together with the command before, \"delay\" to wait, \"stagger\" to offset several targets.\n- Timing comes from the content: each command has a default length (enter 600 ms, move 700 ms, draw follows the path length). Only set \"duration\" to change the pace.\n- Anything that enters later is hidden until it enters. Things that never enter are visible from the start.\n- Every frame is a pure function of time: the same scene always plays the same frames.\n\nCommands\n- enter (fade, pop, grow, slide, draw) and exit (fade, shrink, slide, undraw) bring things in and out.\n- enter also reveals through a clip over the target's box: wipe (behind an edge travelling \"direction\", default right), iris (from the centre; \"shape\": circle or box) and split (from a line through the middle; \"orientation\": horizontal or vertical). exit wipe hides the same way. Reveals need a width and a height: use draw / undraw for a straight line.\n- draw draws strokes on to a fraction; move, rotate, scale and fade change the pose (about the centre); style blends solid colours and stroke width.\n- enter also has zoom (settles from larger) and rise (rises a short way, overshooting a touch); pop and zoom take a starting \"scale\".\n- morph turns a shape into another node's shape (keep the target hidden); match does the same for a whole group, part by part (Smart Animate: draw the end state as a second, hidden group whose parts share names with the first); follow moves along a path node (with \"rotate\", moves made meanwhile turn with the path).\n- Emphasis draws the eye and returns to rest: pulse (swell), shake (side to side, or \"axis\": \"vertical\"), teeter (rock), wave (bob, no settling), wiggle (seeded wander; the same seed wanders the same way) and color-pulse (tint and back).\n- Emphasis stacks on other motion: a shake during a slide shakes as it slides. Give move, rotate or scale \"blend\": \"add\" to stack them too (what they add stays); \"blend\": \"replace\" makes a change take over instead.\n- Any command but enter and exit can \"repeat\" (loop, mirror back and forth, or offset to carry on: rotate by 90, repeat 4 is a full turn); \"duration\" is one cycle.\n- Springs (\"spring-gentle\", \"spring-quick\", \"spring-bouncy\", \"spring-slow\" or { \"type\": \"spring\", \u2026 }) feel physical; leave \"duration\" out and the spring sets it.\n- \"steps\": 12 (on a command, or for the whole scene with set_animation_settings) holds poses \"on twos\" for a hand-drawn look. \"geometric\": true on scale or a camera zooms at an even rate.\n- Commands share their names and defaults with Flair's motion primitives (get_animation shows each one's \"flairPrimitive\"), and emphasis, reveals and follows export to Flair exactly.\n- effect tweens a numeric parameter of a live path effect already on the node (twist angle, wiggle time, zig zag size).\n\nWorking method\n1. 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 to start from a Flair effect and edit it).\n2. Plan a few shots, each one idea. Add them with insert_shots, or edit_animation to make several edits as one step (dry_run first when unsure).\n3. 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.\n4. To make a reusable Flair effect, set_animation_controls (colour controls stand for every use of their default colour) and export_flair_effect.\n\nKeep motion purposeful: one thing moving at a time reads best, ease-out for arrivals, ease-in for exits, and hold long enough to see each result.";
1626
1707
 
1627
- export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPLIT_ORIENTATIONS, type MotionCamera, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionControl, type MotionDirection, type MotionDrawCommand, type MotionEdit, type MotionEditOp, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMorphCommand, type MotionMoveCommand, type MotionNodeEntry, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, describeMotionElements, describeMotionShots, fitMotionRect, flairAtLeast, flairCurveFor, flairEaseFor, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, motionAddTrackKey, motionClipAttrs, motionCommandDuration, motionCommandRepeat, motionCycleDuration, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionIssue, motionIssueKey, motionIssueLine, motionNodeClips, motionNodeOffset, motionPathLength, motionRestValue, motionRevealClip, motionRevealPadding, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionTrackKey, namedWithSuggestion, parseMotionScene, resolveMotionCamera, segmentProgress, segmentValue, shotShapeProblems, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, trackValue, withMotionLayers, withViewBox };
1708
+ export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, FLAIR_EXPORT_VERSION, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairImportOptions, type FlairImportResult, type FlairMotionExport, type FlairSpringEase, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, MOTION_ADDITIVE_PROPERTIES, MOTION_BLENDS, MOTION_CAMERA_MS, MOTION_COMMAND_SCHEMA, MOTION_COMMAND_TYPES, MOTION_DEFAULT_DURATIONS, MOTION_DEFAULT_HOLD, MOTION_DIRECTIONS, MOTION_DRAW_EFFECT_ID, MOTION_DRAW_MS_PER_UNIT, MOTION_DRAW_RANGE, MOTION_EASE_IN_OUT, MOTION_EASE_OUT, MOTION_EDIT_OPS, MOTION_ENTER_STYLES, MOTION_EXIT_STYLES, MOTION_IRIS_SHAPES, MOTION_ISSUE_CODES, MOTION_MIN_CHANGE_MS, MOTION_REPEAT_MODES, MOTION_SPEED_RANGE, MOTION_SPLIT_ORIENTATIONS, type MotionCamera, type MotionClipShape, type MotionColorPulseCommand, type MotionCommand, type MotionCommandBase, type MotionCommandTiming, type MotionCommandType, type MotionControl, type MotionDirection, type MotionDrawCommand, type MotionEdit, type MotionEditOp, type MotionEditResult, type MotionEffectCommand, type MotionEnterCommand, type MotionEnterStyle, type MotionExitCommand, type MotionExitStyle, type MotionFadeCommand, type MotionFit, type MotionFitOptions, type MotionFollowCommand, type MotionFrame, type MotionFrameOptions, type MotionIrisShape, type MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMatch, type MotionMatchCommand, type MotionMorphCommand, type MotionMoveCommand, type MotionNodeEntry, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionReveal, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionSplitOrientation, type MotionStyleCommand, type MotionSvgOptions, type MotionTeeterCommand, type MotionTimeline, type MotionValue, type MotionWaitCommand, type MotionWaveCommand, type MotionWiggleCommand, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, describeMotionElements, describeMotionShots, fitMotionRect, fitMotionScene, flairAtLeast, flairCurveFor, flairEaseFor, freshShotId, fromFlairSvgMotion, fromFlairVectorEffect, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, matchMotionNodes, motionAddTrackKey, motionClipAttrs, motionCommandDuration, motionCommandRepeat, motionCycleDuration, motionFlairPrimitive, motionFollowRoute, motionFrameAt, motionFrameToSvg, motionIssue, motionIssueKey, motionIssueLine, motionNodeClips, motionNodeOffset, motionPathLength, motionRestValue, motionRevealClip, motionRevealPadding, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionShotTimeScale, motionTrackKey, namedWithSuggestion, parseMotionScene, resolveMotionCamera, segmentProgress, segmentValue, shotShapeProblems, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, trackValue, withMotionLayers, withViewBox };