framer-motion 12.24.6 → 12.24.7
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.
|
@@ -67,6 +67,10 @@ const AnimatePresence = ({ children, custom, initial = true, onExitComplete, pre
|
|
|
67
67
|
* Track which exiting children have finished animating out.
|
|
68
68
|
*/
|
|
69
69
|
const exitComplete = useConstant(() => new Map());
|
|
70
|
+
/**
|
|
71
|
+
* Track which components are currently processing exit to prevent duplicate processing.
|
|
72
|
+
*/
|
|
73
|
+
const exitingComponents = useRef(new Set());
|
|
70
74
|
/**
|
|
71
75
|
* Save children to render as React state. To ensure this component is concurrent-safe,
|
|
72
76
|
* we check for exiting children via an effect.
|
|
@@ -88,6 +92,7 @@ const AnimatePresence = ({ children, custom, initial = true, onExitComplete, pre
|
|
|
88
92
|
}
|
|
89
93
|
else {
|
|
90
94
|
exitComplete.delete(key);
|
|
95
|
+
exitingComponents.current.delete(key);
|
|
91
96
|
}
|
|
92
97
|
}
|
|
93
98
|
}, [renderedChildren, presentKeys.length, presentKeys.join("-")]);
|
|
@@ -139,6 +144,10 @@ const AnimatePresence = ({ children, custom, initial = true, onExitComplete, pre
|
|
|
139
144
|
: presentChildren === renderedChildren ||
|
|
140
145
|
presentKeys.includes(key);
|
|
141
146
|
const onExit = () => {
|
|
147
|
+
if (exitingComponents.current.has(key)) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
exitingComponents.current.add(key);
|
|
142
151
|
if (exitComplete.has(key)) {
|
|
143
152
|
exitComplete.set(key, true);
|
|
144
153
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","sources":["../../../../src/components/AnimatePresence/index.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { useContext, useMemo, useRef, useState } from \"react\"\nimport { LayoutGroupContext } from \"../../context/LayoutGroupContext\"\nimport { useConstant } from \"../../utils/use-constant\"\nimport { useIsomorphicLayoutEffect } from \"../../utils/use-isomorphic-effect\"\nimport { PresenceChild } from \"./PresenceChild\"\nimport { AnimatePresenceProps } from \"./types\"\nimport { usePresence } from \"./use-presence\"\nimport { ComponentKey, getChildKey, onlyElements } from \"./utils\"\n\n/**\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 * Any `motion` components that have an `exit` property defined will animate out when removed from\n * the tree.\n *\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\n * once all `motion` components have finished animating out. Likewise, any components using\n * `usePresence` all need to call `safeToRemove`.\n *\n * @public\n */\nexport const AnimatePresence = ({\n children,\n custom,\n initial = true,\n onExitComplete,\n presenceAffectsLayout = true,\n mode = \"sync\",\n propagate = false,\n anchorX = \"left\",\n root\n}: React.PropsWithChildren<AnimatePresenceProps>) => {\n const [isParentPresent, safeToRemove] = usePresence(propagate)\n\n /**\n * Filter any children that aren't ReactElements. We can only track components\n * between renders with a props.key.\n */\n const presentChildren = useMemo(() => onlyElements(children), [children])\n\n /**\n * Track the keys of the currently rendered children. This is used to\n * determine which children are exiting.\n */\n const presentKeys =\n propagate && !isParentPresent ? [] : presentChildren.map(getChildKey)\n\n /**\n * If `initial={false}` we only want to pass this to components in the first render.\n */\n const isInitialRender = useRef(true)\n\n /**\n * A ref containing the currently present children. When all exit animations\n * are complete, we use this to re-render the component with the latest children\n * *committed* rather than the latest children *rendered*.\n */\n const pendingPresentChildren = useRef(presentChildren)\n\n /**\n * Track which exiting children have finished animating out.\n */\n const exitComplete = useConstant(() => new Map<ComponentKey, boolean>())\n\n /**\n * Save children to render as React state. To ensure this component is concurrent-safe,\n * we check for exiting children via an effect.\n */\n const [diffedChildren, setDiffedChildren] = useState(presentChildren)\n const [renderedChildren, setRenderedChildren] = useState(presentChildren)\n\n useIsomorphicLayoutEffect(() => {\n isInitialRender.current = false\n pendingPresentChildren.current = presentChildren\n\n /**\n * Update complete status of exiting children.\n */\n for (let i = 0; i < renderedChildren.length; i++) {\n const key = getChildKey(renderedChildren[i])\n\n if (!presentKeys.includes(key)) {\n if (exitComplete.get(key) !== true) {\n exitComplete.set(key, false)\n }\n } else {\n exitComplete.delete(key)\n }\n }\n }, [renderedChildren, presentKeys.length, presentKeys.join(\"-\")])\n\n const exitingChildren: any[] = []\n\n if (presentChildren !== diffedChildren) {\n let nextChildren = [...presentChildren]\n\n /**\n * Loop through all the currently rendered components and decide which\n * are exiting.\n */\n for (let i = 0; i < renderedChildren.length; i++) {\n const child = renderedChildren[i]\n const key = getChildKey(child)\n\n if (!presentKeys.includes(key)) {\n nextChildren.splice(i, 0, child)\n exitingChildren.push(child)\n }\n }\n\n /**\n * If we're in \"wait\" mode, and we have exiting children, we want to\n * only render these until they've all exited.\n */\n if (mode === \"wait\" && exitingChildren.length) {\n nextChildren = exitingChildren\n }\n\n setRenderedChildren(onlyElements(nextChildren))\n setDiffedChildren(presentChildren)\n\n /**\n * Early return to ensure once we've set state with the latest diffed\n * children, we can immediately re-render.\n */\n return null\n }\n\n if (\n process.env.NODE_ENV !== \"production\" &&\n mode === \"wait\" &&\n renderedChildren.length > 1\n ) {\n console.warn(\n `You're attempting to animate multiple children within AnimatePresence, but its mode is set to \"wait\". This will lead to odd visual behaviour.`\n )\n }\n\n /**\n * If we've been provided a forceRender function by the LayoutGroupContext,\n * we can use it to force a re-render amongst all surrounding components once\n * all components have finished animating out.\n */\n const { forceRender } = useContext(LayoutGroupContext)\n\n return (\n <>\n {renderedChildren.map((child) => {\n const key = getChildKey(child)\n\n const isPresent =\n propagate && !isParentPresent\n ? false\n : presentChildren === renderedChildren ||\n presentKeys.includes(key)\n\n const onExit = () => {\n if (exitComplete.has(key)) {\n exitComplete.set(key, true)\n } else {\n return\n }\n\n let isEveryExitComplete = true\n exitComplete.forEach((isExitComplete) => {\n if (!isExitComplete) isEveryExitComplete = false\n })\n\n if (isEveryExitComplete) {\n forceRender?.()\n setRenderedChildren(pendingPresentChildren.current)\n\n propagate && safeToRemove?.()\n\n onExitComplete && onExitComplete()\n }\n }\n\n return (\n <PresenceChild\n key={key}\n isPresent={isPresent}\n initial={\n !isInitialRender.current || initial\n ? undefined\n : false\n }\n custom={custom}\n presenceAffectsLayout={presenceAffectsLayout}\n mode={mode}\n root={root}\n onExitComplete={isPresent ? undefined : onExit}\n anchorX={anchorX}\n >\n {child}\n </PresenceChild>\n )\n })}\n </>\n )\n}\n"],"names":[],"mappings":";;;;;;;;;;AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCG;AACI;;AAaH;;;AAGG;AACH;AAEA;;;AAGG;AACH;AAGA;;AAEG;AACH;AAEA;;;;AAIG;AACH;AAEA;;AAEG;;AAGH;;;AAGG;;;;AAKC;AACA;AAEA;;AAEG;AACH;;;;AAKY;;;;AAGJ;;;AAGZ;;AAIA;AACI;AAEA;;;AAGG;AACH;AACI;AACA;;;AAII;;;AAIR;;;AAGG;;;;AAKH;;AAGA;;;AAGG;AACH;;AAGJ;AAEI;AACA;AAEA;;AAKJ;;;;AAIG;;;AAMS;AAEA;AAEQ;;AAEE
|
|
1
|
+
{"version":3,"file":"index.mjs","sources":["../../../../src/components/AnimatePresence/index.tsx"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { useContext, useMemo, useRef, useState } from \"react\"\nimport { LayoutGroupContext } from \"../../context/LayoutGroupContext\"\nimport { useConstant } from \"../../utils/use-constant\"\nimport { useIsomorphicLayoutEffect } from \"../../utils/use-isomorphic-effect\"\nimport { PresenceChild } from \"./PresenceChild\"\nimport { AnimatePresenceProps } from \"./types\"\nimport { usePresence } from \"./use-presence\"\nimport { ComponentKey, getChildKey, onlyElements } from \"./utils\"\n\n/**\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 * Any `motion` components that have an `exit` property defined will animate out when removed from\n * the tree.\n *\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\n * once all `motion` components have finished animating out. Likewise, any components using\n * `usePresence` all need to call `safeToRemove`.\n *\n * @public\n */\nexport const AnimatePresence = ({\n children,\n custom,\n initial = true,\n onExitComplete,\n presenceAffectsLayout = true,\n mode = \"sync\",\n propagate = false,\n anchorX = \"left\",\n root\n}: React.PropsWithChildren<AnimatePresenceProps>) => {\n const [isParentPresent, safeToRemove] = usePresence(propagate)\n\n /**\n * Filter any children that aren't ReactElements. We can only track components\n * between renders with a props.key.\n */\n const presentChildren = useMemo(() => onlyElements(children), [children])\n\n /**\n * Track the keys of the currently rendered children. This is used to\n * determine which children are exiting.\n */\n const presentKeys =\n propagate && !isParentPresent ? [] : presentChildren.map(getChildKey)\n\n /**\n * If `initial={false}` we only want to pass this to components in the first render.\n */\n const isInitialRender = useRef(true)\n\n /**\n * A ref containing the currently present children. When all exit animations\n * are complete, we use this to re-render the component with the latest children\n * *committed* rather than the latest children *rendered*.\n */\n const pendingPresentChildren = useRef(presentChildren)\n\n /**\n * Track which exiting children have finished animating out.\n */\n const exitComplete = useConstant(() => new Map<ComponentKey, boolean>())\n\n /**\n * Track which components are currently processing exit to prevent duplicate processing.\n */\n const exitingComponents = useRef(new Set<ComponentKey>())\n\n /**\n * Save children to render as React state. To ensure this component is concurrent-safe,\n * we check for exiting children via an effect.\n */\n const [diffedChildren, setDiffedChildren] = useState(presentChildren)\n const [renderedChildren, setRenderedChildren] = useState(presentChildren)\n\n useIsomorphicLayoutEffect(() => {\n isInitialRender.current = false\n pendingPresentChildren.current = presentChildren\n\n /**\n * Update complete status of exiting children.\n */\n for (let i = 0; i < renderedChildren.length; i++) {\n const key = getChildKey(renderedChildren[i])\n\n if (!presentKeys.includes(key)) {\n if (exitComplete.get(key) !== true) {\n exitComplete.set(key, false)\n }\n } else {\n exitComplete.delete(key)\n exitingComponents.current.delete(key)\n }\n }\n }, [renderedChildren, presentKeys.length, presentKeys.join(\"-\")])\n\n const exitingChildren: any[] = []\n\n if (presentChildren !== diffedChildren) {\n let nextChildren = [...presentChildren]\n\n /**\n * Loop through all the currently rendered components and decide which\n * are exiting.\n */\n for (let i = 0; i < renderedChildren.length; i++) {\n const child = renderedChildren[i]\n const key = getChildKey(child)\n\n if (!presentKeys.includes(key)) {\n nextChildren.splice(i, 0, child)\n exitingChildren.push(child)\n }\n }\n\n /**\n * If we're in \"wait\" mode, and we have exiting children, we want to\n * only render these until they've all exited.\n */\n if (mode === \"wait\" && exitingChildren.length) {\n nextChildren = exitingChildren\n }\n\n setRenderedChildren(onlyElements(nextChildren))\n setDiffedChildren(presentChildren)\n\n /**\n * Early return to ensure once we've set state with the latest diffed\n * children, we can immediately re-render.\n */\n return null\n }\n\n if (\n process.env.NODE_ENV !== \"production\" &&\n mode === \"wait\" &&\n renderedChildren.length > 1\n ) {\n console.warn(\n `You're attempting to animate multiple children within AnimatePresence, but its mode is set to \"wait\". This will lead to odd visual behaviour.`\n )\n }\n\n /**\n * If we've been provided a forceRender function by the LayoutGroupContext,\n * we can use it to force a re-render amongst all surrounding components once\n * all components have finished animating out.\n */\n const { forceRender } = useContext(LayoutGroupContext)\n\n return (\n <>\n {renderedChildren.map((child) => {\n const key = getChildKey(child)\n\n const isPresent =\n propagate && !isParentPresent\n ? false\n : presentChildren === renderedChildren ||\n presentKeys.includes(key)\n\n const onExit = () => {\n if (exitingComponents.current.has(key)) {\n return\n }\n exitingComponents.current.add(key)\n\n if (exitComplete.has(key)) {\n exitComplete.set(key, true)\n } else {\n return\n }\n\n let isEveryExitComplete = true\n exitComplete.forEach((isExitComplete) => {\n if (!isExitComplete) isEveryExitComplete = false\n })\n\n if (isEveryExitComplete) {\n forceRender?.()\n setRenderedChildren(pendingPresentChildren.current)\n\n propagate && safeToRemove?.()\n\n onExitComplete && onExitComplete()\n }\n }\n\n return (\n <PresenceChild\n key={key}\n isPresent={isPresent}\n initial={\n !isInitialRender.current || initial\n ? undefined\n : false\n }\n custom={custom}\n presenceAffectsLayout={presenceAffectsLayout}\n mode={mode}\n root={root}\n onExitComplete={isPresent ? undefined : onExit}\n anchorX={anchorX}\n >\n {child}\n </PresenceChild>\n )\n })}\n </>\n )\n}\n"],"names":[],"mappings":";;;;;;;;;;AAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgCG;AACI;;AAaH;;;AAGG;AACH;AAEA;;;AAGG;AACH;AAGA;;AAEG;AACH;AAEA;;;;AAIG;AACH;AAEA;;AAEG;;AAGH;;AAEG;;AAGH;;;AAGG;;;;AAKC;AACA;AAEA;;AAEG;AACH;;;;AAKY;;;;AAGJ;AACA;;;AAGZ;;AAIA;AACI;AAEA;;;AAGG;AACH;AACI;AACA;;;AAII;;;AAIR;;;AAGG;;;;AAKH;;AAGA;;;AAGG;AACH;;AAGJ;AAEI;AACA;AAEA;;AAKJ;;;;AAIG;;;AAMS;AAEA;AAEQ;;AAEE;;;;;AAMN;AAEA;AACI;;;;;;AAMJ;AACI;;AACJ;;;AAII;AAEA;;;AAIR;AAEA;AAMgB;AACA;;AAehC;;"}
|
|
@@ -5436,6 +5436,10 @@
|
|
|
5436
5436
|
* Track which exiting children have finished animating out.
|
|
5437
5437
|
*/
|
|
5438
5438
|
const exitComplete = useConstant(() => new Map());
|
|
5439
|
+
/**
|
|
5440
|
+
* Track which components are currently processing exit to prevent duplicate processing.
|
|
5441
|
+
*/
|
|
5442
|
+
const exitingComponents = React$1.useRef(new Set());
|
|
5439
5443
|
/**
|
|
5440
5444
|
* Save children to render as React state. To ensure this component is concurrent-safe,
|
|
5441
5445
|
* we check for exiting children via an effect.
|
|
@@ -5457,6 +5461,7 @@
|
|
|
5457
5461
|
}
|
|
5458
5462
|
else {
|
|
5459
5463
|
exitComplete.delete(key);
|
|
5464
|
+
exitingComponents.current.delete(key);
|
|
5460
5465
|
}
|
|
5461
5466
|
}
|
|
5462
5467
|
}, [renderedChildren, presentKeys.length, presentKeys.join("-")]);
|
|
@@ -5507,6 +5512,10 @@
|
|
|
5507
5512
|
: presentChildren === renderedChildren ||
|
|
5508
5513
|
presentKeys.includes(key);
|
|
5509
5514
|
const onExit = () => {
|
|
5515
|
+
if (exitingComponents.current.has(key)) {
|
|
5516
|
+
return;
|
|
5517
|
+
}
|
|
5518
|
+
exitingComponents.current.add(key);
|
|
5510
5519
|
if (exitComplete.has(key)) {
|
|
5511
5520
|
exitComplete.set(key, true);
|
|
5512
5521
|
}
|