animejs 4.3.6 → 4.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +6 -9
  2. package/dist/bundles/anime.esm.js +973 -391
  3. package/dist/bundles/anime.esm.min.js +2 -2
  4. package/dist/bundles/anime.umd.js +977 -390
  5. package/dist/bundles/anime.umd.min.js +2 -2
  6. package/dist/modules/animatable/animatable.cjs +1 -1
  7. package/dist/modules/animatable/animatable.js +2 -2
  8. package/dist/modules/animatable/index.cjs +1 -1
  9. package/dist/modules/animatable/index.js +1 -1
  10. package/dist/modules/animation/additive.cjs +1 -1
  11. package/dist/modules/animation/additive.js +1 -1
  12. package/dist/modules/animation/animation.cjs +38 -16
  13. package/dist/modules/animation/animation.d.ts +2 -2
  14. package/dist/modules/animation/animation.js +42 -20
  15. package/dist/modules/animation/composition.cjs +1 -1
  16. package/dist/modules/animation/composition.js +3 -3
  17. package/dist/modules/animation/index.cjs +1 -1
  18. package/dist/modules/animation/index.js +1 -1
  19. package/dist/modules/core/clock.cjs +1 -1
  20. package/dist/modules/core/clock.js +1 -1
  21. package/dist/modules/core/colors.cjs +1 -1
  22. package/dist/modules/core/colors.js +1 -1
  23. package/dist/modules/core/consts.cjs +3 -9
  24. package/dist/modules/core/consts.d.ts +1 -5
  25. package/dist/modules/core/consts.js +4 -8
  26. package/dist/modules/core/globals.cjs +16 -5
  27. package/dist/modules/core/globals.d.ts +22 -1
  28. package/dist/modules/core/globals.js +18 -6
  29. package/dist/modules/core/helpers.cjs +7 -10
  30. package/dist/modules/core/helpers.js +8 -11
  31. package/dist/modules/core/render.cjs +7 -34
  32. package/dist/modules/core/render.js +8 -35
  33. package/dist/modules/core/styles.cjs +53 -32
  34. package/dist/modules/core/styles.d.ts +1 -0
  35. package/dist/modules/core/styles.js +55 -35
  36. package/dist/modules/core/targets.cjs +1 -1
  37. package/dist/modules/core/targets.js +1 -1
  38. package/dist/modules/core/transforms.cjs +129 -13
  39. package/dist/modules/core/transforms.d.ts +1 -0
  40. package/dist/modules/core/transforms.js +130 -15
  41. package/dist/modules/core/units.cjs +1 -1
  42. package/dist/modules/core/units.js +1 -1
  43. package/dist/modules/core/values.cjs +68 -8
  44. package/dist/modules/core/values.d.ts +5 -2
  45. package/dist/modules/core/values.js +69 -11
  46. package/dist/modules/draggable/draggable.cjs +1 -1
  47. package/dist/modules/draggable/draggable.js +1 -1
  48. package/dist/modules/draggable/index.cjs +1 -1
  49. package/dist/modules/draggable/index.js +1 -1
  50. package/dist/modules/easings/cubic-bezier/index.cjs +1 -1
  51. package/dist/modules/easings/cubic-bezier/index.js +1 -1
  52. package/dist/modules/easings/eases/index.cjs +1 -1
  53. package/dist/modules/easings/eases/index.js +1 -1
  54. package/dist/modules/easings/eases/parser.cjs +1 -1
  55. package/dist/modules/easings/eases/parser.js +1 -1
  56. package/dist/modules/easings/index.cjs +1 -1
  57. package/dist/modules/easings/index.js +1 -1
  58. package/dist/modules/easings/irregular/index.cjs +1 -1
  59. package/dist/modules/easings/irregular/index.js +1 -1
  60. package/dist/modules/easings/linear/index.cjs +1 -1
  61. package/dist/modules/easings/linear/index.js +1 -1
  62. package/dist/modules/easings/none.cjs +1 -1
  63. package/dist/modules/easings/none.js +1 -1
  64. package/dist/modules/easings/spring/index.cjs +1 -1
  65. package/dist/modules/easings/spring/index.js +1 -1
  66. package/dist/modules/easings/steps/index.cjs +1 -1
  67. package/dist/modules/easings/steps/index.js +1 -1
  68. package/dist/modules/engine/engine.cjs +1 -1
  69. package/dist/modules/engine/engine.js +1 -1
  70. package/dist/modules/engine/index.cjs +1 -1
  71. package/dist/modules/engine/index.js +1 -1
  72. package/dist/modules/events/index.cjs +1 -1
  73. package/dist/modules/events/index.js +1 -1
  74. package/dist/modules/events/scroll.cjs +1 -1
  75. package/dist/modules/events/scroll.js +1 -1
  76. package/dist/modules/index.cjs +9 -1
  77. package/dist/modules/index.d.ts +1 -0
  78. package/dist/modules/index.js +4 -1
  79. package/dist/modules/layout/index.cjs +1 -1
  80. package/dist/modules/layout/index.js +1 -1
  81. package/dist/modules/layout/layout.cjs +29 -25
  82. package/dist/modules/layout/layout.d.ts +4 -3
  83. package/dist/modules/layout/layout.js +30 -26
  84. package/dist/modules/scope/index.cjs +1 -1
  85. package/dist/modules/scope/index.js +1 -1
  86. package/dist/modules/scope/scope.cjs +1 -1
  87. package/dist/modules/scope/scope.js +1 -1
  88. package/dist/modules/svg/drawable.cjs +1 -1
  89. package/dist/modules/svg/drawable.js +1 -1
  90. package/dist/modules/svg/helpers.cjs +1 -1
  91. package/dist/modules/svg/helpers.js +1 -1
  92. package/dist/modules/svg/index.cjs +1 -1
  93. package/dist/modules/svg/index.js +1 -1
  94. package/dist/modules/svg/morphto.cjs +3 -6
  95. package/dist/modules/svg/morphto.js +3 -6
  96. package/dist/modules/svg/motionpath.cjs +1 -1
  97. package/dist/modules/svg/motionpath.js +1 -1
  98. package/dist/modules/text/index.cjs +3 -1
  99. package/dist/modules/text/index.d.ts +1 -0
  100. package/dist/modules/text/index.js +2 -1
  101. package/dist/modules/text/scramble.cjs +272 -0
  102. package/dist/modules/text/scramble.d.ts +3 -0
  103. package/dist/modules/text/scramble.js +270 -0
  104. package/dist/modules/text/split.cjs +5 -5
  105. package/dist/modules/text/split.d.ts +5 -5
  106. package/dist/modules/text/split.js +5 -5
  107. package/dist/modules/timeline/index.cjs +1 -1
  108. package/dist/modules/timeline/index.js +1 -1
  109. package/dist/modules/timeline/position.cjs +1 -1
  110. package/dist/modules/timeline/position.js +1 -1
  111. package/dist/modules/timeline/timeline.cjs +36 -18
  112. package/dist/modules/timeline/timeline.d.ts +6 -5
  113. package/dist/modules/timeline/timeline.js +37 -19
  114. package/dist/modules/timer/index.cjs +1 -1
  115. package/dist/modules/timer/index.js +1 -1
  116. package/dist/modules/timer/timer.cjs +8 -12
  117. package/dist/modules/timer/timer.d.ts +2 -0
  118. package/dist/modules/timer/timer.js +9 -13
  119. package/dist/modules/types/index.d.ts +76 -8
  120. package/dist/modules/utils/chainable.cjs +8 -5
  121. package/dist/modules/utils/chainable.js +8 -5
  122. package/dist/modules/utils/index.cjs +5 -1
  123. package/dist/modules/utils/index.d.ts +1 -0
  124. package/dist/modules/utils/index.js +2 -1
  125. package/dist/modules/utils/number.cjs +1 -1
  126. package/dist/modules/utils/number.js +1 -1
  127. package/dist/modules/utils/random.cjs +1 -1
  128. package/dist/modules/utils/random.js +1 -1
  129. package/dist/modules/utils/stagger.cjs +117 -20
  130. package/dist/modules/utils/stagger.js +118 -21
  131. package/dist/modules/utils/target.cjs +1 -1
  132. package/dist/modules/utils/target.js +1 -1
  133. package/dist/modules/utils/time.cjs +5 -3
  134. package/dist/modules/utils/time.d.ts +1 -1
  135. package/dist/modules/utils/time.js +5 -3
  136. package/dist/modules/waapi/composition.cjs +1 -1
  137. package/dist/modules/waapi/composition.js +1 -1
  138. package/dist/modules/waapi/index.cjs +1 -1
  139. package/dist/modules/waapi/index.js +1 -1
  140. package/dist/modules/waapi/waapi.cjs +19 -20
  141. package/dist/modules/waapi/waapi.js +20 -21
  142. package/package.json +2 -1
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Anime.js - ESM bundle
3
- * @version v4.3.6
3
+ * @version v4.4.1
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
@@ -46,7 +46,8 @@
46
46
  * @callback StaggerFunction
47
47
  * @param {Target} [target]
48
48
  * @param {Number} [index]
49
- * @param {Number} [length]
49
+ * @param {TargetsArray} [targets]
50
+ * @param {Tween|null} [prevTween]
50
51
  * @param {Timeline} [tl]
51
52
  * @return {T}
52
53
  */
@@ -54,9 +55,9 @@
54
55
  /**
55
56
  * @typedef {Object} StaggerParams
56
57
  * @property {Number|String} [start]
57
- * @property {Number|'first'|'center'|'last'|'random'} [from]
58
+ * @property {Number|'first'|'center'|'last'|'random'|Array.<Number>} [from]
58
59
  * @property {Boolean} [reversed]
59
- * @property {Array.<Number>} [grid]
60
+ * @property {Array.<Number>|Boolean} [grid]
60
61
  * @property {('x'|'y')} [axis]
61
62
  * @property {String|((target: Target, i: Number, length: Number) => Number)} [use]
62
63
  * @property {Number} [total]
@@ -117,8 +118,8 @@
117
118
 
118
119
  // A hack to get both ease names suggestions AND allow any strings
119
120
  // https://github.com/microsoft/TypeScript/issues/29729#issuecomment-460346421
120
- /** @typedef {(String & {})|EaseStringParamNames|EasingFunction|Spring} EasingParam */
121
- /** @typedef {(String & {})|EaseStringParamNames|WAAPIEaseStringParamNames|EasingFunction|Spring} WAAPIEasingParam */
121
+ /** @typedef {(String & {})|EaseStringParamNames|EasingFunction|Spring|TweakRegister} EasingParam */
122
+ /** @typedef {(String & {})|EaseStringParamNames|WAAPIEaseStringParamNames|EasingFunction|Spring|TweakRegister} WAAPIEasingParam */
122
123
 
123
124
  // Spring types
124
125
 
@@ -174,6 +175,7 @@
174
175
  * @property {Boolean|ScrollObserver} [autoplay]
175
176
  * @property {Number} [frameRate]
176
177
  * @property {Number} [playbackRate]
178
+ * @property {Number} [priority]
177
179
  */
178
180
 
179
181
  /**
@@ -184,9 +186,10 @@
184
186
 
185
187
  /**
186
188
  * @callback FunctionValue
187
- * @param {Target} target - The animated target
188
- * @param {Number} index - The target index
189
- * @param {Number} length - The total number of animated targets
189
+ * @param {Target} [target] - The animated target
190
+ * @param {Number} [index] - The target index
191
+ * @param {TargetsArray} [targets] - The array of all animated targets
192
+ * @param {Tween|null} [prevTween] - The previous sibling tween for the same target and property
190
193
  * @return {Number|String|TweenObjectValue|EasingParam|Array.<Number|String|TweenObjectValue>}
191
194
  */
192
195
 
@@ -355,7 +358,7 @@
355
358
  * - `'label'` - Label: Position animation at a named label position (e.g., `'My Label'`)<br>
356
359
  * - `stagger(String|Nummber)` - Stagger multi-elements animation positions (e.g., 10, 20, 30...)
357
360
  *
358
- * @typedef {TimelinePosition | StaggerFunction<Number|String>} TimelineAnimationPosition
361
+ * @typedef {TimelinePosition | StaggerFunction<Number|String> | TweakRegister} TimelineAnimationPosition
359
362
  */
360
363
 
361
364
  /**
@@ -379,7 +382,7 @@
379
382
  * @callback WAAPIFunctionValue
380
383
  * @param {DOMTarget} target - The animated target
381
384
  * @param {Number} index - The target index
382
- * @param {Number} length - The total number of animated targets
385
+ * @param {DOMTargetsArray} targets - The array of all animated targets
383
386
  * @return {WAAPITweenValue|WAAPIEasingParam}
384
387
  */
385
388
 
@@ -626,6 +629,26 @@
626
629
  * @property {Boolean} [debug]
627
630
  */
628
631
 
632
+ /**
633
+ * @typedef {Object} ScrambleTextParams
634
+ * @property {String|function(Target, Number, TargetsArray): String} [text] - the text to transition to, otherwise uses the original text
635
+ * @property {String|function(Target, Number, TargetsArray): String} [chars] - the characters used for scramble; named sets: 'lowercase', 'uppercase', 'numbers', 'symbols', 'braille', 'blocks', 'shades'; range syntax: 'A-Z', 'a-z0-9'; defaults to 'a-zA-Z0-9!%#_'
636
+ * @property {EasingParam} [ease] - the easing applied to the scramble animation
637
+ * @property {Number|'left'|'center'|'right'|'random'|'auto'} [from] - where the reveal wave starts from, 'auto' (default) uses 'left' when text grows and 'right' when it shrinks
638
+ * @property {Boolean} [reversed] - reverses the reveal order, so 'center' reveals from edges inward instead of center outward
639
+ * @property {Boolean|Number|String} [cursor] - characters displayed at the leading edge of the reveal wave; true uses '_', a number is a char code, a string is used directly
640
+ * @property {Number} [perturbation] - adds random timing offsets to each character's start and end, creating a more organic reveal
641
+ * @property {Number} [seed] - a seed for the random number generator to produce reproducible scramble sequences
642
+ * @property {Boolean|String} [override] - controls the starting appearance: false shows original text, true scrambles it (default), '' starts from blank, ' ' replaces characters with spaces, a custom string (supports range syntax like 'A-Z') uses its characters as scramble set
643
+ * @property {Number} [revealRate] - characters per second entering the active zone; higher values make the reveal wave move faster (default: 60)
644
+ * @property {Number} [settleDuration] - time in ms each character spends scrambling before settling into its final glyph (default: 300)
645
+ * @property {Number} [settleRate] - how many times per second scramble characters cycle in the active zone (default: 30)
646
+ * @property {Number|function(Target, Number, TargetsArray): Number} [duration] - if set to a value greater than 0, overrides the computed duration from interval and settle; if unset or 0, duration is calculated automatically from text length and timing parameters
647
+ * @property {Number|function(Target, Number, TargetsArray): Number} [revealDelay] - delay in ms before the reveal wave starts within the scramble animation
648
+ * @property {Number|function(Target, Number, TargetsArray): Number} [delay] - delay in ms before the entire scramble animation starts
649
+ * @property {function(String, Number): void} [onChange] - callback fired each time a character changes during scramble; receives the current scrambled text and the eased progress (0-1)
650
+ */
651
+
629
652
  // SVG types
630
653
 
631
654
  /**
@@ -641,7 +664,7 @@
641
664
  // TODO: Do we need to check if we're running inside a worker ?
642
665
  const isBrowser = typeof window !== 'undefined';
643
666
 
644
- /** @typedef {Window & {AnimeJS: Array} & {AnimeJSDevTools: any}|null} AnimeJSWindow
667
+ /** @typedef {Window & {AnimeJS: Array}|null} AnimeJSWindow
645
668
 
646
669
  /** @type {AnimeJSWindow} */
647
670
  const win = isBrowser ? /** @type {AnimeJSWindow} */(/** @type {unknown} */(window)) : null;
@@ -688,7 +711,6 @@ const isRegisteredTargetSymbol = Symbol();
688
711
  const isDomSymbol = Symbol();
689
712
  const isSvgSymbol = Symbol();
690
713
  const transformsSymbol = Symbol();
691
- const morphPointsSymbol = Symbol();
692
714
  const proxyTargetSymbol = Symbol();
693
715
 
694
716
  // Numbers
@@ -712,6 +734,7 @@ const shortTransforms = /*#__PURE__*/ (() => {
712
734
  })();
713
735
 
714
736
  const validTransforms = [
737
+ 'perspective',
715
738
  'translateX',
716
739
  'translateY',
717
740
  'translateZ',
@@ -726,9 +749,6 @@ const validTransforms = [
726
749
  'skew',
727
750
  'skewX',
728
751
  'skewY',
729
- 'matrix',
730
- 'matrix3d',
731
- 'perspective',
732
752
  ];
733
753
 
734
754
  const transformsFragmentStrings = /*#__PURE__*/ validTransforms.reduce((a, v) => ({...a, [v]: v + '('}), {});
@@ -751,12 +771,23 @@ const digitWithExponentRgx = /[-+]?\d*\.?\d+(?:e[-+]?\d)?/gi;
751
771
  // export const unitsExecRgx = /^([-+]?\d*\.?\d+(?:[eE][-+]?\d+)?)+([a-z]+|%)$/i;
752
772
  const unitsExecRgx = /^([-+]?\d*\.?\d+(?:e[-+]?\d+)?)([a-z]+|%)$/i;
753
773
  const lowerCaseRgx = /([a-z])([A-Z])/g;
754
- const transformsExecRgx = /(\w+)(\([^)]+\)+)/g; // Match inline transforms with cacl() values, returns the value wrapped in ()
755
774
  const relativeValuesExecRgx = /(\*=|\+=|-=)/;
756
775
  const cssVariableMatchRgx = /var\(\s*(--[\w-]+)(?:\s*,\s*([^)]+))?\s*\)/;
757
776
 
758
777
 
759
778
 
779
+ /**
780
+ * @typedef {Object} EditorGlobals
781
+ * @property {boolean} showPanel
782
+ * @property {boolean} synced
783
+ * @property {Function} addAnimation
784
+ * @property {Function} addTimeline
785
+ * @property {Function} addTimelineChild
786
+ * @property {Function} resolveStagger
787
+ * @property {Object|null} _head
788
+ * @property {Object|null} _tail
789
+ */
790
+
760
791
  /** @type {DefaultsParams} */
761
792
  const defaults = {
762
793
  id: null,
@@ -800,11 +831,11 @@ const globals = {
800
831
  timeScale: 1,
801
832
  /** @type {Number} */
802
833
  tickThreshold: 200,
834
+ /** @type {EditorGlobals|null} */
835
+ editor: null,
803
836
  };
804
837
 
805
- const devTools = isBrowser && win.AnimeJSDevTools;
806
-
807
- const globalVersions = { version: '4.3.6', engine: null };
838
+ const globalVersions = { version: '4.4.1', engine: null };
808
839
 
809
840
  if (isBrowser) {
810
841
  if (!win.AnimeJS) win.AnimeJS = [];
@@ -920,8 +951,6 @@ const _round = Math.round;
920
951
  */
921
952
  const clamp$1 = (v, min, max) => v < min ? min : v > max ? max : v;
922
953
 
923
- const powCache = {};
924
-
925
954
  /**
926
955
  * Rounds a number to specified decimal places
927
956
  *
@@ -929,13 +958,12 @@ const powCache = {};
929
958
  * @param {Number} decimalLength - Number of decimal places
930
959
  * @return {Number}
931
960
  */
932
- const round$1 = (v, decimalLength) => {
933
- if (decimalLength < 0) return v;
934
- if (!decimalLength) return _round(v);
935
- let p = powCache[decimalLength];
936
- if (!p) p = powCache[decimalLength] = 10 ** decimalLength;
937
- return _round(v * p) / p;
938
- };
961
+ const round$1 = (v, decimalLength) => {
962
+ if (decimalLength < 0) return v;
963
+ if (!decimalLength) return _round(v);
964
+ const p = 10 ** decimalLength;
965
+ return _round(v * p) / p;
966
+ };
939
967
 
940
968
  /**
941
969
  * Snaps a value to nearest increment or array value
@@ -1066,28 +1094,143 @@ const addChild = (parent, child, sortMethod, prevProp = '_prev', nextProp = '_ne
1066
1094
  */
1067
1095
  const parseInlineTransforms = (target, propName, animationInlineStyles) => {
1068
1096
  const inlineTransforms = target.style.transform;
1069
- let inlinedStylesPropertyValue;
1070
1097
  if (inlineTransforms) {
1071
1098
  const cachedTransforms = target[transformsSymbol];
1072
- let t; while (t = transformsExecRgx.exec(inlineTransforms)) {
1073
- const inlinePropertyName = t[1];
1074
- // const inlinePropertyValue = t[2];
1075
- const inlinePropertyValue = t[2].slice(1, -1);
1076
- cachedTransforms[inlinePropertyName] = inlinePropertyValue;
1077
- if (inlinePropertyName === propName) {
1078
- inlinedStylesPropertyValue = inlinePropertyValue;
1079
- // Store the new parsed inline styles if animationInlineStyles is provided
1080
- if (animationInlineStyles) {
1081
- animationInlineStyles[propName] = inlinePropertyValue;
1099
+ let pos = 0;
1100
+ const len = inlineTransforms.length;
1101
+ let fullTranslateValue;
1102
+ while (pos < len) {
1103
+ // Skip whitespace
1104
+ while (pos < len && inlineTransforms.charCodeAt(pos) === 32) pos++;
1105
+ if (pos >= len) break;
1106
+ // Read function name
1107
+ const nameStart = pos;
1108
+ while (pos < len && inlineTransforms.charCodeAt(pos) !== 40) pos++;
1109
+ if (pos >= len) break;
1110
+ const name = inlineTransforms.substring(nameStart, pos);
1111
+ // Scan to closing paren, recording top-level comma positions
1112
+ let depth = 1;
1113
+ const valueStart = pos + 1;
1114
+ let c1 = -1, c2 = -1;
1115
+ pos++;
1116
+ while (pos < len && depth > 0) {
1117
+ const c = inlineTransforms.charCodeAt(pos);
1118
+ if (c === 40) depth++;
1119
+ else if (c === 41) depth--;
1120
+ else if (c === 44 && depth === 1) {
1121
+ if (c1 === -1) c1 = pos;
1122
+ else if (c2 === -1) c2 = pos;
1123
+ }
1124
+ pos++;
1125
+ }
1126
+ const valueEnd = pos - 1;
1127
+ // Decompose multi-arg functions into individual axis properties
1128
+ if (name === 'translate' || name === 'translate3d') {
1129
+ if (c1 === -1) {
1130
+ cachedTransforms.translateX = inlineTransforms.substring(valueStart, valueEnd).trim();
1131
+ } else {
1132
+ cachedTransforms.translateX = inlineTransforms.substring(valueStart, c1).trim();
1133
+ if (c2 === -1) {
1134
+ cachedTransforms.translateY = inlineTransforms.substring(c1 + 1, valueEnd).trim();
1135
+ } else {
1136
+ cachedTransforms.translateY = inlineTransforms.substring(c1 + 1, c2).trim();
1137
+ cachedTransforms.translateZ = inlineTransforms.substring(c2 + 1, valueEnd).trim();
1138
+ }
1139
+ }
1140
+ fullTranslateValue = inlineTransforms.substring(valueStart, valueEnd);
1141
+ } else if (name === 'scale' || name === 'scale3d') {
1142
+ if (c1 === -1) {
1143
+ cachedTransforms.scale = inlineTransforms.substring(valueStart, valueEnd).trim();
1144
+ } else {
1145
+ cachedTransforms.scaleX = inlineTransforms.substring(valueStart, c1).trim();
1146
+ if (c2 === -1) {
1147
+ cachedTransforms.scaleY = inlineTransforms.substring(c1 + 1, valueEnd).trim();
1148
+ } else {
1149
+ cachedTransforms.scaleY = inlineTransforms.substring(c1 + 1, c2).trim();
1150
+ cachedTransforms.scaleZ = inlineTransforms.substring(c2 + 1, valueEnd).trim();
1151
+ }
1082
1152
  }
1153
+ } else {
1154
+ cachedTransforms[name] = inlineTransforms.substring(valueStart, valueEnd);
1083
1155
  }
1084
1156
  }
1157
+ // Resolve the requested property from the cache
1158
+ if (propName === 'translate3d' && fullTranslateValue) {
1159
+ if (animationInlineStyles) animationInlineStyles[propName] = fullTranslateValue;
1160
+ return fullTranslateValue;
1161
+ }
1162
+ const cached = cachedTransforms[propName];
1163
+ if (!isUnd(cached)) {
1164
+ if (animationInlineStyles) animationInlineStyles[propName] = cached;
1165
+ return cached;
1166
+ }
1085
1167
  }
1086
- return inlineTransforms && !isUnd(inlinedStylesPropertyValue) ? inlinedStylesPropertyValue :
1168
+ return propName === 'translate3d' ? '0px, 0px, 0px' :
1169
+ propName === 'rotate3d' ? '0, 0, 0, 0deg' :
1087
1170
  stringStartsWith(propName, 'scale') ? '1' :
1088
1171
  stringStartsWith(propName, 'rotate') || stringStartsWith(propName, 'skew') ? '0deg' : '0px';
1089
1172
  };
1090
1173
 
1174
+ /**
1175
+ * Builds a CSS transform string from the target's cached transform properties.
1176
+ * Iterates validTransforms in order (perspective > translate > rotate > scale > skew > matrix).
1177
+ * When adjacent axis properties are all present, emits a shorter shorthand (translateX + translateY -> translate(x, y))
1178
+ * The index is advanced past consumed properties so they are not emitted twice.
1179
+ * Properties without a grouping partner (e.g. translateY alone, scaleZ alone) emit individually.
1180
+ *
1181
+ * @param {Record<String, String>} props
1182
+ * @return {String}
1183
+ */
1184
+ const buildTransformString = (props) => {
1185
+ let str = emptyString;
1186
+ for (let i = 0, l = validTransforms.length; i < l; i++) {
1187
+ const key = validTransforms[i];
1188
+ const val = props[key];
1189
+ if (val !== undefined) {
1190
+ // Group translateX with adjacent translateY / translateZ
1191
+ if (key === 'translateX') {
1192
+ const next = props.translateY;
1193
+ if (next !== undefined) {
1194
+ const next2 = props.translateZ;
1195
+ if (next2 !== undefined) {
1196
+ str += `translate3d(${val},${next},${next2}) `;
1197
+ i += 2;
1198
+ } else {
1199
+ str += `translate(${val},${next}) `;
1200
+ i += 1;
1201
+ }
1202
+ continue;
1203
+ }
1204
+ }
1205
+ // Group scaleX with adjacent scaleY / scaleZ (only when standalone scale is absent)
1206
+ if (key === 'scaleX' && props.scale === undefined) {
1207
+ const next = props.scaleY;
1208
+ if (next !== undefined) {
1209
+ const next2 = props.scaleZ;
1210
+ if (next2 !== undefined) {
1211
+ str += `scale3d(${val},${next},${next2}) `;
1212
+ i += 2;
1213
+ } else {
1214
+ str += `scale(${val},${next}) `;
1215
+ i += 1;
1216
+ }
1217
+ continue;
1218
+ }
1219
+ }
1220
+ // All other properties: emit individually using pre-built fragment string
1221
+ str += `${transformsFragmentStrings[key]}${val}) `;
1222
+ }
1223
+ // Preserve non-animatable rotate3d in correct position (after rotateZ, before scale)
1224
+ if (key === 'rotateZ') {
1225
+ if (props.rotate3d !== undefined) str += `rotate3d(${props.rotate3d}) `;
1226
+ }
1227
+ }
1228
+ // Preserve non-animatable matrix/matrix3d from inline styles
1229
+ if (props.matrix !== undefined) str += `matrix(${props.matrix}) `;
1230
+ if (props.matrix3d !== undefined) str += `matrix3d(${props.matrix3d}) `;
1231
+ return str;
1232
+ };
1233
+
1091
1234
 
1092
1235
 
1093
1236
  /**
@@ -1189,15 +1332,16 @@ const setValue = (targetValue, defaultValue) => {
1189
1332
  * @param {TweenPropValue} value
1190
1333
  * @param {Target} target
1191
1334
  * @param {Number} index
1192
- * @param {Number} total
1193
- * @param {Object} [store]
1335
+ * @param {TargetsArray} targets
1336
+ * @param {Object|null} store
1337
+ * @param {Tween|null} prevTween
1194
1338
  * @return {any}
1195
1339
  */
1196
- const getFunctionValue = (value, target, index, total, store) => {
1340
+ const getFunctionValue = (value, target, index, targets, store, prevTween) => {
1197
1341
  let func;
1198
1342
  if (isFnc(value)) {
1199
1343
  func = () => {
1200
- const computed = /** @type {Function} */(value)(target, index, total);
1344
+ const computed = /** @type {Function} */(value)(target, index, targets, prevTween);
1201
1345
  // Fallback to 0 if the function returns undefined / NaN / null / false / 0
1202
1346
  return !isNaN(+computed) ? +computed : computed || 0;
1203
1347
  };
@@ -1264,9 +1408,17 @@ const getCSSValue = (target, propName, animationInlineStyles) => {
1264
1408
  */
1265
1409
  const getOriginalAnimatableValue = (target, propName, tweenType, animationInlineStyles) => {
1266
1410
  const type = !isUnd(tweenType) ? tweenType : getTweenType(target, propName);
1267
- return type === tweenTypes.OBJECT ? target[propName] || 0 :
1268
- type === tweenTypes.ATTRIBUTE ? /** @type {DOMTarget} */(target).getAttribute(propName) :
1269
- type === tweenTypes.TRANSFORM ? parseInlineTransforms(/** @type {DOMTarget} */(target), propName, animationInlineStyles) :
1411
+ if (type === tweenTypes.OBJECT) {
1412
+ const value = target[propName];
1413
+ if (value && animationInlineStyles) animationInlineStyles[propName] = value;
1414
+ return value || 0;
1415
+ }
1416
+ if (type === tweenTypes.ATTRIBUTE) {
1417
+ const value = /** @type {DOMTarget} */(target).getAttribute(propName);
1418
+ if (value && animationInlineStyles) animationInlineStyles[propName] = value;
1419
+ return value;
1420
+ }
1421
+ return type === tweenTypes.TRANSFORM ? parseInlineTransforms(/** @type {DOMTarget} */(target), propName, animationInlineStyles) :
1270
1422
  type === tweenTypes.CSS_VAR ? getCSSValue(/** @type {DOMTarget} */(target), propName, animationInlineStyles).trimStart() :
1271
1423
  getCSSValue(/** @type {DOMTarget} */(target), propName, animationInlineStyles);
1272
1424
  };
@@ -1368,6 +1520,54 @@ const decomposeTweenValue = (tween, targetObject) => {
1368
1520
 
1369
1521
  const decomposedOriginalValue = createDecomposedValueTargetObject();
1370
1522
 
1523
+ /**
1524
+ * @param {Tween} tween
1525
+ * @param {Number} progress
1526
+ * @param {Number} precision
1527
+ * @return {String}
1528
+ */
1529
+ const composeColorValue = (tween, progress, precision) => {
1530
+ const mod = tween._modifier;
1531
+ const fn = tween._fromNumbers;
1532
+ const tn = tween._toNumbers;
1533
+ const r = round$1(clamp$1(/** @type {Number} */(mod(lerp$1(fn[0], tn[0], progress))), 0, 255), 0);
1534
+ const g = round$1(clamp$1(/** @type {Number} */(mod(lerp$1(fn[1], tn[1], progress))), 0, 255), 0);
1535
+ const b = round$1(clamp$1(/** @type {Number} */(mod(lerp$1(fn[2], tn[2], progress))), 0, 255), 0);
1536
+ const a = clamp$1(/** @type {Number} */(mod(round$1(lerp$1(fn[3], tn[3], progress), precision))), 0, 1);
1537
+ if (tween._composition !== compositionTypes.none) {
1538
+ const ns = tween._numbers;
1539
+ ns[0] = r;
1540
+ ns[1] = g;
1541
+ ns[2] = b;
1542
+ ns[3] = a;
1543
+ }
1544
+ return `rgba(${r},${g},${b},${a})`;
1545
+ };
1546
+
1547
+ /**
1548
+ * @param {Tween} tween
1549
+ * @param {Number} progress
1550
+ * @param {Number} precision
1551
+ * @return {String}
1552
+ */
1553
+ const composeComplexValue = (tween, progress, precision) => {
1554
+ const mod = tween._modifier;
1555
+ const fn = tween._fromNumbers;
1556
+ const tn = tween._toNumbers;
1557
+ const ts = tween._strings;
1558
+ const hasComposition = tween._composition !== compositionTypes.none;
1559
+ let v = ts[0];
1560
+ for (let j = 0, l = tn.length; j < l; j++) {
1561
+ const n = /** @type {Number} */(mod(round$1(lerp$1(fn[j], tn[j], progress), precision)));
1562
+ const s = ts[j + 1];
1563
+ v += `${s ? n + s : n}`;
1564
+ if (hasComposition) {
1565
+ tween._numbers[j] = n;
1566
+ }
1567
+ }
1568
+ return v;
1569
+ };
1570
+
1371
1571
 
1372
1572
 
1373
1573
 
@@ -1396,7 +1596,6 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
1396
1596
  const _hasChildren = tickable._hasChildren;
1397
1597
  const tickableDelay = tickable._delay;
1398
1598
  const tickablePrevAbsoluteTime = tickable._currentTime; // TODO: rename ._currentTime to ._absoluteCurrentTime
1399
-
1400
1599
  const tickableEndTime = tickableDelay + iterationDuration;
1401
1600
  const tickableAbsoluteTime = time - tickableDelay;
1402
1601
  const tickablePrevTime = clamp$1(tickablePrevAbsoluteTime, -tickableDelay, duration);
@@ -1528,30 +1727,9 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
1528
1727
  number = /** @type {Number} */(tweenModifier(round$1(lerp$1(tween._fromNumber, tween._toNumber, tweenProgress), tweenPrecision)));
1529
1728
  value = `${number}${tween._unit}`;
1530
1729
  } else if (tweenValueType === valueTypes.COLOR) {
1531
- const fn = tween._fromNumbers;
1532
- const tn = tween._toNumbers;
1533
- const r = round$1(clamp$1(/** @type {Number} */(tweenModifier(lerp$1(fn[0], tn[0], tweenProgress))), 0, 255), 0);
1534
- const g = round$1(clamp$1(/** @type {Number} */(tweenModifier(lerp$1(fn[1], tn[1], tweenProgress))), 0, 255), 0);
1535
- const b = round$1(clamp$1(/** @type {Number} */(tweenModifier(lerp$1(fn[2], tn[2], tweenProgress))), 0, 255), 0);
1536
- const a = clamp$1(/** @type {Number} */(tweenModifier(round$1(lerp$1(fn[3], tn[3], tweenProgress), tweenPrecision))), 0, 1);
1537
- value = `rgba(${r},${g},${b},${a})`;
1538
- if (tweenHasComposition) {
1539
- const ns = tween._numbers;
1540
- ns[0] = r;
1541
- ns[1] = g;
1542
- ns[2] = b;
1543
- ns[3] = a;
1544
- }
1730
+ value = composeColorValue(tween, tweenProgress, tweenPrecision);
1545
1731
  } else if (tweenValueType === valueTypes.COMPLEX) {
1546
- value = tween._strings[0];
1547
- for (let j = 0, l = tween._toNumbers.length; j < l; j++) {
1548
- const n = /** @type {Number} */(tweenModifier(round$1(lerp$1(tween._fromNumbers[j], tween._toNumbers[j], tweenProgress), tweenPrecision)));
1549
- const s = tween._strings[j + 1];
1550
- value += `${s ? n + s : n}`;
1551
- if (tweenHasComposition) {
1552
- tween._numbers[j] = n;
1553
- }
1554
- }
1732
+ value = composeComplexValue(tween, tweenProgress, tweenPrecision);
1555
1733
  }
1556
1734
 
1557
1735
  // For additive tweens and Animatables
@@ -1594,14 +1772,8 @@ const render = (tickable, time, muteCallbacks, internalRender, tickMode) => {
1594
1772
 
1595
1773
  }
1596
1774
 
1597
- // NOTE: Possible improvement: Use translate(x,y) / translate3d(x,y,z) syntax
1598
- // to reduce memory usage on string composition
1599
1775
  if (tweenTransformsNeedUpdate && tween._renderTransforms) {
1600
- let str = emptyString;
1601
- for (let key in tweenTargetTransformsProperties) {
1602
- str += `${transformsFragmentStrings[key]}${tweenTargetTransformsProperties[key]}) `;
1603
- }
1604
- tweenStyle.transform = str;
1776
+ tweenStyle.transform = buildTransformString(tweenTargetTransformsProperties);
1605
1777
  tweenTransformsNeedUpdate = 0;
1606
1778
  }
1607
1779
 
@@ -1712,7 +1884,6 @@ const tick = (tickable, time, muteCallbacks, internalRender, tickMode) => {
1712
1884
 
1713
1885
  // Renders on timeline are triggered by its children so it needs to be set after rendering the children
1714
1886
  if (!muteCallbacks && tlChildrenHasRendered) tl.onRender(/** @type {CallbackArgument} */(tl));
1715
-
1716
1887
  // Triggers the timeline onComplete() once all chindren all completed and the current time has reached the end
1717
1888
  if ((tlChildrenHaveCompleted || tlIsRunningBackwards) && tl._currentTime >= tl.duration) {
1718
1889
  // Make sure the paused flag is false in case it has been skipped in the render function
@@ -1766,59 +1937,78 @@ const sanitizePropertyName = (propertyName, target, tweenType) => {
1766
1937
  /**
1767
1938
  * @template {Renderable} T
1768
1939
  * @param {T} renderable
1940
+ * @param {Boolean} [inlineStylesOnly]
1769
1941
  * @return {T}
1770
1942
  */
1771
- const cleanInlineStyles = renderable => {
1772
- // Allow cleanInlineStyles() to be called on timelines
1943
+ const revertValues = (renderable, inlineStylesOnly = false) => {
1944
+ // Allow revertValues() to be called on timelines
1773
1945
  if (renderable._hasChildren) {
1774
- forEachChildren(renderable, cleanInlineStyles, true);
1946
+ forEachChildren(renderable, (/** @type {Renderable} */child) => revertValues(child, inlineStylesOnly), true);
1775
1947
  } else {
1776
1948
  const animation = /** @type {JSAnimation} */(renderable);
1777
1949
  animation.pause();
1778
1950
  forEachChildren(animation, (/** @type {Tween} */tween) => {
1779
1951
  const tweenProperty = tween.property;
1780
1952
  const tweenTarget = tween.target;
1781
- if (tweenTarget[isDomSymbol]) {
1782
- const targetStyle = /** @type {DOMTarget} */(tweenTarget).style;
1783
- const originalInlinedValue = tween._inlineValue;
1784
- const tweenHadNoInlineValue = isNil(originalInlinedValue) || originalInlinedValue === emptyString;
1785
- if (tween._tweenType === tweenTypes.TRANSFORM) {
1786
- const cachedTransforms = tweenTarget[transformsSymbol];
1787
- if (tweenHadNoInlineValue) {
1788
- delete cachedTransforms[tweenProperty];
1789
- } else {
1790
- cachedTransforms[tweenProperty] = originalInlinedValue;
1791
- }
1792
- if (tween._renderTransforms) {
1793
- if (!Object.keys(cachedTransforms).length) {
1794
- targetStyle.removeProperty('transform');
1953
+ const tweenType = tween._tweenType;
1954
+ const originalInlinedValue = tween._inlineValue;
1955
+ const tweenHadNoInlineValue = isNil(originalInlinedValue) || originalInlinedValue === emptyString;
1956
+ if (tweenType === tweenTypes.OBJECT) {
1957
+ if (!inlineStylesOnly && !tweenHadNoInlineValue) {
1958
+ tweenTarget[tweenProperty] = originalInlinedValue;
1959
+ }
1960
+ } else if (tweenTarget[isDomSymbol]) {
1961
+ if (tweenType === tweenTypes.ATTRIBUTE) {
1962
+ if (!inlineStylesOnly) {
1963
+ if (tweenHadNoInlineValue) {
1964
+ /** @type {DOMTarget} */(tweenTarget).removeAttribute(tweenProperty);
1795
1965
  } else {
1796
- let str = emptyString;
1797
- for (let key in cachedTransforms) {
1798
- str += transformsFragmentStrings[key] + cachedTransforms[key] + ') ';
1799
- }
1800
- targetStyle.transform = str;
1966
+ /** @type {DOMTarget} */(tweenTarget).setAttribute(tweenProperty, /** @type {String} */(originalInlinedValue));
1801
1967
  }
1802
1968
  }
1803
1969
  } else {
1804
- if (tweenHadNoInlineValue) {
1805
- targetStyle.removeProperty(toLowerCase(tweenProperty));
1970
+ const targetStyle = /** @type {DOMTarget} */(tweenTarget).style;
1971
+ if (tweenType === tweenTypes.TRANSFORM) {
1972
+ const cachedTransforms = tweenTarget[transformsSymbol];
1973
+ if (tweenHadNoInlineValue) {
1974
+ delete cachedTransforms[tweenProperty];
1975
+ } else {
1976
+ cachedTransforms[tweenProperty] = originalInlinedValue;
1977
+ }
1978
+ if (tween._renderTransforms) {
1979
+ if (!Object.keys(cachedTransforms).length) {
1980
+ targetStyle.removeProperty('transform');
1981
+ } else {
1982
+ targetStyle.transform = buildTransformString(cachedTransforms);
1983
+ }
1984
+ }
1806
1985
  } else {
1807
- targetStyle[tweenProperty] = originalInlinedValue;
1986
+ if (tweenHadNoInlineValue) {
1987
+ targetStyle.removeProperty(toLowerCase(tweenProperty));
1988
+ } else {
1989
+ targetStyle[tweenProperty] = originalInlinedValue;
1990
+ }
1808
1991
  }
1809
1992
  }
1810
- if (animation._tail === tween) {
1811
- animation.targets.forEach(t => {
1812
- if (t.getAttribute && t.getAttribute('style') === emptyString) {
1813
- t.removeAttribute('style');
1814
- } });
1815
- }
1993
+ }
1994
+ if (tweenTarget[isDomSymbol] && animation._tail === tween) {
1995
+ animation.targets.forEach(t => {
1996
+ if (t.getAttribute && t.getAttribute('style') === emptyString) {
1997
+ t.removeAttribute('style');
1998
+ } });
1816
1999
  }
1817
2000
  });
1818
2001
  }
1819
2002
  return renderable;
1820
2003
  };
1821
2004
 
2005
+ /**
2006
+ * @template {Renderable} T
2007
+ * @param {T} renderable
2008
+ * @return {T}
2009
+ */
2010
+ const cleanInlineStyles = renderable => revertValues(renderable, true);
2011
+
1822
2012
 
1823
2013
 
1824
2014
  /*
@@ -2503,6 +2693,9 @@ const reviveTimer = timer => {
2503
2693
 
2504
2694
  let timerId = 0;
2505
2695
 
2696
+ /** @param {Timer} prev @param {Timer} child */
2697
+ const sortByPriority = (prev, child) => prev._priority > child._priority;
2698
+
2506
2699
  /**
2507
2700
  * Base class used to create Timers, Animations and Timelines
2508
2701
  */
@@ -2529,6 +2722,7 @@ class Timer extends Clock {
2529
2722
  autoplay,
2530
2723
  frameRate,
2531
2724
  playbackRate,
2725
+ priority,
2532
2726
  onComplete,
2533
2727
  onLoop,
2534
2728
  onPause,
@@ -2550,16 +2744,6 @@ class Timer extends Clock {
2550
2744
  /** @type {Number} */(timerLoop) < 0 ? Infinity :
2551
2745
  /** @type {Number} */(timerLoop) + 1;
2552
2746
 
2553
- if (devTools) {
2554
- const isInfinite = timerIterationCount === Infinity;
2555
- const registered = devTools.register(this, parameters, isInfinite);
2556
- if (registered && isInfinite) {
2557
- const minIterations = alternate ? 2 : 1;
2558
- const iterations = parent ? devTools.maxNestedInfiniteLoops : devTools.maxInfiniteLoops;
2559
- timerIterationCount = Math.max(iterations, minIterations);
2560
- }
2561
- }
2562
-
2563
2747
  let offsetPosition = 0;
2564
2748
 
2565
2749
  if (parent) {
@@ -2643,6 +2827,8 @@ class Timer extends Clock {
2643
2827
  this._fps = setValue(frameRate, timerDefaults.frameRate);
2644
2828
  /** @type {Number} */
2645
2829
  this._speed = setValue(playbackRate, timerDefaults.playbackRate);
2830
+ /** @type {Number} */
2831
+ this._priority = +setValue(priority, 1);
2646
2832
  }
2647
2833
 
2648
2834
  get cancelled() {
@@ -2787,7 +2973,7 @@ class Timer extends Clock {
2787
2973
  tick(this, minValue, 0, 0, tickModes.FORCE);
2788
2974
  } else {
2789
2975
  if (!this._running) {
2790
- addChild(engine, this);
2976
+ addChild(engine, this, sortByPriority);
2791
2977
  engine._hasChildren = true;
2792
2978
  this._running = true;
2793
2979
  }
@@ -3382,7 +3568,7 @@ class JSAnimation extends Timer {
3382
3568
  * @param {Number} [parentPosition]
3383
3569
  * @param {Boolean} [fastSet=false]
3384
3570
  * @param {Number} [index=0]
3385
- * @param {Number} [length=0]
3571
+ * @param {TargetsArray} [allTargets]
3386
3572
  */
3387
3573
  constructor(
3388
3574
  targets,
@@ -3391,7 +3577,7 @@ class JSAnimation extends Timer {
3391
3577
  parentPosition,
3392
3578
  fastSet = false,
3393
3579
  index = 0,
3394
- length = 0
3580
+ allTargets
3395
3581
  ) {
3396
3582
 
3397
3583
  super(/** @type {TimerParams & AnimationParams} */(parameters), parent, parentPosition);
@@ -3442,7 +3628,7 @@ class JSAnimation extends Timer {
3442
3628
 
3443
3629
  const target = parsedTargets[targetIndex];
3444
3630
  const ti = index || targetIndex;
3445
- const tl = length || targetsLength;
3631
+ const tl = allTargets || parsedTargets;
3446
3632
 
3447
3633
  let lastTransformGroupIndex = NaN;
3448
3634
  let lastTransformGroupLength = NaN;
@@ -3518,7 +3704,14 @@ class JSAnimation extends Timer {
3518
3704
  toFunctionStore.func = null;
3519
3705
  fromFunctionStore.func = null;
3520
3706
 
3521
- const computedToValue = getFunctionValue(key.to, target, ti, tl, toFunctionStore);
3707
+ const computedComposition = getFunctionValue(setValue(key.composition, tComposition), target, ti, tl, null, null);
3708
+ const tweenComposition = isNum(computedComposition) ? computedComposition : compositionTypes[computedComposition];
3709
+ if (!siblings && tweenComposition !== compositionTypes.none) siblings = getTweenSiblings(target, propName);
3710
+ // Timelines pass the last sibling tween if it belongs to the same timeline
3711
+ // Standalone animations only pass prevTween when the property has multiple keyframes
3712
+ const tailTween = siblings ? siblings._tail : null;
3713
+ const prevSiblingTween = parent && tailTween && tailTween.parent.parent === parent ? tailTween : prevTween;
3714
+ const computedToValue = getFunctionValue(key.to, target, ti, tl, toFunctionStore, prevSiblingTween);
3522
3715
 
3523
3716
  let tweenToValue;
3524
3717
  // Allows function based values to return an object syntax value ({to: v})
@@ -3528,20 +3721,18 @@ class JSAnimation extends Timer {
3528
3721
  } else {
3529
3722
  tweenToValue = computedToValue;
3530
3723
  }
3531
- const tweenFromValue = getFunctionValue(key.from, target, ti, tl);
3724
+ const tweenFromValue = getFunctionValue(key.from, target, ti, tl, null, prevSiblingTween);
3532
3725
  const easeToParse = key.ease || tEasing;
3533
3726
 
3534
- const easeFunctionResult = getFunctionValue(easeToParse, target, ti, tl);
3727
+ const easeFunctionResult = getFunctionValue(easeToParse, target, ti, tl, null, prevSiblingTween);
3535
3728
  const keyEasing = isFnc(easeFunctionResult) || isStr(easeFunctionResult) ? easeFunctionResult : easeToParse;
3536
3729
 
3537
3730
  const hasSpring = !isUnd(keyEasing) && !isUnd(/** @type {Spring} */(keyEasing).ease);
3538
3731
  const tweenEasing = hasSpring ? /** @type {Spring} */(keyEasing).ease : keyEasing;
3539
3732
  // Calculate default individual keyframe duration by dividing the tl of keyframes
3540
- const tweenDuration = hasSpring ? /** @type {Spring} */(keyEasing).settlingDuration : getFunctionValue(setValue(key.duration, (l > 1 ? getFunctionValue(tDuration, target, ti, tl) / l : tDuration)), target, ti, tl);
3733
+ const tweenDuration = hasSpring ? /** @type {Spring} */(keyEasing).settlingDuration : getFunctionValue(setValue(key.duration, (l > 1 ? getFunctionValue(tDuration, target, ti, tl, null, prevSiblingTween) / l : tDuration)), target, ti, tl, null, prevSiblingTween);
3541
3734
  // Default delay value should only be applied to the first tween
3542
- const tweenDelay = getFunctionValue(setValue(key.delay, (!tweenIndex ? tDelay : 0)), target, ti, tl);
3543
- const computedComposition = getFunctionValue(setValue(key.composition, tComposition), target, ti, tl);
3544
- const tweenComposition = isNum(computedComposition) ? computedComposition : compositionTypes[computedComposition];
3735
+ const tweenDelay = getFunctionValue(setValue(key.delay, (!tweenIndex ? tDelay : 0)), target, ti, tl, null, prevSiblingTween);
3545
3736
  // Modifiers are treated differently and don't accept function based value to prevent having to pass a function wrapper
3546
3737
  const tweenModifier = key.modifier || tModifier;
3547
3738
  const hasFromvalue = !isUnd(tweenFromValue);
@@ -3558,7 +3749,6 @@ class JSAnimation extends Timer {
3558
3749
  let prevSibling = prevTween;
3559
3750
 
3560
3751
  if (tweenComposition !== compositionTypes.none) {
3561
- if (!siblings) siblings = getTweenSiblings(target, propName);
3562
3752
  let nextSibling = siblings._head;
3563
3753
  // Iterate trough all the next siblings until we find a sibling with an equal or inferior start time
3564
3754
  while (nextSibling && !nextSibling._isOverridden && nextSibling._absoluteStartTime <= absoluteStartTime) {
@@ -3577,8 +3767,8 @@ class JSAnimation extends Timer {
3577
3767
 
3578
3768
  // Decompose values
3579
3769
  if (isFromToValue) {
3580
- decomposeRawValue(isFromToArray ? getFunctionValue(tweenToValue[0], target, ti, tl, fromFunctionStore) : tweenFromValue, fromTargetObject);
3581
- decomposeRawValue(isFromToArray ? getFunctionValue(tweenToValue[1], target, ti, tl, toFunctionStore) : tweenToValue, toTargetObject);
3770
+ decomposeRawValue(isFromToArray ? getFunctionValue(tweenToValue[0], target, ti, tl, fromFunctionStore, prevSiblingTween) : tweenFromValue, fromTargetObject);
3771
+ decomposeRawValue(isFromToArray ? getFunctionValue(tweenToValue[1], target, ti, tl, toFunctionStore, prevSiblingTween) : tweenToValue, toTargetObject);
3582
3772
  // Needed to force an inline style registration
3583
3773
  const originalValue = getOriginalAnimatableValue(target, propName, tweenType, inlineStylesStore);
3584
3774
  if (fromTargetObject.t === valueTypes.NUMBER) {
@@ -3732,6 +3922,18 @@ class JSAnimation extends Timer {
3732
3922
  composeTween(tween, siblings);
3733
3923
  }
3734
3924
 
3925
+ // Pre-compute the tween end value for function-based value chaining (ie morphTo / scrambleText in keyframe arrays and timelines)
3926
+ const vt = tween._valueType;
3927
+ if (vt === valueTypes.COMPLEX) {
3928
+ tween._value = composeComplexValue(tween, 1, -1);
3929
+ } else if (vt === valueTypes.COLOR) {
3930
+ tween._value = composeColorValue(tween, 1, -1);
3931
+ } else if (vt === valueTypes.UNIT) {
3932
+ tween._value = `${tweenModifier(tween._toNumber)}${tween._unit}`;
3933
+ } else {
3934
+ tween._value = tweenModifier(tween._toNumber);
3935
+ }
3936
+
3735
3937
  if (isNaN(firstTweenChangeStartTime)) {
3736
3938
  firstTweenChangeStartTime = tween._startTime;
3737
3939
  }
@@ -3889,7 +4091,7 @@ class JSAnimation extends Timer {
3889
4091
  */
3890
4092
  revert() {
3891
4093
  super.revert();
3892
- return cleanInlineStyles(this);
4094
+ return revertValues(this);
3893
4095
  }
3894
4096
 
3895
4097
  /**
@@ -3911,170 +4113,12 @@ class JSAnimation extends Timer {
3911
4113
  * @param {AnimationParams} parameters
3912
4114
  * @return {JSAnimation}
3913
4115
  */
3914
- const animate = (targets, parameters) => new JSAnimation(targets, parameters, null, 0, false).init();
3915
-
3916
-
3917
-
3918
-
3919
-
3920
- const WAAPIAnimationsLookups = {
3921
- _head: null,
3922
- _tail: null,
3923
- };
3924
-
3925
- /**
3926
- * @param {DOMTarget} $el
3927
- * @param {String} [property]
3928
- * @param {WAAPIAnimation} [parent]
3929
- * @return {globalThis.Animation}
3930
- */
3931
- const removeWAAPIAnimation = ($el, property, parent) => {
3932
- let nextLookup = WAAPIAnimationsLookups._head;
3933
- let anim;
3934
- while (nextLookup) {
3935
- const next = nextLookup._next;
3936
- const matchTarget = nextLookup.$el === $el;
3937
- const matchProperty = !property || nextLookup.property === property;
3938
- const matchParent = !parent || nextLookup.parent === parent;
3939
- if (matchTarget && matchProperty && matchParent) {
3940
- anim = nextLookup.animation;
3941
- try { anim.commitStyles(); } catch {} anim.cancel();
3942
- removeChild(WAAPIAnimationsLookups, nextLookup);
3943
- const lookupParent = nextLookup.parent;
3944
- if (lookupParent) {
3945
- lookupParent._completed++;
3946
- if (lookupParent.animations.length === lookupParent._completed) {
3947
- lookupParent.completed = true;
3948
- lookupParent.paused = true;
3949
- if (!lookupParent.muteCallbacks) {
3950
- lookupParent.onComplete(lookupParent);
3951
- lookupParent._resolve(lookupParent);
3952
- }
3953
- }
3954
- }
3955
- }
3956
- nextLookup = next;
3957
- }
3958
- return anim;
3959
- };
3960
-
3961
- /**
3962
- * @param {WAAPIAnimation} parent
3963
- * @param {DOMTarget} $el
3964
- * @param {String} property
3965
- * @param {PropertyIndexedKeyframes} keyframes
3966
- * @param {KeyframeAnimationOptions} params
3967
- * @retun {globalThis.Animation}
3968
- */
3969
- const addWAAPIAnimation = (parent, $el, property, keyframes, params) => {
3970
- const animation = $el.animate(keyframes, params);
3971
- const animTotalDuration = params.delay + (+params.duration * params.iterations);
3972
- animation.playbackRate = parent._speed;
3973
- if (parent.paused) animation.pause();
3974
- if (parent.duration < animTotalDuration) {
3975
- parent.duration = animTotalDuration;
3976
- parent.controlAnimation = animation;
3977
- }
3978
- parent.animations.push(animation);
3979
- removeWAAPIAnimation($el, property);
3980
- addChild(WAAPIAnimationsLookups, { parent, animation, $el, property, _next: null, _prev: null });
3981
- const handleRemove = () => removeWAAPIAnimation($el, property, parent);
3982
- animation.oncancel = handleRemove;
3983
- animation.onremove = handleRemove;
3984
- if (!parent.persist) {
3985
- animation.onfinish = handleRemove;
3986
- }
3987
- return animation;
3988
- };
3989
-
3990
-
3991
-
3992
-
3993
-
3994
- /**
3995
- * @overload
3996
- * @param {DOMTargetSelector} targetSelector
3997
- * @param {String} propName
3998
- * @return {String}
3999
- *
4000
- * @overload
4001
- * @param {JSTargetsParam} targetSelector
4002
- * @param {String} propName
4003
- * @return {Number|String}
4004
- *
4005
- * @overload
4006
- * @param {DOMTargetsParam} targetSelector
4007
- * @param {String} propName
4008
- * @param {String} unit
4009
- * @return {String}
4010
- *
4011
- * @overload
4012
- * @param {TargetsParam} targetSelector
4013
- * @param {String} propName
4014
- * @param {Boolean} unit
4015
- * @return {Number}
4016
- *
4017
- * @param {TargetsParam} targetSelector
4018
- * @param {String} propName
4019
- * @param {String|Boolean} [unit]
4020
- */
4021
- function get(targetSelector, propName, unit) {
4022
- const targets = registerTargets(targetSelector);
4023
- if (!targets.length) return;
4024
- const [ target ] = targets;
4025
- const tweenType = getTweenType(target, propName);
4026
- const normalizePropName = sanitizePropertyName(propName, target, tweenType);
4027
- let originalValue = getOriginalAnimatableValue(target, normalizePropName);
4028
- if (isUnd(unit)) {
4029
- return originalValue;
4116
+ const animate = (targets, parameters) => {
4117
+ if (globals.editor) {
4118
+ return globals.editor.addAnimation(targets, parameters);
4030
4119
  } else {
4031
- decomposeRawValue(originalValue, decomposedOriginalValue);
4032
- if (decomposedOriginalValue.t === valueTypes.NUMBER || decomposedOriginalValue.t === valueTypes.UNIT) {
4033
- if (unit === false) {
4034
- return decomposedOriginalValue.n;
4035
- } else {
4036
- const convertedValue = convertValueUnit(/** @type {DOMTarget} */(target), decomposedOriginalValue, /** @type {String} */(unit), false);
4037
- return `${round$1(convertedValue.n, globals.precision)}${convertedValue.u}`;
4038
- }
4039
- }
4120
+ return new JSAnimation(targets, parameters, null, 0, false).init();
4040
4121
  }
4041
- }
4042
-
4043
- /**
4044
- * @param {TargetsParam} targets
4045
- * @param {AnimationParams} parameters
4046
- * @return {JSAnimation}
4047
- */
4048
- const set = (targets, parameters) => {
4049
- if (isUnd(parameters)) return;
4050
- parameters.duration = minValue;
4051
- // Do not overrides currently active tweens by default
4052
- parameters.composition = setValue(parameters.composition, compositionTypes.none);
4053
- // Skip init() and force rendering by playing the animation
4054
- return new JSAnimation(targets, parameters, null, 0, true).resume();
4055
- };
4056
-
4057
- /**
4058
- * @param {TargetsParam} targets
4059
- * @param {Renderable|WAAPIAnimation} [renderable]
4060
- * @param {String} [propertyName]
4061
- * @return {TargetsArray}
4062
- */
4063
- const remove = (targets, renderable, propertyName) => {
4064
- const targetsArray = parseTargets(targets);
4065
- for (let i = 0, l = targetsArray.length; i < l; i++) {
4066
- removeWAAPIAnimation(
4067
- /** @type {DOMTarget} */(targetsArray[i]),
4068
- propertyName,
4069
- renderable && /** @type {WAAPIAnimation} */(renderable).controlAnimation && /** @type {WAAPIAnimation} */(renderable),
4070
- );
4071
- }
4072
- removeTargetsFromRenderable(
4073
- targetsArray,
4074
- /** @type {Renderable} */(renderable),
4075
- propertyName
4076
- );
4077
- return targetsArray;
4078
4122
  };
4079
4123
 
4080
4124
 
@@ -4130,6 +4174,8 @@ const parseTimelinePosition = (timeline, timePosition) => {
4130
4174
 
4131
4175
 
4132
4176
 
4177
+
4178
+
4133
4179
  /**
4134
4180
  * @param {Timeline} tl
4135
4181
  * @return {Number}
@@ -4151,7 +4197,7 @@ function getTimelineTotalDuration(tl) {
4151
4197
  * @param {Number} timePosition
4152
4198
  * @param {TargetsParam} targets
4153
4199
  * @param {Number} [index]
4154
- * @param {Number} [length]
4200
+ * @param {TargetsArray} [allTargets]
4155
4201
  * @return {Timeline}
4156
4202
  *
4157
4203
  * @param {TimerParams|AnimationParams} childParams
@@ -4159,15 +4205,15 @@ function getTimelineTotalDuration(tl) {
4159
4205
  * @param {Number} timePosition
4160
4206
  * @param {TargetsParam} [targets]
4161
4207
  * @param {Number} [index]
4162
- * @param {Number} [length]
4208
+ * @param {TargetsArray} [allTargets]
4163
4209
  */
4164
- function addTlChild(childParams, tl, timePosition, targets, index, length) {
4210
+ function addTlChild(childParams, tl, timePosition, targets, index, allTargets) {
4165
4211
  const isSetter = isNum(childParams.duration) && /** @type {Number} */(childParams.duration) <= minValue;
4166
4212
  // Offset the tl position with -minValue for 0 duration animations or .set() calls in order to align their end value with the defined position
4167
4213
  const adjustedPosition = isSetter ? timePosition - minValue : timePosition;
4168
4214
  if (tl.composition) tick(tl, adjustedPosition, 1, 1, tickModes.AUTO);
4169
4215
  const tlChild = targets ?
4170
- new JSAnimation(targets,/** @type {AnimationParams} */(childParams), tl, adjustedPosition, false, index, length) :
4216
+ new JSAnimation(targets,/** @type {AnimationParams} */(childParams), tl, adjustedPosition, false, index, allTargets) :
4171
4217
  new Timer(/** @type {TimerParams} */(childParams), tl, adjustedPosition);
4172
4218
  if (tl.composition) tlChild.init(true);
4173
4219
  // TODO: Might be better to insert at a position relative to startTime?
@@ -4215,7 +4261,7 @@ class Timeline extends Timer {
4215
4261
  * @overload
4216
4262
  * @param {TargetsParam} a1
4217
4263
  * @param {AnimationParams} a2
4218
- * @param {TimelinePosition|StaggerFunction<Number|String>} [a3]
4264
+ * @param {TimelinePosition|StaggerFunction<Number|String>|TweakRegister} [a3]
4219
4265
  * @return {this}
4220
4266
  *
4221
4267
  * @overload
@@ -4225,7 +4271,7 @@ class Timeline extends Timer {
4225
4271
  *
4226
4272
  * @param {TargetsParam|TimerParams} a1
4227
4273
  * @param {TimelinePosition|AnimationParams} a2
4228
- * @param {TimelinePosition|StaggerFunction<Number|String>} [a3]
4274
+ * @param {TimelinePosition|StaggerFunction<Number|String>|TweakRegister} [a3]
4229
4275
  */
4230
4276
  add(a1, a2, a3) {
4231
4277
  const isAnim = isObj(a2);
@@ -4234,9 +4280,11 @@ class Timeline extends Timer {
4234
4280
  this._hasChildren = true;
4235
4281
  if (isAnim) {
4236
4282
  const childParams = /** @type {AnimationParams} */(a2);
4237
- // Check for function for children stagger positions
4238
- if (isFnc(a3)) {
4239
- const staggeredPosition = a3;
4283
+ const editorHook = globals.editor && globals.editor.addTimelineChild;
4284
+ const isStaggerType = a3 && /** @type {TweakRegister} */(a3).type === 'Stagger' && globals.editor;
4285
+ // Check for function or Stagger type children positions
4286
+ const staggeredPosition = isFnc(a3) ? a3 : null;
4287
+ if (staggeredPosition || isStaggerType) {
4240
4288
  const parsedTargetsArray = parseTargets(/** @type {TargetsParam} */(a1));
4241
4289
  // Store initial duration before adding new children that will change the duration
4242
4290
  const tlDuration = this.duration;
@@ -4247,28 +4295,36 @@ class Timeline extends Timer {
4247
4295
  let i = 0;
4248
4296
  /** @type {Number} */
4249
4297
  const parsedLength = (parsedTargetsArray.length);
4298
+ // Call editor hook once for the entire stagger group instead of per target
4299
+ const resolvedParams = editorHook ? editorHook(/** @type {TargetsParam} */(a1), childParams, this.id, a3, parsedLength) : null;
4300
+ // Resolve stagger AFTER editor hook so tweaked position value (a3.defaultValue) is used
4301
+ const staggerFn = staggeredPosition || globals.editor.resolveStagger(/** @type {TweakRegister} */(a3).defaultValue);
4250
4302
  parsedTargetsArray.forEach((/** @type {Target} */target) => {
4251
4303
  // Create a new parameter object for each staggered children
4252
- const staggeredChildParams = { ...childParams };
4304
+ const staggeredChildParams = { ...(resolvedParams || childParams) };
4253
4305
  // Reset the duration of the timeline iteration before each stagger to prevent wrong start value calculation
4254
4306
  this.duration = tlDuration;
4255
4307
  this.iterationDuration = tlIterationDuration;
4256
4308
  if (!isUnd(id)) staggeredChildParams.id = id + '-' + i;
4309
+ const staggeredTimePosition = parseTimelinePosition(this, staggerFn(target, i, parsedTargetsArray, null, this));
4257
4310
  addTlChild(
4258
4311
  staggeredChildParams,
4259
4312
  this,
4260
- parseTimelinePosition(this, staggeredPosition(target, i, parsedLength, this)),
4313
+ staggeredTimePosition,
4261
4314
  target,
4262
4315
  i,
4263
- parsedLength
4316
+ parsedTargetsArray,
4264
4317
  );
4265
4318
  i++;
4266
4319
  });
4267
4320
  } else {
4321
+ // Call editor hook before resolving position so tweaked values are applied
4322
+ const resolvedChildParams = editorHook ? editorHook(/** @type {TargetsParam} */(a1), childParams, this.id, a3) : childParams;
4323
+ const resolvedPosition = a3 && /** @type {*} */(a3).type ? /** @type {*} */(a3).defaultValue : a3;
4268
4324
  addTlChild(
4269
- childParams,
4325
+ resolvedChildParams,
4270
4326
  this,
4271
- parseTimelinePosition(this, a3),
4327
+ parseTimelinePosition(this, resolvedPosition),
4272
4328
  /** @type {TargetsParam} */(a1),
4273
4329
  );
4274
4330
  }
@@ -4390,7 +4446,7 @@ class Timeline extends Timer {
4390
4446
  revert() {
4391
4447
  super.revert();
4392
4448
  forEachChildren(this, (/** @type {JSAnimation|Timer} */child) => child.revert, true);
4393
- return cleanInlineStyles(this);
4449
+ return revertValues(this);
4394
4450
  }
4395
4451
 
4396
4452
  /**
@@ -4410,7 +4466,12 @@ class Timeline extends Timer {
4410
4466
  * @param {TimelineParams} [parameters]
4411
4467
  * @return {Timeline}
4412
4468
  */
4413
- const createTimeline = parameters => new Timeline(parameters).init();
4469
+ const createTimeline = parameters => {
4470
+ if (globals.editor) {
4471
+ return /** @type {Timeline} */(/** @type {unknown} */(globals.editor.addTimeline(parameters)));
4472
+ }
4473
+ return new Timeline(parameters).init();
4474
+ };
4414
4475
 
4415
4476
 
4416
4477
 
@@ -4857,6 +4918,170 @@ const createSpring = (parameters) => {
4857
4918
 
4858
4919
 
4859
4920
 
4921
+ const WAAPIAnimationsLookups = {
4922
+ _head: null,
4923
+ _tail: null,
4924
+ };
4925
+
4926
+ /**
4927
+ * @param {DOMTarget} $el
4928
+ * @param {String} [property]
4929
+ * @param {WAAPIAnimation} [parent]
4930
+ * @return {globalThis.Animation}
4931
+ */
4932
+ const removeWAAPIAnimation = ($el, property, parent) => {
4933
+ let nextLookup = WAAPIAnimationsLookups._head;
4934
+ let anim;
4935
+ while (nextLookup) {
4936
+ const next = nextLookup._next;
4937
+ const matchTarget = nextLookup.$el === $el;
4938
+ const matchProperty = !property || nextLookup.property === property;
4939
+ const matchParent = !parent || nextLookup.parent === parent;
4940
+ if (matchTarget && matchProperty && matchParent) {
4941
+ anim = nextLookup.animation;
4942
+ try { anim.commitStyles(); } catch {} anim.cancel();
4943
+ removeChild(WAAPIAnimationsLookups, nextLookup);
4944
+ const lookupParent = nextLookup.parent;
4945
+ if (lookupParent) {
4946
+ lookupParent._completed++;
4947
+ if (lookupParent.animations.length === lookupParent._completed) {
4948
+ lookupParent.completed = true;
4949
+ lookupParent.paused = true;
4950
+ if (!lookupParent.muteCallbacks) {
4951
+ lookupParent.onComplete(lookupParent);
4952
+ lookupParent._resolve(lookupParent);
4953
+ }
4954
+ }
4955
+ }
4956
+ }
4957
+ nextLookup = next;
4958
+ }
4959
+ return anim;
4960
+ };
4961
+
4962
+ /**
4963
+ * @param {WAAPIAnimation} parent
4964
+ * @param {DOMTarget} $el
4965
+ * @param {String} property
4966
+ * @param {PropertyIndexedKeyframes} keyframes
4967
+ * @param {KeyframeAnimationOptions} params
4968
+ * @retun {globalThis.Animation}
4969
+ */
4970
+ const addWAAPIAnimation = (parent, $el, property, keyframes, params) => {
4971
+ const animation = $el.animate(keyframes, params);
4972
+ const animTotalDuration = params.delay + (+params.duration * params.iterations);
4973
+ animation.playbackRate = parent._speed;
4974
+ if (parent.paused) animation.pause();
4975
+ if (parent.duration < animTotalDuration) {
4976
+ parent.duration = animTotalDuration;
4977
+ parent.controlAnimation = animation;
4978
+ }
4979
+ parent.animations.push(animation);
4980
+ removeWAAPIAnimation($el, property);
4981
+ addChild(WAAPIAnimationsLookups, { parent, animation, $el, property, _next: null, _prev: null });
4982
+ const handleRemove = () => removeWAAPIAnimation($el, property, parent);
4983
+ animation.oncancel = handleRemove;
4984
+ animation.onremove = handleRemove;
4985
+ if (!parent.persist) {
4986
+ animation.onfinish = handleRemove;
4987
+ }
4988
+ return animation;
4989
+ };
4990
+
4991
+
4992
+
4993
+
4994
+
4995
+ /**
4996
+ * @overload
4997
+ * @param {DOMTargetSelector} targetSelector
4998
+ * @param {String} propName
4999
+ * @return {String}
5000
+ *
5001
+ * @overload
5002
+ * @param {JSTargetsParam} targetSelector
5003
+ * @param {String} propName
5004
+ * @return {Number|String}
5005
+ *
5006
+ * @overload
5007
+ * @param {DOMTargetsParam} targetSelector
5008
+ * @param {String} propName
5009
+ * @param {String} unit
5010
+ * @return {String}
5011
+ *
5012
+ * @overload
5013
+ * @param {TargetsParam} targetSelector
5014
+ * @param {String} propName
5015
+ * @param {Boolean} unit
5016
+ * @return {Number}
5017
+ *
5018
+ * @param {TargetsParam} targetSelector
5019
+ * @param {String} propName
5020
+ * @param {String|Boolean} [unit]
5021
+ */
5022
+ function get(targetSelector, propName, unit) {
5023
+ const targets = registerTargets(targetSelector);
5024
+ if (!targets.length) return;
5025
+ const [ target ] = targets;
5026
+ const tweenType = getTweenType(target, propName);
5027
+ const normalizePropName = sanitizePropertyName(propName, target, tweenType);
5028
+ let originalValue = getOriginalAnimatableValue(target, normalizePropName);
5029
+ if (isUnd(unit)) {
5030
+ return originalValue;
5031
+ } else {
5032
+ decomposeRawValue(originalValue, decomposedOriginalValue);
5033
+ if (decomposedOriginalValue.t === valueTypes.NUMBER || decomposedOriginalValue.t === valueTypes.UNIT) {
5034
+ if (unit === false) {
5035
+ return decomposedOriginalValue.n;
5036
+ } else {
5037
+ const convertedValue = convertValueUnit(/** @type {DOMTarget} */(target), decomposedOriginalValue, /** @type {String} */(unit), false);
5038
+ return `${round$1(convertedValue.n, globals.precision)}${convertedValue.u}`;
5039
+ }
5040
+ }
5041
+ }
5042
+ }
5043
+
5044
+ /**
5045
+ * @param {TargetsParam} targets
5046
+ * @param {AnimationParams} parameters
5047
+ * @return {JSAnimation}
5048
+ */
5049
+ const set = (targets, parameters) => {
5050
+ if (isUnd(parameters)) return;
5051
+ parameters.duration = minValue;
5052
+ // Do not overrides currently active tweens by default
5053
+ parameters.composition = setValue(parameters.composition, compositionTypes.none);
5054
+ // Skip init() and force rendering by playing the animation
5055
+ return new JSAnimation(targets, parameters, null, 0, true).resume();
5056
+ };
5057
+
5058
+ /**
5059
+ * @param {TargetsParam} targets
5060
+ * @param {Renderable|WAAPIAnimation} [renderable]
5061
+ * @param {String} [propertyName]
5062
+ * @return {TargetsArray}
5063
+ */
5064
+ const remove = (targets, renderable, propertyName) => {
5065
+ const targetsArray = parseTargets(targets);
5066
+ for (let i = 0, l = targetsArray.length; i < l; i++) {
5067
+ removeWAAPIAnimation(
5068
+ /** @type {DOMTarget} */(targetsArray[i]),
5069
+ propertyName,
5070
+ renderable && /** @type {WAAPIAnimation} */(renderable).controlAnimation && /** @type {WAAPIAnimation} */(renderable),
5071
+ );
5072
+ }
5073
+ removeTargetsFromRenderable(
5074
+ targetsArray,
5075
+ /** @type {Renderable} */(renderable),
5076
+ propertyName
5077
+ );
5078
+ return targetsArray;
5079
+ };
5080
+
5081
+
5082
+
5083
+
5084
+
4860
5085
  /**
4861
5086
  * @param {Event} e
4862
5087
  */
@@ -6059,19 +6284,20 @@ const sync = (callback = noop) => {
6059
6284
  };
6060
6285
 
6061
6286
  /**
6062
- * @param {(...args: any[]) => Tickable | ((...args: any[]) => void)} constructor
6287
+ * @param {(...args: any[]) => Tickable | ((...args: any[]) => void) | void} constructor
6063
6288
  * @return {(...args: any[]) => Tickable | ((...args: any[]) => void)}
6064
6289
  */
6065
6290
  const keepTime = constructor => {
6066
6291
  /** @type {Tickable} */
6067
6292
  let tracked;
6068
6293
  return (...args) => {
6069
- let currentIteration, currentIterationProgress, reversed, alternate;
6294
+ let currentIteration, currentIterationProgress, reversed, alternate, startTime;
6070
6295
  if (tracked) {
6071
6296
  currentIteration = tracked.currentIteration;
6072
6297
  currentIterationProgress = tracked.iterationProgress;
6073
6298
  reversed = tracked.reversed;
6074
6299
  alternate = tracked._alternate;
6300
+ startTime = tracked._startTime;
6075
6301
  tracked.revert();
6076
6302
  }
6077
6303
  const cleanup = constructor(...args);
@@ -6079,6 +6305,7 @@ const keepTime = constructor => {
6079
6305
  if (!isUnd(currentIterationProgress)) {
6080
6306
  /** @type {Tickable} */(tracked).currentIteration = currentIteration;
6081
6307
  /** @type {Tickable} */(tracked).iterationProgress = (alternate ? !(currentIteration % 2) ? reversed : !reversed : reversed) ? 1 - currentIterationProgress : currentIterationProgress;
6308
+ /** @type {Tickable} */(tracked)._startTime = startTime;
6082
6309
  }
6083
6310
  return cleanup || noop;
6084
6311
  }
@@ -7424,12 +7651,12 @@ let transformsPropertiesRegistered = null;
7424
7651
  * @param {WAAPIKeyframeValue} value
7425
7652
  * @param {DOMTarget} $el
7426
7653
  * @param {Number} i
7427
- * @param {Number} targetsLength
7654
+ * @param {DOMTargetsArray} parsedTargets
7428
7655
  * @return {String}
7429
7656
  */
7430
- const normalizeTweenValue = (propName, value, $el, i, targetsLength) => {
7657
+ const normalizeTweenValue = (propName, value, $el, i, parsedTargets) => {
7431
7658
  // Do not try to compute strings with getFunctionValue otherwise it will convert CSS variables
7432
- let v = isStr(value) ? value : getFunctionValue(/** @type {any} */(value), $el, i, targetsLength);
7659
+ let v = isStr(value) ? value : getFunctionValue(/** @type {any} */(value), $el, i, parsedTargets, null, null);
7433
7660
  if (!isNum(v)) return v;
7434
7661
  if (commonDefaultPXProperties.includes(propName) || stringStartsWith(propName, 'translate')) return `${v}px`;
7435
7662
  if (stringStartsWith(propName, 'rotate') || stringStartsWith(propName, 'skew')) return `${v}deg`;
@@ -7442,18 +7669,18 @@ const normalizeTweenValue = (propName, value, $el, i, targetsLength) => {
7442
7669
  * @param {WAAPIKeyframeValue} from
7443
7670
  * @param {WAAPIKeyframeValue} to
7444
7671
  * @param {Number} i
7445
- * @param {Number} targetsLength
7672
+ * @param {DOMTargetsArray} parsedTargets
7446
7673
  * @return {WAAPITweenValue}
7447
7674
  */
7448
- const parseIndividualTweenValue = ($el, propName, from, to, i, targetsLength) => {
7675
+ const parseIndividualTweenValue = ($el, propName, from, to, i, parsedTargets) => {
7449
7676
  /** @type {WAAPITweenValue} */
7450
7677
  let tweenValue = '0';
7451
- const computedTo = !isUnd(to) ? normalizeTweenValue(propName, to, $el, i, targetsLength) : getComputedStyle($el)[propName];
7678
+ const computedTo = !isUnd(to) ? normalizeTweenValue(propName, to, $el, i, parsedTargets) : getComputedStyle($el)[propName];
7452
7679
  if (!isUnd(from)) {
7453
- const computedFrom = normalizeTweenValue(propName, from, $el, i, targetsLength);
7680
+ const computedFrom = normalizeTweenValue(propName, from, $el, i, parsedTargets);
7454
7681
  tweenValue = [computedFrom, computedTo];
7455
7682
  } else {
7456
- tweenValue = isArr(to) ? to.map((/** @type {any} */v) => normalizeTweenValue(propName, v, $el, i, targetsLength)) : computedTo;
7683
+ tweenValue = isArr(to) ? to.map((/** @type {any} */v) => normalizeTweenValue(propName, v, $el, i, parsedTargets)) : computedTo;
7457
7684
  }
7458
7685
  return tweenValue;
7459
7686
  };
@@ -7492,9 +7719,8 @@ class WAAPIAnimation {
7492
7719
  }
7493
7720
 
7494
7721
  const parsedTargets = registerTargets(targets);
7495
- const targetsLength = parsedTargets.length;
7496
7722
 
7497
- if (!targetsLength) {
7723
+ if (!parsedTargets.length) {
7498
7724
  console.warn(`No target found. Make sure the element you're trying to animate is accessible before creating your animation.`);
7499
7725
  }
7500
7726
 
@@ -7550,7 +7776,7 @@ class WAAPIAnimation {
7550
7776
 
7551
7777
  const easeToParse = setValue(params.ease, globals.defaults.ease);
7552
7778
 
7553
- const easeFunctionResult = getFunctionValue(easeToParse, $el, i, targetsLength);
7779
+ const easeFunctionResult = getFunctionValue(easeToParse, $el, i, parsedTargets, null, null);
7554
7780
  const keyEasing = isFnc(easeFunctionResult) || isStr(easeFunctionResult) ? easeFunctionResult : easeToParse;
7555
7781
 
7556
7782
  const spring = /** @type {Spring} */(easeToParse).ease && easeToParse;
@@ -7558,9 +7784,9 @@ class WAAPIAnimation {
7558
7784
  const easing = parseWAAPIEasing(keyEasing);
7559
7785
 
7560
7786
  /** @type {Number} */
7561
- const duration = (spring ? /** @type {Spring} */(spring).settlingDuration : getFunctionValue(setValue(params.duration, globals.defaults.duration), $el, i, targetsLength)) * timeScale;
7787
+ const duration = (spring ? /** @type {Spring} */(spring).settlingDuration : getFunctionValue(setValue(params.duration, globals.defaults.duration), $el, i, parsedTargets, null, null)) * timeScale;
7562
7788
  /** @type {Number} */
7563
- const delay = getFunctionValue(setValue(params.delay, globals.defaults.delay), $el, i, targetsLength) * timeScale;
7789
+ const delay = getFunctionValue(setValue(params.delay, globals.defaults.delay), $el, i, parsedTargets, null, null) * timeScale;
7564
7790
  /** @type {CompositeOperation} */
7565
7791
  const composite = /** @type {CompositeOperation} */(setValue(params.composition, 'replace'));
7566
7792
 
@@ -7586,19 +7812,19 @@ class WAAPIAnimation {
7586
7812
  const to = /** @type {WAAPITweenOptions} */(tweenOptions).to;
7587
7813
  const from = /** @type {WAAPITweenOptions} */(tweenOptions).from;
7588
7814
  /** @type {Number} */
7589
- tweenParams.duration = (tweenOptionsSpring ? /** @type {Spring} */(tweenOptionsSpring).settlingDuration : getFunctionValue(setValue(tweenOptions.duration, duration), $el, i, targetsLength)) * timeScale;
7815
+ tweenParams.duration = (tweenOptionsSpring ? /** @type {Spring} */(tweenOptionsSpring).settlingDuration : getFunctionValue(setValue(tweenOptions.duration, duration), $el, i, parsedTargets, null, null)) * timeScale;
7590
7816
  /** @type {Number} */
7591
- tweenParams.delay = getFunctionValue(setValue(tweenOptions.delay, delay), $el, i, targetsLength) * timeScale;
7817
+ tweenParams.delay = getFunctionValue(setValue(tweenOptions.delay, delay), $el, i, parsedTargets, null, null) * timeScale;
7592
7818
  /** @type {CompositeOperation} */
7593
7819
  tweenParams.composite = /** @type {CompositeOperation} */(setValue(tweenOptions.composition, composite));
7594
7820
  /** @type {String} */
7595
7821
  tweenParams.easing = parseWAAPIEasing(tweenOptionsEase);
7596
- parsedPropertyValue = parseIndividualTweenValue($el, name, from, to, i, targetsLength);
7822
+ parsedPropertyValue = parseIndividualTweenValue($el, name, from, to, i, parsedTargets);
7597
7823
  if (individualTransformProperty) {
7598
7824
  keyframes[`--${individualTransformProperty}`] = parsedPropertyValue;
7599
7825
  cachedTransforms[individualTransformProperty] = parsedPropertyValue;
7600
7826
  } else {
7601
- keyframes[name] = parseIndividualTweenValue($el, name, from, to, i, targetsLength);
7827
+ keyframes[name] = parseIndividualTweenValue($el, name, from, to, i, parsedTargets);
7602
7828
  }
7603
7829
  addWAAPIAnimation(this, $el, name, keyframes, tweenParams);
7604
7830
  if (!isUnd(from)) {
@@ -7611,8 +7837,8 @@ class WAAPIAnimation {
7611
7837
  }
7612
7838
  } else {
7613
7839
  parsedPropertyValue = isArr(propertyValue) ?
7614
- propertyValue.map((/** @type {any} */v) => normalizeTweenValue(name, v, $el, i, targetsLength)) :
7615
- normalizeTweenValue(name, /** @type {any} */(propertyValue), $el, i, targetsLength);
7840
+ propertyValue.map((/** @type {any} */v) => normalizeTweenValue(name, v, $el, i, parsedTargets)) :
7841
+ normalizeTweenValue(name, /** @type {any} */(propertyValue), $el, i, parsedTargets);
7616
7842
  if (individualTransformProperty) {
7617
7843
  keyframes[`--${individualTransformProperty}`] = parsedPropertyValue;
7618
7844
  cachedTransforms[individualTransformProperty] = parsedPropertyValue;
@@ -7845,6 +8071,7 @@ const waapi = {
7845
8071
 
7846
8072
  /**
7847
8073
  * @typedef {Object} LayoutSpecificAnimationParams
8074
+ * @property {Number|String} [id]
7848
8075
  * @property {Number|FunctionValue} [delay]
7849
8076
  * @property {Number|FunctionValue} [duration]
7850
8077
  * @property {EasingParam|FunctionValue} [ease]
@@ -7887,7 +8114,7 @@ const waapi = {
7887
8114
  * @property {String} id
7888
8115
  * @property {DOMTarget} $el
7889
8116
  * @property {Number} index
7890
- * @property {Number} total
8117
+ * @property {Array<DOMTarget>} targets
7891
8118
  * @property {Number} delay
7892
8119
  * @property {Number} duration
7893
8120
  * @property {EasingParam} ease
@@ -8031,7 +8258,7 @@ const createNode = ($el, parentNode, state, recycledNode) => {
8031
8258
  node.$measure = $el;
8032
8259
  node.id = dataId;
8033
8260
  node.index = 0;
8034
- node.total = 1;
8261
+ node.targets = null;
8035
8262
  node.delay = 0;
8036
8263
  node.duration = 0;
8037
8264
  node.ease = null;
@@ -8217,12 +8444,12 @@ const updateNodeProperties = (node, props) => {
8217
8444
  * @param {LayoutAnimationTimingsParams} params
8218
8445
  */
8219
8446
  const updateNodeTimingParams = (node, params) => {
8220
- const easeFunctionResult = getFunctionValue(params.ease, node.$el, node.index, node.total);
8447
+ const easeFunctionResult = getFunctionValue(params.ease, node.$el, node.index, node.targets, null, null);
8221
8448
  const keyEasing = isFnc(easeFunctionResult) ? easeFunctionResult : params.ease;
8222
8449
  const hasSpring = !isUnd(keyEasing) && !isUnd(/** @type {Spring} */(keyEasing).ease);
8223
8450
  node.ease = hasSpring ? /** @type {Spring} */(keyEasing).ease : keyEasing;
8224
- node.duration = hasSpring ? /** @type {Spring} */(keyEasing).settlingDuration : getFunctionValue(params.duration, node.$el, node.index, node.total);
8225
- node.delay = getFunctionValue(params.delay, node.$el, node.index, node.total);
8451
+ node.duration = hasSpring ? /** @type {Spring} */(keyEasing).settlingDuration : getFunctionValue(params.duration, node.$el, node.index, node.targets, null, null);
8452
+ node.delay = getFunctionValue(params.delay, node.$el, node.index, node.targets, null, null);
8226
8453
  };
8227
8454
 
8228
8455
  /**
@@ -8595,10 +8822,12 @@ class LayoutSnapshot {
8595
8822
 
8596
8823
  const inRootNodeIds = new Set();
8597
8824
  // Update index and total for inital timing calculation
8598
- let index = 0, total = this.nodes.size;
8825
+ let index = 0;
8826
+ const allNodeTargets = [];
8827
+ this.nodes.forEach((node) => { allNodeTargets.push(node.$el); });
8599
8828
  this.nodes.forEach((node, id) => {
8600
8829
  node.index = index++;
8601
- node.total = total;
8830
+ node.targets = allNodeTargets;
8602
8831
  // Track ids of nodes that belong to the current root to filter detached matches
8603
8832
  if (node && node.measuredIsInsideRoot) {
8604
8833
  inRootNodeIds.add(id);
@@ -8710,8 +8939,8 @@ class AutoLayout {
8710
8939
  this.params = params;
8711
8940
  /** @type {DOMTarget} */
8712
8941
  this.root = /** @type {DOMTarget} */(registerTargets(root)[0]);
8713
- /** @type {Number} */
8714
- this.id = layoutId++;
8942
+ /** @type {Number|String} */
8943
+ this.id = params.id || layoutId++;
8715
8944
  /** @type {LayoutChildrenParam} */
8716
8945
  this.children = params.children || '*';
8717
8946
  /** @type {Boolean} */
@@ -8834,7 +9063,9 @@ class AutoLayout {
8834
9063
  duration: setValue(params.duration, this.params.duration),
8835
9064
  };
8836
9065
  /** @type {TimelineParams} */
8837
- const tlParams = {};
9066
+ const tlParams = {
9067
+ id: this.id
9068
+ };
8838
9069
  const onComplete = setValue(params.onComplete, this.params.onComplete);
8839
9070
  const onPause = setValue(params.onPause, this.params.onPause);
8840
9071
  for (let name in defaults) {
@@ -8848,7 +9079,8 @@ class AutoLayout {
8848
9079
  }
8849
9080
  tlParams.onComplete = () => {
8850
9081
  const ap = /** @type {ScrollObserver} */(params.autoplay);
8851
- const isScrollControled = ap && ap.linked;
9082
+ const ed = globals.editor;
9083
+ const isScrollControled = (ap && ap.linked) || (ed && ed.showPanel);
8852
9084
  if (isScrollControled) {
8853
9085
  if (onComplete) onComplete(this.timeline);
8854
9086
  return;
@@ -9047,41 +9279,39 @@ class AutoLayout {
9047
9279
  animatedParent = animatedParent.parentNode;
9048
9280
  }
9049
9281
 
9050
- const animatingTotal = animating.length;
9051
-
9052
9282
  // Root is always animated first in sync with the first child (animating.length is the total of children)
9053
9283
  if (node === rootNode) {
9054
9284
  node.index = 0;
9055
- node.total = animatingTotal;
9285
+ node.targets = animating;
9056
9286
  updateNodeTimingParams(node, animationTimings);
9057
9287
  } else if (node.isEntering) {
9058
9288
  node.index = animatedParent ? animatedParent.index : enteringIndex;
9059
- node.total = animatedParent ? animatingTotal : entering.length;
9289
+ node.targets = animatedParent ? animating : entering;
9060
9290
  updateNodeTimingParams(node, enterFromTimings);
9061
9291
  enteringIndex++;
9062
9292
  } else if (node.isLeaving) {
9063
9293
  node.index = animatedParent ? animatedParent.index : leavingIndex;
9064
- node.total = animatedParent ? animatingTotal : leaving.length;
9294
+ node.targets = animatedParent ? animating : leaving;
9065
9295
  leavingIndex++;
9066
9296
  updateNodeTimingParams(node, leaveToTimings);
9067
9297
  } else if (node.isTarget) {
9068
9298
  node.index = animatingIndex++;
9069
- node.total = animatingTotal;
9299
+ node.targets = animating;
9070
9300
  updateNodeTimingParams(node, animationTimings);
9071
9301
  } else {
9072
9302
  node.index = animatedParent ? animatedParent.index : 0;
9073
- node.total = animatingTotal;
9303
+ node.targets = animating;
9074
9304
  updateNodeTimingParams(node, swapAtTimings);
9075
9305
  }
9076
9306
 
9077
9307
  // Make sure the old state node has its inex and total values up to date for valid "from" function values calculation
9078
9308
  oldStateNode.index = node.index;
9079
- oldStateNode.total = node.total;
9309
+ oldStateNode.targets = node.targets;
9080
9310
 
9081
9311
  // Computes all values up front so we can check for changes and we don't have to re-compute them inside the animation props
9082
9312
  for (let prop in nodeProperties) {
9083
- nodeProperties[prop] = getFunctionValue(nodeProperties[prop], $el, node.index, node.total);
9084
- oldStateNodeProperties[prop] = getFunctionValue(oldStateNodeProperties[prop], $el, oldStateNode.index, oldStateNode.total);
9313
+ nodeProperties[prop] = getFunctionValue(nodeProperties[prop], $el, node.index, node.targets, null, null);
9314
+ oldStateNodeProperties[prop] = getFunctionValue(oldStateNodeProperties[prop], $el, oldStateNode.index, oldStateNode.targets, null, null);
9085
9315
  }
9086
9316
 
9087
9317
  // Use a 1px tolerance to detect dimensions changes to prevent width / height animations on barelly visible elements
@@ -9307,8 +9537,8 @@ class AutoLayout {
9307
9537
  }
9308
9538
  $el.style.transform = oldState.getComputedValue($el, 'transform');
9309
9539
  if (animatedSwap.includes($el)) {
9310
- node.ease = getFunctionValue(swapAtParams.ease, $el, node.index, node.total);
9311
- node.duration = getFunctionValue(swapAtParams.duration, $el, node.index, node.total);
9540
+ node.ease = getFunctionValue(swapAtParams.ease, $el, node.index, node.targets, null, null);
9541
+ node.duration = getFunctionValue(swapAtParams.duration, $el, node.index, node.targets, null, null);
9312
9542
  }
9313
9543
  }
9314
9544
  this.transformAnimation = waapi.animate(transformed, {
@@ -9323,7 +9553,7 @@ class AutoLayout {
9323
9553
  if (!animatedSwap.includes($el)) return newValue;
9324
9554
  const oldValue = oldState.getComputedValue($el, 'transform');
9325
9555
  const node = newState.getNode($el);
9326
- return [oldValue, getFunctionValue(swapAtProps.transform, $el, node.index, node.total), newValue]
9556
+ return [oldValue, getFunctionValue(swapAtProps.transform, $el, node.index, node.targets, null, null), newValue]
9327
9557
  },
9328
9558
  autoplay: false,
9329
9559
  // persist: true,
@@ -9380,10 +9610,13 @@ const chain = fn => {
9380
9610
  const result = fn(...args);
9381
9611
  return new Proxy(noop, {
9382
9612
  apply: (_, __, [v]) => result(v),
9383
- get: (_, prop) => chain(/**@param {...Number|String} nextArgs */(...nextArgs) => {
9384
- const nextResult = chainables[prop](...nextArgs);
9385
- return (/**@type {Number|String} */v) => nextResult(result(v));
9386
- })
9613
+ get: (_, prop) => {
9614
+ if (!chainables[prop]) return undefined;
9615
+ return chain(/**@param {...Number|String} nextArgs */(...nextArgs) => {
9616
+ const nextResult = chainables[prop](...nextArgs);
9617
+ return (/**@type {Number|String} */v) => nextResult(result(v));
9618
+ })
9619
+ }
9387
9620
  });
9388
9621
  }
9389
9622
  };
@@ -9594,24 +9827,28 @@ const shuffle = items => {
9594
9827
  * @param {StaggerParams} [params]
9595
9828
  * @return {StaggerFunction<Number>}
9596
9829
  */
9830
+
9597
9831
  /**
9598
9832
  * @overload
9599
9833
  * @param {String} val
9600
9834
  * @param {StaggerParams} [params]
9601
9835
  * @return {StaggerFunction<String>}
9602
9836
  */
9837
+
9603
9838
  /**
9604
9839
  * @overload
9605
9840
  * @param {[Number, Number]} val
9606
9841
  * @param {StaggerParams} [params]
9607
9842
  * @return {StaggerFunction<Number>}
9608
9843
  */
9844
+
9609
9845
  /**
9610
9846
  * @overload
9611
9847
  * @param {[String, String]} val
9612
9848
  * @param {StaggerParams} [params]
9613
9849
  * @return {StaggerFunction<String>}
9614
9850
  */
9851
+
9615
9852
  /**
9616
9853
  * @param {Number|String|[Number, Number]|[String, String]} val The staggered value or range
9617
9854
  * @param {StaggerParams} [params] The stagger parameters
@@ -9620,6 +9857,7 @@ const shuffle = items => {
9620
9857
  const stagger = (val, params = {}) => {
9621
9858
  let values = [];
9622
9859
  let maxValue = 0;
9860
+ let cachedOffset;
9623
9861
  const from = params.from;
9624
9862
  const reversed = params.reversed;
9625
9863
  const ease = params.ease;
@@ -9627,12 +9865,14 @@ const stagger = (val, params = {}) => {
9627
9865
  const hasSpring = hasEasing && !isUnd(/** @type {Spring} */(ease).ease);
9628
9866
  const staggerEase = hasSpring ? /** @type {Spring} */(ease).ease : hasEasing ? parseEase(ease) : null;
9629
9867
  const grid = params.grid;
9868
+ const autoGrid = grid === true;
9630
9869
  const axis = params.axis;
9631
9870
  const customTotal = params.total;
9632
9871
  const fromFirst = isUnd(from) || from === 0 || from === 'first';
9633
9872
  const fromCenter = from === 'center';
9634
9873
  const fromLast = from === 'last';
9635
9874
  const fromRandom = from === 'random';
9875
+ const fromArr = isArr(from);
9636
9876
  const isRange = isArr(val);
9637
9877
  const useProp = params.use;
9638
9878
  const val1 = isRange ? parseNumber(val[0]) : parseNumber(val);
@@ -9640,40 +9880,129 @@ const stagger = (val, params = {}) => {
9640
9880
  const unitMatch = unitsExecRgx.exec((isRange ? val[1] : val) + emptyString);
9641
9881
  const start = params.start || 0 + (isRange ? val1 : 0);
9642
9882
  let fromIndex = fromFirst ? 0 : isNum(from) ? from : 0;
9643
- return (target, i, t, tl) => {
9883
+ return (target, i, t, _, tl) => {
9644
9884
  const [ registeredTarget ] = registerTargets(target);
9645
- const total = isUnd(customTotal) ? t : customTotal;
9885
+ const total = isUnd(customTotal) ? t.length : customTotal;
9646
9886
  const customIndex = !isUnd(useProp) ? isFnc(useProp) ? useProp(registeredTarget, i, total) : getOriginalAnimatableValue(registeredTarget, useProp) : false;
9647
9887
  const staggerIndex = isNum(customIndex) || isStr(customIndex) && isNum(+customIndex) ? +customIndex : i;
9648
9888
  if (fromCenter) fromIndex = (total - 1) / 2;
9649
9889
  if (fromLast) fromIndex = total - 1;
9650
9890
  if (!values.length) {
9651
- for (let index = 0; index < total; index++) {
9652
- if (!grid) {
9653
- values.push(abs(fromIndex - index));
9891
+ if (autoGrid) {
9892
+ let hasPositions = true;
9893
+ let minPosX = Infinity;
9894
+ let minPosY = Infinity;
9895
+ let maxPosX = -Infinity;
9896
+ let maxPosY = -Infinity;
9897
+ const pxArr = [];
9898
+ const pyArr = [];
9899
+ for (let index = 0; index < total; index++) {
9900
+ const el = t[index];
9901
+ let px = 0;
9902
+ let py = 0;
9903
+ let found = false;
9904
+ if (el && isFnc(el.getBoundingClientRect)) {
9905
+ const rect = el.getBoundingClientRect();
9906
+ px = rect.left + rect.width / 2;
9907
+ py = rect.top + rect.height / 2;
9908
+ found = true;
9909
+ } else {
9910
+ const obj = /** @type {JSTarget} */(el);
9911
+ if (obj && isNum(obj.x) && isNum(obj.y)) {
9912
+ px = obj.x;
9913
+ py = obj.y;
9914
+ found = true;
9915
+ }
9916
+ }
9917
+ if (!found) {
9918
+ hasPositions = false;
9919
+ break;
9920
+ }
9921
+ pxArr.push(px);
9922
+ pyArr.push(py);
9923
+ if (px < minPosX) minPosX = px;
9924
+ if (py < minPosY) minPosY = py;
9925
+ if (px > maxPosX) maxPosX = px;
9926
+ if (py > maxPosY) maxPosY = py;
9927
+ }
9928
+ if (hasPositions) {
9929
+ let fX = pxArr[0];
9930
+ let fY = pyArr[0];
9931
+ if (fromArr) {
9932
+ fX = minPosX + from[0] * (maxPosX - minPosX);
9933
+ fY = minPosY + from[1] * (maxPosY - minPosY);
9934
+ } else if (fromCenter) {
9935
+ fX = (minPosX + maxPosX) / 2;
9936
+ fY = (minPosY + maxPosY) / 2;
9937
+ } else if (fromLast) {
9938
+ fX = pxArr[total - 1];
9939
+ fY = pyArr[total - 1];
9940
+ } else if (isNum(from)) {
9941
+ fX = pxArr[from];
9942
+ fY = pyArr[from];
9943
+ }
9944
+ for (let index = 0; index < total; index++) {
9945
+ const distanceX = fX - pxArr[index];
9946
+ const distanceY = fY - pyArr[index];
9947
+ let value = sqrt(distanceX * distanceX + distanceY * distanceY);
9948
+ if (axis === 'x') value = -distanceX;
9949
+ if (axis === 'y') value = -distanceY;
9950
+ values.push(value);
9951
+ }
9952
+ let minDist = Infinity;
9953
+ for (let index = 0, l = values.length; index < l; index++) {
9954
+ const absVal = abs(values[index]);
9955
+ if (absVal > 0 && absVal < minDist) minDist = absVal;
9956
+ }
9957
+ if (minDist > 0 && minDist < Infinity) {
9958
+ for (let index = 0, l = values.length; index < l; index++) {
9959
+ values[index] = values[index] / minDist;
9960
+ }
9961
+ }
9654
9962
  } else {
9655
- const fromX = !fromCenter ? fromIndex % grid[0] : (grid[0] - 1) / 2;
9656
- const fromY = !fromCenter ? floor(fromIndex / grid[0]) : (grid[1] - 1) / 2;
9657
- const toX = index % grid[0];
9658
- const toY = floor(index / grid[0]);
9659
- const distanceX = fromX - toX;
9660
- const distanceY = fromY - toY;
9661
- let value = sqrt(distanceX * distanceX + distanceY * distanceY);
9662
- if (axis === 'x') value = -distanceX;
9663
- if (axis === 'y') value = -distanceY;
9664
- values.push(value);
9963
+ for (let index = 0; index < total; index++) {
9964
+ values.push(abs(fromIndex - index));
9965
+ }
9966
+ }
9967
+ } else {
9968
+ for (let index = 0; index < total; index++) {
9969
+ if (!grid) {
9970
+ values.push(abs(fromIndex - index));
9971
+ } else {
9972
+ let fromX, fromY;
9973
+ if (fromArr) {
9974
+ fromX = from[0] * (grid[0] - 1);
9975
+ fromY = from[1] * (grid[1] - 1);
9976
+ } else if (fromCenter) {
9977
+ fromX = (grid[0] - 1) / 2;
9978
+ fromY = (grid[1] - 1) / 2;
9979
+ } else {
9980
+ fromX = fromIndex % grid[0];
9981
+ fromY = floor(fromIndex / grid[0]);
9982
+ }
9983
+ const toX = index % grid[0];
9984
+ const toY = floor(index / grid[0]);
9985
+ const distanceX = fromX - toX;
9986
+ const distanceY = fromY - toY;
9987
+ let value = sqrt(distanceX * distanceX + distanceY * distanceY);
9988
+ if (axis === 'x') value = -distanceX;
9989
+ if (axis === 'y') value = -distanceY;
9990
+ values.push(value);
9991
+ }
9665
9992
  }
9666
- maxValue = max(...values);
9667
9993
  }
9994
+ maxValue = max(...values);
9668
9995
  if (staggerEase) values = values.map(val => staggerEase(val / maxValue) * maxValue);
9669
9996
  if (reversed) values = values.map(val => axis ? (val < 0) ? val * -1 : -val : abs(maxValue - val));
9670
9997
  if (fromRandom) values = shuffle(values);
9671
9998
  }
9672
9999
  const spacing = isRange ? (val2 - val1) / maxValue : val1;
9673
- const offset = tl ? parseTimelinePosition(tl, isUnd(params.start) ? tl.iterationDuration : start) : /** @type {Number} */(start);
10000
+ if (isUnd(cachedOffset)) {
10001
+ cachedOffset = tl ? parseTimelinePosition(tl, isUnd(params.start) ? tl.iterationDuration : start) : /** @type {Number} */(start);
10002
+ }
9674
10003
  /** @type {String|Number} */
9675
- let output = offset + ((spacing * round$1(values[staggerIndex], 2)) || 0);
9676
- if (params.modifier) output = params.modifier(output);
10004
+ let output = cachedOffset + ((spacing * round$1(values[staggerIndex], 2)) || 0);
10005
+ if (params.modifier) output = params.modifier(/** @type {Number} */(output));
9677
10006
  if (unitMatch) output = `${output}${unitMatch[2]}`;
9678
10007
  return output;
9679
10008
  }
@@ -9682,11 +10011,13 @@ const stagger = (val, params = {}) => {
9682
10011
  var index$2 = /*#__PURE__*/Object.freeze({
9683
10012
  __proto__: null,
9684
10013
  $: registerTargets,
10014
+ addChild: addChild,
9685
10015
  clamp: clamp,
9686
10016
  cleanInlineStyles: cleanInlineStyles,
9687
10017
  createSeededRandom: createSeededRandom,
9688
10018
  damp: damp,
9689
10019
  degToRad: degToRad,
10020
+ forEachChildren: forEachChildren,
9690
10021
  get: get,
9691
10022
  keepTime: keepTime,
9692
10023
  lerp: lerp,
@@ -9697,6 +10028,7 @@ var index$2 = /*#__PURE__*/Object.freeze({
9697
10028
  random: random,
9698
10029
  randomPick: randomPick,
9699
10030
  remove: remove,
10031
+ removeChild: removeChild,
9700
10032
  round: round,
9701
10033
  roundPad: roundPad,
9702
10034
  set: set,
@@ -9896,7 +10228,7 @@ const createDrawable = (selector, start = 0, end = 0) => {
9896
10228
  * @param {Number} [precision]
9897
10229
  * @return {FunctionValue}
9898
10230
  */
9899
- const morphTo = (path2, precision = .33) => ($path1) => {
10231
+ const morphTo = (path2, precision = .33) => ($path1, index, total, prevTween) => {
9900
10232
  const tagName1 = ($path1.tagName || '').toLowerCase();
9901
10233
  if (!tagName1.match(/^(path|polygon|polyline)$/)) {
9902
10234
  throw new Error(`Can't morph a <${$path1.tagName}> SVG element. Use <path>, <polygon> or <polyline>.`);
@@ -9911,7 +10243,7 @@ const morphTo = (path2, precision = .33) => ($path1) => {
9911
10243
  }
9912
10244
  const isPath = $path1.tagName === 'path';
9913
10245
  const separator = isPath ? ' ' : ',';
9914
- const previousPoints = $path1[morphPointsSymbol];
10246
+ const previousPoints = prevTween ? prevTween._value : null;
9915
10247
  if (previousPoints) $path1.setAttribute(isPath ? 'd' : 'points', previousPoints);
9916
10248
 
9917
10249
  let v1 = '', v2 = '';
@@ -9933,8 +10265,6 @@ const morphTo = (path2, precision = .33) => ($path1) => {
9933
10265
  }
9934
10266
  }
9935
10267
 
9936
- $path1[morphPointsSymbol] = v2;
9937
-
9938
10268
  return [v1, v2];
9939
10269
  };
9940
10270
 
@@ -10120,7 +10450,7 @@ const processHTMLTemplate = (htmlTemplate, store, node, $parentFragment, type, d
10120
10450
  */
10121
10451
  class TextSplitter {
10122
10452
  /**
10123
- * @param {HTMLElement|NodeList|String|Array<HTMLElement>} target
10453
+ * @param {Element|NodeList|String|Array<Element>} target
10124
10454
  * @param {TextSplitterParams} [parameters]
10125
10455
  */
10126
10456
  constructor(target, parameters = {}) {
@@ -10192,11 +10522,11 @@ class TextSplitter {
10192
10522
  }
10193
10523
 
10194
10524
  /**
10195
- * @param {(...args: any[]) => Tickable | (() => void)} effect
10525
+ * @param {(...args: any[]) => Tickable | (() => void) | void} effect
10196
10526
  * @return this
10197
10527
  */
10198
10528
  addEffect(effect) {
10199
- if (!isFnc(effect)) return console.warn('Effect must return a function.');
10529
+ if (!isFnc(effect)) { console.warn('Effect must return a function.'); return this; }
10200
10530
  const refreshableEffect = keepTime(effect);
10201
10531
  this.effects.push(refreshableEffect);
10202
10532
  if (this.ready) this.effectsCleanups[this.effects.length - 1] = refreshableEffect(this);
@@ -10402,7 +10732,7 @@ class TextSplitter {
10402
10732
  }
10403
10733
 
10404
10734
  /**
10405
- * @param {HTMLElement|NodeList|String|Array<HTMLElement>} target
10735
+ * @param {Element|NodeList|String|Array<Element>} target
10406
10736
  * @param {TextSplitterParams} [parameters]
10407
10737
  * @return {TextSplitter}
10408
10738
  */
@@ -10420,11 +10750,263 @@ const split = (target, parameters) => {
10420
10750
  return new TextSplitter(target, parameters);
10421
10751
  };
10422
10752
 
10753
+
10754
+
10755
+ /**
10756
+ * '-' is the range operator; place it at the start or end of the string to use it as a literal (e.g. '-abc' or 'abc-')
10757
+ * @param {String} str
10758
+ * @return {String}
10759
+ */
10760
+ const expandCharRanges = (str) => {
10761
+ let result = '';
10762
+ for (let i = 0, l = str.length; i < l; i++) {
10763
+ if (i + 2 < l && str[i + 1] === '-' && str.charCodeAt(i) < str.charCodeAt(i + 2)) {
10764
+ const start = str.charCodeAt(i);
10765
+ const end = str.charCodeAt(i + 2);
10766
+ for (let c = start; c <= end; c++) result += String.fromCharCode(c);
10767
+ i += 2;
10768
+ } else {
10769
+ result += str[i];
10770
+ }
10771
+ }
10772
+ return result;
10773
+ };
10774
+
10775
+ const charSets = {
10776
+ lowercase: 'a-z',
10777
+ uppercase: 'A-Z',
10778
+ numbers: '0-9',
10779
+ symbols: '!%#_|*+=',
10780
+ braille: '⠀-⣿',
10781
+ blocks: '▀-▟',
10782
+ shades: '░-▓',
10783
+ };
10784
+
10785
+ const originalTexts = new WeakMap();
10786
+
10787
+ /**
10788
+ * Returns a function-based tween value that scrambles the target's text content,
10789
+ * progressively revealing the original text.
10790
+ *
10791
+ * @param {ScrambleTextParams} [params]
10792
+ * @return {FunctionValue}
10793
+ */
10794
+ const scrambleText = (params = {}) => {
10795
+ if (!params) params = {};
10796
+ const charsParam = params.chars;
10797
+ const easeFn = parseEase(params.ease || 'linear');
10798
+ const text = params.text;
10799
+ const fromParam = params.from;
10800
+ const reversed = params.reversed || false;
10801
+ const perturbation = params.perturbation || 0;
10802
+ const cursorParam = params.cursor;
10803
+ const cursorChars = cursorParam === true ? '_'
10804
+ : typeof cursorParam === 'number' ? String.fromCharCode(cursorParam)
10805
+ : typeof cursorParam === 'string' ? cursorParam
10806
+ : '';
10807
+ const cursorLen = cursorChars.length;
10808
+ const seed = params.seed || 0;
10809
+ const override = params.override !== undefined ? params.override : true;
10810
+ const revealRate = params.revealRate || 60;
10811
+ const interval = 1000 * globals.timeScale / revealRate;
10812
+ const settleDuration = params.settleDuration || 300 * globals.timeScale;
10813
+ const settleRate = params.settleRate || 30;
10814
+ const durationParam = params.duration;
10815
+ const revealDelayParam = params.revealDelay;
10816
+ const delayParam = params.delay;
10817
+ const onChange = params.onChange || noop;
10818
+
10819
+ return (target, index, targets, prevTween) => {
10820
+ const rawChars = typeof charsParam === 'function' ? charsParam(target, index, targets) : (charsParam || 'a-zA-Z0-9!%#_');
10821
+ const characters = expandCharRanges(charSets[rawChars] || rawChars);
10822
+ const totalChars = characters.length - 1;
10823
+ const duration = typeof durationParam === 'function' ? durationParam(target, index, targets) : durationParam;
10824
+ const revealDelay = typeof revealDelayParam === 'function' ? revealDelayParam(target, index, targets) : (revealDelayParam || 0);
10825
+ const delay = typeof delayParam === 'function' ? delayParam(target, index, targets) : (delayParam || 0);
10826
+ const rng = seed ? createSeededRandom(seed) : createSeededRandom();
10827
+ if (!originalTexts.has(target)) originalTexts.set(target, target.textContent);
10828
+ const startingText = prevTween ? prevTween._value : target.textContent;
10829
+ const targetText = text !== undefined
10830
+ ? (typeof text === 'function' ? text(target, index, targets) : text)
10831
+ : prevTween ? prevTween._value
10832
+ : originalTexts.get(target);
10833
+ const settledText = targetText === ' ' || targetText === '&nbsp;' ? ' ' : targetText;
10834
+ const startLength = startingText === ' ' ? 0 : startingText.length;
10835
+ const endLength = settledText.length;
10836
+ const overrideChars = override === true ? characters
10837
+ : typeof override === 'string' && override.length > 0 ? expandCharRanges(charSets[/** @type {String} */(override)] || /** @type {String} */(override))
10838
+ : null;
10839
+ const totalOverrideChars = overrideChars ? overrideChars.length - 1 : 0;
10840
+ // Space override uses &nbsp; so the browser doesn't collapse consecutive spaces in innerHTML
10841
+ const overrideChar = override === ' ' ? ' ' : null;
10842
+ // When starting from blank, only animate the target text length to avoid padding beyond it
10843
+ const animLength = override === '' ? endLength : Math.max(startLength, endLength);
10844
+ // Compute total duration from interval spacing and settle time, or use the explicit duration
10845
+ const animDuration = duration > 0 ? duration : (animLength - 1) * interval + settleDuration;
10846
+ const computedDuration = round$1((animDuration + revealDelay) / globals.timeScale, 0) * globals.timeScale;
10847
+ const revealDelayRatio = revealDelay > 0 ? round$1(revealDelay / computedDuration, 12) : 0;
10848
+ // Auto-resolve reveal direction: shrinking text reveals from right, growing from left
10849
+ const resolvedFrom = fromParam === undefined || fromParam === 'auto' ? (endLength < startLength ? 'right' : 'left') : fromParam;
10850
+ const charOrder = new Int32Array(animLength);
10851
+ if (resolvedFrom === 'random') {
10852
+ for (let i = 0; i < animLength; i++) charOrder[i] = i;
10853
+ for (let i = animLength - 1; i > 0; i--) {
10854
+ const j = rng(0, i);
10855
+ const t = charOrder[i]; charOrder[i] = charOrder[j]; charOrder[j] = t;
10856
+ }
10857
+ } else {
10858
+ const ref = resolvedFrom === 'right' ? (override === '' || !startLength ? animLength : startLength) - 1
10859
+ : resolvedFrom === 'center' ? ((override === '' || !startLength ? animLength : startLength) - 1) / 2
10860
+ : typeof resolvedFrom === 'number' ? resolvedFrom
10861
+ : 0;
10862
+ const abs = Math.abs;
10863
+ const indices = new Array(animLength);
10864
+ for (let i = 0; i < animLength; i++) indices[i] = i;
10865
+ indices.sort((a, b) => abs(a - ref) - abs(b - ref));
10866
+ for (let i = 0; i < animLength; i++) charOrder[indices[i]] = i;
10867
+ }
10868
+ if (reversed) {
10869
+ const last = animLength - 1;
10870
+ for (let i = 0; i < animLength; i++) charOrder[i] = last - charOrder[i];
10871
+ }
10872
+ // settleRatio is the fraction of the animation each character spends in the active scrambling zone
10873
+ const settleRatio = round$1(settleDuration / animDuration, 12);
10874
+ // settleSpacing is the time gap between consecutive characters entering the active zone
10875
+ const settleSpacing = round$1((1 - settleRatio) / animLength, 12);
10876
+ const cursorZone = cursorLen * settleSpacing;
10877
+ // stepRatio controls how often scramble characters refresh (based on settleRate)
10878
+ const stepRatio = round$1(1000 * globals.timeScale / (settleRate * computedDuration), 12);
10879
+ // Pre-compute per-character start and settle times
10880
+ const charStarts = new Float32Array(animLength);
10881
+ const charEnds = new Float32Array(animLength);
10882
+ const scale = perturbation > 0 ? perturbation * settleRatio : 0;
10883
+ for (let c = 0; c < animLength; c++) {
10884
+ const so = scale > 0 ? (rng(0, 2000) - 1000) / 1000 * scale : 0;
10885
+ const eo = scale > 0 ? (rng(0, 2000) - 1000) / 1000 * scale : 0;
10886
+ charStarts[c] = charOrder[c] * settleSpacing + so;
10887
+ charEnds[c] = Math.ceil((charStarts[c] + settleRatio + eo) / stepRatio) * stepRatio;
10888
+ }
10889
+ // When text shrinks with non-sequential from modes, delay target settle times past all extras
10890
+ if (endLength < animLength && resolvedFrom !== 'left' && resolvedFrom !== 'right' && resolvedFrom !== 'random') {
10891
+ let maxExtraEnd = 0;
10892
+ for (let c = endLength; c < animLength; c++) {
10893
+ if (charEnds[c] > maxExtraEnd) maxExtraEnd = charEnds[c];
10894
+ }
10895
+ const targets = new Array(endLength);
10896
+ for (let c = 0; c < endLength; c++) targets[c] = c;
10897
+ targets.sort((a, b) => charOrder[a] - charOrder[b]);
10898
+ const targetSpacing = (1 - maxExtraEnd) / endLength;
10899
+ for (let i = 0; i < endLength; i++) {
10900
+ const revealTime = maxExtraEnd + i * targetSpacing;
10901
+ if (revealTime > charEnds[targets[i]]) {
10902
+ charEnds[targets[i]] = revealTime;
10903
+ }
10904
+ }
10905
+ }
10906
+ // charCache holds the current scramble character for each position, refreshed at settleRate
10907
+ const charCache = new Array(animLength);
10908
+ for (let c = 0; c < animLength; c++) {
10909
+ charCache[c] = characters[rng(0, totalChars)];
10910
+ }
10911
+ // overrideCache holds scramble characters for the starting text (override: true or custom string)
10912
+ const overrideCache = overrideChars ? (overrideChars === characters ? charCache : new Array(animLength)) : null;
10913
+ if (overrideCache && overrideCache !== charCache) {
10914
+ for (let c = 0; c < animLength; c++) {
10915
+ overrideCache[c] = overrideChar || /** @type {String} */(overrideChars)[rng(0, overrideChars.length - 1)];
10916
+ }
10917
+ }
10918
+ // Build the initial display text based on override mode
10919
+ let fillStartText = startingText;
10920
+ if (!prevTween) {
10921
+ if (override === '') {
10922
+ fillStartText = '';
10923
+ } else if (overrideChars) {
10924
+ fillStartText = '';
10925
+ for (let c = 0; c < startLength; c++) {
10926
+ fillStartText += startingText[c] === ' ' ? ' ' : /** @type {Array<String>} */(overrideCache)[c];
10927
+ }
10928
+ }
10929
+ }
10930
+
10931
+ let lastValue = -1;
10932
+ let lastStep = -1;
10933
+ let scrambled = '';
10934
+ const hasOverride = override !== '';
10935
+ const hasOverrideChars = !!overrideChars;
10936
+ const hasCursor = cursorLen > 0;
10937
+
10938
+ return {
10939
+ from: 0,
10940
+ to: 1,
10941
+ duration: computedDuration,
10942
+ delay: delay,
10943
+ ease: 'linear',
10944
+ modifier: (v) => {
10945
+ if (v === lastValue) return scrambled;
10946
+ lastValue = v;
10947
+ if (delay > 0 && v <= 0) { scrambled = startingText; return startingText; }
10948
+ if (v <= 0) { scrambled = fillStartText; return fillStartText; }
10949
+ if (v >= 1) { scrambled = settledText; return settledText; }
10950
+ scrambled = '';
10951
+ // Only refresh scramble characters when we cross a settleRate step boundary
10952
+ const currentStep = (v / stepRatio) | 0;
10953
+ const refreshChars = currentStep !== lastStep;
10954
+ if (refreshChars) lastStep = currentStep;
10955
+ // Subtract delay ratio to get the effective animation progress
10956
+ const linear = revealDelayRatio > 0 ? (v - revealDelayRatio) / (1 - revealDelayRatio) : v;
10957
+ const t = linear > 0 ? easeFn(linear) : 0;
10958
+ for (let c = 0; c < animLength; c++) {
10959
+ // Each character has its own start/end window based on its reveal order
10960
+ const charStart = charStarts[c];
10961
+ const charEnd = charEnds[c];
10962
+ // Settled zone: character has finished its transition
10963
+ if (t >= charEnd) {
10964
+ if (c < endLength) scrambled += settledText[c];
10965
+ continue;
10966
+ }
10967
+ // Pre-transition zone: reveal wave hasn't reached this character yet
10968
+ if (t <= 0 || t < charStart) {
10969
+ if (hasOverride && c < startLength) {
10970
+ if (hasOverrideChars) {
10971
+ if (startingText[c] === ' ') {
10972
+ scrambled += ' ';
10973
+ } else {
10974
+ if (refreshChars) /** @type {Array<String>} */(overrideCache)[c] = overrideChar || /** @type {String} */(overrideChars)[rng(0, totalOverrideChars)];
10975
+ scrambled += /** @type {Array<String>} */(overrideCache)[c];
10976
+ }
10977
+ } else {
10978
+ // Default (override: false): show the original starting text
10979
+ scrambled += startingText[c];
10980
+ }
10981
+ }
10982
+ continue;
10983
+ }
10984
+ // Active zone: character is between charStart and charEnd
10985
+ const isSpace = (c < endLength && settledText[c] === ' ') || (c < startLength && startingText[c] === ' ');
10986
+ if (isSpace) {
10987
+ scrambled += ' ';
10988
+ } else if (hasCursor && t - charStart < cursorZone) {
10989
+ // Cursor sub-zone: show cursor character based on position within cursor width
10990
+ scrambled += cursorChars[cursorLen - 1 - (((t - charStart) / settleSpacing) | 0)];
10991
+ } else {
10992
+ // Scramble zone: show cycling random characters
10993
+ if (refreshChars) charCache[c] = characters[rng(0, totalChars)];
10994
+ scrambled += charCache[c];
10995
+ }
10996
+ }
10997
+ if (refreshChars) onChange(scrambled, t);
10998
+ return scrambled;
10999
+ }
11000
+ }
11001
+ }
11002
+ };
11003
+
10423
11004
  var index = /*#__PURE__*/Object.freeze({
10424
11005
  __proto__: null,
10425
11006
  TextSplitter: TextSplitter,
11007
+ scrambleText: scrambleText,
10426
11008
  split: split,
10427
11009
  splitText: splitText
10428
11010
  });
10429
11011
 
10430
- export { registerTargets as $, Animatable, AutoLayout, Draggable, JSAnimation, Scope, ScrollObserver, Spring, TextSplitter, Timeline, Timer, WAAPIAnimation, animate, clamp, cleanInlineStyles, createAnimatable, createDraggable, createDrawable, createLayout, createMotionPath, createScope, createSeededRandom, createSpring, createTimeline, createTimer, cubicBezier, damp, degToRad, eases, index$3 as easings, engine, get, irregular, keepTime, lerp, linear, mapRange, morphTo, onScroll, padEnd, padStart, radToDeg, random, randomPick, remove, round, roundPad, scrollContainers, set, shuffle, snap, split, splitText, spring, stagger, steps, index$1 as svg, sync, index as text, index$2 as utils, waapi, wrap };
11012
+ export { registerTargets as $, Animatable, AutoLayout, Draggable, JSAnimation, Scope, ScrollObserver, Spring, TextSplitter, Timeline, Timer, WAAPIAnimation, addChild, animate, clamp, cleanInlineStyles, createAnimatable, createDraggable, createDrawable, createLayout, createMotionPath, createScope, createSeededRandom, createSpring, createTimeline, createTimer, cubicBezier, damp, degToRad, eases, index$3 as easings, engine, forEachChildren, get, globals, irregular, keepTime, lerp, linear, mapRange, morphTo, onScroll, padEnd, padStart, radToDeg, random, randomPick, remove, removeChild, round, roundPad, scrambleText, scrollContainers, set, shuffle, snap, split, splitText, spring, stagger, steps, index$1 as svg, sync, index as text, index$2 as utils, waapi, wrap };