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
|
@@ -2309,176 +2309,6 @@
|
|
|
2309
2309
|
current: false,
|
|
2310
2310
|
};
|
|
2311
2311
|
|
|
2312
|
-
/*
|
|
2313
|
-
Detect and load appropriate clock setting for the execution environment
|
|
2314
|
-
*/
|
|
2315
|
-
const defaultTimestep = (1 / 60) * 1000;
|
|
2316
|
-
const getCurrentTime = typeof performance !== "undefined"
|
|
2317
|
-
? () => performance.now()
|
|
2318
|
-
: () => Date.now();
|
|
2319
|
-
const onNextFrame = typeof window !== "undefined"
|
|
2320
|
-
? (callback) => window.requestAnimationFrame(callback)
|
|
2321
|
-
: (callback) => setTimeout(() => callback(getCurrentTime()), defaultTimestep);
|
|
2322
|
-
|
|
2323
|
-
function createRenderStep(runNextFrame) {
|
|
2324
|
-
/**
|
|
2325
|
-
* We create and reuse two arrays, one to queue jobs for the current frame
|
|
2326
|
-
* and one for the next. We reuse to avoid triggering GC after x frames.
|
|
2327
|
-
*/
|
|
2328
|
-
let toRun = [];
|
|
2329
|
-
let toRunNextFrame = [];
|
|
2330
|
-
/**
|
|
2331
|
-
*
|
|
2332
|
-
*/
|
|
2333
|
-
let numToRun = 0;
|
|
2334
|
-
/**
|
|
2335
|
-
* Track whether we're currently processing jobs in this step. This way
|
|
2336
|
-
* we can decide whether to schedule new jobs for this frame or next.
|
|
2337
|
-
*/
|
|
2338
|
-
let isProcessing = false;
|
|
2339
|
-
let flushNextFrame = false;
|
|
2340
|
-
/**
|
|
2341
|
-
* A set of processes which were marked keepAlive when scheduled.
|
|
2342
|
-
*/
|
|
2343
|
-
const toKeepAlive = new WeakSet();
|
|
2344
|
-
const step = {
|
|
2345
|
-
/**
|
|
2346
|
-
* Schedule a process to run on the next frame.
|
|
2347
|
-
*/
|
|
2348
|
-
schedule: (callback, keepAlive = false, immediate = false) => {
|
|
2349
|
-
const addToCurrentFrame = immediate && isProcessing;
|
|
2350
|
-
const buffer = addToCurrentFrame ? toRun : toRunNextFrame;
|
|
2351
|
-
if (keepAlive)
|
|
2352
|
-
toKeepAlive.add(callback);
|
|
2353
|
-
// If the buffer doesn't already contain this callback, add it
|
|
2354
|
-
if (buffer.indexOf(callback) === -1) {
|
|
2355
|
-
buffer.push(callback);
|
|
2356
|
-
// If we're adding it to the currently running buffer, update its measured size
|
|
2357
|
-
if (addToCurrentFrame && isProcessing)
|
|
2358
|
-
numToRun = toRun.length;
|
|
2359
|
-
}
|
|
2360
|
-
return callback;
|
|
2361
|
-
},
|
|
2362
|
-
/**
|
|
2363
|
-
* Cancel the provided callback from running on the next frame.
|
|
2364
|
-
*/
|
|
2365
|
-
cancel: (callback) => {
|
|
2366
|
-
const index = toRunNextFrame.indexOf(callback);
|
|
2367
|
-
if (index !== -1)
|
|
2368
|
-
toRunNextFrame.splice(index, 1);
|
|
2369
|
-
toKeepAlive.delete(callback);
|
|
2370
|
-
},
|
|
2371
|
-
/**
|
|
2372
|
-
* Execute all schedule callbacks.
|
|
2373
|
-
*/
|
|
2374
|
-
process: (frameData) => {
|
|
2375
|
-
/**
|
|
2376
|
-
* If we're already processing we've probably been triggered by a flushSync
|
|
2377
|
-
* inside an existing process. Instead of executing, mark flushNextFrame
|
|
2378
|
-
* as true and ensure we flush the following frame at the end of this one.
|
|
2379
|
-
*/
|
|
2380
|
-
if (isProcessing) {
|
|
2381
|
-
flushNextFrame = true;
|
|
2382
|
-
return;
|
|
2383
|
-
}
|
|
2384
|
-
isProcessing = true;
|
|
2385
|
-
[toRun, toRunNextFrame] = [toRunNextFrame, toRun];
|
|
2386
|
-
// Clear the next frame list
|
|
2387
|
-
toRunNextFrame.length = 0;
|
|
2388
|
-
// Execute this frame
|
|
2389
|
-
numToRun = toRun.length;
|
|
2390
|
-
if (numToRun) {
|
|
2391
|
-
for (let i = 0; i < numToRun; i++) {
|
|
2392
|
-
const callback = toRun[i];
|
|
2393
|
-
callback(frameData);
|
|
2394
|
-
if (toKeepAlive.has(callback)) {
|
|
2395
|
-
step.schedule(callback);
|
|
2396
|
-
runNextFrame();
|
|
2397
|
-
}
|
|
2398
|
-
}
|
|
2399
|
-
}
|
|
2400
|
-
isProcessing = false;
|
|
2401
|
-
if (flushNextFrame) {
|
|
2402
|
-
flushNextFrame = false;
|
|
2403
|
-
step.process(frameData);
|
|
2404
|
-
}
|
|
2405
|
-
},
|
|
2406
|
-
};
|
|
2407
|
-
return step;
|
|
2408
|
-
}
|
|
2409
|
-
|
|
2410
|
-
const frameData = {
|
|
2411
|
-
delta: 0,
|
|
2412
|
-
timestamp: 0,
|
|
2413
|
-
};
|
|
2414
|
-
|
|
2415
|
-
const maxElapsed$1 = 40;
|
|
2416
|
-
let useDefaultElapsed = true;
|
|
2417
|
-
let runNextFrame = false;
|
|
2418
|
-
let isProcessing = false;
|
|
2419
|
-
const stepsOrder = [
|
|
2420
|
-
"read",
|
|
2421
|
-
"update",
|
|
2422
|
-
"preRender",
|
|
2423
|
-
"render",
|
|
2424
|
-
"postRender",
|
|
2425
|
-
];
|
|
2426
|
-
const steps = stepsOrder.reduce((acc, key) => {
|
|
2427
|
-
acc[key] = createRenderStep(() => (runNextFrame = true));
|
|
2428
|
-
return acc;
|
|
2429
|
-
}, {});
|
|
2430
|
-
const sync = stepsOrder.reduce((acc, key) => {
|
|
2431
|
-
const step = steps[key];
|
|
2432
|
-
acc[key] = (process, keepAlive = false, immediate = false) => {
|
|
2433
|
-
if (!runNextFrame)
|
|
2434
|
-
startLoop();
|
|
2435
|
-
return step.schedule(process, keepAlive, immediate);
|
|
2436
|
-
};
|
|
2437
|
-
return acc;
|
|
2438
|
-
}, {});
|
|
2439
|
-
const cancelSync = stepsOrder.reduce((acc, key) => {
|
|
2440
|
-
acc[key] = steps[key].cancel;
|
|
2441
|
-
return acc;
|
|
2442
|
-
}, {});
|
|
2443
|
-
const flushSync = stepsOrder.reduce((acc, key) => {
|
|
2444
|
-
acc[key] = () => steps[key].process(frameData);
|
|
2445
|
-
return acc;
|
|
2446
|
-
}, {});
|
|
2447
|
-
const processStep = (stepId) => steps[stepId].process(frameData);
|
|
2448
|
-
const processFrame = (timestamp) => {
|
|
2449
|
-
runNextFrame = false;
|
|
2450
|
-
frameData.delta = useDefaultElapsed
|
|
2451
|
-
? defaultTimestep
|
|
2452
|
-
: Math.max(Math.min(timestamp - frameData.timestamp, maxElapsed$1), 1);
|
|
2453
|
-
frameData.timestamp = timestamp;
|
|
2454
|
-
isProcessing = true;
|
|
2455
|
-
stepsOrder.forEach(processStep);
|
|
2456
|
-
isProcessing = false;
|
|
2457
|
-
if (runNextFrame) {
|
|
2458
|
-
useDefaultElapsed = false;
|
|
2459
|
-
onNextFrame(processFrame);
|
|
2460
|
-
}
|
|
2461
|
-
};
|
|
2462
|
-
const startLoop = () => {
|
|
2463
|
-
runNextFrame = true;
|
|
2464
|
-
useDefaultElapsed = true;
|
|
2465
|
-
if (!isProcessing)
|
|
2466
|
-
onNextFrame(processFrame);
|
|
2467
|
-
};
|
|
2468
|
-
|
|
2469
|
-
function delay(callback, timeout) {
|
|
2470
|
-
const start = performance.now();
|
|
2471
|
-
const checkElapsed = ({ timestamp }) => {
|
|
2472
|
-
const elapsed = timestamp - start;
|
|
2473
|
-
if (elapsed >= timeout) {
|
|
2474
|
-
cancelSync.read(checkElapsed);
|
|
2475
|
-
callback(elapsed - timeout);
|
|
2476
|
-
}
|
|
2477
|
-
};
|
|
2478
|
-
sync.read(checkElapsed, true);
|
|
2479
|
-
return () => cancelSync.read(checkElapsed);
|
|
2480
|
-
}
|
|
2481
|
-
|
|
2482
2312
|
/*
|
|
2483
2313
|
Value in range from progress
|
|
2484
2314
|
|
|
@@ -2857,6 +2687,16 @@
|
|
|
2857
2687
|
return undampedFreq * Math.sqrt(1 - dampingRatio * dampingRatio);
|
|
2858
2688
|
}
|
|
2859
2689
|
|
|
2690
|
+
/*
|
|
2691
|
+
Convert velocity into velocity per second
|
|
2692
|
+
|
|
2693
|
+
@param [number]: Unit per frame
|
|
2694
|
+
@param [number]: Frame duration in ms
|
|
2695
|
+
*/
|
|
2696
|
+
function velocityPerSecond$1(velocity, frameDuration) {
|
|
2697
|
+
return frameDuration ? velocity * (1000 / frameDuration) : 0;
|
|
2698
|
+
}
|
|
2699
|
+
|
|
2860
2700
|
const durationKeys = ["duration", "bounce"];
|
|
2861
2701
|
const physicsKeys = ["stiffness", "damping", "mass"];
|
|
2862
2702
|
function isSpringType(options, keys) {
|
|
@@ -2885,6 +2725,7 @@
|
|
|
2885
2725
|
}
|
|
2886
2726
|
return springOptions;
|
|
2887
2727
|
}
|
|
2728
|
+
const velocitySampleDuration = 5;
|
|
2888
2729
|
/**
|
|
2889
2730
|
* This is based on the spring implementation of Wobble https://github.com/skevy/wobble
|
|
2890
2731
|
*/
|
|
@@ -2896,11 +2737,10 @@
|
|
|
2896
2737
|
const state = { done: false, value: from };
|
|
2897
2738
|
let { stiffness, damping, mass, velocity, duration, isResolvedFromDuration, } = getSpringOptions(options);
|
|
2898
2739
|
let resolveSpring = zero;
|
|
2899
|
-
let
|
|
2740
|
+
let initialVelocity = velocity ? -(velocity / 1000) : 0.0;
|
|
2741
|
+
const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
|
|
2900
2742
|
function createSpring() {
|
|
2901
|
-
const initialVelocity = velocity ? -(velocity / 1000) : 0.0;
|
|
2902
2743
|
const initialDelta = to - from;
|
|
2903
|
-
const dampingRatio = damping / (2 * Math.sqrt(stiffness * mass));
|
|
2904
2744
|
const undampedAngularFreq = Math.sqrt(stiffness / mass) / 1000;
|
|
2905
2745
|
/**
|
|
2906
2746
|
* If we're working within what looks like a 0-1 range, change the default restDelta
|
|
@@ -2922,29 +2762,6 @@
|
|
|
2922
2762
|
Math.sin(angularFreq * t) +
|
|
2923
2763
|
initialDelta * Math.cos(angularFreq * t)));
|
|
2924
2764
|
};
|
|
2925
|
-
resolveVelocity = (t) => {
|
|
2926
|
-
// TODO Resolve these calculations with the above
|
|
2927
|
-
const envelope = Math.exp(-dampingRatio * undampedAngularFreq * t);
|
|
2928
|
-
return (dampingRatio *
|
|
2929
|
-
undampedAngularFreq *
|
|
2930
|
-
envelope *
|
|
2931
|
-
((Math.sin(angularFreq * t) *
|
|
2932
|
-
(initialVelocity +
|
|
2933
|
-
dampingRatio *
|
|
2934
|
-
undampedAngularFreq *
|
|
2935
|
-
initialDelta)) /
|
|
2936
|
-
angularFreq +
|
|
2937
|
-
initialDelta * Math.cos(angularFreq * t)) -
|
|
2938
|
-
envelope *
|
|
2939
|
-
(Math.cos(angularFreq * t) *
|
|
2940
|
-
(initialVelocity +
|
|
2941
|
-
dampingRatio *
|
|
2942
|
-
undampedAngularFreq *
|
|
2943
|
-
initialDelta) -
|
|
2944
|
-
angularFreq *
|
|
2945
|
-
initialDelta *
|
|
2946
|
-
Math.sin(angularFreq * t)));
|
|
2947
|
-
};
|
|
2948
2765
|
}
|
|
2949
2766
|
else if (dampingRatio === 1) {
|
|
2950
2767
|
// Critically damped spring
|
|
@@ -2978,7 +2795,21 @@
|
|
|
2978
2795
|
next: (t) => {
|
|
2979
2796
|
const current = resolveSpring(t);
|
|
2980
2797
|
if (!isResolvedFromDuration) {
|
|
2981
|
-
|
|
2798
|
+
let currentVelocity = initialVelocity;
|
|
2799
|
+
if (t !== 0) {
|
|
2800
|
+
/**
|
|
2801
|
+
* We only need to calculate velocity for under-damped springs
|
|
2802
|
+
* as over- and critically-damped springs can't overshoot, so
|
|
2803
|
+
* checking only for displacement is enough.
|
|
2804
|
+
*/
|
|
2805
|
+
if (dampingRatio < 1) {
|
|
2806
|
+
const prevT = Math.max(0, t - velocitySampleDuration);
|
|
2807
|
+
currentVelocity = velocityPerSecond$1(current - resolveSpring(prevT), t - prevT);
|
|
2808
|
+
}
|
|
2809
|
+
else {
|
|
2810
|
+
currentVelocity = 0;
|
|
2811
|
+
}
|
|
2812
|
+
}
|
|
2982
2813
|
const isBelowVelocityThreshold = Math.abs(currentVelocity) <= restSpeed;
|
|
2983
2814
|
const isBelowDisplacementThreshold = Math.abs(to - current) <= restDelta;
|
|
2984
2815
|
state.done =
|
|
@@ -2991,7 +2822,7 @@
|
|
|
2991
2822
|
return state;
|
|
2992
2823
|
},
|
|
2993
2824
|
flipTarget: () => {
|
|
2994
|
-
|
|
2825
|
+
initialVelocity = -initialVelocity;
|
|
2995
2826
|
[from, to] = [to, from];
|
|
2996
2827
|
createSpring();
|
|
2997
2828
|
},
|
|
@@ -3026,6 +2857,163 @@
|
|
|
3026
2857
|
};
|
|
3027
2858
|
}
|
|
3028
2859
|
|
|
2860
|
+
/*
|
|
2861
|
+
Detect and load appropriate clock setting for the execution environment
|
|
2862
|
+
*/
|
|
2863
|
+
const defaultTimestep = (1 / 60) * 1000;
|
|
2864
|
+
const getCurrentTime = typeof performance !== "undefined"
|
|
2865
|
+
? () => performance.now()
|
|
2866
|
+
: () => Date.now();
|
|
2867
|
+
const onNextFrame = typeof window !== "undefined"
|
|
2868
|
+
? (callback) => window.requestAnimationFrame(callback)
|
|
2869
|
+
: (callback) => setTimeout(() => callback(getCurrentTime()), defaultTimestep);
|
|
2870
|
+
|
|
2871
|
+
function createRenderStep(runNextFrame) {
|
|
2872
|
+
/**
|
|
2873
|
+
* We create and reuse two arrays, one to queue jobs for the current frame
|
|
2874
|
+
* and one for the next. We reuse to avoid triggering GC after x frames.
|
|
2875
|
+
*/
|
|
2876
|
+
let toRun = [];
|
|
2877
|
+
let toRunNextFrame = [];
|
|
2878
|
+
/**
|
|
2879
|
+
*
|
|
2880
|
+
*/
|
|
2881
|
+
let numToRun = 0;
|
|
2882
|
+
/**
|
|
2883
|
+
* Track whether we're currently processing jobs in this step. This way
|
|
2884
|
+
* we can decide whether to schedule new jobs for this frame or next.
|
|
2885
|
+
*/
|
|
2886
|
+
let isProcessing = false;
|
|
2887
|
+
let flushNextFrame = false;
|
|
2888
|
+
/**
|
|
2889
|
+
* A set of processes which were marked keepAlive when scheduled.
|
|
2890
|
+
*/
|
|
2891
|
+
const toKeepAlive = new WeakSet();
|
|
2892
|
+
const step = {
|
|
2893
|
+
/**
|
|
2894
|
+
* Schedule a process to run on the next frame.
|
|
2895
|
+
*/
|
|
2896
|
+
schedule: (callback, keepAlive = false, immediate = false) => {
|
|
2897
|
+
const addToCurrentFrame = immediate && isProcessing;
|
|
2898
|
+
const buffer = addToCurrentFrame ? toRun : toRunNextFrame;
|
|
2899
|
+
if (keepAlive)
|
|
2900
|
+
toKeepAlive.add(callback);
|
|
2901
|
+
// If the buffer doesn't already contain this callback, add it
|
|
2902
|
+
if (buffer.indexOf(callback) === -1) {
|
|
2903
|
+
buffer.push(callback);
|
|
2904
|
+
// If we're adding it to the currently running buffer, update its measured size
|
|
2905
|
+
if (addToCurrentFrame && isProcessing)
|
|
2906
|
+
numToRun = toRun.length;
|
|
2907
|
+
}
|
|
2908
|
+
return callback;
|
|
2909
|
+
},
|
|
2910
|
+
/**
|
|
2911
|
+
* Cancel the provided callback from running on the next frame.
|
|
2912
|
+
*/
|
|
2913
|
+
cancel: (callback) => {
|
|
2914
|
+
const index = toRunNextFrame.indexOf(callback);
|
|
2915
|
+
if (index !== -1)
|
|
2916
|
+
toRunNextFrame.splice(index, 1);
|
|
2917
|
+
toKeepAlive.delete(callback);
|
|
2918
|
+
},
|
|
2919
|
+
/**
|
|
2920
|
+
* Execute all schedule callbacks.
|
|
2921
|
+
*/
|
|
2922
|
+
process: (frameData) => {
|
|
2923
|
+
/**
|
|
2924
|
+
* If we're already processing we've probably been triggered by a flushSync
|
|
2925
|
+
* inside an existing process. Instead of executing, mark flushNextFrame
|
|
2926
|
+
* as true and ensure we flush the following frame at the end of this one.
|
|
2927
|
+
*/
|
|
2928
|
+
if (isProcessing) {
|
|
2929
|
+
flushNextFrame = true;
|
|
2930
|
+
return;
|
|
2931
|
+
}
|
|
2932
|
+
isProcessing = true;
|
|
2933
|
+
[toRun, toRunNextFrame] = [toRunNextFrame, toRun];
|
|
2934
|
+
// Clear the next frame list
|
|
2935
|
+
toRunNextFrame.length = 0;
|
|
2936
|
+
// Execute this frame
|
|
2937
|
+
numToRun = toRun.length;
|
|
2938
|
+
if (numToRun) {
|
|
2939
|
+
for (let i = 0; i < numToRun; i++) {
|
|
2940
|
+
const callback = toRun[i];
|
|
2941
|
+
callback(frameData);
|
|
2942
|
+
if (toKeepAlive.has(callback)) {
|
|
2943
|
+
step.schedule(callback);
|
|
2944
|
+
runNextFrame();
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
isProcessing = false;
|
|
2949
|
+
if (flushNextFrame) {
|
|
2950
|
+
flushNextFrame = false;
|
|
2951
|
+
step.process(frameData);
|
|
2952
|
+
}
|
|
2953
|
+
},
|
|
2954
|
+
};
|
|
2955
|
+
return step;
|
|
2956
|
+
}
|
|
2957
|
+
|
|
2958
|
+
const frameData = {
|
|
2959
|
+
delta: 0,
|
|
2960
|
+
timestamp: 0,
|
|
2961
|
+
};
|
|
2962
|
+
|
|
2963
|
+
const maxElapsed$1 = 40;
|
|
2964
|
+
let useDefaultElapsed = true;
|
|
2965
|
+
let runNextFrame = false;
|
|
2966
|
+
let isProcessing = false;
|
|
2967
|
+
const stepsOrder = [
|
|
2968
|
+
"read",
|
|
2969
|
+
"update",
|
|
2970
|
+
"preRender",
|
|
2971
|
+
"render",
|
|
2972
|
+
"postRender",
|
|
2973
|
+
];
|
|
2974
|
+
const steps = stepsOrder.reduce((acc, key) => {
|
|
2975
|
+
acc[key] = createRenderStep(() => (runNextFrame = true));
|
|
2976
|
+
return acc;
|
|
2977
|
+
}, {});
|
|
2978
|
+
const sync = stepsOrder.reduce((acc, key) => {
|
|
2979
|
+
const step = steps[key];
|
|
2980
|
+
acc[key] = (process, keepAlive = false, immediate = false) => {
|
|
2981
|
+
if (!runNextFrame)
|
|
2982
|
+
startLoop();
|
|
2983
|
+
return step.schedule(process, keepAlive, immediate);
|
|
2984
|
+
};
|
|
2985
|
+
return acc;
|
|
2986
|
+
}, {});
|
|
2987
|
+
const cancelSync = stepsOrder.reduce((acc, key) => {
|
|
2988
|
+
acc[key] = steps[key].cancel;
|
|
2989
|
+
return acc;
|
|
2990
|
+
}, {});
|
|
2991
|
+
const flushSync = stepsOrder.reduce((acc, key) => {
|
|
2992
|
+
acc[key] = () => steps[key].process(frameData);
|
|
2993
|
+
return acc;
|
|
2994
|
+
}, {});
|
|
2995
|
+
const processStep = (stepId) => steps[stepId].process(frameData);
|
|
2996
|
+
const processFrame = (timestamp) => {
|
|
2997
|
+
runNextFrame = false;
|
|
2998
|
+
frameData.delta = useDefaultElapsed
|
|
2999
|
+
? defaultTimestep
|
|
3000
|
+
: Math.max(Math.min(timestamp - frameData.timestamp, maxElapsed$1), 1);
|
|
3001
|
+
frameData.timestamp = timestamp;
|
|
3002
|
+
isProcessing = true;
|
|
3003
|
+
stepsOrder.forEach(processStep);
|
|
3004
|
+
isProcessing = false;
|
|
3005
|
+
if (runNextFrame) {
|
|
3006
|
+
useDefaultElapsed = false;
|
|
3007
|
+
onNextFrame(processFrame);
|
|
3008
|
+
}
|
|
3009
|
+
};
|
|
3010
|
+
const startLoop = () => {
|
|
3011
|
+
runNextFrame = true;
|
|
3012
|
+
useDefaultElapsed = true;
|
|
3013
|
+
if (!isProcessing)
|
|
3014
|
+
onNextFrame(processFrame);
|
|
3015
|
+
};
|
|
3016
|
+
|
|
3029
3017
|
const types = { decay, keyframes, spring };
|
|
3030
3018
|
function loopElapsed(elapsed, duration, delay = 0) {
|
|
3031
3019
|
return elapsed - duration - delay;
|
|
@@ -3094,7 +3082,7 @@
|
|
|
3094
3082
|
latest = interpolateFromNumber(latest);
|
|
3095
3083
|
isComplete = isForwardPlayback ? state.done : elapsed <= 0;
|
|
3096
3084
|
}
|
|
3097
|
-
onUpdate
|
|
3085
|
+
onUpdate && onUpdate(latest);
|
|
3098
3086
|
if (isComplete) {
|
|
3099
3087
|
if (repeatCount === 0) {
|
|
3100
3088
|
computedDuration =
|
|
@@ -3109,29 +3097,19 @@
|
|
|
3109
3097
|
}
|
|
3110
3098
|
}
|
|
3111
3099
|
function play() {
|
|
3112
|
-
onPlay
|
|
3100
|
+
onPlay && onPlay();
|
|
3113
3101
|
driverControls = driver(update);
|
|
3114
3102
|
driverControls.start();
|
|
3115
3103
|
}
|
|
3116
3104
|
autoplay && play();
|
|
3117
3105
|
return {
|
|
3118
3106
|
stop: () => {
|
|
3119
|
-
onStop
|
|
3107
|
+
onStop && onStop();
|
|
3120
3108
|
driverControls.stop();
|
|
3121
3109
|
},
|
|
3122
3110
|
};
|
|
3123
3111
|
}
|
|
3124
3112
|
|
|
3125
|
-
/*
|
|
3126
|
-
Convert velocity into velocity per second
|
|
3127
|
-
|
|
3128
|
-
@param [number]: Unit per frame
|
|
3129
|
-
@param [number]: Frame duration in ms
|
|
3130
|
-
*/
|
|
3131
|
-
function velocityPerSecond$1(velocity, frameDuration) {
|
|
3132
|
-
return frameDuration ? velocity * (1000 / frameDuration) : 0;
|
|
3133
|
-
}
|
|
3134
|
-
|
|
3135
3113
|
function inertia({ from = 0, velocity = 0, min, max, power = 0.8, timeConstant = 750, bounceStiffness = 500, bounceDamping = 10, restDelta = 1, modifyTarget, driver, onUpdate, onComplete, onStop, }) {
|
|
3136
3114
|
let currentAnimation;
|
|
3137
3115
|
function isOutOfBounds(v) {
|
|
@@ -3212,6 +3190,22 @@
|
|
|
3212
3190
|
};
|
|
3213
3191
|
}
|
|
3214
3192
|
|
|
3193
|
+
/**
|
|
3194
|
+
* Timeout defined in ms
|
|
3195
|
+
*/
|
|
3196
|
+
function delay(callback, timeout) {
|
|
3197
|
+
const start = performance.now();
|
|
3198
|
+
const checkElapsed = ({ timestamp }) => {
|
|
3199
|
+
const elapsed = timestamp - start;
|
|
3200
|
+
if (elapsed >= timeout) {
|
|
3201
|
+
cancelSync.read(checkElapsed);
|
|
3202
|
+
callback(elapsed - timeout);
|
|
3203
|
+
}
|
|
3204
|
+
};
|
|
3205
|
+
sync.read(checkElapsed, true);
|
|
3206
|
+
return () => cancelSync.read(checkElapsed);
|
|
3207
|
+
}
|
|
3208
|
+
|
|
3215
3209
|
/**
|
|
3216
3210
|
* Decide whether a transition is defined on a given Transition.
|
|
3217
3211
|
* This filters out orchestration options and returns true
|
|
@@ -3298,6 +3292,9 @@
|
|
|
3298
3292
|
*/
|
|
3299
3293
|
function getAnimation(key, value, target, transition, onComplete) {
|
|
3300
3294
|
const valueTransition = getValueTransition(transition, key) || {};
|
|
3295
|
+
const { elapsed = 0 } = transition;
|
|
3296
|
+
valueTransition.elapsed =
|
|
3297
|
+
elapsed - secondsToMilliseconds(transition.delay || 0);
|
|
3301
3298
|
let origin = valueTransition.from !== undefined ? valueTransition.from : value.get();
|
|
3302
3299
|
const isTargetAnimatable = isAnimatable(key, target);
|
|
3303
3300
|
if (origin === "none" && isTargetAnimatable && typeof target === "string") {
|
|
@@ -3325,20 +3322,23 @@
|
|
|
3325
3322
|
onComplete,
|
|
3326
3323
|
onUpdate: (v) => value.set(v),
|
|
3327
3324
|
};
|
|
3328
|
-
|
|
3325
|
+
const animation = valueTransition.type === "inertia" ||
|
|
3329
3326
|
valueTransition.type === "decay"
|
|
3330
3327
|
? inertia({ ...options, ...valueTransition })
|
|
3331
3328
|
: animate$1({
|
|
3332
3329
|
...getPopmotionAnimationOptions(valueTransition, options, key),
|
|
3333
3330
|
onUpdate: (v) => {
|
|
3334
3331
|
options.onUpdate(v);
|
|
3335
|
-
valueTransition.onUpdate &&
|
|
3332
|
+
valueTransition.onUpdate &&
|
|
3333
|
+
valueTransition.onUpdate(v);
|
|
3336
3334
|
},
|
|
3337
3335
|
onComplete: () => {
|
|
3338
3336
|
options.onComplete();
|
|
3339
|
-
valueTransition.onComplete &&
|
|
3337
|
+
valueTransition.onComplete &&
|
|
3338
|
+
valueTransition.onComplete();
|
|
3340
3339
|
},
|
|
3341
3340
|
});
|
|
3341
|
+
return () => animation.stop();
|
|
3342
3342
|
}
|
|
3343
3343
|
function set() {
|
|
3344
3344
|
const finalTarget = resolveFinalValueInKeyframes(target);
|
|
@@ -3346,13 +3346,16 @@
|
|
|
3346
3346
|
onComplete();
|
|
3347
3347
|
valueTransition.onUpdate && valueTransition.onUpdate(finalTarget);
|
|
3348
3348
|
valueTransition.onComplete && valueTransition.onComplete();
|
|
3349
|
-
return
|
|
3349
|
+
return () => { };
|
|
3350
3350
|
}
|
|
3351
|
-
|
|
3351
|
+
const useInstantAnimation = !isOriginAnimatable ||
|
|
3352
3352
|
!isTargetAnimatable ||
|
|
3353
|
-
valueTransition.type === false
|
|
3354
|
-
|
|
3355
|
-
|
|
3353
|
+
valueTransition.type === false;
|
|
3354
|
+
return useInstantAnimation
|
|
3355
|
+
? valueTransition.elapsed
|
|
3356
|
+
? () => delay(set, -valueTransition.elapsed)
|
|
3357
|
+
: set()
|
|
3358
|
+
: start();
|
|
3356
3359
|
}
|
|
3357
3360
|
function isZero(value) {
|
|
3358
3361
|
return (value === 0 ||
|
|
@@ -3377,21 +3380,7 @@
|
|
|
3377
3380
|
transition = { type: false };
|
|
3378
3381
|
}
|
|
3379
3382
|
return value.start((onComplete) => {
|
|
3380
|
-
|
|
3381
|
-
const animation = getAnimation(key, value, target, transition, onComplete);
|
|
3382
|
-
const delayBy = getDelayFromTransition(transition, key);
|
|
3383
|
-
const start = () => (controls = animation());
|
|
3384
|
-
let cancelDelay;
|
|
3385
|
-
if (delayBy) {
|
|
3386
|
-
cancelDelay = delay(start, secondsToMilliseconds(delayBy));
|
|
3387
|
-
}
|
|
3388
|
-
else {
|
|
3389
|
-
start();
|
|
3390
|
-
}
|
|
3391
|
-
return () => {
|
|
3392
|
-
cancelDelay && cancelDelay();
|
|
3393
|
-
controls && controls.stop();
|
|
3394
|
-
};
|
|
3383
|
+
return getAnimation(key, value, target, { ...transition, delay: getDelayFromTransition(transition, key) }, onComplete);
|
|
3395
3384
|
});
|
|
3396
3385
|
}
|
|
3397
3386
|
|
|
@@ -3484,7 +3473,7 @@
|
|
|
3484
3473
|
* This will be replaced by the build step with the latest version number.
|
|
3485
3474
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
3486
3475
|
*/
|
|
3487
|
-
this.version = "7.
|
|
3476
|
+
this.version = "7.8.0";
|
|
3488
3477
|
/**
|
|
3489
3478
|
* Duration, in milliseconds, since last updating frame.
|
|
3490
3479
|
*
|
|
@@ -3927,6 +3916,40 @@
|
|
|
3927
3916
|
return Boolean(isMotionValue(value) && value.add);
|
|
3928
3917
|
}
|
|
3929
3918
|
|
|
3919
|
+
const appearStoreId = (id, value) => `${id}: ${value}`;
|
|
3920
|
+
|
|
3921
|
+
function handoffOptimizedAppearAnimation(id, name) {
|
|
3922
|
+
const { MotionAppearAnimations } = window;
|
|
3923
|
+
const animationId = appearStoreId(id, transformProps.has(name) ? "transform" : name);
|
|
3924
|
+
const animation = MotionAppearAnimations && MotionAppearAnimations.get(animationId);
|
|
3925
|
+
if (animation) {
|
|
3926
|
+
/**
|
|
3927
|
+
* We allow the animation to persist until the next frame:
|
|
3928
|
+
* 1. So it continues to play until Framer Motion is ready to render
|
|
3929
|
+
* (avoiding a potential flash of the element's original state)
|
|
3930
|
+
* 2. As all independent transforms share a single transform animation, stopping
|
|
3931
|
+
* it synchronously would prevent subsequent transforms from handing off.
|
|
3932
|
+
*/
|
|
3933
|
+
sync.render(() => {
|
|
3934
|
+
/**
|
|
3935
|
+
* Animation.cancel() throws so it needs to be wrapped in a try/catch
|
|
3936
|
+
*/
|
|
3937
|
+
try {
|
|
3938
|
+
animation.cancel();
|
|
3939
|
+
MotionAppearAnimations.delete(animationId);
|
|
3940
|
+
}
|
|
3941
|
+
catch (e) { }
|
|
3942
|
+
});
|
|
3943
|
+
return animation.currentTime || 0;
|
|
3944
|
+
}
|
|
3945
|
+
else {
|
|
3946
|
+
return 0;
|
|
3947
|
+
}
|
|
3948
|
+
}
|
|
3949
|
+
|
|
3950
|
+
const optimizedAppearDataId = "framerAppearId";
|
|
3951
|
+
const optimizedAppearDataAttribute = "data-" + camelToDash(optimizedAppearDataId);
|
|
3952
|
+
|
|
3930
3953
|
function animateVisualElement(visualElement, definition, options = {}) {
|
|
3931
3954
|
visualElement.notify("AnimationStart", definition);
|
|
3932
3955
|
let animation;
|
|
@@ -4004,7 +4027,7 @@
|
|
|
4004
4027
|
shouldBlockAnimation(animationTypeState, key))) {
|
|
4005
4028
|
continue;
|
|
4006
4029
|
}
|
|
4007
|
-
let valueTransition = { delay, ...transition };
|
|
4030
|
+
let valueTransition = { delay, elapsed: 0, ...transition };
|
|
4008
4031
|
/**
|
|
4009
4032
|
* Make animation instant if this is a transform prop and we should reduce motion.
|
|
4010
4033
|
*/
|
|
@@ -4015,6 +4038,16 @@
|
|
|
4015
4038
|
delay: 0,
|
|
4016
4039
|
};
|
|
4017
4040
|
}
|
|
4041
|
+
/**
|
|
4042
|
+
* If this is the first time a value is being animated, check
|
|
4043
|
+
* to see if we're handling off from an existing animation.
|
|
4044
|
+
*/
|
|
4045
|
+
if (!value.hasAnimated) {
|
|
4046
|
+
const appearId = visualElement.getProps()[optimizedAppearDataAttribute];
|
|
4047
|
+
if (appearId) {
|
|
4048
|
+
valueTransition.elapsed = handoffOptimizedAppearAnimation(appearId, key);
|
|
4049
|
+
}
|
|
4050
|
+
}
|
|
4018
4051
|
let animation = startAnimation(key, value, valueTarget, valueTransition);
|
|
4019
4052
|
if (isWillChangeMotionValue(willChange)) {
|
|
4020
4053
|
willChange.add(key);
|
|
@@ -5766,7 +5799,7 @@
|
|
|
5766
5799
|
* and warn against mismatches.
|
|
5767
5800
|
*/
|
|
5768
5801
|
{
|
|
5769
|
-
warnOnce(nextValue.version === "7.
|
|
5802
|
+
warnOnce(nextValue.version === "7.8.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.8.0 may not work as expected.`);
|
|
5770
5803
|
}
|
|
5771
5804
|
}
|
|
5772
5805
|
else if (isMotionValue(prevValue)) {
|
|
@@ -10194,6 +10227,46 @@
|
|
|
10194
10227
|
return reset;
|
|
10195
10228
|
}
|
|
10196
10229
|
|
|
10230
|
+
const featureTests = {
|
|
10231
|
+
waapi: () => Object.hasOwnProperty.call(Element.prototype, "animate"),
|
|
10232
|
+
};
|
|
10233
|
+
const results = {};
|
|
10234
|
+
const supports = {};
|
|
10235
|
+
/**
|
|
10236
|
+
* Generate features tests that cache their results.
|
|
10237
|
+
*/
|
|
10238
|
+
for (const key in featureTests) {
|
|
10239
|
+
supports[key] = () => {
|
|
10240
|
+
if (results[key] === undefined)
|
|
10241
|
+
results[key] = featureTests[key]();
|
|
10242
|
+
return results[key];
|
|
10243
|
+
};
|
|
10244
|
+
}
|
|
10245
|
+
|
|
10246
|
+
const cubicBezierAsString = ([a, b, c, d]) => `cubic-bezier(${a}, ${b}, ${c}, ${d})`;
|
|
10247
|
+
|
|
10248
|
+
function animateStyle(element, valueName, keyframes, { delay, duration, ease }) {
|
|
10249
|
+
if (!supports.waapi())
|
|
10250
|
+
return undefined;
|
|
10251
|
+
const animation = element.animate({ [valueName]: keyframes }, {
|
|
10252
|
+
delay,
|
|
10253
|
+
duration,
|
|
10254
|
+
easing: Array.isArray(ease) ? cubicBezierAsString(ease) : ease,
|
|
10255
|
+
fill: "both",
|
|
10256
|
+
});
|
|
10257
|
+
return animation;
|
|
10258
|
+
}
|
|
10259
|
+
|
|
10260
|
+
function startOptimizedAppearAnimation(element, name, keyframes, options) {
|
|
10261
|
+
window.MotionAppearAnimations || (window.MotionAppearAnimations = new Map());
|
|
10262
|
+
const id = element.dataset[optimizedAppearDataId];
|
|
10263
|
+
const animation = animateStyle(element, name, keyframes, options);
|
|
10264
|
+
if (id && animation) {
|
|
10265
|
+
window.MotionAppearAnimations.set(appearStoreId(id, name), animation);
|
|
10266
|
+
}
|
|
10267
|
+
return animation;
|
|
10268
|
+
}
|
|
10269
|
+
|
|
10197
10270
|
const createObject = () => ({});
|
|
10198
10271
|
class StateVisualElement extends VisualElement {
|
|
10199
10272
|
build() { }
|
|
@@ -10343,8 +10416,11 @@
|
|
|
10343
10416
|
exports.mix = mix$1;
|
|
10344
10417
|
exports.motion = motion;
|
|
10345
10418
|
exports.motionValue = motionValue;
|
|
10419
|
+
exports.optimizedAppearDataAttribute = optimizedAppearDataAttribute;
|
|
10346
10420
|
exports.pipe = pipe;
|
|
10347
10421
|
exports.resolveMotionValue = resolveMotionValue;
|
|
10422
|
+
exports.spring = spring;
|
|
10423
|
+
exports.startOptimizedAppearAnimation = startOptimizedAppearAnimation;
|
|
10348
10424
|
exports.transform = transform;
|
|
10349
10425
|
exports.unwrapMotionComponent = unwrapMotionComponent;
|
|
10350
10426
|
exports.useAnimation = useAnimation;
|