motion 11.11.14 → 11.11.16

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.
@@ -0,0 +1,564 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ function memo(callback) {
6
+ let result;
7
+ return () => {
8
+ if (result === undefined)
9
+ result = callback();
10
+ return result;
11
+ };
12
+ }
13
+
14
+ const supportsScrollTimeline = memo(() => window.ScrollTimeline !== undefined);
15
+
16
+ class GroupPlaybackControls {
17
+ constructor(animations) {
18
+ // Bound to accomodate common `return animation.stop` pattern
19
+ this.stop = () => this.runAll("stop");
20
+ this.animations = animations.filter(Boolean);
21
+ }
22
+ then(onResolve, onReject) {
23
+ return Promise.all(this.animations).then(onResolve).catch(onReject);
24
+ }
25
+ /**
26
+ * TODO: Filter out cancelled or stopped animations before returning
27
+ */
28
+ getAll(propName) {
29
+ return this.animations[0][propName];
30
+ }
31
+ setAll(propName, newValue) {
32
+ for (let i = 0; i < this.animations.length; i++) {
33
+ this.animations[i][propName] = newValue;
34
+ }
35
+ }
36
+ attachTimeline(timeline, fallback) {
37
+ const subscriptions = this.animations.map((animation) => {
38
+ if (supportsScrollTimeline() && animation.attachTimeline) {
39
+ return animation.attachTimeline(timeline);
40
+ }
41
+ else {
42
+ return fallback(animation);
43
+ }
44
+ });
45
+ return () => {
46
+ subscriptions.forEach((cancel, i) => {
47
+ cancel && cancel();
48
+ this.animations[i].stop();
49
+ });
50
+ };
51
+ }
52
+ get time() {
53
+ return this.getAll("time");
54
+ }
55
+ set time(time) {
56
+ this.setAll("time", time);
57
+ }
58
+ get speed() {
59
+ return this.getAll("speed");
60
+ }
61
+ set speed(speed) {
62
+ this.setAll("speed", speed);
63
+ }
64
+ get startTime() {
65
+ return this.getAll("startTime");
66
+ }
67
+ get duration() {
68
+ let max = 0;
69
+ for (let i = 0; i < this.animations.length; i++) {
70
+ max = Math.max(max, this.animations[i].duration);
71
+ }
72
+ return max;
73
+ }
74
+ runAll(methodName) {
75
+ this.animations.forEach((controls) => controls[methodName]());
76
+ }
77
+ flatten() {
78
+ this.runAll("flatten");
79
+ }
80
+ play() {
81
+ this.runAll("play");
82
+ }
83
+ pause() {
84
+ this.runAll("pause");
85
+ }
86
+ cancel() {
87
+ this.runAll("cancel");
88
+ }
89
+ complete() {
90
+ this.runAll("complete");
91
+ }
92
+ }
93
+
94
+ const noop = (any) => any;
95
+
96
+ let invariant = noop;
97
+ if (process.env.NODE_ENV !== "production") {
98
+ invariant = (check, message) => {
99
+ if (!check) {
100
+ throw new Error(message);
101
+ }
102
+ };
103
+ }
104
+
105
+ function resolveElements(elements, scope, selectorCache) {
106
+ var _a;
107
+ if (typeof elements === "string") {
108
+ let root = document;
109
+ if (scope) {
110
+ invariant(Boolean(scope.current), "Scope provided, but no element detected.");
111
+ root = scope.current;
112
+ }
113
+ if (selectorCache) {
114
+ (_a = selectorCache[elements]) !== null && _a !== void 0 ? _a : (selectorCache[elements] = root.querySelectorAll(elements));
115
+ elements = selectorCache[elements];
116
+ }
117
+ else {
118
+ elements = root.querySelectorAll(elements);
119
+ }
120
+ }
121
+ else if (elements instanceof Element) {
122
+ elements = [elements];
123
+ }
124
+ /**
125
+ * Return an empty array
126
+ */
127
+ return Array.from(elements || []);
128
+ }
129
+
130
+ /**
131
+ * Converts seconds to milliseconds
132
+ *
133
+ * @param seconds - Time in seconds.
134
+ * @return milliseconds - Converted time in milliseconds.
135
+ */
136
+ const secondsToMilliseconds = (seconds) => seconds * 1000;
137
+ const millisecondsToSeconds = (milliseconds) => milliseconds / 1000;
138
+
139
+ function getValueTransition(transition, key) {
140
+ return transition
141
+ ? transition[key] ||
142
+ transition["default"] ||
143
+ transition
144
+ : undefined;
145
+ }
146
+
147
+ const isBezierDefinition = (easing) => Array.isArray(easing) && typeof easing[0] === "number";
148
+
149
+ /*
150
+ Progress within given range
151
+
152
+ Given a lower limit and an upper limit, we return the progress
153
+ (expressed as a number 0-1) represented by the given value, and
154
+ limit that progress to within 0-1.
155
+
156
+ @param [number]: Lower limit
157
+ @param [number]: Upper limit
158
+ @param [number]: Value to find progress within given range
159
+ @return [number]: Progress of value within range as expressed 0-1
160
+ */
161
+ const progress = (from, to, value) => {
162
+ const toFromDifference = to - from;
163
+ return toFromDifference === 0 ? 1 : (value - from) / toFromDifference;
164
+ };
165
+
166
+ // Create a linear easing point for every 10 ms
167
+ const resolution = 10;
168
+ const generateLinearEasing = (easing, duration // as milliseconds
169
+ ) => {
170
+ let points = "";
171
+ const numPoints = Math.max(Math.round(duration / resolution), 2);
172
+ for (let i = 0; i < numPoints; i++) {
173
+ points += easing(progress(0, numPoints - 1, i)) + ", ";
174
+ }
175
+ return `linear(${points.substring(0, points.length - 2)})`;
176
+ };
177
+
178
+ /**
179
+ * Add the ability for test suites to manually set support flags
180
+ * to better test more environments.
181
+ */
182
+ const supportsFlags = {
183
+ linearEasing: undefined,
184
+ };
185
+
186
+ function memoSupports(callback, supportsFlag) {
187
+ const memoized = memo(callback);
188
+ return () => { var _a; return (_a = supportsFlags[supportsFlag]) !== null && _a !== void 0 ? _a : memoized(); };
189
+ }
190
+
191
+ const supportsLinearEasing = /*@__PURE__*/ memoSupports(() => {
192
+ try {
193
+ document
194
+ .createElement("div")
195
+ .animate({ opacity: 0 }, { easing: "linear(0, 1)" });
196
+ }
197
+ catch (e) {
198
+ return false;
199
+ }
200
+ return true;
201
+ }, "linearEasing");
202
+
203
+ const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
204
+ const supportedWaapiEasing = {
205
+ linear: "linear",
206
+ ease: "ease",
207
+ easeIn: "ease-in",
208
+ easeOut: "ease-out",
209
+ easeInOut: "ease-in-out",
210
+ circIn: /*@__PURE__*/ cubicBezierAsString([0, 0.65, 0.55, 1]),
211
+ circOut: /*@__PURE__*/ cubicBezierAsString([0.55, 0, 1, 0.45]),
212
+ backIn: /*@__PURE__*/ cubicBezierAsString([0.31, 0.01, 0.66, -0.59]),
213
+ backOut: /*@__PURE__*/ cubicBezierAsString([0.33, 1.53, 0.69, 0.99]),
214
+ };
215
+ function mapEasingToNativeEasing(easing, duration) {
216
+ if (!easing) {
217
+ return undefined;
218
+ }
219
+ else if (typeof easing === "function" && supportsLinearEasing()) {
220
+ return generateLinearEasing(easing, duration);
221
+ }
222
+ else if (isBezierDefinition(easing)) {
223
+ return cubicBezierAsString(easing);
224
+ }
225
+ else if (Array.isArray(easing)) {
226
+ return easing.map((segmentEasing) => mapEasingToNativeEasing(segmentEasing, duration) ||
227
+ supportedWaapiEasing.easeOut);
228
+ }
229
+ else {
230
+ return supportedWaapiEasing[easing];
231
+ }
232
+ }
233
+
234
+ function startWaapiAnimation(element, valueName, keyframes, { delay = 0, duration = 300, repeat = 0, repeatType = "loop", ease = "easeInOut", times, } = {}) {
235
+ const keyframeOptions = { [valueName]: keyframes };
236
+ if (times)
237
+ keyframeOptions.offset = times;
238
+ const easing = mapEasingToNativeEasing(ease, duration);
239
+ /**
240
+ * If this is an easing array, apply to keyframes, not animation as a whole
241
+ */
242
+ if (Array.isArray(easing))
243
+ keyframeOptions.easing = easing;
244
+ return element.animate(keyframeOptions, {
245
+ delay,
246
+ duration,
247
+ easing: !Array.isArray(easing) ? easing : "linear",
248
+ fill: "both",
249
+ iterations: repeat + 1,
250
+ direction: repeatType === "reverse" ? "alternate" : "normal",
251
+ });
252
+ }
253
+
254
+ /**
255
+ * Implement a practical max duration for keyframe generation
256
+ * to prevent infinite loops
257
+ */
258
+ const maxGeneratorDuration = 20000;
259
+ function calcGeneratorDuration(generator) {
260
+ let duration = 0;
261
+ const timeStep = 50;
262
+ let state = generator.next(duration);
263
+ while (!state.done && duration < maxGeneratorDuration) {
264
+ duration += timeStep;
265
+ state = generator.next(duration);
266
+ }
267
+ return duration >= maxGeneratorDuration ? Infinity : duration;
268
+ }
269
+
270
+ /**
271
+ * Create a progress => progress easing function from a generator.
272
+ */
273
+ function createGeneratorEasing(options, scale = 100, createGenerator) {
274
+ const generator = createGenerator({ ...options, keyframes: [0, scale] });
275
+ const duration = Math.min(calcGeneratorDuration(generator), maxGeneratorDuration);
276
+ return {
277
+ type: "keyframes",
278
+ ease: (progress) => generator.next(duration * progress).value / scale,
279
+ duration: millisecondsToSeconds(duration),
280
+ };
281
+ }
282
+
283
+ const createUnitType = (unit) => ({
284
+ test: (v) => typeof v === "string" && v.endsWith(unit) && v.split(" ").length === 1,
285
+ parse: parseFloat,
286
+ transform: (v) => `${v}${unit}`,
287
+ });
288
+ const px = /*@__PURE__*/ createUnitType("px");
289
+
290
+ const browserNumberValueTypes = {
291
+ // Border props
292
+ borderWidth: px,
293
+ borderTopWidth: px,
294
+ borderRightWidth: px,
295
+ borderBottomWidth: px,
296
+ borderLeftWidth: px,
297
+ borderRadius: px,
298
+ radius: px,
299
+ borderTopLeftRadius: px,
300
+ borderTopRightRadius: px,
301
+ borderBottomRightRadius: px,
302
+ borderBottomLeftRadius: px,
303
+ // Positioning props
304
+ width: px,
305
+ maxWidth: px,
306
+ height: px,
307
+ maxHeight: px,
308
+ top: px,
309
+ right: px,
310
+ bottom: px,
311
+ left: px,
312
+ // Spacing props
313
+ padding: px,
314
+ paddingTop: px,
315
+ paddingRight: px,
316
+ paddingBottom: px,
317
+ paddingLeft: px,
318
+ margin: px,
319
+ marginTop: px,
320
+ marginRight: px,
321
+ marginBottom: px,
322
+ marginLeft: px,
323
+ // Misc
324
+ backgroundPositionX: px,
325
+ backgroundPositionY: px,
326
+ };
327
+
328
+ function isGenerator(type) {
329
+ return typeof type === "function";
330
+ }
331
+
332
+ function attachTimeline(animation, timeline) {
333
+ animation.timeline = timeline;
334
+ animation.onfinish = null;
335
+ }
336
+
337
+ const isNotNull = (value) => value !== null;
338
+ function getFinalKeyframe(keyframes, { repeat, repeatType = "loop" }, finalKeyframe) {
339
+ const resolvedKeyframes = keyframes.filter(isNotNull);
340
+ const index = repeat && repeatType !== "loop" && repeat % 2 === 1
341
+ ? 0
342
+ : resolvedKeyframes.length - 1;
343
+ return !index || finalKeyframe === undefined
344
+ ? resolvedKeyframes[index]
345
+ : finalKeyframe;
346
+ }
347
+
348
+ function setCSSVar(element, name, value) {
349
+ element.style.setProperty(`--${name}`, value);
350
+ }
351
+ function setStyle(element, name, value) {
352
+ element.style[name] = value;
353
+ }
354
+
355
+ const supportsPartialKeyframes = /*@__PURE__*/ memo(() => {
356
+ try {
357
+ document.createElement("div").animate({ opacity: [1] });
358
+ }
359
+ catch (e) {
360
+ return false;
361
+ }
362
+ return true;
363
+ });
364
+
365
+ const supportsWaapi = /*@__PURE__*/ memo(() => Object.hasOwnProperty.call(Element.prototype, "animate"));
366
+
367
+ const state = new WeakMap();
368
+ function hydrateKeyframes(valueName, keyframes, read) {
369
+ for (let i = 0; i < keyframes.length; i++) {
370
+ if (keyframes[i] === null) {
371
+ keyframes[i] = i === 0 ? read() : keyframes[i - 1];
372
+ }
373
+ if (typeof keyframes[i] === "number" &&
374
+ browserNumberValueTypes[valueName]) {
375
+ keyframes[i] = browserNumberValueTypes[valueName].transform(keyframes[i]);
376
+ }
377
+ }
378
+ if (!supportsPartialKeyframes() && keyframes.length < 2) {
379
+ keyframes.unshift(read());
380
+ }
381
+ }
382
+ const defaultEasing = "easeOut";
383
+ function getElementAnimationState(element) {
384
+ const animationState = state.get(element) || new Map();
385
+ state.set(element, animationState);
386
+ return state.get(element);
387
+ }
388
+ class NativeAnimation {
389
+ constructor(element, valueName, valueKeyframes, options) {
390
+ const isCSSVar = valueName.startsWith("--");
391
+ this.setValue = isCSSVar ? setCSSVar : setStyle;
392
+ this.options = options;
393
+ this.updateFinishedPromise();
394
+ invariant(typeof options.type !== "string", `animateMini doesn't support "type" as a string. Did you mean to import { spring } from "framer-motion"?`);
395
+ const existingAnimation = getElementAnimationState(element).get(valueName);
396
+ existingAnimation && existingAnimation.stop();
397
+ const readInitialKeyframe = () => {
398
+ return valueName.startsWith("--")
399
+ ? element.style.getPropertyValue(valueName)
400
+ : window.getComputedStyle(element)[valueName];
401
+ };
402
+ if (!Array.isArray(valueKeyframes)) {
403
+ valueKeyframes = [valueKeyframes];
404
+ }
405
+ hydrateKeyframes(valueName, valueKeyframes, readInitialKeyframe);
406
+ if (isGenerator(options.type)) {
407
+ const generatorOptions = createGeneratorEasing(options, 100, options.type);
408
+ options.ease = supportsLinearEasing()
409
+ ? generatorOptions.ease
410
+ : defaultEasing;
411
+ options.duration = secondsToMilliseconds(generatorOptions.duration);
412
+ options.type = "keyframes";
413
+ }
414
+ else {
415
+ options.ease = options.ease || defaultEasing;
416
+ }
417
+ this.removeAnimation = () => { var _a; return (_a = state.get(element)) === null || _a === void 0 ? void 0 : _a.delete(valueName); };
418
+ const onFinish = () => {
419
+ this.setValue(element, valueName, getFinalKeyframe(valueKeyframes, this.options));
420
+ this.cancel();
421
+ this.resolveFinishedPromise();
422
+ };
423
+ if (!supportsWaapi()) {
424
+ onFinish();
425
+ }
426
+ else {
427
+ this.animation = startWaapiAnimation(element, valueName, valueKeyframes, options);
428
+ if (options.autoplay === false) {
429
+ this.animation.pause();
430
+ }
431
+ this.animation.onfinish = onFinish;
432
+ if (this.pendingTimeline) {
433
+ attachTimeline(this.animation, this.pendingTimeline);
434
+ }
435
+ getElementAnimationState(element).set(valueName, this);
436
+ }
437
+ }
438
+ get duration() {
439
+ return millisecondsToSeconds(this.options.duration || 300);
440
+ }
441
+ get time() {
442
+ var _a;
443
+ if (this.animation) {
444
+ return millisecondsToSeconds(((_a = this.animation) === null || _a === void 0 ? void 0 : _a.currentTime) || 0);
445
+ }
446
+ return 0;
447
+ }
448
+ set time(newTime) {
449
+ if (this.animation) {
450
+ this.animation.currentTime = secondsToMilliseconds(newTime);
451
+ }
452
+ }
453
+ get speed() {
454
+ return this.animation ? this.animation.playbackRate : 1;
455
+ }
456
+ set speed(newSpeed) {
457
+ if (this.animation) {
458
+ this.animation.playbackRate = newSpeed;
459
+ }
460
+ }
461
+ get state() {
462
+ return this.animation ? this.animation.playState : "finished";
463
+ }
464
+ get startTime() {
465
+ return this.animation ? this.animation.startTime : null;
466
+ }
467
+ flatten() {
468
+ var _a;
469
+ if (!this.animation)
470
+ return;
471
+ (_a = this.animation.effect) === null || _a === void 0 ? void 0 : _a.updateTiming({ easing: "linear" });
472
+ }
473
+ play() {
474
+ if (this.state === "finished") {
475
+ this.updateFinishedPromise();
476
+ }
477
+ this.animation && this.animation.play();
478
+ }
479
+ pause() {
480
+ this.animation && this.animation.pause();
481
+ }
482
+ stop() {
483
+ if (!this.animation ||
484
+ this.state === "idle" ||
485
+ this.state === "finished") {
486
+ return;
487
+ }
488
+ if (this.animation.commitStyles) {
489
+ this.animation.commitStyles();
490
+ }
491
+ this.cancel();
492
+ }
493
+ complete() {
494
+ this.animation && this.animation.finish();
495
+ }
496
+ cancel() {
497
+ this.removeAnimation();
498
+ try {
499
+ this.animation && this.animation.cancel();
500
+ }
501
+ catch (e) { }
502
+ }
503
+ /**
504
+ * Allows the returned animation to be awaited or promise-chained. Currently
505
+ * resolves when the animation finishes at all but in a future update could/should
506
+ * reject if its cancels.
507
+ */
508
+ then(resolve, reject) {
509
+ return this.currentFinishedPromise.then(resolve, reject);
510
+ }
511
+ updateFinishedPromise() {
512
+ this.currentFinishedPromise = new Promise((resolve) => {
513
+ this.resolveFinishedPromise = resolve;
514
+ });
515
+ }
516
+ attachTimeline(timeline) {
517
+ if (!this.animation) {
518
+ this.pendingTimeline = timeline;
519
+ }
520
+ else {
521
+ attachTimeline(this.animation, timeline);
522
+ }
523
+ return noop;
524
+ }
525
+ }
526
+
527
+ function animateElements(elementOrSelector, keyframes, options, scope) {
528
+ const elements = resolveElements(elementOrSelector, scope);
529
+ const numElements = elements.length;
530
+ invariant(Boolean(numElements), "No valid element provided.");
531
+ const animations = [];
532
+ for (let i = 0; i < numElements; i++) {
533
+ const element = elements[i];
534
+ const elementTransition = { ...options };
535
+ /**
536
+ * Resolve stagger function if provided.
537
+ */
538
+ if (typeof elementTransition.delay === "function") {
539
+ elementTransition.delay = elementTransition.delay(i, numElements);
540
+ }
541
+ for (const valueName in keyframes) {
542
+ const valueKeyframes = keyframes[valueName];
543
+ const valueOptions = {
544
+ ...getValueTransition(options, valueName),
545
+ };
546
+ valueOptions.duration = valueOptions.duration
547
+ ? secondsToMilliseconds(valueOptions.duration)
548
+ : valueOptions.duration;
549
+ valueOptions.delay = secondsToMilliseconds(valueOptions.delay || 0);
550
+ animations.push(new NativeAnimation(element, valueName, valueKeyframes, valueOptions));
551
+ }
552
+ }
553
+ return animations;
554
+ }
555
+
556
+ const createScopedWaapiAnimate = (scope) => {
557
+ function scopedAnimate(elementOrSelector, keyframes, options) {
558
+ return new GroupPlaybackControls(animateElements(elementOrSelector, keyframes, options, scope));
559
+ }
560
+ return scopedAnimate;
561
+ };
562
+ const animateMini = /*@__PURE__*/ createScopedWaapiAnimate();
563
+
564
+ exports.animate = animateMini;
@@ -1468,6 +1468,10 @@ class BaseAnimation {
1468
1468
  then(resolve, reject) {
1469
1469
  return this.currentFinishedPromise.then(resolve, reject);
1470
1470
  }
1471
+ flatten() {
1472
+ this.options.type = "keyframes";
1473
+ this.options.ease = "linear";
1474
+ }
1471
1475
  updateFinishedPromise() {
1472
1476
  this.currentFinishedPromise = new Promise((resolve) => {
1473
1477
  this.resolveFinishedPromise = resolve;
@@ -2282,6 +2286,13 @@ class MainThreadAnimation extends BaseAnimation {
2282
2286
  this.resolver = new KeyframeResolver$1(keyframes, onResolved, name, motionValue, element);
2283
2287
  this.resolver.scheduleResolve();
2284
2288
  }
2289
+ flatten() {
2290
+ super.flatten();
2291
+ // If we've already resolved the animation, re-initialise it
2292
+ if (this._resolved) {
2293
+ Object.assign(this._resolved, this.initPlayback(this._resolved.keyframes));
2294
+ }
2295
+ }
2285
2296
  initPlayback(keyframes$1) {
2286
2297
  const { type = "keyframes", repeat = 0, repeatDelay = 0, repeatType, velocity = 0, } = this.options;
2287
2298
  const generatorFactory = isGenerator(type)
@@ -3072,6 +3083,9 @@ class GroupPlaybackControls {
3072
3083
  runAll(methodName) {
3073
3084
  this.animations.forEach((controls) => controls[methodName]());
3074
3085
  }
3086
+ flatten() {
3087
+ this.runAll("flatten");
3088
+ }
3075
3089
  play() {
3076
3090
  this.runAll("play");
3077
3091
  }
@@ -3281,7 +3295,7 @@ class MotionValue {
3281
3295
  * This will be replaced by the build step with the latest version number.
3282
3296
  * When MotionValues are provided to motion components, warn if versions are mixed.
3283
3297
  */
3284
- this.version = "11.11.13";
3298
+ this.version = "11.11.16";
3285
3299
  /**
3286
3300
  * Tracks whether this value can output a velocity. Currently this is only true
3287
3301
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -9024,7 +9038,7 @@ function updateMotionValuesFromProps(element, next, prev) {
9024
9038
  * and warn against mismatches.
9025
9039
  */
9026
9040
  if (process.env.NODE_ENV === "development") {
9027
- warnOnce(nextValue.version === "11.11.13", `Attempting to mix Motion versions ${nextValue.version} with 11.11.13 may not work as expected.`);
9041
+ warnOnce(nextValue.version === "11.11.16", `Attempting to mix Motion versions ${nextValue.version} with 11.11.16 may not work as expected.`);
9028
9042
  }
9029
9043
  }
9030
9044
  else if (isMotionValue(prevValue)) {