use-motion-ref.mjs 1.79 KB
"use client";
import { useRef, useInsertionEffect, useCallback } from 'react';

/**
 * Creates a ref function that, when called, hydrates the provided
 * external ref and VisualElement.
 */
function useMotionRef(visualState, visualElement, externalRef) {
    /**
     * Store externalRef in a ref to avoid including it in the useCallback
     * dependency array. Including externalRef in dependencies causes issues
     * with libraries like Radix UI that create new callback refs on each render
     * when using asChild - this would cause the callback to be recreated,
     * triggering element remounts and breaking AnimatePresence exit animations.
     */
    const externalRefContainer = useRef(externalRef);
    useInsertionEffect(() => {
        externalRefContainer.current = externalRef;
    });
    // Store cleanup function returned by callback refs (React 19 feature)
    const refCleanup = useRef(null);
    return useCallback((instance) => {
        if (instance) {
            visualState.onMount?.(instance);
        }
        const ref = externalRefContainer.current;
        if (typeof ref === "function") {
            if (instance) {
                const cleanup = ref(instance);
                if (typeof cleanup === "function") {
                    refCleanup.current = cleanup;
                }
            }
            else if (refCleanup.current) {
                refCleanup.current();
                refCleanup.current = null;
            }
            else {
                ref(instance);
            }
        }
        else if (ref) {
            ref.current = instance;
        }
        if (visualElement) {
            instance ? visualElement.mount(instance) : visualElement.unmount();
        }
    }, [visualElement]);
}

export { useMotionRef };
//# sourceMappingURL=use-motion-ref.mjs.map