"use client";
import { useEffect, useRef } from "react";
import { TRANSITION_CONFIG } from "../transition/config.js";
import { useEnsuredRef } from "../useEnsuredRef.js";
import { focusElementWithin, getFocusableElements } from "./utils.js";
const noop = ()=>{
// do nothing
};
/**
 * This hook is mostly for internal use only for dialog accessibility behavior
 * to prevent the focus from moving outside of the dialog while it is visible.
 * This API was developed to be used with the `useCSSTransition`/`useTransition`
 * hooks as well.
 *
 * @example
 * Main Usage
 * ```tsx
 * import {
 *   Button,
 *   useFocusContainer,
 *   useScaleTransition,
 *   useToggle,
 * } from "@react-md/core";
 * import type { ReactElement } from "react";
 *
 * function Example(): ReactElement {
 *   const { toggled, enable, disable } = useToggle(false);
 *
 *   const { eventHandlers, transitionOptions } = useFocusContainer({
 *     activate: toggled,
 *   });
 *   const { elementProps, rendered } = useScaleTransition({
 *     transitionIn: toggled,
 *     temporary: true,
 *     ...transitionOptions,
 *   });
 *
 *   return (
 *     <>
 *       <Button onClick={enable}>Toggle</Button>
 *       {rendered && (
 *         <div {...eventHandlers} {...elementProps}>
 *           <Button onClick={disable}>Button 1</Button>
 *           <Button onClick={disable}>Button 2</Button>
 *           <Button onClick={disable}>Button 3</Button>
 *           <Button onClick={disable}>Button 4</Button>
 *         </div>
 *       )}
 *     </>
 *   );
 * }
 * ```
 *
 * @remarks \@since 6.0.0
 */ export function useFocusContainer(options) {
    const { nodeRef, activate, onEntering = noop, onEntered = noop, onExiting = noop, onExited = noop, onKeyDown = noop, programmatic = false, disableTransition = false, isFocusTypeDisabled = noop } = options;
    const [ref, refCallback] = useEnsuredRef(nodeRef);
    const prevFocus = useRef(null);
    useEffect(()=>{
        if (!activate || !(document.activeElement instanceof HTMLElement)) {
            return;
        }
        prevFocus.current = document.activeElement;
    }, [
        activate
    ]);
    const handleMountFocus = (callback, skipped)=>(appearing)=>{
            callback(appearing);
            const instance = ref.current;
            if (instance && !skipped && !isFocusTypeDisabled("mount") && (!document.activeElement || !instance.contains(document.activeElement))) {
                instance.focus();
            }
        };
    const handleUnmountFocus = (callback, skipped)=>()=>{
            callback();
            if (skipped || isFocusTypeDisabled("unmount")) {
                return;
            }
            // For some reason, the `"Enter"` keydown event fires at a different timing
            // than the Space  keydown event.
            window.requestAnimationFrame(()=>{
                prevFocus.current?.focus();
            });
        };
    return {
        nodeRef: ref,
        transitionOptions: {
            nodeRef: refCallback,
            onEntering: handleMountFocus(onEntering, false),
            onEntered: handleMountFocus(onEntered, !disableTransition && !TRANSITION_CONFIG.disabled),
            onExiting: handleUnmountFocus(onExiting, false),
            onExited: handleUnmountFocus(onExited, !disableTransition && !TRANSITION_CONFIG.disabled)
        },
        eventHandlers: {
            onKeyDown (event) {
                onKeyDown(event);
                if (event.isPropagationStopped() || event.key !== "Tab" || isFocusTypeDisabled("keyboard")) {
                    return;
                }
                const { target, shiftKey, currentTarget } = event;
                const elements = getFocusableElements(currentTarget, programmatic);
                const count = elements.length;
                if (count === 0) {
                    event.preventDefault();
                    return;
                }
                // if the container element is the current focus, need to either focus
                // the first or last element so focus doesn't escape
                let type;
                if (count === 1 || !shiftKey && (target === currentTarget || target === elements[count - 1])) {
                    type = "first";
                } else if (shiftKey && (target === currentTarget || target === elements[0])) {
                    type = "last";
                }
                if (type) {
                    event.preventDefault();
                    focusElementWithin({
                        type,
                        elements,
                        container: currentTarget
                    });
                }
            }
        }
    };
}

//# sourceMappingURL=useFocusContainer.js.map