import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// (C) 2007-2025 GoodData Corporation
import { useCallback, useEffect, useMemo, useRef, } from "react";
import { usePropState } from "@gooddata/sdk-ui";
import { DropdownButtonKeyboardWrapper } from "./DropdownButtonKeyboardWrapper.js";
import { UiFocusManager } from "../@ui/UiFocusManager/UiFocusManager.js";
import { resolveRef } from "../@ui/UiFocusManager/utils.js";
import { FullScreenOverlay, Overlay } from "../Overlay/index.js";
import { useMediaQuery } from "../responsive/useMediaQuery.js";
import { useId } from "../utils/useId.js";
const SCROLLBAR_SELECTOR = ".fixedDataTableLayout_main .ScrollbarLayout_main";
const MOBILE_DROPDOWN_ALIGN_POINTS = [
    {
        align: "tl tl",
    },
];
/**
 * Element.matches is only supported via prefix in IE11 and Edge.
 */
function matches(element, selector) {
    const matchesImpl = element.matches ?? element.msMatchesSelector;
    return matchesImpl.call(element, selector);
}
/**
 * Prevent the overlay from closing when scrolling and finishing
 * with a cursor position outside of the overlay.
 */
function shouldCloseOnClick(e) {
    const activeElement = document.activeElement ?? e.target;
    if (!activeElement) {
        return false;
    }
    const hasScrolled = matches(activeElement, SCROLLBAR_SELECTOR);
    return !hasScrolled;
}
/**
 * @internal
 */
export function Dropdown(props) {
    const { isOpen: isOpenProp, onToggle, className, openOnInit, closeOnParentScroll, closeOnMouseDrag, closeOnOutsideClick = true, overlayPositionType, alignPoints = [
        {
            align: "bl tl",
        },
    ], overlayZIndex, ignoreClicksOnByClass = [], renderBody, renderButton, onOpenStateChanged, fullscreenOnMobile = true, enableEventPropagation = false, closeOnEscape = false, autofocusOnOpen = false, initialFocus, returnFocusTo, accessibilityConfig, shouldTrapFocus = true, } = props;
    const [isOpen, setIsOpen] = usePropState(isOpenProp ?? openOnInit ?? false);
    const id = useId();
    const dropdownId = `dropdown-${id}`;
    const dropdownButtonId = `dropdown-button-${id}`;
    const buttonWrapperRef = useRef(null);
    const _renderButton = (renderProps) => (_jsx(DropdownButtonKeyboardWrapper, { onToggle: renderProps.toggleDropdown, closeOnEscape: closeOnEscape, isOpen: renderProps.isOpen, ref: buttonWrapperRef, id: dropdownButtonId, children: renderButton(renderProps) }));
    const toggleDropdown = useCallback((desiredState) => {
        if (typeof desiredState === "boolean") {
            if (onToggle) {
                onToggle(desiredState);
            }
            else {
                setIsOpen(desiredState);
            }
        }
        else {
            if (onToggle) {
                onToggle();
            }
            else {
                setIsOpen((state) => !state);
            }
        }
    }, [onToggle, setIsOpen]);
    const closeDropdown = useCallback(() => {
        toggleDropdown(false);
    }, [toggleDropdown]);
    const openDropdown = useCallback(() => {
        toggleDropdown(true);
    }, [toggleDropdown]);
    const mountRef = useRef(false);
    const buttonRef = useRef(null);
    useEffect(() => {
        if (mountRef.current && onOpenStateChanged) {
            onOpenStateChanged(isOpen);
        }
        return () => {
            mountRef.current = true;
        };
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [isOpen]);
    const renderButtonProps = useMemo(() => {
        const role = accessibilityConfig?.triggerRole ?? "button";
        return {
            isOpen,
            openDropdown,
            closeDropdown,
            toggleDropdown,
            dropdownId,
            ariaAttributes: {
                role,
                "aria-controls": isOpen ? dropdownId : undefined,
                "aria-expanded": isOpen,
                "aria-haspopup": accessibilityConfig?.popupRole ?? true,
            },
            accessibilityConfig: {
                role,
                popupId: dropdownId,
                isExpanded: isOpen,
            },
        };
    }, [
        accessibilityConfig?.popupRole,
        accessibilityConfig?.triggerRole,
        closeDropdown,
        dropdownId,
        isOpen,
        openDropdown,
        toggleDropdown,
    ]);
    const renderBodyProps = {
        closeDropdown,
        ariaAttributes: {
            id: dropdownId,
            "aria-labelledby": dropdownButtonId,
            role: accessibilityConfig?.popupRole ?? "dialog",
        },
    };
    const handleTabOut = useCallback(() => {
        closeDropdown();
        resolveRef(returnFocusTo)?.focus();
    }, [closeDropdown, returnFocusTo]);
    const isMobileDevice = useMediaQuery("mobileDevice");
    const renderDropdown = isOpen ? (fullscreenOnMobile && isMobileDevice ? (_jsx(FullScreenOverlay, { alignTo: "body", alignPoints: MOBILE_DROPDOWN_ALIGN_POINTS, children: _jsx(UiFocusManager, { tabOutHandler: shouldTrapFocus ? undefined : handleTabOut, enableFocusTrap: shouldTrapFocus, enableAutofocus: autofocusOnOpen ? { initialFocus } : false, enableReturnFocusOnUnmount: { returnFocusTo }, children: _jsxs("div", { className: "gd-mobile-dropdown-overlay overlay gd-flex-row-container", children: [_jsx("div", { className: "gd-mobile-dropdown-header gd-flex-item", children: _renderButton({
                            ...renderButtonProps,
                            isMobile: true,
                            buttonRef: { current: null },
                        }) }), _jsx("div", { className: "gd-mobile-dropdown-content gd-flex-item-stretch gd-flex-row-container", children: renderBody({
                            ...renderBodyProps,
                            isMobile: true,
                        }) })] }) }) })) : (_jsx(Overlay, { alignTo: `#${dropdownButtonId}`, positionType: overlayPositionType, alignPoints: alignPoints, closeOnOutsideClick: closeOnOutsideClick, closeOnMouseDrag: closeOnMouseDrag, closeOnParentScroll: closeOnParentScroll, closeOnEscape: closeOnEscape, shouldCloseOnClick: shouldCloseOnClick, ignoreClicksOnByClass: ignoreClicksOnByClass, onClose: closeDropdown, 
        // Overlay prevents event propagation by default using defaultProps for these
        onClick: enableEventPropagation ? () => { } : undefined, onMouseOver: enableEventPropagation ? () => { } : undefined, onMouseUp: enableEventPropagation ? () => { } : undefined, zIndex: overlayZIndex, children: _jsx(UiFocusManager, { tabOutHandler: shouldTrapFocus ? undefined : handleTabOut, enableFocusTrap: shouldTrapFocus, enableAutofocus: autofocusOnOpen ? { initialFocus } : false, enableReturnFocusOnUnmount: { returnFocusTo }, children: _jsx("div", { className: "overlay dropdown-body", children: renderBody({
                    ...renderBodyProps,
                    isMobile: false,
                }) }) }) }))) : null;
    return (_jsxs("div", { className: className, children: [_renderButton({
                ...renderButtonProps,
                isMobile: false,
                buttonRef,
            }), renderDropdown] }));
}
//# sourceMappingURL=Dropdown.js.map