import { __esDecorate, __runInitializers } from "tslib";
import { html } from 'lit';
import { property, state } from 'lit/decorators.js';
import { classMap } from 'lit/directives/class-map.js';
import { nanoid } from 'nanoid';
import UiList from '../../list/internals/List.js';
import { setDisabled } from '../../../lib/disabled.js';
import { bound } from '../../../decorators/bound.js';
let Menu = (() => {
    let _classSuper = UiList;
    let _instanceExtraInitializers = [];
    let _open_decorators;
    let _open_initializers = [];
    let _open_extraInitializers = [];
    let _disabled_decorators;
    let _disabled_initializers = [];
    let _disabled_extraInitializers = [];
    let _selectOnActivate_decorators;
    let _selectOnActivate_initializers = [];
    let _selectOnActivate_extraInitializers = [];
    let _activeSubMenu_decorators;
    let _activeSubMenu_initializers = [];
    let _activeSubMenu_extraInitializers = [];
    let _handleSubMenuSelect_decorators;
    return class Menu extends _classSuper {
        static {
            const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
            _open_decorators = [property({ type: Boolean, reflect: true })];
            _disabled_decorators = [property({ type: Boolean, reflect: true })];
            _selectOnActivate_decorators = [property({ type: Boolean })];
            _activeSubMenu_decorators = [state()];
            _handleSubMenuSelect_decorators = [bound];
            __esDecorate(this, null, _open_decorators, { kind: "accessor", name: "open", static: false, private: false, access: { has: obj => "open" in obj, get: obj => obj.open, set: (obj, value) => { obj.open = value; } }, metadata: _metadata }, _open_initializers, _open_extraInitializers);
            __esDecorate(this, null, _disabled_decorators, { kind: "accessor", name: "disabled", static: false, private: false, access: { has: obj => "disabled" in obj, get: obj => obj.disabled, set: (obj, value) => { obj.disabled = value; } }, metadata: _metadata }, _disabled_initializers, _disabled_extraInitializers);
            __esDecorate(this, null, _selectOnActivate_decorators, { kind: "accessor", name: "selectOnActivate", static: false, private: false, access: { has: obj => "selectOnActivate" in obj, get: obj => obj.selectOnActivate, set: (obj, value) => { obj.selectOnActivate = value; } }, metadata: _metadata }, _selectOnActivate_initializers, _selectOnActivate_extraInitializers);
            __esDecorate(this, null, _activeSubMenu_decorators, { kind: "accessor", name: "activeSubMenu", static: false, private: false, access: { has: obj => "activeSubMenu" in obj, get: obj => obj.activeSubMenu, set: (obj, value) => { obj.activeSubMenu = value; } }, metadata: _metadata }, _activeSubMenu_initializers, _activeSubMenu_extraInitializers);
            __esDecorate(this, null, _handleSubMenuSelect_decorators, { kind: "method", name: "handleSubMenuSelect", static: false, private: false, access: { has: obj => "handleSubMenuSelect" in obj, get: obj => obj.handleSubMenuSelect }, metadata: _metadata }, null, _instanceExtraInitializers);
            if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
        }
        #open_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _open_initializers, false
        /**
         * Whether the menu is disabled
         * @attribute
         */
        ));
        /**
         * Whether the menu is currently open
         * @attribute
         */
        get open() { return this.#open_accessor_storage; }
        set open(value) { this.#open_accessor_storage = value; }
        #disabled_accessor_storage = (__runInitializers(this, _open_extraInitializers), __runInitializers(this, _disabled_initializers, false
        /**
         * Whether to select menu items when they are activated.
         * When true, clicking or pressing Enter/Space on a menu item will mark it as selected.
         * When false (default), menu items will not be marked as selected when activated.
         *
         * Note, this is different than `selectActive` as this property controls the class names
         * set on the menu item.
         * @attribute
         */
        ));
        /**
         * Whether the menu is disabled
         * @attribute
         */
        get disabled() { return this.#disabled_accessor_storage; }
        set disabled(value) { this.#disabled_accessor_storage = value; }
        #selectOnActivate_accessor_storage = (__runInitializers(this, _disabled_extraInitializers), __runInitializers(this, _selectOnActivate_initializers, false
        /**
         * Currently active sub-menu
         */
        ));
        /**
         * Whether to select menu items when they are activated.
         * When true, clicking or pressing Enter/Space on a menu item will mark it as selected.
         * When false (default), menu items will not be marked as selected when activated.
         *
         * Note, this is different than `selectActive` as this property controls the class names
         * set on the menu item.
         * @attribute
         */
        get selectOnActivate() { return this.#selectOnActivate_accessor_storage; }
        set selectOnActivate(value) { this.#selectOnActivate_accessor_storage = value; }
        #activeSubMenu_accessor_storage = (__runInitializers(this, _selectOnActivate_extraInitializers), __runInitializers(this, _activeSubMenu_initializers, null));
        /**
         * Currently active sub-menu
         */
        get activeSubMenu() { return this.#activeSubMenu_accessor_storage; }
        set activeSubMenu(value) { this.#activeSubMenu_accessor_storage = value; }
        constructor() {
            super();
            __runInitializers(this, _activeSubMenu_extraInitializers);
            this.selector = 'ui-menu-item';
            this.ariaExpanded = 'false';
            this.addEventListener('beforetoggle', this.handleBeforeToggle.bind(this));
        }
        connectedCallback() {
            super.connectedCallback();
            this.setAttribute('role', 'menu');
            this.setAttribute('tabindex', '-1');
            if (!this.hasAttribute('popover')) {
                this.setAttribute('popover', 'auto');
            }
            if (!this.id) {
                this.id = nanoid();
            }
        }
        updated(changedProperties) {
            super.updated(changedProperties);
            if (changedProperties.has('disabled')) {
                setDisabled(this, this.disabled);
            }
        }
        togglePopover(force) {
            if (!this.open && !this.disabled) {
                this.positionMenu();
            }
            this.open = !this.open;
            this.ariaExpanded = String(this.open);
            this.tabIndex = this.open ? 0 : -1;
            const result = super.togglePopover(force);
            if (this.open) {
                this.focus();
            }
            return result;
        }
        queryMenuItems() {
            const slot = this.shadowRoot?.querySelector('slot');
            if (!slot)
                return [];
            const { selector } = this;
            return Array.from(slot.assignedElements({ flatten: true })).filter((el) => el.matches(selector));
        }
        show() {
            this.showPopover();
        }
        hide() {
            this.hidePopover();
        }
        /**
         * Shows the menu
         */
        showPopover() {
            this.tabIndex = 0; // Make menu focusable
            this.ariaExpanded = 'true';
            this.positionMenu();
            super.showPopover();
            this.open = true;
            this.focus();
            this.dispatchEvent(new CustomEvent('open'));
        }
        /**
         * Hides the menu
         */
        hidePopover() {
            this.tabIndex = -1;
            this.ariaExpanded = 'false';
            super.hidePopover();
            this.open = false;
            this.closeSubMenu();
            this.dispatchEvent(new CustomEvent('close'));
        }
        positionMenu() {
            // for the frame, make the element visible (without animations)
            // to take measurements correctly.
            this.classList.add('measurements');
            // Reset any previous manual positioning to let CSS anchor positioning work
            this.style.removeProperty('position-area');
            this.style.removeProperty('max-height');
            this.style.removeProperty('max-width');
            // Let CSS anchor positioning handle the positioning automatically
            // Only intervene if we need to set max-height for overflow cases
            const box = this.getBoundingClientRect();
            this.classList.remove('measurements');
            // Check if the menu content is being clipped
            const isVerticallyClipped = this.scrollHeight > this.clientHeight;
            const isHorizontallyClipped = this.scrollWidth > this.clientWidth;
            // Get the actual bottom and right edges of the menu
            const menuBottom = box.top + box.height;
            const menuRight = box.left + box.width;
            // Detect if menu is positioned above or below the anchor
            // by checking if the menu is in the upper or lower half of the viewport
            const viewportMiddle = innerHeight / 2;
            const isMenuInUpperHalf = box.top < viewportMiddle;
            // console.log(`Menu positioned at: top=${box.top}, left=${box.left}, bottom=${menuBottom}, right=${menuRight}`)
            // console.log(
            // eslint-disable-next-line max-len
            //   `Menu is in upper half: ${isMenuInUpperHalf}, Vertically clipped: ${isVerticallyClipped}, Horizontally clipped: ${isHorizontallyClipped}`
            // )
            // Add CSS class to control animation direction
            if (isMenuInUpperHalf) {
                this.classList.add('menu-positioned-above');
                this.classList.remove('menu-positioned-below');
            }
            else {
                this.classList.add('menu-positioned-below');
                this.classList.remove('menu-positioned-above');
            }
            // Only set max-height if the menu would overflow the viewport OR is already clipped
            if (menuBottom > innerHeight || isVerticallyClipped) {
                let availableHeight;
                if (isMenuInUpperHalf) {
                    // Menu is positioned below the anchor - available space is from top to bottom of viewport
                    availableHeight = innerHeight - box.top;
                }
                else {
                    // Menu is positioned above the anchor - available space is from top of viewport to bottom of menu
                    availableHeight = box.top + box.height;
                }
                this.style.maxHeight = `${Math.max(200, availableHeight - 20)}px`;
            }
            // Only set max-width if the menu would overflow the viewport OR is already clipped
            if (menuRight > innerWidth || isHorizontallyClipped) {
                const availableWidth = innerWidth - box.left;
                if (availableWidth < 200) {
                    this.style.maxWidth = `${Math.max(180, availableWidth - 20)}px`;
                }
            }
        }
        /**
         * Handles beforetoggle event from popover
         */
        handleBeforeToggle(e) {
            const toggleEvent = e;
            if (toggleEvent.newState === 'closed') {
                this.open = false;
                this.closeSubMenu();
            }
        }
        /**
         * Handles keyboard navigation for the menu
         */
        handleKeydown(e) {
            if (!this.open || e.defaultPrevented)
                return;
            switch (e.key) {
                case 'Escape':
                    e.preventDefault();
                    this.hide();
                    break;
                case 'ArrowRight':
                    e.preventDefault();
                    this.openSubMenu();
                    break;
                case 'ArrowLeft':
                    e.preventDefault();
                    this.closeSubMenu();
                    break;
                default:
                    // Let the parent UiList handle other keys
                    super.handleKeydown(e);
            }
        }
        handleSubMenuSelect(e) {
            super.notifySelect(e.detail.item, e.detail.index);
        }
        /**
         * Opens the sub-menu for the currently active item
         */
        openSubMenu() {
            const activeItem = this.activeListItem;
            if (activeItem?.hasSubMenu) {
                activeItem.openSubMenu();
            }
        }
        /**
         * Closes the currently open sub-menu
         */
        closeSubMenu() {
            if (this.activeSubMenu) {
                this.activeSubMenu.removeEventListener('select', this.handleSubMenuSelect);
                this.activeSubMenu.hide();
                this.activeSubMenu = null;
            }
        }
        /**
         * Sets the active sub-menu
         */
        setActiveSubMenu(subMenu) {
            this.activeSubMenu = subMenu;
            subMenu?.addEventListener('select', this.handleSubMenuSelect);
        }
        notifySelect(item, index) {
            // Only handle selection if selectOnActivate is enabled
            if (this.selectOnActivate) {
                this.clearSelection();
                item.selected = true;
            }
            this.hide();
            return super.notifySelect(item, index);
        }
        /**
         * Clears selection from all menu items
         */
        clearSelection() {
            const items = this.queryMenuItems();
            items.forEach((menuItem) => {
                menuItem.selected = false;
            });
        }
        /**
         * Gets the currently selected menu item
         */
        get selectedItem() {
            const items = this.queryMenuItems();
            return items.find((item) => item.selected) || null;
        }
        /**
         * Sets the selected menu item
         */
        setSelectedItem(item) {
            this.clearSelection();
            if (item) {
                item.selected = true;
            }
        }
        /**
         * Handles sub-menu opening
         */
        handleSubMenuOpen(e) {
            const subMenu = e.detail.subMenu;
            this.setActiveSubMenu(subMenu);
        }
        /**
         * Handles slot changes to update menu items
         */
        handleSlotChange() {
            // Update the items list when slot content changes
            this.updateItems();
        }
        render() {
            const classes = classMap({
                'menu-container': true,
            });
            return html `
      <div class=${classes}>
        <slot @slotchange=${this.handleSlotChange}></slot>
      </div>
    `;
        }
    };
})();
/**
 * Material Design 3 Menu component with sub-menu support.
 * Uses Popover API and Anchor Positioning API for modern positioning.
 *
 * @fires select - Dispatched when a menu item is selected
 * @fires close - Dispatched when the menu is closed
 * @fires open - Dispatched when the menu is opened
 */
export default Menu;
//# sourceMappingURL=Menu.js.map