animejs 4.3.6 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. package/README.md +8 -11
  2. package/dist/bundles/anime.esm.js +1033 -421
  3. package/dist/bundles/anime.esm.min.js +2 -2
  4. package/dist/bundles/anime.umd.js +1038 -421
  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 +66 -63
  32. package/dist/modules/core/render.js +68 -65
  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 - core - CJS
3
- * @version v4.3.6
3
+ * @version v4.4.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
@@ -9,6 +9,7 @@
9
9
 
10
10
  var consts = require('./consts.cjs');
11
11
  var helpers = require('./helpers.cjs');
12
+ var transforms = require('./transforms.cjs');
12
13
 
13
14
  /**
14
15
  * @import {
@@ -59,58 +60,78 @@ const sanitizePropertyName = (propertyName, target, tweenType) => {
59
60
  /**
60
61
  * @template {Renderable} T
61
62
  * @param {T} renderable
63
+ * @param {Boolean} [inlineStylesOnly]
62
64
  * @return {T}
63
65
  */
64
- const cleanInlineStyles = renderable => {
65
- // Allow cleanInlineStyles() to be called on timelines
66
+ const revertValues = (renderable, inlineStylesOnly = false) => {
67
+ // Allow revertValues() to be called on timelines
66
68
  if (renderable._hasChildren) {
67
- helpers.forEachChildren(renderable, cleanInlineStyles, true);
69
+ helpers.forEachChildren(renderable, (/** @type {Renderable} */child) => revertValues(child, inlineStylesOnly), true);
68
70
  } else {
69
71
  const animation = /** @type {JSAnimation} */(renderable);
70
72
  animation.pause();
71
73
  helpers.forEachChildren(animation, (/** @type {Tween} */tween) => {
72
74
  const tweenProperty = tween.property;
73
75
  const tweenTarget = tween.target;
74
- if (tweenTarget[consts.isDomSymbol]) {
75
- const targetStyle = /** @type {DOMTarget} */(tweenTarget).style;
76
- const originalInlinedValue = tween._inlineValue;
77
- const tweenHadNoInlineValue = helpers.isNil(originalInlinedValue) || originalInlinedValue === consts.emptyString;
78
- if (tween._tweenType === consts.tweenTypes.TRANSFORM) {
79
- const cachedTransforms = tweenTarget[consts.transformsSymbol];
80
- if (tweenHadNoInlineValue) {
81
- delete cachedTransforms[tweenProperty];
82
- } else {
83
- cachedTransforms[tweenProperty] = originalInlinedValue;
84
- }
85
- if (tween._renderTransforms) {
86
- if (!Object.keys(cachedTransforms).length) {
87
- targetStyle.removeProperty('transform');
76
+ const tweenType = tween._tweenType;
77
+ const originalInlinedValue = tween._inlineValue;
78
+ const tweenHadNoInlineValue = helpers.isNil(originalInlinedValue) || originalInlinedValue === consts.emptyString;
79
+ if (tweenType === consts.tweenTypes.OBJECT) {
80
+ if (!inlineStylesOnly && !tweenHadNoInlineValue) {
81
+ tweenTarget[tweenProperty] = originalInlinedValue;
82
+ }
83
+ } else if (tweenTarget[consts.isDomSymbol]) {
84
+ if (tweenType === consts.tweenTypes.ATTRIBUTE) {
85
+ if (!inlineStylesOnly) {
86
+ if (tweenHadNoInlineValue) {
87
+ /** @type {DOMTarget} */(tweenTarget).removeAttribute(tweenProperty);
88
88
  } else {
89
- let str = consts.emptyString;
90
- for (let key in cachedTransforms) {
91
- str += consts.transformsFragmentStrings[key] + cachedTransforms[key] + ') ';
92
- }
93
- targetStyle.transform = str;
89
+ /** @type {DOMTarget} */(tweenTarget).setAttribute(tweenProperty, /** @type {String} */(originalInlinedValue));
94
90
  }
95
91
  }
96
92
  } else {
97
- if (tweenHadNoInlineValue) {
98
- targetStyle.removeProperty(helpers.toLowerCase(tweenProperty));
93
+ const targetStyle = /** @type {DOMTarget} */(tweenTarget).style;
94
+ if (tweenType === consts.tweenTypes.TRANSFORM) {
95
+ const cachedTransforms = tweenTarget[consts.transformsSymbol];
96
+ if (tweenHadNoInlineValue) {
97
+ delete cachedTransforms[tweenProperty];
98
+ } else {
99
+ cachedTransforms[tweenProperty] = originalInlinedValue;
100
+ }
101
+ if (tween._renderTransforms) {
102
+ if (!Object.keys(cachedTransforms).length) {
103
+ targetStyle.removeProperty('transform');
104
+ } else {
105
+ targetStyle.transform = transforms.buildTransformString(cachedTransforms);
106
+ }
107
+ }
99
108
  } else {
100
- targetStyle[tweenProperty] = originalInlinedValue;
109
+ if (tweenHadNoInlineValue) {
110
+ targetStyle.removeProperty(helpers.toLowerCase(tweenProperty));
111
+ } else {
112
+ targetStyle[tweenProperty] = originalInlinedValue;
113
+ }
101
114
  }
102
115
  }
103
- if (animation._tail === tween) {
104
- animation.targets.forEach(t => {
105
- if (t.getAttribute && t.getAttribute('style') === consts.emptyString) {
106
- t.removeAttribute('style');
107
- } });
108
- }
116
+ }
117
+ if (tweenTarget[consts.isDomSymbol] && animation._tail === tween) {
118
+ animation.targets.forEach(t => {
119
+ if (t.getAttribute && t.getAttribute('style') === consts.emptyString) {
120
+ t.removeAttribute('style');
121
+ } });
109
122
  }
110
123
  });
111
124
  }
112
125
  return renderable;
113
126
  };
114
127
 
128
+ /**
129
+ * @template {Renderable} T
130
+ * @param {T} renderable
131
+ * @return {T}
132
+ */
133
+ const cleanInlineStyles = renderable => revertValues(renderable, true);
134
+
115
135
  exports.cleanInlineStyles = cleanInlineStyles;
136
+ exports.revertValues = revertValues;
116
137
  exports.sanitizePropertyName = sanitizePropertyName;
@@ -1,4 +1,5 @@
1
1
  export function sanitizePropertyName(propertyName: string, target: Target, tweenType: tweenTypes): string;
2
+ export function revertValues<T extends Renderable>(renderable: T, inlineStylesOnly?: boolean): T;
2
3
  export function cleanInlineStyles<T extends Renderable>(renderable: T): T;
3
4
  import type { Target } from '../types/index.js';
4
5
  import { tweenTypes } from './consts.js';
@@ -1,12 +1,13 @@
1
1
  /**
2
2
  * Anime.js - core - ESM
3
- * @version v4.3.6
3
+ * @version v4.4.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
7
7
 
8
- import { tweenTypes, shortTransforms, isDomSymbol, transformsSymbol, transformsFragmentStrings, emptyString } from './consts.js';
9
- import { forEachChildren, isSvg, toLowerCase, isNil } from './helpers.js';
8
+ import { tweenTypes, isDomSymbol, transformsSymbol, emptyString, shortTransforms } from './consts.js';
9
+ import { forEachChildren, toLowerCase, isNil, isSvg } from './helpers.js';
10
+ import { buildTransformString } from './transforms.js';
10
11
 
11
12
  /**
12
13
  * @import {
@@ -57,57 +58,76 @@ const sanitizePropertyName = (propertyName, target, tweenType) => {
57
58
  /**
58
59
  * @template {Renderable} T
59
60
  * @param {T} renderable
61
+ * @param {Boolean} [inlineStylesOnly]
60
62
  * @return {T}
61
63
  */
62
- const cleanInlineStyles = renderable => {
63
- // Allow cleanInlineStyles() to be called on timelines
64
+ const revertValues = (renderable, inlineStylesOnly = false) => {
65
+ // Allow revertValues() to be called on timelines
64
66
  if (renderable._hasChildren) {
65
- forEachChildren(renderable, cleanInlineStyles, true);
67
+ forEachChildren(renderable, (/** @type {Renderable} */child) => revertValues(child, inlineStylesOnly), true);
66
68
  } else {
67
69
  const animation = /** @type {JSAnimation} */(renderable);
68
70
  animation.pause();
69
71
  forEachChildren(animation, (/** @type {Tween} */tween) => {
70
72
  const tweenProperty = tween.property;
71
73
  const tweenTarget = tween.target;
72
- if (tweenTarget[isDomSymbol]) {
73
- const targetStyle = /** @type {DOMTarget} */(tweenTarget).style;
74
- const originalInlinedValue = tween._inlineValue;
75
- const tweenHadNoInlineValue = isNil(originalInlinedValue) || originalInlinedValue === emptyString;
76
- if (tween._tweenType === tweenTypes.TRANSFORM) {
77
- const cachedTransforms = tweenTarget[transformsSymbol];
78
- if (tweenHadNoInlineValue) {
79
- delete cachedTransforms[tweenProperty];
80
- } else {
81
- cachedTransforms[tweenProperty] = originalInlinedValue;
82
- }
83
- if (tween._renderTransforms) {
84
- if (!Object.keys(cachedTransforms).length) {
85
- targetStyle.removeProperty('transform');
74
+ const tweenType = tween._tweenType;
75
+ const originalInlinedValue = tween._inlineValue;
76
+ const tweenHadNoInlineValue = isNil(originalInlinedValue) || originalInlinedValue === emptyString;
77
+ if (tweenType === tweenTypes.OBJECT) {
78
+ if (!inlineStylesOnly && !tweenHadNoInlineValue) {
79
+ tweenTarget[tweenProperty] = originalInlinedValue;
80
+ }
81
+ } else if (tweenTarget[isDomSymbol]) {
82
+ if (tweenType === tweenTypes.ATTRIBUTE) {
83
+ if (!inlineStylesOnly) {
84
+ if (tweenHadNoInlineValue) {
85
+ /** @type {DOMTarget} */(tweenTarget).removeAttribute(tweenProperty);
86
86
  } else {
87
- let str = emptyString;
88
- for (let key in cachedTransforms) {
89
- str += transformsFragmentStrings[key] + cachedTransforms[key] + ') ';
90
- }
91
- targetStyle.transform = str;
87
+ /** @type {DOMTarget} */(tweenTarget).setAttribute(tweenProperty, /** @type {String} */(originalInlinedValue));
92
88
  }
93
89
  }
94
90
  } else {
95
- if (tweenHadNoInlineValue) {
96
- targetStyle.removeProperty(toLowerCase(tweenProperty));
91
+ const targetStyle = /** @type {DOMTarget} */(tweenTarget).style;
92
+ if (tweenType === tweenTypes.TRANSFORM) {
93
+ const cachedTransforms = tweenTarget[transformsSymbol];
94
+ if (tweenHadNoInlineValue) {
95
+ delete cachedTransforms[tweenProperty];
96
+ } else {
97
+ cachedTransforms[tweenProperty] = originalInlinedValue;
98
+ }
99
+ if (tween._renderTransforms) {
100
+ if (!Object.keys(cachedTransforms).length) {
101
+ targetStyle.removeProperty('transform');
102
+ } else {
103
+ targetStyle.transform = buildTransformString(cachedTransforms);
104
+ }
105
+ }
97
106
  } else {
98
- targetStyle[tweenProperty] = originalInlinedValue;
107
+ if (tweenHadNoInlineValue) {
108
+ targetStyle.removeProperty(toLowerCase(tweenProperty));
109
+ } else {
110
+ targetStyle[tweenProperty] = originalInlinedValue;
111
+ }
99
112
  }
100
113
  }
101
- if (animation._tail === tween) {
102
- animation.targets.forEach(t => {
103
- if (t.getAttribute && t.getAttribute('style') === emptyString) {
104
- t.removeAttribute('style');
105
- } });
106
- }
114
+ }
115
+ if (tweenTarget[isDomSymbol] && animation._tail === tween) {
116
+ animation.targets.forEach(t => {
117
+ if (t.getAttribute && t.getAttribute('style') === emptyString) {
118
+ t.removeAttribute('style');
119
+ } });
107
120
  }
108
121
  });
109
122
  }
110
123
  return renderable;
111
124
  };
112
125
 
113
- export { cleanInlineStyles, sanitizePropertyName };
126
+ /**
127
+ * @template {Renderable} T
128
+ * @param {T} renderable
129
+ * @return {T}
130
+ */
131
+ const cleanInlineStyles = renderable => revertValues(renderable, true);
132
+
133
+ export { cleanInlineStyles, revertValues, sanitizePropertyName };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Anime.js - core - CJS
3
- * @version v4.3.6
3
+ * @version v4.4.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Anime.js - core - ESM
3
- * @version v4.3.6
3
+ * @version v4.4.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Anime.js - core - CJS
3
- * @version v4.3.6
3
+ * @version v4.4.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
@@ -24,26 +24,142 @@ var helpers = require('./helpers.cjs');
24
24
  */
25
25
  const parseInlineTransforms = (target, propName, animationInlineStyles) => {
26
26
  const inlineTransforms = target.style.transform;
27
- let inlinedStylesPropertyValue;
28
27
  if (inlineTransforms) {
29
28
  const cachedTransforms = target[consts.transformsSymbol];
30
- let t; while (t = consts.transformsExecRgx.exec(inlineTransforms)) {
31
- const inlinePropertyName = t[1];
32
- // const inlinePropertyValue = t[2];
33
- const inlinePropertyValue = t[2].slice(1, -1);
34
- cachedTransforms[inlinePropertyName] = inlinePropertyValue;
35
- if (inlinePropertyName === propName) {
36
- inlinedStylesPropertyValue = inlinePropertyValue;
37
- // Store the new parsed inline styles if animationInlineStyles is provided
38
- if (animationInlineStyles) {
39
- animationInlineStyles[propName] = inlinePropertyValue;
29
+ let pos = 0;
30
+ const len = inlineTransforms.length;
31
+ let fullTranslateValue;
32
+ while (pos < len) {
33
+ // Skip whitespace
34
+ while (pos < len && inlineTransforms.charCodeAt(pos) === 32) pos++;
35
+ if (pos >= len) break;
36
+ // Read function name
37
+ const nameStart = pos;
38
+ while (pos < len && inlineTransforms.charCodeAt(pos) !== 40) pos++;
39
+ if (pos >= len) break;
40
+ const name = inlineTransforms.substring(nameStart, pos);
41
+ // Scan to closing paren, recording top-level comma positions
42
+ let depth = 1;
43
+ const valueStart = pos + 1;
44
+ let c1 = -1, c2 = -1;
45
+ pos++;
46
+ while (pos < len && depth > 0) {
47
+ const c = inlineTransforms.charCodeAt(pos);
48
+ if (c === 40) depth++;
49
+ else if (c === 41) depth--;
50
+ else if (c === 44 && depth === 1) {
51
+ if (c1 === -1) c1 = pos;
52
+ else if (c2 === -1) c2 = pos;
40
53
  }
54
+ pos++;
41
55
  }
56
+ const valueEnd = pos - 1;
57
+ // Decompose multi-arg functions into individual axis properties
58
+ if (name === 'translate' || name === 'translate3d') {
59
+ if (c1 === -1) {
60
+ cachedTransforms.translateX = inlineTransforms.substring(valueStart, valueEnd).trim();
61
+ } else {
62
+ cachedTransforms.translateX = inlineTransforms.substring(valueStart, c1).trim();
63
+ if (c2 === -1) {
64
+ cachedTransforms.translateY = inlineTransforms.substring(c1 + 1, valueEnd).trim();
65
+ } else {
66
+ cachedTransforms.translateY = inlineTransforms.substring(c1 + 1, c2).trim();
67
+ cachedTransforms.translateZ = inlineTransforms.substring(c2 + 1, valueEnd).trim();
68
+ }
69
+ }
70
+ fullTranslateValue = inlineTransforms.substring(valueStart, valueEnd);
71
+ } else if (name === 'scale' || name === 'scale3d') {
72
+ if (c1 === -1) {
73
+ cachedTransforms.scale = inlineTransforms.substring(valueStart, valueEnd).trim();
74
+ } else {
75
+ cachedTransforms.scaleX = inlineTransforms.substring(valueStart, c1).trim();
76
+ if (c2 === -1) {
77
+ cachedTransforms.scaleY = inlineTransforms.substring(c1 + 1, valueEnd).trim();
78
+ } else {
79
+ cachedTransforms.scaleY = inlineTransforms.substring(c1 + 1, c2).trim();
80
+ cachedTransforms.scaleZ = inlineTransforms.substring(c2 + 1, valueEnd).trim();
81
+ }
82
+ }
83
+ } else {
84
+ cachedTransforms[name] = inlineTransforms.substring(valueStart, valueEnd);
85
+ }
86
+ }
87
+ // Resolve the requested property from the cache
88
+ if (propName === 'translate3d' && fullTranslateValue) {
89
+ if (animationInlineStyles) animationInlineStyles[propName] = fullTranslateValue;
90
+ return fullTranslateValue;
91
+ }
92
+ const cached = cachedTransforms[propName];
93
+ if (!helpers.isUnd(cached)) {
94
+ if (animationInlineStyles) animationInlineStyles[propName] = cached;
95
+ return cached;
42
96
  }
43
97
  }
44
- return inlineTransforms && !helpers.isUnd(inlinedStylesPropertyValue) ? inlinedStylesPropertyValue :
98
+ return propName === 'translate3d' ? '0px, 0px, 0px' :
99
+ propName === 'rotate3d' ? '0, 0, 0, 0deg' :
45
100
  helpers.stringStartsWith(propName, 'scale') ? '1' :
46
101
  helpers.stringStartsWith(propName, 'rotate') || helpers.stringStartsWith(propName, 'skew') ? '0deg' : '0px';
47
102
  };
48
103
 
104
+ /**
105
+ * Builds a CSS transform string from the target's cached transform properties.
106
+ * Iterates validTransforms in order (perspective > translate > rotate > scale > skew > matrix).
107
+ * When adjacent axis properties are all present, emits a shorter shorthand (translateX + translateY -> translate(x, y))
108
+ * The index is advanced past consumed properties so they are not emitted twice.
109
+ * Properties without a grouping partner (e.g. translateY alone, scaleZ alone) emit individually.
110
+ *
111
+ * @param {Record<String, String>} props
112
+ * @return {String}
113
+ */
114
+ const buildTransformString = (props) => {
115
+ let str = consts.emptyString;
116
+ for (let i = 0, l = consts.validTransforms.length; i < l; i++) {
117
+ const key = consts.validTransforms[i];
118
+ const val = props[key];
119
+ if (val !== undefined) {
120
+ // Group translateX with adjacent translateY / translateZ
121
+ if (key === 'translateX') {
122
+ const next = props.translateY;
123
+ if (next !== undefined) {
124
+ const next2 = props.translateZ;
125
+ if (next2 !== undefined) {
126
+ str += `translate3d(${val},${next},${next2}) `;
127
+ i += 2;
128
+ } else {
129
+ str += `translate(${val},${next}) `;
130
+ i += 1;
131
+ }
132
+ continue;
133
+ }
134
+ }
135
+ // Group scaleX with adjacent scaleY / scaleZ (only when standalone scale is absent)
136
+ if (key === 'scaleX' && props.scale === undefined) {
137
+ const next = props.scaleY;
138
+ if (next !== undefined) {
139
+ const next2 = props.scaleZ;
140
+ if (next2 !== undefined) {
141
+ str += `scale3d(${val},${next},${next2}) `;
142
+ i += 2;
143
+ } else {
144
+ str += `scale(${val},${next}) `;
145
+ i += 1;
146
+ }
147
+ continue;
148
+ }
149
+ }
150
+ // All other properties: emit individually using pre-built fragment string
151
+ str += `${consts.transformsFragmentStrings[key]}${val}) `;
152
+ }
153
+ // Preserve non-animatable rotate3d in correct position (after rotateZ, before scale)
154
+ if (key === 'rotateZ') {
155
+ if (props.rotate3d !== undefined) str += `rotate3d(${props.rotate3d}) `;
156
+ }
157
+ }
158
+ // Preserve non-animatable matrix/matrix3d from inline styles
159
+ if (props.matrix !== undefined) str += `matrix(${props.matrix}) `;
160
+ if (props.matrix3d !== undefined) str += `matrix3d(${props.matrix3d}) `;
161
+ return str;
162
+ };
163
+
164
+ exports.buildTransformString = buildTransformString;
49
165
  exports.parseInlineTransforms = parseInlineTransforms;
@@ -1,2 +1,3 @@
1
1
  export function parseInlineTransforms(target: DOMTarget, propName: string, animationInlineStyles: any): string;
2
+ export function buildTransformString(props: Record<string, string>): string;
2
3
  import type { DOMTarget } from '../types/index.js';
@@ -1,11 +1,11 @@
1
1
  /**
2
2
  * Anime.js - core - ESM
3
- * @version v4.3.6
3
+ * @version v4.4.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
7
7
 
8
- import { transformsSymbol, transformsExecRgx } from './consts.js';
8
+ import { transformsFragmentStrings, emptyString, validTransforms, transformsSymbol } from './consts.js';
9
9
  import { isUnd, stringStartsWith } from './helpers.js';
10
10
 
11
11
  /**
@@ -22,26 +22,141 @@ import { isUnd, stringStartsWith } from './helpers.js';
22
22
  */
23
23
  const parseInlineTransforms = (target, propName, animationInlineStyles) => {
24
24
  const inlineTransforms = target.style.transform;
25
- let inlinedStylesPropertyValue;
26
25
  if (inlineTransforms) {
27
26
  const cachedTransforms = target[transformsSymbol];
28
- let t; while (t = transformsExecRgx.exec(inlineTransforms)) {
29
- const inlinePropertyName = t[1];
30
- // const inlinePropertyValue = t[2];
31
- const inlinePropertyValue = t[2].slice(1, -1);
32
- cachedTransforms[inlinePropertyName] = inlinePropertyValue;
33
- if (inlinePropertyName === propName) {
34
- inlinedStylesPropertyValue = inlinePropertyValue;
35
- // Store the new parsed inline styles if animationInlineStyles is provided
36
- if (animationInlineStyles) {
37
- animationInlineStyles[propName] = inlinePropertyValue;
27
+ let pos = 0;
28
+ const len = inlineTransforms.length;
29
+ let fullTranslateValue;
30
+ while (pos < len) {
31
+ // Skip whitespace
32
+ while (pos < len && inlineTransforms.charCodeAt(pos) === 32) pos++;
33
+ if (pos >= len) break;
34
+ // Read function name
35
+ const nameStart = pos;
36
+ while (pos < len && inlineTransforms.charCodeAt(pos) !== 40) pos++;
37
+ if (pos >= len) break;
38
+ const name = inlineTransforms.substring(nameStart, pos);
39
+ // Scan to closing paren, recording top-level comma positions
40
+ let depth = 1;
41
+ const valueStart = pos + 1;
42
+ let c1 = -1, c2 = -1;
43
+ pos++;
44
+ while (pos < len && depth > 0) {
45
+ const c = inlineTransforms.charCodeAt(pos);
46
+ if (c === 40) depth++;
47
+ else if (c === 41) depth--;
48
+ else if (c === 44 && depth === 1) {
49
+ if (c1 === -1) c1 = pos;
50
+ else if (c2 === -1) c2 = pos;
38
51
  }
52
+ pos++;
39
53
  }
54
+ const valueEnd = pos - 1;
55
+ // Decompose multi-arg functions into individual axis properties
56
+ if (name === 'translate' || name === 'translate3d') {
57
+ if (c1 === -1) {
58
+ cachedTransforms.translateX = inlineTransforms.substring(valueStart, valueEnd).trim();
59
+ } else {
60
+ cachedTransforms.translateX = inlineTransforms.substring(valueStart, c1).trim();
61
+ if (c2 === -1) {
62
+ cachedTransforms.translateY = inlineTransforms.substring(c1 + 1, valueEnd).trim();
63
+ } else {
64
+ cachedTransforms.translateY = inlineTransforms.substring(c1 + 1, c2).trim();
65
+ cachedTransforms.translateZ = inlineTransforms.substring(c2 + 1, valueEnd).trim();
66
+ }
67
+ }
68
+ fullTranslateValue = inlineTransforms.substring(valueStart, valueEnd);
69
+ } else if (name === 'scale' || name === 'scale3d') {
70
+ if (c1 === -1) {
71
+ cachedTransforms.scale = inlineTransforms.substring(valueStart, valueEnd).trim();
72
+ } else {
73
+ cachedTransforms.scaleX = inlineTransforms.substring(valueStart, c1).trim();
74
+ if (c2 === -1) {
75
+ cachedTransforms.scaleY = inlineTransforms.substring(c1 + 1, valueEnd).trim();
76
+ } else {
77
+ cachedTransforms.scaleY = inlineTransforms.substring(c1 + 1, c2).trim();
78
+ cachedTransforms.scaleZ = inlineTransforms.substring(c2 + 1, valueEnd).trim();
79
+ }
80
+ }
81
+ } else {
82
+ cachedTransforms[name] = inlineTransforms.substring(valueStart, valueEnd);
83
+ }
84
+ }
85
+ // Resolve the requested property from the cache
86
+ if (propName === 'translate3d' && fullTranslateValue) {
87
+ if (animationInlineStyles) animationInlineStyles[propName] = fullTranslateValue;
88
+ return fullTranslateValue;
89
+ }
90
+ const cached = cachedTransforms[propName];
91
+ if (!isUnd(cached)) {
92
+ if (animationInlineStyles) animationInlineStyles[propName] = cached;
93
+ return cached;
40
94
  }
41
95
  }
42
- return inlineTransforms && !isUnd(inlinedStylesPropertyValue) ? inlinedStylesPropertyValue :
96
+ return propName === 'translate3d' ? '0px, 0px, 0px' :
97
+ propName === 'rotate3d' ? '0, 0, 0, 0deg' :
43
98
  stringStartsWith(propName, 'scale') ? '1' :
44
99
  stringStartsWith(propName, 'rotate') || stringStartsWith(propName, 'skew') ? '0deg' : '0px';
45
100
  };
46
101
 
47
- export { parseInlineTransforms };
102
+ /**
103
+ * Builds a CSS transform string from the target's cached transform properties.
104
+ * Iterates validTransforms in order (perspective > translate > rotate > scale > skew > matrix).
105
+ * When adjacent axis properties are all present, emits a shorter shorthand (translateX + translateY -> translate(x, y))
106
+ * The index is advanced past consumed properties so they are not emitted twice.
107
+ * Properties without a grouping partner (e.g. translateY alone, scaleZ alone) emit individually.
108
+ *
109
+ * @param {Record<String, String>} props
110
+ * @return {String}
111
+ */
112
+ const buildTransformString = (props) => {
113
+ let str = emptyString;
114
+ for (let i = 0, l = validTransforms.length; i < l; i++) {
115
+ const key = validTransforms[i];
116
+ const val = props[key];
117
+ if (val !== undefined) {
118
+ // Group translateX with adjacent translateY / translateZ
119
+ if (key === 'translateX') {
120
+ const next = props.translateY;
121
+ if (next !== undefined) {
122
+ const next2 = props.translateZ;
123
+ if (next2 !== undefined) {
124
+ str += `translate3d(${val},${next},${next2}) `;
125
+ i += 2;
126
+ } else {
127
+ str += `translate(${val},${next}) `;
128
+ i += 1;
129
+ }
130
+ continue;
131
+ }
132
+ }
133
+ // Group scaleX with adjacent scaleY / scaleZ (only when standalone scale is absent)
134
+ if (key === 'scaleX' && props.scale === undefined) {
135
+ const next = props.scaleY;
136
+ if (next !== undefined) {
137
+ const next2 = props.scaleZ;
138
+ if (next2 !== undefined) {
139
+ str += `scale3d(${val},${next},${next2}) `;
140
+ i += 2;
141
+ } else {
142
+ str += `scale(${val},${next}) `;
143
+ i += 1;
144
+ }
145
+ continue;
146
+ }
147
+ }
148
+ // All other properties: emit individually using pre-built fragment string
149
+ str += `${transformsFragmentStrings[key]}${val}) `;
150
+ }
151
+ // Preserve non-animatable rotate3d in correct position (after rotateZ, before scale)
152
+ if (key === 'rotateZ') {
153
+ if (props.rotate3d !== undefined) str += `rotate3d(${props.rotate3d}) `;
154
+ }
155
+ }
156
+ // Preserve non-animatable matrix/matrix3d from inline styles
157
+ if (props.matrix !== undefined) str += `matrix(${props.matrix}) `;
158
+ if (props.matrix3d !== undefined) str += `matrix3d(${props.matrix3d}) `;
159
+ return str;
160
+ };
161
+
162
+ export { buildTransformString, parseInlineTransforms };
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Anime.js - core - CJS
3
- * @version v4.3.6
3
+ * @version v4.4.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Anime.js - core - ESM
3
- * @version v4.3.6
3
+ * @version v4.4.0
4
4
  * @license MIT
5
5
  * @copyright 2026 - Julian Garnier
6
6
  */