export class Modal {
    constructor(selectorOrElement, options = {}) {
        this.triggerElement = null;
        this.focusableElements = [];
        this.isOpen = false;
        this.backdropElement = null;
        this.handleKeydown = (event) => {
            if (event.key === "Escape" && this.options.closeOnEscape) {
                event.preventDefault();
                this.close();
                return;
            }
            if (event.key === "Tab" && this.options.trapFocus) {
                this.handleTabKey(event);
            }
        };
        this.handleCloseClick = () => {
            this.close();
        };
        this.element =
            typeof selectorOrElement === "string"
                ? document.querySelector(selectorOrElement)
                : selectorOrElement;
        this.options = {
            closeOnBackdrop: options.closeOnBackdrop ?? true,
            closeOnEscape: options.closeOnEscape ?? true,
            animationDuration: options.animationDuration ?? 300,
            openClass: options.openClass ?? "modal--open",
            backdropClass: options.backdropClass ?? "modal-backdrop",
            trapFocus: options.trapFocus ?? true,
            focusElement: options.focusElement ?? "",
            returnFocus: options.returnFocus ?? true,
            onOpen: options.onOpen ?? (() => { }),
            onClose: options.onClose ?? (() => { }),
            onBeforeClose: options.onBeforeClose ?? (() => true),
        };
        if (!this.element) {
            console.warn("[Stylescape] Modal element not found");
            return;
        }
        this.init();
    }
    get opened() {
        return this.isOpen;
    }
    open(trigger) {
        if (!this.element || this.isOpen)
            return;
        this.triggerElement =
            trigger || document.activeElement;
        this.createBackdrop();
        this.element.hidden = false;
        this.element.setAttribute("aria-hidden", "false");
        document.body.classList.add("modal-open");
        document.body.style.overflow = "hidden";
        requestAnimationFrame(() => {
            this.element?.classList.add(this.options.openClass);
            this.backdropElement?.classList.add(`${this.options.backdropClass}--visible`);
        });
        this.updateFocusableElements();
        this.setInitialFocus();
        document.addEventListener("keydown", this.handleKeydown);
        this.isOpen = true;
        this.options.onOpen(this.element);
    }
    close() {
        if (!this.element || !this.isOpen)
            return;
        if (this.options.onBeforeClose(this.element) === false) {
            return;
        }
        this.element.classList.remove(this.options.openClass);
        this.backdropElement?.classList.remove(`${this.options.backdropClass}--visible`);
        setTimeout(() => {
            if (!this.element)
                return;
            this.element.hidden = true;
            this.element.setAttribute("aria-hidden", "true");
            document.body.classList.remove("modal-open");
            document.body.style.overflow = "";
            this.removeBackdrop();
            if (this.options.returnFocus && this.triggerElement) {
                this.triggerElement.focus();
            }
            this.isOpen = false;
            this.options.onClose(this.element);
        }, this.options.animationDuration);
        document.removeEventListener("keydown", this.handleKeydown);
    }
    toggle(trigger) {
        if (this.isOpen) {
            this.close();
        }
        else {
            this.open(trigger);
        }
    }
    setContent(html) {
        const content = this.element?.querySelector("[data-ss-modal-content], .modal-content");
        if (content) {
            content.innerHTML = html;
            this.updateFocusableElements();
        }
    }
    destroy() {
        this.close();
        document.removeEventListener("keydown", this.handleKeydown);
        this.element
            ?.querySelectorAll("[data-ss-modal-close]")
            .forEach((button) => {
            button.removeEventListener("click", this.handleCloseClick);
        });
        this.element = null;
    }
    static initModals() {
        const modals = [];
        const modalMap = new Map();
        document
            .querySelectorAll('[data-ss="modal"]')
            .forEach((el) => {
            const closeOnBackdrop = el.dataset.ssModalCloseBackdrop !== "false";
            const closeOnEscape = el.dataset.ssModalCloseEscape !== "false";
            const modal = new Modal(el, {
                closeOnBackdrop,
                closeOnEscape,
            });
            modals.push(modal);
            if (el.id) {
                modalMap.set(`#${el.id}`, modal);
            }
        });
        document
            .querySelectorAll("[data-ss-modal-trigger]")
            .forEach((trigger) => {
            const targetSelector = trigger.dataset.ssModalTrigger;
            if (targetSelector) {
                const modal = modalMap.get(targetSelector);
                if (modal) {
                    trigger.addEventListener("click", () => modal.open(trigger));
                }
            }
        });
        return modals;
    }
    init() {
        if (!this.element)
            return;
        this.element.setAttribute("role", "dialog");
        this.element.setAttribute("aria-modal", "true");
        this.element.setAttribute("aria-hidden", "true");
        this.element.hidden = true;
        this.element
            .querySelectorAll("[data-ss-modal-close]")
            .forEach((button) => {
            button.addEventListener("click", this.handleCloseClick);
        });
    }
    createBackdrop() {
        this.backdropElement = document.createElement("div");
        this.backdropElement.className = this.options.backdropClass;
        if (this.options.closeOnBackdrop) {
            this.backdropElement.addEventListener("click", () => this.close());
        }
        document.body.appendChild(this.backdropElement);
    }
    removeBackdrop() {
        this.backdropElement?.remove();
        this.backdropElement = null;
    }
    updateFocusableElements() {
        if (!this.element)
            return;
        const focusableSelectors = [
            "button:not([disabled])",
            "input:not([disabled])",
            "select:not([disabled])",
            "textarea:not([disabled])",
            "a[href]",
            '[tabindex]:not([tabindex="-1"])',
        ].join(",");
        this.focusableElements = Array.from(this.element.querySelectorAll(focusableSelectors));
    }
    setInitialFocus() {
        if (!this.element)
            return;
        if (this.options.focusElement) {
            const focusEl = this.element.querySelector(this.options.focusElement);
            if (focusEl) {
                focusEl.focus();
                return;
            }
        }
        if (this.focusableElements.length > 0) {
            this.focusableElements[0].focus();
        }
        else {
            this.element.setAttribute("tabindex", "-1");
            this.element.focus();
        }
    }
    handleTabKey(event) {
        if (this.focusableElements.length === 0)
            return;
        const firstElement = this.focusableElements[0];
        const lastElement = this.focusableElements[this.focusableElements.length - 1];
        if (event.shiftKey) {
            if (document.activeElement === firstElement) {
                event.preventDefault();
                lastElement.focus();
            }
        }
        else {
            if (document.activeElement === lastElement) {
                event.preventDefault();
                firstElement.focus();
            }
        }
    }
}
export default Modal;
//# sourceMappingURL=Modal.js.map