framer-motion 1.9.1 → 1.10.3

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/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  Framer Motion adheres to [Semantic Versioning](http://semver.org/).
4
4
 
5
+ ## [1.10.3] 2020-03-23
6
+
7
+ ### Fix
8
+
9
+ - Replacing the functionality of `DragControls` `e.preventDefault()` with CSS and HTML attributes. ([@inventingwithmonster](https://github.com/inventingwithmonster) in [#495](https://github.com/framer/motion/pull/495))
10
+
11
+ ## [1.10.2] 2020-03-23
12
+
13
+ ### Fix
14
+
15
+ - Fixing `PresenceChild` losing correct count of exiting children if it re-renders. ([@inventingwithmonster](https://github.com/inventingwithmonster) in [#490](https://github.com/framer/motion/pull/490))
16
+
17
+ ## [1.10.1] 2020-03-23
18
+
19
+ ### Fix
20
+
21
+ - Fixing `AnimatePresence` children not re-rendering when their exiting siblings have been removed from the tree (which broke siblings `positionTransition` and `layoutTransition`). ([@inventingwithmonster](https://github.com/inventingwithmonster) in [#489](https://github.com/framer/motion/pull/489))
22
+ - Adding `null` check for `getTranslateFromMatrix` ([@JoyalJoyMadeckal](https://github.com/JoyalJoyMadeckal) in [#482](https://github.com/framer/motion/pull/482))
23
+
24
+ ## [1.10.0] 2020-03-19
25
+
26
+ ### Added
27
+
28
+ - `AnimatePresence` now supports multiple `usePresence` children within a given sub-tree.
29
+
5
30
  ## [1.9.1] 2020-03-06
6
31
 
7
32
  ### Fixed
@@ -15,7 +15,7 @@
15
15
  "members": [
16
16
  {
17
17
  "kind": "Variable",
18
- "docComment": "/**\n * The `AnimatePresence` component enables the use of the `exit` prop to animate components when they're removed from the component tree.\n *\n * When adding/removing more than a single child component, every component **must** be given a unique `key` prop.\n *\n * You can propagate exit animations throughout a tree by using variants.\n *\n * @library\n *\n * You can use any component(s) within `AnimatePresence`, but the first `Frame` in each should have an `exit` property defined.\n * ```jsx\n * import { Frame, AnimatePresence } from 'framer'\n *\n * // As items are added and removed from `items`\n * export function Items({ items }) {\n * return (\n * <AnimatePresence>\n * {items.map(item => (\n * <Frame\n * key={item.id}\n * initial={{ opacity: 0 }}\n * animate={{ opacity: 1 }}\n * exit={{ opacity: 0 }}\n * />\n * ))}\n * </AnimatePresence>\n * )\n * }\n * ```\n *\n * @motion\n *\n * You can use any component(s) within `AnimatePresence`, but the first `motion` component in each should have an `exit` property defined.\n * ```jsx\n * import { motion, AnimatePresence } from 'framer-motion'\n *\n * export const Items = ({ items }) => (\n * <AnimatePresence>\n * {items.map(item => (\n * <motion.div\n * key={item.id}\n * initial={{ opacity: 0 }}\n * animate={{ opacity: 1 }}\n * exit={{ opacity: 0 }}\n * />\n * ))}\n * </AnimatePresence>\n * )\n * ```\n *\n * @public\n */\n",
18
+ "docComment": "/**\n * `AnimatePresence` enables the animation of components that have been removed from the tree.\n *\n * When adding/removing more than a single child, every child **must** be given a unique `key` prop.\n *\n * @library\n *\n * Any `Frame` components that have an `exit` property defined will animate out when removed from the tree.\n * ```jsx\n * import { Frame, AnimatePresence } from 'framer'\n *\n * // As items are added and removed from `items`\n * export function Items({ items }) {\n * return (\n * <AnimatePresence>\n * {items.map(item => (\n * <Frame\n * key={item.id}\n * initial={{ opacity: 0 }}\n * animate={{ opacity: 1 }}\n * exit={{ opacity: 0 }}\n * />\n * ))}\n * </AnimatePresence>\n * )\n * }\n * ```\n *\n * You can sequence exit animations throughout a tree using variants.\n *\n * @motion\n *\n * Any `motion` components that have an `exit` property defined will animate out when removed from the tree.\n * ```jsx\n * import { motion, AnimatePresence } from 'framer-motion'\n *\n * export const Items = ({ items }) => (\n * <AnimatePresence>\n * {items.map(item => (\n * <motion.div\n * key={item.id}\n * initial={{ opacity: 0 }}\n * animate={{ opacity: 1 }}\n * exit={{ opacity: 0 }}\n * />\n * ))}\n * </AnimatePresence>\n * )\n * ```\n *\n * You can sequence exit animations throughout a tree using variants.\n *\n * If a child contains multiple `motion` components with `exit` props, it will only unmount the child once all `motion` components have finished animating out. Likewise, any components using `usePresence` all need to call `safeToRemove`.\n *\n * @public\n */\n",
19
19
  "excerptTokens": [
20
20
  {
21
21
  "kind": "Reference",
@@ -13330,7 +13330,7 @@
13330
13330
  },
13331
13331
  {
13332
13332
  "kind": "Function",
13333
- "docComment": "/**\n * When a component is the child of an `AnimatePresence` component, it has access to information about whether it's still present the React tree. `usePresence` can be used to access that data and perform operations before the component can be considered safe to remove.\n *\n * It returns two values. `isPresent` is a boolean that is `true` when the component is present within the React tree. It is `false` when it's been removed, but still visible.\n *\n * When `isPresent` is `false`, the `safeToRemove` callback can be used to tell `AnimatePresence` that it's safe to remove the component from the DOM, for instance after a animation has completed.\n * ```jsx\n * const [isPresent, safeToRemove] = usePresence()\n *\n * useEffect(() => {\n * !isPresent setTimeout(safeToRemove, 1000)\n * }, [isPresent])\n * ```\n *\n * @public\n */\n",
13333
+ "docComment": "/**\n * When a component is the child of `AnimatePresence`, it can use `usePresence` to access information about whether it's still present in the React tree.\n * ```jsx\n * import { usePresence } from \"framer-motion\"\n *\n * export const Component = () => {\n * const [isPresent, safeToRemove] = usePresence()\n *\n * useEffect(() => {\n * !isPresent setTimeout(safeToRemove, 1000)\n * }, [isPresent])\n *\n * return <div />\n * }\n * ```\n *\n * If `isPresent` is `false`, it means that a component has been removed the tree, but `AnimatePresence` won't really remove it until `safeToRemove` has been called.\n *\n * @public\n */\n",
13334
13334
  "excerptTokens": [
13335
13335
  {
13336
13336
  "kind": "Content",
@@ -1605,6 +1605,8 @@ var AnimationControls = /** @class */ (function () {
1605
1605
  */
1606
1606
  var animationControls = function () { return new AnimationControls(); };
1607
1607
 
1608
+ var PresenceContext = React.createContext(null);
1609
+
1608
1610
  /**
1609
1611
  * @internal
1610
1612
  */
@@ -1625,10 +1627,11 @@ var isAnimationControls = function (v) {
1625
1627
  var useMotionContext = function (parentContext, controls, values, isStatic, _a) {
1626
1628
  if (isStatic === void 0) { isStatic = false; }
1627
1629
  var initial = _a.initial, animate = _a.animate, variants = _a.variants, whileTap = _a.whileTap, whileHover = _a.whileHover;
1630
+ var _b;
1631
+ var presenceContext = React.useContext(PresenceContext);
1628
1632
  // Override initial with that from a parent context, if defined
1629
- if (parentContext.exitProps &&
1630
- parentContext.exitProps.initial !== undefined) {
1631
- initial = parentContext.exitProps.initial;
1633
+ if (((_b = presenceContext) === null || _b === void 0 ? void 0 : _b.initial) !== undefined) {
1634
+ initial = presenceContext.initial;
1632
1635
  }
1633
1636
  var initialState;
1634
1637
  if (initial === false && !isAnimationControls(animate)) {
@@ -1708,14 +1711,13 @@ var useMotionContext = function (parentContext, controls, values, isStatic, _a)
1708
1711
  *
1709
1712
  * @internal
1710
1713
  */
1711
- function useValueAnimationControls(config, props, subscribeToParentControls, parentContext) {
1714
+ function useValueAnimationControls(config, props, subscribeToParentControls) {
1712
1715
  var variants = props.variants, transition = props.transition;
1713
1716
  var parentControls = React.useContext(MotionContext).controls;
1717
+ var presenceContext = React.useContext(PresenceContext);
1714
1718
  var controls = useConstant(function () { return new ValueAnimationControls(config); });
1715
1719
  // Reset and resubscribe children every render to ensure stagger order is correct
1716
- if (!parentContext ||
1717
- !parentContext.exitProps ||
1718
- !parentContext.exitProps.isExiting) {
1720
+ if (!presenceContext || presenceContext.isPresent) {
1719
1721
  controls.resetChildren();
1720
1722
  controls.setProps(props);
1721
1723
  controls.setVariants(variants);
@@ -1790,7 +1792,7 @@ var createMotionComponent = function (_a) {
1790
1792
  var controlsConfig = useConstant(function () {
1791
1793
  return getValueControlsConfig(ref, values);
1792
1794
  });
1793
- var controls = useValueAnimationControls(controlsConfig, props, shouldInheritVariant, parentContext);
1795
+ var controls = useValueAnimationControls(controlsConfig, props, shouldInheritVariant);
1794
1796
  var context = useMotionContext(parentContext, controls, values, isStatic, props);
1795
1797
  var functionality = isStatic
1796
1798
  ? null
@@ -2587,10 +2589,6 @@ var isRefObject = function (ref) {
2587
2589
  };
2588
2590
 
2589
2591
  var noop = function (v) { return v; };
2590
- /**
2591
- * Don't block the default pointerdown behaviour of these elements.
2592
- */
2593
- var allowDefaultPointerDown = new Set(["INPUT", "TEXTAREA", "SELECT"]);
2594
2592
  var ComponentDragControls = /** @class */ (function () {
2595
2593
  function ComponentDragControls(_a) {
2596
2594
  var ref = _a.ref, values = _a.values, controls = _a.controls;
@@ -2670,20 +2668,7 @@ var ComponentDragControls = /** @class */ (function () {
2670
2668
  var _this = this;
2671
2669
  var _b = (_a === void 0 ? {} : _a).snapToCursor, snapToCursor = _b === void 0 ? false : _b;
2672
2670
  snapToCursor && this.snapToCursor(originEvent);
2673
- var onSessionStart = function (event) {
2674
- // Prevent browser-specific behaviours like text selection or Chrome's image dragging.
2675
- if (event.target &&
2676
- !allowDefaultPointerDown.has(event.target.tagName)) {
2677
- // On iOS it's important to not `preventDefault` the `touchstart`
2678
- // event, as otherwise clicks won't fire inside the draggable element.
2679
- if (!supportsTouchEvents()) {
2680
- event.preventDefault();
2681
- // Make sure input elements loose focus when we prevent the default.
2682
- if (document.activeElement instanceof HTMLElement) {
2683
- document.activeElement.blur();
2684
- }
2685
- }
2686
- }
2671
+ var onSessionStart = function () {
2687
2672
  // Initiate viewport scroll blocking on touch start. This is a very aggressive approach
2688
2673
  // which has come out of the difficulty in us being able to do this once a scroll gesture
2689
2674
  // has initiated in mobile browsers. This means if there's a horizontally-scrolling carousel
@@ -3228,7 +3213,12 @@ var getTranslateFromMatrix = function (pos2, pos3) { return function (_bbox, _a)
3228
3213
  }
3229
3214
  else {
3230
3215
  var matrix = transform.match(/^matrix\((.+)\)$/);
3231
- return getPosFromMatrix(matrix[1], pos2);
3216
+ if (matrix) {
3217
+ return getPosFromMatrix(matrix[1], pos2);
3218
+ }
3219
+ else {
3220
+ return 0;
3221
+ }
3232
3222
  }
3233
3223
  }; };
3234
3224
  var transformKeys = new Set(["x", "y", "z"]);
@@ -4007,28 +3997,54 @@ var getAnimationComponent = function (props) {
4007
3997
  return animatePropType ? AnimatePropComponents[animatePropType] : undefined;
4008
3998
  };
4009
3999
 
4000
+ /**
4001
+ * When a component is the child of `AnimatePresence`, it can use `usePresence`
4002
+ * to access information about whether it's still present in the React tree.
4003
+ *
4004
+ * ```jsx
4005
+ * import { usePresence } from "framer-motion"
4006
+ *
4007
+ * export const Component = () => {
4008
+ * const [isPresent, safeToRemove] = usePresence()
4009
+ *
4010
+ * useEffect(() => {
4011
+ * !isPresent setTimeout(safeToRemove, 1000)
4012
+ * }, [isPresent])
4013
+ *
4014
+ * return <div />
4015
+ * }
4016
+ * ```
4017
+ *
4018
+ * If `isPresent` is `false`, it means that a component has been removed the tree, but
4019
+ * `AnimatePresence` won't really remove it until `safeToRemove` has been called.
4020
+ *
4021
+ * @public
4022
+ */
4023
+ function usePresence() {
4024
+ var context = React.useContext(PresenceContext);
4025
+ if (context === null)
4026
+ return [true];
4027
+ var isPresent = context.isPresent, onExitComplete = context.onExitComplete, register = context.register;
4028
+ React.useEffect(register, []);
4029
+ return !isPresent && onExitComplete ? [false, onExitComplete] : [true];
4030
+ }
4031
+
4010
4032
  var Exit = {
4011
4033
  key: "exit",
4012
- shouldRender: function (_a, _b) {
4013
- var exit = _a.exit;
4014
- var exitProps = _b.exitProps;
4015
- var hasExitProps = !!exitProps;
4016
- var hasExitAnimation = !!exit;
4017
- heyListen.invariant(!hasExitProps || (hasExitProps && hasExitAnimation), "No exit prop defined on a child of AnimatePresence.");
4018
- return hasExitProps && hasExitAnimation;
4019
- },
4034
+ shouldRender: function (props) { return !!props.exit && !checkShouldInheritVariant(props); },
4020
4035
  Component: makeRenderlessComponent(function (props) {
4021
- var animate = props.animate, controls = props.controls, parentContext = props.parentContext, exit = props.exit;
4022
- var exitProps = parentContext.exitProps;
4036
+ var _a;
4037
+ var animate = props.animate, controls = props.controls, exit = props.exit;
4038
+ var _b = usePresence(), isPresent = _b[0], onExitComplete = _b[1];
4039
+ var presenceContext = React.useContext(PresenceContext);
4023
4040
  var isPlayingExitAnimation = React.useRef(false);
4024
- // This early return is more for types - it won't actually run because of the `shouldRender` above.
4025
- if (!exitProps || !exit)
4026
- return;
4027
- var isExiting = exitProps.isExiting, custom = exitProps.custom, onExitComplete = exitProps.onExitComplete;
4041
+ var custom = ((_a = presenceContext) === null || _a === void 0 ? void 0 : _a.custom) !== undefined
4042
+ ? presenceContext.custom
4043
+ : props.custom;
4028
4044
  React.useEffect(function () {
4029
- if (isExiting) {
4045
+ if (!isPresent) {
4030
4046
  if (!isPlayingExitAnimation.current && exit) {
4031
- controls.setProps(tslib.__assign(tslib.__assign({}, props), { custom: custom !== undefined ? custom : props.custom }));
4047
+ controls.setProps(tslib.__assign(tslib.__assign({}, props), { custom: custom }));
4032
4048
  controls.start(exit).then(onExitComplete);
4033
4049
  }
4034
4050
  isPlayingExitAnimation.current = true;
@@ -4038,10 +4054,10 @@ var Exit = {
4038
4054
  !(animate instanceof AnimationControls)) {
4039
4055
  controls.start(animate);
4040
4056
  }
4041
- if (!isExiting) {
4057
+ if (isPresent) {
4042
4058
  isPlayingExitAnimation.current = false;
4043
4059
  }
4044
- }, [isExiting]);
4060
+ }, [isPresent]);
4045
4061
  }),
4046
4062
  };
4047
4063
 
@@ -4083,6 +4099,19 @@ function filterValidProps(props) {
4083
4099
  }
4084
4100
  return domProps;
4085
4101
  }
4102
+ var buildHTMLProps = function (values, style, isStatic, isDrag) {
4103
+ // The `any` isn't ideal but it is the type of createElement props argument
4104
+ var props = {
4105
+ style: buildStyleAttr(values, style, isStatic),
4106
+ };
4107
+ if (isDrag) {
4108
+ // Disable text selection
4109
+ props.style.userSelect = "none";
4110
+ // Disable the ghost element when a user drags
4111
+ props.draggable = false;
4112
+ }
4113
+ return props;
4114
+ };
4086
4115
  var buildSVGProps = function (values, style) {
4087
4116
  var motionValueStyles = resolveCurrent(values);
4088
4117
  var props = styler.buildSVGAttrs(motionValueStyles, undefined, undefined, undefined, undefined, false);
@@ -4104,7 +4133,7 @@ function createDomMotionConfig(Component) {
4104
4133
  var forwardedProps = isDOM ? filterValidProps(props) : props;
4105
4134
  var staticVisualStyles = isSVG
4106
4135
  ? buildSVGProps(values, style)
4107
- : { style: buildStyleAttr(values, style, isStatic) };
4136
+ : buildHTMLProps(values, style, isStatic, !!props.drag);
4108
4137
  return React.createElement(Component, tslib.__assign(tslib.__assign(tslib.__assign({}, forwardedProps), { ref: ref }), staticVisualStyles));
4109
4138
  },
4110
4139
  /**
@@ -4778,13 +4807,29 @@ function useDragControls() {
4778
4807
  }
4779
4808
 
4780
4809
  var PresenceChild = function (_a) {
4781
- var children = _a.children, exitProps = _a.exitProps;
4782
- var context = React.useContext(MotionContext);
4783
- // Create a new `value` in all instances to ensure `motion` children re-render
4784
- // and detect any layout changes that might have occurred.
4785
- context = tslib.__assign(tslib.__assign({}, context), { exitProps: exitProps || {} });
4786
- return (React.createElement(MotionContext.Provider, { value: context }, children));
4787
- };
4810
+ var children = _a.children, initial = _a.initial, isPresent = _a.isPresent, onExitComplete = _a.onExitComplete, custom = _a.custom;
4811
+ var numPresenceChildren = React.useRef(0);
4812
+ var numExitComplete = React.useRef(0);
4813
+ var context = {
4814
+ initial: initial,
4815
+ isPresent: isPresent,
4816
+ custom: custom,
4817
+ onExitComplete: function () {
4818
+ numExitComplete.current++;
4819
+ var allComplete = numExitComplete.current >= numPresenceChildren.current;
4820
+ onExitComplete && allComplete && onExitComplete();
4821
+ },
4822
+ };
4823
+ var register = React.useMemo(function () {
4824
+ numExitComplete.current = 0;
4825
+ return function () {
4826
+ numPresenceChildren.current++;
4827
+ return function () { return numPresenceChildren.current--; };
4828
+ };
4829
+ }, [isPresent]);
4830
+ return (React.createElement(PresenceContext.Provider, { value: tslib.__assign(tslib.__assign({}, context), { register: register }) }, children));
4831
+ };
4832
+
4788
4833
  function getChildKey(child) {
4789
4834
  return child.key || "";
4790
4835
  }
@@ -4811,18 +4856,14 @@ function onlyElements(children) {
4811
4856
  return filtered;
4812
4857
  }
4813
4858
  /**
4814
- * The `AnimatePresence` component enables the use of the `exit` prop to animate components
4815
- * when they're removed from the component tree.
4816
- *
4817
- * When adding/removing more than a single child component, every component
4818
- * **must** be given a unique `key` prop.
4859
+ * `AnimatePresence` enables the animation of components that have been removed from the tree.
4819
4860
  *
4820
- * You can propagate exit animations throughout a tree by using variants.
4861
+ * When adding/removing more than a single child, every child **must** be given a unique `key` prop.
4821
4862
  *
4822
4863
  * @library
4823
4864
  *
4824
- * You can use any component(s) within `AnimatePresence`, but the first `Frame` in each should
4825
- * have an `exit` property defined.
4865
+ * Any `Frame` components that have an `exit` property defined will animate out when removed from
4866
+ * the tree.
4826
4867
  *
4827
4868
  * ```jsx
4828
4869
  * import { Frame, AnimatePresence } from 'framer'
@@ -4844,10 +4885,12 @@ function onlyElements(children) {
4844
4885
  * }
4845
4886
  * ```
4846
4887
  *
4888
+ * You can sequence exit animations throughout a tree using variants.
4889
+ *
4847
4890
  * @motion
4848
4891
  *
4849
- * You can use any component(s) within `AnimatePresence`, but the first `motion` component in each should
4850
- * have an `exit` property defined.
4892
+ * Any `motion` components that have an `exit` property defined will animate out when removed from
4893
+ * the tree.
4851
4894
  *
4852
4895
  * ```jsx
4853
4896
  * import { motion, AnimatePresence } from 'framer-motion'
@@ -4866,6 +4909,12 @@ function onlyElements(children) {
4866
4909
  * )
4867
4910
  * ```
4868
4911
  *
4912
+ * You can sequence exit animations throughout a tree using variants.
4913
+ *
4914
+ * If a child contains multiple `motion` components with `exit` props, it will only unmount the child
4915
+ * once all `motion` components have finished animating out. Likewise, any components using
4916
+ * `usePresence` all need to call `safeToRemove`.
4917
+ *
4869
4918
  * @public
4870
4919
  */
4871
4920
  var AnimatePresence = function (_a) {
@@ -4891,7 +4940,7 @@ var AnimatePresence = function (_a) {
4891
4940
  // we play onMount animations or not.
4892
4941
  if (isInitialRender.current) {
4893
4942
  isInitialRender.current = false;
4894
- return (React.createElement(React.Fragment, null, filteredChildren.map(function (child) { return (React.createElement(PresenceChild, { key: getChildKey(child), exitProps: initial ? undefined : { initial: false } }, child)); })));
4943
+ return (React.createElement(React.Fragment, null, filteredChildren.map(function (child) { return (React.createElement(PresenceChild, { key: getChildKey(child), isPresent: true, initial: initial ? undefined : false }, child)); })));
4895
4944
  }
4896
4945
  // If this is a subsequent render, deal with entering and exiting children
4897
4946
  var childrenToRender = tslib.__spreadArrays(filteredChildren);
@@ -4938,18 +4987,13 @@ var AnimatePresence = function (_a) {
4938
4987
  onExitComplete && onExitComplete();
4939
4988
  }
4940
4989
  };
4941
- var exitProps = {
4942
- custom: custom,
4943
- isExiting: true,
4944
- onExitComplete: onExit,
4945
- };
4946
- childrenToRender.splice(insertionIndex, 0, React.createElement(PresenceChild, { key: getChildKey(child), exitProps: exitProps }, child));
4990
+ childrenToRender.splice(insertionIndex, 0, React.createElement(PresenceChild, { key: getChildKey(child), isPresent: false, onExitComplete: onExit, custom: custom }, child));
4947
4991
  });
4948
4992
  // Add `MotionContext` even to children that don't need it to ensure we're rendering
4949
4993
  // the same tree between renders
4950
4994
  childrenToRender = childrenToRender.map(function (child) {
4951
4995
  var key = child.key;
4952
- return exiting.has(key) ? (child) : (React.createElement(PresenceChild, { key: getChildKey(child) }, child));
4996
+ return exiting.has(key) ? (child) : (React.createElement(PresenceChild, { key: getChildKey(child), isPresent: true }, child));
4953
4997
  });
4954
4998
  presentChildren.current = childrenToRender;
4955
4999
  if (process.env.NODE_ENV !== "production" &&
@@ -4962,36 +5006,6 @@ var AnimatePresence = function (_a) {
4962
5006
  : childrenToRender.map(function (child) { return React.cloneElement(child); })));
4963
5007
  };
4964
5008
 
4965
- /**
4966
- * When a component is the child of an `AnimatePresence` component, it has access to
4967
- * information about whether it's still present the React tree. `usePresence` can be
4968
- * used to access that data and perform operations before the component can be considered
4969
- * safe to remove.
4970
- *
4971
- * It returns two values. `isPresent` is a boolean that is `true` when the component
4972
- * is present within the React tree. It is `false` when it's been removed, but still visible.
4973
- *
4974
- * When `isPresent` is `false`, the `safeToRemove` callback can be used to tell `AnimatePresence`
4975
- * that it's safe to remove the component from the DOM, for instance after a animation has completed.
4976
- *
4977
- * ```jsx
4978
- * const [isPresent, safeToRemove] = usePresence()
4979
- *
4980
- * useEffect(() => {
4981
- * !isPresent setTimeout(safeToRemove, 1000)
4982
- * }, [isPresent])
4983
- * ```
4984
- *
4985
- * @public
4986
- */
4987
- function usePresence() {
4988
- var exitProps = React.useContext(MotionContext).exitProps;
4989
- if (!exitProps)
4990
- return [true];
4991
- var isExiting = exitProps.isExiting, onExitComplete = exitProps.onExitComplete;
4992
- return isExiting && onExitComplete ? [false, onExitComplete] : [true];
4993
- }
4994
-
4995
5009
  // Does this device prefer reduced motion? Returns `null` server-side.
4996
5010
  var prefersReducedMotion = motionValue(null);
4997
5011
  if (typeof window !== "undefined") {
@@ -17,18 +17,14 @@ import { SpringProps } from 'popmotion';
17
17
  import { SVGAttributes } from 'react';
18
18
 
19
19
  /**
20
- * The `AnimatePresence` component enables the use of the `exit` prop to animate components
21
- * when they're removed from the component tree.
20
+ * `AnimatePresence` enables the animation of components that have been removed from the tree.
22
21
  *
23
- * When adding/removing more than a single child component, every component
24
- * **must** be given a unique `key` prop.
25
- *
26
- * You can propagate exit animations throughout a tree by using variants.
22
+ * When adding/removing more than a single child, every child **must** be given a unique `key` prop.
27
23
  *
28
24
  * @library
29
25
  *
30
- * You can use any component(s) within `AnimatePresence`, but the first `Frame` in each should
31
- * have an `exit` property defined.
26
+ * Any `Frame` components that have an `exit` property defined will animate out when removed from
27
+ * the tree.
32
28
  *
33
29
  * ```jsx
34
30
  * import { Frame, AnimatePresence } from 'framer'
@@ -50,10 +46,12 @@ import { SVGAttributes } from 'react';
50
46
  * }
51
47
  * ```
52
48
  *
49
+ * You can sequence exit animations throughout a tree using variants.
50
+ *
53
51
  * @motion
54
52
  *
55
- * You can use any component(s) within `AnimatePresence`, but the first `motion` component in each should
56
- * have an `exit` property defined.
53
+ * Any `motion` components that have an `exit` property defined will animate out when removed from
54
+ * the tree.
57
55
  *
58
56
  * ```jsx
59
57
  * import { motion, AnimatePresence } from 'framer-motion'
@@ -72,6 +70,12 @@ import { SVGAttributes } from 'react';
72
70
  * )
73
71
  * ```
74
72
  *
73
+ * You can sequence exit animations throughout a tree using variants.
74
+ *
75
+ * If a child contains multiple `motion` components with `exit` props, it will only unmount the child
76
+ * once all `motion` components have finished animating out. Likewise, any components using
77
+ * `usePresence` all need to call `safeToRemove`.
78
+ *
75
79
  * @public
76
80
  */
77
81
  export declare const AnimatePresence: FunctionComponent<AnimatePresenceProps>;
@@ -1406,13 +1410,6 @@ export declare interface EventInfo {
1406
1410
  point: Point;
1407
1411
  }
1408
1412
 
1409
- declare interface ExitProps {
1410
- initial?: false | VariantLabels;
1411
- isExiting?: boolean;
1412
- onExitComplete?: () => void;
1413
- custom?: any;
1414
- }
1415
-
1416
1413
  /**
1417
1414
  * @public
1418
1415
  */
@@ -2417,7 +2414,6 @@ declare interface MotionContextProps {
2417
2414
  animate?: VariantLabels;
2418
2415
  static?: boolean;
2419
2416
  hasMounted?: RefObject<boolean>;
2420
- exitProps?: ExitProps;
2421
2417
  isReducedMotion?: boolean | undefined;
2422
2418
  }
2423
2419
 
@@ -4944,25 +4940,26 @@ export declare function useMotionValue<T>(initial: T): MotionValue<T>;
4944
4940
  export declare function usePanGesture({ onPan, onPanStart, onPanEnd, onPanSessionStart }: PanHandlers, ref: RefObject<Element>): void;
4945
4941
 
4946
4942
  /**
4947
- * When a component is the child of an `AnimatePresence` component, it has access to
4948
- * information about whether it's still present the React tree. `usePresence` can be
4949
- * used to access that data and perform operations before the component can be considered
4950
- * safe to remove.
4943
+ * When a component is the child of `AnimatePresence`, it can use `usePresence`
4944
+ * to access information about whether it's still present in the React tree.
4951
4945
  *
4952
- * It returns two values. `isPresent` is a boolean that is `true` when the component
4953
- * is present within the React tree. It is `false` when it's been removed, but still visible.
4946
+ * ```jsx
4947
+ * import { usePresence } from "framer-motion"
4954
4948
  *
4955
- * When `isPresent` is `false`, the `safeToRemove` callback can be used to tell `AnimatePresence`
4956
- * that it's safe to remove the component from the DOM, for instance after a animation has completed.
4949
+ * export const Component = () => {
4950
+ * const [isPresent, safeToRemove] = usePresence()
4957
4951
  *
4958
- * ```jsx
4959
- * const [isPresent, safeToRemove] = usePresence()
4952
+ * useEffect(() => {
4953
+ * !isPresent setTimeout(safeToRemove, 1000)
4954
+ * }, [isPresent])
4960
4955
  *
4961
- * useEffect(() => {
4962
- * !isPresent setTimeout(safeToRemove, 1000)
4963
- * }, [isPresent])
4956
+ * return <div />
4957
+ * }
4964
4958
  * ```
4965
4959
  *
4960
+ * If `isPresent` is `false`, it means that a component has been removed the tree, but
4961
+ * `AnimatePresence` won't really remove it until `safeToRemove` has been called.
4962
+ *
4966
4963
  * @public
4967
4964
  */
4968
4965
  export declare function usePresence(): Present | NotPresent;