/*!
 * Custom elements for Nanopore-Digital Web applications
 */
import { proxyCustomElement, HTMLElement, createEvent, forceUpdate, Build, Host } from '@stencil/core/internal/client';
import { g as getDirectChildren } from './dom.js';
import { C as ComponentStore } from './component-store.js';
import { t as transformTag, h } from './renderer.js';
import { d as defineCustomElement$5 } from './icon.js';
import { d as defineCustomElement$4 } from './icon-button.js';
import { d as defineCustomElement$3 } from './masked-overflow.js';
import { d as defineCustomElement$2 } from './tooltip.js';

const tabGroupCss = ":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:2px solid var(--nano-color-neutral-300);--indicator-transition:var(--nano-transition-fast);--indicator-color:var(--nano-color-primary-1000);--indicator-track-color:var(--nano-color-neutral-300);--indicator-size:0;--tab-spacing:var(--nano-spacing-md);--content-spacing:var(--nano-spacing-l1-default);display:block;position:relative;z-index:var(--nano-z-index-raised)}.group{display:flex;border-radius:0;inline-size:100%;flex:inherit}:host([equal-tab-size]) .group__tabs-border,.group__tabs[has-scroll-controls] .group__tabs-border{display:none}.group__tabs::part(items){gap:var(--tab-spacing)}.group--top{flex-direction:column}.group--top .group__tabs{--fade-size:100px}.group--top .group__tabs::part(items){align-items:flex-end}.group--top .group__tabs-border{flex:1;border-block-end:var(--border)}.group--top .group__body{order:2;position:relative;flex:1 1 auto;border-block-end:var(--border);padding-block:var(--content-spacing)}.group--start{flex-direction:row}:host([equal-tab-size]) .group--start .group__tabs::part(items){display:grid;grid-auto-rows:1fr}.group--start .group__tabs-border{flex:1;border-inline-end:var(--border)}.group--start .group__body{flex:1 1 auto;order:2;overflow:hidden;padding-inline-start:var(--content-spacing)}";

let id = 0;
const NanoTabGroup$1 = /*@__PURE__*/ proxyCustomElement(class NanoTabGroup extends HTMLElement {
    constructor() {
        super();
        this.__registerHost();
        this.__attachShadow();
        this.nanoTabShow = createEvent(this, "nanoTabShow", 7);
        this.nanoTabHide = createEvent(this, "nanoTabHide", 7);
        this.nanoTabWillClose = createEvent(this, "nanoTabWillClose", 7);
        this.nanoTabClose = createEvent(this, "nanoTabClose", 7);
    }
    baseId = `nano-tab-group-${++id}`;
    activeTab;
    activePanel;
    isRtl;
    initialTouchX = null;
    initialTouchY = null;
    init = true;
    _tab;
    get tab() {
        return this._tab;
    }
    set tab(tabName) {
        if (this.activeTab && this.activeTab.panel === this._tab)
            return;
        const selectedTabEle = this.getAllActiveTabs.find((el) => el.panel === tabName);
        if (!selectedTabEle)
            return;
        if (!this.init && this.storeId) {
            ComponentStore.update(this.storeId);
        }
        this._tab = tabName;
        this.setActiveTab(selectedTabEle);
    }
    get host() { return this; }
    /**
     * The placement of the tabs.
     */
    placement = 'top';
    /**
     * Disables the scroll arrows that appear when tabs overflow.
     */
    noScrollControls = false;
    /** Make all tabs equal size. This is only recommended when there are a small number of tabs */
    equalTabSize = false;
    /** Size of tabs. Default is `regular`. `large` is only available when `placement="top"` */
    size;
    /**
     * Store the open tab against this ID in the component store.
     * Use in combination with `storeMethod`
     */
    storeId;
    /**
     * The method of storage.
     * Either session storage, url hash (after an '#') or url query (after an '?').
     */
    storeMethod = 'url-hash';
    /**
     * Disable 'swipe to change tab' on devices with touch
     */
    disableSwipe;
    /** Emitted when a tab is shown. */
    nanoTabShow;
    /** Emitted when a tab is hidden. */
    nanoTabHide;
    /** Emitted when the tab is closable and the close button is activated. */
    nanoTabWillClose;
    /** Emitted when a closable tab is removed. */
    nanoTabClose;
    /** Shows the specified tab panel. */
    async show(panel) {
        if (this.activeTab && this.activeTab.panel === panel)
            return;
        const tab = this.getAllActiveTabs.find((el) => el.panel === panel);
        if (tab)
            this.setActiveTab(tab);
    }
    // Internal Methods
    get getAllActiveTabs() {
        return this.getAllTabs.filter((el) => !el.disabled);
    }
    get getAllTabs() {
        return getDirectChildren(this.host, transformTag('nano-tab'));
    }
    get getAllPanels() {
        return getDirectChildren(this.host, transformTag('nano-tab-content'));
    }
    get getActiveTab() {
        return this.getAllActiveTabs.find((el) => el.active);
    }
    setActiveTab(tab, emitEvents = true) {
        if (tab &&
            tab !== this.activeTab &&
            !tab.disabled &&
            this.getAllActiveTabs.includes(tab)) {
            const previousTab = this.activeTab;
            this.activeTab = tab;
            this.tab = tab.panel;
            // Sync tabs and panels
            this.getAllActiveTabs.map((el) => (el.active = el === this.activeTab));
            this.getAllPanels.map((el) => {
                if (el.name === this.activeTab.panel) {
                    el.active = true;
                    this.activePanel = el;
                }
                else
                    el.active = false;
                el.removeAttribute('animation-dir');
            });
            // Emit events
            if (emitEvents) {
                if (previousTab) {
                    this.nanoTabHide.emit({ name: previousTab.panel });
                }
                this.nanoTabShow.emit({ name: this.activeTab.panel });
            }
        }
    }
    setAriaLabels() {
        const tabs = this.getAllActiveTabs;
        const panels = this.getAllPanels;
        // Link each tab with its corresponding panel
        tabs.map((tab, i) => {
            const panel = panels.find((el) => el.name === tab.panel);
            if (panel) {
                if (!panel.id)
                    panel.id = `${this.baseId}-panel-${i}`;
                if (!tab.id)
                    tab.id = `${this.baseId}-tab-${i}`;
                tab.setAttribute('aria-controls', panel.id);
                panel.setAttribute('aria-labelledby', tab.id);
            }
        });
    }
    // Event handlers
    handleTabClose(ev) {
        let tabIndex = this.getAllActiveTabs.indexOf(ev.target);
        const tab = ev.target;
        if (tabIndex < 0)
            return;
        const panel = this.getAllPanels.find((el) => el.name === tab.panel);
        if (!panel)
            return;
        ev.stopImmediatePropagation();
        const closeEv = this.nanoTabWillClose.emit({ name: tab.panel });
        if (closeEv.defaultPrevented)
            return;
        // Show the previous tab if the tab is currently active
        if (tab.active) {
            tabIndex = tabIndex === 0 ? 1 : tabIndex - 1;
            const prevTab = this.getAllActiveTabs[tabIndex]?.panel;
            if (prevTab)
                this.host.show(prevTab);
        }
        tab.remove();
        panel.remove();
        this.nanoTabClose.emit({ name: tab.panel });
        forceUpdate(this.host);
    }
    handleClick = (event) => {
        const target = event.target;
        const tab = target.closest(transformTag('nano-tab'));
        if (tab)
            this.setActiveTab(tab);
    };
    handleKeyDown = (event) => {
        const activeEl = document.activeElement;
        if (!activeEl ||
            activeEl.tagName.toLowerCase() !== transformTag('nano-tab'))
            return;
        // Activate a tab
        if (['Enter', ' '].includes(event.key)) {
            const target = event.target;
            const tab = target.closest(transformTag('nano-tab'));
            if (tab) {
                this.setActiveTab(tab);
                event.preventDefault();
                event.stopPropagation();
            }
        }
        // Move focus left or right
        if (![
            'ArrowLeft',
            'ArrowRight',
            'ArrowUp',
            'ArrowDown',
            'Home',
            'End',
        ].includes(event.key))
            return;
        const tabs = this.getAllActiveTabs;
        let index = tabs.indexOf(activeEl);
        if (event.key === 'Home')
            index = 0;
        if (event.key === 'End')
            index = tabs.length - 1;
        if (this.placement === 'top') {
            if ((this.isRtl && event.key === 'ArrowRight') ||
                (!this.isRtl && event.key === 'ArrowLeft')) {
                index = Math.max(0, index - 1);
            }
            if ((this.isRtl && event.key === 'ArrowLeft') ||
                (!this.isRtl && event.key === 'ArrowRight')) {
                index = Math.min(tabs.length - 1, index + 1);
            }
        }
        if (this.placement === 'start') {
            if (event.key === 'ArrowUp')
                index = Math.max(0, index - 1);
            if (event.key === 'ArrowDown')
                index = Math.min(tabs.length - 1, index + 1);
        }
        tabs[index].setFocus();
        // need to stop bubbling otherwise it will focus on parent tabs if nested
        event.stopPropagation();
        // stop the browser moving about
        event.preventDefault();
    };
    handleTouchStart = (event) => {
        if (this.disableSwipe)
            return;
        const touch = event.changedTouches[0];
        this.initialTouchX = touch.pageX;
        this.initialTouchY = touch.pageY;
    };
    handleTouchEnd = (event) => {
        if (this.disableSwipe)
            return;
        const touch = event.changedTouches[0];
        const distX = touch.pageX - this.initialTouchX; // get horizontal dist travelled
        const threshold = 70;
        const xDiff = this.initialTouchX - touch.clientX;
        const yDiff = this.initialTouchY - touch.clientY;
        const isHorizontalSwipe = Math.abs(distX) >= threshold && Math.abs(yDiff) <= 50;
        const tabs = this.getAllActiveTabs;
        const currIndex = tabs.findIndex((el) => el.active);
        if (isHorizontalSwipe) {
            const toGo = (distX < 0 && this.placement === 'top') ||
                (distX > 0 && this.placement !== 'top')
                ? 1
                : -1;
            if (tabs[currIndex + toGo]) {
                this.setActiveTab(tabs[currIndex + toGo]);
                if (Math.abs(xDiff) > Math.abs(yDiff)) {
                    if (xDiff > 0)
                        this.activePanel.setAttribute('animation-dir', 'left');
                    else
                        this.activePanel.setAttribute('animation-dir', 'right');
                }
            }
        }
        this.initialTouchX = null;
        this.initialTouchY = null;
    };
    handleContentSlotChange = () => {
        setTimeout(() => {
            this.setAriaLabels();
            this.setActiveTab(this.getActiveTab || this.getAllActiveTabs[0], false);
        });
    };
    handleTabSlotChange = () => {
        setTimeout(() => {
            this.setAriaLabels();
            this.setActiveTab(this.getActiveTab || this.getAllActiveTabs[0], false);
        }, 500);
    };
    // Stencil hooks
    componentWillLoad() {
        this.init = true;
    }
    componentDidLoad() {
        // Initial IO - watching for all content to be loaded
        const observer = new IntersectionObserver((entries, observer) => {
            if (entries[0].intersectionRatio > 0) {
                this.setAriaLabels();
                if (this.storeId) {
                    ComponentStore.init(this, ['tab'], this.storeMethod, this.storeId);
                    const store = ComponentStore.get(this.storeId);
                    const storedTab = store.retrieve()?.tab;
                    // if a tab is in storage, set it as active now
                    if (storedTab && storedTab !== store.initialState?.tab) {
                        this.getAllActiveTabs.forEach((element) => {
                            if (element.panel === storedTab) {
                                element.active = true;
                            }
                            else {
                                element.active = false;
                            }
                        });
                    }
                }
                this.setActiveTab(this.getActiveTab || this.getAllActiveTabs[0], false);
                observer.unobserve(entries[0].target);
                this.init = false;
            }
        });
        observer.observe(this.host);
    }
    connectedCallback() {
        this.isRtl =
            this.host.dir === 'rtl' || this.host.ownerDocument.dir === 'rtl';
        if (Build.isServer) {
            this.setActiveTab(this.getActiveTab || this.getAllActiveTabs[0], false);
            this.setAriaLabels();
        }
    }
    render() {
        this.isRtl = this.host.ownerDocument.dir === 'rtl';
        if (this.getAllTabs.length === 0)
            return;
        return (h(Host, { dir: this.isRtl ? 'rtl' : null, class: "nano-tab-group" }, h("div", { part: "base", class: {
                group: true,
                'group--top': this.placement === 'top',
                'group--start': this.placement === 'start',
            }, onClick: this.handleClick, onKeyDown: this.handleKeyDown }, h("nano-masked-overflow", { role: "navigation", class: "group__tabs", part: "tabs__wrapper", exportparts: "items:tabs, scroll-button:tabs__scroll-button, indicator:active-tab-indicator", orientation: this.placement === 'top' ? 'horizontal' : 'vertical', isActiveHandler: (itm) => this.activeTab === itm, scrollControls: !this.noScrollControls, hideScrollbars: true }, h("slot", { name: "tabs", onSlotchange: this.handleTabSlotChange }), h("div", { class: "group__tabs-border" })), h("div", { part: "body", class: "group__body", onTouchStart: this.handleTouchStart, onTouchEnd: this.handleTouchEnd }, h("slot", { onSlotchange: this.handleContentSlotChange })))));
    }
    static get style() { return tabGroupCss; }
}, [257, "nano-tab-group", {
        "placement": [513],
        "noScrollControls": [4, "no-scroll-controls"],
        "equalTabSize": [516, "equal-tab-size"],
        "size": [513],
        "storeId": [1, "store-id"],
        "storeMethod": [1, "store-method"],
        "disableSwipe": [4, "disable-swipe"],
        "show": [64]
    }, [[0, "nanoTabClose", "handleTabClose"]]]);
function defineCustomElement$1() {
    if (typeof customElements === "undefined") {
        return;
    }
    const components = ["nano-tab-group", "nano-icon", "nano-icon-button", "nano-masked-overflow", "nano-tooltip"];
    components.forEach(tagName => { switch (tagName) {
        case "nano-tab-group":
            if (!customElements.get(tagName)) {
                customElements.define(tagName, NanoTabGroup$1);
            }
            break;
        case "nano-icon":
            if (!customElements.get(tagName)) {
                defineCustomElement$5();
            }
            break;
        case "nano-icon-button":
            if (!customElements.get(tagName)) {
                defineCustomElement$4();
            }
            break;
        case "nano-masked-overflow":
            if (!customElements.get(tagName)) {
                defineCustomElement$3();
            }
            break;
        case "nano-tooltip":
            if (!customElements.get(tagName)) {
                defineCustomElement$2();
            }
            break;
    } });
}

const NanoTabGroup = NanoTabGroup$1;
const defineCustomElement = defineCustomElement$1;

export { NanoTabGroup, defineCustomElement };
