framer-motion 7.7.0 → 7.7.1
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 +529 -155
- package/dist/es/animation/legacy-popmotion/index.mjs +1 -1
- package/dist/es/animation/legacy-popmotion/inertia.mjs +2 -2
- package/dist/es/animation/utils/is-animatable.mjs +1 -1
- package/dist/es/frameloop/create-render-step.mjs +88 -0
- package/dist/es/frameloop/data.mjs +6 -0
- package/dist/es/frameloop/index.mjs +59 -0
- package/dist/es/frameloop/on-next-frame.mjs +12 -0
- package/dist/es/gestures/PanSession.mjs +4 -3
- package/dist/es/gestures/drag/VisualElementDragControls.mjs +1 -1
- package/dist/es/motion/features/layout/MeasureLayout.mjs +1 -1
- package/dist/es/projection/animation/mix-values.mjs +1 -1
- package/dist/es/projection/geometry/delta-remove.mjs +1 -1
- package/dist/es/projection/node/create-projection-node.mjs +1 -1
- package/dist/es/projection/styles/scale-border-radius.mjs +1 -1
- package/dist/es/projection/styles/scale-box-shadow.mjs +1 -1
- package/dist/es/render/VisualElement.mjs +1 -1
- package/dist/es/render/dom/utils/unit-conversion.mjs +2 -1
- package/dist/es/render/dom/value-types/animatable-none.mjs +2 -1
- package/dist/es/render/dom/value-types/defaults.mjs +2 -1
- package/dist/es/render/dom/value-types/dimensions.mjs +2 -1
- package/dist/es/render/dom/value-types/find.mjs +2 -1
- package/dist/es/render/dom/value-types/number.mjs +2 -1
- package/dist/es/render/dom/value-types/type-int.mjs +1 -1
- package/dist/es/render/svg/utils/path.mjs +1 -1
- package/dist/es/render/svg/utils/transform-origin.mjs +1 -1
- package/dist/es/render/utils/motion-values.mjs +1 -1
- package/dist/es/render/utils/setters.mjs +1 -1
- package/dist/es/utils/delay.mjs +1 -1
- package/dist/es/utils/interpolate.mjs +1 -1
- package/dist/es/utils/mix-color.mjs +4 -1
- package/dist/es/utils/mix-complex.mjs +5 -24
- package/dist/es/utils/use-animation-frame.mjs +1 -1
- package/dist/es/utils/use-force-update.mjs +1 -1
- package/dist/es/utils/use-instant-transition.mjs +1 -1
- package/dist/es/value/index.mjs +4 -3
- package/dist/es/value/types/color/hex.mjs +40 -0
- package/dist/es/value/types/color/hsla.mjs +22 -0
- package/dist/es/value/types/color/index.mjs +28 -0
- package/dist/es/value/types/color/rgba.mjs +25 -0
- package/dist/es/value/types/color/utils.mjs +23 -0
- package/dist/es/value/types/complex/filter.mjs +30 -0
- package/dist/es/value/types/complex/index.mjs +61 -0
- package/dist/es/value/types/numbers/index.mjs +17 -0
- package/dist/es/value/types/numbers/units.mjs +19 -0
- package/dist/es/value/types/utils.mjs +15 -0
- package/dist/es/value/use-combine-values.mjs +1 -1
- package/dist/framer-motion.dev.js +284 -230
- package/dist/framer-motion.js +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/projection.dev.js +5451 -5397
- 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/size-webpack-dom-animation.js +1 -1
- package/dist/size-webpack-dom-max.js +1 -1
- package/dist/size-webpack-m.js +1 -1
- package/dist/three-entry.d.ts +7 -2
- package/package.json +9 -11
package/dist/cjs/index.js
CHANGED
|
@@ -3,9 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var React = require('react');
|
|
6
|
-
var styleValueTypes = require('style-value-types');
|
|
7
6
|
var heyListen = require('hey-listen');
|
|
8
|
-
var sync = require('framesync');
|
|
9
7
|
var dom = require('@motionone/dom');
|
|
10
8
|
|
|
11
9
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -30,7 +28,6 @@ function _interopNamespace(e) {
|
|
|
30
28
|
|
|
31
29
|
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
|
|
32
30
|
var React__namespace = /*#__PURE__*/_interopNamespace(React);
|
|
33
|
-
var sync__default = /*#__PURE__*/_interopDefaultLegacy(sync);
|
|
34
31
|
|
|
35
32
|
/**
|
|
36
33
|
* @public
|
|
@@ -563,75 +560,121 @@ const getValueAsType = (value, type) => {
|
|
|
563
560
|
: value;
|
|
564
561
|
};
|
|
565
562
|
|
|
563
|
+
const clamp = (min, max, v) => Math.min(Math.max(v, min), max);
|
|
564
|
+
|
|
565
|
+
const number = {
|
|
566
|
+
test: (v) => typeof v === "number",
|
|
567
|
+
parse: parseFloat,
|
|
568
|
+
transform: (v) => v,
|
|
569
|
+
};
|
|
570
|
+
const alpha = {
|
|
571
|
+
...number,
|
|
572
|
+
transform: (v) => clamp(0, 1, v),
|
|
573
|
+
};
|
|
574
|
+
const scale = {
|
|
575
|
+
...number,
|
|
576
|
+
default: 1,
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
/**
|
|
580
|
+
* TODO: When we move from string as a source of truth to data models
|
|
581
|
+
* everything in this folder should probably be referred to as models vs types
|
|
582
|
+
*/
|
|
583
|
+
// If this number is a decimal, make it just five decimal places
|
|
584
|
+
// to avoid exponents
|
|
585
|
+
const sanitize = (v) => Math.round(v * 100000) / 100000;
|
|
586
|
+
const floatRegex = /(-)?([\d]*\.?[\d])+/g;
|
|
587
|
+
const colorRegex = /(#[0-9a-f]{6}|#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))/gi;
|
|
588
|
+
const singleColorRegex = /^(#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))$/i;
|
|
589
|
+
function isString(v) {
|
|
590
|
+
return typeof v === "string";
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
const createUnitType = (unit) => ({
|
|
594
|
+
test: (v) => isString(v) && v.endsWith(unit) && v.split(" ").length === 1,
|
|
595
|
+
parse: parseFloat,
|
|
596
|
+
transform: (v) => `${v}${unit}`,
|
|
597
|
+
});
|
|
598
|
+
const degrees = createUnitType("deg");
|
|
599
|
+
const percent = createUnitType("%");
|
|
600
|
+
const px = createUnitType("px");
|
|
601
|
+
const vh = createUnitType("vh");
|
|
602
|
+
const vw = createUnitType("vw");
|
|
603
|
+
const progressPercentage = {
|
|
604
|
+
...percent,
|
|
605
|
+
parse: (v) => percent.parse(v) / 100,
|
|
606
|
+
transform: (v) => percent.transform(v * 100),
|
|
607
|
+
};
|
|
608
|
+
|
|
566
609
|
const int = {
|
|
567
|
-
...
|
|
610
|
+
...number,
|
|
568
611
|
transform: Math.round,
|
|
569
612
|
};
|
|
570
613
|
|
|
571
614
|
const numberValueTypes = {
|
|
572
615
|
// Border props
|
|
573
|
-
borderWidth:
|
|
574
|
-
borderTopWidth:
|
|
575
|
-
borderRightWidth:
|
|
576
|
-
borderBottomWidth:
|
|
577
|
-
borderLeftWidth:
|
|
578
|
-
borderRadius:
|
|
579
|
-
radius:
|
|
580
|
-
borderTopLeftRadius:
|
|
581
|
-
borderTopRightRadius:
|
|
582
|
-
borderBottomRightRadius:
|
|
583
|
-
borderBottomLeftRadius:
|
|
616
|
+
borderWidth: px,
|
|
617
|
+
borderTopWidth: px,
|
|
618
|
+
borderRightWidth: px,
|
|
619
|
+
borderBottomWidth: px,
|
|
620
|
+
borderLeftWidth: px,
|
|
621
|
+
borderRadius: px,
|
|
622
|
+
radius: px,
|
|
623
|
+
borderTopLeftRadius: px,
|
|
624
|
+
borderTopRightRadius: px,
|
|
625
|
+
borderBottomRightRadius: px,
|
|
626
|
+
borderBottomLeftRadius: px,
|
|
584
627
|
// Positioning props
|
|
585
|
-
width:
|
|
586
|
-
maxWidth:
|
|
587
|
-
height:
|
|
588
|
-
maxHeight:
|
|
589
|
-
size:
|
|
590
|
-
top:
|
|
591
|
-
right:
|
|
592
|
-
bottom:
|
|
593
|
-
left:
|
|
628
|
+
width: px,
|
|
629
|
+
maxWidth: px,
|
|
630
|
+
height: px,
|
|
631
|
+
maxHeight: px,
|
|
632
|
+
size: px,
|
|
633
|
+
top: px,
|
|
634
|
+
right: px,
|
|
635
|
+
bottom: px,
|
|
636
|
+
left: px,
|
|
594
637
|
// Spacing props
|
|
595
|
-
padding:
|
|
596
|
-
paddingTop:
|
|
597
|
-
paddingRight:
|
|
598
|
-
paddingBottom:
|
|
599
|
-
paddingLeft:
|
|
600
|
-
margin:
|
|
601
|
-
marginTop:
|
|
602
|
-
marginRight:
|
|
603
|
-
marginBottom:
|
|
604
|
-
marginLeft:
|
|
638
|
+
padding: px,
|
|
639
|
+
paddingTop: px,
|
|
640
|
+
paddingRight: px,
|
|
641
|
+
paddingBottom: px,
|
|
642
|
+
paddingLeft: px,
|
|
643
|
+
margin: px,
|
|
644
|
+
marginTop: px,
|
|
645
|
+
marginRight: px,
|
|
646
|
+
marginBottom: px,
|
|
647
|
+
marginLeft: px,
|
|
605
648
|
// Transform props
|
|
606
|
-
rotate:
|
|
607
|
-
rotateX:
|
|
608
|
-
rotateY:
|
|
609
|
-
rotateZ:
|
|
610
|
-
scale
|
|
611
|
-
scaleX:
|
|
612
|
-
scaleY:
|
|
613
|
-
scaleZ:
|
|
614
|
-
skew:
|
|
615
|
-
skewX:
|
|
616
|
-
skewY:
|
|
617
|
-
distance:
|
|
618
|
-
translateX:
|
|
619
|
-
translateY:
|
|
620
|
-
translateZ:
|
|
621
|
-
x:
|
|
622
|
-
y:
|
|
623
|
-
z:
|
|
624
|
-
perspective:
|
|
625
|
-
transformPerspective:
|
|
626
|
-
opacity:
|
|
627
|
-
originX:
|
|
628
|
-
originY:
|
|
629
|
-
originZ:
|
|
649
|
+
rotate: degrees,
|
|
650
|
+
rotateX: degrees,
|
|
651
|
+
rotateY: degrees,
|
|
652
|
+
rotateZ: degrees,
|
|
653
|
+
scale,
|
|
654
|
+
scaleX: scale,
|
|
655
|
+
scaleY: scale,
|
|
656
|
+
scaleZ: scale,
|
|
657
|
+
skew: degrees,
|
|
658
|
+
skewX: degrees,
|
|
659
|
+
skewY: degrees,
|
|
660
|
+
distance: px,
|
|
661
|
+
translateX: px,
|
|
662
|
+
translateY: px,
|
|
663
|
+
translateZ: px,
|
|
664
|
+
x: px,
|
|
665
|
+
y: px,
|
|
666
|
+
z: px,
|
|
667
|
+
perspective: px,
|
|
668
|
+
transformPerspective: px,
|
|
669
|
+
opacity: alpha,
|
|
670
|
+
originX: progressPercentage,
|
|
671
|
+
originY: progressPercentage,
|
|
672
|
+
originZ: px,
|
|
630
673
|
// Misc
|
|
631
674
|
zIndex: int,
|
|
632
675
|
// SVG
|
|
633
|
-
fillOpacity:
|
|
634
|
-
strokeOpacity:
|
|
676
|
+
fillOpacity: alpha,
|
|
677
|
+
strokeOpacity: alpha,
|
|
635
678
|
numOctaves: int,
|
|
636
679
|
};
|
|
637
680
|
|
|
@@ -888,7 +931,7 @@ function filterProps(props, isDom, forwardMotionProps) {
|
|
|
888
931
|
function calcOrigin$1(origin, offset, size) {
|
|
889
932
|
return typeof origin === "string"
|
|
890
933
|
? origin
|
|
891
|
-
:
|
|
934
|
+
: px.transform(offset + size * origin);
|
|
892
935
|
}
|
|
893
936
|
/**
|
|
894
937
|
* The SVG transform origin defaults are different to CSS and is less intuitive,
|
|
@@ -922,10 +965,10 @@ function buildSVGPath(attrs, length, spacing = 1, offset = 0, useDashCase = true
|
|
|
922
965
|
// when defining props on a React component.
|
|
923
966
|
const keys = useDashCase ? dashKeys : camelKeys;
|
|
924
967
|
// Build the dash offset
|
|
925
|
-
attrs[keys.offset] =
|
|
968
|
+
attrs[keys.offset] = px.transform(-offset);
|
|
926
969
|
// Build the dash array
|
|
927
|
-
const pathLength =
|
|
928
|
-
const pathSpacing =
|
|
970
|
+
const pathLength = px.transform(length);
|
|
971
|
+
const pathSpacing = px.transform(spacing);
|
|
929
972
|
attrs[keys.array] = `${pathLength} ${pathSpacing}`;
|
|
930
973
|
}
|
|
931
974
|
|
|
@@ -1943,6 +1986,175 @@ const isEasingArray = (ease) => {
|
|
|
1943
1986
|
return Array.isArray(ease) && typeof ease[0] !== "number";
|
|
1944
1987
|
};
|
|
1945
1988
|
|
|
1989
|
+
/**
|
|
1990
|
+
* Returns true if the provided string is a color, ie rgba(0,0,0,0) or #000,
|
|
1991
|
+
* but false if a number or multiple colors
|
|
1992
|
+
*/
|
|
1993
|
+
const isColorString = (type, testProp) => (v) => {
|
|
1994
|
+
return Boolean((isString(v) && singleColorRegex.test(v) && v.startsWith(type)) ||
|
|
1995
|
+
(testProp && Object.prototype.hasOwnProperty.call(v, testProp)));
|
|
1996
|
+
};
|
|
1997
|
+
const splitColor = (aName, bName, cName) => (v) => {
|
|
1998
|
+
if (!isString(v))
|
|
1999
|
+
return v;
|
|
2000
|
+
const [a, b, c, alpha] = v.match(floatRegex);
|
|
2001
|
+
return {
|
|
2002
|
+
[aName]: parseFloat(a),
|
|
2003
|
+
[bName]: parseFloat(b),
|
|
2004
|
+
[cName]: parseFloat(c),
|
|
2005
|
+
alpha: alpha !== undefined ? parseFloat(alpha) : 1,
|
|
2006
|
+
};
|
|
2007
|
+
};
|
|
2008
|
+
|
|
2009
|
+
const clampRgbUnit = (v) => clamp(0, 255, v);
|
|
2010
|
+
const rgbUnit = {
|
|
2011
|
+
...number,
|
|
2012
|
+
transform: (v) => Math.round(clampRgbUnit(v)),
|
|
2013
|
+
};
|
|
2014
|
+
const rgba = {
|
|
2015
|
+
test: isColorString("rgb", "red"),
|
|
2016
|
+
parse: splitColor("red", "green", "blue"),
|
|
2017
|
+
transform: ({ red, green, blue, alpha: alpha$1 = 1 }) => "rgba(" +
|
|
2018
|
+
rgbUnit.transform(red) +
|
|
2019
|
+
", " +
|
|
2020
|
+
rgbUnit.transform(green) +
|
|
2021
|
+
", " +
|
|
2022
|
+
rgbUnit.transform(blue) +
|
|
2023
|
+
", " +
|
|
2024
|
+
sanitize(alpha.transform(alpha$1)) +
|
|
2025
|
+
")",
|
|
2026
|
+
};
|
|
2027
|
+
|
|
2028
|
+
function parseHex(v) {
|
|
2029
|
+
let r = "";
|
|
2030
|
+
let g = "";
|
|
2031
|
+
let b = "";
|
|
2032
|
+
let a = "";
|
|
2033
|
+
// If we have 6 characters, ie #FF0000
|
|
2034
|
+
if (v.length > 5) {
|
|
2035
|
+
r = v.substring(1, 3);
|
|
2036
|
+
g = v.substring(3, 5);
|
|
2037
|
+
b = v.substring(5, 7);
|
|
2038
|
+
a = v.substring(7, 9);
|
|
2039
|
+
// Or we have 3 characters, ie #F00
|
|
2040
|
+
}
|
|
2041
|
+
else {
|
|
2042
|
+
r = v.substring(1, 2);
|
|
2043
|
+
g = v.substring(2, 3);
|
|
2044
|
+
b = v.substring(3, 4);
|
|
2045
|
+
a = v.substring(4, 5);
|
|
2046
|
+
r += r;
|
|
2047
|
+
g += g;
|
|
2048
|
+
b += b;
|
|
2049
|
+
a += a;
|
|
2050
|
+
}
|
|
2051
|
+
return {
|
|
2052
|
+
red: parseInt(r, 16),
|
|
2053
|
+
green: parseInt(g, 16),
|
|
2054
|
+
blue: parseInt(b, 16),
|
|
2055
|
+
alpha: a ? parseInt(a, 16) / 255 : 1,
|
|
2056
|
+
};
|
|
2057
|
+
}
|
|
2058
|
+
const hex = {
|
|
2059
|
+
test: isColorString("#"),
|
|
2060
|
+
parse: parseHex,
|
|
2061
|
+
transform: rgba.transform,
|
|
2062
|
+
};
|
|
2063
|
+
|
|
2064
|
+
const hsla = {
|
|
2065
|
+
test: isColorString("hsl", "hue"),
|
|
2066
|
+
parse: splitColor("hue", "saturation", "lightness"),
|
|
2067
|
+
transform: ({ hue, saturation, lightness, alpha: alpha$1 = 1 }) => {
|
|
2068
|
+
return ("hsla(" +
|
|
2069
|
+
Math.round(hue) +
|
|
2070
|
+
", " +
|
|
2071
|
+
percent.transform(sanitize(saturation)) +
|
|
2072
|
+
", " +
|
|
2073
|
+
percent.transform(sanitize(lightness)) +
|
|
2074
|
+
", " +
|
|
2075
|
+
sanitize(alpha.transform(alpha$1)) +
|
|
2076
|
+
")");
|
|
2077
|
+
},
|
|
2078
|
+
};
|
|
2079
|
+
|
|
2080
|
+
const color = {
|
|
2081
|
+
test: (v) => rgba.test(v) || hex.test(v) || hsla.test(v),
|
|
2082
|
+
parse: (v) => {
|
|
2083
|
+
if (rgba.test(v)) {
|
|
2084
|
+
return rgba.parse(v);
|
|
2085
|
+
}
|
|
2086
|
+
else if (hsla.test(v)) {
|
|
2087
|
+
return hsla.parse(v);
|
|
2088
|
+
}
|
|
2089
|
+
else {
|
|
2090
|
+
return hex.parse(v);
|
|
2091
|
+
}
|
|
2092
|
+
},
|
|
2093
|
+
transform: (v) => {
|
|
2094
|
+
return isString(v)
|
|
2095
|
+
? v
|
|
2096
|
+
: v.hasOwnProperty("red")
|
|
2097
|
+
? rgba.transform(v)
|
|
2098
|
+
: hsla.transform(v);
|
|
2099
|
+
},
|
|
2100
|
+
};
|
|
2101
|
+
|
|
2102
|
+
const colorToken = "${c}";
|
|
2103
|
+
const numberToken = "${n}";
|
|
2104
|
+
function test(v) {
|
|
2105
|
+
var _a, _b, _c, _d;
|
|
2106
|
+
return (isNaN(v) &&
|
|
2107
|
+
isString(v) &&
|
|
2108
|
+
((_b = (_a = v.match(floatRegex)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) +
|
|
2109
|
+
((_d = (_c = v.match(colorRegex)) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) >
|
|
2110
|
+
0);
|
|
2111
|
+
}
|
|
2112
|
+
function analyseComplexValue(v) {
|
|
2113
|
+
if (typeof v === "number")
|
|
2114
|
+
v = `${v}`;
|
|
2115
|
+
const values = [];
|
|
2116
|
+
let numColors = 0;
|
|
2117
|
+
let numNumbers = 0;
|
|
2118
|
+
const colors = v.match(colorRegex);
|
|
2119
|
+
if (colors) {
|
|
2120
|
+
numColors = colors.length;
|
|
2121
|
+
// Strip colors from input so they're not picked up by number regex.
|
|
2122
|
+
// There's a better way to combine these regex searches, but its beyond my regex skills
|
|
2123
|
+
v = v.replace(colorRegex, colorToken);
|
|
2124
|
+
values.push(...colors.map(color.parse));
|
|
2125
|
+
}
|
|
2126
|
+
const numbers = v.match(floatRegex);
|
|
2127
|
+
if (numbers) {
|
|
2128
|
+
numNumbers = numbers.length;
|
|
2129
|
+
v = v.replace(floatRegex, numberToken);
|
|
2130
|
+
values.push(...numbers.map(number.parse));
|
|
2131
|
+
}
|
|
2132
|
+
return { values, numColors, numNumbers, tokenised: v };
|
|
2133
|
+
}
|
|
2134
|
+
function parse(v) {
|
|
2135
|
+
return analyseComplexValue(v).values;
|
|
2136
|
+
}
|
|
2137
|
+
function createTransformer(source) {
|
|
2138
|
+
const { values, numColors, tokenised } = analyseComplexValue(source);
|
|
2139
|
+
const numValues = values.length;
|
|
2140
|
+
return (v) => {
|
|
2141
|
+
let output = tokenised;
|
|
2142
|
+
for (let i = 0; i < numValues; i++) {
|
|
2143
|
+
output = output.replace(i < numColors ? colorToken : numberToken, i < numColors
|
|
2144
|
+
? color.transform(v[i])
|
|
2145
|
+
: sanitize(v[i]));
|
|
2146
|
+
}
|
|
2147
|
+
return output;
|
|
2148
|
+
};
|
|
2149
|
+
}
|
|
2150
|
+
const convertNumbersToZero = (v) => typeof v === "number" ? 0 : v;
|
|
2151
|
+
function getAnimatableNone$1(v) {
|
|
2152
|
+
const parsed = parse(v);
|
|
2153
|
+
const transformer = createTransformer(v);
|
|
2154
|
+
return transformer(parsed.map(convertNumbersToZero));
|
|
2155
|
+
}
|
|
2156
|
+
const complex = { test, parse, createTransformer, getAnimatableNone: getAnimatableNone$1 };
|
|
2157
|
+
|
|
1946
2158
|
/**
|
|
1947
2159
|
* Check if a value is animatable. Examples:
|
|
1948
2160
|
*
|
|
@@ -1962,7 +2174,7 @@ const isAnimatable = (key, value) => {
|
|
|
1962
2174
|
if (typeof value === "number" || Array.isArray(value))
|
|
1963
2175
|
return true;
|
|
1964
2176
|
if (typeof value === "string" && // It's animatable if we have a string
|
|
1965
|
-
|
|
2177
|
+
complex.test(value) && // And it contains numbers and/or colors
|
|
1966
2178
|
!value.startsWith("url(") // Unless it starts with "url("
|
|
1967
2179
|
) {
|
|
1968
2180
|
return true;
|
|
@@ -2020,25 +2232,51 @@ const getDefaultTransition = (valueKey, to) => {
|
|
|
2020
2232
|
return { to, ...transitionFactory(to) };
|
|
2021
2233
|
};
|
|
2022
2234
|
|
|
2235
|
+
/**
|
|
2236
|
+
* Properties that should default to 1 or 100%
|
|
2237
|
+
*/
|
|
2238
|
+
const maxDefaults = new Set(["brightness", "contrast", "saturate", "opacity"]);
|
|
2239
|
+
function applyDefaultFilter(v) {
|
|
2240
|
+
const [name, value] = v.slice(0, -1).split("(");
|
|
2241
|
+
if (name === "drop-shadow")
|
|
2242
|
+
return v;
|
|
2243
|
+
const [number] = value.match(floatRegex) || [];
|
|
2244
|
+
if (!number)
|
|
2245
|
+
return v;
|
|
2246
|
+
const unit = value.replace(number, "");
|
|
2247
|
+
let defaultValue = maxDefaults.has(name) ? 1 : 0;
|
|
2248
|
+
if (number !== value)
|
|
2249
|
+
defaultValue *= 100;
|
|
2250
|
+
return name + "(" + defaultValue + unit + ")";
|
|
2251
|
+
}
|
|
2252
|
+
const functionRegex = /([a-z-]*)\(.*?\)/g;
|
|
2253
|
+
const filter = {
|
|
2254
|
+
...complex,
|
|
2255
|
+
getAnimatableNone: (v) => {
|
|
2256
|
+
const functions = v.match(functionRegex);
|
|
2257
|
+
return functions ? functions.map(applyDefaultFilter).join(" ") : v;
|
|
2258
|
+
},
|
|
2259
|
+
};
|
|
2260
|
+
|
|
2023
2261
|
/**
|
|
2024
2262
|
* A map of default value types for common values
|
|
2025
2263
|
*/
|
|
2026
2264
|
const defaultValueTypes = {
|
|
2027
2265
|
...numberValueTypes,
|
|
2028
2266
|
// Color props
|
|
2029
|
-
color
|
|
2030
|
-
backgroundColor:
|
|
2031
|
-
outlineColor:
|
|
2032
|
-
fill:
|
|
2033
|
-
stroke:
|
|
2267
|
+
color,
|
|
2268
|
+
backgroundColor: color,
|
|
2269
|
+
outlineColor: color,
|
|
2270
|
+
fill: color,
|
|
2271
|
+
stroke: color,
|
|
2034
2272
|
// Border props
|
|
2035
|
-
borderColor:
|
|
2036
|
-
borderTopColor:
|
|
2037
|
-
borderRightColor:
|
|
2038
|
-
borderBottomColor:
|
|
2039
|
-
borderLeftColor:
|
|
2040
|
-
filter
|
|
2041
|
-
WebkitFilter:
|
|
2273
|
+
borderColor: color,
|
|
2274
|
+
borderTopColor: color,
|
|
2275
|
+
borderRightColor: color,
|
|
2276
|
+
borderBottomColor: color,
|
|
2277
|
+
borderLeftColor: color,
|
|
2278
|
+
filter,
|
|
2279
|
+
WebkitFilter: filter,
|
|
2042
2280
|
};
|
|
2043
2281
|
/**
|
|
2044
2282
|
* Gets the default ValueType for the provided value key
|
|
@@ -2048,8 +2286,8 @@ const getDefaultValueType = (key) => defaultValueTypes[key];
|
|
|
2048
2286
|
function getAnimatableNone(key, value) {
|
|
2049
2287
|
var _a;
|
|
2050
2288
|
let defaultValueType = getDefaultValueType(key);
|
|
2051
|
-
if (defaultValueType !==
|
|
2052
|
-
defaultValueType =
|
|
2289
|
+
if (defaultValueType !== filter)
|
|
2290
|
+
defaultValueType = complex;
|
|
2053
2291
|
// If value is not recognised as animatable, ie "none", create an animatable version origin based on the target
|
|
2054
2292
|
return (_a = defaultValueType.getAnimatableNone) === null || _a === void 0 ? void 0 : _a.call(defaultValueType, value);
|
|
2055
2293
|
}
|
|
@@ -2058,21 +2296,176 @@ const instantAnimationState = {
|
|
|
2058
2296
|
current: false,
|
|
2059
2297
|
};
|
|
2060
2298
|
|
|
2299
|
+
/*
|
|
2300
|
+
Detect and load appropriate clock setting for the execution environment
|
|
2301
|
+
*/
|
|
2302
|
+
const defaultTimestep = (1 / 60) * 1000;
|
|
2303
|
+
const getCurrentTime = typeof performance !== "undefined"
|
|
2304
|
+
? () => performance.now()
|
|
2305
|
+
: () => Date.now();
|
|
2306
|
+
const onNextFrame = typeof window !== "undefined"
|
|
2307
|
+
? (callback) => window.requestAnimationFrame(callback)
|
|
2308
|
+
: (callback) => setTimeout(() => callback(getCurrentTime()), defaultTimestep);
|
|
2309
|
+
|
|
2310
|
+
function createRenderStep(runNextFrame) {
|
|
2311
|
+
/**
|
|
2312
|
+
* We create and reuse two arrays, one to queue jobs for the current frame
|
|
2313
|
+
* and one for the next. We reuse to avoid triggering GC after x frames.
|
|
2314
|
+
*/
|
|
2315
|
+
let toRun = [];
|
|
2316
|
+
let toRunNextFrame = [];
|
|
2317
|
+
/**
|
|
2318
|
+
*
|
|
2319
|
+
*/
|
|
2320
|
+
let numToRun = 0;
|
|
2321
|
+
/**
|
|
2322
|
+
* Track whether we're currently processing jobs in this step. This way
|
|
2323
|
+
* we can decide whether to schedule new jobs for this frame or next.
|
|
2324
|
+
*/
|
|
2325
|
+
let isProcessing = false;
|
|
2326
|
+
let flushNextFrame = false;
|
|
2327
|
+
/**
|
|
2328
|
+
* A set of processes which were marked keepAlive when scheduled.
|
|
2329
|
+
*/
|
|
2330
|
+
const toKeepAlive = new WeakSet();
|
|
2331
|
+
const step = {
|
|
2332
|
+
/**
|
|
2333
|
+
* Schedule a process to run on the next frame.
|
|
2334
|
+
*/
|
|
2335
|
+
schedule: (callback, keepAlive = false, immediate = false) => {
|
|
2336
|
+
const addToCurrentFrame = immediate && isProcessing;
|
|
2337
|
+
const buffer = addToCurrentFrame ? toRun : toRunNextFrame;
|
|
2338
|
+
if (keepAlive)
|
|
2339
|
+
toKeepAlive.add(callback);
|
|
2340
|
+
// If the buffer doesn't already contain this callback, add it
|
|
2341
|
+
if (buffer.indexOf(callback) === -1) {
|
|
2342
|
+
buffer.push(callback);
|
|
2343
|
+
// If we're adding it to the currently running buffer, update its measured size
|
|
2344
|
+
if (addToCurrentFrame && isProcessing)
|
|
2345
|
+
numToRun = toRun.length;
|
|
2346
|
+
}
|
|
2347
|
+
return callback;
|
|
2348
|
+
},
|
|
2349
|
+
/**
|
|
2350
|
+
* Cancel the provided callback from running on the next frame.
|
|
2351
|
+
*/
|
|
2352
|
+
cancel: (callback) => {
|
|
2353
|
+
const index = toRunNextFrame.indexOf(callback);
|
|
2354
|
+
if (index !== -1)
|
|
2355
|
+
toRunNextFrame.splice(index, 1);
|
|
2356
|
+
toKeepAlive.delete(callback);
|
|
2357
|
+
},
|
|
2358
|
+
/**
|
|
2359
|
+
* Execute all schedule callbacks.
|
|
2360
|
+
*/
|
|
2361
|
+
process: (frameData) => {
|
|
2362
|
+
/**
|
|
2363
|
+
* If we're already processing we've probably been triggered by a flushSync
|
|
2364
|
+
* inside an existing process. Instead of executing, mark flushNextFrame
|
|
2365
|
+
* as true and ensure we flush the following frame at the end of this one.
|
|
2366
|
+
*/
|
|
2367
|
+
if (isProcessing) {
|
|
2368
|
+
flushNextFrame = true;
|
|
2369
|
+
return;
|
|
2370
|
+
}
|
|
2371
|
+
isProcessing = true;
|
|
2372
|
+
[toRun, toRunNextFrame] = [toRunNextFrame, toRun];
|
|
2373
|
+
// Clear the next frame list
|
|
2374
|
+
toRunNextFrame.length = 0;
|
|
2375
|
+
// Execute this frame
|
|
2376
|
+
numToRun = toRun.length;
|
|
2377
|
+
if (numToRun) {
|
|
2378
|
+
for (let i = 0; i < numToRun; i++) {
|
|
2379
|
+
const callback = toRun[i];
|
|
2380
|
+
callback(frameData);
|
|
2381
|
+
if (toKeepAlive.has(callback)) {
|
|
2382
|
+
step.schedule(callback);
|
|
2383
|
+
runNextFrame();
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
isProcessing = false;
|
|
2388
|
+
if (flushNextFrame) {
|
|
2389
|
+
flushNextFrame = false;
|
|
2390
|
+
step.process(frameData);
|
|
2391
|
+
}
|
|
2392
|
+
},
|
|
2393
|
+
};
|
|
2394
|
+
return step;
|
|
2395
|
+
}
|
|
2396
|
+
|
|
2397
|
+
const frameData = {
|
|
2398
|
+
delta: 0,
|
|
2399
|
+
timestamp: 0,
|
|
2400
|
+
};
|
|
2401
|
+
|
|
2402
|
+
const maxElapsed = 40;
|
|
2403
|
+
let useDefaultElapsed = true;
|
|
2404
|
+
let runNextFrame = false;
|
|
2405
|
+
let isProcessing = false;
|
|
2406
|
+
const stepsOrder = [
|
|
2407
|
+
"read",
|
|
2408
|
+
"update",
|
|
2409
|
+
"preRender",
|
|
2410
|
+
"render",
|
|
2411
|
+
"postRender",
|
|
2412
|
+
];
|
|
2413
|
+
const steps = stepsOrder.reduce((acc, key) => {
|
|
2414
|
+
acc[key] = createRenderStep(() => (runNextFrame = true));
|
|
2415
|
+
return acc;
|
|
2416
|
+
}, {});
|
|
2417
|
+
const sync = stepsOrder.reduce((acc, key) => {
|
|
2418
|
+
const step = steps[key];
|
|
2419
|
+
acc[key] = (process, keepAlive = false, immediate = false) => {
|
|
2420
|
+
if (!runNextFrame)
|
|
2421
|
+
startLoop();
|
|
2422
|
+
return step.schedule(process, keepAlive, immediate);
|
|
2423
|
+
};
|
|
2424
|
+
return acc;
|
|
2425
|
+
}, {});
|
|
2426
|
+
const cancelSync = stepsOrder.reduce((acc, key) => {
|
|
2427
|
+
acc[key] = steps[key].cancel;
|
|
2428
|
+
return acc;
|
|
2429
|
+
}, {});
|
|
2430
|
+
const flushSync = stepsOrder.reduce((acc, key) => {
|
|
2431
|
+
acc[key] = () => steps[key].process(frameData);
|
|
2432
|
+
return acc;
|
|
2433
|
+
}, {});
|
|
2434
|
+
const processStep = (stepId) => steps[stepId].process(frameData);
|
|
2435
|
+
const processFrame = (timestamp) => {
|
|
2436
|
+
runNextFrame = false;
|
|
2437
|
+
frameData.delta = useDefaultElapsed
|
|
2438
|
+
? defaultTimestep
|
|
2439
|
+
: Math.max(Math.min(timestamp - frameData.timestamp, maxElapsed), 1);
|
|
2440
|
+
frameData.timestamp = timestamp;
|
|
2441
|
+
isProcessing = true;
|
|
2442
|
+
stepsOrder.forEach(processStep);
|
|
2443
|
+
isProcessing = false;
|
|
2444
|
+
if (runNextFrame) {
|
|
2445
|
+
useDefaultElapsed = false;
|
|
2446
|
+
onNextFrame(processFrame);
|
|
2447
|
+
}
|
|
2448
|
+
};
|
|
2449
|
+
const startLoop = () => {
|
|
2450
|
+
runNextFrame = true;
|
|
2451
|
+
useDefaultElapsed = true;
|
|
2452
|
+
if (!isProcessing)
|
|
2453
|
+
onNextFrame(processFrame);
|
|
2454
|
+
};
|
|
2455
|
+
|
|
2061
2456
|
function delay(callback, timeout) {
|
|
2062
2457
|
const start = performance.now();
|
|
2063
2458
|
const checkElapsed = ({ timestamp }) => {
|
|
2064
2459
|
const elapsed = timestamp - start;
|
|
2065
2460
|
if (elapsed >= timeout) {
|
|
2066
|
-
|
|
2461
|
+
cancelSync.read(checkElapsed);
|
|
2067
2462
|
callback(elapsed - timeout);
|
|
2068
2463
|
}
|
|
2069
2464
|
};
|
|
2070
|
-
|
|
2071
|
-
return () =>
|
|
2465
|
+
sync.read(checkElapsed, true);
|
|
2466
|
+
return () => cancelSync.read(checkElapsed);
|
|
2072
2467
|
}
|
|
2073
2468
|
|
|
2074
|
-
const clamp = (min, max, v) => Math.min(Math.max(v, min), max);
|
|
2075
|
-
|
|
2076
2469
|
/*
|
|
2077
2470
|
Value in range from progress
|
|
2078
2471
|
|
|
@@ -2144,13 +2537,14 @@ const mixLinearColor = (from, to, v) => {
|
|
|
2144
2537
|
const fromExpo = from * from;
|
|
2145
2538
|
return Math.sqrt(Math.max(0, v * (to * to - fromExpo) + fromExpo));
|
|
2146
2539
|
};
|
|
2147
|
-
const colorTypes = [
|
|
2540
|
+
const colorTypes = [hex, rgba, hsla];
|
|
2148
2541
|
const getColorType = (v) => colorTypes.find((type) => type.test(v));
|
|
2149
2542
|
function asRGBA(color) {
|
|
2150
2543
|
const type = getColorType(color);
|
|
2151
2544
|
heyListen.invariant(Boolean(type), `'${color}' is not an animatable color. Use the equivalent color code instead.`);
|
|
2152
2545
|
let model = type.parse(color);
|
|
2153
|
-
if (type ===
|
|
2546
|
+
if (type === hsla) {
|
|
2547
|
+
// TODO Remove this cast - needed since Framer Motion's stricter typing
|
|
2154
2548
|
model = hslaToRgba(model);
|
|
2155
2549
|
}
|
|
2156
2550
|
return model;
|
|
@@ -2164,7 +2558,7 @@ const mixColor = (from, to) => {
|
|
|
2164
2558
|
blended.green = mixLinearColor(fromRGBA.green, toRGBA.green, v);
|
|
2165
2559
|
blended.blue = mixLinearColor(fromRGBA.blue, toRGBA.blue, v);
|
|
2166
2560
|
blended.alpha = mix(fromRGBA.alpha, toRGBA.alpha, v);
|
|
2167
|
-
return
|
|
2561
|
+
return rgba.transform(blended);
|
|
2168
2562
|
};
|
|
2169
2563
|
};
|
|
2170
2564
|
|
|
@@ -2172,7 +2566,7 @@ function getMixer$1(origin, target) {
|
|
|
2172
2566
|
if (typeof origin === "number") {
|
|
2173
2567
|
return (v) => mix(origin, target, v);
|
|
2174
2568
|
}
|
|
2175
|
-
else if (
|
|
2569
|
+
else if (color.test(origin)) {
|
|
2176
2570
|
return mixColor(origin, target);
|
|
2177
2571
|
}
|
|
2178
2572
|
else {
|
|
@@ -2205,34 +2599,14 @@ const mixObject = (origin, target) => {
|
|
|
2205
2599
|
return output;
|
|
2206
2600
|
};
|
|
2207
2601
|
};
|
|
2208
|
-
/**
|
|
2209
|
-
* TODO: Combine with function within complex when style-value-types moved inside Framer Motion
|
|
2210
|
-
*/
|
|
2211
|
-
function analyse(value) {
|
|
2212
|
-
const parsed = styleValueTypes.complex.parse(value);
|
|
2213
|
-
const numValues = parsed.length;
|
|
2214
|
-
let numNumbers = 0;
|
|
2215
|
-
let numColors = 0;
|
|
2216
|
-
for (let i = 0; i < numValues; i++) {
|
|
2217
|
-
// Parsed complex values return with colors first, so if we've seen any number
|
|
2218
|
-
// we're already past that part of the array and don't need to continue running typeof
|
|
2219
|
-
if (numNumbers || typeof parsed[i] === "number") {
|
|
2220
|
-
numNumbers++;
|
|
2221
|
-
}
|
|
2222
|
-
else {
|
|
2223
|
-
numColors++;
|
|
2224
|
-
}
|
|
2225
|
-
}
|
|
2226
|
-
return { parsed, numNumbers, numColors };
|
|
2227
|
-
}
|
|
2228
2602
|
const mixComplex = (origin, target) => {
|
|
2229
|
-
const template =
|
|
2230
|
-
const originStats =
|
|
2231
|
-
const targetStats =
|
|
2603
|
+
const template = complex.createTransformer(target);
|
|
2604
|
+
const originStats = analyseComplexValue(origin);
|
|
2605
|
+
const targetStats = analyseComplexValue(target);
|
|
2232
2606
|
const canInterpolate = originStats.numColors === targetStats.numColors &&
|
|
2233
2607
|
originStats.numNumbers >= targetStats.numNumbers;
|
|
2234
2608
|
if (canInterpolate) {
|
|
2235
|
-
return pipe(mixArray(originStats.
|
|
2609
|
+
return pipe(mixArray(originStats.values, targetStats.values), template);
|
|
2236
2610
|
}
|
|
2237
2611
|
else {
|
|
2238
2612
|
heyListen.warning(true, `Complex values '${origin}' and '${target}' too different to mix. Ensure all colors are of the same type, and that each contains the same quantity of number and color values. Falling back to instant transition.`);
|
|
@@ -2263,7 +2637,7 @@ function detectMixerFactory(v) {
|
|
|
2263
2637
|
return mixNumber;
|
|
2264
2638
|
}
|
|
2265
2639
|
else if (typeof v === "string") {
|
|
2266
|
-
if (
|
|
2640
|
+
if (color.test(v)) {
|
|
2267
2641
|
return mixColor;
|
|
2268
2642
|
}
|
|
2269
2643
|
else {
|
|
@@ -2654,8 +3028,8 @@ function hasRepeatDelayElapsed(elapsed, duration, delay, isForwardPlayback) {
|
|
|
2654
3028
|
const framesync = (update) => {
|
|
2655
3029
|
const passTimestamp = ({ delta }) => update(delta);
|
|
2656
3030
|
return {
|
|
2657
|
-
start: () =>
|
|
2658
|
-
stop: () =>
|
|
3031
|
+
start: () => sync.update(passTimestamp, true),
|
|
3032
|
+
stop: () => cancelSync.update(passTimestamp),
|
|
2659
3033
|
};
|
|
2660
3034
|
};
|
|
2661
3035
|
function animate$1({ from, autoplay = true, driver = framesync, elapsed = 0, repeat: repeatMax = 0, repeatType = "loop", repeatDelay = 0, onPlay, onStop, onComplete, onRepeat, onUpdate, type = "keyframes", ...options }) {
|
|
@@ -2801,7 +3175,7 @@ function inertia({ from = 0, velocity = 0, min, max, power = 0.8, timeConstant =
|
|
|
2801
3175
|
const checkBoundary = (v) => {
|
|
2802
3176
|
prev = current;
|
|
2803
3177
|
current = v;
|
|
2804
|
-
velocity = velocityPerSecond(v - prev,
|
|
3178
|
+
velocity = velocityPerSecond(v - prev, frameData.delta);
|
|
2805
3179
|
if ((heading === 1 && v > boundary) ||
|
|
2806
3180
|
(heading === -1 && v < boundary)) {
|
|
2807
3181
|
startSpring({ from: v, to: boundary, velocity });
|
|
@@ -3092,7 +3466,7 @@ class MotionValue {
|
|
|
3092
3466
|
* This will be replaced by the build step with the latest version number.
|
|
3093
3467
|
* When MotionValues are provided to motion components, warn if versions are mixed.
|
|
3094
3468
|
*/
|
|
3095
|
-
this.version = "7.7.
|
|
3469
|
+
this.version = "7.7.1";
|
|
3096
3470
|
/**
|
|
3097
3471
|
* Duration, in milliseconds, since last updating frame.
|
|
3098
3472
|
*
|
|
@@ -3135,11 +3509,11 @@ class MotionValue {
|
|
|
3135
3509
|
this.prev = this.current;
|
|
3136
3510
|
this.current = v;
|
|
3137
3511
|
// Update timestamp
|
|
3138
|
-
const { delta, timestamp } =
|
|
3512
|
+
const { delta, timestamp } = frameData;
|
|
3139
3513
|
if (this.lastUpdated !== timestamp) {
|
|
3140
3514
|
this.timeDelta = delta;
|
|
3141
3515
|
this.lastUpdated = timestamp;
|
|
3142
|
-
|
|
3516
|
+
sync.postRender(this.scheduleVelocityCheck);
|
|
3143
3517
|
}
|
|
3144
3518
|
// Update update subscribers
|
|
3145
3519
|
if (this.prev !== this.current) {
|
|
@@ -3162,7 +3536,7 @@ class MotionValue {
|
|
|
3162
3536
|
*
|
|
3163
3537
|
* @internal
|
|
3164
3538
|
*/
|
|
3165
|
-
this.scheduleVelocityCheck = () =>
|
|
3539
|
+
this.scheduleVelocityCheck = () => sync.postRender(this.velocityCheck);
|
|
3166
3540
|
/**
|
|
3167
3541
|
* Updates `prev` with `current` if the value hasn't been updated this frame.
|
|
3168
3542
|
* This ensures velocity calculations return `0`.
|
|
@@ -3386,7 +3760,7 @@ const auto = {
|
|
|
3386
3760
|
/**
|
|
3387
3761
|
* A list of value types commonly used for dimensions
|
|
3388
3762
|
*/
|
|
3389
|
-
const dimensionValueTypes = [
|
|
3763
|
+
const dimensionValueTypes = [number, px, percent, degrees, vw, vh, auto];
|
|
3390
3764
|
/**
|
|
3391
3765
|
* Tests a dimensional value against the list of dimension ValueTypes
|
|
3392
3766
|
*/
|
|
@@ -3395,7 +3769,7 @@ const findDimensionValueType = (v) => dimensionValueTypes.find(testValueType(v))
|
|
|
3395
3769
|
/**
|
|
3396
3770
|
* A list of all ValueTypes
|
|
3397
3771
|
*/
|
|
3398
|
-
const valueTypes = [...dimensionValueTypes,
|
|
3772
|
+
const valueTypes = [...dimensionValueTypes, color, complex];
|
|
3399
3773
|
/**
|
|
3400
3774
|
* Tests a value against the list of ValueTypes
|
|
3401
3775
|
*/
|
|
@@ -3501,7 +3875,7 @@ function checkTargetForNewValues(visualElement, target, origin) {
|
|
|
3501
3875
|
// If this is a number read as a string, ie "0" or "200", convert it to a number
|
|
3502
3876
|
value = parseFloat(value);
|
|
3503
3877
|
}
|
|
3504
|
-
else if (!findValueType(value) &&
|
|
3878
|
+
else if (!findValueType(value) && complex.test(targetValue)) {
|
|
3505
3879
|
value = getAnimatableNone(key, targetValue);
|
|
3506
3880
|
}
|
|
3507
3881
|
visualElement.addValue(key, motionValue(value));
|
|
@@ -4062,7 +4436,7 @@ class PanSession {
|
|
|
4062
4436
|
if (!isPanStarted && !isDistancePastThreshold)
|
|
4063
4437
|
return;
|
|
4064
4438
|
const { point } = info;
|
|
4065
|
-
const { timestamp } =
|
|
4439
|
+
const { timestamp } = frameData;
|
|
4066
4440
|
this.history.push({ ...point, timestamp });
|
|
4067
4441
|
const { onStart, onMove } = this.handlers;
|
|
4068
4442
|
if (!isPanStarted) {
|
|
@@ -4080,7 +4454,7 @@ class PanSession {
|
|
|
4080
4454
|
return;
|
|
4081
4455
|
}
|
|
4082
4456
|
// Throttle mouse move event to once per frame
|
|
4083
|
-
|
|
4457
|
+
sync.update(this.updatePoint, true);
|
|
4084
4458
|
};
|
|
4085
4459
|
this.handlePointerUp = (event, info) => {
|
|
4086
4460
|
this.end();
|
|
@@ -4099,7 +4473,7 @@ class PanSession {
|
|
|
4099
4473
|
const info = extractEventInfo(event);
|
|
4100
4474
|
const initialInfo = transformPoint(info, this.transformPagePoint);
|
|
4101
4475
|
const { point } = initialInfo;
|
|
4102
|
-
const { timestamp } =
|
|
4476
|
+
const { timestamp } = frameData;
|
|
4103
4477
|
this.history = [{ ...point, timestamp }];
|
|
4104
4478
|
const { onSessionStart } = handlers;
|
|
4105
4479
|
onSessionStart &&
|
|
@@ -4111,7 +4485,7 @@ class PanSession {
|
|
|
4111
4485
|
}
|
|
4112
4486
|
end() {
|
|
4113
4487
|
this.removeListeners && this.removeListeners();
|
|
4114
|
-
|
|
4488
|
+
cancelSync.update(this.updatePoint);
|
|
4115
4489
|
}
|
|
4116
4490
|
}
|
|
4117
4491
|
function transformPoint(info, transformPagePoint) {
|
|
@@ -4593,7 +4967,7 @@ class VisualElementDragControls {
|
|
|
4593
4967
|
/**
|
|
4594
4968
|
* If the MotionValue is a percentage value convert to px
|
|
4595
4969
|
*/
|
|
4596
|
-
if (
|
|
4970
|
+
if (percent.test(current)) {
|
|
4597
4971
|
const measuredAxis = (_b = (_a = this.visualElement.projection) === null || _a === void 0 ? void 0 : _a.layout) === null || _b === void 0 ? void 0 : _b.layoutBox[axis];
|
|
4598
4972
|
if (measuredAxis) {
|
|
4599
4973
|
const length = calcLength(measuredAxis);
|
|
@@ -5123,7 +5497,7 @@ const setAndResetVelocity = (value, to) => {
|
|
|
5123
5497
|
value.set(to, false);
|
|
5124
5498
|
value.set(to);
|
|
5125
5499
|
};
|
|
5126
|
-
const isNumOrPxType = (v) => v ===
|
|
5500
|
+
const isNumOrPxType = (v) => v === number || v === px;
|
|
5127
5501
|
var BoundingBoxDimension;
|
|
5128
5502
|
(function (BoundingBoxDimension) {
|
|
5129
5503
|
BoundingBoxDimension["width"] = "width";
|
|
@@ -5259,7 +5633,7 @@ const checkAndConvertChangedValueTypes = (visualElement, target, origin = {}, tr
|
|
|
5259
5633
|
if (typeof to === "string") {
|
|
5260
5634
|
target[key] = parseFloat(to);
|
|
5261
5635
|
}
|
|
5262
|
-
else if (Array.isArray(to) && toType ===
|
|
5636
|
+
else if (Array.isArray(to) && toType === px) {
|
|
5263
5637
|
target[key] = to.map(parseFloat);
|
|
5264
5638
|
}
|
|
5265
5639
|
}
|
|
@@ -5377,7 +5751,7 @@ function updateMotionValuesFromProps(element, next, prev) {
|
|
|
5377
5751
|
* and warn against mismatches.
|
|
5378
5752
|
*/
|
|
5379
5753
|
if (process.env.NODE_ENV === "development") {
|
|
5380
|
-
warnOnce(nextValue.version === "7.7.
|
|
5754
|
+
warnOnce(nextValue.version === "7.7.1", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.7.1 may not work as expected.`);
|
|
5381
5755
|
}
|
|
5382
5756
|
}
|
|
5383
5757
|
else if (isMotionValue(prevValue)) {
|
|
@@ -5494,7 +5868,7 @@ class VisualElement {
|
|
|
5494
5868
|
this.triggerBuild();
|
|
5495
5869
|
this.renderInstance(this.current, this.renderState, this.props.style, this.projection);
|
|
5496
5870
|
};
|
|
5497
|
-
this.scheduleRender = () =>
|
|
5871
|
+
this.scheduleRender = () => sync.render(this.render, false, true);
|
|
5498
5872
|
const { latestValues, renderState } = visualState;
|
|
5499
5873
|
this.latestValues = latestValues;
|
|
5500
5874
|
this.baseTarget = { ...latestValues };
|
|
@@ -5568,8 +5942,8 @@ class VisualElement {
|
|
|
5568
5942
|
unmount() {
|
|
5569
5943
|
var _a, _b, _c;
|
|
5570
5944
|
(_a = this.projection) === null || _a === void 0 ? void 0 : _a.unmount();
|
|
5571
|
-
|
|
5572
|
-
|
|
5945
|
+
cancelSync.update(this.notifyUpdate);
|
|
5946
|
+
cancelSync.render(this.render);
|
|
5573
5947
|
this.valueSubscriptions.forEach((remove) => remove());
|
|
5574
5948
|
(_b = this.removeFromVariantTree) === null || _b === void 0 ? void 0 : _b.call(this);
|
|
5575
5949
|
(_c = this.parent) === null || _c === void 0 ? void 0 : _c.children.delete(this);
|
|
@@ -5583,7 +5957,7 @@ class VisualElement {
|
|
|
5583
5957
|
const removeOnChange = value.onChange((latestValue) => {
|
|
5584
5958
|
this.latestValues[key] = latestValue;
|
|
5585
5959
|
this.props.onUpdate &&
|
|
5586
|
-
|
|
5960
|
+
sync.update(this.notifyUpdate, false, true);
|
|
5587
5961
|
if (valueIsTransform && this.projection) {
|
|
5588
5962
|
this.projection.isTransformDirty = true;
|
|
5589
5963
|
}
|
|
@@ -6004,7 +6378,7 @@ const correctBorderRadius = {
|
|
|
6004
6378
|
* going to be stretched appropriately. Otherwise, if it's a pixel, convert it to a number.
|
|
6005
6379
|
*/
|
|
6006
6380
|
if (typeof latest === "string") {
|
|
6007
|
-
if (
|
|
6381
|
+
if (px.test(latest)) {
|
|
6008
6382
|
latest = parseFloat(latest);
|
|
6009
6383
|
}
|
|
6010
6384
|
else {
|
|
@@ -6036,11 +6410,11 @@ const correctBoxShadow = {
|
|
|
6036
6410
|
return varToken;
|
|
6037
6411
|
});
|
|
6038
6412
|
}
|
|
6039
|
-
const shadow =
|
|
6413
|
+
const shadow = complex.parse(latest);
|
|
6040
6414
|
// TODO: Doesn't support multiple shadows
|
|
6041
6415
|
if (shadow.length > 5)
|
|
6042
6416
|
return original;
|
|
6043
|
-
const template =
|
|
6417
|
+
const template = complex.createTransformer(latest);
|
|
6044
6418
|
const offset = typeof shadow[0] !== "number" ? 1 : 0;
|
|
6045
6419
|
// Calculate the overall context scale
|
|
6046
6420
|
const xScale = projectionDelta.x.scale * treeScale.x;
|
|
@@ -6131,7 +6505,7 @@ class MeasureLayoutWithContext extends React__default["default"].Component {
|
|
|
6131
6505
|
* it's in charge of the exit animation and therefore should
|
|
6132
6506
|
* be in charge of the safe to remove. Otherwise we call it here.
|
|
6133
6507
|
*/
|
|
6134
|
-
|
|
6508
|
+
sync.postRender(() => {
|
|
6135
6509
|
var _a;
|
|
6136
6510
|
if (!((_a = projection.getStack()) === null || _a === void 0 ? void 0 : _a.members.length)) {
|
|
6137
6511
|
this.safeToRemove();
|
|
@@ -6234,7 +6608,7 @@ function animate(from, to, transition = {}) {
|
|
|
6234
6608
|
const borders = ["TopLeft", "TopRight", "BottomLeft", "BottomRight"];
|
|
6235
6609
|
const numBorders = borders.length;
|
|
6236
6610
|
const asNumber = (value) => typeof value === "string" ? parseFloat(value) : value;
|
|
6237
|
-
const isPx = (value) => typeof value === "number" ||
|
|
6611
|
+
const isPx = (value) => typeof value === "number" || px.test(value);
|
|
6238
6612
|
function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnlyMember) {
|
|
6239
6613
|
var _a, _b, _c, _d;
|
|
6240
6614
|
if (shouldCrossfadeOpacity) {
|
|
@@ -6263,7 +6637,7 @@ function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnl
|
|
|
6263
6637
|
isPx(followRadius) === isPx(leadRadius);
|
|
6264
6638
|
if (canMix) {
|
|
6265
6639
|
target[borderLabel] = Math.max(mix(asNumber(followRadius), asNumber(leadRadius), progress), 0);
|
|
6266
|
-
if (
|
|
6640
|
+
if (percent.test(leadRadius) || percent.test(followRadius)) {
|
|
6267
6641
|
target[borderLabel] += "%";
|
|
6268
6642
|
}
|
|
6269
6643
|
}
|
|
@@ -6352,7 +6726,7 @@ function removePointDelta(point, translate, scale, originPoint, boxScale) {
|
|
|
6352
6726
|
* Remove a delta from an axis. This is essentially the steps of applyAxisDelta in reverse
|
|
6353
6727
|
*/
|
|
6354
6728
|
function removeAxisDelta(axis, translate = 0, scale = 1, origin = 0.5, boxScale, originAxis = axis, sourceAxis = axis) {
|
|
6355
|
-
if (
|
|
6729
|
+
if (percent.test(translate)) {
|
|
6356
6730
|
translate = parseFloat(translate);
|
|
6357
6731
|
const relativeProgress = mix(sourceAxis.min, sourceAxis.max, translate / 100);
|
|
6358
6732
|
translate = relativeProgress - sourceAxis.min;
|
|
@@ -6819,7 +7193,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6819
7193
|
(_a = this.getStack()) === null || _a === void 0 ? void 0 : _a.remove(this);
|
|
6820
7194
|
(_b = this.parent) === null || _b === void 0 ? void 0 : _b.children.delete(this);
|
|
6821
7195
|
this.instance = undefined;
|
|
6822
|
-
|
|
7196
|
+
cancelSync.preRender(this.updateProjection);
|
|
6823
7197
|
}
|
|
6824
7198
|
// only on the root
|
|
6825
7199
|
blockUpdate() {
|
|
@@ -6910,16 +7284,16 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6910
7284
|
this.nodes.forEach(notifyLayoutUpdate);
|
|
6911
7285
|
this.clearAllSnapshots();
|
|
6912
7286
|
// Flush any scheduled updates
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
7287
|
+
flushSync.update();
|
|
7288
|
+
flushSync.preRender();
|
|
7289
|
+
flushSync.render();
|
|
6916
7290
|
}
|
|
6917
7291
|
clearAllSnapshots() {
|
|
6918
7292
|
this.nodes.forEach(clearSnapshot);
|
|
6919
7293
|
this.sharedNodes.forEach(removeLeadSnapshots);
|
|
6920
7294
|
}
|
|
6921
7295
|
scheduleUpdateProjection() {
|
|
6922
|
-
|
|
7296
|
+
sync.preRender(this.updateProjection, false, true);
|
|
6923
7297
|
}
|
|
6924
7298
|
scheduleCheckAfterUnmount() {
|
|
6925
7299
|
/**
|
|
@@ -6927,7 +7301,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
6927
7301
|
* we manually call didUpdate to give a chance to the siblings to animate.
|
|
6928
7302
|
* Otherwise, cleanup all snapshots to prevents future nodes from reusing them.
|
|
6929
7303
|
*/
|
|
6930
|
-
|
|
7304
|
+
sync.postRender(() => {
|
|
6931
7305
|
if (this.isLayoutDirty) {
|
|
6932
7306
|
this.root.didUpdate();
|
|
6933
7307
|
}
|
|
@@ -7391,7 +7765,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
7391
7765
|
(_b = this.resumingFrom.currentAnimation) === null || _b === void 0 ? void 0 : _b.stop();
|
|
7392
7766
|
}
|
|
7393
7767
|
if (this.pendingAnimation) {
|
|
7394
|
-
|
|
7768
|
+
cancelSync.update(this.pendingAnimation);
|
|
7395
7769
|
this.pendingAnimation = undefined;
|
|
7396
7770
|
}
|
|
7397
7771
|
/**
|
|
@@ -7399,7 +7773,7 @@ function createProjectionNode({ attachResizeListener, defaultParent, measureScro
|
|
|
7399
7773
|
* where the target is the same as when the animation started, so we can
|
|
7400
7774
|
* calculate the relative positions correctly for instant transitions.
|
|
7401
7775
|
*/
|
|
7402
|
-
this.pendingAnimation =
|
|
7776
|
+
this.pendingAnimation = sync.update(() => {
|
|
7403
7777
|
globalProjectionState.hasAnimatedSinceResize = true;
|
|
7404
7778
|
this.currentAnimation = animate(0, animationTarget, {
|
|
7405
7779
|
...options,
|
|
@@ -7953,7 +8327,7 @@ function useForceUpdate() {
|
|
|
7953
8327
|
* Defer this to the end of the next animation frame in case there are multiple
|
|
7954
8328
|
* synchronous calls.
|
|
7955
8329
|
*/
|
|
7956
|
-
const deferredForceRender = React.useCallback(() =>
|
|
8330
|
+
const deferredForceRender = React.useCallback(() => sync.postRender(forceRender), [forceRender]);
|
|
7957
8331
|
return [deferredForceRender, forcedRenderCount];
|
|
7958
8332
|
}
|
|
7959
8333
|
|
|
@@ -8533,7 +8907,7 @@ function useCombineMotionValues(values, combineValues) {
|
|
|
8533
8907
|
* Subscribe to all motion values found within the template. Whenever any of them change,
|
|
8534
8908
|
* schedule an update.
|
|
8535
8909
|
*/
|
|
8536
|
-
useMultiOnChange(values, () =>
|
|
8910
|
+
useMultiOnChange(values, () => sync.update(updateValue, false, true), () => cancelSync.update(updateValue));
|
|
8537
8911
|
return value;
|
|
8538
8912
|
}
|
|
8539
8913
|
|
|
@@ -8771,8 +9145,8 @@ function useAnimationFrame(callback) {
|
|
|
8771
9145
|
initialTimestamp.current = timestamp;
|
|
8772
9146
|
callback(timestamp - initialTimestamp.current, delta);
|
|
8773
9147
|
};
|
|
8774
|
-
|
|
8775
|
-
return () =>
|
|
9148
|
+
sync.update(provideTimeSinceStart, true);
|
|
9149
|
+
return () => cancelSync.update(provideTimeSinceStart);
|
|
8776
9150
|
}, [callback]);
|
|
8777
9151
|
}
|
|
8778
9152
|
|
|
@@ -9176,7 +9550,7 @@ function useInstantTransition() {
|
|
|
9176
9550
|
/**
|
|
9177
9551
|
* Unblock after two animation frames, otherwise this will unblock too soon.
|
|
9178
9552
|
*/
|
|
9179
|
-
|
|
9553
|
+
sync.postRender(() => sync.postRender(() => (instantAnimationState.current = false)));
|
|
9180
9554
|
}, [forcedRenderCount]);
|
|
9181
9555
|
return (callback) => {
|
|
9182
9556
|
startInstantLayoutTransition(() => {
|