framer-motion 8.4.4 → 8.4.5
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/index.js +85 -36
- package/dist/es/animation/create-instant-animation.mjs +1 -2
- package/dist/es/animation/index.mjs +2 -4
- package/dist/es/animation/legacy-popmotion/index.mjs +19 -0
- package/dist/es/animation/optimized-appear/handoff.mjs +19 -2
- package/dist/es/animation/waapi/create-accelerated-animation.mjs +23 -15
- package/dist/es/motion/utils/use-visual-element.mjs +13 -5
- package/dist/es/render/utils/animation.mjs +1 -1
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/value/index.mjs +7 -7
- package/dist/framer-motion.dev.js +85 -36
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +133 -133
- package/dist/projection.dev.js +53 -29
- package/dist/size-rollup-dom-animation-m.js +1 -1
- package/dist/size-rollup-dom-animation.js +1 -1
- package/dist/size-rollup-dom-max.js +1 -1
- package/dist/size-rollup-m.js +1 -1
- package/dist/size-rollup-motion.js +1 -1
- package/dist/size-webpack-dom-animation.js +1 -1
- package/dist/size-webpack-dom-max.js +1 -1
- package/dist/size-webpack-m.js +1 -1
- package/dist/three-entry.d.ts +62 -62
- package/package.json +9 -9
|
@@ -79,11 +79,19 @@
|
|
|
79
79
|
visualElement && visualElement.render();
|
|
80
80
|
});
|
|
81
81
|
/**
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
82
|
+
* Ideally this function would always run in a useEffect.
|
|
83
|
+
*
|
|
84
|
+
* However, if we have optimised appear animations to handoff from,
|
|
85
|
+
* it needs to happen synchronously to ensure there's no flash of
|
|
86
|
+
* incorrect styles in the event of a hydration error.
|
|
87
|
+
*
|
|
88
|
+
* So if we detect a situtation where optimised appear animations
|
|
89
|
+
* are running, we use useLayoutEffect to trigger animations.
|
|
85
90
|
*/
|
|
86
|
-
|
|
91
|
+
const useAnimateChangesEffect = window.MotionAppearAnimations
|
|
92
|
+
? useIsomorphicLayoutEffect
|
|
93
|
+
: React.useEffect;
|
|
94
|
+
useAnimateChangesEffect(() => {
|
|
87
95
|
if (visualElement && visualElement.animationState) {
|
|
88
96
|
visualElement.animationState.animateChanges();
|
|
89
97
|
}
|
|
@@ -2079,7 +2087,7 @@
|
|
|
2079
2087
|
* This will be replaced by the build step with the latest version number.
|
|
2080
2088
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
2081
2089
|
*/
|
|
2082
|
-
this.version = "8.4.
|
|
2090
|
+
this.version = "8.4.5";
|
|
2083
2091
|
/**
|
|
2084
2092
|
* Duration, in milliseconds, since last updating frame.
|
|
2085
2093
|
*
|
|
@@ -2318,11 +2326,11 @@
|
|
|
2318
2326
|
*
|
|
2319
2327
|
* @internal
|
|
2320
2328
|
*/
|
|
2321
|
-
start(
|
|
2329
|
+
start(startAnimation) {
|
|
2322
2330
|
this.stop();
|
|
2323
2331
|
return new Promise((resolve) => {
|
|
2324
2332
|
this.hasAnimated = true;
|
|
2325
|
-
this.
|
|
2333
|
+
this.animation = startAnimation(resolve) || null;
|
|
2326
2334
|
if (this.events.animationStart) {
|
|
2327
2335
|
this.events.animationStart.notify();
|
|
2328
2336
|
}
|
|
@@ -2339,8 +2347,8 @@
|
|
|
2339
2347
|
* @public
|
|
2340
2348
|
*/
|
|
2341
2349
|
stop() {
|
|
2342
|
-
if (this.
|
|
2343
|
-
this.
|
|
2350
|
+
if (this.animation) {
|
|
2351
|
+
this.animation.stop();
|
|
2344
2352
|
if (this.events.animationCancel) {
|
|
2345
2353
|
this.events.animationCancel.notify();
|
|
2346
2354
|
}
|
|
@@ -2353,10 +2361,10 @@
|
|
|
2353
2361
|
* @public
|
|
2354
2362
|
*/
|
|
2355
2363
|
isAnimating() {
|
|
2356
|
-
return !!this.
|
|
2364
|
+
return !!this.animation;
|
|
2357
2365
|
}
|
|
2358
2366
|
clearAnimation() {
|
|
2359
|
-
this.
|
|
2367
|
+
this.animation = null;
|
|
2360
2368
|
}
|
|
2361
2369
|
/**
|
|
2362
2370
|
* Destroy and clean up subscribers to this `MotionValue`.
|
|
@@ -2775,11 +2783,28 @@
|
|
|
2775
2783
|
|
|
2776
2784
|
const appearStoreId = (id, value) => `${id}: ${value}`;
|
|
2777
2785
|
|
|
2778
|
-
function handoffOptimizedAppearAnimation(id, name) {
|
|
2786
|
+
function handoffOptimizedAppearAnimation(id, name, value) {
|
|
2779
2787
|
const { MotionAppearAnimations } = window;
|
|
2780
2788
|
const animationId = appearStoreId(id, transformProps.has(name) ? "transform" : name);
|
|
2781
2789
|
const animation = MotionAppearAnimations && MotionAppearAnimations.get(animationId);
|
|
2782
2790
|
if (animation) {
|
|
2791
|
+
const sampledTime = performance.now();
|
|
2792
|
+
/**
|
|
2793
|
+
* Resync handoff animation with optimised animation.
|
|
2794
|
+
*
|
|
2795
|
+
* This step would be unnecessary if we triggered animateChanges() in useEffect,
|
|
2796
|
+
* but due to potential hydration errors we currently fire them in useLayoutEffect.
|
|
2797
|
+
*
|
|
2798
|
+
* By the time we're safely ready to cancel the optimised WAAPI animation,
|
|
2799
|
+
* the main thread might have been blocked and desynced the two animations.
|
|
2800
|
+
*
|
|
2801
|
+
* Here, we resync the two animations before the optimised WAAPI animation is cancelled.
|
|
2802
|
+
*/
|
|
2803
|
+
sync.update(() => {
|
|
2804
|
+
if (value.animation) {
|
|
2805
|
+
value.animation.currentTime = performance.now() - sampledTime;
|
|
2806
|
+
}
|
|
2807
|
+
});
|
|
2783
2808
|
/**
|
|
2784
2809
|
* We allow the animation to persist until the next frame:
|
|
2785
2810
|
* 1. So it continues to play until Framer Motion is ready to render
|
|
@@ -2788,12 +2813,12 @@
|
|
|
2788
2813
|
* it synchronously would prevent subsequent transforms from handing off.
|
|
2789
2814
|
*/
|
|
2790
2815
|
sync.render(() => {
|
|
2816
|
+
MotionAppearAnimations.delete(animationId);
|
|
2791
2817
|
/**
|
|
2792
2818
|
* Animation.cancel() throws so it needs to be wrapped in a try/catch
|
|
2793
2819
|
*/
|
|
2794
2820
|
try {
|
|
2795
2821
|
animation.cancel();
|
|
2796
|
-
MotionAppearAnimations.delete(animationId);
|
|
2797
2822
|
}
|
|
2798
2823
|
catch (e) { }
|
|
2799
2824
|
});
|
|
@@ -3594,6 +3619,25 @@
|
|
|
3594
3619
|
onStop && onStop();
|
|
3595
3620
|
driverControls && driverControls.stop();
|
|
3596
3621
|
},
|
|
3622
|
+
/**
|
|
3623
|
+
* Set the current time of the animation. This is purposefully
|
|
3624
|
+
* mirroring the WAAPI animation API to make them interchanagable.
|
|
3625
|
+
* Going forward this file should be ported more towards
|
|
3626
|
+
* https://github.com/motiondivision/motionone/blob/main/packages/animation/src/Animation.ts
|
|
3627
|
+
* Which behaviourally adheres to WAAPI as far as possible.
|
|
3628
|
+
*
|
|
3629
|
+
* WARNING: This is not safe to use for most animations. We currently
|
|
3630
|
+
* only use it for handoff from WAAPI within Framer.
|
|
3631
|
+
*
|
|
3632
|
+
* This animation function consumes time every frame rather than being sampled for time.
|
|
3633
|
+
* So the sample() method performs some headless frames to ensure
|
|
3634
|
+
* repeats are handled correctly. Ideally in the future we will replace
|
|
3635
|
+
* that method with this, once repeat calculations are pure.
|
|
3636
|
+
*/
|
|
3637
|
+
set currentTime(t) {
|
|
3638
|
+
elapsed = initialElapsed;
|
|
3639
|
+
update(t);
|
|
3640
|
+
},
|
|
3597
3641
|
/**
|
|
3598
3642
|
* animate() can't yet be sampled for time, instead it
|
|
3599
3643
|
* consumes time. So to sample it we have to run a low
|
|
@@ -3750,21 +3794,29 @@
|
|
|
3750
3794
|
/**
|
|
3751
3795
|
* Animation interrupt callback.
|
|
3752
3796
|
*/
|
|
3753
|
-
return
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3797
|
+
return {
|
|
3798
|
+
get currentTime() {
|
|
3799
|
+
return animation.currentTime || 0;
|
|
3800
|
+
},
|
|
3801
|
+
set currentTime(t) {
|
|
3802
|
+
animation.currentTime = t;
|
|
3803
|
+
},
|
|
3804
|
+
stop: () => {
|
|
3805
|
+
/**
|
|
3806
|
+
* WAAPI doesn't natively have any interruption capabilities.
|
|
3807
|
+
*
|
|
3808
|
+
* Rather than read commited styles back out of the DOM, we can
|
|
3809
|
+
* create a renderless JS animation and sample it twice to calculate
|
|
3810
|
+
* its current value, "previous" value, and therefore allow
|
|
3811
|
+
* Motion to calculate velocity for any subsequent animation.
|
|
3812
|
+
*/
|
|
3813
|
+
const { currentTime } = animation;
|
|
3814
|
+
if (currentTime) {
|
|
3815
|
+
const sampleAnimation = animate$1({ ...options, autoplay: false });
|
|
3816
|
+
value.setWithVelocity(sampleAnimation.sample(currentTime - sampleDelta).value, sampleAnimation.sample(currentTime).value, sampleDelta);
|
|
3817
|
+
}
|
|
3818
|
+
sync.update(() => animation.cancel());
|
|
3819
|
+
},
|
|
3768
3820
|
};
|
|
3769
3821
|
}
|
|
3770
3822
|
|
|
@@ -3788,9 +3840,8 @@
|
|
|
3788
3840
|
const setValue = () => {
|
|
3789
3841
|
onUpdate && onUpdate(keyframes[keyframes.length - 1]);
|
|
3790
3842
|
onComplete && onComplete();
|
|
3791
|
-
return () => { };
|
|
3792
3843
|
};
|
|
3793
|
-
return elapsed ? delay(setValue, -elapsed) : setValue();
|
|
3844
|
+
return elapsed ? { stop: delay(setValue, -elapsed) } : setValue();
|
|
3794
3845
|
}
|
|
3795
3846
|
|
|
3796
3847
|
function inertia({ keyframes, velocity = 0, min, max, power = 0.8, timeConstant = 750, bounceStiffness = 500, bounceDamping = 10, restDelta = 1, modifyTarget, driver, onUpdate, onComplete, onStop, }) {
|
|
@@ -4067,8 +4118,7 @@
|
|
|
4067
4118
|
* If this is an inertia animation, we currently don't support pre-generating
|
|
4068
4119
|
* keyframes for this as such it must always run on the main thread.
|
|
4069
4120
|
*/
|
|
4070
|
-
|
|
4071
|
-
return () => animation.stop();
|
|
4121
|
+
return inertia(options);
|
|
4072
4122
|
}
|
|
4073
4123
|
/**
|
|
4074
4124
|
* If there's no transition defined for this value, we can generate
|
|
@@ -4106,8 +4156,7 @@
|
|
|
4106
4156
|
/**
|
|
4107
4157
|
* If we didn't create an accelerated animation, create a JS animation
|
|
4108
4158
|
*/
|
|
4109
|
-
|
|
4110
|
-
return () => animation.stop();
|
|
4159
|
+
return animate$1(options);
|
|
4111
4160
|
};
|
|
4112
4161
|
};
|
|
4113
4162
|
|
|
@@ -4196,7 +4245,7 @@
|
|
|
4196
4245
|
if (!value.hasAnimated) {
|
|
4197
4246
|
const appearId = visualElement.getProps()[optimizedAppearDataAttribute];
|
|
4198
4247
|
if (appearId) {
|
|
4199
|
-
valueTransition.elapsed = handoffOptimizedAppearAnimation(appearId, key);
|
|
4248
|
+
valueTransition.elapsed = handoffOptimizedAppearAnimation(appearId, key, value);
|
|
4200
4249
|
}
|
|
4201
4250
|
}
|
|
4202
4251
|
let animation = value.start(createMotionValueAnimation(key, value, valueTarget, visualElement.shouldReduceMotion && transformProps.has(key)
|
|
@@ -5946,7 +5995,7 @@
|
|
|
5946
5995
|
* and warn against mismatches.
|
|
5947
5996
|
*/
|
|
5948
5997
|
{
|
|
5949
|
-
warnOnce(nextValue.version === "8.4.
|
|
5998
|
+
warnOnce(nextValue.version === "8.4.5", `Attempting to mix Framer Motion versions ${nextValue.version} with 8.4.5 may not work as expected.`);
|
|
5950
5999
|
}
|
|
5951
6000
|
}
|
|
5952
6001
|
else if (isMotionValue(prevValue)) {
|