motion 10.1.3 → 10.3.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 (102) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +1 -0
  3. package/dist/main.cjs.js +4 -0
  4. package/dist/main.es.js +2 -0
  5. package/dist/motion.min.js +1 -1
  6. package/dist/motion.umd.js +524 -189
  7. package/dist/size-animate-dom.js +1 -1
  8. package/dist/size-animate-style.js +1 -1
  9. package/dist/size-react.js +1 -1
  10. package/dist/size-spring.js +1 -1
  11. package/dist/size-timeline-dom.js +1 -1
  12. package/dist/size-webpack-animate.js +1 -1
  13. package/dist/targets/dom/animate-style.cjs.js +136 -111
  14. package/dist/targets/dom/animate-style.es.js +139 -114
  15. package/dist/targets/dom/animate.cjs.js +16 -3
  16. package/dist/targets/dom/animate.es.js +17 -4
  17. package/dist/targets/dom/data.cjs.js +4 -2
  18. package/dist/targets/dom/data.es.js +4 -2
  19. package/dist/targets/dom/style.cjs.js +1 -1
  20. package/dist/targets/dom/style.es.js +2 -2
  21. package/dist/targets/dom/timeline/index.cjs.js +17 -7
  22. package/dist/targets/dom/timeline/index.es.js +18 -8
  23. package/dist/targets/dom/timeline/utils/calc-time.cjs.js +3 -1
  24. package/dist/targets/dom/timeline/utils/calc-time.es.js +3 -1
  25. package/dist/targets/dom/utils/apply.cjs.js +4 -8
  26. package/dist/targets/dom/utils/apply.es.js +3 -7
  27. package/dist/targets/dom/utils/controls.cjs.js +6 -2
  28. package/dist/targets/dom/utils/controls.es.js +6 -2
  29. package/dist/targets/dom/utils/css-var.cjs.js +2 -2
  30. package/dist/targets/dom/utils/css-var.es.js +3 -3
  31. package/dist/targets/dom/utils/easing.cjs.js +7 -2
  32. package/dist/targets/dom/utils/easing.es.js +7 -3
  33. package/dist/targets/dom/utils/feature-detection.cjs.js +4 -4
  34. package/dist/targets/dom/utils/feature-detection.es.js +4 -4
  35. package/dist/targets/dom/utils/get-style-name.cjs.js +13 -0
  36. package/dist/targets/dom/utils/get-style-name.es.js +9 -0
  37. package/dist/targets/dom/utils/keyframes.cjs.js +2 -4
  38. package/dist/targets/dom/utils/keyframes.es.js +2 -4
  39. package/dist/targets/dom/utils/options.cjs.js +1 -1
  40. package/dist/targets/dom/utils/options.es.js +1 -1
  41. package/dist/targets/dom/utils/stop-animation.cjs.js +2 -0
  42. package/dist/targets/dom/utils/stop-animation.es.js +2 -0
  43. package/dist/targets/dom/utils/transforms.cjs.js +10 -7
  44. package/dist/targets/dom/utils/transforms.es.js +10 -7
  45. package/dist/targets/js/{animate-number.cjs.js → NumberAnimation.cjs.js} +42 -29
  46. package/dist/targets/js/{animate-number.es.js → NumberAnimation.es.js} +43 -29
  47. package/dist/targets/js/easing/glide/generator.cjs.js +99 -0
  48. package/dist/targets/js/easing/glide/generator.es.js +95 -0
  49. package/dist/targets/js/easing/glide/index.cjs.js +10 -0
  50. package/dist/targets/js/easing/glide/index.es.js +6 -0
  51. package/dist/targets/js/easing/spring/generator.cjs.js +64 -0
  52. package/dist/targets/js/easing/spring/generator.es.js +57 -0
  53. package/dist/targets/js/easing/spring/index.cjs.js +10 -0
  54. package/dist/targets/js/easing/spring/index.es.js +6 -0
  55. package/dist/targets/js/easing/utils/create-generator-easing.cjs.js +71 -0
  56. package/dist/targets/js/easing/utils/create-generator-easing.es.js +67 -0
  57. package/dist/targets/js/easing/{get-function.cjs.js → utils/get-function.cjs.js} +3 -3
  58. package/dist/targets/js/easing/{get-function.es.js → utils/get-function.es.js} +3 -3
  59. package/dist/targets/js/easing/utils/has-reached-target.cjs.js +10 -0
  60. package/dist/targets/js/easing/utils/has-reached-target.es.js +6 -0
  61. package/dist/targets/js/easing/utils/pregenerate-keyframes.cjs.js +34 -0
  62. package/dist/targets/js/easing/utils/pregenerate-keyframes.es.js +30 -0
  63. package/dist/targets/react/hooks/use-animation.cjs.js +5 -2
  64. package/dist/targets/react/hooks/use-animation.es.js +5 -2
  65. package/dist/targets/react/utils/keyframes.cjs.js +5 -3
  66. package/dist/targets/react/utils/keyframes.es.js +6 -4
  67. package/dist/utils/is-number.cjs.js +7 -0
  68. package/dist/utils/is-number.es.js +3 -0
  69. package/dist/utils/stagger.cjs.js +3 -2
  70. package/dist/utils/stagger.es.js +3 -2
  71. package/dist/utils/velocity-per-second.cjs.js +15 -0
  72. package/dist/utils/velocity-per-second.es.js +11 -0
  73. package/package.json +8 -14
  74. package/types/index.d.ts +2 -0
  75. package/types/targets/dom/animate-style.d.ts +2 -2
  76. package/types/targets/dom/data.d.ts +1 -7
  77. package/types/targets/dom/style.d.ts +1 -1
  78. package/types/targets/dom/types.d.ts +24 -18
  79. package/types/targets/dom/utils/apply.d.ts +3 -2
  80. package/types/targets/dom/utils/controls.d.ts +3 -3
  81. package/types/targets/dom/utils/easing.d.ts +2 -1
  82. package/types/targets/dom/utils/get-style-name.d.ts +1 -0
  83. package/types/targets/dom/utils/keyframes.d.ts +1 -1
  84. package/types/targets/dom/utils/stop-animation.d.ts +1 -1
  85. package/types/targets/dom/utils/transforms.d.ts +2 -2
  86. package/types/targets/js/{animate-number.d.ts → NumberAnimation.d.ts} +2 -3
  87. package/types/targets/js/easing/glide/generator.d.ts +5 -0
  88. package/types/targets/js/easing/glide/index.d.ts +2 -0
  89. package/types/targets/js/easing/glide/types.d.ts +14 -0
  90. package/types/targets/js/easing/spring/generator.d.ts +6 -0
  91. package/types/targets/js/easing/spring/index.d.ts +2 -0
  92. package/types/targets/js/easing/spring/types.d.ts +10 -0
  93. package/types/targets/js/easing/utils/create-generator-easing.d.ts +3 -0
  94. package/types/targets/js/easing/{get-function.d.ts → utils/get-function.d.ts} +2 -2
  95. package/types/targets/js/easing/utils/has-reached-target.d.ts +1 -0
  96. package/types/targets/js/easing/utils/pregenerate-keyframes.d.ts +7 -0
  97. package/types/targets/js/types.d.ts +11 -0
  98. package/types/utils/is-number.d.ts +1 -0
  99. package/types/generators/index.d.ts +0 -2
  100. package/types/generators/spring/create.d.ts +0 -13
  101. package/types/generators/spring/index.d.ts +0 -2
  102. package/types/generators/types.d.ts +0 -7
@@ -7,151 +7,176 @@ var cssVar = require('./utils/css-var.cjs.js');
7
7
  var noop = require('../../utils/noop.cjs.js');
8
8
  var time = require('./utils/time.cjs.js');
9
9
  var transforms = require('./utils/transforms.cjs.js');
10
- var stopAnimation = require('./utils/stop-animation.cjs.js');
11
10
  var easing = require('./utils/easing.cjs.js');
12
11
  var featureDetection = require('./utils/feature-detection.cjs.js');
13
12
  var apply = require('./utils/apply.cjs.js');
14
- var animateNumber = require('../js/animate-number.cjs.js');
13
+ var NumberAnimation = require('../js/NumberAnimation.cjs.js');
15
14
  var keyframes = require('./utils/keyframes.cjs.js');
16
15
  var style = require('./style.cjs.js');
17
16
  var defaults = require('./utils/defaults.cjs.js');
17
+ var getStyleName = require('./utils/get-style-name.cjs.js');
18
+ var isNumber = require('../../utils/is-number.cjs.js');
19
+ var stopAnimation = require('./utils/stop-animation.cjs.js');
18
20
 
19
- function animateStyle(element, name, keyframesDefinition, options = {}) {
21
+ function animateStyle(element, key, keyframesDefinition, options = {}) {
22
+ let animation;
20
23
  let { duration = defaults.defaults.duration, delay = defaults.defaults.delay, endDelay = defaults.defaults.endDelay, repeat = defaults.defaults.repeat, easing: easing$1 = defaults.defaults.easing, direction, offset, allowWebkitAcceleration = false, } = options;
21
24
  const data$1 = data.getAnimationData(element);
22
25
  let canAnimateNatively = featureDetection.supports.waapi();
23
26
  let render = noop.noop;
24
- const valueIsTransform = transforms.isTransform(name);
27
+ const valueIsTransform = transforms.isTransform(key);
25
28
  /**
26
29
  * If this is an individual transform, we need to map its
27
30
  * key to a CSS variable and update the element's transform style
28
31
  */
29
- if (valueIsTransform) {
30
- if (transforms.transformAlias[name])
31
- name = transforms.transformAlias[name];
32
- transforms.addTransformToElement(element, name);
33
- name = transforms.asTransformCssVar(name);
34
- }
32
+ valueIsTransform && transforms.addTransformToElement(element, key);
33
+ const name = getStyleName.getStyleName(key);
35
34
  /**
36
35
  * Get definition of value, this will be used to convert numerical
37
36
  * keyframes into the default value type.
38
37
  */
39
- const definition = transforms.transformPropertyDefinitions.get(name);
40
- /**
41
- * Replace null values with the previous keyframe value, or read
42
- * it from the DOM if it's the first keyframe.
43
- *
44
- * TODO: This needs to come after the valueIsTransform
45
- * check so it can correctly read the underlying value.
46
- * Should make a test for this.
47
- */
48
- let keyframes$1 = keyframes.hydrateKeyframes(keyframes.keyframesList(keyframesDefinition), element, name);
49
- stopCurrentAnimation(data$1, name);
38
+ const definition = transforms.transformDefinitions.get(name);
50
39
  /**
51
- * If this is a CSS variable we need to register it with the browser
52
- * before it can be animated natively. We also set it with setProperty
53
- * rather than directly onto the element.style object.
40
+ * Stop the current animation, if any. Because this will trigger
41
+ * commitStyles (DOM writes) and we might later trigger DOM reads,
42
+ * this is fired now and we return a factory function to create
43
+ * the actual animation that can get called in batch,
54
44
  */
55
- if (cssVar.isCssVar(name)) {
56
- render = apply.createCssVariableRenderer(element, name);
57
- if (featureDetection.supports.cssRegisterProperty()) {
58
- cssVar.registerCssVariable(name);
59
- }
60
- else {
61
- canAnimateNatively = false;
62
- }
63
- }
64
- else {
65
- render = apply.createStyleRenderer(element, name);
66
- }
67
- let animation;
45
+ stopAnimation.stopAnimation(data$1.animations[name]);
68
46
  /**
69
- * If we can animate this value with WAAPI, do so. Currently this only
70
- * feature detects CSS.registerProperty but could check WAAPI too.
47
+ * Batchable factory function containing all DOM reads.
71
48
  */
72
- if (canAnimateNatively) {
49
+ return () => {
50
+ const readInitialValue = () => { var _a, _b; return (_b = (_a = style.style.get(element, name)) !== null && _a !== void 0 ? _a : definition === null || definition === void 0 ? void 0 : definition.initialValue) !== null && _b !== void 0 ? _b : 0; };
73
51
  /**
74
- * Convert numbers to default value types. Currently this only supports
75
- * transforms but it could also support other value types.
52
+ * Replace null values with the previous keyframe value, or read
53
+ * it from the DOM if it's the first keyframe.
76
54
  */
77
- if (definition) {
78
- keyframes$1 = keyframes$1.map((value) => typeof value === "number" ? definition.toDefaultUnit(value) : value);
79
- }
80
- if (!featureDetection.supports.partialKeyframes() && keyframes$1.length === 1) {
81
- keyframes$1.unshift(style.style.get(element, name));
55
+ let keyframes$1 = keyframes.hydrateKeyframes(keyframes.keyframesList(keyframesDefinition), readInitialValue);
56
+ if (easing.isCustomEasing(easing$1)) {
57
+ const custom = easing$1.createAnimation(keyframes$1, readInitialValue, valueIsTransform, name, data$1);
58
+ easing$1 = custom.easing;
59
+ if (custom.keyframes !== undefined)
60
+ keyframes$1 = custom.keyframes;
61
+ if (custom.duration !== undefined)
62
+ duration = custom.duration;
82
63
  }
83
- const animationOptions = {
84
- delay: time.ms(delay),
85
- duration: time.ms(duration),
86
- endDelay: time.ms(endDelay),
87
- easing: !easing.isEasingList(easing$1) ? easing.convertEasing(easing$1) : undefined,
88
- direction,
89
- iterations: repeat + 1,
90
- fill: "both",
91
- };
92
- animation = element.animate({
93
- [name]: keyframes$1,
94
- offset,
95
- easing: easing.isEasingList(easing$1) ? easing$1.map(easing.convertEasing) : undefined,
96
- }, animationOptions);
97
64
  /**
98
- * Polyfill finished Promise in browsers that don't support it
65
+ * If this is a CSS variable we need to register it with the browser
66
+ * before it can be animated natively. We also set it with setProperty
67
+ * rather than directly onto the element.style object.
99
68
  */
100
- if (!animation.finished) {
101
- animation.finished = new Promise((resolve, reject) => {
102
- animation.onfinish = resolve;
103
- animation.oncancel = reject;
104
- });
69
+ if (cssVar.isCssVar(name)) {
70
+ render = apply.cssVariableRenderer(element, name);
71
+ if (featureDetection.supports.cssRegisterProperty()) {
72
+ cssVar.registerCssVariable(name);
73
+ }
74
+ else {
75
+ canAnimateNatively = false;
76
+ }
77
+ }
78
+ else {
79
+ render = apply.styleRenderer(element, name);
105
80
  }
106
- const target = keyframes$1[keyframes$1.length - 1];
107
- animation.finished.then(() => render(target)).catch(noop.noop);
108
81
  /**
109
- * This forces Webkit to run animations on the main thread by exploiting
110
- * this condition:
111
- * https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp?rev=281238#L1099
112
- *
113
- * This fixes Webkit's timing bugs, like accelerated animations falling
114
- * out of sync with main thread animations and massive delays in starting
115
- * accelerated animations in WKWebView.
82
+ * If we can animate this value with WAAPI, do so. Currently this only
83
+ * feature detects CSS.registerProperty but could check WAAPI too.
116
84
  */
117
- if (!allowWebkitAcceleration)
118
- animation.playbackRate = 1.000001;
119
- }
120
- else if (valueIsTransform && keyframes$1.every(isNumber)) {
121
- if (keyframes$1.length === 1) {
122
- keyframes$1.unshift(style.style.get(element, name) || (definition === null || definition === void 0 ? void 0 : definition.initialValue) || 0);
85
+ if (canAnimateNatively) {
86
+ /**
87
+ * Convert numbers to default value types. Currently this only supports
88
+ * transforms but it could also support other value types.
89
+ */
90
+ if (definition) {
91
+ keyframes$1 = keyframes$1.map((value) => isNumber.isNumber(value) ? definition.toDefaultUnit(value) : value);
92
+ }
93
+ /**
94
+ * If this browser doesn't support partial/implicit keyframes we need to
95
+ * explicitly provide one.
96
+ */
97
+ if (!featureDetection.supports.partialKeyframes() && keyframes$1.length === 1) {
98
+ keyframes$1.unshift(readInitialValue());
99
+ }
100
+ const animationOptions = {
101
+ delay: time.ms(delay),
102
+ duration: time.ms(duration),
103
+ endDelay: time.ms(endDelay),
104
+ easing: !easing.isEasingList(easing$1) ? easing.convertEasing(easing$1) : undefined,
105
+ direction,
106
+ iterations: repeat + 1,
107
+ fill: "both",
108
+ };
109
+ animation = element.animate({
110
+ [name]: keyframes$1,
111
+ offset,
112
+ easing: easing.isEasingList(easing$1) ? easing$1.map(easing.convertEasing) : undefined,
113
+ }, animationOptions);
114
+ /**
115
+ * Polyfill finished Promise in browsers that don't support it
116
+ */
117
+ if (!animation.finished) {
118
+ animation.finished = new Promise((resolve, reject) => {
119
+ animation.onfinish = resolve;
120
+ animation.oncancel = reject;
121
+ });
122
+ }
123
+ const target = keyframes$1[keyframes$1.length - 1];
124
+ animation.finished
125
+ .then(() => {
126
+ // Apply styles to target
127
+ render(target);
128
+ // Ensure fill modes don't persist
129
+ animation.cancel();
130
+ })
131
+ .catch(noop.noop);
132
+ /**
133
+ * This forces Webkit to run animations on the main thread by exploiting
134
+ * this condition:
135
+ * https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp?rev=281238#L1099
136
+ *
137
+ * This fixes Webkit's timing bugs, like accelerated animations falling
138
+ * out of sync with main thread animations and massive delays in starting
139
+ * accelerated animations in WKWebView.
140
+ */
141
+ if (!allowWebkitAcceleration)
142
+ animation.playbackRate = 1.000001;
143
+ /**
144
+ * If we can't animate the value natively then we can fallback to the numbers-only
145
+ * polyfill for transforms. All keyframes must be numerical.
146
+ */
147
+ }
148
+ else if (valueIsTransform && keyframes$1.every(isNumber.isNumber)) {
149
+ /**
150
+ * If we only have a single keyframe, we need to create an initial keyframe by reading
151
+ * the current value from the DOM.
152
+ */
153
+ if (keyframes$1.length === 1) {
154
+ keyframes$1.unshift(parseFloat(readInitialValue()));
155
+ }
156
+ if (definition) {
157
+ const applyStyle = render;
158
+ render = (v) => applyStyle(definition.toDefaultUnit(v));
159
+ }
160
+ animation = new NumberAnimation.NumberAnimation(render, keyframes$1, Object.assign(Object.assign({}, options), { duration,
161
+ easing: easing$1 }));
162
+ }
163
+ else {
164
+ const target = keyframes$1[keyframes$1.length - 1];
165
+ render(definition && isNumber.isNumber(target)
166
+ ? definition.toDefaultUnit(target)
167
+ : target);
123
168
  }
169
+ data$1.animations[name] = animation;
124
170
  /**
125
- * Transform styles are currently only accepted as numbers of
126
- * their default value type, so here we loop through and map
127
- * them to numbers.
171
+ * When an animation finishes, delete the reference to the previous animation.
128
172
  */
129
- keyframes$1 = keyframes$1.map((value) => typeof value === "string" ? parseFloat(value) : value);
130
- if (definition) {
131
- const applyStyle = render;
132
- render = (v) => applyStyle(definition.toDefaultUnit(v));
133
- }
134
- animation = animateNumber.animateNumber(render, keyframes$1, options);
135
- }
136
- else {
137
- const target = keyframes$1[keyframes$1.length - 1];
138
- render(definition && typeof target === "number"
139
- ? definition.toDefaultUnit(target)
140
- : target);
141
- }
142
- data$1.activeAnimations[name] = animation;
143
- /**
144
- * When an animation finishes, delete the reference to the previous animation.
145
- */
146
- animation === null || animation === void 0 ? void 0 : animation.finished.then(() => (data$1.activeAnimations[name] = undefined)).catch(noop.noop);
147
- return animation;
148
- }
149
- function stopCurrentAnimation(data, name) {
150
- if (data.activeAnimations[name]) {
151
- stopAnimation.stopAnimation(data.activeAnimations[name]);
152
- data.activeAnimations[name] = undefined;
153
- }
173
+ animation === null || animation === void 0 ? void 0 : animation.finished.then(() => {
174
+ data$1.animations[name] = undefined;
175
+ data$1.generators[name] = undefined;
176
+ data$1.prevGeneratorState[name] = undefined;
177
+ }).catch(noop.noop);
178
+ return animation;
179
+ };
154
180
  }
155
- const isNumber = (value) => typeof value === "number";
156
181
 
157
182
  exports.animateStyle = animateStyle;
@@ -2,152 +2,177 @@ import { getAnimationData } from './data.es.js';
2
2
  import { isCssVar, registerCssVariable } from './utils/css-var.es.js';
3
3
  import { noop } from '../../utils/noop.es.js';
4
4
  import { ms } from './utils/time.es.js';
5
- import { isTransform, transformAlias, addTransformToElement, asTransformCssVar, transformPropertyDefinitions } from './utils/transforms.es.js';
6
- import { stopAnimation } from './utils/stop-animation.es.js';
7
- import { isEasingList, convertEasing } from './utils/easing.es.js';
5
+ import { isTransform, addTransformToElement, transformDefinitions } from './utils/transforms.es.js';
6
+ import { isCustomEasing, isEasingList, convertEasing } from './utils/easing.es.js';
8
7
  import { supports } from './utils/feature-detection.es.js';
9
- import { createCssVariableRenderer, createStyleRenderer } from './utils/apply.es.js';
10
- import { animateNumber } from '../js/animate-number.es.js';
8
+ import { cssVariableRenderer, styleRenderer } from './utils/apply.es.js';
9
+ import { NumberAnimation } from '../js/NumberAnimation.es.js';
11
10
  import { hydrateKeyframes, keyframesList } from './utils/keyframes.es.js';
12
11
  import { style } from './style.es.js';
13
12
  import { defaults } from './utils/defaults.es.js';
13
+ import { getStyleName } from './utils/get-style-name.es.js';
14
+ import { isNumber } from '../../utils/is-number.es.js';
15
+ import { stopAnimation } from './utils/stop-animation.es.js';
14
16
 
15
- function animateStyle(element, name, keyframesDefinition, options = {}) {
17
+ function animateStyle(element, key, keyframesDefinition, options = {}) {
18
+ let animation;
16
19
  let { duration = defaults.duration, delay = defaults.delay, endDelay = defaults.endDelay, repeat = defaults.repeat, easing = defaults.easing, direction, offset, allowWebkitAcceleration = false, } = options;
17
20
  const data = getAnimationData(element);
18
21
  let canAnimateNatively = supports.waapi();
19
22
  let render = noop;
20
- const valueIsTransform = isTransform(name);
23
+ const valueIsTransform = isTransform(key);
21
24
  /**
22
25
  * If this is an individual transform, we need to map its
23
26
  * key to a CSS variable and update the element's transform style
24
27
  */
25
- if (valueIsTransform) {
26
- if (transformAlias[name])
27
- name = transformAlias[name];
28
- addTransformToElement(element, name);
29
- name = asTransformCssVar(name);
30
- }
28
+ valueIsTransform && addTransformToElement(element, key);
29
+ const name = getStyleName(key);
31
30
  /**
32
31
  * Get definition of value, this will be used to convert numerical
33
32
  * keyframes into the default value type.
34
33
  */
35
- const definition = transformPropertyDefinitions.get(name);
36
- /**
37
- * Replace null values with the previous keyframe value, or read
38
- * it from the DOM if it's the first keyframe.
39
- *
40
- * TODO: This needs to come after the valueIsTransform
41
- * check so it can correctly read the underlying value.
42
- * Should make a test for this.
43
- */
44
- let keyframes = hydrateKeyframes(keyframesList(keyframesDefinition), element, name);
45
- stopCurrentAnimation(data, name);
34
+ const definition = transformDefinitions.get(name);
46
35
  /**
47
- * If this is a CSS variable we need to register it with the browser
48
- * before it can be animated natively. We also set it with setProperty
49
- * rather than directly onto the element.style object.
36
+ * Stop the current animation, if any. Because this will trigger
37
+ * commitStyles (DOM writes) and we might later trigger DOM reads,
38
+ * this is fired now and we return a factory function to create
39
+ * the actual animation that can get called in batch,
50
40
  */
51
- if (isCssVar(name)) {
52
- render = createCssVariableRenderer(element, name);
53
- if (supports.cssRegisterProperty()) {
54
- registerCssVariable(name);
55
- }
56
- else {
57
- canAnimateNatively = false;
58
- }
59
- }
60
- else {
61
- render = createStyleRenderer(element, name);
62
- }
63
- let animation;
41
+ stopAnimation(data.animations[name]);
64
42
  /**
65
- * If we can animate this value with WAAPI, do so. Currently this only
66
- * feature detects CSS.registerProperty but could check WAAPI too.
43
+ * Batchable factory function containing all DOM reads.
67
44
  */
68
- if (canAnimateNatively) {
45
+ return () => {
46
+ const readInitialValue = () => { var _a, _b; return (_b = (_a = style.get(element, name)) !== null && _a !== void 0 ? _a : definition === null || definition === void 0 ? void 0 : definition.initialValue) !== null && _b !== void 0 ? _b : 0; };
69
47
  /**
70
- * Convert numbers to default value types. Currently this only supports
71
- * transforms but it could also support other value types.
48
+ * Replace null values with the previous keyframe value, or read
49
+ * it from the DOM if it's the first keyframe.
72
50
  */
73
- if (definition) {
74
- keyframes = keyframes.map((value) => typeof value === "number" ? definition.toDefaultUnit(value) : value);
75
- }
76
- if (!supports.partialKeyframes() && keyframes.length === 1) {
77
- keyframes.unshift(style.get(element, name));
51
+ let keyframes = hydrateKeyframes(keyframesList(keyframesDefinition), readInitialValue);
52
+ if (isCustomEasing(easing)) {
53
+ const custom = easing.createAnimation(keyframes, readInitialValue, valueIsTransform, name, data);
54
+ easing = custom.easing;
55
+ if (custom.keyframes !== undefined)
56
+ keyframes = custom.keyframes;
57
+ if (custom.duration !== undefined)
58
+ duration = custom.duration;
78
59
  }
79
- const animationOptions = {
80
- delay: ms(delay),
81
- duration: ms(duration),
82
- endDelay: ms(endDelay),
83
- easing: !isEasingList(easing) ? convertEasing(easing) : undefined,
84
- direction,
85
- iterations: repeat + 1,
86
- fill: "both",
87
- };
88
- animation = element.animate({
89
- [name]: keyframes,
90
- offset,
91
- easing: isEasingList(easing) ? easing.map(convertEasing) : undefined,
92
- }, animationOptions);
93
60
  /**
94
- * Polyfill finished Promise in browsers that don't support it
61
+ * If this is a CSS variable we need to register it with the browser
62
+ * before it can be animated natively. We also set it with setProperty
63
+ * rather than directly onto the element.style object.
95
64
  */
96
- if (!animation.finished) {
97
- animation.finished = new Promise((resolve, reject) => {
98
- animation.onfinish = resolve;
99
- animation.oncancel = reject;
100
- });
65
+ if (isCssVar(name)) {
66
+ render = cssVariableRenderer(element, name);
67
+ if (supports.cssRegisterProperty()) {
68
+ registerCssVariable(name);
69
+ }
70
+ else {
71
+ canAnimateNatively = false;
72
+ }
73
+ }
74
+ else {
75
+ render = styleRenderer(element, name);
101
76
  }
102
- const target = keyframes[keyframes.length - 1];
103
- animation.finished.then(() => render(target)).catch(noop);
104
77
  /**
105
- * This forces Webkit to run animations on the main thread by exploiting
106
- * this condition:
107
- * https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp?rev=281238#L1099
108
- *
109
- * This fixes Webkit's timing bugs, like accelerated animations falling
110
- * out of sync with main thread animations and massive delays in starting
111
- * accelerated animations in WKWebView.
78
+ * If we can animate this value with WAAPI, do so. Currently this only
79
+ * feature detects CSS.registerProperty but could check WAAPI too.
112
80
  */
113
- if (!allowWebkitAcceleration)
114
- animation.playbackRate = 1.000001;
115
- }
116
- else if (valueIsTransform && keyframes.every(isNumber)) {
117
- if (keyframes.length === 1) {
118
- keyframes.unshift(style.get(element, name) || (definition === null || definition === void 0 ? void 0 : definition.initialValue) || 0);
81
+ if (canAnimateNatively) {
82
+ /**
83
+ * Convert numbers to default value types. Currently this only supports
84
+ * transforms but it could also support other value types.
85
+ */
86
+ if (definition) {
87
+ keyframes = keyframes.map((value) => isNumber(value) ? definition.toDefaultUnit(value) : value);
88
+ }
89
+ /**
90
+ * If this browser doesn't support partial/implicit keyframes we need to
91
+ * explicitly provide one.
92
+ */
93
+ if (!supports.partialKeyframes() && keyframes.length === 1) {
94
+ keyframes.unshift(readInitialValue());
95
+ }
96
+ const animationOptions = {
97
+ delay: ms(delay),
98
+ duration: ms(duration),
99
+ endDelay: ms(endDelay),
100
+ easing: !isEasingList(easing) ? convertEasing(easing) : undefined,
101
+ direction,
102
+ iterations: repeat + 1,
103
+ fill: "both",
104
+ };
105
+ animation = element.animate({
106
+ [name]: keyframes,
107
+ offset,
108
+ easing: isEasingList(easing) ? easing.map(convertEasing) : undefined,
109
+ }, animationOptions);
110
+ /**
111
+ * Polyfill finished Promise in browsers that don't support it
112
+ */
113
+ if (!animation.finished) {
114
+ animation.finished = new Promise((resolve, reject) => {
115
+ animation.onfinish = resolve;
116
+ animation.oncancel = reject;
117
+ });
118
+ }
119
+ const target = keyframes[keyframes.length - 1];
120
+ animation.finished
121
+ .then(() => {
122
+ // Apply styles to target
123
+ render(target);
124
+ // Ensure fill modes don't persist
125
+ animation.cancel();
126
+ })
127
+ .catch(noop);
128
+ /**
129
+ * This forces Webkit to run animations on the main thread by exploiting
130
+ * this condition:
131
+ * https://trac.webkit.org/browser/webkit/trunk/Source/WebCore/platform/graphics/ca/GraphicsLayerCA.cpp?rev=281238#L1099
132
+ *
133
+ * This fixes Webkit's timing bugs, like accelerated animations falling
134
+ * out of sync with main thread animations and massive delays in starting
135
+ * accelerated animations in WKWebView.
136
+ */
137
+ if (!allowWebkitAcceleration)
138
+ animation.playbackRate = 1.000001;
139
+ /**
140
+ * If we can't animate the value natively then we can fallback to the numbers-only
141
+ * polyfill for transforms. All keyframes must be numerical.
142
+ */
143
+ }
144
+ else if (valueIsTransform && keyframes.every(isNumber)) {
145
+ /**
146
+ * If we only have a single keyframe, we need to create an initial keyframe by reading
147
+ * the current value from the DOM.
148
+ */
149
+ if (keyframes.length === 1) {
150
+ keyframes.unshift(parseFloat(readInitialValue()));
151
+ }
152
+ if (definition) {
153
+ const applyStyle = render;
154
+ render = (v) => applyStyle(definition.toDefaultUnit(v));
155
+ }
156
+ animation = new NumberAnimation(render, keyframes, Object.assign(Object.assign({}, options), { duration,
157
+ easing }));
158
+ }
159
+ else {
160
+ const target = keyframes[keyframes.length - 1];
161
+ render(definition && isNumber(target)
162
+ ? definition.toDefaultUnit(target)
163
+ : target);
119
164
  }
165
+ data.animations[name] = animation;
120
166
  /**
121
- * Transform styles are currently only accepted as numbers of
122
- * their default value type, so here we loop through and map
123
- * them to numbers.
167
+ * When an animation finishes, delete the reference to the previous animation.
124
168
  */
125
- keyframes = keyframes.map((value) => typeof value === "string" ? parseFloat(value) : value);
126
- if (definition) {
127
- const applyStyle = render;
128
- render = (v) => applyStyle(definition.toDefaultUnit(v));
129
- }
130
- animation = animateNumber(render, keyframes, options);
131
- }
132
- else {
133
- const target = keyframes[keyframes.length - 1];
134
- render(definition && typeof target === "number"
135
- ? definition.toDefaultUnit(target)
136
- : target);
137
- }
138
- data.activeAnimations[name] = animation;
139
- /**
140
- * When an animation finishes, delete the reference to the previous animation.
141
- */
142
- animation === null || animation === void 0 ? void 0 : animation.finished.then(() => (data.activeAnimations[name] = undefined)).catch(noop);
143
- return animation;
144
- }
145
- function stopCurrentAnimation(data, name) {
146
- if (data.activeAnimations[name]) {
147
- stopAnimation(data.activeAnimations[name]);
148
- data.activeAnimations[name] = undefined;
149
- }
169
+ animation === null || animation === void 0 ? void 0 : animation.finished.then(() => {
170
+ data.animations[name] = undefined;
171
+ data.generators[name] = undefined;
172
+ data.prevGeneratorState[name] = undefined;
173
+ }).catch(noop);
174
+ return animation;
175
+ };
150
176
  }
151
- const isNumber = (value) => typeof value === "number";
152
177
 
153
178
  export { animateStyle };
@@ -12,18 +12,31 @@ var defaults = require('./utils/defaults.cjs.js');
12
12
  function animate(elements, keyframes, options$1 = {}) {
13
13
  var _a;
14
14
  elements = resolveElements.resolveElements(elements);
15
- const animations = [];
16
15
  const numElements = elements.length;
16
+ /**
17
+ * Create and start new animations
18
+ */
19
+ const animationFactories = [];
17
20
  for (let i = 0; i < numElements; i++) {
18
21
  const element = elements[i];
19
22
  for (const key in keyframes) {
20
23
  const valueOptions = options.getOptions(options$1, key);
21
24
  valueOptions.delay = stagger.resolveOption(valueOptions.delay, i, numElements);
22
25
  const animation = animateStyle.animateStyle(element, key, keyframes[key], valueOptions);
23
- animation && animations.push(animation);
26
+ animationFactories.push(animation);
24
27
  }
25
28
  }
26
- return controls.createAnimationControls(animations, (_a = options$1.duration) !== null && _a !== void 0 ? _a : defaults.defaults.duration);
29
+ return controls.createAnimations(animationFactories,
30
+ /**
31
+ * TODO:
32
+ * If easing is set to spring or glide, duration will be dynamically
33
+ * generated. Ideally we would dynamically generate this from
34
+ * animation.effect.getComputedTiming().duration but this isn't
35
+ * supported in iOS13 or our number polyfill. Perhaps it's possible
36
+ * to Proxy animations returned from animateStyle that has duration
37
+ * as a getter.
38
+ */
39
+ (_a = options$1.duration) !== null && _a !== void 0 ? _a : defaults.defaults.duration);
27
40
  }
28
41
 
29
42
  exports.animate = animate;