class CustomModal {
    static DRAGGABLE_MIN_WIDTH=768;
    constructor(element, options = {}) {
        if (!element) {
            return;
        }
        this.element = element instanceof HTMLElement ? element : document.querySelector(element);
        if (!this.element) {
            return;
        }
        const isDraggable = element.getAttribute("data-cm-draggable") === "true";
        const isCompact = element.getAttribute("data-cm-compact") === "true";
        const hasNoBackdrop = element.getAttribute("data-cm-no-backdrop") === "true";
        this.options = {
            backdrop: element.getAttribute("data-cm-backdrop") !== "static",
            keyboard: element.getAttribute("data-cm-keyboard") !== "false",
            noBackdrop: hasNoBackdrop,
            draggable: isDraggable,
            persistent: element.getAttribute("data-cm-persistent") === "true",
            placement: element.getAttribute("data-cm-placement") || null,
            margin: parseInt(element.getAttribute("data-cm-margin")) || 20,
            constrain: element.getAttribute("data-cm-constrain") === "true",
            compact: isCompact,
            savePosition: element.getAttribute("data-cm-save-position") === "true",
            focus: true,
            ...options
        };
        this.isShown = false;
        this.isTransitioning = false;
        this.backdrop = null;
        this.scrollbarWidth = 0;
        this.backdropReady = false;
        this.backdropAnimationTimer = null;
        this.backdropRemovalTimer = null;
        this.dialog = this.element.querySelector(".modal-dialog");
        this.content = this.element.querySelector(".modal-content");
        this.isDragging = false;
        this.dragStartX = 0;
        this.dragStartY = 0;
        this.modalStartX = 0;
        this.modalStartY = 0;
        this.lastPosition = null;
        this.handleEscapeKey = this.handleEscapeKey.bind(this);
        this.handleBackdropClick = this.handleBackdropClick.bind(this);
        this.handleOutsideClick = this.handleOutsideClick.bind(this);
        this.handleDragStart = this.handleDragStart.bind(this);
        this.handleDragMove = this.handleDragMove.bind(this);
        this.handleDragEnd = this.handleDragEnd.bind(this);
        this.handleResize = this.handleResize.bind(this);
        this.element.customModalAPI = this;
        this.#init();
    }
    #init() {
        if (this.element.classList.contains("cm-initialized")) return;
        this.element.classList.add("cm-initialized");
    }
    #isDraggableEnabled() {
        if (this.options.compact && this.options.draggable) {
            return true;
        }
        return this.options.draggable && window.innerWidth > CustomModal.DRAGGABLE_MIN_WIDTH;
    }
    show() {
        if (this.isShown || this.isTransitioning) return;
        const showEvent = new CustomEvent("show.cm.modal", {
            cancelable: true,
            bubbles: true
        });
        this.element.dispatchEvent(showEvent);
        if (showEvent.defaultPrevented) return;
        const isDraggableNow = this.#isDraggableEnabled();
        this.options.noBackdrop = this.element.getAttribute("data-cm-no-backdrop") === "true" || isDraggableNow;
        this.isShown = true;
        this.isTransitioning = true;
        this.#handleBodyScroll(true);
        this.#showBackdrop(() => {
            this.element.style.display = "block";
            this.element.setAttribute("aria-modal", "true");
            this.element.setAttribute("role", "dialog");
            if (this.options.compact && this.dialog) {
                this.dialog.classList.add("custom-modal-compact");
            }
            this.element.addEventListener("click", this.handleBackdropClick);
            if (this.dialog) {
                this.dialog.scrollTop = 0;
            }
            this.element.offsetHeight;
            this.element.classList.add("show");
            if (this.options.focus) {
                this.#enforceFocus();
            }
            if (this.options.keyboard) {
                document.addEventListener("keydown", this.handleEscapeKey);
            }
            if (isDraggableNow) {
                this.#setupDraggable();
                setTimeout(() => {
                    document.addEventListener("mousedown", this.handleOutsideClick, {
                        capture: true
                    });
                    document.addEventListener("touchstart", this.handleOutsideClick, {
                        capture: true,
                        passive: true
                    });
                }, 100);
                window.addEventListener("resize", this.handleResize);
            }
            this.#transitionComplete(() => {
                this.isTransitioning = false;
                const shownEvent = new CustomEvent("shown.cm.modal", {
                    bubbles: true
                });
                this.element.dispatchEvent(shownEvent);
            });
        });
    }
    hide() {
        if (!this.isShown || this.isTransitioning) return;
        const hideEvent = new CustomEvent("hide.cm.modal", {
            cancelable: true,
            bubbles: true
        });
        this.element.dispatchEvent(hideEvent);
        if (hideEvent.defaultPrevented) return;
        this.isShown = false;
        this.isTransitioning = true;
        this.element.classList.remove("show");
        if (this.backdrop && this.backdrop.classList.contains("fade")) {
            this.backdrop.classList.remove("show");
        }
        document.removeEventListener("keydown", this.handleEscapeKey);
        this.element.removeEventListener("click", this.handleBackdropClick);
        document.removeEventListener("mousedown", this.handleOutsideClick, {
            capture: true
        });
        document.removeEventListener("touchstart", this.handleOutsideClick, {
            capture: true
        });
        window.removeEventListener("resize", this.handleResize);
        if (this.options.draggable) {
            this.#removeDraggable();
        }
        if (this.options.compact && this.dialog) {
            this.dialog.classList.remove("custom-modal-compact");
        }
        this.#transitionComplete(() => {
            this.isTransitioning = false;
            this.element.style.display = "none";
            this.element.removeAttribute("aria-modal");
            this.element.removeAttribute("role");
            this.#removeBackdrop();
            this.#handleBodyScroll(false);
            const hiddenEvent = new CustomEvent("hidden.cm.modal", {
                bubbles: true
            });
            this.element.dispatchEvent(hiddenEvent);
        });
    }
    toggle() {
        this.isShown ? this.hide() : this.show();
    }
    #showBackdrop(callback) {
        if (this.options.noBackdrop) {
            callback();
            return;
        }
        if (this.backdropRemovalTimer) {
            clearTimeout(this.backdropRemovalTimer);
            this.backdropRemovalTimer = null;
        }
        if (this.backdrop) {
            callback();
            return;
        }
        const animate = this.element.classList.contains("fade");
        this.backdropReady = false;
        this.backdrop = document.createElement("div");
        this.backdrop.className = "custom-modal-backdrop" + (animate ? " fade" : "");
        const rootNode = this.element.getRootNode();
        const appendTarget = rootNode instanceof ShadowRoot ? rootNode : document.body;
        appendTarget.appendChild(this.backdrop);
        if (animate) {
            this.backdrop.offsetHeight;
            this.backdrop.classList.add("show");
        }
        const backdropClickHandler = () => {
            if (!this.backdropReady || this.isTransitioning) return;
            if (this.options.backdrop) {
                this.hide();
            }
        };
        if (this.backdrop) {
            this.backdrop.addEventListener("click", backdropClickHandler);
        }
        if (animate) {
            const transitionDuration = this.#getTransitionDuration(this.backdrop);
            if (this.backdropAnimationTimer) {
                clearTimeout(this.backdropAnimationTimer);
            }
            this.backdropAnimationTimer = setTimeout(() => {
                this.backdropAnimationTimer = null;
                this.backdropReady = true;
                callback();
            }, transitionDuration);
        } else {
            this.backdropReady = true;
            callback();
        }
    }
    #removeBackdrop() {
        if (this.backdropAnimationTimer) {
            clearTimeout(this.backdropAnimationTimer);
            this.backdropAnimationTimer = null;
        }
        if (!this.backdrop) return;
        const animate = this.backdrop.classList.contains("fade");
        const doRemove = () => {
            if (this.backdrop) {
                this.backdrop.remove();
                this.backdrop = null;
                this.backdropReady = false;
                this.backdropRemovalTimer = null;
            }
        };
        if (animate) {
            if (this.backdropRemovalTimer) {
                clearTimeout(this.backdropRemovalTimer);
            }
            const transitionDuration = this.#getTransitionDuration(this.backdrop);
            this.backdropRemovalTimer = setTimeout(doRemove, transitionDuration);
        } else {
            doRemove();
        }
    }
    handleEscapeKey(event) {
        if (event.key === "Escape" && this.isShown && this.options.keyboard) {
            event.preventDefault();
            this.hide();
        }
    }
    handleBackdropClick(event) {
        if (this.isTransitioning) return;
        if (this.options.noBackdrop) return;
        if (event.target === event.currentTarget && this.options.backdrop) {
            this.hide();
        }
    }
    handleOutsideClick(event) {
        if (this.options.persistent) {
            return;
        }
        const clickedElement = event.touches ? document.elementFromPoint(event.touches[0].clientX, event.touches[0].clientY) : event.target;
        if (!clickedElement) {
            return;
        }
        if (this.isTransitioning || this.isDragging) {
            return;
        }
        if (this.dialog && this.dialog.contains(clickedElement)) {
            return;
        }
        const clickedInsideAnyModal = clickedElement.closest('.modal[data-custom-modal="true"], [data-custom-modal="true"]');
        if (clickedInsideAnyModal && clickedInsideAnyModal !== this.element) {
            return;
        }
        const floatingSelectors = [ ".color-picker-popup", ".color-picker-swatch", ".color-picker-container", ".color-picker", '[class*="color-picker"]', '[class*="colorpicker"]', ".dropdown-menu", ".popover", ".tooltip", ".select-dropdown", ".autocomplete-dropdown", ".select-bottom-sheet", ".external-select-overlay", ".select-bottom-sheet-backdrop", '[class*="bottom-sheet"]', ".datepicker", ".date-picker", '[class*="datepicker"]', "[data-floating-ui]", "[data-popper]", ".popper", "[data-tippy-root]", ".tippy-box", ".fx-tooltip" ];
        const isFloatingElement = floatingSelectors.some(selector => clickedElement.closest(selector));
        if (isFloatingElement) {
            return;
        }
        const ariaDescribedBy = clickedElement.closest("[aria-describedby]")?.getAttribute("aria-describedby");
        const ariaLabelledBy = clickedElement.closest("[aria-labelledby]")?.getAttribute("aria-labelledby");
        if (ariaDescribedBy && this.dialog.querySelector(`#${ariaDescribedBy}`)) {
            return;
        }
        if (ariaLabelledBy && this.dialog.querySelector(`#${ariaLabelledBy}`)) {
            return;
        }
        const clickedWithId = clickedElement.closest("[id]");
        if (clickedWithId) {
            const controlledByModal = this.dialog.querySelector(`[aria-controls="${clickedWithId.id}"], [aria-owns="${clickedWithId.id}"]`);
            if (controlledByModal) {
                return;
            }
        }
        this.hide();
    }
    #handleBodyScroll(lock) {
        if (lock) {
            this.scrollbarWidth = this.#getScrollbarWidth();
            if (this.scrollbarWidth > 0) {
                document.body.style.paddingRight = this.scrollbarWidth + "px";
            }
            document.body.classList.add("custom-modal-open");
            document.body.style.overflow = "hidden";
        } else {
            const openModals = document.querySelectorAll(".custom-modal.show");
            if (openModals.length === 0) {
                document.body.classList.remove("custom-modal-open");
                document.body.style.overflow = "";
                document.body.style.paddingRight = "";
            }
        }
    }
    #getScrollbarWidth() {
        const scrollDiv = document.createElement("div");
        scrollDiv.style.cssText = "width: 100px; height: 100px; overflow: scroll; position: absolute; top: -9999px;";
        document.body.appendChild(scrollDiv);
        const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
        document.body.removeChild(scrollDiv);
        return scrollbarWidth;
    }
    #enforceFocus() {
        document.removeEventListener("focusin", this.handleFocusTrap);
        this.handleFocusTrap = event => {
            if (this.isShown && !this.element.contains(event.target) && event.target !== document.body) {
                const focusedInAnotherModal = event.target.closest('.modal.show[data-custom-modal="true"]');
                if (focusedInAnotherModal && focusedInAnotherModal !== this.element) {
                    return;
                }
                const focusedInExternalDropdown = event.target.closest(".select-dropdown");
                if (focusedInExternalDropdown) {
                    return;
                }
                this.element.focus();
            }
        };
        document.addEventListener("focusin", this.handleFocusTrap);
        this.element.focus();
    }
    #transitionComplete(callback) {
        const element = this.element;
        const animate = element.classList.contains("fade");
        if (!animate) {
            callback();
            return;
        }
        const transitionDuration = this.#getTransitionDuration(element);
        const handleTransitionEnd = () => {
            element.removeEventListener("transitionend", handleTransitionEnd);
            callback();
        };
        element.addEventListener("transitionend", handleTransitionEnd);
        setTimeout(() => {
            if (element) {
                element.removeEventListener("transitionend", handleTransitionEnd);
                callback();
            }
        }, transitionDuration + 50);
    }
    #getTransitionDuration(element) {
        const computedStyle = window.getComputedStyle(element);
        const duration = parseFloat(computedStyle.transitionDuration) * 1e3;
        return duration || 300;
    }
    #setupDraggable() {
        if (!this.dialog) return;
        this.dragHandle = this.dialog.querySelector("[data-cm-drag-handle]");
        if (!this.dragHandle) return;
        this.dialog.classList.add("custom-modal-draggable");
        this.dragHandle.classList.add("custom-modal-drag-active");
        this.#applyPlacement();
        this.dragHandle.addEventListener("mousedown", this.handleDragStart);
        this.dragHandle.addEventListener("touchstart", this.handleDragStart, {
            passive: false
        });
    }
    #applyPlacement() {
        if (!this.dialog) return;
        const rect = this.dialog.getBoundingClientRect();
        const margin = this.options.margin;
        const placement = this.options.placement ? this.options.placement.toLowerCase() : null;
        let left, top;
        if (this.options.savePosition && this.element.id) {
            const savedPos = localStorage.getItem(`cm_position_${this.element.id}`);
            if (savedPos) {
                try {
                    const pos = JSON.parse(savedPos);
                    if (pos.left >= 0 && pos.left < window.innerWidth - 50 && pos.top >= 0 && pos.top < window.innerHeight - 50) {
                        this.lastPosition = pos;
                    }
                } catch (e) {}
            }
        }
        if (this.lastPosition) {
            left = this.lastPosition.left;
            top = this.lastPosition.top;
        } else if (placement) {
            left = (window.innerWidth - rect.width) / 2;
            top = (window.innerHeight - rect.height) / 2;
            if (placement.includes("left")) {
                left = margin;
            } else if (placement.includes("right")) {
                left = window.innerWidth - rect.width - margin;
            }
            if (placement.includes("top")) {
                top = margin;
            } else if (placement.includes("bottom")) {
                top = window.innerHeight - rect.height - margin;
            }
        } else {
            left = (window.innerWidth - rect.width) / 2;
            top = (window.innerHeight - rect.height) / 2;
        }
        this.dialog.style.cssText = `\n            --cm-width: ${rect.width}px;\n            position: fixed !important;\n            left: ${left}px !important;\n            top: ${top}px !important;\n            margin: 0 !important;\n            transform: none !important;\n            pointer-events: auto !important;\n        `;
    }
    #removeDraggable() {
        if (this.dragHandle) {
            this.dragHandle.removeEventListener("mousedown", this.handleDragStart);
            this.dragHandle.removeEventListener("touchstart", this.handleDragStart);
            this.dragHandle.classList.remove("custom-modal-drag-active");
        }
        document.removeEventListener("mousemove", this.handleDragMove);
        document.removeEventListener("mouseup", this.handleDragEnd);
        document.removeEventListener("touchmove", this.handleDragMove);
        document.removeEventListener("touchend", this.handleDragEnd);
        if (this.dialog) {
            this.dialog.classList.remove("custom-modal-draggable");
            this.dialog.classList.remove("custom-modal-dragging");
            this.dialog.style.cssText = "";
        }
        this.dragHandle = null;
    }
    handleDragStart(event) {
        const target = event.target;
        if (target.closest("button, input, select, textarea, a, [data-cm-dismiss]")) {
            return;
        }
        event.preventDefault();
        const rect = this.dialog.getBoundingClientRect();
        const clientX = event.type === "touchstart" ? event.touches[0].clientX : event.clientX;
        const clientY = event.type === "touchstart" ? event.touches[0].clientY : event.clientY;
        this.dragOffsetX = clientX - rect.left;
        this.dragOffsetY = clientY - rect.top;
        this.dialog.style.cssText = `\n            --cm-width: ${rect.width}px;\n            position: fixed !important;\n            left: ${rect.left}px !important;\n            top: ${rect.top}px !important;\n            margin: 0 !important;\n            transform: none !important;\n            pointer-events: auto !important;\n        `;
        this.isDragging = true;
        document.addEventListener("mousemove", this.handleDragMove);
        document.addEventListener("mouseup", this.handleDragEnd);
        document.addEventListener("touchmove", this.handleDragMove, {
            passive: false
        });
        document.addEventListener("touchend", this.handleDragEnd);
        this.dialog.classList.add("custom-modal-dragging");
    }
    handleDragMove(event) {
        if (!this.isDragging) return;
        event.preventDefault();
        const clientX = event.type === "touchmove" ? event.touches[0].clientX : event.clientX;
        const clientY = event.type === "touchmove" ? event.touches[0].clientY : event.clientY;
        let newLeft = clientX - this.dragOffsetX;
        let newTop = clientY - this.dragOffsetY;
        if (this.options.constrain) {
            const rect = this.dialog.getBoundingClientRect();
            const minLeft = 0;
            const maxLeft = window.innerWidth - rect.width;
            newLeft = Math.max(minLeft, Math.min(maxLeft, newLeft));
            const minTop = 0;
            const maxTop = window.innerHeight - rect.height;
            newTop = Math.max(minTop, Math.min(maxTop, newTop));
        }
        this.dialog.style.setProperty("left", newLeft + "px", "important");
        this.dialog.style.setProperty("top", newTop + "px", "important");
    }
    handleDragEnd() {
        if (!this.isDragging) return;
        this.isDragging = false;
        if (this.dialog) {
            const rect = this.dialog.getBoundingClientRect();
            const visibleLeft = Math.max(0, rect.left);
            const visibleRight = Math.min(window.innerWidth, rect.right);
            const visibleTop = Math.max(0, rect.top);
            const visibleBottom = Math.min(window.innerHeight, rect.bottom);
            const visibleWidth = Math.max(0, visibleRight - visibleLeft);
            const visibleHeight = Math.max(0, visibleBottom - visibleTop);
            const visibleArea = visibleWidth * visibleHeight;
            const totalArea = rect.width * rect.height;
            const visiblePercent = totalArea > 0 ? visibleArea / totalArea : 0;
            if (visiblePercent >= .7) {
                this.lastPosition = {
                    left: rect.left,
                    top: rect.top
                };
                if (this.options.savePosition && this.element.id) {
                    localStorage.setItem(`cm_position_${this.element.id}`, JSON.stringify(this.lastPosition));
                }
            } else {
                this.lastPosition = null;
                if (this.options.savePosition && this.element.id) {
                    localStorage.removeItem(`cm_position_${this.element.id}`);
                }
            }
        }
        document.removeEventListener("mousemove", this.handleDragMove);
        document.removeEventListener("mouseup", this.handleDragEnd);
        document.removeEventListener("touchmove", this.handleDragMove);
        document.removeEventListener("touchend", this.handleDragEnd);
        this.dialog.classList.remove("custom-modal-dragging");
    }
    handleResize() {
        if (!this.isShown || !this.dialog) return;
        this.lastPosition = null;
        if (this.options.savePosition && this.element.id) {
            localStorage.removeItem(`cm_position_${this.element.id}`);
        }
        this.#applyPlacement();
    }
    destroy() {
        if (this.isShown) {
            this.hide();
        }
        this.#removeDraggable();
        document.removeEventListener("keydown", this.handleEscapeKey);
        if (this.handleFocusTrap) {
            document.removeEventListener("focusin", this.handleFocusTrap);
        }
        if (this.backdrop) {
            this.backdrop.remove();
            this.backdrop = null;
        }
        delete this.element.customModalAPI;
        this.element.classList.remove("cm-initialized");
    }
    static getInstance(element) {
        const el = element instanceof HTMLElement ? element : document.querySelector(element);
        if (el && el.getAttribute("data-custom-modal") === "true") {
            return el.customModalAPI || null;
        }
        return null;
    }
    static getOrCreateInstance(element, options = {}) {
        let instance = CustomModal.getInstance(element);
        if (!instance) {
            instance = new CustomModal(element, options);
        }
        return instance;
    }
}

if (!window.__customModalInitialized) {
    window.__customModalInitialized = true;
    document.addEventListener("click", function(event) {
        const trigger = event.target.closest('[data-cm-toggle="custom-modal"]');
        if (trigger) {
            event.preventDefault();
            const targetSelector = trigger.getAttribute("data-cm-target");
            if (!targetSelector) {
                return;
            }
            const targetElement = document.querySelector(targetSelector);
            if (!targetElement) {
                return;
            }
            const modal = CustomModal.getOrCreateInstance(targetElement);
            if (modal.isTransitioning) {
                return;
            }
            modal.toggle();
        }
    });
    document.addEventListener("click", function(event) {
        const actualTarget = event.composedPath && event.composedPath()[0] || event.target;
        const dismissBtn = actualTarget.closest('[data-cm-dismiss="custom-modal"]');
        if (dismissBtn) {
            event.preventDefault();
            const modal = dismissBtn.closest('.modal[data-custom-modal="true"]');
            if (!modal) {
                return;
            }
            const instance = CustomModal.getInstance(modal);
            if (instance) {
                instance.hide();
            }
        }
    });
}

if (!window.__customModalResizeInitialized) {
    window.__customModalResizeInitialized = true;
    let lastWidth = window.innerWidth;
    let lastHeight = window.innerHeight;
    function handleGlobalScreenChange() {
        const newWidth = window.innerWidth;
        const newHeight = window.innerHeight;
        const widthChanged = Math.abs(newWidth - lastWidth) > 100;
        const heightChanged = Math.abs(newHeight - lastHeight) > 100;
        if (widthChanged || heightChanged) {
            const keysToRemove = [];
            for (let i = 0; i < localStorage.length; i++) {
                const key = localStorage.key(i);
                if (key && key.startsWith("cm_position_")) {
                    keysToRemove.push(key);
                }
            }
            keysToRemove.forEach(key => localStorage.removeItem(key));
            document.querySelectorAll('.modal[data-custom-modal="true"]').forEach(modalEl => {
                const instance = modalEl.customModalAPI;
                if (instance) {
                    instance.lastPosition = null;
                }
            });
            lastWidth = newWidth;
            lastHeight = newHeight;
        }
    }
    window.addEventListener("resize", handleGlobalScreenChange);
    window.addEventListener("orientationchange", () => {
        setTimeout(handleGlobalScreenChange, 100);
    });
}

export { CustomModal };

if (typeof window !== "undefined") {
    window.CustomModal = CustomModal;
}