framer-motion 9.1.7 → 10.0.0-alpha.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 CHANGED
@@ -1635,33 +1635,10 @@ class InViewFeature extends Feature {
1635
1635
  this.hasEnteredView = false;
1636
1636
  this.isInView = false;
1637
1637
  }
1638
- /**
1639
- * TODO: Remove this in 10.0
1640
- */
1641
- viewportFallback() {
1642
- /**
1643
- * Fire this in an rAF because, at this point, the animation state
1644
- * won't have flushed for the first time and there's certain logic in
1645
- * there that behaves differently on the initial animation.
1646
- */
1647
- requestAnimationFrame(() => {
1648
- this.hasEnteredView = true;
1649
- const { onViewportEnter } = this.node.getProps();
1650
- onViewportEnter && onViewportEnter(null);
1651
- if (this.node.animationState) {
1652
- this.node.animationState.setActive("whileInView", true);
1653
- }
1654
- });
1655
- }
1656
1638
  startObserver() {
1657
1639
  this.unmount();
1658
1640
  const { viewport = {} } = this.node.getProps();
1659
- const { root, margin: rootMargin, amount = "some", once, fallback = true, } = viewport;
1660
- if (typeof IntersectionObserver === "undefined") {
1661
- if (fallback)
1662
- this.viewportFallback();
1663
- return;
1664
- }
1641
+ const { root, margin: rootMargin, amount = "some", once } = viewport;
1665
1642
  const options = {
1666
1643
  root: root ? root.current : undefined,
1667
1644
  rootMargin,
@@ -1978,6 +1955,16 @@ function velocityPerSecond(velocity, frameDuration) {
1978
1955
  return frameDuration ? velocity * (1000 / frameDuration) : 0;
1979
1956
  }
1980
1957
 
1958
+ const warned = new Set();
1959
+ function warnOnce(condition, message, element) {
1960
+ if (condition || warned.has(message))
1961
+ return;
1962
+ console.warn(message);
1963
+ if (element)
1964
+ console.warn(element);
1965
+ warned.add(message);
1966
+ }
1967
+
1981
1968
  const isFloat = (value) => {
1982
1969
  return !isNaN(parseFloat(value));
1983
1970
  };
@@ -2000,7 +1987,7 @@ class MotionValue {
2000
1987
  * This will be replaced by the build step with the latest version number.
2001
1988
  * When MotionValues are provided to motion components, warn if versions are mixed.
2002
1989
  */
2003
- this.version = "9.1.7";
1990
+ this.version = "10.0.0-alpha.1";
2004
1991
  /**
2005
1992
  * Duration, in milliseconds, since last updating frame.
2006
1993
  *
@@ -2120,6 +2107,9 @@ class MotionValue {
2120
2107
  * @deprecated
2121
2108
  */
2122
2109
  onChange(subscription) {
2110
+ if (process.env.NODE_ENV !== "production") {
2111
+ warnOnce(false, `value.onChange(callback) is deprecated. Switch to value.on("change", callback).`);
2112
+ }
2123
2113
  return this.on("change", subscription);
2124
2114
  }
2125
2115
  on(eventName, callback) {
@@ -3614,6 +3604,7 @@ const acceleratedValues = new Set([
3614
3604
  "clipPath",
3615
3605
  "filter",
3616
3606
  "transform",
3607
+ "backgroundColor",
3617
3608
  ]);
3618
3609
  /**
3619
3610
  * 10ms is chosen here as it strikes a balance between smooth
@@ -3633,14 +3624,14 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
3633
3624
  /**
3634
3625
  * If this animation needs pre-generated keyframes then generate.
3635
3626
  */
3636
- if (options.type === "spring" || !isWaapiSupportedEasing(options.ease)) {
3637
- /**
3638
- * If we need to pre-generate keyframes and repeat is infinite then
3639
- * early return as this will lock the thread.
3640
- */
3641
- if (options.repeat === Infinity)
3642
- return;
3643
- const sampleAnimation = animateValue({ ...options, elapsed: 0 });
3627
+ if (options.type === "spring" ||
3628
+ valueName === "backgroundColor" ||
3629
+ !isWaapiSupportedEasing(options.ease)) {
3630
+ const sampleAnimation = animateValue({
3631
+ ...options,
3632
+ repeat: 0,
3633
+ elapsed: 0,
3634
+ });
3644
3635
  let state = { done: false, value: keyframes[0] };
3645
3636
  const pregeneratedKeyframes = [];
3646
3637
  /**
@@ -7819,16 +7810,6 @@ function initPrefersReducedMotion() {
7819
7810
  }
7820
7811
  }
7821
7812
 
7822
- const warned = new Set();
7823
- function warnOnce(condition, message, element) {
7824
- if (condition || warned.has(message))
7825
- return;
7826
- console.warn(message);
7827
- if (element)
7828
- console.warn(element);
7829
- warned.add(message);
7830
- }
7831
-
7832
7813
  function updateMotionValuesFromProps(element, next, prev) {
7833
7814
  const { willChange } = next;
7834
7815
  for (const key in next) {
@@ -7848,7 +7829,7 @@ function updateMotionValuesFromProps(element, next, prev) {
7848
7829
  * and warn against mismatches.
7849
7830
  */
7850
7831
  if (process.env.NODE_ENV === "development") {
7851
- warnOnce(nextValue.version === "9.1.7", `Attempting to mix Framer Motion versions ${nextValue.version} with 9.1.7 may not work as expected.`);
7832
+ warnOnce(nextValue.version === "10.0.0-alpha.1", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.0.0-alpha.1 may not work as expected.`);
7852
7833
  }
7853
7834
  }
7854
7835
  else if (isMotionValue(prevValue)) {
@@ -8926,13 +8907,7 @@ function onlyElements(children) {
8926
8907
  * @public
8927
8908
  */
8928
8909
  const AnimatePresence = ({ children, custom, initial = true, onExitComplete, exitBeforeEnter, presenceAffectsLayout = true, mode = "sync", }) => {
8929
- // Support deprecated exitBeforeEnter prop
8930
- if (exitBeforeEnter) {
8931
- mode = "wait";
8932
- if (process.env.NODE_ENV !== "production") {
8933
- warnOnce(false, "Replace exitBeforeEnter with mode='wait'");
8934
- }
8935
- }
8910
+ exports.invariant(!exitBeforeEnter, "Replace exitBeforeEnter with mode='wait'");
8936
8911
  // We want to force a re-render once all exiting animations have finished. We
8937
8912
  // either use a local forceRender function, or one from a parent context if it exists.
8938
8913
  let [forceRender] = useForceUpdate();
@@ -9027,45 +9002,6 @@ const AnimatePresence = ({ children, custom, initial = true, onExitComplete, exi
9027
9002
  : childrenToRender.map((child) => React.cloneElement(child))));
9028
9003
  };
9029
9004
 
9030
- /**
9031
- * @deprecated
9032
- */
9033
- const DeprecatedLayoutGroupContext = React.createContext(null);
9034
-
9035
- const shouldInheritGroup = (inherit) => inherit === true;
9036
- const shouldInheritId = (inherit) => shouldInheritGroup(inherit === true) || inherit === "id";
9037
- const LayoutGroup = ({ children, id, inheritId, inherit = true }) => {
9038
- // Maintain backwards-compatibility with inheritId until 7.0
9039
- if (inheritId !== undefined)
9040
- inherit = inheritId;
9041
- const layoutGroupContext = React.useContext(LayoutGroupContext);
9042
- const deprecatedLayoutGroupContext = React.useContext(DeprecatedLayoutGroupContext);
9043
- const [forceRender, key] = useForceUpdate();
9044
- const context = React.useRef(null);
9045
- const upstreamId = layoutGroupContext.id || deprecatedLayoutGroupContext;
9046
- if (context.current === null) {
9047
- if (shouldInheritId(inherit) && upstreamId) {
9048
- id = id ? upstreamId + "-" + id : upstreamId;
9049
- }
9050
- context.current = {
9051
- id,
9052
- group: shouldInheritGroup(inherit)
9053
- ? layoutGroupContext.group || nodeGroup()
9054
- : nodeGroup(),
9055
- };
9056
- }
9057
- const memoizedContext = React.useMemo(() => ({ ...context.current, forceRender }), [key]);
9058
- return (React__namespace.createElement(LayoutGroupContext.Provider, { value: memoizedContext }, children));
9059
- };
9060
-
9061
- let id = 0;
9062
- const AnimateSharedLayout = ({ children }) => {
9063
- React__namespace.useEffect(() => {
9064
- exports.warning(false, "AnimateSharedLayout is deprecated: https://www.framer.com/docs/guide-upgrade/##shared-layout-animations");
9065
- }, []);
9066
- return (React__namespace.createElement(LayoutGroup, { id: useConstant(() => `asl-${id++}`) }, children));
9067
- };
9068
-
9069
9005
  /**
9070
9006
  * `MotionConfig` is used to set configuration options for all children `motion` components.
9071
9007
  *
@@ -9163,6 +9099,28 @@ function isLazyBundle(features) {
9163
9099
  return typeof features === "function";
9164
9100
  }
9165
9101
 
9102
+ const shouldInheritGroup = (inherit) => inherit === true;
9103
+ const shouldInheritId = (inherit) => shouldInheritGroup(inherit === true) || inherit === "id";
9104
+ const LayoutGroup = ({ children, id, inherit = true }) => {
9105
+ const layoutGroupContext = React.useContext(LayoutGroupContext);
9106
+ const [forceRender, key] = useForceUpdate();
9107
+ const context = React.useRef(null);
9108
+ const upstreamId = layoutGroupContext.id;
9109
+ if (context.current === null) {
9110
+ if (shouldInheritId(inherit) && upstreamId) {
9111
+ id = id ? upstreamId + "-" + id : upstreamId;
9112
+ }
9113
+ context.current = {
9114
+ id,
9115
+ group: shouldInheritGroup(inherit)
9116
+ ? layoutGroupContext.group || nodeGroup()
9117
+ : nodeGroup(),
9118
+ };
9119
+ }
9120
+ const memoizedContext = React.useMemo(() => ({ ...context.current, forceRender }), [key]);
9121
+ return (React__namespace.createElement(LayoutGroupContext.Provider, { value: memoizedContext }, children));
9122
+ };
9123
+
9166
9124
  const ReorderContext = React.createContext(null);
9167
9125
 
9168
9126
  function checkReorder(order, value, offset, velocity) {
@@ -10251,15 +10209,6 @@ const thresholds = {
10251
10209
  all: 1,
10252
10210
  };
10253
10211
  function inView(elementOrSelector, onStart, { root, margin: rootMargin, amount = "any" } = {}) {
10254
- /**
10255
- * If this browser doesn't support IntersectionObserver, return a dummy stop function.
10256
- * Default triggering of onStart is tricky - it could be used for starting/stopping
10257
- * videos, lazy loading content etc. We could provide an option to enable a fallback, or
10258
- * provide a fallback callback option.
10259
- */
10260
- if (typeof IntersectionObserver === "undefined") {
10261
- return () => { };
10262
- }
10263
10212
  const elements = resolveElements(elementOrSelector);
10264
10213
  const activeIntersections = new WeakMap();
10265
10214
  const onIntersectionChange = (entries) => {
@@ -10706,9 +10655,16 @@ function useInvertedScale(scale) {
10706
10655
  return { scaleX, scaleY };
10707
10656
  }
10708
10657
 
10658
+ let id = 0;
10659
+ const AnimateSharedLayout = ({ children }) => {
10660
+ React__namespace.useEffect(() => {
10661
+ exports.invariant(false, "AnimateSharedLayout is deprecated: https://www.framer.com/docs/guide-upgrade/##shared-layout-animations");
10662
+ }, []);
10663
+ return (React__namespace.createElement(LayoutGroup, { id: useConstant(() => `asl-${id++}`) }, children));
10664
+ };
10665
+
10709
10666
  exports.AnimatePresence = AnimatePresence;
10710
10667
  exports.AnimateSharedLayout = AnimateSharedLayout;
10711
- exports.DeprecatedLayoutGroupContext = DeprecatedLayoutGroupContext;
10712
10668
  exports.DragControls = DragControls;
10713
10669
  exports.FlatTree = FlatTree;
10714
10670
  exports.LayoutGroup = LayoutGroup;
@@ -13,6 +13,7 @@ const acceleratedValues = new Set([
13
13
  "clipPath",
14
14
  "filter",
15
15
  "transform",
16
+ "backgroundColor",
16
17
  ]);
17
18
  /**
18
19
  * 10ms is chosen here as it strikes a balance between smooth
@@ -32,14 +33,14 @@ function createAcceleratedAnimation(value, valueName, { onUpdate, onComplete, ..
32
33
  /**
33
34
  * If this animation needs pre-generated keyframes then generate.
34
35
  */
35
- if (options.type === "spring" || !isWaapiSupportedEasing(options.ease)) {
36
- /**
37
- * If we need to pre-generate keyframes and repeat is infinite then
38
- * early return as this will lock the thread.
39
- */
40
- if (options.repeat === Infinity)
41
- return;
42
- const sampleAnimation = animateValue({ ...options, elapsed: 0 });
36
+ if (options.type === "spring" ||
37
+ valueName === "backgroundColor" ||
38
+ !isWaapiSupportedEasing(options.ease)) {
39
+ const sampleAnimation = animateValue({
40
+ ...options,
41
+ repeat: 0,
42
+ elapsed: 0,
43
+ });
43
44
  let state = { done: false, value: keyframes[0] };
44
45
  const pregeneratedKeyframes = [];
45
46
  /**
@@ -6,7 +6,7 @@ import { PresenceChild } from './PresenceChild.mjs';
6
6
  import { LayoutGroupContext } from '../../context/LayoutGroupContext.mjs';
7
7
  import { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs';
8
8
  import { useUnmountEffect } from '../../utils/use-unmount-effect.mjs';
9
- import { warnOnce } from '../../utils/warn-once.mjs';
9
+ import { invariant } from '../../utils/errors.mjs';
10
10
 
11
11
  const getChildKey = (child) => child.key || "";
12
12
  function updateChildLookup(children, allChildren) {
@@ -58,13 +58,7 @@ function onlyElements(children) {
58
58
  * @public
59
59
  */
60
60
  const AnimatePresence = ({ children, custom, initial = true, onExitComplete, exitBeforeEnter, presenceAffectsLayout = true, mode = "sync", }) => {
61
- // Support deprecated exitBeforeEnter prop
62
- if (exitBeforeEnter) {
63
- mode = "wait";
64
- if (process.env.NODE_ENV !== "production") {
65
- warnOnce(false, "Replace exitBeforeEnter with mode='wait'");
66
- }
67
- }
61
+ invariant(!exitBeforeEnter, "Replace exitBeforeEnter with mode='wait'");
68
62
  // We want to force a re-render once all exiting animations have finished. We
69
63
  // either use a local forceRender function, or one from a parent context if it exists.
70
64
  let [forceRender] = useForceUpdate();
@@ -1,4 +1,4 @@
1
- import { warning } from '../utils/errors.mjs';
1
+ import { invariant } from '../utils/errors.mjs';
2
2
  import * as React from 'react';
3
3
  import { useConstant } from '../utils/use-constant.mjs';
4
4
  import { LayoutGroup } from './LayoutGroup/index.mjs';
@@ -6,7 +6,7 @@ import { LayoutGroup } from './LayoutGroup/index.mjs';
6
6
  let id = 0;
7
7
  const AnimateSharedLayout = ({ children }) => {
8
8
  React.useEffect(() => {
9
- warning(false, "AnimateSharedLayout is deprecated: https://www.framer.com/docs/guide-upgrade/##shared-layout-animations");
9
+ invariant(false, "AnimateSharedLayout is deprecated: https://www.framer.com/docs/guide-upgrade/##shared-layout-animations");
10
10
  }, []);
11
11
  return (React.createElement(LayoutGroup, { id: useConstant(() => `asl-${id++}`) }, children));
12
12
  };
@@ -1,21 +1,16 @@
1
1
  import * as React from 'react';
2
2
  import { useContext, useRef, useMemo } from 'react';
3
3
  import { LayoutGroupContext } from '../../context/LayoutGroupContext.mjs';
4
- import { DeprecatedLayoutGroupContext } from '../../context/DeprecatedLayoutGroupContext.mjs';
5
4
  import { useForceUpdate } from '../../utils/use-force-update.mjs';
6
5
  import { nodeGroup } from '../../projection/node/group.mjs';
7
6
 
8
7
  const shouldInheritGroup = (inherit) => inherit === true;
9
8
  const shouldInheritId = (inherit) => shouldInheritGroup(inherit === true) || inherit === "id";
10
- const LayoutGroup = ({ children, id, inheritId, inherit = true }) => {
11
- // Maintain backwards-compatibility with inheritId until 7.0
12
- if (inheritId !== undefined)
13
- inherit = inheritId;
9
+ const LayoutGroup = ({ children, id, inherit = true }) => {
14
10
  const layoutGroupContext = useContext(LayoutGroupContext);
15
- const deprecatedLayoutGroupContext = useContext(DeprecatedLayoutGroupContext);
16
11
  const [forceRender, key] = useForceUpdate();
17
12
  const context = useRef(null);
18
- const upstreamId = layoutGroupContext.id || deprecatedLayoutGroupContext;
13
+ const upstreamId = layoutGroupContext.id;
19
14
  if (context.current === null) {
20
15
  if (shouldInheritId(inherit) && upstreamId) {
21
16
  id = id ? upstreamId + "-" + id : upstreamId;
package/dist/es/index.mjs CHANGED
@@ -1,7 +1,6 @@
1
1
  export { createDomMotionComponent, motion } from './render/dom/motion.mjs';
2
2
  export { m } from './render/dom/motion-minimal.mjs';
3
3
  export { AnimatePresence } from './components/AnimatePresence/index.mjs';
4
- export { AnimateSharedLayout } from './components/AnimateSharedLayout.mjs';
5
4
  export { MotionConfig } from './components/MotionConfig/index.mjs';
6
5
  export { LazyMotion } from './components/LazyMotion/index.mjs';
7
6
  export { LayoutGroup } from './components/LayoutGroup/index.mjs';
@@ -68,7 +67,6 @@ export { MotionContext, useVisualElementContext } from './context/MotionContext/
68
67
  export { MotionConfigContext } from './context/MotionConfigContext.mjs';
69
68
  export { PresenceContext } from './context/PresenceContext.mjs';
70
69
  export { LayoutGroupContext } from './context/LayoutGroupContext.mjs';
71
- export { DeprecatedLayoutGroupContext } from './context/DeprecatedLayoutGroupContext.mjs';
72
70
  export { SwitchLayoutGroupContext } from './context/SwitchLayoutGroupContext.mjs';
73
71
  export { anticipate } from './easing/anticipate.mjs';
74
72
  export { backIn, backInOut, backOut } from './easing/back.mjs';
@@ -78,6 +76,7 @@ export { cubicBezier } from './easing/cubic-bezier.mjs';
78
76
  export { FlatTree } from './render/utils/flat-tree.mjs';
79
77
  export { useAnimatedState as useDeprecatedAnimatedState } from './animation/hooks/use-animated-state.mjs';
80
78
  export { useInvertedScale as useDeprecatedInvertedScale } from './value/use-inverted-scale.mjs';
79
+ export { AnimateSharedLayout } from './components/AnimateSharedLayout.mjs';
81
80
  export { animations } from './motion/features/animations.mjs';
82
81
  export { checkTargetForNewValues } from './render/utils/setters.mjs';
83
82
  export { createBox } from './projection/geometry/models.mjs';
@@ -11,33 +11,10 @@ class InViewFeature extends Feature {
11
11
  this.hasEnteredView = false;
12
12
  this.isInView = false;
13
13
  }
14
- /**
15
- * TODO: Remove this in 10.0
16
- */
17
- viewportFallback() {
18
- /**
19
- * Fire this in an rAF because, at this point, the animation state
20
- * won't have flushed for the first time and there's certain logic in
21
- * there that behaves differently on the initial animation.
22
- */
23
- requestAnimationFrame(() => {
24
- this.hasEnteredView = true;
25
- const { onViewportEnter } = this.node.getProps();
26
- onViewportEnter && onViewportEnter(null);
27
- if (this.node.animationState) {
28
- this.node.animationState.setActive("whileInView", true);
29
- }
30
- });
31
- }
32
14
  startObserver() {
33
15
  this.unmount();
34
16
  const { viewport = {} } = this.node.getProps();
35
- const { root, margin: rootMargin, amount = "some", once, fallback = true, } = viewport;
36
- if (typeof IntersectionObserver === "undefined") {
37
- if (fallback)
38
- this.viewportFallback();
39
- return;
40
- }
17
+ const { root, margin: rootMargin, amount = "some", once } = viewport;
41
18
  const options = {
42
19
  root: root ? root.current : undefined,
43
20
  rootMargin,
@@ -5,15 +5,6 @@ const thresholds = {
5
5
  all: 1,
6
6
  };
7
7
  function inView(elementOrSelector, onStart, { root, margin: rootMargin, amount = "any" } = {}) {
8
- /**
9
- * If this browser doesn't support IntersectionObserver, return a dummy stop function.
10
- * Default triggering of onStart is tricky - it could be used for starting/stopping
11
- * videos, lazy loading content etc. We could provide an option to enable a fallback, or
12
- * provide a fallback callback option.
13
- */
14
- if (typeof IntersectionObserver === "undefined") {
15
- return () => { };
16
- }
17
8
  const elements = resolveElements(elementOrSelector);
18
9
  const activeIntersections = new WeakMap();
19
10
  const onIntersectionChange = (entries) => {
@@ -22,7 +22,7 @@ function updateMotionValuesFromProps(element, next, prev) {
22
22
  * and warn against mismatches.
23
23
  */
24
24
  if (process.env.NODE_ENV === "development") {
25
- warnOnce(nextValue.version === "9.1.7", `Attempting to mix Framer Motion versions ${nextValue.version} with 9.1.7 may not work as expected.`);
25
+ warnOnce(nextValue.version === "10.0.0-alpha.1", `Attempting to mix Framer Motion versions ${nextValue.version} with 10.0.0-alpha.1 may not work as expected.`);
26
26
  }
27
27
  }
28
28
  else if (isMotionValue(prevValue)) {
@@ -2,6 +2,7 @@ import { frameData } from '../frameloop/data.mjs';
2
2
  import { sync } from '../frameloop/index.mjs';
3
3
  import { SubscriptionManager } from '../utils/subscription-manager.mjs';
4
4
  import { velocityPerSecond } from '../utils/velocity-per-second.mjs';
5
+ import { warnOnce } from '../utils/warn-once.mjs';
5
6
 
6
7
  const isFloat = (value) => {
7
8
  return !isNaN(parseFloat(value));
@@ -25,7 +26,7 @@ class MotionValue {
25
26
  * This will be replaced by the build step with the latest version number.
26
27
  * When MotionValues are provided to motion components, warn if versions are mixed.
27
28
  */
28
- this.version = "9.1.7";
29
+ this.version = "10.0.0-alpha.1";
29
30
  /**
30
31
  * Duration, in milliseconds, since last updating frame.
31
32
  *
@@ -145,6 +146,9 @@ class MotionValue {
145
146
  * @deprecated
146
147
  */
147
148
  onChange(subscription) {
149
+ if (process.env.NODE_ENV !== "production") {
150
+ warnOnce(false, `value.onChange(callback) is deprecated. Switch to value.on("change", callback).`);
151
+ }
148
152
  return this.on("change", subscription);
149
153
  }
150
154
  on(eventName, callback) {