/**
 * Copyright IBM Corp. 2026
 *
 * This source code is licensed under the Apache-2.0 license found in the
 * LICENSE file in the root directory of this source tree.
 */

import "../../globals/settings.js";
import { carbonElement } from "../../globals/decorators/carbon-element.js";
import { __decorate } from "../../_virtual/_@oxc-project_runtime@0.126.0/helpers/decorate.js";
import HostListener from "../../globals/decorators/host-listener.js";
import HostListenerMixin from "../../globals/mixins/host-listener.js";
import menu_default$1 from "./menu.scss.js";
import { MenuContext, menuDefaultState } from "./menu-context.js";
import { MENU_SIZE } from "./defs.js";
import { MENU_CLOSE_ROOT_EVENT } from "./menu-item.js";
import { LitElement, html } from "lit";
import { property, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { consume, provide } from "@lit/context";
//#region src/components/menu/menu.ts
/**
* Copyright IBM Corp. 2024, 2026
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/
let CDSMenu = class CDSMenu extends HostListenerMixin(LitElement) {
	constructor(..._args) {
		super(..._args);
		this.context = {
			...menuDefaultState,
			updateFromChild: (updatedItem) => {
				this.context = {
					...this.context,
					...updatedItem
				};
			}
		};
		this.spacing = 8;
		this.items = [];
		this.activeitems = [];
		this.isChild = false;
		this.isRtl = false;
		this.isRoot = true;
		this.direction = "ltr";
		this.open = true;
		this.position = [-1, -1];
		this.size = "sm";
		this.backgroundToken = "layer";
		this.border = false;
		this.x = 0;
		this.y = 0;
		this._handleBlur = (e) => {
			const { isRoot } = this.context;
			if (this.open && isRoot && !this.contains(e.relatedTarget)) this.dispatchCloseEvent(e);
		};
		this._handleKeyDown = (e) => {
			const { isRoot } = this.context;
			e.stopPropagation();
			if (e.key === "Escape" || !isRoot && e.key === "ArrowLeft") this.dispatchCloseEvent(e);
			else {
				if (e.key === "ArrowUp" || e.key === "ArrowDown") e.preventDefault();
				this._focusItem(e);
			}
		};
		this._focusItem = (e) => {
			let currentItem;
			if (document.activeElement?.tagName !== "CDS-MENU") {
				const shadowRootActiveEl = this._findActiveElementInShadowRoot(document);
				currentItem = this.activeitems.findIndex((activeItem) => {
					return shadowRootActiveEl == activeItem.item || activeItem.item.shadowRoot?.activeElement === shadowRootActiveEl;
				});
			} else currentItem = 0;
			let indexToFocus = currentItem;
			if (currentItem === -1) indexToFocus = 0;
			else if (e) {
				if (e.key === "ArrowUp") indexToFocus = indexToFocus - 1;
				if (e.key === "ArrowDown") indexToFocus = indexToFocus + 1;
			}
			if (indexToFocus < 0) indexToFocus = this.activeitems.length - 1;
			if (indexToFocus >= this.activeitems.length) indexToFocus = 0;
			if (indexToFocus !== currentItem) this.activeitems[indexToFocus]?.item?.focus();
		};
		this._findActiveElementInShadowRoot = (shadowRoot) => {
			if (shadowRoot === null) return null;
			let activeElement = shadowRoot.activeElement;
			while (activeElement && activeElement.shadowRoot && activeElement.shadowRoot.activeElement) activeElement = activeElement.shadowRoot.activeElement;
			return activeElement;
		};
		this._notEmpty = (value) => {
			return value !== null && value !== void 0;
		};
		this._fitValue = (range, axis) => {
			const { isRoot } = this.context;
			const { width, height } = (this.shadowRoot?.querySelector(`.cds-custom--menu`) ?? this).getBoundingClientRect();
			const alignment = isRoot ? "vertical" : "horizontal";
			const axes = {
				x: {
					max: window.innerWidth,
					size: width,
					anchor: alignment === "horizontal" ? range[1] : range[0],
					reversedAnchor: alignment === "horizontal" ? range[0] : range[1],
					offset: 0
				},
				y: {
					max: window.innerHeight,
					size: height,
					anchor: alignment === "horizontal" ? range[0] : range[1],
					reversedAnchor: alignment === "horizontal" ? range[1] : range[0],
					offset: isRoot ? 0 : 4
				}
			};
			if (this.actionButtonWidth && this.actionButtonWidth < axes.x.size && (this.menuAlignment === "bottom" || this.menuAlignment === "top")) axes.x.size = this.actionButtonWidth;
			if (this.actionButtonWidth && (this.menuAlignment === "bottom-end" || this.menuAlignment === "top-end") && axes.x.anchor >= 87 && this.actionButtonWidth < axes.x.size) {
				const diff = axes.x.anchor + axes.x.reversedAnchor;
				axes.x.anchor = axes.x.anchor + diff;
			}
			const { max, size, anchor, reversedAnchor, offset } = axes[axis];
			const options = [
				max - this.spacing - size - anchor >= 0 ? anchor - offset : false,
				reversedAnchor - size >= 0 ? reversedAnchor - size + offset : false,
				max - this.spacing - size
			];
			const topAlignment = this.menuAlignment === "top" || this.menuAlignment === "top-end" || this.menuAlignment === "top-start";
			if (typeof options[0] === "number" && topAlignment && options[0] >= 0 && !options[1] && axis === "y") this.style.transform = "translate(0)";
			else if (topAlignment && !options[0] && axis === "y") options[0] = anchor - offset;
			const bestOption = options.find((option) => option !== false);
			return bestOption >= this.spacing ? bestOption : this.spacing;
		};
		this._getPosition = (x) => {
			if (Array.isArray(x)) {
				const filtered = x.filter(this._notEmpty);
				if (filtered.length === 2) return filtered;
				else return;
			} else return [x, x];
		};
		this._calculatePosition = () => {
			const ranges = {
				x: this._getPosition(this.x),
				y: this._getPosition(this.y)
			};
			if (!ranges.x || !ranges.y) return [-1, -1];
			return [this._fitValue(ranges.x, "x") ?? -1, this._fitValue(ranges.y, "y") ?? -1];
		};
		this._handleOpen = async () => {
			const pos = this._calculatePosition();
			if (this.isRtl) {
				this.style.insetInlineStart = `initial`;
				this.style.insetInlineEnd = `${pos[0]}px`;
			} else {
				this.style.insetInlineStart = `${pos[0]}px`;
				this.style.insetInlineEnd = `initial`;
			}
			this.style.insetBlockStart = `${pos[1]}px`;
			this.position = pos;
			await this.updateComplete;
			this._registerMenuItems();
			this._setActiveItems();
			const init = {
				bubbles: true,
				cancelable: true,
				composed: true
			};
			if (this.dispatchEvent(new CustomEvent(this.constructor.eventOnOpen, init))) this.dispatchEvent(new CustomEvent(this.constructor.eventOnOpen, init));
		};
		this.dispatchCloseEvent = (e) => {
			const init = {
				bubbles: true,
				cancelable: true,
				composed: true,
				detail: {
					triggeredBy: e?.target,
					triggerEventType: e?.type
				}
			};
			if (this.dispatchEvent(new CustomEvent(this.constructor.eventOnClose, init))) this.dispatchEvent(new CustomEvent(this.constructor.eventOnClose, init));
		};
		this._handleClose = () => {
			this.position = [-1, -1];
			this.style.removeProperty("inset-inline-start");
			this.style.removeProperty("inset-inline-end");
			this.style.removeProperty("inset-block-start");
		};
		this._handleRootCloseRequest = (event) => {
			if (!this.context?.isRoot) return;
			this.dispatchCloseEvent(event.detail?.triggerEvent ?? event);
		};
		this._newContextCreate = () => {
			this.context = {
				...this.context,
				isRoot: false,
				size: this.size
			};
		};
		this._registerMenuItems = () => {
			let items;
			if (this.isChild) items = this.querySelector("slot[name=\"submenu\"]")?.assignedElements() ?? [];
			else items = this.shadowRoot?.querySelector("slot")?.assignedElements() ?? [];
			this.items = items?.filter((item) => {
				if (item.tagName === "CDS-MENU-ITEM") return !item.disabled;
				return item.tagName !== "CDS-MENU-ITEM-DIVIDER";
			});
		};
		this._setActiveItems = () => {
			this.activeitems = [];
			this.items?.map((item) => {
				let activeItem;
				switch (item.tagName) {
					case "CDS-MENU-ITEM-RADIO-GROUP": {
						const slotElements = item.querySelectorAll(`cds-custom-menu-item`);
						if (slotElements?.length) for (const entry of slotElements.entries()) {
							activeItem = {
								item: entry[1],
								parent: item
							};
							this.activeitems = [...this.activeitems, activeItem];
						}
						break;
					}
					case "CDS-MENU-ITEM-GROUP":
						(item.shadowRoot?.querySelector("slot")?.assignedElements())?.map((el) => {
							activeItem = {
								item: el,
								parent: el
							};
							this.activeitems = [...this.activeitems, activeItem];
						});
						break;
					case "CDS-MENU-ITEM-SELECTABLE":
						activeItem = {
							item: item.shadowRoot?.querySelector(`cds-custom-menu-item`),
							parent: item
						};
						this.activeitems = [...this.activeitems, activeItem];
						break;
					default:
						activeItem = {
							item,
							parent: null
						};
						this.activeitems = [...this.activeitems, activeItem];
				}
			});
			(this.activeitems[0]?.item ?? document.activeElement).focus();
		};
	}
	/**
	* The name of the custom event fired when the the Menu should be closed.
	*/
	static get eventOnClose() {
		return `cds-custom-menu-closed`;
	}
	/**
	* The name of the custom event fired when the the Menu should be opened.
	*/
	static get eventOnOpen() {
		return `cds-custom-menu-opened`;
	}
	updated(changedProperties) {
		if (changedProperties.has("open")) if (this.open) this._handleOpen();
		else this._handleClose();
	}
	connectedCallback() {
		super.connectedCallback();
		this.addEventListener("icon-detect", () => {
			this.shadowRoot?.querySelector(".cds-custom--menu")?.classList.add(`cds-custom--menu--with-icons`);
		});
		this.addEventListener(MENU_CLOSE_ROOT_EVENT, this._handleRootCloseRequest);
	}
	disconnectedCallback() {
		this.removeEventListener(MENU_CLOSE_ROOT_EVENT, this._handleRootCloseRequest);
		super.disconnectedCallback();
	}
	async firstUpdated() {
		this.isRtl = this.direction === "rtl";
		this.isRoot = this.context.isRoot;
		if (this.isChild) this._newContextCreate();
		await this.updateComplete;
		this._registerMenuItems();
		this._setActiveItems();
		(this.shadowRoot?.querySelector("slot"))?.addEventListener("slotchange", () => {
			this._registerMenuItems();
			this._setActiveItems();
		});
	}
	render() {
		const { open, menuAlignment, label, position, _handleKeyDown: handleKeyDown } = this;
		return html`
      <ul
        class="${classMap({
			[`cds-custom--menu`]: true,
			[`cds-custom--menu--${this.size}`]: this.size,
			[`cds-custom--menu--box-shadow-top`]: menuAlignment && menuAlignment.slice(0, 3) === "top",
			[`cds-custom--menu--open`]: open,
			[`cds-custom--menu--shown`]: position[0] >= 0 && position[1] >= 0,
			[`cds-custom--menu--with-selectable-items`]: this.context.hasSelectableItems,
			[`cds-custom--menu--border`]: this.border,
			[`cds-custom--menu--background-token__background`]: this.backgroundToken === "background"
		})}"
        aria-label="${label}"
        tabindex="-1"
        @keydown="${handleKeyDown}"
        role="menu">
        <slot></slot>
      </ul>
    `;
	}
	static {
		this.styles = menu_default$1;
	}
};
__decorate([provide({ context: MenuContext }), consume({ context: MenuContext })], CDSMenu.prototype, "context", void 0);
__decorate([state()], CDSMenu.prototype, "items", void 0);
__decorate([state()], CDSMenu.prototype, "activeitems", void 0);
__decorate([property({ type: String })], CDSMenu.prototype, "label", void 0);
__decorate([property({ type: Boolean })], CDSMenu.prototype, "isChild", void 0);
__decorate([property()], CDSMenu.prototype, "actionButtonWidth", void 0);
__decorate([property({ type: Boolean })], CDSMenu.prototype, "isRtl", void 0);
__decorate([property({ type: Boolean })], CDSMenu.prototype, "isRoot", void 0);
__decorate([property({ type: String })], CDSMenu.prototype, "direction", void 0);
__decorate([property({
	type: Boolean,
	reflect: true
})], CDSMenu.prototype, "open", void 0);
__decorate([property({ type: HTMLElement })], CDSMenu.prototype, "focusreturn", void 0);
__decorate([property()], CDSMenu.prototype, "position", void 0);
__decorate([property({ attribute: true })], CDSMenu.prototype, "size", void 0);
__decorate([property()], CDSMenu.prototype, "mode", void 0);
__decorate([property({
	type: String,
	attribute: "background-token"
})], CDSMenu.prototype, "backgroundToken", void 0);
__decorate([property({ type: Boolean })], CDSMenu.prototype, "border", void 0);
__decorate([property({ type: String })], CDSMenu.prototype, "menuAlignment", void 0);
__decorate([property()], CDSMenu.prototype, "x", void 0);
__decorate([property()], CDSMenu.prototype, "y", void 0);
__decorate([HostListener("focusout")], CDSMenu.prototype, "_handleBlur", void 0);
CDSMenu = __decorate([carbonElement(`cds-custom-menu`)], CDSMenu);
var menu_default = CDSMenu;
//#endregion
export { MENU_SIZE, menu_default as default };

//# sourceMappingURL=menu.js.map