motion 12.6.2 → 12.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/debug.js +12 -12
- package/dist/cjs/index.js +402 -347
- package/dist/cjs/mini.js +339 -352
- package/dist/cjs/react-client.js +169 -176
- package/dist/cjs/react-m.js +18 -22
- package/dist/cjs/react-mini.js +275 -336
- package/dist/es/framer-motion/dist/es/animation/animate/index.mjs +2 -2
- package/dist/es/framer-motion/dist/es/animation/animators/AcceleratedAnimation.mjs +7 -4
- package/dist/es/framer-motion/dist/es/animation/animators/MainThreadAnimation.mjs +8 -6
- package/dist/es/framer-motion/dist/es/animation/animators/waapi/animate-elements.mjs +10 -8
- package/dist/es/framer-motion/dist/es/animation/animators/waapi/animate-sequence.mjs +2 -2
- package/dist/es/framer-motion/dist/es/animation/animators/waapi/animate-style.mjs +2 -2
- package/dist/es/framer-motion/dist/es/animation/generators/spring/index.mjs +11 -1
- package/dist/es/framer-motion/dist/es/animation/interfaces/motion-value.mjs +3 -3
- package/dist/es/framer-motion/dist/es/animation/interfaces/visual-element-target.mjs +1 -2
- package/dist/es/framer-motion/dist/es/animation/interfaces/visual-element-variant.mjs +1 -2
- package/dist/es/framer-motion/dist/es/animation/optimized-appear/handoff.mjs +2 -4
- package/dist/es/framer-motion/dist/es/animation/optimized-appear/start.mjs +4 -6
- package/dist/es/framer-motion/dist/es/animation/sequence/create.mjs +3 -3
- package/dist/es/framer-motion/dist/es/animation/sequence/utils/calc-time.mjs +1 -2
- package/dist/es/framer-motion/dist/es/components/AnimatePresence/index.mjs +2 -2
- package/dist/es/framer-motion/dist/es/gestures/drag/VisualElementDragControls.mjs +5 -10
- package/dist/es/framer-motion/dist/es/motion/features/animation/index.mjs +1 -2
- package/dist/es/framer-motion/dist/es/motion/index.mjs +2 -3
- package/dist/es/framer-motion/dist/es/motion/utils/use-visual-element.mjs +3 -5
- package/dist/es/framer-motion/dist/es/projection/node/create-projection-node.mjs +19 -27
- package/dist/es/framer-motion/dist/es/projection/styles/transform.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/VisualElement.mjs +3 -4
- package/dist/es/framer-motion/dist/es/render/dom/DOMKeyframesResolver.mjs +1 -2
- package/dist/es/framer-motion/dist/es/render/dom/resize/handle-element.mjs +5 -6
- package/dist/es/framer-motion/dist/es/render/dom/scroll/track.mjs +1 -2
- package/dist/es/framer-motion/dist/es/render/dom/utils/css-variables-conversion.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/dom/utils/filter-props.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/html/utils/scrape-motion-values.mjs +1 -2
- package/dist/es/framer-motion/dist/es/render/utils/KeyframesResolver.mjs +2 -3
- package/dist/es/framer-motion/dist/es/render/utils/animation-state.mjs +3 -5
- package/dist/es/framer-motion/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/framer-motion/dist/es/render/utils/resolve-variants.mjs +1 -1
- package/dist/es/framer-motion/dist/es/utils/mix/complex.mjs +1 -2
- package/dist/es/framer-motion/dist/es/value/types/complex/index.mjs +2 -3
- package/dist/es/framer-motion/dist/es/value/use-scroll.mjs +2 -2
- package/dist/es/motion-dom/dist/es/animation/{controls/BaseGroup.mjs → GroupAnimation.mjs} +4 -5
- package/dist/es/motion-dom/dist/es/animation/GroupAnimationWithThen.mjs +9 -0
- package/dist/es/motion-dom/dist/es/animation/NativeAnimation.mjs +161 -0
- package/dist/es/motion-dom/dist/es/animation/generators/utils/is-generator.mjs +1 -1
- package/dist/es/motion-dom/dist/es/animation/keyframes/get-final.mjs +12 -0
- package/dist/es/motion-dom/dist/es/animation/keyframes/hydrate.mjs +26 -0
- package/dist/es/motion-dom/dist/es/animation/utils/get-value-transition.mjs +3 -5
- package/dist/es/motion-dom/dist/es/animation/waapi/easing/cubic-bezier.mjs +3 -0
- package/dist/es/motion-dom/dist/es/animation/waapi/easing/is-supported.mjs +14 -0
- package/dist/es/motion-dom/dist/es/animation/waapi/easing/map-easing.mjs +26 -0
- package/dist/es/motion-dom/dist/es/animation/waapi/easing/supported.mjs +15 -0
- package/dist/es/{framer-motion/dist/es/animation/animators/waapi/index.mjs → motion-dom/dist/es/animation/waapi/start-waapi-animation.mjs} +8 -6
- package/dist/es/{framer-motion/dist/es/animation/animators/waapi/utils/supports-partial-keyframes.mjs → motion-dom/dist/es/animation/waapi/supports/partial-keyframes.mjs} +2 -2
- package/dist/es/motion-dom/dist/es/animation/waapi/utils/apply-generator.mjs +14 -0
- package/dist/es/motion-dom/dist/es/animation/waapi/utils/linear.mjs +1 -4
- package/dist/es/motion-dom/dist/es/animation/waapi/utils/px-values.mjs +39 -0
- package/dist/es/motion-dom/dist/es/gestures/press/index.mjs +1 -1
- package/dist/es/motion-dom/dist/es/render/dom/style.mjs +15 -0
- package/dist/es/motion-dom/dist/es/utils/resolve-elements.mjs +2 -7
- package/dist/es/motion-dom/dist/es/utils/supports/flags.mjs +1 -3
- package/dist/es/motion-dom/dist/es/utils/supports/memo.mjs +1 -1
- package/dist/es/motion-dom/dist/es/value/index.mjs +1 -1
- package/dist/es/motion-utils/dist/es/errors.mjs +2 -4
- package/dist/motion.dev.js +402 -347
- package/dist/motion.js +1 -1
- package/package.json +3 -3
- package/dist/es/framer-motion/dist/es/animation/animators/waapi/NativeAnimation.mjs +0 -116
- package/dist/es/framer-motion/dist/es/animation/animators/waapi/utils/style.mjs +0 -8
- package/dist/es/motion-dom/dist/es/animation/controls/Group.mjs +0 -13
- package/dist/es/motion-dom/dist/es/animation/waapi/NativeAnimationControls.mjs +0 -85
- package/dist/es/motion-dom/dist/es/animation/waapi/utils/easing.mjs +0 -44
package/dist/cjs/react-mini.js
CHANGED
|
@@ -23,10 +23,7 @@ function useUnmountEffect(callback) {
|
|
|
23
23
|
return react.useEffect(() => () => callback(), []);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
const noop = (any) => any;
|
|
28
|
-
|
|
29
|
-
let invariant = noop;
|
|
26
|
+
let invariant = () => { };
|
|
30
27
|
if (process.env.NODE_ENV !== "production") {
|
|
31
28
|
invariant = (check, message) => {
|
|
32
29
|
if (!check) {
|
|
@@ -45,23 +42,8 @@ function memo(callback) {
|
|
|
45
42
|
};
|
|
46
43
|
}
|
|
47
44
|
|
|
48
|
-
/*
|
|
49
|
-
Progress within given range
|
|
50
|
-
|
|
51
|
-
Given a lower limit and an upper limit, we return the progress
|
|
52
|
-
(expressed as a number 0-1) represented by the given value, and
|
|
53
|
-
limit that progress to within 0-1.
|
|
54
|
-
|
|
55
|
-
@param [number]: Lower limit
|
|
56
|
-
@param [number]: Upper limit
|
|
57
|
-
@param [number]: Value to find progress within given range
|
|
58
|
-
@return [number]: Progress of value within range as expressed 0-1
|
|
59
|
-
*/
|
|
60
45
|
/*#__NO_SIDE_EFFECTS__*/
|
|
61
|
-
const
|
|
62
|
-
const toFromDifference = to - from;
|
|
63
|
-
return toFromDifference === 0 ? 1 : (value - from) / toFromDifference;
|
|
64
|
-
};
|
|
46
|
+
const noop = (any) => any;
|
|
65
47
|
|
|
66
48
|
/**
|
|
67
49
|
* Converts seconds to milliseconds
|
|
@@ -76,15 +58,14 @@ const millisecondsToSeconds = (milliseconds) => milliseconds / 1000;
|
|
|
76
58
|
|
|
77
59
|
const supportsScrollTimeline = /* @__PURE__ */ memo(() => window.ScrollTimeline !== undefined);
|
|
78
60
|
|
|
79
|
-
class
|
|
61
|
+
class GroupAnimation {
|
|
80
62
|
constructor(animations) {
|
|
81
63
|
// Bound to accomodate common `return animation.stop` pattern
|
|
82
64
|
this.stop = () => this.runAll("stop");
|
|
83
65
|
this.animations = animations.filter(Boolean);
|
|
84
66
|
}
|
|
85
67
|
get finished() {
|
|
86
|
-
|
|
87
|
-
return Promise.all(this.animations.map((animation) => "finished" in animation ? animation.finished : animation));
|
|
68
|
+
return Promise.all(this.animations.map((animation) => animation.finished));
|
|
88
69
|
}
|
|
89
70
|
/**
|
|
90
71
|
* TODO: Filter out cancelled or stopped animations before returning
|
|
@@ -155,141 +136,104 @@ class BaseGroupPlaybackControls {
|
|
|
155
136
|
}
|
|
156
137
|
}
|
|
157
138
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
*/
|
|
162
|
-
class GroupPlaybackControls extends BaseGroupPlaybackControls {
|
|
163
|
-
then(onResolve, onReject) {
|
|
164
|
-
return Promise.all(this.animations).then(onResolve).catch(onReject);
|
|
139
|
+
class GroupAnimationWithThen extends GroupAnimation {
|
|
140
|
+
then(onResolve, _onReject) {
|
|
141
|
+
return this.finished.finally(onResolve).then(() => { });
|
|
165
142
|
}
|
|
166
143
|
}
|
|
167
144
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
function calcGeneratorDuration(generator) {
|
|
182
|
-
let duration = 0;
|
|
183
|
-
const timeStep = 50;
|
|
184
|
-
let state = generator.next(duration);
|
|
185
|
-
while (!state.done && duration < maxGeneratorDuration) {
|
|
186
|
-
duration += timeStep;
|
|
187
|
-
state = generator.next(duration);
|
|
188
|
-
}
|
|
189
|
-
return duration >= maxGeneratorDuration ? Infinity : duration;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Create a progress => progress easing function from a generator.
|
|
194
|
-
*/
|
|
195
|
-
function createGeneratorEasing(options, scale = 100, createGenerator) {
|
|
196
|
-
const generator = createGenerator({ ...options, keyframes: [0, scale] });
|
|
197
|
-
const duration = Math.min(calcGeneratorDuration(generator), maxGeneratorDuration);
|
|
198
|
-
return {
|
|
199
|
-
type: "keyframes",
|
|
200
|
-
ease: (progress) => {
|
|
201
|
-
return generator.next(duration * progress).value / scale;
|
|
202
|
-
},
|
|
203
|
-
duration: millisecondsToSeconds(duration),
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function isGenerator(type) {
|
|
208
|
-
return typeof type === "function";
|
|
209
|
-
}
|
|
145
|
+
const isCSSVar = (name) => name.startsWith("--");
|
|
146
|
+
const style = {
|
|
147
|
+
set: (element, name, value) => {
|
|
148
|
+
isCSSVar(name)
|
|
149
|
+
? element.style.setProperty(name, value)
|
|
150
|
+
: (element.style[name] = value);
|
|
151
|
+
},
|
|
152
|
+
get: (element, name) => {
|
|
153
|
+
return isCSSVar(name)
|
|
154
|
+
? element.style.getPropertyValue(name)
|
|
155
|
+
: element.style[name];
|
|
156
|
+
},
|
|
157
|
+
};
|
|
210
158
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
159
|
+
const isNotNull = (value) => value !== null;
|
|
160
|
+
function getFinalKeyframe(keyframes, { repeat, repeatType = "loop" }, finalKeyframe) {
|
|
161
|
+
const resolvedKeyframes = keyframes.filter(isNotNull);
|
|
162
|
+
const index = repeat && repeatType !== "loop" && repeat % 2 === 1
|
|
163
|
+
? 0
|
|
164
|
+
: resolvedKeyframes.length - 1;
|
|
165
|
+
return !index || finalKeyframe === undefined
|
|
166
|
+
? resolvedKeyframes[index]
|
|
167
|
+
: finalKeyframe;
|
|
214
168
|
}
|
|
215
169
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}
|
|
220
|
-
get duration() {
|
|
221
|
-
var _a, _b, _c;
|
|
222
|
-
const durationInMs = ((_b = (_a = this.animation) === null || _a === void 0 ? void 0 : _a.effect) === null || _b === void 0 ? void 0 : _b.getComputedTiming().duration) ||
|
|
223
|
-
((_c = this.options) === null || _c === void 0 ? void 0 : _c.duration) ||
|
|
224
|
-
300;
|
|
225
|
-
return millisecondsToSeconds(Number(durationInMs));
|
|
226
|
-
}
|
|
227
|
-
get time() {
|
|
228
|
-
var _a;
|
|
229
|
-
if (this.animation) {
|
|
230
|
-
return millisecondsToSeconds(((_a = this.animation) === null || _a === void 0 ? void 0 : _a.currentTime) || 0);
|
|
231
|
-
}
|
|
232
|
-
return 0;
|
|
233
|
-
}
|
|
234
|
-
set time(newTime) {
|
|
235
|
-
if (this.animation) {
|
|
236
|
-
this.animation.currentTime = secondsToMilliseconds(newTime);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
get speed() {
|
|
240
|
-
return this.animation ? this.animation.playbackRate : 1;
|
|
241
|
-
}
|
|
242
|
-
set speed(newSpeed) {
|
|
243
|
-
if (this.animation) {
|
|
244
|
-
this.animation.playbackRate = newSpeed;
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
get state() {
|
|
248
|
-
return this.animation ? this.animation.playState : "finished";
|
|
249
|
-
}
|
|
250
|
-
get startTime() {
|
|
251
|
-
return this.animation ? this.animation.startTime : null;
|
|
252
|
-
}
|
|
253
|
-
get finished() {
|
|
254
|
-
return this.animation ? this.animation.finished : Promise.resolve();
|
|
170
|
+
const supportsPartialKeyframes = /*@__PURE__*/ memo(() => {
|
|
171
|
+
try {
|
|
172
|
+
document.createElement("div").animate({ opacity: [1] });
|
|
255
173
|
}
|
|
256
|
-
|
|
257
|
-
|
|
174
|
+
catch (e) {
|
|
175
|
+
return false;
|
|
258
176
|
}
|
|
259
|
-
|
|
260
|
-
|
|
177
|
+
return true;
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const pxValues = new Set([
|
|
181
|
+
// Border props
|
|
182
|
+
"borderWidth",
|
|
183
|
+
"borderTopWidth",
|
|
184
|
+
"borderRightWidth",
|
|
185
|
+
"borderBottomWidth",
|
|
186
|
+
"borderLeftWidth",
|
|
187
|
+
"borderRadius",
|
|
188
|
+
"radius",
|
|
189
|
+
"borderTopLeftRadius",
|
|
190
|
+
"borderTopRightRadius",
|
|
191
|
+
"borderBottomRightRadius",
|
|
192
|
+
"borderBottomLeftRadius",
|
|
193
|
+
// Positioning props
|
|
194
|
+
"width",
|
|
195
|
+
"maxWidth",
|
|
196
|
+
"height",
|
|
197
|
+
"maxHeight",
|
|
198
|
+
"top",
|
|
199
|
+
"right",
|
|
200
|
+
"bottom",
|
|
201
|
+
"left",
|
|
202
|
+
// Spacing props
|
|
203
|
+
"padding",
|
|
204
|
+
"paddingTop",
|
|
205
|
+
"paddingRight",
|
|
206
|
+
"paddingBottom",
|
|
207
|
+
"paddingLeft",
|
|
208
|
+
"margin",
|
|
209
|
+
"marginTop",
|
|
210
|
+
"marginRight",
|
|
211
|
+
"marginBottom",
|
|
212
|
+
"marginLeft",
|
|
213
|
+
// Misc
|
|
214
|
+
"backgroundPositionX",
|
|
215
|
+
"backgroundPositionY",
|
|
216
|
+
]);
|
|
217
|
+
|
|
218
|
+
function hydrateKeyframes(element, name, keyframes, pseudoElement) {
|
|
219
|
+
if (!Array.isArray(keyframes)) {
|
|
220
|
+
keyframes = [keyframes];
|
|
261
221
|
}
|
|
262
|
-
|
|
263
|
-
if (
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
222
|
+
for (let i = 0; i < keyframes.length; i++) {
|
|
223
|
+
if (keyframes[i] === null) {
|
|
224
|
+
keyframes[i] =
|
|
225
|
+
i === 0 && !pseudoElement
|
|
226
|
+
? style.get(element, name)
|
|
227
|
+
: keyframes[i - 1];
|
|
267
228
|
}
|
|
268
|
-
if (
|
|
269
|
-
|
|
229
|
+
if (typeof keyframes[i] === "number" && pxValues.has(name)) {
|
|
230
|
+
keyframes[i] = keyframes[i] + "px";
|
|
270
231
|
}
|
|
271
|
-
this.cancel();
|
|
272
|
-
}
|
|
273
|
-
flatten() {
|
|
274
|
-
var _a, _b;
|
|
275
|
-
if (!this.animation || !((_a = this.options) === null || _a === void 0 ? void 0 : _a.allowFlatten))
|
|
276
|
-
return;
|
|
277
|
-
(_b = this.animation.effect) === null || _b === void 0 ? void 0 : _b.updateTiming({ easing: "linear" });
|
|
278
|
-
}
|
|
279
|
-
attachTimeline(timeline) {
|
|
280
|
-
if (this.animation)
|
|
281
|
-
attachTimeline(this.animation, timeline);
|
|
282
|
-
return noop;
|
|
283
232
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
}
|
|
287
|
-
cancel() {
|
|
288
|
-
try {
|
|
289
|
-
this.animation && this.animation.cancel();
|
|
290
|
-
}
|
|
291
|
-
catch (e) { }
|
|
233
|
+
if (!pseudoElement && !supportsPartialKeyframes() && keyframes.length < 2) {
|
|
234
|
+
keyframes.unshift(style.get(element, name));
|
|
292
235
|
}
|
|
236
|
+
return keyframes;
|
|
293
237
|
}
|
|
294
238
|
|
|
295
239
|
const isBezierDefinition = (easing) => Array.isArray(easing) && typeof easing[0] === "number";
|
|
@@ -298,13 +242,11 @@ const isBezierDefinition = (easing) => Array.isArray(easing) && typeof easing[0]
|
|
|
298
242
|
* Add the ability for test suites to manually set support flags
|
|
299
243
|
* to better test more environments.
|
|
300
244
|
*/
|
|
301
|
-
const supportsFlags = {
|
|
302
|
-
linearEasing: undefined,
|
|
303
|
-
};
|
|
245
|
+
const supportsFlags = {};
|
|
304
246
|
|
|
305
247
|
function memoSupports(callback, supportsFlag) {
|
|
306
248
|
const memoized = memo(callback);
|
|
307
|
-
return () =>
|
|
249
|
+
return () => supportsFlags[supportsFlag] ?? memoized();
|
|
308
250
|
}
|
|
309
251
|
|
|
310
252
|
const supportsLinearEasing = /*@__PURE__*/ memoSupports(() => {
|
|
@@ -325,12 +267,13 @@ resolution = 10 // as milliseconds
|
|
|
325
267
|
let points = "";
|
|
326
268
|
const numPoints = Math.max(Math.round(duration / resolution), 2);
|
|
327
269
|
for (let i = 0; i < numPoints; i++) {
|
|
328
|
-
points += easing(
|
|
270
|
+
points += easing(i / (numPoints - 1)) + ", ";
|
|
329
271
|
}
|
|
330
272
|
return `linear(${points.substring(0, points.length - 2)})`;
|
|
331
273
|
};
|
|
332
274
|
|
|
333
275
|
const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
|
|
276
|
+
|
|
334
277
|
const supportedWaapiEasing = {
|
|
335
278
|
linear: "linear",
|
|
336
279
|
ease: "ease",
|
|
@@ -342,6 +285,7 @@ const supportedWaapiEasing = {
|
|
|
342
285
|
backIn: /*@__PURE__*/ cubicBezierAsString([0.31, 0.01, 0.66, -0.59]),
|
|
343
286
|
backOut: /*@__PURE__*/ cubicBezierAsString([0.33, 1.53, 0.69, 0.99]),
|
|
344
287
|
};
|
|
288
|
+
|
|
345
289
|
function mapEasingToNativeEasing(easing, duration) {
|
|
346
290
|
if (!easing) {
|
|
347
291
|
return undefined;
|
|
@@ -361,29 +305,10 @@ function mapEasingToNativeEasing(easing, duration) {
|
|
|
361
305
|
}
|
|
362
306
|
}
|
|
363
307
|
|
|
364
|
-
function
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
}
|
|
369
|
-
else if (typeof elementOrSelector === "string") {
|
|
370
|
-
let root = document;
|
|
371
|
-
if (scope) {
|
|
372
|
-
// TODO: Refactor to utils package
|
|
373
|
-
// invariant(
|
|
374
|
-
// Boolean(scope.current),
|
|
375
|
-
// "Scope provided, but no element detected."
|
|
376
|
-
// )
|
|
377
|
-
root = scope.current;
|
|
378
|
-
}
|
|
379
|
-
const elements = (_a = selectorCache === null || selectorCache === void 0 ? void 0 : selectorCache[elementOrSelector]) !== null && _a !== void 0 ? _a : root.querySelectorAll(elementOrSelector);
|
|
380
|
-
return elements ? Array.from(elements) : [];
|
|
381
|
-
}
|
|
382
|
-
return Array.from(elementOrSelector);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duration = 300, repeat = 0, repeatType = "loop", ease = "easeInOut", times, } = {}) {
|
|
386
|
-
const keyframeOptions = { [valueName]: keyframes };
|
|
308
|
+
function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duration = 300, repeat = 0, repeatType = "loop", ease = "easeInOut", times, } = {}, pseudoElement = undefined) {
|
|
309
|
+
const keyframeOptions = {
|
|
310
|
+
[valueName]: keyframes,
|
|
311
|
+
};
|
|
387
312
|
if (times)
|
|
388
313
|
keyframeOptions.offset = times;
|
|
389
314
|
const easing = mapEasingToNativeEasing(ease, duration);
|
|
@@ -399,187 +324,199 @@ function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duratio
|
|
|
399
324
|
fill: "both",
|
|
400
325
|
iterations: repeat + 1,
|
|
401
326
|
direction: repeatType === "reverse" ? "alternate" : "normal",
|
|
327
|
+
pseudoElement,
|
|
402
328
|
});
|
|
403
329
|
return animation;
|
|
404
330
|
}
|
|
405
331
|
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
parse: parseFloat,
|
|
409
|
-
transform: (v) => `${v}${unit}`,
|
|
410
|
-
});
|
|
411
|
-
const px = /*@__PURE__*/ createUnitType("px");
|
|
412
|
-
|
|
413
|
-
const browserNumberValueTypes = {
|
|
414
|
-
// Border props
|
|
415
|
-
borderWidth: px,
|
|
416
|
-
borderTopWidth: px,
|
|
417
|
-
borderRightWidth: px,
|
|
418
|
-
borderBottomWidth: px,
|
|
419
|
-
borderLeftWidth: px,
|
|
420
|
-
borderRadius: px,
|
|
421
|
-
radius: px,
|
|
422
|
-
borderTopLeftRadius: px,
|
|
423
|
-
borderTopRightRadius: px,
|
|
424
|
-
borderBottomRightRadius: px,
|
|
425
|
-
borderBottomLeftRadius: px,
|
|
426
|
-
// Positioning props
|
|
427
|
-
width: px,
|
|
428
|
-
maxWidth: px,
|
|
429
|
-
height: px,
|
|
430
|
-
maxHeight: px,
|
|
431
|
-
top: px,
|
|
432
|
-
right: px,
|
|
433
|
-
bottom: px,
|
|
434
|
-
left: px,
|
|
435
|
-
// Spacing props
|
|
436
|
-
padding: px,
|
|
437
|
-
paddingTop: px,
|
|
438
|
-
paddingRight: px,
|
|
439
|
-
paddingBottom: px,
|
|
440
|
-
paddingLeft: px,
|
|
441
|
-
margin: px,
|
|
442
|
-
marginTop: px,
|
|
443
|
-
marginRight: px,
|
|
444
|
-
marginBottom: px,
|
|
445
|
-
marginLeft: px,
|
|
446
|
-
// Misc
|
|
447
|
-
backgroundPositionX: px,
|
|
448
|
-
backgroundPositionY: px,
|
|
449
|
-
};
|
|
450
|
-
|
|
451
|
-
const isNotNull = (value) => value !== null;
|
|
452
|
-
function getFinalKeyframe(keyframes, { repeat, repeatType = "loop" }, finalKeyframe) {
|
|
453
|
-
const resolvedKeyframes = keyframes.filter(isNotNull);
|
|
454
|
-
const index = repeat && repeatType !== "loop" && repeat % 2 === 1
|
|
455
|
-
? 0
|
|
456
|
-
: resolvedKeyframes.length - 1;
|
|
457
|
-
return !index || finalKeyframe === undefined
|
|
458
|
-
? resolvedKeyframes[index]
|
|
459
|
-
: finalKeyframe;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
function setCSSVar(element, name, value) {
|
|
463
|
-
element.style.setProperty(name, value);
|
|
464
|
-
}
|
|
465
|
-
function setStyle(element, name, value) {
|
|
466
|
-
element.style[name] = value;
|
|
332
|
+
function isGenerator(type) {
|
|
333
|
+
return typeof type === "function" && "applyToOptions" in type;
|
|
467
334
|
}
|
|
468
335
|
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
}
|
|
473
|
-
catch (e) {
|
|
474
|
-
return false;
|
|
475
|
-
}
|
|
476
|
-
return true;
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
const supportsWaapi = /*@__PURE__*/ memo(() => Object.hasOwnProperty.call(Element.prototype, "animate"));
|
|
480
|
-
|
|
481
|
-
const state = new WeakMap();
|
|
482
|
-
function hydrateKeyframes(valueName, keyframes, read) {
|
|
483
|
-
for (let i = 0; i < keyframes.length; i++) {
|
|
484
|
-
if (keyframes[i] === null) {
|
|
485
|
-
keyframes[i] = i === 0 ? read() : keyframes[i - 1];
|
|
486
|
-
}
|
|
487
|
-
if (typeof keyframes[i] === "number" &&
|
|
488
|
-
browserNumberValueTypes[valueName]) {
|
|
489
|
-
keyframes[i] = browserNumberValueTypes[valueName].transform(keyframes[i]);
|
|
490
|
-
}
|
|
336
|
+
function applyGeneratorOptions({ type, ...options }) {
|
|
337
|
+
if (isGenerator(type)) {
|
|
338
|
+
return type.applyToOptions(options);
|
|
491
339
|
}
|
|
492
|
-
|
|
493
|
-
|
|
340
|
+
else {
|
|
341
|
+
options.duration ?? (options.duration = 300);
|
|
342
|
+
options.ease ?? (options.ease = "easeOut");
|
|
494
343
|
}
|
|
344
|
+
return options;
|
|
495
345
|
}
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
346
|
+
|
|
347
|
+
const animationMaps = new WeakMap();
|
|
348
|
+
const animationMapKey = (name, pseudoElement) => `${name}:${pseudoElement}`;
|
|
349
|
+
function getAnimationMap(element) {
|
|
350
|
+
const map = animationMaps.get(element) || new Map();
|
|
351
|
+
animationMaps.set(element, map);
|
|
352
|
+
return map;
|
|
501
353
|
}
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
valueKeyframes = [valueKeyframes];
|
|
515
|
-
}
|
|
516
|
-
hydrateKeyframes(valueName, valueKeyframes, readInitialKeyframe);
|
|
517
|
-
// TODO: Replace this with toString()?
|
|
518
|
-
if (isGenerator(options.type)) {
|
|
519
|
-
const generatorOptions = createGeneratorEasing(options, 100, options.type);
|
|
520
|
-
options.ease = supportsLinearEasing()
|
|
521
|
-
? generatorOptions.ease
|
|
522
|
-
: defaultEasing;
|
|
523
|
-
options.duration = secondsToMilliseconds(generatorOptions.duration);
|
|
524
|
-
options.type = "keyframes";
|
|
354
|
+
/**
|
|
355
|
+
* NativeAnimation implements AnimationPlaybackControls for the browser's Web Animations API.
|
|
356
|
+
*/
|
|
357
|
+
class NativeAnimation {
|
|
358
|
+
constructor(options) {
|
|
359
|
+
/**
|
|
360
|
+
* If we already have an animation, we don't need to instantiate one
|
|
361
|
+
* and can just use this as a controls interface.
|
|
362
|
+
*/
|
|
363
|
+
if ("animation" in options) {
|
|
364
|
+
this.animation = options.animation;
|
|
365
|
+
return;
|
|
525
366
|
}
|
|
526
|
-
|
|
527
|
-
|
|
367
|
+
const { element, name, keyframes: unresolvedKeyframes, pseudoElement, allowFlatten = false, } = options;
|
|
368
|
+
let { transition } = options;
|
|
369
|
+
this.allowFlatten = allowFlatten;
|
|
370
|
+
/**
|
|
371
|
+
* Stop any existing animations on the element before reading existing keyframes.
|
|
372
|
+
*
|
|
373
|
+
* TODO: Check for VisualElement before using animation state. This is a fallback
|
|
374
|
+
* for mini animate(). Do this when implementing NativeAnimationExtended.
|
|
375
|
+
*/
|
|
376
|
+
const animationMap = getAnimationMap(element);
|
|
377
|
+
const key = animationMapKey(name, pseudoElement || "");
|
|
378
|
+
const currentAnimation = animationMap.get(key);
|
|
379
|
+
currentAnimation && currentAnimation.stop();
|
|
380
|
+
/**
|
|
381
|
+
* TODO: If these keyframes aren't correctly hydrated then we want to throw
|
|
382
|
+
* run an instant animation.
|
|
383
|
+
*/
|
|
384
|
+
const keyframes = hydrateKeyframes(element, name, unresolvedKeyframes, pseudoElement);
|
|
385
|
+
invariant(typeof transition.type !== "string", `animateMini doesn't support "type" as a string. Did you mean to import { spring } from "motion"?`);
|
|
386
|
+
transition = applyGeneratorOptions(transition);
|
|
387
|
+
this.animation = startWaapiAnimation(element, name, keyframes, transition, pseudoElement);
|
|
388
|
+
if (transition.autoplay === false) {
|
|
389
|
+
this.animation.pause();
|
|
528
390
|
}
|
|
529
|
-
|
|
530
|
-
|
|
391
|
+
this.removeAnimation = () => animationMap.delete(key);
|
|
392
|
+
this.animation.onfinish = () => {
|
|
393
|
+
if (!pseudoElement) {
|
|
394
|
+
style.set(element, name, getFinalKeyframe(keyframes, transition));
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
this.commitStyles();
|
|
398
|
+
}
|
|
531
399
|
this.cancel();
|
|
532
|
-
this.resolveFinishedPromise();
|
|
533
|
-
};
|
|
534
|
-
const init = () => {
|
|
535
|
-
this.setValue = isCSSVar ? setCSSVar : setStyle;
|
|
536
|
-
this.options = options;
|
|
537
|
-
this.updateFinishedPromise();
|
|
538
|
-
this.removeAnimation = () => {
|
|
539
|
-
const elementState = state.get(element);
|
|
540
|
-
elementState && elementState.delete(valueName);
|
|
541
|
-
};
|
|
542
400
|
};
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
401
|
+
/**
|
|
402
|
+
* TODO: Check for VisualElement before using animation state.
|
|
403
|
+
*/
|
|
404
|
+
animationMap.set(key, this);
|
|
405
|
+
}
|
|
406
|
+
play() {
|
|
407
|
+
this.animation.play();
|
|
408
|
+
}
|
|
409
|
+
pause() {
|
|
410
|
+
this.animation.pause();
|
|
411
|
+
}
|
|
412
|
+
complete() {
|
|
413
|
+
this.animation.finish();
|
|
414
|
+
}
|
|
415
|
+
cancel() {
|
|
416
|
+
try {
|
|
417
|
+
this.animation.cancel();
|
|
547
418
|
}
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
getElementAnimationState(element).set(valueName, this);
|
|
419
|
+
catch (e) { }
|
|
420
|
+
this.removeAnimation();
|
|
421
|
+
}
|
|
422
|
+
stop() {
|
|
423
|
+
const { state } = this;
|
|
424
|
+
if (state === "idle" || state === "finished") {
|
|
425
|
+
return;
|
|
556
426
|
}
|
|
427
|
+
this.commitStyles();
|
|
428
|
+
this.cancel();
|
|
557
429
|
}
|
|
558
430
|
/**
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
431
|
+
* WAAPI doesn't natively have any interruption capabilities.
|
|
432
|
+
*
|
|
433
|
+
* In this method, we commit styles back to the DOM before cancelling
|
|
434
|
+
* the animation.
|
|
435
|
+
*
|
|
436
|
+
* This is designed to be overridden by NativeAnimationExtended, which
|
|
437
|
+
* will create a renderless JS animation and sample it twice to calculate
|
|
438
|
+
* its current value, "previous" value, and therefore allow
|
|
439
|
+
* Motion to also correctly calculate velocity for any subsequent animation
|
|
440
|
+
* while deferring the commit until the next animation frame.
|
|
562
441
|
*/
|
|
563
|
-
|
|
564
|
-
|
|
442
|
+
commitStyles() {
|
|
443
|
+
this.animation.commitStyles?.();
|
|
565
444
|
}
|
|
566
|
-
|
|
567
|
-
this.
|
|
568
|
-
|
|
569
|
-
|
|
445
|
+
get duration() {
|
|
446
|
+
console.log(this.animation.effect?.getComputedTiming());
|
|
447
|
+
const duration = this.animation.effect?.getComputedTiming().duration || 0;
|
|
448
|
+
return millisecondsToSeconds(Number(duration));
|
|
570
449
|
}
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
450
|
+
get time() {
|
|
451
|
+
return millisecondsToSeconds(Number(this.animation.currentTime) || 0);
|
|
452
|
+
}
|
|
453
|
+
set time(newTime) {
|
|
454
|
+
this.animation.currentTime = secondsToMilliseconds(newTime);
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* The playback speed of the animation.
|
|
458
|
+
* 1 = normal speed, 2 = double speed, 0.5 = half speed.
|
|
459
|
+
*/
|
|
460
|
+
get speed() {
|
|
461
|
+
return this.animation.playbackRate;
|
|
462
|
+
}
|
|
463
|
+
set speed(newSpeed) {
|
|
464
|
+
this.animation.playbackRate = newSpeed;
|
|
465
|
+
}
|
|
466
|
+
get state() {
|
|
467
|
+
return this.animation.playState;
|
|
468
|
+
}
|
|
469
|
+
get startTime() {
|
|
470
|
+
return Number(this.animation.startTime);
|
|
471
|
+
}
|
|
472
|
+
get finished() {
|
|
473
|
+
return this.animation.finished;
|
|
474
|
+
}
|
|
475
|
+
flatten() {
|
|
476
|
+
if (this.allowFlatten) {
|
|
477
|
+
this.animation.effect?.updateTiming({ easing: "linear" });
|
|
574
478
|
}
|
|
575
|
-
super.play();
|
|
576
479
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
480
|
+
/**
|
|
481
|
+
* Attaches a timeline to the animation, for instance the `ScrollTimeline`.
|
|
482
|
+
*/
|
|
483
|
+
attachTimeline(timeline) {
|
|
484
|
+
this.animation.timeline = timeline;
|
|
485
|
+
this.animation.onfinish = null;
|
|
486
|
+
return noop;
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Allows the animation to be awaited.
|
|
490
|
+
*
|
|
491
|
+
* @deprecated Use `finished` instead.
|
|
492
|
+
*/
|
|
493
|
+
then(onResolve, onReject) {
|
|
494
|
+
return this.finished.then(onResolve).catch(onReject);
|
|
580
495
|
}
|
|
581
496
|
}
|
|
582
497
|
|
|
498
|
+
function getValueTransition(transition, key) {
|
|
499
|
+
return (transition?.[key] ??
|
|
500
|
+
transition?.["default"] ??
|
|
501
|
+
transition);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
function resolveElements(elementOrSelector, scope, selectorCache) {
|
|
505
|
+
if (elementOrSelector instanceof EventTarget) {
|
|
506
|
+
return [elementOrSelector];
|
|
507
|
+
}
|
|
508
|
+
else if (typeof elementOrSelector === "string") {
|
|
509
|
+
let root = document;
|
|
510
|
+
if (scope) {
|
|
511
|
+
root = scope.current;
|
|
512
|
+
}
|
|
513
|
+
const elements = selectorCache?.[elementOrSelector] ??
|
|
514
|
+
root.querySelectorAll(elementOrSelector);
|
|
515
|
+
return elements ? Array.from(elements) : [];
|
|
516
|
+
}
|
|
517
|
+
return Array.from(elementOrSelector);
|
|
518
|
+
}
|
|
519
|
+
|
|
583
520
|
function animateElements(elementOrSelector, keyframes, options, scope) {
|
|
584
521
|
const elements = resolveElements(elementOrSelector, scope);
|
|
585
522
|
const numElements = elements.length;
|
|
@@ -599,13 +536,15 @@ function animateElements(elementOrSelector, keyframes, options, scope) {
|
|
|
599
536
|
const valueOptions = {
|
|
600
537
|
...getValueTransition(elementTransition, valueName),
|
|
601
538
|
};
|
|
602
|
-
valueOptions.duration = valueOptions.duration
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
539
|
+
valueOptions.duration && (valueOptions.duration = secondsToMilliseconds(valueOptions.duration));
|
|
540
|
+
valueOptions.delay && (valueOptions.delay = secondsToMilliseconds(valueOptions.delay));
|
|
541
|
+
animations.push(new NativeAnimation({
|
|
542
|
+
element,
|
|
543
|
+
name: valueName,
|
|
544
|
+
keyframes: valueKeyframes,
|
|
545
|
+
transition: valueOptions,
|
|
546
|
+
allowFlatten: !elementTransition.type && !elementTransition.ease,
|
|
547
|
+
}));
|
|
609
548
|
}
|
|
610
549
|
}
|
|
611
550
|
return animations;
|
|
@@ -613,7 +552,7 @@ function animateElements(elementOrSelector, keyframes, options, scope) {
|
|
|
613
552
|
|
|
614
553
|
const createScopedWaapiAnimate = (scope) => {
|
|
615
554
|
function scopedAnimate(elementOrSelector, keyframes, options) {
|
|
616
|
-
return new
|
|
555
|
+
return new GroupAnimationWithThen(animateElements(elementOrSelector, keyframes, options, scope));
|
|
617
556
|
}
|
|
618
557
|
return scopedAnimate;
|
|
619
558
|
};
|