/*!
 * Built with Stencil
 * By PostNord.
 */
import { h, Host, forceUpdate, } from "@stencil/core";
import { awaitTopbar, en, isSmallScreen, reduceMotion } from "../../../index";
import { close as closeIcon } from "pn-design-assets/pn-assets/icons.js";
import { translations } from "./translation";
/**
 * Present content in a modal that overlays everything on the current page.
 * Use the prop `open` to toggle the visiblity.
 * Use the event `modalToggle` to determine when the modal is being closed/opened by the user.
 *
 * @slot - The default slot, will be placed in the middle content area.
 * @slot image - Place an image or illustration at the top of the modal. {@since v7.15.0}
 * @slot header - Place the title + lead text in the header. {@since v7.14.0}
 * @slot buttons - Place buttons inside the modal at the bottom.
 * pn-buttons aligns automatically to the right, set the data-left attribute on the button you want to align to the left.
 */
export class PnModal {
    mo;
    standardAnimationDuration = 400;
    animationDuration = this.standardAnimationDuration;
    modalTimeout;
    modalElement;
    modalContainer;
    modalPicture;
    hostElement;
    isClosing = false;
    isOpening = false;
    /** If true, the modal content will remove overflow CSS property. */
    removeOverflow = false;
    /** Set a label for the modal. @since v7.14.0 */
    label;
    /** Set a descriptive text for the modal. @since v7.14.0 */
    helpertext;
    /** Set the language. @since v7.14.0 */
    language = null;
    /** Bind to this property if you want to control the visibility of the modal from your own data. @category Features */
    open = false;
    /**
     * Prevent users from closing the modal by clicking on the backdrop or the `ESC` key.
     * @since v7.14.0
     * @category Features
     */
    persistent = false;
    /**
     * Hide the close button. If you disable this, make sure you build your own cancel button.
     * @since v7.14.0
     * @category Features
     */
    hideClose = false;
    /**
     * Allow overflow if possible. When the modal opens, it will check scrollHeight > offsetHeight.
     * Do not use if you have a lot of conditional rendering inside the modal.
     * @since v7.14.0
     */
    allowOverflow = false;
    /**
     * Use the `sheet` visual. Aligns the modal to the right.
     * @since v7.14.0
     * @category Visual
     */
    sheet = false;
    /**
     * Define your own max width of the modal. Default is `45em`.
     * @category Visual
     * @since v7.14.0
     */
    maxWidth = null;
    handleOpen() {
        if (this.open)
            this.openModal();
        else {
            this.closeModal();
            /** In the next update, we can remove this one so you can finally stack modals. */
            this.close.emit(true);
        }
        this.handleOverflow();
        clearTimeout(this.modalTimeout);
        this.isClosing = !this.open && true;
        if (reduceMotion())
            this.animationDuration = 0;
        else
            this.animationDuration = this.standardAnimationDuration;
        this.modalTimeout = setTimeout(() => {
            this.isClosing = false;
            this.modalVisiblity.emit({ visible: this.open });
        }, this.animationDuration);
    }
    handleMaxWidth() {
        const width = this.maxWidth || '45em';
        this.modalElement.style.setProperty('--pn-modal-max-width', width);
    }
    handleOverflow() {
        if (this.allowOverflow)
            this.setOverflow();
    }
    /** This event is fired when the modal is toggled. {@since v7.14.0} */
    modalToggle;
    /** This event is dispatched after the opening/closing animation has finished playing. {@since v7.14.0} */
    modalVisiblity;
    /**
     * Event fired when the modal is closed, either by clicking on the dark background or by clicking on the close button.
     * @deprecated Use the new `modalToggle` event instead.
     */
    close;
    connectedCallback() {
        this.mo = new MutationObserver(() => forceUpdate(this.hostElement));
        this.mo.observe(this.hostElement, { childList: true, subtree: true });
    }
    disconnectedCallback() {
        if (this.mo)
            this.mo.disconnect();
    }
    async componentWillLoad() {
        if (this.language === null)
            await awaitTopbar(this.hostElement);
    }
    componentDidLoad() {
        this.handleMaxWidth();
        if (this.open)
            this.openModal();
    }
    translate(prop) {
        return translations?.[prop]?.[this.language || en] || prop;
    }
    showImage() {
        return !!this.modalPicture?.innerHTML;
    }
    showHeader() {
        return !!(this.label || this.helpertext || this.hostElement.querySelector('[slot="header"]')?.textContent);
    }
    setOverflow() {
        this.removeOverflow = !this.hasOverflow();
    }
    hasOverflow() {
        const multiplyWith = isSmallScreen() ? 0.95 : 0.85;
        return this.modalContainer?.scrollHeight > innerHeight * multiplyWith;
    }
    isSameModal(target) {
        return this.modalElement.isSameNode(target);
    }
    handleKeyboard(event) {
        if (event.key !== 'Escape')
            return;
        event.preventDefault();
        event.stopImmediatePropagation();
        if (!this.persistent)
            this.setModalClose();
    }
    clickModalBackground(event) {
        const { clientY, clientX } = event;
        const notInsideAnyModal = event.target.localName !== this.modalElement.localName;
        const notThisModal = !this.isSameModal(event.target);
        if (notInsideAnyModal || notThisModal)
            return;
        const { top, left, height, width } = this.modalElement.getBoundingClientRect();
        const isInModal = top <= clientY && clientY <= top + height && left <= clientX && clientX <= left + width;
        if (!isInModal && !this.persistent)
            this.toggleOpen(false);
    }
    setModalClose() {
        this.toggleOpen(false);
    }
    closeModal() {
        this.modalElement.close();
    }
    openModal() {
        this.modalElement.showModal();
    }
    toggleOpen(state) {
        this.open = state ?? !this.open;
    }
    render() {
        return (h(Host, { key: 'd965a05833b311fed1f1f7ba245c9401ab77b765' }, h("dialog", { key: 'd60d253a75dd3f82b684fce659a9a917d6181c62', class: "pn-modal", "data-closing": this.isClosing, "data-sheet": this.sheet, "data-image": this.showImage(), "data-allow-overflow": this.removeOverflow, onClose: () => this.setModalClose(), onCancel: () => this.setModalClose(), onToggle: () => this.modalToggle.emit({ open: this.open }), onKeyDown: event => this.handleKeyboard(event), onClick: event => this.clickModalBackground(event), ref: el => (this.modalElement = el) }, !this.hideClose && (h("pn-button", { key: '4d25a2e559a8aca6286a9fc7a94f82285bd8ad4e', small: true, class: "pn-modal-close-button", icon: closeIcon, iconOnly: true, arialabel: this.translate('CLOSE_MODAL'), appearance: "light", variant: "borderless", type: "button", onPnClick: () => this.setModalClose() })), h("div", { key: '3953eef2505ccda4786177c01ae9af92874d65a1', class: "pn-modal-container", ref: el => (this.modalContainer = el) }, h("div", { key: 'de0730ef36d305f2ff2652510838df85bdbdee5e', class: "pn-modal-image", hidden: !this.showImage() }, h("picture", { key: 'c26ae160c243b630d7a1ba71a8d4cac523096cfd', class: "pn-modal-picture", ref: el => (this.modalPicture = el) }, h("slot", { key: '4d2425b17367b4ccd2215e54cfedbee6731a9daf', name: "image" }))), h("header", { key: '815bef72c5b9a2982b7dd62059314ef120221ee0', class: "pn-modal-header", hidden: !this.showHeader() }, this.label && h("h2", { key: '41ae0e9a7d8adca27764bf6be026d0bc59df9b90', class: "pn-modal-label" }, this.label), this.helpertext && h("p", { key: '4fac7c6daf49eaff4a56b7c217f49e7f0507299f', class: "pn-modal-text" }, this.helpertext), h("slot", { key: '8ce017defaa66a4bfec5ef38398b3104ed0ff7f9', name: "header" })), h("section", { key: '3ad1dc180db0ad42a4fa99dc6c9a17fc153af362', class: "pn-modal-content" }, h("slot", { key: 'bddef9aa3cd8b78be3facd5ebd3e88d72b9eb219' })), h("nav", { key: 'edc771b8ca813ed6c9b20f688847c9c22072f0a1', class: "pn-modal-buttons" }, h("slot", { key: '75dcf50e07c985f95836251881b8c214bc1b58c6', name: "buttons" }))))));
    }
    static get is() { return "pn-modal"; }
    static get originalStyleUrls() {
        return {
            "$": ["pn-modal.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["pn-modal.css"]
        };
    }
    static get properties() {
        return {
            "label": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.14.0"
                        }],
                    "text": "Set a label for the modal."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "label"
            },
            "helpertext": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.14.0"
                        }],
                    "text": "Set a descriptive text for the modal."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "helpertext"
            },
            "language": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "PnLanguages",
                    "resolved": "\"\" | \"da\" | \"en\" | \"fi\" | \"no\" | \"sv\"",
                    "references": {
                        "PnLanguages": {
                            "location": "import",
                            "path": "@/index",
                            "id": "src/index.ts::PnLanguages",
                            "referenceLocation": "PnLanguages"
                        }
                    }
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.14.0"
                        }],
                    "text": "Set the language."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "language",
                "defaultValue": "null"
            },
            "open": {
                "type": "boolean",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Bind to this property if you want to control the visibility of the modal from your own data."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "open",
                "defaultValue": "false"
            },
            "persistent": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.14.0"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Prevent users from closing the modal by clicking on the backdrop or the `ESC` key."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "persistent",
                "defaultValue": "false"
            },
            "hideClose": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.14.0"
                        }, {
                            "name": "category",
                            "text": "Features"
                        }],
                    "text": "Hide the close button. If you disable this, make sure you build your own cancel button."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "hide-close",
                "defaultValue": "false"
            },
            "allowOverflow": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.14.0"
                        }],
                    "text": "Allow overflow if possible. When the modal opens, it will check scrollHeight > offsetHeight.\nDo not use if you have a lot of conditional rendering inside the modal."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "allow-overflow",
                "defaultValue": "false"
            },
            "sheet": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "since",
                            "text": "v7.14.0"
                        }, {
                            "name": "category",
                            "text": "Visual"
                        }],
                    "text": "Use the `sheet` visual. Aligns the modal to the right."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "sheet",
                "defaultValue": "false"
            },
            "maxWidth": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "category",
                            "text": "Visual"
                        }, {
                            "name": "since",
                            "text": "v7.14.0"
                        }],
                    "text": "Define your own max width of the modal. Default is `45em`."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "max-width",
                "defaultValue": "null"
            }
        };
    }
    static get states() {
        return {
            "isClosing": {},
            "isOpening": {},
            "removeOverflow": {}
        };
    }
    static get events() {
        return [{
                "method": "modalToggle",
                "name": "modalToggle",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "This event is fired when the modal is toggled. {@since v7.14.0}"
                },
                "complexType": {
                    "original": "{ open: boolean }",
                    "resolved": "{ open: boolean; }",
                    "references": {}
                }
            }, {
                "method": "modalVisiblity",
                "name": "modalVisiblity",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "This event is dispatched after the opening/closing animation has finished playing. {@since v7.14.0}"
                },
                "complexType": {
                    "original": "{ visible: boolean }",
                    "resolved": "{ visible: boolean; }",
                    "references": {}
                }
            }, {
                "method": "close",
                "name": "close",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [{
                            "name": "deprecated",
                            "text": "Use the new `modalToggle` event instead."
                        }],
                    "text": "Event fired when the modal is closed, either by clicking on the dark background or by clicking on the close button."
                },
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                }
            }];
    }
    static get elementRef() { return "hostElement"; }
    static get watchers() {
        return [{
                "propName": "open",
                "methodName": "handleOpen"
            }, {
                "propName": "maxWidth",
                "methodName": "handleMaxWidth"
            }];
    }
    static get listeners() {
        return [{
                "name": "resize",
                "method": "handleOverflow",
                "target": "window",
                "capture": false,
                "passive": true
            }];
    }
}
