framer-motion 7.6.6 → 7.6.8
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 +94 -67
- package/dist/es/projection/geometry/delta-apply.mjs +4 -1
- package/dist/es/projection/node/create-projection-node.mjs +73 -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 +0 -11
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/value/index.mjs +1 -1
- package/dist/framer-motion.dev.js +94 -67
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +15 -4
- package/dist/projection.dev.js +90 -63
- 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 +15 -4
- package/package.json +5 -5
package/dist/cjs/index.js
CHANGED
|
@@ -254,11 +254,11 @@ const globalProjectionState = {
|
|
|
254
254
|
hasEverUpdated: false,
|
|
255
255
|
};
|
|
256
256
|
|
|
257
|
-
let id$
|
|
257
|
+
let id$2 = 1;
|
|
258
258
|
function useProjectionId() {
|
|
259
259
|
return useConstant(() => {
|
|
260
260
|
if (globalProjectionState.hasEverUpdated) {
|
|
261
|
-
return id$
|
|
261
|
+
return id$2++;
|
|
262
262
|
}
|
|
263
263
|
});
|
|
264
264
|
}
|
|
@@ -2258,7 +2258,7 @@ class MotionValue {
|
|
|
2258
2258
|
* This will be replaced by the build step with the latest version number.
|
|
2259
2259
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
2260
2260
|
*/
|
|
2261
|
-
this.version = "7.6.
|
|
2261
|
+
this.version = "7.6.8";
|
|
2262
2262
|
/**
|
|
2263
2263
|
* Duration, in milliseconds, since last updating frame.
|
|
2264
2264
|
*
|
|
@@ -3615,7 +3615,10 @@ function applyTreeDeltas(box, treeScale, treePath, isSharedTransition = false) {
|
|
|
3615
3615
|
node.options.layoutScroll &&
|
|
3616
3616
|
node.scroll &&
|
|
3617
3617
|
node !== node.root) {
|
|
3618
|
-
transformBox(box, {
|
|
3618
|
+
transformBox(box, {
|
|
3619
|
+
x: -node.scroll.offset.x,
|
|
3620
|
+
y: -node.scroll.offset.y,
|
|
3621
|
+
});
|
|
3619
3622
|
}
|
|
3620
3623
|
if (delta) {
|
|
3621
3624
|
// Incoporate each ancestor's scale into a culmulative treeScale for this component
|
|
@@ -3664,8 +3667,8 @@ function measurePageBox(element, rootProjectionNode, transformPagePoint) {
|
|
|
3664
3667
|
const viewportBox = measureViewportBox(element, transformPagePoint);
|
|
3665
3668
|
const { scroll } = rootProjectionNode;
|
|
3666
3669
|
if (scroll) {
|
|
3667
|
-
translateAxis(viewportBox.x, scroll.x);
|
|
3668
|
-
translateAxis(viewportBox.y, scroll.y);
|
|
3670
|
+
translateAxis(viewportBox.x, scroll.offset.x);
|
|
3671
|
+
translateAxis(viewportBox.y, scroll.offset.y);
|
|
3669
3672
|
}
|
|
3670
3673
|
return viewportBox;
|
|
3671
3674
|
}
|
|
@@ -4521,7 +4524,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
4521
4524
|
* and warn against mismatches.
|
|
4522
4525
|
*/
|
|
4523
4526
|
if (process.env.NODE_ENV === "development") {
|
|
4524
|
-
warnOnce(nextValue.version === "7.6.
|
|
4527
|
+
warnOnce(nextValue.version === "7.6.8", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.6.8 may not work as expected.`);
|
|
4525
4528
|
}
|
|
4526
4529
|
}
|
|
4527
4530
|
else if (isMotionValue(prevValue)) {
|
|
@@ -4675,17 +4678,6 @@ class VisualElement {
|
|
|
4675
4678
|
}
|
|
4676
4679
|
}
|
|
4677
4680
|
}
|
|
4678
|
-
/**
|
|
4679
|
-
* Update external values with initial values
|
|
4680
|
-
*/
|
|
4681
|
-
if (props.values) {
|
|
4682
|
-
for (const key in props.values) {
|
|
4683
|
-
const value = props.values[key];
|
|
4684
|
-
if (latestValues[key] !== undefined && isMotionValue(value)) {
|
|
4685
|
-
value.set(latestValues[key]);
|
|
4686
|
-
}
|
|
4687
|
-
}
|
|
4688
|
-
}
|
|
4689
4681
|
}
|
|
4690
4682
|
/**
|
|
4691
4683
|
* This method takes React props and returns found MotionValues. For example, HTML
|
|
@@ -5610,7 +5602,6 @@ class NodeStack {
|
|
|
5610
5602
|
node.snapshot = prevLead.snapshot;
|
|
5611
5603
|
node.snapshot.latestValues =
|
|
5612
5604
|
prevLead.animationValues || prevLead.latestValues;
|
|
5613
|
-
node.snapshot.isShared = true;
|
|
5614
5605
|
}
|
|
5615
5606
|
if ((_a = node.root) === null || _a === void 0 ? void 0 : _a.isUpdating) {
|
|
5616
5607
|
node.isLayoutDirty = true;
|
|
@@ -5656,8 +5647,8 @@ class NodeStack {
|
|
|
5656
5647
|
}
|
|
5657
5648
|
}
|
|
5658
5649
|
|
|
5659
|
-
const identityProjection = "translate3d(0px, 0px, 0) scale(1, 1) scale(1, 1)";
|
|
5660
5650
|
function buildProjectionTransform(delta, treeScale, latestTransform) {
|
|
5651
|
+
let transform = "";
|
|
5661
5652
|
/**
|
|
5662
5653
|
* The translations we use to calculate are always relative to the viewport coordinate space.
|
|
5663
5654
|
* But when we apply scales, we also scale the coordinate space of an element and its children.
|
|
@@ -5666,12 +5657,16 @@ function buildProjectionTransform(delta, treeScale, latestTransform) {
|
|
|
5666
5657
|
*/
|
|
5667
5658
|
const xTranslate = delta.x.translate / treeScale.x;
|
|
5668
5659
|
const yTranslate = delta.y.translate / treeScale.y;
|
|
5669
|
-
|
|
5660
|
+
if (xTranslate || yTranslate) {
|
|
5661
|
+
transform = `translate3d(${xTranslate}px, ${yTranslate}px, 0) `;
|
|
5662
|
+
}
|
|
5670
5663
|
/**
|
|
5671
5664
|
* Apply scale correction for the tree transform.
|
|
5672
5665
|
* This will apply scale to the screen-orientated axes.
|
|
5673
5666
|
*/
|
|
5674
|
-
|
|
5667
|
+
if (treeScale.x !== 1 || treeScale.y !== 1) {
|
|
5668
|
+
transform += `scale(${1 / treeScale.x}, ${1 / treeScale.y}) `;
|
|
5669
|
+
}
|
|
5675
5670
|
if (latestTransform) {
|
|
5676
5671
|
const { rotate, rotateX, rotateY } = latestTransform;
|
|
5677
5672
|
if (rotate)
|
|
@@ -5687,8 +5682,10 @@ function buildProjectionTransform(delta, treeScale, latestTransform) {
|
|
|
5687
5682
|
*/
|
|
5688
5683
|
const elementScaleX = delta.x.scale * treeScale.x;
|
|
5689
5684
|
const elementScaleY = delta.y.scale * treeScale.y;
|
|
5690
|
-
|
|
5691
|
-
|
|
5685
|
+
if (elementScaleX !== 1 || elementScaleY !== 1) {
|
|
5686
|
+
transform += `scale(${elementScaleX}, ${elementScaleY})`;
|
|
5687
|
+
}
|
|
5688
|
+
return transform || "none";
|
|
5692
5689
|
}
|
|
5693
5690
|
|
|
5694
5691
|
const compareByDepth = (a, b) => a.depth - b.depth;
|
|
@@ -5719,9 +5716,18 @@ const transformAxes = ["", "X", "Y", "Z"];
|
|
|
5719
5716
|
* which has a noticeable difference in spring animations
|
|
5720
5717
|
*/
|
|
5721
5718
|
const animationTarget = 1000;
|
|
5719
|
+
let id$1 = 0;
|
|
5722
5720
|
function createProjectionNode({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform, }) {
|
|
5723
5721
|
return class ProjectionNode {
|
|
5724
5722
|
constructor(elementId, latestValues = {}, parent = defaultParent === null || defaultParent === void 0 ? void 0 : defaultParent()) {
|
|
5723
|
+
/**
|
|
5724
|
+
* A unique ID generated for every projection node.
|
|
5725
|
+
*/
|
|
5726
|
+
this.id = id$1++;
|
|
5727
|
+
/**
|
|
5728
|
+
* An id that represents a unique session instigated by startUpdate.
|
|
5729
|
+
*/
|
|
5730
|
+
this.animationId = 0;
|
|
5725
5731
|
/**
|
|
5726
5732
|
* A Set containing all this component's children. This is used to iterate
|
|
5727
5733
|
* through the children.
|
|
@@ -5830,8 +5836,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
5830
5836
|
hasListeners(name) {
|
|
5831
5837
|
return this.eventHandlers.has(name);
|
|
5832
5838
|
}
|
|
5833
|
-
registerPotentialNode(
|
|
5834
|
-
this.potentialNodes.set(
|
|
5839
|
+
registerPotentialNode(elementId, node) {
|
|
5840
|
+
this.potentialNodes.set(elementId, node);
|
|
5835
5841
|
}
|
|
5836
5842
|
/**
|
|
5837
5843
|
* Lifecycles
|
|
@@ -5964,6 +5970,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
5964
5970
|
return;
|
|
5965
5971
|
this.isUpdating = true;
|
|
5966
5972
|
(_a = this.nodes) === null || _a === void 0 ? void 0 : _a.forEach(resetRotation);
|
|
5973
|
+
this.animationId++;
|
|
5967
5974
|
}
|
|
5968
5975
|
willUpdate(shouldNotifyListeners = true) {
|
|
5969
5976
|
var _a, _b, _c;
|
|
@@ -5978,11 +5985,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
5978
5985
|
for (let i = 0; i < this.path.length; i++) {
|
|
5979
5986
|
const node = this.path[i];
|
|
5980
5987
|
node.shouldResetTransform = true;
|
|
5981
|
-
|
|
5982
|
-
* TODO: Check we haven't updated the scroll
|
|
5983
|
-
* since the last didUpdate
|
|
5984
|
-
*/
|
|
5985
|
-
node.updateScroll();
|
|
5988
|
+
node.updateScroll("snapshot");
|
|
5986
5989
|
}
|
|
5987
5990
|
const { layoutId, layout } = this.options;
|
|
5988
5991
|
if (layoutId === undefined && !layout)
|
|
@@ -6098,10 +6101,20 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6098
6101
|
this.notifyListeners("measure", this.layout.layoutBox);
|
|
6099
6102
|
(_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);
|
|
6100
6103
|
}
|
|
6101
|
-
updateScroll() {
|
|
6102
|
-
|
|
6103
|
-
|
|
6104
|
-
this.scroll
|
|
6104
|
+
updateScroll(phase = "measure") {
|
|
6105
|
+
let needsMeasurement = Boolean(this.options.layoutScroll && this.instance);
|
|
6106
|
+
if (this.scroll &&
|
|
6107
|
+
this.scroll.animationId === this.root.animationId &&
|
|
6108
|
+
this.scroll.phase === phase) {
|
|
6109
|
+
needsMeasurement = false;
|
|
6110
|
+
}
|
|
6111
|
+
if (needsMeasurement) {
|
|
6112
|
+
this.scroll = {
|
|
6113
|
+
animationId: this.root.animationId,
|
|
6114
|
+
phase,
|
|
6115
|
+
isRoot: checkIsScrollRoot(this.instance),
|
|
6116
|
+
offset: measureScroll(this.instance),
|
|
6117
|
+
};
|
|
6105
6118
|
}
|
|
6106
6119
|
}
|
|
6107
6120
|
resetTransform() {
|
|
@@ -6123,6 +6136,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6123
6136
|
}
|
|
6124
6137
|
}
|
|
6125
6138
|
measure(removeTransform = true) {
|
|
6139
|
+
var _a;
|
|
6126
6140
|
const pageBox = this.measurePageBox();
|
|
6127
6141
|
let layoutBox = this.removeElementScroll(pageBox);
|
|
6128
6142
|
/**
|
|
@@ -6134,10 +6148,17 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6134
6148
|
layoutBox = this.removeTransform(layoutBox);
|
|
6135
6149
|
}
|
|
6136
6150
|
roundBox(layoutBox);
|
|
6151
|
+
const positionStyle = (_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.readValue("position");
|
|
6152
|
+
const position = positionStyle === "fixed" || positionStyle === "sticky"
|
|
6153
|
+
? positionStyle
|
|
6154
|
+
: "static";
|
|
6137
6155
|
return {
|
|
6156
|
+
animationId: this.root.animationId,
|
|
6138
6157
|
measuredBox: pageBox,
|
|
6139
6158
|
layoutBox,
|
|
6140
6159
|
latestValues: {},
|
|
6160
|
+
source: this.id,
|
|
6161
|
+
position,
|
|
6141
6162
|
};
|
|
6142
6163
|
}
|
|
6143
6164
|
measurePageBox() {
|
|
@@ -6148,8 +6169,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6148
6169
|
// Remove viewport scroll to give page-relative coordinates
|
|
6149
6170
|
const { scroll } = this.root;
|
|
6150
6171
|
if (scroll) {
|
|
6151
|
-
translateAxis(box.x, scroll.x);
|
|
6152
|
-
translateAxis(box.y, scroll.y);
|
|
6172
|
+
translateAxis(box.x, scroll.offset.x);
|
|
6173
|
+
translateAxis(box.y, scroll.offset.y);
|
|
6153
6174
|
}
|
|
6154
6175
|
return box;
|
|
6155
6176
|
}
|
|
@@ -6162,13 +6183,13 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6162
6183
|
*/
|
|
6163
6184
|
for (let i = 0; i < this.path.length; i++) {
|
|
6164
6185
|
const node = this.path[i];
|
|
6165
|
-
const { scroll, options
|
|
6186
|
+
const { scroll, options } = node;
|
|
6166
6187
|
if (node !== this.root && scroll && options.layoutScroll) {
|
|
6167
6188
|
/**
|
|
6168
6189
|
* If this is a new scroll root, we want to remove all previous scrolls
|
|
6169
6190
|
* from the viewport box.
|
|
6170
6191
|
*/
|
|
6171
|
-
if (
|
|
6192
|
+
if (scroll.isRoot) {
|
|
6172
6193
|
copyBoxInto(boxWithoutScroll, box);
|
|
6173
6194
|
const { scroll: rootScroll } = this.root;
|
|
6174
6195
|
/**
|
|
@@ -6176,12 +6197,12 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6176
6197
|
* to the measured bounding box.
|
|
6177
6198
|
*/
|
|
6178
6199
|
if (rootScroll) {
|
|
6179
|
-
translateAxis(boxWithoutScroll.x, -rootScroll.x);
|
|
6180
|
-
translateAxis(boxWithoutScroll.y, -rootScroll.y);
|
|
6200
|
+
translateAxis(boxWithoutScroll.x, -rootScroll.offset.x);
|
|
6201
|
+
translateAxis(boxWithoutScroll.y, -rootScroll.offset.y);
|
|
6181
6202
|
}
|
|
6182
6203
|
}
|
|
6183
|
-
translateAxis(boxWithoutScroll.x, scroll.x);
|
|
6184
|
-
translateAxis(boxWithoutScroll.y, scroll.y);
|
|
6204
|
+
translateAxis(boxWithoutScroll.x, scroll.offset.x);
|
|
6205
|
+
translateAxis(boxWithoutScroll.y, scroll.offset.y);
|
|
6185
6206
|
}
|
|
6186
6207
|
}
|
|
6187
6208
|
return boxWithoutScroll;
|
|
@@ -6196,8 +6217,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6196
6217
|
node.scroll &&
|
|
6197
6218
|
node !== node.root) {
|
|
6198
6219
|
transformBox(withTransforms, {
|
|
6199
|
-
x: -node.scroll.x,
|
|
6200
|
-
y: -node.scroll.y,
|
|
6220
|
+
x: -node.scroll.offset.x,
|
|
6221
|
+
y: -node.scroll.offset.y,
|
|
6201
6222
|
});
|
|
6202
6223
|
}
|
|
6203
6224
|
if (!hasTransform(node.latestValues))
|
|
@@ -6431,7 +6452,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6431
6452
|
}
|
|
6432
6453
|
}
|
|
6433
6454
|
setAnimationOrigin(delta, hasOnlyRelativeTargetChanged = false) {
|
|
6434
|
-
var _a;
|
|
6455
|
+
var _a, _b;
|
|
6435
6456
|
const snapshot = this.snapshot;
|
|
6436
6457
|
const snapshotLatestValues = (snapshot === null || snapshot === void 0 ? void 0 : snapshot.latestValues) || {};
|
|
6437
6458
|
const mixedValues = { ...this.latestValues };
|
|
@@ -6439,8 +6460,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6439
6460
|
this.relativeTarget = this.relativeTargetOrigin = undefined;
|
|
6440
6461
|
this.attemptToResolveRelativeTarget = !hasOnlyRelativeTargetChanged;
|
|
6441
6462
|
const relativeLayout = createBox();
|
|
6442
|
-
const isSharedLayoutAnimation = snapshot === null || snapshot === void 0 ? void 0 : snapshot.
|
|
6443
|
-
const isOnlyMember = (((
|
|
6463
|
+
const isSharedLayoutAnimation = (snapshot === null || snapshot === void 0 ? void 0 : snapshot.source) !== ((_a = this.layout) === null || _a === void 0 ? void 0 : _a.source);
|
|
6464
|
+
const isOnlyMember = (((_b = this.getStack()) === null || _b === void 0 ? void 0 : _b.members.length) || 0) <= 1;
|
|
6444
6465
|
const shouldCrossfadeOpacity = Boolean(isSharedLayoutAnimation &&
|
|
6445
6466
|
!isOnlyMember &&
|
|
6446
6467
|
this.options.crossfade === true &&
|
|
@@ -6621,25 +6642,30 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6621
6642
|
return;
|
|
6622
6643
|
// If there's no detected rotation values, we can early return without a forced render.
|
|
6623
6644
|
let hasRotate = false;
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
continue;
|
|
6634
|
-
}
|
|
6645
|
+
/**
|
|
6646
|
+
* An unrolled check for rotation values. Most elements don't have any rotation and
|
|
6647
|
+
* skipping the nested loop and new object creation is 50% faster.
|
|
6648
|
+
*/
|
|
6649
|
+
const { latestValues } = visualElement;
|
|
6650
|
+
if (latestValues.rotate ||
|
|
6651
|
+
latestValues.rotateX ||
|
|
6652
|
+
latestValues.rotateY ||
|
|
6653
|
+
latestValues.rotateZ) {
|
|
6635
6654
|
hasRotate = true;
|
|
6636
|
-
// Record the rotation and then temporarily set it to 0
|
|
6637
|
-
resetValues[key] = visualElement.getStaticValue(key);
|
|
6638
|
-
visualElement.setStaticValue(key, 0);
|
|
6639
6655
|
}
|
|
6640
6656
|
// If there's no rotation values, we don't need to do any more.
|
|
6641
6657
|
if (!hasRotate)
|
|
6642
6658
|
return;
|
|
6659
|
+
const resetValues = {};
|
|
6660
|
+
// Check the rotate value of all axes and reset to 0
|
|
6661
|
+
for (let i = 0; i < transformAxes.length; i++) {
|
|
6662
|
+
const key = "rotate" + transformAxes[i];
|
|
6663
|
+
// Record the rotation and then temporarily set it to 0
|
|
6664
|
+
if (latestValues[key]) {
|
|
6665
|
+
resetValues[key] = latestValues[key];
|
|
6666
|
+
visualElement.setStaticValue(key, 0);
|
|
6667
|
+
}
|
|
6668
|
+
}
|
|
6643
6669
|
// Force a render of this element to apply the transform with all rotations
|
|
6644
6670
|
// set to 0.
|
|
6645
6671
|
visualElement === null || visualElement === void 0 ? void 0 : visualElement.render();
|
|
@@ -6781,11 +6807,12 @@ function notifyLayoutUpdate(node) {
|
|
|
6781
6807
|
node.hasListeners("didUpdate")) {
|
|
6782
6808
|
const { layoutBox: layout, measuredBox: measuredLayout } = node.layout;
|
|
6783
6809
|
const { animationType } = node.options;
|
|
6810
|
+
const isShared = snapshot.source !== node.layout.source;
|
|
6784
6811
|
// TODO Maybe we want to also resize the layout snapshot so we don't trigger
|
|
6785
6812
|
// animations for instance if layout="size" and an element has only changed position
|
|
6786
6813
|
if (animationType === "size") {
|
|
6787
6814
|
eachAxis((axis) => {
|
|
6788
|
-
const axisSnapshot =
|
|
6815
|
+
const axisSnapshot = isShared
|
|
6789
6816
|
? snapshot.measuredBox[axis]
|
|
6790
6817
|
: snapshot.layoutBox[axis];
|
|
6791
6818
|
const length = calcLength(axisSnapshot);
|
|
@@ -6795,7 +6822,7 @@ function notifyLayoutUpdate(node) {
|
|
|
6795
6822
|
}
|
|
6796
6823
|
else if (shouldAnimatePositionOnly(animationType, snapshot.layoutBox, layout)) {
|
|
6797
6824
|
eachAxis((axis) => {
|
|
6798
|
-
const axisSnapshot =
|
|
6825
|
+
const axisSnapshot = isShared
|
|
6799
6826
|
? snapshot.measuredBox[axis]
|
|
6800
6827
|
: snapshot.layoutBox[axis];
|
|
6801
6828
|
const length = calcLength(layout[axis]);
|
|
@@ -6805,7 +6832,7 @@ function notifyLayoutUpdate(node) {
|
|
|
6805
6832
|
const layoutDelta = createDelta();
|
|
6806
6833
|
calcBoxDelta(layoutDelta, layout, snapshot.layoutBox);
|
|
6807
6834
|
const visualDelta = createDelta();
|
|
6808
|
-
if (
|
|
6835
|
+
if (isShared) {
|
|
6809
6836
|
calcBoxDelta(visualDelta, node.applyTransform(measuredLayout, true), snapshot.measuredBox);
|
|
6810
6837
|
}
|
|
6811
6838
|
else {
|
|
@@ -6901,7 +6928,7 @@ const defaultLayoutTransition = {
|
|
|
6901
6928
|
duration: 0.45,
|
|
6902
6929
|
ease: [0.4, 0, 0.1, 1],
|
|
6903
6930
|
};
|
|
6904
|
-
function mountNodeEarly(node,
|
|
6931
|
+
function mountNodeEarly(node, elementId) {
|
|
6905
6932
|
/**
|
|
6906
6933
|
* Rather than searching the DOM from document we can search the
|
|
6907
6934
|
* path for the deepest mounted ancestor and search from there
|
|
@@ -6914,7 +6941,7 @@ function mountNodeEarly(node, id) {
|
|
|
6914
6941
|
}
|
|
6915
6942
|
}
|
|
6916
6943
|
const searchElement = searchNode && searchNode !== node.root ? searchNode.instance : document;
|
|
6917
|
-
const element = searchElement.querySelector(`[data-projection-id="${
|
|
6944
|
+
const element = searchElement.querySelector(`[data-projection-id="${elementId}"]`);
|
|
6918
6945
|
if (element)
|
|
6919
6946
|
node.mount(element, true);
|
|
6920
6947
|
}
|
|
@@ -56,7 +56,10 @@ function applyTreeDeltas(box, treeScale, treePath, isSharedTransition = false) {
|
|
|
56
56
|
node.options.layoutScroll &&
|
|
57
57
|
node.scroll &&
|
|
58
58
|
node !== node.root) {
|
|
59
|
-
transformBox(box, {
|
|
59
|
+
transformBox(box, {
|
|
60
|
+
x: -node.scroll.offset.x,
|
|
61
|
+
y: -node.scroll.offset.y,
|
|
62
|
+
});
|
|
60
63
|
}
|
|
61
64
|
if (delta) {
|
|
62
65
|
// Incoporate each ancestor's scale into a culmulative treeScale for this component
|
|
@@ -26,9 +26,18 @@ const transformAxes = ["", "X", "Y", "Z"];
|
|
|
26
26
|
* which has a noticeable difference in spring animations
|
|
27
27
|
*/
|
|
28
28
|
const animationTarget = 1000;
|
|
29
|
+
let id = 0;
|
|
29
30
|
function createProjectionNode({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform, }) {
|
|
30
31
|
return class ProjectionNode {
|
|
31
32
|
constructor(elementId, latestValues = {}, parent = defaultParent === null || defaultParent === void 0 ? void 0 : defaultParent()) {
|
|
33
|
+
/**
|
|
34
|
+
* A unique ID generated for every projection node.
|
|
35
|
+
*/
|
|
36
|
+
this.id = id++;
|
|
37
|
+
/**
|
|
38
|
+
* An id that represents a unique session instigated by startUpdate.
|
|
39
|
+
*/
|
|
40
|
+
this.animationId = 0;
|
|
32
41
|
/**
|
|
33
42
|
* A Set containing all this component's children. This is used to iterate
|
|
34
43
|
* through the children.
|
|
@@ -137,8 +146,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
137
146
|
hasListeners(name) {
|
|
138
147
|
return this.eventHandlers.has(name);
|
|
139
148
|
}
|
|
140
|
-
registerPotentialNode(
|
|
141
|
-
this.potentialNodes.set(
|
|
149
|
+
registerPotentialNode(elementId, node) {
|
|
150
|
+
this.potentialNodes.set(elementId, node);
|
|
142
151
|
}
|
|
143
152
|
/**
|
|
144
153
|
* Lifecycles
|
|
@@ -271,6 +280,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
271
280
|
return;
|
|
272
281
|
this.isUpdating = true;
|
|
273
282
|
(_a = this.nodes) === null || _a === void 0 ? void 0 : _a.forEach(resetRotation);
|
|
283
|
+
this.animationId++;
|
|
274
284
|
}
|
|
275
285
|
willUpdate(shouldNotifyListeners = true) {
|
|
276
286
|
var _a, _b, _c;
|
|
@@ -285,11 +295,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
285
295
|
for (let i = 0; i < this.path.length; i++) {
|
|
286
296
|
const node = this.path[i];
|
|
287
297
|
node.shouldResetTransform = true;
|
|
288
|
-
|
|
289
|
-
* TODO: Check we haven't updated the scroll
|
|
290
|
-
* since the last didUpdate
|
|
291
|
-
*/
|
|
292
|
-
node.updateScroll();
|
|
298
|
+
node.updateScroll("snapshot");
|
|
293
299
|
}
|
|
294
300
|
const { layoutId, layout } = this.options;
|
|
295
301
|
if (layoutId === undefined && !layout)
|
|
@@ -405,10 +411,20 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
405
411
|
this.notifyListeners("measure", this.layout.layoutBox);
|
|
406
412
|
(_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);
|
|
407
413
|
}
|
|
408
|
-
updateScroll() {
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
this.scroll
|
|
414
|
+
updateScroll(phase = "measure") {
|
|
415
|
+
let needsMeasurement = Boolean(this.options.layoutScroll && this.instance);
|
|
416
|
+
if (this.scroll &&
|
|
417
|
+
this.scroll.animationId === this.root.animationId &&
|
|
418
|
+
this.scroll.phase === phase) {
|
|
419
|
+
needsMeasurement = false;
|
|
420
|
+
}
|
|
421
|
+
if (needsMeasurement) {
|
|
422
|
+
this.scroll = {
|
|
423
|
+
animationId: this.root.animationId,
|
|
424
|
+
phase,
|
|
425
|
+
isRoot: checkIsScrollRoot(this.instance),
|
|
426
|
+
offset: measureScroll(this.instance),
|
|
427
|
+
};
|
|
412
428
|
}
|
|
413
429
|
}
|
|
414
430
|
resetTransform() {
|
|
@@ -430,6 +446,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
430
446
|
}
|
|
431
447
|
}
|
|
432
448
|
measure(removeTransform = true) {
|
|
449
|
+
var _a;
|
|
433
450
|
const pageBox = this.measurePageBox();
|
|
434
451
|
let layoutBox = this.removeElementScroll(pageBox);
|
|
435
452
|
/**
|
|
@@ -441,10 +458,17 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
441
458
|
layoutBox = this.removeTransform(layoutBox);
|
|
442
459
|
}
|
|
443
460
|
roundBox(layoutBox);
|
|
461
|
+
const positionStyle = (_a = this.options.visualElement) === null || _a === void 0 ? void 0 : _a.readValue("position");
|
|
462
|
+
const position = positionStyle === "fixed" || positionStyle === "sticky"
|
|
463
|
+
? positionStyle
|
|
464
|
+
: "static";
|
|
444
465
|
return {
|
|
466
|
+
animationId: this.root.animationId,
|
|
445
467
|
measuredBox: pageBox,
|
|
446
468
|
layoutBox,
|
|
447
469
|
latestValues: {},
|
|
470
|
+
source: this.id,
|
|
471
|
+
position,
|
|
448
472
|
};
|
|
449
473
|
}
|
|
450
474
|
measurePageBox() {
|
|
@@ -455,8 +479,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
455
479
|
// Remove viewport scroll to give page-relative coordinates
|
|
456
480
|
const { scroll } = this.root;
|
|
457
481
|
if (scroll) {
|
|
458
|
-
translateAxis(box.x, scroll.x);
|
|
459
|
-
translateAxis(box.y, scroll.y);
|
|
482
|
+
translateAxis(box.x, scroll.offset.x);
|
|
483
|
+
translateAxis(box.y, scroll.offset.y);
|
|
460
484
|
}
|
|
461
485
|
return box;
|
|
462
486
|
}
|
|
@@ -469,13 +493,13 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
469
493
|
*/
|
|
470
494
|
for (let i = 0; i < this.path.length; i++) {
|
|
471
495
|
const node = this.path[i];
|
|
472
|
-
const { scroll, options
|
|
496
|
+
const { scroll, options } = node;
|
|
473
497
|
if (node !== this.root && scroll && options.layoutScroll) {
|
|
474
498
|
/**
|
|
475
499
|
* If this is a new scroll root, we want to remove all previous scrolls
|
|
476
500
|
* from the viewport box.
|
|
477
501
|
*/
|
|
478
|
-
if (
|
|
502
|
+
if (scroll.isRoot) {
|
|
479
503
|
copyBoxInto(boxWithoutScroll, box);
|
|
480
504
|
const { scroll: rootScroll } = this.root;
|
|
481
505
|
/**
|
|
@@ -483,12 +507,12 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
483
507
|
* to the measured bounding box.
|
|
484
508
|
*/
|
|
485
509
|
if (rootScroll) {
|
|
486
|
-
translateAxis(boxWithoutScroll.x, -rootScroll.x);
|
|
487
|
-
translateAxis(boxWithoutScroll.y, -rootScroll.y);
|
|
510
|
+
translateAxis(boxWithoutScroll.x, -rootScroll.offset.x);
|
|
511
|
+
translateAxis(boxWithoutScroll.y, -rootScroll.offset.y);
|
|
488
512
|
}
|
|
489
513
|
}
|
|
490
|
-
translateAxis(boxWithoutScroll.x, scroll.x);
|
|
491
|
-
translateAxis(boxWithoutScroll.y, scroll.y);
|
|
514
|
+
translateAxis(boxWithoutScroll.x, scroll.offset.x);
|
|
515
|
+
translateAxis(boxWithoutScroll.y, scroll.offset.y);
|
|
492
516
|
}
|
|
493
517
|
}
|
|
494
518
|
return boxWithoutScroll;
|
|
@@ -503,8 +527,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
503
527
|
node.scroll &&
|
|
504
528
|
node !== node.root) {
|
|
505
529
|
transformBox(withTransforms, {
|
|
506
|
-
x: -node.scroll.x,
|
|
507
|
-
y: -node.scroll.y,
|
|
530
|
+
x: -node.scroll.offset.x,
|
|
531
|
+
y: -node.scroll.offset.y,
|
|
508
532
|
});
|
|
509
533
|
}
|
|
510
534
|
if (!hasTransform(node.latestValues))
|
|
@@ -738,7 +762,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
738
762
|
}
|
|
739
763
|
}
|
|
740
764
|
setAnimationOrigin(delta, hasOnlyRelativeTargetChanged = false) {
|
|
741
|
-
var _a;
|
|
765
|
+
var _a, _b;
|
|
742
766
|
const snapshot = this.snapshot;
|
|
743
767
|
const snapshotLatestValues = (snapshot === null || snapshot === void 0 ? void 0 : snapshot.latestValues) || {};
|
|
744
768
|
const mixedValues = { ...this.latestValues };
|
|
@@ -746,8 +770,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
746
770
|
this.relativeTarget = this.relativeTargetOrigin = undefined;
|
|
747
771
|
this.attemptToResolveRelativeTarget = !hasOnlyRelativeTargetChanged;
|
|
748
772
|
const relativeLayout = createBox();
|
|
749
|
-
const isSharedLayoutAnimation = snapshot === null || snapshot === void 0 ? void 0 : snapshot.
|
|
750
|
-
const isOnlyMember = (((
|
|
773
|
+
const isSharedLayoutAnimation = (snapshot === null || snapshot === void 0 ? void 0 : snapshot.source) !== ((_a = this.layout) === null || _a === void 0 ? void 0 : _a.source);
|
|
774
|
+
const isOnlyMember = (((_b = this.getStack()) === null || _b === void 0 ? void 0 : _b.members.length) || 0) <= 1;
|
|
751
775
|
const shouldCrossfadeOpacity = Boolean(isSharedLayoutAnimation &&
|
|
752
776
|
!isOnlyMember &&
|
|
753
777
|
this.options.crossfade === true &&
|
|
@@ -928,25 +952,30 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
928
952
|
return;
|
|
929
953
|
// If there's no detected rotation values, we can early return without a forced render.
|
|
930
954
|
let hasRotate = false;
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
continue;
|
|
941
|
-
}
|
|
955
|
+
/**
|
|
956
|
+
* An unrolled check for rotation values. Most elements don't have any rotation and
|
|
957
|
+
* skipping the nested loop and new object creation is 50% faster.
|
|
958
|
+
*/
|
|
959
|
+
const { latestValues } = visualElement;
|
|
960
|
+
if (latestValues.rotate ||
|
|
961
|
+
latestValues.rotateX ||
|
|
962
|
+
latestValues.rotateY ||
|
|
963
|
+
latestValues.rotateZ) {
|
|
942
964
|
hasRotate = true;
|
|
943
|
-
// Record the rotation and then temporarily set it to 0
|
|
944
|
-
resetValues[key] = visualElement.getStaticValue(key);
|
|
945
|
-
visualElement.setStaticValue(key, 0);
|
|
946
965
|
}
|
|
947
966
|
// If there's no rotation values, we don't need to do any more.
|
|
948
967
|
if (!hasRotate)
|
|
949
968
|
return;
|
|
969
|
+
const resetValues = {};
|
|
970
|
+
// Check the rotate value of all axes and reset to 0
|
|
971
|
+
for (let i = 0; i < transformAxes.length; i++) {
|
|
972
|
+
const key = "rotate" + transformAxes[i];
|
|
973
|
+
// Record the rotation and then temporarily set it to 0
|
|
974
|
+
if (latestValues[key]) {
|
|
975
|
+
resetValues[key] = latestValues[key];
|
|
976
|
+
visualElement.setStaticValue(key, 0);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
950
979
|
// Force a render of this element to apply the transform with all rotations
|
|
951
980
|
// set to 0.
|
|
952
981
|
visualElement === null || visualElement === void 0 ? void 0 : visualElement.render();
|
|
@@ -1088,11 +1117,12 @@ function notifyLayoutUpdate(node) {
|
|
|
1088
1117
|
node.hasListeners("didUpdate")) {
|
|
1089
1118
|
const { layoutBox: layout, measuredBox: measuredLayout } = node.layout;
|
|
1090
1119
|
const { animationType } = node.options;
|
|
1120
|
+
const isShared = snapshot.source !== node.layout.source;
|
|
1091
1121
|
// TODO Maybe we want to also resize the layout snapshot so we don't trigger
|
|
1092
1122
|
// animations for instance if layout="size" and an element has only changed position
|
|
1093
1123
|
if (animationType === "size") {
|
|
1094
1124
|
eachAxis((axis) => {
|
|
1095
|
-
const axisSnapshot =
|
|
1125
|
+
const axisSnapshot = isShared
|
|
1096
1126
|
? snapshot.measuredBox[axis]
|
|
1097
1127
|
: snapshot.layoutBox[axis];
|
|
1098
1128
|
const length = calcLength(axisSnapshot);
|
|
@@ -1102,7 +1132,7 @@ function notifyLayoutUpdate(node) {
|
|
|
1102
1132
|
}
|
|
1103
1133
|
else if (shouldAnimatePositionOnly(animationType, snapshot.layoutBox, layout)) {
|
|
1104
1134
|
eachAxis((axis) => {
|
|
1105
|
-
const axisSnapshot =
|
|
1135
|
+
const axisSnapshot = isShared
|
|
1106
1136
|
? snapshot.measuredBox[axis]
|
|
1107
1137
|
: snapshot.layoutBox[axis];
|
|
1108
1138
|
const length = calcLength(layout[axis]);
|
|
@@ -1112,7 +1142,7 @@ function notifyLayoutUpdate(node) {
|
|
|
1112
1142
|
const layoutDelta = createDelta();
|
|
1113
1143
|
calcBoxDelta(layoutDelta, layout, snapshot.layoutBox);
|
|
1114
1144
|
const visualDelta = createDelta();
|
|
1115
|
-
if (
|
|
1145
|
+
if (isShared) {
|
|
1116
1146
|
calcBoxDelta(visualDelta, node.applyTransform(measuredLayout, true), snapshot.measuredBox);
|
|
1117
1147
|
}
|
|
1118
1148
|
else {
|
|
@@ -1208,7 +1238,7 @@ const defaultLayoutTransition = {
|
|
|
1208
1238
|
duration: 0.45,
|
|
1209
1239
|
ease: [0.4, 0, 0.1, 1],
|
|
1210
1240
|
};
|
|
1211
|
-
function mountNodeEarly(node,
|
|
1241
|
+
function mountNodeEarly(node, elementId) {
|
|
1212
1242
|
/**
|
|
1213
1243
|
* Rather than searching the DOM from document we can search the
|
|
1214
1244
|
* path for the deepest mounted ancestor and search from there
|
|
@@ -1221,7 +1251,7 @@ function mountNodeEarly(node, id) {
|
|
|
1221
1251
|
}
|
|
1222
1252
|
}
|
|
1223
1253
|
const searchElement = searchNode && searchNode !== node.root ? searchNode.instance : document;
|
|
1224
|
-
const element = searchElement.querySelector(`[data-projection-id="${
|
|
1254
|
+
const element = searchElement.querySelector(`[data-projection-id="${elementId}"]`);
|
|
1225
1255
|
if (element)
|
|
1226
1256
|
node.mount(element, true);
|
|
1227
1257
|
}
|