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

var index = require('./index-DGttnXif.js');
var dom = require('./dom-Dxk5vXYq.js');
var tabbable = require('./tabbable-C-YwPfjA.js');
var renderer = require('./renderer-jVpDRMfV.js');
var slot = require('./slot-CfuOT0U4.js');
var activeElement = require('./active-element-Vtuxns0n.js');

/**
 * Quality of life for transition handling.
 * Adds / removes transitionend events. Resolves on complete

 * @param el element
 * @returns a promise that resolves when the transition is done
 */
/**
 * handles hiding and showing elements properly (with display),
 * along with transitions, so they are no longer viewable in the dom.
 * - OnHide remove show class, listen for transition end, then display: none on finish
 * - OnShow, display block on start then add a show class
 *
 * @param el
 * @param options
 * @returns a promise of resolving as either 'show' or 'hidden'
 */
const displayTransition = (el, options) => {
    const opts = {
        className: '',
        show: true,
        showDisplay: 'block',
        showProp: 'classList',
        timeout: 1000,
        ...options,
    };
    return new Promise((resolve) => {
        const showCb = (e) => {
            if ((e.target === el || e.composedPath().some((el) => el === e.target)) &&
                (!opts.transitionProp || opts.transitionProp.includes(e.propertyName))) {
                el.dataset.displayTransition = 'true';
                el.removeEventListener('transitionend', showCb);
                resolve('shown');
            }
        };
        const hideCb = (e) => {
            if ((e.target === el || e.composedPath().some((el) => el === e.target)) &&
                (!opts.transitionProp || opts.transitionProp.includes(e.propertyName))) {
                el.style.display = 'none';
                el.dataset.displayTransition = 'false';
                el.removeEventListener('transitionend', hideCb);
                resolve('hidden');
            }
        };
        if (opts.show) {
            el.addEventListener('transitionend', showCb);
            el.style.display = opts.showDisplay;
            setTimeout(() => el[opts.showProp].add(opts.className), 50);
        }
        else {
            el.addEventListener('transitionend', hideCb);
            el[opts.showProp].remove(opts.className);
        }
        // If no transition, resolve after timeout
        if (opts.timeout) {
            setTimeout(() => {
                if (opts.show && el.dataset.displayTransition !== 'true') {
                    el.dataset.displayTransition = 'true';
                    el.removeEventListener('transitionend', showCb);
                    resolve('shown');
                }
                else if (!opts.show && el.dataset.displayTransition !== 'false') {
                    el.style.display = 'none';
                    el.dataset.displayTransition = 'false';
                    el.removeEventListener('transitionend', hideCb);
                    resolve('hidden');
                }
            }, opts.timeout);
        }
    });
};

const navItemCss = ":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{display:contents}.navitem{background:inherit;color:inherit}a,button{all:unset;color:inherit;text-decoration:inherit;cursor:pointer;display:flex;align-items:center;justify-content:space-between;padding:var(--padding);gap:var(--nano-spacing-md);inline-size:100%;box-sizing:border-box;background:inherit}a:hover,a:focus,a:active,button:hover,button:focus,button:active{color:inherit}a:focus-visible,button:focus-visible{outline:var(--nano-focus-ring);outline-offset:var(--nano-focus-ring-offset)}a[disabled],button[disabled]{opacity:0.5;cursor:not-allowed}.navitem__label{margin-inline-end:auto}.navitem__modal{all:unset;display:none;position:absolute;color:initial;opacity:0;transition:var(--nano-transition-fast) ease}.navitem--open .navitem__modal{opacity:1}::slotted([slot=close-button]){all:unset}::slotted([slot=close-button]):focus-visible{outline:var(--nano-focus-ring);outline-offset:var(--nano-focus-ring-offset)}";

const NavItem = class {
    constructor(hostRef) {
        index.registerInstance(this, hostRef);
        this.nanoClose = index.createEvent(this, "nanoClose", 7);
        this.nanoOpen = index.createEvent(this, "nanoOpen", 7);
        this.nanoOpening = index.createEvent(this, "nanoOpening", 7);
        this.nanoClosing = index.createEvent(this, "nanoClosing", 7);
    }
    secondaryDiv;
    slotCtrl = new slot.HasSlotController(this, 'secondary', 'close-button');
    controlElement;
    get host() { return index.getElement(this); }
    didOpen = false;
    isInMenuDrawer = false;
    /** Href to link to. Alternatively, slot an `<a>` element */
    href = null;
    /** Target to use for links */
    target = '_self';
    /** Disable the nav item */
    disabled = false;
    /** Whether a secondary menu should be or is currently open */
    open = false;
    /** Whether this menu item is currently 'selected' */
    selected = false;
    /** Changes behaviour so automatically becomes `selected` onClick */
    checkbox = false;
    /** Whether secondary menus should close on blur */
    closeOnBlur = true;
    /** Emitted when the nav item closes it's secondary navigation. */
    nanoClose;
    /** Emitted when the nav item opens it's secondary navigation. */
    nanoOpen;
    /** Emitted when the nav item is about to open it's secondary navigation. */
    nanoOpening;
    /** Emitted when the nav item is about to close it's secondary navigation. */
    nanoClosing;
    /**
     * Sets focus on the first button or anchor present. Use this method instead of the global
     * `element.focus()`.
     */
    async setFocus() {
        if (!this.controlElement)
            return;
        this.controlElement.focus();
    }
    openChange() {
        if (!this.slotCtrl.has('secondary'))
            return;
        if (this.open)
            this.openSecondary();
        else
            this.closeSecondary();
    }
    didOpenChange() {
        if (!this.slotCtrl.has('secondary'))
            return;
        if (!this.didOpen) {
            /* closing. Remove blur events, add focus back to originating button */
            if (activeElement.focusInContainer(this.host, this.controlElement)) {
                this.controlElement.focus({ preventScroll: true });
            }
            this.nanoClose.emit({ secondaryMenu: this.secondaryDiv });
            return;
        }
        // opening
        /* scroll content into view, focus on it */
        const panelIO = new window.IntersectionObserver((data) => {
            if (data[0].boundingClientRect.top < 0) {
                this.secondaryDiv.scrollIntoView({
                    behavior: 'smooth',
                });
            }
            panelIO.disconnect();
        }, { threshold: 1 });
        panelIO.observe(this.secondaryDiv);
        this.secondaryDiv.focus({ preventScroll: true });
        const focusableChild = tabbable.getTabbableElements(this.secondaryDiv, true);
        if (focusableChild[0]) {
            focusableChild[0].focus({ preventScroll: true });
        }
        this.nanoOpen.emit({ secondaryMenu: this.secondaryDiv });
    }
    handleClose(e) {
        if (!this.didOpen || !this.slotCtrl.has('secondary') || !this.closeOnBlur)
            return;
        if (e.key && e.key === 'Escape') {
            this.closeSecondary();
            return;
        }
        if (!e.composedPath().some((el) => el === this.secondaryDiv)) {
            this.closeSecondary();
        }
    }
    closeSecondary = async () => {
        if (!this.slotCtrl.has('secondary') || !this.open)
            return;
        this.open = false;
        await displayTransition(this.secondaryDiv, {
            className: 'modal--open',
            showProp: 'part',
            show: false,
        });
        this.nanoClosing.emit({ secondaryMenu: this.secondaryDiv });
        this.didOpen = false;
    };
    openSecondary = async () => {
        if (!this.slotCtrl.has('secondary') || this.open)
            return;
        this.open = true;
        await displayTransition(this.secondaryDiv, {
            className: 'modal--open',
            showProp: 'part',
            show: true,
        });
        this.nanoOpening.emit({ secondaryMenu: this.secondaryDiv });
        this.didOpen = true;
    };
    toggleSecondary = () => {
        if (!this.slotCtrl.has('secondary'))
            return;
        if (this.didOpen)
            this.closeSecondary();
        else
            this.openSecondary();
    };
    handleClick = () => {
        if (this.disabled)
            return;
        if (this.slotCtrl.has('secondary')) {
            this.toggleSecondary();
            return;
        }
        if (this.checkbox) {
            this.selected = !this.selected;
        }
    };
    handleDefaultSlotChange = () => {
        const slottedA = dom.getDirectChildren(this.host, 'a')[0];
        if (slottedA) {
            this.href = slottedA.getAttribute('href');
            const label = document.createElement('span');
            slottedA.childNodes.forEach((el) => {
                label.append(el);
            });
            this.host.append(label);
            slottedA.remove();
        }
    };
    /** Closes the secondary nav panel if it is open */
    async closeMenu() {
        this.closeSecondary();
    }
    /** Opens the secondary nav panel if it is not open */
    async openMenu() {
        this.openSecondary();
    }
    connectedCallback() {
        this.handleDefaultSlotChange();
        this.isInMenuDrawer = !!this.host.closest(renderer.transformTag('nano-menu-drawer'));
    }
    componentDidLoad() {
        this.openChange();
    }
    render() {
        return (renderer.h(index.Host, { key: 'b6ce27588c1ca2ac2a42d0aada06d7f554a1174a', class: {
                'nano-menu-drawer': this.isInMenuDrawer,
                'nano-nav-item': true,
                disabled: this.disabled,
            }, role: this.host.closest('[role="menu"]') ? 'menuitem' : undefined, "aria-disabled": this.disabled ? 'true' : undefined }, renderer.h("div", { key: 'e8faa3568a13feb95ef131f0bd412577120fbf84', class: {
                navitem: true,
                'navitem--open': this.open,
                'navitem--active': this.selected,
            }, part: "trigger-wrapper" }, this.href && !this.disabled && (renderer.h("a", { key: '4a4da7478db63015d0dcd81ed053146f8eeac5f3', part: "trigger trigger--anchor", target: this.target, ref: (a) => (this.controlElement = a), href: this.href, class: {
                navitem__trigger: true,
            } }, renderer.h("slot", { key: '1eafb7864368850ad2539c402eb1b00877f3d55e', name: "icon-start" }), renderer.h("span", { key: '8953312d4dad64ced970d2f1120c07b6c36070f1', class: "navitem__label", part: "label" }, renderer.h("slot", { key: '390f468f8d1f5d4f0669cae53ef140e452b16b07', onSlotchange: this.handleDefaultSlotChange })), renderer.h("slot", { key: '3ecd42c2ca6c1546f48a1a5fcf7742d90ad4e1c4', name: "icon-end" }))), (!this.href || this.disabled) && (renderer.h("button", { key: '0694ce0708264ef1305e4b926a2f40f1875025a9', role: this.checkbox ? 'checkbox' : undefined, "aria-checked": this.checkbox ? this.selected.toString() : undefined, part: "trigger trigger--button", ref: (btn) => (this.controlElement = btn), onClick: this.handleClick, disabled: this.disabled, class: {
                navitem__trigger: true,
            } }, renderer.h("slot", { key: 'c3cc4fcbb527f5f8ea2786243fe610d587e36190', name: "icon-start" }), renderer.h("span", { key: '385c92f1f2cc26b9c7e4f1a8601920c1f3bf2171', class: "navitem__label", part: "label" }, renderer.h("slot", { key: '4e7a75c8903081856c20206aa309c2a9855991da', onSlotchange: this.handleDefaultSlotChange })), renderer.h("slot", { key: '668b95901ba0b914ccc193d4f3cc4433d908c014', name: "icon-end" }))), this.slotCtrl.has('secondary') && !this.disabled && (renderer.h("div", { key: 'f81c9aeb6c903b25a662fd1fc615d6f95f6b8f4d', part: "modal", class: {
                navitem__modal: true,
                'navitem__modal--open': this.didOpen,
            }, ref: (div) => (this.secondaryDiv = div), tabIndex: -1 }, renderer.h("div", { key: '70a4b002e989753c461c7dac4dd975200a92e3de', class: "navitem__modal-content", part: `modal-content ${this.didOpen ? 'modal-content--open' : ''}` }, this.slotCtrl.has('close-button') && (renderer.h("div", { key: '7b0daad80ae03a29789c9d2bef74d2473f2f1f39', part: "close-button", onClick: this.closeSecondary }, renderer.h("slot", { key: '858798062958ea0f4ee809cbf853bdb83dd4d184', name: "close-button" }))), renderer.h("slot", { key: '41583a8cc59babbfb1a9a084a3de31c61a145fbc', name: "secondary" })), renderer.h("div", { key: '5c260dca9a8fdf7951349df64a037fc7415c3c4b', class: "navitem__modal-mask", onClick: this.closeSecondary, part: `modal-mask ${this.didOpen ? 'modal-mask--open' : ''}` }))))));
    }
    static get watchers() { return {
        "open": ["openChange"],
        "didOpen": ["didOpenChange"]
    }; }
};
NavItem.style = navItemCss;

exports.nano_nav_item = NavItem;
