framer-motion 12.23.24 → 12.23.26
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/README.md +10 -4
- package/dist/cjs/client.js +1 -1
- package/dist/cjs/dom.js +85 -1
- package/dist/cjs/{feature-bundle-v2Gb94eA.js → feature-bundle-kvRbMDEA.js} +110 -105
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/m.js +85 -1
- package/dist/dom.js +1 -1
- package/dist/es/motion/features/layout/MeasureLayout.mjs +0 -20
- package/dist/es/projection/node/create-projection-node.mjs +26 -19
- package/dist/es/projection/styles/scale-correction.mjs +18 -1
- package/dist/framer-motion.dev.js +110 -105
- package/dist/framer-motion.js +1 -1
- package/dist/size-rollup-animate.js +1 -1
- package/dist/size-rollup-dom-animation-assets.js +1 -1
- package/dist/size-rollup-dom-animation.js +1 -1
- package/dist/size-rollup-dom-max-assets.js +1 -1
- package/dist/size-rollup-dom-max.js +1 -1
- package/dist/size-rollup-m.js +1 -1
- package/dist/size-rollup-motion.js +1 -1
- package/dist/types/client.d.ts +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/{types.d-BJcRxCew.d.ts → types.d-DagZKalS.d.ts} +2 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -108,21 +108,27 @@ Motion is sustainable thanks to the kind support of its sponsors.
|
|
|
108
108
|
|
|
109
109
|
[Become a sponsor](https://motion.dev/sponsor)
|
|
110
110
|
|
|
111
|
-
###
|
|
111
|
+
### Partners
|
|
112
112
|
|
|
113
|
-
Motion powers
|
|
113
|
+
Motion powers the animations for all websites built with Framer, the web builder for creative pros. The Motion website itself is built on Framer, for its delightful canvas-based editing and powerful CMS features.
|
|
114
114
|
|
|
115
115
|
<a href="https://framer.link/FlnUbQY">
|
|
116
116
|
<img alt="Framer" src="https://github.com/user-attachments/assets/22a79be7-672e-4336-bfb7-5d55d1deb917" width="250px" height="150px">
|
|
117
117
|
</a>
|
|
118
118
|
|
|
119
|
+
Motion drives the animations on the Cursor homepage, and is working with Cursor to bring powerful AI workflows to the Motion examples and docs.
|
|
120
|
+
|
|
121
|
+
<a href="https://cursor.com">
|
|
122
|
+
<img alt="Cursor" src="https://github.com/user-attachments/assets/81c482d3-c2c2-4b35-bbcf-933b28d5b448" width="250px" height="150px" />
|
|
123
|
+
</a>
|
|
124
|
+
|
|
119
125
|
### Platinum
|
|
120
126
|
|
|
121
|
-
<a href="https://linear.app"><img alt="Linear" src="https://github.com/user-attachments/assets/f9ce44b4-af28-4770-bb6e-9515b474bfb2" width="250px" height="150px"></a> <a href="https://figma.com"><img alt="Figma" src="https://github.com/user-attachments/assets/1077d0ab-4305-4a1f-81c8-d5be8c4c6717" width="250px" height="150px"></a> <a href="https://sanity.io"><img alt="Sanity" src="https://github.com/user-attachments/assets/80134088-f456-483f-8edd-940593c120ce" width="250px" height="150px"></a>
|
|
127
|
+
<a href="https://linear.app"><img alt="Linear" src="https://github.com/user-attachments/assets/f9ce44b4-af28-4770-bb6e-9515b474bfb2" width="250px" height="150px"></a> <a href="https://figma.com"><img alt="Figma" src="https://github.com/user-attachments/assets/1077d0ab-4305-4a1f-81c8-d5be8c4c6717" width="250px" height="150px"></a> <a href="https://sanity.io"><img alt="Sanity" src="https://github.com/user-attachments/assets/80134088-f456-483f-8edd-940593c120ce" width="250px" height="150px"></a> <a href="https://animations.dev"><img alt="Sanity" src="https://github.com/user-attachments/assets/7c5ab87d-c7d9-44b4-9c7e-f9e6a9f3ba3b" width="250px" height="150px"></a>
|
|
122
128
|
|
|
123
129
|
### Gold
|
|
124
130
|
|
|
125
|
-
<a href="https://
|
|
131
|
+
<a href="https://liveblocks.io"><img alt="Liveblocks" src="https://github.com/user-attachments/assets/28eddbe5-1617-4e74-969d-2eb6fcd481af" width="200px" height="120px"></a> <a href="https://lu.ma"><img alt="Luma" src="https://github.com/user-attachments/assets/ac282433-6adb-4ad2-9fd2-5c6ee513c14b" width="200px" height="120px"></a> <a href="https://notion.com"><img alt="Notion" src="https://github.com/user-attachments/assets/a27a6033-3cb0-4232-a6bb-625e1824517b" width="200px" height="120px"></a> <a href="https://lottiefiles.com"><img alt="LottieFiles" src="https://github.com/user-attachments/assets/4e99d8c7-4cba-43ee-93c5-93861ae708ec" width="200px" height="120px"></a>
|
|
126
132
|
|
|
127
133
|
### Silver
|
|
128
134
|
|
package/dist/cjs/client.js
CHANGED
package/dist/cjs/dom.js
CHANGED
|
@@ -1468,7 +1468,91 @@ function renderHTML(element, { style, vars }, styleProp, projection) {
|
|
|
1468
1468
|
}
|
|
1469
1469
|
}
|
|
1470
1470
|
|
|
1471
|
-
|
|
1471
|
+
function pixelsToPercent(pixels, axis) {
|
|
1472
|
+
if (axis.max === axis.min)
|
|
1473
|
+
return 0;
|
|
1474
|
+
return (pixels / (axis.max - axis.min)) * 100;
|
|
1475
|
+
}
|
|
1476
|
+
/**
|
|
1477
|
+
* We always correct borderRadius as a percentage rather than pixels to reduce paints.
|
|
1478
|
+
* For example, if you are projecting a box that is 100px wide with a 10px borderRadius
|
|
1479
|
+
* into a box that is 200px wide with a 20px borderRadius, that is actually a 10%
|
|
1480
|
+
* borderRadius in both states. If we animate between the two in pixels that will trigger
|
|
1481
|
+
* a paint each time. If we animate between the two in percentage we'll avoid a paint.
|
|
1482
|
+
*/
|
|
1483
|
+
const correctBorderRadius = {
|
|
1484
|
+
correct: (latest, node) => {
|
|
1485
|
+
if (!node.target)
|
|
1486
|
+
return latest;
|
|
1487
|
+
/**
|
|
1488
|
+
* If latest is a string, if it's a percentage we can return immediately as it's
|
|
1489
|
+
* going to be stretched appropriately. Otherwise, if it's a pixel, convert it to a number.
|
|
1490
|
+
*/
|
|
1491
|
+
if (typeof latest === "string") {
|
|
1492
|
+
if (motionDom.px.test(latest)) {
|
|
1493
|
+
latest = parseFloat(latest);
|
|
1494
|
+
}
|
|
1495
|
+
else {
|
|
1496
|
+
return latest;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
/**
|
|
1500
|
+
* If latest is a number, it's a pixel value. We use the current viewportBox to calculate that
|
|
1501
|
+
* pixel value as a percentage of each axis
|
|
1502
|
+
*/
|
|
1503
|
+
const x = pixelsToPercent(latest, node.target.x);
|
|
1504
|
+
const y = pixelsToPercent(latest, node.target.y);
|
|
1505
|
+
return `${x}% ${y}%`;
|
|
1506
|
+
},
|
|
1507
|
+
};
|
|
1508
|
+
|
|
1509
|
+
const correctBoxShadow = {
|
|
1510
|
+
correct: (latest, { treeScale, projectionDelta }) => {
|
|
1511
|
+
const original = latest;
|
|
1512
|
+
const shadow = motionDom.complex.parse(latest);
|
|
1513
|
+
// TODO: Doesn't support multiple shadows
|
|
1514
|
+
if (shadow.length > 5)
|
|
1515
|
+
return original;
|
|
1516
|
+
const template = motionDom.complex.createTransformer(latest);
|
|
1517
|
+
const offset = typeof shadow[0] !== "number" ? 1 : 0;
|
|
1518
|
+
// Calculate the overall context scale
|
|
1519
|
+
const xScale = projectionDelta.x.scale * treeScale.x;
|
|
1520
|
+
const yScale = projectionDelta.y.scale * treeScale.y;
|
|
1521
|
+
shadow[0 + offset] /= xScale;
|
|
1522
|
+
shadow[1 + offset] /= yScale;
|
|
1523
|
+
/**
|
|
1524
|
+
* Ideally we'd correct x and y scales individually, but because blur and
|
|
1525
|
+
* spread apply to both we have to take a scale average and apply that instead.
|
|
1526
|
+
* We could potentially improve the outcome of this by incorporating the ratio between
|
|
1527
|
+
* the two scales.
|
|
1528
|
+
*/
|
|
1529
|
+
const averageScale = motionDom.mixNumber(xScale, yScale, 0.5);
|
|
1530
|
+
// Blur
|
|
1531
|
+
if (typeof shadow[2 + offset] === "number")
|
|
1532
|
+
shadow[2 + offset] /= averageScale;
|
|
1533
|
+
// Spread
|
|
1534
|
+
if (typeof shadow[3 + offset] === "number")
|
|
1535
|
+
shadow[3 + offset] /= averageScale;
|
|
1536
|
+
return template(shadow);
|
|
1537
|
+
},
|
|
1538
|
+
};
|
|
1539
|
+
|
|
1540
|
+
const scaleCorrectors = {
|
|
1541
|
+
borderRadius: {
|
|
1542
|
+
...correctBorderRadius,
|
|
1543
|
+
applyTo: [
|
|
1544
|
+
"borderTopLeftRadius",
|
|
1545
|
+
"borderTopRightRadius",
|
|
1546
|
+
"borderBottomLeftRadius",
|
|
1547
|
+
"borderBottomRightRadius",
|
|
1548
|
+
],
|
|
1549
|
+
},
|
|
1550
|
+
borderTopLeftRadius: correctBorderRadius,
|
|
1551
|
+
borderTopRightRadius: correctBorderRadius,
|
|
1552
|
+
borderBottomLeftRadius: correctBorderRadius,
|
|
1553
|
+
borderBottomRightRadius: correctBorderRadius,
|
|
1554
|
+
boxShadow: correctBoxShadow,
|
|
1555
|
+
};
|
|
1472
1556
|
|
|
1473
1557
|
function isForcedMotionValue(key, { layout, layoutId }) {
|
|
1474
1558
|
return (motionDom.transformProps.has(key) ||
|
|
@@ -825,7 +825,91 @@ class NodeStack {
|
|
|
825
825
|
}
|
|
826
826
|
}
|
|
827
827
|
|
|
828
|
-
|
|
828
|
+
function pixelsToPercent(pixels, axis) {
|
|
829
|
+
if (axis.max === axis.min)
|
|
830
|
+
return 0;
|
|
831
|
+
return (pixels / (axis.max - axis.min)) * 100;
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* We always correct borderRadius as a percentage rather than pixels to reduce paints.
|
|
835
|
+
* For example, if you are projecting a box that is 100px wide with a 10px borderRadius
|
|
836
|
+
* into a box that is 200px wide with a 20px borderRadius, that is actually a 10%
|
|
837
|
+
* borderRadius in both states. If we animate between the two in pixels that will trigger
|
|
838
|
+
* a paint each time. If we animate between the two in percentage we'll avoid a paint.
|
|
839
|
+
*/
|
|
840
|
+
const correctBorderRadius = {
|
|
841
|
+
correct: (latest, node) => {
|
|
842
|
+
if (!node.target)
|
|
843
|
+
return latest;
|
|
844
|
+
/**
|
|
845
|
+
* If latest is a string, if it's a percentage we can return immediately as it's
|
|
846
|
+
* going to be stretched appropriately. Otherwise, if it's a pixel, convert it to a number.
|
|
847
|
+
*/
|
|
848
|
+
if (typeof latest === "string") {
|
|
849
|
+
if (motionDom.px.test(latest)) {
|
|
850
|
+
latest = parseFloat(latest);
|
|
851
|
+
}
|
|
852
|
+
else {
|
|
853
|
+
return latest;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* If latest is a number, it's a pixel value. We use the current viewportBox to calculate that
|
|
858
|
+
* pixel value as a percentage of each axis
|
|
859
|
+
*/
|
|
860
|
+
const x = pixelsToPercent(latest, node.target.x);
|
|
861
|
+
const y = pixelsToPercent(latest, node.target.y);
|
|
862
|
+
return `${x}% ${y}%`;
|
|
863
|
+
},
|
|
864
|
+
};
|
|
865
|
+
|
|
866
|
+
const correctBoxShadow = {
|
|
867
|
+
correct: (latest, { treeScale, projectionDelta }) => {
|
|
868
|
+
const original = latest;
|
|
869
|
+
const shadow = motionDom.complex.parse(latest);
|
|
870
|
+
// TODO: Doesn't support multiple shadows
|
|
871
|
+
if (shadow.length > 5)
|
|
872
|
+
return original;
|
|
873
|
+
const template = motionDom.complex.createTransformer(latest);
|
|
874
|
+
const offset = typeof shadow[0] !== "number" ? 1 : 0;
|
|
875
|
+
// Calculate the overall context scale
|
|
876
|
+
const xScale = projectionDelta.x.scale * treeScale.x;
|
|
877
|
+
const yScale = projectionDelta.y.scale * treeScale.y;
|
|
878
|
+
shadow[0 + offset] /= xScale;
|
|
879
|
+
shadow[1 + offset] /= yScale;
|
|
880
|
+
/**
|
|
881
|
+
* Ideally we'd correct x and y scales individually, but because blur and
|
|
882
|
+
* spread apply to both we have to take a scale average and apply that instead.
|
|
883
|
+
* We could potentially improve the outcome of this by incorporating the ratio between
|
|
884
|
+
* the two scales.
|
|
885
|
+
*/
|
|
886
|
+
const averageScale = motionDom.mixNumber(xScale, yScale, 0.5);
|
|
887
|
+
// Blur
|
|
888
|
+
if (typeof shadow[2 + offset] === "number")
|
|
889
|
+
shadow[2 + offset] /= averageScale;
|
|
890
|
+
// Spread
|
|
891
|
+
if (typeof shadow[3 + offset] === "number")
|
|
892
|
+
shadow[3 + offset] /= averageScale;
|
|
893
|
+
return template(shadow);
|
|
894
|
+
},
|
|
895
|
+
};
|
|
896
|
+
|
|
897
|
+
const scaleCorrectors = {
|
|
898
|
+
borderRadius: {
|
|
899
|
+
...correctBorderRadius,
|
|
900
|
+
applyTo: [
|
|
901
|
+
"borderTopLeftRadius",
|
|
902
|
+
"borderTopRightRadius",
|
|
903
|
+
"borderBottomLeftRadius",
|
|
904
|
+
"borderBottomRightRadius",
|
|
905
|
+
],
|
|
906
|
+
},
|
|
907
|
+
borderTopLeftRadius: correctBorderRadius,
|
|
908
|
+
borderTopRightRadius: correctBorderRadius,
|
|
909
|
+
borderBottomLeftRadius: correctBorderRadius,
|
|
910
|
+
borderBottomRightRadius: correctBorderRadius,
|
|
911
|
+
boxShadow: correctBoxShadow,
|
|
912
|
+
};
|
|
829
913
|
function addScaleCorrector(correctors) {
|
|
830
914
|
for (const key in correctors) {
|
|
831
915
|
scaleCorrectors[key] = correctors[key];
|
|
@@ -1042,6 +1126,7 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
|
|
|
1042
1126
|
*/
|
|
1043
1127
|
this.eventHandlers = new Map();
|
|
1044
1128
|
this.hasTreeAnimated = false;
|
|
1129
|
+
this.layoutVersion = 0;
|
|
1045
1130
|
// Note: Currently only running on root node
|
|
1046
1131
|
this.updateScheduled = false;
|
|
1047
1132
|
this.scheduleUpdate = () => this.update();
|
|
@@ -1081,6 +1166,7 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
|
|
|
1081
1166
|
* Frame calculations
|
|
1082
1167
|
*/
|
|
1083
1168
|
this.resolvedRelativeTargetAt = 0.0;
|
|
1169
|
+
this.linkedParentVersion = 0;
|
|
1084
1170
|
this.hasProjected = false;
|
|
1085
1171
|
this.isVisible = true;
|
|
1086
1172
|
this.animationProgress = 0;
|
|
@@ -1434,6 +1520,7 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
|
|
|
1434
1520
|
}
|
|
1435
1521
|
const prevLayout = this.layout;
|
|
1436
1522
|
this.layout = this.measure(false);
|
|
1523
|
+
this.layoutVersion++;
|
|
1437
1524
|
this.layoutCorrected = createBox();
|
|
1438
1525
|
this.isLayoutDirty = false;
|
|
1439
1526
|
this.projectionDelta = undefined;
|
|
@@ -1653,25 +1740,23 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
|
|
|
1653
1740
|
if (!this.layout || !(layout || layoutId))
|
|
1654
1741
|
return;
|
|
1655
1742
|
this.resolvedRelativeTargetAt = motionDom.frameData.timestamp;
|
|
1743
|
+
const relativeParent = this.getClosestProjectingParent();
|
|
1744
|
+
if (relativeParent &&
|
|
1745
|
+
this.linkedParentVersion !== relativeParent.layoutVersion &&
|
|
1746
|
+
!relativeParent.options.layoutRoot) {
|
|
1747
|
+
this.removeRelativeTarget();
|
|
1748
|
+
}
|
|
1656
1749
|
/**
|
|
1657
1750
|
* If we don't have a targetDelta but do have a layout, we can attempt to resolve
|
|
1658
1751
|
* a relativeParent. This will allow a component to perform scale correction
|
|
1659
1752
|
* even if no animation has started.
|
|
1660
1753
|
*/
|
|
1661
1754
|
if (!this.targetDelta && !this.relativeTarget) {
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
relativeParent.layout &&
|
|
1665
|
-
this.animationProgress !== 1) {
|
|
1666
|
-
this.relativeParent = relativeParent;
|
|
1667
|
-
this.forceRelativeParentToResolveTarget();
|
|
1668
|
-
this.relativeTarget = createBox();
|
|
1669
|
-
this.relativeTargetOrigin = createBox();
|
|
1670
|
-
calcRelativePosition(this.relativeTargetOrigin, this.layout.layoutBox, relativeParent.layout.layoutBox);
|
|
1671
|
-
copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
|
|
1755
|
+
if (relativeParent && relativeParent.layout) {
|
|
1756
|
+
this.createRelativeTarget(relativeParent, this.layout.layoutBox, relativeParent.layout.layoutBox);
|
|
1672
1757
|
}
|
|
1673
1758
|
else {
|
|
1674
|
-
this.
|
|
1759
|
+
this.removeRelativeTarget();
|
|
1675
1760
|
}
|
|
1676
1761
|
}
|
|
1677
1762
|
/**
|
|
@@ -1721,19 +1806,13 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
|
|
|
1721
1806
|
*/
|
|
1722
1807
|
if (this.attemptToResolveRelativeTarget) {
|
|
1723
1808
|
this.attemptToResolveRelativeTarget = false;
|
|
1724
|
-
const relativeParent = this.getClosestProjectingParent();
|
|
1725
1809
|
if (relativeParent &&
|
|
1726
1810
|
Boolean(relativeParent.resumingFrom) ===
|
|
1727
1811
|
Boolean(this.resumingFrom) &&
|
|
1728
1812
|
!relativeParent.options.layoutScroll &&
|
|
1729
1813
|
relativeParent.target &&
|
|
1730
1814
|
this.animationProgress !== 1) {
|
|
1731
|
-
this.relativeParent
|
|
1732
|
-
this.forceRelativeParentToResolveTarget();
|
|
1733
|
-
this.relativeTarget = createBox();
|
|
1734
|
-
this.relativeTargetOrigin = createBox();
|
|
1735
|
-
calcRelativePosition(this.relativeTargetOrigin, this.target, relativeParent.target);
|
|
1736
|
-
copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
|
|
1815
|
+
this.createRelativeTarget(relativeParent, this.target, relativeParent.target);
|
|
1737
1816
|
}
|
|
1738
1817
|
else {
|
|
1739
1818
|
this.relativeParent = this.relativeTarget = undefined;
|
|
@@ -1765,6 +1844,18 @@ function createProjectionNode$1({ attachResizeListener, defaultParent, measureSc
|
|
|
1765
1844
|
this.options.layoutRoot) &&
|
|
1766
1845
|
this.layout);
|
|
1767
1846
|
}
|
|
1847
|
+
createRelativeTarget(relativeParent, layout, parentLayout) {
|
|
1848
|
+
this.relativeParent = relativeParent;
|
|
1849
|
+
this.linkedParentVersion = relativeParent.layoutVersion;
|
|
1850
|
+
this.forceRelativeParentToResolveTarget();
|
|
1851
|
+
this.relativeTarget = createBox();
|
|
1852
|
+
this.relativeTargetOrigin = createBox();
|
|
1853
|
+
calcRelativePosition(this.relativeTargetOrigin, layout, parentLayout);
|
|
1854
|
+
copyBoxInto(this.relativeTarget, this.relativeTargetOrigin);
|
|
1855
|
+
}
|
|
1856
|
+
removeRelativeTarget() {
|
|
1857
|
+
this.relativeParent = this.relativeTarget = undefined;
|
|
1858
|
+
}
|
|
1768
1859
|
calcProjection() {
|
|
1769
1860
|
const lead = this.getLead();
|
|
1770
1861
|
const isShared = Boolean(this.resumingFrom) || this !== lead;
|
|
@@ -2532,75 +2623,6 @@ const HTMLProjectionNode = createProjectionNode$1({
|
|
|
2532
2623
|
checkIsScrollRoot: (instance) => Boolean(window.getComputedStyle(instance).position === "fixed"),
|
|
2533
2624
|
});
|
|
2534
2625
|
|
|
2535
|
-
function pixelsToPercent(pixels, axis) {
|
|
2536
|
-
if (axis.max === axis.min)
|
|
2537
|
-
return 0;
|
|
2538
|
-
return (pixels / (axis.max - axis.min)) * 100;
|
|
2539
|
-
}
|
|
2540
|
-
/**
|
|
2541
|
-
* We always correct borderRadius as a percentage rather than pixels to reduce paints.
|
|
2542
|
-
* For example, if you are projecting a box that is 100px wide with a 10px borderRadius
|
|
2543
|
-
* into a box that is 200px wide with a 20px borderRadius, that is actually a 10%
|
|
2544
|
-
* borderRadius in both states. If we animate between the two in pixels that will trigger
|
|
2545
|
-
* a paint each time. If we animate between the two in percentage we'll avoid a paint.
|
|
2546
|
-
*/
|
|
2547
|
-
const correctBorderRadius = {
|
|
2548
|
-
correct: (latest, node) => {
|
|
2549
|
-
if (!node.target)
|
|
2550
|
-
return latest;
|
|
2551
|
-
/**
|
|
2552
|
-
* If latest is a string, if it's a percentage we can return immediately as it's
|
|
2553
|
-
* going to be stretched appropriately. Otherwise, if it's a pixel, convert it to a number.
|
|
2554
|
-
*/
|
|
2555
|
-
if (typeof latest === "string") {
|
|
2556
|
-
if (motionDom.px.test(latest)) {
|
|
2557
|
-
latest = parseFloat(latest);
|
|
2558
|
-
}
|
|
2559
|
-
else {
|
|
2560
|
-
return latest;
|
|
2561
|
-
}
|
|
2562
|
-
}
|
|
2563
|
-
/**
|
|
2564
|
-
* If latest is a number, it's a pixel value. We use the current viewportBox to calculate that
|
|
2565
|
-
* pixel value as a percentage of each axis
|
|
2566
|
-
*/
|
|
2567
|
-
const x = pixelsToPercent(latest, node.target.x);
|
|
2568
|
-
const y = pixelsToPercent(latest, node.target.y);
|
|
2569
|
-
return `${x}% ${y}%`;
|
|
2570
|
-
},
|
|
2571
|
-
};
|
|
2572
|
-
|
|
2573
|
-
const correctBoxShadow = {
|
|
2574
|
-
correct: (latest, { treeScale, projectionDelta }) => {
|
|
2575
|
-
const original = latest;
|
|
2576
|
-
const shadow = motionDom.complex.parse(latest);
|
|
2577
|
-
// TODO: Doesn't support multiple shadows
|
|
2578
|
-
if (shadow.length > 5)
|
|
2579
|
-
return original;
|
|
2580
|
-
const template = motionDom.complex.createTransformer(latest);
|
|
2581
|
-
const offset = typeof shadow[0] !== "number" ? 1 : 0;
|
|
2582
|
-
// Calculate the overall context scale
|
|
2583
|
-
const xScale = projectionDelta.x.scale * treeScale.x;
|
|
2584
|
-
const yScale = projectionDelta.y.scale * treeScale.y;
|
|
2585
|
-
shadow[0 + offset] /= xScale;
|
|
2586
|
-
shadow[1 + offset] /= yScale;
|
|
2587
|
-
/**
|
|
2588
|
-
* Ideally we'd correct x and y scales individually, but because blur and
|
|
2589
|
-
* spread apply to both we have to take a scale average and apply that instead.
|
|
2590
|
-
* We could potentially improve the outcome of this by incorporating the ratio between
|
|
2591
|
-
* the two scales.
|
|
2592
|
-
*/
|
|
2593
|
-
const averageScale = motionDom.mixNumber(xScale, yScale, 0.5);
|
|
2594
|
-
// Blur
|
|
2595
|
-
if (typeof shadow[2 + offset] === "number")
|
|
2596
|
-
shadow[2 + offset] /= averageScale;
|
|
2597
|
-
// Spread
|
|
2598
|
-
if (typeof shadow[3 + offset] === "number")
|
|
2599
|
-
shadow[3 + offset] /= averageScale;
|
|
2600
|
-
return template(shadow);
|
|
2601
|
-
},
|
|
2602
|
-
};
|
|
2603
|
-
|
|
2604
2626
|
/**
|
|
2605
2627
|
* Bounding boxes tend to be defined as top, left, right, bottom. For various operations
|
|
2606
2628
|
* it's easier to consider each axis individually. This function returns a bounding box
|
|
@@ -5872,7 +5894,6 @@ class MeasureLayoutWithContext extends React.Component {
|
|
|
5872
5894
|
componentDidMount() {
|
|
5873
5895
|
const { visualElement, layoutGroup, switchLayoutGroup, layoutId } = this.props;
|
|
5874
5896
|
const { projection } = visualElement;
|
|
5875
|
-
addScaleCorrector(defaultScaleCorrectors);
|
|
5876
5897
|
if (projection) {
|
|
5877
5898
|
if (layoutGroup.group)
|
|
5878
5899
|
layoutGroup.group.add(projection);
|
|
@@ -5971,22 +5992,6 @@ function MeasureLayout(props) {
|
|
|
5971
5992
|
const layoutGroup = React.useContext(LayoutGroupContext);
|
|
5972
5993
|
return (jsxRuntime.jsx(MeasureLayoutWithContext, { ...props, layoutGroup: layoutGroup, switchLayoutGroup: React.useContext(SwitchLayoutGroupContext), isPresent: isPresent, safeToRemove: safeToRemove }));
|
|
5973
5994
|
}
|
|
5974
|
-
const defaultScaleCorrectors = {
|
|
5975
|
-
borderRadius: {
|
|
5976
|
-
...correctBorderRadius,
|
|
5977
|
-
applyTo: [
|
|
5978
|
-
"borderTopLeftRadius",
|
|
5979
|
-
"borderTopRightRadius",
|
|
5980
|
-
"borderBottomLeftRadius",
|
|
5981
|
-
"borderBottomRightRadius",
|
|
5982
|
-
],
|
|
5983
|
-
},
|
|
5984
|
-
borderTopLeftRadius: correctBorderRadius,
|
|
5985
|
-
borderTopRightRadius: correctBorderRadius,
|
|
5986
|
-
borderBottomLeftRadius: correctBorderRadius,
|
|
5987
|
-
borderBottomRightRadius: correctBorderRadius,
|
|
5988
|
-
boxShadow: correctBoxShadow,
|
|
5989
|
-
};
|
|
5990
5995
|
|
|
5991
5996
|
const drag = {
|
|
5992
5997
|
pan: {
|
package/dist/cjs/index.js
CHANGED
|
@@ -4,7 +4,7 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
4
4
|
|
|
5
5
|
var jsxRuntime = require('react/jsx-runtime');
|
|
6
6
|
var React = require('react');
|
|
7
|
-
var featureBundle = require('./feature-bundle-
|
|
7
|
+
var featureBundle = require('./feature-bundle-kvRbMDEA.js');
|
|
8
8
|
var motionDom = require('motion-dom');
|
|
9
9
|
var motionUtils = require('motion-utils');
|
|
10
10
|
|
package/dist/cjs/m.js
CHANGED
|
@@ -75,7 +75,91 @@ function variantLabelsAsDependency(prop) {
|
|
|
75
75
|
return Array.isArray(prop) ? prop.join(" ") : prop;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
function pixelsToPercent(pixels, axis) {
|
|
79
|
+
if (axis.max === axis.min)
|
|
80
|
+
return 0;
|
|
81
|
+
return (pixels / (axis.max - axis.min)) * 100;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* We always correct borderRadius as a percentage rather than pixels to reduce paints.
|
|
85
|
+
* For example, if you are projecting a box that is 100px wide with a 10px borderRadius
|
|
86
|
+
* into a box that is 200px wide with a 20px borderRadius, that is actually a 10%
|
|
87
|
+
* borderRadius in both states. If we animate between the two in pixels that will trigger
|
|
88
|
+
* a paint each time. If we animate between the two in percentage we'll avoid a paint.
|
|
89
|
+
*/
|
|
90
|
+
const correctBorderRadius = {
|
|
91
|
+
correct: (latest, node) => {
|
|
92
|
+
if (!node.target)
|
|
93
|
+
return latest;
|
|
94
|
+
/**
|
|
95
|
+
* If latest is a string, if it's a percentage we can return immediately as it's
|
|
96
|
+
* going to be stretched appropriately. Otherwise, if it's a pixel, convert it to a number.
|
|
97
|
+
*/
|
|
98
|
+
if (typeof latest === "string") {
|
|
99
|
+
if (motionDom.px.test(latest)) {
|
|
100
|
+
latest = parseFloat(latest);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
return latest;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* If latest is a number, it's a pixel value. We use the current viewportBox to calculate that
|
|
108
|
+
* pixel value as a percentage of each axis
|
|
109
|
+
*/
|
|
110
|
+
const x = pixelsToPercent(latest, node.target.x);
|
|
111
|
+
const y = pixelsToPercent(latest, node.target.y);
|
|
112
|
+
return `${x}% ${y}%`;
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
const correctBoxShadow = {
|
|
117
|
+
correct: (latest, { treeScale, projectionDelta }) => {
|
|
118
|
+
const original = latest;
|
|
119
|
+
const shadow = motionDom.complex.parse(latest);
|
|
120
|
+
// TODO: Doesn't support multiple shadows
|
|
121
|
+
if (shadow.length > 5)
|
|
122
|
+
return original;
|
|
123
|
+
const template = motionDom.complex.createTransformer(latest);
|
|
124
|
+
const offset = typeof shadow[0] !== "number" ? 1 : 0;
|
|
125
|
+
// Calculate the overall context scale
|
|
126
|
+
const xScale = projectionDelta.x.scale * treeScale.x;
|
|
127
|
+
const yScale = projectionDelta.y.scale * treeScale.y;
|
|
128
|
+
shadow[0 + offset] /= xScale;
|
|
129
|
+
shadow[1 + offset] /= yScale;
|
|
130
|
+
/**
|
|
131
|
+
* Ideally we'd correct x and y scales individually, but because blur and
|
|
132
|
+
* spread apply to both we have to take a scale average and apply that instead.
|
|
133
|
+
* We could potentially improve the outcome of this by incorporating the ratio between
|
|
134
|
+
* the two scales.
|
|
135
|
+
*/
|
|
136
|
+
const averageScale = motionDom.mixNumber(xScale, yScale, 0.5);
|
|
137
|
+
// Blur
|
|
138
|
+
if (typeof shadow[2 + offset] === "number")
|
|
139
|
+
shadow[2 + offset] /= averageScale;
|
|
140
|
+
// Spread
|
|
141
|
+
if (typeof shadow[3 + offset] === "number")
|
|
142
|
+
shadow[3 + offset] /= averageScale;
|
|
143
|
+
return template(shadow);
|
|
144
|
+
},
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const scaleCorrectors = {
|
|
148
|
+
borderRadius: {
|
|
149
|
+
...correctBorderRadius,
|
|
150
|
+
applyTo: [
|
|
151
|
+
"borderTopLeftRadius",
|
|
152
|
+
"borderTopRightRadius",
|
|
153
|
+
"borderBottomLeftRadius",
|
|
154
|
+
"borderBottomRightRadius",
|
|
155
|
+
],
|
|
156
|
+
},
|
|
157
|
+
borderTopLeftRadius: correctBorderRadius,
|
|
158
|
+
borderTopRightRadius: correctBorderRadius,
|
|
159
|
+
borderBottomLeftRadius: correctBorderRadius,
|
|
160
|
+
borderBottomRightRadius: correctBorderRadius,
|
|
161
|
+
boxShadow: correctBoxShadow,
|
|
162
|
+
};
|
|
79
163
|
|
|
80
164
|
function isForcedMotionValue(key, { layout, layoutId }) {
|
|
81
165
|
return (motionDom.transformProps.has(key) ||
|