framer-motion 10.13.2-alpha.3 → 10.14.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.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var indexLegacy = require('./index-legacy-f5238c85.js');
5
+ var indexLegacy = require('./index-legacy-767d8769.js');
6
6
 
7
7
 
8
8
 
@@ -1948,7 +1948,6 @@ function animateValue({ autoplay = true, delay = 0, driver = frameloopDriver, ke
1948
1948
  return state;
1949
1949
  };
1950
1950
  const stopAnimationDriver = () => {
1951
- console.log("stopping animation");
1952
1951
  animationDriver && animationDriver.stop();
1953
1952
  animationDriver = undefined;
1954
1953
  };
@@ -2180,16 +2179,14 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
2180
2179
  /**
2181
2180
  * Animation interrupt callback.
2182
2181
  */
2183
- return {
2182
+ const controls = {
2184
2183
  then(resolve, reject) {
2185
2184
  return currentFinishedPromise.then(resolve, reject);
2186
2185
  },
2187
- get timeline() {
2188
- return animation.timeline;
2189
- },
2190
- set timeline(timeline) {
2186
+ attachTimeline(timeline) {
2191
2187
  animation.timeline = timeline;
2192
2188
  animation.onfinish = null;
2189
+ return noop;
2193
2190
  },
2194
2191
  get time() {
2195
2192
  return millisecondsToSeconds(animation.currentTime || 0);
@@ -2241,6 +2238,7 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
2241
2238
  complete: () => animation.finish(),
2242
2239
  cancel: safeCancel,
2243
2240
  };
2241
+ return controls;
2244
2242
  }
2245
2243
 
2246
2244
  function createInstantAnimation({ keyframes, delay, onUpdate, onComplete, }) {
@@ -2659,7 +2657,7 @@ class MotionValue {
2659
2657
  * This will be replaced by the build step with the latest version number.
2660
2658
  * When MotionValues are provided to motion components, warn if versions are mixed.
2661
2659
  */
2662
- this.version = "10.13.2-alpha.3";
2660
+ this.version = "10.14.0";
2663
2661
  /**
2664
2662
  * Duration, in milliseconds, since last updating frame.
2665
2663
  *
@@ -3418,6 +3416,23 @@ function resolveElements(elements, scope, selectorCache) {
3418
3416
 
3419
3417
  const visualElementStore = new WeakMap();
3420
3418
 
3419
+ function observeTimeline(update, timeline) {
3420
+ let prevProgress;
3421
+ const onFrame = () => {
3422
+ const { currentTime } = timeline;
3423
+ const percentage = currentTime === null ? 0 : currentTime.value;
3424
+ const progress = percentage / 100;
3425
+ if (prevProgress !== progress) {
3426
+ update(progress);
3427
+ }
3428
+ prevProgress = progress;
3429
+ };
3430
+ frame.update(onFrame, true);
3431
+ return () => cancelFrame(onFrame);
3432
+ }
3433
+
3434
+ const supportsScrollTimeline = memo(() => window.ScrollTimeline !== undefined);
3435
+
3421
3436
  class GroupPlaybackControls {
3422
3437
  constructor(animations) {
3423
3438
  this.animations = animations.filter(Boolean);
@@ -3436,11 +3451,25 @@ class GroupPlaybackControls {
3436
3451
  this.animations[i][propName] = newValue;
3437
3452
  }
3438
3453
  }
3439
- get timeline() {
3440
- return this.getAll("timeline");
3441
- }
3442
- set timeline(timeline) {
3443
- this.setAll("timeline", timeline);
3454
+ attachTimeline(timeline) {
3455
+ const cancelAll = this.animations.map((animation) => {
3456
+ if (supportsScrollTimeline() && animation.attachTimeline) {
3457
+ animation.attachTimeline(timeline);
3458
+ }
3459
+ else {
3460
+ animation.pause();
3461
+ return observeTimeline((progress) => {
3462
+ animation.time = animation.duration * progress;
3463
+ }, timeline);
3464
+ }
3465
+ });
3466
+ return () => {
3467
+ cancelAll.forEach((cancelTimeline, i) => {
3468
+ if (cancelTimeline)
3469
+ cancelTimeline();
3470
+ this.animations[i].stop();
3471
+ });
3472
+ };
3444
3473
  }
3445
3474
  get time() {
3446
3475
  return this.getAll("time");
@@ -3842,7 +3871,7 @@ function updateMotionValuesFromProps(element, next, prev) {
3842
3871
  * and warn against mismatches.
3843
3872
  */
3844
3873
  if (process.env.NODE_ENV === "development") {
3845
- warnOnce(nextValue.version === "10.13.2-alpha.3", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.13.2-alpha.3 may not work as expected.`);
3874
+ warnOnce(nextValue.version === "10.14.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.14.0 may not work as expected.`);
3846
3875
  }
3847
3876
  }
3848
3877
  else if (isMotionValue(prevValue)) {
@@ -5310,7 +5339,6 @@ function scrollInfo(onScroll, { container = document.documentElement, ...options
5310
5339
  };
5311
5340
  }
5312
5341
 
5313
- const supportsScrollTimeline = memo(() => window.ScrollTimeline !== undefined);
5314
5342
  function scrollTimelineFallback({ source, axis = "y" }) {
5315
5343
  // ScrollTimeline records progress as a percentage CSSUnitValue
5316
5344
  const currentTime = { value: 0 };
@@ -5334,22 +5362,12 @@ function getTimeline({ source = document.documentElement, axis = "y", } = {}) {
5334
5362
  }
5335
5363
  function scroll(onScroll, options) {
5336
5364
  const timeline = getTimeline(options);
5337
- let prevProgress;
5338
- const onFrame = () => {
5339
- const { currentTime } = timeline;
5340
- const percentage = currentTime === null ? 0 : currentTime.value;
5341
- const progress = percentage / 100;
5342
- if (prevProgress !== progress) {
5343
- onScroll(progress);
5344
- }
5345
- prevProgress = progress;
5346
- };
5347
- frame.update(onFrame, true);
5348
- return () => {
5349
- cancelFrame(onFrame);
5350
- if (timeline.cancel)
5351
- timeline.cancel();
5352
- };
5365
+ if (typeof onScroll === "function") {
5366
+ return observeTimeline(onScroll, timeline);
5367
+ }
5368
+ else {
5369
+ return onScroll.attachTimeline(timeline);
5370
+ }
5353
5371
  }
5354
5372
 
5355
5373
  const thresholds = {
package/dist/cjs/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
5
  var React = require('react');
6
- var indexLegacy = require('./index-legacy-f5238c85.js');
6
+ var indexLegacy = require('./index-legacy-767d8769.js');
7
7
 
8
8
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
9
9
 
@@ -5874,7 +5874,12 @@ const appearStoreId = (id, value) => `${id}: ${value}`;
5874
5874
 
5875
5875
  const appearAnimationStore = new Map();
5876
5876
 
5877
- function handoffOptimizedAppearAnimation(id, name, _value,
5877
+ function handoffOptimizedAppearAnimation(id, name,
5878
+ /**
5879
+ * Legacy argument. This function is inlined apart from framer-motion so
5880
+ * will co-ordinate with Shuang with how best to remove this.
5881
+ */
5882
+ _value,
5878
5883
  /**
5879
5884
  * This function is loaded via window by startOptimisedAnimation.
5880
5885
  * By accepting `sync` as an argument, rather than using it via
@@ -5885,7 +5890,6 @@ function handoffOptimizedAppearAnimation(id, name, _value,
5885
5890
  frame) {
5886
5891
  const storeId = appearStoreId(id, indexLegacy.transformProps.has(name) ? "transform" : name);
5887
5892
  const appearAnimation = appearAnimationStore.get(storeId);
5888
- console.log("appear animation", storeId, appearAnimation);
5889
5893
  if (!appearAnimation)
5890
5894
  return 0;
5891
5895
  const { animation, startTime } = appearAnimation;
@@ -5896,38 +5900,10 @@ frame) {
5896
5900
  */
5897
5901
  try {
5898
5902
  animation.cancel();
5899
- console.log("cancelled at", performance.now());
5900
5903
  }
5901
5904
  catch (e) { }
5902
5905
  };
5903
5906
  if (startTime !== null) {
5904
- const sampledTime = performance.now();
5905
- console.log({ sampledTime });
5906
- /**
5907
- * Resync handoff animation with optimised animation.
5908
- *
5909
- * This step would be unnecessary if we triggered animateChanges() in useEffect,
5910
- * but due to potential hydration errors we currently fire them in useLayoutEffect.
5911
- *
5912
- * By the time we're safely ready to cancel the optimised WAAPI animation,
5913
- * the main thread might have been blocked and desynced the two animations.
5914
- *
5915
- * Here, we resync the two animations before the optimised WAAPI animation is cancelled.
5916
- */
5917
- // frame.preRender(() => {
5918
- // if (value.animation) {
5919
- // console.log("initial time", value.animation.time)
5920
- // value.animation.time = millisecondsToSeconds(
5921
- // performance.now() - sampledTime
5922
- // )
5923
- // console.log(
5924
- // "value animation time",
5925
- // value.animation.time,
5926
- // performance.now(),
5927
- // frameData.timestamp
5928
- // )
5929
- // }
5930
- // })
5931
5907
  /**
5932
5908
  * We allow the animation to persist until the next frame:
5933
5909
  * 1. So it continues to play until Framer Motion is ready to render
@@ -5942,8 +5918,7 @@ frame) {
5942
5918
  * an updated value for several frames, even as the animation plays smoothly via
5943
5919
  * the GPU.
5944
5920
  */
5945
- console.log("start animation at", sampledTime - startTime || 0);
5946
- return sampledTime - startTime || 0;
5921
+ return performance.now() - startTime || 0;
5947
5922
  }
5948
5923
  else {
5949
5924
  cancelOptimisedAnimation();
@@ -309,6 +309,13 @@ interface SVGAttributes {
309
309
  zoomAndPan?: string | undefined;
310
310
  }
311
311
 
312
+ interface ProgressTimeline {
313
+ currentTime: null | {
314
+ value: number;
315
+ };
316
+ cancel?: VoidFunction;
317
+ }
318
+
312
319
  interface AnimationPlaybackLifecycles<V> {
313
320
  onUpdate?: (latest: V) => void;
314
321
  onPlay?: () => void;
@@ -360,7 +367,7 @@ interface AnimationPlaybackControls {
360
367
  complete: () => void;
361
368
  cancel: () => void;
362
369
  then: (onResolve: VoidFunction, onReject?: VoidFunction) => Promise<void>;
363
- timeline?: AnimationTimeline | null;
370
+ attachTimeline?: (timeline: ProgressTimeline) => VoidFunction;
364
371
  }
365
372
  declare type DynamicOption<T> = (i: number, total: number) => T;
366
373
  interface CSSStyleDeclarationWithTransform extends Omit<CSSStyleDeclaration, "direction" | "transition"> {
@@ -674,7 +681,30 @@ interface ScrollInfoOptions {
674
681
  smooth?: number;
675
682
  }
676
683
 
677
- declare class ScrollTimeline {
684
+ declare class GroupPlaybackControls implements AnimationPlaybackControls {
685
+ animations: AnimationPlaybackControls[];
686
+ constructor(animations: Array<AnimationPlaybackControls | undefined>);
687
+ then(onResolve: VoidFunction, onReject?: VoidFunction): Promise<void>;
688
+ /**
689
+ * TODO: Filter out cancelled or stopped animations before returning
690
+ */
691
+ private getAll;
692
+ private setAll;
693
+ attachTimeline(timeline: any): () => void;
694
+ get time(): number;
695
+ set time(time: number);
696
+ get speed(): number;
697
+ set speed(speed: number);
698
+ get duration(): number;
699
+ private runAll;
700
+ play(): void;
701
+ pause(): void;
702
+ stop(): void;
703
+ cancel(): void;
704
+ complete(): void;
705
+ }
706
+
707
+ declare class ScrollTimeline implements ProgressTimeline {
678
708
  constructor(options: ScrollOptions);
679
709
  currentTime: null | {
680
710
  value: number;
@@ -686,7 +716,7 @@ declare global {
686
716
  ScrollTimeline: ScrollTimeline;
687
717
  }
688
718
  }
689
- declare function scroll(onScroll: OnScroll, options?: ScrollOptions): () => void;
719
+ declare function scroll(onScroll: OnScroll | GroupPlaybackControls, options?: ScrollOptions): VoidFunction;
690
720
 
691
721
  declare function scrollInfo(onScroll: OnScrollInfo, { container, ...options }?: ScrollInfoOptions): () => void;
692
722
 
@@ -1,3 +1,6 @@
1
+ import { observeTimeline } from '../render/dom/scroll/observe.mjs';
2
+ import { supportsScrollTimeline } from '../render/dom/scroll/supports.mjs';
3
+
1
4
  class GroupPlaybackControls {
2
5
  constructor(animations) {
3
6
  this.animations = animations.filter(Boolean);
@@ -16,11 +19,25 @@ class GroupPlaybackControls {
16
19
  this.animations[i][propName] = newValue;
17
20
  }
18
21
  }
19
- get timeline() {
20
- return this.getAll("timeline");
21
- }
22
- set timeline(timeline) {
23
- this.setAll("timeline", timeline);
22
+ attachTimeline(timeline) {
23
+ const cancelAll = this.animations.map((animation) => {
24
+ if (supportsScrollTimeline() && animation.attachTimeline) {
25
+ animation.attachTimeline(timeline);
26
+ }
27
+ else {
28
+ animation.pause();
29
+ return observeTimeline((progress) => {
30
+ animation.time = animation.duration * progress;
31
+ }, timeline);
32
+ }
33
+ });
34
+ return () => {
35
+ cancelAll.forEach((cancelTimeline, i) => {
36
+ if (cancelTimeline)
37
+ cancelTimeline();
38
+ this.animations[i].stop();
39
+ });
40
+ };
24
41
  }
25
42
  get time() {
26
43
  return this.getAll("time");
@@ -192,7 +192,6 @@ function animateValue({ autoplay = true, delay = 0, driver = frameloopDriver, ke
192
192
  return state;
193
193
  };
194
194
  const stopAnimationDriver = () => {
195
- console.log("stopping animation");
196
195
  animationDriver && animationDriver.stop();
197
196
  animationDriver = undefined;
198
197
  };
@@ -4,7 +4,8 @@ import { getFinalKeyframe } from './utils/get-final-keyframe.mjs';
4
4
  import { animateValue } from '../js/index.mjs';
5
5
  import { millisecondsToSeconds, secondsToMilliseconds } from '../../../utils/time-conversion.mjs';
6
6
  import { memo } from '../../../utils/memo.mjs';
7
- import { cancelFrame, frame } from '../../../frameloop/frame.mjs';
7
+ import { noop } from '../../../utils/noop.mjs';
8
+ import { frame, cancelFrame } from '../../../frameloop/frame.mjs';
8
9
 
9
10
  const supportsWaapi = memo(() => Object.hasOwnProperty.call(Element.prototype, "animate"));
10
11
  /**
@@ -120,16 +121,14 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
120
121
  /**
121
122
  * Animation interrupt callback.
122
123
  */
123
- return {
124
+ const controls = {
124
125
  then(resolve, reject) {
125
126
  return currentFinishedPromise.then(resolve, reject);
126
127
  },
127
- get timeline() {
128
- return animation.timeline;
129
- },
130
- set timeline(timeline) {
128
+ attachTimeline(timeline) {
131
129
  animation.timeline = timeline;
132
130
  animation.onfinish = null;
131
+ return noop;
133
132
  },
134
133
  get time() {
135
134
  return millisecondsToSeconds(animation.currentTime || 0);
@@ -181,6 +180,7 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
181
180
  complete: () => animation.finish(),
182
181
  cancel: safeCancel,
183
182
  };
183
+ return controls;
184
184
  }
185
185
 
186
186
  export { createAcceleratedAnimation };
@@ -2,7 +2,12 @@ import { transformProps } from '../../render/html/utils/transform.mjs';
2
2
  import { appearAnimationStore } from './store.mjs';
3
3
  import { appearStoreId } from './store-id.mjs';
4
4
 
5
- function handoffOptimizedAppearAnimation(id, name, _value,
5
+ function handoffOptimizedAppearAnimation(id, name,
6
+ /**
7
+ * Legacy argument. This function is inlined apart from framer-motion so
8
+ * will co-ordinate with Shuang with how best to remove this.
9
+ */
10
+ _value,
6
11
  /**
7
12
  * This function is loaded via window by startOptimisedAnimation.
8
13
  * By accepting `sync` as an argument, rather than using it via
@@ -13,7 +18,6 @@ function handoffOptimizedAppearAnimation(id, name, _value,
13
18
  frame) {
14
19
  const storeId = appearStoreId(id, transformProps.has(name) ? "transform" : name);
15
20
  const appearAnimation = appearAnimationStore.get(storeId);
16
- console.log("appear animation", storeId, appearAnimation);
17
21
  if (!appearAnimation)
18
22
  return 0;
19
23
  const { animation, startTime } = appearAnimation;
@@ -24,38 +28,10 @@ frame) {
24
28
  */
25
29
  try {
26
30
  animation.cancel();
27
- console.log("cancelled at", performance.now());
28
31
  }
29
32
  catch (e) { }
30
33
  };
31
34
  if (startTime !== null) {
32
- const sampledTime = performance.now();
33
- console.log({ sampledTime });
34
- /**
35
- * Resync handoff animation with optimised animation.
36
- *
37
- * This step would be unnecessary if we triggered animateChanges() in useEffect,
38
- * but due to potential hydration errors we currently fire them in useLayoutEffect.
39
- *
40
- * By the time we're safely ready to cancel the optimised WAAPI animation,
41
- * the main thread might have been blocked and desynced the two animations.
42
- *
43
- * Here, we resync the two animations before the optimised WAAPI animation is cancelled.
44
- */
45
- // frame.preRender(() => {
46
- // if (value.animation) {
47
- // console.log("initial time", value.animation.time)
48
- // value.animation.time = millisecondsToSeconds(
49
- // performance.now() - sampledTime
50
- // )
51
- // console.log(
52
- // "value animation time",
53
- // value.animation.time,
54
- // performance.now(),
55
- // frameData.timestamp
56
- // )
57
- // }
58
- // })
59
35
  /**
60
36
  * We allow the animation to persist until the next frame:
61
37
  * 1. So it continues to play until Framer Motion is ready to render
@@ -70,8 +46,7 @@ frame) {
70
46
  * an updated value for several frames, even as the animation plays smoothly via
71
47
  * the GPU.
72
48
  */
73
- console.log("start animation at", sampledTime - startTime || 0);
74
- return sampledTime - startTime || 0;
49
+ return performance.now() - startTime || 0;
75
50
  }
76
51
  else {
77
52
  cancelOptimisedAnimation();
package/dist/es/index.mjs CHANGED
@@ -71,6 +71,7 @@ export { mix } from './utils/mix.mjs';
71
71
  export { pipe } from './utils/pipe.mjs';
72
72
  export { progress } from './utils/progress.mjs';
73
73
  export { wrap } from './utils/wrap.mjs';
74
+ export { cancelSync, sync } from './frameloop/index-legacy.mjs';
74
75
  export { anticipate } from './easing/anticipate.mjs';
75
76
  export { backIn, backInOut, backOut } from './easing/back.mjs';
76
77
  export { circIn, circInOut, circOut } from './easing/circ.mjs';
@@ -83,7 +84,6 @@ export { distance, distance2D } from './utils/distance.mjs';
83
84
  export { invariant, warning } from './utils/errors.mjs';
84
85
  export { interpolate } from './utils/interpolate.mjs';
85
86
  export { cancelFrame, frame, frameData, steps } from './frameloop/frame.mjs';
86
- export { cancelSync, sync } from './frameloop/index-legacy.mjs';
87
87
  export { animations } from './motion/features/animations.mjs';
88
88
  export { checkTargetForNewValues } from './render/utils/setters.mjs';
89
89
  export { createBox } from './projection/geometry/models.mjs';
@@ -1,8 +1,7 @@
1
- import { memo } from '../../../utils/memo.mjs';
2
1
  import { scrollInfo } from './track.mjs';
3
- import { frame, cancelFrame } from '../../../frameloop/frame.mjs';
2
+ import { observeTimeline } from './observe.mjs';
3
+ import { supportsScrollTimeline } from './supports.mjs';
4
4
 
5
- const supportsScrollTimeline = memo(() => window.ScrollTimeline !== undefined);
6
5
  function scrollTimelineFallback({ source, axis = "y" }) {
7
6
  // ScrollTimeline records progress as a percentage CSSUnitValue
8
7
  const currentTime = { value: 0 };
@@ -26,22 +25,12 @@ function getTimeline({ source = document.documentElement, axis = "y", } = {}) {
26
25
  }
27
26
  function scroll(onScroll, options) {
28
27
  const timeline = getTimeline(options);
29
- let prevProgress;
30
- const onFrame = () => {
31
- const { currentTime } = timeline;
32
- const percentage = currentTime === null ? 0 : currentTime.value;
33
- const progress = percentage / 100;
34
- if (prevProgress !== progress) {
35
- onScroll(progress);
36
- }
37
- prevProgress = progress;
38
- };
39
- frame.update(onFrame, true);
40
- return () => {
41
- cancelFrame(onFrame);
42
- if (timeline.cancel)
43
- timeline.cancel();
44
- };
28
+ if (typeof onScroll === "function") {
29
+ return observeTimeline(onScroll, timeline);
30
+ }
31
+ else {
32
+ return onScroll.attachTimeline(timeline);
33
+ }
45
34
  }
46
35
 
47
36
  export { scroll };
@@ -0,0 +1,18 @@
1
+ import { frame, cancelFrame } from '../../../frameloop/frame.mjs';
2
+
3
+ function observeTimeline(update, timeline) {
4
+ let prevProgress;
5
+ const onFrame = () => {
6
+ const { currentTime } = timeline;
7
+ const percentage = currentTime === null ? 0 : currentTime.value;
8
+ const progress = percentage / 100;
9
+ if (prevProgress !== progress) {
10
+ update(progress);
11
+ }
12
+ prevProgress = progress;
13
+ };
14
+ frame.update(onFrame, true);
15
+ return () => cancelFrame(onFrame);
16
+ }
17
+
18
+ export { observeTimeline };
@@ -0,0 +1,5 @@
1
+ import { memo } from '../../../utils/memo.mjs';
2
+
3
+ const supportsScrollTimeline = memo(() => window.ScrollTimeline !== undefined);
4
+
5
+ export { supportsScrollTimeline };
@@ -22,7 +22,7 @@ function updateMotionValuesFromProps(element, next, prev) {
22
22
  * and warn against mismatches.
23
23
  */
24
24
  if (process.env.NODE_ENV === "development") {
25
- warnOnce(nextValue.version === "10.13.2-alpha.3", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.13.2-alpha.3 may not work as expected.`);
25
+ warnOnce(nextValue.version === "10.14.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.14.0 may not work as expected.`);
26
26
  }
27
27
  }
28
28
  else if (isMotionValue(prevValue)) {
@@ -25,7 +25,7 @@ class MotionValue {
25
25
  * This will be replaced by the build step with the latest version number.
26
26
  * When MotionValues are provided to motion components, warn if versions are mixed.
27
27
  */
28
- this.version = "10.13.2-alpha.3";
28
+ this.version = "10.14.0";
29
29
  /**
30
30
  * Duration, in milliseconds, since last updating frame.
31
31
  *