framer-motion 7.7.0 → 7.7.2

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.
Files changed (65) hide show
  1. package/dist/cjs/index.js +549 -174
  2. package/dist/es/animation/legacy-popmotion/index.mjs +5 -3
  3. package/dist/es/animation/legacy-popmotion/inertia.mjs +2 -2
  4. package/dist/es/animation/utils/is-animatable.mjs +1 -1
  5. package/dist/es/animation/utils/transitions.mjs +5 -2
  6. package/dist/es/frameloop/create-render-step.mjs +88 -0
  7. package/dist/es/frameloop/data.mjs +6 -0
  8. package/dist/es/frameloop/index.mjs +59 -0
  9. package/dist/es/frameloop/on-next-frame.mjs +12 -0
  10. package/dist/es/gestures/PanSession.mjs +4 -3
  11. package/dist/es/gestures/drag/VisualElementDragControls.mjs +4 -5
  12. package/dist/es/gestures/drag/utils/constraints.mjs +1 -2
  13. package/dist/es/motion/features/layout/MeasureLayout.mjs +1 -1
  14. package/dist/es/projection/animation/mix-values.mjs +7 -8
  15. package/dist/es/projection/geometry/delta-remove.mjs +1 -1
  16. package/dist/es/projection/node/create-projection-node.mjs +1 -1
  17. package/dist/es/projection/styles/scale-border-radius.mjs +1 -1
  18. package/dist/es/projection/styles/scale-box-shadow.mjs +1 -1
  19. package/dist/es/render/VisualElement.mjs +1 -1
  20. package/dist/es/render/dom/utils/unit-conversion.mjs +2 -1
  21. package/dist/es/render/dom/value-types/animatable-none.mjs +2 -1
  22. package/dist/es/render/dom/value-types/defaults.mjs +2 -1
  23. package/dist/es/render/dom/value-types/dimensions.mjs +2 -1
  24. package/dist/es/render/dom/value-types/find.mjs +2 -1
  25. package/dist/es/render/dom/value-types/number.mjs +2 -1
  26. package/dist/es/render/dom/value-types/type-int.mjs +1 -1
  27. package/dist/es/render/svg/utils/path.mjs +1 -1
  28. package/dist/es/render/svg/utils/transform-origin.mjs +1 -1
  29. package/dist/es/render/utils/animation-state.mjs +1 -2
  30. package/dist/es/render/utils/motion-values.mjs +1 -1
  31. package/dist/es/render/utils/setters.mjs +1 -1
  32. package/dist/es/utils/delay.mjs +1 -1
  33. package/dist/es/utils/interpolate.mjs +1 -1
  34. package/dist/es/utils/mix-color.mjs +4 -1
  35. package/dist/es/utils/mix-complex.mjs +5 -24
  36. package/dist/es/utils/use-animation-frame.mjs +1 -1
  37. package/dist/es/utils/use-force-update.mjs +1 -1
  38. package/dist/es/utils/use-instant-transition.mjs +1 -1
  39. package/dist/es/value/index.mjs +4 -3
  40. package/dist/es/value/types/color/hex.mjs +40 -0
  41. package/dist/es/value/types/color/hsla.mjs +22 -0
  42. package/dist/es/value/types/color/index.mjs +28 -0
  43. package/dist/es/value/types/color/rgba.mjs +25 -0
  44. package/dist/es/value/types/color/utils.mjs +23 -0
  45. package/dist/es/value/types/complex/filter.mjs +30 -0
  46. package/dist/es/value/types/complex/index.mjs +61 -0
  47. package/dist/es/value/types/numbers/index.mjs +17 -0
  48. package/dist/es/value/types/numbers/units.mjs +19 -0
  49. package/dist/es/value/types/utils.mjs +15 -0
  50. package/dist/es/value/use-combine-values.mjs +1 -1
  51. package/dist/framer-motion.dev.js +304 -249
  52. package/dist/framer-motion.js +1 -1
  53. package/dist/index.d.ts +7 -2
  54. package/dist/projection.dev.js +5455 -5397
  55. package/dist/size-rollup-dom-animation-assets.js +1 -1
  56. package/dist/size-rollup-dom-animation.js +1 -1
  57. package/dist/size-rollup-dom-max-assets.js +1 -1
  58. package/dist/size-rollup-dom-max.js +1 -1
  59. package/dist/size-rollup-m.js +1 -1
  60. package/dist/size-rollup-motion.js +1 -1
  61. package/dist/size-webpack-dom-animation.js +1 -1
  62. package/dist/size-webpack-dom-max.js +1 -1
  63. package/dist/size-webpack-m.js +1 -1
  64. package/dist/three-entry.d.ts +7 -2
  65. package/package.json +9 -11
@@ -558,207 +558,52 @@
558
558
  : value;
559
559
  };
560
560
 
561
- const clamp$2 = (min, max) => (v) => Math.max(Math.min(v, max), min);
562
- const sanitize = (v) => (v % 1 ? Number(v.toFixed(5)) : v);
563
- const floatRegex = /(-)?([\d]*\.?[\d])+/g;
564
- 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;
565
- const singleColorRegex = /^(#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))$/i;
566
- function isString$1(v) {
567
- return typeof v === 'string';
568
- }
561
+ const clamp$1 = (min, max, v) => Math.min(Math.max(v, min), max);
569
562
 
570
563
  const number = {
571
- test: (v) => typeof v === 'number',
564
+ test: (v) => typeof v === "number",
572
565
  parse: parseFloat,
573
566
  transform: (v) => v,
574
567
  };
575
- const alpha = Object.assign(Object.assign({}, number), { transform: clamp$2(0, 1) });
576
- const scale = Object.assign(Object.assign({}, number), { default: 1 });
577
-
578
- const createUnitType = (unit) => ({
579
- test: (v) => isString$1(v) && v.endsWith(unit) && v.split(' ').length === 1,
580
- parse: parseFloat,
581
- transform: (v) => `${v}${unit}`,
582
- });
583
- const degrees = createUnitType('deg');
584
- const percent = createUnitType('%');
585
- const px = createUnitType('px');
586
- const vh = createUnitType('vh');
587
- const vw = createUnitType('vw');
588
- const progressPercentage = Object.assign(Object.assign({}, percent), { parse: (v) => percent.parse(v) / 100, transform: (v) => percent.transform(v * 100) });
589
-
590
- const isColorString = (type, testProp) => (v) => {
591
- return Boolean((isString$1(v) && singleColorRegex.test(v) && v.startsWith(type)) ||
592
- (testProp && Object.prototype.hasOwnProperty.call(v, testProp)));
593
- };
594
- const splitColor = (aName, bName, cName) => (v) => {
595
- if (!isString$1(v))
596
- return v;
597
- const [a, b, c, alpha] = v.match(floatRegex);
598
- return {
599
- [aName]: parseFloat(a),
600
- [bName]: parseFloat(b),
601
- [cName]: parseFloat(c),
602
- alpha: alpha !== undefined ? parseFloat(alpha) : 1,
603
- };
604
- };
605
-
606
- const hsla = {
607
- test: isColorString('hsl', 'hue'),
608
- parse: splitColor('hue', 'saturation', 'lightness'),
609
- transform: ({ hue, saturation, lightness, alpha: alpha$1 = 1 }) => {
610
- return ('hsla(' +
611
- Math.round(hue) +
612
- ', ' +
613
- percent.transform(sanitize(saturation)) +
614
- ', ' +
615
- percent.transform(sanitize(lightness)) +
616
- ', ' +
617
- sanitize(alpha.transform(alpha$1)) +
618
- ')');
619
- },
568
+ const alpha = {
569
+ ...number,
570
+ transform: (v) => clamp$1(0, 1, v),
620
571
  };
621
-
622
- const clampRgbUnit = clamp$2(0, 255);
623
- const rgbUnit = Object.assign(Object.assign({}, number), { transform: (v) => Math.round(clampRgbUnit(v)) });
624
- const rgba = {
625
- test: isColorString('rgb', 'red'),
626
- parse: splitColor('red', 'green', 'blue'),
627
- transform: ({ red, green, blue, alpha: alpha$1 = 1 }) => 'rgba(' +
628
- rgbUnit.transform(red) +
629
- ', ' +
630
- rgbUnit.transform(green) +
631
- ', ' +
632
- rgbUnit.transform(blue) +
633
- ', ' +
634
- sanitize(alpha.transform(alpha$1)) +
635
- ')',
572
+ const scale = {
573
+ ...number,
574
+ default: 1,
636
575
  };
637
576
 
638
- function parseHex(v) {
639
- let r = '';
640
- let g = '';
641
- let b = '';
642
- let a = '';
643
- if (v.length > 5) {
644
- r = v.substr(1, 2);
645
- g = v.substr(3, 2);
646
- b = v.substr(5, 2);
647
- a = v.substr(7, 2);
648
- }
649
- else {
650
- r = v.substr(1, 1);
651
- g = v.substr(2, 1);
652
- b = v.substr(3, 1);
653
- a = v.substr(4, 1);
654
- r += r;
655
- g += g;
656
- b += b;
657
- a += a;
658
- }
659
- return {
660
- red: parseInt(r, 16),
661
- green: parseInt(g, 16),
662
- blue: parseInt(b, 16),
663
- alpha: a ? parseInt(a, 16) / 255 : 1,
664
- };
577
+ /**
578
+ * TODO: When we move from string as a source of truth to data models
579
+ * everything in this folder should probably be referred to as models vs types
580
+ */
581
+ // If this number is a decimal, make it just five decimal places
582
+ // to avoid exponents
583
+ const sanitize = (v) => Math.round(v * 100000) / 100000;
584
+ const floatRegex = /(-)?([\d]*\.?[\d])+/g;
585
+ 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;
586
+ const singleColorRegex = /^(#[0-9a-f]{3}|#(?:[0-9a-f]{2}){2,4}|(rgb|hsl)a?\((-?[\d\.]+%?[,\s]+){2}(-?[\d\.]+%?)\s*[\,\/]?\s*[\d\.]*%?\))$/i;
587
+ function isString$1(v) {
588
+ return typeof v === "string";
665
589
  }
666
- const hex = {
667
- test: isColorString('#'),
668
- parse: parseHex,
669
- transform: rgba.transform,
670
- };
671
590
 
672
- const color = {
673
- test: (v) => rgba.test(v) || hex.test(v) || hsla.test(v),
674
- parse: (v) => {
675
- if (rgba.test(v)) {
676
- return rgba.parse(v);
677
- }
678
- else if (hsla.test(v)) {
679
- return hsla.parse(v);
680
- }
681
- else {
682
- return hex.parse(v);
683
- }
684
- },
685
- transform: (v) => {
686
- return isString$1(v)
687
- ? v
688
- : v.hasOwnProperty('red')
689
- ? rgba.transform(v)
690
- : hsla.transform(v);
691
- },
591
+ const createUnitType = (unit) => ({
592
+ test: (v) => isString$1(v) && v.endsWith(unit) && v.split(" ").length === 1,
593
+ parse: parseFloat,
594
+ transform: (v) => `${v}${unit}`,
595
+ });
596
+ const degrees = createUnitType("deg");
597
+ const percent = createUnitType("%");
598
+ const px = createUnitType("px");
599
+ const vh = createUnitType("vh");
600
+ const vw = createUnitType("vw");
601
+ const progressPercentage = {
602
+ ...percent,
603
+ parse: (v) => percent.parse(v) / 100,
604
+ transform: (v) => percent.transform(v * 100),
692
605
  };
693
606
 
694
- const colorToken = '${c}';
695
- const numberToken = '${n}';
696
- function test(v) {
697
- var _a, _b, _c, _d;
698
- return (isNaN(v) &&
699
- isString$1(v) &&
700
- ((_b = (_a = v.match(floatRegex)) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0) + ((_d = (_c = v.match(colorRegex)) === null || _c === void 0 ? void 0 : _c.length) !== null && _d !== void 0 ? _d : 0) > 0);
701
- }
702
- function analyse$1(v) {
703
- if (typeof v === 'number')
704
- v = `${v}`;
705
- const values = [];
706
- let numColors = 0;
707
- const colors = v.match(colorRegex);
708
- if (colors) {
709
- numColors = colors.length;
710
- v = v.replace(colorRegex, colorToken);
711
- values.push(...colors.map(color.parse));
712
- }
713
- const numbers = v.match(floatRegex);
714
- if (numbers) {
715
- v = v.replace(floatRegex, numberToken);
716
- values.push(...numbers.map(number.parse));
717
- }
718
- return { values, numColors, tokenised: v };
719
- }
720
- function parse(v) {
721
- return analyse$1(v).values;
722
- }
723
- function createTransformer(v) {
724
- const { values, numColors, tokenised } = analyse$1(v);
725
- const numValues = values.length;
726
- return (v) => {
727
- let output = tokenised;
728
- for (let i = 0; i < numValues; i++) {
729
- output = output.replace(i < numColors ? colorToken : numberToken, i < numColors ? color.transform(v[i]) : sanitize(v[i]));
730
- }
731
- return output;
732
- };
733
- }
734
- const convertNumbersToZero = (v) => typeof v === 'number' ? 0 : v;
735
- function getAnimatableNone$1(v) {
736
- const parsed = parse(v);
737
- const transformer = createTransformer(v);
738
- return transformer(parsed.map(convertNumbersToZero));
739
- }
740
- const complex = { test, parse, createTransformer, getAnimatableNone: getAnimatableNone$1 };
741
-
742
- const maxDefaults = new Set(['brightness', 'contrast', 'saturate', 'opacity']);
743
- function applyDefaultFilter(v) {
744
- let [name, value] = v.slice(0, -1).split('(');
745
- if (name === 'drop-shadow')
746
- return v;
747
- const [number] = value.match(floatRegex) || [];
748
- if (!number)
749
- return v;
750
- const unit = value.replace(number, '');
751
- let defaultValue = maxDefaults.has(name) ? 1 : 0;
752
- if (number !== value)
753
- defaultValue *= 100;
754
- return name + '(' + defaultValue + unit + ')';
755
- }
756
- const functionRegex = /([a-z-]*)\(.*?\)/g;
757
- const filter = Object.assign(Object.assign({}, complex), { getAnimatableNone: (v) => {
758
- const functions = v.match(functionRegex);
759
- return functions ? functions.map(applyDefaultFilter).join(' ') : v;
760
- } });
761
-
762
607
  const int = {
763
608
  ...number,
764
609
  transform: Math.round,
@@ -2154,6 +1999,175 @@
2154
1999
  return Array.isArray(ease) && typeof ease[0] !== "number";
2155
2000
  };
2156
2001
 
2002
+ /**
2003
+ * Returns true if the provided string is a color, ie rgba(0,0,0,0) or #000,
2004
+ * but false if a number or multiple colors
2005
+ */
2006
+ const isColorString = (type, testProp) => (v) => {
2007
+ return Boolean((isString$1(v) && singleColorRegex.test(v) && v.startsWith(type)) ||
2008
+ (testProp && Object.prototype.hasOwnProperty.call(v, testProp)));
2009
+ };
2010
+ const splitColor = (aName, bName, cName) => (v) => {
2011
+ if (!isString$1(v))
2012
+ return v;
2013
+ const [a, b, c, alpha] = v.match(floatRegex);
2014
+ return {
2015
+ [aName]: parseFloat(a),
2016
+ [bName]: parseFloat(b),
2017
+ [cName]: parseFloat(c),
2018
+ alpha: alpha !== undefined ? parseFloat(alpha) : 1,
2019
+ };
2020
+ };
2021
+
2022
+ const clampRgbUnit = (v) => clamp$1(0, 255, v);
2023
+ const rgbUnit = {
2024
+ ...number,
2025
+ transform: (v) => Math.round(clampRgbUnit(v)),
2026
+ };
2027
+ const rgba = {
2028
+ test: isColorString("rgb", "red"),
2029
+ parse: splitColor("red", "green", "blue"),
2030
+ transform: ({ red, green, blue, alpha: alpha$1 = 1 }) => "rgba(" +
2031
+ rgbUnit.transform(red) +
2032
+ ", " +
2033
+ rgbUnit.transform(green) +
2034
+ ", " +
2035
+ rgbUnit.transform(blue) +
2036
+ ", " +
2037
+ sanitize(alpha.transform(alpha$1)) +
2038
+ ")",
2039
+ };
2040
+
2041
+ function parseHex(v) {
2042
+ let r = "";
2043
+ let g = "";
2044
+ let b = "";
2045
+ let a = "";
2046
+ // If we have 6 characters, ie #FF0000
2047
+ if (v.length > 5) {
2048
+ r = v.substring(1, 3);
2049
+ g = v.substring(3, 5);
2050
+ b = v.substring(5, 7);
2051
+ a = v.substring(7, 9);
2052
+ // Or we have 3 characters, ie #F00
2053
+ }
2054
+ else {
2055
+ r = v.substring(1, 2);
2056
+ g = v.substring(2, 3);
2057
+ b = v.substring(3, 4);
2058
+ a = v.substring(4, 5);
2059
+ r += r;
2060
+ g += g;
2061
+ b += b;
2062
+ a += a;
2063
+ }
2064
+ return {
2065
+ red: parseInt(r, 16),
2066
+ green: parseInt(g, 16),
2067
+ blue: parseInt(b, 16),
2068
+ alpha: a ? parseInt(a, 16) / 255 : 1,
2069
+ };
2070
+ }
2071
+ const hex = {
2072
+ test: isColorString("#"),
2073
+ parse: parseHex,
2074
+ transform: rgba.transform,
2075
+ };
2076
+
2077
+ const hsla = {
2078
+ test: isColorString("hsl", "hue"),
2079
+ parse: splitColor("hue", "saturation", "lightness"),
2080
+ transform: ({ hue, saturation, lightness, alpha: alpha$1 = 1 }) => {
2081
+ return ("hsla(" +
2082
+ Math.round(hue) +
2083
+ ", " +
2084
+ percent.transform(sanitize(saturation)) +
2085
+ ", " +
2086
+ percent.transform(sanitize(lightness)) +
2087
+ ", " +
2088
+ sanitize(alpha.transform(alpha$1)) +
2089
+ ")");
2090
+ },
2091
+ };
2092
+
2093
+ const color = {
2094
+ test: (v) => rgba.test(v) || hex.test(v) || hsla.test(v),
2095
+ parse: (v) => {
2096
+ if (rgba.test(v)) {
2097
+ return rgba.parse(v);
2098
+ }
2099
+ else if (hsla.test(v)) {
2100
+ return hsla.parse(v);
2101
+ }
2102
+ else {
2103
+ return hex.parse(v);
2104
+ }
2105
+ },
2106
+ transform: (v) => {
2107
+ return isString$1(v)
2108
+ ? v
2109
+ : v.hasOwnProperty("red")
2110
+ ? rgba.transform(v)
2111
+ : hsla.transform(v);
2112
+ },
2113
+ };
2114
+
2115
+ const colorToken = "${c}";
2116
+ const numberToken = "${n}";
2117
+ function test(v) {
2118
+ var _a, _b;
2119
+ return (isNaN(v) &&
2120
+ isString$1(v) &&
2121
+ (((_a = v.match(floatRegex)) === null || _a === void 0 ? void 0 : _a.length) || 0) +
2122
+ (((_b = v.match(colorRegex)) === null || _b === void 0 ? void 0 : _b.length) || 0) >
2123
+ 0);
2124
+ }
2125
+ function analyseComplexValue(v) {
2126
+ if (typeof v === "number")
2127
+ v = `${v}`;
2128
+ const values = [];
2129
+ let numColors = 0;
2130
+ let numNumbers = 0;
2131
+ const colors = v.match(colorRegex);
2132
+ if (colors) {
2133
+ numColors = colors.length;
2134
+ // Strip colors from input so they're not picked up by number regex.
2135
+ // There's a better way to combine these regex searches, but its beyond my regex skills
2136
+ v = v.replace(colorRegex, colorToken);
2137
+ values.push(...colors.map(color.parse));
2138
+ }
2139
+ const numbers = v.match(floatRegex);
2140
+ if (numbers) {
2141
+ numNumbers = numbers.length;
2142
+ v = v.replace(floatRegex, numberToken);
2143
+ values.push(...numbers.map(number.parse));
2144
+ }
2145
+ return { values, numColors, numNumbers, tokenised: v };
2146
+ }
2147
+ function parse(v) {
2148
+ return analyseComplexValue(v).values;
2149
+ }
2150
+ function createTransformer(source) {
2151
+ const { values, numColors, tokenised } = analyseComplexValue(source);
2152
+ const numValues = values.length;
2153
+ return (v) => {
2154
+ let output = tokenised;
2155
+ for (let i = 0; i < numValues; i++) {
2156
+ output = output.replace(i < numColors ? colorToken : numberToken, i < numColors
2157
+ ? color.transform(v[i])
2158
+ : sanitize(v[i]));
2159
+ }
2160
+ return output;
2161
+ };
2162
+ }
2163
+ const convertNumbersToZero = (v) => typeof v === "number" ? 0 : v;
2164
+ function getAnimatableNone$1(v) {
2165
+ const parsed = parse(v);
2166
+ const transformer = createTransformer(v);
2167
+ return transformer(parsed.map(convertNumbersToZero));
2168
+ }
2169
+ const complex = { test, parse, createTransformer, getAnimatableNone: getAnimatableNone$1 };
2170
+
2157
2171
  /**
2158
2172
  * Check if a value is animatable. Examples:
2159
2173
  *
@@ -2231,6 +2245,32 @@
2231
2245
  return { to, ...transitionFactory(to) };
2232
2246
  };
2233
2247
 
2248
+ /**
2249
+ * Properties that should default to 1 or 100%
2250
+ */
2251
+ const maxDefaults = new Set(["brightness", "contrast", "saturate", "opacity"]);
2252
+ function applyDefaultFilter(v) {
2253
+ const [name, value] = v.slice(0, -1).split("(");
2254
+ if (name === "drop-shadow")
2255
+ return v;
2256
+ const [number] = value.match(floatRegex) || [];
2257
+ if (!number)
2258
+ return v;
2259
+ const unit = value.replace(number, "");
2260
+ let defaultValue = maxDefaults.has(name) ? 1 : 0;
2261
+ if (number !== value)
2262
+ defaultValue *= 100;
2263
+ return name + "(" + defaultValue + unit + ")";
2264
+ }
2265
+ const functionRegex = /([a-z-]*)\(.*?\)/g;
2266
+ const filter = {
2267
+ ...complex,
2268
+ getAnimatableNone: (v) => {
2269
+ const functions = v.match(functionRegex);
2270
+ return functions ? functions.map(applyDefaultFilter).join(" ") : v;
2271
+ },
2272
+ };
2273
+
2234
2274
  /**
2235
2275
  * A map of default value types for common values
2236
2276
  */
@@ -2269,6 +2309,9 @@
2269
2309
  current: false,
2270
2310
  };
2271
2311
 
2312
+ /*
2313
+ Detect and load appropriate clock setting for the execution environment
2314
+ */
2272
2315
  const defaultTimestep = (1 / 60) * 1000;
2273
2316
  const getCurrentTime = typeof performance !== "undefined"
2274
2317
  ? () => performance.now()
@@ -2278,39 +2321,71 @@
2278
2321
  : (callback) => setTimeout(() => callback(getCurrentTime()), defaultTimestep);
2279
2322
 
2280
2323
  function createRenderStep(runNextFrame) {
2324
+ /**
2325
+ * We create and reuse two arrays, one to queue jobs for the current frame
2326
+ * and one for the next. We reuse to avoid triggering GC after x frames.
2327
+ */
2281
2328
  let toRun = [];
2282
2329
  let toRunNextFrame = [];
2330
+ /**
2331
+ *
2332
+ */
2283
2333
  let numToRun = 0;
2334
+ /**
2335
+ * Track whether we're currently processing jobs in this step. This way
2336
+ * we can decide whether to schedule new jobs for this frame or next.
2337
+ */
2284
2338
  let isProcessing = false;
2285
2339
  let flushNextFrame = false;
2340
+ /**
2341
+ * A set of processes which were marked keepAlive when scheduled.
2342
+ */
2286
2343
  const toKeepAlive = new WeakSet();
2287
2344
  const step = {
2345
+ /**
2346
+ * Schedule a process to run on the next frame.
2347
+ */
2288
2348
  schedule: (callback, keepAlive = false, immediate = false) => {
2289
2349
  const addToCurrentFrame = immediate && isProcessing;
2290
2350
  const buffer = addToCurrentFrame ? toRun : toRunNextFrame;
2291
2351
  if (keepAlive)
2292
2352
  toKeepAlive.add(callback);
2353
+ // If the buffer doesn't already contain this callback, add it
2293
2354
  if (buffer.indexOf(callback) === -1) {
2294
2355
  buffer.push(callback);
2356
+ // If we're adding it to the currently running buffer, update its measured size
2295
2357
  if (addToCurrentFrame && isProcessing)
2296
2358
  numToRun = toRun.length;
2297
2359
  }
2298
2360
  return callback;
2299
2361
  },
2362
+ /**
2363
+ * Cancel the provided callback from running on the next frame.
2364
+ */
2300
2365
  cancel: (callback) => {
2301
2366
  const index = toRunNextFrame.indexOf(callback);
2302
2367
  if (index !== -1)
2303
2368
  toRunNextFrame.splice(index, 1);
2304
2369
  toKeepAlive.delete(callback);
2305
2370
  },
2371
+ /**
2372
+ * Execute all schedule callbacks.
2373
+ */
2306
2374
  process: (frameData) => {
2375
+ /**
2376
+ * If we're already processing we've probably been triggered by a flushSync
2377
+ * inside an existing process. Instead of executing, mark flushNextFrame
2378
+ * as true and ensure we flush the following frame at the end of this one.
2379
+ */
2307
2380
  if (isProcessing) {
2308
2381
  flushNextFrame = true;
2309
2382
  return;
2310
2383
  }
2311
2384
  isProcessing = true;
2312
2385
  [toRun, toRunNextFrame] = [toRunNextFrame, toRun];
2386
+ // Clear the next frame list
2313
2387
  toRunNextFrame.length = 0;
2388
+ // Execute this frame
2314
2389
  numToRun = toRun.length;
2315
2390
  if (numToRun) {
2316
2391
  for (let i = 0; i < numToRun; i++) {
@@ -2332,14 +2407,15 @@
2332
2407
  return step;
2333
2408
  }
2334
2409
 
2410
+ const frameData = {
2411
+ delta: 0,
2412
+ timestamp: 0,
2413
+ };
2414
+
2335
2415
  const maxElapsed$1 = 40;
2336
2416
  let useDefaultElapsed = true;
2337
2417
  let runNextFrame = false;
2338
2418
  let isProcessing = false;
2339
- const frame = {
2340
- delta: 0,
2341
- timestamp: 0,
2342
- };
2343
2419
  const stepsOrder = [
2344
2420
  "read",
2345
2421
  "update",
@@ -2365,16 +2441,16 @@
2365
2441
  return acc;
2366
2442
  }, {});
2367
2443
  const flushSync = stepsOrder.reduce((acc, key) => {
2368
- acc[key] = () => steps[key].process(frame);
2444
+ acc[key] = () => steps[key].process(frameData);
2369
2445
  return acc;
2370
2446
  }, {});
2371
- const processStep = (stepId) => steps[stepId].process(frame);
2447
+ const processStep = (stepId) => steps[stepId].process(frameData);
2372
2448
  const processFrame = (timestamp) => {
2373
2449
  runNextFrame = false;
2374
- frame.delta = useDefaultElapsed
2450
+ frameData.delta = useDefaultElapsed
2375
2451
  ? defaultTimestep
2376
- : Math.max(Math.min(timestamp - frame.timestamp, maxElapsed$1), 1);
2377
- frame.timestamp = timestamp;
2452
+ : Math.max(Math.min(timestamp - frameData.timestamp, maxElapsed$1), 1);
2453
+ frameData.timestamp = timestamp;
2378
2454
  isProcessing = true;
2379
2455
  stepsOrder.forEach(processStep);
2380
2456
  isProcessing = false;
@@ -2389,7 +2465,6 @@
2389
2465
  if (!isProcessing)
2390
2466
  onNextFrame(processFrame);
2391
2467
  };
2392
- const getFrameData = () => frame;
2393
2468
 
2394
2469
  function delay(callback, timeout) {
2395
2470
  const start = performance.now();
@@ -2404,8 +2479,6 @@
2404
2479
  return () => cancelSync.read(checkElapsed);
2405
2480
  }
2406
2481
 
2407
- const clamp$1 = (min, max, v) => Math.min(Math.max(v, min), max);
2408
-
2409
2482
  /*
2410
2483
  Value in range from progress
2411
2484
 
@@ -2484,6 +2557,7 @@
2484
2557
  invariant(Boolean(type), `'${color}' is not an animatable color. Use the equivalent color code instead.`);
2485
2558
  let model = type.parse(color);
2486
2559
  if (type === hsla) {
2560
+ // TODO Remove this cast - needed since Framer Motion's stricter typing
2487
2561
  model = hslaToRgba(model);
2488
2562
  }
2489
2563
  return model;
@@ -2538,34 +2612,14 @@
2538
2612
  return output;
2539
2613
  };
2540
2614
  };
2541
- /**
2542
- * TODO: Combine with function within complex when style-value-types moved inside Framer Motion
2543
- */
2544
- function analyse(value) {
2545
- const parsed = complex.parse(value);
2546
- const numValues = parsed.length;
2547
- let numNumbers = 0;
2548
- let numColors = 0;
2549
- for (let i = 0; i < numValues; i++) {
2550
- // Parsed complex values return with colors first, so if we've seen any number
2551
- // we're already past that part of the array and don't need to continue running typeof
2552
- if (numNumbers || typeof parsed[i] === "number") {
2553
- numNumbers++;
2554
- }
2555
- else {
2556
- numColors++;
2557
- }
2558
- }
2559
- return { parsed, numNumbers, numColors };
2560
- }
2561
2615
  const mixComplex = (origin, target) => {
2562
2616
  const template = complex.createTransformer(target);
2563
- const originStats = analyse(origin);
2564
- const targetStats = analyse(target);
2617
+ const originStats = analyseComplexValue(origin);
2618
+ const targetStats = analyseComplexValue(target);
2565
2619
  const canInterpolate = originStats.numColors === targetStats.numColors &&
2566
2620
  originStats.numNumbers >= targetStats.numNumbers;
2567
2621
  if (canInterpolate) {
2568
- return pipe(mixArray(originStats.parsed, targetStats.parsed), template);
2622
+ return pipe(mixArray(originStats.values, targetStats.values), template);
2569
2623
  }
2570
2624
  else {
2571
2625
  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.`);
@@ -3042,8 +3096,10 @@
3042
3096
  }
3043
3097
  onUpdate === null || onUpdate === void 0 ? void 0 : onUpdate(latest);
3044
3098
  if (isComplete) {
3045
- if (repeatCount === 0)
3046
- computedDuration !== null && computedDuration !== void 0 ? computedDuration : (computedDuration = elapsed);
3099
+ if (repeatCount === 0) {
3100
+ computedDuration =
3101
+ computedDuration !== undefined ? computedDuration : elapsed;
3102
+ }
3047
3103
  if (repeatCount < repeatMax) {
3048
3104
  hasRepeatDelayElapsed(elapsed, computedDuration, repeatDelay, isForwardPlayback) && repeat();
3049
3105
  }
@@ -3134,7 +3190,7 @@
3134
3190
  const checkBoundary = (v) => {
3135
3191
  prev = current;
3136
3192
  current = v;
3137
- velocity = velocityPerSecond$1(v - prev, getFrameData().delta);
3193
+ velocity = velocityPerSecond$1(v - prev, frameData.delta);
3138
3194
  if ((heading === 1 && v > boundary) ||
3139
3195
  (heading === -1 && v < boundary)) {
3140
3196
  startSpring({ from: v, to: boundary, velocity });
@@ -3204,9 +3260,12 @@
3204
3260
  * Get the delay for a value by checking Transition with decreasing specificity.
3205
3261
  */
3206
3262
  function getDelayFromTransition(transition, key) {
3207
- var _a, _b;
3208
3263
  const valueTransition = getValueTransition(transition, key) || {};
3209
- return (_b = (_a = valueTransition.delay) !== null && _a !== void 0 ? _a : transition.delay) !== null && _b !== void 0 ? _b : 0;
3264
+ return valueTransition.delay !== undefined
3265
+ ? valueTransition.delay
3266
+ : transition.delay !== undefined
3267
+ ? transition.delay
3268
+ : 0;
3210
3269
  }
3211
3270
  function hydrateKeyframes(options) {
3212
3271
  if (Array.isArray(options.to) && options.to[0] === null) {
@@ -3425,7 +3484,7 @@
3425
3484
  * This will be replaced by the build step with the latest version number.
3426
3485
  * When MotionValues are provided to motion components, warn if versions are mixed.
3427
3486
  */
3428
- this.version = "7.7.0";
3487
+ this.version = "7.7.2";
3429
3488
  /**
3430
3489
  * Duration, in milliseconds, since last updating frame.
3431
3490
  *
@@ -3468,7 +3527,7 @@
3468
3527
  this.prev = this.current;
3469
3528
  this.current = v;
3470
3529
  // Update timestamp
3471
- const { delta, timestamp } = getFrameData();
3530
+ const { delta, timestamp } = frameData;
3472
3531
  if (this.lastUpdated !== timestamp) {
3473
3532
  this.timeDelta = delta;
3474
3533
  this.lastUpdated = timestamp;
@@ -4049,7 +4108,6 @@
4049
4108
  * what to animate those to.
4050
4109
  */
4051
4110
  function animateChanges(options, changedActiveType) {
4052
- var _a;
4053
4111
  const props = visualElement.getProps();
4054
4112
  const context = visualElement.getVariantContext(true) || {};
4055
4113
  /**
@@ -4082,7 +4140,7 @@
4082
4140
  for (let i = 0; i < numAnimationTypes; i++) {
4083
4141
  const type = reversePriorityOrder[i];
4084
4142
  const typeState = state[type];
4085
- const prop = (_a = props[type]) !== null && _a !== void 0 ? _a : context[type];
4143
+ const prop = props[type] !== undefined ? props[type] : context[type];
4086
4144
  const propIsVariant = isVariantLabel(prop);
4087
4145
  /**
4088
4146
  * If this type has *just* changed isActive status, set activeDelta
@@ -4395,7 +4453,7 @@
4395
4453
  if (!isPanStarted && !isDistancePastThreshold)
4396
4454
  return;
4397
4455
  const { point } = info;
4398
- const { timestamp } = getFrameData();
4456
+ const { timestamp } = frameData;
4399
4457
  this.history.push({ ...point, timestamp });
4400
4458
  const { onStart, onMove } = this.handlers;
4401
4459
  if (!isPanStarted) {
@@ -4432,7 +4490,7 @@
4432
4490
  const info = extractEventInfo(event);
4433
4491
  const initialInfo = transformPoint(info, this.transformPagePoint);
4434
4492
  const { point } = initialInfo;
4435
- const { timestamp } = getFrameData();
4493
+ const { timestamp } = frameData;
4436
4494
  this.history = [{ ...point, timestamp }];
4437
4495
  const { onSessionStart } = handlers;
4438
4496
  onSessionStart &&
@@ -4654,10 +4712,9 @@
4654
4712
  };
4655
4713
  }
4656
4714
  function resolvePointElastic(dragElastic, label) {
4657
- var _a;
4658
4715
  return typeof dragElastic === "number"
4659
4716
  ? dragElastic
4660
- : (_a = dragElastic[label]) !== null && _a !== void 0 ? _a : 0;
4717
+ : dragElastic[label] || 0;
4661
4718
  }
4662
4719
 
4663
4720
  const createAxisDelta = () => ({
@@ -5079,11 +5136,10 @@
5079
5136
  const { drag, dragMomentum, dragElastic, dragTransition, dragSnapToOrigin, onDragTransitionEnd, } = this.getProps();
5080
5137
  const constraints = this.constraints || {};
5081
5138
  const momentumAnimations = eachAxis((axis) => {
5082
- var _a;
5083
5139
  if (!shouldDrag(axis, drag, this.currentDirection)) {
5084
5140
  return;
5085
5141
  }
5086
- let transition = (_a = constraints === null || constraints === void 0 ? void 0 : constraints[axis]) !== null && _a !== void 0 ? _a : {};
5142
+ let transition = (constraints === null || constraints === void 0 ? void 0 : constraints[axis]) || {};
5087
5143
  if (dragSnapToOrigin)
5088
5144
  transition = { min: 0, max: 0 };
5089
5145
  /**
@@ -5127,12 +5183,12 @@
5127
5183
  * - Otherwise, we apply the delta to the x/y motion values.
5128
5184
  */
5129
5185
  getAxisMotionValue(axis) {
5130
- var _a, _b;
5186
+ var _a;
5131
5187
  const dragKey = "_drag" + axis.toUpperCase();
5132
5188
  const externalMotionValue = this.visualElement.getProps()[dragKey];
5133
5189
  return externalMotionValue
5134
5190
  ? externalMotionValue
5135
- : this.visualElement.getValue(axis, (_b = (_a = this.visualElement.getProps().initial) === null || _a === void 0 ? void 0 : _a[axis]) !== null && _b !== void 0 ? _b : 0);
5191
+ : this.visualElement.getValue(axis, ((_a = this.visualElement.getProps().initial) === null || _a === void 0 ? void 0 : _a[axis]) || 0);
5136
5192
  }
5137
5193
  snapToCursor(point) {
5138
5194
  eachAxis((axis) => {
@@ -5710,7 +5766,7 @@
5710
5766
  * and warn against mismatches.
5711
5767
  */
5712
5768
  {
5713
- warnOnce(nextValue.version === "7.7.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.7.0 may not work as expected.`);
5769
+ warnOnce(nextValue.version === "7.7.2", `Attempting to mix Framer Motion versions ${nextValue.version} with 7.7.2 may not work as expected.`);
5714
5770
  }
5715
5771
  }
5716
5772
  else if (isMotionValue(prevValue)) {
@@ -6569,16 +6625,14 @@
6569
6625
  const asNumber = (value) => typeof value === "string" ? parseFloat(value) : value;
6570
6626
  const isPx = (value) => typeof value === "number" || px.test(value);
6571
6627
  function mixValues(target, follow, lead, progress, shouldCrossfadeOpacity, isOnlyMember) {
6572
- var _a, _b, _c, _d;
6573
6628
  if (shouldCrossfadeOpacity) {
6574
6629
  target.opacity = mix$1(0,
6575
- // (follow?.opacity as number) ?? 0,
6576
6630
  // TODO Reinstate this if only child
6577
- (_a = lead.opacity) !== null && _a !== void 0 ? _a : 1, easeCrossfadeIn(progress));
6578
- target.opacityExit = mix$1((_b = follow.opacity) !== null && _b !== void 0 ? _b : 1, 0, easeCrossfadeOut(progress));
6631
+ lead.opacity !== undefined ? lead.opacity : 1, easeCrossfadeIn(progress));
6632
+ target.opacityExit = mix$1(follow.opacity !== undefined ? follow.opacity : 1, 0, easeCrossfadeOut(progress));
6579
6633
  }
6580
6634
  else if (isOnlyMember) {
6581
- target.opacity = mix$1((_c = follow.opacity) !== null && _c !== void 0 ? _c : 1, (_d = lead.opacity) !== null && _d !== void 0 ? _d : 1, progress);
6635
+ target.opacity = mix$1(follow.opacity !== undefined ? follow.opacity : 1, lead.opacity !== undefined ? lead.opacity : 1, progress);
6582
6636
  }
6583
6637
  /**
6584
6638
  * Mix border radius
@@ -6612,8 +6666,9 @@
6612
6666
  }
6613
6667
  }
6614
6668
  function getRadius(values, radiusName) {
6615
- var _a;
6616
- return (_a = values[radiusName]) !== null && _a !== void 0 ? _a : values.borderRadius;
6669
+ return values[radiusName] !== undefined
6670
+ ? values[radiusName]
6671
+ : values.borderRadius;
6617
6672
  }
6618
6673
  // /**
6619
6674
  // * We only want to mix the background color if there's a follow element