framer-motion 7.6.7 → 7.6.9
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 +115 -56
- package/dist/es/projection/geometry/delta-apply.mjs +4 -1
- package/dist/es/projection/node/create-projection-node.mjs +90 -43
- package/dist/es/projection/shared/stack.mjs +0 -1
- package/dist/es/projection/styles/transform.mjs +12 -6
- package/dist/es/projection/utils/measure.mjs +2 -2
- package/dist/es/render/VisualElement.mjs +5 -0
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/value/index.mjs +1 -1
- package/dist/framer-motion.dev.js +115 -56
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +16 -4
- package/dist/projection.dev.js +111 -52
- package/dist/size-rollup-dom-animation.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 +16 -4
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -1333,15 +1333,27 @@ declare class FlatTree {
|
|
|
1333
1333
|
forEach(callback: (child: WithDepth) => void): void;
|
|
1334
1334
|
}
|
|
1335
1335
|
|
|
1336
|
+
declare type Position = "static" | "sticky" | "fixed";
|
|
1336
1337
|
interface Measurements {
|
|
1338
|
+
animationId: number;
|
|
1337
1339
|
measuredBox: Box;
|
|
1338
1340
|
layoutBox: Box;
|
|
1339
1341
|
latestValues: ResolvedValues;
|
|
1340
|
-
|
|
1342
|
+
source: number;
|
|
1343
|
+
position: Position;
|
|
1344
|
+
}
|
|
1345
|
+
declare type Phase = "snapshot" | "measure";
|
|
1346
|
+
interface ScrollMeasurements {
|
|
1347
|
+
animationId: number;
|
|
1348
|
+
phase: Phase;
|
|
1349
|
+
isRoot: boolean;
|
|
1350
|
+
offset: Point;
|
|
1341
1351
|
}
|
|
1342
1352
|
declare type LayoutEvents = "willUpdate" | "didUpdate" | "beforeMeasure" | "measure" | "projectionUpdate" | "animationStart" | "animationComplete";
|
|
1343
1353
|
interface IProjectionNode<I = unknown> {
|
|
1354
|
+
id: number;
|
|
1344
1355
|
elementId: number | undefined;
|
|
1356
|
+
animationId: number;
|
|
1345
1357
|
parent?: IProjectionNode;
|
|
1346
1358
|
relativeParent?: IProjectionNode;
|
|
1347
1359
|
root?: IProjectionNode;
|
|
@@ -1360,13 +1372,13 @@ interface IProjectionNode<I = unknown> {
|
|
|
1360
1372
|
relativeTarget?: Box;
|
|
1361
1373
|
targetDelta?: Delta;
|
|
1362
1374
|
targetWithTransforms?: Box;
|
|
1363
|
-
scroll?:
|
|
1364
|
-
isScrollRoot?: boolean;
|
|
1375
|
+
scroll?: ScrollMeasurements;
|
|
1365
1376
|
treeScale?: Point;
|
|
1366
1377
|
projectionDelta?: Delta;
|
|
1367
1378
|
projectionDeltaWithTransform?: Delta;
|
|
1368
1379
|
latestValues: ResolvedValues;
|
|
1369
1380
|
isLayoutDirty: boolean;
|
|
1381
|
+
isProjectionDirty: boolean;
|
|
1370
1382
|
shouldResetTransform: boolean;
|
|
1371
1383
|
prevTransformTemplateValue: string | undefined;
|
|
1372
1384
|
isUpdateBlocked(): boolean;
|
|
@@ -1384,7 +1396,7 @@ interface IProjectionNode<I = unknown> {
|
|
|
1384
1396
|
updateLayout(): void;
|
|
1385
1397
|
updateSnapshot(): void;
|
|
1386
1398
|
clearSnapshot(): void;
|
|
1387
|
-
updateScroll(): void;
|
|
1399
|
+
updateScroll(phase?: Phase): void;
|
|
1388
1400
|
scheduleUpdateProjection(): void;
|
|
1389
1401
|
scheduleCheckAfterUnmount(): void;
|
|
1390
1402
|
checkUpdateFailed(): void;
|
package/dist/projection.dev.js
CHANGED
|
@@ -1242,7 +1242,7 @@
|
|
|
1242
1242
|
* This will be replaced by the build step with the latest version number.
|
|
1243
1243
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
1244
1244
|
*/
|
|
1245
|
-
this.version = "7.6.
|
|
1245
|
+
this.version = "7.6.9";
|
|
1246
1246
|
/**
|
|
1247
1247
|
* Duration, in milliseconds, since last updating frame.
|
|
1248
1248
|
*
|
|
@@ -2194,7 +2194,10 @@
|
|
|
2194
2194
|
node.options.layoutScroll &&
|
|
2195
2195
|
node.scroll &&
|
|
2196
2196
|
node !== node.root) {
|
|
2197
|
-
transformBox(box, {
|
|
2197
|
+
transformBox(box, {
|
|
2198
|
+
x: -node.scroll.offset.x,
|
|
2199
|
+
y: -node.scroll.offset.y,
|
|
2200
|
+
});
|
|
2198
2201
|
}
|
|
2199
2202
|
if (delta) {
|
|
2200
2203
|
// Incoporate each ancestor's scale into a culmulative treeScale for this component
|
|
@@ -2420,7 +2423,6 @@
|
|
|
2420
2423
|
node.snapshot = prevLead.snapshot;
|
|
2421
2424
|
node.snapshot.latestValues =
|
|
2422
2425
|
prevLead.animationValues || prevLead.latestValues;
|
|
2423
|
-
node.snapshot.isShared = true;
|
|
2424
2426
|
}
|
|
2425
2427
|
if ((_a = node.root) === null || _a === void 0 ? void 0 : _a.isUpdating) {
|
|
2426
2428
|
node.isLayoutDirty = true;
|
|
@@ -2471,8 +2473,8 @@
|
|
|
2471
2473
|
Object.assign(scaleCorrectors, correctors);
|
|
2472
2474
|
}
|
|
2473
2475
|
|
|
2474
|
-
const identityProjection = "translate3d(0px, 0px, 0) scale(1, 1) scale(1, 1)";
|
|
2475
2476
|
function buildProjectionTransform(delta, treeScale, latestTransform) {
|
|
2477
|
+
let transform = "";
|
|
2476
2478
|
/**
|
|
2477
2479
|
* The translations we use to calculate are always relative to the viewport coordinate space.
|
|
2478
2480
|
* But when we apply scales, we also scale the coordinate space of an element and its children.
|
|
@@ -2481,12 +2483,16 @@
|
|
|
2481
2483
|
*/
|
|
2482
2484
|
const xTranslate = delta.x.translate / treeScale.x;
|
|
2483
2485
|
const yTranslate = delta.y.translate / treeScale.y;
|
|
2484
|
-
|
|
2486
|
+
if (xTranslate || yTranslate) {
|
|
2487
|
+
transform = `translate3d(${xTranslate}px, ${yTranslate}px, 0) `;
|
|
2488
|
+
}
|
|
2485
2489
|
/**
|
|
2486
2490
|
* Apply scale correction for the tree transform.
|
|
2487
2491
|
* This will apply scale to the screen-orientated axes.
|
|
2488
2492
|
*/
|
|
2489
|
-
|
|
2493
|
+
if (treeScale.x !== 1 || treeScale.y !== 1) {
|
|
2494
|
+
transform += `scale(${1 / treeScale.x}, ${1 / treeScale.y}) `;
|
|
2495
|
+
}
|
|
2490
2496
|
if (latestTransform) {
|
|
2491
2497
|
const { rotate, rotateX, rotateY } = latestTransform;
|
|
2492
2498
|
if (rotate)
|
|
@@ -2502,8 +2508,10 @@
|
|
|
2502
2508
|
*/
|
|
2503
2509
|
const elementScaleX = delta.x.scale * treeScale.x;
|
|
2504
2510
|
const elementScaleY = delta.y.scale * treeScale.y;
|
|
2505
|
-
|
|
2506
|
-
|
|
2511
|
+
if (elementScaleX !== 1 || elementScaleY !== 1) {
|
|
2512
|
+
transform += `scale(${elementScaleX}, ${elementScaleY})`;
|
|
2513
|
+
}
|
|
2514
|
+
return transform || "none";
|
|
2507
2515
|
}
|
|
2508
2516
|
|
|
2509
2517
|
function eachAxis(callback) {
|
|
@@ -2568,9 +2576,18 @@
|
|
|
2568
2576
|
* which has a noticeable difference in spring animations
|
|
2569
2577
|
*/
|
|
2570
2578
|
const animationTarget = 1000;
|
|
2579
|
+
let id = 0;
|
|
2571
2580
|
function createProjectionNode({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform, }) {
|
|
2572
2581
|
return class ProjectionNode {
|
|
2573
2582
|
constructor(elementId, latestValues = {}, parent = defaultParent === null || defaultParent === void 0 ? void 0 : defaultParent()) {
|
|
2583
|
+
/**
|
|
2584
|
+
* A unique ID generated for every projection node.
|
|
2585
|
+
*/
|
|
2586
|
+
this.id = id++;
|
|
2587
|
+
/**
|
|
2588
|
+
* An id that represents a unique session instigated by startUpdate.
|
|
2589
|
+
*/
|
|
2590
|
+
this.animationId = 0;
|
|
2574
2591
|
/**
|
|
2575
2592
|
* A Set containing all this component's children. This is used to iterate
|
|
2576
2593
|
* through the children.
|
|
@@ -2597,6 +2614,11 @@
|
|
|
2597
2614
|
* and if one node is dirtied, they all are.
|
|
2598
2615
|
*/
|
|
2599
2616
|
this.isLayoutDirty = false;
|
|
2617
|
+
/**
|
|
2618
|
+
* Flag to true if we think the projection calculations for this or any
|
|
2619
|
+
* child might need recalculating as a result of an updated transform or layout animation.
|
|
2620
|
+
*/
|
|
2621
|
+
this.isProjectionDirty = false;
|
|
2600
2622
|
/**
|
|
2601
2623
|
* Block layout updates for instant layout transitions throughout the tree.
|
|
2602
2624
|
*/
|
|
@@ -2679,8 +2701,8 @@
|
|
|
2679
2701
|
hasListeners(name) {
|
|
2680
2702
|
return this.eventHandlers.has(name);
|
|
2681
2703
|
}
|
|
2682
|
-
registerPotentialNode(
|
|
2683
|
-
this.potentialNodes.set(
|
|
2704
|
+
registerPotentialNode(elementId, node) {
|
|
2705
|
+
this.potentialNodes.set(elementId, node);
|
|
2684
2706
|
}
|
|
2685
2707
|
/**
|
|
2686
2708
|
* Lifecycles
|
|
@@ -2813,6 +2835,7 @@
|
|
|
2813
2835
|
return;
|
|
2814
2836
|
this.isUpdating = true;
|
|
2815
2837
|
(_a = this.nodes) === null || _a === void 0 ? void 0 : _a.forEach(resetRotation);
|
|
2838
|
+
this.animationId++;
|
|
2816
2839
|
}
|
|
2817
2840
|
willUpdate(shouldNotifyListeners = true) {
|
|
2818
2841
|
var _a, _b, _c;
|
|
@@ -2827,11 +2850,7 @@
|
|
|
2827
2850
|
for (let i = 0; i < this.path.length; i++) {
|
|
2828
2851
|
const node = this.path[i];
|
|
2829
2852
|
node.shouldResetTransform = true;
|
|
2830
|
-
|
|
2831
|
-
* TODO: Check we haven't updated the scroll
|
|
2832
|
-
* since the last didUpdate
|
|
2833
|
-
*/
|
|
2834
|
-
node.updateScroll();
|
|
2853
|
+
node.updateScroll("snapshot");
|
|
2835
2854
|
}
|
|
2836
2855
|
const { layoutId, layout } = this.options;
|
|
2837
2856
|
if (layoutId === undefined && !layout)
|
|
@@ -2947,10 +2966,20 @@
|
|
|
2947
2966
|
this.notifyListeners("measure", this.layout.layoutBox);
|
|
2948
2967
|
(_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.notify("LayoutMeasure", this.layout.layoutBox, prevLayout === null || prevLayout === void 0 ? void 0 : prevLayout.layoutBox);
|
|
2949
2968
|
}
|
|
2950
|
-
updateScroll() {
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
this.scroll
|
|
2969
|
+
updateScroll(phase = "measure") {
|
|
2970
|
+
let needsMeasurement = Boolean(this.options.layoutScroll && this.instance);
|
|
2971
|
+
if (this.scroll &&
|
|
2972
|
+
this.scroll.animationId === this.root.animationId &&
|
|
2973
|
+
this.scroll.phase === phase) {
|
|
2974
|
+
needsMeasurement = false;
|
|
2975
|
+
}
|
|
2976
|
+
if (needsMeasurement) {
|
|
2977
|
+
this.scroll = {
|
|
2978
|
+
animationId: this.root.animationId,
|
|
2979
|
+
phase,
|
|
2980
|
+
isRoot: checkIsScrollRoot(this.instance),
|
|
2981
|
+
offset: measureScroll(this.instance),
|
|
2982
|
+
};
|
|
2954
2983
|
}
|
|
2955
2984
|
}
|
|
2956
2985
|
resetTransform() {
|
|
@@ -2972,6 +3001,7 @@
|
|
|
2972
3001
|
}
|
|
2973
3002
|
}
|
|
2974
3003
|
measure(removeTransform = true) {
|
|
3004
|
+
var _a;
|
|
2975
3005
|
const pageBox = this.measurePageBox();
|
|
2976
3006
|
let layoutBox = this.removeElementScroll(pageBox);
|
|
2977
3007
|
/**
|
|
@@ -2983,10 +3013,17 @@
|
|
|
2983
3013
|
layoutBox = this.removeTransform(layoutBox);
|
|
2984
3014
|
}
|
|
2985
3015
|
roundBox(layoutBox);
|
|
3016
|
+
const positionStyle = (_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.readValue("position");
|
|
3017
|
+
const position = positionStyle === "fixed" || positionStyle === "sticky"
|
|
3018
|
+
? positionStyle
|
|
3019
|
+
: "static";
|
|
2986
3020
|
return {
|
|
3021
|
+
animationId: this.root.animationId,
|
|
2987
3022
|
measuredBox: pageBox,
|
|
2988
3023
|
layoutBox,
|
|
2989
3024
|
latestValues: {},
|
|
3025
|
+
source: this.id,
|
|
3026
|
+
position,
|
|
2990
3027
|
};
|
|
2991
3028
|
}
|
|
2992
3029
|
measurePageBox() {
|
|
@@ -2997,8 +3034,8 @@
|
|
|
2997
3034
|
// Remove viewport scroll to give page-relative coordinates
|
|
2998
3035
|
const { scroll } = this.root;
|
|
2999
3036
|
if (scroll) {
|
|
3000
|
-
translateAxis(box.x, scroll.x);
|
|
3001
|
-
translateAxis(box.y, scroll.y);
|
|
3037
|
+
translateAxis(box.x, scroll.offset.x);
|
|
3038
|
+
translateAxis(box.y, scroll.offset.y);
|
|
3002
3039
|
}
|
|
3003
3040
|
return box;
|
|
3004
3041
|
}
|
|
@@ -3011,13 +3048,13 @@
|
|
|
3011
3048
|
*/
|
|
3012
3049
|
for (let i = 0; i < this.path.length; i++) {
|
|
3013
3050
|
const node = this.path[i];
|
|
3014
|
-
const { scroll, options
|
|
3051
|
+
const { scroll, options } = node;
|
|
3015
3052
|
if (node !== this.root && scroll && options.layoutScroll) {
|
|
3016
3053
|
/**
|
|
3017
3054
|
* If this is a new scroll root, we want to remove all previous scrolls
|
|
3018
3055
|
* from the viewport box.
|
|
3019
3056
|
*/
|
|
3020
|
-
if (
|
|
3057
|
+
if (scroll.isRoot) {
|
|
3021
3058
|
copyBoxInto(boxWithoutScroll, box);
|
|
3022
3059
|
const { scroll: rootScroll } = this.root;
|
|
3023
3060
|
/**
|
|
@@ -3025,12 +3062,12 @@
|
|
|
3025
3062
|
* to the measured bounding box.
|
|
3026
3063
|
*/
|
|
3027
3064
|
if (rootScroll) {
|
|
3028
|
-
translateAxis(boxWithoutScroll.x, -rootScroll.x);
|
|
3029
|
-
translateAxis(boxWithoutScroll.y, -rootScroll.y);
|
|
3065
|
+
translateAxis(boxWithoutScroll.x, -rootScroll.offset.x);
|
|
3066
|
+
translateAxis(boxWithoutScroll.y, -rootScroll.offset.y);
|
|
3030
3067
|
}
|
|
3031
3068
|
}
|
|
3032
|
-
translateAxis(boxWithoutScroll.x, scroll.x);
|
|
3033
|
-
translateAxis(boxWithoutScroll.y, scroll.y);
|
|
3069
|
+
translateAxis(boxWithoutScroll.x, scroll.offset.x);
|
|
3070
|
+
translateAxis(boxWithoutScroll.y, scroll.offset.y);
|
|
3034
3071
|
}
|
|
3035
3072
|
}
|
|
3036
3073
|
return boxWithoutScroll;
|
|
@@ -3045,8 +3082,8 @@
|
|
|
3045
3082
|
node.scroll &&
|
|
3046
3083
|
node !== node.root) {
|
|
3047
3084
|
transformBox(withTransforms, {
|
|
3048
|
-
x: -node.scroll.x,
|
|
3049
|
-
y: -node.scroll.y,
|
|
3085
|
+
x: -node.scroll.offset.x,
|
|
3086
|
+
y: -node.scroll.offset.y,
|
|
3050
3087
|
});
|
|
3051
3088
|
}
|
|
3052
3089
|
if (!hasTransform(node.latestValues))
|
|
@@ -3084,6 +3121,7 @@
|
|
|
3084
3121
|
*/
|
|
3085
3122
|
setTargetDelta(delta) {
|
|
3086
3123
|
this.targetDelta = delta;
|
|
3124
|
+
this.isProjectionDirty = true;
|
|
3087
3125
|
this.root.scheduleUpdateProjection();
|
|
3088
3126
|
}
|
|
3089
3127
|
setOptions(options) {
|
|
@@ -3107,6 +3145,14 @@
|
|
|
3107
3145
|
*/
|
|
3108
3146
|
resolveTargetDelta() {
|
|
3109
3147
|
var _a;
|
|
3148
|
+
/**
|
|
3149
|
+
* Propagate isProjectionDirty. Nodes are ordered by depth, so if the parent here
|
|
3150
|
+
* is dirty we can simply pass this forward.
|
|
3151
|
+
*/
|
|
3152
|
+
this.isProjectionDirty || (this.isProjectionDirty = this.getLead().isProjectionDirty ||
|
|
3153
|
+
Boolean(this.parent && this.parent.isProjectionDirty));
|
|
3154
|
+
if (!this.isProjectionDirty)
|
|
3155
|
+
return;
|
|
3110
3156
|
const { layout, layoutId } = this.options;
|
|
3111
3157
|
/**
|
|
3112
3158
|
* If we have no layout, we can't perform projection, so early return
|
|
@@ -3210,6 +3256,9 @@
|
|
|
3210
3256
|
}
|
|
3211
3257
|
calcProjection() {
|
|
3212
3258
|
var _a;
|
|
3259
|
+
if (!this.isProjectionDirty)
|
|
3260
|
+
return;
|
|
3261
|
+
this.isProjectionDirty = false;
|
|
3213
3262
|
const { layout, layoutId } = this.options;
|
|
3214
3263
|
/**
|
|
3215
3264
|
* If this section of the tree isn't animating we can
|
|
@@ -3280,7 +3329,7 @@
|
|
|
3280
3329
|
}
|
|
3281
3330
|
}
|
|
3282
3331
|
setAnimationOrigin(delta, hasOnlyRelativeTargetChanged = false) {
|
|
3283
|
-
var _a;
|
|
3332
|
+
var _a, _b;
|
|
3284
3333
|
const snapshot = this.snapshot;
|
|
3285
3334
|
const snapshotLatestValues = (snapshot === null || snapshot === void 0 ? void 0 : snapshot.latestValues) || {};
|
|
3286
3335
|
const mixedValues = { ...this.latestValues };
|
|
@@ -3288,8 +3337,8 @@
|
|
|
3288
3337
|
this.relativeTarget = this.relativeTargetOrigin = undefined;
|
|
3289
3338
|
this.attemptToResolveRelativeTarget = !hasOnlyRelativeTargetChanged;
|
|
3290
3339
|
const relativeLayout = createBox();
|
|
3291
|
-
const isSharedLayoutAnimation = snapshot === null || snapshot === void 0 ? void 0 : snapshot.
|
|
3292
|
-
const isOnlyMember = (((
|
|
3340
|
+
const isSharedLayoutAnimation = (snapshot === null || snapshot === void 0 ? void 0 : snapshot.source) !== ((_a = this.layout) === null || _a === void 0 ? void 0 : _a.source);
|
|
3341
|
+
const isOnlyMember = (((_b = this.getStack()) === null || _b === void 0 ? void 0 : _b.members.length) || 0) <= 1;
|
|
3293
3342
|
const shouldCrossfadeOpacity = Boolean(isSharedLayoutAnimation &&
|
|
3294
3343
|
!isOnlyMember &&
|
|
3295
3344
|
this.options.crossfade === true &&
|
|
@@ -3470,25 +3519,30 @@
|
|
|
3470
3519
|
return;
|
|
3471
3520
|
// If there's no detected rotation values, we can early return without a forced render.
|
|
3472
3521
|
let hasRotate = false;
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
continue;
|
|
3483
|
-
}
|
|
3522
|
+
/**
|
|
3523
|
+
* An unrolled check for rotation values. Most elements don't have any rotation and
|
|
3524
|
+
* skipping the nested loop and new object creation is 50% faster.
|
|
3525
|
+
*/
|
|
3526
|
+
const { latestValues } = visualElement;
|
|
3527
|
+
if (latestValues.rotate ||
|
|
3528
|
+
latestValues.rotateX ||
|
|
3529
|
+
latestValues.rotateY ||
|
|
3530
|
+
latestValues.rotateZ) {
|
|
3484
3531
|
hasRotate = true;
|
|
3485
|
-
// Record the rotation and then temporarily set it to 0
|
|
3486
|
-
resetValues[key] = visualElement.getStaticValue(key);
|
|
3487
|
-
visualElement.setStaticValue(key, 0);
|
|
3488
3532
|
}
|
|
3489
3533
|
// If there's no rotation values, we don't need to do any more.
|
|
3490
3534
|
if (!hasRotate)
|
|
3491
3535
|
return;
|
|
3536
|
+
const resetValues = {};
|
|
3537
|
+
// Check the rotate value of all axes and reset to 0
|
|
3538
|
+
for (let i = 0; i < transformAxes.length; i++) {
|
|
3539
|
+
const key = "rotate" + transformAxes[i];
|
|
3540
|
+
// Record the rotation and then temporarily set it to 0
|
|
3541
|
+
if (latestValues[key]) {
|
|
3542
|
+
resetValues[key] = latestValues[key];
|
|
3543
|
+
visualElement.setStaticValue(key, 0);
|
|
3544
|
+
}
|
|
3545
|
+
}
|
|
3492
3546
|
// Force a render of this element to apply the transform with all rotations
|
|
3493
3547
|
// set to 0.
|
|
3494
3548
|
visualElement === null || visualElement === void 0 ? void 0 : visualElement.render();
|
|
@@ -3630,11 +3684,12 @@
|
|
|
3630
3684
|
node.hasListeners("didUpdate")) {
|
|
3631
3685
|
const { layoutBox: layout, measuredBox: measuredLayout } = node.layout;
|
|
3632
3686
|
const { animationType } = node.options;
|
|
3687
|
+
const isShared = snapshot.source !== node.layout.source;
|
|
3633
3688
|
// TODO Maybe we want to also resize the layout snapshot so we don't trigger
|
|
3634
3689
|
// animations for instance if layout="size" and an element has only changed position
|
|
3635
3690
|
if (animationType === "size") {
|
|
3636
3691
|
eachAxis((axis) => {
|
|
3637
|
-
const axisSnapshot =
|
|
3692
|
+
const axisSnapshot = isShared
|
|
3638
3693
|
? snapshot.measuredBox[axis]
|
|
3639
3694
|
: snapshot.layoutBox[axis];
|
|
3640
3695
|
const length = calcLength(axisSnapshot);
|
|
@@ -3644,7 +3699,7 @@
|
|
|
3644
3699
|
}
|
|
3645
3700
|
else if (shouldAnimatePositionOnly(animationType, snapshot.layoutBox, layout)) {
|
|
3646
3701
|
eachAxis((axis) => {
|
|
3647
|
-
const axisSnapshot =
|
|
3702
|
+
const axisSnapshot = isShared
|
|
3648
3703
|
? snapshot.measuredBox[axis]
|
|
3649
3704
|
: snapshot.layoutBox[axis];
|
|
3650
3705
|
const length = calcLength(layout[axis]);
|
|
@@ -3654,7 +3709,7 @@
|
|
|
3654
3709
|
const layoutDelta = createDelta();
|
|
3655
3710
|
calcBoxDelta(layoutDelta, layout, snapshot.layoutBox);
|
|
3656
3711
|
const visualDelta = createDelta();
|
|
3657
|
-
if (
|
|
3712
|
+
if (isShared) {
|
|
3658
3713
|
calcBoxDelta(visualDelta, node.applyTransform(measuredLayout, true), snapshot.measuredBox);
|
|
3659
3714
|
}
|
|
3660
3715
|
else {
|
|
@@ -3750,7 +3805,7 @@
|
|
|
3750
3805
|
duration: 0.45,
|
|
3751
3806
|
ease: [0.4, 0, 0.1, 1],
|
|
3752
3807
|
};
|
|
3753
|
-
function mountNodeEarly(node,
|
|
3808
|
+
function mountNodeEarly(node, elementId) {
|
|
3754
3809
|
/**
|
|
3755
3810
|
* Rather than searching the DOM from document we can search the
|
|
3756
3811
|
* path for the deepest mounted ancestor and search from there
|
|
@@ -3763,7 +3818,7 @@
|
|
|
3763
3818
|
}
|
|
3764
3819
|
}
|
|
3765
3820
|
const searchElement = searchNode && searchNode !== node.root ? searchNode.instance : document;
|
|
3766
|
-
const element = searchElement.querySelector(`[data-projection-id="${
|
|
3821
|
+
const element = searchElement.querySelector(`[data-projection-id="${elementId}"]`);
|
|
3767
3822
|
if (element)
|
|
3768
3823
|
node.mount(element, true);
|
|
3769
3824
|
}
|
|
@@ -4742,7 +4797,7 @@
|
|
|
4742
4797
|
* and warn against mismatches.
|
|
4743
4798
|
*/
|
|
4744
4799
|
{
|
|
4745
|
-
warnOnce(nextValue.version === "7.6.
|
|
4800
|
+
warnOnce(nextValue.version === "7.6.9", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.6.9 may not work as expected.`);
|
|
4746
4801
|
}
|
|
4747
4802
|
}
|
|
4748
4803
|
else if (isMotionValue(prevValue)) {
|
|
@@ -4944,10 +4999,14 @@
|
|
|
4944
4999
|
this.current = null;
|
|
4945
5000
|
}
|
|
4946
5001
|
bindToMotionValue(key, value) {
|
|
5002
|
+
const valueIsTransform = transformProps.has(key);
|
|
4947
5003
|
const removeOnChange = value.onChange((latestValue) => {
|
|
4948
5004
|
this.latestValues[key] = latestValue;
|
|
4949
5005
|
this.props.onUpdate &&
|
|
4950
5006
|
sync.update(this.notifyUpdate, false, true);
|
|
5007
|
+
if (valueIsTransform && this.projection) {
|
|
5008
|
+
this.projection.isProjectionDirty = true;
|
|
5009
|
+
}
|
|
4951
5010
|
});
|
|
4952
5011
|
const removeOnRenderRequest = value.onRenderRequest(this.scheduleRender);
|
|
4953
5012
|
this.valueSubscriptions.set(key, () => {
|