/*!
 * Custom elements for Nanopore-Digital Web applications
 */
import { proxyCustomElement, HTMLElement, createEvent, Host } from '@stencil/core/internal/client';
import { h } from './renderer.js';
import { M as Modal } from './modal.js';
import { l as lockBodyScrolling, u as unlockBodyScrolling } from './scroll.js';
import { H as HasSlotController } from './slot.js';
import { w as waitForEvent } from './events.js';
import { C as ComponentStore } from './component-store.js';
import { g as getActiveElement } from './active-element.js';
import { d as drag } from './drag.js';
import { g as getTabbableElements } from './tabbable.js';
import { d as defineCustomElement$4 } from './icon.js';
import { d as defineCustomElement$3 } from './icon-button.js';
import { d as defineCustomElement$2 } from './sticker.js';
import { d as defineCustomElement$1 } from './tooltip.js';

const drawerCss = ":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{--size:25rem;--min-size:25rem;--max-size:50%;--panel-background:var(--nano-color-surface-300);--panel-shadow:var(--nano-shadow-l3);--scrim-color:var(--nano-overlay-background-color);--header-button-color:var(--nano-color-primary-1200);--header-button-size:1.375rem;--footer-background:var(--panel-background);--header-background:var(--panel-background);--header-spacing:var(--nano-spacing-l) var(--nano-spacing-l1-default);--body-spacing:var(--nano-spacing-l1-default);--footer-spacing:var(--nano-spacing-l) var(--nano-spacing-l1-default);--dir:1}:host([placement=top]),:host([placement=bottom]){--max-size:80%}:host(:dir(rtl)){--dir:-1}:host-context([dir=rtl]){--dir:-1}.drawer{inset-block-start:0;inset-inline-start:0;pointer-events:none;overflow:hidden;border:none;inline-size:100%;block-size:100%;color:unset;background-color:unset}.drawer::backdrop{display:none}.drawer--contained{position:absolute;z-index:initial}.drawer--fixed{position:fixed;z-index:var(--nano-z-index-modal)}.drawer__panel{position:absolute;max-inline-size:100%;max-block-size:100%;background-color:var(--panel-background);box-shadow:var(--panel-shadow);pointer-events:all;transition:var(--nano-transition-fast) opacity, var(--nano-transition-fast) transform;display:flex}.drawer--top .drawer__panel,.drawer--bottom .drawer__panel{flex-direction:column}@media (forced-colors: active){.drawer__panel{border:solid 1px var(--nano-color-base-1000)}}.drawer__panel:focus{outline:none}.drawer--nodismiss .drawer__panel{animation:cannotClose 0.25s ease-in-out 1}@keyframes cannotClose{0%{scale:1}50%{scale:1.08}100%{scale:1}}.drawer--top .drawer__panel{inset-block:0 auto;inset-inline:0 auto;inline-size:100%;block-size:var(--size);opacity:0;transform:translateY(-100%)}.drawer--bottom .drawer__panel{inset-block:auto 0;inset-inline:0 auto;inline-size:100%;block-size:var(--size);opacity:0;transform:translateY(100%)}.drawer--top.drawer--open .drawer__panel,.drawer--bottom.drawer--open .drawer__panel{opacity:1;transform:translateY(0)}.drawer--start .drawer__panel{inset-block:0 auto;inset-inline:0 auto;inline-size:var(--size);block-size:100%;opacity:0;transform:translateX(calc(var(--dir) * -100%))}.drawer--end .drawer__panel{inset-block:0 auto;inset-inline:auto 0;inline-size:var(--size);block-size:100%;opacity:0;transform:translateX(calc(var(--dir) * 100%))}.drawer--start.drawer--open .drawer__panel,.drawer--end.drawer--open .drawer__panel{opacity:1;transform:translateX(0)}.drawer__resize-handle{display:flex;align-items:center;justify-content:center;position:absolute;z-index:var(--nano-z-index-dropdown);color:var(--nano-color-primary-1200);background-color:var(--nano-color-neutral-75)}.drawer__resize-handle:focus{outline:none}.drawer__resize-handle:focus-visible{background-color:var(--nano-focus-ring-color)}.drawer__resize-handle:active{color:var(--nano-color-primary-800)}.drawer--top .drawer__resize-handle,.drawer--bottom .drawer__resize-handle{cursor:row-resize;inset-inline:0}.drawer--end .drawer__resize-handle,.drawer--start .drawer__resize-handle{cursor:col-resize;inset-block:0}.drawer--end .drawer__resize-handle{inset-inline-start:0}.drawer--start .drawer__resize-handle{inset-inline-end:0}.drawer--top .drawer__resize-handle{inset-block-end:0}.drawer--bottom .drawer__resize-handle{inset-block-start:0}.drawer__header{inline-size:100%;display:flex;background-color:var(--header-background);align-items:center;padding:var(--header-spacing)}[stuck] .drawer__header{box-shadow:var(--nano-shadow-l0)}.drawer__title{flex:1 1 auto;margin:0;font-weight:var(--nano-font-weight-normal);font-size:var(--nano-font-size-xl);line-height:var(--nano-line-height-denser);text-wrap:balance}.drawer__header-actions{flex-shrink:0;display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--nano-spacing-sm);color:var(--header-button-color);inset-inline-end:calc(var(--nano-spacing-l1-default) / 2 * -1);position:relative}.drawer__header-actions .drawer__close,.drawer__header-actions ::slotted(.nano-icon-button){flex:0 0 auto;display:flex;align-items:center;font-size:var(--header-button-size)}.drawer__main{display:flex;flex-direction:column;overflow:auto;-webkit-overflow-scrolling:touch;flex:1 1 auto}.drawer__body{display:block;flex:1 1 auto;padding:var(--body-spacing);padding-block:0 var(--body-spacing);padding-inline:var(--body-spacing)}.drawer:not(.drawer--has-header) .drawer__body{padding-block-start:var(--body-spacing)}.drawer__footer{inline-size:100%;text-align:end;padding:var(--footer-spacing);background:var(--footer-background);inset-block-start:1px;position:relative;border-block-start:1px solid var(--nano-color-neutral-300);gap:var(--nano-spacing-md);display:inline-flex}.drawer:not(.drawer--has-footer) .drawer__footer{display:none}.drawer__overlay{display:block;position:fixed;inset:0;background-color:var(--scrim-color);pointer-events:all;opacity:0;transition:var(--nano-transition-fast) opacity}.drawer--open .drawer__overlay{opacity:1}.drawer--contained .drawer__overlay{display:none}";

const Drawer = /*@__PURE__*/ proxyCustomElement(class Drawer extends HTMLElement {
    constructor() {
        super();
        this.__registerHost();
        this.__attachShadow();
        this.nanoShow = createEvent(this, "nanoShow", 7);
        this.nanoHide = createEvent(this, "nanoHide", 7);
        this.nanoAfterHide = createEvent(this, "nanoAfterHide", 7);
        this.nanoAfterShow = createEvent(this, "nanoAfterShow", 7);
        this.nanoInitialFocus = createEvent(this, "nanoInitialFocus", 7);
        this.nanoRequestClose = createEvent(this, "nanoRequestClose", 7);
    }
    get host() { return this; }
    originalTrigger;
    drawer;
    overlay;
    modal;
    slotCtrl = new HasSlotController(this, 'footer');
    get panel() {
        return this._panel;
    }
    set panel(ele) {
        if (this._panel) {
            this.panel.removeEventListener('animationend', this.handleTransitionEnd);
        }
        if (!ele)
            return;
        ele.addEventListener('transitionend', this.handleTransitionEnd);
        this._panel = ele;
    }
    _panel;
    noDismiss = false;
    isOpen = false;
    // Public API
    /**
     * Indicates whether or not the drawer is open. You can toggle this attribute to show and hide the drawer, or you can
     * use the `show()` and `hide()` methods and this attribute will reflect the drawer's open state.
     */
    open = false;
    /**
     * The drawer'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. If you need to display HTML, use the `label` slot instead.
     */
    label;
    /** The direction from which the drawer will open. */
    placement = 'end';
    /**
     * By default, the drawer slides out of its containing block (usually the viewport). To make the drawer slide out of
     * its parent element, set this attribute and add `position: relative` to the parent.
     */
    contained = false;
    /**
     * Removes the header. This will also remove the default close button, so please ensure you provide an easy,
     * accessible way for users to dismiss the drawer.
     */
    noHeader = 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';
    /** 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;
    /** Relocate the dialog to the root of the DOM. Useful for elements bound via css `transform: ...` */
    hoist = false;
    /** Makes the drawer resizable */
    resizable = 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 drawer opens. */
    nanoShow;
    /** Emitted when the drawer closes. */
    nanoHide;
    /** Emitted after the drawer closes and all animations are complete. */
    nanoAfterHide;
    /** Emitted after the drawer opens and all animations are complete. */
    nanoAfterShow;
    /**
     * Emitted when the drawer opens and is ready to receive focus. Calling
     * `event.preventDefault()` will prevent focusing and allow you to set it on a different element, such as an input.
     */
    nanoInitialFocus;
    /**
     * Emitted when the user attempts to
     * close the drawer by clicking the close button, clicking the overlay, or pressing escape. Calling
     * `event.preventDefault()` will keep the drawer open. Avoid using this unless closing the drawer will result in
     * destructive behavior such as data loss.
     */
    nanoRequestClose;
    /**
     * Shows the drawer.
     * @returns a promise that resolves when the drawer has finished opening
     */
    async show() {
        if (this.open)
            return undefined;
        this.open = true;
        return waitForEvent(this.host, 'nanoAfterShow');
    }
    /**
     * Hides the drawer
     * @returns a promise that resolves when the drawer has finished closing
     */
    async hide() {
        if (!this.open)
            return undefined;
        this.open = false;
        return waitForEvent(this.host, 'nanoAfterHide');
    }
    requestClose(source) {
        const nanoRequestClose = this.nanoRequestClose.emit({ source });
        if (nanoRequestClose.defaultPrevented || this.noUserDismiss) {
            this.noDismiss = true;
            setTimeout(() => (this.noDismiss = false), 250);
            return;
        }
        this.hide();
    }
    // Prop Change Handlers
    handleNoModalChange() {
        if (this.open && !this.contained) {
            this.modal.activate();
            if (typeof this.drawer?.showPopover === 'function') {
                this.drawer.showPopover();
            }
            lockBodyScrolling(this.host);
        }
        if (this.open && this.contained) {
            this.modal.deactivate();
            unlockBodyScrolling(this.host);
        }
    }
    async handleOpenChange() {
        if (this.open) {
            // Show
            this.nanoShow.emit();
            this.addOpenListeners();
            this.originalTrigger = getActiveElement();
            // Lock body scrolling only if the drawer isn't contained
            if (!this.contained) {
                this.modal.activate();
                if (typeof this.drawer?.showPopover === 'function') {
                    this.drawer.showPopover();
                }
                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');
            }
            this.drawer.hidden = false;
            this.isOpen = true;
            // Set initial focus
            requestAnimationFrame(() => {
                const nanoInitialFocus = this.nanoInitialFocus.emit();
                if (!nanoInitialFocus.defaultPrevented) {
                    const firstTabbable = autoFocusTarget ||
                        getTabbableElements(this.host, true, true, true)[0] ||
                        this.panel;
                    firstTabbable.focus({ preventScroll: true });
                }
                // Restore the autofocus attribute
                if (autoFocusTarget) {
                    autoFocusTarget.setAttribute('autofocus', '');
                }
            });
            return;
        }
        // Hide
        this.nanoHide.emit();
        this.removeOpenListeners();
        if (!this.contained) {
            this.modal.deactivate();
            unlockBodyScrolling(this.host);
        }
        // Restore focus to the original trigger
        const returnFocus = this.originalTrigger && typeof this.originalTrigger.focus === 'function'
            ? this.originalTrigger
            : document.body;
        returnFocus.focus();
        requestAnimationFrame(() => {
            this.isOpen = false;
        });
    }
    // Event Handling
    addOpenListeners() {
        document.addEventListener('keydown', this.handleDocumentKeyDown);
    }
    removeOpenListeners() {
        document.removeEventListener('keydown', this.handleDocumentKeyDown);
    }
    handleDocumentKeyDown = (event) => {
        // Contained drawers aren't modal and don't respond to the escape key
        if (this.contained) {
            return;
        }
        if (event.key === 'Escape' && this.modal.isActive() && this.open) {
            event.stopImmediatePropagation();
            this.requestClose('keyboard');
        }
    };
    handleTransitionEnd = (event) => {
        if (event.propertyName === 'opacity' &&
            event
                .composedPath()
                .find((node) => node === this.panel || node === this.overlay)) {
            if (!this.open) {
                this.drawer.hidden = true;
                // Now that the dialog is hidden, restore the overlay and panel for next time
                this.overlay.hidden = false;
                this.panel.hidden = false;
                if (!this.contained && typeof this.drawer?.hidePopover === 'function') {
                    this.drawer.hidePopover();
                }
                this.nanoAfterHide.emit();
                return;
            }
            this.nanoAfterShow.emit();
        }
    };
    get panelSize() {
        const vertical = ['top', 'bottom'].includes(this.placement);
        return vertical ? this.panel.offsetHeight : this.panel.offsetWidth;
    }
    set panelSize(size) {
        const prop = ['top', 'bottom'].includes(this.placement)
            ? 'blockSize'
            : 'inlineSize';
        this.panel.style[prop] = `clamp(var(--min-size), ${size + 'px'}, var(--max-size))`;
    }
    handleKeyDown = (event) => {
        if ([
            'ArrowLeft',
            'ArrowRight',
            'ArrowUp',
            'ArrowDown',
            'Home',
            'End',
        ].includes(event.key)) {
            let newPosition = this.panelSize;
            const flip = this.placement === 'end' || this.placement === 'bottom';
            const incr = (event.shiftKey ? 30 : 5) * (flip ? -1 : 1);
            const vertical = ['top', 'bottom'].includes(this.placement);
            event.preventDefault();
            if ((event.key === 'ArrowLeft' && !vertical) ||
                (event.key === 'ArrowUp' && vertical)) {
                newPosition -= incr;
            }
            if ((event.key === 'ArrowRight' && !vertical) ||
                (event.key === 'ArrowDown' && vertical)) {
                newPosition += incr;
            }
            if (event.key === 'Home') {
                newPosition = 0;
            }
            if (event.key === 'End') {
                newPosition = 10000;
            }
            this.panelSize = newPosition;
        }
    };
    handleDrag = (e) => {
        // Prevent text selection when dragging
        e.preventDefault();
        const vertical = ['top', 'bottom'].includes(this.placement);
        const flip = this.placement === 'end' || this.placement === 'bottom';
        const initDimension = vertical
            ? this.panel.offsetHeight
            : this.panel.offsetWidth;
        drag(this.host, {
            relative: true,
            initialEvent: e,
            onMove: (x, y) => {
                let movedPixels = vertical ? y : x;
                if (flip)
                    movedPixels *= -1;
                this.panelSize = initDimension + movedPixels;
            },
        });
    };
    // Component Lifecycle
    connectedCallback() {
        this.handleHoistChange();
        this.modal = new Modal(this.host);
    }
    disconnectedCallback() {
        unlockBodyScrolling(this.host);
    }
    componentWillLoad() {
        // Show on init if open
        if (this.storeId)
            ComponentStore.init(this, ['open'], this.storeMethod, this.storeId);
    }
    componentDidLoad() {
        this.drawer.hidden = !this.open;
        if (this.open) {
            this.handleNoModalChange();
            this.show();
        }
    }
    render() {
        return (h(Host, { key: '487ea65e478b81f58f3302110777a756e5dcf7d4', class: "nano-drawer" }, h("div", { key: '12feebdc459f4643d41d5d2dc19643c13c0d9809', ref: (ele) => (this.drawer = ele), part: "base", class: {
                drawer: true,
                'drawer--open': this.open,
                [`drawer--${this.placement}`]: true,
                'drawer--contained': this.contained,
                'drawer--fixed': !this.contained,
                'drawer--has-footer': this.slotCtrl.has('footer'),
                'drawer--has-header': !this.noHeader,
                'drawer--nodismiss': this.noDismiss,
            }, popover: !this.contained ? 'manual' : undefined }, h("div", { key: 'e38b14383dadea34b11db92d6871518b82192859', ref: (ele) => (this.overlay = ele), part: "overlay", class: "drawer__overlay", onClick: () => this.requestClose('overlay'), tabindex: "-1" }), h("div", { key: '4a934cc84b9d4ff06bff84feaf75ac8d463d2d5f', ref: (ele) => (this.panel = ele), part: "panel", class: "drawer__panel", role: "dialog", "aria-modal": "true", "aria-hidden": this.isOpen ? 'false' : 'true', "aria-label": this.noHeader ? this.label : undefined, "aria-labelledby": !this.noHeader ? 'title' : undefined, tabindex: "0" }, this.resizable && (h("div", { key: '7c8d1c12356974522a698d69ff2e9015dd60ae92', part: "resize-handle", class: "drawer__resize-handle", tabindex: "0", role: "separator", "aria-label": "Resize", onKeyDown: this.handleKeyDown, onMouseDown: this.handleDrag, onTouchStart: this.handleDrag }, h("slot", { key: '48e2497abc58310beb96648b4cc44d80ae28431f', name: "handle" }, ['start', 'end'].includes(this.placement) ? (h("nano-icon", { slot: "handle", name: "solid/grip-dots-vertical" })) : (h("nano-icon", { slot: "handle", name: "solid/grip-dots" }))))), h("div", { key: '425d5eb60035fb44b7c3ea4ddf4f338d429893ab', class: "drawer__main" }, !this.noHeader && (h("nano-sticker", { key: '1f8eac374619dd3b607862254c2573e19963374c' }, h("div", { key: '070d62dd270a2040f32e509ec0a2a5eb8c739367', part: "header", class: "drawer__header" }, h("div", { key: 'f3d0155227515ad548ee70e65a2213711dc13a3a', part: "title", class: "drawer__title", id: "title" }, h("slot", { key: '61410c8918849984dd31854a042ec3209c1ca175', name: "label" }, this.label.length > 0
            ? this.label
            : String.fromCharCode(65279))), h("div", { key: '262e4616c018e346596b089968f6af8b4a39436a', part: "header-actions", class: "drawer__header-actions" }, h("slot", { key: '81245d6449637ca85f631d2065b173dfa3b6c663', name: "header-actions" }), !this.noUserDismiss && (h("nano-icon-button", { key: '0b88624e93df33a23f3f132d05d5f8fbc418f520', part: "close-button", exportparts: "base:close-button__base", class: "drawer__close", iconName: "light/xmark", label: "Close", onClick: () => this.requestClose('close-button') })))))), h("div", { key: '50a441f9c9417ba4fa29f30b63cc54eaf5618a98', part: "body", class: "drawer__body" }, h("slot", { key: '478310362285c4ea2fcde71838da527640bf09da' })), h("nano-sticker", { key: 'bb6c4a2c6ce89a03270daaf194b0a78914437c2b', position: "bottom" }, h("footer", { key: 'efbb6ac1f46e3bce948a236f01e26adc63b628cc', part: "footer", class: "drawer__footer" }, h("slot", { key: '5a3d95c01ce45c51715d89e4cc3064f337d59b23', name: "footer" }))))))));
    }
    static get watchers() { return {
        "hoist": ["handleHoistChange"],
        "contained": ["handleNoModalChange"],
        "open": ["handleOpenChange"]
    }; }
    static get style() { return drawerCss; }
}, [257, "nano-drawer", {
        "open": [1540],
        "label": [513],
        "placement": [513],
        "contained": [516],
        "noHeader": [516, "no-header"],
        "storeId": [1, "store-id"],
        "storeMethod": [1, "store-method"],
        "noUserDismiss": [4, "no-user-dismiss"],
        "hoist": [4],
        "resizable": [4],
        "noDismiss": [32],
        "isOpen": [32],
        "show": [64],
        "hide": [64]
    }, undefined, {
        "hoist": ["handleHoistChange"],
        "contained": ["handleNoModalChange"],
        "open": ["handleOpenChange"]
    }]);
function defineCustomElement() {
    if (typeof customElements === "undefined") {
        return;
    }
    const components = ["nano-drawer", "nano-icon", "nano-icon-button", "nano-sticker", "nano-tooltip"];
    components.forEach(tagName => { switch (tagName) {
        case "nano-drawer":
            if (!customElements.get(tagName)) {
                customElements.define(tagName, Drawer);
            }
            break;
        case "nano-icon":
            if (!customElements.get(tagName)) {
                defineCustomElement$4();
            }
            break;
        case "nano-icon-button":
            if (!customElements.get(tagName)) {
                defineCustomElement$3();
            }
            break;
        case "nano-sticker":
            if (!customElements.get(tagName)) {
                defineCustomElement$2();
            }
            break;
        case "nano-tooltip":
            if (!customElements.get(tagName)) {
                defineCustomElement$1();
            }
            break;
    } });
}

export { Drawer as D, defineCustomElement as d };
