/*!
 * Custom elements for Nanopore-Digital Web applications
 */
import { Host, } from "@stencil/core";
import { getDirectChildren } from "../../utils/dom";
import { displayTransition } from "../../utils/transitions";
import { getTabbableElements } from "../../utils/tabbable";
import { h, transformTag } from "../../utils/renderer";
import { HasSlotController } from "../../utils/slot";
import { focusInContainer } from "../../utils/active-element";
/**
 * Nav items provide options or links for the user to pick from a menu or navigation bar.
 *
 * @slot icon-start - an icon at the start of the main control
 * @slot icon-end - an icon at the end of the main control
 * @slot secondary - a content panel in which you can place any html to display on click
 * @slot close-button - a button to close the secondary content panel
 * @slot - use the default slot for either `<a>` or text (if constructing a secondary content panel or using `href` directly)
 *
 * @part trigger - the controlling `<a>` or `<button>` element
 * @part trigger--button - the controlling `<button>` element
 * @part trigger--anchor - the controlling <a> element
 * @part trigger-wrapper - the wrapping div around the control (shadow `<button>` / `<a>` or slotted `<a>`)
 * @part label - the label text of the nav item
 * @part modal - the div that contains the secondary content panel
 * @part modal--open - the div that contains the secondary content panel when open
 * @part modal--close - the div that contains the secondary content panel when closed
 * @part modal-content - the div that contains the secondary content panel content
 * @part modal-content--open - the div that contains the secondary content panel content when open
 * @part modal-mask - the div that covers the screen when the secondary content panel is open
 * @part close-button - the div that contains the close button for the secondary content panel
 * @part close-button-icon - the icon inside the close button for the secondary content panel
 *
 * @version 1.0.0
 * @status stable
 */
export class NavItem {
    secondaryDiv;
    slotCtrl = new HasSlotController(this, 'secondary', 'close-button');
    controlElement;
    host;
    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 (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 = 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 = 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(transformTag('nano-menu-drawer'));
    }
    componentDidLoad() {
        this.openChange();
    }
    render() {
        return (h(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 }, h("div", { key: 'e8faa3568a13feb95ef131f0bd412577120fbf84', class: {
                navitem: true,
                'navitem--open': this.open,
                'navitem--active': this.selected,
            }, part: "trigger-wrapper" }, this.href && !this.disabled && (h("a", { key: '4a4da7478db63015d0dcd81ed053146f8eeac5f3', part: "trigger trigger--anchor", target: this.target, ref: (a) => (this.controlElement = a), href: this.href, class: {
                navitem__trigger: true,
            } }, h("slot", { key: '1eafb7864368850ad2539c402eb1b00877f3d55e', name: "icon-start" }), h("span", { key: '8953312d4dad64ced970d2f1120c07b6c36070f1', class: "navitem__label", part: "label" }, h("slot", { key: '390f468f8d1f5d4f0669cae53ef140e452b16b07', onSlotchange: this.handleDefaultSlotChange })), h("slot", { key: '3ecd42c2ca6c1546f48a1a5fcf7742d90ad4e1c4', name: "icon-end" }))), (!this.href || this.disabled) && (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,
            } }, h("slot", { key: 'c3cc4fcbb527f5f8ea2786243fe610d587e36190', name: "icon-start" }), h("span", { key: '385c92f1f2cc26b9c7e4f1a8601920c1f3bf2171', class: "navitem__label", part: "label" }, h("slot", { key: '4e7a75c8903081856c20206aa309c2a9855991da', onSlotchange: this.handleDefaultSlotChange })), h("slot", { key: '668b95901ba0b914ccc193d4f3cc4433d908c014', name: "icon-end" }))), this.slotCtrl.has('secondary') && !this.disabled && (h("div", { key: 'f81c9aeb6c903b25a662fd1fc615d6f95f6b8f4d', part: "modal", class: {
                navitem__modal: true,
                'navitem__modal--open': this.didOpen,
            }, ref: (div) => (this.secondaryDiv = div), tabIndex: -1 }, h("div", { key: '70a4b002e989753c461c7dac4dd975200a92e3de', class: "navitem__modal-content", part: `modal-content ${this.didOpen ? 'modal-content--open' : ''}` }, this.slotCtrl.has('close-button') && (h("div", { key: '7b0daad80ae03a29789c9d2bef74d2473f2f1f39', part: "close-button", onClick: this.closeSecondary }, h("slot", { key: '858798062958ea0f4ee809cbf853bdb83dd4d184', name: "close-button" }))), h("slot", { key: '41583a8cc59babbfb1a9a084a3de31c61a145fbc', name: "secondary" })), h("div", { key: '5c260dca9a8fdf7951349df64a037fc7415c3c4b', class: "navitem__modal-mask", onClick: this.closeSecondary, part: `modal-mask ${this.didOpen ? 'modal-mask--open' : ''}` }))))));
    }
    static get is() { return "nano-nav-item"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["nav-item.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["nav-item.css"]
        };
    }
    static get properties() {
        return {
            "href": {
                "type": "string",
                "attribute": "href",
                "mutable": true,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Href to link to. Alternatively, slot an `<a>` element"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "null"
            },
            "target": {
                "type": "string",
                "attribute": "target",
                "mutable": false,
                "complexType": {
                    "original": "'_self' | '_blank' | '_parent' | '_top'",
                    "resolved": "\"_blank\" | \"_parent\" | \"_self\" | \"_top\"",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Target to use for links"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "'_self'"
            },
            "disabled": {
                "type": "boolean",
                "attribute": "disabled",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Disable the nav item"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "false"
            },
            "open": {
                "type": "boolean",
                "attribute": "open",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Whether a secondary menu should be or is currently open"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "false"
            },
            "selected": {
                "type": "boolean",
                "attribute": "selected",
                "mutable": true,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Whether this menu item is currently 'selected'"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "false"
            },
            "checkbox": {
                "type": "boolean",
                "attribute": "checkbox",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Changes behaviour so automatically becomes `selected` onClick"
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "defaultValue": "false"
            },
            "closeOnBlur": {
                "type": "boolean",
                "attribute": "close-on-blur",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Whether secondary menus should close on blur"
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "defaultValue": "true"
            }
        };
    }
    static get states() {
        return {
            "didOpen": {},
            "isInMenuDrawer": {}
        };
    }
    static get events() {
        return [{
                "method": "nanoClose",
                "name": "nanoClose",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the nav item closes it's secondary navigation."
                },
                "complexType": {
                    "original": "NavItemEventDetail",
                    "resolved": "NavItemEventDetail",
                    "references": {
                        "NavItemEventDetail": {
                            "location": "import",
                            "path": "./nav-item-interface",
                            "id": "src/components/nav-item/nav-item-interface.d.ts::NavItemEventDetail"
                        }
                    }
                }
            }, {
                "method": "nanoOpen",
                "name": "nanoOpen",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the nav item opens it's secondary navigation."
                },
                "complexType": {
                    "original": "NavItemEventDetail",
                    "resolved": "NavItemEventDetail",
                    "references": {
                        "NavItemEventDetail": {
                            "location": "import",
                            "path": "./nav-item-interface",
                            "id": "src/components/nav-item/nav-item-interface.d.ts::NavItemEventDetail"
                        }
                    }
                }
            }, {
                "method": "nanoOpening",
                "name": "nanoOpening",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the nav item is about to open it's secondary navigation."
                },
                "complexType": {
                    "original": "NavItemEventDetail",
                    "resolved": "NavItemEventDetail",
                    "references": {
                        "NavItemEventDetail": {
                            "location": "import",
                            "path": "./nav-item-interface",
                            "id": "src/components/nav-item/nav-item-interface.d.ts::NavItemEventDetail"
                        }
                    }
                }
            }, {
                "method": "nanoClosing",
                "name": "nanoClosing",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Emitted when the nav item is about to close it's secondary navigation."
                },
                "complexType": {
                    "original": "NavItemEventDetail",
                    "resolved": "NavItemEventDetail",
                    "references": {
                        "NavItemEventDetail": {
                            "location": "import",
                            "path": "./nav-item-interface",
                            "id": "src/components/nav-item/nav-item-interface.d.ts::NavItemEventDetail"
                        }
                    }
                }
            }];
    }
    static get methods() {
        return {
            "setFocus": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Sets focus on the first button or anchor present. Use this method instead of the global\n`element.focus()`.",
                    "tags": []
                }
            },
            "closeMenu": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Closes the secondary nav panel if it is open",
                    "tags": []
                }
            },
            "openMenu": {
                "complexType": {
                    "signature": "() => Promise<void>",
                    "parameters": [],
                    "references": {
                        "Promise": {
                            "location": "global",
                            "id": "global::Promise"
                        }
                    },
                    "return": "Promise<void>"
                },
                "docs": {
                    "text": "Opens the secondary nav panel if it is not open",
                    "tags": []
                }
            }
        };
    }
    static get elementRef() { return "host"; }
    static get watchers() {
        return [{
                "propName": "open",
                "methodName": "openChange"
            }, {
                "propName": "didOpen",
                "methodName": "didOpenChange"
            }];
    }
    static get listeners() {
        return [{
                "name": "click",
                "method": "handleClose",
                "target": "body",
                "capture": false,
                "passive": false
            }, {
                "name": "keyup",
                "method": "handleClose",
                "target": "body",
                "capture": false,
                "passive": false
            }];
    }
}
