framer-motion 12.24.9 → 12.24.10

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.
@@ -1,64 +1,51 @@
1
1
  "use client";
2
- import { useRef, useCallback } from 'react';
3
- import { isRefObject } from '../../utils/is-ref-object.mjs';
2
+ import { useRef, useInsertionEffect, useCallback } from 'react';
4
3
 
5
- /**
6
- * Set a given ref to a given value
7
- * This utility takes care of different types of refs: callback refs and RefObject(s)
8
- * Returns a cleanup function if the ref callback returns one (React 19 feature)
9
- */
10
- function setRef(ref, value) {
11
- if (typeof ref === "function") {
12
- return ref(value);
13
- }
14
- else if (isRefObject(ref)) {
15
- ref.current = value;
16
- }
17
- }
18
4
  /**
19
5
  * Creates a ref function that, when called, hydrates the provided
20
6
  * external ref and VisualElement.
21
7
  */
22
8
  function useMotionRef(visualState, visualElement, externalRef) {
23
- // Store the cleanup function from external ref if it returns one
24
- const externalRefCleanupRef = useRef(null);
9
+ /**
10
+ * Store externalRef in a ref to avoid including it in the useCallback
11
+ * dependency array. Including externalRef in dependencies causes issues
12
+ * with libraries like Radix UI that create new callback refs on each render
13
+ * when using asChild - this would cause the callback to be recreated,
14
+ * triggering element remounts and breaking AnimatePresence exit animations.
15
+ */
16
+ const externalRefContainer = useRef(externalRef);
17
+ useInsertionEffect(() => {
18
+ externalRefContainer.current = externalRef;
19
+ });
20
+ // Store cleanup function returned by callback refs (React 19 feature)
21
+ const refCleanup = useRef(null);
25
22
  return useCallback((instance) => {
26
23
  if (instance) {
27
- visualState.onMount && visualState.onMount(instance);
24
+ visualState.onMount?.(instance);
28
25
  }
29
26
  if (visualElement) {
30
- if (instance) {
31
- visualElement.mount(instance);
32
- }
33
- else {
34
- visualElement.unmount();
35
- }
27
+ instance ? visualElement.mount(instance) : visualElement.unmount();
36
28
  }
37
- if (externalRef) {
29
+ const ref = externalRefContainer.current;
30
+ if (typeof ref === "function") {
38
31
  if (instance) {
39
- // Mount: call the external ref and store any cleanup function
40
- const cleanup = setRef(externalRef, instance);
32
+ const cleanup = ref(instance);
41
33
  if (typeof cleanup === "function") {
42
- externalRefCleanupRef.current = cleanup;
34
+ refCleanup.current = cleanup;
43
35
  }
44
36
  }
37
+ else if (refCleanup.current) {
38
+ refCleanup.current();
39
+ refCleanup.current = null;
40
+ }
45
41
  else {
46
- // Unmount: call stored cleanup function if available, otherwise call ref with null
47
- if (externalRefCleanupRef.current) {
48
- externalRefCleanupRef.current();
49
- externalRefCleanupRef.current = null;
50
- }
51
- else {
52
- // Fallback to React <19 behavior for refs that don't return cleanup
53
- setRef(externalRef, instance);
54
- }
42
+ ref(instance);
55
43
  }
56
44
  }
57
- },
58
- /**
59
- * Include all dependencies to ensure the callback updates correctly
60
- */
61
- [visualElement, visualState, externalRef]);
45
+ else if (ref) {
46
+ ref.current = instance;
47
+ }
48
+ }, [visualElement]);
62
49
  }
63
50
 
64
51
  export { useMotionRef };
@@ -1 +1 @@
1
- {"version":3,"file":"use-motion-ref.mjs","sources":["../../../../src/motion/utils/use-motion-ref.ts"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { useCallback, useRef } from \"react\"\nimport type { VisualElement } from \"../../render/VisualElement\"\nimport { isRefObject } from \"../../utils/is-ref-object\"\nimport { VisualState } from \"./use-visual-state\"\n\n/**\n * Set a given ref to a given value\n * This utility takes care of different types of refs: callback refs and RefObject(s)\n * Returns a cleanup function if the ref callback returns one (React 19 feature)\n */\nfunction setRef<T>(ref: React.Ref<T>, value: T): void | (() => void) {\n if (typeof ref === \"function\") {\n return ref(value)\n } else if (isRefObject(ref)) {\n ;(ref as any).current = value\n }\n}\n\n/**\n * Creates a ref function that, when called, hydrates the provided\n * external ref and VisualElement.\n */\nexport function useMotionRef<Instance, RenderState>(\n visualState: VisualState<Instance, RenderState>,\n visualElement?: VisualElement<Instance> | null,\n externalRef?: React.Ref<Instance>\n): React.Ref<Instance> {\n // Store the cleanup function from external ref if it returns one\n const externalRefCleanupRef = useRef<(() => void) | null>(null)\n\n return useCallback(\n (instance: Instance) => {\n if (instance) {\n visualState.onMount && visualState.onMount(instance)\n }\n\n if (visualElement) {\n if (instance) {\n visualElement.mount(instance)\n } else {\n visualElement.unmount()\n }\n }\n\n if (externalRef) {\n if (instance) {\n // Mount: call the external ref and store any cleanup function\n const cleanup = setRef(externalRef, instance)\n if (typeof cleanup === \"function\") {\n externalRefCleanupRef.current = cleanup\n }\n } else {\n // Unmount: call stored cleanup function if available, otherwise call ref with null\n if (externalRefCleanupRef.current) {\n externalRefCleanupRef.current()\n externalRefCleanupRef.current = null\n } else {\n // Fallback to React <19 behavior for refs that don't return cleanup\n setRef(externalRef, instance)\n }\n }\n }\n },\n /**\n * Include all dependencies to ensure the callback updates correctly\n */\n [visualElement, visualState, externalRef]\n )\n}\n"],"names":[],"mappings":";;;;AAQA;;;;AAIG;AACH;AACI;AACI;;AACG;AACD;;AAEV;AAEA;;;AAGG;;;AAOC;AAEA;;;;;;AAQgB;;;;;;;;;;AAUA;AACI;;;;;AAIJ;;AAEI;;;;AAGA;;;;;AAKhB;;AAEG;AACH;AAER;;"}
1
+ {"version":3,"file":"use-motion-ref.mjs","sources":["../../../../src/motion/utils/use-motion-ref.ts"],"sourcesContent":["\"use client\"\n\nimport * as React from \"react\"\nimport { useCallback, useInsertionEffect, useRef } from \"react\"\nimport type { VisualElement } from \"../../render/VisualElement\"\nimport { VisualState } from \"./use-visual-state\"\n\n/**\n * Creates a ref function that, when called, hydrates the provided\n * external ref and VisualElement.\n */\nexport function useMotionRef<Instance, RenderState>(\n visualState: VisualState<Instance, RenderState>,\n visualElement?: VisualElement<Instance> | null,\n externalRef?: React.Ref<Instance>\n): React.Ref<Instance> {\n /**\n * Store externalRef in a ref to avoid including it in the useCallback\n * dependency array. Including externalRef in dependencies causes issues\n * with libraries like Radix UI that create new callback refs on each render\n * when using asChild - this would cause the callback to be recreated,\n * triggering element remounts and breaking AnimatePresence exit animations.\n */\n const externalRefContainer = useRef(externalRef)\n useInsertionEffect(() => {\n externalRefContainer.current = externalRef\n })\n\n // Store cleanup function returned by callback refs (React 19 feature)\n const refCleanup = useRef<(() => void) | null>(null)\n\n return useCallback(\n (instance: Instance) => {\n if (instance) {\n visualState.onMount?.(instance)\n }\n\n if (visualElement) {\n instance ? visualElement.mount(instance) : visualElement.unmount()\n }\n\n const ref = externalRefContainer.current\n if (typeof ref === \"function\") {\n if (instance) {\n const cleanup = ref(instance)\n if (typeof cleanup === \"function\") {\n refCleanup.current = cleanup\n }\n } else if (refCleanup.current) {\n refCleanup.current()\n refCleanup.current = null\n } else {\n ref(instance)\n }\n } else if (ref) {\n ;(ref as React.MutableRefObject<Instance>).current = instance\n }\n },\n [visualElement]\n )\n}\n"],"names":[],"mappings":";;;AAOA;;;AAGG;;AAMC;;;;;;AAMG;AACH;;AAEI;AACJ;;AAGA;AAEA;;AAGY;;;AAIA;;AAGJ;AACA;;AAEQ;AACA;AACI;;;AAED;;AAEH;;;;;;;AAKF;;AAEV;AAGR;;"}
@@ -5137,7 +5137,7 @@
5137
5137
  * Set a given ref to a given value
5138
5138
  * This utility takes care of different types of refs: callback refs and RefObject(s)
5139
5139
  */
5140
- function setRef$1(ref, value) {
5140
+ function setRef(ref, value) {
5141
5141
  if (typeof ref === "function") {
5142
5142
  return ref(value);
5143
5143
  }
@@ -5153,7 +5153,7 @@
5153
5153
  return (node) => {
5154
5154
  let hasCleanup = false;
5155
5155
  const cleanups = refs.map((ref) => {
5156
- const cleanup = setRef$1(ref, node);
5156
+ const cleanup = setRef(ref, node);
5157
5157
  if (!hasCleanup && typeof cleanup === "function") {
5158
5158
  hasCleanup = true;
5159
5159
  }
@@ -5171,7 +5171,7 @@
5171
5171
  cleanup();
5172
5172
  }
5173
5173
  else {
5174
- setRef$1(refs[i], null);
5174
+ setRef(refs[i], null);
5175
5175
  }
5176
5176
  }
5177
5177
  };
@@ -9748,69 +9748,51 @@
9748
9748
 
9749
9749
  const motionComponentSymbol = Symbol.for("motionComponentSymbol");
9750
9750
 
9751
- function isRefObject(ref) {
9752
- return (ref &&
9753
- typeof ref === "object" &&
9754
- Object.prototype.hasOwnProperty.call(ref, "current"));
9755
- }
9756
-
9757
- /**
9758
- * Set a given ref to a given value
9759
- * This utility takes care of different types of refs: callback refs and RefObject(s)
9760
- * Returns a cleanup function if the ref callback returns one (React 19 feature)
9761
- */
9762
- function setRef(ref, value) {
9763
- if (typeof ref === "function") {
9764
- return ref(value);
9765
- }
9766
- else if (isRefObject(ref)) {
9767
- ref.current = value;
9768
- }
9769
- }
9770
9751
  /**
9771
9752
  * Creates a ref function that, when called, hydrates the provided
9772
9753
  * external ref and VisualElement.
9773
9754
  */
9774
9755
  function useMotionRef(visualState, visualElement, externalRef) {
9775
- // Store the cleanup function from external ref if it returns one
9776
- const externalRefCleanupRef = React$1.useRef(null);
9756
+ /**
9757
+ * Store externalRef in a ref to avoid including it in the useCallback
9758
+ * dependency array. Including externalRef in dependencies causes issues
9759
+ * with libraries like Radix UI that create new callback refs on each render
9760
+ * when using asChild - this would cause the callback to be recreated,
9761
+ * triggering element remounts and breaking AnimatePresence exit animations.
9762
+ */
9763
+ const externalRefContainer = React$1.useRef(externalRef);
9764
+ React$1.useInsertionEffect(() => {
9765
+ externalRefContainer.current = externalRef;
9766
+ });
9767
+ // Store cleanup function returned by callback refs (React 19 feature)
9768
+ const refCleanup = React$1.useRef(null);
9777
9769
  return React$1.useCallback((instance) => {
9778
9770
  if (instance) {
9779
- visualState.onMount && visualState.onMount(instance);
9771
+ visualState.onMount?.(instance);
9780
9772
  }
9781
9773
  if (visualElement) {
9782
- if (instance) {
9783
- visualElement.mount(instance);
9784
- }
9785
- else {
9786
- visualElement.unmount();
9787
- }
9774
+ instance ? visualElement.mount(instance) : visualElement.unmount();
9788
9775
  }
9789
- if (externalRef) {
9776
+ const ref = externalRefContainer.current;
9777
+ if (typeof ref === "function") {
9790
9778
  if (instance) {
9791
- // Mount: call the external ref and store any cleanup function
9792
- const cleanup = setRef(externalRef, instance);
9779
+ const cleanup = ref(instance);
9793
9780
  if (typeof cleanup === "function") {
9794
- externalRefCleanupRef.current = cleanup;
9781
+ refCleanup.current = cleanup;
9795
9782
  }
9796
9783
  }
9784
+ else if (refCleanup.current) {
9785
+ refCleanup.current();
9786
+ refCleanup.current = null;
9787
+ }
9797
9788
  else {
9798
- // Unmount: call stored cleanup function if available, otherwise call ref with null
9799
- if (externalRefCleanupRef.current) {
9800
- externalRefCleanupRef.current();
9801
- externalRefCleanupRef.current = null;
9802
- }
9803
- else {
9804
- // Fallback to React <19 behavior for refs that don't return cleanup
9805
- setRef(externalRef, instance);
9806
- }
9789
+ ref(instance);
9807
9790
  }
9808
9791
  }
9809
- },
9810
- /**
9811
- * Include all dependencies to ensure the callback updates correctly
9812
- */
9813
- [visualElement, visualState, externalRef]);
9792
+ else if (ref) {
9793
+ ref.current = instance;
9794
+ }
9795
+ }, [visualElement]);
9814
9796
  }
9815
9797
 
9816
9798
  /**
@@ -9818,6 +9800,12 @@
9818
9800
  */
9819
9801
  const SwitchLayoutGroupContext = React$1.createContext({});
9820
9802
 
9803
+ function isRefObject(ref) {
9804
+ return (ref &&
9805
+ typeof ref === "object" &&
9806
+ Object.prototype.hasOwnProperty.call(ref, "current"));
9807
+ }
9808
+
9821
9809
  function useVisualElement(Component, visualState, props, createVisualElement, ProjectionNodeConstructor, isSVG) {
9822
9810
  const { visualElement: parent } = React$1.useContext(MotionContext);
9823
9811
  const lazyContext = React$1.useContext(LazyContext);