framer-motion 7.6.7 → 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 -56
- 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/utils/motion-values.mjs +1 -1
- package/dist/es/value/index.mjs +1 -1
- package/dist/framer-motion.dev.js +94 -56
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +15 -4
- package/dist/projection.dev.js +90 -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-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)) {
|
|
@@ -5599,7 +5602,6 @@ class NodeStack {
|
|
|
5599
5602
|
node.snapshot = prevLead.snapshot;
|
|
5600
5603
|
node.snapshot.latestValues =
|
|
5601
5604
|
prevLead.animationValues || prevLead.latestValues;
|
|
5602
|
-
node.snapshot.isShared = true;
|
|
5603
5605
|
}
|
|
5604
5606
|
if ((_a = node.root) === null || _a === void 0 ? void 0 : _a.isUpdating) {
|
|
5605
5607
|
node.isLayoutDirty = true;
|
|
@@ -5645,8 +5647,8 @@ class NodeStack {
|
|
|
5645
5647
|
}
|
|
5646
5648
|
}
|
|
5647
5649
|
|
|
5648
|
-
const identityProjection = "translate3d(0px, 0px, 0) scale(1, 1) scale(1, 1)";
|
|
5649
5650
|
function buildProjectionTransform(delta, treeScale, latestTransform) {
|
|
5651
|
+
let transform = "";
|
|
5650
5652
|
/**
|
|
5651
5653
|
* The translations we use to calculate are always relative to the viewport coordinate space.
|
|
5652
5654
|
* But when we apply scales, we also scale the coordinate space of an element and its children.
|
|
@@ -5655,12 +5657,16 @@ function buildProjectionTransform(delta, treeScale, latestTransform) {
|
|
|
5655
5657
|
*/
|
|
5656
5658
|
const xTranslate = delta.x.translate / treeScale.x;
|
|
5657
5659
|
const yTranslate = delta.y.translate / treeScale.y;
|
|
5658
|
-
|
|
5660
|
+
if (xTranslate || yTranslate) {
|
|
5661
|
+
transform = `translate3d(${xTranslate}px, ${yTranslate}px, 0) `;
|
|
5662
|
+
}
|
|
5659
5663
|
/**
|
|
5660
5664
|
* Apply scale correction for the tree transform.
|
|
5661
5665
|
* This will apply scale to the screen-orientated axes.
|
|
5662
5666
|
*/
|
|
5663
|
-
|
|
5667
|
+
if (treeScale.x !== 1 || treeScale.y !== 1) {
|
|
5668
|
+
transform += `scale(${1 / treeScale.x}, ${1 / treeScale.y}) `;
|
|
5669
|
+
}
|
|
5664
5670
|
if (latestTransform) {
|
|
5665
5671
|
const { rotate, rotateX, rotateY } = latestTransform;
|
|
5666
5672
|
if (rotate)
|
|
@@ -5676,8 +5682,10 @@ function buildProjectionTransform(delta, treeScale, latestTransform) {
|
|
|
5676
5682
|
*/
|
|
5677
5683
|
const elementScaleX = delta.x.scale * treeScale.x;
|
|
5678
5684
|
const elementScaleY = delta.y.scale * treeScale.y;
|
|
5679
|
-
|
|
5680
|
-
|
|
5685
|
+
if (elementScaleX !== 1 || elementScaleY !== 1) {
|
|
5686
|
+
transform += `scale(${elementScaleX}, ${elementScaleY})`;
|
|
5687
|
+
}
|
|
5688
|
+
return transform || "none";
|
|
5681
5689
|
}
|
|
5682
5690
|
|
|
5683
5691
|
const compareByDepth = (a, b) => a.depth - b.depth;
|
|
@@ -5708,9 +5716,18 @@ const transformAxes = ["", "X", "Y", "Z"];
|
|
|
5708
5716
|
* which has a noticeable difference in spring animations
|
|
5709
5717
|
*/
|
|
5710
5718
|
const animationTarget = 1000;
|
|
5719
|
+
let id$1 = 0;
|
|
5711
5720
|
function createProjectionNode({ attachResizeListener, defaultParent, measureScroll, checkIsScrollRoot, resetTransform, }) {
|
|
5712
5721
|
return class ProjectionNode {
|
|
5713
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;
|
|
5714
5731
|
/**
|
|
5715
5732
|
* A Set containing all this component's children. This is used to iterate
|
|
5716
5733
|
* through the children.
|
|
@@ -5819,8 +5836,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
5819
5836
|
hasListeners(name) {
|
|
5820
5837
|
return this.eventHandlers.has(name);
|
|
5821
5838
|
}
|
|
5822
|
-
registerPotentialNode(
|
|
5823
|
-
this.potentialNodes.set(
|
|
5839
|
+
registerPotentialNode(elementId, node) {
|
|
5840
|
+
this.potentialNodes.set(elementId, node);
|
|
5824
5841
|
}
|
|
5825
5842
|
/**
|
|
5826
5843
|
* Lifecycles
|
|
@@ -5953,6 +5970,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
5953
5970
|
return;
|
|
5954
5971
|
this.isUpdating = true;
|
|
5955
5972
|
(_a = this.nodes) === null || _a === void 0 ? void 0 : _a.forEach(resetRotation);
|
|
5973
|
+
this.animationId++;
|
|
5956
5974
|
}
|
|
5957
5975
|
willUpdate(shouldNotifyListeners = true) {
|
|
5958
5976
|
var _a, _b, _c;
|
|
@@ -5967,11 +5985,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
5967
5985
|
for (let i = 0; i < this.path.length; i++) {
|
|
5968
5986
|
const node = this.path[i];
|
|
5969
5987
|
node.shouldResetTransform = true;
|
|
5970
|
-
|
|
5971
|
-
* TODO: Check we haven't updated the scroll
|
|
5972
|
-
* since the last didUpdate
|
|
5973
|
-
*/
|
|
5974
|
-
node.updateScroll();
|
|
5988
|
+
node.updateScroll("snapshot");
|
|
5975
5989
|
}
|
|
5976
5990
|
const { layoutId, layout } = this.options;
|
|
5977
5991
|
if (layoutId === undefined && !layout)
|
|
@@ -6087,10 +6101,20 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6087
6101
|
this.notifyListeners("measure", this.layout.layoutBox);
|
|
6088
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);
|
|
6089
6103
|
}
|
|
6090
|
-
updateScroll() {
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
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
|
+
};
|
|
6094
6118
|
}
|
|
6095
6119
|
}
|
|
6096
6120
|
resetTransform() {
|
|
@@ -6112,6 +6136,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6112
6136
|
}
|
|
6113
6137
|
}
|
|
6114
6138
|
measure(removeTransform = true) {
|
|
6139
|
+
var _a;
|
|
6115
6140
|
const pageBox = this.measurePageBox();
|
|
6116
6141
|
let layoutBox = this.removeElementScroll(pageBox);
|
|
6117
6142
|
/**
|
|
@@ -6123,10 +6148,17 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6123
6148
|
layoutBox = this.removeTransform(layoutBox);
|
|
6124
6149
|
}
|
|
6125
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";
|
|
6126
6155
|
return {
|
|
6156
|
+
animationId: this.root.animationId,
|
|
6127
6157
|
measuredBox: pageBox,
|
|
6128
6158
|
layoutBox,
|
|
6129
6159
|
latestValues: {},
|
|
6160
|
+
source: this.id,
|
|
6161
|
+
position,
|
|
6130
6162
|
};
|
|
6131
6163
|
}
|
|
6132
6164
|
measurePageBox() {
|
|
@@ -6137,8 +6169,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6137
6169
|
// Remove viewport scroll to give page-relative coordinates
|
|
6138
6170
|
const { scroll } = this.root;
|
|
6139
6171
|
if (scroll) {
|
|
6140
|
-
translateAxis(box.x, scroll.x);
|
|
6141
|
-
translateAxis(box.y, scroll.y);
|
|
6172
|
+
translateAxis(box.x, scroll.offset.x);
|
|
6173
|
+
translateAxis(box.y, scroll.offset.y);
|
|
6142
6174
|
}
|
|
6143
6175
|
return box;
|
|
6144
6176
|
}
|
|
@@ -6151,13 +6183,13 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6151
6183
|
*/
|
|
6152
6184
|
for (let i = 0; i < this.path.length; i++) {
|
|
6153
6185
|
const node = this.path[i];
|
|
6154
|
-
const { scroll, options
|
|
6186
|
+
const { scroll, options } = node;
|
|
6155
6187
|
if (node !== this.root && scroll && options.layoutScroll) {
|
|
6156
6188
|
/**
|
|
6157
6189
|
* If this is a new scroll root, we want to remove all previous scrolls
|
|
6158
6190
|
* from the viewport box.
|
|
6159
6191
|
*/
|
|
6160
|
-
if (
|
|
6192
|
+
if (scroll.isRoot) {
|
|
6161
6193
|
copyBoxInto(boxWithoutScroll, box);
|
|
6162
6194
|
const { scroll: rootScroll } = this.root;
|
|
6163
6195
|
/**
|
|
@@ -6165,12 +6197,12 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6165
6197
|
* to the measured bounding box.
|
|
6166
6198
|
*/
|
|
6167
6199
|
if (rootScroll) {
|
|
6168
|
-
translateAxis(boxWithoutScroll.x, -rootScroll.x);
|
|
6169
|
-
translateAxis(boxWithoutScroll.y, -rootScroll.y);
|
|
6200
|
+
translateAxis(boxWithoutScroll.x, -rootScroll.offset.x);
|
|
6201
|
+
translateAxis(boxWithoutScroll.y, -rootScroll.offset.y);
|
|
6170
6202
|
}
|
|
6171
6203
|
}
|
|
6172
|
-
translateAxis(boxWithoutScroll.x, scroll.x);
|
|
6173
|
-
translateAxis(boxWithoutScroll.y, scroll.y);
|
|
6204
|
+
translateAxis(boxWithoutScroll.x, scroll.offset.x);
|
|
6205
|
+
translateAxis(boxWithoutScroll.y, scroll.offset.y);
|
|
6174
6206
|
}
|
|
6175
6207
|
}
|
|
6176
6208
|
return boxWithoutScroll;
|
|
@@ -6185,8 +6217,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6185
6217
|
node.scroll &&
|
|
6186
6218
|
node !== node.root) {
|
|
6187
6219
|
transformBox(withTransforms, {
|
|
6188
|
-
x: -node.scroll.x,
|
|
6189
|
-
y: -node.scroll.y,
|
|
6220
|
+
x: -node.scroll.offset.x,
|
|
6221
|
+
y: -node.scroll.offset.y,
|
|
6190
6222
|
});
|
|
6191
6223
|
}
|
|
6192
6224
|
if (!hasTransform(node.latestValues))
|
|
@@ -6420,7 +6452,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6420
6452
|
}
|
|
6421
6453
|
}
|
|
6422
6454
|
setAnimationOrigin(delta, hasOnlyRelativeTargetChanged = false) {
|
|
6423
|
-
var _a;
|
|
6455
|
+
var _a, _b;
|
|
6424
6456
|
const snapshot = this.snapshot;
|
|
6425
6457
|
const snapshotLatestValues = (snapshot === null || snapshot === void 0 ? void 0 : snapshot.latestValues) || {};
|
|
6426
6458
|
const mixedValues = { ...this.latestValues };
|
|
@@ -6428,8 +6460,8 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6428
6460
|
this.relativeTarget = this.relativeTargetOrigin = undefined;
|
|
6429
6461
|
this.attemptToResolveRelativeTarget = !hasOnlyRelativeTargetChanged;
|
|
6430
6462
|
const relativeLayout = createBox();
|
|
6431
|
-
const isSharedLayoutAnimation = snapshot === null || snapshot === void 0 ? void 0 : snapshot.
|
|
6432
|
-
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;
|
|
6433
6465
|
const shouldCrossfadeOpacity = Boolean(isSharedLayoutAnimation &&
|
|
6434
6466
|
!isOnlyMember &&
|
|
6435
6467
|
this.options.crossfade === true &&
|
|
@@ -6610,25 +6642,30 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6610
6642
|
return;
|
|
6611
6643
|
// If there's no detected rotation values, we can early return without a forced render.
|
|
6612
6644
|
let hasRotate = false;
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
continue;
|
|
6623
|
-
}
|
|
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) {
|
|
6624
6654
|
hasRotate = true;
|
|
6625
|
-
// Record the rotation and then temporarily set it to 0
|
|
6626
|
-
resetValues[key] = visualElement.getStaticValue(key);
|
|
6627
|
-
visualElement.setStaticValue(key, 0);
|
|
6628
6655
|
}
|
|
6629
6656
|
// If there's no rotation values, we don't need to do any more.
|
|
6630
6657
|
if (!hasRotate)
|
|
6631
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
|
+
}
|
|
6632
6669
|
// Force a render of this element to apply the transform with all rotations
|
|
6633
6670
|
// set to 0.
|
|
6634
6671
|
visualElement === null || visualElement === void 0 ? void 0 : visualElement.render();
|
|
@@ -6770,11 +6807,12 @@ function notifyLayoutUpdate(node) {
|
|
|
6770
6807
|
node.hasListeners("didUpdate")) {
|
|
6771
6808
|
const { layoutBox: layout, measuredBox: measuredLayout } = node.layout;
|
|
6772
6809
|
const { animationType } = node.options;
|
|
6810
|
+
const isShared = snapshot.source !== node.layout.source;
|
|
6773
6811
|
// TODO Maybe we want to also resize the layout snapshot so we don't trigger
|
|
6774
6812
|
// animations for instance if layout="size" and an element has only changed position
|
|
6775
6813
|
if (animationType === "size") {
|
|
6776
6814
|
eachAxis((axis) => {
|
|
6777
|
-
const axisSnapshot =
|
|
6815
|
+
const axisSnapshot = isShared
|
|
6778
6816
|
? snapshot.measuredBox[axis]
|
|
6779
6817
|
: snapshot.layoutBox[axis];
|
|
6780
6818
|
const length = calcLength(axisSnapshot);
|
|
@@ -6784,7 +6822,7 @@ function notifyLayoutUpdate(node) {
|
|
|
6784
6822
|
}
|
|
6785
6823
|
else if (shouldAnimatePositionOnly(animationType, snapshot.layoutBox, layout)) {
|
|
6786
6824
|
eachAxis((axis) => {
|
|
6787
|
-
const axisSnapshot =
|
|
6825
|
+
const axisSnapshot = isShared
|
|
6788
6826
|
? snapshot.measuredBox[axis]
|
|
6789
6827
|
: snapshot.layoutBox[axis];
|
|
6790
6828
|
const length = calcLength(layout[axis]);
|
|
@@ -6794,7 +6832,7 @@ function notifyLayoutUpdate(node) {
|
|
|
6794
6832
|
const layoutDelta = createDelta();
|
|
6795
6833
|
calcBoxDelta(layoutDelta, layout, snapshot.layoutBox);
|
|
6796
6834
|
const visualDelta = createDelta();
|
|
6797
|
-
if (
|
|
6835
|
+
if (isShared) {
|
|
6798
6836
|
calcBoxDelta(visualDelta, node.applyTransform(measuredLayout, true), snapshot.measuredBox);
|
|
6799
6837
|
}
|
|
6800
6838
|
else {
|
|
@@ -6890,7 +6928,7 @@ const defaultLayoutTransition = {
|
|
|
6890
6928
|
duration: 0.45,
|
|
6891
6929
|
ease: [0.4, 0, 0.1, 1],
|
|
6892
6930
|
};
|
|
6893
|
-
function mountNodeEarly(node,
|
|
6931
|
+
function mountNodeEarly(node, elementId) {
|
|
6894
6932
|
/**
|
|
6895
6933
|
* Rather than searching the DOM from document we can search the
|
|
6896
6934
|
* path for the deepest mounted ancestor and search from there
|
|
@@ -6903,7 +6941,7 @@ function mountNodeEarly(node, id) {
|
|
|
6903
6941
|
}
|
|
6904
6942
|
}
|
|
6905
6943
|
const searchElement = searchNode && searchNode !== node.root ? searchNode.instance : document;
|
|
6906
|
-
const element = searchElement.querySelector(`[data-projection-id="${
|
|
6944
|
+
const element = searchElement.querySelector(`[data-projection-id="${elementId}"]`);
|
|
6907
6945
|
if (element)
|
|
6908
6946
|
node.mount(element, true);
|
|
6909
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
|
}
|
|
@@ -62,7 +62,6 @@ class NodeStack {
|
|
|
62
62
|
node.snapshot = prevLead.snapshot;
|
|
63
63
|
node.snapshot.latestValues =
|
|
64
64
|
prevLead.animationValues || prevLead.latestValues;
|
|
65
|
-
node.snapshot.isShared = true;
|
|
66
65
|
}
|
|
67
66
|
if ((_a = node.root) === null || _a === void 0 ? void 0 : _a.isUpdating) {
|
|
68
67
|
node.isLayoutDirty = true;
|