animejs 4.1.2 → 4.1.4

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/lib/anime.esm.js CHANGED
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * anime.js - ESM
3
- * @version v4.1.2
3
+ * @version v4.1.4
4
4
  * @author Julian Garnier
5
5
  * @license MIT
6
6
  * @copyright (c) 2025 Julian Garnier
7
7
  * @see https://animejs.com
8
8
  */
9
9
 
10
- // Global types ///////////////////////////////////////////////////////////////
10
+ // Global types ////////////////////////////////////////////////////////////////
11
11
 
12
12
  /**
13
13
  * @typedef {Object} DefaultsParams
@@ -38,17 +38,18 @@
38
38
  /** @typedef {JSAnimation|Timeline} Renderable */
39
39
  /** @typedef {Timer|Renderable} Tickable */
40
40
  /** @typedef {Timer&JSAnimation&Timeline} CallbackArgument */
41
- /** @typedef {Animatable|Tickable|Draggable|ScrollObserver|TextSplitter|Scope} Revertible */
41
+ /** @typedef {Animatable|Tickable|WAAPIAnimation|Draggable|ScrollObserver|TextSplitter|Scope} Revertible */
42
42
 
43
- // Stagger types //////////////////////////////////////////////////////////////
43
+ // Stagger types ///////////////////////////////////////////////////////////////
44
44
 
45
45
  /**
46
+ * @template T
46
47
  * @callback StaggerFunction
47
48
  * @param {Target} [target]
48
49
  * @param {Number} [index]
49
50
  * @param {Number} [length]
50
51
  * @param {Timeline} [tl]
51
- * @return {Number|String}
52
+ * @return {T}
52
53
  */
53
54
 
54
55
  /**
@@ -58,13 +59,13 @@
58
59
  * @property {Boolean} [reversed]
59
60
  * @property {Array.<Number>} [grid]
60
61
  * @property {('x'|'y')} [axis]
61
- * @property {String|StaggerFunction} [use]
62
+ * @property {String|((target: Target, i: Number, length: Number) => Number)} [use]
62
63
  * @property {Number} [total]
63
64
  * @property {EasingParam} [ease]
64
65
  * @property {TweenModifier} [modifier]
65
66
  */
66
67
 
67
- // Eases types ////////////////////////////////////////////////////////////////
68
+ // Eases types /////////////////////////////////////////////////////////////////
68
69
 
69
70
  /**
70
71
  * @callback EasingFunction
@@ -92,7 +93,17 @@
92
93
  /** @typedef {Array.<TargetSelector>|TargetSelector} TargetsParam */
93
94
  /** @typedef {Array.<Target>} TargetsArray */
94
95
 
95
- // Callback types ////////////////////////////////////////////////////////////
96
+ // Spring types ////////////////////////////////////////////////////////////////
97
+
98
+ /**
99
+ * @typedef {Object} SpringParams
100
+ * @property {Number} [mass=1] - Mass, default 1
101
+ * @property {Number} [stiffness=100] - Stiffness, default 100
102
+ * @property {Number} [damping=10] - Damping, default 10
103
+ * @property {Number} [velocity=0] - Initial velocity, default 0
104
+ */
105
+
106
+ // Callback types //////////////////////////////////////////////////////////////
96
107
 
97
108
  /**
98
109
  * @template T
@@ -119,7 +130,7 @@
119
130
  * @property {Callback<T>} [onRender]
120
131
  */
121
132
 
122
- // Timer types ////////////////////////////////////////////////////////////////
133
+ // Timer types /////////////////////////////////////////////////////////////////
123
134
 
124
135
  /**
125
136
  * @typedef {Object} TimerOptions
@@ -141,7 +152,7 @@
141
152
  * @typedef {TimerOptions & TickableCallbacks<Timer>} TimerParams
142
153
  */
143
154
 
144
- // Tween types ////////////////////////////////////////////////////////////////
155
+ // Tween types /////////////////////////////////////////////////////////////////
145
156
 
146
157
  /**
147
158
  * @callback FunctionValue
@@ -212,7 +223,7 @@
212
223
  /** @typedef {WeakMap.<Target, TweenLookups>} TweenReplaceLookups */
213
224
  /** @typedef {Map.<Target, TweenLookups>} TweenAdditiveLookups */
214
225
 
215
- // Animation types ////////////////////////////////////////////////////////////
226
+ // JSAnimation types ///////////////////////////////////////////////////////////
216
227
 
217
228
  /**
218
229
  * @typedef {Number|String|FunctionValue} TweenParamValue
@@ -286,7 +297,36 @@
286
297
  * @typedef {Record<String, TweenOptions | Callback<JSAnimation> | TweenModifier | boolean | PercentageKeyframes | DurationKeyframes | ScrollObserver> & TimerOptions & AnimationOptions & TweenParamsOptions & TickableCallbacks<JSAnimation> & RenderableCallbacks<JSAnimation>} AnimationParams
287
298
  */
288
299
 
289
- // Timeline types /////////////////////////////////////////////////////////////
300
+ // Timeline types //////////////////////////////////////////////////////////////
301
+
302
+ /**
303
+ * Accepts:<br>
304
+ * - `Number` - Absolute position in milliseconds (e.g., `500` places element at exactly 500ms)<br>
305
+ * - `'+=Number'` - Addition: Position element X ms after the last element (e.g., `'+=100'`)<br>
306
+ * - `'-=Number'` - Subtraction: Position element X ms before the last element's end (e.g., `'-=100'`)<br>
307
+ * - `'*=Number'` - Multiplier: Position element at a fraction of the total duration (e.g., `'*=.5'` for halfway)<br>
308
+ * - `'<'` - Previous end: Position element at the end position of the previous element<br>
309
+ * - `'<<'` - Previous start: Position element at the start position of the previous element<br>
310
+ * - `'<<+=Number'` - Combined: Position element relative to previous element's start (e.g., `'<<+=250'`)<br>
311
+ * - `'label'` - Label: Position element at a named label position (e.g., `'My Label'`)
312
+ *
313
+ * @typedef {Number|`+=${Number}`|`-=${Number}`|`*=${Number}`|'<'|'<<'|`<<+=${Number}`|`<<-=${Number}`|String} TimelinePosition
314
+ */
315
+
316
+ /**
317
+ * Accepts:<br>
318
+ * - `Number` - Absolute position in milliseconds (e.g., `500` places animation at exactly 500ms)<br>
319
+ * - `'+=Number'` - Addition: Position animation X ms after the last animation (e.g., `'+=100'`)<br>
320
+ * - `'-=Number'` - Subtraction: Position animation X ms before the last animation's end (e.g., `'-=100'`)<br>
321
+ * - `'*=Number'` - Multiplier: Position animation at a fraction of the total duration (e.g., `'*=.5'` for halfway)<br>
322
+ * - `'<'` - Previous end: Position animation at the end position of the previous animation<br>
323
+ * - `'<<'` - Previous start: Position animation at the start position of the previous animation<br>
324
+ * - `'<<+=Number'` - Combined: Position animation relative to previous animation's start (e.g., `'<<+=250'`)<br>
325
+ * - `'label'` - Label: Position animation at a named label position (e.g., `'My Label'`)<br>
326
+ * - `stagger(String|Nummber)` - Stagger multi-elements animation positions (e.g., 10, 20, 30...)
327
+ *
328
+ * @typedef {TimelinePosition | StaggerFunction<Number|String>} TimelineAnimationPosition
329
+ */
290
330
 
291
331
  /**
292
332
  * @typedef {Object} TimelineOptions
@@ -298,7 +338,57 @@
298
338
  * @typedef {TimerOptions & TimelineOptions & TickableCallbacks<Timeline> & RenderableCallbacks<Timeline>} TimelineParams
299
339
  */
300
340
 
301
- // Animatable types ///////////////////////////////////////////////////////////
341
+ // WAAPIAnimation types ////////////////////////////////////////////////////////
342
+
343
+ /**
344
+ * @typedef {String|Number|Array<String>|Array<Number>} WAAPITweenValue
345
+ */
346
+
347
+ /**
348
+ * @callback WAAPIFunctionValue
349
+ * @param {DOMTarget} target - The animated target
350
+ * @param {Number} index - The target index
351
+ * @param {Number} length - The total number of animated targets
352
+ * @return {WAAPITweenValue}
353
+ */
354
+
355
+ /**
356
+ * @typedef {WAAPITweenValue|WAAPIFunctionValue|Array<String|Number|WAAPIFunctionValue>} WAAPIKeyframeValue
357
+ */
358
+
359
+ /**
360
+ * @typedef {(animation: WAAPIAnimation) => void} WAAPICallback
361
+ */
362
+
363
+ /**
364
+ * @typedef {Object} WAAPITweenOptions
365
+ * @property {WAAPIKeyframeValue} [to]
366
+ * @property {WAAPIKeyframeValue} [from]
367
+ * @property {Number|WAAPIFunctionValue} [duration]
368
+ * @property {Number|WAAPIFunctionValue} [delay]
369
+ * @property {EasingParam} [ease]
370
+ * @property {CompositeOperation} [composition]
371
+ */
372
+
373
+ /**
374
+ * @typedef {Object} WAAPIAnimationOptions
375
+ * @property {Number|Boolean} [loop]
376
+ * @property {Boolean} [Reversed]
377
+ * @property {Boolean} [Alternate]
378
+ * @property {Boolean|ScrollObserver} [autoplay]
379
+ * @property {Number} [playbackRate]
380
+ * @property {Number|WAAPIFunctionValue} [duration]
381
+ * @property {Number|WAAPIFunctionValue} [delay]
382
+ * @property {EasingParam} [ease]
383
+ * @property {CompositeOperation} [composition]
384
+ * @property {WAAPICallback} [onComplete]
385
+ */
386
+
387
+ /**
388
+ * @typedef {Record<String, WAAPIKeyframeValue | WAAPIAnimationOptions | Boolean | ScrollObserver | WAAPICallback | EasingParam | WAAPITweenOptions> & WAAPIAnimationOptions} WAAPIAnimationParams
389
+ */
390
+
391
+ // Animatable types ////////////////////////////////////////////////////////////
302
392
 
303
393
  /**
304
394
  * @callback AnimatablePropertySetter
@@ -334,7 +424,7 @@
334
424
  * @typedef {Record<String, TweenParamValue | EasingParam | TweenModifier | TweenComposition | AnimatablePropertyParamsOptions> & AnimatablePropertyParamsOptions} AnimatableParams
335
425
  */
336
426
 
337
- // Scope types ////////////////////////////////////////////////////////////////
427
+ // Scope types /////////////////////////////////////////////////////////////////
338
428
 
339
429
  /**
340
430
  * @typedef {Object} ReactRef
@@ -377,7 +467,52 @@
377
467
  * @return {ScopeCleanupCallback|void}
378
468
  */
379
469
 
380
- // Draggable types ////////////////////////////////////////////////////////////
470
+ // Scroll types ////////////////////////////////////////////////////////////////
471
+
472
+ /**
473
+ * @typedef {String|Number} ScrollThresholdValue
474
+ */
475
+
476
+ /**
477
+ * @typedef {Object} ScrollThresholdParam
478
+ * @property {ScrollThresholdValue} [target]
479
+ * @property {ScrollThresholdValue} [container]
480
+ */
481
+
482
+ /**
483
+ * @callback ScrollObserverAxisCallback
484
+ * @param {ScrollObserver} self
485
+ * @return {'x'|'y'}
486
+ */
487
+
488
+ /**
489
+ * @callback ScrollThresholdCallback
490
+ * @param {ScrollObserver} self
491
+ * @return {ScrollThresholdValue|ScrollThresholdParam}
492
+ */
493
+
494
+ /**
495
+ * @typedef {Object} ScrollObserverParams
496
+ * @property {Number|String} [id]
497
+ * @property {Boolean|Number|String|EasingParam} [sync]
498
+ * @property {TargetsParam} [container]
499
+ * @property {TargetsParam} [target]
500
+ * @property {'x'|'y'|ScrollObserverAxisCallback|((observer: ScrollObserver) => 'x'|'y'|ScrollObserverAxisCallback)} [axis]
501
+ * @property {ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback|((observer: ScrollObserver) => ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback)} [enter]
502
+ * @property {ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback|((observer: ScrollObserver) => ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback)} [leave]
503
+ * @property {Boolean|((observer: ScrollObserver) => Boolean)} [repeat]
504
+ * @property {Boolean} [debug]
505
+ * @property {Callback<ScrollObserver>} [onEnter]
506
+ * @property {Callback<ScrollObserver>} [onLeave]
507
+ * @property {Callback<ScrollObserver>} [onEnterForward]
508
+ * @property {Callback<ScrollObserver>} [onLeaveForward]
509
+ * @property {Callback<ScrollObserver>} [onEnterBackward]
510
+ * @property {Callback<ScrollObserver>} [onLeaveBackward]
511
+ * @property {Callback<ScrollObserver>} [onUpdate]
512
+ * @property {Callback<ScrollObserver>} [onSyncComplete]
513
+ */
514
+
515
+ // Draggable types /////////////////////////////////////////////////////////////
381
516
 
382
517
  /**
383
518
  * @typedef {Object} DraggableAxisParam
@@ -426,7 +561,7 @@
426
561
  * @property {Callback<Draggable>} [onAfterResize]
427
562
  */
428
563
 
429
- // Text types /////////////////////////////////////////////////////////////////
564
+ // Text types //////////////////////////////////////////////////////////////////
430
565
 
431
566
  /**
432
567
  * @typedef {Object} splitTemplateParams
@@ -455,7 +590,7 @@
455
590
  * @property {Boolean} [debug]
456
591
  */
457
592
 
458
- // SVG types //////////////////////////////////////////////////////////////////
593
+ // SVG types ///////////////////////////////////////////////////////////////////
459
594
 
460
595
  /**
461
596
  * @typedef {SVGGeometryElement & {
@@ -619,13 +754,13 @@ const globals = {
619
754
  defaults,
620
755
  /** @type {Number} */
621
756
  precision: 4,
622
- /** @type {Number} */
757
+ /** @type {Number} equals 1 in ms mode, 0.001 in s mode */
623
758
  timeScale: 1,
624
759
  /** @type {Number} */
625
760
  tickThreshold: 200,
626
761
  };
627
762
 
628
- const globalVersions = { version: '4.1.2', engine: null };
763
+ const globalVersions = { version: '4.1.4', engine: null };
629
764
 
630
765
  if (isBrowser) {
631
766
  if (!win.AnimeJS) win.AnimeJS = [];
@@ -648,7 +783,6 @@ const toLowerCase = str => str.replace(lowerCaseRgx, '$1-$2').toLowerCase();
648
783
  */
649
784
  const stringStartsWith = (str, sub) => str.indexOf(sub) === 0;
650
785
 
651
- // Time
652
786
  // Note: Date.now is used instead of performance.now since it is precise enough for timings calculations, performs slightly faster and works in Node.js environement.
653
787
  const now = Date.now;
654
788
 
@@ -767,7 +901,7 @@ const shuffle = items => {
767
901
  * @param {Number} v
768
902
  * @return {Number}
769
903
  */
770
- const clampInfinity = v => v === Infinity ? maxValue : v === -Infinity ? -1e12 : v;
904
+ const clampInfinity = v => v === Infinity ? maxValue : v === -Infinity ? -maxValue : v;
771
905
 
772
906
  /**
773
907
  * @param {Number} v
@@ -1405,9 +1539,10 @@ class Engine extends Clock {
1405
1539
  this.pauseOnDocumentHidden = true;
1406
1540
  /** @type {DefaultsParams} */
1407
1541
  this.defaults = defaults;
1408
- this.paused = isBrowser && doc.hidden ? true : false;
1542
+ // this.paused = isBrowser && doc.hidden ? true : false;
1543
+ this.paused = true;
1409
1544
  /** @type {Number|NodeJS.Immediate} */
1410
- this.reqId = null;
1545
+ this.reqId = 0;
1411
1546
  }
1412
1547
 
1413
1548
  update() {
@@ -1442,13 +1577,16 @@ class Engine extends Clock {
1442
1577
  }
1443
1578
 
1444
1579
  wake() {
1445
- if (this.useDefaultMainLoop && !this.reqId && !this.paused) {
1580
+ if (this.useDefaultMainLoop && !this.reqId) {
1581
+ // Imediatly request a tick to update engine._elapsedTime and get accurate offsetPosition calculation in timer.js
1582
+ this.requestTick(now());
1446
1583
  this.reqId = engineTickMethod(tickEngine);
1447
1584
  }
1448
1585
  return this;
1449
1586
  }
1450
1587
 
1451
1588
  pause() {
1589
+ if (!this.reqId) return;
1452
1590
  this.paused = true;
1453
1591
  return killEngine();
1454
1592
  }
@@ -1589,6 +1727,7 @@ function getNodeList(v) {
1589
1727
  */
1590
1728
  function parseTargets(targets) {
1591
1729
  if (isNil(targets)) return /** @type {TargetsArray} */([]);
1730
+ if (!isBrowser) return /** @type {JSTargetsArray} */(isArr(targets) && targets.flat(Infinity) || [targets]);
1592
1731
  if (isArr(targets)) {
1593
1732
  const flattened = targets.flat(Infinity);
1594
1733
  /** @type {TargetsArray} */
@@ -1629,7 +1768,6 @@ function parseTargets(targets) {
1629
1768
  }
1630
1769
  return parsed;
1631
1770
  }
1632
- if (!isBrowser) return /** @type {JSTargetsArray} */([targets]);
1633
1771
  const nodeList = getNodeList(targets);
1634
1772
  if (nodeList) return /** @type {DOMTargetsArray} */(Array.from(nodeList));
1635
1773
  return /** @type {TargetsArray} */([targets]);
@@ -1770,7 +1908,7 @@ const createDrawableProxy = ($el, start, end) => {
1770
1908
  // const v1 = round(+value.slice(0, spaceIndex), precision);
1771
1909
  // const v2 = round(+value.slice(spaceIndex + 1), precision);
1772
1910
  const scaleFactor = getScaleFactor($scalled);
1773
- const os = v1 * -1e3 * scaleFactor;
1911
+ const os = v1 * -pathLength * scaleFactor;
1774
1912
  const d1 = (v2 * pathLength * scaleFactor) + os;
1775
1913
  const d2 = (pathLength * scaleFactor +
1776
1914
  ((v1 === 0 && v2 === 1) || (v1 === 1 && v2 === 0) ? 0 : 10 * scaleFactor) - d1);
@@ -2279,12 +2417,16 @@ const composeTween = (tween, siblings) => {
2279
2417
 
2280
2418
  const prevChangeStartTime = prevSibling._startTime;
2281
2419
  const prevTLOffset = prevAbsEndTime - (prevChangeStartTime + prevSibling._updateDuration);
2420
+ // Rounding is necessary here to minimize floating point errors when working in seconds
2421
+ const updatedPrevChangeDuration = round(absoluteUpdateStartTime - prevTLOffset - prevChangeStartTime, 12);
2282
2422
 
2283
- prevSibling._changeDuration = absoluteUpdateStartTime - prevTLOffset - prevChangeStartTime;
2284
- prevSibling._currentTime = prevSibling._changeDuration;
2423
+ prevSibling._changeDuration = updatedPrevChangeDuration;
2424
+ prevSibling._currentTime = updatedPrevChangeDuration;
2285
2425
  prevSibling._isOverlapped = 1;
2286
2426
 
2287
- if (prevSibling._changeDuration < minValue) {
2427
+ // Override the previous tween if its new _changeDuration is lower than minValue
2428
+ // TODO: See if it's even neceseeary to test against minValue, checking for 0 might be enough
2429
+ if (updatedPrevChangeDuration < minValue) {
2288
2430
  overrideTween(prevSibling);
2289
2431
  }
2290
2432
  }
@@ -2315,7 +2457,7 @@ const composeTween = (tween, siblings) => {
2315
2457
  prevParent.cancel();
2316
2458
  // Previously, calling .cancel() on a timeline child would affect the render order of other children
2317
2459
  // Worked around this by marking it as .completed and using .pause() for safe removal in the engine loop
2318
- // This is no longer needed since timeline tween composition is now handled separatly
2460
+ // This is no longer needed since timeline tween composition is now handled separately
2319
2461
  // Keeping this here for reference
2320
2462
  // prevParent.completed = true;
2321
2463
  // prevParent.pause();
@@ -2514,18 +2656,17 @@ class Timer extends Clock {
2514
2656
  /** @type {Number} */(timerLoop) < 0 ? Infinity :
2515
2657
  /** @type {Number} */(timerLoop) + 1;
2516
2658
 
2659
+
2517
2660
  let offsetPosition = 0;
2518
2661
 
2519
2662
  if (parent) {
2520
2663
  offsetPosition = parentPosition;
2521
2664
  } else {
2522
- let startTime = now();
2523
- // Make sure to tick the engine once if suspended to avoid big gaps with the following offsetPosition calculation
2524
- if (engine.paused) {
2525
- engine.requestTick(startTime);
2526
- startTime = engine._elapsedTime;
2527
- }
2528
- offsetPosition = startTime - engine._startTime;
2665
+ // Make sure to tick the engine once if not currently running to get up to date engine._elapsedTime
2666
+ // to avoid big gaps with the following offsetPosition calculation
2667
+ if (!engine.reqId) engine.requestTick(now());
2668
+ // Make sure to scale the offset position with globals.timeScale to properly handle seconds unit
2669
+ offsetPosition = (engine._elapsedTime - engine._startTime) * globals.timeScale;
2529
2670
  }
2530
2671
 
2531
2672
  // Timer's parameters
@@ -2726,6 +2867,9 @@ class Timer extends Clock {
2726
2867
  /** @return {this} */
2727
2868
  resetTime() {
2728
2869
  const timeScale = 1 / (this._speed * engine._speed);
2870
+ // TODO: See if we can safely use engine._elapsedTime here
2871
+ // if (!engine.reqId) engine.requestTick(now())
2872
+ // this._startTime = engine._elapsedTime - (this._currentTime + this._delay) * timeScale;
2729
2873
  this._startTime = now() - (this._currentTime + this._delay) * timeScale;
2730
2874
  return this;
2731
2875
  }
@@ -2887,7 +3031,6 @@ class Timer extends Clock {
2887
3031
 
2888
3032
  }
2889
3033
 
2890
-
2891
3034
  /**
2892
3035
  * @param {TimerParams} [parameters]
2893
3036
  * @return {Timer}
@@ -2931,10 +3074,10 @@ const binarySubdivide = (aX, mX1, mX2) => {
2931
3074
  };
2932
3075
 
2933
3076
  /**
2934
- * @param {Number} [mX1]
2935
- * @param {Number} [mY1]
2936
- * @param {Number} [mX2]
2937
- * @param {Number} [mY2]
3077
+ * @param {Number} [mX1] The x coordinate of the first point
3078
+ * @param {Number} [mY1] The y coordinate of the first point
3079
+ * @param {Number} [mX2] The x coordinate of the second point
3080
+ * @param {Number} [mY2] The y coordinate of the second point
2938
3081
  * @return {EasingFunction}
2939
3082
  */
2940
3083
 
@@ -2957,7 +3100,7 @@ const steps = (steps = 10, fromStart) => {
2957
3100
  /**
2958
3101
  * Without parameters, the linear function creates a non-eased transition.
2959
3102
  * Parameters, if used, creates a piecewise linear easing by interpolating linearly between the specified points.
2960
- * @param {...String|Number} [args] - Points
3103
+ * @param {...(String|Number)} args - Points
2961
3104
  * @return {EasingFunction}
2962
3105
  */
2963
3106
  const linear = (...args) => {
@@ -3605,7 +3748,8 @@ class JSAnimation extends Timer {
3605
3748
  const isFromToArray = isArr(tweenToValue);
3606
3749
  const isFromToValue = isFromToArray || (hasFromvalue && hasToValue);
3607
3750
  const tweenStartTime = prevTween ? lastTweenChangeEndTime + tweenDelay : tweenDelay;
3608
- const absoluteStartTime = absoluteOffsetTime + tweenStartTime;
3751
+ // Rounding is necessary here to minimize floating point errors when working in seconds
3752
+ const absoluteStartTime = round(absoluteOffsetTime + tweenStartTime, 12);
3609
3753
 
3610
3754
  // Force a onRender callback if the animation contains at least one from value and autoplay is set to false
3611
3755
  if (!shouldTriggerRender && (hasFromvalue || isFromToArray)) shouldTriggerRender = 1;
@@ -3733,7 +3877,7 @@ class JSAnimation extends Timer {
3733
3877
 
3734
3878
  // Tween factory
3735
3879
 
3736
- // Rounding is necessary here to minimize floating point errors
3880
+ // Rounding is necessary here to minimize floating point errors when working in seconds
3737
3881
  const tweenUpdateDuration = round(+tweenDuration || minValue, 12);
3738
3882
 
3739
3883
  /** @type {Tween} */
@@ -3782,7 +3926,7 @@ class JSAnimation extends Timer {
3782
3926
  if (isNaN(firstTweenChangeStartTime)) {
3783
3927
  firstTweenChangeStartTime = tween._startTime;
3784
3928
  }
3785
- // Rounding is necessary here to minimize floating point errors
3929
+ // Rounding is necessary here to minimize floating point errors when working in seconds
3786
3930
  lastTweenChangeEndTime = round(tweenStartTime + tweenUpdateDuration, 12);
3787
3931
  prevTween = tween;
3788
3932
  animationAnimationLength++;
@@ -3965,7 +4109,7 @@ const WAAPIEasesLookups = {
3965
4109
 
3966
4110
  const WAAPIeases = /*#__PURE__*/(() => {
3967
4111
  const list = {};
3968
- for (let type in easeTypes) list[type] = a => easeTypes[type](easeInPower(a));
4112
+ for (let type in easeTypes) list[type] = (/** @type {String|Number} */p) => easeTypes[type](easeInPower(p));
3969
4113
  return /** @type {Record<String, EasingFunction>} */(list);
3970
4114
  })();
3971
4115
 
@@ -4001,54 +4145,6 @@ const parseWAAPIEasing = (ease) => {
4001
4145
  return parsedEase;
4002
4146
  };
4003
4147
 
4004
- /**
4005
- * @typedef {String|Number|Array<String>|Array<Number>} WAAPITweenValue
4006
- */
4007
-
4008
- /**
4009
- * @callback WAAPIFunctionvalue
4010
- * @param {DOMTarget} target - The animated target
4011
- * @param {Number} index - The target index
4012
- * @param {Number} length - The total number of animated targets
4013
- * @return {WAAPITweenValue}
4014
- */
4015
-
4016
- /**
4017
- * @typedef {WAAPITweenValue|WAAPIFunctionvalue|Array<String|Number|WAAPIFunctionvalue>} WAAPIKeyframeValue
4018
- */
4019
-
4020
- /**
4021
- * @typedef {(animation: WAAPIAnimation) => void} WAAPICallback
4022
- */
4023
-
4024
- /**
4025
- * @typedef {Object} WAAPITweenOptions
4026
- * @property {WAAPIKeyframeValue} [to]
4027
- * @property {WAAPIKeyframeValue} [from]
4028
- * @property {Number|WAAPIFunctionvalue} [duration]
4029
- * @property {Number|WAAPIFunctionvalue} [delay]
4030
- * @property {EasingParam} [ease]
4031
- * @property {CompositeOperation} [composition]
4032
- */
4033
-
4034
- /**
4035
- * @typedef {Object} WAAPIAnimationOptions
4036
- * @property {Number|Boolean} [loop]
4037
- * @property {Boolean} [Reversed]
4038
- * @property {Boolean} [Alternate]
4039
- * @property {Boolean|ScrollObserver} [autoplay]
4040
- * @property {Number} [playbackRate]
4041
- * @property {Number|WAAPIFunctionvalue} [duration]
4042
- * @property {Number|WAAPIFunctionvalue} [delay]
4043
- * @property {EasingParam} [ease]
4044
- * @property {CompositeOperation} [composition]
4045
- * @property {WAAPICallback} [onComplete]
4046
- */
4047
-
4048
- /**
4049
- * @typedef {Record<String, WAAPIKeyframeValue | WAAPIAnimationOptions | Boolean | ScrollObserver | WAAPICallback | EasingParam | WAAPITweenOptions> & WAAPIAnimationOptions} WAAPIAnimationParams
4050
- */
4051
-
4052
4148
  const transformsShorthands = ['x', 'y', 'z'];
4053
4149
  const commonDefaultPXProperties = [
4054
4150
  'perspective',
@@ -4346,7 +4442,7 @@ class WAAPIAnimation {
4346
4442
  * @return {this}
4347
4443
  */
4348
4444
  forEach(callback) {
4349
- const cb = isStr(callback) ? a => a[callback]() : callback;
4445
+ const cb = isStr(callback) ? (/** @type {globalThis.Animation} */a) => a[callback]() : callback;
4350
4446
  this.animations.forEach(cb);
4351
4447
  return this;
4352
4448
  }
@@ -4879,10 +4975,6 @@ const utils = {
4879
4975
 
4880
4976
 
4881
4977
 
4882
- /**
4883
- * @typedef {Number|String|Function} TimePosition
4884
- */
4885
-
4886
4978
  /**
4887
4979
  * Timeline's children offsets positions parser
4888
4980
  * @param {Timeline} timeline
@@ -4900,7 +4992,7 @@ const getPrevChildOffset = (timeline, timePosition) => {
4900
4992
 
4901
4993
  /**
4902
4994
  * @param {Timeline} timeline
4903
- * @param {TimePosition} [timePosition]
4995
+ * @param {TimelinePosition} [timePosition]
4904
4996
  * @return {Number}
4905
4997
  */
4906
4998
  const parseTimelinePosition = (timeline, timePosition) => {
@@ -5006,17 +5098,17 @@ class Timeline extends Timer {
5006
5098
  * @overload
5007
5099
  * @param {TargetsParam} a1
5008
5100
  * @param {AnimationParams} a2
5009
- * @param {TimePosition} [a3]
5101
+ * @param {TimelinePosition|StaggerFunction<Number|String>} [a3]
5010
5102
  * @return {this}
5011
5103
  *
5012
5104
  * @overload
5013
5105
  * @param {TimerParams} a1
5014
- * @param {TimePosition} [a2]
5106
+ * @param {TimelinePosition} [a2]
5015
5107
  * @return {this}
5016
5108
  *
5017
5109
  * @param {TargetsParam|TimerParams} a1
5018
- * @param {AnimationParams|TimePosition} a2
5019
- * @param {TimePosition} [a3]
5110
+ * @param {TimelinePosition|AnimationParams} a2
5111
+ * @param {TimelinePosition|StaggerFunction<Number|String>} [a3]
5020
5112
  */
5021
5113
  add(a1, a2, a3) {
5022
5114
  const isAnim = isObj(a2);
@@ -5027,7 +5119,7 @@ class Timeline extends Timer {
5027
5119
  const childParams = /** @type {AnimationParams} */(a2);
5028
5120
  // Check for function for children stagger positions
5029
5121
  if (isFnc(a3)) {
5030
- const staggeredPosition = /** @type {Function} */(a3);
5122
+ const staggeredPosition = a3;
5031
5123
  const parsedTargetsArray = parseTargets(/** @type {TargetsParam} */(a1));
5032
5124
  // Store initial duration before adding new children that will change the duration
5033
5125
  const tlDuration = this.duration;
@@ -5036,7 +5128,8 @@ class Timeline extends Timer {
5036
5128
  // Store the original id in order to add specific indexes to the new animations ids
5037
5129
  const id = childParams.id;
5038
5130
  let i = 0;
5039
- const parsedLength = parsedTargetsArray.length;
5131
+ /** @type {Number} */
5132
+ const parsedLength = (parsedTargetsArray.length);
5040
5133
  parsedTargetsArray.forEach((/** @type {Target} */target) => {
5041
5134
  // Create a new parameter object for each staggered children
5042
5135
  const staggeredChildParams = { ...childParams };
@@ -5047,7 +5140,7 @@ class Timeline extends Timer {
5047
5140
  addTlChild(
5048
5141
  staggeredChildParams,
5049
5142
  this,
5050
- staggeredPosition(target, i, parsedLength, this),
5143
+ parseTimelinePosition(this, staggeredPosition(target, i, parsedLength, this)),
5051
5144
  target,
5052
5145
  i,
5053
5146
  parsedLength
@@ -5067,7 +5160,7 @@ class Timeline extends Timer {
5067
5160
  addTlChild(
5068
5161
  /** @type TimerParams */(a1),
5069
5162
  this,
5070
- parseTimelinePosition(this,/** @type TimePosition */(a2)),
5163
+ parseTimelinePosition(this,a2),
5071
5164
  );
5072
5165
  }
5073
5166
  return this.init(1); // 1 = internalRender
@@ -5077,21 +5170,21 @@ class Timeline extends Timer {
5077
5170
  /**
5078
5171
  * @overload
5079
5172
  * @param {Tickable} [synced]
5080
- * @param {TimePosition} [position]
5173
+ * @param {TimelinePosition} [position]
5081
5174
  * @return {this}
5082
5175
  *
5083
5176
  * @overload
5084
5177
  * @param {globalThis.Animation} [synced]
5085
- * @param {TimePosition} [position]
5178
+ * @param {TimelinePosition} [position]
5086
5179
  * @return {this}
5087
5180
  *
5088
5181
  * @overload
5089
5182
  * @param {WAAPIAnimation} [synced]
5090
- * @param {TimePosition} [position]
5183
+ * @param {TimelinePosition} [position]
5091
5184
  * @return {this}
5092
5185
  *
5093
5186
  * @param {Tickable|WAAPIAnimation|globalThis.Animation} [synced]
5094
- * @param {TimePosition} [position]
5187
+ * @param {TimelinePosition} [position]
5095
5188
  */
5096
5189
  sync(synced, position) {
5097
5190
  if (isUnd(synced) || synced && isUnd(synced.pause)) return this;
@@ -5103,7 +5196,7 @@ class Timeline extends Timer {
5103
5196
  /**
5104
5197
  * @param {TargetsParam} targets
5105
5198
  * @param {AnimationParams} parameters
5106
- * @param {TimePosition} [position]
5199
+ * @param {TimelinePosition} [position]
5107
5200
  * @return {this}
5108
5201
  */
5109
5202
  set(targets, parameters, position) {
@@ -5115,7 +5208,7 @@ class Timeline extends Timer {
5115
5208
 
5116
5209
  /**
5117
5210
  * @param {Callback<Timer>} callback
5118
- * @param {TimePosition} [position]
5211
+ * @param {TimelinePosition} [position]
5119
5212
  * @return {this}
5120
5213
  */
5121
5214
  call(callback, position) {
@@ -5125,13 +5218,13 @@ class Timeline extends Timer {
5125
5218
 
5126
5219
  /**
5127
5220
  * @param {String} labelName
5128
- * @param {TimePosition} [position]
5221
+ * @param {TimelinePosition} [position]
5129
5222
  * @return {this}
5130
5223
  *
5131
5224
  */
5132
5225
  label(labelName, position) {
5133
5226
  if (isUnd(labelName) || labelName && !isStr(labelName)) return this;
5134
- this.labels[labelName] = parseTimelinePosition(this,/** @type TimePosition */(position));
5227
+ this.labels[labelName] = parseTimelinePosition(this, position);
5135
5228
  return this;
5136
5229
  }
5137
5230
 
@@ -5203,20 +5296,49 @@ class Animatable {
5203
5296
  */
5204
5297
  constructor(targets, parameters) {
5205
5298
  if (scope.current) scope.current.register(this);
5299
+ const beginHandler = () => {
5300
+ if (this.callbacks.completed) this.callbacks.reset();
5301
+ this.callbacks.play();
5302
+ };
5303
+ const pauseHandler = () => {
5304
+ if (this.callbacks.completed) return;
5305
+ let paused = true;
5306
+ for (let name in this.animations) {
5307
+ const anim = this.animations[name];
5308
+ if (!anim.paused && paused) {
5309
+ paused = false;
5310
+ break;
5311
+ }
5312
+ }
5313
+ if (paused) {
5314
+ this.callbacks.complete();
5315
+ }
5316
+ };
5317
+ /** @type {AnimationParams} */
5318
+ const globalParams = {
5319
+ onBegin: beginHandler,
5320
+ onComplete: pauseHandler,
5321
+ onPause: pauseHandler,
5322
+ };
5206
5323
  /** @type {AnimationParams} */
5207
- const globalParams = {};
5324
+ const callbacksAnimationParams = { v: 1, autoplay: false };
5208
5325
  const properties = {};
5209
5326
  this.targets = [];
5210
5327
  this.animations = {};
5328
+ /** @type {JSAnimation|null} */
5329
+ this.callbacks = null;
5211
5330
  if (isUnd(targets) || isUnd(parameters)) return;
5212
5331
  for (let propName in parameters) {
5213
5332
  const paramValue = parameters[propName];
5214
5333
  if (isKey(propName)) {
5215
5334
  properties[propName] = paramValue;
5335
+ } else if (stringStartsWith(propName, 'on')) {
5336
+ callbacksAnimationParams[propName] = paramValue;
5216
5337
  } else {
5217
5338
  globalParams[propName] = paramValue;
5218
5339
  }
5219
5340
  }
5341
+ this.callbacks = new JSAnimation({ v: 0 }, callbacksAnimationParams);
5220
5342
  for (let propName in properties) {
5221
5343
  const propValue = properties[propName];
5222
5344
  const isObjValue = isObj(propValue);
@@ -5276,6 +5398,7 @@ class Animatable {
5276
5398
  }
5277
5399
  this.animations = {};
5278
5400
  this.targets.length = 0;
5401
+ if (this.callbacks) this.callbacks.revert();
5279
5402
  return this;
5280
5403
  }
5281
5404
  }
@@ -5285,7 +5408,7 @@ class Animatable {
5285
5408
  * @param {AnimatableParams} parameters
5286
5409
  * @return {AnimatableObject}
5287
5410
  */
5288
- const createAnimatable = (targets, parameters) => /** @type {AnimatableObject} */(new Animatable(targets, parameters));
5411
+ const createAnimatable = (targets, parameters) => /** @type {AnimatableObject} */ (new Animatable(targets, parameters));
5289
5412
 
5290
5413
 
5291
5414
 
@@ -5295,6 +5418,8 @@ const createAnimatable = (targets, parameters) => /** @type {AnimatableObject} *
5295
5418
  * Webkit Copyright © 2016 Apple Inc
5296
5419
  */
5297
5420
 
5421
+ const maxSpringParamValue = K * 10;
5422
+
5298
5423
  /**
5299
5424
  * @typedef {Object} SpringParams
5300
5425
  * @property {Number} [mass=1] - Mass, default 1
@@ -5302,7 +5427,6 @@ const createAnimatable = (targets, parameters) => /** @type {AnimatableObject} *
5302
5427
  * @property {Number} [damping=10] - Damping, default 10
5303
5428
  * @property {Number} [velocity=0] - Initial velocity, default 0
5304
5429
  */
5305
-
5306
5430
  class Spring {
5307
5431
  /**
5308
5432
  * @param {SpringParams} [parameters]
@@ -5314,10 +5438,10 @@ class Spring {
5314
5438
  this.maxDuration = 60000; // The maximum allowed spring duration in ms (default 1 min)
5315
5439
  this.maxRestSteps = this.restDuration / this.timeStep / K; // How many steps allowed after reaching restThreshold before stopping the duration calculation
5316
5440
  this.maxIterations = this.maxDuration / this.timeStep / K; // Calculate the maximum iterations allowed based on maxDuration
5317
- this.m = clamp(setValue(parameters.mass, 1), 0, K);
5318
- this.s = clamp(setValue(parameters.stiffness, 100), 1, K);
5319
- this.d = clamp(setValue(parameters.damping, 10), .1, K);
5320
- this.v = clamp(setValue(parameters.velocity, 0), -1e3, K);
5441
+ this.m = clamp(setValue(parameters.mass, 1), 0, maxSpringParamValue);
5442
+ this.s = clamp(setValue(parameters.stiffness, 100), 1, maxSpringParamValue);
5443
+ this.d = clamp(setValue(parameters.damping, 10), .1, maxSpringParamValue);
5444
+ this.v = clamp(setValue(parameters.velocity, 0), -maxSpringParamValue, maxSpringParamValue);
5321
5445
  this.w0 = 0;
5322
5446
  this.zeta = 0;
5323
5447
  this.wd = 0;
@@ -5368,7 +5492,7 @@ class Spring {
5368
5492
  }
5369
5493
 
5370
5494
  set mass(v) {
5371
- this.m = clamp(setValue(v, 1), 0, K);
5495
+ this.m = clamp(setValue(v, 1), 0, maxSpringParamValue);
5372
5496
  this.compute();
5373
5497
  }
5374
5498
 
@@ -5377,7 +5501,7 @@ class Spring {
5377
5501
  }
5378
5502
 
5379
5503
  set stiffness(v) {
5380
- this.s = clamp(setValue(v, 100), 1, K);
5504
+ this.s = clamp(setValue(v, 100), 1, maxSpringParamValue);
5381
5505
  this.compute();
5382
5506
  }
5383
5507
 
@@ -5386,7 +5510,7 @@ class Spring {
5386
5510
  }
5387
5511
 
5388
5512
  set damping(v) {
5389
- this.d = clamp(setValue(v, 10), .1, K);
5513
+ this.d = clamp(setValue(v, 10), .1, maxSpringParamValue);
5390
5514
  this.compute();
5391
5515
  }
5392
5516
 
@@ -5395,7 +5519,7 @@ class Spring {
5395
5519
  }
5396
5520
 
5397
5521
  set velocity(v) {
5398
- this.v = clamp(setValue(v, 0), -1e3, K);
5522
+ this.v = clamp(setValue(v, 0), -maxSpringParamValue, maxSpringParamValue);
5399
5523
  this.compute();
5400
5524
  }
5401
5525
  }
@@ -5665,7 +5789,7 @@ class Draggable {
5665
5789
  /** @type {[Number, Number, Number, Number]} */
5666
5790
  this.dragArea = [0, 0, 0, 0]; // x, y, w, h
5667
5791
  /** @type {[Number, Number, Number, Number]} */
5668
- this.containerBounds = [-1e12, maxValue, maxValue, -1e12]; // t, r, b, l
5792
+ this.containerBounds = [-maxValue, maxValue, maxValue, -maxValue]; // t, r, b, l
5669
5793
  /** @type {[Number, Number, Number, Number]} */
5670
5794
  this.scrollBounds = [0, 0, 0, 0]; // t, r, b, l
5671
5795
  /** @type {[Number, Number, Number, Number]} */
@@ -5694,32 +5818,23 @@ class Draggable {
5694
5818
  this.touchActionStyles = null;
5695
5819
  this.transforms = new Transforms(this.$target);
5696
5820
  this.overshootCoords = { x: 0, y: 0 };
5697
- this.overshootXTicker = new Timer({ autoplay: false }, null, 0).init();
5698
- this.overshootYTicker = new Timer({ autoplay: false }, null, 0).init();
5699
- this.updateTicker = new Timer({ autoplay: false }, null, 0).init();
5700
- this.overshootXTicker.onUpdate = () => {
5701
- if (this.disabled[0]) return;
5702
- this.updated = true;
5703
- this.manual = true;
5704
- this.animate[this.xProp](this.overshootCoords.x, 0);
5705
- };
5706
- this.overshootXTicker.onComplete = () => {
5707
- if (this.disabled[0]) return;
5708
- this.manual = false;
5709
- this.animate[this.xProp](this.overshootCoords.x, 0);
5710
- };
5711
- this.overshootYTicker.onUpdate = () => {
5712
- if (this.disabled[1]) return;
5713
- this.updated = true;
5714
- this.manual = true;
5715
- this.animate[this.yProp](this.overshootCoords.y, 0);
5716
- };
5717
- this.overshootYTicker.onComplete = () => {
5718
- if (this.disabled[1]) return;
5719
- this.manual = false;
5720
- this.animate[this.yProp](this.overshootCoords.y, 0);
5721
- };
5722
- this.updateTicker.onUpdate = () => this.update();
5821
+ this.overshootTicker = new Timer({
5822
+ autoplay: false,
5823
+ onUpdate: () => {
5824
+ this.updated = true;
5825
+ this.manual = true;
5826
+ // Use a duration of 1 to prevent the animatable from completing immediately to prevent issues with onSettle()
5827
+ // https://github.com/juliangarnier/anime/issues/1045
5828
+ if (!this.disabled[0]) this.animate[this.xProp](this.overshootCoords.x, 1);
5829
+ if (!this.disabled[1]) this.animate[this.yProp](this.overshootCoords.y, 1);
5830
+ },
5831
+ onComplete: () => {
5832
+ this.manual = false;
5833
+ if (!this.disabled[0]) this.animate[this.xProp](this.overshootCoords.x, 0);
5834
+ if (!this.disabled[1]) this.animate[this.yProp](this.overshootCoords.y, 0);
5835
+ },
5836
+ }, null, 0).init();
5837
+ this.updateTicker = new Timer({ autoplay: false, onUpdate: () => this.update() }, null,0,).init();
5723
5838
  this.contained = !isUnd(container);
5724
5839
  this.manual = false;
5725
5840
  this.grabbed = false;
@@ -5730,7 +5845,7 @@ class Draggable {
5730
5845
  this.enabled = false;
5731
5846
  this.initialized = false;
5732
5847
  this.activeProp = this.disabled[1] ? xProp : yProp;
5733
- this.animate.animations[this.activeProp].onRender = () => {
5848
+ this.animate.callbacks.onRender = () => {
5734
5849
  const hasUpdated = this.updated;
5735
5850
  const hasMoved = this.grabbed && hasUpdated;
5736
5851
  const hasReleased = !hasMoved && this.released;
@@ -5742,7 +5857,8 @@ class Draggable {
5742
5857
  this.deltaY = dy;
5743
5858
  this.coords[2] = x;
5744
5859
  this.coords[3] = y;
5745
- // Check if dx or dy are not 0 to check if the draggable has actually moved https://github.com/juliangarnier/anime/issues/1032
5860
+ // Check if dx or dy are not 0 to check if the draggable has actually moved
5861
+ // https://github.com/juliangarnier/anime/issues/1032
5746
5862
  if (hasUpdated && (dx || dy)) {
5747
5863
  this.onUpdate(this);
5748
5864
  }
@@ -5753,9 +5869,9 @@ class Draggable {
5753
5869
  this.angle = atan2(dy, dx);
5754
5870
  }
5755
5871
  };
5756
- this.animate.animations[this.activeProp].onComplete = () => {
5872
+ this.animate.callbacks.onComplete = () => {
5757
5873
  if ((!this.grabbed && this.released)) {
5758
- // Set eleased to false before calling onSettle to avoid recursion
5874
+ // Set released to false before calling onSettle to avoid recursion
5759
5875
  this.released = false;
5760
5876
  }
5761
5877
  if (!this.manual) {
@@ -5823,7 +5939,7 @@ class Draggable {
5823
5939
  setX(x, muteUpdateCallback = false) {
5824
5940
  if (this.disabled[0]) return;
5825
5941
  const v = round(x, 5);
5826
- this.overshootXTicker.pause();
5942
+ this.overshootTicker.pause();
5827
5943
  this.manual = true;
5828
5944
  this.updated = !muteUpdateCallback;
5829
5945
  this.destX = v;
@@ -5841,7 +5957,7 @@ class Draggable {
5841
5957
  setY(y, muteUpdateCallback = false) {
5842
5958
  if (this.disabled[1]) return;
5843
5959
  const v = round(y, 5);
5844
- this.overshootYTicker.pause();
5960
+ this.overshootTicker.pause();
5845
5961
  this.manual = true;
5846
5962
  this.updated = !muteUpdateCallback;
5847
5963
  this.destY = v;
@@ -5898,6 +6014,9 @@ class Draggable {
5898
6014
 
5899
6015
  updateBoundingValues() {
5900
6016
  const $container = this.$container;
6017
+ // Return early if no $container defined to prevents error when reading scrollWidth / scrollHeight
6018
+ // https://github.com/juliangarnier/anime/issues/1064
6019
+ if (!$container) return;
5901
6020
  const cx = this.x;
5902
6021
  const cy = this.y;
5903
6022
  const cx2 = this.coords[2];
@@ -5967,14 +6086,13 @@ class Draggable {
5967
6086
  }
5968
6087
 
5969
6088
  /**
5970
- * Returns 0 if not OB, 1 if x is OB, 2 if y is OB, 3 if both x and y are OB
5971
- *
5972
6089
  * @param {Array} bounds
5973
6090
  * @param {Number} x
5974
6091
  * @param {Number} y
5975
6092
  * @return {Number}
5976
6093
  */
5977
6094
  isOutOfBounds(bounds, x, y) {
6095
+ // Returns 0 if not OB, 1 if x is OB, 2 if y is OB, 3 if both x and y are OB
5978
6096
  if (!this.contained) return 0;
5979
6097
  const [ bt, br, bb, bl ] = bounds;
5980
6098
  const [ dx, dy ] = this.disabled;
@@ -6107,8 +6225,7 @@ class Draggable {
6107
6225
 
6108
6226
  stop() {
6109
6227
  this.updateTicker.pause();
6110
- this.overshootXTicker.pause();
6111
- this.overshootYTicker.pause();
6228
+ this.overshootTicker.pause();
6112
6229
  // Pauses the in bounds onRelease animations
6113
6230
  for (let prop in this.animate.animations) this.animate.animations[prop].pause();
6114
6231
  remove(this, null, 'x');
@@ -6135,10 +6252,10 @@ class Draggable {
6135
6252
  const canScroll = this.canScroll;
6136
6253
  if (!this.containerArray && this.isOutOfBounds(scrollBounds, x, y)) {
6137
6254
  const [ st, sr, sb, sl ] = scrollBounds;
6138
- const t = round(clamp(y - st, -1e12, 0), 0);
6255
+ const t = round(clamp(y - st, -maxValue, 0), 0);
6139
6256
  const r = round(clamp(x - sr, 0, maxValue), 0);
6140
6257
  const b = round(clamp(y - sb, 0, maxValue), 0);
6141
- const l = round(clamp(x - sl, -1e12, 0), 0);
6258
+ const l = round(clamp(x - sl, -maxValue, 0), 0);
6142
6259
  new JSAnimation(scroll, {
6143
6260
  x: round(scroll.x + (l ? l - gap : r ? r + gap : 0), 0),
6144
6261
  y: round(scroll.y + (t ? t - gap : b ? b + gap : 0), 0),
@@ -6196,7 +6313,7 @@ class Draggable {
6196
6313
  */
6197
6314
  handleDown(e) {
6198
6315
  const $eTarget = /** @type {HTMLElement} */(e.target);
6199
- if (this.grabbed || /** @type {HTMLInputElement} */($eTarget).type === 'range') return;
6316
+ if (this.grabbed || /** @type {HTMLInputElement} */($eTarget).type === 'range') return;
6200
6317
 
6201
6318
  e.stopPropagation();
6202
6319
 
@@ -6415,8 +6532,7 @@ class Draggable {
6415
6532
  composition,
6416
6533
  }).init();
6417
6534
 
6418
- this.overshootXTicker.stretch(durationX).restart();
6419
- this.overshootYTicker.stretch(durationY).restart();
6535
+ this.overshootTicker.stretch(max(durationX, durationY)).restart();
6420
6536
 
6421
6537
  } else {
6422
6538
 
@@ -6546,8 +6662,7 @@ class Draggable {
6546
6662
  this.disable();
6547
6663
  this.$target.classList.remove('is-disabled');
6548
6664
  this.updateTicker.revert();
6549
- this.overshootXTicker.revert();
6550
- this.overshootYTicker.revert();
6665
+ this.overshootTicker.revert();
6551
6666
  this.resizeTicker.revert();
6552
6667
  this.animate.revert();
6553
6668
  this.resizeObserver.disconnect();
@@ -6820,10 +6935,6 @@ class Scope {
6820
6935
  */
6821
6936
  const createScope = params => new Scope(params);
6822
6937
 
6823
- /**
6824
- * @typedef {String|Number} ScrollThresholdValue
6825
- */
6826
-
6827
6938
  /**
6828
6939
  * @return {Number}
6829
6940
  */
@@ -6975,8 +7086,8 @@ class ScrollContainer {
6975
7086
  height = this.winHeight;
6976
7087
  } else {
6977
7088
  const elRect = $el.getBoundingClientRect();
6978
- width = elRect.width;
6979
- height = elRect.height;
7089
+ width = $el.clientWidth;
7090
+ height = $el.clientHeight;
6980
7091
  this.top = elRect.top;
6981
7092
  this.left = elRect.left;
6982
7093
  }
@@ -7134,45 +7245,6 @@ let scrollerIndex = 0;
7134
7245
 
7135
7246
  const debugColors$1 = ['#FF4B4B','#FF971B','#FFC730','#F9F640','#7AFF5A','#18FF74','#17E09B','#3CFFEC','#05DBE9','#33B3F1','#638CF9','#C563FE','#FF4FCF','#F93F8A'];
7136
7247
 
7137
- /**
7138
- * @typedef {Object} ScrollThresholdParam
7139
- * @property {ScrollThresholdValue} [target]
7140
- * @property {ScrollThresholdValue} [container]
7141
- */
7142
-
7143
- /**
7144
- * @callback ScrollObserverAxisCallback
7145
- * @param {ScrollObserver} self
7146
- * @return {'x'|'y'}
7147
- */
7148
-
7149
- /**
7150
- * @callback ScrollThresholdCallback
7151
- * @param {ScrollObserver} self
7152
- * @return {ScrollThresholdValue|ScrollThresholdParam}
7153
- */
7154
-
7155
- /**
7156
- * @typedef {Object} ScrollObserverParams
7157
- * @property {Number|String} [id]
7158
- * @property {Boolean|Number|String|EasingParam} [sync]
7159
- * @property {TargetsParam} [container]
7160
- * @property {TargetsParam} [target]
7161
- * @property {'x'|'y'|ScrollObserverAxisCallback|((observer: ScrollObserver) => 'x'|'y'|ScrollObserverAxisCallback)} [axis]
7162
- * @property {ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback|((observer: ScrollObserver) => ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback)} [enter]
7163
- * @property {ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback|((observer: ScrollObserver) => ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback)} [leave]
7164
- * @property {Boolean|((observer: ScrollObserver) => Boolean)} [repeat]
7165
- * @property {Boolean} [debug]
7166
- * @property {Callback<ScrollObserver>} [onEnter]
7167
- * @property {Callback<ScrollObserver>} [onLeave]
7168
- * @property {Callback<ScrollObserver>} [onEnterForward]
7169
- * @property {Callback<ScrollObserver>} [onLeaveForward]
7170
- * @property {Callback<ScrollObserver>} [onEnterBackward]
7171
- * @property {Callback<ScrollObserver>} [onLeaveBackward]
7172
- * @property {Callback<ScrollObserver>} [onUpdate]
7173
- * @property {Callback<ScrollObserver>} [onSyncComplete]
7174
- */
7175
-
7176
7248
  class ScrollObserver {
7177
7249
  /**
7178
7250
  * @param {ScrollObserverParams} parameters
@@ -7256,6 +7328,8 @@ class ScrollObserver {
7256
7328
  this.forceEnter = false;
7257
7329
  /** @type {Boolean} */
7258
7330
  this.hasEntered = false;
7331
+ /** @type {Boolean} */
7332
+ this.isReady = false;
7259
7333
  // /** @type {Array.<Number>} */
7260
7334
  // this.offsets = [];
7261
7335
  /** @type {Number} */
@@ -7344,6 +7418,8 @@ class ScrollObserver {
7344
7418
  }
7345
7419
 
7346
7420
  refresh() {
7421
+ // This flag is used to prevent running handleScroll() outside of this.refresh() with values not calculated
7422
+ this.isReady = true;
7347
7423
  this.reverted = false;
7348
7424
  const params = this._params;
7349
7425
  this.repeat = setValue(parseScrollObserverFunctionParameter(params.repeat, this), true);
@@ -7609,6 +7685,7 @@ class ScrollObserver {
7609
7685
  }
7610
7686
 
7611
7687
  handleScroll() {
7688
+ if (!this.isReady) return;
7612
7689
  const linked = this.linked;
7613
7690
  const sync = this.sync;
7614
7691
  const syncEase = this.syncEase;
@@ -7640,7 +7717,7 @@ class ScrollObserver {
7640
7717
  if (syncSmooth && isNum(syncSmooth)) {
7641
7718
  if (/** @type {Number} */(syncSmooth) < 1) {
7642
7719
  const step = 0.0001;
7643
- const snap = lp < p && p === 1 ? step : lp > p && !p ? -1e-4 : 0;
7720
+ const snap = lp < p && p === 1 ? step : lp > p && !p ? -step : 0;
7644
7721
  p = round(lerp(lp, p, interpolate(.01, .2, /** @type {Number} */(syncSmooth)), false) + snap, 6);
7645
7722
  }
7646
7723
  } else if (syncEase) {
@@ -7732,6 +7809,7 @@ class ScrollObserver {
7732
7809
  this.removeDebug();
7733
7810
  }
7734
7811
  this.reverted = true;
7812
+ this.isReady = false;
7735
7813
  return this;
7736
7814
  }
7737
7815
 
@@ -7746,7 +7824,7 @@ const onScroll = (parameters = {}) => new ScrollObserver(parameters);
7746
7824
 
7747
7825
 
7748
7826
 
7749
- const segmenter = !isUnd(Intl) && Intl.Segmenter;
7827
+ const segmenter = (typeof Intl !== 'undefined') && Intl.Segmenter;
7750
7828
  const valueRgx = /\{value\}/g;
7751
7829
  const indexRgx = /\{i\}/g;
7752
7830
  const whiteSpaceGroupRgx = /(\s+)/;
@@ -8201,9 +8279,33 @@ const text = {
8201
8279
 
8202
8280
 
8203
8281
  /**
8204
- * @param {Number|String|[Number|String,Number|String]} val
8205
- * @param {StaggerParams} params
8206
- * @return {StaggerFunction}
8282
+ * @overload
8283
+ * @param {Number} val
8284
+ * @param {StaggerParams} [params]
8285
+ * @return {StaggerFunction<Number>}
8286
+ */
8287
+ /**
8288
+ * @overload
8289
+ * @param {String} val
8290
+ * @param {StaggerParams} [params]
8291
+ * @return {StaggerFunction<String>}
8292
+ */
8293
+ /**
8294
+ * @overload
8295
+ * @param {[Number, Number]} val
8296
+ * @param {StaggerParams} [params]
8297
+ * @return {StaggerFunction<Number>}
8298
+ */
8299
+ /**
8300
+ * @overload
8301
+ * @param {[String, String]} val
8302
+ * @param {StaggerParams} [params]
8303
+ * @return {StaggerFunction<String>}
8304
+ */
8305
+ /**
8306
+ * @param {Number|String|[Number, Number]|[String, String]} val The staggered value or range
8307
+ * @param {StaggerParams} [params] The stagger parameters
8308
+ * @return {StaggerFunction<Number|String>}
8207
8309
  */
8208
8310
  const stagger = (val, params = {}) => {
8209
8311
  let values = [];