framer-motion 7.8.1 → 7.9.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.
package/README.md CHANGED
@@ -43,6 +43,7 @@ It does all this:
43
43
  - SVG paths
44
44
  - Exit animations
45
45
  - Server-side rendering
46
+ - Hardware-accelerated animations
46
47
  - Orchestrate animations across components
47
48
  - CSS variables
48
49
 
@@ -70,17 +71,17 @@ export const MyComponent = ({ isVisible }) => (
70
71
 
71
72
  ### 📚 Docs
72
73
 
73
- - Check out [our documentation](https://www.framer.com/docs/) for guides and a full API reference.
74
- - Or see [our examples](https://www.framer.com/docs/examples/) for inspiration.
74
+ - Check out [our documentation](https://www.framer.com/docs/) for guides and a full API reference.
75
+ - Or see [our examples](https://www.framer.com/docs/examples/) for inspiration.
75
76
 
76
77
  ### 💎 Contribute
77
78
 
78
- - Want to contribute to Framer Motion? Our [contributing guide](https://github.com/framer/motion/blob/master/CONTRIBUTING.md) has you covered.
79
+ - Want to contribute to Framer Motion? Our [contributing guide](https://github.com/framer/motion/blob/master/CONTRIBUTING.md) has you covered.
79
80
 
80
81
  ### 👩🏻‍⚖️ License
81
82
 
82
- - Framer Motion is MIT licensed.
83
+ - Framer Motion is MIT licensed.
83
84
 
84
85
  ### ✨ Framer
85
86
 
86
- - Design and publish sites that inspire. [Try Framer for free](https://www.framer.com/).
87
+ - Design and publish sites that inspire. [Try Framer for free](https://www.framer.com/).
package/dist/cjs/index.js CHANGED
@@ -2119,12 +2119,12 @@ class MotionValue {
2119
2119
  *
2120
2120
  * @internal
2121
2121
  */
2122
- constructor(init) {
2122
+ constructor(init, options = {}) {
2123
2123
  /**
2124
2124
  * This will be replaced by the build step with the latest version number.
2125
2125
  * When MotionValues are provided to motion components, warn if versions are mixed.
2126
2126
  */
2127
- this.version = "7.8.1";
2127
+ this.version = "7.9.0";
2128
2128
  /**
2129
2129
  * Duration, in milliseconds, since last updating frame.
2130
2130
  *
@@ -2213,6 +2213,7 @@ class MotionValue {
2213
2213
  this.hasAnimated = false;
2214
2214
  this.prev = this.current = init;
2215
2215
  this.canTrackVelocity = isFloat(this.current);
2216
+ this.owner = options.owner;
2216
2217
  }
2217
2218
  /**
2218
2219
  * Adds a function that will be notified when the `MotionValue` is updated.
@@ -2312,6 +2313,11 @@ class MotionValue {
2312
2313
  this.passiveEffect(v, this.updateAndNotify);
2313
2314
  }
2314
2315
  }
2316
+ setWithVelocity(prev, current, delta) {
2317
+ this.set(current);
2318
+ this.prev = prev;
2319
+ this.timeDelta = delta;
2320
+ }
2315
2321
  /**
2316
2322
  * Returns the latest state of `MotionValue`
2317
2323
  *
@@ -2398,8 +2404,8 @@ class MotionValue {
2398
2404
  this.stop();
2399
2405
  }
2400
2406
  }
2401
- function motionValue(init) {
2402
- return new MotionValue(init);
2407
+ function motionValue(init, options) {
2408
+ return new MotionValue(init, options);
2403
2409
  }
2404
2410
 
2405
2411
  /**
@@ -2765,7 +2771,7 @@ function checkTargetForNewValues(visualElement, target, origin) {
2765
2771
  else if (!findValueType(value) && complex.test(targetValue)) {
2766
2772
  value = getAnimatableNone(key, targetValue);
2767
2773
  }
2768
- visualElement.addValue(key, motionValue(value));
2774
+ visualElement.addValue(key, motionValue(value, { owner: visualElement }));
2769
2775
  if (origin[key] === undefined) {
2770
2776
  origin[key] = value;
2771
2777
  }
@@ -2842,38 +2848,6 @@ const instantAnimationState = {
2842
2848
  current: false,
2843
2849
  };
2844
2850
 
2845
- /**
2846
- *
2847
- */
2848
- function createAcceleratedAnimation() {
2849
- return () => { };
2850
- }
2851
-
2852
- /**
2853
- * Timeout defined in ms
2854
- */
2855
- function delay(callback, timeout) {
2856
- const start = performance.now();
2857
- const checkElapsed = ({ timestamp }) => {
2858
- const elapsed = timestamp - start;
2859
- if (elapsed >= timeout) {
2860
- cancelSync.read(checkElapsed);
2861
- callback(elapsed - timeout);
2862
- }
2863
- };
2864
- sync.read(checkElapsed, true);
2865
- return () => cancelSync.read(checkElapsed);
2866
- }
2867
-
2868
- function createInstantAnimation({ keyframes, elapsed, onUpdate, onComplete, }) {
2869
- const setValue = () => {
2870
- onUpdate && onUpdate(keyframes[keyframes.length - 1]);
2871
- onComplete && onComplete();
2872
- return () => { };
2873
- };
2874
- return elapsed ? delay(setValue, -elapsed) : setValue();
2875
- }
2876
-
2877
2851
  // Accepts an easing function and returns a new one that outputs mirrored values for
2878
2852
  // the second half of the animation. Turns easeIn into easeInOut.
2879
2853
  const mirrorEasing = (easing) => (p) => p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
@@ -3562,7 +3536,7 @@ const framesync = (update) => {
3562
3536
  stop: () => cancelSync.update(passTimestamp),
3563
3537
  };
3564
3538
  };
3565
- function animate$1({ duration, driver = framesync, elapsed = 0, repeat: repeatMax = 0, repeatType = "loop", repeatDelay = 0, keyframes, onPlay, onStop, onComplete, onRepeat, onUpdate, type = "keyframes", ...options }) {
3539
+ function animate$1({ duration, driver = framesync, elapsed = 0, repeat: repeatMax = 0, repeatType = "loop", repeatDelay = 0, keyframes, autoplay = true, onPlay, onStop, onComplete, onRepeat, onUpdate, type = "keyframes", ...options }) {
3566
3540
  var _a, _b;
3567
3541
  let driverControls;
3568
3542
  let repeatCount = 0;
@@ -3633,15 +3607,132 @@ function animate$1({ duration, driver = framesync, elapsed = 0, repeat: repeatMa
3633
3607
  driverControls = driver(update);
3634
3608
  driverControls.start();
3635
3609
  }
3636
- play();
3610
+ autoplay && play();
3637
3611
  return {
3638
3612
  stop: () => {
3639
3613
  onStop && onStop();
3640
3614
  driverControls.stop();
3641
3615
  },
3616
+ sample: (t) => {
3617
+ return animation.next(Math.max(0, t)).value;
3618
+ },
3642
3619
  };
3643
3620
  }
3644
3621
 
3622
+ const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
3623
+
3624
+ function animateStyle(element, valueName, keyframes, { delay = 0, duration, repeat = 0, repeatType = "loop", ease, times, } = {}) {
3625
+ return element.animate({ [valueName]: keyframes, offset: times }, {
3626
+ delay,
3627
+ duration,
3628
+ easing: Array.isArray(ease) ? cubicBezierAsString(ease) : ease,
3629
+ fill: "both",
3630
+ iterations: repeat + 1,
3631
+ direction: repeatType === "reverse" ? "alternate" : "normal",
3632
+ });
3633
+ }
3634
+
3635
+ /**
3636
+ * 10ms is chosen here as it strikes a balance between smooth
3637
+ * results (more than one keyframe per frame at 60fps) and
3638
+ * keyframe quantity.
3639
+ */
3640
+ const sampleDelta = 10; //ms
3641
+ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ...options }) {
3642
+ let { keyframes, duration = 0.3, elapsed = 0, ease } = options;
3643
+ /**
3644
+ * If this is a spring animation, pre-generate keyframes and
3645
+ * record duration.
3646
+ *
3647
+ * TODO: When introducing support for values beyond opacity it
3648
+ * might be better to use `animate.sample()`
3649
+ */
3650
+ if (options.type === "spring") {
3651
+ const springAnimation = spring(options);
3652
+ let state = { done: false, value: keyframes[0] };
3653
+ const springKeyframes = [];
3654
+ let t = 0;
3655
+ while (!state.done) {
3656
+ state = springAnimation.next(t);
3657
+ springKeyframes.push(state.value);
3658
+ t += sampleDelta;
3659
+ }
3660
+ keyframes = springKeyframes;
3661
+ duration = t - sampleDelta;
3662
+ ease = "linear";
3663
+ }
3664
+ const animation = animateStyle(value.owner.current, valueName, keyframes, {
3665
+ ...options,
3666
+ delay: -elapsed,
3667
+ duration,
3668
+ /**
3669
+ * This function is currently not called if ease is provided
3670
+ * as a function so the cast is safe.
3671
+ *
3672
+ * However it would be possible for a future refinement to port
3673
+ * in easing pregeneration from Motion One for browsers that
3674
+ * support the upcoming `linear()` easing function.
3675
+ */
3676
+ ease: ease,
3677
+ });
3678
+ /**
3679
+ * Prefer the `onfinish` prop as it's more widely supported than
3680
+ * the `finished` promise.
3681
+ *
3682
+ * Here, we synchronously set the provided MotionValue to the end
3683
+ * keyframe. If we didn't, when the WAAPI animation is finished it would
3684
+ * be removed from the element which would then revert to its old styles.
3685
+ */
3686
+ animation.onfinish = () => {
3687
+ value.set(keyframes[keyframes.length - 1]);
3688
+ onComplete && onComplete();
3689
+ };
3690
+ /**
3691
+ * Animation interrupt callback.
3692
+ */
3693
+ return () => {
3694
+ /**
3695
+ * WAAPI doesn't natively have any interruption capabilities.
3696
+ *
3697
+ * Rather than read commited styles back out of the DOM, we can
3698
+ * create a renderless JS animation and sample it twice to calculate
3699
+ * its current value, "previous" value, and therefore allow
3700
+ * Motion to calculate velocity for any subsequent animation.
3701
+ */
3702
+ const { currentTime } = animation;
3703
+ if (currentTime) {
3704
+ const sampleAnimation = animate$1(options);
3705
+ value.setWithVelocity(sampleAnimation.sample(currentTime - sampleDelta), sampleAnimation.sample(currentTime), sampleDelta);
3706
+ }
3707
+ sync.update(() => animation.cancel());
3708
+ };
3709
+ }
3710
+
3711
+ /**
3712
+ * Timeout defined in ms
3713
+ */
3714
+ function delay(callback, timeout) {
3715
+ const start = performance.now();
3716
+ const checkElapsed = ({ timestamp }) => {
3717
+ const elapsed = timestamp - start;
3718
+ if (elapsed >= timeout) {
3719
+ cancelSync.read(checkElapsed);
3720
+ callback(elapsed - timeout);
3721
+ }
3722
+ };
3723
+ sync.read(checkElapsed, true);
3724
+ return () => cancelSync.read(checkElapsed);
3725
+ }
3726
+
3727
+ function createInstantAnimation({ keyframes, elapsed, onUpdate, onComplete, }) {
3728
+ const setValue = () => {
3729
+ onUpdate && onUpdate(keyframes[keyframes.length - 1]);
3730
+ onComplete && onComplete();
3731
+ return () => { };
3732
+ };
3733
+ return elapsed ? delay(setValue, -elapsed) : setValue();
3734
+ }
3735
+
3645
3736
  function inertia({ keyframes, velocity = 0, min, max, power = 0.8, timeConstant = 750, bounceStiffness = 500, bounceDamping = 10, restDelta = 1, modifyTarget, driver, onUpdate, onComplete, onStop, }) {
3646
3737
  const origin = keyframes[0];
3647
3738
  let currentAnimation;
@@ -3880,7 +3971,7 @@ for (const key in featureTests) {
3880
3971
  /**
3881
3972
  * A list of values that can be hardware-accelerated.
3882
3973
  */
3883
- const acceleratedValues = new Set([]);
3974
+ const acceleratedValues = new Set(["opacity"]);
3884
3975
  const createMotionValueAnimation = (valueName, value, target, transition = {}) => {
3885
3976
  return (onComplete) => {
3886
3977
  const valueTransition = getValueTransition(transition, valueName) || {};
@@ -3960,19 +4051,22 @@ const createMotionValueAnimation = (valueName, value, target, transition = {}) =
3960
4051
  if (options.repeatDelay) {
3961
4052
  options.repeatDelay = secondsToMilliseconds(options.repeatDelay);
3962
4053
  }
3963
- const canAccelerateAnimation = acceleratedValues.has(valueName) &&
3964
- supports.waapi() &&
3965
- value.owner &&
3966
- !value.owner.getProps().onUpdate &&
3967
- !options.repeat;
4054
+ const visualElement = value.owner;
4055
+ const element = visualElement && visualElement.current;
4056
+ const canAccelerateAnimation = supports.waapi() &&
4057
+ acceleratedValues.has(valueName) &&
4058
+ !options.repeatDelay &&
4059
+ options.repeatType !== "mirror" &&
4060
+ options.damping !== 0 &&
4061
+ typeof options.ease !== "function" &&
4062
+ visualElement &&
4063
+ element instanceof HTMLElement &&
4064
+ !visualElement.getProps().onUpdate;
3968
4065
  if (canAccelerateAnimation) {
3969
4066
  /**
3970
4067
  * If this animation is capable of being run via WAAPI, then do so.
3971
- *
3972
- * TODO: Currently no values are hardware accelerated so this clause
3973
- * will never trigger. Animation to be added in subsequent PR.
3974
4068
  */
3975
- return createAcceleratedAnimation();
4069
+ return createAcceleratedAnimation(value, valueName, options);
3976
4070
  }
3977
4071
  else {
3978
4072
  /**
@@ -5833,7 +5927,7 @@ function updateMotionValuesFromProps(element, next, prev) {
5833
5927
  * and warn against mismatches.
5834
5928
  */
5835
5929
  if (process.env.NODE_ENV === "development") {
5836
- warnOnce(nextValue.version === "7.8.1", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.8.1 may not work as expected.`);
5930
+ warnOnce(nextValue.version === "7.9.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.9.0 may not work as expected.`);
5837
5931
  }
5838
5932
  }
5839
5933
  else if (isMotionValue(prevValue)) {
@@ -5841,7 +5935,7 @@ function updateMotionValuesFromProps(element, next, prev) {
5841
5935
  * If we're swapping from a motion value to a static value,
5842
5936
  * create a new motion value from that
5843
5937
  */
5844
- element.addValue(key, motionValue(nextValue));
5938
+ element.addValue(key, motionValue(nextValue, { owner: element }));
5845
5939
  if (isWillChangeMotionValue(willChange)) {
5846
5940
  willChange.remove(key);
5847
5941
  }
@@ -6256,7 +6350,7 @@ class VisualElement {
6256
6350
  }
6257
6351
  let value = this.values.get(key);
6258
6352
  if (value === undefined && defaultValue !== undefined) {
6259
- value = motionValue(defaultValue);
6353
+ value = motionValue(defaultValue, { owner: this });
6260
6354
  this.addValue(key, value);
6261
6355
  }
6262
6356
  return value;
@@ -9652,20 +9746,6 @@ function useResetProjection() {
9652
9746
  return reset;
9653
9747
  }
9654
9748
 
9655
- const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
9656
-
9657
- function animateStyle(element, valueName, keyframes, { delay, duration, ease }) {
9658
- if (!supports.waapi())
9659
- return undefined;
9660
- const animation = element.animate({ [valueName]: keyframes }, {
9661
- delay,
9662
- duration,
9663
- easing: Array.isArray(ease) ? cubicBezierAsString(ease) : ease,
9664
- fill: "both",
9665
- });
9666
- return animation;
9667
- }
9668
-
9669
9749
  function startOptimizedAppearAnimation(element, name, keyframes, options) {
9670
9750
  window.MotionAppearAnimations || (window.MotionAppearAnimations = new Map());
9671
9751
  const id = element.dataset[optimizedAppearDataId];
@@ -1,7 +1,7 @@
1
1
  import { warning } from 'hey-listen';
2
2
  import { secondsToMilliseconds } from '../utils/time-conversion.mjs';
3
3
  import { instantAnimationState } from '../utils/use-instant-transition-state.mjs';
4
- import { createAcceleratedAnimation } from './create-accelerated-animation.mjs';
4
+ import { createAcceleratedAnimation } from './waapi/create-accelerated-animation.mjs';
5
5
  import { createInstantAnimation } from './create-instant-animation.mjs';
6
6
  import { animate } from './legacy-popmotion/index.mjs';
7
7
  import { inertia } from './legacy-popmotion/inertia.mjs';
@@ -14,7 +14,7 @@ import { supports } from './waapi/supports.mjs';
14
14
  /**
15
15
  * A list of values that can be hardware-accelerated.
16
16
  */
17
- const acceleratedValues = new Set([]);
17
+ const acceleratedValues = new Set(["opacity"]);
18
18
  const createMotionValueAnimation = (valueName, value, target, transition = {}) => {
19
19
  return (onComplete) => {
20
20
  const valueTransition = getValueTransition(transition, valueName) || {};
@@ -94,19 +94,22 @@ const createMotionValueAnimation = (valueName, value, target, transition = {}) =
94
94
  if (options.repeatDelay) {
95
95
  options.repeatDelay = secondsToMilliseconds(options.repeatDelay);
96
96
  }
97
- const canAccelerateAnimation = acceleratedValues.has(valueName) &&
98
- supports.waapi() &&
99
- value.owner &&
100
- !value.owner.getProps().onUpdate &&
101
- !options.repeat;
97
+ const visualElement = value.owner;
98
+ const element = visualElement && visualElement.current;
99
+ const canAccelerateAnimation = supports.waapi() &&
100
+ acceleratedValues.has(valueName) &&
101
+ !options.repeatDelay &&
102
+ options.repeatType !== "mirror" &&
103
+ options.damping !== 0 &&
104
+ typeof options.ease !== "function" &&
105
+ visualElement &&
106
+ element instanceof HTMLElement &&
107
+ !visualElement.getProps().onUpdate;
102
108
  if (canAccelerateAnimation) {
103
109
  /**
104
110
  * If this animation is capable of being run via WAAPI, then do so.
105
- *
106
- * TODO: Currently no values are hardware accelerated so this clause
107
- * will never trigger. Animation to be added in subsequent PR.
108
111
  */
109
- return createAcceleratedAnimation();
112
+ return createAcceleratedAnimation(value, valueName, options);
110
113
  }
111
114
  else {
112
115
  /**
@@ -28,7 +28,7 @@ const framesync = (update) => {
28
28
  stop: () => cancelSync.update(passTimestamp),
29
29
  };
30
30
  };
31
- function animate({ duration, driver = framesync, elapsed = 0, repeat: repeatMax = 0, repeatType = "loop", repeatDelay = 0, keyframes, onPlay, onStop, onComplete, onRepeat, onUpdate, type = "keyframes", ...options }) {
31
+ function animate({ duration, driver = framesync, elapsed = 0, repeat: repeatMax = 0, repeatType = "loop", repeatDelay = 0, keyframes, autoplay = true, onPlay, onStop, onComplete, onRepeat, onUpdate, type = "keyframes", ...options }) {
32
32
  var _a, _b;
33
33
  let driverControls;
34
34
  let repeatCount = 0;
@@ -99,12 +99,15 @@ function animate({ duration, driver = framesync, elapsed = 0, repeat: repeatMax
99
99
  driverControls = driver(update);
100
100
  driverControls.start();
101
101
  }
102
- play();
102
+ autoplay && play();
103
103
  return {
104
104
  stop: () => {
105
105
  onStop && onStop();
106
106
  driverControls.stop();
107
107
  },
108
+ sample: (t) => {
109
+ return animation.next(Math.max(0, t)).value;
110
+ },
108
111
  };
109
112
  }
110
113
 
@@ -0,0 +1,82 @@
1
+ import { sync } from '../../frameloop/index.mjs';
2
+ import { animate } from '../legacy-popmotion/index.mjs';
3
+ import { spring } from '../legacy-popmotion/spring.mjs';
4
+ import { animateStyle } from './index.mjs';
5
+
6
+ /**
7
+ * 10ms is chosen here as it strikes a balance between smooth
8
+ * results (more than one keyframe per frame at 60fps) and
9
+ * keyframe quantity.
10
+ */
11
+ const sampleDelta = 10; //ms
12
+ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ...options }) {
13
+ let { keyframes, duration = 0.3, elapsed = 0, ease } = options;
14
+ /**
15
+ * If this is a spring animation, pre-generate keyframes and
16
+ * record duration.
17
+ *
18
+ * TODO: When introducing support for values beyond opacity it
19
+ * might be better to use `animate.sample()`
20
+ */
21
+ if (options.type === "spring") {
22
+ const springAnimation = spring(options);
23
+ let state = { done: false, value: keyframes[0] };
24
+ const springKeyframes = [];
25
+ let t = 0;
26
+ while (!state.done) {
27
+ state = springAnimation.next(t);
28
+ springKeyframes.push(state.value);
29
+ t += sampleDelta;
30
+ }
31
+ keyframes = springKeyframes;
32
+ duration = t - sampleDelta;
33
+ ease = "linear";
34
+ }
35
+ const animation = animateStyle(value.owner.current, valueName, keyframes, {
36
+ ...options,
37
+ delay: -elapsed,
38
+ duration,
39
+ /**
40
+ * This function is currently not called if ease is provided
41
+ * as a function so the cast is safe.
42
+ *
43
+ * However it would be possible for a future refinement to port
44
+ * in easing pregeneration from Motion One for browsers that
45
+ * support the upcoming `linear()` easing function.
46
+ */
47
+ ease: ease,
48
+ });
49
+ /**
50
+ * Prefer the `onfinish` prop as it's more widely supported than
51
+ * the `finished` promise.
52
+ *
53
+ * Here, we synchronously set the provided MotionValue to the end
54
+ * keyframe. If we didn't, when the WAAPI animation is finished it would
55
+ * be removed from the element which would then revert to its old styles.
56
+ */
57
+ animation.onfinish = () => {
58
+ value.set(keyframes[keyframes.length - 1]);
59
+ onComplete && onComplete();
60
+ };
61
+ /**
62
+ * Animation interrupt callback.
63
+ */
64
+ return () => {
65
+ /**
66
+ * WAAPI doesn't natively have any interruption capabilities.
67
+ *
68
+ * Rather than read commited styles back out of the DOM, we can
69
+ * create a renderless JS animation and sample it twice to calculate
70
+ * its current value, "previous" value, and therefore allow
71
+ * Motion to calculate velocity for any subsequent animation.
72
+ */
73
+ const { currentTime } = animation;
74
+ if (currentTime) {
75
+ const sampleAnimation = animate(options);
76
+ value.setWithVelocity(sampleAnimation.sample(currentTime - sampleDelta), sampleAnimation.sample(currentTime), sampleDelta);
77
+ }
78
+ sync.update(() => animation.cancel());
79
+ };
80
+ }
81
+
82
+ export { createAcceleratedAnimation };
@@ -1,16 +1,14 @@
1
- import { supports } from './supports.mjs';
2
1
  import { cubicBezierAsString } from './easing.mjs';
3
2
 
4
- function animateStyle(element, valueName, keyframes, { delay, duration, ease }) {
5
- if (!supports.waapi())
6
- return undefined;
7
- const animation = element.animate({ [valueName]: keyframes }, {
3
+ function animateStyle(element, valueName, keyframes, { delay = 0, duration, repeat = 0, repeatType = "loop", ease, times, } = {}) {
4
+ return element.animate({ [valueName]: keyframes, offset: times }, {
8
5
  delay,
9
6
  duration,
10
7
  easing: Array.isArray(ease) ? cubicBezierAsString(ease) : ease,
11
8
  fill: "both",
9
+ iterations: repeat + 1,
10
+ direction: repeatType === "reverse" ? "alternate" : "normal",
12
11
  });
13
- return animation;
14
12
  }
15
13
 
16
14
  export { animateStyle };
@@ -403,7 +403,7 @@ class VisualElement {
403
403
  }
404
404
  let value = this.values.get(key);
405
405
  if (value === undefined && defaultValue !== undefined) {
406
- value = motionValue(defaultValue);
406
+ value = motionValue(defaultValue, { owner: this });
407
407
  this.addValue(key, value);
408
408
  }
409
409
  return value;
@@ -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 === "7.8.1", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.8.1 may not work as expected.`);
25
+ warnOnce(nextValue.version === "7.9.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.9.0 may not work as expected.`);
26
26
  }
27
27
  }
28
28
  else if (isMotionValue(prevValue)) {
@@ -30,7 +30,7 @@ function updateMotionValuesFromProps(element, next, prev) {
30
30
  * If we're swapping from a motion value to a static value,
31
31
  * create a new motion value from that
32
32
  */
33
- element.addValue(key, motionValue(nextValue));
33
+ element.addValue(key, motionValue(nextValue, { owner: element }));
34
34
  if (isWillChangeMotionValue(willChange)) {
35
35
  willChange.remove(key);
36
36
  }
@@ -89,7 +89,7 @@ function checkTargetForNewValues(visualElement, target, origin) {
89
89
  else if (!findValueType(value) && complex.test(targetValue)) {
90
90
  value = getAnimatableNone(key, targetValue);
91
91
  }
92
- visualElement.addValue(key, motionValue(value));
92
+ visualElement.addValue(key, motionValue(value, { owner: visualElement }));
93
93
  if (origin[key] === undefined) {
94
94
  origin[key] = value;
95
95
  }
@@ -20,12 +20,12 @@ class MotionValue {
20
20
  *
21
21
  * @internal
22
22
  */
23
- constructor(init) {
23
+ constructor(init, options = {}) {
24
24
  /**
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 = "7.8.1";
28
+ this.version = "7.9.0";
29
29
  /**
30
30
  * Duration, in milliseconds, since last updating frame.
31
31
  *
@@ -114,6 +114,7 @@ class MotionValue {
114
114
  this.hasAnimated = false;
115
115
  this.prev = this.current = init;
116
116
  this.canTrackVelocity = isFloat(this.current);
117
+ this.owner = options.owner;
117
118
  }
118
119
  /**
119
120
  * Adds a function that will be notified when the `MotionValue` is updated.
@@ -213,6 +214,11 @@ class MotionValue {
213
214
  this.passiveEffect(v, this.updateAndNotify);
214
215
  }
215
216
  }
217
+ setWithVelocity(prev, current, delta) {
218
+ this.set(current);
219
+ this.prev = prev;
220
+ this.timeDelta = delta;
221
+ }
216
222
  /**
217
223
  * Returns the latest state of `MotionValue`
218
224
  *
@@ -299,8 +305,8 @@ class MotionValue {
299
305
  this.stop();
300
306
  }
301
307
  }
302
- function motionValue(init) {
303
- return new MotionValue(init);
308
+ function motionValue(init, options) {
309
+ return new MotionValue(init, options);
304
310
  }
305
311
 
306
312
  export { MotionValue, motionValue };