import { r as registerInstance, c as createEvent, w as writeTask, h, H as Host, g as getElement } from './index-BdVwMG9u.js';
import { b as balBrowser } from './browser-B1u-Mq75.js';
import { c as componentOnReady, d as deepReady, w as wait } from './helpers-BNj87EbG.js';
import { p as prepareOverlay, d as dismiss, e as eventMethod, F as FOCUS_TRAP_DISABLE_CLASS } from './overlays-DuvWMrlA.js';
import { B as BalScrollHandler } from './scroll-X92R_eyZ.js';
import './config.utils-B7jugjyM.js';

const getClassMap = (classes) => {
    const map = {};
    getClassList(classes).forEach(c => (map[c] = true));
    return map;
};
const getClassList = (classes) => {
    if (classes !== undefined) {
        const array = Array.isArray(classes) ? classes : classes.split(' ');
        return array
            .filter(c => c != null)
            .map(c => c.trim())
            .filter(c => c !== '');
    }
    return [];
};

const attachComponent = async (delegate, container, component, cssClasses, componentProps) => {
    if (delegate) {
        return delegate.attachViewToDom(container, component, componentProps, cssClasses);
    }
    if (typeof component !== 'string' && !(component instanceof HTMLElement)) {
        throw new Error('framework delegate is missing');
    }
    const el = typeof component === 'string'
        ? container.ownerDocument && container.ownerDocument.createElement(component)
        : component;
    if (cssClasses) {
        cssClasses.forEach(c => el.classList.add(c));
    }
    if (componentProps) {
        Object.assign(el, componentProps);
    }
    container.appendChild(el);
    await new Promise(resolve => componentOnReady(el, resolve));
    return el;
};
const detachComponent = (delegate, element) => {
    if (element) {
        if (delegate) {
            const container = element.parentElement;
            return delegate.removeViewFromDom(container, element);
        }
        element.remove();
    }
    return Promise.resolve();
};

const balModalCss = ".bal-modal,.bal-modal__background{bottom:0;left:0;position:absolute;right:0;top:0}:root{--bal-modal-background:var(--bal-color-white);--bal-modal-backdrop-background:var(--bal-color-primary-6);--bal-modal-backdrop-opacity:.6;--bal-modal-radius:var(--bal-radius-large)}.bal-modal{-ms-flex-align:center;align-items:center;display:none;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:start;justify-content:flex-start;overflow:hidden;position:fixed;z-index:var(--bal-z-index-modal)}.bal-modal--is-active{display:-ms-flexbox;display:flex}.bal-modal__background{background:var(--bal-modal-backdrop-background);opacity:var(--bal-modal-backdrop-opacity)}.bal-modal__header__title{padding-right:2.5rem;line-height:2rem}.bal-modal__header__close{position:absolute !important;display:-ms-flexbox !important;display:flex !important;right:1.25rem !important;top:1.5rem !important;-ms-flex-align:center;align-items:center;-ms-flex-pack:center;justify-content:center;min-width:2rem;max-width:2rem;min-height:2rem;max-height:2rem}.bal-modal__container{position:fixed;top:0;bottom:0;left:0;right:0;overflow-x:none;overflow-y:auto;-ms-overflow-y:visible;padding:.5rem}@media screen and (min-width: 769px),print{.bal-modal__container{padding:0}}.bal-modal__content{overflow:none;position:relative;width:100%;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;background:var(--bal-modal-background);border-radius:var(--bal-modal-radius);padding:1rem}@media screen and (min-width: 769px),print{.bal-modal__content{margin:3rem auto;width:var(--bal-modal-width, var(--bal-width, 40rem))}}.bal-modal__content .bal-modal__header{padding-bottom:1rem}.bal-modal__content .bal-modal__header__close{right:1.2rem !important;top:.7rem !important}@media screen and (min-width: 769px),print{.bal-modal__content{padding:1.5rem}.bal-modal__content .bal-modal__header{padding-bottom:1.5rem}.bal-modal__content .bal-modal__header__close{right:1.6rem !important;top:1.2rem !important}}@media screen and (min-width: 1024px){.bal-modal__content{padding:2.5rem}.bal-modal__content .bal-modal__header{padding-bottom:2.5rem}.bal-modal__content .bal-modal__header__close{right:2.7rem !important;top:2.2rem !important}}@media screen and (min-width: 769px),print{.bal-modal__content--has-spacing-small{padding:1rem}.bal-modal__content--has-spacing-small .bal-modal__header{padding-bottom:1rem}.bal-modal__content--has-spacing-small .bal-modal__header__close{right:1.1rem !important;top:.7rem !important}}@media screen and (min-width: 1024px){.bal-modal__content--has-spacing-small{padding:1rem}.bal-modal__content--has-spacing-small .bal-modal__header{padding-bottom:1rem}.bal-modal__content--has-spacing-small .bal-modal__header__close{right:1.1rem !important;top:.7rem !important}}@media screen and (min-width: 769px),print{.bal-modal__content--has-spacing-medium{padding:1.5rem}.bal-modal__content--has-spacing-medium .bal-modal__header{padding-bottom:1.5rem}.bal-modal__content--has-spacing-medium .bal-modal__header__close{right:1.6rem !important;top:1.2rem !important}}@media screen and (min-width: 1024px){.bal-modal__content--has-spacing-medium{padding:1.5rem}.bal-modal__content--has-spacing-medium .bal-modal__header{padding-bottom:1.5rem}.bal-modal__content--has-spacing-medium .bal-modal__header__close{right:1.6rem !important;top:1.2rem !important}}.bal-modal__body>bal-button-group{padding-top:1rem}";

const Modal = class {
    constructor(hostRef) {
        registerInstance(this, hostRef);
        this.didPresent = createEvent(this, "balModalDidPresent");
        this.willPresent = createEvent(this, "balModalWillPresent");
        this.willDismiss = createEvent(this, "balModalWillDismiss");
        this.didDismiss = createEvent(this, "balModalDidDismiss");
        this.isClickedOutsideOnMouseDown = false;
        this.isClickedOutsideOnMouseUp = false;
        this.bodyScrollHandler = new BalScrollHandler();
        this.presented = false;
        /**
         * Defines the width of the modal body
         */
        this.modalWidth = 640;
        /**
         * Defines the space/padding of the modal
         */
        this.space = '';
        /**
         * If `true`, a backdrop will be displayed behind the modal.
         */
        this.hasBackdrop = true;
        /**
         * If `true`, the modal can be closed with the escape key or the little close button.
         */
        this.isClosable = true;
        /**
         * If `true`, the modal can be closed with the click outside of the modal
         */
        this.backdropDismiss = true;
        /**
         * If `true`, focus will not be allowed to move outside of this overlay.
         * If `false`, focus will be allowed to move outside of the overlay.
         *
         * In most scenarios this property should remain set to `true`. Setting
         * this property to `false` can cause severe accessibility issues as users
         * relying on assistive technologies may be able to move focus into
         * a confusing state. We recommend only setting this to `false` when
         * absolutely necessary.
         *
         * Developers may want to consider disabling focus trapping if this
         * overlay presents a non-Ionic overlay from a 3rd party library.
         * Developers would disable focus trapping on the Ionic overlay
         * when presenting the 3rd party overlay and then re-enable
         * focus trapping when dismissing the 3rd party overlay and moving
         * focus back to the Ionic overlay.
         */
        this.focusTrap = true;
        /**
         * @internal
         */
        this.demo = false;
    }
    connectedCallback() {
        this.bodyScrollHandler.connect();
        prepareOverlay(this);
        if (balBrowser.hasDocument && this.demo) {
            this.open();
        }
    }
    disconnectedCallback() {
        this.bodyScrollHandler.disconnect();
    }
    /**
     * @internal Opens the modal.
     */
    async open() {
        await deepReady(this.usersElement);
        this.setModalActiveOnBody();
        writeTask(() => {
            if (this.modalBackgroundElement) {
                this.modalBackgroundElement.classList.add('fadeIn');
            }
            if (this.modalContentElement) {
                this.modalContentElement.classList.add('fadeInDown');
            }
        });
        if (this.presented) {
            return;
        }
        this.willPresent.emit();
        this.presented = true;
        await wait(150);
        writeTask(() => {
            if (this.modalBackgroundElement) {
                this.modalBackgroundElement.classList.remove('fadeIn');
            }
            if (this.modalContentElement) {
                this.modalContentElement.classList.remove('fadeInDown');
            }
        });
        this.didPresent.emit();
    }
    /**
     * @internal Closes the modal.
     */
    async close() {
        this.willDismiss.emit();
        this.unsetModalActiveOnBody();
        this.presented = false;
        this.didDismiss.emit();
    }
    /**
     * Presents the modal through the modal controller
     */
    async present() {
        this.setModalActiveOnBody();
        if (this.presented) {
            return;
        }
        const container = this.el.querySelector(`.bal-modal__content`);
        if (!container) {
            throw new Error('container is undefined');
        }
        const componentProps = Object.assign(Object.assign({}, this.componentProps), { modal: this.el });
        this.usersElement = await attachComponent(this.delegate, container, this.component, [], componentProps);
        await this.open();
    }
    /**
     * Closes the presented modal with the modal controller
     */
    async dismiss(data, role) {
        this.unsetModalActiveOnBody();
        if (this.delegate === undefined) {
            await this.close();
            return true;
        }
        const dismissed = await dismiss(this, data, role, async () => {
            writeTask(() => {
                if (this.modalBackgroundElement) {
                    this.modalBackgroundElement.classList.add('fadeOut');
                }
                if (this.modalContentElement) {
                    this.modalContentElement.classList.add('fadeOutUp');
                }
            });
            await wait(140);
        });
        if (dismissed) {
            await detachComponent(this.delegate, this.usersElement);
        }
        return dismissed;
    }
    /**
     * Returns a promise that resolves when the modal did dismiss.
     */
    onDidDismiss() {
        return eventMethod(this.el, 'balModalDidDismiss');
    }
    /**
     * Returns a promise that resolves when the modal will dismiss.
     */
    onWillDismiss() {
        return eventMethod(this.el, 'balModalWillDismiss');
    }
    async onClickCloseButton(ev) {
        if (this.isClosable && this.presented && ev && ev.target) {
            const element = ev.target;
            const closestBalButton = element.closest('bal-button');
            if (closestBalButton && closestBalButton.hasAttribute('modal-close')) {
                await this.dismiss(undefined, 'model-close');
            }
            if (this.backdropDismiss && this.isClickedOutsideOnMouseUp && this.isClickedOutsideOnMouseDown) {
                await this.dismiss(undefined, 'model-close');
            }
        }
    }
    async onMouseDown(ev) {
        this.isClickedOutsideOnMouseDown = this.isClickedOutside(ev);
    }
    async onMouseUp(ev) {
        this.isClickedOutsideOnMouseUp = this.isClickedOutside(ev);
    }
    async handleKeyUp(ev) {
        const modals = Array.from(document.querySelectorAll('bal-modal')).filter(el => el.hasAttribute('aria-presented'));
        const numbers = modals
            .map(el => el.overlayIndex)
            .map(num => parseInt(num))
            .filter(num => !Number.isNaN(num));
        const max = Math.max(...numbers);
        if (this.overlayIndex === max) {
            ev.preventDefault();
            ev.stopPropagation();
            if (this.presented && this.isClosable) {
                if (ev.key === 'Escape' || ev.key === 'Esc') {
                    if (this.delegate) {
                        await this.dismiss(undefined, 'model-escape');
                    }
                    else {
                        await this.close();
                    }
                }
            }
        }
    }
    setModalActiveOnBody() {
        if (!this.demo) {
            this.bodyScrollHandler.disable();
        }
    }
    unsetModalActiveOnBody() {
        this.bodyScrollHandler.enable();
    }
    isClickedOutside(ev) {
        if (this.isClosable && this.presented && ev && ev.target && this.backdropDismiss) {
            const element = ev.target;
            return element.classList.contains('bal-modal__container');
        }
        return false;
    }
    render() {
        return (h(Host, { key: '21dbd50aedd60d75a2960d6701b44cf61ccc7329', "aria-modal": "true", "aria-presented": this.presented ? 'true' : null, "data-testid": this.dataTestId, tabindex: "-1", class: Object.assign({ 'bal-modal': true, 'bal-modal--is-closable': this.isClosable, 'bal-modal--is-active': this.presented, [FOCUS_TRAP_DISABLE_CLASS]: this.focusTrap === false }, getClassMap(this.cssClass)), style: {
                '--bal-width': `${this.modalWidth}px`,
            } }, h("div", { key: '69921023055a78f365056dda59e297e985220d4a', class: {
                'bal-modal__background': true,
                'is-hidden': !this.hasBackdrop,
            }, ref: div => (this.modalBackgroundElement = div) }), h("div", { key: '59af5c19fcfb216e36a1d2ac540f25f35be03c59', class: {
                'bal-modal__container': true,
            }, ref: div => (this.modalContainerElement = div) }, h("div", { key: '02dd5fe3d3172f0aea3c0b3b7a3a6882ad8fb39b', class: {
                'bal-modal__content': true,
                [`bal-modal__content--has-spacing-${this.space}`]: true,
            }, ref: div => (this.modalContentElement = div) }, h("slot", { key: '3b5532f46d38d8b598be0540df655f4f813629fb' })))));
    }
    get el() { return getElement(this); }
};
Modal.style = balModalCss;

const ModalBody = class {
    constructor(hostRef) {
        registerInstance(this, hostRef);
    }
    render() {
        return (h(Host, { key: '2bef5892f7f6e90bb4c893f4c5ca5027dece343a', class: "bal-modal__body" }, h("slot", { key: '45b45f4141bd105c11f57628e6ea2ba989ef1a55' })));
    }
};

const ModalHeader = class {
    constructor(hostRef) {
        registerInstance(this, hostRef);
        this.closeHandler = () => {
            if (this.parentModal) {
                this.parentModal.dismiss(undefined, 'model-close');
            }
        };
    }
    get parentModal() {
        return this.el.closest('bal-modal');
    }
    render() {
        var _a;
        return (h(Host, { key: 'b115e1393596c7d7124ce8b3015e4a2c4c56dcd4', class: "bal-modal__header" }, h("div", { key: '06407c1c1848ea62615f30aaa13966facb3e5246', class: "bal-modal__header__title" }, h("bal-heading", { key: 'c0784a83d66a5d28e028fc66f26b8ef72f5689df', level: "h2", space: "none" }, h("slot", { key: '41a254e6b622293d5ef84a65e7b0c02241bc7014' }))), ((_a = this.parentModal) === null || _a === void 0 ? void 0 : _a.isClosable) ? (h("bal-close", { class: "bal-modal__header__close data-test-modal-close", onClick: this.closeHandler })) : ('')));
    }
    get el() { return getElement(this); }
};

export { Modal as bal_modal, ModalBody as bal_modal_body, ModalHeader as bal_modal_header };
