@weasel-js/animator 1.10.1 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,970 @@
1
+ import { EasingSpec, SpringPresetName } from '@weasel-js/geom';
2
+
3
+ /**
4
+ * What an axis of a `T` goes by: a field of a plain object, or a path into a nested one, as a
5
+ * pose's `knee` and `knee.rotation` are. `never` for a number or an array, whose axes have
6
+ * indexes only.
7
+ */
8
+ type AxisName<T> = T extends number | readonly unknown[] ? never : T extends object ? {
9
+ [K in keyof T & string]: NonNullable<T[K]> extends number ? K : K | `${K}.${string}`;
10
+ }[keyof T & string] : string;
11
+ /** One of a target's axes: its index, or its name where the target's axes have names. */
12
+ type AxisRef<T = unknown> = number | AxisName<T>;
13
+
14
+ /** How a target's value maps to the flat numbers an animation moves, and back. */
15
+ interface TargetAxes<T> {
16
+ count: number;
17
+ to(value: T): number[];
18
+ from(axes: ArrayLike<number>): T;
19
+ /** Indexes of axes that are angles in radians. An animation starting from one takes the short
20
+ * way round to its destination. */
21
+ angles?: readonly number[];
22
+ /** A name for each axis, in the order `to` answers them, for `axes` options to go by. A dot
23
+ * makes a path: `knee.rotation` is also reached as `knee`, with the joint's other axes. */
24
+ names?: readonly string[];
25
+ /** Optional. `value` with `delta` added axis by axis: what `from` answers for `to(value)`
26
+ * plus `delta`, built with no array between. A read of a moving target goes through it. */
27
+ add?(value: T, delta: ArrayLike<number>): T;
28
+ /** Optional. Puts `value`'s axes into `out` from `at`: what `to` answers, with no array
29
+ * built. `readInto` goes through it. */
30
+ write?(value: T, out: AxisBuffer, at: number): void;
31
+ }
32
+ /** Somewhere a target's axes are written as numbers. */
33
+ type AxisBuffer = Float64Array | Float32Array | number[];
34
+ /** What {@link createTarget} takes. */
35
+ interface TargetOptions<T> {
36
+ /** The committed value: what shows when nothing is animating. */
37
+ get(): T;
38
+ /** Commits a value: an animation's destination as it starts, and where a canceled one stopped. */
39
+ set(value: T): void;
40
+ /** How `T` maps to numbers. Default: a number, an array of numbers, or a plain object whose
41
+ * fields are all numbers, read from `get()` when the target is made. */
42
+ axes?: TargetAxes<T>;
43
+ /** Called once a frame, after the frame's animations, with the value to show: on every frame
44
+ * the target is moving, as an animation starts on it or is redirected, and once more as it
45
+ * comes to rest. Omit for a target whose reader
46
+ * calls `read()` itself. */
47
+ show?(value: T): void;
48
+ /** Called once a frame, after every target that was shown that frame: for a table that
49
+ * publishes many targets at once. Targets passing the same function share one call. */
50
+ publish?(): void;
51
+ }
52
+ /**
53
+ * One value an animator can move. Pass it as `target` to `tween`, `spring`, `physics` or `decay`.
54
+ *
55
+ * An animation on a target commits its destination when it starts and contributes only what is
56
+ * left to travel, so several on one target add: a second started mid-flight bends the motion
57
+ * toward its own destination and neither cancels the other.
58
+ */
59
+ interface Target<T> {
60
+ /** The value to show: the committed value plus what every running animation has left to travel. */
61
+ read(): T;
62
+ /**
63
+ * As `read`, as numbers: writes the value's `axisCount` axes into `out` from `at` (default 0),
64
+ * in the order the target's `axes.to` answers them. For a reader of many targets that wants
65
+ * the numbers and no value built for each.
66
+ */
67
+ readInto(out: AxisBuffer, at?: number): void;
68
+ /** How many axes `readInto` writes. */
69
+ readonly axisCount: number;
70
+ /** How its value maps to numbers. */
71
+ readonly axes: TargetAxes<T>;
72
+ /**
73
+ * The indexes of the axes `axes` names, in the order named: what a hold's or a track's `axes`
74
+ * resolves through. A name is one of `axes.names`, or a path over several of them; an index
75
+ * passes through. Throws on a name or an index the target has no axis for.
76
+ */
77
+ axisIndexes(axes: readonly AxisRef<T>[]): number[];
78
+ /** The committed value: what shows once nothing is moving it. */
79
+ committed(): T;
80
+ /** Writes the committed value. Animations moving the target go on adding to the new one. */
81
+ commit(value: T): void;
82
+ /** Whether any animation is moving it. */
83
+ readonly active: boolean;
84
+ /**
85
+ * Stops every animation moving it. Each commits where it was, so the value on screen stays,
86
+ * unless `commit` is false: then the committed value is left as it stands and the target
87
+ * shows it. Pass false after something else has written the committed value mid-flight.
88
+ */
89
+ stop(opts?: {
90
+ commit?: boolean;
91
+ }): void;
92
+ }
93
+ /** Make a {@link Target} over a value the caller owns. */
94
+ declare function createTarget<T>(opts: TargetOptions<T>): Target<T>;
95
+
96
+ /** Which of a node's two per-anchor color arrays an override applies to. */
97
+ type VertexColorChannel = 'fill' | 'stroke';
98
+ /** Function-form override: receives the consumer-supplied base color
99
+ * array and the current animation timestamp (ms, from the animator's
100
+ * clock). Returns a flat RGBA float array (values in 0..1, matching
101
+ * the renderer's `stroke.vertexColors` / `PathDrawCommand.vertexColors`
102
+ * color space) of the same length as `base`. */
103
+ type ColorOverrideFn = (base: readonly number[], tMs: number) => number[];
104
+ /** Either a static per-anchor RGBA float array (0..1) or a function-form
105
+ * override (see {@link ColorOverrideFn}). */
106
+ type ColorOverride = readonly number[] | ColorOverrideFn;
107
+ /** Per-node, per-channel store of color overrides. Attached to `useAnimator` as
108
+ * `animator.colorOverrides`; painted onto scene nodes by `<SceneCanvas animator>`
109
+ * and onto a `createPathLayer`'s nodes by its `colorOverrides` option. */
110
+ declare class ColorOverrideRegistry {
111
+ private readonly map;
112
+ private readonly slots;
113
+ private readonly tables;
114
+ private _version;
115
+ set(id: string, channel: VertexColorChannel, override: ColorOverride): void;
116
+ /** Drops `id`'s override on `channel`, and the colors a finished or canceled animation on its
117
+ * {@link target} left painted. An animation still running goes on. */
118
+ clear(id: string, channel: VertexColorChannel): void;
119
+ clearAll(): void;
120
+ /** What `set` stored for `id`'s `channel`; failing that, the colors its {@link target} paints. */
121
+ get(id: string, channel: VertexColorChannel): ColorOverride | undefined;
122
+ /** Whether anything overrides `id`, on either channel. */
123
+ has(id: string): boolean;
124
+ /**
125
+ * The {@link Target} for `id`'s colors on `channel`: `length` numbers, flat RGBA per anchor.
126
+ * Every caller for one node and channel gets the same one, so their animations add. The
127
+ * registry holds its committed colors and nothing writes the scene.
128
+ *
129
+ * What it paints: with no override from `set`, its colors in place of the painter's own; over
130
+ * one, only what its animations have left to travel, added on top. Ask again for each
131
+ * animation rather than keeping it: {@link release} and {@link clear} drop a resting one, and
132
+ * the target it had throws from then on.
133
+ */
134
+ target(id: string, channel: VertexColorChannel, length: number): Target<number[]>;
135
+ private tableOf;
136
+ private drop;
137
+ /** Drops the colors `id`'s {@link target} on `channel` left painted, unless an animation is
138
+ * still moving it. An override from `set` stays. */
139
+ release(id: string, channel: VertexColorChannel): void;
140
+ /**
141
+ * The colors to paint on `id`'s `channel`, given the colors the painter would
142
+ * otherwise paint and the frame's timestamp. A function override needs that
143
+ * `base` and must return an array of its length; failing either, `base`
144
+ * stands. A {@link target} in motion then adds what it has left to travel.
145
+ */
146
+ resolve(id: string, channel: VertexColorChannel, base: readonly number[] | undefined, tMs: number): readonly number[] | undefined;
147
+ private apply;
148
+ version(): number;
149
+ }
150
+
151
+ /** One keyframe. `easing` shapes the approach INTO this key from the previous
152
+ * one, so the first key's easing is never consulted. */
153
+ interface Keyframe<T> {
154
+ /** Time within the track's timeline, in ms. */
155
+ t: number;
156
+ value: T;
157
+ /** A function, the name of a built-in, or cubic-bezier control points. */
158
+ easing?: EasingSpec;
159
+ }
160
+ /** A track sampled as a pure function of the playhead. Scrubbing one is free
161
+ * and order-independent. Give it `onTick`, a `target`, or both. */
162
+ interface SampledTrack<T> {
163
+ kind: 'sampled';
164
+ label?: string;
165
+ /** Sorted ascending by `t`. Of keys sharing a time, the last in the array is
166
+ * the value at exactly that time. */
167
+ keys: Keyframe<T>[];
168
+ /** Required unless the track has a `target`, or every key's value is a number, a number
169
+ * array or a plain object of numbers, all of one shape; those are lerped field by field. */
170
+ interpolate?: Interpolate<T>;
171
+ /** Built once per segment and cached. Takes precedence over `interpolate`. */
172
+ interpolator?: InterpolatorFactory<T>;
173
+ /** Told each sampled value, at any playhead. Optional beside a `target`. */
174
+ onTick?: (value: T) => void;
175
+ /**
176
+ * A value for the track to move. While the playhead is within the track's keys, the target
177
+ * shows the sampled value in place of its committed one, as under `animator.hold`, with
178
+ * what an animation on the target shows apart from its destination added on top. Once the playhead is past the last key, or the
179
+ * timeline finishes or is canceled, the target keeps the value it was showing; before the
180
+ * first key the track leaves the target alone.
181
+ *
182
+ * With no `interpolate` or `interpolator`, the track is sampled in the target's axes: each
183
+ * axis lerps on its own, an angle axis the short way round from the key before, and every
184
+ * sample is a value the axes built, a key's own included.
185
+ */
186
+ target?: Target<T>;
187
+ /** What `target` goes by in a clip, for `toClip` to write and a `ClipBinder` to resolve.
188
+ * A target has no name of its own. */
189
+ targetName?: string;
190
+ /** What `interpolate` goes by in a clip, as `targetName` is for `target`. */
191
+ interpolateName?: string;
192
+ /** The track's share among the target's holds, as `HoldOptions.weight`. Default 1. */
193
+ weight?: number | (() => number);
194
+ /** What a function `weight` goes by in a clip, as `targetName` is for `target`. */
195
+ weightName?: string;
196
+ /** The axes of the target the track holds, by name or by index, as `HoldOptions.axes`.
197
+ * Default: every axis. A clip carries them as they are written here. */
198
+ axes?: readonly AxisRef<T>[];
199
+ }
200
+ /** A clock that events are booked against, reading in ms. An `AudioEngine`
201
+ * from `@weasel-js/audio` is one. */
202
+ interface TimelineClock {
203
+ now(): number;
204
+ }
205
+ /** What `book` hands back so the booking can be retracted. A `VoiceHandle` from
206
+ * `@weasel-js/audio` is one. */
207
+ interface EventBookingHandle {
208
+ stop(): void;
209
+ }
210
+ /** One entry on an `EventTrack`. Give it `fire`, `book`, or both. */
211
+ interface TimelineEvent {
212
+ /** Time within the track's timeline, in ms. */
213
+ t: number;
214
+ /** What the event goes by in a clip: a `ClipBinder` turns it and `data` into `fire` and
215
+ * `book`. */
216
+ name?: string;
217
+ /** Carried with `name` into a clip. Anything JSON holds. */
218
+ data?: unknown;
219
+ /** Runs on the frame that crosses the edge, told how far behind the frame it
220
+ * was crossed, in ms — never negative, and measured against `duration` on
221
+ * the loop seam, where the outgoing lap's tail fires after the wrap. */
222
+ fire?: (lateBy: number) => void;
223
+ /** Runs up to `booking.lookahead` before the edge on a timeline with a
224
+ * `booking`, once per crossing, with the `booking.clock` time the edge lands
225
+ * at — never earlier than that clock's `now()`. A returned handle is stopped
226
+ * if a pause, seek, rate change, loop change, edit or cancel invalidates the
227
+ * booking before the clock reaches `when`; the event is then booked again
228
+ * wherever playback next reaches it. A booking with no handle stands. */
229
+ book?: (when: number) => EventBookingHandle | void;
230
+ }
231
+ /** A track of edge crossings, in forward playback only — a `seek` neither
232
+ * fires nor books the span it skips. An event the playhead is sitting on,
233
+ * after a seek or at the start, fires when playback next advances from there
234
+ * and never while paused. */
235
+ interface EventTrack {
236
+ kind: 'event';
237
+ label?: string;
238
+ /** Sorted ascending by `t`. */
239
+ events: TimelineEvent[];
240
+ }
241
+ /** How a timeline books its events against an outside clock. */
242
+ interface EventBooking {
243
+ clock: TimelineClock;
244
+ /** How far ahead of the playhead to book, in clock ms. Default 100. An event
245
+ * first reached later than this — after a frame longer than it — books late. */
246
+ lookahead?: number;
247
+ /** An event first reached more than this many clock ms after its edge is
248
+ * skipped instead of booked late. Default `Infinity`. */
249
+ maxLate?: number;
250
+ }
251
+ /** A nested timeline, evaluated at `playhead - at`. Children are NOT registered
252
+ * with the animator separately; the parent evaluates them. */
253
+ interface TimelineTrack {
254
+ kind: 'timeline';
255
+ label?: string;
256
+ at: number;
257
+ timeline: NestedTimeline;
258
+ }
259
+ /** Any track a timeline can hold. */
260
+ type Track = SampledTrack<any> | EventTrack | TimelineTrack;
261
+ /** What a child timeline may declare. The parent owns playback, so `loop`,
262
+ * `autoplay`, `onDone` and `cancelKey` have no meaning below the root. */
263
+ interface NestedTimeline {
264
+ tracks: Track[];
265
+ /** Defaults to the largest end time across `tracks`. */
266
+ duration?: number;
267
+ }
268
+ /** What `animator.timeline` takes: a root timeline, which owns playback. */
269
+ interface TimelineOptions extends NestedTimeline {
270
+ /** `true` loops forever, `n` loops n additional times. Default false. */
271
+ loop?: boolean | number;
272
+ /** Default true. When false the timeline registers but holds at t=0 until resumed. */
273
+ autoplay?: boolean;
274
+ /** Called when playback reaches the end of its last lap. */
275
+ onDone?: () => void;
276
+ /** Any new animation passed the same `cancelKey` cancels this one. */
277
+ cancelKey?: string;
278
+ /** Names this timeline in `animator.watch` events and `animator.live()`. */
279
+ label?: string;
280
+ /** Books each event's `book` against a clock the timeline does not own, so a
281
+ * consumer on that clock lands it at its true sub-frame time. The frame
282
+ * clock's mapping onto it is smoothed each frame and resynced on a jump. */
283
+ booking?: EventBooking;
284
+ }
285
+ /** What `animator.timeline` returns: playback control plus live editing. */
286
+ interface TimelineHandle extends AnimationHandle {
287
+ /** Move the playhead. Fires no event itself, at any depth; an event exactly
288
+ * at `t` fires when playback next advances. Sampled tracks are sampled at
289
+ * `t` at once, so a target they hold reads the new value before the next frame. */
290
+ seek(t: number): void;
291
+ /** Change the loop policy. `true` loops forever, `n` allows n more laps,
292
+ * `false` stops at `duration`. Sets policy only — a timeline already parked
293
+ * at `duration` does not restart, because `rearm` declines to revive one.
294
+ * Rewind it with `seek(0)` and `resume()` to play it again. */
295
+ setLoop(loop: boolean | number): void;
296
+ /** The loop policy as it now stands: `true` endless, `false` stopping at
297
+ * `duration`, `n` for n laps still allowed. A finite count falls as laps
298
+ * are consumed, matching what `setLoop` takes. */
299
+ loop(): boolean | number;
300
+ /** Current playhead in ms. */
301
+ time(): number;
302
+ duration(): number;
303
+ tracks(): readonly Track[];
304
+ /** Run `fn`, then recompute duration, drop cached interpolators, sample the
305
+ * tracks again where the playhead stands, and notify.
306
+ * Every mutation must go through this — an edited keyframe otherwise keeps
307
+ * interpolating toward its old value with no visible error. */
308
+ edit(fn: () => void): void;
309
+ /** Notified after each `edit`. Returns an unsubscribe. */
310
+ subscribe(cb: () => void): () => void;
311
+ /** Notified when playback changes other than by time passing: `pause`,
312
+ * `resume`, `seek`, `setTimeScale`, `setLoop`, a cancel, and the playhead
313
+ * reaching the end. What a view of the playhead listens to, so a change
314
+ * made elsewhere reaches it. Returns an unsubscribe. */
315
+ subscribePlayback(cb: () => void): () => void;
316
+ }
317
+
318
+ /** The arrays a table can keep its rows' values on screen in. */
319
+ type ShownArray = Float64Array | Float32Array;
320
+ /** What {@link createTargetTable} takes. */
321
+ interface TargetTableOptions<S extends ShownArray = Float64Array> {
322
+ /** How many numbers a row holds. */
323
+ axes: number;
324
+ /** The kind of array to keep `shown` in. Default `Float64Array`. Pass `Float32Array` for a
325
+ * painter that uploads it: the table then fills that each frame, and no copy is made. */
326
+ shown?: new (length: number) => S;
327
+ /** Rows to make room for at first. The table grows past it. Default 64. */
328
+ capacity?: number;
329
+ /** Called after `row` is committed: by `set`, by an animation starting on it, and by one
330
+ * canceled on it. */
331
+ set?(row: number): void;
332
+ /** Called once a frame, after the animator has filled `shown` for the rows it is moving. */
333
+ show?(): void;
334
+ }
335
+ /**
336
+ * Many like values an animator can move, kept as rows of numbers in flat arrays: for thousands
337
+ * of particles, dots, or vertex colors, where a `Target` apiece costs a read apiece. Each row
338
+ * is a target (`target(row)`), so it tweens, springs, coasts, and holds like any other, and
339
+ * every row's value on screen is in `shown` after each frame, with no call per row.
340
+ */
341
+ interface TargetTable<S extends ShownArray = Float64Array> {
342
+ readonly axes: number;
343
+ /** How many rows are in use. */
344
+ readonly size: number;
345
+ /** Every row's committed value, row `r` at `r * axes`. A new array once the table grows, so
346
+ * read it from the table each time. Write a row through `set`. */
347
+ readonly committed: Float64Array;
348
+ /** Every row's value on screen, laid out as `committed`: current after each frame of the
349
+ * animator moving the rows, and whenever it is read between frames. A new array once the
350
+ * table grows. A `Float32Array` where the table was made with `shown: Float32Array`. */
351
+ readonly shown: S;
352
+ /** Adds a row at `value` and answers its index, which a removed row's index is reused for. */
353
+ add(value: ArrayLike<number>): number;
354
+ /** Stops whatever is moving `row` and frees it. Its target is dead from here: a row added
355
+ * later may take the index, and gets a target of its own. */
356
+ remove(row: number): void;
357
+ /** Commits `value` to `row`. A row that is moving keeps what its animations have left on top. */
358
+ set(row: number, value: ArrayLike<number>): void;
359
+ /** Row `row` as a target, the same one on every call. */
360
+ target(row: number): Target<number[]>;
361
+ }
362
+ /** Make a {@link TargetTable} whose rows each hold `axes` numbers. */
363
+ declare function createTargetTable<S extends ShownArray = Float64Array>(opts: TargetTableOptions<S>): TargetTable<S>;
364
+
365
+ /** What every animation on a {@link Target} takes. */
366
+ interface OnTarget<T> {
367
+ /** The value to move. */
368
+ target: Target<T>;
369
+ /** Told this animation's own value each frame: its destination plus what it has left to travel. */
370
+ onTick?: (value: T) => void;
371
+ onDone?: () => void;
372
+ /** Any new animation passed the same cancelKey cancels the prior one in flight. Leave it off
373
+ * to let animations on one target add. */
374
+ cancelKey?: string;
375
+ /** False to take `cancelKey` without canceling the animations holding it, so it adds to them
376
+ * and `cancelKey`, `pauseKey`, and `isActive` reach them all. Default true. */
377
+ interrupt?: boolean;
378
+ /** Names this animation in {@link AnimatorEvent}s and `animator.live()`. */
379
+ label?: string;
380
+ }
381
+ /** A tween on a {@link Target}. `to` is committed as it starts, and it contributes what is left
382
+ * to travel, so it adds to whatever else is moving the target. */
383
+ interface TargetTweenOptions<T> extends OnTarget<T> {
384
+ to: T;
385
+ /** Where its own travel starts. Default: the target's committed value, so the value on screen
386
+ * does not move as it starts. */
387
+ from?: T;
388
+ ms: number;
389
+ easing?: EasingSpec;
390
+ /** The path from `from` to `to`, where a straight line per axis is not it. */
391
+ interpolate?: Interpolate<T>;
392
+ /** As `interpolate`, built once at the start. Takes precedence. */
393
+ interpolator?: InterpolatorFactory<T>;
394
+ }
395
+ /** A spring on a {@link Target}. Needs positive stiffness, damping and mass. Interrupting an
396
+ * animation on the same target under the same `cancelKey`, it starts at that one's velocity
397
+ * unless given its own. */
398
+ interface TargetSpringOptions<T> extends OnTarget<T> {
399
+ to: T;
400
+ /** As {@link TargetTweenOptions.from}. */
401
+ from?: T;
402
+ /** Initial velocity in T-units per second. */
403
+ velocity?: T;
404
+ preset?: SpringPresetName;
405
+ stiffness?: number;
406
+ damping?: number;
407
+ mass?: number;
408
+ /** Distance from `to` and speed, both in axis units, under which it has come to rest. Default 0.01. */
409
+ restThreshold?: number;
410
+ }
411
+ /** Spring and coast as one animation on a {@link Target}. With `to: null` it coasts on its
412
+ * velocity, committing where it is when it stops. */
413
+ interface TargetPhysicsOptions<T> extends Omit<TargetSpringOptions<T>, 'to'> {
414
+ to?: T | null;
415
+ }
416
+ /** What `animator.hold` takes. */
417
+ interface HoldOptions<T> {
418
+ /** The value to hold. */
419
+ target: Target<T>;
420
+ /** What to show in place of the committed value: a value, or a function read each frame.
421
+ * A value is read as the hold starts and again at `touch()`, and costs a frame nothing. */
422
+ value: T | (() => T);
423
+ /** Its share among the target's holds, 0 to 1: a number, or a function read each frame.
424
+ * Default 1. Holds on one target show their weighted average, and whatever their weights
425
+ * leave short of 1 is the committed value's. */
426
+ weight?: number | (() => number);
427
+ /**
428
+ * The axes of the target it holds, each by name or by index: a plain object's fields
429
+ * (`['y']`), a rig's joints (`['armL', 'foreL']`) or one of a joint's own
430
+ * (`['armL.rotation']`), as `target.axisIndexes` resolves them when the hold starts. The
431
+ * rest are left to the target's other holds and its committed value, and a release commits
432
+ * only these. Default: every axis.
433
+ */
434
+ axes?: readonly AxisRef<T>[];
435
+ /** Any new animation passed the same cancelKey cancels this one. */
436
+ cancelKey?: string;
437
+ /** Names this hold in {@link AnimatorEvent}s and `animator.live()`. */
438
+ label?: string;
439
+ /** With `false`, it takes its `cancelKey` without canceling whoever holds it. Default true. */
440
+ interrupt?: boolean;
441
+ }
442
+ /** What `animator.hold` returns. `cancel` commits what the hold was showing, as `release()`
443
+ * does; pausing it or scaling its time changes nothing, since it has no clock. */
444
+ interface HoldHandle extends AnimationHandle {
445
+ /** Says a function-form `value` or `weight` changed outside a frame, so the target shows it
446
+ * now rather than at the next frame the animator happens to run. A `value` given as an
447
+ * object and then written in place shows only once this is called. */
448
+ touch(): void;
449
+ /** Ends the hold. By default it commits the value it was showing, so the target stays where
450
+ * it is; with `commit: false` the committed value is left alone and the target falls back
451
+ * to it. */
452
+ release(opts?: {
453
+ commit?: boolean;
454
+ }): void;
455
+ }
456
+ /** What `animator.holdRows` takes. */
457
+ interface HoldRowsOptions {
458
+ /** The table whose rows it holds. */
459
+ table: TargetTable<ShownArray>;
460
+ /** The rows to hold. Default: every row the table has as the hold starts. */
461
+ rows?: ArrayLike<number>;
462
+ /** The weight each row starts at, 0 to 1. Default 1. */
463
+ weight?: number;
464
+ /** The axes of each row it holds, by index. Default: all of them. */
465
+ axes?: readonly number[];
466
+ /** Any new animation passed the same cancelKey cancels this one. */
467
+ cancelKey?: string;
468
+ /** Names it in {@link AnimatorEvent}s and `animator.live()`. */
469
+ label?: string;
470
+ /** With `false`, it takes its `cancelKey` without canceling whoever holds it. Default true. */
471
+ interrupt?: boolean;
472
+ }
473
+ /**
474
+ * What `animator.holdRows` returns: a hold on each of its rows, which shows that row's value in
475
+ * `values` at its weight in `weights`, mixed with the row's other holds as `hold`'s are. Write
476
+ * either in place and call `touch()`. A row stopped through its target, or removed from the
477
+ * table, is let go of; the rest stay held until the hold is released or canceled, each
478
+ * committing what it showed, as `release()` does.
479
+ */
480
+ interface RowsHoldHandle extends HoldHandle {
481
+ /** Each row's value to hold, laid out as `table.committed`: row `r` at `r * table.axes`.
482
+ * A held row starts at its committed value. A new array once the table grows. */
483
+ readonly values: Float64Array;
484
+ /** Each held row's weight, 0 to 1, row `r` at `r`. A new array once the table grows. */
485
+ readonly weights: Float64Array;
486
+ }
487
+ /** A coast on a {@link Target}: it commits where it stops. */
488
+ interface TargetDecayOptions<T> extends OnTarget<T> {
489
+ /** As {@link TargetTweenOptions.from}. */
490
+ from?: T;
491
+ velocity: T;
492
+ /** Per-second velocity multiplier in (0, 1). Default 0.95. */
493
+ friction?: number;
494
+ /** Speed below which it stops. Default 0.5. */
495
+ threshold?: number;
496
+ }
497
+
498
+ /** A stagger run's own options: the factory form's fourth argument, and part
499
+ * of every fluent builder method's options. */
500
+ interface StaggerOptions {
501
+ /** Cancel-key for the supervising registration. `animator.cancelKey(key)`
502
+ * cancels the whole stagger; `animator.isActive(key)` returns true while
503
+ * any timer or child is alive. */
504
+ cancelKey?: string;
505
+ /** Names this stagger in {@link AnimatorEvent}s and `animator.live()`. */
506
+ label?: string;
507
+ }
508
+ /** Per-index delay schedule. Number ⇒ `index * delay` ms. Function ⇒ caller
509
+ * decides the absolute delay for each index (e.g. `i => i * i * 30`). */
510
+ type StaggerDelay = number | ((index: number) => number);
511
+ /** Produces the animation for one staggered item. */
512
+ type StaggerFactory<TItem> = (item: TItem, index: number) => AnimationHandle;
513
+ /** A `T` value or a function that derives one from the per-item context. Used
514
+ * by the fluent builder methods (`.tween`, `.spring`) so each item can
515
+ * vary an option (e.g. `to: (_item, i) => (i + 1) * 10`). */
516
+ type StaggerPerItem<T, TItem> = T | ((item: TItem, index: number) => T);
517
+ /** Options for the stagger builder's `.tween` in its `onTick` form: a tween per item, where
518
+ * `from`, `to` and `ms` may each vary by item. `cancelKey` and `label` belong
519
+ * to the stagger as a whole, as in {@link StaggerOptions}. */
520
+ interface StaggerTweenOptions<T, TItem> extends StaggerOptions {
521
+ /** Absent: this form hands values to `onTick`. {@link StaggerTargetTweenOptions} moves targets. */
522
+ target?: undefined;
523
+ from: StaggerPerItem<T, TItem>;
524
+ to: StaggerPerItem<T, TItem>;
525
+ ms: StaggerPerItem<number, TItem>;
526
+ easing?: EasingSpec;
527
+ interpolate?: Interpolate<T>;
528
+ interpolator?: InterpolatorFactory<T>;
529
+ onTick: (value: T, item: TItem, index: number) => void;
530
+ onDone?: (item: TItem, index: number) => void;
531
+ }
532
+ /** Options for the stagger builder's `.spring` in its `onTick` form: a spring per item, where
533
+ * `from`, `to` and `velocity` may each vary by item. */
534
+ interface StaggerSpringOptions<T, TItem> extends StaggerOptions, Pick<SpringOptions<T>, 'preset' | 'stiffness' | 'damping' | 'mass' | 'interpolate' | 'add' | 'subtract' | 'scale' | 'magnitude' | 'restThreshold'> {
535
+ /** Absent: this form hands values to `onTick`. {@link StaggerTargetSpringOptions} moves targets. */
536
+ target?: undefined;
537
+ from: StaggerPerItem<T, TItem>;
538
+ to: StaggerPerItem<T, TItem>;
539
+ velocity?: StaggerPerItem<T, TItem>;
540
+ onTick: (value: T, item: TItem, index: number) => void;
541
+ onDone?: (item: TItem, index: number) => void;
542
+ }
543
+ /** What the stagger builder's methods share where each item's animation moves a {@link Target}. */
544
+ interface StaggerOnTarget<T, TItem> extends StaggerOptions {
545
+ /** The target an item's animation moves: one for them all, or a function of the item.
546
+ * Default: the item itself, where the items are targets. */
547
+ target?: StaggerPerItem<Target<T>, TItem>;
548
+ /** Told an item's animation's own value each frame, as `TargetTweenOptions.onTick` is. */
549
+ onTick?: (value: T, item: TItem, index: number) => void;
550
+ onDone?: (item: TItem, index: number) => void;
551
+ }
552
+ /** Options for the stagger builder's `.tween` moving targets: `animator.tween`'s target form
553
+ * per item, where `to`, `from` and `ms` may each vary by item. The tweens share no
554
+ * `cancelKey`, so each adds to whatever else is moving its target. */
555
+ interface StaggerTargetTweenOptions<T, TItem> extends StaggerOnTarget<T, TItem>, Pick<TargetTweenOptions<T>, 'easing' | 'interpolate' | 'interpolator'> {
556
+ to: StaggerPerItem<T, TItem>;
557
+ from?: StaggerPerItem<T, TItem>;
558
+ ms: StaggerPerItem<number, TItem>;
559
+ }
560
+ /** Options for the stagger builder's `.spring` moving targets: `animator.spring`'s target
561
+ * form per item, where `to`, `from` and `velocity` may each vary by item. */
562
+ interface StaggerTargetSpringOptions<T, TItem> extends StaggerOnTarget<T, TItem>, Pick<TargetSpringOptions<T>, 'preset' | 'stiffness' | 'damping' | 'mass' | 'restThreshold'> {
563
+ to: StaggerPerItem<T, TItem>;
564
+ from?: StaggerPerItem<T, TItem>;
565
+ velocity?: StaggerPerItem<T, TItem>;
566
+ }
567
+ /** `.tween`'s options where the items are targets, each moved by its own tween. No options
568
+ * fit where they are not. */
569
+ type StaggerItemTweenOptions<TItem> = TItem extends Target<infer T> ? StaggerTargetTweenOptions<T, TItem> : never;
570
+ /** `.spring`'s options where the items are targets, as {@link StaggerItemTweenOptions}. */
571
+ type StaggerItemSpringOptions<TItem> = TItem extends Target<infer T> ? StaggerTargetSpringOptions<T, TItem> : never;
572
+ /** Narrows a builder method's target options to the call that names its `target`. */
573
+ type Naming = {
574
+ target: NonNullable<unknown>;
575
+ };
576
+ /**
577
+ * Fluent form of `Animator.stagger`: pick what to run per item after the
578
+ * items and the delay schedule are already fixed.
579
+ *
580
+ * `.tween` and `.spring` each take three shapes of options. Where the items are targets, each
581
+ * item's animation moves the item: `animator.stagger(targets, 80).spring({ to: (t) => ... })`.
582
+ * With a `target`, it moves the target that names for the item. With neither, it hands its
583
+ * values to `onTick`.
584
+ */
585
+ interface StaggerBuilder<TItem> {
586
+ /** Run an arbitrary per-item factory. */
587
+ each(factory: StaggerFactory<TItem>, opts?: StaggerOptions): AnimationHandle;
588
+ /** Per-item `animator.tween` with per-item-varying options. */
589
+ tween(opts: StaggerItemTweenOptions<TItem>): AnimationHandle;
590
+ tween<T>(opts: StaggerTargetTweenOptions<T, TItem> & Naming): AnimationHandle;
591
+ tween<T>(opts: StaggerTweenOptions<T, TItem>): AnimationHandle;
592
+ /** Per-item `animator.spring` with per-item-varying options. */
593
+ spring(opts: StaggerItemSpringOptions<TItem>): AnimationHandle;
594
+ spring<T>(opts: StaggerTargetSpringOptions<T, TItem> & Naming): AnimationHandle;
595
+ spring<T>(opts: StaggerSpringOptions<T, TItem>): AnimationHandle;
596
+ }
597
+
598
+ /** Blends two `T` values at eased progress `t`. Called once per frame; see
599
+ * {@link InterpolatorFactory} when the blend has setup worth hoisting. */
600
+ type Interpolate<T> = (from: T, to: T, t: number) => T;
601
+ /** Built ONCE at tween start with (from, to); the returned function is called with `t ∈ [0, 1]`
602
+ * each frame. Use for interpolators with expensive setup (color-space conversion, path-string
603
+ * parsing) — d3-interpolate's shape exactly. */
604
+ type InterpolatorFactory<T> = (from: T, to: T) => (t: number) => T;
605
+ /** A running animation. Cancel it, or bend its time — pausing and time-scaling
606
+ * act on this animation's own virtual clock, independent of the animator's. */
607
+ interface AnimationHandle {
608
+ /** Monotonic id assigned by the animator. */
609
+ id: number;
610
+ /** Cancel this animation. Idempotent — no-op once already finished/canceled. */
611
+ cancel(): void;
612
+ /** Freeze this animation's virtual clock. Idempotent. */
613
+ pause(): void;
614
+ /** Resume this animation's virtual clock. Idempotent. */
615
+ resume(): void;
616
+ /** Multiply this animation's virtual-clock rate by `scale`. 1 = normal, 0 holds it still, and
617
+ * below 0 plays it backward: run back to its start, it ends there holding its start value,
618
+ * as it ends holding its destination going forward, and `onDone` runs. */
619
+ setTimeScale(scale: number): void;
620
+ /** This animation's own time scale. 1 once it has finished, since the
621
+ * animator no longer holds an entry to read. */
622
+ timeScale(): number;
623
+ /** True iff this handle is currently paused. */
624
+ isPaused(): boolean;
625
+ }
626
+ /** A duration-based animation from `from` to `to` over `ms`, shaped by an
627
+ * easing curve. Reach for a spring instead when the motion should respond to
628
+ * where the value already is rather than restart from a fixed duration. */
629
+ interface TweenOptions<T> {
630
+ /** Absent: this form hands values to `onTick`. The `Target` form of these options moves a target. */
631
+ target?: undefined;
632
+ from: T;
633
+ to: T;
634
+ ms: number;
635
+ easing?: EasingSpec;
636
+ /** Required when T is not `number`. For T = number, defaults to linear numeric lerp. */
637
+ interpolate?: Interpolate<T>;
638
+ /** Factory interpolator built once at tween start. Takes precedence over `interpolate`
639
+ * when both are provided. */
640
+ interpolator?: InterpolatorFactory<T>;
641
+ onTick: (value: T) => void;
642
+ onDone?: () => void;
643
+ /** Any new animation passed the same cancelKey cancels the prior one in flight. */
644
+ cancelKey?: string;
645
+ /** Names this animation in {@link AnimatorEvent}s and `animator.live()`. */
646
+ label?: string;
647
+ }
648
+ /** A spring animation: runs until the value settles on `to` rather than for a
649
+ * set duration, so it absorbs an initial velocity naturally. Non-numeric `T`
650
+ * needs the four vector helpers. */
651
+ interface SpringOptions<T> {
652
+ /** Absent: this form hands values to `onTick`. The `Target` form of these options moves a target. */
653
+ target?: undefined;
654
+ from: T;
655
+ to: T;
656
+ /** Initial velocity in T-units per second. Default: zero (T-shape-aware). */
657
+ velocity?: T;
658
+ preset?: SpringPresetName;
659
+ stiffness?: number;
660
+ damping?: number;
661
+ mass?: number;
662
+ interpolate?: Interpolate<T>;
663
+ /** Vector helpers — required for non-numeric T. When `from`, `to` and `velocity` are numbers, number
664
+ * arrays or plain objects of numeric fields of one shape, and stiffness, damping and mass are
665
+ * positive, the motion is solved in closed form and these only decide when it has come to rest —
666
+ * a `subtract` that wraps an angle won't change the path. */
667
+ add?: (a: T, b: T) => T;
668
+ subtract?: (a: T, b: T) => T;
669
+ scale?: (v: T, k: number) => T;
670
+ magnitude?: (v: T) => number;
671
+ /** Velocity magnitude below which the spring is considered settled. Default 0.01. */
672
+ restThreshold?: number;
673
+ onTick: (value: T) => void;
674
+ onDone?: () => void;
675
+ cancelKey?: string;
676
+ /** Names this animation in {@link AnimatorEvent}s and `animator.live()`. */
677
+ label?: string;
678
+ }
679
+ /** Spring and decay as one animation. With a `to`, a spring pulls toward it;
680
+ * with `to: null`, the value coasts on its velocity. Either can become the
681
+ * other mid-flight through the handle. */
682
+ interface PhysicsOptions<T> {
683
+ /** Absent: this form hands values to `onTick`. The `Target` form of these options moves a target. */
684
+ target?: undefined;
685
+ from: T;
686
+ /** Target. `null` ⇒ no spring force (decay-mode). */
687
+ to?: T | null;
688
+ /** Initial velocity in T-units per second. */
689
+ velocity?: T;
690
+ preset?: SpringPresetName;
691
+ stiffness?: number;
692
+ damping?: number;
693
+ mass?: number;
694
+ restThreshold?: number;
695
+ /** Vector helpers — required for non-numeric T. When `from`, `to` and `velocity` are numbers, number
696
+ * arrays or plain objects of numeric fields of one shape, and stiffness, damping and mass are
697
+ * positive, the motion is solved in closed form and these only decide when it has come to rest —
698
+ * a `subtract` that wraps an angle won't change the path. */
699
+ add?: (a: T, b: T) => T;
700
+ subtract?: (a: T, b: T) => T;
701
+ scale?: (v: T, k: number) => T;
702
+ magnitude?: (v: T) => number;
703
+ onTick: (value: T) => void;
704
+ onDone?: () => void;
705
+ cancelKey?: string;
706
+ /** Names this animation in {@link AnimatorEvent}s and `animator.live()`. */
707
+ label?: string;
708
+ }
709
+ /** An `AnimationHandle` that can also be steered while it runs — the point of
710
+ * the physics primitive. */
711
+ interface PhysicsHandle<T = unknown> extends AnimationHandle {
712
+ /** Retarget mid-flight. `null` ⇒ switch to decay-mode (no spring force). */
713
+ setTarget(to: T | null): void;
714
+ /** Replace the current velocity in T-units per second. */
715
+ setVelocity(v: T): void;
716
+ }
717
+ /** Momentum: coast from `from` at `velocity`, slowing by `friction` each
718
+ * second until below `threshold`. What a flick-to-pan leaves behind. */
719
+ interface DecayOptions<T> {
720
+ /** Absent: this form hands values to `onTick`. The `Target` form of these options moves a target. */
721
+ target?: undefined;
722
+ from: T;
723
+ velocity: T;
724
+ /** Per-second velocity multiplier in (0, 1). Default 0.95. */
725
+ friction?: number;
726
+ /** Velocity magnitude below which decay stops. Default 0.5. */
727
+ threshold?: number;
728
+ /** When `from` and `velocity` are numbers, number arrays or plain objects of numeric fields of one
729
+ * shape and `friction` is below 1, the motion is solved in closed form: `add` and `scale` go
730
+ * unused and `magnitude` only decides when it has come to rest. */
731
+ add: (a: T, b: T) => T;
732
+ scale: (v: T, k: number) => T;
733
+ magnitude: (v: T) => number;
734
+ onTick: (value: T) => void;
735
+ onDone?: () => void;
736
+ cancelKey?: string;
737
+ /** Names this animation in {@link AnimatorEvent}s and `animator.live()`. */
738
+ label?: string;
739
+ }
740
+ /** Options for `useAnimator`. Everything here is an injection seam for tests;
741
+ * the defaults are the real clock and rAF. */
742
+ interface UseAnimatorOptions {
743
+ /** Optional clock injection for tests. Returns ms since some epoch. */
744
+ now?: () => number;
745
+ /** Optional rAF / cAF injection for tests. Defaults to window.requestAnimationFrame. */
746
+ requestFrame?: (cb: (t: number) => void) => number;
747
+ cancelFrame?: (handle: number) => void;
748
+ }
749
+ /**
750
+ * Owns every running animation on a canvas and drives them from one rAF loop.
751
+ * Beyond the primitives (`tween`, `spring`, `decay`, `physics`) it offers
752
+ * composition — `loop`, `stagger` — and bulk control by handle, by cancel-key,
753
+ * or over everything at once.
754
+ *
755
+ * An animator does not know about the scene. An animation either reports values
756
+ * through `onTick` and the caller decides what to do with them, or moves a
757
+ * {@link Target}, where several on one target add.
758
+ */
759
+ interface Animator {
760
+ tween<T>(opts: TweenOptions<T> | TargetTweenOptions<T>): AnimationHandle;
761
+ spring<T>(opts: SpringOptions<T> | TargetSpringOptions<T>): AnimationHandle;
762
+ decay<T>(opts: DecayOptions<T> | TargetDecayOptions<T>): AnimationHandle;
763
+ /** With `to` set, behaves as a spring; with `to: null`, as a velocity-driven decay.
764
+ * Retarget mid-flight via the returned handle's `setTarget`. */
765
+ physics<T>(opts: PhysicsOptions<T> | TargetPhysicsOptions<T>): PhysicsHandle<T>;
766
+ /** Shows a value on a {@link Target} in place of its committed one until canceled or released.
767
+ * It covers an animation's move to a destination; a coast, push, or `from` offset adds on top. */
768
+ hold<T>(opts: HoldOptions<T>): HoldHandle;
769
+ /** Holds rows of a target table at values and weights the caller writes into flat arrays: a
770
+ * hold on each row, as `hold` would put there, with no function asked for any of them. */
771
+ holdRows(opts: HoldRowsOptions): RowsHoldHandle;
772
+ /** Cancel a specific animation by handle. Pose stays at current value (no jump). */
773
+ cancel(handle: AnimationHandle): void;
774
+ /** Cancel every animation currently active under `key`. */
775
+ cancelKey(key: string): void;
776
+ /** Cancel everything. Useful from a destructor or "reset scene" path. */
777
+ cancelAll(): void;
778
+ /** True iff at least one animation is active. With `key`, scoped to that cancelKey. */
779
+ isActive(key?: string): boolean;
780
+ /**
781
+ * True while the animator is executing an animation tick. Lets an adapter wrapper detect a
782
+ * `setPose` called from inside another animation's onTick and avoid scheduling a new
783
+ * animation that would fight the caller.
784
+ */
785
+ isTicking(): boolean;
786
+ /** Freeze every animation managed by this animator. */
787
+ pause(): void;
788
+ /** Resume every animation managed by this animator. */
789
+ resume(): void;
790
+ /** True iff the animator is currently globally paused. */
791
+ isPaused(): boolean;
792
+ /** Multiply every animation's virtual-clock rate by `scale`. Below 0 plays every one backward,
793
+ * as each handle's `setTimeScale` does, while the animator's own clock goes on forward: one
794
+ * started meanwhile is at its start already, and ends at once. */
795
+ setTimeScale(scale: number): void;
796
+ /** The global time scale. Per-animation scales multiply on top of it. */
797
+ timeScale(): number;
798
+ /** Freeze every animation whose `cancelKey` matches. */
799
+ pauseKey(key: string): void;
800
+ /** Resume every animation whose `cancelKey` matches. */
801
+ resumeKey(key: string): void;
802
+ /** Set per-animation timeScale for every animation whose `cancelKey` matches. */
803
+ setTimeScaleByKey(key: string, scale: number): void;
804
+ /**
805
+ * Repeatedly invokes `factory` to produce a child animation. The factory must wire its
806
+ * returned handle's `onDone` to call `next` so the loop advances. The returned handle's
807
+ * pause/resume/setTimeScale/cancel delegate to the in-flight child, and
808
+ * `animator.cancel(handle)`, `animator.cancelKey(opts.cancelKey)`, and
809
+ * `animator.isActive(opts.cancelKey)` all work for it.
810
+ */
811
+ loop(factory: LoopFactory, opts?: LoopOptions): AnimationHandle;
812
+ /** Sugar over `loop`: a tween between two values, repeated per `direction`. Registered
813
+ * with the animator like `loop`. */
814
+ tweenLoop<T>(opts: TweenLoopOptions<T>): AnimationHandle;
815
+ /**
816
+ * Schedules a per-item animation, offset by `delay` ms per index (or a custom function of
817
+ * the index). Pass `factory` and get a composite `AnimationHandle`; omit it and get a
818
+ * `StaggerBuilder` for fluent `.each` / `.tween` / `.spring` calls, the last two of which
819
+ * move the items themselves where they are targets.
820
+ *
821
+ * The composite handle's `cancel` cancels the items still waiting AND the in-flight
822
+ * children. The delays run on the animator's clock, not the wall's: a pause or a time
823
+ * scale holds or stretches the waiting items along with the children, and a hidden tab
824
+ * holds both. `animator.cancel(handle)`, `animator.cancelKey(opts.cancelKey)`, and
825
+ * `animator.isActive(opts.cancelKey)` all work for it.
826
+ */
827
+ stagger<TItem>(items: readonly TItem[], delay: StaggerDelay): StaggerBuilder<TItem>;
828
+ stagger<TItem>(items: readonly TItem[], delay: StaggerDelay, factory: StaggerFactory<TItem>, opts?: StaggerOptions): AnimationHandle;
829
+ /**
830
+ * Keyframe timeline. Registered like any other animation, so its playhead
831
+ * responds to `pause`, `setTimeScale` and `cancelKey`. Sampled tracks are a
832
+ * pure function of the playhead; event tracks fire only on forward playback.
833
+ */
834
+ timeline(opts: TimelineOptions): TimelineHandle;
835
+ /** Per-node, per-channel color override registry, painted onto scene nodes by
836
+ * `<SceneCanvas animator>` and read by `createPathLayer`. Only this animator can move its
837
+ * per-node targets. Cleared automatically on animator unmount. */
838
+ colorOverrides: ColorOverrideRegistry;
839
+ /**
840
+ * Subscribe to a callback fired once per RAF frame while any animation is active; returns
841
+ * an unsubscribe. For consumers that repaint from a non-scene channel such as
842
+ * `colorOverrides`, whose writes do not trigger a repaint the way scene mutations do.
843
+ * Fires AFTER the frame's animations have ticked.
844
+ */
845
+ onTick(cb: () => void): () => void;
846
+ /**
847
+ * Keeps the animator's RAF loop running until the returned cancel function is called. For
848
+ * effects read on every frame that have no progress state of their own; without it the
849
+ * loop would idle and `onTick` would stop firing.
850
+ */
851
+ keepAlive(): () => void;
852
+ /**
853
+ * Subscribe to the lifecycle of every animation this animator runs, the
854
+ * composites and timelines included. Returns an unsubscribe. Events arrive
855
+ * synchronously, as each thing happens — see {@link AnimatorEvent} for the
856
+ * order. With no listener attached nothing is built or delivered, so an
857
+ * unwatched animator pays nothing for this.
858
+ */
859
+ watch(listener: AnimatorListener): () => void;
860
+ /** What is running right now, in registration order: a fresh snapshot per
861
+ * call, for a debug overlay to draw. */
862
+ live(): LiveAnimation[];
863
+ }
864
+ /** Which animator call started an animation. A loop, tween loop or stagger is
865
+ * an entry of its own beside the children it runs; `keepAlive` holds the
866
+ * frame loop open and animates nothing. */
867
+ type AnimationKind = 'tween' | 'spring' | 'decay' | 'physics' | 'timeline' | 'loop' | 'tweenLoop' | 'stagger' | 'keepAlive' | 'hold';
868
+ /** Who an {@link AnimatorEvent} is about. One object per registration, so the
869
+ * same animation's events share it by identity. */
870
+ interface AnimationInfo {
871
+ /** The id on the animation's handle. */
872
+ readonly id: number;
873
+ readonly kind: AnimationKind;
874
+ /** The animation's `cancelKey`. Pose helpers key by node, as `pose:<id>`. */
875
+ readonly key?: string;
876
+ /** The animation's `label` option. */
877
+ readonly label?: string;
878
+ }
879
+ /** One row of `animator.live()`. */
880
+ interface LiveAnimation extends AnimationInfo {
881
+ /** Paused on its own handle. The animator-wide pause is `animator.isPaused()`. */
882
+ readonly paused: boolean;
883
+ /** Its own time scale; the animator's multiplies on top. */
884
+ readonly timeScale: number;
885
+ /** Virtual ms its clock has advanced since it started. */
886
+ readonly elapsed: number;
887
+ /** 0 to 1, for a tween or a timeline (the playhead over its duration).
888
+ * Absent where there is no end to measure against: physics, composites. */
889
+ readonly progress?: number;
890
+ }
891
+ /**
892
+ * One thing happening to an animation, as `animator.watch` delivers it.
893
+ *
894
+ * - `start` — registered. A finished timeline that `seek` or `edit` revives
895
+ * starts again, under the same id.
896
+ * - `end` — finished on its own. Delivered once every animation has ticked
897
+ * that frame, in registration order.
898
+ * - `cancel` — stopped by its handle, `cancel`, `cancelKey` or `cancelAll`.
899
+ * - `interrupt` — stopped because `by` claimed its `cancelKey`. Delivered
900
+ * before `by`'s `start`.
901
+ * - `error` — its tick threw (an `onTick`, `onDone` or interpolator), so it was
902
+ * taken off the table, after the frame's other animations ticked. In place of
903
+ * `cancel`, or after `end` when `onDone` threw. The error is also logged.
904
+ * - `lap` — a looping timeline wrapped; `lap` counts wraps since it started.
905
+ * - `fire` — an event on a timeline's event track was crossed, at any depth.
906
+ * `path` indexes from the root timeline's `tracks()` down through each
907
+ * nested timeline to the event track. Delivered after the event's own `fire`.
908
+ */
909
+ type AnimatorEvent = {
910
+ readonly type: 'start' | 'end' | 'cancel';
911
+ readonly animation: AnimationInfo;
912
+ } | {
913
+ readonly type: 'interrupt';
914
+ readonly animation: AnimationInfo;
915
+ readonly by: AnimationInfo;
916
+ } | {
917
+ readonly type: 'error';
918
+ readonly animation: AnimationInfo;
919
+ readonly error: unknown;
920
+ } | {
921
+ readonly type: 'lap';
922
+ readonly animation: AnimationInfo;
923
+ readonly lap: number;
924
+ } | {
925
+ readonly type: 'fire';
926
+ readonly animation: AnimationInfo;
927
+ readonly track: EventTrack;
928
+ readonly path: readonly number[];
929
+ readonly event: TimelineEvent;
930
+ /** As the event's own `fire` is told: ms behind the frame it was crossed. */
931
+ readonly lateBy: number;
932
+ };
933
+ /** Receives what `animator.watch` delivers. */
934
+ type AnimatorListener = (event: AnimatorEvent) => void;
935
+ /** Options for `Animator.loop`. */
936
+ interface LoopOptions {
937
+ /** Maximum number of iterations. Default Infinity. */
938
+ count?: number;
939
+ /** Invoked when the loop reaches `count` iterations naturally (not on cancel). */
940
+ onDone?: () => void;
941
+ /** Any new animation passed the same cancelKey cancels the prior one in flight.
942
+ * Also enables `animator.cancelKey` / `animator.isActive(key)` for this loop. */
943
+ cancelKey?: string;
944
+ /** Names this loop in {@link AnimatorEvent}s and `animator.live()`. */
945
+ label?: string;
946
+ }
947
+ /** Produces one iteration of a loop. Must arrange for `next` to be called when
948
+ * the animation it returns finishes, or the loop stalls after one pass. */
949
+ type LoopFactory = (iteration: number, next: () => void) => AnimationHandle;
950
+ /** Options for `Animator.tweenLoop` — a tween's options plus how each
951
+ * iteration relates to the last. */
952
+ interface TweenLoopOptions<T> {
953
+ from: T;
954
+ to: T;
955
+ ms: number;
956
+ easing?: EasingSpec;
957
+ /** `restart` (default): from→to every iteration.
958
+ * `reverse`: to→from every iteration.
959
+ * `alternate`: even iterations from→to, odd iterations to→from. */
960
+ direction?: 'restart' | 'reverse' | 'alternate';
961
+ count?: number;
962
+ interpolate?: Interpolate<T>;
963
+ onTick: (value: T) => void;
964
+ onDone?: () => void;
965
+ cancelKey?: string;
966
+ /** Names this animation in {@link AnimatorEvent}s and `animator.live()`. */
967
+ label?: string;
968
+ }
969
+
970
+ export { type TargetTableOptions as $, type Animator as A, type StaggerItemSpringOptions as B, type ColorOverride as C, type DecayOptions as D, type EventBooking as E, type StaggerItemTweenOptions as F, type StaggerOptions as G, type HoldHandle as H, type Interpolate as I, type StaggerPerItem as J, type Keyframe as K, type LiveAnimation as L, type StaggerSpringOptions as M, type NestedTimeline as N, type StaggerTargetSpringOptions as O, type PhysicsHandle as P, type StaggerTargetTweenOptions as Q, type RowsHoldHandle as R, type SampledTrack as S, type Target as T, type StaggerTweenOptions as U, type VertexColorChannel as V, type TargetDecayOptions as W, type TargetOptions as X, type TargetPhysicsOptions as Y, type TargetSpringOptions as Z, type TargetTable as _, type AnimationHandle as a, type TargetTweenOptions as a0, type TimelineClock as a1, type TimelineHandle as a2, type TimelineOptions as a3, type TimelineTrack as a4, type Track as a5, type TweenLoopOptions as a6, type TweenOptions as a7, type UseAnimatorOptions as a8, createTarget as a9, createTargetTable as aa, type TimelineEvent as b, type TargetAxes as c, type AnimationInfo as d, type AnimationKind as e, type AnimatorEvent as f, type AnimatorListener as g, type AxisBuffer as h, type AxisName as i, type AxisRef as j, type ColorOverrideFn as k, ColorOverrideRegistry as l, type EventBookingHandle as m, type EventTrack as n, type HoldOptions as o, type HoldRowsOptions as p, type InterpolatorFactory as q, type LoopFactory as r, type LoopOptions as s, type Naming as t, type PhysicsOptions as u, type ShownArray as v, type SpringOptions as w, type StaggerBuilder as x, type StaggerDelay as y, type StaggerFactory as z };