@pixerate/editor 0.57.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;
@@ -631,8 +792,16 @@ declare function createMotionScene(artwork: VectorDocument, init?: Partial<Omit<
631
792
  * Changes are exact where Flair can express them: a change with a linear, cubic-out or
632
793
  * cubic-in-out curve (the editor's defaults) is one change, and so (Flair 0.36 and later) is
633
794
  * one with any cubic-bezier curve, written as `[x1, y1, x2, y2]`. Anything else (springs,
634
- * elastic, `hold`, pulses and shakes, follows, morphs and live-effect tweens) is sampled at the
635
- * scene's `fps` into short linear changes, which Flair plays the same way.
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.
636
805
  */
637
806
  /** Flair's easing names. */
638
807
  type FlairEaseName = 'linear' | 'in-out' | 'out';
@@ -649,6 +818,13 @@ interface FlairSvgAnimation {
649
818
  ease?: FlairEase;
650
819
  attrs?: Record<string, readonly [string | number, string | number]>;
651
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;
652
828
  view?: readonly [number, number, number, number] | string;
653
829
  }
654
830
  /** Mirrors `SvgMotion` in `@pixerate/flair/vector`. */
@@ -714,6 +890,12 @@ interface FlairExportOptions {
714
890
  * Flair, and they are sampled into linear steps.
715
891
  */
716
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;
717
899
  }
718
900
  /** The Flair easing that matches `ease` (within 1% everywhere), if any. */
719
901
  declare function flairEaseFor(ease: AnimationEasing): FlairEaseName | undefined;
@@ -906,12 +1088,16 @@ declare function describeMotionElements(scene: MotionScene): {
906
1088
  /** A scene's shots with their timing, as agents see them. */
907
1089
  declare function describeMotionShots(scene: MotionScene): {
908
1090
  commands: ({
1091
+ flairPrimitive?: string | undefined;
909
1092
  start: number;
910
1093
  end: number;
911
1094
  type: "enter";
912
1095
  style?: MotionEnterStyle;
913
1096
  direction?: MotionDirection;
914
1097
  distance?: number;
1098
+ scale?: number;
1099
+ shape?: MotionIrisShape;
1100
+ orientation?: MotionSplitOrientation;
915
1101
  targets: string[];
916
1102
  duration?: number;
917
1103
  delay?: number;
@@ -921,6 +1107,7 @@ declare function describeMotionShots(scene: MotionScene): {
921
1107
  note?: string;
922
1108
  index: number;
923
1109
  } | {
1110
+ flairPrimitive?: string | undefined;
924
1111
  start: number;
925
1112
  end: number;
926
1113
  type: "exit";
@@ -936,6 +1123,7 @@ declare function describeMotionShots(scene: MotionScene): {
936
1123
  note?: string;
937
1124
  index: number;
938
1125
  } | {
1126
+ flairPrimitive?: string | undefined;
939
1127
  start: number;
940
1128
  end: number;
941
1129
  type: "draw";
@@ -950,6 +1138,7 @@ declare function describeMotionShots(scene: MotionScene): {
950
1138
  note?: string;
951
1139
  index: number;
952
1140
  } | {
1141
+ flairPrimitive?: string | undefined;
953
1142
  start: number;
954
1143
  end: number;
955
1144
  type: "move";
@@ -970,6 +1159,7 @@ declare function describeMotionShots(scene: MotionScene): {
970
1159
  note?: string;
971
1160
  index: number;
972
1161
  } | {
1162
+ flairPrimitive?: string | undefined;
973
1163
  start: number;
974
1164
  end: number;
975
1165
  type: "rotate";
@@ -984,6 +1174,7 @@ declare function describeMotionShots(scene: MotionScene): {
984
1174
  note?: string;
985
1175
  index: number;
986
1176
  } | {
1177
+ flairPrimitive?: string | undefined;
987
1178
  start: number;
988
1179
  end: number;
989
1180
  type: "scale";
@@ -1000,6 +1191,7 @@ declare function describeMotionShots(scene: MotionScene): {
1000
1191
  note?: string;
1001
1192
  index: number;
1002
1193
  } | {
1194
+ flairPrimitive?: string | undefined;
1003
1195
  start: number;
1004
1196
  end: number;
1005
1197
  type: "fade";
@@ -1013,6 +1205,7 @@ declare function describeMotionShots(scene: MotionScene): {
1013
1205
  note?: string;
1014
1206
  index: number;
1015
1207
  } | {
1208
+ flairPrimitive?: string | undefined;
1016
1209
  start: number;
1017
1210
  end: number;
1018
1211
  type: "style";
@@ -1028,6 +1221,7 @@ declare function describeMotionShots(scene: MotionScene): {
1028
1221
  note?: string;
1029
1222
  index: number;
1030
1223
  } | {
1224
+ flairPrimitive?: string | undefined;
1031
1225
  start: number;
1032
1226
  end: number;
1033
1227
  type: "morph";
@@ -1041,6 +1235,7 @@ declare function describeMotionShots(scene: MotionScene): {
1041
1235
  note?: string;
1042
1236
  index: number;
1043
1237
  } | {
1238
+ flairPrimitive?: string | undefined;
1044
1239
  start: number;
1045
1240
  end: number;
1046
1241
  type: "follow";
@@ -1057,6 +1252,7 @@ declare function describeMotionShots(scene: MotionScene): {
1057
1252
  note?: string;
1058
1253
  index: number;
1059
1254
  } | {
1255
+ flairPrimitive?: string | undefined;
1060
1256
  start: number;
1061
1257
  end: number;
1062
1258
  type: "pulse";
@@ -1071,11 +1267,77 @@ declare function describeMotionShots(scene: MotionScene): {
1071
1267
  note?: string;
1072
1268
  index: number;
1073
1269
  } | {
1270
+ flairPrimitive?: string | undefined;
1074
1271
  start: number;
1075
1272
  end: number;
1076
1273
  type: "shake";
1077
1274
  amount?: number;
1078
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;
1079
1341
  targets: string[];
1080
1342
  duration?: number;
1081
1343
  delay?: number;
@@ -1085,6 +1347,7 @@ declare function describeMotionShots(scene: MotionScene): {
1085
1347
  note?: string;
1086
1348
  index: number;
1087
1349
  } | {
1350
+ flairPrimitive?: string | undefined;
1088
1351
  start: number;
1089
1352
  end: number;
1090
1353
  type: "effect";
@@ -1100,6 +1363,7 @@ declare function describeMotionShots(scene: MotionScene): {
1100
1363
  note?: string;
1101
1364
  index: number;
1102
1365
  } | {
1366
+ flairPrimitive?: string | undefined;
1103
1367
  start: number;
1104
1368
  end: number;
1105
1369
  type: "wait";
@@ -1128,6 +1392,6 @@ declare function createAnimationEditorToolProvider(controller: AnimationEditorCo
1128
1392
  * A short authoring guide for a model writing vector animations with the animation editor's
1129
1393
  * tools. Static, so it caches well as part of a system prompt.
1130
1394
  */
1131
- 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.";
1132
1396
 
1133
- 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_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, flairCurveFor, 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 };