/*!
 * Custom elements for Nanopore-Digital Web applications
 */
'use strict';

var index = require('./index-DGttnXif.js');
var renderer = require('./renderer-jVpDRMfV.js');
var modal = require('./modal-BlzeVZW4.js');
var scroll = require('./scroll-C6pO9RvO.js');
var slot = require('./slot-CfuOT0U4.js');
var componentStore = require('./component-store-C5eBOK0w.js');
var tabbable = require('./tabbable-C-YwPfjA.js');
require('./dom-Dxk5vXYq.js');
require('./throttle-CrRDOkln.js');

const dialogCss = ":host,*,*::before,*::after{box-sizing:border-box}[hidden]{display:none !important}@media (prefers-reduced-motion: reduce){:host,*,*::before,*::after{animation-duration:0.01ms !important;animation-iteration-count:1 !important;transition-duration:0.01ms !important;scroll-behavior:auto !important}}:host,*,*::before,*::after{box-sizing:border-box}[hidden]{display:none !important}@media (prefers-reduced-motion: reduce){:host,*,*::before,*::after{animation-duration:0.01ms !important;animation-iteration-count:1 !important;transition-duration:0.01ms !important;scroll-behavior:auto !important}}:host{--border-radius:0;--content-background:var(--nano-color-surface-300);--content-color:var(--nano-color-base-1000);--footer-content:var(--nano-color-neutral-75);--scrim-color:var(--nano-overlay-background-color);--box-shadow:var(--nano-shadow-l3);--close-button-color:var(--nano-color-primary-1200);--width:50rem;--height:auto;--body-padding-v:var(--nano-spacing-l1-default);--body-padding-h:var(--nano-spacing-l1-default);--header-padding-v:var(--nano-spacing-l);--header-padding-h:var(--nano-spacing-l1-default);--footer-padding-v:var(--nano-spacing-l);--footer-padding-h:var(--nano-spacing-l1-default)}.dialog{display:flex;align-items:center;justify-content:center;position:fixed;inset:0;z-index:var(--nano-z-index-modal);border:none;inline-size:unset;block-size:unset;color:var(--content-color);background-color:unset}.dialog::backdrop{display:none}.dialog__panel{display:flex;flex-direction:column;z-index:2;inline-size:var(--width);block-size:var(--height);max-inline-size:calc(100% - (var(--nano-spacing-xl) + var(--nano-scroll-lock-size)));max-block-size:calc(92vh - var(--nano-spacing-xl));background-color:var(--content-background);border-radius:var(--border-radius);box-shadow:var(--box-shadow);opacity:0;transform:scale(0.8);transition:var(--nano-transition-fast) opacity, var(--nano-transition-fast) transform}.dialog__panel:focus{outline:none}.dialog--open .dialog__panel{display:flex;opacity:1;transform:none}.dialog--nodismiss .dialog__panel{animation:cannotClose 0.25s ease-in-out 1}@keyframes cannotClose{0%{transform:scale(1)}50%{transform:scale(1.08)}100%{transform:scale(1)}}.dialog__header{flex:0 0 auto;display:flex;inline-size:100%;background-color:var(--content-background);border-radius:var(--border-radius) var(--border-radius) 0 0;transition:var(--nano-transition-x-fast) box-shadow;min-inline-size:auto;padding-block:var(--header-padding-v);padding-inline:var(--header-padding-h)}[stuck] .dialog__header{box-shadow:var(--nano-shadow-l0)}.dialog__title{flex:1 1 auto;font-weight:var(--nano-font-weight-normal);font-size:var(--nano-font-size-xl);line-height:var(--nano-line-height-denser);text-wrap:balance}.dialog__close-icon{flex:0 0 auto;display:flex;align-items:center;font-size:1.375rem;position:relative;inset-inline-end:calc(var(--nano-spacing-l1-default) / 2 * -1);--color:var(--close-button-color)}.dialog__body-wrap{flex:1 1 auto;overflow:auto;-webkit-overflow-scrolling:touch;border-radius:var(--border-radius)}.dialog:not(.dialog--has-header) .dialog__body-wrap{border-start-start-radius:0;border-start-end-radius:0;border-end-start-radius:inherit;border-end-end-radius:inherit}.dialog:not(.dialog--has-footer) .dialog__body-wrap{border-start-start-radius:inherit;border-start-end-radius:inherit;border-end-start-radius:0;border-end-end-radius:0}.dialog__body{padding-block:0 var(--body-padding-v);padding-inline:var(--body-padding-h)}.dialog:not(.dialog--has-header) .dialog__body{padding-block-start:var(--body-padding-v)}.dialog__body ::slotted(*){max-inline-size:100%}.dialog__footer{inline-size:100%;padding-block:var(--footer-padding-v);padding-inline:var(--footer-padding-h);background:var(--footer-content);border-radius:0 0 var(--border-radius) var(--border-radius);position:relative;inset-block-start:1px;min-inline-size:auto;border-block-start:1px solid var(--nano-color-neutral-300);gap:var(--nano-spacing-md);display:inline-flex}.dialog:not(.dialog--has-footer) .dialog__footer{display:none}.dialog__overlay{position:fixed;inset:0 !important;background-color:var(--scrim-color);opacity:0;transition:var(--nano-transition-fast) opacity}.dialog--open .dialog__overlay{opacity:1}";

let id = 0;
const Dialog = class {
    constructor(hostRef) {
        index.registerInstance(this, hostRef);
        this.nanoShow = index.createEvent(this, "nanoShow", 7);
        this.nanoAfterShow = index.createEvent(this, "nanoAfterShow", 7);
        this.nanoHide = index.createEvent(this, "nanoHide", 7);
        this.nanoAfterHide = index.createEvent(this, "nanoAfterHide", 7);
        this.nanoInitialFocus = index.createEvent(this, "nanoInitialFocus", 7);
        this.nanoRequestClose = index.createEvent(this, "nanoRequestClose", 7);
    }
    componentId = `dialog-${++id}`;
    modal;
    willShow = false;
    willHide = false;
    originalTrigger;
    overlay;
    dialog;
    slotCtrl = new slot.HasSlotController(this, 'footer');
    get panel() {
        return this._panel;
    }
    set panel(p) {
        if (this._panel) {
            this.panel.removeEventListener('transitionend', this.handleTransitionEnd);
        }
        p.addEventListener('transitionend', this.handleTransitionEnd);
        this._panel = p;
    }
    _panel;
    get host() { return index.getElement(this); }
    noDismiss = false;
    hidden = true;
    /** Show a colour ribbon at the top of the modal */
    showRibbon = true;
    /** Indicates whether or not the dialog is open. You can use this in lieu of the show/hide methods. */
    open = false;
    handleOpenChange() {
        if (this.open)
            this.show();
        else
            this.hide();
    }
    /** The dialog's label as displayed in the header. You should always include a relevant
     * label even when using `no-header`, as it is required for proper accessibility. */
    label;
    /** Set to true to disable the header. This will also remove the default close button,
     * so please ensure you  provide an easy, accessible way for users to dismiss the dialog. */
    noHeader = false;
    /** An alternative to `preventDefault()` on the `nanoRequestClose` event. This will hide the close button and disable clicks on the overlay or presses the `Escape` key  */
    noUserDismiss = false;
    /** Store search queries (against this ID) to the component store. Use in conjunction with storeMethod */
    storeId;
    /** The method of storage. Either session storage, url hash (after the '#') or url query (after the '?'). */
    storeMethod = 'url-hash';
    /** Relocate the dialog to the root of the DOM. Useful for elements bound via css `transform: ...` */
    hoist = false;
    handleHoistChange() {
        // if native popover is supported then bail as this is not required
        if ('popover' in globalThis.HTMLElement.prototype ||
            !this.hoist ||
            Array.from(document.body.children).includes(this.host))
            return;
        document.body.prepend(this.host);
    }
    /** Emitted when the dialog opens. Calling `event.preventDefault()` will prevent it from being opened. */
    nanoShow;
    /** Emitted after the dialog opens and all transitions are complete. */
    nanoAfterShow;
    /** Emitted when the dialog closes. Calling `event.preventDefault()` will prevent it from being closed. */
    nanoHide;
    /** Emitted after the dialog closes and all transitions are complete. */
    nanoAfterHide;
    /** Emitted when the dialog opens and the panel gains focus. Calling `event.preventDefault()` will prevent
     * focus and allow you to set it on a different element in the dialog, such as an input or button. */
    nanoInitialFocus;
    /** Emitted when the user clicks the close button, clicks the overlay, or presses the `Escape` key. Calling `event.preventDefault()` will prevent the dialog from closing. */
    nanoRequestClose;
    /** Shows the dialog */
    async show() {
        if (this.willShow) {
            return;
        }
        const nanoShow = this.nanoShow.emit();
        if (nanoShow.defaultPrevented) {
            this.open = false;
            return;
        }
        if (this.dialog)
            this.dialog.hidden = false;
        this.originalTrigger = document.activeElement;
        this.willShow = true;
        this.hidden = false;
        this.open = true;
        this.modal.activate();
        if (typeof this.dialog?.showPopover === 'function') {
            this.dialog.showPopover();
        }
        scroll.lockBodyScrolling(this.host);
        // When the drawer is shown, Safari will attempt to set focus on whatever element has autofocus. This causes the
        // drawer's animation to jitter.
        const autoFocusTarget = this.host.querySelector('[autofocus]');
        if (autoFocusTarget) {
            autoFocusTarget.removeAttribute('autofocus');
        }
        // Wait for the next frame before setting initial focus so the dialog is technically visible
        this.host.addEventListener('nanoAfterShow', () => {
            const nanoInitialFocus = this.nanoInitialFocus.emit();
            if (!nanoInitialFocus.defaultPrevented) {
                const firstTabbable = autoFocusTarget ||
                    tabbable.getTabbableElements(this.host, true, true, true)[0] ||
                    this.panel;
                firstTabbable.focus({ preventScroll: true });
            }
        }, { once: true });
    }
    /** Hides the dialog */
    async hide() {
        if (this.willHide) {
            return;
        }
        const nanoHide = this.nanoHide.emit();
        if (nanoHide.defaultPrevented) {
            this.open = true;
            return;
        }
        this.willHide = true;
        this.open = false;
        this.modal.deactivate();
        this.stopVideos();
        // Restore focus to the original trigger
        const trigger = this.originalTrigger;
        if (trigger) {
            if (trigger['setFocus'] && typeof trigger['setFocus'] === 'function') {
                // @ts-expect-error setFocus is a custom method on the element
                trigger.setFocus();
            }
            else
                trigger.focus();
        }
        setTimeout(() => {
            if (!this.open && typeof this.dialog?.hidePopover === 'function') {
                this.dialog.hidePopover();
            }
            scroll.unlockBodyScrolling(this.host);
        }, 300);
    }
    handleKeyDown = (event) => {
        if (event.key === 'Escape') {
            this.requestClose();
        }
    };
    requestClose = () => {
        const nanoOverlayDismiss = this.nanoRequestClose.emit();
        if (!nanoOverlayDismiss.defaultPrevented && !this.noUserDismiss) {
            this.hide();
        }
        else {
            this.noDismiss = true;
            setTimeout(() => (this.noDismiss = false), 250);
        }
    };
    handleTransitionEnd = (event) => {
        if (event.propertyName === 'opacity' &&
            event
                .composedPath()
                .find((node) => node === this.panel || node === this.overlay)) {
            // Ensure we only emit one event when the target element is no longer visible
            this.willShow = false;
            this.willHide = false;
            if (this.open)
                this.nanoAfterShow.emit();
            else
                this.nanoAfterHide.emit();
            if (!this.open) {
                this.dialog.hidden = true;
                this.hidden = true;
            }
        }
    };
    stopVideos() {
        const videos = Array.from(this.host.querySelectorAll('iframe,video'));
        videos.forEach((video) => {
            if (video.tagName.toLowerCase() === 'video')
                video.pause();
            else {
                const src = video.src;
                video.src = src;
            }
        });
    }
    connectedCallback() {
        this.handleHoistChange();
        this.modal = new modal.Modal(this.host);
    }
    componentWillLoad() {
        if (this.storeId) {
            componentStore.ComponentStore.init(this, ['open'], this.storeMethod, this.storeId);
        }
    }
    componentDidLoad() {
        this.dialog.hidden = !this.open;
        // Show on init if open
        if (this.open) {
            this.show();
            this.nanoAfterShow.emit();
        }
    }
    disconnectedCallback() {
        scroll.unlockBodyScrolling(this.host);
        if (!this.panel)
            return;
        this.panel.removeEventListener('transitionend', this.handleTransitionEnd);
    }
    render() {
        return (renderer.h(index.Host, { key: 'b6ba3eea63e7aee1da10dca2a653a6c9f7d66266', class: "nano-dialog" }, renderer.h("div", { key: '8ac30cda032a4fbc89b432f16ce3e9adb88ca68e', part: "base", class: {
                dialog: true,
                'dialog--open': this.open,
                'dialog--has-footer': this.slotCtrl.has('footer'),
                'dialog--has-header': !this.noHeader,
                'dialog--nodismiss': this.noDismiss,
                'dialog--with-ribbon': this.showRibbon,
            }, onKeyDown: this.handleKeyDown, ref: (ele) => (this.dialog = ele), popover: "manual" }, renderer.h("div", { key: '4d2cde77fa9c8796daa2591eb425d1694f211d90', part: "overlay", class: "dialog__overlay", ref: (el) => (this.overlay = el), onClick: this.requestClose }), renderer.h("div", { key: 'a99ea663fbb2560aaa8f49f23325a661f96dece6', ref: (el) => (this.panel = el), part: "panel", class: "dialog__panel", role: "dialog", "aria-modal": "true", "aria-hidden": !this.hidden ? 'false' : 'true', "aria-label": this.noHeader ? this.label : null, "aria-labelledby": !this.noHeader ? `${this.componentId}-title` : null, tabIndex: -1 }, renderer.h("div", { key: '0e0bab9c4307d64cd9d7deb14603d1a5e1f9d27c', class: "dialog__body-wrap" }, !this.noHeader && (renderer.h("nano-sticker", { key: '6f1ea1f827d3a18622515f57b5c55d9cb4daa8a0' }, renderer.h("header", { key: 'd1cb39f7c1878810f85c7641fdae2217180327b3', part: "header", class: "dialog__header" }, renderer.h("span", { key: '7f0ac92358b64688eca01979fd68a665802636d6', part: "title", class: "dialog__title", id: `${this.componentId}-title` }, renderer.h("slot", { key: '9b53b34fa5f815a46e9bbd961acecbe592b14cb5', name: "label" }, this.label || String.fromCharCode(65279))), !this.noUserDismiss && (renderer.h("nano-icon-button", { key: '4b110b4b490ede1f757046d252de8e2015f50d6e', part: "close-button", exportparts: "base:close-button__base", class: "dialog__close-icon", label: "close dialog", onClick: this.requestClose, iconName: "light/xmark" }))))), renderer.h("div", { key: 'f2225d9d4753b91afd697466b897e20441704f82', part: "body", class: "dialog__body" }, renderer.h("slot", { key: '1bc02a8964d47650a45dd047bac390615823b176' })), this.slotCtrl.has('footer') && (renderer.h("nano-sticker", { key: '9cca925aa007316b93475d54194278ee69fcfdd6', position: "bottom" }, renderer.h("footer", { key: '8b1b57752c43c3e010361c90da2cd3e647243828', part: "footer", class: "dialog__footer" }, renderer.h("slot", { key: '3fdf3ec86fb5efd8a97a8ddee887dac53d3f58be', name: "footer" })))))))));
    }
    static get watchers() { return {
        "open": ["handleOpenChange"],
        "hoist": ["handleHoistChange"]
    }; }
};
Dialog.style = dialogCss;

exports.nano_dialog = Dialog;
