@pixerate/editor 0.56.0 → 0.58.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.
@@ -1,7 +1,8 @@
1
1
  import { b as AnimationEasing } from '../easing-CNGk-W6d.js';
2
2
  import { b as AnimationLoopMode, c as AnimationPlayer, C as Clock } from '../player-W-5DX3Go.js';
3
- import { V as VectorDocument, a as VectorNode, b as VectorBounds, c as VectorSvgExportOptions } from '../svg-CPK82TtU.js';
4
- import { A as AffineMatrix } from '../bezier-DYBvLgUH.js';
3
+ import { V as VectorDocument, a as VectorNode, b as VectorBounds, c as VectorSvgExportOptions } from '../svg-Dh17jCyA.js';
4
+ import { a as MotionBehavior } from '../behavior-Ymbld6jL.js';
5
+ import { A as AffineMatrix, B as BezierPath } from '../bezier-DYBvLgUH.js';
5
6
  import { H as HistoryManager } from '../HistoryManager-DWSLd6Tf.js';
6
7
  import { A as AgentToolProvider } from '../registry-7AZFuand.js';
7
8
  import { J as JsonSchema } from '../schema-Di0CS6Pe.js';
@@ -84,24 +85,46 @@ interface MotionCommandBase {
84
85
  /** Why this command is here (for people and agents reading the scene). */
85
86
  note?: string;
86
87
  }
87
- type MotionEnterStyle = 'fade' | 'pop' | 'grow' | 'slide' | 'draw';
88
- type MotionExitStyle = 'fade' | 'shrink' | 'slide' | 'undraw';
88
+ type MotionEnterStyle = 'fade' | 'pop' | 'grow' | 'slide' | 'draw' | 'zoom' | 'rise' | 'wipe' | 'iris' | 'split';
89
+ type MotionExitStyle = 'fade' | 'shrink' | 'slide' | 'undraw' | 'wipe';
89
90
  type MotionDirection = 'up' | 'down' | 'left' | 'right';
90
- /** Brings hidden targets in. Targets entered in a shot are hidden before it. */
91
+ /** The opening an `iris` reveals through. */
92
+ type MotionIrisShape = 'circle' | 'box';
93
+ /** The line a `split` opens from. */
94
+ type MotionSplitOrientation = 'horizontal' | 'vertical';
95
+ /**
96
+ * Brings hidden targets in. Targets entered in a shot are hidden before it. Each style is a
97
+ * Flair motion primitive (`entrance.<style>`) with the same defaults.
98
+ */
91
99
  interface MotionEnterCommand extends MotionCommandBase {
92
100
  type: 'enter';
93
- /** Default `fade`. `draw` draws the outline on, then fades the fill in. */
101
+ /**
102
+ * Default `fade`. `draw` draws the outline on, then fades the fill in. `pop` scales up past
103
+ * full size and settles; `zoom` settles from larger; `rise` rises a short way with a little
104
+ * overshoot. `wipe`, `iris` and `split` reveal the target through a clip over its box (see
105
+ * `MotionFrame.clips`), reaching past it far enough to show its whole stroke.
106
+ */
94
107
  style?: MotionEnterStyle;
95
- /** For `slide`: the direction of travel (default `up`). */
108
+ /**
109
+ * For `slide`: the direction of travel (default `up`). For `wipe`: the way the edge travels
110
+ * (default `right`, which reveals from the left).
111
+ */
96
112
  direction?: MotionDirection;
97
- /** For `slide`: how far in document units (default 40). */
113
+ /** For `slide` (default 40) and `rise` (default 20): how far in document units. */
98
114
  distance?: number;
115
+ /** For `pop` (default 0.5) and `zoom` (default 1.6): the starting scale. */
116
+ scale?: number;
117
+ /** For `iris`: open through a `circle` (default; an ellipse on a box that is not square) or a `box`. */
118
+ shape?: MotionIrisShape;
119
+ /** For `split`: open up and down from a `horizontal` line through the middle (default), or left and right from a `vertical` one. */
120
+ orientation?: MotionSplitOrientation;
99
121
  }
100
122
  /** Takes targets out. */
101
123
  interface MotionExitCommand extends MotionCommandBase {
102
124
  type: 'exit';
103
- /** Default `fade`. */
125
+ /** Default `fade`. `wipe` hides the target behind an edge travelling `direction` (a wipe in, reversed). */
104
126
  style?: MotionExitStyle;
127
+ /** For `slide`: the direction of travel (default `down`). For `wipe`: the way the edge travels (default `right`, which hides from the left). */
105
128
  direction?: MotionDirection;
106
129
  distance?: number;
107
130
  }
@@ -161,7 +184,10 @@ interface MotionFollowCommand extends MotionCommandBase {
161
184
  type: 'follow';
162
185
  /** Id of a path node in the artwork (it can be hidden). */
163
186
  path: string;
164
- /** Turn with the path's direction (default false). */
187
+ /**
188
+ * Turn with the path's direction (default false). Moves, shakes and wiggles made during the
189
+ * follow then turn with it too: they are offsets from the target's place on the path.
190
+ */
165
191
  rotate?: boolean;
166
192
  /** Fractions of the path's length to travel between (default 0 → 1). */
167
193
  from?: number;
@@ -174,12 +200,56 @@ interface MotionPulseCommand extends MotionCommandBase {
174
200
  amount?: number;
175
201
  count?: number;
176
202
  }
177
- /** Shakes side to side, settling. */
203
+ /** Shakes side to side (or up and down), settling. */
178
204
  interface MotionShakeCommand extends MotionCommandBase {
179
205
  type: 'shake';
180
206
  /** Distance in document units (default 8). */
181
207
  amount?: number;
182
208
  count?: number;
209
+ /** Default `horizontal`. */
210
+ axis?: 'horizontal' | 'vertical';
211
+ }
212
+ /** Rocks about the centre by `angle` either way, settling (Flair's `emphasis.teeter`). */
213
+ interface MotionTeeterCommand extends MotionCommandBase {
214
+ type: 'teeter';
215
+ /** Degrees either way (default 8). */
216
+ angle?: number;
217
+ /** Rocks (default 3). */
218
+ count?: number;
219
+ }
220
+ /** Bobs up and down without settling, like something floating (Flair's `emphasis.wave`). */
221
+ interface MotionWaveCommand extends MotionCommandBase {
222
+ type: 'wave';
223
+ /** Height in document units (default 6). */
224
+ amount?: number;
225
+ /** Bobs (default 2). */
226
+ count?: number;
227
+ }
228
+ /**
229
+ * Wanders about its place as smooth seeded noise, easing out of and back to rest (Flair's
230
+ * `emphasis.wiggle`). The same seed always wanders the same way.
231
+ */
232
+ interface MotionWiggleCommand extends MotionCommandBase {
233
+ type: 'wiggle';
234
+ /** Up to about this far, in document units (default 6). */
235
+ amount?: number;
236
+ /** Wanders per second, in Hz (default 3). */
237
+ frequency?: number;
238
+ /** Layers of finer detail (default 2). */
239
+ octaves?: number;
240
+ /** Also turns about the centre by up to about this many degrees (default 0). */
241
+ rotate?: number;
242
+ /** A whole number; default: one picked from the target's id, so each target wanders its own way. */
243
+ seed?: number;
244
+ }
245
+ /** Tints solid paint toward a colour and back, `count` times (Flair's `emphasis.color-pulse`). */
246
+ interface MotionColorPulseCommand extends MotionCommandBase {
247
+ type: 'color-pulse';
248
+ /** The tint (default `#f59e0b`). Mixes in OKLab. */
249
+ color?: string;
250
+ /** Which paint (default `fill`). On a group it tints every path in it. */
251
+ paint?: 'fill' | 'stroke';
252
+ count?: number;
183
253
  }
184
254
  /** Tweens a numeric parameter of a live path effect on the target (twist angle, wiggle time, zig zag size…). */
185
255
  interface MotionEffectCommand extends MotionCommandBase {
@@ -197,11 +267,13 @@ interface MotionWaitCommand {
197
267
  with?: 'after' | 'previous';
198
268
  note?: string;
199
269
  }
200
- type MotionCommand = MotionEnterCommand | MotionExitCommand | MotionDrawCommand | MotionMoveCommand | MotionRotateCommand | MotionScaleCommand | MotionFadeCommand | MotionStyleCommand | MotionMorphCommand | MotionFollowCommand | MotionPulseCommand | MotionShakeCommand | MotionEffectCommand | MotionWaitCommand;
270
+ type MotionCommand = MotionEnterCommand | MotionExitCommand | MotionDrawCommand | MotionMoveCommand | MotionRotateCommand | MotionScaleCommand | MotionFadeCommand | MotionStyleCommand | MotionMorphCommand | MotionFollowCommand | MotionPulseCommand | MotionShakeCommand | MotionTeeterCommand | MotionWaveCommand | MotionWiggleCommand | MotionColorPulseCommand | MotionEffectCommand | MotionWaitCommand;
201
271
  type MotionCommandType = MotionCommand['type'];
202
272
  declare const MOTION_COMMAND_TYPES: readonly MotionCommandType[];
203
273
  declare const MOTION_ENTER_STYLES: readonly MotionEnterStyle[];
204
274
  declare const MOTION_EXIT_STYLES: readonly MotionExitStyle[];
275
+ declare const MOTION_IRIS_SHAPES: readonly MotionIrisShape[];
276
+ declare const MOTION_SPLIT_ORIENTATIONS: readonly MotionSplitOrientation[];
205
277
  declare const MOTION_DIRECTIONS: readonly MotionDirection[];
206
278
  /**
207
279
  * A colour parameter of the effect made from the scene: it stands for every use of its
@@ -228,6 +300,12 @@ declare const MOTION_CAMERA_MS = 1000;
228
300
  /** `draw` lasts `length × MOTION_DRAW_MS_PER_UNIT`, clamped to `MOTION_DRAW_RANGE`. */
229
301
  declare const MOTION_DRAW_MS_PER_UNIT = 1.5;
230
302
  declare const MOTION_DRAW_RANGE: readonly [number, number];
303
+ /**
304
+ * The Flair motion primitive (`@pixerate/flair/motion`) a command plays, or undefined when
305
+ * Flair has none (`move`, `scale`, `fade`, `style`, `morph`, `effect`, `wait` are the editor's
306
+ * own). Commands and primitives of the same name take the same parameters and defaults.
307
+ */
308
+ declare function motionFlairPrimitive(command: MotionCommand): string | undefined;
231
309
 
232
310
  /**
233
311
  * Problems with a scene, as data: every issue has a stable `code`, a severity, the shot and
@@ -258,6 +336,10 @@ declare const MOTION_ISSUE_CODES: {
258
336
  readonly severity: "error";
259
337
  readonly wording: "A follow path must be a path node, not a group.";
260
338
  };
339
+ readonly 'reveal-no-box': {
340
+ readonly severity: "warning";
341
+ readonly wording: "A wipe, iris or split cannot clip a node with no width or height (a lone straight line), so it fades instead.";
342
+ };
261
343
  readonly 'unknown-shape': {
262
344
  readonly severity: "error";
263
345
  readonly wording: "A morph names a shape the artwork does not have.";
@@ -284,7 +366,7 @@ declare const MOTION_ISSUE_CODES: {
284
366
  };
285
367
  readonly 'paint-not-color': {
286
368
  readonly severity: "warning";
287
- readonly wording: "A style command recolours a gradient or empty paint, which only switches at the end.";
369
+ readonly wording: "A style command recolours a gradient or empty paint, which only switches at the end, or a colour pulse has no solid paint to tint.";
288
370
  };
289
371
  readonly overlap: {
290
372
  readonly severity: "warning";
@@ -386,16 +468,12 @@ declare const isMotionCommand: (command: unknown) => command is MotionCommand;
386
468
  * Properties a segment can change. Offsets (`x`, `y`, `rotation`) are relative to the rest
387
469
  * pose, scales multiply it, and turns and scales are about the node's centre at rest.
388
470
  * `effect:<effectId>:<param>` tweens a live path effect's parameter. `camera` (node `""`) is
389
- * the view box `[x, y, width, height]`.
471
+ * the view box `[x, y, width, height]`. `clipRect` (`[x, y, width, height]`) and `clipCircle`
472
+ * (`[cx, cy, r]`) are the reveal clips of `wipe`, `iris` and `split`, in the units of the
473
+ * node's own box (0–1 across it, SVG's `objectBoundingBox`), as Flair's clip reveals are.
390
474
  */
391
- type MotionProperty = 'opacity' | 'x' | 'y' | 'rotation' | 'scaleX' | 'scaleY' | 'fill' | 'stroke' | 'strokeWidth' | 'fillOpacity' | 'drawStart' | 'drawEnd' | 'shape' | 'follow' | 'camera' | `effect:${string}:${string}`;
475
+ type MotionProperty = 'opacity' | 'x' | 'y' | 'rotation' | 'scaleX' | 'scaleY' | 'fill' | 'stroke' | 'strokeWidth' | 'fillOpacity' | 'drawStart' | 'drawEnd' | 'shape' | 'follow' | 'clipRect' | 'clipCircle' | 'camera' | `effect:${string}:${string}`;
392
476
  type MotionValue = number | string | readonly number[];
393
- /** An oscillation laid over a segment (`pulse`: scale up and back; `shake`: side to side, settling). */
394
- interface MotionWave {
395
- kind: 'pulse' | 'shake';
396
- amount: number;
397
- count: number;
398
- }
399
477
  interface MotionSegment {
400
478
  /** Node id (`""` for the camera). */
401
479
  node: string;
@@ -408,7 +486,16 @@ interface MotionSegment {
408
486
  /** The shot and command (index in `run`) it comes from. */
409
487
  shot: string;
410
488
  command: number;
411
- wave?: MotionWave;
489
+ /**
490
+ * How the change gets from `from` to `to` when not straight along its ease (a pulse there and
491
+ * back, a settling oscillation, a wriggle): Flair's `behavior`, exported as is.
492
+ */
493
+ behavior?: MotionBehavior;
494
+ /**
495
+ * Which number of the node's exported value this is (x 0, y 1, rotation 2, matching the
496
+ * transform Flair is given), so a wriggle wanders each on the channel Flair uses. Default 0.
497
+ */
498
+ index?: number;
412
499
  /** For `follow`: the path node id, and whether to turn with it. */
413
500
  path?: string;
414
501
  rotate?: boolean;
@@ -457,9 +544,39 @@ interface MotionNodeEntry {
457
544
  };
458
545
  /** Bounds at rest in document space. */
459
546
  bounds: VectorBounds | null;
547
+ /** Bounds at rest in its parent's space (what a reveal clip's box is). */
548
+ box: VectorBounds | null;
460
549
  }
461
550
  /** Every node of the artwork by id (cached per node list). */
462
551
  declare function indexMotionNodes(nodes: readonly VectorNode[]): Map<string, MotionNodeEntry>;
552
+ /**
553
+ * How far past its box (as a share of its width and height) a reveal clip reaches, so it shows
554
+ * the whole stroke: the stroke's reach over the box plus 0.02, at most 1 (Flair's padding). Null
555
+ * when the box has no width or height (a lone straight line), which a clip cannot reveal.
556
+ */
557
+ declare function motionRevealPadding(entry: MotionNodeEntry): readonly [number, number] | null;
558
+ /** What a reveal clip animates: a wipe (in, or out with `hide`), an iris or a split. */
559
+ type MotionReveal = {
560
+ style: 'wipe';
561
+ direction?: MotionDirection;
562
+ hide?: boolean;
563
+ } | {
564
+ style: 'iris';
565
+ shape?: MotionIrisShape;
566
+ } | {
567
+ style: 'split';
568
+ orientation?: MotionSplitOrientation;
569
+ };
570
+ /**
571
+ * The reveal clip a `wipe`, `iris` or `split` animates, from and to (Flair's `entrance.wipe`,
572
+ * `entrance.iris`, `entrance.split` and `exit.wipe`), or null when the node's box has no width
573
+ * or height. An exit wipe is the enter wipe the other way, reversed in time.
574
+ */
575
+ declare function motionRevealClip(entry: MotionNodeEntry, reveal: MotionReveal): {
576
+ property: 'clipRect' | 'clipCircle';
577
+ from: number[];
578
+ to: number[];
579
+ } | null;
463
580
  /** A property's value with no animation. */
464
581
  declare function motionRestValue(entry: MotionNodeEntry | undefined, property: MotionProperty, artwork: {
465
582
  width: number;
@@ -472,12 +589,15 @@ declare function segmentProgress(segment: MotionSegment, time: number): {
472
589
  u: number;
473
590
  eased: number;
474
591
  };
475
- /** A segment's value at `time`. */
476
- declare function segmentValue(segment: MotionSegment, time: number): MotionValue;
592
+ /**
593
+ * A segment's value at `time`: along its ease, through its behaviour when it has one. `raw`
594
+ * ignores the behaviour (the value it swings towards), as Flair is given it.
595
+ */
596
+ declare function segmentValue(segment: MotionSegment, time: number, raw?: boolean): MotionValue;
477
597
  /** The segment in effect at `time` (the latest to have started), if any. */
478
598
  declare function activeSegment(track: readonly MotionSegment[] | undefined, time: number): MotionSegment | undefined;
479
- /** A track's value at `time`, or `undefined` when nothing animates it. */
480
- declare function trackValue(track: readonly MotionSegment[] | undefined, time: number): MotionValue | undefined;
599
+ /** A track's value at `time`, or `undefined` when nothing animates it. `raw` ignores behaviours (see `segmentValue`). */
600
+ declare function trackValue(track: readonly MotionSegment[] | undefined, time: number, raw?: boolean): MotionValue | undefined;
481
601
  declare const motionTrackKey: (node: string, property: MotionProperty) => string;
482
602
  /** Grows a rectangle to the artwork's aspect ratio (about its centre). */
483
603
  declare function fitMotionRect(rect: MotionRect, aspect: number): MotionRect;
@@ -500,11 +620,32 @@ declare function compileMotionScene(scene: MotionScene): MotionTimeline;
500
620
  /** The shot playing at `time` (the last one at the end). */
501
621
  declare function motionShotAt(timeline: MotionTimeline, time: number): MotionShotTiming | undefined;
502
622
 
623
+ /**
624
+ * A reveal clip (`wipe`, `iris`, `split`) in the units of the node's own box: 0–1 across it,
625
+ * as SVG's `clipPathUnits="objectBoundingBox"` and Flair's clip reveals are.
626
+ */
627
+ type MotionClipShape = {
628
+ shape: 'rect';
629
+ x: number;
630
+ y: number;
631
+ width: number;
632
+ height: number;
633
+ } | {
634
+ shape: 'circle';
635
+ cx: number;
636
+ cy: number;
637
+ r: number;
638
+ };
503
639
  /** The artwork as it stands at one time, and where the camera looks. */
504
640
  interface MotionFrame {
505
641
  time: number;
506
642
  document: VectorDocument;
507
643
  camera: MotionRect;
644
+ /**
645
+ * Reveal clips by node id, outermost first: draw each of those nodes inside a group clipped
646
+ * to each shape (`motionFrameToSvg` does). The vector model has no clips, so they ride here.
647
+ */
648
+ clips: Record<string, MotionClipShape[]>;
508
649
  }
509
650
  interface MotionFrameOptions {
510
651
  /** Control values (`{ accent: "#0ea5e9" }`): each recolours its control's default colour. */
@@ -518,15 +659,33 @@ interface MotionFrameOptions {
518
659
  declare const MOTION_DRAW_EFFECT_ID = "~draw";
519
660
  /** A copy of the scene with each control's default colour replaced by its value (exact, case-insensitive matches). */
520
661
  declare function applyMotionControlValues(scene: MotionScene, values: Record<string, string> | undefined): MotionScene;
521
- /** The transform a node's offsets, turn, scale and follow add (parent space), or null when none. */
522
- declare function motionNodeOffset(entry: MotionNodeEntry, timeline: MotionTimeline, time: number, nodes?: Map<string, MotionNodeEntry>): {
662
+ /**
663
+ * The path a node follows, in the node's parent's space (live effects left off), or null when
664
+ * `path` is not a path or cannot be measured. Lengths and turns along it are measured there.
665
+ */
666
+ declare function motionFollowRoute(entry: MotionNodeEntry, path: MotionNodeEntry | undefined): BezierPath | null;
667
+ /**
668
+ * The transform a node's offsets, turn, scale and follow add (parent space), or null when none:
669
+ * scaled and turned about its centre, offset by `dx`, `dy`, then (following a path) its centre
670
+ * carried to the point on the path and turned with it, as Flair's `along` carries a wrapper.
671
+ * `raw` ignores behaviours (the pose a pulse or shake swings towards, as Flair is given it);
672
+ * `follow: false` leaves the follow out (`dx` … `scaleY` never include it).
673
+ */
674
+ declare function motionNodeOffset(entry: MotionNodeEntry, timeline: MotionTimeline, time: number, nodes?: Map<string, MotionNodeEntry>, raw?: boolean, follow?: boolean): {
523
675
  matrix: AffineMatrix;
524
676
  dx: number;
525
677
  dy: number;
526
678
  rotation: number;
527
679
  scaleX: number;
528
680
  scaleY: number;
681
+ follow: {
682
+ x: number;
683
+ y: number;
684
+ angle: number;
685
+ } | null;
529
686
  } | null;
687
+ /** A node's reveal clips at `time`, outermost first (rect, then circle), with sizes kept ≥ 0. */
688
+ declare function motionNodeClips(id: string, timeline: MotionTimeline, time: number): MotionClipShape[];
530
689
  /**
531
690
  * The scene at `time` (ms): the artwork with every change applied, and the camera. A pure
532
691
  * function of time, so frames can be drawn in any order (and the same frames come out every time).
@@ -534,7 +693,9 @@ declare function motionNodeOffset(entry: MotionNodeEntry, timeline: MotionTimeli
534
693
  declare function motionFrameAt(scene: MotionScene, time: number, options?: MotionFrameOptions): MotionFrame;
535
694
  interface MotionSvgOptions extends MotionFrameOptions, VectorSvgExportOptions {
536
695
  }
537
- /** The scene at `time` as a standalone SVG (the camera becomes the `viewBox`). */
696
+ /** A clip shape's SVG attributes. */
697
+ declare function motionClipAttrs(clip: MotionClipShape): Record<string, number>;
698
+ /** The scene at `time` as a standalone SVG (the camera becomes the `viewBox`, reveal clips wrap their nodes). */
538
699
  declare function motionFrameToSvg(scene: MotionScene, time: number, options?: MotionSvgOptions): string;
539
700
  /** Replaces the root `viewBox` of an SVG string. */
540
701
  declare function withViewBox(svg: string, box: MotionRect): string;
@@ -629,12 +790,23 @@ declare function createMotionScene(artwork: VectorDocument, init?: Partial<Omit<
629
790
  * Flair's effect editor. The types are mirrored here so this package does not depend on Flair.
630
791
  *
631
792
  * Changes are exact where Flair can express them: a change with a linear, cubic-out or
632
- * cubic-in-out curve (the editor's defaults) is one change. Anything else (other easings,
633
- * pulses and shakes, follows, morphs and live-effect tweens) is sampled at the scene's `fps`
634
- * into short linear changes, which Flair plays the same way.
793
+ * cubic-in-out curve (the editor's defaults) is one change, and so (Flair 0.36 and later) is
794
+ * one with any cubic-bezier curve, written as `[x1, y1, x2, y2]`. Anything else (springs,
795
+ * elastic, `hold`, morphs and live-effect tweens) is sampled at the
796
+ * scene's `fps` into short linear changes, which Flair plays the same way. Pulses, shakes,
797
+ * teeters, waves, wiggles and colour pulses are one change with a `behavior` (Flair 0.38).
798
+ *
799
+ * Reveals (`wipe`, `iris`, `split`) wrap their node in a group clipped through a rect or circle
800
+ * in the group's own box units (`clipPathUnits="objectBoundingBox"`), as Flair's
801
+ * `entrance.wipe` does, and animate the shape's attributes. A follow wraps its node in a group
802
+ * that Flair's `along` carries along a copy of the path in the node's parent's units (written
803
+ * in `<defs>`, so the path may be hidden or anywhere), turning with it for `orient`, as
804
+ * Flair's `path.follow` does.
635
805
  */
636
806
  /** Flair's easing names. */
637
807
  type FlairEaseName = 'linear' | 'in-out' | 'out';
808
+ /** A Flair easing: a name, or (Flair 0.36 and later) a CSS cubic-bezier `[x1, y1, x2, y2]`. */
809
+ type FlairEase = FlairEaseName | readonly [number, number, number, number];
638
810
  /** Flair's curves, for matching. */
639
811
  declare const FLAIR_EASES: Readonly<Record<FlairEaseName, (t: number) => number>>;
640
812
  /** One change of a Flair `SvgMotion` (mirrors `SvgAnimation` in `@pixerate/flair/vector`). */
@@ -643,9 +815,16 @@ interface FlairSvgAnimation {
643
815
  step?: number;
644
816
  delay?: number;
645
817
  ms?: number;
646
- ease?: FlairEaseName;
818
+ ease?: FlairEase;
647
819
  attrs?: Record<string, readonly [string | number, string | number]>;
648
820
  draw?: boolean | readonly [number, number];
821
+ /** Moves the element along a path (by id), from and to the fractions of its length in `at`. */
822
+ along?: string;
823
+ at?: readonly [number, number];
824
+ /** With `along`: turns the element with the path's direction. */
825
+ orient?: boolean;
826
+ /** Flair 0.38 and later: how the change swings from → to (see `MotionBehavior`). */
827
+ behavior?: MotionBehavior;
649
828
  view?: readonly [number, number, number, number] | string;
650
829
  }
651
830
  /** Mirrors `SvgMotion` in `@pixerate/flair/vector`. */
@@ -704,9 +883,28 @@ interface FlairExportOptions {
704
883
  fps?: number;
705
884
  /** Decimal places (default 3). */
706
885
  precision?: number;
886
+ /**
887
+ * Write cubic-bezier easings (the `ease`, `ease-in`, `ease-out`, `ease-in-out`, `ease-in-back`
888
+ * and `ease-out-back` presets, and `{ type: 'cubic-bezier' }` curves) as one change with
889
+ * `ease: [x1, y1, x2, y2]` (default true). Needs Flair 0.36 or later; set false for older
890
+ * Flair, and they are sampled into linear steps.
891
+ */
892
+ curves?: boolean;
893
+ /**
894
+ * Write pulses, shakes, teeters, waves, wiggles and colour pulses as one change with a Flair
895
+ * `behavior` (default true), so they play exactly. Needs Flair 0.38 or later; set false for
896
+ * older Flair, and they are sampled into linear steps.
897
+ */
898
+ behaviors?: boolean;
707
899
  }
708
900
  /** The Flair easing that matches `ease` (within 1% everywhere), if any. */
709
901
  declare function flairEaseFor(ease: AnimationEasing): FlairEaseName | undefined;
902
+ /**
903
+ * The Flair easing for `ease`: a Flair name when one matches within 1%, else (with `curves`,
904
+ * the default) the curve's `[x1, y1, x2, y2]` when it is a cubic-bezier. Undefined for curves
905
+ * Flair cannot play (springs, elastic, `hold`), which are sampled.
906
+ */
907
+ declare function flairCurveFor(ease: AnimationEasing, curves?: boolean): FlairEase | undefined;
710
908
  /** A scene as a Flair `SvgMotion`. */
711
909
  declare function toFlairSvgMotion(scene: MotionScene, options?: FlairExportOptions): FlairMotionExport;
712
910
  interface FlairEffectOptions extends FlairExportOptions {
@@ -890,12 +1088,16 @@ declare function describeMotionElements(scene: MotionScene): {
890
1088
  /** A scene's shots with their timing, as agents see them. */
891
1089
  declare function describeMotionShots(scene: MotionScene): {
892
1090
  commands: ({
1091
+ flairPrimitive?: string | undefined;
893
1092
  start: number;
894
1093
  end: number;
895
1094
  type: "enter";
896
1095
  style?: MotionEnterStyle;
897
1096
  direction?: MotionDirection;
898
1097
  distance?: number;
1098
+ scale?: number;
1099
+ shape?: MotionIrisShape;
1100
+ orientation?: MotionSplitOrientation;
899
1101
  targets: string[];
900
1102
  duration?: number;
901
1103
  delay?: number;
@@ -905,6 +1107,7 @@ declare function describeMotionShots(scene: MotionScene): {
905
1107
  note?: string;
906
1108
  index: number;
907
1109
  } | {
1110
+ flairPrimitive?: string | undefined;
908
1111
  start: number;
909
1112
  end: number;
910
1113
  type: "exit";
@@ -920,6 +1123,7 @@ declare function describeMotionShots(scene: MotionScene): {
920
1123
  note?: string;
921
1124
  index: number;
922
1125
  } | {
1126
+ flairPrimitive?: string | undefined;
923
1127
  start: number;
924
1128
  end: number;
925
1129
  type: "draw";
@@ -934,6 +1138,7 @@ declare function describeMotionShots(scene: MotionScene): {
934
1138
  note?: string;
935
1139
  index: number;
936
1140
  } | {
1141
+ flairPrimitive?: string | undefined;
937
1142
  start: number;
938
1143
  end: number;
939
1144
  type: "move";
@@ -954,6 +1159,7 @@ declare function describeMotionShots(scene: MotionScene): {
954
1159
  note?: string;
955
1160
  index: number;
956
1161
  } | {
1162
+ flairPrimitive?: string | undefined;
957
1163
  start: number;
958
1164
  end: number;
959
1165
  type: "rotate";
@@ -968,6 +1174,7 @@ declare function describeMotionShots(scene: MotionScene): {
968
1174
  note?: string;
969
1175
  index: number;
970
1176
  } | {
1177
+ flairPrimitive?: string | undefined;
971
1178
  start: number;
972
1179
  end: number;
973
1180
  type: "scale";
@@ -984,6 +1191,7 @@ declare function describeMotionShots(scene: MotionScene): {
984
1191
  note?: string;
985
1192
  index: number;
986
1193
  } | {
1194
+ flairPrimitive?: string | undefined;
987
1195
  start: number;
988
1196
  end: number;
989
1197
  type: "fade";
@@ -997,6 +1205,7 @@ declare function describeMotionShots(scene: MotionScene): {
997
1205
  note?: string;
998
1206
  index: number;
999
1207
  } | {
1208
+ flairPrimitive?: string | undefined;
1000
1209
  start: number;
1001
1210
  end: number;
1002
1211
  type: "style";
@@ -1012,6 +1221,7 @@ declare function describeMotionShots(scene: MotionScene): {
1012
1221
  note?: string;
1013
1222
  index: number;
1014
1223
  } | {
1224
+ flairPrimitive?: string | undefined;
1015
1225
  start: number;
1016
1226
  end: number;
1017
1227
  type: "morph";
@@ -1025,6 +1235,7 @@ declare function describeMotionShots(scene: MotionScene): {
1025
1235
  note?: string;
1026
1236
  index: number;
1027
1237
  } | {
1238
+ flairPrimitive?: string | undefined;
1028
1239
  start: number;
1029
1240
  end: number;
1030
1241
  type: "follow";
@@ -1041,6 +1252,7 @@ declare function describeMotionShots(scene: MotionScene): {
1041
1252
  note?: string;
1042
1253
  index: number;
1043
1254
  } | {
1255
+ flairPrimitive?: string | undefined;
1044
1256
  start: number;
1045
1257
  end: number;
1046
1258
  type: "pulse";
@@ -1055,11 +1267,77 @@ declare function describeMotionShots(scene: MotionScene): {
1055
1267
  note?: string;
1056
1268
  index: number;
1057
1269
  } | {
1270
+ flairPrimitive?: string | undefined;
1058
1271
  start: number;
1059
1272
  end: number;
1060
1273
  type: "shake";
1061
1274
  amount?: number;
1062
1275
  count?: number;
1276
+ axis?: "horizontal" | "vertical";
1277
+ targets: string[];
1278
+ duration?: number;
1279
+ delay?: number;
1280
+ stagger?: number;
1281
+ with?: "after" | "previous";
1282
+ ease?: AnimationEasing;
1283
+ note?: string;
1284
+ index: number;
1285
+ } | {
1286
+ flairPrimitive?: string | undefined;
1287
+ start: number;
1288
+ end: number;
1289
+ type: "teeter";
1290
+ angle?: number;
1291
+ count?: number;
1292
+ targets: string[];
1293
+ duration?: number;
1294
+ delay?: number;
1295
+ stagger?: number;
1296
+ with?: "after" | "previous";
1297
+ ease?: AnimationEasing;
1298
+ note?: string;
1299
+ index: number;
1300
+ } | {
1301
+ flairPrimitive?: string | undefined;
1302
+ start: number;
1303
+ end: number;
1304
+ type: "wave";
1305
+ amount?: number;
1306
+ count?: number;
1307
+ targets: string[];
1308
+ duration?: number;
1309
+ delay?: number;
1310
+ stagger?: number;
1311
+ with?: "after" | "previous";
1312
+ ease?: AnimationEasing;
1313
+ note?: string;
1314
+ index: number;
1315
+ } | {
1316
+ flairPrimitive?: string | undefined;
1317
+ start: number;
1318
+ end: number;
1319
+ type: "wiggle";
1320
+ amount?: number;
1321
+ frequency?: number;
1322
+ octaves?: number;
1323
+ rotate?: number;
1324
+ seed?: number;
1325
+ targets: string[];
1326
+ duration?: number;
1327
+ delay?: number;
1328
+ stagger?: number;
1329
+ with?: "after" | "previous";
1330
+ ease?: AnimationEasing;
1331
+ note?: string;
1332
+ index: number;
1333
+ } | {
1334
+ flairPrimitive?: string | undefined;
1335
+ start: number;
1336
+ end: number;
1337
+ type: "color-pulse";
1338
+ color?: string;
1339
+ paint?: "fill" | "stroke";
1340
+ count?: number;
1063
1341
  targets: string[];
1064
1342
  duration?: number;
1065
1343
  delay?: number;
@@ -1069,6 +1347,7 @@ declare function describeMotionShots(scene: MotionScene): {
1069
1347
  note?: string;
1070
1348
  index: number;
1071
1349
  } | {
1350
+ flairPrimitive?: string | undefined;
1072
1351
  start: number;
1073
1352
  end: number;
1074
1353
  type: "effect";
@@ -1084,6 +1363,7 @@ declare function describeMotionShots(scene: MotionScene): {
1084
1363
  note?: string;
1085
1364
  index: number;
1086
1365
  } | {
1366
+ flairPrimitive?: string | undefined;
1087
1367
  start: number;
1088
1368
  end: number;
1089
1369
  type: "wait";
@@ -1112,6 +1392,6 @@ declare function createAnimationEditorToolProvider(controller: AnimationEditorCo
1112
1392
  * A short authoring guide for a model writing vector animations with the animation editor's
1113
1393
  * tools. Static, so it caches well as part of a system prompt.
1114
1394
  */
1115
- 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- 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- morph turns a shape into another node's shape (keep the target hidden); follow moves along a path node; pulse and shake draw the eye.\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).\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.";
1395
+ 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- 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).\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.";
1116
1396
 
1117
- export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairMotionExport, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, 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_ISSUE_CODES, MOTION_MIN_CHANGE_MS, type MotionCamera, 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 MotionIssue, type MotionIssueCode, type MotionIssueSeverity, type MotionMorphCommand, type MotionMoveCommand, type MotionNodeEntry, type MotionPreset, type MotionProperty, type MotionPulseCommand, type MotionRect, type MotionRotateCommand, type MotionScaleCommand, type MotionScene, MotionSceneFormatError, type MotionSegment, type MotionShakeCommand, type MotionShot, type MotionShotTiming, type MotionStyleCommand, type MotionSvgOptions, type MotionTimeline, type MotionValue, type MotionWaitCommand, type MotionWave, activeSegment, applyMotionControlValues, applyMotionEdits, checkMotionScene, commandShapeProblems, compileMotionScene, createAnimationEditorToolProvider, createMotionScene, describeMotionElements, describeMotionShots, fitMotionRect, flairEaseFor, freshShotId, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, motionCommandDuration, motionFrameAt, motionFrameToSvg, motionIssue, motionIssueKey, motionIssueLine, motionNodeOffset, motionPathLength, motionRestValue, motionSceneShapeProblems, motionSceneToJson, motionShotAt, motionTrackKey, namedWithSuggestion, parseMotionScene, resolveMotionCamera, segmentProgress, segmentValue, shotShapeProblems, suggestName, toFlairEffectDocument, toFlairSvgMotion, toFlairVectorEffect, trackValue, withViewBox };
1397
+ export { ANIMATION_EDITOR_AGENT_INSTRUCTIONS, AnimationEditorController, type AnimationEditorOptions, type AnimationEditorSelection, type AnimationEditorState, type AnimationEditorToolProviderOptions, FLAIR_EASES, type FlairEase, type FlairEaseName, type FlairEffectDocument, type FlairEffectOptions, type FlairExportOptions, type FlairMotionExport, type FlairSvgAnimation, type FlairSvgMotion, type FlairVectorEffect, 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_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, flairCurveFor, flairEaseFor, freshShotId, indexMotionNodes, interpolateMotionValue, isMotionCommand, isMotionShot, motionClipAttrs, motionCommandDuration, 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, withViewBox };