import { jsx as _jsx } from "react/jsx-runtime";
// (C) 2025-2026 GoodData Corporation
import { useCallback, useMemo, useRef } from "react";
import { useAutoupdateRef } from "@gooddata/sdk-ui";
import { getFocusableElements, isElementFocusable } from "../../utils/domUtilities.js";
import { resolveRef } from "./utils.js";
/**
 * @internal
 */
export function UiReturnFocusOnUnmount({ children, ...options }) {
    const connectors = useUiReturnFocusOnUnmountConnectors(options);
    return (_jsx("div", { style: { display: "contents" }, ...connectors, children: children }));
}
/**
 * @internal
 */
export const useUiReturnFocusOnUnmountConnectors = ({ returnFocusTo, focusVisible, } = {}) => {
    const originalFocusRef = useRef(document.activeElement);
    const returnFocusToRef = useAutoupdateRef(returnFocusTo);
    const focusVisibleRef = useAutoupdateRef(focusVisible);
    const hasMountedRef = useRef(false);
    const ref = useCallback((element) => {
        if (element) {
            hasMountedRef.current = true;
            return;
        }
        if (!hasMountedRef.current) {
            return;
        }
        hasMountedRef.current = false;
        const generalElementToFocus = resolveRef(returnFocusToRef.current) ?? originalFocusRef.current;
        const focusableElement = isElementFocusable(generalElementToFocus)
            ? generalElementToFocus
            : getFocusableElements(generalElementToFocus).firstElement;
        if (!focusableElement) {
            return;
        }
        // Defer the focus call to a microtask so that it runs after React's commit phase completes.
        // This avoids triggering state updates (and act() warnings) during React's commit phase.
        // The focus still happens before the next paint.
        queueMicrotask(() => {
            // Only return focus if it was truly lost (e.g., moved to <body> because the
            // focused element was removed from the DOM). If the user already clicked on
            // another element, don't steal focus from it.
            if (document.activeElement && document.activeElement !== document.body) {
                return;
            }
            // @ts-expect-error focusVisible property is defined in FocusOptions in higher TypeScript versions
            focusableElement.focus({ focusVisible: focusVisibleRef.current });
        });
    }, [returnFocusToRef, focusVisibleRef]);
    return useMemo(() => ({ ref }), [ref]);
};
