framer-motion 11.6.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
  */
@@ -1215,6 +1281,10 @@ function memo(callback) {
1215
1281
  };
1216
1282
  }
1217
1283
 
1284
+ function isGenerator(type) {
1285
+ return typeof type === "function";
1286
+ }
1287
+
1218
1288
  let now;
1219
1289
  function clearTime() {
1220
1290
  now = undefined;
@@ -1302,7 +1372,8 @@ function canAnimate(keyframes, name, type, velocity) {
1302
1372
  if (!isOriginAnimatable || !isTargetAnimatable) {
1303
1373
  return false;
1304
1374
  }
1305
- return hasKeyframesChanged(keyframes) || (type === "spring" && velocity);
1375
+ return (hasKeyframesChanged(keyframes) ||
1376
+ ((type === "spring" || isGenerator(type)) && velocity));
1306
1377
  }
1307
1378
 
1308
1379
  /**
@@ -1718,54 +1789,6 @@ function inertia({ keyframes, velocity = 0.0, power = 0.8, timeConstant = 325, b
1718
1789
  };
1719
1790
  }
1720
1791
 
1721
- /*
1722
- Bezier function generator
1723
- This has been modified from Gaëtan Renaudeau's BezierEasing
1724
- https://github.com/gre/bezier-easing/blob/master/src/index.js
1725
- https://github.com/gre/bezier-easing/blob/master/LICENSE
1726
-
1727
- I've removed the newtonRaphsonIterate algo because in benchmarking it
1728
- wasn't noticiably faster than binarySubdivision, indeed removing it
1729
- usually improved times, depending on the curve.
1730
- I also removed the lookup table, as for the added bundle size and loop we're
1731
- only cutting ~4 or so subdivision iterations. I bumped the max iterations up
1732
- to 12 to compensate and this still tended to be faster for no perceivable
1733
- loss in accuracy.
1734
- Usage
1735
- const easeOut = cubicBezier(.17,.67,.83,.67);
1736
- const x = easeOut(0.5); // returns 0.627...
1737
- */
1738
- // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
1739
- const calcBezier = (t, a1, a2) => (((1.0 - 3.0 * a2 + 3.0 * a1) * t + (3.0 * a2 - 6.0 * a1)) * t + 3.0 * a1) *
1740
- t;
1741
- const subdivisionPrecision = 0.0000001;
1742
- const subdivisionMaxIterations = 12;
1743
- function binarySubdivide(x, lowerBound, upperBound, mX1, mX2) {
1744
- let currentX;
1745
- let currentT;
1746
- let i = 0;
1747
- do {
1748
- currentT = lowerBound + (upperBound - lowerBound) / 2.0;
1749
- currentX = calcBezier(currentT, mX1, mX2) - x;
1750
- if (currentX > 0.0) {
1751
- upperBound = currentT;
1752
- }
1753
- else {
1754
- lowerBound = currentT;
1755
- }
1756
- } while (Math.abs(currentX) > subdivisionPrecision &&
1757
- ++i < subdivisionMaxIterations);
1758
- return currentT;
1759
- }
1760
- function cubicBezier(mX1, mY1, mX2, mY2) {
1761
- // If this is a linear gradient, return linear easing
1762
- if (mX1 === mY1 && mX2 === mY2)
1763
- return noop;
1764
- const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
1765
- // If animation is at start/end, return t without easing
1766
- return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
1767
- }
1768
-
1769
1792
  const easeIn = /*@__PURE__*/ cubicBezier(0.42, 0, 1, 1);
1770
1793
  const easeOut = /*@__PURE__*/ cubicBezier(0, 0, 0.58, 1);
1771
1794
  const easeInOut = /*@__PURE__*/ cubicBezier(0.42, 0, 0.58, 1);
@@ -1774,24 +1797,6 @@ const isEasingArray = (ease) => {
1774
1797
  return Array.isArray(ease) && typeof ease[0] !== "number";
1775
1798
  };
1776
1799
 
1777
- // Accepts an easing function and returns a new one that outputs mirrored values for
1778
- // the second half of the animation. Turns easeIn into easeInOut.
1779
- const mirrorEasing = (easing) => (p) => p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
1780
-
1781
- // Accepts an easing function and returns a new one that outputs reversed values.
1782
- // Turns easeIn into easeOut.
1783
- const reverseEasing = (easing) => (p) => 1 - easing(1 - p);
1784
-
1785
- const circIn = (p) => 1 - Math.sin(Math.acos(p));
1786
- const circOut = reverseEasing(circIn);
1787
- const circInOut = mirrorEasing(circIn);
1788
-
1789
- const backOut = /*@__PURE__*/ cubicBezier(0.33, 1.53, 0.69, 0.99);
1790
- const backIn = /*@__PURE__*/ reverseEasing(backOut);
1791
- const backInOut = /*@__PURE__*/ mirrorEasing(backIn);
1792
-
1793
- const anticipate = (p) => (p *= 2) < 1 ? 0.5 * backIn(p) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
1794
-
1795
1800
  const easingLookup = {
1796
1801
  linear: noop,
1797
1802
  easeIn,
@@ -2284,7 +2289,9 @@ class MainThreadAnimation extends BaseAnimation {
2284
2289
  }
2285
2290
  initPlayback(keyframes$1) {
2286
2291
  const { type = "keyframes", repeat = 0, repeatDelay = 0, repeatType, velocity = 0, } = this.options;
2287
- const generatorFactory = generators[type] || keyframes;
2292
+ const generatorFactory = isGenerator(type)
2293
+ ? type
2294
+ : generators[type] || keyframes;
2288
2295
  /**
2289
2296
  * If our generator doesn't support mixing numbers, we need to replace keyframes with
2290
2297
  * [0, 100] and then make a function that maps that to the actual keyframes.
@@ -2597,9 +2604,47 @@ const acceleratedValues = new Set([
2597
2604
 
2598
2605
  const isBezierDefinition = (easing) => Array.isArray(easing) && typeof easing[0] === "number";
2599
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");
2600
2643
  function isWaapiSupportedEasing(easing) {
2601
- return Boolean(!easing ||
2602
- (typeof easing === "string" && easing in supportedWaapiEasing) ||
2644
+ return Boolean((typeof easing === "function" && supportsLinearEasing()) ||
2645
+ !easing ||
2646
+ (typeof easing === "string" &&
2647
+ (easing in supportedWaapiEasing || supportsLinearEasing())) ||
2603
2648
  isBezierDefinition(easing) ||
2604
2649
  (Array.isArray(easing) && easing.every(isWaapiSupportedEasing)));
2605
2650
  }
@@ -2615,19 +2660,19 @@ const supportedWaapiEasing = {
2615
2660
  backIn: /*@__PURE__*/ cubicBezierAsString([0.31, 0.01, 0.66, -0.59]),
2616
2661
  backOut: /*@__PURE__*/ cubicBezierAsString([0.33, 1.53, 0.69, 0.99]),
2617
2662
  };
2618
- function mapEasingToNativeEasingWithDefault(easing) {
2619
- return (mapEasingToNativeEasing(easing) ||
2620
- supportedWaapiEasing.easeOut);
2621
- }
2622
- function mapEasingToNativeEasing(easing) {
2663
+ function mapEasingToNativeEasing(easing, duration) {
2623
2664
  if (!easing) {
2624
2665
  return undefined;
2625
2666
  }
2667
+ else if (typeof easing === "function" && supportsLinearEasing()) {
2668
+ return generateLinearEasing(easing, duration);
2669
+ }
2626
2670
  else if (isBezierDefinition(easing)) {
2627
2671
  return cubicBezierAsString(easing);
2628
2672
  }
2629
2673
  else if (Array.isArray(easing)) {
2630
- return easing.map(mapEasingToNativeEasingWithDefault);
2674
+ return easing.map((segmentEasing) => mapEasingToNativeEasing(segmentEasing, duration) ||
2675
+ supportedWaapiEasing.easeOut);
2631
2676
  }
2632
2677
  else {
2633
2678
  return supportedWaapiEasing[easing];
@@ -2638,7 +2683,7 @@ function animateStyle(element, valueName, keyframes, { delay = 0, duration = 300
2638
2683
  const keyframeOptions = { [valueName]: keyframes };
2639
2684
  if (times)
2640
2685
  keyframeOptions.offset = times;
2641
- const easing = mapEasingToNativeEasing(ease);
2686
+ const easing = mapEasingToNativeEasing(ease, duration);
2642
2687
  /**
2643
2688
  * If this is an easing array, apply to keyframes, not animation as a whole
2644
2689
  */
@@ -2672,7 +2717,9 @@ const maxDuration = 20000;
2672
2717
  * handing off.
2673
2718
  */
2674
2719
  function requiresPregeneratedKeyframes(options) {
2675
- return options.type === "spring" || !isWaapiSupportedEasing(options.ease);
2720
+ return (isGenerator(options.type) ||
2721
+ options.type === "spring" ||
2722
+ !isWaapiSupportedEasing(options.ease));
2676
2723
  }
2677
2724
  function pregenerateKeyframes(keyframes, options) {
2678
2725
  /**
@@ -2706,6 +2753,14 @@ function pregenerateKeyframes(keyframes, options) {
2706
2753
  ease: "linear",
2707
2754
  };
2708
2755
  }
2756
+ const unsupportedEasingFunctions = {
2757
+ anticipate,
2758
+ backInOut,
2759
+ circInOut,
2760
+ };
2761
+ function isUnsupportedEase(key) {
2762
+ return key in unsupportedEasingFunctions;
2763
+ }
2709
2764
  class AcceleratedAnimation extends BaseAnimation {
2710
2765
  constructor(options) {
2711
2766
  super(options);
@@ -2723,6 +2778,16 @@ class AcceleratedAnimation extends BaseAnimation {
2723
2778
  if (!((_a = motionValue.owner) === null || _a === void 0 ? void 0 : _a.current)) {
2724
2779
  return false;
2725
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
+ }
2726
2791
  /**
2727
2792
  * If this animation needs pre-generated keyframes then generate.
2728
2793
  */
@@ -3218,7 +3283,7 @@ class MotionValue {
3218
3283
  * This will be replaced by the build step with the latest version number.
3219
3284
  * When MotionValues are provided to motion components, warn if versions are mixed.
3220
3285
  */
3221
- this.version = "11.6.0";
3286
+ this.version = "11.8.0";
3222
3287
  /**
3223
3288
  * Tracks whether this value can output a velocity. Currently this is only true
3224
3289
  * if the value is numerical, but we might be able to widen the scope here and support
@@ -5841,7 +5906,7 @@ function updateMotionValuesFromProps(element, next, prev) {
5841
5906
  * and warn against mismatches.
5842
5907
  */
5843
5908
  if (process.env.NODE_ENV === "development") {
5844
- warnOnce(nextValue.version === "11.6.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.6.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.`);
5845
5910
  }
5846
5911
  }
5847
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.6.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
  */
@@ -1658,6 +1724,10 @@ class DOMKeyframesResolver extends KeyframeResolver {
1658
1724
  }
1659
1725
  }
1660
1726
 
1727
+ function isGenerator(type) {
1728
+ return typeof type === "function";
1729
+ }
1730
+
1661
1731
  /**
1662
1732
  * Check if a value is animatable. Examples:
1663
1733
  *
@@ -1718,7 +1788,8 @@ function canAnimate(keyframes, name, type, velocity) {
1718
1788
  if (!isOriginAnimatable || !isTargetAnimatable) {
1719
1789
  return false;
1720
1790
  }
1721
- return hasKeyframesChanged(keyframes) || (type === "spring" && velocity);
1791
+ return (hasKeyframesChanged(keyframes) ||
1792
+ ((type === "spring" || isGenerator(type)) && velocity));
1722
1793
  }
1723
1794
 
1724
1795
  /**
@@ -2124,54 +2195,6 @@ function inertia({ keyframes, velocity = 0.0, power = 0.8, timeConstant = 325, b
2124
2195
  };
2125
2196
  }
2126
2197
 
2127
- /*
2128
- Bezier function generator
2129
- This has been modified from Gaëtan Renaudeau's BezierEasing
2130
- https://github.com/gre/bezier-easing/blob/master/src/index.js
2131
- https://github.com/gre/bezier-easing/blob/master/LICENSE
2132
-
2133
- I've removed the newtonRaphsonIterate algo because in benchmarking it
2134
- wasn't noticiably faster than binarySubdivision, indeed removing it
2135
- usually improved times, depending on the curve.
2136
- I also removed the lookup table, as for the added bundle size and loop we're
2137
- only cutting ~4 or so subdivision iterations. I bumped the max iterations up
2138
- to 12 to compensate and this still tended to be faster for no perceivable
2139
- loss in accuracy.
2140
- Usage
2141
- const easeOut = cubicBezier(.17,.67,.83,.67);
2142
- const x = easeOut(0.5); // returns 0.627...
2143
- */
2144
- // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
2145
- const calcBezier = (t, a1, a2) => (((1.0 - 3.0 * a2 + 3.0 * a1) * t + (3.0 * a2 - 6.0 * a1)) * t + 3.0 * a1) *
2146
- t;
2147
- const subdivisionPrecision = 0.0000001;
2148
- const subdivisionMaxIterations = 12;
2149
- function binarySubdivide(x, lowerBound, upperBound, mX1, mX2) {
2150
- let currentX;
2151
- let currentT;
2152
- let i = 0;
2153
- do {
2154
- currentT = lowerBound + (upperBound - lowerBound) / 2.0;
2155
- currentX = calcBezier(currentT, mX1, mX2) - x;
2156
- if (currentX > 0.0) {
2157
- upperBound = currentT;
2158
- }
2159
- else {
2160
- lowerBound = currentT;
2161
- }
2162
- } while (Math.abs(currentX) > subdivisionPrecision &&
2163
- ++i < subdivisionMaxIterations);
2164
- return currentT;
2165
- }
2166
- function cubicBezier(mX1, mY1, mX2, mY2) {
2167
- // If this is a linear gradient, return linear easing
2168
- if (mX1 === mY1 && mX2 === mY2)
2169
- return noop;
2170
- const getTForX = (aX) => binarySubdivide(aX, 0, 1, mX1, mX2);
2171
- // If animation is at start/end, return t without easing
2172
- return (t) => t === 0 || t === 1 ? t : calcBezier(getTForX(t), mY1, mY2);
2173
- }
2174
-
2175
2198
  const easeIn = /*@__PURE__*/ cubicBezier(0.42, 0, 1, 1);
2176
2199
  const easeOut = /*@__PURE__*/ cubicBezier(0, 0, 0.58, 1);
2177
2200
  const easeInOut = /*@__PURE__*/ cubicBezier(0.42, 0, 0.58, 1);
@@ -2180,24 +2203,6 @@ const isEasingArray = (ease) => {
2180
2203
  return Array.isArray(ease) && typeof ease[0] !== "number";
2181
2204
  };
2182
2205
 
2183
- // Accepts an easing function and returns a new one that outputs mirrored values for
2184
- // the second half of the animation. Turns easeIn into easeInOut.
2185
- const mirrorEasing = (easing) => (p) => p <= 0.5 ? easing(2 * p) / 2 : (2 - easing(2 * (1 - p))) / 2;
2186
-
2187
- // Accepts an easing function and returns a new one that outputs reversed values.
2188
- // Turns easeIn into easeOut.
2189
- const reverseEasing = (easing) => (p) => 1 - easing(1 - p);
2190
-
2191
- const circIn = (p) => 1 - Math.sin(Math.acos(p));
2192
- const circOut = reverseEasing(circIn);
2193
- const circInOut = mirrorEasing(circIn);
2194
-
2195
- const backOut = /*@__PURE__*/ cubicBezier(0.33, 1.53, 0.69, 0.99);
2196
- const backIn = /*@__PURE__*/ reverseEasing(backOut);
2197
- const backInOut = /*@__PURE__*/ mirrorEasing(backIn);
2198
-
2199
- const anticipate = (p) => (p *= 2) < 1 ? 0.5 * backIn(p) : 0.5 * (2 - Math.pow(2, -10 * (p - 1)));
2200
-
2201
2206
  const easingLookup = {
2202
2207
  linear: noop,
2203
2208
  easeIn,
@@ -2690,7 +2695,9 @@ class MainThreadAnimation extends BaseAnimation {
2690
2695
  }
2691
2696
  initPlayback(keyframes$1) {
2692
2697
  const { type = "keyframes", repeat = 0, repeatDelay = 0, repeatType, velocity = 0, } = this.options;
2693
- const generatorFactory = generators[type] || keyframes;
2698
+ const generatorFactory = isGenerator(type)
2699
+ ? type
2700
+ : generators[type] || keyframes;
2694
2701
  /**
2695
2702
  * If our generator doesn't support mixing numbers, we need to replace keyframes with
2696
2703
  * [0, 100] and then make a function that maps that to the actual keyframes.
@@ -3003,9 +3010,47 @@ const acceleratedValues = new Set([
3003
3010
 
3004
3011
  const isBezierDefinition = (easing) => Array.isArray(easing) && typeof easing[0] === "number";
3005
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");
3006
3049
  function isWaapiSupportedEasing(easing) {
3007
- return Boolean(!easing ||
3008
- (typeof easing === "string" && easing in supportedWaapiEasing) ||
3050
+ return Boolean((typeof easing === "function" && supportsLinearEasing()) ||
3051
+ !easing ||
3052
+ (typeof easing === "string" &&
3053
+ (easing in supportedWaapiEasing || supportsLinearEasing())) ||
3009
3054
  isBezierDefinition(easing) ||
3010
3055
  (Array.isArray(easing) && easing.every(isWaapiSupportedEasing)));
3011
3056
  }
@@ -3021,19 +3066,19 @@ const supportedWaapiEasing = {
3021
3066
  backIn: /*@__PURE__*/ cubicBezierAsString([0.31, 0.01, 0.66, -0.59]),
3022
3067
  backOut: /*@__PURE__*/ cubicBezierAsString([0.33, 1.53, 0.69, 0.99]),
3023
3068
  };
3024
- function mapEasingToNativeEasingWithDefault(easing) {
3025
- return (mapEasingToNativeEasing(easing) ||
3026
- supportedWaapiEasing.easeOut);
3027
- }
3028
- function mapEasingToNativeEasing(easing) {
3069
+ function mapEasingToNativeEasing(easing, duration) {
3029
3070
  if (!easing) {
3030
3071
  return undefined;
3031
3072
  }
3073
+ else if (typeof easing === "function" && supportsLinearEasing()) {
3074
+ return generateLinearEasing(easing, duration);
3075
+ }
3032
3076
  else if (isBezierDefinition(easing)) {
3033
3077
  return cubicBezierAsString(easing);
3034
3078
  }
3035
3079
  else if (Array.isArray(easing)) {
3036
- return easing.map(mapEasingToNativeEasingWithDefault);
3080
+ return easing.map((segmentEasing) => mapEasingToNativeEasing(segmentEasing, duration) ||
3081
+ supportedWaapiEasing.easeOut);
3037
3082
  }
3038
3083
  else {
3039
3084
  return supportedWaapiEasing[easing];
@@ -3044,7 +3089,7 @@ function animateStyle(element, valueName, keyframes, { delay = 0, duration = 300
3044
3089
  const keyframeOptions = { [valueName]: keyframes };
3045
3090
  if (times)
3046
3091
  keyframeOptions.offset = times;
3047
- const easing = mapEasingToNativeEasing(ease);
3092
+ const easing = mapEasingToNativeEasing(ease, duration);
3048
3093
  /**
3049
3094
  * If this is an easing array, apply to keyframes, not animation as a whole
3050
3095
  */
@@ -3078,7 +3123,9 @@ const maxDuration = 20000;
3078
3123
  * handing off.
3079
3124
  */
3080
3125
  function requiresPregeneratedKeyframes(options) {
3081
- return options.type === "spring" || !isWaapiSupportedEasing(options.ease);
3126
+ return (isGenerator(options.type) ||
3127
+ options.type === "spring" ||
3128
+ !isWaapiSupportedEasing(options.ease));
3082
3129
  }
3083
3130
  function pregenerateKeyframes(keyframes, options) {
3084
3131
  /**
@@ -3112,6 +3159,14 @@ function pregenerateKeyframes(keyframes, options) {
3112
3159
  ease: "linear",
3113
3160
  };
3114
3161
  }
3162
+ const unsupportedEasingFunctions = {
3163
+ anticipate,
3164
+ backInOut,
3165
+ circInOut,
3166
+ };
3167
+ function isUnsupportedEase(key) {
3168
+ return key in unsupportedEasingFunctions;
3169
+ }
3115
3170
  class AcceleratedAnimation extends BaseAnimation {
3116
3171
  constructor(options) {
3117
3172
  super(options);
@@ -3129,6 +3184,16 @@ class AcceleratedAnimation extends BaseAnimation {
3129
3184
  if (!((_a = motionValue.owner) === null || _a === void 0 ? void 0 : _a.current)) {
3130
3185
  return false;
3131
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
+ }
3132
3197
  /**
3133
3198
  * If this animation needs pre-generated keyframes then generate.
3134
3199
  */
@@ -3757,7 +3822,7 @@ function updateMotionValuesFromProps(element, next, prev) {
3757
3822
  * and warn against mismatches.
3758
3823
  */
3759
3824
  if (process.env.NODE_ENV === "development") {
3760
- warnOnce(nextValue.version === "11.6.0", `Attempting to mix Framer Motion versions ${nextValue.version} with 11.6.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.`);
3761
3826
  }
3762
3827
  }
3763
3828
  else if (isMotionValue(prevValue)) {
@@ -4859,7 +4924,7 @@ function createAnimationsFromSequence(sequence, { defaultTransition = {}, ...seq
4859
4924
  * If this animation should and can use a spring, generate a spring easing function.
4860
4925
  */
4861
4926
  const numKeyframes = valueKeyframesAsList.length;
4862
- if (numKeyframes <= 2 && type === "spring") {
4927
+ if ((numKeyframes <= 2 && type === "spring") || isGenerator(type)) {
4863
4928
  /**
4864
4929
  * As we're creating an easing function from a spring,
4865
4930
  * ideally we want to generate it using the real distance