@ue-too/animate 0.14.1 → 0.15.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.
package/README.md CHANGED
@@ -24,11 +24,13 @@ Keyframe-based animation library for TypeScript canvas applications.
24
24
  ## Installation
25
25
 
26
26
  Using Bun:
27
+
27
28
  ```bash
28
29
  bun add @ue-too/animate
29
30
  ```
30
31
 
31
32
  Using npm:
33
+
32
34
  ```bash
33
35
  npm install @ue-too/animate
34
36
  ```
@@ -44,13 +46,15 @@ let opacity = 0;
44
46
 
45
47
  // Create fade-in animation
46
48
  const fadeIn = new Animation(
47
- [
48
- { percentage: 0, value: 0 }, // Start at 0% with value 0
49
- { percentage: 1, value: 1 } // End at 100% with value 1
50
- ],
51
- (value) => { opacity = value; }, // Apply function updates the value
52
- numberHelperFunctions, // Number interpolation helper
53
- 1000 // Duration in milliseconds
49
+ [
50
+ { percentage: 0, value: 0 }, // Start at 0% with value 0
51
+ { percentage: 1, value: 1 }, // End at 100% with value 1
52
+ ],
53
+ value => {
54
+ opacity = value;
55
+ }, // Apply function updates the value
56
+ numberHelperFunctions, // Number interpolation helper
57
+ 1000 // Duration in milliseconds
54
58
  );
55
59
 
56
60
  // Start the animation
@@ -58,9 +62,9 @@ fadeIn.start();
58
62
 
59
63
  // In your animation loop (e.g., requestAnimationFrame)
60
64
  function gameLoop(deltaTime: number) {
61
- fadeIn.animate(deltaTime); // Update animation with elapsed time
62
- console.log('Opacity:', opacity);
63
- requestAnimationFrame(() => gameLoop(16)); // ~60 FPS
65
+ fadeIn.animate(deltaTime); // Update animation with elapsed time
66
+ console.log('Opacity:', opacity);
67
+ requestAnimationFrame(() => gameLoop(16)); // ~60 FPS
64
68
  }
65
69
  ```
66
70
 
@@ -72,18 +76,19 @@ Keyframes define values at specific points in an animation's progress:
72
76
 
73
77
  ```typescript
74
78
  type Keyframe<T> = {
75
- percentage: number; // 0.0 (start) to 1.0 (end)
76
- value: T; // Value at this point
77
- easingFn?: (t: number) => number; // Optional easing for this segment
79
+ percentage: number; // 0.0 (start) to 1.0 (end)
80
+ value: T; // Value at this point
81
+ easingFn?: (t: number) => number; // Optional easing for this segment
78
82
  };
79
83
  ```
80
84
 
81
85
  **Example with easing:**
86
+
82
87
  ```typescript
83
88
  const keyframes = [
84
- { percentage: 0, value: 0 },
85
- { percentage: 0.5, value: 100, easingFn: (t) => t * t }, // Ease-in quadratic
86
- { percentage: 1, value: 200 }
89
+ { percentage: 0, value: 0 },
90
+ { percentage: 0.5, value: 100, easingFn: t => t * t }, // Ease-in quadratic
91
+ { percentage: 1, value: 200 },
87
92
  ];
88
93
  ```
89
94
 
@@ -93,7 +98,7 @@ Helpers provide type-specific interpolation logic:
93
98
 
94
99
  ```typescript
95
100
  interface AnimatableAttributeHelper<T> {
96
- lerp(ratio: number, start: Keyframe<T>, end: Keyframe<T>): T;
101
+ lerp(ratio: number, start: Keyframe<T>, end: Keyframe<T>): T;
97
102
  }
98
103
  ```
99
104
 
@@ -113,6 +118,7 @@ const animation = new Animation<T>(
113
118
  ```
114
119
 
115
120
  **Methods:**
121
+
116
122
  - `start()`: Start the animation
117
123
  - `stop()`: Stop and reset the animation
118
124
  - `pause()`: Pause at current position
@@ -124,6 +130,7 @@ const animation = new Animation<T>(
124
130
  - `tearDown()`: Clean up animation state
125
131
 
126
132
  **Properties:**
133
+
127
134
  - `loops: boolean`: Whether animation loops
128
135
  - `maxLoopCount?: number`: Maximum number of loops (undefined = infinite)
129
136
  - `duration: number`: Animation duration in milliseconds
@@ -146,6 +153,7 @@ const composite = new CompositeAnimation(
146
153
  ```
147
154
 
148
155
  **Methods:**
156
+
149
157
  - `addAnimation(name: string, animator: Animator, startTime: number)`: Add animation at specific time
150
158
  - `addAnimationAfter(name: string, animator: Animator, after: string)`: Add after another animation
151
159
  - `addAnimationBefore(name: string, animator: Animator, before: string)`: Add before another animation
@@ -164,13 +172,15 @@ import { Animation, numberHelperFunctions } from '@ue-too/animate';
164
172
 
165
173
  let scale = 1;
166
174
  const scaleAnimation = new Animation(
167
- [
168
- { percentage: 0, value: 1 },
169
- { percentage: 1, value: 2 }
170
- ],
171
- (value) => { scale = value; },
172
- numberHelperFunctions,
173
- 500
175
+ [
176
+ { percentage: 0, value: 1 },
177
+ { percentage: 1, value: 2 },
178
+ ],
179
+ value => {
180
+ scale = value;
181
+ },
182
+ numberHelperFunctions,
183
+ 500
174
184
  );
175
185
  ```
176
186
 
@@ -185,13 +195,15 @@ import { Point } from '@ue-too/math';
185
195
  let position: Point = { x: 0, y: 0 };
186
196
 
187
197
  const moveAnimation = new Animation(
188
- [
189
- { percentage: 0, value: { x: 0, y: 0 } },
190
- { percentage: 1, value: { x: 100, y: 100 } }
191
- ],
192
- (value) => { position = value; },
193
- pointHelperFunctions,
194
- 1000
198
+ [
199
+ { percentage: 0, value: { x: 0, y: 0 } },
200
+ { percentage: 1, value: { x: 100, y: 100 } },
201
+ ],
202
+ value => {
203
+ position = value;
204
+ },
205
+ pointHelperFunctions,
206
+ 1000
195
207
  );
196
208
  ```
197
209
 
@@ -200,19 +212,21 @@ const moveAnimation = new Animation(
200
212
  Interpolate RGB colors:
201
213
 
202
214
  ```typescript
203
- import { Animation, rgbHelperFunctions, RGB } from '@ue-too/animate';
215
+ import { Animation, RGB, rgbHelperFunctions } from '@ue-too/animate';
204
216
 
205
217
  let color: RGB = { r: 255, g: 0, b: 0 };
206
218
 
207
219
  const colorAnimation = new Animation(
208
- [
209
- { percentage: 0, value: { r: 255, g: 0, b: 0 } }, // Red
210
- { percentage: 0.5, value: { r: 255, g: 255, b: 0 } }, // Yellow
211
- { percentage: 1, value: { r: 0, g: 255, b: 0 } } // Green
212
- ],
213
- (value) => { color = value; },
214
- rgbHelperFunctions,
215
- 2000
220
+ [
221
+ { percentage: 0, value: { r: 255, g: 0, b: 0 } }, // Red
222
+ { percentage: 0.5, value: { r: 255, g: 255, b: 0 } }, // Yellow
223
+ { percentage: 1, value: { r: 0, g: 255, b: 0 } }, // Green
224
+ ],
225
+ value => {
226
+ color = value;
227
+ },
228
+ rgbHelperFunctions,
229
+ 2000
216
230
  );
217
231
  ```
218
232
 
@@ -226,13 +240,15 @@ import { Animation, stringHelperFunctions } from '@ue-too/animate';
226
240
  let state = 'idle';
227
241
 
228
242
  const stateAnimation = new Animation(
229
- [
230
- { percentage: 0, value: 'idle' },
231
- { percentage: 1, value: 'active' }
232
- ],
233
- (value) => { state = value; },
234
- stringHelperFunctions,
235
- 500
243
+ [
244
+ { percentage: 0, value: 'idle' },
245
+ { percentage: 1, value: 'active' },
246
+ ],
247
+ value => {
248
+ state = value;
249
+ },
250
+ stringHelperFunctions,
251
+ 500
236
252
  );
237
253
  ```
238
254
 
@@ -246,15 +262,17 @@ import { Animation, integerHelperFunctions } from '@ue-too/animate';
246
262
  let frameIndex = 0;
247
263
 
248
264
  const frameAnimation = new Animation(
249
- [
250
- { percentage: 0, value: 0 },
251
- { percentage: 0.33, value: 1 },
252
- { percentage: 0.66, value: 2 },
253
- { percentage: 1, value: 3 }
254
- ],
255
- (value) => { frameIndex = value; },
256
- integerHelperFunctions,
257
- 400
265
+ [
266
+ { percentage: 0, value: 0 },
267
+ { percentage: 0.33, value: 1 },
268
+ { percentage: 0.66, value: 2 },
269
+ { percentage: 1, value: 3 },
270
+ ],
271
+ value => {
272
+ frameIndex = value;
273
+ },
274
+ integerHelperFunctions,
275
+ 400
258
276
  );
259
277
  ```
260
278
 
@@ -268,23 +286,27 @@ import { Animation, numberHelperFunctions } from '@ue-too/animate';
268
286
  let opacity = 0;
269
287
 
270
288
  const fadeIn = new Animation(
271
- [
272
- { percentage: 0, value: 0 },
273
- { percentage: 1, value: 1, easingFn: (t) => t * t } // Ease-in
274
- ],
275
- (value) => { opacity = value; },
276
- numberHelperFunctions,
277
- 500
289
+ [
290
+ { percentage: 0, value: 0 },
291
+ { percentage: 1, value: 1, easingFn: t => t * t }, // Ease-in
292
+ ],
293
+ value => {
294
+ opacity = value;
295
+ },
296
+ numberHelperFunctions,
297
+ 500
278
298
  );
279
299
 
280
300
  const fadeOut = new Animation(
281
- [
282
- { percentage: 0, value: 1 },
283
- { percentage: 1, value: 0, easingFn: (t) => 1 - (1 - t) * (1 - t) } // Ease-out
284
- ],
285
- (value) => { opacity = value; },
286
- numberHelperFunctions,
287
- 500
301
+ [
302
+ { percentage: 0, value: 1 },
303
+ { percentage: 1, value: 0, easingFn: t => 1 - (1 - t) * (1 - t) }, // Ease-out
304
+ ],
305
+ value => {
306
+ opacity = value;
307
+ },
308
+ numberHelperFunctions,
309
+ 500
288
310
  );
289
311
  ```
290
312
 
@@ -297,14 +319,20 @@ import { Point } from '@ue-too/math';
297
319
  let spritePosition: Point = { x: 0, y: 0 };
298
320
 
299
321
  const bounce = new Animation(
300
- [
301
- { percentage: 0, value: { x: 0, y: 0 } },
302
- { percentage: 0.5, value: { x: 0, y: -50 }, easingFn: (t) => 1 - Math.pow(1 - t, 3) }, // Ease-out up
303
- { percentage: 1, value: { x: 0, y: 0 }, easingFn: (t) => t * t * t } // Ease-in down
304
- ],
305
- (value) => { spritePosition = value; },
306
- pointHelperFunctions,
307
- 1000
322
+ [
323
+ { percentage: 0, value: { x: 0, y: 0 } },
324
+ {
325
+ percentage: 0.5,
326
+ value: { x: 0, y: -50 },
327
+ easingFn: t => 1 - Math.pow(1 - t, 3),
328
+ }, // Ease-out up
329
+ { percentage: 1, value: { x: 0, y: 0 }, easingFn: t => t * t * t }, // Ease-in down
330
+ ],
331
+ value => {
332
+ spritePosition = value;
333
+ },
334
+ pointHelperFunctions,
335
+ 1000
308
336
  );
309
337
 
310
338
  bounce.loops = true; // Loop forever
@@ -313,30 +341,52 @@ bounce.loops = true; // Loop forever
313
341
  ### Sequential Animation Sequence
314
342
 
315
343
  ```typescript
316
- import { Animation, CompositeAnimation, numberHelperFunctions, pointHelperFunctions } from '@ue-too/animate';
344
+ import {
345
+ Animation,
346
+ CompositeAnimation,
347
+ numberHelperFunctions,
348
+ pointHelperFunctions,
349
+ } from '@ue-too/animate';
317
350
 
318
- let x = 0, y = 0, opacity = 0;
351
+ let x = 0,
352
+ y = 0,
353
+ opacity = 0;
319
354
 
320
355
  // Create individual animations
321
356
  const fadeIn = new Animation(
322
- [{ percentage: 0, value: 0 }, { percentage: 1, value: 1 }],
323
- (value) => { opacity = value; },
324
- numberHelperFunctions,
325
- 500
357
+ [
358
+ { percentage: 0, value: 0 },
359
+ { percentage: 1, value: 1 },
360
+ ],
361
+ value => {
362
+ opacity = value;
363
+ },
364
+ numberHelperFunctions,
365
+ 500
326
366
  );
327
367
 
328
368
  const slideRight = new Animation(
329
- [{ percentage: 0, value: 0 }, { percentage: 1, value: 100 }],
330
- (value) => { x = value; },
331
- numberHelperFunctions,
332
- 500
369
+ [
370
+ { percentage: 0, value: 0 },
371
+ { percentage: 1, value: 100 },
372
+ ],
373
+ value => {
374
+ x = value;
375
+ },
376
+ numberHelperFunctions,
377
+ 500
333
378
  );
334
379
 
335
380
  const slideDown = new Animation(
336
- [{ percentage: 0, value: 0 }, { percentage: 1, value: 50 }],
337
- (value) => { y = value; },
338
- numberHelperFunctions,
339
- 300
381
+ [
382
+ { percentage: 0, value: 0 },
383
+ { percentage: 1, value: 50 },
384
+ ],
385
+ value => {
386
+ y = value;
387
+ },
388
+ numberHelperFunctions,
389
+ 300
340
390
  );
341
391
 
342
392
  // Create sequence: fade in, then slide right, then slide down
@@ -349,9 +399,9 @@ sequence.start();
349
399
 
350
400
  // Update in game loop
351
401
  function update(deltaTime: number) {
352
- sequence.animate(deltaTime);
353
- // Render sprite at (x, y) with opacity
354
- requestAnimationFrame(() => update(16));
402
+ sequence.animate(deltaTime);
403
+ // Render sprite at (x, y) with opacity
404
+ requestAnimationFrame(() => update(16));
355
405
  }
356
406
  ```
357
407
 
@@ -376,12 +426,12 @@ sequence.addAnimationAfter('scale', scaleAnimation, 'fadeIn');
376
426
  const animation = new Animation(/* ... */);
377
427
 
378
428
  animation.onStart(() => {
379
- console.log('Animation started!');
429
+ console.log('Animation started!');
380
430
  });
381
431
 
382
432
  animation.onEnd(() => {
383
- console.log('Animation completed!');
384
- // Trigger next action
433
+ console.log('Animation completed!');
434
+ // Trigger next action
385
435
  });
386
436
 
387
437
  animation.start();
@@ -410,20 +460,23 @@ const easeOut = (t: number) => 1 - (1 - t) * (1 - t);
410
460
 
411
461
  // Ease-in-out quadratic
412
462
  const easeInOut = (t: number) =>
413
- t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
463
+ t < 0.5 ? 2 * t * t : 1 - Math.pow(-2 * t + 2, 2) / 2;
414
464
 
415
465
  // Elastic ease-out
416
466
  const elasticOut = (t: number) => {
417
- const c4 = (2 * Math.PI) / 3;
418
- return t === 0 ? 0 : t === 1 ? 1
419
- : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
467
+ const c4 = (2 * Math.PI) / 3;
468
+ return t === 0
469
+ ? 0
470
+ : t === 1
471
+ ? 1
472
+ : Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
420
473
  };
421
474
 
422
475
  // Use in keyframe
423
476
  const keyframe = {
424
- percentage: 1,
425
- value: 100,
426
- easingFn: easeInOut
477
+ percentage: 1,
478
+ value: 100,
479
+ easingFn: easeInOut,
427
480
  };
428
481
  ```
429
482
 
@@ -440,18 +493,20 @@ This package is written in TypeScript with complete type definitions:
440
493
  type Position = { x: number; y: number };
441
494
 
442
495
  const posAnimation: Animation<Position> = new Animation(
443
- [{ percentage: 0, value: { x: 0, y: 0 } }],
444
- (value: Position) => { /* ... */ },
445
- pointHelperFunctions,
446
- 1000
496
+ [{ percentage: 0, value: { x: 0, y: 0 } }],
497
+ (value: Position) => {
498
+ /* ... */
499
+ },
500
+ pointHelperFunctions,
501
+ 1000
447
502
  );
448
503
 
449
504
  // Custom helper functions are type-safe
450
505
  const myHelper: AnimatableAttributeHelper<number> = {
451
- lerp: (ratio, start, end) => {
452
- // TypeScript knows start.value and end.value are numbers
453
- return start.value + ratio * (end.value - start.value);
454
- }
506
+ lerp: (ratio, start, end) => {
507
+ // TypeScript knows start.value and end.value are numbers
508
+ return start.value + ratio * (end.value - start.value);
509
+ },
455
510
  };
456
511
  ```
457
512
 
@@ -473,6 +528,7 @@ This animation library follows these principles:
473
528
  - **Memory**: Each animation retains keyframe data and callbacks
474
529
 
475
530
  **Performance Tips:**
531
+
476
532
  - Reuse animation instances when possible
477
533
  - Use composite animations to group related animations
478
534
  - Unsubscribe from callbacks (`onStart`, `onEnd`) when no longer needed
@@ -1,4 +1,4 @@
1
- import { Point } from "@ue-too/math";
1
+ import { Point } from '@ue-too/math';
2
2
  /**
3
3
  * Represents a keyframe in an animation timeline.
4
4
  *
@@ -1,4 +1,4 @@
1
- import { AnimatableAttributeHelper, Keyframe } from "./animatable-attribute";
1
+ import { AnimatableAttributeHelper, Keyframe } from './animatable-attribute';
2
2
  /**
3
3
  * Linear easing function (no easing).
4
4
  *
package/index.d.ts CHANGED
@@ -98,5 +98,5 @@
98
98
  * @see {@link Animation} for single value animations
99
99
  * @see {@link CompositeAnimation} for animation sequencing
100
100
  */
101
- export * from "./animatable-attribute";
102
- export * from "./composite-animation";
101
+ export * from './animatable-attribute';
102
+ export * from './composite-animation';
package/index.js.map CHANGED
@@ -5,10 +5,10 @@
5
5
  "composite-animation.ts"
6
6
  ],
7
7
  "sourcesContent": [
8
- "import { PointCal, Point } from \"@ue-too/math\";\n\n/**\n * Represents a keyframe in an animation timeline.\n *\n * @remarks\n * A keyframe defines a value at a specific point in the animation's progress.\n * Keyframes are defined with a percentage from 0.0 (start) to 1.0 (end), along\n * with the value at that point and an optional easing function for interpolation\n * to the next keyframe.\n *\n * @typeParam T - The type of value being animated (number, Point, RGB, etc.)\n *\n * @example\n * ```typescript\n * const keyframe: Keyframe<number> = {\n * percentage: 0.5,\n * value: 50,\n * easingFn: (t) => t * t // Ease-in quadratic\n * };\n * ```\n *\n * @category Types\n */\nexport type Keyframe<T> = {\n /** Animation progress from 0.0 (start) to 1.0 (end) */\n percentage: number;\n /** Value at this keyframe */\n value: T;\n /** Optional easing function for interpolation to next keyframe */\n easingFn?: (percentage: number) => number;\n}\n\n/**\n * Interface for type-specific interpolation helpers.\n *\n * @remarks\n * Animation helpers provide the `lerp` (linear interpolation) logic for specific types.\n * Different types require different interpolation strategies:\n * - Numbers: Simple linear interpolation\n * - Points: Component-wise interpolation\n * - Colors (RGB): Component-wise color interpolation\n * - Strings: Step-based (threshold) interpolation\n *\n * @typeParam T - The type of value being interpolated\n *\n * @example\n * ```typescript\n * const myHelper: AnimatableAttributeHelper<number> = {\n * lerp: (ratio, start, end) => {\n * const t = (ratio - start.percentage) / (end.percentage - start.percentage);\n * return start.value + t * (end.value - start.value);\n * }\n * };\n * ```\n *\n * @category Helpers\n */\nexport interface AnimatableAttributeHelper<T> {\n /**\n * Interpolates between two keyframes at a given ratio.\n *\n * @param ratio - Current animation progress (0.0 to 1.0)\n * @param start - Starting keyframe\n * @param end - Ending keyframe\n * @returns Interpolated value at the given ratio\n */\n lerp(ratio: number, start: Keyframe<T>, end: Keyframe<T>): T;\n}\n\n/**\n * Built-in interpolation helper for animating Point values.\n *\n * @remarks\n * Provides linear interpolation for 2D points with optional easing.\n * Interpolates both x and y components independently.\n *\n * @category Helpers\n */\nexport const pointHelperFunctions: AnimatableAttributeHelper<Point> = {\n lerp: (ratio: number, start: Keyframe<Point>, end: Keyframe<Point>): Point => {\n const inbetweenRatio = (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if(start.easingFn){\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = PointCal.addVector(start.value, PointCal.multiplyVectorByScalar(PointCal.subVector(end.value, start.value), transformed));\n return res;\n }\n};\n\nexport class PointAnimationHelper implements AnimatableAttributeHelper<Point> {\n\n constructor(){\n\n }\n\n lerp(ratio: number, start: Keyframe<Point>, end: Keyframe<Point>): Point {\n const inbetweenRatio = (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if(start.easingFn){\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = PointCal.addVector(start.value, PointCal.multiplyVectorByScalar(PointCal.subVector(end.value, start.value), transformed));\n return res;\n }\n\n}\n\n/**\n * Built-in interpolation helper for animating number values.\n *\n * @remarks\n * Provides linear interpolation for numeric values with optional easing.\n *\n * @category Helpers\n */\nexport const numberHelperFunctions: AnimatableAttributeHelper<number> = {\n lerp: (ratio: number, start: Keyframe<number>, end: Keyframe<number>): number => {\n const inbetweenRatio = (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if(start.easingFn){\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = start.value + transformed * (end.value - start.value);\n return res;\n }\n}\n\nexport class NumberAnimationHelper implements AnimatableAttributeHelper<number>{\n\n constructor(){\n\n }\n\n lerp(ratio: number, start: Keyframe<number>, end: Keyframe<number>): number {\n const inbetweenRatio = (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if(start.easingFn){\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = start.value + transformed * (end.value - start.value);\n return res;\n }\n}\n\n/**\n * Built-in interpolation helper for animating string values.\n *\n * @remarks\n * Uses step-based interpolation with a 50% threshold. Returns start value until\n * 50% progress, then switches to end value. Useful for discrete property changes.\n *\n * @category Helpers\n */\nexport const stringHelperFunctions: AnimatableAttributeHelper<string> = {\n lerp: (ratio: number, start: Keyframe<string>, end: Keyframe<string>): string => {\n const percentageScale = (ratio - start.percentage) / (end.percentage - start.percentage)\n // if percentageScale is negative that means it's before the start value just return start value \n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5 ? start.value : end.value;\n }\n}\n\nexport class StringAnimationHelper implements AnimatableAttributeHelper<string>{\n constructor(){\n\n }\n \n lerp(ratio: number, start: Keyframe<string>, end: Keyframe<string>): string {\n const percentageScale = (ratio - start.percentage) / (end.percentage - start.percentage)\n // if percentageScale is negative that means it's before the start value just return start value \n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5 ? start.value : end.value;\n }\n}\n\n/**\n * Built-in interpolation helper for animating integer values.\n *\n * @remarks\n * Uses step-based interpolation with a 50% threshold, similar to strings.\n * Useful for discrete numeric properties like indices or counts.\n *\n * @category Helpers\n */\nexport const integerHelperFunctions: AnimatableAttributeHelper<number> = {\n lerp: (ratio: number, start: Keyframe<number>, end: Keyframe<number>): number => {\n const percentageScale = (ratio - start.percentage) / (end.percentage - start.percentage)\n // if percentageScale is negative that means it's before the start value just return start value \n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5 ? start.value : end.value;\n }\n}\n\nexport class IntegerAnimationHelper implements AnimatableAttributeHelper<number>{\n constructor(){\n\n }\n\n lerp(ratio: number, start: Keyframe<number>, end: Keyframe<number>): number {\n const percentageScale = (ratio - start.percentage) / (end.percentage - start.percentage)\n // if percentageScale is negative that means it's before the start value just return start value \n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5 ? start.value : end.value;\n }\n}\n\n/**\n * RGB color type for color animations.\n *\n * @remarks\n * Represents a color with red, green, and blue components (0-255).\n *\n * @category Types\n */\nexport type RGB = {r: number, g: number, b: number};\n\n/**\n * Built-in interpolation helper for animating RGB color values.\n *\n * @remarks\n * Provides linear interpolation for RGB colors with component-wise blending.\n *\n * @category Helpers\n */\nexport const rgbHelperFunctions: AnimatableAttributeHelper<RGB> = {\n lerp: (ratio: number, start: Keyframe<RGB>, end: Keyframe<RGB>): RGB => {\n const res = {\n r: start.value.r + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.r - start.value.r),\n g: start.value.g + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.g - start.value.g),\n b: start.value.b + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.b - start.value.b),\n }\n return res;\n }\n}\n\nexport class RGBAnimationHelper implements AnimatableAttributeHelper<RGB> {\n constructor(){\n\n }\n\n lerp(ratio: number, start: Keyframe<RGB>, end: Keyframe<RGB>): RGB {\n const res = {\n r: start.value.r + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.r - start.value.r),\n g: start.value.g + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.g - start.value.g),\n b: start.value.b + ((ratio - start.percentage) / (end.percentage - start.percentage)) * (end.value.b - start.value.b),\n }\n return res;\n }\n}\n",
9
- "import { AnimatableAttributeHelper, Keyframe } from \"./animatable-attribute\";\n\n/**\n * Linear easing function (no easing).\n *\n * @param percentage - Animation progress (0.0 to 1.0)\n * @returns Same as input (linear progression)\n *\n * @category Easing\n */\nexport const linear = (percentage: number) => {\n return percentage;\n}\n\n/**\n * Core interface for all animators in the animation system.\n *\n * @remarks\n * The Animator interface defines the contract for both individual animations ({@link Animation})\n * and composite animations ({@link CompositeAnimation}). All animators support:\n * - Lifecycle control (start, stop, pause, resume)\n * - Duration management with delays and drag time\n * - Looping with optional max loop count\n * - Parent-child relationships for composition\n * - Event callbacks for start and end\n *\n * @category Core\n */\nexport interface Animator{\n loops: boolean;\n duration: number;\n delay: number;\n drag: number;\n nonCascadingDuration(newDuration: number): void;\n start(): void;\n stop(): void;\n pause(): void;\n resume(): void;\n animate(deltaTime: number): void;\n setUp(): void;\n resetAnimationState(): void;\n tearDown(): void;\n setParent(parent: AnimatorContainer): void;\n detachParent(): void;\n toggleReverse(reverse: boolean): void;\n onEnd(callback: Function): UnSubscribe;\n onStart(callback: Function): UnSubscribe;\n clearOnStart(): void;\n clearOnEnd(): void;\n maxLoopCount: number | undefined;\n playing: boolean;\n}\n\n/**\n * Function type for unsubscribing from animation events.\n *\n * @category Core\n */\nexport type UnSubscribe = () => void;\n\n/**\n * Interface for containers that hold and manage child animators.\n *\n * @remarks\n * Implemented by {@link CompositeAnimation} to manage hierarchical animation structures.\n * Handles duration updates and prevents cyclic dependencies.\n *\n * @category Core\n */\nexport interface AnimatorContainer {\n updateDuration(): void;\n checkCyclicChildren(): boolean;\n containsAnimation(animationInInterest: Animator): boolean;\n}\n\n/**\n * Container for sequencing and composing multiple animations.\n *\n * @remarks\n * CompositeAnimation allows you to orchestrate complex animation sequences by:\n * - **Sequencing**: Add animations to play one after another\n * - **Overlapping**: Start animations before previous ones complete\n * - **Synchronizing**: Play multiple animations simultaneously\n * - **Nesting**: Compose animations contain other composite animations\n *\n * ## Key Features\n *\n * - Add animations at specific time offsets\n * - Position animations relative to other animations (`addAnimationAfter`, `addAnimationBefore`)\n * - Automatic duration calculation based on child animations\n * - Hierarchical composition for complex sequences\n * - Prevent cyclic animation dependencies\n *\n * @example\n * Basic sequence\n * ```typescript\n * const sequence = new CompositeAnimation();\n *\n * // Add first animation at start (time 0)\n * sequence.addAnimation('fadeIn', fadeAnimation, 0);\n *\n * // Add second animation after first completes\n * sequence.addAnimationAfter('slideIn', slideAnimation, 'fadeIn');\n *\n * // Add third animation to overlap with second (100ms after second starts)\n * sequence.addAnimationAdmist('scaleUp', scaleAnimation, 'slideIn', 100);\n *\n * sequence.start();\n * ```\n *\n * @category Core\n */\nexport class CompositeAnimation implements Animator, AnimatorContainer{\n\n private animations: Map<string, {animator: Animator, startTime?: number}>;\n private localTime: number;\n private _duration: number;\n private onGoing: boolean;\n private loop: boolean;\n private playedTime: number;\n private setUpFn: Function;\n private tearDownFn: Function;\n private _dragTime: number;\n private _delayTime: number;\n private parent: AnimatorContainer | undefined;\n private _maxLoopCount: number | undefined;\n\n private endCallbacks: Function[] = [];\n private startCallbacks: Function[] = [];\n\n private reverse: boolean;\n\n constructor(animations: Map<string, {animator: Animator, startTime?: number}> = new Map(), loop: boolean = false, parent: AnimatorContainer | undefined = undefined, setupFn: Function = ()=>{}, tearDownFn: Function = ()=>{}){\n this.animations = animations;\n this._duration = 0;\n this.calculateDuration();\n this.localTime = -1;\n this.onGoing = false;\n this.loop = loop;\n this.setUpFn = setupFn;\n this.tearDownFn = tearDownFn;\n this._delayTime = 0;\n this._dragTime = 0;\n this.parent = parent;\n this.animations.forEach((animation) => {\n animation.animator.setParent(this);\n });\n this.reverse = false;\n this.playedTime = 0;\n }\n\n toggleReverse(reverse: boolean){\n if(this.reverse == reverse){\n return;\n }\n this.reverse = reverse;\n this.animations.forEach((animation) => {\n animation.animator.toggleReverse(reverse);\n });\n }\n \n setParent(parent: AnimatorContainer){\n this.parent = parent;\n }\n\n detachParent(){\n this.parent = undefined;\n }\n\n animate(deltaTime: number): void {\n if(!this.onGoing || this.localTime > this._duration + this._delayTime + this._dragTime || this.localTime < 0 || this.animations.size == 0){\n return;\n }\n this.localTime += deltaTime;\n if (this.localTime - deltaTime <= 0 && deltaTime > 0){\n // console.log(\"composite animation start\");\n this.startCallbacks.forEach((callback) => {\n queueMicrotask(()=>{callback()});\n });\n }\n this.animateChildren(deltaTime);\n this.checkTerminalAndLoop();\n }\n\n checkTerminalAndLoop(){\n if(this.localTime >= this._duration + this._delayTime + this._dragTime){\n // console.log(\"composite animation end\");\n this.playedTime += 1;\n this.endCallbacks.forEach((callback) => {\n queueMicrotask(()=>{callback()});\n });\n if(!this.loops || (this.maxLoopCount != undefined && this.playedTime >= this.maxLoopCount)){\n // this.onGoing = false;\n this.stop();\n } else {\n // if loop is true and current loop is not the last loop, then prepare to start the animations again\n // this.onGoing = true;\n // this.localTime = 0;\n // this.animations.forEach((animation) => {\n // if(animation.animator.loops){\n // animation.animator.startAnimation();\n // }\n // });\n this.start();\n }\n }\n }\n\n animateChildren(deltaTime: number){\n const prevLocalTime = this.localTime - deltaTime;\n if(this.localTime < this._delayTime){\n return;\n }\n this.animations.forEach((animation, name: string) => {\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n if(!this.childShouldAnimate(animation, prevLocalTime)){\n this.wrapUpAnimator({animator: animation.animator, startTime: animation.startTime, name: name}, prevLocalTime);\n return;\n }\n if(prevLocalTime - this._delayTime < animation.startTime){\n animation.animator.animate(this.localTime - this._delayTime - animation.startTime);\n } else {\n animation.animator.animate(deltaTime);\n }\n });\n }\n\n childShouldAnimate(animation: {animator: Animator, startTime?: number}, prevLocalTime: number): boolean{\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n if(this.localTime - this._delayTime >= animation.startTime && this.localTime - this._delayTime <= animation.startTime + animation.animator.duration){\n return true;\n }\n return false;\n }\n\n wrapUpAnimator(animation: {animator: Animator, startTime?: number, name: string}, prevLocalTime: number){\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n if(this.localTime - this._delayTime > animation.startTime + animation.animator.duration && prevLocalTime - this._delayTime < animation.startTime + animation.animator.duration){\n // console.log(\"wrap up\", animation.name);\n // console.log(\"time remaining\", animation.startTime + animation.animator.duration - (prevLocalTime - this._delayTime));\n \n animation.animator.animate(animation.startTime + animation.animator.duration - (prevLocalTime - this._delayTime));\n }\n }\n\n pause(): void {\n this.onGoing = false;\n this.animations.forEach((animation) => {\n animation.animator.pause();\n });\n }\n\n resume(): void {\n this.onGoing = true;\n this.animations.forEach((animation) => {\n animation.animator.resume();\n });\n }\n\n start(): void {\n this.onGoing = true;\n this.setUp();\n this.localTime = 0;\n this.animations.forEach((animation) => {\n animation.animator.start();\n });\n }\n\n stop(): void {\n this.onGoing = false;\n this.playedTime = 0;\n this.localTime = this._duration + 0.1;\n this.animations.forEach((animation) => {\n animation.animator.stop();\n });\n this.tearDown();\n }\n\n get duration(): number {\n return this._duration + this._delayTime + this._dragTime;\n }\n\n set duration(duration: number) {\n if(duration < 0){\n return;\n }\n const originalDuration = this._duration + this._delayTime + this._dragTime;\n const scale = duration / originalDuration;\n const newDelayTime = this._delayTime * scale;\n const newDragTime = this._dragTime * scale;\n this._delayTime = newDelayTime;\n this._dragTime = newDragTime;\n this.animations.forEach((animation)=>{\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n animation.startTime *= scale;\n const newDuration = animation.animator.duration * scale;\n animation.animator.nonCascadingDuration(newDuration);\n });\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n nonCascadingDuration(newDuration: number): void {\n if(newDuration < 0){\n return;\n }\n const originalDuration = this._duration + this._delayTime + this._dragTime;\n const scale = newDuration / originalDuration;\n const newDelayTime = this._delayTime * scale;\n const newDragTime = this._dragTime * scale;\n this._delayTime = newDelayTime;\n this._dragTime = newDragTime;\n this.animations.forEach((animation)=>{\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n animation.startTime *= scale;\n const newDuration = animation.animator.duration * scale;\n animation.animator.nonCascadingDuration(newDuration);\n });\n this.calculateDuration();\n }\n\n resetAnimationState(): void {\n this.onGoing = false;\n this.animations.forEach((animation) => {\n animation.animator.resetAnimationState();\n });\n }\n\n getTrueDuration(): number{\n return this._duration;\n }\n\n setUp(): void {\n this.setUpFn();\n this.animations.forEach((animation) => {\n animation.animator.setUp();\n });\n }\n\n tearDown(): void {\n this.tearDownFn();\n this.animations.forEach((animation) => {\n animation.animator.tearDown();\n }); \n }\n\n addAnimation(name: string, animation: Animator, startTime: number = 0, endCallback: Function = ()=>{}){\n if(this.animations.has(name)){\n return;\n }\n if(this.parent !== undefined && this.parent.containsAnimation(animation)){\n return;\n }\n this.animations.set(name, {animator: animation, startTime: startTime});\n animation.setParent(this);\n if(this.localTime > startTime){\n animation.animate(this.localTime - startTime);\n }\n const endTime = startTime + animation.duration;\n this._duration = Math.max(this._duration, endTime);\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n addAnimationAfter(name: string, animation: Animator, afterName: string, delay: number = 0){\n let afterAnimation = this.animations.get(afterName);\n if(afterAnimation == undefined){\n return;\n }\n if(afterAnimation.startTime == undefined){\n afterAnimation.startTime = 0;\n }\n let startTime = afterAnimation.startTime + afterAnimation.animator.duration;\n startTime += delay;\n this.addAnimation(name, animation, startTime);\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n addAnimationAdmist(name: string, animation: Animator, admistName: string, delay: number){\n let admistAnimation = this.animations.get(admistName);\n if(admistAnimation == undefined){\n return;\n }\n if(admistAnimation.startTime == undefined){\n admistAnimation.startTime = 0;\n }\n let startTime = admistAnimation.startTime + delay;\n this.addAnimation(name, animation, startTime);\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n addAnimationBefore(name: string, animation: Animator, beforeName: string, aheadTime: number = 0){\n let beforeAnimation = this.animations.get(beforeName);\n if(beforeAnimation == undefined){\n return;\n }\n if(beforeAnimation.startTime == undefined){\n beforeAnimation.startTime = 0;\n }\n let startTime = beforeAnimation.startTime;\n startTime -= aheadTime;\n this.addAnimation(name, animation, startTime);\n if (startTime < 0){\n const pushOver = 0 - startTime;\n this.animations.forEach((animation) => {\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n animation.startTime += pushOver;\n });\n }\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n removeAnimation(name: string){\n let animation = this.animations.get(name);\n let deleted = this.animations.delete(name);\n if(deleted){\n if(animation != undefined){\n animation.animator.detachParent();\n }\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n }\n\n set delay(delayTime: number){\n this._delayTime = delayTime;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n get delay(): number{\n return this._delayTime;\n }\n\n set drag(dragTime: number){\n this._dragTime = dragTime;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n get drag(): number {\n return this._dragTime;\n }\n\n removeDelay(){\n this._delayTime = 0;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n removeDrag(){\n this._dragTime = 0;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n updateDuration(): void {\n if(this.checkCyclicChildren()){\n return;\n }\n this.calculateDuration();\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n calculateDuration(){\n this._duration = 0;\n this.animations.forEach((animation)=>{\n if(animation.startTime == undefined){\n animation.startTime = 0;\n }\n const endTime = animation.startTime + animation.animator.duration;\n this._duration = Math.max(this._duration, endTime);\n });\n }\n \n get loops(): boolean {\n return this.loop;\n }\n\n set loops(loop: boolean) {\n this.loop = loop;\n }\n\n checkCyclicChildren(): boolean {\n const allChildren: Animator[] = [];\n allChildren.push(this);\n const visited = new Set<Animator>();\n while(allChildren.length > 0){\n const current = allChildren.pop();\n if(current == undefined){\n continue;\n }\n if(visited.has(current)){\n return true;\n }\n visited.add(current);\n if(current instanceof CompositeAnimation){\n current.animations.forEach((animation) => {\n allChildren.push(animation.animator);\n });\n }\n }\n return false;\n }\n\n forceToggleLoop(loop: boolean){\n this.loop = true;\n this.animations.forEach((animation) => {\n animation.animator.loops = true;\n });\n }\n\n containsAnimation(animationInInterest: Animator): boolean {\n if(this.parent !== undefined){\n return this.parent.containsAnimation(animationInInterest);\n }\n const allChildren: Animator[] = [];\n allChildren.push(this);\n const visited = new Set<Animator>();\n while(allChildren.length > 0){\n const current = allChildren.pop();\n if(current == undefined){\n continue;\n }\n if(current == animationInInterest){\n return true;\n }\n if(visited.has(current)){\n continue;\n }\n visited.add(current);\n if(current instanceof CompositeAnimation){\n current.animations.forEach((animation) => {\n allChildren.push(animation.animator);\n });\n }\n }\n return false;\n }\n\n onEnd(callback: Function): UnSubscribe{\n this.endCallbacks.push(callback);\n return ()=>{\n this.endCallbacks = this.endCallbacks.filter((cb) => cb != callback);\n }\n }\n\n onStart(callback: Function): UnSubscribe{\n this.startCallbacks.push(callback);\n return ()=>{\n this.startCallbacks = this.startCallbacks.filter((cb) => cb != callback);\n }\n }\n\n clearOnEnd(): void {\n this.endCallbacks = [];\n }\n\n clearOnStart(): void {\n this.startCallbacks = [];\n }\n\n get playing(): boolean {\n return this.onGoing;\n }\n\n get maxLoopCount(): number | undefined {\n return this._maxLoopCount;\n }\n\n set maxLoopCount(maxLoopCount: number | undefined) {\n this._maxLoopCount = maxLoopCount;\n }\n}\n\n/**\n * Keyframe-based animation for a single value.\n *\n * @remarks\n * The Animation class interpolates a value through a series of keyframes over time.\n * It handles:\n * - Keyframe interpolation with binary search for efficiency\n * - Easing functions for smooth motion curves\n * - Reverse playback\n * - Looping with optional max loop count\n * - Delays before start and drag time after completion\n * - Lifecycle callbacks\n *\n * ## How It Works\n *\n * 1. Define keyframes at percentages (0.0 to 1.0) along the timeline\n * 2. Provide a callback to apply the animated value\n * 3. Provide an interpolation helper for the value type\n * 4. Call `animate(deltaTime)` each frame to progress the animation\n *\n * @typeParam T - The type of value being animated\n *\n * @example\n * Animating a number with easing\n * ```typescript\n * let opacity = 0;\n *\n * const fadeIn = new Animation(\n * [\n * { percentage: 0, value: 0 },\n * { percentage: 1, value: 1, easingFn: (t) => t * t } // Ease-in\n * ],\n * (value) => { opacity = value; },\n * numberHelperFunctions,\n * 1000 // 1 second duration\n * );\n *\n * fadeIn.start();\n *\n * // In animation loop\n * function loop(deltaTime: number) {\n * fadeIn.animate(deltaTime);\n * element.style.opacity = opacity;\n * }\n * ```\n *\n * @category Core\n */\nexport class Animation<T> implements Animator{\n\n private localTime: number; // local time starting from 0 up til duration\n private _duration: number;\n private keyframes: Keyframe<T>[];\n private animatableAttributeHelper: AnimatableAttributeHelper<T>;\n private applyAnimationValue: (value: T) => void;\n private easeFn: (percentage: number) => number;\n private onGoing: boolean;\n private currentKeyframeIndex: number;\n private loop: boolean;\n private playedTime: number;\n private setUpFn: Function;\n private tearDownFn: Function;\n private parent: AnimatorContainer | undefined;\n private delayTime: number = 0;\n private dragTime: number = 0;\n\n private reverse: boolean = false;\n private endCallbacks: Function[] = [];\n private startCallbacks: Function[] = [];\n private startAfterDelayCallbacks: Function[] = [];\n\n private zeroPercentageValue: T;\n private _maxLoopCount: number | undefined;\n private _fillMode: 'none' | 'forwards' | 'backwards' | 'both' = 'none';\n\n constructor(keyFrames: Keyframe<T>[], applyAnimationValue: (value: T) => void, animatableAttributeHelper: AnimatableAttributeHelper<T>, duration: number = 1000, loop: boolean = false, parent: AnimatorContainer | undefined = undefined, setUpFn: Function = ()=>{}, tearDownFn: Function = ()=>{}, easeFn: (percentage: number) => number = linear){\n this._duration = duration;\n this.keyframes = keyFrames;\n this.animatableAttributeHelper = animatableAttributeHelper;\n this.applyAnimationValue = applyAnimationValue;\n this.easeFn = easeFn;\n this.onGoing = false;\n this.localTime = duration + 0.1;\n this.currentKeyframeIndex = 0;\n this.loop = loop;\n this.setUpFn = setUpFn;\n this.tearDownFn = tearDownFn;\n this.parent = parent;\n this.playedTime = 0;\n this.zeroPercentageValue = this.findValue(0, keyFrames, animatableAttributeHelper);\n }\n\n toggleReverse(reverse: boolean): void{\n this.reverse = reverse;\n }\n\n start(): void{\n this.localTime = 0;\n this.currentKeyframeIndex = 0;\n this.onGoing = true;\n // this.applyAnimationValue(this.zeroPercentageValue);\n this.setUp();\n }\n\n stop(): void{\n this.onGoing = false;\n this.localTime = this._duration + this.dragTime + this.delayTime + 0.1;\n this.playedTime = 0;\n this.tearDown();\n }\n\n pause(): void{\n this.onGoing = false;\n }\n\n resume(){\n this.onGoing = true;\n }\n\n get playing(): boolean {\n return this.onGoing;\n }\n\n animate(deltaTime: number){\n if(this.onGoing != true || this.localTime < 0) {\n return;\n }\n if(deltaTime == 0){\n return;\n }\n this.localTime += deltaTime;\n // console.log(\"--------------------\");\n // console.log(\"local time\", this.localTime);\n // console.log(\"delta time\", deltaTime);\n if(this.localTime - deltaTime <= 0 && deltaTime > 0){\n // console.log(\"--------------------\");\n // console.log(\"current localtime\", this.localTime);\n // console.log(\"current delta time\", deltaTime);\n // console.log(\"previous local time\", this.localTime - deltaTime);\n // console.log(\"animation start\");\n // console.log(`the animation has been played ${this.playedTime} times`);\n // console.log(`the animation is now playing for the ${this.playedTime + 1} time`);\n this.startCallbacks.forEach((callback) => {\n queueMicrotask(()=>{callback()});\n });\n }\n if(this.localTime >= this.delayTime && (this.localTime <= this.delayTime + this._duration + this.dragTime || this.localTime - deltaTime <= this.delayTime + this._duration + this.dragTime)){\n // console.log(\"local time\", this.localTime);\n // console.log(\"duration\", this.duration);\n // console.log(\"local time would trigger end\", this.localTime >= this._duration + this.delayTime + this.dragTime);\n // console.log(\"delta time\", deltaTime);\n if(this.localTime - deltaTime <= this.delayTime && this.delayTime !== 0 && deltaTime > 0){\n this.startAfterDelayCallbacks.forEach((callback) => {\n queueMicrotask(()=>{callback()});\n });\n this.applyAnimationValue(this.zeroPercentageValue);\n }\n let localTimePercentage = (this.localTime - this.delayTime) / (this._duration);\n let targetPercentage = this.easeFn(localTimePercentage);\n if (localTimePercentage > 1){\n targetPercentage = this.easeFn(1);\n }\n let value: T;\n // console.log(\"currentKeyframeIndex\", this.currentKeyframeIndex, \"length\", this.keyFrames.length);\n if(this.currentKeyframeIndex < this.keyframes.length && this.currentKeyframeIndex >= 0 && (this.reverse ? 1 - this.keyframes[this.currentKeyframeIndex].percentage == targetPercentage : this.keyframes[this.currentKeyframeIndex].percentage == targetPercentage) ){\n value = this.keyframes[this.currentKeyframeIndex].value;\n } else {\n value = this.findValue(targetPercentage, this.keyframes, this.animatableAttributeHelper);\n }\n if(this.reverse){\n while(this.currentKeyframeIndex >= 0 && 1 - this.keyframes[this.currentKeyframeIndex].percentage <= targetPercentage){\n this.currentKeyframeIndex -= 1;\n }\n } else {\n while(this.currentKeyframeIndex < this.keyframes.length && this.keyframes[this.currentKeyframeIndex].percentage <= targetPercentage){\n this.currentKeyframeIndex += 1;\n }\n }\n this.applyAnimationValue(value);\n if(this.localTime >= this._duration + this.dragTime + this.delayTime){\n // console.log(\"animation should end\");\n this.playedTime += 1;\n this.endCallbacks.forEach((callback) => {\n queueMicrotask(()=>{callback()});\n });\n if(!this.loops || (this._maxLoopCount != undefined && this.playedTime >= (this.maxLoopCount ?? 0))){\n // this.onGoing = false;\n // console.log(\"animation should stop after \", this.playedTime, \" loops\");\n this.stop();\n } else {\n // console.log(\"animation should restart\");\n this.onGoing = true;\n this.localTime = 0;\n this.currentKeyframeIndex = 0;\n this.start();\n }\n }\n // if((this.localTime >= this._duration + this.delayTime + this.dragTime) && this.loop){\n // // this.startAnimation();\n // this.localTime = 0;\n // this.onGoing = true;\n // this.currentKeyframeIndex = 0;\n // }\n }\n }\n\n findValue(valuePercentage: number, keyframes: Keyframe<T>[], animatableAttributeHelper: AnimatableAttributeHelper<T>): T{\n if(valuePercentage > 1){\n if(this.reverse){\n return animatableAttributeHelper.lerp(valuePercentage, keyframes[1], keyframes[0]);\n }\n return animatableAttributeHelper.lerp(valuePercentage, keyframes[keyframes.length - 2], keyframes[keyframes.length - 1]);\n }\n if(valuePercentage < 0){\n if(this.reverse){\n return animatableAttributeHelper.lerp(valuePercentage, keyframes[keyframes.length - 2], keyframes[keyframes.length - 1]);\n }\n return animatableAttributeHelper.lerp(valuePercentage, keyframes[1], keyframes[0]);\n }\n let left = 0;\n let right = keyframes.length - 1;\n while (left <= right) {\n let mid = left + Math.floor((right - left) / 2);\n const midPercentage = this.reverse ? 1 - keyframes[mid].percentage : keyframes[mid].percentage;\n if(midPercentage == valuePercentage) {\n return keyframes[mid].value;\n } else if(midPercentage < valuePercentage){\n if(this.reverse){\n right = mid - 1;\n } else {\n left = mid + 1;\n }\n } else {\n if(this.reverse){\n left = mid + 1;\n } else {\n right = mid - 1;\n }\n }\n }\n if(left > keyframes.length - 1){\n // excceding the keyframes\n left = keyframes.length - 1;\n }\n const interpolateStartFrame = this.reverse ? {percentage: 1 - keyframes[left].percentage, value: keyframes[left].value} : keyframes[left - 1];\n const interplateEndFrame = this.reverse ? {percentage: 1 - keyframes[left - 1].percentage, value: keyframes[left - 1].value} : keyframes[left];\n // return animatableAttributeHelper.lerp(valuePercentage, keyframes[left - 1], keyframes[left]);\n return animatableAttributeHelper.lerp(valuePercentage, interpolateStartFrame, interplateEndFrame);\n }\n\n setUp(): void {\n // this.applyAnimationValue(this.keyframes[0].value);\n this.setUpFn();\n }\n\n tearDown(): void {\n this.tearDownFn(); \n }\n\n get loops(): boolean {\n return this.loop;\n }\n\n set loops(loop: boolean) {\n this.loop = loop;\n }\n\n get duration(): number {\n return this._duration + this.delayTime + this.dragTime;\n }\n\n set duration(duration: number) {\n if(duration < 0){\n return;\n }\n const originalDuration = this._duration + this.delayTime + this.dragTime;\n const scale = duration / originalDuration;\n const newDelayTime = this.delayTime * scale;\n const newDragTime = this.dragTime * scale;\n this.delayTime = newDelayTime;\n this.dragTime = newDragTime;\n this._duration = this._duration * scale;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n nonCascadingDuration(newDuration: number): void {\n if(newDuration < 0){\n return;\n }\n const originalDuration = this._duration + this.delayTime + this.dragTime;\n const scale = newDuration / originalDuration;\n const newDelayTime = this.delayTime * scale;\n const newDragTime = this.dragTime * scale;\n this.delayTime = newDelayTime;\n this.dragTime = newDragTime;\n this._duration = newDuration;\n }\n\n resetAnimationState(): void {\n this.onGoing = false;\n this.applyAnimationValue(this.keyframes[0].value);\n this.currentKeyframeIndex = 0;\n this.setUp();\n }\n\n wrapUp(): void {\n this.onGoing = false;\n this.localTime = this._duration + this.dragTime + this.delayTime + 0.1;\n this.currentKeyframeIndex = 0;\n }\n\n get delay(): number {\n return this.delayTime;\n }\n\n set delay(delayTime: number){\n this.delayTime = delayTime;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n get drag(): number {\n return this.dragTime;\n }\n\n set drag(dragTime: number){\n this.dragTime = dragTime;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n get trueDuration(): number {\n return this._duration;\n }\n\n set trueDuration(duration: number){\n this._duration = duration;\n if(this.parent != undefined){\n this.parent.updateDuration();\n }\n }\n\n setParent(parent: AnimatorContainer){\n this.parent = parent;\n }\n\n detachParent(): void {\n this.parent = undefined;\n }\n\n set keyFrames(keyFrames: Keyframe<T>[]){\n this.keyframes = keyFrames;\n this.zeroPercentageValue = this.findValue(0, keyFrames, this.animatableAttributeHelper);\n }\n\n get keyFrames(): Keyframe<T>[]{\n return this.keyframes;\n }\n\n get easeFunction(): (percentage: number) => number {\n return this.easeFn;\n }\n\n set easeFunction(easeFn: (percentage: number) => number){\n this.easeFn = easeFn;\n }\n\n onEnd(callback: Function): UnSubscribe{\n this.endCallbacks.push(callback);\n return ()=>{\n this.endCallbacks = this.endCallbacks.filter((cb) => cb != callback);\n }\n }\n\n onStart(callback: Function): UnSubscribe{\n this.startCallbacks.push(callback);\n return ()=>{\n this.startCallbacks = this.startCallbacks.filter((cb) => cb != callback);\n }\n }\n\n onStartAfterDelay(callback: Function): UnSubscribe{\n this.startAfterDelayCallbacks.push(callback);\n return ()=>{\n this.startAfterDelayCallbacks = this.startAfterDelayCallbacks.filter((cb) => cb != callback);\n }\n }\n\n clearOnEnd(): void {\n this.endCallbacks = [];\n }\n\n clearOnStart(): void {\n this.startCallbacks = [];\n }\n\n get maxLoopCount(): number | undefined {\n return this._maxLoopCount;\n }\n\n set maxLoopCount(maxLoopCount: number | undefined) {\n this._maxLoopCount = maxLoopCount;\n }\n}\n\nexport interface Keyframes<T> {\n keyframes: Keyframe<T>[];\n from(value: T): Keyframes<T>;\n to(value: T): Keyframes<T>;\n insertAt(percentage: number, value: T): void;\n clearFrames(): void;\n}\n\nexport class KeyFramesContiner<T> {\n\n private _keyframes: Keyframe<T>[];\n\n constructor(){\n this._keyframes = [];\n }\n\n get keyframes(): Keyframe<T>[] {\n return this._keyframes;\n }\n\n from(value: T): Keyframes<T>{\n if(this._keyframes.length == 0){\n this._keyframes.push({percentage: 0, value: value});\n } else {\n if(this._keyframes[0].percentage == 0){\n this._keyframes[0].value = value;\n } else {\n this._keyframes.unshift({percentage: 0, value: value});\n }\n }\n return this;\n }\n\n to(value: T): Keyframes<T>{\n if(this._keyframes.length == 0){\n this._keyframes.push({percentage: 1, value: value});\n } else {\n if(this._keyframes[this._keyframes.length - 1].percentage == 1){\n this._keyframes[this._keyframes.length - 1].value = value;\n } else {\n this._keyframes.push({percentage: 1, value: value});\n }\n }\n return this;\n }\n\n insertAt(percentage: number, value: T): void{\n this._keyframes.push({percentage: percentage, value: value});\n }\n\n clearFrames(): void{\n this._keyframes = [];\n }\n}\n"
8
+ "import { Point, PointCal } from '@ue-too/math';\n\n/**\n * Represents a keyframe in an animation timeline.\n *\n * @remarks\n * A keyframe defines a value at a specific point in the animation's progress.\n * Keyframes are defined with a percentage from 0.0 (start) to 1.0 (end), along\n * with the value at that point and an optional easing function for interpolation\n * to the next keyframe.\n *\n * @typeParam T - The type of value being animated (number, Point, RGB, etc.)\n *\n * @example\n * ```typescript\n * const keyframe: Keyframe<number> = {\n * percentage: 0.5,\n * value: 50,\n * easingFn: (t) => t * t // Ease-in quadratic\n * };\n * ```\n *\n * @category Types\n */\nexport type Keyframe<T> = {\n /** Animation progress from 0.0 (start) to 1.0 (end) */\n percentage: number;\n /** Value at this keyframe */\n value: T;\n /** Optional easing function for interpolation to next keyframe */\n easingFn?: (percentage: number) => number;\n};\n\n/**\n * Interface for type-specific interpolation helpers.\n *\n * @remarks\n * Animation helpers provide the `lerp` (linear interpolation) logic for specific types.\n * Different types require different interpolation strategies:\n * - Numbers: Simple linear interpolation\n * - Points: Component-wise interpolation\n * - Colors (RGB): Component-wise color interpolation\n * - Strings: Step-based (threshold) interpolation\n *\n * @typeParam T - The type of value being interpolated\n *\n * @example\n * ```typescript\n * const myHelper: AnimatableAttributeHelper<number> = {\n * lerp: (ratio, start, end) => {\n * const t = (ratio - start.percentage) / (end.percentage - start.percentage);\n * return start.value + t * (end.value - start.value);\n * }\n * };\n * ```\n *\n * @category Helpers\n */\nexport interface AnimatableAttributeHelper<T> {\n /**\n * Interpolates between two keyframes at a given ratio.\n *\n * @param ratio - Current animation progress (0.0 to 1.0)\n * @param start - Starting keyframe\n * @param end - Ending keyframe\n * @returns Interpolated value at the given ratio\n */\n lerp(ratio: number, start: Keyframe<T>, end: Keyframe<T>): T;\n}\n\n/**\n * Built-in interpolation helper for animating Point values.\n *\n * @remarks\n * Provides linear interpolation for 2D points with optional easing.\n * Interpolates both x and y components independently.\n *\n * @category Helpers\n */\nexport const pointHelperFunctions: AnimatableAttributeHelper<Point> = {\n lerp: (\n ratio: number,\n start: Keyframe<Point>,\n end: Keyframe<Point>\n ): Point => {\n const inbetweenRatio =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if (start.easingFn) {\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = PointCal.addVector(\n start.value,\n PointCal.multiplyVectorByScalar(\n PointCal.subVector(end.value, start.value),\n transformed\n )\n );\n return res;\n },\n};\n\nexport class PointAnimationHelper implements AnimatableAttributeHelper<Point> {\n constructor() {}\n\n lerp(ratio: number, start: Keyframe<Point>, end: Keyframe<Point>): Point {\n const inbetweenRatio =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if (start.easingFn) {\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = PointCal.addVector(\n start.value,\n PointCal.multiplyVectorByScalar(\n PointCal.subVector(end.value, start.value),\n transformed\n )\n );\n return res;\n }\n}\n\n/**\n * Built-in interpolation helper for animating number values.\n *\n * @remarks\n * Provides linear interpolation for numeric values with optional easing.\n *\n * @category Helpers\n */\nexport const numberHelperFunctions: AnimatableAttributeHelper<number> = {\n lerp: (\n ratio: number,\n start: Keyframe<number>,\n end: Keyframe<number>\n ): number => {\n const inbetweenRatio =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if (start.easingFn) {\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = start.value + transformed * (end.value - start.value);\n return res;\n },\n};\n\nexport class NumberAnimationHelper implements AnimatableAttributeHelper<number> {\n constructor() {}\n\n lerp(\n ratio: number,\n start: Keyframe<number>,\n end: Keyframe<number>\n ): number {\n const inbetweenRatio =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n let transformed = inbetweenRatio;\n if (start.easingFn) {\n transformed = start.easingFn(inbetweenRatio);\n }\n const res = start.value + transformed * (end.value - start.value);\n return res;\n }\n}\n\n/**\n * Built-in interpolation helper for animating string values.\n *\n * @remarks\n * Uses step-based interpolation with a 50% threshold. Returns start value until\n * 50% progress, then switches to end value. Useful for discrete property changes.\n *\n * @category Helpers\n */\nexport const stringHelperFunctions: AnimatableAttributeHelper<string> = {\n lerp: (\n ratio: number,\n start: Keyframe<string>,\n end: Keyframe<string>\n ): string => {\n const percentageScale =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n // if percentageScale is negative that means it's before the start value just return start value\n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5\n ? start.value\n : end.value;\n },\n};\n\nexport class StringAnimationHelper implements AnimatableAttributeHelper<string> {\n constructor() {}\n\n lerp(\n ratio: number,\n start: Keyframe<string>,\n end: Keyframe<string>\n ): string {\n const percentageScale =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n // if percentageScale is negative that means it's before the start value just return start value\n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5\n ? start.value\n : end.value;\n }\n}\n\n/**\n * Built-in interpolation helper for animating integer values.\n *\n * @remarks\n * Uses step-based interpolation with a 50% threshold, similar to strings.\n * Useful for discrete numeric properties like indices or counts.\n *\n * @category Helpers\n */\nexport const integerHelperFunctions: AnimatableAttributeHelper<number> = {\n lerp: (\n ratio: number,\n start: Keyframe<number>,\n end: Keyframe<number>\n ): number => {\n const percentageScale =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n // if percentageScale is negative that means it's before the start value just return start value\n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5\n ? start.value\n : end.value;\n },\n};\n\nexport class IntegerAnimationHelper implements AnimatableAttributeHelper<number> {\n constructor() {}\n\n lerp(\n ratio: number,\n start: Keyframe<number>,\n end: Keyframe<number>\n ): number {\n const percentageScale =\n (ratio - start.percentage) / (end.percentage - start.percentage);\n // if percentageScale is negative that means it's before the start value just return start value\n // if percentageScale is more than 1 that means it's after the end value just return the end value\n // if percentageScale is less than 0.5 return the start value else return the end value\n return percentageScale < 0 || percentageScale < 0.5\n ? start.value\n : end.value;\n }\n}\n\n/**\n * RGB color type for color animations.\n *\n * @remarks\n * Represents a color with red, green, and blue components (0-255).\n *\n * @category Types\n */\nexport type RGB = { r: number; g: number; b: number };\n\n/**\n * Built-in interpolation helper for animating RGB color values.\n *\n * @remarks\n * Provides linear interpolation for RGB colors with component-wise blending.\n *\n * @category Helpers\n */\nexport const rgbHelperFunctions: AnimatableAttributeHelper<RGB> = {\n lerp: (ratio: number, start: Keyframe<RGB>, end: Keyframe<RGB>): RGB => {\n const res = {\n r:\n start.value.r +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.r - start.value.r),\n g:\n start.value.g +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.g - start.value.g),\n b:\n start.value.b +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.b - start.value.b),\n };\n return res;\n },\n};\n\nexport class RGBAnimationHelper implements AnimatableAttributeHelper<RGB> {\n constructor() {}\n\n lerp(ratio: number, start: Keyframe<RGB>, end: Keyframe<RGB>): RGB {\n const res = {\n r:\n start.value.r +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.r - start.value.r),\n g:\n start.value.g +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.g - start.value.g),\n b:\n start.value.b +\n ((ratio - start.percentage) /\n (end.percentage - start.percentage)) *\n (end.value.b - start.value.b),\n };\n return res;\n }\n}\n",
9
+ "import { AnimatableAttributeHelper, Keyframe } from './animatable-attribute';\n\n/**\n * Linear easing function (no easing).\n *\n * @param percentage - Animation progress (0.0 to 1.0)\n * @returns Same as input (linear progression)\n *\n * @category Easing\n */\nexport const linear = (percentage: number) => {\n return percentage;\n};\n\n/**\n * Core interface for all animators in the animation system.\n *\n * @remarks\n * The Animator interface defines the contract for both individual animations ({@link Animation})\n * and composite animations ({@link CompositeAnimation}). All animators support:\n * - Lifecycle control (start, stop, pause, resume)\n * - Duration management with delays and drag time\n * - Looping with optional max loop count\n * - Parent-child relationships for composition\n * - Event callbacks for start and end\n *\n * @category Core\n */\nexport interface Animator {\n loops: boolean;\n duration: number;\n delay: number;\n drag: number;\n nonCascadingDuration(newDuration: number): void;\n start(): void;\n stop(): void;\n pause(): void;\n resume(): void;\n animate(deltaTime: number): void;\n setUp(): void;\n resetAnimationState(): void;\n tearDown(): void;\n setParent(parent: AnimatorContainer): void;\n detachParent(): void;\n toggleReverse(reverse: boolean): void;\n onEnd(callback: Function): UnSubscribe;\n onStart(callback: Function): UnSubscribe;\n clearOnStart(): void;\n clearOnEnd(): void;\n maxLoopCount: number | undefined;\n playing: boolean;\n}\n\n/**\n * Function type for unsubscribing from animation events.\n *\n * @category Core\n */\nexport type UnSubscribe = () => void;\n\n/**\n * Interface for containers that hold and manage child animators.\n *\n * @remarks\n * Implemented by {@link CompositeAnimation} to manage hierarchical animation structures.\n * Handles duration updates and prevents cyclic dependencies.\n *\n * @category Core\n */\nexport interface AnimatorContainer {\n updateDuration(): void;\n checkCyclicChildren(): boolean;\n containsAnimation(animationInInterest: Animator): boolean;\n}\n\n/**\n * Container for sequencing and composing multiple animations.\n *\n * @remarks\n * CompositeAnimation allows you to orchestrate complex animation sequences by:\n * - **Sequencing**: Add animations to play one after another\n * - **Overlapping**: Start animations before previous ones complete\n * - **Synchronizing**: Play multiple animations simultaneously\n * - **Nesting**: Compose animations contain other composite animations\n *\n * ## Key Features\n *\n * - Add animations at specific time offsets\n * - Position animations relative to other animations (`addAnimationAfter`, `addAnimationBefore`)\n * - Automatic duration calculation based on child animations\n * - Hierarchical composition for complex sequences\n * - Prevent cyclic animation dependencies\n *\n * @example\n * Basic sequence\n * ```typescript\n * const sequence = new CompositeAnimation();\n *\n * // Add first animation at start (time 0)\n * sequence.addAnimation('fadeIn', fadeAnimation, 0);\n *\n * // Add second animation after first completes\n * sequence.addAnimationAfter('slideIn', slideAnimation, 'fadeIn');\n *\n * // Add third animation to overlap with second (100ms after second starts)\n * sequence.addAnimationAdmist('scaleUp', scaleAnimation, 'slideIn', 100);\n *\n * sequence.start();\n * ```\n *\n * @category Core\n */\nexport class CompositeAnimation implements Animator, AnimatorContainer {\n private animations: Map<string, { animator: Animator; startTime?: number }>;\n private localTime: number;\n private _duration: number;\n private onGoing: boolean;\n private loop: boolean;\n private playedTime: number;\n private setUpFn: Function;\n private tearDownFn: Function;\n private _dragTime: number;\n private _delayTime: number;\n private parent: AnimatorContainer | undefined;\n private _maxLoopCount: number | undefined;\n\n private endCallbacks: Function[] = [];\n private startCallbacks: Function[] = [];\n\n private reverse: boolean;\n\n constructor(\n animations: Map<\n string,\n { animator: Animator; startTime?: number }\n > = new Map(),\n loop: boolean = false,\n parent: AnimatorContainer | undefined = undefined,\n setupFn: Function = () => {},\n tearDownFn: Function = () => {}\n ) {\n this.animations = animations;\n this._duration = 0;\n this.calculateDuration();\n this.localTime = -1;\n this.onGoing = false;\n this.loop = loop;\n this.setUpFn = setupFn;\n this.tearDownFn = tearDownFn;\n this._delayTime = 0;\n this._dragTime = 0;\n this.parent = parent;\n this.animations.forEach(animation => {\n animation.animator.setParent(this);\n });\n this.reverse = false;\n this.playedTime = 0;\n }\n\n toggleReverse(reverse: boolean) {\n if (this.reverse == reverse) {\n return;\n }\n this.reverse = reverse;\n this.animations.forEach(animation => {\n animation.animator.toggleReverse(reverse);\n });\n }\n\n setParent(parent: AnimatorContainer) {\n this.parent = parent;\n }\n\n detachParent() {\n this.parent = undefined;\n }\n\n animate(deltaTime: number): void {\n if (\n !this.onGoing ||\n this.localTime >\n this._duration + this._delayTime + this._dragTime ||\n this.localTime < 0 ||\n this.animations.size == 0\n ) {\n return;\n }\n this.localTime += deltaTime;\n if (this.localTime - deltaTime <= 0 && deltaTime > 0) {\n // console.log(\"composite animation start\");\n this.startCallbacks.forEach(callback => {\n queueMicrotask(() => {\n callback();\n });\n });\n }\n this.animateChildren(deltaTime);\n this.checkTerminalAndLoop();\n }\n\n checkTerminalAndLoop() {\n if (\n this.localTime >=\n this._duration + this._delayTime + this._dragTime\n ) {\n // console.log(\"composite animation end\");\n this.playedTime += 1;\n this.endCallbacks.forEach(callback => {\n queueMicrotask(() => {\n callback();\n });\n });\n if (\n !this.loops ||\n (this.maxLoopCount != undefined &&\n this.playedTime >= this.maxLoopCount)\n ) {\n // this.onGoing = false;\n this.stop();\n } else {\n // if loop is true and current loop is not the last loop, then prepare to start the animations again\n // this.onGoing = true;\n // this.localTime = 0;\n // this.animations.forEach((animation) => {\n // if(animation.animator.loops){\n // animation.animator.startAnimation();\n // }\n // });\n this.start();\n }\n }\n }\n\n animateChildren(deltaTime: number) {\n const prevLocalTime = this.localTime - deltaTime;\n if (this.localTime < this._delayTime) {\n return;\n }\n this.animations.forEach((animation, name: string) => {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n if (!this.childShouldAnimate(animation, prevLocalTime)) {\n this.wrapUpAnimator(\n {\n animator: animation.animator,\n startTime: animation.startTime,\n name: name,\n },\n prevLocalTime\n );\n return;\n }\n if (prevLocalTime - this._delayTime < animation.startTime) {\n animation.animator.animate(\n this.localTime - this._delayTime - animation.startTime\n );\n } else {\n animation.animator.animate(deltaTime);\n }\n });\n }\n\n childShouldAnimate(\n animation: { animator: Animator; startTime?: number },\n prevLocalTime: number\n ): boolean {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n if (\n this.localTime - this._delayTime >= animation.startTime &&\n this.localTime - this._delayTime <=\n animation.startTime + animation.animator.duration\n ) {\n return true;\n }\n return false;\n }\n\n wrapUpAnimator(\n animation: { animator: Animator; startTime?: number; name: string },\n prevLocalTime: number\n ) {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n if (\n this.localTime - this._delayTime >\n animation.startTime + animation.animator.duration &&\n prevLocalTime - this._delayTime <\n animation.startTime + animation.animator.duration\n ) {\n // console.log(\"wrap up\", animation.name);\n // console.log(\"time remaining\", animation.startTime + animation.animator.duration - (prevLocalTime - this._delayTime));\n\n animation.animator.animate(\n animation.startTime +\n animation.animator.duration -\n (prevLocalTime - this._delayTime)\n );\n }\n }\n\n pause(): void {\n this.onGoing = false;\n this.animations.forEach(animation => {\n animation.animator.pause();\n });\n }\n\n resume(): void {\n this.onGoing = true;\n this.animations.forEach(animation => {\n animation.animator.resume();\n });\n }\n\n start(): void {\n this.onGoing = true;\n this.setUp();\n this.localTime = 0;\n this.animations.forEach(animation => {\n animation.animator.start();\n });\n }\n\n stop(): void {\n this.onGoing = false;\n this.playedTime = 0;\n this.localTime = this._duration + 0.1;\n this.animations.forEach(animation => {\n animation.animator.stop();\n });\n this.tearDown();\n }\n\n get duration(): number {\n return this._duration + this._delayTime + this._dragTime;\n }\n\n set duration(duration: number) {\n if (duration < 0) {\n return;\n }\n const originalDuration =\n this._duration + this._delayTime + this._dragTime;\n const scale = duration / originalDuration;\n const newDelayTime = this._delayTime * scale;\n const newDragTime = this._dragTime * scale;\n this._delayTime = newDelayTime;\n this._dragTime = newDragTime;\n this.animations.forEach(animation => {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n animation.startTime *= scale;\n const newDuration = animation.animator.duration * scale;\n animation.animator.nonCascadingDuration(newDuration);\n });\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n nonCascadingDuration(newDuration: number): void {\n if (newDuration < 0) {\n return;\n }\n const originalDuration =\n this._duration + this._delayTime + this._dragTime;\n const scale = newDuration / originalDuration;\n const newDelayTime = this._delayTime * scale;\n const newDragTime = this._dragTime * scale;\n this._delayTime = newDelayTime;\n this._dragTime = newDragTime;\n this.animations.forEach(animation => {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n animation.startTime *= scale;\n const newDuration = animation.animator.duration * scale;\n animation.animator.nonCascadingDuration(newDuration);\n });\n this.calculateDuration();\n }\n\n resetAnimationState(): void {\n this.onGoing = false;\n this.animations.forEach(animation => {\n animation.animator.resetAnimationState();\n });\n }\n\n getTrueDuration(): number {\n return this._duration;\n }\n\n setUp(): void {\n this.setUpFn();\n this.animations.forEach(animation => {\n animation.animator.setUp();\n });\n }\n\n tearDown(): void {\n this.tearDownFn();\n this.animations.forEach(animation => {\n animation.animator.tearDown();\n });\n }\n\n addAnimation(\n name: string,\n animation: Animator,\n startTime: number = 0,\n endCallback: Function = () => {}\n ) {\n if (this.animations.has(name)) {\n return;\n }\n if (\n this.parent !== undefined &&\n this.parent.containsAnimation(animation)\n ) {\n return;\n }\n this.animations.set(name, {\n animator: animation,\n startTime: startTime,\n });\n animation.setParent(this);\n if (this.localTime > startTime) {\n animation.animate(this.localTime - startTime);\n }\n const endTime = startTime + animation.duration;\n this._duration = Math.max(this._duration, endTime);\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n addAnimationAfter(\n name: string,\n animation: Animator,\n afterName: string,\n delay: number = 0\n ) {\n let afterAnimation = this.animations.get(afterName);\n if (afterAnimation == undefined) {\n return;\n }\n if (afterAnimation.startTime == undefined) {\n afterAnimation.startTime = 0;\n }\n let startTime =\n afterAnimation.startTime + afterAnimation.animator.duration;\n startTime += delay;\n this.addAnimation(name, animation, startTime);\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n addAnimationAdmist(\n name: string,\n animation: Animator,\n admistName: string,\n delay: number\n ) {\n let admistAnimation = this.animations.get(admistName);\n if (admistAnimation == undefined) {\n return;\n }\n if (admistAnimation.startTime == undefined) {\n admistAnimation.startTime = 0;\n }\n let startTime = admistAnimation.startTime + delay;\n this.addAnimation(name, animation, startTime);\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n addAnimationBefore(\n name: string,\n animation: Animator,\n beforeName: string,\n aheadTime: number = 0\n ) {\n let beforeAnimation = this.animations.get(beforeName);\n if (beforeAnimation == undefined) {\n return;\n }\n if (beforeAnimation.startTime == undefined) {\n beforeAnimation.startTime = 0;\n }\n let startTime = beforeAnimation.startTime;\n startTime -= aheadTime;\n this.addAnimation(name, animation, startTime);\n if (startTime < 0) {\n const pushOver = 0 - startTime;\n this.animations.forEach(animation => {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n animation.startTime += pushOver;\n });\n }\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n removeAnimation(name: string) {\n let animation = this.animations.get(name);\n let deleted = this.animations.delete(name);\n if (deleted) {\n if (animation != undefined) {\n animation.animator.detachParent();\n }\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n }\n\n set delay(delayTime: number) {\n this._delayTime = delayTime;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n get delay(): number {\n return this._delayTime;\n }\n\n set drag(dragTime: number) {\n this._dragTime = dragTime;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n get drag(): number {\n return this._dragTime;\n }\n\n removeDelay() {\n this._delayTime = 0;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n removeDrag() {\n this._dragTime = 0;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n updateDuration(): void {\n if (this.checkCyclicChildren()) {\n return;\n }\n this.calculateDuration();\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n calculateDuration() {\n this._duration = 0;\n this.animations.forEach(animation => {\n if (animation.startTime == undefined) {\n animation.startTime = 0;\n }\n const endTime = animation.startTime + animation.animator.duration;\n this._duration = Math.max(this._duration, endTime);\n });\n }\n\n get loops(): boolean {\n return this.loop;\n }\n\n set loops(loop: boolean) {\n this.loop = loop;\n }\n\n checkCyclicChildren(): boolean {\n const allChildren: Animator[] = [];\n allChildren.push(this);\n const visited = new Set<Animator>();\n while (allChildren.length > 0) {\n const current = allChildren.pop();\n if (current == undefined) {\n continue;\n }\n if (visited.has(current)) {\n return true;\n }\n visited.add(current);\n if (current instanceof CompositeAnimation) {\n current.animations.forEach(animation => {\n allChildren.push(animation.animator);\n });\n }\n }\n return false;\n }\n\n forceToggleLoop(loop: boolean) {\n this.loop = true;\n this.animations.forEach(animation => {\n animation.animator.loops = true;\n });\n }\n\n containsAnimation(animationInInterest: Animator): boolean {\n if (this.parent !== undefined) {\n return this.parent.containsAnimation(animationInInterest);\n }\n const allChildren: Animator[] = [];\n allChildren.push(this);\n const visited = new Set<Animator>();\n while (allChildren.length > 0) {\n const current = allChildren.pop();\n if (current == undefined) {\n continue;\n }\n if (current == animationInInterest) {\n return true;\n }\n if (visited.has(current)) {\n continue;\n }\n visited.add(current);\n if (current instanceof CompositeAnimation) {\n current.animations.forEach(animation => {\n allChildren.push(animation.animator);\n });\n }\n }\n return false;\n }\n\n onEnd(callback: Function): UnSubscribe {\n this.endCallbacks.push(callback);\n return () => {\n this.endCallbacks = this.endCallbacks.filter(cb => cb != callback);\n };\n }\n\n onStart(callback: Function): UnSubscribe {\n this.startCallbacks.push(callback);\n return () => {\n this.startCallbacks = this.startCallbacks.filter(\n cb => cb != callback\n );\n };\n }\n\n clearOnEnd(): void {\n this.endCallbacks = [];\n }\n\n clearOnStart(): void {\n this.startCallbacks = [];\n }\n\n get playing(): boolean {\n return this.onGoing;\n }\n\n get maxLoopCount(): number | undefined {\n return this._maxLoopCount;\n }\n\n set maxLoopCount(maxLoopCount: number | undefined) {\n this._maxLoopCount = maxLoopCount;\n }\n}\n\n/**\n * Keyframe-based animation for a single value.\n *\n * @remarks\n * The Animation class interpolates a value through a series of keyframes over time.\n * It handles:\n * - Keyframe interpolation with binary search for efficiency\n * - Easing functions for smooth motion curves\n * - Reverse playback\n * - Looping with optional max loop count\n * - Delays before start and drag time after completion\n * - Lifecycle callbacks\n *\n * ## How It Works\n *\n * 1. Define keyframes at percentages (0.0 to 1.0) along the timeline\n * 2. Provide a callback to apply the animated value\n * 3. Provide an interpolation helper for the value type\n * 4. Call `animate(deltaTime)` each frame to progress the animation\n *\n * @typeParam T - The type of value being animated\n *\n * @example\n * Animating a number with easing\n * ```typescript\n * let opacity = 0;\n *\n * const fadeIn = new Animation(\n * [\n * { percentage: 0, value: 0 },\n * { percentage: 1, value: 1, easingFn: (t) => t * t } // Ease-in\n * ],\n * (value) => { opacity = value; },\n * numberHelperFunctions,\n * 1000 // 1 second duration\n * );\n *\n * fadeIn.start();\n *\n * // In animation loop\n * function loop(deltaTime: number) {\n * fadeIn.animate(deltaTime);\n * element.style.opacity = opacity;\n * }\n * ```\n *\n * @category Core\n */\nexport class Animation<T> implements Animator {\n private localTime: number; // local time starting from 0 up til duration\n private _duration: number;\n private keyframes: Keyframe<T>[];\n private animatableAttributeHelper: AnimatableAttributeHelper<T>;\n private applyAnimationValue: (value: T) => void;\n private easeFn: (percentage: number) => number;\n private onGoing: boolean;\n private currentKeyframeIndex: number;\n private loop: boolean;\n private playedTime: number;\n private setUpFn: Function;\n private tearDownFn: Function;\n private parent: AnimatorContainer | undefined;\n private delayTime: number = 0;\n private dragTime: number = 0;\n\n private reverse: boolean = false;\n private endCallbacks: Function[] = [];\n private startCallbacks: Function[] = [];\n private startAfterDelayCallbacks: Function[] = [];\n\n private zeroPercentageValue: T;\n private _maxLoopCount: number | undefined;\n private _fillMode: 'none' | 'forwards' | 'backwards' | 'both' = 'none';\n\n constructor(\n keyFrames: Keyframe<T>[],\n applyAnimationValue: (value: T) => void,\n animatableAttributeHelper: AnimatableAttributeHelper<T>,\n duration: number = 1000,\n loop: boolean = false,\n parent: AnimatorContainer | undefined = undefined,\n setUpFn: Function = () => {},\n tearDownFn: Function = () => {},\n easeFn: (percentage: number) => number = linear\n ) {\n this._duration = duration;\n this.keyframes = keyFrames;\n this.animatableAttributeHelper = animatableAttributeHelper;\n this.applyAnimationValue = applyAnimationValue;\n this.easeFn = easeFn;\n this.onGoing = false;\n this.localTime = duration + 0.1;\n this.currentKeyframeIndex = 0;\n this.loop = loop;\n this.setUpFn = setUpFn;\n this.tearDownFn = tearDownFn;\n this.parent = parent;\n this.playedTime = 0;\n this.zeroPercentageValue = this.findValue(\n 0,\n keyFrames,\n animatableAttributeHelper\n );\n }\n\n toggleReverse(reverse: boolean): void {\n this.reverse = reverse;\n }\n\n start(): void {\n this.localTime = 0;\n this.currentKeyframeIndex = 0;\n this.onGoing = true;\n // this.applyAnimationValue(this.zeroPercentageValue);\n this.setUp();\n }\n\n stop(): void {\n this.onGoing = false;\n this.localTime = this._duration + this.dragTime + this.delayTime + 0.1;\n this.playedTime = 0;\n this.tearDown();\n }\n\n pause(): void {\n this.onGoing = false;\n }\n\n resume() {\n this.onGoing = true;\n }\n\n get playing(): boolean {\n return this.onGoing;\n }\n\n animate(deltaTime: number) {\n if (this.onGoing != true || this.localTime < 0) {\n return;\n }\n if (deltaTime == 0) {\n return;\n }\n this.localTime += deltaTime;\n // console.log(\"--------------------\");\n // console.log(\"local time\", this.localTime);\n // console.log(\"delta time\", deltaTime);\n if (this.localTime - deltaTime <= 0 && deltaTime > 0) {\n // console.log(\"--------------------\");\n // console.log(\"current localtime\", this.localTime);\n // console.log(\"current delta time\", deltaTime);\n // console.log(\"previous local time\", this.localTime - deltaTime);\n // console.log(\"animation start\");\n // console.log(`the animation has been played ${this.playedTime} times`);\n // console.log(`the animation is now playing for the ${this.playedTime + 1} time`);\n this.startCallbacks.forEach(callback => {\n queueMicrotask(() => {\n callback();\n });\n });\n }\n if (\n this.localTime >= this.delayTime &&\n (this.localTime <=\n this.delayTime + this._duration + this.dragTime ||\n this.localTime - deltaTime <=\n this.delayTime + this._duration + this.dragTime)\n ) {\n // console.log(\"local time\", this.localTime);\n // console.log(\"duration\", this.duration);\n // console.log(\"local time would trigger end\", this.localTime >= this._duration + this.delayTime + this.dragTime);\n // console.log(\"delta time\", deltaTime);\n if (\n this.localTime - deltaTime <= this.delayTime &&\n this.delayTime !== 0 &&\n deltaTime > 0\n ) {\n this.startAfterDelayCallbacks.forEach(callback => {\n queueMicrotask(() => {\n callback();\n });\n });\n this.applyAnimationValue(this.zeroPercentageValue);\n }\n let localTimePercentage =\n (this.localTime - this.delayTime) / this._duration;\n let targetPercentage = this.easeFn(localTimePercentage);\n if (localTimePercentage > 1) {\n targetPercentage = this.easeFn(1);\n }\n let value: T;\n // console.log(\"currentKeyframeIndex\", this.currentKeyframeIndex, \"length\", this.keyFrames.length);\n if (\n this.currentKeyframeIndex < this.keyframes.length &&\n this.currentKeyframeIndex >= 0 &&\n (this.reverse\n ? 1 -\n this.keyframes[this.currentKeyframeIndex]\n .percentage ==\n targetPercentage\n : this.keyframes[this.currentKeyframeIndex].percentage ==\n targetPercentage)\n ) {\n value = this.keyframes[this.currentKeyframeIndex].value;\n } else {\n value = this.findValue(\n targetPercentage,\n this.keyframes,\n this.animatableAttributeHelper\n );\n }\n if (this.reverse) {\n while (\n this.currentKeyframeIndex >= 0 &&\n 1 - this.keyframes[this.currentKeyframeIndex].percentage <=\n targetPercentage\n ) {\n this.currentKeyframeIndex -= 1;\n }\n } else {\n while (\n this.currentKeyframeIndex < this.keyframes.length &&\n this.keyframes[this.currentKeyframeIndex].percentage <=\n targetPercentage\n ) {\n this.currentKeyframeIndex += 1;\n }\n }\n this.applyAnimationValue(value);\n if (\n this.localTime >=\n this._duration + this.dragTime + this.delayTime\n ) {\n // console.log(\"animation should end\");\n this.playedTime += 1;\n this.endCallbacks.forEach(callback => {\n queueMicrotask(() => {\n callback();\n });\n });\n if (\n !this.loops ||\n (this._maxLoopCount != undefined &&\n this.playedTime >= (this.maxLoopCount ?? 0))\n ) {\n // this.onGoing = false;\n // console.log(\"animation should stop after \", this.playedTime, \" loops\");\n this.stop();\n } else {\n // console.log(\"animation should restart\");\n this.onGoing = true;\n this.localTime = 0;\n this.currentKeyframeIndex = 0;\n this.start();\n }\n }\n // if((this.localTime >= this._duration + this.delayTime + this.dragTime) && this.loop){\n // // this.startAnimation();\n // this.localTime = 0;\n // this.onGoing = true;\n // this.currentKeyframeIndex = 0;\n // }\n }\n }\n\n findValue(\n valuePercentage: number,\n keyframes: Keyframe<T>[],\n animatableAttributeHelper: AnimatableAttributeHelper<T>\n ): T {\n if (valuePercentage > 1) {\n if (this.reverse) {\n return animatableAttributeHelper.lerp(\n valuePercentage,\n keyframes[1],\n keyframes[0]\n );\n }\n return animatableAttributeHelper.lerp(\n valuePercentage,\n keyframes[keyframes.length - 2],\n keyframes[keyframes.length - 1]\n );\n }\n if (valuePercentage < 0) {\n if (this.reverse) {\n return animatableAttributeHelper.lerp(\n valuePercentage,\n keyframes[keyframes.length - 2],\n keyframes[keyframes.length - 1]\n );\n }\n return animatableAttributeHelper.lerp(\n valuePercentage,\n keyframes[1],\n keyframes[0]\n );\n }\n let left = 0;\n let right = keyframes.length - 1;\n while (left <= right) {\n let mid = left + Math.floor((right - left) / 2);\n const midPercentage = this.reverse\n ? 1 - keyframes[mid].percentage\n : keyframes[mid].percentage;\n if (midPercentage == valuePercentage) {\n return keyframes[mid].value;\n } else if (midPercentage < valuePercentage) {\n if (this.reverse) {\n right = mid - 1;\n } else {\n left = mid + 1;\n }\n } else {\n if (this.reverse) {\n left = mid + 1;\n } else {\n right = mid - 1;\n }\n }\n }\n if (left > keyframes.length - 1) {\n // excceding the keyframes\n left = keyframes.length - 1;\n }\n const interpolateStartFrame = this.reverse\n ? {\n percentage: 1 - keyframes[left].percentage,\n value: keyframes[left].value,\n }\n : keyframes[left - 1];\n const interplateEndFrame = this.reverse\n ? {\n percentage: 1 - keyframes[left - 1].percentage,\n value: keyframes[left - 1].value,\n }\n : keyframes[left];\n // return animatableAttributeHelper.lerp(valuePercentage, keyframes[left - 1], keyframes[left]);\n return animatableAttributeHelper.lerp(\n valuePercentage,\n interpolateStartFrame,\n interplateEndFrame\n );\n }\n\n setUp(): void {\n // this.applyAnimationValue(this.keyframes[0].value);\n this.setUpFn();\n }\n\n tearDown(): void {\n this.tearDownFn();\n }\n\n get loops(): boolean {\n return this.loop;\n }\n\n set loops(loop: boolean) {\n this.loop = loop;\n }\n\n get duration(): number {\n return this._duration + this.delayTime + this.dragTime;\n }\n\n set duration(duration: number) {\n if (duration < 0) {\n return;\n }\n const originalDuration =\n this._duration + this.delayTime + this.dragTime;\n const scale = duration / originalDuration;\n const newDelayTime = this.delayTime * scale;\n const newDragTime = this.dragTime * scale;\n this.delayTime = newDelayTime;\n this.dragTime = newDragTime;\n this._duration = this._duration * scale;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n nonCascadingDuration(newDuration: number): void {\n if (newDuration < 0) {\n return;\n }\n const originalDuration =\n this._duration + this.delayTime + this.dragTime;\n const scale = newDuration / originalDuration;\n const newDelayTime = this.delayTime * scale;\n const newDragTime = this.dragTime * scale;\n this.delayTime = newDelayTime;\n this.dragTime = newDragTime;\n this._duration = newDuration;\n }\n\n resetAnimationState(): void {\n this.onGoing = false;\n this.applyAnimationValue(this.keyframes[0].value);\n this.currentKeyframeIndex = 0;\n this.setUp();\n }\n\n wrapUp(): void {\n this.onGoing = false;\n this.localTime = this._duration + this.dragTime + this.delayTime + 0.1;\n this.currentKeyframeIndex = 0;\n }\n\n get delay(): number {\n return this.delayTime;\n }\n\n set delay(delayTime: number) {\n this.delayTime = delayTime;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n get drag(): number {\n return this.dragTime;\n }\n\n set drag(dragTime: number) {\n this.dragTime = dragTime;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n get trueDuration(): number {\n return this._duration;\n }\n\n set trueDuration(duration: number) {\n this._duration = duration;\n if (this.parent != undefined) {\n this.parent.updateDuration();\n }\n }\n\n setParent(parent: AnimatorContainer) {\n this.parent = parent;\n }\n\n detachParent(): void {\n this.parent = undefined;\n }\n\n set keyFrames(keyFrames: Keyframe<T>[]) {\n this.keyframes = keyFrames;\n this.zeroPercentageValue = this.findValue(\n 0,\n keyFrames,\n this.animatableAttributeHelper\n );\n }\n\n get keyFrames(): Keyframe<T>[] {\n return this.keyframes;\n }\n\n get easeFunction(): (percentage: number) => number {\n return this.easeFn;\n }\n\n set easeFunction(easeFn: (percentage: number) => number) {\n this.easeFn = easeFn;\n }\n\n onEnd(callback: Function): UnSubscribe {\n this.endCallbacks.push(callback);\n return () => {\n this.endCallbacks = this.endCallbacks.filter(cb => cb != callback);\n };\n }\n\n onStart(callback: Function): UnSubscribe {\n this.startCallbacks.push(callback);\n return () => {\n this.startCallbacks = this.startCallbacks.filter(\n cb => cb != callback\n );\n };\n }\n\n onStartAfterDelay(callback: Function): UnSubscribe {\n this.startAfterDelayCallbacks.push(callback);\n return () => {\n this.startAfterDelayCallbacks =\n this.startAfterDelayCallbacks.filter(cb => cb != callback);\n };\n }\n\n clearOnEnd(): void {\n this.endCallbacks = [];\n }\n\n clearOnStart(): void {\n this.startCallbacks = [];\n }\n\n get maxLoopCount(): number | undefined {\n return this._maxLoopCount;\n }\n\n set maxLoopCount(maxLoopCount: number | undefined) {\n this._maxLoopCount = maxLoopCount;\n }\n}\n\nexport interface Keyframes<T> {\n keyframes: Keyframe<T>[];\n from(value: T): Keyframes<T>;\n to(value: T): Keyframes<T>;\n insertAt(percentage: number, value: T): void;\n clearFrames(): void;\n}\n\nexport class KeyFramesContiner<T> {\n private _keyframes: Keyframe<T>[];\n\n constructor() {\n this._keyframes = [];\n }\n\n get keyframes(): Keyframe<T>[] {\n return this._keyframes;\n }\n\n from(value: T): Keyframes<T> {\n if (this._keyframes.length == 0) {\n this._keyframes.push({ percentage: 0, value: value });\n } else {\n if (this._keyframes[0].percentage == 0) {\n this._keyframes[0].value = value;\n } else {\n this._keyframes.unshift({ percentage: 0, value: value });\n }\n }\n return this;\n }\n\n to(value: T): Keyframes<T> {\n if (this._keyframes.length == 0) {\n this._keyframes.push({ percentage: 1, value: value });\n } else {\n if (this._keyframes[this._keyframes.length - 1].percentage == 1) {\n this._keyframes[this._keyframes.length - 1].value = value;\n } else {\n this._keyframes.push({ percentage: 1, value: value });\n }\n }\n return this;\n }\n\n insertAt(percentage: number, value: T): void {\n this._keyframes.push({ percentage: percentage, value: value });\n }\n\n clearFrames(): void {\n this._keyframes = [];\n }\n}\n"
10
10
  ],
11
- "mappings": "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",
11
+ "mappings": "AAAA,mBAAgB,qBA+ET,IAAM,EAAyD,CAClE,KAAM,CACF,EACA,EACA,IACQ,CACR,IAAM,GACD,EAAQ,EAAM,aAAe,EAAI,WAAa,EAAM,YACrD,EAAc,EAClB,GAAI,EAAM,SACN,EAAc,EAAM,SAAS,CAAc,EAS/C,OAPY,EAAS,UACjB,EAAM,MACN,EAAS,uBACL,EAAS,UAAU,EAAI,MAAO,EAAM,KAAK,EACzC,CACJ,CACJ,EAGR,EAEO,MAAM,CAAiE,CAC1E,WAAW,EAAG,EAEd,IAAI,CAAC,EAAe,EAAwB,EAA6B,CACrE,IAAM,GACD,EAAQ,EAAM,aAAe,EAAI,WAAa,EAAM,YACrD,EAAc,EAClB,GAAI,EAAM,SACN,EAAc,EAAM,SAAS,CAAc,EAS/C,OAPY,EAAS,UACjB,EAAM,MACN,EAAS,uBACL,EAAS,UAAU,EAAI,MAAO,EAAM,KAAK,EACzC,CACJ,CACJ,EAGR,CAUO,IAAM,EAA2D,CACpE,KAAM,CACF,EACA,EACA,IACS,CACT,IAAM,GACD,EAAQ,EAAM,aAAe,EAAI,WAAa,EAAM,YACrD,EAAc,EAClB,GAAI,EAAM,SACN,EAAc,EAAM,SAAS,CAAc,EAG/C,OADY,EAAM,MAAQ,GAAe,EAAI,MAAQ,EAAM,OAGnE,EAEO,MAAM,CAAmE,CAC5E,WAAW,EAAG,EAEd,IAAI,CACA,EACA,EACA,EACM,CACN,IAAM,GACD,EAAQ,EAAM,aAAe,EAAI,WAAa,EAAM,YACrD,EAAc,EAClB,GAAI,EAAM,SACN,EAAc,EAAM,SAAS,CAAc,EAG/C,OADY,EAAM,MAAQ,GAAe,EAAI,MAAQ,EAAM,OAGnE,CAWO,IAAM,EAA2D,CACpE,KAAM,CACF,EACA,EACA,IACS,CACT,IAAM,GACD,EAAQ,EAAM,aAAe,EAAI,WAAa,EAAM,YAIzD,OAAO,EAAkB,GAAK,EAAkB,IAC1C,EAAM,MACN,EAAI,MAElB,EAEO,MAAM,CAAmE,CAC5E,WAAW,EAAG,EAEd,IAAI,CACA,EACA,EACA,EACM,CACN,IAAM,GACD,EAAQ,EAAM,aAAe,EAAI,WAAa,EAAM,YAIzD,OAAO,EAAkB,GAAK,EAAkB,IAC1C,EAAM,MACN,EAAI,MAElB,CAWO,IAAM,EAA4D,CACrE,KAAM,CACF,EACA,EACA,IACS,CACT,IAAM,GACD,EAAQ,EAAM,aAAe,EAAI,WAAa,EAAM,YAIzD,OAAO,EAAkB,GAAK,EAAkB,IAC1C,EAAM,MACN,EAAI,MAElB,EAEO,MAAM,CAAoE,CAC7E,WAAW,EAAG,EAEd,IAAI,CACA,EACA,EACA,EACM,CACN,IAAM,GACD,EAAQ,EAAM,aAAe,EAAI,WAAa,EAAM,YAIzD,OAAO,EAAkB,GAAK,EAAkB,IAC1C,EAAM,MACN,EAAI,MAElB,CAoBO,IAAM,EAAqD,CAC9D,KAAM,CAAC,EAAe,EAAsB,IAA4B,CAkBpE,MAjBY,CACR,EACI,EAAM,MAAM,GACV,EAAQ,EAAM,aACX,EAAI,WAAa,EAAM,aACvB,EAAI,MAAM,EAAI,EAAM,MAAM,GACnC,EACI,EAAM,MAAM,GACV,EAAQ,EAAM,aACX,EAAI,WAAa,EAAM,aACvB,EAAI,MAAM,EAAI,EAAM,MAAM,GACnC,EACI,EAAM,MAAM,GACV,EAAQ,EAAM,aACX,EAAI,WAAa,EAAM,aACvB,EAAI,MAAM,EAAI,EAAM,MAAM,EACvC,EAGR,EAEO,MAAM,CAA6D,CACtE,WAAW,EAAG,EAEd,IAAI,CAAC,EAAe,EAAsB,EAAyB,CAkB/D,MAjBY,CACR,EACI,EAAM,MAAM,GACV,EAAQ,EAAM,aACX,EAAI,WAAa,EAAM,aACvB,EAAI,MAAM,EAAI,EAAM,MAAM,GACnC,EACI,EAAM,MAAM,GACV,EAAQ,EAAM,aACX,EAAI,WAAa,EAAM,aACvB,EAAI,MAAM,EAAI,EAAM,MAAM,GACnC,EACI,EAAM,MAAM,GACV,EAAQ,EAAM,aACX,EAAI,WAAa,EAAM,aACvB,EAAI,MAAM,EAAI,EAAM,MAAM,EACvC,EAGR,CCvTO,IAAM,EAAS,CAAC,IAAuB,CAC1C,OAAO,GAqGJ,MAAM,CAA0D,CAC3D,WACA,UACA,UACA,QACA,KACA,WACA,QACA,WACA,UACA,WACA,OACA,cAEA,aAA2B,CAAC,EAC5B,eAA6B,CAAC,EAE9B,QAER,WAAW,CACP,EAGI,IAAI,IACR,EAAgB,GAChB,EAAwC,OACxC,EAAoB,IAAM,GAC1B,EAAuB,IAAM,GAC/B,CACE,KAAK,WAAa,EAClB,KAAK,UAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,UAAY,GACjB,KAAK,QAAU,GACf,KAAK,KAAO,EACZ,KAAK,QAAU,EACf,KAAK,WAAa,EAClB,KAAK,WAAa,EAClB,KAAK,UAAY,EACjB,KAAK,OAAS,EACd,KAAK,WAAW,QAAQ,KAAa,CACjC,EAAU,SAAS,UAAU,IAAI,EACpC,EACD,KAAK,QAAU,GACf,KAAK,WAAa,EAGtB,aAAa,CAAC,EAAkB,CAC5B,GAAI,KAAK,SAAW,EAChB,OAEJ,KAAK,QAAU,EACf,KAAK,WAAW,QAAQ,KAAa,CACjC,EAAU,SAAS,cAAc,CAAO,EAC3C,EAGL,SAAS,CAAC,EAA2B,CACjC,KAAK,OAAS,EAGlB,YAAY,EAAG,CACX,KAAK,OAAS,OAGlB,OAAO,CAAC,EAAyB,CAC7B,GACI,CAAC,KAAK,SACN,KAAK,UACD,KAAK,UAAY,KAAK,WAAa,KAAK,WAC5C,KAAK,UAAY,GACjB,KAAK,WAAW,MAAQ,EAExB,OAGJ,GADA,KAAK,WAAa,EACd,KAAK,UAAY,GAAa,GAAK,EAAY,EAE/C,KAAK,eAAe,QAAQ,KAAY,CACpC,eAAe,IAAM,CACjB,EAAS,EACZ,EACJ,EAEL,KAAK,gBAAgB,CAAS,EAC9B,KAAK,qBAAqB,EAG9B,oBAAoB,EAAG,CACnB,GACI,KAAK,WACL,KAAK,UAAY,KAAK,WAAa,KAAK,UASxC,GANA,KAAK,YAAc,EACnB,KAAK,aAAa,QAAQ,KAAY,CAClC,eAAe,IAAM,CACjB,EAAS,EACZ,EACJ,EAEG,CAAC,KAAK,OACL,KAAK,cAAgB,MAClB,KAAK,YAAc,KAAK,aAG5B,KAAK,KAAK,EAUV,UAAK,MAAM,EAKvB,eAAe,CAAC,EAAmB,CAC/B,IAAM,EAAgB,KAAK,UAAY,EACvC,GAAI,KAAK,UAAY,KAAK,WACtB,OAEJ,KAAK,WAAW,QAAQ,CAAC,EAAW,IAAiB,CACjD,GAAI,EAAU,WAAa,KACvB,EAAU,UAAY,EAE1B,GAAI,CAAC,KAAK,mBAAmB,EAAW,CAAa,EAAG,CACpD,KAAK,eACD,CACI,SAAU,EAAU,SACpB,UAAW,EAAU,UACrB,KAAM,CACV,EACA,CACJ,EACA,OAEJ,GAAI,EAAgB,KAAK,WAAa,EAAU,UAC5C,EAAU,SAAS,QACf,KAAK,UAAY,KAAK,WAAa,EAAU,SACjD,EAEA,OAAU,SAAS,QAAQ,CAAS,EAE3C,EAGL,kBAAkB,CACd,EACA,EACO,CACP,GAAI,EAAU,WAAa,KACvB,EAAU,UAAY,EAE1B,GACI,KAAK,UAAY,KAAK,YAAc,EAAU,WAC9C,KAAK,UAAY,KAAK,YAClB,EAAU,UAAY,EAAU,SAAS,SAE7C,MAAO,GAEX,MAAO,GAGX,cAAc,CACV,EACA,EACF,CACE,GAAI,EAAU,WAAa,KACvB,EAAU,UAAY,EAE1B,GACI,KAAK,UAAY,KAAK,WAClB,EAAU,UAAY,EAAU,SAAS,UAC7C,EAAgB,KAAK,WACjB,EAAU,UAAY,EAAU,SAAS,SAK7C,EAAU,SAAS,QACf,EAAU,UACN,EAAU,SAAS,UAClB,EAAgB,KAAK,WAC9B,EAIR,KAAK,EAAS,CACV,KAAK,QAAU,GACf,KAAK,WAAW,QAAQ,KAAa,CACjC,EAAU,SAAS,MAAM,EAC5B,EAGL,MAAM,EAAS,CACX,KAAK,QAAU,GACf,KAAK,WAAW,QAAQ,KAAa,CACjC,EAAU,SAAS,OAAO,EAC7B,EAGL,KAAK,EAAS,CACV,KAAK,QAAU,GACf,KAAK,MAAM,EACX,KAAK,UAAY,EACjB,KAAK,WAAW,QAAQ,KAAa,CACjC,EAAU,SAAS,MAAM,EAC5B,EAGL,IAAI,EAAS,CACT,KAAK,QAAU,GACf,KAAK,WAAa,EAClB,KAAK,UAAY,KAAK,UAAY,IAClC,KAAK,WAAW,QAAQ,KAAa,CACjC,EAAU,SAAS,KAAK,EAC3B,EACD,KAAK,SAAS,KAGd,SAAQ,EAAW,CACnB,OAAO,KAAK,UAAY,KAAK,WAAa,KAAK,aAG/C,SAAQ,CAAC,EAAkB,CAC3B,GAAI,EAAW,EACX,OAEJ,IAAM,EACF,KAAK,UAAY,KAAK,WAAa,KAAK,UACtC,EAAQ,EAAW,EACnB,EAAe,KAAK,WAAa,EACjC,EAAc,KAAK,UAAY,EAYrC,GAXA,KAAK,WAAa,EAClB,KAAK,UAAY,EACjB,KAAK,WAAW,QAAQ,KAAa,CACjC,GAAI,EAAU,WAAa,KACvB,EAAU,UAAY,EAE1B,EAAU,WAAa,EACvB,IAAM,EAAc,EAAU,SAAS,SAAW,EAClD,EAAU,SAAS,qBAAqB,CAAW,EACtD,EACD,KAAK,kBAAkB,EACnB,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,EAInC,oBAAoB,CAAC,EAA2B,CAC5C,GAAI,EAAc,EACd,OAEJ,IAAM,EACF,KAAK,UAAY,KAAK,WAAa,KAAK,UACtC,EAAQ,EAAc,EACtB,EAAe,KAAK,WAAa,EACjC,EAAc,KAAK,UAAY,EACrC,KAAK,WAAa,EAClB,KAAK,UAAY,EACjB,KAAK,WAAW,QAAQ,KAAa,CACjC,GAAI,EAAU,WAAa,KACvB,EAAU,UAAY,EAE1B,EAAU,WAAa,EACvB,IAAM,EAAc,EAAU,SAAS,SAAW,EAClD,EAAU,SAAS,qBAAqB,CAAW,EACtD,EACD,KAAK,kBAAkB,EAG3B,mBAAmB,EAAS,CACxB,KAAK,QAAU,GACf,KAAK,WAAW,QAAQ,KAAa,CACjC,EAAU,SAAS,oBAAoB,EAC1C,EAGL,eAAe,EAAW,CACtB,OAAO,KAAK,UAGhB,KAAK,EAAS,CACV,KAAK,QAAQ,EACb,KAAK,WAAW,QAAQ,KAAa,CACjC,EAAU,SAAS,MAAM,EAC5B,EAGL,QAAQ,EAAS,CACb,KAAK,WAAW,EAChB,KAAK,WAAW,QAAQ,KAAa,CACjC,EAAU,SAAS,SAAS,EAC/B,EAGL,YAAY,CACR,EACA,EACA,EAAoB,EACpB,EAAwB,IAAM,GAChC,CACE,GAAI,KAAK,WAAW,IAAI,CAAI,EACxB,OAEJ,GACI,KAAK,SAAW,QAChB,KAAK,OAAO,kBAAkB,CAAS,EAEvC,OAOJ,GALA,KAAK,WAAW,IAAI,EAAM,CACtB,SAAU,EACV,UAAW,CACf,CAAC,EACD,EAAU,UAAU,IAAI,EACpB,KAAK,UAAY,EACjB,EAAU,QAAQ,KAAK,UAAY,CAAS,EAEhD,IAAM,EAAU,EAAY,EAAU,SAEtC,GADA,KAAK,UAAY,KAAK,IAAI,KAAK,UAAW,CAAO,EAC7C,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,EAInC,iBAAiB,CACb,EACA,EACA,EACA,EAAgB,EAClB,CACE,IAAI,EAAiB,KAAK,WAAW,IAAI,CAAS,EAClD,GAAI,GAAkB,KAClB,OAEJ,GAAI,EAAe,WAAa,KAC5B,EAAe,UAAY,EAE/B,IAAI,EACA,EAAe,UAAY,EAAe,SAAS,SAIvD,GAHA,GAAa,EACb,KAAK,aAAa,EAAM,EAAW,CAAS,EAC5C,KAAK,kBAAkB,EACnB,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,EAInC,kBAAkB,CACd,EACA,EACA,EACA,EACF,CACE,IAAI,EAAkB,KAAK,WAAW,IAAI,CAAU,EACpD,GAAI,GAAmB,KACnB,OAEJ,GAAI,EAAgB,WAAa,KAC7B,EAAgB,UAAY,EAEhC,IAAI,EAAY,EAAgB,UAAY,EAG5C,GAFA,KAAK,aAAa,EAAM,EAAW,CAAS,EAC5C,KAAK,kBAAkB,EACnB,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,EAInC,kBAAkB,CACd,EACA,EACA,EACA,EAAoB,EACtB,CACE,IAAI,EAAkB,KAAK,WAAW,IAAI,CAAU,EACpD,GAAI,GAAmB,KACnB,OAEJ,GAAI,EAAgB,WAAa,KAC7B,EAAgB,UAAY,EAEhC,IAAI,EAAY,EAAgB,UAGhC,GAFA,GAAa,EACb,KAAK,aAAa,EAAM,EAAW,CAAS,EACxC,EAAY,EAAG,CACf,IAAM,EAAW,EAAI,EACrB,KAAK,WAAW,QAAQ,KAAa,CACjC,GAAI,EAAU,WAAa,KACvB,EAAU,UAAY,EAE1B,EAAU,WAAa,EAC1B,EAGL,GADA,KAAK,kBAAkB,EACnB,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,EAInC,eAAe,CAAC,EAAc,CAC1B,IAAI,EAAY,KAAK,WAAW,IAAI,CAAI,EAExC,GADc,KAAK,WAAW,OAAO,CAAI,EAC5B,CACT,GAAI,GAAa,KACb,EAAU,SAAS,aAAa,EAGpC,GADA,KAAK,kBAAkB,EACnB,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,MAKnC,MAAK,CAAC,EAAmB,CAEzB,GADA,KAAK,WAAa,EACd,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,KAI/B,MAAK,EAAW,CAChB,OAAO,KAAK,cAGZ,KAAI,CAAC,EAAkB,CAEvB,GADA,KAAK,UAAY,EACb,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,KAI/B,KAAI,EAAW,CACf,OAAO,KAAK,UAGhB,WAAW,EAAG,CAEV,GADA,KAAK,WAAa,EACd,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,EAInC,UAAU,EAAG,CAET,GADA,KAAK,UAAY,EACb,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,EAInC,cAAc,EAAS,CACnB,GAAI,KAAK,oBAAoB,EACzB,OAGJ,GADA,KAAK,kBAAkB,EACnB,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,EAInC,iBAAiB,EAAG,CAChB,KAAK,UAAY,EACjB,KAAK,WAAW,QAAQ,KAAa,CACjC,GAAI,EAAU,WAAa,KACvB,EAAU,UAAY,EAE1B,IAAM,EAAU,EAAU,UAAY,EAAU,SAAS,SACzD,KAAK,UAAY,KAAK,IAAI,KAAK,UAAW,CAAO,EACpD,KAGD,MAAK,EAAY,CACjB,OAAO,KAAK,QAGZ,MAAK,CAAC,EAAe,CACrB,KAAK,KAAO,EAGhB,mBAAmB,EAAY,CAC3B,IAAM,EAA0B,CAAC,EACjC,EAAY,KAAK,IAAI,EACrB,IAAM,EAAU,IAAI,IACpB,MAAO,EAAY,OAAS,EAAG,CAC3B,IAAM,EAAU,EAAY,IAAI,EAChC,GAAI,GAAW,KACX,SAEJ,GAAI,EAAQ,IAAI,CAAO,EACnB,MAAO,GAGX,GADA,EAAQ,IAAI,CAAO,EACf,aAAmB,EACnB,EAAQ,WAAW,QAAQ,KAAa,CACpC,EAAY,KAAK,EAAU,QAAQ,EACtC,EAGT,MAAO,GAGX,eAAe,CAAC,EAAe,CAC3B,KAAK,KAAO,GACZ,KAAK,WAAW,QAAQ,KAAa,CACjC,EAAU,SAAS,MAAQ,GAC9B,EAGL,iBAAiB,CAAC,EAAwC,CACtD,GAAI,KAAK,SAAW,OAChB,OAAO,KAAK,OAAO,kBAAkB,CAAmB,EAE5D,IAAM,EAA0B,CAAC,EACjC,EAAY,KAAK,IAAI,EACrB,IAAM,EAAU,IAAI,IACpB,MAAO,EAAY,OAAS,EAAG,CAC3B,IAAM,EAAU,EAAY,IAAI,EAChC,GAAI,GAAW,KACX,SAEJ,GAAI,GAAW,EACX,MAAO,GAEX,GAAI,EAAQ,IAAI,CAAO,EACnB,SAGJ,GADA,EAAQ,IAAI,CAAO,EACf,aAAmB,EACnB,EAAQ,WAAW,QAAQ,KAAa,CACpC,EAAY,KAAK,EAAU,QAAQ,EACtC,EAGT,MAAO,GAGX,KAAK,CAAC,EAAiC,CAEnC,OADA,KAAK,aAAa,KAAK,CAAQ,EACxB,IAAM,CACT,KAAK,aAAe,KAAK,aAAa,OAAO,KAAM,GAAM,CAAQ,GAIzE,OAAO,CAAC,EAAiC,CAErC,OADA,KAAK,eAAe,KAAK,CAAQ,EAC1B,IAAM,CACT,KAAK,eAAiB,KAAK,eAAe,OACtC,KAAM,GAAM,CAChB,GAIR,UAAU,EAAS,CACf,KAAK,aAAe,CAAC,EAGzB,YAAY,EAAS,CACjB,KAAK,eAAiB,CAAC,KAGvB,QAAO,EAAY,CACnB,OAAO,KAAK,WAGZ,aAAY,EAAuB,CACnC,OAAO,KAAK,iBAGZ,aAAY,CAAC,EAAkC,CAC/C,KAAK,cAAgB,EAE7B,CAkDO,MAAM,CAAiC,CAClC,UACA,UACA,UACA,0BACA,oBACA,OACA,QACA,qBACA,KACA,WACA,QACA,WACA,OACA,UAAoB,EACpB,SAAmB,EAEnB,QAAmB,GACnB,aAA2B,CAAC,EAC5B,eAA6B,CAAC,EAC9B,yBAAuC,CAAC,EAExC,oBACA,cACA,UAAwD,OAEhE,WAAW,CACP,EACA,EACA,EACA,EAAmB,KACnB,EAAgB,GAChB,EAAwC,OACxC,EAAoB,IAAM,GAC1B,EAAuB,IAAM,GAC7B,EAAyC,EAC3C,CACE,KAAK,UAAY,EACjB,KAAK,UAAY,EACjB,KAAK,0BAA4B,EACjC,KAAK,oBAAsB,EAC3B,KAAK,OAAS,EACd,KAAK,QAAU,GACf,KAAK,UAAY,EAAW,IAC5B,KAAK,qBAAuB,EAC5B,KAAK,KAAO,EACZ,KAAK,QAAU,EACf,KAAK,WAAa,EAClB,KAAK,OAAS,EACd,KAAK,WAAa,EAClB,KAAK,oBAAsB,KAAK,UAC5B,EACA,EACA,CACJ,EAGJ,aAAa,CAAC,EAAwB,CAClC,KAAK,QAAU,EAGnB,KAAK,EAAS,CACV,KAAK,UAAY,EACjB,KAAK,qBAAuB,EAC5B,KAAK,QAAU,GAEf,KAAK,MAAM,EAGf,IAAI,EAAS,CACT,KAAK,QAAU,GACf,KAAK,UAAY,KAAK,UAAY,KAAK,SAAW,KAAK,UAAY,IACnE,KAAK,WAAa,EAClB,KAAK,SAAS,EAGlB,KAAK,EAAS,CACV,KAAK,QAAU,GAGnB,MAAM,EAAG,CACL,KAAK,QAAU,MAGf,QAAO,EAAY,CACnB,OAAO,KAAK,QAGhB,OAAO,CAAC,EAAmB,CACvB,GAAI,KAAK,SAAW,IAAQ,KAAK,UAAY,EACzC,OAEJ,GAAI,GAAa,EACb,OAMJ,GAJA,KAAK,WAAa,EAId,KAAK,UAAY,GAAa,GAAK,EAAY,EAQ/C,KAAK,eAAe,QAAQ,KAAY,CACpC,eAAe,IAAM,CACjB,EAAS,EACZ,EACJ,EAEL,GACI,KAAK,WAAa,KAAK,YACtB,KAAK,WACF,KAAK,UAAY,KAAK,UAAY,KAAK,UACvC,KAAK,UAAY,GACb,KAAK,UAAY,KAAK,UAAY,KAAK,UACjD,CAKE,GACI,KAAK,UAAY,GAAa,KAAK,WACnC,KAAK,YAAc,GACnB,EAAY,EAEZ,KAAK,yBAAyB,QAAQ,KAAY,CAC9C,eAAe,IAAM,CACjB,EAAS,EACZ,EACJ,EACD,KAAK,oBAAoB,KAAK,mBAAmB,EAErD,IAAI,GACC,KAAK,UAAY,KAAK,WAAa,KAAK,UACzC,EAAmB,KAAK,OAAO,CAAmB,EACtD,GAAI,EAAsB,EACtB,EAAmB,KAAK,OAAO,CAAC,EAEpC,IAAI,EAEJ,GACI,KAAK,qBAAuB,KAAK,UAAU,QAC3C,KAAK,sBAAwB,IAC5B,KAAK,QACA,EACI,KAAK,UAAU,KAAK,sBACf,YACT,EACA,KAAK,UAAU,KAAK,sBAAsB,YAC1C,GAEN,EAAQ,KAAK,UAAU,KAAK,sBAAsB,MAElD,OAAQ,KAAK,UACT,EACA,KAAK,UACL,KAAK,yBACT,EAEJ,GAAI,KAAK,QACL,MACI,KAAK,sBAAwB,GAC7B,EAAI,KAAK,UAAU,KAAK,sBAAsB,YAC1C,EAEJ,KAAK,sBAAwB,EAGjC,WACI,KAAK,qBAAuB,KAAK,UAAU,QAC3C,KAAK,UAAU,KAAK,sBAAsB,YACtC,EAEJ,KAAK,sBAAwB,EAIrC,GADA,KAAK,oBAAoB,CAAK,EAE1B,KAAK,WACL,KAAK,UAAY,KAAK,SAAW,KAAK,UAStC,GANA,KAAK,YAAc,EACnB,KAAK,aAAa,QAAQ,KAAY,CAClC,eAAe,IAAM,CACjB,EAAS,EACZ,EACJ,EAEG,CAAC,KAAK,OACL,KAAK,eAAiB,MACnB,KAAK,aAAe,KAAK,cAAgB,GAI7C,KAAK,KAAK,EAGV,UAAK,QAAU,GACf,KAAK,UAAY,EACjB,KAAK,qBAAuB,EAC5B,KAAK,MAAM,GAY3B,SAAS,CACL,EACA,EACA,EACC,CACD,GAAI,EAAkB,EAAG,CACrB,GAAI,KAAK,QACL,OAAO,EAA0B,KAC7B,EACA,EAAU,GACV,EAAU,EACd,EAEJ,OAAO,EAA0B,KAC7B,EACA,EAAU,EAAU,OAAS,GAC7B,EAAU,EAAU,OAAS,EACjC,EAEJ,GAAI,EAAkB,EAAG,CACrB,GAAI,KAAK,QACL,OAAO,EAA0B,KAC7B,EACA,EAAU,EAAU,OAAS,GAC7B,EAAU,EAAU,OAAS,EACjC,EAEJ,OAAO,EAA0B,KAC7B,EACA,EAAU,GACV,EAAU,EACd,EAEJ,IAAI,EAAO,EACP,EAAQ,EAAU,OAAS,EAC/B,MAAO,GAAQ,EAAO,CAClB,IAAI,EAAM,EAAO,KAAK,OAAO,EAAQ,GAAQ,CAAC,EACxC,EAAgB,KAAK,QACrB,EAAI,EAAU,GAAK,WACnB,EAAU,GAAK,WACrB,GAAI,GAAiB,EACjB,OAAO,EAAU,GAAK,MACnB,QAAI,EAAgB,EACvB,GAAI,KAAK,QACL,EAAQ,EAAM,EAEd,OAAO,EAAM,EAGjB,QAAI,KAAK,QACL,EAAO,EAAM,EAEb,OAAQ,EAAM,EAI1B,GAAI,EAAO,EAAU,OAAS,EAE1B,EAAO,EAAU,OAAS,EAE9B,IAAM,EAAwB,KAAK,QAC7B,CACI,WAAY,EAAI,EAAU,GAAM,WAChC,MAAO,EAAU,GAAM,KAC3B,EACA,EAAU,EAAO,GACjB,EAAqB,KAAK,QAC1B,CACI,WAAY,EAAI,EAAU,EAAO,GAAG,WACpC,MAAO,EAAU,EAAO,GAAG,KAC/B,EACA,EAAU,GAEhB,OAAO,EAA0B,KAC7B,EACA,EACA,CACJ,EAGJ,KAAK,EAAS,CAEV,KAAK,QAAQ,EAGjB,QAAQ,EAAS,CACb,KAAK,WAAW,KAGhB,MAAK,EAAY,CACjB,OAAO,KAAK,QAGZ,MAAK,CAAC,EAAe,CACrB,KAAK,KAAO,KAGZ,SAAQ,EAAW,CACnB,OAAO,KAAK,UAAY,KAAK,UAAY,KAAK,YAG9C,SAAQ,CAAC,EAAkB,CAC3B,GAAI,EAAW,EACX,OAEJ,IAAM,EACF,KAAK,UAAY,KAAK,UAAY,KAAK,SACrC,EAAQ,EAAW,EACnB,EAAe,KAAK,UAAY,EAChC,EAAc,KAAK,SAAW,EAIpC,GAHA,KAAK,UAAY,EACjB,KAAK,SAAW,EAChB,KAAK,UAAY,KAAK,UAAY,EAC9B,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,EAInC,oBAAoB,CAAC,EAA2B,CAC5C,GAAI,EAAc,EACd,OAEJ,IAAM,EACF,KAAK,UAAY,KAAK,UAAY,KAAK,SACrC,EAAQ,EAAc,EACtB,EAAe,KAAK,UAAY,EAChC,EAAc,KAAK,SAAW,EACpC,KAAK,UAAY,EACjB,KAAK,SAAW,EAChB,KAAK,UAAY,EAGrB,mBAAmB,EAAS,CACxB,KAAK,QAAU,GACf,KAAK,oBAAoB,KAAK,UAAU,GAAG,KAAK,EAChD,KAAK,qBAAuB,EAC5B,KAAK,MAAM,EAGf,MAAM,EAAS,CACX,KAAK,QAAU,GACf,KAAK,UAAY,KAAK,UAAY,KAAK,SAAW,KAAK,UAAY,IACnE,KAAK,qBAAuB,KAG5B,MAAK,EAAW,CAChB,OAAO,KAAK,aAGZ,MAAK,CAAC,EAAmB,CAEzB,GADA,KAAK,UAAY,EACb,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,KAI/B,KAAI,EAAW,CACf,OAAO,KAAK,YAGZ,KAAI,CAAC,EAAkB,CAEvB,GADA,KAAK,SAAW,EACZ,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,KAI/B,aAAY,EAAW,CACvB,OAAO,KAAK,aAGZ,aAAY,CAAC,EAAkB,CAE/B,GADA,KAAK,UAAY,EACb,KAAK,QAAU,KACf,KAAK,OAAO,eAAe,EAInC,SAAS,CAAC,EAA2B,CACjC,KAAK,OAAS,EAGlB,YAAY,EAAS,CACjB,KAAK,OAAS,UAGd,UAAS,CAAC,EAA0B,CACpC,KAAK,UAAY,EACjB,KAAK,oBAAsB,KAAK,UAC5B,EACA,EACA,KAAK,yBACT,KAGA,UAAS,EAAkB,CAC3B,OAAO,KAAK,aAGZ,aAAY,EAAmC,CAC/C,OAAO,KAAK,UAGZ,aAAY,CAAC,EAAwC,CACrD,KAAK,OAAS,EAGlB,KAAK,CAAC,EAAiC,CAEnC,OADA,KAAK,aAAa,KAAK,CAAQ,EACxB,IAAM,CACT,KAAK,aAAe,KAAK,aAAa,OAAO,KAAM,GAAM,CAAQ,GAIzE,OAAO,CAAC,EAAiC,CAErC,OADA,KAAK,eAAe,KAAK,CAAQ,EAC1B,IAAM,CACT,KAAK,eAAiB,KAAK,eAAe,OACtC,KAAM,GAAM,CAChB,GAIR,iBAAiB,CAAC,EAAiC,CAE/C,OADA,KAAK,yBAAyB,KAAK,CAAQ,EACpC,IAAM,CACT,KAAK,yBACD,KAAK,yBAAyB,OAAO,KAAM,GAAM,CAAQ,GAIrE,UAAU,EAAS,CACf,KAAK,aAAe,CAAC,EAGzB,YAAY,EAAS,CACjB,KAAK,eAAiB,CAAC,KAGvB,aAAY,EAAuB,CACnC,OAAO,KAAK,iBAGZ,aAAY,CAAC,EAAkC,CAC/C,KAAK,cAAgB,EAE7B,CAUO,MAAM,CAAqB,CACtB,WAER,WAAW,EAAG,CACV,KAAK,WAAa,CAAC,KAGnB,UAAS,EAAkB,CAC3B,OAAO,KAAK,WAGhB,IAAI,CAAC,EAAwB,CACzB,GAAI,KAAK,WAAW,QAAU,EAC1B,KAAK,WAAW,KAAK,CAAE,WAAY,EAAG,MAAO,CAAM,CAAC,EAEpD,QAAI,KAAK,WAAW,GAAG,YAAc,EACjC,KAAK,WAAW,GAAG,MAAQ,EAE3B,UAAK,WAAW,QAAQ,CAAE,WAAY,EAAG,MAAO,CAAM,CAAC,EAG/D,OAAO,KAGX,EAAE,CAAC,EAAwB,CACvB,GAAI,KAAK,WAAW,QAAU,EAC1B,KAAK,WAAW,KAAK,CAAE,WAAY,EAAG,MAAO,CAAM,CAAC,EAEpD,QAAI,KAAK,WAAW,KAAK,WAAW,OAAS,GAAG,YAAc,EAC1D,KAAK,WAAW,KAAK,WAAW,OAAS,GAAG,MAAQ,EAEpD,UAAK,WAAW,KAAK,CAAE,WAAY,EAAG,MAAO,CAAM,CAAC,EAG5D,OAAO,KAGX,QAAQ,CAAC,EAAoB,EAAgB,CACzC,KAAK,WAAW,KAAK,CAAE,WAAY,EAAY,MAAO,CAAM,CAAC,EAGjE,WAAW,EAAS,CAChB,KAAK,WAAa,CAAC,EAE3B",
12
12
  "debugId": "A64492CFE695240C64756E2164756E21",
13
13
  "names": []
14
14
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ue-too/animate",
3
3
  "type": "module",
4
- "version": "0.14.1",
4
+ "version": "0.15.0",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -20,7 +20,7 @@
20
20
  "./package.json": "./package.json"
21
21
  },
22
22
  "dependencies": {
23
- "@ue-too/math": "^0.14.1"
23
+ "@ue-too/math": "^0.15.0"
24
24
  },
25
25
  "main": "./index.js",
26
26
  "types": "./index.d.ts",