animejs 4.1.2 → 4.1.3

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/types/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * anime.js - ESM
3
- * @version v4.1.2
3
+ * @version v4.1.3
4
4
  * @author Julian Garnier
5
5
  * @license MIT
6
6
  * @copyright (c) 2025 Julian Garnier
@@ -137,12 +137,12 @@ const globals = {
137
137
  defaults,
138
138
  /** @type {Number} */
139
139
  precision: 4,
140
- /** @type {Number} */
140
+ /** @type {Number} equals 1 in ms mode, 0.001 in s mode */
141
141
  timeScale: 1,
142
142
  /** @type {Number} */
143
143
  tickThreshold: 200,
144
144
  };
145
- const globalVersions = { version: '4.1.2', engine: null };
145
+ const globalVersions = { version: '4.1.3', engine: null };
146
146
  if (isBrowser) {
147
147
  if (!win.AnimeJS)
148
148
  win.AnimeJS = [];
@@ -162,7 +162,6 @@ const toLowerCase = str => str.replace(lowerCaseRgx, '$1-$2').toLowerCase();
162
162
  * @return {Boolean}
163
163
  */
164
164
  const stringStartsWith = (str, sub) => str.indexOf(sub) === 0;
165
- // Time
166
165
  // 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.
167
166
  const now = Date.now;
168
167
  // Types checkers
@@ -864,9 +863,10 @@ class Engine extends Clock {
864
863
  this.pauseOnDocumentHidden = true;
865
864
  /** @type {DefaultsParams} */
866
865
  this.defaults = defaults;
867
- this.paused = isBrowser && doc.hidden ? true : false;
866
+ // this.paused = isBrowser && doc.hidden ? true : false;
867
+ this.paused = true;
868
868
  /** @type {Number|NodeJS.Immediate} */
869
- this.reqId = null;
869
+ this.reqId = 0;
870
870
  }
871
871
  update() {
872
872
  const time = this._currentTime = now();
@@ -896,12 +896,16 @@ class Engine extends Clock {
896
896
  }
897
897
  }
898
898
  wake() {
899
- if (this.useDefaultMainLoop && !this.reqId && !this.paused) {
899
+ if (this.useDefaultMainLoop && !this.reqId) {
900
+ // Imediatly request a tick to update engine._elapsedTime and get accurate offsetPosition calculation in timer.js
901
+ this.requestTick(now());
900
902
  this.reqId = engineTickMethod(tickEngine);
901
903
  }
902
904
  return this;
903
905
  }
904
906
  pause() {
907
+ if (!this.reqId)
908
+ return;
905
909
  this.paused = true;
906
910
  return killEngine();
907
911
  }
@@ -1033,6 +1037,8 @@ function getNodeList(v) {
1033
1037
  function parseTargets(targets) {
1034
1038
  if (isNil(targets))
1035
1039
  return /** @type {TargetsArray} */ ([]);
1040
+ if (!isBrowser)
1041
+ return /** @type {JSTargetsArray} */ (isArr(targets) && targets.flat(Infinity) || [targets]);
1036
1042
  if (isArr(targets)) {
1037
1043
  const flattened = targets.flat(Infinity);
1038
1044
  /** @type {TargetsArray} */
@@ -1074,8 +1080,6 @@ function parseTargets(targets) {
1074
1080
  }
1075
1081
  return parsed;
1076
1082
  }
1077
- if (!isBrowser)
1078
- return /** @type {JSTargetsArray} */ ([targets]);
1079
1083
  const nodeList = getNodeList(targets);
1080
1084
  if (nodeList)
1081
1085
  return /** @type {DOMTargetsArray} */ (Array.from(nodeList));
@@ -1676,10 +1680,14 @@ const composeTween = (tween, siblings) => {
1676
1680
  if (prevAbsEndTime > absoluteUpdateStartTime) {
1677
1681
  const prevChangeStartTime = prevSibling._startTime;
1678
1682
  const prevTLOffset = prevAbsEndTime - (prevChangeStartTime + prevSibling._updateDuration);
1679
- prevSibling._changeDuration = absoluteUpdateStartTime - prevTLOffset - prevChangeStartTime;
1680
- prevSibling._currentTime = prevSibling._changeDuration;
1683
+ // Rounding is necessary here to minimize floating point errors when working in seconds
1684
+ const updatedPrevChangeDuration = round(absoluteUpdateStartTime - prevTLOffset - prevChangeStartTime, 12);
1685
+ prevSibling._changeDuration = updatedPrevChangeDuration;
1686
+ prevSibling._currentTime = updatedPrevChangeDuration;
1681
1687
  prevSibling._isOverlapped = 1;
1682
- if (prevSibling._changeDuration < minValue) {
1688
+ // Override the previous tween if its new _changeDuration is lower than minValue
1689
+ // TODO: See if it's even neceseeary to test against minValue, checking for 0 might be enough
1690
+ if (updatedPrevChangeDuration < minValue) {
1683
1691
  overrideTween(prevSibling);
1684
1692
  }
1685
1693
  }
@@ -1709,7 +1717,7 @@ const composeTween = (tween, siblings) => {
1709
1717
  prevParent.cancel();
1710
1718
  // Previously, calling .cancel() on a timeline child would affect the render order of other children
1711
1719
  // Worked around this by marking it as .completed and using .pause() for safe removal in the engine loop
1712
- // This is no longer needed since timeline tween composition is now handled separatly
1720
+ // This is no longer needed since timeline tween composition is now handled separately
1713
1721
  // Keeping this here for reference
1714
1722
  // prevParent.completed = true;
1715
1723
  // prevParent.pause();
@@ -1873,13 +1881,12 @@ class Timer extends Clock {
1873
1881
  offsetPosition = parentPosition;
1874
1882
  }
1875
1883
  else {
1876
- let startTime = now();
1877
- // Make sure to tick the engine once if suspended to avoid big gaps with the following offsetPosition calculation
1878
- if (engine.paused) {
1879
- engine.requestTick(startTime);
1880
- startTime = engine._elapsedTime;
1881
- }
1882
- offsetPosition = startTime - engine._startTime;
1884
+ // Make sure to tick the engine once if not currently running to get up to date engine._elapsedTime
1885
+ // to avoid big gaps with the following offsetPosition calculation
1886
+ if (!engine.reqId)
1887
+ engine.requestTick(now());
1888
+ // Make sure to scale the offset position with globals.timeScale to properly handle seconds unit
1889
+ offsetPosition = (engine._elapsedTime - engine._startTime) * globals.timeScale;
1883
1890
  }
1884
1891
  // Timer's parameters
1885
1892
  this.id = !isUnd(id) ? id : ++timerId;
@@ -2062,6 +2069,9 @@ class Timer extends Clock {
2062
2069
  /** @return {this} */
2063
2070
  resetTime() {
2064
2071
  const timeScale = 1 / (this._speed * engine._speed);
2072
+ // TODO: See if we can safely use engine._elapsedTime here
2073
+ // if (!engine.reqId) engine.requestTick(now())
2074
+ // this._startTime = engine._elapsedTime - (this._currentTime + this._delay) * timeScale;
2065
2075
  this._startTime = now() - (this._currentTime + this._delay) * timeScale;
2066
2076
  return this;
2067
2077
  }
@@ -2256,10 +2266,10 @@ const binarySubdivide = (aX, mX1, mX2) => {
2256
2266
  return currentT;
2257
2267
  };
2258
2268
  /**
2259
- * @param {Number} [mX1]
2260
- * @param {Number} [mY1]
2261
- * @param {Number} [mX2]
2262
- * @param {Number} [mY2]
2269
+ * @param {Number} [mX1] The x coordinate of the first point
2270
+ * @param {Number} [mY1] The y coordinate of the first point
2271
+ * @param {Number} [mX2] The x coordinate of the second point
2272
+ * @param {Number} [mY2] The y coordinate of the second point
2263
2273
  * @return {EasingFunction}
2264
2274
  */
2265
2275
  const cubicBezier = (mX1 = 0.5, mY1 = 0.0, mX2 = 0.5, mY2 = 1.0) => (mX1 === mY1 && mX2 === mY2) ? none :
@@ -2279,7 +2289,7 @@ const steps = (steps = 10, fromStart) => {
2279
2289
  /**
2280
2290
  * Without parameters, the linear function creates a non-eased transition.
2281
2291
  * Parameters, if used, creates a piecewise linear easing by interpolating linearly between the specified points.
2282
- * @param {...String|Number} [args] - Points
2292
+ * @param {...(String|Number)} args - Points
2283
2293
  * @return {EasingFunction}
2284
2294
  */
2285
2295
  const linear = (...args) => {
@@ -2875,7 +2885,8 @@ class JSAnimation extends Timer {
2875
2885
  const isFromToArray = isArr(tweenToValue);
2876
2886
  const isFromToValue = isFromToArray || (hasFromvalue && hasToValue);
2877
2887
  const tweenStartTime = prevTween ? lastTweenChangeEndTime + tweenDelay : tweenDelay;
2878
- const absoluteStartTime = absoluteOffsetTime + tweenStartTime;
2888
+ // Rounding is necessary here to minimize floating point errors when working in seconds
2889
+ const absoluteStartTime = round(absoluteOffsetTime + tweenStartTime, 12);
2879
2890
  // Force a onRender callback if the animation contains at least one from value and autoplay is set to false
2880
2891
  if (!shouldTriggerRender && (hasFromvalue || isFromToArray))
2881
2892
  shouldTriggerRender = 1;
@@ -2992,7 +3003,7 @@ class JSAnimation extends Timer {
2992
3003
  shortestValue.s = cloneArray(longestValue.s);
2993
3004
  }
2994
3005
  // Tween factory
2995
- // Rounding is necessary here to minimize floating point errors
3006
+ // Rounding is necessary here to minimize floating point errors when working in seconds
2996
3007
  const tweenUpdateDuration = round(+tweenDuration || minValue, 12);
2997
3008
  /** @type {Tween} */
2998
3009
  const tween = {
@@ -3038,7 +3049,7 @@ class JSAnimation extends Timer {
3038
3049
  if (isNaN(firstTweenChangeStartTime)) {
3039
3050
  firstTweenChangeStartTime = tween._startTime;
3040
3051
  }
3041
- // Rounding is necessary here to minimize floating point errors
3052
+ // Rounding is necessary here to minimize floating point errors when working in seconds
3042
3053
  lastTweenChangeEndTime = round(tweenStartTime + tweenUpdateDuration, 12);
3043
3054
  prevTween = tween;
3044
3055
  animationAnimationLength++;
@@ -3202,7 +3213,7 @@ const WAAPIEasesLookups = {
3202
3213
  const WAAPIeases = /*#__PURE__*/ (() => {
3203
3214
  const list = {};
3204
3215
  for (let type in easeTypes)
3205
- list[type] = a => easeTypes[type](easeInPower(a));
3216
+ list[type] = (/** @type {String|Number} */ p) => easeTypes[type](easeInPower(p));
3206
3217
  return /** @type {Record<String, EasingFunction>} */ (list);
3207
3218
  })();
3208
3219
  /**
@@ -3241,47 +3252,6 @@ const parseWAAPIEasing = (ease) => {
3241
3252
  }
3242
3253
  return parsedEase;
3243
3254
  };
3244
- /**
3245
- * @typedef {String|Number|Array<String>|Array<Number>} WAAPITweenValue
3246
- */
3247
- /**
3248
- * @callback WAAPIFunctionvalue
3249
- * @param {DOMTarget} target - The animated target
3250
- * @param {Number} index - The target index
3251
- * @param {Number} length - The total number of animated targets
3252
- * @return {WAAPITweenValue}
3253
- */
3254
- /**
3255
- * @typedef {WAAPITweenValue|WAAPIFunctionvalue|Array<String|Number|WAAPIFunctionvalue>} WAAPIKeyframeValue
3256
- */
3257
- /**
3258
- * @typedef {(animation: WAAPIAnimation) => void} WAAPICallback
3259
- */
3260
- /**
3261
- * @typedef {Object} WAAPITweenOptions
3262
- * @property {WAAPIKeyframeValue} [to]
3263
- * @property {WAAPIKeyframeValue} [from]
3264
- * @property {Number|WAAPIFunctionvalue} [duration]
3265
- * @property {Number|WAAPIFunctionvalue} [delay]
3266
- * @property {EasingParam} [ease]
3267
- * @property {CompositeOperation} [composition]
3268
- */
3269
- /**
3270
- * @typedef {Object} WAAPIAnimationOptions
3271
- * @property {Number|Boolean} [loop]
3272
- * @property {Boolean} [Reversed]
3273
- * @property {Boolean} [Alternate]
3274
- * @property {Boolean|ScrollObserver} [autoplay]
3275
- * @property {Number} [playbackRate]
3276
- * @property {Number|WAAPIFunctionvalue} [duration]
3277
- * @property {Number|WAAPIFunctionvalue} [delay]
3278
- * @property {EasingParam} [ease]
3279
- * @property {CompositeOperation} [composition]
3280
- * @property {WAAPICallback} [onComplete]
3281
- */
3282
- /**
3283
- * @typedef {Record<String, WAAPIKeyframeValue | WAAPIAnimationOptions | Boolean | ScrollObserver | WAAPICallback | EasingParam | WAAPITweenOptions> & WAAPIAnimationOptions} WAAPIAnimationParams
3284
- */
3285
3255
  const transformsShorthands = ['x', 'y', 'z'];
3286
3256
  const commonDefaultPXProperties = [
3287
3257
  'perspective',
@@ -3575,7 +3545,7 @@ class WAAPIAnimation {
3575
3545
  * @return {this}
3576
3546
  */
3577
3547
  forEach(callback) {
3578
- const cb = isStr(callback) ? a => a[callback]() : callback;
3548
+ const cb = isStr(callback) ? (/** @type {globalThis.Animation} */ a) => a[callback]() : callback;
3579
3549
  this.animations.forEach(cb);
3580
3550
  return this;
3581
3551
  }
@@ -4076,9 +4046,6 @@ const utils = {
4076
4046
  };
4077
4047
 
4078
4048
 
4079
- /**
4080
- * @typedef {Number|String|Function} TimePosition
4081
- */
4082
4049
  /**
4083
4050
  * Timeline's children offsets positions parser
4084
4051
  * @param {Timeline} timeline
@@ -4095,7 +4062,7 @@ const getPrevChildOffset = (timeline, timePosition) => {
4095
4062
  };
4096
4063
  /**
4097
4064
  * @param {Timeline} timeline
4098
- * @param {TimePosition} [timePosition]
4065
+ * @param {TimelinePosition} [timePosition]
4099
4066
  * @return {Number}
4100
4067
  */
4101
4068
  const parseTimelinePosition = (timeline, timePosition) => {
@@ -4201,17 +4168,17 @@ class Timeline extends Timer {
4201
4168
  * @overload
4202
4169
  * @param {TargetsParam} a1
4203
4170
  * @param {AnimationParams} a2
4204
- * @param {TimePosition} [a3]
4171
+ * @param {TimelinePosition|StaggerFunction<Number|String>} [a3]
4205
4172
  * @return {this}
4206
4173
  *
4207
4174
  * @overload
4208
4175
  * @param {TimerParams} a1
4209
- * @param {TimePosition} [a2]
4176
+ * @param {TimelinePosition} [a2]
4210
4177
  * @return {this}
4211
4178
  *
4212
4179
  * @param {TargetsParam|TimerParams} a1
4213
- * @param {AnimationParams|TimePosition} a2
4214
- * @param {TimePosition} [a3]
4180
+ * @param {TimelinePosition|AnimationParams} a2
4181
+ * @param {TimelinePosition|StaggerFunction<Number|String>} [a3]
4215
4182
  */
4216
4183
  add(a1, a2, a3) {
4217
4184
  const isAnim = isObj(a2);
@@ -4222,7 +4189,7 @@ class Timeline extends Timer {
4222
4189
  const childParams = /** @type {AnimationParams} */ (a2);
4223
4190
  // Check for function for children stagger positions
4224
4191
  if (isFnc(a3)) {
4225
- const staggeredPosition = /** @type {Function} */ (a3);
4192
+ const staggeredPosition = a3;
4226
4193
  const parsedTargetsArray = parseTargets(/** @type {TargetsParam} */ (a1));
4227
4194
  // Store initial duration before adding new children that will change the duration
4228
4195
  const tlDuration = this.duration;
@@ -4231,7 +4198,8 @@ class Timeline extends Timer {
4231
4198
  // Store the original id in order to add specific indexes to the new animations ids
4232
4199
  const id = childParams.id;
4233
4200
  let i = 0;
4234
- const parsedLength = parsedTargetsArray.length;
4201
+ /** @type {Number} */
4202
+ const parsedLength = (parsedTargetsArray.length);
4235
4203
  parsedTargetsArray.forEach((/** @type {Target} */ target) => {
4236
4204
  // Create a new parameter object for each staggered children
4237
4205
  const staggeredChildParams = { ...childParams };
@@ -4240,7 +4208,7 @@ class Timeline extends Timer {
4240
4208
  this.iterationDuration = tlIterationDuration;
4241
4209
  if (!isUnd(id))
4242
4210
  staggeredChildParams.id = id + '-' + i;
4243
- addTlChild(staggeredChildParams, this, staggeredPosition(target, i, parsedLength, this), target, i, parsedLength);
4211
+ addTlChild(staggeredChildParams, this, parseTimelinePosition(this, staggeredPosition(target, i, parsedLength, this)), target, i, parsedLength);
4244
4212
  i++;
4245
4213
  });
4246
4214
  }
@@ -4252,7 +4220,7 @@ class Timeline extends Timer {
4252
4220
  else {
4253
4221
  // It's a Timer
4254
4222
  addTlChild(
4255
- /** @type TimerParams */ (a1), this, parseTimelinePosition(this, /** @type TimePosition */ (a2)));
4223
+ /** @type TimerParams */ (a1), this, parseTimelinePosition(this, a2));
4256
4224
  }
4257
4225
  return this.init(1); // 1 = internalRender
4258
4226
  }
@@ -4260,21 +4228,21 @@ class Timeline extends Timer {
4260
4228
  /**
4261
4229
  * @overload
4262
4230
  * @param {Tickable} [synced]
4263
- * @param {TimePosition} [position]
4231
+ * @param {TimelinePosition} [position]
4264
4232
  * @return {this}
4265
4233
  *
4266
4234
  * @overload
4267
4235
  * @param {globalThis.Animation} [synced]
4268
- * @param {TimePosition} [position]
4236
+ * @param {TimelinePosition} [position]
4269
4237
  * @return {this}
4270
4238
  *
4271
4239
  * @overload
4272
4240
  * @param {WAAPIAnimation} [synced]
4273
- * @param {TimePosition} [position]
4241
+ * @param {TimelinePosition} [position]
4274
4242
  * @return {this}
4275
4243
  *
4276
4244
  * @param {Tickable|WAAPIAnimation|globalThis.Animation} [synced]
4277
- * @param {TimePosition} [position]
4245
+ * @param {TimelinePosition} [position]
4278
4246
  */
4279
4247
  sync(synced, position) {
4280
4248
  if (isUnd(synced) || synced && isUnd(synced.pause))
@@ -4286,7 +4254,7 @@ class Timeline extends Timer {
4286
4254
  /**
4287
4255
  * @param {TargetsParam} targets
4288
4256
  * @param {AnimationParams} parameters
4289
- * @param {TimePosition} [position]
4257
+ * @param {TimelinePosition} [position]
4290
4258
  * @return {this}
4291
4259
  */
4292
4260
  set(targets, parameters, position) {
@@ -4298,7 +4266,7 @@ class Timeline extends Timer {
4298
4266
  }
4299
4267
  /**
4300
4268
  * @param {Callback<Timer>} callback
4301
- * @param {TimePosition} [position]
4269
+ * @param {TimelinePosition} [position]
4302
4270
  * @return {this}
4303
4271
  */
4304
4272
  call(callback, position) {
@@ -4308,14 +4276,14 @@ class Timeline extends Timer {
4308
4276
  }
4309
4277
  /**
4310
4278
  * @param {String} labelName
4311
- * @param {TimePosition} [position]
4279
+ * @param {TimelinePosition} [position]
4312
4280
  * @return {this}
4313
4281
  *
4314
4282
  */
4315
4283
  label(labelName, position) {
4316
4284
  if (isUnd(labelName) || labelName && !isStr(labelName))
4317
4285
  return this;
4318
- this.labels[labelName] = parseTimelinePosition(this, /** @type TimePosition */ (position));
4286
+ this.labels[labelName] = parseTimelinePosition(this, position);
4319
4287
  return this;
4320
4288
  }
4321
4289
  /**
@@ -4383,11 +4351,39 @@ class Animatable {
4383
4351
  constructor(targets, parameters) {
4384
4352
  if (scope.current)
4385
4353
  scope.current.register(this);
4354
+ const beginHandler = () => {
4355
+ if (this.callbacks.completed)
4356
+ this.callbacks.reset();
4357
+ this.callbacks.play();
4358
+ };
4359
+ const pauseHandler = () => {
4360
+ if (this.callbacks.completed)
4361
+ return;
4362
+ let paused = true;
4363
+ for (let name in this.animations) {
4364
+ const anim = this.animations[name];
4365
+ if (!anim.paused && paused) {
4366
+ paused = false;
4367
+ break;
4368
+ }
4369
+ }
4370
+ if (paused) {
4371
+ this.callbacks.complete();
4372
+ }
4373
+ };
4386
4374
  /** @type {AnimationParams} */
4387
- const globalParams = {};
4375
+ const globalParams = {
4376
+ onBegin: beginHandler,
4377
+ onComplete: pauseHandler,
4378
+ onPause: pauseHandler,
4379
+ };
4380
+ /** @type {AnimationParams} */
4381
+ const callbacksAnimationParams = { v: 1, autoplay: false };
4388
4382
  const properties = {};
4389
4383
  this.targets = [];
4390
4384
  this.animations = {};
4385
+ /** @type {JSAnimation|null} */
4386
+ this.callbacks = null;
4391
4387
  if (isUnd(targets) || isUnd(parameters))
4392
4388
  return;
4393
4389
  for (let propName in parameters) {
@@ -4395,10 +4391,14 @@ class Animatable {
4395
4391
  if (isKey(propName)) {
4396
4392
  properties[propName] = paramValue;
4397
4393
  }
4394
+ else if (stringStartsWith(propName, 'on')) {
4395
+ callbacksAnimationParams[propName] = paramValue;
4396
+ }
4398
4397
  else {
4399
4398
  globalParams[propName] = paramValue;
4400
4399
  }
4401
4400
  }
4401
+ this.callbacks = new JSAnimation({ v: 0 }, callbacksAnimationParams);
4402
4402
  for (let propName in properties) {
4403
4403
  const propValue = properties[propName];
4404
4404
  const isObjValue = isObj(propValue);
@@ -4465,6 +4465,8 @@ class Animatable {
4465
4465
  }
4466
4466
  this.animations = {};
4467
4467
  this.targets.length = 0;
4468
+ if (this.callbacks)
4469
+ this.callbacks.revert();
4468
4470
  return this;
4469
4471
  }
4470
4472
  }
@@ -4480,6 +4482,7 @@ const createAnimatable = (targets, parameters) => /** @type {AnimatableObject} *
4480
4482
  * Spring ease solver adapted from https://webkit.org/demos/spring/spring.js
4481
4483
  * Webkit Copyright © 2016 Apple Inc
4482
4484
  */
4485
+ const maxSpringParamValue = K * 10;
4483
4486
  /**
4484
4487
  * @typedef {Object} SpringParams
4485
4488
  * @property {Number} [mass=1] - Mass, default 1
@@ -4498,10 +4501,10 @@ class Spring {
4498
4501
  this.maxDuration = 60000; // The maximum allowed spring duration in ms (default 1 min)
4499
4502
  this.maxRestSteps = this.restDuration / this.timeStep / K; // How many steps allowed after reaching restThreshold before stopping the duration calculation
4500
4503
  this.maxIterations = this.maxDuration / this.timeStep / K; // Calculate the maximum iterations allowed based on maxDuration
4501
- this.m = clamp(setValue(parameters.mass, 1), 0, K);
4502
- this.s = clamp(setValue(parameters.stiffness, 100), 1, K);
4503
- this.d = clamp(setValue(parameters.damping, 10), .1, K);
4504
- this.v = clamp(setValue(parameters.velocity, 0), -1e3, K);
4504
+ this.m = clamp(setValue(parameters.mass, 1), 0, maxSpringParamValue);
4505
+ this.s = clamp(setValue(parameters.stiffness, 100), 1, maxSpringParamValue);
4506
+ this.d = clamp(setValue(parameters.damping, 10), .1, maxSpringParamValue);
4507
+ this.v = clamp(setValue(parameters.velocity, 0), -1e4, maxSpringParamValue);
4505
4508
  this.w0 = 0;
4506
4509
  this.zeta = 0;
4507
4510
  this.wd = 0;
@@ -4550,28 +4553,28 @@ class Spring {
4550
4553
  return this.m;
4551
4554
  }
4552
4555
  set mass(v) {
4553
- this.m = clamp(setValue(v, 1), 0, K);
4556
+ this.m = clamp(setValue(v, 1), 0, maxSpringParamValue);
4554
4557
  this.compute();
4555
4558
  }
4556
4559
  get stiffness() {
4557
4560
  return this.s;
4558
4561
  }
4559
4562
  set stiffness(v) {
4560
- this.s = clamp(setValue(v, 100), 1, K);
4563
+ this.s = clamp(setValue(v, 100), 1, maxSpringParamValue);
4561
4564
  this.compute();
4562
4565
  }
4563
4566
  get damping() {
4564
4567
  return this.d;
4565
4568
  }
4566
4569
  set damping(v) {
4567
- this.d = clamp(setValue(v, 10), .1, K);
4570
+ this.d = clamp(setValue(v, 10), .1, maxSpringParamValue);
4568
4571
  this.compute();
4569
4572
  }
4570
4573
  get velocity() {
4571
4574
  return this.v;
4572
4575
  }
4573
4576
  set velocity(v) {
4574
- this.v = clamp(setValue(v, 0), -1e3, K);
4577
+ this.v = clamp(setValue(v, 0), -1e4, maxSpringParamValue);
4575
4578
  this.compute();
4576
4579
  }
4577
4580
  }
@@ -4872,36 +4875,27 @@ class Draggable {
4872
4875
  this.touchActionStyles = null;
4873
4876
  this.transforms = new Transforms(this.$target);
4874
4877
  this.overshootCoords = { x: 0, y: 0 };
4875
- this.overshootXTicker = new Timer({ autoplay: false }, null, 0).init();
4876
- this.overshootYTicker = new Timer({ autoplay: false }, null, 0).init();
4877
- this.updateTicker = new Timer({ autoplay: false }, null, 0).init();
4878
- this.overshootXTicker.onUpdate = () => {
4879
- if (this.disabled[0])
4880
- return;
4881
- this.updated = true;
4882
- this.manual = true;
4883
- this.animate[this.xProp](this.overshootCoords.x, 0);
4884
- };
4885
- this.overshootXTicker.onComplete = () => {
4886
- if (this.disabled[0])
4887
- return;
4888
- this.manual = false;
4889
- this.animate[this.xProp](this.overshootCoords.x, 0);
4890
- };
4891
- this.overshootYTicker.onUpdate = () => {
4892
- if (this.disabled[1])
4893
- return;
4894
- this.updated = true;
4895
- this.manual = true;
4896
- this.animate[this.yProp](this.overshootCoords.y, 0);
4897
- };
4898
- this.overshootYTicker.onComplete = () => {
4899
- if (this.disabled[1])
4900
- return;
4901
- this.manual = false;
4902
- this.animate[this.yProp](this.overshootCoords.y, 0);
4903
- };
4904
- this.updateTicker.onUpdate = () => this.update();
4878
+ this.overshootTicker = new Timer({
4879
+ autoplay: false,
4880
+ onUpdate: () => {
4881
+ this.updated = true;
4882
+ this.manual = true;
4883
+ // Use a duration of 1 to prevent the animatable from completing immediately to prevent issues with onSettle()
4884
+ // https://github.com/juliangarnier/anime/issues/1045
4885
+ if (!this.disabled[0])
4886
+ this.animate[this.xProp](this.overshootCoords.x, 1);
4887
+ if (!this.disabled[1])
4888
+ this.animate[this.yProp](this.overshootCoords.y, 1);
4889
+ },
4890
+ onComplete: () => {
4891
+ this.manual = false;
4892
+ if (!this.disabled[0])
4893
+ this.animate[this.xProp](this.overshootCoords.x, 0);
4894
+ if (!this.disabled[1])
4895
+ this.animate[this.yProp](this.overshootCoords.y, 0);
4896
+ },
4897
+ }, null, 0).init();
4898
+ this.updateTicker = new Timer({ autoplay: false, onUpdate: () => this.update() }, null, 0).init();
4905
4899
  this.contained = !isUnd(container);
4906
4900
  this.manual = false;
4907
4901
  this.grabbed = false;
@@ -4912,7 +4906,7 @@ class Draggable {
4912
4906
  this.enabled = false;
4913
4907
  this.initialized = false;
4914
4908
  this.activeProp = this.disabled[1] ? xProp : yProp;
4915
- this.animate.animations[this.activeProp].onRender = () => {
4909
+ this.animate.callbacks.onRender = () => {
4916
4910
  const hasUpdated = this.updated;
4917
4911
  const hasMoved = this.grabbed && hasUpdated;
4918
4912
  const hasReleased = !hasMoved && this.released;
@@ -4924,7 +4918,8 @@ class Draggable {
4924
4918
  this.deltaY = dy;
4925
4919
  this.coords[2] = x;
4926
4920
  this.coords[3] = y;
4927
- // Check if dx or dy are not 0 to check if the draggable has actually moved https://github.com/juliangarnier/anime/issues/1032
4921
+ // Check if dx or dy are not 0 to check if the draggable has actually moved
4922
+ // https://github.com/juliangarnier/anime/issues/1032
4928
4923
  if (hasUpdated && (dx || dy)) {
4929
4924
  this.onUpdate(this);
4930
4925
  }
@@ -4936,9 +4931,9 @@ class Draggable {
4936
4931
  this.angle = atan2(dy, dx);
4937
4932
  }
4938
4933
  };
4939
- this.animate.animations[this.activeProp].onComplete = () => {
4934
+ this.animate.callbacks.onComplete = () => {
4940
4935
  if ((!this.grabbed && this.released)) {
4941
- // Set eleased to false before calling onSettle to avoid recursion
4936
+ // Set released to false before calling onSettle to avoid recursion
4942
4937
  this.released = false;
4943
4938
  }
4944
4939
  if (!this.manual) {
@@ -5008,7 +5003,7 @@ class Draggable {
5008
5003
  if (this.disabled[0])
5009
5004
  return;
5010
5005
  const v = round(x, 5);
5011
- this.overshootXTicker.pause();
5006
+ this.overshootTicker.pause();
5012
5007
  this.manual = true;
5013
5008
  this.updated = !muteUpdateCallback;
5014
5009
  this.destX = v;
@@ -5026,7 +5021,7 @@ class Draggable {
5026
5021
  if (this.disabled[1])
5027
5022
  return;
5028
5023
  const v = round(y, 5);
5029
- this.overshootYTicker.pause();
5024
+ this.overshootTicker.pause();
5030
5025
  this.manual = true;
5031
5026
  this.updated = !muteUpdateCallback;
5032
5027
  this.destY = v;
@@ -5073,6 +5068,10 @@ class Draggable {
5073
5068
  }
5074
5069
  updateBoundingValues() {
5075
5070
  const $container = this.$container;
5071
+ // Return early if no $container defined to prevents error when reading scrollWidth / scrollHeight
5072
+ // https://github.com/juliangarnier/anime/issues/1064
5073
+ if (!$container)
5074
+ return;
5076
5075
  const cx = this.x;
5077
5076
  const cy = this.y;
5078
5077
  const cx2 = this.coords[2];
@@ -5142,14 +5141,13 @@ class Draggable {
5142
5141
  this.setY(cy, true);
5143
5142
  }
5144
5143
  /**
5145
- * Returns 0 if not OB, 1 if x is OB, 2 if y is OB, 3 if both x and y are OB
5146
- *
5147
5144
  * @param {Array} bounds
5148
5145
  * @param {Number} x
5149
5146
  * @param {Number} y
5150
5147
  * @return {Number}
5151
5148
  */
5152
5149
  isOutOfBounds(bounds, x, y) {
5150
+ // Returns 0 if not OB, 1 if x is OB, 2 if y is OB, 3 if both x and y are OB
5153
5151
  if (!this.contained)
5154
5152
  return 0;
5155
5153
  const [bt, br, bb, bl] = bounds;
@@ -5280,8 +5278,7 @@ class Draggable {
5280
5278
  }
5281
5279
  stop() {
5282
5280
  this.updateTicker.pause();
5283
- this.overshootXTicker.pause();
5284
- this.overshootYTicker.pause();
5281
+ this.overshootTicker.pause();
5285
5282
  // Pauses the in bounds onRelease animations
5286
5283
  for (let prop in this.animate.animations)
5287
5284
  this.animate.animations[prop].pause();
@@ -5368,7 +5365,7 @@ class Draggable {
5368
5365
  */
5369
5366
  handleDown(e) {
5370
5367
  const $eTarget = /** @type {HTMLElement} */ (e.target);
5371
- if (this.grabbed || /** @type {HTMLInputElement} */ ($eTarget).type === 'range')
5368
+ if (this.grabbed || /** @type {HTMLInputElement} */ ($eTarget).type === 'range')
5372
5369
  return;
5373
5370
  e.stopPropagation();
5374
5371
  this.grabbed = true;
@@ -5567,8 +5564,7 @@ class Draggable {
5567
5564
  ease: releaseEase,
5568
5565
  composition,
5569
5566
  }).init();
5570
- this.overshootXTicker.stretch(durationX).restart();
5571
- this.overshootYTicker.stretch(durationY).restart();
5567
+ this.overshootTicker.stretch(max(durationX, durationY)).restart();
5572
5568
  }
5573
5569
  else {
5574
5570
  if (!disabledX)
@@ -5688,8 +5684,7 @@ class Draggable {
5688
5684
  this.disable();
5689
5685
  this.$target.classList.remove('is-disabled');
5690
5686
  this.updateTicker.revert();
5691
- this.overshootXTicker.revert();
5692
- this.overshootYTicker.revert();
5687
+ this.overshootTicker.revert();
5693
5688
  this.resizeTicker.revert();
5694
5689
  this.animate.revert();
5695
5690
  this.resizeObserver.disconnect();
@@ -5961,9 +5956,6 @@ class Scope {
5961
5956
  */
5962
5957
  const createScope = params => new Scope(params);
5963
5958
 
5964
- /**
5965
- * @typedef {String|Number} ScrollThresholdValue
5966
- */
5967
5959
  /**
5968
5960
  * @return {Number}
5969
5961
  */
@@ -6112,8 +6104,8 @@ class ScrollContainer {
6112
6104
  }
6113
6105
  else {
6114
6106
  const elRect = $el.getBoundingClientRect();
6115
- width = elRect.width;
6116
- height = elRect.height;
6107
+ width = $el.clientWidth;
6108
+ height = $el.clientHeight;
6117
6109
  this.top = elRect.top;
6118
6110
  this.left = elRect.left;
6119
6111
  }
@@ -6266,41 +6258,6 @@ const getAnimationDomTarget = linked => {
6266
6258
  };
6267
6259
  let scrollerIndex = 0;
6268
6260
  const debugColors$1 = ['#FF4B4B', '#FF971B', '#FFC730', '#F9F640', '#7AFF5A', '#18FF74', '#17E09B', '#3CFFEC', '#05DBE9', '#33B3F1', '#638CF9', '#C563FE', '#FF4FCF', '#F93F8A'];
6269
- /**
6270
- * @typedef {Object} ScrollThresholdParam
6271
- * @property {ScrollThresholdValue} [target]
6272
- * @property {ScrollThresholdValue} [container]
6273
- */
6274
- /**
6275
- * @callback ScrollObserverAxisCallback
6276
- * @param {ScrollObserver} self
6277
- * @return {'x'|'y'}
6278
- */
6279
- /**
6280
- * @callback ScrollThresholdCallback
6281
- * @param {ScrollObserver} self
6282
- * @return {ScrollThresholdValue|ScrollThresholdParam}
6283
- */
6284
- /**
6285
- * @typedef {Object} ScrollObserverParams
6286
- * @property {Number|String} [id]
6287
- * @property {Boolean|Number|String|EasingParam} [sync]
6288
- * @property {TargetsParam} [container]
6289
- * @property {TargetsParam} [target]
6290
- * @property {'x'|'y'|ScrollObserverAxisCallback|((observer: ScrollObserver) => 'x'|'y'|ScrollObserverAxisCallback)} [axis]
6291
- * @property {ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback|((observer: ScrollObserver) => ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback)} [enter]
6292
- * @property {ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback|((observer: ScrollObserver) => ScrollThresholdValue|ScrollThresholdParam|ScrollThresholdCallback)} [leave]
6293
- * @property {Boolean|((observer: ScrollObserver) => Boolean)} [repeat]
6294
- * @property {Boolean} [debug]
6295
- * @property {Callback<ScrollObserver>} [onEnter]
6296
- * @property {Callback<ScrollObserver>} [onLeave]
6297
- * @property {Callback<ScrollObserver>} [onEnterForward]
6298
- * @property {Callback<ScrollObserver>} [onLeaveForward]
6299
- * @property {Callback<ScrollObserver>} [onEnterBackward]
6300
- * @property {Callback<ScrollObserver>} [onLeaveBackward]
6301
- * @property {Callback<ScrollObserver>} [onUpdate]
6302
- * @property {Callback<ScrollObserver>} [onSyncComplete]
6303
- */
6304
6261
  class ScrollObserver {
6305
6262
  /**
6306
6263
  * @param {ScrollObserverParams} parameters
@@ -6861,7 +6818,7 @@ class ScrollObserver {
6861
6818
  const onScroll = (parameters = {}) => new ScrollObserver(parameters);
6862
6819
 
6863
6820
 
6864
- const segmenter = !isUnd(Intl) && Intl.Segmenter;
6821
+ const segmenter = (typeof Intl !== 'undefined') && Intl.Segmenter;
6865
6822
  const valueRgx = /\{value\}/g;
6866
6823
  const indexRgx = /\{i\}/g;
6867
6824
  const whiteSpaceGroupRgx = /(\s+)/;
@@ -7328,9 +7285,33 @@ const text = {
7328
7285
 
7329
7286
 
7330
7287
  /**
7331
- * @param {Number|String|[Number|String,Number|String]} val
7332
- * @param {StaggerParams} params
7333
- * @return {StaggerFunction}
7288
+ * @overload
7289
+ * @param {Number} val
7290
+ * @param {StaggerParams} [params]
7291
+ * @return {StaggerFunction<Number>}
7292
+ */
7293
+ /**
7294
+ * @overload
7295
+ * @param {String} val
7296
+ * @param {StaggerParams} [params]
7297
+ * @return {StaggerFunction<String>}
7298
+ */
7299
+ /**
7300
+ * @overload
7301
+ * @param {[Number, Number]} val
7302
+ * @param {StaggerParams} [params]
7303
+ * @return {StaggerFunction<Number>}
7304
+ */
7305
+ /**
7306
+ * @overload
7307
+ * @param {[String, String]} val
7308
+ * @param {StaggerParams} [params]
7309
+ * @return {StaggerFunction<String>}
7310
+ */
7311
+ /**
7312
+ * @param {Number|String|[Number, Number]|[String, String]} val The staggered value or range
7313
+ * @param {StaggerParams} [params] The stagger parameters
7314
+ * @return {StaggerFunction<Number|String>}
7334
7315
  */
7335
7316
  const stagger = (val, params = {}) => {
7336
7317
  let values = [];