framer-motion 7.7.3 → 7.8.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/dist/cjs/index.js +313 -237
- package/dist/es/animation/legacy-popmotion/index.mjs +3 -3
- package/dist/es/animation/legacy-popmotion/spring.mjs +20 -28
- package/dist/es/animation/optimized-appear/data-id.mjs +6 -0
- package/dist/es/animation/optimized-appear/handoff.mjs +34 -0
- package/dist/es/animation/optimized-appear/start.mjs +15 -0
- package/dist/es/animation/optimized-appear/store-id.mjs +3 -0
- package/dist/es/animation/utils/transitions.mjs +19 -24
- package/dist/es/animation/waapi/easing.mjs +3 -0
- package/dist/es/animation/waapi/index.mjs +16 -0
- package/dist/es/animation/waapi/supports.mjs +17 -0
- package/dist/es/index.mjs +3 -0
- package/dist/es/render/utils/animation.mjs +13 -1
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/utils/delay.mjs +3 -0
- package/dist/es/value/index.mjs +1 -1
- package/dist/framer-motion.dev.js +313 -237
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +32 -2
- package/dist/projection.dev.js +59 -70
- package/dist/size-rollup-dom-animation-assets.js +1 -1
- package/dist/size-rollup-dom-animation.js +1 -1
- package/dist/size-rollup-dom-max-assets.js +1 -1
- package/dist/size-rollup-dom-max.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/three-entry.d.ts +3 -1
- package/package.json +11 -9
package/dist/cjs/index.js
CHANGED
|
@@ -2296,176 +2296,6 @@ const instantAnimationState = {
|
|
|
2296
2296
|
current: false,
|
|
2297
2297
|
};
|
|
2298
2298
|
|
|
2299
|
-
/*
|
|
2300
|
-
Detect and load appropriate clock setting for the execution environment
|
|
2301
|
-
*/
|
|
2302
|
-
const defaultTimestep = (1 / 60) * 1000;
|
|
2303
|
-
const getCurrentTime = typeof performance !== "undefined"
|
|
2304
|
-
? () => performance.now()
|
|
2305
|
-
: () => Date.now();
|
|
2306
|
-
const onNextFrame = typeof window !== "undefined"
|
|
2307
|
-
? (callback) => window.requestAnimationFrame(callback)
|
|
2308
|
-
: (callback) => setTimeout(() => callback(getCurrentTime()), defaultTimestep);
|
|
2309
|
-
|
|
2310
|
-
function createRenderStep(runNextFrame) {
|
|
2311
|
-
/**
|
|
2312
|
-
* We create and reuse two arrays, one to queue jobs for the current frame
|
|
2313
|
-
* and one for the next. We reuse to avoid triggering GC after x frames.
|
|
2314
|
-
*/
|
|
2315
|
-
let toRun = [];
|
|
2316
|
-
let toRunNextFrame = [];
|
|
2317
|
-
/**
|
|
2318
|
-
*
|
|
2319
|
-
*/
|
|
2320
|
-
let numToRun = 0;
|
|
2321
|
-
/**
|
|
2322
|
-
* Track whether we're currently processing jobs in this step. This way
|
|
2323
|
-
* we can decide whether to schedule new jobs for this frame or next.
|
|
2324
|
-
*/
|
|
2325
|
-
let isProcessing = false;
|
|
2326
|
-
let flushNextFrame = false;
|
|
2327
|
-
/**
|
|
2328
|
-
* A set of processes which were marked keepAlive when scheduled.
|
|
2329
|
-
*/
|
|
2330
|
-
const toKeepAlive = new WeakSet();
|
|
2331
|
-
const step = {
|
|
2332
|
-
/**
|
|
2333
|
-
* Schedule a process to run on the next frame.
|
|
2334
|
-
*/
|
|
2335
|
-
schedule: (callback, keepAlive = false, immediate = false) => {
|
|
2336
|
-
const addToCurrentFrame = immediate && isProcessing;
|
|
2337
|
-
const buffer = addToCurrentFrame ? toRun : toRunNextFrame;
|
|
2338
|
-
if (keepAlive)
|
|
2339
|
-
toKeepAlive.add(callback);
|
|
2340
|
-
// If the buffer doesn't already contain this callback, add it
|
|
2341
|
-
if (buffer.indexOf(callback) === -1) {
|
|
2342
|
-
buffer.push(callback);
|
|
2343
|
-
// If we're adding it to the currently running buffer, update its measured size
|
|
2344
|
-
if (addToCurrentFrame && isProcessing)
|
|
2345
|
-
numToRun = toRun.length;
|
|
2346
|
-
}
|
|
2347
|
-
return callback;
|
|
2348
|
-
},
|
|
2349
|
-
/**
|
|
2350
|
-
* Cancel the provided callback from running on the next frame.
|
|
2351
|
-
*/
|
|
2352
|
-
cancel: (callback) => {
|
|
2353
|
-
const index = toRunNextFrame.indexOf(callback);
|
|
2354
|
-
if (index !== -1)
|
|
2355
|
-
toRunNextFrame.splice(index, 1);
|
|
2356
|
-
toKeepAlive.delete(callback);
|
|
2357
|
-
},
|
|
2358
|
-
/**
|
|
2359
|
-
* Execute all schedule callbacks.
|
|
2360
|
-
*/
|
|
2361
|
-
process: (frameData) => {
|
|
2362
|
-
/**
|
|
2363
|
-
* If we're already processing we've probably been triggered by a flushSync
|
|
2364
|
-
* inside an existing process. Instead of executing, mark flushNextFrame
|
|
2365
|
-
* as true and ensure we flush the following frame at the end of this one.
|
|
2366
|
-
*/
|
|
2367
|
-
if (isProcessing) {
|
|
2368
|
-
flushNextFrame = true;
|
|
2369
|
-
return;
|
|
2370
|
-
}
|
|
2371
|
-
isProcessing = true;
|
|
2372
|
-
[toRun, toRunNextFrame] = [toRunNextFrame, toRun];
|
|
2373
|
-
// Clear the next frame list
|
|
2374
|
-
toRunNextFrame.length = 0;
|
|
2375
|
-
// Execute this frame
|
|
2376
|
-
numToRun = toRun.length;
|
|
2377
|
-
if (numToRun) {
|
|
2378
|
-
for (let i = 0; i < numToRun; i++) {
|
|
2379
|
-
const callback = toRun[i];
|
|
2380
|
-
callback(frameData);
|
|
2381
|
-
if (toKeepAlive.has(callback)) {
|
|
2382
|
-
step.schedule(callback);
|
|
2383
|
-
runNextFrame();
|
|
2384
|
-
}
|
|
2385
|
-
}
|
|
2386
|
-
}
|
|
2387
|
-
isProcessing = false;
|
|
2388
|
-
if (flushNextFrame) {
|
|
2389
|
-
flushNextFrame = false;
|
|
2390
|
-
step.process(frameData);
|
|
2391
|
-
}
|
|
2392
|
-
},
|
|
2393
|
-
};
|
|
2394
|
-
return step;
|
|
2395
|
-
}
|
|
2396
|
-
|
|
2397
|
-
const frameData = {
|
|
2398
|
-
delta: 0,
|
|
2399
|
-
timestamp: 0,
|
|
2400
|
-
};
|
|
2401
|
-
|
|
2402
|
-
const maxElapsed = 40;
|
|
2403
|
-
let useDefaultElapsed = true;
|
|
2404
|
-
let runNextFrame = false;
|
|
2405
|
-
let isProcessing = false;
|
|
2406
|
-
const stepsOrder = [
|
|
2407
|
-
"read",
|
|
2408
|
-
"update",
|
|
2409
|
-
"preRender",
|
|
2410
|
-
"render",
|
|
2411
|
-
"postRender",
|
|
2412
|
-
];
|
|
2413
|
-
const steps = stepsOrder.reduce((acc, key) => {
|
|
2414
|
-
acc[key] = createRenderStep(() => (runNextFrame = true));
|
|
2415
|
-
return acc;
|
|
2416
|
-
}, {});
|
|
2417
|
-
const sync = stepsOrder.reduce((acc, key) => {
|
|
2418
|
-
const step = steps[key];
|
|
2419
|
-
acc[key] = (process, keepAlive = false, immediate = false) => {
|
|
2420
|
-
if (!runNextFrame)
|
|
2421
|
-
startLoop();
|
|
2422
|
-
return step.schedule(process, keepAlive, immediate);
|
|
2423
|
-
};
|
|
2424
|
-
return acc;
|
|
2425
|
-
}, {});
|
|
2426
|
-
const cancelSync = stepsOrder.reduce((acc, key) => {
|
|
2427
|
-
acc[key] = steps[key].cancel;
|
|
2428
|
-
return acc;
|
|
2429
|
-
}, {});
|
|
2430
|
-
const flushSync = stepsOrder.reduce((acc, key) => {
|
|
2431
|
-
acc[key] = () => steps[key].process(frameData);
|
|
2432
|
-
return acc;
|
|
2433
|
-
}, {});
|
|
2434
|
-
const processStep = (stepId) => steps[stepId].process(frameData);
|
|
2435
|
-
const processFrame = (timestamp) => {
|
|
2436
|
-
runNextFrame = false;
|
|
2437
|
-
frameData.delta = useDefaultElapsed
|
|
2438
|
-
? defaultTimestep
|
|
2439
|
-
: Math.max(Math.min(timestamp - frameData.timestamp, maxElapsed), 1);
|
|
2440
|
-
frameData.timestamp = timestamp;
|
|
2441
|
-
isProcessing = true;
|
|
2442
|
-
stepsOrder.forEach(processStep);
|
|
2443
|
-
isProcessing = false;
|
|
2444
|
-
if (runNextFrame) {
|
|
2445
|
-
useDefaultElapsed = false;
|
|
2446
|
-
onNextFrame(processFrame);
|
|
2447
|
-
}
|
|
2448
|
-
};
|
|
2449
|
-
const startLoop = () => {
|
|
2450
|
-
runNextFrame = true;
|
|
2451
|
-
useDefaultElapsed = true;
|
|
2452
|
-
if (!isProcessing)
|
|
2453
|
-
onNextFrame(processFrame);
|
|
2454
|
-
};
|
|
2455
|
-
|
|
2456
|
-
function delay(callback, timeout) {
|
|
2457
|
-
const start = performance.now();
|
|
2458
|
-
const checkElapsed = ({ timestamp }) => {
|
|
2459
|
-
const elapsed = timestamp - start;
|
|
2460
|
-
if (elapsed >= timeout) {
|
|
2461
|
-
cancelSync.read(checkElapsed);
|
|
2462
|
-
callback(elapsed - timeout);
|
|
2463
|
-
}
|
|
2464
|
-
};
|
|
2465
|
-
sync.read(checkElapsed, true);
|
|
2466
|
-
return () => cancelSync.read(checkElapsed);
|
|
2467
|
-
}
|
|
2468
|
-
|
|
2469
2299
|
/*
|
|
2470
2300
|
Value in range from progress
|
|
2471
2301
|
|
|
@@ -2844,6 +2674,16 @@ function calcAngularFreq(undampedFreq, dampingRatio) {
|
|
|
2844
2674
|
return undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
|
|
2845
2675
|
}
|
|
2846
2676
|
|
|
2677
|
+
/*
|
|
2678
|
+
Convert velocity into velocity per second
|
|
2679
|
+
|
|
2680
|
+
@param [number]: Unit per frame
|
|
2681
|
+
@param [number]: Frame duration in ms
|
|
2682
|
+
*/
|
|
2683
|
+
function velocityPerSecond(velocity, frameDuration) {
|
|
2684
|
+
return frameDuration ? velocity * (1000 / frameDuration) : 0;
|
|
2685
|
+
}
|
|
2686
|
+
|
|
2847
2687
|
const durationKeys = ["duration", "bounce"];
|
|
2848
2688
|
const physicsKeys = ["stiffness", "damping", "mass"];
|
|
2849
2689
|
function isSpringType(options, keys) {
|
|
@@ -2872,6 +2712,7 @@ function getSpringOptions(options) {
|
|
|
2872
2712
|
}
|
|
2873
2713
|
return springOptions;
|
|
2874
2714
|
}
|
|
2715
|
+
const velocitySampleDuration = 5;
|
|
2875
2716
|
/**
|
|
2876
2717
|
* This is based on the spring implementation of Wobble https://github.com/skevy/wobble
|
|
2877
2718
|
*/
|
|
@@ -2883,11 +2724,10 @@ function spring({ from = 0.0, to = 1.0, restSpeed = 2, restDelta = 0.01, ...opti
|
|
|
2883
2724
|
const state = { done: false, value: from };
|
|
2884
2725
|
let { stiffness, damping, mass, velocity, duration, isResolvedFromDuration, } = getSpringOptions(options);
|
|
2885
2726
|
let resolveSpring = zero;
|
|
2886
|
-
let
|
|
2727
|
+
let initialVelocity = velocity ? -(velocity / 1000) : 0.0;
|
|
2728
|
+
const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
|
|
2887
2729
|
function createSpring() {
|
|
2888
|
-
const initialVelocity = velocity ? -(velocity / 1000) : 0.0;
|
|
2889
2730
|
const initialDelta = to - from;
|
|
2890
|
-
const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
|
|
2891
2731
|
const undampedAngularFreq = Math.sqrt(stiffness / mass) / 1000;
|
|
2892
2732
|
/**
|
|
2893
2733
|
* If we're working within what looks like a 0-1 range, change the default restDelta
|
|
@@ -2909,29 +2749,6 @@ function spring({ from = 0.0, to = 1.0, restSpeed = 2, restDelta = 0.01, ...opti
|
|
|
2909
2749
|
Math.sin(angularFreq * t) +
|
|
2910
2750
|
initialDelta * Math.cos(angularFreq * t)));
|
|
2911
2751
|
};
|
|
2912
|
-
resolveVelocity = (t) => {
|
|
2913
|
-
// TODO Resolve these calculations with the above
|
|
2914
|
-
const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
|
|
2915
|
-
return (dampingRatio *
|
|
2916
|
-
undampedAngularFreq *
|
|
2917
|
-
envelope *
|
|
2918
|
-
((Math.sin(angularFreq * t) *
|
|
2919
|
-
(initialVelocity +
|
|
2920
|
-
dampingRatio *
|
|
2921
|
-
undampedAngularFreq *
|
|
2922
|
-
initialDelta)) /
|
|
2923
|
-
angularFreq +
|
|
2924
|
-
initialDelta * Math.cos(angularFreq * t)) -
|
|
2925
|
-
envelope *
|
|
2926
|
-
(Math.cos(angularFreq * t) *
|
|
2927
|
-
(initialVelocity +
|
|
2928
|
-
dampingRatio *
|
|
2929
|
-
undampedAngularFreq *
|
|
2930
|
-
initialDelta) -
|
|
2931
|
-
angularFreq *
|
|
2932
|
-
initialDelta *
|
|
2933
|
-
Math.sin(angularFreq * t)));
|
|
2934
|
-
};
|
|
2935
2752
|
}
|
|
2936
2753
|
else if (dampingRatio === 1) {
|
|
2937
2754
|
// Critically damped spring
|
|
@@ -2965,7 +2782,21 @@ function spring({ from = 0.0, to = 1.0, restSpeed = 2, restDelta = 0.01, ...opti
|
|
|
2965
2782
|
next: (t) => {
|
|
2966
2783
|
const current = resolveSpring(t);
|
|
2967
2784
|
if (!isResolvedFromDuration) {
|
|
2968
|
-
|
|
2785
|
+
let currentVelocity = initialVelocity;
|
|
2786
|
+
if (t !== 0) {
|
|
2787
|
+
/**
|
|
2788
|
+
* We only need to calculate velocity for under-damped springs
|
|
2789
|
+
* as over- and critically-damped springs can't overshoot, so
|
|
2790
|
+
* checking only for displacement is enough.
|
|
2791
|
+
*/
|
|
2792
|
+
if (dampingRatio < 1) {
|
|
2793
|
+
const prevT = Math.max(0, t - velocitySampleDuration);
|
|
2794
|
+
currentVelocity = velocityPerSecond(current - resolveSpring(prevT), t - prevT);
|
|
2795
|
+
}
|
|
2796
|
+
else {
|
|
2797
|
+
currentVelocity = 0;
|
|
2798
|
+
}
|
|
2799
|
+
}
|
|
2969
2800
|
const isBelowVelocityThreshold = Math.abs(currentVelocity) <= restSpeed;
|
|
2970
2801
|
const isBelowDisplacementThreshold = Math.abs(to - current) <= restDelta;
|
|
2971
2802
|
state.done =
|
|
@@ -2978,7 +2809,7 @@ function spring({ from = 0.0, to = 1.0, restSpeed = 2, restDelta = 0.01, ...opti
|
|
|
2978
2809
|
return state;
|
|
2979
2810
|
},
|
|
2980
2811
|
flipTarget: () => {
|
|
2981
|
-
|
|
2812
|
+
initialVelocity = -initialVelocity;
|
|
2982
2813
|
[from, to] = [to, from];
|
|
2983
2814
|
createSpring();
|
|
2984
2815
|
},
|
|
@@ -3013,6 +2844,163 @@ function decay({ velocity = 0, from = 0, power = 0.8, timeConstant = 350, restDe
|
|
|
3013
2844
|
};
|
|
3014
2845
|
}
|
|
3015
2846
|
|
|
2847
|
+
/*
|
|
2848
|
+
Detect and load appropriate clock setting for the execution environment
|
|
2849
|
+
*/
|
|
2850
|
+
const defaultTimestep = (1 / 60) * 1000;
|
|
2851
|
+
const getCurrentTime = typeof performance !== "undefined"
|
|
2852
|
+
? () => performance.now()
|
|
2853
|
+
: () => Date.now();
|
|
2854
|
+
const onNextFrame = typeof window !== "undefined"
|
|
2855
|
+
? (callback) => window.requestAnimationFrame(callback)
|
|
2856
|
+
: (callback) => setTimeout(() => callback(getCurrentTime()), defaultTimestep);
|
|
2857
|
+
|
|
2858
|
+
function createRenderStep(runNextFrame) {
|
|
2859
|
+
/**
|
|
2860
|
+
* We create and reuse two arrays, one to queue jobs for the current frame
|
|
2861
|
+
* and one for the next. We reuse to avoid triggering GC after x frames.
|
|
2862
|
+
*/
|
|
2863
|
+
let toRun = [];
|
|
2864
|
+
let toRunNextFrame = [];
|
|
2865
|
+
/**
|
|
2866
|
+
*
|
|
2867
|
+
*/
|
|
2868
|
+
let numToRun = 0;
|
|
2869
|
+
/**
|
|
2870
|
+
* Track whether we're currently processing jobs in this step. This way
|
|
2871
|
+
* we can decide whether to schedule new jobs for this frame or next.
|
|
2872
|
+
*/
|
|
2873
|
+
let isProcessing = false;
|
|
2874
|
+
let flushNextFrame = false;
|
|
2875
|
+
/**
|
|
2876
|
+
* A set of processes which were marked keepAlive when scheduled.
|
|
2877
|
+
*/
|
|
2878
|
+
const toKeepAlive = new WeakSet();
|
|
2879
|
+
const step = {
|
|
2880
|
+
/**
|
|
2881
|
+
* Schedule a process to run on the next frame.
|
|
2882
|
+
*/
|
|
2883
|
+
schedule: (callback, keepAlive = false, immediate = false) => {
|
|
2884
|
+
const addToCurrentFrame = immediate && isProcessing;
|
|
2885
|
+
const buffer = addToCurrentFrame ? toRun : toRunNextFrame;
|
|
2886
|
+
if (keepAlive)
|
|
2887
|
+
toKeepAlive.add(callback);
|
|
2888
|
+
// If the buffer doesn't already contain this callback, add it
|
|
2889
|
+
if (buffer.indexOf(callback) === -1) {
|
|
2890
|
+
buffer.push(callback);
|
|
2891
|
+
// If we're adding it to the currently running buffer, update its measured size
|
|
2892
|
+
if (addToCurrentFrame && isProcessing)
|
|
2893
|
+
numToRun = toRun.length;
|
|
2894
|
+
}
|
|
2895
|
+
return callback;
|
|
2896
|
+
},
|
|
2897
|
+
/**
|
|
2898
|
+
* Cancel the provided callback from running on the next frame.
|
|
2899
|
+
*/
|
|
2900
|
+
cancel: (callback) => {
|
|
2901
|
+
const index = toRunNextFrame.indexOf(callback);
|
|
2902
|
+
if (index !== -1)
|
|
2903
|
+
toRunNextFrame.splice(index, 1);
|
|
2904
|
+
toKeepAlive.delete(callback);
|
|
2905
|
+
},
|
|
2906
|
+
/**
|
|
2907
|
+
* Execute all schedule callbacks.
|
|
2908
|
+
*/
|
|
2909
|
+
process: (frameData) => {
|
|
2910
|
+
/**
|
|
2911
|
+
* If we're already processing we've probably been triggered by a flushSync
|
|
2912
|
+
* inside an existing process. Instead of executing, mark flushNextFrame
|
|
2913
|
+
* as true and ensure we flush the following frame at the end of this one.
|
|
2914
|
+
*/
|
|
2915
|
+
if (isProcessing) {
|
|
2916
|
+
flushNextFrame = true;
|
|
2917
|
+
return;
|
|
2918
|
+
}
|
|
2919
|
+
isProcessing = true;
|
|
2920
|
+
[toRun, toRunNextFrame] = [toRunNextFrame, toRun];
|
|
2921
|
+
// Clear the next frame list
|
|
2922
|
+
toRunNextFrame.length = 0;
|
|
2923
|
+
// Execute this frame
|
|
2924
|
+
numToRun = toRun.length;
|
|
2925
|
+
if (numToRun) {
|
|
2926
|
+
for (let i = 0; i < numToRun; i++) {
|
|
2927
|
+
const callback = toRun[i];
|
|
2928
|
+
callback(frameData);
|
|
2929
|
+
if (toKeepAlive.has(callback)) {
|
|
2930
|
+
step.schedule(callback);
|
|
2931
|
+
runNextFrame();
|
|
2932
|
+
}
|
|
2933
|
+
}
|
|
2934
|
+
}
|
|
2935
|
+
isProcessing = false;
|
|
2936
|
+
if (flushNextFrame) {
|
|
2937
|
+
flushNextFrame = false;
|
|
2938
|
+
step.process(frameData);
|
|
2939
|
+
}
|
|
2940
|
+
},
|
|
2941
|
+
};
|
|
2942
|
+
return step;
|
|
2943
|
+
}
|
|
2944
|
+
|
|
2945
|
+
const frameData = {
|
|
2946
|
+
delta: 0,
|
|
2947
|
+
timestamp: 0,
|
|
2948
|
+
};
|
|
2949
|
+
|
|
2950
|
+
const maxElapsed = 40;
|
|
2951
|
+
let useDefaultElapsed = true;
|
|
2952
|
+
let runNextFrame = false;
|
|
2953
|
+
let isProcessing = false;
|
|
2954
|
+
const stepsOrder = [
|
|
2955
|
+
"read",
|
|
2956
|
+
"update",
|
|
2957
|
+
"preRender",
|
|
2958
|
+
"render",
|
|
2959
|
+
"postRender",
|
|
2960
|
+
];
|
|
2961
|
+
const steps = stepsOrder.reduce((acc, key) => {
|
|
2962
|
+
acc[key] = createRenderStep(() => (runNextFrame = true));
|
|
2963
|
+
return acc;
|
|
2964
|
+
}, {});
|
|
2965
|
+
const sync = stepsOrder.reduce((acc, key) => {
|
|
2966
|
+
const step = steps[key];
|
|
2967
|
+
acc[key] = (process, keepAlive = false, immediate = false) => {
|
|
2968
|
+
if (!runNextFrame)
|
|
2969
|
+
startLoop();
|
|
2970
|
+
return step.schedule(process, keepAlive, immediate);
|
|
2971
|
+
};
|
|
2972
|
+
return acc;
|
|
2973
|
+
}, {});
|
|
2974
|
+
const cancelSync = stepsOrder.reduce((acc, key) => {
|
|
2975
|
+
acc[key] = steps[key].cancel;
|
|
2976
|
+
return acc;
|
|
2977
|
+
}, {});
|
|
2978
|
+
const flushSync = stepsOrder.reduce((acc, key) => {
|
|
2979
|
+
acc[key] = () => steps[key].process(frameData);
|
|
2980
|
+
return acc;
|
|
2981
|
+
}, {});
|
|
2982
|
+
const processStep = (stepId) => steps[stepId].process(frameData);
|
|
2983
|
+
const processFrame = (timestamp) => {
|
|
2984
|
+
runNextFrame = false;
|
|
2985
|
+
frameData.delta = useDefaultElapsed
|
|
2986
|
+
? defaultTimestep
|
|
2987
|
+
: Math.max(Math.min(timestamp - frameData.timestamp, maxElapsed), 1);
|
|
2988
|
+
frameData.timestamp = timestamp;
|
|
2989
|
+
isProcessing = true;
|
|
2990
|
+
stepsOrder.forEach(processStep);
|
|
2991
|
+
isProcessing = false;
|
|
2992
|
+
if (runNextFrame) {
|
|
2993
|
+
useDefaultElapsed = false;
|
|
2994
|
+
onNextFrame(processFrame);
|
|
2995
|
+
}
|
|
2996
|
+
};
|
|
2997
|
+
const startLoop = () => {
|
|
2998
|
+
runNextFrame = true;
|
|
2999
|
+
useDefaultElapsed = true;
|
|
3000
|
+
if (!isProcessing)
|
|
3001
|
+
onNextFrame(processFrame);
|
|
3002
|
+
};
|
|
3003
|
+
|
|
3016
3004
|
const types = { decay, keyframes, spring };
|
|
3017
3005
|
function loopElapsed(elapsed, duration, delay = 0) {
|
|
3018
3006
|
return elapsed - duration - delay;
|
|
@@ -3081,7 +3069,7 @@ function animate$1({ from, autoplay = true, driver = framesync, elapsed = 0, rep
|
|
|
3081
3069
|
latest = interpolateFromNumber(latest);
|
|
3082
3070
|
isComplete = isForwardPlayback ? state.done : elapsed <= 0;
|
|
3083
3071
|
}
|
|
3084
|
-
onUpdate
|
|
3072
|
+
onUpdate && onUpdate(latest);
|
|
3085
3073
|
if (isComplete) {
|
|
3086
3074
|
if (repeatCount === 0) {
|
|
3087
3075
|
computedDuration =
|
|
@@ -3096,29 +3084,19 @@ function animate$1({ from, autoplay = true, driver = framesync, elapsed = 0, rep
|
|
|
3096
3084
|
}
|
|
3097
3085
|
}
|
|
3098
3086
|
function play() {
|
|
3099
|
-
onPlay
|
|
3087
|
+
onPlay && onPlay();
|
|
3100
3088
|
driverControls = driver(update);
|
|
3101
3089
|
driverControls.start();
|
|
3102
3090
|
}
|
|
3103
3091
|
autoplay && play();
|
|
3104
3092
|
return {
|
|
3105
3093
|
stop: () => {
|
|
3106
|
-
onStop
|
|
3094
|
+
onStop && onStop();
|
|
3107
3095
|
driverControls.stop();
|
|
3108
3096
|
},
|
|
3109
3097
|
};
|
|
3110
3098
|
}
|
|
3111
3099
|
|
|
3112
|
-
/*
|
|
3113
|
-
Convert velocity into velocity per second
|
|
3114
|
-
|
|
3115
|
-
@param [number]: Unit per frame
|
|
3116
|
-
@param [number]: Frame duration in ms
|
|
3117
|
-
*/
|
|
3118
|
-
function velocityPerSecond(velocity, frameDuration) {
|
|
3119
|
-
return frameDuration ? velocity * (1000 / frameDuration) : 0;
|
|
3120
|
-
}
|
|
3121
|
-
|
|
3122
3100
|
function inertia({ from = 0, velocity = 0, min, max, power = 0.8, timeConstant = 750, bounceStiffness = 500, bounceDamping = 10, restDelta = 1, modifyTarget, driver, onUpdate, onComplete, onStop, }) {
|
|
3123
3101
|
let currentAnimation;
|
|
3124
3102
|
function isOutOfBounds(v) {
|
|
@@ -3199,6 +3177,22 @@ function inertia({ from = 0, velocity = 0, min, max, power = 0.8, timeConstant =
|
|
|
3199
3177
|
};
|
|
3200
3178
|
}
|
|
3201
3179
|
|
|
3180
|
+
/**
|
|
3181
|
+
* Timeout defined in ms
|
|
3182
|
+
*/
|
|
3183
|
+
function delay(callback, timeout) {
|
|
3184
|
+
const start = performance.now();
|
|
3185
|
+
const checkElapsed = ({ timestamp }) => {
|
|
3186
|
+
const elapsed = timestamp - start;
|
|
3187
|
+
if (elapsed >= timeout) {
|
|
3188
|
+
cancelSync.read(checkElapsed);
|
|
3189
|
+
callback(elapsed - timeout);
|
|
3190
|
+
}
|
|
3191
|
+
};
|
|
3192
|
+
sync.read(checkElapsed, true);
|
|
3193
|
+
return () => cancelSync.read(checkElapsed);
|
|
3194
|
+
}
|
|
3195
|
+
|
|
3202
3196
|
/**
|
|
3203
3197
|
* Decide whether a transition is defined on a given Transition.
|
|
3204
3198
|
* This filters out orchestration options and returns true
|
|
@@ -3285,6 +3279,9 @@ function getPopmotionAnimationOptions(transition, options, key) {
|
|
|
3285
3279
|
*/
|
|
3286
3280
|
function getAnimation(key, value, target, transition, onComplete) {
|
|
3287
3281
|
const valueTransition = getValueTransition(transition, key) || {};
|
|
3282
|
+
const { elapsed = 0 } = transition;
|
|
3283
|
+
valueTransition.elapsed =
|
|
3284
|
+
elapsed - secondsToMilliseconds(transition.delay || 0);
|
|
3288
3285
|
let origin = valueTransition.from !== undefined ? valueTransition.from : value.get();
|
|
3289
3286
|
const isTargetAnimatable = isAnimatable(key, target);
|
|
3290
3287
|
if (origin === "none" && isTargetAnimatable && typeof target === "string") {
|
|
@@ -3312,20 +3309,23 @@ function getAnimation(key, value, target, transition, onComplete) {
|
|
|
3312
3309
|
onComplete,
|
|
3313
3310
|
onUpdate: (v) => value.set(v),
|
|
3314
3311
|
};
|
|
3315
|
-
|
|
3312
|
+
const animation = valueTransition.type === "inertia" ||
|
|
3316
3313
|
valueTransition.type === "decay"
|
|
3317
3314
|
? inertia({ ...options, ...valueTransition })
|
|
3318
3315
|
: animate$1({
|
|
3319
3316
|
...getPopmotionAnimationOptions(valueTransition, options, key),
|
|
3320
3317
|
onUpdate: (v) => {
|
|
3321
3318
|
options.onUpdate(v);
|
|
3322
|
-
valueTransition.onUpdate &&
|
|
3319
|
+
valueTransition.onUpdate &&
|
|
3320
|
+
valueTransition.onUpdate(v);
|
|
3323
3321
|
},
|
|
3324
3322
|
onComplete: () => {
|
|
3325
3323
|
options.onComplete();
|
|
3326
|
-
valueTransition.onComplete &&
|
|
3324
|
+
valueTransition.onComplete &&
|
|
3325
|
+
valueTransition.onComplete();
|
|
3327
3326
|
},
|
|
3328
3327
|
});
|
|
3328
|
+
return () => animation.stop();
|
|
3329
3329
|
}
|
|
3330
3330
|
function set() {
|
|
3331
3331
|
const finalTarget = resolveFinalValueInKeyframes(target);
|
|
@@ -3333,13 +3333,16 @@ function getAnimation(key, value, target, transition, onComplete) {
|
|
|
3333
3333
|
onComplete();
|
|
3334
3334
|
valueTransition.onUpdate && valueTransition.onUpdate(finalTarget);
|
|
3335
3335
|
valueTransition.onComplete && valueTransition.onComplete();
|
|
3336
|
-
return
|
|
3336
|
+
return () => { };
|
|
3337
3337
|
}
|
|
3338
|
-
|
|
3338
|
+
const useInstantAnimation = !isOriginAnimatable ||
|
|
3339
3339
|
!isTargetAnimatable ||
|
|
3340
|
-
valueTransition.type === false
|
|
3341
|
-
|
|
3342
|
-
|
|
3340
|
+
valueTransition.type === false;
|
|
3341
|
+
return useInstantAnimation
|
|
3342
|
+
? valueTransition.elapsed
|
|
3343
|
+
? () => delay(set, -valueTransition.elapsed)
|
|
3344
|
+
: set()
|
|
3345
|
+
: start();
|
|
3343
3346
|
}
|
|
3344
3347
|
function isZero(value) {
|
|
3345
3348
|
return (value === 0 ||
|
|
@@ -3364,21 +3367,7 @@ function startAnimation(key, value, target, transition = {}) {
|
|
|
3364
3367
|
transition = { type: false };
|
|
3365
3368
|
}
|
|
3366
3369
|
return value.start((onComplete) => {
|
|
3367
|
-
|
|
3368
|
-
const animation = getAnimation(key, value, target, transition, onComplete);
|
|
3369
|
-
const delayBy = getDelayFromTransition(transition, key);
|
|
3370
|
-
const start = () => (controls = animation());
|
|
3371
|
-
let cancelDelay;
|
|
3372
|
-
if (delayBy) {
|
|
3373
|
-
cancelDelay = delay(start, secondsToMilliseconds(delayBy));
|
|
3374
|
-
}
|
|
3375
|
-
else {
|
|
3376
|
-
start();
|
|
3377
|
-
}
|
|
3378
|
-
return () => {
|
|
3379
|
-
cancelDelay && cancelDelay();
|
|
3380
|
-
controls && controls.stop();
|
|
3381
|
-
};
|
|
3370
|
+
return getAnimation(key, value, target, { ...transition, delay: getDelayFromTransition(transition, key) }, onComplete);
|
|
3382
3371
|
});
|
|
3383
3372
|
}
|
|
3384
3373
|
|
|
@@ -3471,7 +3460,7 @@ class MotionValue {
|
|
|
3471
3460
|
* This will be replaced by the build step with the latest version number.
|
|
3472
3461
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
3473
3462
|
*/
|
|
3474
|
-
this.version = "7.
|
|
3463
|
+
this.version = "7.8.0";
|
|
3475
3464
|
/**
|
|
3476
3465
|
* Duration, in milliseconds, since last updating frame.
|
|
3477
3466
|
*
|
|
@@ -3914,6 +3903,40 @@ function isWillChangeMotionValue(value) {
|
|
|
3914
3903
|
return Boolean(isMotionValue(value) && value.add);
|
|
3915
3904
|
}
|
|
3916
3905
|
|
|
3906
|
+
const appearStoreId = (id, value) => `${id}: ${value}`;
|
|
3907
|
+
|
|
3908
|
+
function handoffOptimizedAppearAnimation(id, name) {
|
|
3909
|
+
const { MotionAppearAnimations } = window;
|
|
3910
|
+
const animationId = appearStoreId(id, transformProps.has(name) ? "transform" : name);
|
|
3911
|
+
const animation = MotionAppearAnimations && MotionAppearAnimations.get(animationId);
|
|
3912
|
+
if (animation) {
|
|
3913
|
+
/**
|
|
3914
|
+
* We allow the animation to persist until the next frame:
|
|
3915
|
+
* 1. So it continues to play until Framer Motion is ready to render
|
|
3916
|
+
* (avoiding a potential flash of the element's original state)
|
|
3917
|
+
* 2. As all independent transforms share a single transform animation, stopping
|
|
3918
|
+
* it synchronously would prevent subsequent transforms from handing off.
|
|
3919
|
+
*/
|
|
3920
|
+
sync.render(() => {
|
|
3921
|
+
/**
|
|
3922
|
+
* Animation.cancel() throws so it needs to be wrapped in a try/catch
|
|
3923
|
+
*/
|
|
3924
|
+
try {
|
|
3925
|
+
animation.cancel();
|
|
3926
|
+
MotionAppearAnimations.delete(animationId);
|
|
3927
|
+
}
|
|
3928
|
+
catch (e) { }
|
|
3929
|
+
});
|
|
3930
|
+
return animation.currentTime || 0;
|
|
3931
|
+
}
|
|
3932
|
+
else {
|
|
3933
|
+
return 0;
|
|
3934
|
+
}
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3937
|
+
const optimizedAppearDataId = "framerAppearId";
|
|
3938
|
+
const optimizedAppearDataAttribute = "data-" + camelToDash(optimizedAppearDataId);
|
|
3939
|
+
|
|
3917
3940
|
function animateVisualElement(visualElement, definition, options = {}) {
|
|
3918
3941
|
visualElement.notify("AnimationStart", definition);
|
|
3919
3942
|
let animation;
|
|
@@ -3991,7 +4014,7 @@ function animateTarget(visualElement, definition, { delay = 0, transitionOverrid
|
|
|
3991
4014
|
shouldBlockAnimation(animationTypeState, key))) {
|
|
3992
4015
|
continue;
|
|
3993
4016
|
}
|
|
3994
|
-
let valueTransition = { delay, ...transition };
|
|
4017
|
+
let valueTransition = { delay, elapsed: 0, ...transition };
|
|
3995
4018
|
/**
|
|
3996
4019
|
* Make animation instant if this is a transform prop and we should reduce motion.
|
|
3997
4020
|
*/
|
|
@@ -4002,6 +4025,16 @@ function animateTarget(visualElement, definition, { delay = 0, transitionOverrid
|
|
|
4002
4025
|
delay: 0,
|
|
4003
4026
|
};
|
|
4004
4027
|
}
|
|
4028
|
+
/**
|
|
4029
|
+
* If this is the first time a value is being animated, check
|
|
4030
|
+
* to see if we're handling off from an existing animation.
|
|
4031
|
+
*/
|
|
4032
|
+
if (!value.hasAnimated) {
|
|
4033
|
+
const appearId = visualElement.getProps()[optimizedAppearDataAttribute];
|
|
4034
|
+
if (appearId) {
|
|
4035
|
+
valueTransition.elapsed = handoffOptimizedAppearAnimation(appearId, key);
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4005
4038
|
let animation = startAnimation(key, value, valueTarget, valueTransition);
|
|
4006
4039
|
if (isWillChangeMotionValue(willChange)) {
|
|
4007
4040
|
willChange.add(key);
|
|
@@ -5753,7 +5786,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
5753
5786
|
* and warn against mismatches.
|
|
5754
5787
|
*/
|
|
5755
5788
|
if (process.env.NODE_ENV === "development") {
|
|
5756
|
-
warnOnce(nextValue.version === "7.
|
|
5789
|
+
warnOnce(nextValue.version === "7.8.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.8.0 may not work as expected.`);
|
|
5757
5790
|
}
|
|
5758
5791
|
}
|
|
5759
5792
|
else if (isMotionValue(prevValue)) {
|
|
@@ -9573,6 +9606,46 @@ function useResetProjection() {
|
|
|
9573
9606
|
return reset;
|
|
9574
9607
|
}
|
|
9575
9608
|
|
|
9609
|
+
const featureTests = {
|
|
9610
|
+
waapi: () => Object.hasOwnProperty.call(Element.prototype, "animate"),
|
|
9611
|
+
};
|
|
9612
|
+
const results = {};
|
|
9613
|
+
const supports = {};
|
|
9614
|
+
/**
|
|
9615
|
+
* Generate features tests that cache their results.
|
|
9616
|
+
*/
|
|
9617
|
+
for (const key in featureTests) {
|
|
9618
|
+
supports[key] = () => {
|
|
9619
|
+
if (results[key] === undefined)
|
|
9620
|
+
results[key] = featureTests[key]();
|
|
9621
|
+
return results[key];
|
|
9622
|
+
};
|
|
9623
|
+
}
|
|
9624
|
+
|
|
9625
|
+
const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
|
|
9626
|
+
|
|
9627
|
+
function animateStyle(element, valueName, keyframes, { delay, duration, ease }) {
|
|
9628
|
+
if (!supports.waapi())
|
|
9629
|
+
return undefined;
|
|
9630
|
+
const animation = element.animate({ [valueName]: keyframes }, {
|
|
9631
|
+
delay,
|
|
9632
|
+
duration,
|
|
9633
|
+
easing: Array.isArray(ease) ? cubicBezierAsString(ease) : ease,
|
|
9634
|
+
fill: "both",
|
|
9635
|
+
});
|
|
9636
|
+
return animation;
|
|
9637
|
+
}
|
|
9638
|
+
|
|
9639
|
+
function startOptimizedAppearAnimation(element, name, keyframes, options) {
|
|
9640
|
+
window.MotionAppearAnimations || (window.MotionAppearAnimations = new Map());
|
|
9641
|
+
const id = element.dataset[optimizedAppearDataId];
|
|
9642
|
+
const animation = animateStyle(element, name, keyframes, options);
|
|
9643
|
+
if (id && animation) {
|
|
9644
|
+
window.MotionAppearAnimations.set(appearStoreId(id, name), animation);
|
|
9645
|
+
}
|
|
9646
|
+
return animation;
|
|
9647
|
+
}
|
|
9648
|
+
|
|
9576
9649
|
const createObject = () => ({});
|
|
9577
9650
|
class StateVisualElement extends VisualElement {
|
|
9578
9651
|
build() { }
|
|
@@ -9722,8 +9795,11 @@ exports.makeUseVisualState = makeUseVisualState;
|
|
|
9722
9795
|
exports.mix = mix;
|
|
9723
9796
|
exports.motion = motion;
|
|
9724
9797
|
exports.motionValue = motionValue;
|
|
9798
|
+
exports.optimizedAppearDataAttribute = optimizedAppearDataAttribute;
|
|
9725
9799
|
exports.pipe = pipe;
|
|
9726
9800
|
exports.resolveMotionValue = resolveMotionValue;
|
|
9801
|
+
exports.spring = spring;
|
|
9802
|
+
exports.startOptimizedAppearAnimation = startOptimizedAppearAnimation;
|
|
9727
9803
|
exports.transform = transform;
|
|
9728
9804
|
exports.unwrapMotionComponent = unwrapMotionComponent;
|
|
9729
9805
|
exports.useAnimation = useAnimation;
|