framer-motion 11.3.30 → 11.3.31-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 +15 -4
- package/dist/cjs/index.js +111 -34
- package/dist/dom-entry.d.ts +17 -3
- package/dist/dom.js +1 -1
- package/dist/es/animation/optimized-appear/get-appear-id.mjs +1 -1
- package/dist/es/animation/optimized-appear/handoff.mjs +14 -12
- package/dist/es/animation/optimized-appear/start.mjs +75 -15
- package/dist/es/animation/optimized-appear/store-id.mjs +6 -1
- package/dist/es/projection/node/create-projection-node.mjs +4 -3
- package/dist/es/render/VisualElement.mjs +12 -1
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/value/index.mjs +1 -1
- package/dist/framer-motion.dev.js +111 -34
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +17 -5
- package/package.json +4 -4
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.31-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
|
|
@@ -3525,7 +3525,7 @@ const optimizedAppearDataId = "framerAppearId";
|
|
|
3525
3525
|
const optimizedAppearDataAttribute = "data-" + camelToDash(optimizedAppearDataId);
|
|
3526
3526
|
|
|
3527
3527
|
function getOptimisedAppearId(visualElement) {
|
|
3528
|
-
return visualElement.
|
|
3528
|
+
return visualElement.props[optimizedAppearDataAttribute];
|
|
3529
3529
|
}
|
|
3530
3530
|
|
|
3531
3531
|
function getWillChangeName(name) {
|
|
@@ -3790,7 +3790,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
3790
3790
|
* and warn against mismatches.
|
|
3791
3791
|
*/
|
|
3792
3792
|
if (process.env.NODE_ENV === "development") {
|
|
3793
|
-
warnOnce(nextValue.version === "11.3.
|
|
3793
|
+
warnOnce(nextValue.version === "11.3.31-alpha.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.3.31-alpha.0 may not work as expected.`);
|
|
3794
3794
|
}
|
|
3795
3795
|
}
|
|
3796
3796
|
else if (isMotionValue(prevValue)) {
|
|
@@ -4016,7 +4016,11 @@ class VisualElement {
|
|
|
4016
4016
|
if (this.parent && this.isVariantNode && !this.isControllingVariants) {
|
|
4017
4017
|
this.removeFromVariantTree = this.parent.addVariantChild(this);
|
|
4018
4018
|
}
|
|
4019
|
-
this.values.forEach((value, key) =>
|
|
4019
|
+
this.values.forEach((value, key) => {
|
|
4020
|
+
if (!this.valueSubscriptions.has(key)) {
|
|
4021
|
+
this.bindToMotionValue(key, value);
|
|
4022
|
+
}
|
|
4023
|
+
});
|
|
4020
4024
|
if (!hasReducedMotionListener.current) {
|
|
4021
4025
|
initPrefersReducedMotion();
|
|
4022
4026
|
}
|
|
@@ -4039,6 +4043,7 @@ class VisualElement {
|
|
|
4039
4043
|
cancelFrame(this.notifyUpdate);
|
|
4040
4044
|
cancelFrame(this.render);
|
|
4041
4045
|
this.valueSubscriptions.forEach((remove) => remove());
|
|
4046
|
+
this.valueSubscriptions.clear();
|
|
4042
4047
|
this.removeFromVariantTree && this.removeFromVariantTree();
|
|
4043
4048
|
this.parent && this.parent.children.delete(this);
|
|
4044
4049
|
for (const key in this.events) {
|
|
@@ -4066,9 +4071,15 @@ class VisualElement {
|
|
|
4066
4071
|
}
|
|
4067
4072
|
});
|
|
4068
4073
|
const removeOnRenderRequest = value.on("renderRequest", this.scheduleRender);
|
|
4074
|
+
let removeSyncCheck;
|
|
4075
|
+
if (window.MotionCheckAppearSync) {
|
|
4076
|
+
removeSyncCheck = window.MotionCheckAppearSync(this, key, value);
|
|
4077
|
+
}
|
|
4069
4078
|
this.valueSubscriptions.set(key, () => {
|
|
4070
4079
|
removeOnChange();
|
|
4071
4080
|
removeOnRenderRequest();
|
|
4081
|
+
if (removeSyncCheck)
|
|
4082
|
+
removeSyncCheck();
|
|
4072
4083
|
if (value.owner)
|
|
4073
4084
|
value.stop();
|
|
4074
4085
|
});
|
package/dist/cjs/index.js
CHANGED
|
@@ -4862,7 +4862,7 @@ class MotionValue {
|
|
|
4862
4862
|
* This will be replaced by the build step with the latest version number.
|
|
4863
4863
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
4864
4864
|
*/
|
|
4865
|
-
this.version = "11.3.
|
|
4865
|
+
this.version = "11.3.31-alpha.0";
|
|
4866
4866
|
/**
|
|
4867
4867
|
* Tracks whether this value can output a velocity. Currently this is only true
|
|
4868
4868
|
* if the value is numerical, but we might be able to widen the scope here and support
|
|
@@ -5167,7 +5167,7 @@ function setTarget(visualElement, definition) {
|
|
|
5167
5167
|
}
|
|
5168
5168
|
|
|
5169
5169
|
function getOptimisedAppearId(visualElement) {
|
|
5170
|
-
return visualElement.
|
|
5170
|
+
return visualElement.props[optimizedAppearDataAttribute];
|
|
5171
5171
|
}
|
|
5172
5172
|
|
|
5173
5173
|
class WillChangeMotionValue extends MotionValue {
|
|
@@ -7323,7 +7323,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
7323
7323
|
* and warn against mismatches.
|
|
7324
7324
|
*/
|
|
7325
7325
|
if (process.env.NODE_ENV === "development") {
|
|
7326
|
-
warnOnce(nextValue.version === "11.3.
|
|
7326
|
+
warnOnce(nextValue.version === "11.3.31-alpha.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.3.31-alpha.0 may not work as expected.`);
|
|
7327
7327
|
}
|
|
7328
7328
|
}
|
|
7329
7329
|
else if (isMotionValue(prevValue)) {
|
|
@@ -7516,7 +7516,11 @@ class VisualElement {
|
|
|
7516
7516
|
if (this.parent && this.isVariantNode && !this.isControllingVariants) {
|
|
7517
7517
|
this.removeFromVariantTree = this.parent.addVariantChild(this);
|
|
7518
7518
|
}
|
|
7519
|
-
this.values.forEach((value, key) =>
|
|
7519
|
+
this.values.forEach((value, key) => {
|
|
7520
|
+
if (!this.valueSubscriptions.has(key)) {
|
|
7521
|
+
this.bindToMotionValue(key, value);
|
|
7522
|
+
}
|
|
7523
|
+
});
|
|
7520
7524
|
if (!hasReducedMotionListener.current) {
|
|
7521
7525
|
initPrefersReducedMotion();
|
|
7522
7526
|
}
|
|
@@ -7539,6 +7543,7 @@ class VisualElement {
|
|
|
7539
7543
|
cancelFrame(this.notifyUpdate);
|
|
7540
7544
|
cancelFrame(this.render);
|
|
7541
7545
|
this.valueSubscriptions.forEach((remove) => remove());
|
|
7546
|
+
this.valueSubscriptions.clear();
|
|
7542
7547
|
this.removeFromVariantTree && this.removeFromVariantTree();
|
|
7543
7548
|
this.parent && this.parent.children.delete(this);
|
|
7544
7549
|
for (const key in this.events) {
|
|
@@ -7566,9 +7571,15 @@ class VisualElement {
|
|
|
7566
7571
|
}
|
|
7567
7572
|
});
|
|
7568
7573
|
const removeOnRenderRequest = value.on("renderRequest", this.scheduleRender);
|
|
7574
|
+
let removeSyncCheck;
|
|
7575
|
+
if (window.MotionCheckAppearSync) {
|
|
7576
|
+
removeSyncCheck = window.MotionCheckAppearSync(this, key, value);
|
|
7577
|
+
}
|
|
7569
7578
|
this.valueSubscriptions.set(key, () => {
|
|
7570
7579
|
removeOnChange();
|
|
7571
7580
|
removeOnRenderRequest();
|
|
7581
|
+
if (removeSyncCheck)
|
|
7582
|
+
removeSyncCheck();
|
|
7572
7583
|
if (value.owner)
|
|
7573
7584
|
value.stop();
|
|
7574
7585
|
});
|
|
@@ -8969,8 +8980,9 @@ function cancelTreeOptimisedTransformAnimations(projectionNode) {
|
|
|
8969
8980
|
if (!visualElement)
|
|
8970
8981
|
return;
|
|
8971
8982
|
const appearId = getOptimisedAppearId(visualElement);
|
|
8972
|
-
if (window.
|
|
8973
|
-
|
|
8983
|
+
if (window.MotionHasOptimisedAnimation(appearId, "transform")) {
|
|
8984
|
+
const { layout, layoutId } = projectionNode.options;
|
|
8985
|
+
window.MotionCancelOptimisedAnimation(appearId, "transform", frame, !(layout || layoutId));
|
|
8974
8986
|
}
|
|
8975
8987
|
const { parent } = projectionNode;
|
|
8976
8988
|
if (parent && !parent.hasCheckedOptimisedAppear) {
|
|
@@ -9298,7 +9310,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
9298
9310
|
* snapshots in startUpdate(), but we only want to cancel optimised animations
|
|
9299
9311
|
* if a layout animation measurement is actually going to be affected by them.
|
|
9300
9312
|
*/
|
|
9301
|
-
if (window.
|
|
9313
|
+
if (window.MotionCancelOptimisedAnimation &&
|
|
9302
9314
|
!this.hasCheckedOptimisedAppear) {
|
|
9303
9315
|
cancelTreeOptimisedTransformAnimations(this);
|
|
9304
9316
|
}
|
|
@@ -12181,21 +12193,33 @@ function useResetProjection() {
|
|
|
12181
12193
|
return reset;
|
|
12182
12194
|
}
|
|
12183
12195
|
|
|
12184
|
-
const appearStoreId = (
|
|
12196
|
+
const appearStoreId = (elementId, valueName) => {
|
|
12197
|
+
const key = transformProps.has(valueName) ? "transform" : valueName;
|
|
12198
|
+
return `${elementId}: ${key}`;
|
|
12199
|
+
};
|
|
12185
12200
|
|
|
12186
12201
|
const appearAnimationStore = new Map();
|
|
12187
12202
|
const elementsWithAppearAnimations = new Set();
|
|
12188
12203
|
|
|
12189
12204
|
function handoffOptimizedAppearAnimation(elementId, valueName, frame) {
|
|
12190
|
-
const
|
|
12191
|
-
? "transform"
|
|
12192
|
-
: valueName;
|
|
12193
|
-
const storeId = appearStoreId(elementId, optimisedValueName);
|
|
12205
|
+
const storeId = appearStoreId(elementId, valueName);
|
|
12194
12206
|
const optimisedAnimation = appearAnimationStore.get(storeId);
|
|
12195
12207
|
if (!optimisedAnimation) {
|
|
12196
12208
|
return null;
|
|
12197
12209
|
}
|
|
12198
12210
|
const { animation, startTime } = optimisedAnimation;
|
|
12211
|
+
function cancelAnimation() {
|
|
12212
|
+
var _a;
|
|
12213
|
+
(_a = window.MotionCancelOptimisedAnimation) === null || _a === void 0 ? void 0 : _a.call(window, elementId, valueName, frame);
|
|
12214
|
+
}
|
|
12215
|
+
/**
|
|
12216
|
+
* We can cancel the animation once it's finished now that we've synced
|
|
12217
|
+
* with Motion.
|
|
12218
|
+
*
|
|
12219
|
+
* Prefer onfinish over finished as onfinish is backwards compatible with
|
|
12220
|
+
* older browsers.
|
|
12221
|
+
*/
|
|
12222
|
+
animation.onfinish = cancelAnimation;
|
|
12199
12223
|
if (startTime === null || window.MotionHandoffIsComplete) {
|
|
12200
12224
|
/**
|
|
12201
12225
|
* If the startTime is null, this animation is the Paint Ready detection animation
|
|
@@ -12204,13 +12228,7 @@ function handoffOptimizedAppearAnimation(elementId, valueName, frame) {
|
|
|
12204
12228
|
* Or if we've already handed off the animation then we're now interrupting it.
|
|
12205
12229
|
* In which case we need to cancel it.
|
|
12206
12230
|
*/
|
|
12207
|
-
|
|
12208
|
-
frame.render(() => frame.render(() => {
|
|
12209
|
-
try {
|
|
12210
|
-
animation.cancel();
|
|
12211
|
-
}
|
|
12212
|
-
catch (error) { }
|
|
12213
|
-
}));
|
|
12231
|
+
cancelAnimation();
|
|
12214
12232
|
return null;
|
|
12215
12233
|
}
|
|
12216
12234
|
else {
|
|
@@ -12231,6 +12249,18 @@ let startFrameTime;
|
|
|
12231
12249
|
* https://bugs.chromium.org/p/chromium/issues/detail?id=1406850
|
|
12232
12250
|
*/
|
|
12233
12251
|
let readyAnimation;
|
|
12252
|
+
/**
|
|
12253
|
+
* Keep track of animations that were suspended vs cancelled so we
|
|
12254
|
+
* can easily resume them when we're done measuring layout.
|
|
12255
|
+
*/
|
|
12256
|
+
const suspendedAnimations = new Set();
|
|
12257
|
+
function resumeSuspendedAnimations() {
|
|
12258
|
+
suspendedAnimations.forEach((data) => {
|
|
12259
|
+
data.animation.play();
|
|
12260
|
+
data.animation.startTime = data.startTime;
|
|
12261
|
+
});
|
|
12262
|
+
suspendedAnimations.clear();
|
|
12263
|
+
}
|
|
12234
12264
|
function startOptimizedAppearAnimation(element, name, keyframes, options, onReady) {
|
|
12235
12265
|
// Prevent optimised appear animations if Motion has already started animating.
|
|
12236
12266
|
if (window.MotionHandoffIsComplete) {
|
|
@@ -12258,10 +12288,22 @@ function startOptimizedAppearAnimation(element, name, keyframes, options, onRead
|
|
|
12258
12288
|
* of handoff animations.
|
|
12259
12289
|
*/
|
|
12260
12290
|
window.MotionHandoffAnimation = handoffOptimizedAppearAnimation;
|
|
12261
|
-
window.
|
|
12291
|
+
window.MotionHasOptimisedAnimation = (elementId, valueName) => {
|
|
12262
12292
|
if (!elementId)
|
|
12263
12293
|
return false;
|
|
12264
|
-
|
|
12294
|
+
/**
|
|
12295
|
+
* Keep a map of elementIds that have started animating. We check
|
|
12296
|
+
* via ID instead of Element because of hydration errors and
|
|
12297
|
+
* pre-hydration checks. We also actively record IDs as they start
|
|
12298
|
+
* animating rather than simply checking for data-appear-id as
|
|
12299
|
+
* this attrbute might be present but not lead to an animation, for
|
|
12300
|
+
* instance if the element's appear animation is on a different
|
|
12301
|
+
* breakpoint.
|
|
12302
|
+
*/
|
|
12303
|
+
if (!valueName) {
|
|
12304
|
+
return elementsWithAppearAnimations.has(elementId);
|
|
12305
|
+
}
|
|
12306
|
+
const animationId = appearStoreId(elementId, valueName);
|
|
12265
12307
|
return Boolean(appearAnimationStore.get(animationId));
|
|
12266
12308
|
};
|
|
12267
12309
|
/**
|
|
@@ -12269,24 +12311,59 @@ function startOptimizedAppearAnimation(element, name, keyframes, options, onRead
|
|
|
12269
12311
|
* they're the ones that will interfere with the
|
|
12270
12312
|
* layout animation measurements.
|
|
12271
12313
|
*/
|
|
12272
|
-
window.
|
|
12273
|
-
const animationId = appearStoreId(elementId,
|
|
12314
|
+
window.MotionCancelOptimisedAnimation = (elementId, valueName, frame, canResume) => {
|
|
12315
|
+
const animationId = appearStoreId(elementId, valueName);
|
|
12274
12316
|
const data = appearAnimationStore.get(animationId);
|
|
12275
|
-
if (data)
|
|
12317
|
+
if (!data)
|
|
12318
|
+
return;
|
|
12319
|
+
if (frame && canResume === undefined) {
|
|
12320
|
+
/**
|
|
12321
|
+
* Wait until the end of the subsequent frame to cancel the animation
|
|
12322
|
+
* to ensure we don't remove the animation before the main thread has
|
|
12323
|
+
* had a chance to resolve keyframes and render.
|
|
12324
|
+
*/
|
|
12325
|
+
frame.postRender(() => {
|
|
12326
|
+
frame.postRender(() => {
|
|
12327
|
+
data.animation.cancel();
|
|
12328
|
+
});
|
|
12329
|
+
});
|
|
12330
|
+
}
|
|
12331
|
+
else {
|
|
12276
12332
|
data.animation.cancel();
|
|
12333
|
+
}
|
|
12334
|
+
if (frame && canResume) {
|
|
12335
|
+
suspendedAnimations.add(data);
|
|
12336
|
+
frame.render(resumeSuspendedAnimations);
|
|
12337
|
+
}
|
|
12338
|
+
else {
|
|
12277
12339
|
appearAnimationStore.delete(animationId);
|
|
12340
|
+
/**
|
|
12341
|
+
* If there are no more animations left, we can remove the cancel function.
|
|
12342
|
+
* This will let us know when we can stop checking for conflicting layout animations.
|
|
12343
|
+
*/
|
|
12344
|
+
if (!appearAnimationStore.size) {
|
|
12345
|
+
window.MotionCancelOptimisedAnimation = undefined;
|
|
12346
|
+
}
|
|
12278
12347
|
}
|
|
12279
12348
|
};
|
|
12280
|
-
|
|
12281
|
-
|
|
12282
|
-
|
|
12283
|
-
|
|
12284
|
-
|
|
12285
|
-
|
|
12286
|
-
|
|
12287
|
-
|
|
12288
|
-
|
|
12289
|
-
|
|
12349
|
+
window.MotionCheckAppearSync = (visualElement, valueName, value) => {
|
|
12350
|
+
var _a, _b;
|
|
12351
|
+
const appearId = getOptimisedAppearId(visualElement);
|
|
12352
|
+
if (!appearId)
|
|
12353
|
+
return;
|
|
12354
|
+
const valueIsOptimised = (_a = window.MotionHasOptimisedAnimation) === null || _a === void 0 ? void 0 : _a.call(window, appearId, valueName);
|
|
12355
|
+
const externalAnimationValue = (_b = visualElement.props.values) === null || _b === void 0 ? void 0 : _b[valueName];
|
|
12356
|
+
if (!valueIsOptimised || !externalAnimationValue)
|
|
12357
|
+
return;
|
|
12358
|
+
const removeSyncCheck = value.on("change", (latestValue) => {
|
|
12359
|
+
var _a;
|
|
12360
|
+
if (externalAnimationValue.get() !== latestValue) {
|
|
12361
|
+
(_a = window.MotionCancelOptimisedAnimation) === null || _a === void 0 ? void 0 : _a.call(window, appearId, valueName);
|
|
12362
|
+
removeSyncCheck();
|
|
12363
|
+
}
|
|
12364
|
+
});
|
|
12365
|
+
return removeSyncCheck;
|
|
12366
|
+
};
|
|
12290
12367
|
}
|
|
12291
12368
|
const startAnimation = () => {
|
|
12292
12369
|
readyAnimation.cancel();
|
package/dist/dom-entry.d.ts
CHANGED
|
@@ -855,6 +855,20 @@ interface FrameData {
|
|
|
855
855
|
isProcessing: boolean;
|
|
856
856
|
}
|
|
857
857
|
|
|
858
|
+
declare const optimizedAppearDataAttribute: "data-framer-appear-id";
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* Expose only the needed part of the VisualElement interface to
|
|
862
|
+
* ensure React types don't end up in the generic DOM bundle.
|
|
863
|
+
*/
|
|
864
|
+
interface WithAppearProps {
|
|
865
|
+
props: {
|
|
866
|
+
[optimizedAppearDataAttribute]?: string;
|
|
867
|
+
values?: {
|
|
868
|
+
[key: string]: MotionValue<number> | MotionValue<string>;
|
|
869
|
+
};
|
|
870
|
+
};
|
|
871
|
+
}
|
|
858
872
|
type HandoffFunction = (storeId: string, valueName: string, frame: Batcher) => number | null;
|
|
859
873
|
/**
|
|
860
874
|
* The window global object acts as a bridge between our inline script
|
|
@@ -864,9 +878,9 @@ declare global {
|
|
|
864
878
|
interface Window {
|
|
865
879
|
MotionHandoffAnimation?: HandoffFunction;
|
|
866
880
|
MotionHandoffIsComplete?: boolean;
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
881
|
+
MotionHasOptimisedAnimation?: (elementId?: string, valueName?: string) => boolean;
|
|
882
|
+
MotionCancelOptimisedAnimation?: (elementId?: string, valueName?: string, frame?: Batcher, canResume?: boolean) => void;
|
|
883
|
+
MotionCheckAppearSync?: (visualElement: WithAppearProps, valueName: string, value: MotionValue) => VoidFunction | void;
|
|
870
884
|
}
|
|
871
885
|
}
|
|
872
886
|
|