"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ModalRemovePaddingSelector = exports.ModalTitleSelector = exports.ModalContainerSelector = exports.Modal = void 0;
const react_1 = __importStar(require("react"));
const react_dom_1 = require("react-dom");
const use_forwarded_ref_1 = require("@bedrock-layout/use-forwarded-ref");
const fnWithProps_1 = require("../../../types/fnWithProps");
const HandleEsc_1 = require("../../utils/HandleEsc");
const Modal_styled_1 = require("./Modal.styled");
const FOCUSABLE_SELECTOR = [
    "a[href]",
    "button:not([disabled])",
    "input:not([disabled])",
    "select:not([disabled])",
    "textarea:not([disabled])",
    "[tabindex]:not([tabindex=\"-1\"])",
].join(",");
const prefersReducedMotion = () => {
    if (typeof window === "undefined") {
        return false;
    }
    return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
};
const ModalBase = (0, react_1.forwardRef)((_a, ref) => {
    var { children, onClose, isOpen, title, className, onOverlayClick = "close", closeOnEsc = true, portal = true, position, full } = _a, rest = __rest(_a, ["children", "onClose", "isOpen", "title", "className", "onOverlayClick", "closeOnEsc", "portal", "position", "full"]);
    const [isClosing, setIsClosing] = (0, react_1.useState)(false);
    const [isRendered, setIsRendered] = (0, react_1.useState)(false);
    const overlayRef = (0, react_1.useRef)(null);
    const containerRef = (0, use_forwarded_ref_1.useForwardedRef)(ref);
    const previouslyFocusedRef = (0, react_1.useRef)(null);
    const titleId = (0, react_1.useId)();
    (0, react_1.useEffect)(() => {
        if (isOpen) {
            setIsRendered(true);
            setIsClosing(false);
            return;
        }
        if (prefersReducedMotion()) {
            setIsRendered(false);
            setIsClosing(false);
            return;
        }
        setIsClosing(true);
    }, [isOpen]);
    (0, react_1.useEffect)(() => {
        if (!isClosing) {
            return;
        }
        const overlay = overlayRef.current;
        const container = containerRef.current;
        if (!overlay || !container) {
            return;
        }
        overlay.style.animation = "none";
        container.style.animation = "none";
        overlay.offsetHeight;
        overlay.style.removeProperty("animation");
        container.style.removeProperty("animation");
    }, [isClosing, containerRef]);
    (0, react_1.useEffect)(() => {
        var _a;
        if (!isOpen || !isRendered) {
            return;
        }
        const container = containerRef.current;
        const overlay = overlayRef.current;
        if (!container || !overlay) {
            return;
        }
        previouslyFocusedRef.current = document.activeElement instanceof HTMLElement
            ? document.activeElement
            : null;
        const focusables = container.querySelectorAll(FOCUSABLE_SELECTOR);
        ((_a = focusables[0]) !== null && _a !== void 0 ? _a : container).focus();
        const inerted = [];
        let cursor = overlay;
        while (cursor !== document.body) {
            const parentEl = cursor.parentElement;
            if (!parentEl) {
                break;
            }
            for (const child of Array.from(parentEl.children)) {
                if (child === cursor || !(child instanceof HTMLElement)) {
                    continue;
                }
                if (!child.hasAttribute("inert")) {
                    child.setAttribute("inert", "");
                    inerted.push(child);
                }
            }
            cursor = parentEl;
        }
        return () => {
            var _a;
            inerted.forEach((el) => {
                el.removeAttribute("inert");
            });
            (_a = previouslyFocusedRef.current) === null || _a === void 0 ? void 0 : _a.focus();
        };
    }, [isOpen, isRendered, containerRef]);
    const titleElem = title ? react_1.default.createElement(Modal_styled_1.TitleStyled, { id: titleId }, title) : null;
    const handleOverlayClick = (0, react_1.useCallback)((e) => {
        if (e.target !== e.currentTarget) {
            return;
        }
        if (onOverlayClick === "close") {
            onClose();
        }
        else if (typeof onOverlayClick === "function") {
            onOverlayClick();
        }
    }, [onOverlayClick, onClose]);
    const handleAnimationEnd = (0, react_1.useCallback)((e) => {
        if (e.target !== e.currentTarget) {
            return;
        }
        if (isOpen) {
            return;
        }
        setIsRendered(false);
    }, [isOpen]);
    if (!isRendered) {
        return null;
    }
    const overlayVariants = {};
    if (isClosing) {
        overlayVariants.isClosing = true;
    }
    if (position != null) {
        overlayVariants.position = position;
    }
    const containerVariants = {};
    if (isClosing) {
        containerVariants.isClosing = true;
    }
    if (full != null) {
        containerVariants.full = full;
    }
    const childrenCount = react_1.default.Children.count(children);
    const chld = react_1.default.Children.map(children, (child, index) => {
        var _a;
        if (react_1.default.isValidElement(child) && child.type === Modal_styled_1.RemovePadding) {
            const css = Object.assign({}, ((_a = child.props.css) !== null && _a !== void 0 ? _a : {}));
            if (index === 0 && titleElem == null) {
                css.marginTop = Modal_styled_1.NEGATIVE_PADDING;
            }
            if (index === childrenCount - 1) {
                css.marginBottom = Modal_styled_1.NEGATIVE_PADDING;
            }
            return react_1.default.cloneElement(child, { css });
        }
        return child;
    });
    const tree = (react_1.default.createElement(Modal_styled_1.OverlayStyled, Object.assign({}, overlayVariants, { onClick: handleOverlayClick, ref: overlayRef, onAnimationEnd: handleAnimationEnd }),
        closeOnEsc ? react_1.default.createElement(HandleEsc_1.HandleEsc, { onPress: onClose }) : null,
        react_1.default.createElement(Modal_styled_1.ContainerStyled, Object.assign({ role: "dialog", "aria-modal": true, "aria-labelledby": titleElem ? titleId : undefined, tabIndex: -1, className: className }, containerVariants, { ref: containerRef }, rest),
            titleElem,
            chld)));
    if (portal) {
        const root = typeof portal === "boolean" ? document.body : portal;
        return (0, react_dom_1.createPortal)(tree, root);
    }
    return tree;
});
ModalBase.displayName = "Modal";
const Modal = (0, fnWithProps_1.fnWithProps)(ModalBase, {
    RemovePadding: Modal_styled_1.RemovePadding,
});
exports.Modal = Modal;
Modal.toString = () => Modal_styled_1.OverlayStyled.toString();
const ModalContainerSelector = Modal_styled_1.ContainerStyled.toString();
exports.ModalContainerSelector = ModalContainerSelector;
const ModalTitleSelector = Modal_styled_1.TitleStyled.toString();
exports.ModalTitleSelector = ModalTitleSelector;
const ModalRemovePaddingSelector = Modal_styled_1.RemovePadding.toString();
exports.ModalRemovePaddingSelector = ModalRemovePaddingSelector;
//# sourceMappingURL=Modal.js.map