/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */
import { c as customElement } from "../../chunks/runtime.js";
import { ref } from "lit/directives/ref.js";
import { css, html, nothing } from "lit";
import { LitElement, createEvent, safeClassMap } from "@arcgis/lumina";
import { g as getRoundRobinIndex } from "../../chunks/array.js";
import { t as toAriaBoolean } from "../../chunks/aria.js";
import { g as guid } from "../../chunks/guid.js";
import { i as isActivationKey } from "../../chunks/key.js";
import { i as isAction } from "../../chunks/resources.js";
import { u as useSetFocus } from "../../chunks/useSetFocus.js";
import { I as IDS, S as SLOTS, a as ICONS, C as CSS } from "../../chunks/resources2.js";
const styles = css`:host([scale=s]){--calcite-internal-action-menu-gap: var(--calcite-action-menu-items-space, var(--calcite-spacing-xxs));--calcite-internal-action-menu-padding: var(--calcite-spacing-xxs)}:host([scale=m]){--calcite-internal-action-menu-gap: var(--calcite-action-menu-items-space, var(--calcite-spacing-sm));--calcite-internal-action-menu-padding: var(--calcite-spacing-sm)}:host([scale=l]){--calcite-internal-action-menu-gap: var(--calcite-action-menu-items-space, var(--calcite-spacing-sm-plus));--calcite-internal-action-menu-padding: var(--calcite-spacing-sm-plus)}:host{box-sizing:border-box;display:flex;flex-direction:column;font-size:var(--calcite-font-size-relative-lg)}::slotted(calcite-action-group:not(:last-of-type)){border-block-end-width:var(--calcite-border-width-sm);padding-block-end:var(--calcite-internal-action-menu-padding)}.default-trigger{position:relative;block-size:100%;flex:0 1 auto;align-self:stretch}slot[name=trigger]::slotted(calcite-action),calcite-action::slotted([slot=trigger]){position:relative;block-size:100%;flex:0 1 auto;align-self:stretch}.menu{display:flex;max-block-size:45vh;flex-direction:column;flex-wrap:nowrap;overflow-y:auto;overflow-x:hidden;outline:2px solid transparent;outline-offset:2px;gap:var(--calcite-internal-action-menu-gap);padding:var(--calcite-internal-action-menu-padding)}:host([hidden]){display:none}[hidden]{display:none}`;
const SUPPORTED_MENU_NAV_KEYS = ["ArrowUp", "ArrowDown", "End", "Home"];
class ActionMenu extends LitElement {
  constructor() {
    super(...arguments);
    this.guid = guid();
    this.actionElements = [];
    this.menuButtonClick = () => {
      this.toggleOpen();
    };
    this.menuButtonId = IDS.button(this.guid);
    this.menuButtonKeyDown = (event) => {
      const { key } = event;
      const { actionElements, activeMenuItemIndex, open } = this;
      if (!actionElements.length) {
        return;
      }
      if (isActivationKey(key)) {
        event.preventDefault();
        if (!open) {
          this.toggleOpen();
          return;
        }
        const action = actionElements[activeMenuItemIndex];
        if (action) {
          action.click();
        } else {
          this.toggleOpen(false);
        }
      }
      if (key === "Tab") {
        this.open = false;
        return;
      }
      if (key === "Escape") {
        this.toggleOpen(false);
        event.preventDefault();
        return;
      }
      this.handleActionNavigation(event, key, actionElements);
    };
    this.menuId = IDS.menu(this.guid);
    this._open = false;
    this.updateAction = (action, index) => {
      const { guid: guid2, activeMenuItemIndex } = this;
      const id = IDS.action(guid2, index);
      action.tabIndex = -1;
      action.setAttribute("role", "menuitem");
      if (!action.id) {
        action.id = id;
      }
      action.activeDescendant = index === activeMenuItemIndex;
    };
    this.focusSetter = useSetFocus()(this);
    this.mouseDownHandler = (event) => {
      if (!event.composedPath().some(isAction)) {
        return;
      }
      this.activeMenuItemIndex = this.actionElements?.findIndex((action) => action === event.target);
    };
    this.activeMenuItemIndex = -1;
    this.appearance = "solid";
    this.expanded = false;
    this.overlayPositioning = "absolute";
    this.placement = "auto";
    this.topLayerDisabled = false;
    this.scale = "m";
    this.calciteActionMenuCollapse = createEvent({ cancelable: false });
    this.calciteActionMenuExpand = createEvent({ cancelable: false });
    this.calciteActionMenuOpen = createEvent({ cancelable: false });
  }
  static {
    this.properties = { activeMenuItemIndex: [16, {}, { state: true }], menuButtonEl: [16, {}, { state: true }], appearance: [3, {}, { reflect: true }], expanded: [7, {}, { reflect: true, type: Boolean }], flipPlacements: [0, {}, { attribute: false }], label: 1, open: [7, {}, { reflect: true, type: Boolean }], overlayPositioning: [3, {}, { reflect: true }], placement: [3, {}, { reflect: true }], topLayerDisabled: [7, {}, { reflect: true, type: Boolean }], scale: [3, {}, { reflect: true }] };
  }
  static {
    this.styles = styles;
  }
  get open() {
    return this._open;
  }
  set open(open) {
    const oldOpen = this._open;
    if (open !== oldOpen) {
      this._open = open;
      this.openHandler(open);
    }
  }
  async setFocus(options) {
    return this.focusSetter(() => this.menuButtonEl, options);
  }
  connectedCallback() {
    super.connectedCallback();
    this.connectMenuButtonEl();
    this.listen("mousedown", this.mouseDownHandler);
  }
  willUpdate(changes) {
    if (changes.has("expanded") && (this.hasUpdated || this.expanded !== false)) {
      this.expandedHandler();
    }
    if (changes.has("activeMenuItemIndex") && (this.hasUpdated || this.activeMenuItemIndex !== -1)) {
      this.updateActions(this.actionElements);
    }
    if (changes.has("expanded") && this.hasUpdated) {
      if (this.expanded) {
        this.calciteActionMenuExpand.emit();
      } else {
        this.calciteActionMenuCollapse.emit();
      }
    }
  }
  disconnectedCallback() {
    super.disconnectedCallback();
    this.disconnectMenuButtonEl();
  }
  expandedHandler() {
    this.open = false;
    this.setTooltipReferenceElement();
  }
  openHandler(open) {
    if (this.menuButtonEl) {
      this.menuButtonEl.active = open;
      this.menuButtonEl.aria = {
        expanded: open
      };
    }
    if (this.popoverEl) {
      this.popoverEl.open = open;
    }
    this.activeMenuItemIndex = this.open ? 0 : -1;
    this.calciteActionMenuOpen.emit();
    this.setTooltipReferenceElement();
  }
  connectMenuButtonEl() {
    const { menuButtonId, menuId, open, label } = this;
    const menuButtonEl = this.slottedMenuButtonEl || this.defaultMenuButtonEl;
    if (this.menuButtonEl === menuButtonEl) {
      return;
    }
    this.disconnectMenuButtonEl();
    this.menuButtonEl = menuButtonEl;
    this.setTooltipReferenceElement();
    if (!menuButtonEl) {
      return;
    }
    menuButtonEl.active = open;
    menuButtonEl.setAttribute("aria-controls", menuId);
    menuButtonEl.setAttribute("aria-expanded", toAriaBoolean(open));
    menuButtonEl.setAttribute("aria-haspopup", "true");
    if (!menuButtonEl.id) {
      menuButtonEl.id = menuButtonId;
    }
    if (!menuButtonEl.label) {
      menuButtonEl.label = label;
    }
    if (!menuButtonEl.text) {
      menuButtonEl.text = label;
    }
    menuButtonEl.addEventListener("click", this.menuButtonClick);
    menuButtonEl.addEventListener("keydown", this.menuButtonKeyDown);
  }
  disconnectMenuButtonEl() {
    const { menuButtonEl } = this;
    if (!menuButtonEl) {
      return;
    }
    menuButtonEl.removeEventListener("click", this.menuButtonClick);
    menuButtonEl.removeEventListener("keydown", this.menuButtonKeyDown);
    this.menuButtonEl = null;
  }
  setMenuButtonEl(event) {
    const actions = event.target.assignedElements({
      flatten: true
    }).filter((el) => el?.matches("calcite-action"));
    this.slottedMenuButtonEl = actions[0];
    this.connectMenuButtonEl();
  }
  setDefaultMenuButtonEl(el) {
    this.defaultMenuButtonEl = el;
    this.connectMenuButtonEl();
  }
  setPopoverEl(el) {
    if (!el) {
      return;
    }
    this.popoverEl = el;
    el.open = this.open;
  }
  handleCalciteActionClick(event) {
    if (this.actionElements?.some((action) => event.composedPath().includes(action))) {
      this.open = false;
      this.setFocus();
    }
  }
  updateTooltip(event) {
    const tooltips = event.target.assignedElements({
      flatten: true
    }).filter((el) => el?.matches("calcite-tooltip"));
    this.tooltipEl = tooltips[0];
    this.setTooltipReferenceElement();
  }
  setTooltipReferenceElement() {
    const { tooltipEl, expanded, menuButtonEl, open } = this;
    if (tooltipEl) {
      tooltipEl.referenceElement = !expanded && !open ? menuButtonEl : null;
    }
  }
  updateActions(actions) {
    actions?.forEach(this.updateAction);
  }
  async handleDefaultSlotChange(event) {
    const actions = event.target.assignedElements({
      flatten: true
    }).reduce((previousValue, currentValue) => {
      if (currentValue?.matches("calcite-action")) {
        previousValue.push(currentValue);
        return previousValue;
      }
      if (currentValue?.matches("calcite-action-group")) {
        return previousValue.concat(Array.from(currentValue.querySelectorAll("calcite-action")));
      }
      return previousValue;
    }, []);
    await this.componentOnReady();
    this.actionElements = actions.filter((action) => !action.disabled && !action.hidden);
  }
  isValidKey(key, supportedKeys) {
    return !!supportedKeys.find((k) => k === key);
  }
  handleActionNavigation(event, key, actions) {
    if (!this.isValidKey(key, SUPPORTED_MENU_NAV_KEYS)) {
      return;
    }
    event.preventDefault();
    if (!this.open) {
      this.toggleOpen();
      if (key === "Home" || key === "ArrowDown") {
        this.activeMenuItemIndex = 0;
      }
      if (key === "End" || key === "ArrowUp") {
        this.activeMenuItemIndex = actions.length - 1;
      }
      return;
    }
    if (key === "Home") {
      this.activeMenuItemIndex = 0;
    }
    if (key === "End") {
      this.activeMenuItemIndex = actions.length - 1;
    }
    const currentIndex = this.activeMenuItemIndex;
    if (key === "ArrowUp") {
      this.activeMenuItemIndex = getRoundRobinIndex(Math.max(currentIndex - 1, -1), actions.length);
    }
    if (key === "ArrowDown") {
      this.activeMenuItemIndex = getRoundRobinIndex(currentIndex + 1, actions.length);
    }
  }
  toggleOpen(value = !this.open) {
    this.open = value;
  }
  handlePopoverOpen(event) {
    event.stopPropagation();
    this.open = true;
    this.setFocus();
  }
  handlePopoverClose(event) {
    event.stopPropagation();
    this.open = false;
  }
  renderMenuButton() {
    const { appearance, label, scale, expanded } = this;
    const menuButtonSlot = html`<slot name=${SLOTS.trigger} @slotchange=${this.setMenuButtonEl}><calcite-action .appearance=${appearance} .aria=${{ expanded }} class=${safeClassMap(CSS.defaultTrigger)} .icon=${ICONS.menu} .scale=${scale} .text=${label} .textEnabled=${expanded} ${ref(this.setDefaultMenuButtonEl)}></calcite-action></slot>`;
    return menuButtonSlot;
  }
  renderMenuItems() {
    const { actionElements, activeMenuItemIndex, menuId, menuButtonEl, label, placement, overlayPositioning, flipPlacements } = this;
    const activeAction = actionElements[activeMenuItemIndex];
    const activeDescendantId = activeAction?.id || null;
    return html`<calcite-popover auto-close .flipPlacements=${flipPlacements} focus-trap-disabled .label=${label} offset-distance=0 @calcitePopoverClose=${this.handlePopoverClose} @calcitePopoverOpen=${this.handlePopoverOpen} .overlayPositioning=${overlayPositioning} .placement=${placement} pointer-disabled .referenceElement=${menuButtonEl} .scale=${this.scale} .topLayerDisabled=${this.topLayerDisabled} trigger-disabled ${ref(this.setPopoverEl)}><div aria-activedescendant=${activeDescendantId ?? nothing} aria-labelledby=${menuButtonEl?.id ?? nothing} class=${safeClassMap(CSS.menu)} id=${menuId ?? nothing} @click=${this.handleCalciteActionClick} role=menu tabindex=-1><slot @slotchange=${this.handleDefaultSlotChange}></slot></div></calcite-popover>`;
  }
  render() {
    return html`${this.renderMenuButton()}${this.renderMenuItems()}<slot name=${SLOTS.tooltip} @slotchange=${this.updateTooltip}></slot>`;
  }
}
customElement("calcite-action-menu", ActionMenu);
export {
  ActionMenu
};
