import{type PropertyValues,type TemplateResult}from'lit';import{LyraElement}from'../../../internal/lyra-element.js';import type{LyraSize}from'../../../internal/variants.js';import{type MenuFocusTarget}from'./menu-shared.js';export type MenuItemType='normal'|'checkbox'|'radio';export type MenuItemVariant='default'|'danger';export interface MenuItemChangeDetail{value:string;checked:boolean;} /** The navigability flags `` re-checks its roving tabindex against. */ export interface MenuItemStateChangeDetail{ /** `disabled || loading` — the item's effective `interactionDisabled`. */ disabled:boolean;hidden:boolean;inert:boolean;}export interface LyraMenuItemEventMap{'lr-menu-item-state-change':CustomEvent;'lr-menu-item-change':CustomEvent;} /** * `` — a single action row inside ``'s default * slot. Not meaningful on its own (there is no standalone "click a menu item" * use case) — it exists purely as ``'s light-DOM child, the same * relationship `` has to ``/``. * * `role="menuitem"` and the roving `tabindex` both live on *this host * element*, not an internal shadow-DOM button — mirroring ``'s * identical choice (see that class's doc). `` is the sole owner of * this element's `tabIndex`: it flips exactly one navigable item's `tabIndex` * to `0` (the rest sit at `-1`) as its roving-tabindex highlight moves, and * calls `.focus()` directly on this host to move real DOM focus there. * `[part="base"]` is purely a visual box with no interactive semantics of its * own — see the class doc on `` for why real DOM focus (rather * than `aria-activedescendant`) was chosen for this pair. * * Enter/Space activation is handled by ``'s own delegated * `keydown` listener calling `select()` on whichever item is currently * roving-focused (mirrors `` calling `current.select()` from its * own keydown handler). The visual row wires the pointer `click` listener, * and the host's `click()` forwards to that same row, so `select()` fires * identically whether the item was reached by mouse, keyboard, or a * programmatic host click. * * A `` or one or more direct mapped items assigned to the `submenu` slot turns this row * into a submenu parent: the host gains `aria-haspopup="menu"` plus an `aria-expanded` that * renders `"true"` *and* `"false"` (never omitted — the attribute is part of * the role's state, so a Lit `?aria-expanded=` directive would be wrong), a * chevron renders in `[part="submenu-icon"]`, and activation opens the * submenu instead of selecting. The parent `` owns the interaction * policy — the arrow keys (mirrored under RTL), pointer intent, and the * one-submenu-per-level rule — and drives it through `openSubmenu()` / * `closeSubmenu()`; this element owns the ARIA, the naming, and the panel * wiring. Because a submenu parent is a disclosure rather than an action, it * never activates the menu, and neither `type="checkbox"` nor `type="radio"` has any effect on * one. A submenu selection is * the same single `lr-select` event bubbling through the outer menu — there is no separate nested * selection event or public child-to-menu event. * * The default label slot's flattened subtree is visual-only: it is inert and * hidden from assistive technology so the focusable host remains the row's * sole action. Its accessible text names both this item and its submenu's * `role="menu"`, without allowing an open submenu to leak into the item's * name. Direct and flattened, forwarded default-slot labels are observed live * so in-place text edits, reassignments, and relevant visibility changes * update type-ahead and both computed names. Accessibility-hidden branches are * omitted; a real forwarding-slot assignment remains authoritative even when * hidden, while fallback contributes once no assignment remains. A host-level * `aria-label` or `aria-labelledby` remains authoritative; a `label`/ * `aria-label` on the submenu itself does too. An explicitly empty * `aria-label` and a value supplied after the initial computed name both win. * * `type="checkbox"` (mirroring `wa-dropdown-item`'s identical `type` option) * renders `role="menuitemcheckbox"` in place of `role="menuitem"`, with * `aria-checked` reflecting `checked` and a checkmark glyph shown once * `checked` is `true`. Activating a `checkbox`-type item (click, or the * parent's Enter/Space handling via `select()`) first fires a cancelable * `lr-menu-item-change` with the proposed next `checked` value, then mutates * `checked` unless a listener prevents that event. It fires * the owning menu's canonical `lr-select` afterwards either way. `type="normal"` (the default) renders and * behaves exactly as before this option existed — no role, rendering, or * event differences. * * `type="radio"` renders `role="menuitemradio"` instead, reusing the same * `aria-checked` reflection and checkmark glyph as `checkbox`, but with * exclusive-choice group semantics layered on top: activating an already- * `checked` radio is a no-op on `checked` itself — no `lr-menu-item-change` * proposal, no state change, matching native `` * semantics — though it still falls through to the owning menu's usual * selection, exactly like re-activating any other item. Activating an * *unchecked* radio fires the same cancelable `lr-menu-item-change` with * `checked: true`; once that is not prevented, this item becomes `checked` * and every other `type="radio"` item the *same owning ``* owns * directly (never one owned by a nested submenu, which has its own owning * menu) whose `group` matches this item's `group` is unchecked directly — * without an `lr-menu-item-change` of its own. `group` defaults to `undefined`, * so every ungrouped radio row beneath one menu shares a single exclusive * scope unless narrowed by giving each subset its own `group` string. * * @customElement lr-menu-item * @slot - The item's visual label content. Its flattened subtree is inert and hidden from assistive * technology; its accessible text names the host menu item. * @slot icon - Optional decorative leading icon. Its flattened subtree is inert and hidden from * assistive technology. * @slot prefix - Shoelace-compatible decorative alias for leading content. Its flattened subtree is * inert and hidden from assistive technology. * @slot details - Decorative secondary WA-compatible detail text rendered after the label. Its * flattened subtree is inert and hidden from assistive technology. * @slot suffix - Shoelace-compatible decorative trailing content. Its flattened subtree is inert and * hidden from assistive technology. * @slot submenu - A nested `` or direct mapped menu items that open beside this row. * @event lr-menu-item-change - A `type="checkbox"` item was activated, or a `type="radio"` item * was activated while unchecked (an already-checked radio never fires this). * `detail: { value, checked }` contains the item's own `value` and the * proposed next `checked` value, before the property mutates. Cancelable: * prevent it to retain the current `checked` value. The usual * the parent menu's `lr-select` still follows, so selection and close * behavior are unchanged. Never fired for `type="normal"`. Unchecking a radio's group siblings * once this event commits fires no event of its own. * @event lr-menu-item-state-change - Something that decides whether this item is navigable changed: * `disabled`, `loading`, `hidden`, `inert`, or `aria-hidden`. `detail: { disabled, hidden, inert }`, * where `disabled` is the effective `disabled || loading`. `` consumes this to repair its * roving-tabindex state immediately. The last three are plain native attributes rather than * reactive properties, so they are watched with the item's own `MutationObserver`; `aria-hidden` * fires the event without appearing in the detail, which carries only the item's own state flags. * @csspart base - The row (`role` lives on the host — see the class doc). * @csspart icon - Wrapper around the `icon` slot. Not rendered at all when the slot is empty. * @csspart prefix - Wrapper around the `prefix` slot. * @csspart label - Wrapper around the default slot. * @csspart checkmark - The checkmark glyph shown when a `type="checkbox"`/`type="radio"` item is * `checked`. Not rendered at all for `type="normal"`. * @csspart checked-icon - Shoelace-compatible wrapper around the checked glyph. * @csspart details - Wrapper around the `details` slot. * @csspart suffix - Wrapper around the `suffix` slot. * @csspart spinner - Loading spinner. * @csspart spinner__base - Shoelace-compatible alias on the loading spinner. * @csspart submenu-icon - Wrapper around the chevron shown on a submenu parent. Not rendered at all without a `submenu` slot. Mirrors under RTL through this wrapper, never by swapping the glyph. * @csspart submenu - The submenu panel/wrapper. * @cssprop [--submenu-offset=-2px] - Final signed distance between a submenu and its parent row. * Negative values overlap the parent menu; positive values add separation. Mirrors under RTL. * @cssprop [--lr-menu-item-gap=var(--lr-space-xs)] - Gap between the visual parts of * `[part="base"]`, including its leading content, label, trailing details, and state glyphs. * Declared as an inline `var()` fallback (never on `:host`), so an item or any ancestor can retune * it without a `::part(base)` rule. It is constant across the shared size ladder. * @cssprop [--lr-menu-item-radius=var(--lr-form-control-radius)] - Corner radius of the visual row * and focusable host. Its fallback follows the active shared size tier. Declared as an inline * `var()` fallback (never on `:host`), so an item or any ancestor can retune it without a * `::part(base)` rule. * Danger-state hooks are also inline fallbacks, so a menu can retheme only its dangerous rows * without replacing the shared danger palette elsewhere. * @cssprop [--lr-menu-item-danger-color=var(--lr-color-danger)] - Foreground of a * `variant="danger"` row. * @cssprop [--lr-menu-item-danger-hover-bg=var(--lr-color-danger-quiet)] - Background of an enabled * danger row while hovered. * @cssprop [--lr-menu-item-danger-active-bg=color-mix(in oklab, var(--lr-color-danger-quiet), var(--lr-color-mix-partner) var(--lr-color-mix-active))] - Background of an enabled danger row while pressed. * Checked-state hooks are also inline fallbacks, matching ``/``/ * ``/``'s equivalent row-chrome hooks; all three default to no visual * change, so a `type="checkbox"`/`type="radio"` item's checked row paints identically to before * these existed unless a consumer sets one. * @cssprop [--lr-menu-item-checked-bg=transparent] - Background of a checked (`type="checkbox" * checked` or `type="radio" checked`) row. * @cssprop [--lr-menu-item-checked-color=inherit] - Foreground of a checked row. * @cssprop [--lr-menu-item-checked-font-weight=inherit] - Font weight of a checked row. * @cssprop [--lr-menu-item-hover-bg=var(--lr-color-brand-quiet)] - Background of an enabled row * under the pointer. The pressed state mixes from this same value, so a retuned hover fill keeps * its pressed step instead of snapping back to the brand default. * @cssprop [--lr-menu-item-active-bg=color-mix(in oklab,var(--lr-menu-item-hover-bg,var(--lr-color-brand-quiet)),var(--lr-color-mix-partner) var(--lr-color-mix-active))] - * Background of an enabled row while pressed, matching `--lr-option-active-bg`'s equivalent hook. * Left unset, the pressed fill keeps mixing from `--lr-menu-item-hover-bg` as before this hook * existed. * @cssprop [--lr-menu-item-icon-color=inherit] - Foreground of the leading icon wrapper. Unset it * inherits the row's colour, including the danger variant's. * @cssprop [--lr-menu-item-min-height=max(var(--lr-form-control-height),var(--lr-size-24px))] - * Minimum block size of the visual row. Unset it is the shared form-control ladder floored at the * WCAG 2.2 SC 2.5.8 minimum, exactly as before this hook existed. * @method click - Activates the visual row, including checkbox and submenu behavior; no-op while * disabled or loading. * @method select - Activates a selectable item; no-op while disabled/loading and opens submenu parents. * @method openSubmenu - Opens the submenu and resolves after its open state settles. * @method closeSubmenu - Closes the submenu and resolves after its closed state settles. * @method getTextLabel - Returns the visible label used by type-ahead. * @status stable * @since 4.0.0 */ export declare class LyraMenuItem extends LyraElement{ /** Reflected from `submenuExpanded` as a styling hook. The parent `` owns submenu * state through `openSubmenu()`/`closeSubmenu()`, so this is output rather than input and is * not observed. `` inherits this and adds the `submenuopen` spelling to its * own `observedAttributes`, where it genuinely is settable. */ protected static readonly knownUnobservedAttributes:readonly string[];static styles:import("lit").CSSResultGroup[]; /** An id/value available on the item carried by the parent ``'s `lr-select` detail. */ value:string; /** Row density, on the library's shared six-step ladder — `'m'` by default. Scales the row's * height, inline/block padding, font size and corner radius together; `'small'`/`'medium'`/ * `'large'` are accepted as synonyms of `'s'`/`'m'`/`'l'`. Every tier still resolves to at * least the 24px pointer-target floor, so even `'2xs'` stays tappable. Each item carries its * own size rather than inheriting one from ``, so a single compact row inside an * otherwise default menu needs no wrapper. */ size:LyraSize; /** Disables selection and excludes this item from ``'s roving-tabindex nav entirely. */ disabled:boolean; /** Semantic treatment. `default` is the WA spelling of a normal action and `danger` is its * mapped dangerous-action treatment. */ variant:MenuItemVariant; /** `'checkbox'` renders `role="menuitemcheckbox"` with a toggleable `checked` state and a * checkmark glyph, mirroring `wa-dropdown-item`'s identical `type` option. `'radio'` renders * `role="menuitemradio"` with exclusive-choice group semantics — see the class doc for both. */ type:MenuItemType; /** Whether a `type="checkbox"`/`type="radio"` item is checked. Meaningless (ignored) for * `type="normal"`. */ checked:boolean; /** Narrows a `type="radio"` item's exclusive-choice scope to only the other radio items sharing * this same string. Unset (the default), the scope is every `type="radio"` item the same * owning `` owns directly — a nested submenu's radio items already belong to that * submenu's own `` instead, so they're never in scope regardless of `group`. Meaningless * (ignored) for `type="normal"`/`"checkbox"`. */ group?:string; /** Shows progress and makes the row interaction-disabled while an action is pending. */ loading:boolean; /** When set to a safe link URL (`http:`/`https:`/`blob:`/`mailto:`/relative — see * `safeLinkHref`, or `safeDownloadHref` which drops `mailto:` when `download` is set), * `[part="base"]` renders as a real `` instead of a ``, and activation (click, * or the parent's Enter/Space handling, which forwards through `click()` for a link item so the * anchor's own native default action runs) navigates there in addition to firing the usual * `select()`/`lr-select` contract. An unsafe/unparseable `href` falls back to the plain ``, * matching `lr-button`'s identical fallback. Mirrors `wa-dropdown-item`'s link-item support. */ href?:string; /** Native anchor `target`, used only while `href` resolves to a link. Setting this to `'_blank'` * (or any other target) always contributes `noopener noreferrer` to the rendered anchor's `rel` * — matching `lr-button`'s identical pattern. */ target?:string; /** Independently settable author relationship tokens for the rendered link (no default). * `opener` is always stripped, and any `target` force-adds the non-removable * `noopener noreferrer` guard — see `target`. */ rel?:string; /** Native anchor `download` attribute, used only while `href` resolves to a link. Narrows the * safe-URL allowlist to `safeDownloadHref`'s, which drops `mailto:` — a mail handoff names no * retrievable bytes, so it cannot be a download target. */ download?:string; /** Resolved `rel` for the rendered anchor: author tokens minus `opener`, plus the * `noopener noreferrer` guard whenever `target` is set. `undefined` when nothing remains, so the * attribute is omitted entirely rather than rendered empty. */ private get resolvedRel(); /** Resolved, safety-checked `href` for the rendered anchor, or `undefined` when `href` is unset * or fails the allowlist for its sink (`download` present narrows to `safeDownloadHref`). */ private get resolvedHref();private hasIconSlot;private hasDetailsSlot;private hasSuffixSlot;private detailsSlot?;private submenuAssigned;private submenuExpanded;private submenuKind;private slottedLabel;private submenuPanel;private submenuPanelAttached; /** Increments whenever the owned submenu identity becomes stale, so async show/hide continuations * cannot write disclosure state or popup ownership back onto a replacement panel. */ private submenuPanelGeneration; /** `hidden`/`inert`/`aria-hidden` are native attributes, not reactive properties: assigning * `item.inert = true` schedules no Lit update, so `willUpdate()` can never announce them. This * observer is what makes the item — rather than every parent that has to care — the authority on * its own navigability. */ private nativeStateObserver?; /** Watches default-slot label text, including flattened nodes projected from an outer wrapper. */ private labelObserver?;private labelObservationGeneration;private announcedNativeState;private owningMenu;private ownsAriaLabel;private ownedAriaLabelValue;private ownsPanelAriaLabel;private ownedPanelAriaLabelValue; /** Whether a nested `` or direct mapped items are assigned to this item's `submenu` * slot, making it a submenu parent. */ get hasSubmenu():boolean; /** Whether this item's submenu is currently open. Tracks the panel's own state, however it * changed — the parent menu's keyboard/pointer handling, a dismissal, or a direct write. */ get submenuOpen():boolean;set submenuOpen(next:boolean);connectedCallback():void;disconnectedCallback():void; /** Every flag a parent's navigability predicate reads, in one comparable string. */ private nativeStateSignature; /** A `MutationObserver` re-fires for a write that changes nothing (`item.hidden = item.hidden`), * so the signature comparison is what keeps a no-op write from waking every parent menu. */ private onNativeStateMutation;private emitStateChange;protected willUpdate(changed:PropertyValues):void; /** Activates the visual row, matching a consumer click on this focusable host. This preserves the * row's native click event path and its normal, checkbox, radio, and submenu branches. Disabled * and loading items remain inert. */ click():void; /** Activates this item through its owning menu (no-op while `disabled` or `loading`). Called by * this element's own click handler, and by ``'s Enter/Space keydown handling. * For `type="checkbox"`, first emits the cancelable proposed `lr-menu-item-change`; it commits * that proposed `checked` state only when the event is not prevented, then fires selection -- * see the class doc. For `type="radio"`, an already-`checked` item skips the proposal entirely * (no event, no state change -- native radio semantics) and simply falls through to selection; * an unchecked item proposes the same cancelable event with `checked: true` and, once * committed, unchecks every other radio row in its `group` beneath the owning menu. * * A submenu parent is a disclosure rather than an action: it opens its submenu (without * moving focus, since this path is the pointer one -- ``'s own Enter/Space handling * calls `openSubmenu('first')` directly instead) and fires neither event. */ select():void; /** Opens this item's submenu. A no-op without one, or while `disabled`/`loading`. `focus` uses * `'first'` for keyboard activation and `'none'` for * pointer intent, which must not pull focus out from under the keyboard. Re-opening an * already-open submenu still applies the focus target, so ArrowRight moves into a submenu the * pointer opened a moment earlier. */ openSubmenu(focus?:MenuFocusTarget):Promise; /** Closes this item's submenu (and, through it, any of its own descendants). A no-op without * one. Focus is left alone — the caller that moved it knows where it belongs. */ closeSubmenu():Promise;private onIconSlotChange;private onDetailsSlotChange;private syncDetailsSlot;private onSuffixSlotChange;private defaultLabelSlot;private isDefaultLabelBranch;private labelForwardingSlots;private composedParentForNode;private isLabelSubtreeExcluded;private readSlottedLabel;private observeLabelAncestors;private observeLabelContent;private syncSlottedLabel;private onLabelSlotChange;private onForwardedLabelSlotChange;private onSubmenuSlotChange;private syncSubmenuSlot;private connectSubmenuPanel; /** Whether an async submenu operation still owns this item after an awaited panel transition. */ private isCurrentSubmenuPanel;protected updated(changed:PropertyValues):void;protected firstUpdated(changed:PropertyValues):void; /** The private submenu controller reports every state transition, including Escape, outside * dismissal, selection, ancestor teardown, and panel replacement. */ private onPanelStateChange; /** Names the focusable host from its visual-only label text. This also prevents a submenu from * leaking its open content into the parent item's name. */ private applyComputedName; /** Names the submenu's `role="menu"` after the row that opens it — the APG relationship, which * `aria-labelledby` cannot express here because an idref cannot cross a shadow boundary. */ private applyPanelName; /** Text label used by type-ahead and Shoelace-compatible integrations. */ getTextLabel():string;render():TemplateResult;}declare global{interface HTMLElementTagNameMap{'lr-menu-item':LyraMenuItem;}}