framer-motion 11.3.22 → 11.3.23-alpha.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/dom-entry.js +11 -8
- package/dist/cjs/index.js +79 -77
- package/dist/dom-entry.d.ts +9 -4
- package/dist/dom.js +1 -1
- package/dist/es/animation/animators/MainThreadAnimation.mjs +2 -2
- package/dist/es/animation/interfaces/visual-element-target.mjs +7 -4
- package/dist/es/animation/optimized-appear/handoff.mjs +16 -42
- package/dist/es/animation/optimized-appear/start.mjs +35 -12
- package/dist/es/animation/optimized-appear/store.mjs +2 -1
- package/dist/es/motion/utils/use-visual-element.mjs +11 -10
- package/dist/es/projection/node/create-projection-node.mjs +6 -6
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/value/index.mjs +1 -1
- package/dist/framer-motion.dev.js +79 -77
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +10 -4
- package/package.json +2 -2
package/dist/cjs/dom-entry.js
CHANGED
|
@@ -279,7 +279,7 @@ class MotionValue {
|
|
|
279
279
|
* This will be replaced by the build step with the latest version number.
|
|
280
280
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
281
281
|
*/
|
|
282
|
-
this.version = "11.3.
|
|
282
|
+
this.version = "11.3.23-alpha.0";
|
|
283
283
|
/**
|
|
284
284
|
* Tracks whether this value can output a velocity. Currently this is only true
|
|
285
285
|
* if the value is numerical, but we might be able to widen the scope here and support
|
|
@@ -2885,7 +2885,7 @@ class MainThreadAnimation extends BaseAnimation {
|
|
|
2885
2885
|
}
|
|
2886
2886
|
if (this.isStopped)
|
|
2887
2887
|
return;
|
|
2888
|
-
const { driver = frameloopDriver, onPlay } = this.options;
|
|
2888
|
+
const { driver = frameloopDriver, onPlay, startTime } = this.options;
|
|
2889
2889
|
if (!this.driver) {
|
|
2890
2890
|
this.driver = driver((timestamp) => this.tick(timestamp));
|
|
2891
2891
|
}
|
|
@@ -2895,7 +2895,7 @@ class MainThreadAnimation extends BaseAnimation {
|
|
|
2895
2895
|
this.startTime = now - this.holdTime;
|
|
2896
2896
|
}
|
|
2897
2897
|
else if (!this.startTime || this.state === "finished") {
|
|
2898
|
-
this.startTime = now;
|
|
2898
|
+
this.startTime = startTime || now;
|
|
2899
2899
|
}
|
|
2900
2900
|
if (this.state === "finished") {
|
|
2901
2901
|
this.updateFinishedPromise();
|
|
@@ -3606,13 +3606,16 @@ function animateTarget(visualElement, targetAndTransition, { delay = 0, transiti
|
|
|
3606
3606
|
* to see if we're handling off from an existing animation.
|
|
3607
3607
|
*/
|
|
3608
3608
|
let isHandoff = false;
|
|
3609
|
-
if (window.
|
|
3609
|
+
if (window.MotionHandoffAnimation) {
|
|
3610
3610
|
const appearId = getOptimisedAppearId(visualElement);
|
|
3611
3611
|
if (appearId) {
|
|
3612
|
-
const
|
|
3613
|
-
if (
|
|
3614
|
-
valueTransition.elapsed = elapsed;
|
|
3612
|
+
const handoffInfo = window.MotionHandoffAnimation(appearId, key, frame);
|
|
3613
|
+
if (handoffInfo !== null) {
|
|
3615
3614
|
isHandoff = true;
|
|
3615
|
+
const { elapsed, startTime } = handoffInfo;
|
|
3616
|
+
valueTransition.elapsed = elapsed;
|
|
3617
|
+
if (startTime)
|
|
3618
|
+
valueTransition.startTime = startTime;
|
|
3616
3619
|
}
|
|
3617
3620
|
}
|
|
3618
3621
|
}
|
|
@@ -3752,7 +3755,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
3752
3755
|
* and warn against mismatches.
|
|
3753
3756
|
*/
|
|
3754
3757
|
if (process.env.NODE_ENV === "development") {
|
|
3755
|
-
warnOnce(nextValue.version === "11.3.
|
|
3758
|
+
warnOnce(nextValue.version === "11.3.23-alpha.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.3.23-alpha.0 may not work as expected.`);
|
|
3756
3759
|
}
|
|
3757
3760
|
}
|
|
3758
3761
|
else if (isMotionValue(prevValue)) {
|
package/dist/cjs/index.js
CHANGED
|
@@ -223,6 +223,7 @@ const SwitchLayoutGroupContext = React.createContext({});
|
|
|
223
223
|
|
|
224
224
|
let scheduleHandoffComplete = false;
|
|
225
225
|
function useVisualElement(Component, visualState, props, createVisualElement, ProjectionNodeConstructor) {
|
|
226
|
+
var _a;
|
|
226
227
|
const { visualElement: parent } = React.useContext(MotionContext);
|
|
227
228
|
const lazyContext = React.useContext(LazyContext);
|
|
228
229
|
const presenceContext = React.useContext(PresenceContext);
|
|
@@ -263,8 +264,10 @@ function useVisualElement(Component, visualState, props, createVisualElement, Pr
|
|
|
263
264
|
* Cache this value as we want to know whether HandoffAppearAnimations
|
|
264
265
|
* was present on initial render - it will be deleted after this.
|
|
265
266
|
*/
|
|
266
|
-
const
|
|
267
|
-
|
|
267
|
+
const optimisedAppearId = props[optimizedAppearDataAttribute];
|
|
268
|
+
const wantsHandoff = React.useRef(Boolean(optimisedAppearId) &&
|
|
269
|
+
!window.MotionHandoffIsComplete &&
|
|
270
|
+
((_a = window.MotionHasOptimisedAnimation) === null || _a === void 0 ? void 0 : _a.call(window, optimisedAppearId)));
|
|
268
271
|
useIsomorphicLayoutEffect(() => {
|
|
269
272
|
if (!visualElement)
|
|
270
273
|
return;
|
|
@@ -290,19 +293,17 @@ function useVisualElement(Component, visualState, props, createVisualElement, Pr
|
|
|
290
293
|
if (!wantsHandoff.current && visualElement.animationState) {
|
|
291
294
|
visualElement.animationState.animateChanges();
|
|
292
295
|
}
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
queueMicrotask(completeHandoff);
|
|
299
|
-
}
|
|
296
|
+
wantsHandoff.current = false;
|
|
297
|
+
// This ensures all future calls to animateChanges() will run in useEffect
|
|
298
|
+
if (!scheduleHandoffComplete) {
|
|
299
|
+
scheduleHandoffComplete = true;
|
|
300
|
+
queueMicrotask(completeHandoff);
|
|
300
301
|
}
|
|
301
302
|
});
|
|
302
303
|
return visualElement;
|
|
303
304
|
}
|
|
304
305
|
function completeHandoff() {
|
|
305
|
-
window.
|
|
306
|
+
window.MotionHandoffIsComplete = true;
|
|
306
307
|
}
|
|
307
308
|
function createProjectionNode$1(visualElement, props, ProjectionNodeConstructor, initialPromotionConfig) {
|
|
308
309
|
const { layoutId, layout, drag, dragConstraints, layoutScroll, layoutRoot, } = props;
|
|
@@ -4134,7 +4135,7 @@ class MainThreadAnimation extends BaseAnimation {
|
|
|
4134
4135
|
}
|
|
4135
4136
|
if (this.isStopped)
|
|
4136
4137
|
return;
|
|
4137
|
-
const { driver = frameloopDriver, onPlay } = this.options;
|
|
4138
|
+
const { driver = frameloopDriver, onPlay, startTime } = this.options;
|
|
4138
4139
|
if (!this.driver) {
|
|
4139
4140
|
this.driver = driver((timestamp) => this.tick(timestamp));
|
|
4140
4141
|
}
|
|
@@ -4144,7 +4145,7 @@ class MainThreadAnimation extends BaseAnimation {
|
|
|
4144
4145
|
this.startTime = now - this.holdTime;
|
|
4145
4146
|
}
|
|
4146
4147
|
else if (!this.startTime || this.state === "finished") {
|
|
4147
|
-
this.startTime = now;
|
|
4148
|
+
this.startTime = startTime || now;
|
|
4148
4149
|
}
|
|
4149
4150
|
if (this.state === "finished") {
|
|
4150
4151
|
this.updateFinishedPromise();
|
|
@@ -4822,7 +4823,7 @@ class MotionValue {
|
|
|
4822
4823
|
* This will be replaced by the build step with the latest version number.
|
|
4823
4824
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
4824
4825
|
*/
|
|
4825
|
-
this.version = "11.3.
|
|
4826
|
+
this.version = "11.3.23-alpha.0";
|
|
4826
4827
|
/**
|
|
4827
4828
|
* Tracks whether this value can output a velocity. Currently this is only true
|
|
4828
4829
|
* if the value is numerical, but we might be able to widen the scope here and support
|
|
@@ -5236,13 +5237,16 @@ function animateTarget(visualElement, targetAndTransition, { delay = 0, transiti
|
|
|
5236
5237
|
* to see if we're handling off from an existing animation.
|
|
5237
5238
|
*/
|
|
5238
5239
|
let isHandoff = false;
|
|
5239
|
-
if (window.
|
|
5240
|
+
if (window.MotionHandoffAnimation) {
|
|
5240
5241
|
const appearId = getOptimisedAppearId(visualElement);
|
|
5241
5242
|
if (appearId) {
|
|
5242
|
-
const
|
|
5243
|
-
if (
|
|
5244
|
-
valueTransition.elapsed = elapsed;
|
|
5243
|
+
const handoffInfo = window.MotionHandoffAnimation(appearId, key, frame);
|
|
5244
|
+
if (handoffInfo !== null) {
|
|
5245
5245
|
isHandoff = true;
|
|
5246
|
+
const { elapsed, startTime } = handoffInfo;
|
|
5247
|
+
valueTransition.elapsed = elapsed;
|
|
5248
|
+
if (startTime)
|
|
5249
|
+
valueTransition.startTime = startTime;
|
|
5246
5250
|
}
|
|
5247
5251
|
}
|
|
5248
5252
|
}
|
|
@@ -7284,7 +7288,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
7284
7288
|
* and warn against mismatches.
|
|
7285
7289
|
*/
|
|
7286
7290
|
if (process.env.NODE_ENV === "development") {
|
|
7287
|
-
warnOnce(nextValue.version === "11.3.
|
|
7291
|
+
warnOnce(nextValue.version === "11.3.23-alpha.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.3.23-alpha.0 may not work as expected.`);
|
|
7288
7292
|
}
|
|
7289
7293
|
}
|
|
7290
7294
|
else if (isMotionValue(prevValue)) {
|
|
@@ -8926,7 +8930,7 @@ function resetDistortingTransform(key, visualElement, values, sharedAnimationVal
|
|
|
8926
8930
|
}
|
|
8927
8931
|
}
|
|
8928
8932
|
}
|
|
8929
|
-
function
|
|
8933
|
+
function isOptimisedTransformAnimationInTree(projectionNode) {
|
|
8930
8934
|
projectionNode.hasCheckedOptimisedAppear = true;
|
|
8931
8935
|
if (projectionNode.root === projectionNode)
|
|
8932
8936
|
return false;
|
|
@@ -8934,12 +8938,12 @@ function isOptimisedAppearTree(projectionNode) {
|
|
|
8934
8938
|
if (!visualElement) {
|
|
8935
8939
|
return false;
|
|
8936
8940
|
}
|
|
8937
|
-
else if (getOptimisedAppearId(visualElement)) {
|
|
8941
|
+
else if (window.MotionHasOptimisedTransformAnimation(getOptimisedAppearId(visualElement))) {
|
|
8938
8942
|
return true;
|
|
8939
8943
|
}
|
|
8940
8944
|
else if (projectionNode.parent &&
|
|
8941
8945
|
!projectionNode.parent.hasCheckedOptimisedAppear) {
|
|
8942
|
-
return
|
|
8946
|
+
return isOptimisedTransformAnimationInTree(projectionNode.parent);
|
|
8943
8947
|
}
|
|
8944
8948
|
else {
|
|
8945
8949
|
return false;
|
|
@@ -9266,9 +9270,9 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
9266
9270
|
* snapshots in startUpdate(), but we only want to cancel optimised animations
|
|
9267
9271
|
* if a layout animation measurement is actually going to be affected by them.
|
|
9268
9272
|
*/
|
|
9269
|
-
if (window.
|
|
9270
|
-
|
|
9271
|
-
window.
|
|
9273
|
+
if (window.MotionHandoffCancelAll &&
|
|
9274
|
+
isOptimisedTransformAnimationInTree(this)) {
|
|
9275
|
+
window.MotionHandoffCancelAll();
|
|
9272
9276
|
}
|
|
9273
9277
|
!this.root.isUpdating && this.root.startUpdate();
|
|
9274
9278
|
if (this.isLayoutDirty)
|
|
@@ -12152,16 +12156,10 @@ function useResetProjection() {
|
|
|
12152
12156
|
const appearStoreId = (id, value) => `${id}: ${value}`;
|
|
12153
12157
|
|
|
12154
12158
|
const appearAnimationStore = new Map();
|
|
12159
|
+
const elementsWithAppearAnimations = new Set();
|
|
12155
12160
|
|
|
12156
12161
|
let handoffFrameTime;
|
|
12157
|
-
function handoffOptimizedAppearAnimation(elementId, valueName,
|
|
12158
|
-
/**
|
|
12159
|
-
* Legacy arguments. This function is inlined as part of SSG so it can be there's
|
|
12160
|
-
* a version mismatch between the main included Motion and the inlined script.
|
|
12161
|
-
*
|
|
12162
|
-
* Remove in early 2024.
|
|
12163
|
-
*/
|
|
12164
|
-
_value, frame) {
|
|
12162
|
+
function handoffOptimizedAppearAnimation(elementId, valueName, frame) {
|
|
12165
12163
|
const optimisedValueName = transformProps.has(valueName)
|
|
12166
12164
|
? "transform"
|
|
12167
12165
|
: valueName;
|
|
@@ -12171,48 +12169,26 @@ _value, frame) {
|
|
|
12171
12169
|
return null;
|
|
12172
12170
|
}
|
|
12173
12171
|
const { animation, startTime } = optimisedAnimation;
|
|
12174
|
-
|
|
12172
|
+
if (startTime === null || window.MotionHandoffIsComplete) {
|
|
12173
|
+
/**
|
|
12174
|
+
* If the startTime is null, this animation is the Paint Ready detection animation
|
|
12175
|
+
* and we can cancel it immediately without handoff.
|
|
12176
|
+
*
|
|
12177
|
+
* Or if we've already handed off the animation then we're now interrupting it.
|
|
12178
|
+
* In which case we need to cancel it.
|
|
12179
|
+
*/
|
|
12175
12180
|
appearAnimationStore.delete(storeId);
|
|
12176
|
-
|
|
12177
|
-
/**
|
|
12178
|
-
* If we've been provided the frameloop as an argument, use it to defer
|
|
12179
|
-
* cancellation until keyframes of the subsequent animation have been resolved.
|
|
12180
|
-
* This "papers over" a gap where the JS animations haven't rendered with
|
|
12181
|
-
* the latest time after a potential heavy blocking workload.
|
|
12182
|
-
* Otherwise cancel immediately.
|
|
12183
|
-
*
|
|
12184
|
-
* This is an optional dependency to deal with the fact that this inline
|
|
12185
|
-
* script and the library can be version sharded, and there have been
|
|
12186
|
-
* times when this isn't provided as an argument.
|
|
12187
|
-
*/
|
|
12188
|
-
frame.render(() => frame.render(() => {
|
|
12189
|
-
try {
|
|
12190
|
-
animation.cancel();
|
|
12191
|
-
}
|
|
12192
|
-
catch (error) { }
|
|
12193
|
-
}));
|
|
12194
|
-
}
|
|
12195
|
-
else {
|
|
12181
|
+
frame.render(() => frame.render(() => {
|
|
12196
12182
|
try {
|
|
12197
12183
|
animation.cancel();
|
|
12198
12184
|
}
|
|
12199
12185
|
catch (error) { }
|
|
12200
|
-
}
|
|
12201
|
-
};
|
|
12202
|
-
/**
|
|
12203
|
-
* If the startTime is null, this animation is the Paint Ready detection animation
|
|
12204
|
-
* and we can cancel it immediately without handoff.
|
|
12205
|
-
*
|
|
12206
|
-
* Or if we've already handed off the animation then we're now interrupting it.
|
|
12207
|
-
* In which case we need to cancel it.
|
|
12208
|
-
*/
|
|
12209
|
-
if (startTime === null || window.HandoffComplete) {
|
|
12210
|
-
cancelAnimation();
|
|
12186
|
+
}));
|
|
12211
12187
|
return null;
|
|
12212
12188
|
}
|
|
12213
12189
|
else {
|
|
12214
12190
|
/**
|
|
12215
|
-
* Otherwise we're
|
|
12191
|
+
* Otherwise we're starting a main thread animation.
|
|
12216
12192
|
*
|
|
12217
12193
|
* Record the time of the first handoff. We call performance.now() once
|
|
12218
12194
|
* here and once in startOptimisedAnimation to ensure we're getting
|
|
@@ -12227,7 +12203,10 @@ _value, frame) {
|
|
|
12227
12203
|
* an updated value for several frames, even as the animation plays smoothly via
|
|
12228
12204
|
* the GPU.
|
|
12229
12205
|
*/
|
|
12230
|
-
return
|
|
12206
|
+
return {
|
|
12207
|
+
elapsed: handoffFrameTime - startTime || 0,
|
|
12208
|
+
startTime: handoffFrameTime || 0,
|
|
12209
|
+
};
|
|
12231
12210
|
}
|
|
12232
12211
|
}
|
|
12233
12212
|
|
|
@@ -12246,14 +12225,14 @@ let startFrameTime;
|
|
|
12246
12225
|
let readyAnimation;
|
|
12247
12226
|
function startOptimizedAppearAnimation(element, name, keyframes, options, onReady) {
|
|
12248
12227
|
// Prevent optimised appear animations if Motion has already started animating.
|
|
12249
|
-
if (window.
|
|
12250
|
-
window.
|
|
12228
|
+
if (window.MotionHandoffIsComplete) {
|
|
12229
|
+
window.MotionHandoffAnimation = undefined;
|
|
12251
12230
|
return;
|
|
12252
12231
|
}
|
|
12253
12232
|
const id = element.dataset[optimizedAppearDataId];
|
|
12254
12233
|
if (!id)
|
|
12255
12234
|
return;
|
|
12256
|
-
window.
|
|
12235
|
+
window.MotionHandoffAnimation = handoffOptimizedAppearAnimation;
|
|
12257
12236
|
const storeId = appearStoreId(id, name);
|
|
12258
12237
|
if (!readyAnimation) {
|
|
12259
12238
|
readyAnimation = animateStyle(element, name, [keyframes[0], keyframes[0]],
|
|
@@ -12266,15 +12245,37 @@ function startOptimizedAppearAnimation(element, name, keyframes, options, onRead
|
|
|
12266
12245
|
animation: readyAnimation,
|
|
12267
12246
|
startTime: null,
|
|
12268
12247
|
});
|
|
12269
|
-
|
|
12270
|
-
|
|
12271
|
-
|
|
12248
|
+
/**
|
|
12249
|
+
* If there's no readyAnimation then there's been no instantiation
|
|
12250
|
+
* of handoff animations.
|
|
12251
|
+
*/
|
|
12252
|
+
window.MotionHandoffAnimation = handoffOptimizedAppearAnimation;
|
|
12253
|
+
/**
|
|
12254
|
+
* We only need to cancel transform animations as
|
|
12255
|
+
* they're the ones that will interfere with the
|
|
12256
|
+
* layout animation measurements.
|
|
12257
|
+
*/
|
|
12258
|
+
window.MotionHandoffCancelAll = () => {
|
|
12259
|
+
appearAnimationStore.forEach(({ animation }, animationId) => {
|
|
12260
|
+
if (animationId.endsWith("transform")) {
|
|
12272
12261
|
animation.cancel();
|
|
12273
|
-
|
|
12274
|
-
|
|
12275
|
-
|
|
12276
|
-
|
|
12277
|
-
}
|
|
12262
|
+
appearAnimationStore.delete(animationId);
|
|
12263
|
+
}
|
|
12264
|
+
});
|
|
12265
|
+
window.MotionHandoffCancelAll = undefined;
|
|
12266
|
+
};
|
|
12267
|
+
/**
|
|
12268
|
+
* Keep a map of elementIds that have started animating. We check
|
|
12269
|
+
* via ID instead of Element because of hydration errors and
|
|
12270
|
+
* pre-hydration checks. We also actively record IDs as they start
|
|
12271
|
+
* animating rather than simply checking for data-appear-id as
|
|
12272
|
+
* this attrbute might be present but not lead to an animation, for
|
|
12273
|
+
* instance if the element's appear animation is on a different
|
|
12274
|
+
* breakpoint.
|
|
12275
|
+
*/
|
|
12276
|
+
window.MotionHasOptimisedAnimation = (elementId) => Boolean(elementId && elementsWithAppearAnimations.has(elementId));
|
|
12277
|
+
window.MotionHasOptimisedTransformAnimation = (elementId) => Boolean(elementId &&
|
|
12278
|
+
appearAnimationStore.has(appearStoreId(elementId, "transform")));
|
|
12278
12279
|
}
|
|
12279
12280
|
const startAnimation = () => {
|
|
12280
12281
|
readyAnimation.cancel();
|
|
@@ -12295,6 +12296,7 @@ function startOptimizedAppearAnimation(element, name, keyframes, options, onRead
|
|
|
12295
12296
|
if (onReady)
|
|
12296
12297
|
onReady(appearAnimation);
|
|
12297
12298
|
};
|
|
12299
|
+
elementsWithAppearAnimations.add(id);
|
|
12298
12300
|
if (readyAnimation.ready) {
|
|
12299
12301
|
readyAnimation.ready.then(startAnimation).catch(noop);
|
|
12300
12302
|
}
|
package/dist/dom-entry.d.ts
CHANGED
|
@@ -852,16 +852,21 @@ interface FrameData {
|
|
|
852
852
|
isProcessing: boolean;
|
|
853
853
|
}
|
|
854
854
|
|
|
855
|
-
type HandoffFunction = (storeId: string, valueName: string,
|
|
855
|
+
type HandoffFunction = (storeId: string, valueName: string, frame: Batcher) => null | {
|
|
856
|
+
elapsed: number;
|
|
857
|
+
startTime: number;
|
|
858
|
+
};
|
|
856
859
|
/**
|
|
857
860
|
* The window global object acts as a bridge between our inline script
|
|
858
861
|
* triggering the optimized appear animations, and Framer Motion.
|
|
859
862
|
*/
|
|
860
863
|
declare global {
|
|
861
864
|
interface Window {
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
+
MotionHandoffAnimation?: HandoffFunction;
|
|
866
|
+
MotionHandoffIsComplete?: boolean;
|
|
867
|
+
MotionHandoffCancelAll?: VoidFunction;
|
|
868
|
+
MotionHasOptimisedAnimation?: (id?: string) => boolean;
|
|
869
|
+
MotionHasOptimisedTransformAnimation?: (id?: string) => boolean;
|
|
865
870
|
}
|
|
866
871
|
}
|
|
867
872
|
|