framer-motion 11.7.0 → 11.8.0

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.
@@ -340,6 +340,72 @@ function createRenderBatcher(scheduleNextBatch, allowKeepAlive) {
340
340
 
341
341
  const { schedule: frame, cancel: cancelFrame, state: frameData, steps: frameSteps, } = createRenderBatcher(typeof requestAnimationFrame !== "undefined" ? requestAnimationFrame : noop, true);
342
342
 
343
+ /*
344
+ Bezier function generator
345
+ This has been modified from Gaëtan Renaudeau's BezierEasing
346
+ https://github.com/gre/bezier-easing/blob/master/src/index.js
347
+ https://github.com/gre/bezier-easing/blob/master/LICENSE
348
+
349
+ I've removed the newtonRaphsonIterate algo because in benchmarking it
350
+ wasn't noticiably faster than binarySubdivision, indeed removing it
351
+ usually improved times, depending on the curve.
352
+ I also removed the lookup table, as for the added bundle size and loop we're
353
+ only cutting ~4 or so subdivision iterations. I bumped the max iterations up
354
+ to 12 to compensate and this still tended to be faster for no perceivable
355
+ loss in accuracy.
356
+ Usage
357
+ const easeOut = cubicBezier(.17,.67,.83,.67);
358
+ const x = easeOut(0.5); // returns 0.627...
359
+ */
360
+ // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
361
+ const calcBezier = (t, a1, a2) => (((1.0 - 3.0 * a2 + 3.0 * a1) * t + (3.0 * a2 - 6.0 * a1)) * t + 3.0 * a1) *
362
+ t;
363
+ const subdivisionPrecision = 0.0000001;
364
+ const subdivisionMaxIterations = 12;
365
+ function binarySubdivide(x, lowerBound, upperBound, mX1, mX2) {
366
+ let currentX;
367
+ let currentT;
368
+ let i = 0;
369
+ do {
370
+ currentT = lowerBound + (upperBound - lowerBound) / 2.0;
371
+ currentX = calcBezier(currentT, mX1, mX2) - x;
372
+ if (currentX > 0.0) {
373
+ upperBound = currentT;
374
+ }
375
+ else {
376
+ lowerBound = currentT;
377
+ }
378
+ } while (Math.abs(currentX) > subdivisionPrecision &&
379
+ ++i < subdivisionMaxIterations);
380
+ return currentT;
381
+ }
382
+ function cubicBezier(mX1, mY1, mX2, mY2) {
383
+ // If this is a linear gradient, return linear easing
384
+ if (mX1 === mY1 && mX2 === mY2)
385
+ return noop;
386
+ const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
387
+ // If animation is at start/end, return t without easing
388
+ return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
389
+ }
390
+
391
+ // Accepts an easing function and returns a new one that outputs mirrored values for
392
+ // the second half of the animation. Turns easeIn into easeInOut.
393
+ const mirrorEasing = (easing) => (p) => p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
394
+
395
+ // Accepts an easing function and returns a new one that outputs reversed values.
396
+ // Turns easeIn into easeOut.
397
+ const reverseEasing = (easing) => (p) => 1 - easing(1 - p);
398
+
399
+ const backOut = /*@__PURE__*/ cubicBezier(0.33, 1.53, 0.69, 0.99);
400
+ const backIn = /*@__PURE__*/ reverseEasing(backOut);
401
+ const backInOut = /*@__PURE__*/ mirrorEasing(backIn);
402
+
403
+ const anticipate = (p) => (p *= 2) < 1 ? 0.5 * backIn(p) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
404
+
405
+ const circIn = (p) => 1 - Math.sin(Math.acos(p));
406
+ const circOut = reverseEasing(circIn);
407
+ const circInOut = mirrorEasing(circIn);
408
+
343
409
  /**
344
410
  * Check if the value is a zero value string like "0px" or "0%"
345
411
  */
@@ -1723,54 +1789,6 @@ function inertia({ keyframes, velocity = 0.0, power = 0.8, timeConstant = 325, b
1723
1789
  };
1724
1790
  }
1725
1791
 
1726
- /*
1727
- Bezier function generator
1728
- This has been modified from Gaëtan Renaudeau's BezierEasing
1729
- https://github.com/gre/bezier-easing/blob/master/src/index.js
1730
- https://github.com/gre/bezier-easing/blob/master/LICENSE
1731
-
1732
- I've removed the newtonRaphsonIterate algo because in benchmarking it
1733
- wasn't noticiably faster than binarySubdivision, indeed removing it
1734
- usually improved times, depending on the curve.
1735
- I also removed the lookup table, as for the added bundle size and loop we're
1736
- only cutting ~4 or so subdivision iterations. I bumped the max iterations up
1737
- to 12 to compensate and this still tended to be faster for no perceivable
1738
- loss in accuracy.
1739
- Usage
1740
- const easeOut = cubicBezier(.17,.67,.83,.67);
1741
- const x = easeOut(0.5); // returns 0.627...
1742
- */
1743
- // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
1744
- const calcBezier = (t, a1, a2) => (((1.0 - 3.0 * a2 + 3.0 * a1) * t + (3.0 * a2 - 6.0 * a1)) * t + 3.0 * a1) *
1745
- t;
1746
- const subdivisionPrecision = 0.0000001;
1747
- const subdivisionMaxIterations = 12;
1748
- function binarySubdivide(x, lowerBound, upperBound, mX1, mX2) {
1749
- let currentX;
1750
- let currentT;
1751
- let i = 0;
1752
- do {
1753
- currentT = lowerBound + (upperBound - lowerBound) / 2.0;
1754
- currentX = calcBezier(currentT, mX1, mX2) - x;
1755
- if (currentX > 0.0) {
1756
- upperBound = currentT;
1757
- }
1758
- else {
1759
- lowerBound = currentT;
1760
- }
1761
- } while (Math.abs(currentX) > subdivisionPrecision &&
1762
- ++i < subdivisionMaxIterations);
1763
- return currentT;
1764
- }
1765
- function cubicBezier(mX1, mY1, mX2, mY2) {
1766
- // If this is a linear gradient, return linear easing
1767
- if (mX1 === mY1 && mX2 === mY2)
1768
- return noop;
1769
- const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
1770
- // If animation is at start/end, return t without easing
1771
- return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
1772
- }
1773
-
1774
1792
  const easeIn = /*@__PURE__*/ cubicBezier(0.42, 0, 1, 1);
1775
1793
  const easeOut = /*@__PURE__*/ cubicBezier(0, 0, 0.58, 1);
1776
1794
  const easeInOut = /*@__PURE__*/ cubicBezier(0.42, 0, 0.58, 1);
@@ -1779,24 +1797,6 @@ const isEasingArray = (ease) => {
1779
1797
  return Array.isArray(ease) && typeof ease[0] !== "number";
1780
1798
  };
1781
1799
 
1782
- // Accepts an easing function and returns a new one that outputs mirrored values for
1783
- // the second half of the animation. Turns easeIn into easeInOut.
1784
- const mirrorEasing = (easing) => (p) => p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
1785
-
1786
- // Accepts an easing function and returns a new one that outputs reversed values.
1787
- // Turns easeIn into easeOut.
1788
- const reverseEasing = (easing) => (p) => 1 - easing(1 - p);
1789
-
1790
- const circIn = (p) => 1 - Math.sin(Math.acos(p));
1791
- const circOut = reverseEasing(circIn);
1792
- const circInOut = mirrorEasing(circIn);
1793
-
1794
- const backOut = /*@__PURE__*/ cubicBezier(0.33, 1.53, 0.69, 0.99);
1795
- const backIn = /*@__PURE__*/ reverseEasing(backOut);
1796
- const backInOut = /*@__PURE__*/ mirrorEasing(backIn);
1797
-
1798
- const anticipate = (p) => (p *= 2) < 1 ? 0.5 * backIn(p) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
1799
-
1800
1800
  const easingLookup = {
1801
1801
  linear: noop,
1802
1802
  easeIn,
@@ -2604,9 +2604,47 @@ const acceleratedValues = new Set([
2604
2604
 
2605
2605
  const isBezierDefinition = (easing) => Array.isArray(easing) && typeof easing[0] === "number";
2606
2606
 
2607
+ // Create a linear easing point for every 10 ms
2608
+ const resolution = 10;
2609
+ const generateLinearEasing = (easing, duration // as milliseconds
2610
+ ) => {
2611
+ let points = "";
2612
+ const numPoints = Math.max(Math.round(duration / resolution), 2);
2613
+ for (let i = 0; i < numPoints; i++) {
2614
+ points += easing(progress(0, numPoints - 1, i)) + ", ";
2615
+ }
2616
+ return `linear(${points.substring(0, points.length - 2)})`;
2617
+ };
2618
+
2619
+ /**
2620
+ * Add the ability for test suites to manually set support flags
2621
+ * to better test more environments.
2622
+ */
2623
+ const supportsFlags = {
2624
+ linearEasing: undefined,
2625
+ };
2626
+
2627
+ function memoSupports(callback, supportsFlag) {
2628
+ const memoized = memo(callback);
2629
+ return () => { var _a; return (_a = supportsFlags[supportsFlag]) !== null && _a !== void 0 ? _a : memoized(); };
2630
+ }
2631
+
2632
+ const supportsLinearEasing = /*@__PURE__*/ memoSupports(() => {
2633
+ try {
2634
+ document
2635
+ .createElement("div")
2636
+ .animate({ opacity: 0 }, { easing: "linear(0, 1)" });
2637
+ }
2638
+ catch (e) {
2639
+ return false;
2640
+ }
2641
+ return true;
2642
+ }, "linearEasing");
2607
2643
  function isWaapiSupportedEasing(easing) {
2608
- return Boolean(!easing ||
2609
- (typeof easing === "string" && easing in supportedWaapiEasing) ||
2644
+ return Boolean((typeof easing === "function" && supportsLinearEasing()) ||
2645
+ !easing ||
2646
+ (typeof easing === "string" &&
2647
+ (easing in supportedWaapiEasing || supportsLinearEasing())) ||
2610
2648
  isBezierDefinition(easing) ||
2611
2649
  (Array.isArray(easing) && easing.every(isWaapiSupportedEasing)));
2612
2650
  }
@@ -2622,19 +2660,19 @@ const supportedWaapiEasing = {
2622
2660
  backIn: /*@__PURE__*/ cubicBezierAsString([0.31, 0.01, 0.66, -0.59]),
2623
2661
  backOut: /*@__PURE__*/ cubicBezierAsString([0.33, 1.53, 0.69, 0.99]),
2624
2662
  };
2625
- function mapEasingToNativeEasingWithDefault(easing) {
2626
- return (mapEasingToNativeEasing(easing) ||
2627
- supportedWaapiEasing.easeOut);
2628
- }
2629
- function mapEasingToNativeEasing(easing) {
2663
+ function mapEasingToNativeEasing(easing, duration) {
2630
2664
  if (!easing) {
2631
2665
  return undefined;
2632
2666
  }
2667
+ else if (typeof easing === "function" && supportsLinearEasing()) {
2668
+ return generateLinearEasing(easing, duration);
2669
+ }
2633
2670
  else if (isBezierDefinition(easing)) {
2634
2671
  return cubicBezierAsString(easing);
2635
2672
  }
2636
2673
  else if (Array.isArray(easing)) {
2637
- return easing.map(mapEasingToNativeEasingWithDefault);
2674
+ return easing.map((segmentEasing) => mapEasingToNativeEasing(segmentEasing, duration) ||
2675
+ supportedWaapiEasing.easeOut);
2638
2676
  }
2639
2677
  else {
2640
2678
  return supportedWaapiEasing[easing];
@@ -2645,7 +2683,7 @@ function animateStyle(element, valueName, keyframes, { delay = 0, duration = 300
2645
2683
  const keyframeOptions = { [valueName]: keyframes };
2646
2684
  if (times)
2647
2685
  keyframeOptions.offset = times;
2648
- const easing = mapEasingToNativeEasing(ease);
2686
+ const easing = mapEasingToNativeEasing(ease, duration);
2649
2687
  /**
2650
2688
  * If this is an easing array, apply to keyframes, not animation as a whole
2651
2689
  */
@@ -2715,6 +2753,14 @@ function pregenerateKeyframes(keyframes, options) {
2715
2753
  ease: "linear",
2716
2754
  };
2717
2755
  }
2756
+ const unsupportedEasingFunctions = {
2757
+ anticipate,
2758
+ backInOut,
2759
+ circInOut,
2760
+ };
2761
+ function isUnsupportedEase(key) {
2762
+ return key in unsupportedEasingFunctions;
2763
+ }
2718
2764
  class AcceleratedAnimation extends BaseAnimation {
2719
2765
  constructor(options) {
2720
2766
  super(options);
@@ -2732,6 +2778,16 @@ class AcceleratedAnimation extends BaseAnimation {
2732
2778
  if (!((_a = motionValue.owner) === null || _a === void 0 ? void 0 : _a.current)) {
2733
2779
  return false;
2734
2780
  }
2781
+ /**
2782
+ * If the user has provided an easing function name that isn't supported
2783
+ * by WAAPI (like "anticipate"), we need to provide the corressponding
2784
+ * function. This will later get converted to a linear() easing function.
2785
+ */
2786
+ if (typeof ease === "string" &&
2787
+ supportsLinearEasing() &&
2788
+ isUnsupportedEase(ease)) {
2789
+ ease = unsupportedEasingFunctions[ease];
2790
+ }
2735
2791
  /**
2736
2792
  * If this animation needs pre-generated keyframes then generate.
2737
2793
  */
@@ -3227,7 +3283,7 @@ class MotionValue {
3227
3283
  * This will be replaced by the build step with the latest version number.
3228
3284
  * When MotionValues are provided to motion components, warn if versions are mixed.
3229
3285
  */
3230
- this.version = "11.7.0";
3286
+ this.version = "11.8.0";
3231
3287
  /**
3232
3288
  * Tracks whether this value can output a velocity. Currently this is only true
3233
3289
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -5850,7 +5906,7 @@ function updateMotionValuesFromProps(element, next, prev) {
5850
5906
  * and warn against mismatches.
5851
5907
  */
5852
5908
  if (process.env.NODE_ENV === "development") {
5853
- warnOnce(nextValue.version === "11.7.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.7.0 may not work as expected.`);
5909
+ warnOnce(nextValue.version === "11.8.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.8.0 may not work as expected.`);
5854
5910
  }
5855
5911
  }
5856
5912
  else if (isMotionValue(prevValue)) {
@@ -279,7 +279,7 @@ class MotionValue {
279
279
  * This will be replaced by the build step with the latest version number.
280
280
  * When MotionValues are provided to motion components, warn if versions are mixed.
281
281
  */
282
- this.version = "11.7.0";
282
+ this.version = "11.8.0";
283
283
  /**
284
284
  * Tracks whether this value can output a velocity. Currently this is only true
285
285
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -807,6 +807,72 @@ function getFinalKeyframe(keyframes, { repeat, repeatType = "loop" }, finalKeyfr
807
807
  : finalKeyframe;
808
808
  }
809
809
 
810
+ /*
811
+ Bezier function generator
812
+ This has been modified from Gaëtan Renaudeau's BezierEasing
813
+ https://github.com/gre/bezier-easing/blob/master/src/index.js
814
+ https://github.com/gre/bezier-easing/blob/master/LICENSE
815
+
816
+ I've removed the newtonRaphsonIterate algo because in benchmarking it
817
+ wasn't noticiably faster than binarySubdivision, indeed removing it
818
+ usually improved times, depending on the curve.
819
+ I also removed the lookup table, as for the added bundle size and loop we're
820
+ only cutting ~4 or so subdivision iterations. I bumped the max iterations up
821
+ to 12 to compensate and this still tended to be faster for no perceivable
822
+ loss in accuracy.
823
+ Usage
824
+ const easeOut = cubicBezier(.17,.67,.83,.67);
825
+ const x = easeOut(0.5); // returns 0.627...
826
+ */
827
+ // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
828
+ const calcBezier = (t, a1, a2) => (((1.0 - 3.0 * a2 + 3.0 * a1) * t + (3.0 * a2 - 6.0 * a1)) * t + 3.0 * a1) *
829
+ t;
830
+ const subdivisionPrecision = 0.0000001;
831
+ const subdivisionMaxIterations = 12;
832
+ function binarySubdivide(x, lowerBound, upperBound, mX1, mX2) {
833
+ let currentX;
834
+ let currentT;
835
+ let i = 0;
836
+ do {
837
+ currentT = lowerBound + (upperBound - lowerBound) / 2.0;
838
+ currentX = calcBezier(currentT, mX1, mX2) - x;
839
+ if (currentX > 0.0) {
840
+ upperBound = currentT;
841
+ }
842
+ else {
843
+ lowerBound = currentT;
844
+ }
845
+ } while (Math.abs(currentX) > subdivisionPrecision &&
846
+ ++i < subdivisionMaxIterations);
847
+ return currentT;
848
+ }
849
+ function cubicBezier(mX1, mY1, mX2, mY2) {
850
+ // If this is a linear gradient, return linear easing
851
+ if (mX1 === mY1 && mX2 === mY2)
852
+ return noop;
853
+ const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
854
+ // If animation is at start/end, return t without easing
855
+ return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
856
+ }
857
+
858
+ // Accepts an easing function and returns a new one that outputs mirrored values for
859
+ // the second half of the animation. Turns easeIn into easeInOut.
860
+ const mirrorEasing = (easing) => (p) => p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
861
+
862
+ // Accepts an easing function and returns a new one that outputs reversed values.
863
+ // Turns easeIn into easeOut.
864
+ const reverseEasing = (easing) => (p) => 1 - easing(1 - p);
865
+
866
+ const backOut = /*@__PURE__*/ cubicBezier(0.33, 1.53, 0.69, 0.99);
867
+ const backIn = /*@__PURE__*/ reverseEasing(backOut);
868
+ const backInOut = /*@__PURE__*/ mirrorEasing(backIn);
869
+
870
+ const anticipate = (p) => (p *= 2) < 1 ? 0.5 * backIn(p) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
871
+
872
+ const circIn = (p) => 1 - Math.sin(Math.acos(p));
873
+ const circOut = reverseEasing(circIn);
874
+ const circInOut = mirrorEasing(circIn);
875
+
810
876
  /**
811
877
  * Check if the value is a zero value string like "0px" or "0%"
812
878
  */
@@ -2129,54 +2195,6 @@ function inertia({ keyframes, velocity = 0.0, power = 0.8, timeConstant = 325, b
2129
2195
  };
2130
2196
  }
2131
2197
 
2132
- /*
2133
- Bezier function generator
2134
- This has been modified from Gaëtan Renaudeau's BezierEasing
2135
- https://github.com/gre/bezier-easing/blob/master/src/index.js
2136
- https://github.com/gre/bezier-easing/blob/master/LICENSE
2137
-
2138
- I've removed the newtonRaphsonIterate algo because in benchmarking it
2139
- wasn't noticiably faster than binarySubdivision, indeed removing it
2140
- usually improved times, depending on the curve.
2141
- I also removed the lookup table, as for the added bundle size and loop we're
2142
- only cutting ~4 or so subdivision iterations. I bumped the max iterations up
2143
- to 12 to compensate and this still tended to be faster for no perceivable
2144
- loss in accuracy.
2145
- Usage
2146
- const easeOut = cubicBezier(.17,.67,.83,.67);
2147
- const x = easeOut(0.5); // returns 0.627...
2148
- */
2149
- // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
2150
- const calcBezier = (t, a1, a2) => (((1.0 - 3.0 * a2 + 3.0 * a1) * t + (3.0 * a2 - 6.0 * a1)) * t + 3.0 * a1) *
2151
- t;
2152
- const subdivisionPrecision = 0.0000001;
2153
- const subdivisionMaxIterations = 12;
2154
- function binarySubdivide(x, lowerBound, upperBound, mX1, mX2) {
2155
- let currentX;
2156
- let currentT;
2157
- let i = 0;
2158
- do {
2159
- currentT = lowerBound + (upperBound - lowerBound) / 2.0;
2160
- currentX = calcBezier(currentT, mX1, mX2) - x;
2161
- if (currentX > 0.0) {
2162
- upperBound = currentT;
2163
- }
2164
- else {
2165
- lowerBound = currentT;
2166
- }
2167
- } while (Math.abs(currentX) > subdivisionPrecision &&
2168
- ++i < subdivisionMaxIterations);
2169
- return currentT;
2170
- }
2171
- function cubicBezier(mX1, mY1, mX2, mY2) {
2172
- // If this is a linear gradient, return linear easing
2173
- if (mX1 === mY1 && mX2 === mY2)
2174
- return noop;
2175
- const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
2176
- // If animation is at start/end, return t without easing
2177
- return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
2178
- }
2179
-
2180
2198
  const easeIn = /*@__PURE__*/ cubicBezier(0.42, 0, 1, 1);
2181
2199
  const easeOut = /*@__PURE__*/ cubicBezier(0, 0, 0.58, 1);
2182
2200
  const easeInOut = /*@__PURE__*/ cubicBezier(0.42, 0, 0.58, 1);
@@ -2185,24 +2203,6 @@ const isEasingArray = (ease) => {
2185
2203
  return Array.isArray(ease) && typeof ease[0] !== "number";
2186
2204
  };
2187
2205
 
2188
- // Accepts an easing function and returns a new one that outputs mirrored values for
2189
- // the second half of the animation. Turns easeIn into easeInOut.
2190
- const mirrorEasing = (easing) => (p) => p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
2191
-
2192
- // Accepts an easing function and returns a new one that outputs reversed values.
2193
- // Turns easeIn into easeOut.
2194
- const reverseEasing = (easing) => (p) => 1 - easing(1 - p);
2195
-
2196
- const circIn = (p) => 1 - Math.sin(Math.acos(p));
2197
- const circOut = reverseEasing(circIn);
2198
- const circInOut = mirrorEasing(circIn);
2199
-
2200
- const backOut = /*@__PURE__*/ cubicBezier(0.33, 1.53, 0.69, 0.99);
2201
- const backIn = /*@__PURE__*/ reverseEasing(backOut);
2202
- const backInOut = /*@__PURE__*/ mirrorEasing(backIn);
2203
-
2204
- const anticipate = (p) => (p *= 2) < 1 ? 0.5 * backIn(p) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
2205
-
2206
2206
  const easingLookup = {
2207
2207
  linear: noop,
2208
2208
  easeIn,
@@ -3010,9 +3010,47 @@ const acceleratedValues = new Set([
3010
3010
 
3011
3011
  const isBezierDefinition = (easing) => Array.isArray(easing) && typeof easing[0] === "number";
3012
3012
 
3013
+ // Create a linear easing point for every 10 ms
3014
+ const resolution = 10;
3015
+ const generateLinearEasing = (easing, duration // as milliseconds
3016
+ ) => {
3017
+ let points = "";
3018
+ const numPoints = Math.max(Math.round(duration / resolution), 2);
3019
+ for (let i = 0; i < numPoints; i++) {
3020
+ points += easing(progress(0, numPoints - 1, i)) + ", ";
3021
+ }
3022
+ return `linear(${points.substring(0, points.length - 2)})`;
3023
+ };
3024
+
3025
+ /**
3026
+ * Add the ability for test suites to manually set support flags
3027
+ * to better test more environments.
3028
+ */
3029
+ const supportsFlags = {
3030
+ linearEasing: undefined,
3031
+ };
3032
+
3033
+ function memoSupports(callback, supportsFlag) {
3034
+ const memoized = memo(callback);
3035
+ return () => { var _a; return (_a = supportsFlags[supportsFlag]) !== null && _a !== void 0 ? _a : memoized(); };
3036
+ }
3037
+
3038
+ const supportsLinearEasing = /*@__PURE__*/ memoSupports(() => {
3039
+ try {
3040
+ document
3041
+ .createElement("div")
3042
+ .animate({ opacity: 0 }, { easing: "linear(0, 1)" });
3043
+ }
3044
+ catch (e) {
3045
+ return false;
3046
+ }
3047
+ return true;
3048
+ }, "linearEasing");
3013
3049
  function isWaapiSupportedEasing(easing) {
3014
- return Boolean(!easing ||
3015
- (typeof easing === "string" && easing in supportedWaapiEasing) ||
3050
+ return Boolean((typeof easing === "function" && supportsLinearEasing()) ||
3051
+ !easing ||
3052
+ (typeof easing === "string" &&
3053
+ (easing in supportedWaapiEasing || supportsLinearEasing())) ||
3016
3054
  isBezierDefinition(easing) ||
3017
3055
  (Array.isArray(easing) && easing.every(isWaapiSupportedEasing)));
3018
3056
  }
@@ -3028,19 +3066,19 @@ const supportedWaapiEasing = {
3028
3066
  backIn: /*@__PURE__*/ cubicBezierAsString([0.31, 0.01, 0.66, -0.59]),
3029
3067
  backOut: /*@__PURE__*/ cubicBezierAsString([0.33, 1.53, 0.69, 0.99]),
3030
3068
  };
3031
- function mapEasingToNativeEasingWithDefault(easing) {
3032
- return (mapEasingToNativeEasing(easing) ||
3033
- supportedWaapiEasing.easeOut);
3034
- }
3035
- function mapEasingToNativeEasing(easing) {
3069
+ function mapEasingToNativeEasing(easing, duration) {
3036
3070
  if (!easing) {
3037
3071
  return undefined;
3038
3072
  }
3073
+ else if (typeof easing === "function" && supportsLinearEasing()) {
3074
+ return generateLinearEasing(easing, duration);
3075
+ }
3039
3076
  else if (isBezierDefinition(easing)) {
3040
3077
  return cubicBezierAsString(easing);
3041
3078
  }
3042
3079
  else if (Array.isArray(easing)) {
3043
- return easing.map(mapEasingToNativeEasingWithDefault);
3080
+ return easing.map((segmentEasing) => mapEasingToNativeEasing(segmentEasing, duration) ||
3081
+ supportedWaapiEasing.easeOut);
3044
3082
  }
3045
3083
  else {
3046
3084
  return supportedWaapiEasing[easing];
@@ -3051,7 +3089,7 @@ function animateStyle(element, valueName, keyframes, { delay = 0, duration = 300
3051
3089
  const keyframeOptions = { [valueName]: keyframes };
3052
3090
  if (times)
3053
3091
  keyframeOptions.offset = times;
3054
- const easing = mapEasingToNativeEasing(ease);
3092
+ const easing = mapEasingToNativeEasing(ease, duration);
3055
3093
  /**
3056
3094
  * If this is an easing array, apply to keyframes, not animation as a whole
3057
3095
  */
@@ -3121,6 +3159,14 @@ function pregenerateKeyframes(keyframes, options) {
3121
3159
  ease: "linear",
3122
3160
  };
3123
3161
  }
3162
+ const unsupportedEasingFunctions = {
3163
+ anticipate,
3164
+ backInOut,
3165
+ circInOut,
3166
+ };
3167
+ function isUnsupportedEase(key) {
3168
+ return key in unsupportedEasingFunctions;
3169
+ }
3124
3170
  class AcceleratedAnimation extends BaseAnimation {
3125
3171
  constructor(options) {
3126
3172
  super(options);
@@ -3138,6 +3184,16 @@ class AcceleratedAnimation extends BaseAnimation {
3138
3184
  if (!((_a = motionValue.owner) === null || _a === void 0 ? void 0 : _a.current)) {
3139
3185
  return false;
3140
3186
  }
3187
+ /**
3188
+ * If the user has provided an easing function name that isn't supported
3189
+ * by WAAPI (like "anticipate"), we need to provide the corressponding
3190
+ * function. This will later get converted to a linear() easing function.
3191
+ */
3192
+ if (typeof ease === "string" &&
3193
+ supportsLinearEasing() &&
3194
+ isUnsupportedEase(ease)) {
3195
+ ease = unsupportedEasingFunctions[ease];
3196
+ }
3141
3197
  /**
3142
3198
  * If this animation needs pre-generated keyframes then generate.
3143
3199
  */
@@ -3766,7 +3822,7 @@ function updateMotionValuesFromProps(element, next, prev) {
3766
3822
  * and warn against mismatches.
3767
3823
  */
3768
3824
  if (process.env.NODE_ENV === "development") {
3769
- warnOnce(nextValue.version === "11.7.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.7.0 may not work as expected.`);
3825
+ warnOnce(nextValue.version === "11.8.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.8.0 may not work as expected.`);
3770
3826
  }
3771
3827
  }
3772
3828
  else if (isMotionValue(prevValue)) {