dap-design-system 0.61.2 → 0.61.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"navigation-menu-item.component.js","sources":["../../../src/components/navigation-menu/navigation-menu-item.component.ts"],"sourcesContent":["import {\n autoUpdate,\n computePosition,\n flip,\n offset,\n shift,\n size,\n} from '@floating-ui/dom'\nimport clsx from 'clsx'\nimport { nothing, unsafeCSS } from 'lit'\nimport {\n property,\n query,\n queryAssignedElements,\n state,\n} from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { html } from 'lit/static-html.js'\n\nimport { watch } from '../../common/decorators'\nimport {\n FloatingStrategy,\n LinkTarget,\n PopupPlacement,\n TabNavigationMode,\n} from '../../common/types'\nimport { DdsElement } from '../../internal/dds-hu-element'\nimport { SizedMixin } from '../../internal/mixin/sizedMixin'\nimport DapDSButton from '../button/button.component'\nimport DapDSIcon from '../icon/icon.component'\nimport popupStyles from '../popup/popup.scss?inline'\nimport DapDSStack from '../stack/stack.component'\nimport styles from './navigation-menu-item.scss?inline'\nimport { SubmenuController } from './submenu-controller'\n\n/**\n * `dap-ds-navigation-menu-item`\n * @summary A navigation menu item that can contain either a simple link or dropdown content.\n * Supports nested items with cascading flyout behavior. Part of the navigation menu system.\n * This is for NAVIGATION (website menus), not application menus.\n *\n * @element dap-ds-navigation-menu-item\n * @title - Navigation Menu Item\n * @group navigation-menu\n *\n * @property {string} label - The label text for the navigation item. This will be displayed in the title slot if no custom title slot content is provided.\n * @property {'xs' | 'sm' | 'lg'} size - The size of the popup. Default is 'sm'.\n * @property {boolean} disabled - The disabled state of the popup. Default is false.\n * @property {boolean} opened - The open state of the popup. Default is false.\n * @property {'top' | 'right' | 'bottom' | 'left' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end' | 'right-start' | 'right-end'} placement - The placement of the popup (automatically adjusted based on nesting level). Default is 'bottom-start'.\n * @property {'absolute' | 'fixed'} floatingStrategy - The floating strategy of the popup. Default is 'fixed'.\n * @property {number} offset - The offset of the popup. Default is 0.\n * @property {boolean} sync - Whether the popup should sync its width with the trigger. Default is false.\n * @property {number | 'auto'} maxHeight - The maximum height of the popup. Default is 250.\n * @property {number | 'auto'} maxWidth - The maximum width of the popup. Default is 'auto'.\n * @property {boolean} hasArrow - Whether the popup has an arrow. Default is false.\n * @property {boolean} overflow - Whether the popup should overflow. Default is true.\n * @property {boolean} fullWidth - Whether the popup should take full width of the screen. Default is false.\n * @property {boolean} exactHref - Whether the navigation item should be active if the href is exactly the same as the activeHref. Default is false.\n * @property {string} icon - The name of the icon to display in the trigger.\n * @property {string} ariaLabelledBy - The name of the element that labels the navigation dropdown.\n * @property {string} activeHref - The href of the navigation item that is active (receives aria-current=\"page\").\n * @property {string} baseHref - The href of the navigation item. If provided, the navigation item will be active if the href is a substring of the activeHref.\n * @property {string} href - The href URL for the navigation item link. When provided, the default trigger renders as a link.\n * @property {'_blank' | '_self' | '_parent' | '_top'} target - The target attribute for link navigation.\n * @property {string} rel - The rel attribute for link security and behavior.\n * @property {number} level - The nesting level of this navigation item (0 = top-level, automatically set for nested items). Default is 0.\n * @property {'horizontal' | 'vertical'} orientation - The orientation of the parent navigation menu (automatically inherited). Default is 'horizontal'.\n * @property {'group' | 'items'} tabMode - Controls how Tab key navigates through top-level items. Default is 'group'.\n *\n * @event {{ href: string, event: Event }} dds-navigation-item-click - Fired when a navigation item is clicked.\n * @event {{ item: DapDSNavigationMenuItem }} dds-navigation-dropdown-open - Fired when a navigation dropdown is opened.\n *\n * @slot trigger - The trigger element (link, button, etc.) for this navigation item.\n * @slot title - The title of the navigation item.\n * @slot indicator - The expand indicator icon (defaults to arrow icon based on orientation and level).\n * @slot link - A router link element (e.g. Next.js Link) used for SPA navigation.\n * Rendered outside the popup so it is always accessible to programmatic clicks.\n * @slot - The dropdown content (can contain nested dap-ds-navigation-menu-item elements).\n *\n * @csspart base - The base part of the navigation item.\n * @csspart trigger - The trigger element part.\n * @csspart trigger-base - The base part of the trigger button (from dap-ds-button).\n * @csspart trigger-content - The content part of the trigger button (from dap-ds-button).\n * @csspart trigger-high-contrast - The high contrast part of the trigger button (from dap-ds-button).\n * @csspart trigger-stack-base - The base part of the trigger stack (from dap-ds-stack).\n * @csspart title - The title slot wrapper.\n * @csspart indicator - The expand indicator container.\n * @csspart indicator-icon - The expand indicator icon part.\n * @csspart indicator-icon-base - The base part of the indicator icon (from dap-ds-icon).\n * @csspart indicator-icon-icon - The icon part of the indicator icon (from dap-ds-icon).\n * @csspart popup - The dropdown popup container.\n * @csspart content - The dropdown content wrapper (default slot).\n * @csspart arrow - The dropdown arrow part.\n *\n * @cssproperty --dds-navigation-menu-item-spacing - The padding/spacing of the navigation menu item content. (default: var(--dds-spacing-200)).\n * @cssproperty --dds-navigation-menu-item-border-width - The border width of the navigation menu item content. (default: var(--dds-border-width-base)).\n * @cssproperty --dds-navigation-menu-item-border-color - The border color of the navigation menu item content. (default: var(--dds-border-neutral-subtle)).\n * @cssproperty --dds-navigation-menu-item-border-radius - The border radius of the navigation menu item content. (default: var(--dds-radius-base)).\n * @cssproperty --dds-navigation-menu-item-background - The background color of the navigation menu item content. (default: var(--dds-background-neutral-base)).\n * @cssproperty --dds-navigation-menu-item-shadow - The box shadow of the navigation menu item content. (default: var(--dds-shadow-base)).\n *\n * @accessibility\n * - Active navigation items marked with `aria-current=\"page\"`\n * - Dropdowns use `aria-expanded` and `aria-haspopup`\n * - No menu/menuitem roles (this is navigation, not an application menu)\n */\nexport default class DapDSNavigationMenuItem extends SizedMixin(DdsElement) {\n static tagName = 'dap-ds-navigation-menu-item'\n\n static dependencies = {\n 'dap-ds-icon': DapDSIcon,\n 'dap-ds-button': DapDSButton,\n 'dap-ds-stack': DapDSStack,\n }\n\n static readonly styles = unsafeCSS(`${styles}${popupStyles}`)\n\n /** @ignore */\n @query('.popup') readonly popup!: HTMLDivElement\n\n /** @ignore */\n @queryAssignedElements({ slot: 'trigger' })\n private readonly _assignedTrigger!: HTMLElement[]\n\n // Popup properties\n /** @ignore */\n protected triggerElement: Element | null = null\n private cleanup: ReturnType<typeof autoUpdate> | undefined\n public readonly submenuController: SubmenuController\n\n /** The disabled state of the menu item. */\n @property({ reflect: true, type: Boolean }) disabled = false\n\n /** The open state of the dropdown menu. */\n @property({ reflect: true, type: Boolean }) opened = false\n\n /** The placement of the dropdown. */\n @property({ reflect: true }) placement: PopupPlacement = 'bottom-start'\n\n /** The floating strategy of the dropdown. */\n @property({ reflect: true }) floatingStrategy: FloatingStrategy = 'fixed'\n\n /** The offset of the dropdown from the trigger. */\n @property({ type: Number }) offset = 0\n\n /** Whether the dropdown should sync its width with the trigger. */\n @property({ type: Boolean }) sync = false\n\n /** The maximum height of the dropdown. */\n @property({ type: Number }) maxHeight: number | 'auto' = 250\n\n /** The maximum width of the dropdown. */\n @property({ type: Number }) maxWidth: number | 'auto' = 'auto'\n\n /** Whether the dropdown has an arrow. */\n @property({ type: Boolean }) hasArrow = false\n\n /** Whether the dropdown should overflow. */\n @property({ type: Boolean }) overflow = true\n\n /** Whether the dropdown should take full width of the screen. */\n @property({ type: Boolean }) fullWidth = false\n\n /** The name of the icon to display in the trigger. */\n @property({ type: String, reflect: true }) icon?: string\n\n /** ID of element that labels the navigation dropdown. */\n @property({ type: String, attribute: 'aria-labelledby' })\n ariaLabelledBy?: string\n\n /** The href of the navigation item that is active. */\n @property({ type: String, reflect: true }) activeHref?: string\n\n /** The href of the navigation item for prefix matching. */\n @property({ type: String, reflect: true }) baseHref?: string\n\n /** Whether the navigation item should use exact href matching. */\n @property({ type: Boolean, reflect: true }) exactHref = false\n\n /** The href URL for the navigation item link. When provided, the default trigger renders as a link. */\n @property({ type: String, reflect: true }) href?: string\n\n /** The target attribute for link navigation. */\n @property({ type: String, reflect: true }) target?: LinkTarget\n\n /** The rel attribute for link security and behavior. */\n @property({ type: String, reflect: true }) rel?: string\n\n /** The label text for the navigation item, displayed in the title slot when no slot content is provided. */\n @property({ type: String }) label?: string\n\n /** The nesting level of this navigation item (0 = top-level). */\n @property({ type: Number, reflect: true }) level = 0\n\n /** The orientation of the parent navigation menu. */\n @property({ reflect: true }) orientation: 'horizontal' | 'vertical' =\n 'horizontal'\n\n /** Controls tab key behavior (propagated from parent navigation menu). */\n @property({ type: String }) tabMode: TabNavigationMode = 'group'\n\n /** `data-testid` for the default menu trigger button. */\n @property() triggerButtonTestId = 'navigation-menu-item-trigger-button'\n\n @state() hasContent = false\n @state() private hasLink = false\n @state() private hasTitleSlot = false\n @state() private _titleText = ''\n @state() private active = false\n @state() private openedByHover = false\n @state() private _isRovingActive = false\n\n /** Computed property to detect if this item contains nested navigation menu items. */\n get hasNestedItems(): boolean {\n const nestedItems = this.querySelectorAll('dap-ds-navigation-menu-item')\n return nestedItems.length > 0\n }\n\n private get _trigger(): HTMLElement[] {\n // If there are assigned elements in the trigger slot, use only DIRECT children\n if (this._assignedTrigger && this._assignedTrigger.length > 0) {\n const directTriggers = this._assignedTrigger.filter(\n el => el.parentElement === this,\n )\n if (directTriggers.length > 0) {\n return directTriggers\n }\n }\n // Otherwise, find the default button in the shadow DOM\n // When slot has no assigned content, the fallback content (button) is rendered\n // The button is rendered as part of the slot's fallback content in the shadow DOM\n const defaultButton = this.shadowRoot?.querySelector('dap-ds-button')\n return defaultButton ? [defaultButton as HTMLElement] : []\n }\n\n /** Get the element slotted into the `link` slot, if any. */\n private _getLinkElement(): HTMLElement | null {\n const slot = this.shadowRoot?.querySelector(\n 'slot[name=\"link\"]',\n ) as HTMLSlotElement\n if (!slot) return null\n const elements = slot.assignedElements()\n return elements.length > 0 ? (elements[0] as HTMLElement) : null\n }\n\n /** Handle slot change for the `link` slot. */\n private _handleLinkSlotChange = (e: Event) => {\n const slot = e.target as HTMLSlotElement\n if (slot) {\n const elements = slot.assignedElements()\n this.hasLink = elements.length > 0\n // Remove link element from tab order — the trigger is the tab stop\n elements.forEach(el => el.setAttribute('tabindex', '-1'))\n }\n this._updateActiveState()\n }\n\n /** Handle slot change for the `title` slot. */\n private _handleTitleSlotChange = (e: Event) => {\n const slot = e.target as HTMLSlotElement\n if (slot) {\n const nodes = slot.assignedNodes({ flatten: true })\n // Check if slot has any content (elements or text nodes)\n this.hasTitleSlot = nodes.some(\n node =>\n (node.nodeType === Node.ELEMENT_NODE ||\n (node.nodeType === Node.TEXT_NODE &&\n node.textContent?.trim().length)) &&\n node !== slot,\n )\n // Extract text for aria-label on the trigger button. Screen readers may\n // not traverse the multi-level slot chain (dap-ds-button > dap-ds-stack >\n // nav-item slot > title slot), so we provide an explicit label.\n this._titleText = nodes\n .map(n => n.textContent?.trim() ?? '')\n .join(' ')\n .trim()\n }\n }\n\n constructor() {\n super()\n this.submenuController = new SubmenuController(this)\n }\n\n connectedCallback() {\n super.connectedCallback()\n this.addEventListener('click', this._handleClick)\n this.addEventListener('mouseover', this._handleMouseOver)\n this.addEventListener('mouseleave', this._handleMouseLeave)\n this.addEventListener('keydown', this._handleKeyDown)\n this.handleDocumentMouseDown = this.handleDocumentMouseDown.bind(this)\n this._updatePlacementForLevel()\n this.startPositionUpdate()\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.removeEventListener('click', this._handleClick)\n this.removeEventListener('mouseover', this._handleMouseOver)\n this.removeEventListener('mouseleave', this._handleMouseLeave)\n this.removeEventListener('keydown', this._handleKeyDown)\n document.removeEventListener('mousedown', this.handleDocumentMouseDown)\n this.stopPositionUpdate()\n }\n\n async firstUpdated(changedProperties: Map<string, unknown>) {\n super.firstUpdated(changedProperties)\n this._updateNestedItems()\n // Ensure trigger element is initialized even if slotchange didn't fire\n this._handleTriggerSlotChangeCallback()\n }\n\n @watch('opened')\n handleOpenedChange() {\n if (this.opened && (this.hasNestedItems || this.hasContent)) {\n this._applyZIndex()\n this.updateComplete.then(() => {\n this.updatePosition()\n // Update safe triangle coordinates after position update\n this.submenuController.updateSafeTriangle()\n })\n }\n }\n\n @watch('activeHref')\n handleActiveHrefChange() {\n this._updateActiveState()\n this._updateNestedItems()\n }\n\n @watch('href')\n handleHrefChange() {\n this._updateActiveState()\n }\n\n @watch(['level', 'orientation'])\n handleLayoutChange() {\n this._updateNestedItems()\n this._updatePlacementForLevel()\n }\n\n /** Update nested navigation menu items with current properties. */\n private _updateNestedItems() {\n const allNestedItems = this.querySelectorAll(\n 'dap-ds-navigation-menu-item',\n ) as NodeListOf<DapDSNavigationMenuItem>\n\n const nestedItems = Array.from(allNestedItems).filter(item => {\n const parentNavItem = item.parentElement?.closest(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem | null\n return parentNavItem === this\n })\n\n nestedItems.forEach(item => {\n item.level = this.level + 1\n item.orientation = this.orientation\n if (this.activeHref) {\n item.activeHref = this.activeHref\n }\n })\n }\n\n /** Update placement based on nesting level and orientation. */\n private _updatePlacementForLevel() {\n if (this.level === 0) {\n this.placement =\n this.orientation === 'horizontal' ? 'bottom-start' : 'right-start'\n } else {\n this.placement = 'right-start'\n }\n }\n\n /** Calculate z-index based on nesting level. */\n private _calculateZIndex(): number {\n const baseZIndex = 1000\n return baseZIndex + this.level * 10\n }\n\n /** Apply z-index based on nesting level. */\n private _applyZIndex() {\n if (this.popup) {\n const zIndex = this._calculateZIndex()\n this.popup.style.zIndex = String(zIndex)\n }\n }\n\n /** Start automatic position updates using Floating UI. */\n private startPositionUpdate() {\n if (!this.triggerElement || !this.popup) return\n\n this.cleanup = autoUpdate(this.triggerElement, this.popup, () => {\n this.updatePosition()\n })\n }\n\n /** Stop automatic position updates. */\n private stopPositionUpdate() {\n if (this.cleanup) {\n this.cleanup()\n this.cleanup = undefined\n }\n }\n\n /** Update popup position using Floating UI. */\n async updatePosition() {\n if (!this.triggerElement || !this.popup) return\n\n // For fixed positioning, use viewport as boundary to allow popups to escape constrained containers\n // For absolute positioning, use the navigation menu container as boundary\n const boundary =\n this.floatingStrategy === 'fixed'\n ? undefined // undefined means viewport for fixed positioning\n : this.closest('dap-ds-navigation-menu') || undefined\n\n const { x, y } = await computePosition(this.triggerElement, this.popup, {\n placement: this.placement,\n strategy: this.floatingStrategy,\n middleware: [\n offset(this.offset),\n flip({\n boundary: boundary,\n }),\n shift({\n padding: this.fullWidth ? 0 : 8,\n boundary: boundary,\n }),\n size({\n apply: ({ availableHeight, rects }) => {\n if (this.sync) {\n this.popup.style.width = `${rects.reference.width}px`\n }\n if (this.maxHeight !== 'auto') {\n this.popup.style.maxHeight = `${Math.min(this.maxHeight, availableHeight)}px`\n }\n if (this.maxWidth !== 'auto') {\n this.popup.style.maxWidth = `${this.maxWidth}px`\n }\n if (this.fullWidth) {\n this.popup.style.width = '100vw'\n }\n },\n }),\n ],\n })\n\n Object.assign(this.popup.style, {\n left: this.fullWidth ? '0px' : `${x}px`,\n top: `${y}px`,\n })\n }\n\n private _handleClick = (event: Event) => {\n // Prevent disabled items from being clicked\n if (this.disabled) {\n event.preventDefault()\n event.stopImmediatePropagation()\n return\n }\n\n const hasSubmenu = this.hasContent || this.hasNestedItems\n if (hasSubmenu) {\n // Check if click was on trigger element\n const triggerElements = this._trigger\n const path = event.composedPath()\n const isClickOnTrigger = triggerElements.some(trigger =>\n path.includes(trigger),\n )\n\n if (isClickOnTrigger) {\n event.preventDefault()\n event.stopPropagation()\n\n // If submenu was opened by hover, clicking should keep it open\n // Otherwise, toggle the submenu state\n if (this.opened && this.openedByHover) {\n // Clear the hover flag so future clicks will toggle normally\n this.openedByHover = false\n } else {\n // Normal toggle behavior\n this.opened ? this.hideDropDown() : this.showDropDown(false)\n }\n } else if (this.opened) {\n // Click is inside the open popup content (not on the trigger).\n // If a navigable element is in the composed path, it's a SPA link\n // click — close the dropdown so the menu doesn't stay open after\n // client-side navigation.\n const isNavClick = path.some(el => {\n if (!(el instanceof Element)) return false\n const tag = el.tagName.toUpperCase()\n return tag === 'A' || tag === 'DAP-DS-LINK'\n })\n if (isNavClick) {\n this.hideDropDown()\n }\n }\n } else if (this.hasLink) {\n // SPA router link — delegate click to the slotted link element\n const triggerElements = this._trigger\n const path = event.composedPath()\n const isClickOnTrigger = triggerElements.some(trigger =>\n path.includes(trigger),\n )\n if (isClickOnTrigger) {\n event.preventDefault()\n const linkEl = this._getLinkElement()\n if (linkEl) {\n const href = linkEl.getAttribute('href')\n linkEl.click()\n if (href) {\n this.emit('dds-navigation-item-click', { href, event })\n }\n }\n // Close all ancestor open navigation menu items so SPA navigation\n // doesn't leave the dropdown open after a client-side route change.\n let ancestor = this.parentElement?.closest(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem | null\n while (ancestor) {\n if (ancestor.opened) {\n ancestor.hideDropDown()\n }\n ancestor = ancestor.parentElement?.closest(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem | null\n }\n }\n } else {\n // Simple link - emit navigation event\n const triggerElements = this._trigger\n const href = triggerElements[0]?.getAttribute('href')\n if (href) {\n this.emit('dds-navigation-item-click', {\n href,\n event,\n })\n }\n }\n }\n\n private _handleMouseOver = (event: MouseEvent) => {\n // Close sibling items when hovering over a different item\n // This ensures only one item's submenu is open at a time on hover\n // Also cancel any pending timers to prevent race conditions when moving mouse quickly\n const parent = this.parentElement\n if (parent) {\n const siblings =\n parent.querySelectorAll(':scope > dap-ds-navigation-menu-item') || []\n\n siblings.forEach(item => {\n if (item !== this) {\n const siblingItem = item as DapDSNavigationMenuItem\n // Cancel any pending submenu opening timer\n siblingItem.submenuController.cancelPendingOpen()\n // Close if already open\n if (siblingItem.opened) {\n siblingItem.hideDropDown()\n }\n }\n })\n }\n\n event.stopPropagation()\n }\n\n private _handleMouseLeave = (_event: MouseEvent) => {\n // Cancel pending submenu opening timer when mouse leaves the item\n // This prevents the submenu from opening if the mouse leaves before the delay completes\n // Only cancel if the submenu is not already open\n if (!this.opened) {\n this.submenuController.cancelPendingOpen()\n }\n }\n\n /** Handle keyboard navigation for submenu items */\n private _handleKeyDown = (event: KeyboardEvent) => {\n // Handle navigation within THIS item's open submenu\n if (this.opened && (this.hasNestedItems || this.hasContent)) {\n const nestedItems = Array.from(\n this.querySelectorAll(':scope > dap-ds-navigation-menu-item'),\n ) as DapDSNavigationMenuItem[]\n\n if (nestedItems.length > 0) {\n const target = event.target as HTMLElement\n const currentIndex = nestedItems.findIndex(\n item => item.contains(target) || item === target,\n )\n\n // ArrowDown: move to next item in submenu\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n event.stopPropagation()\n const nextIndex =\n currentIndex < nestedItems.length - 1 ? currentIndex + 1 : 0\n nestedItems[nextIndex].focus()\n return\n }\n // ArrowUp: move to previous item in submenu\n else if (event.key === 'ArrowUp') {\n event.preventDefault()\n event.stopPropagation()\n const prevIndex =\n currentIndex > 0 ? currentIndex - 1 : nestedItems.length - 1\n nestedItems[prevIndex].focus()\n return\n }\n // ArrowRight: open nested submenu if current item has one\n else if (event.key === 'ArrowRight' && currentIndex >= 0) {\n const currentItem = nestedItems[currentIndex]\n if (currentItem.hasNestedItems || currentItem.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!currentItem.opened) {\n currentItem.showDropDown()\n currentItem.updateComplete.then(() => {\n const firstNested = currentItem.querySelector(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem\n if (firstNested) {\n firstNested.focus()\n }\n })\n }\n return\n }\n }\n // Enter or Space: activate the current focused item\n else if (\n (event.key === 'Enter' || event.key === ' ') &&\n currentIndex >= 0\n ) {\n const currentItem = nestedItems[currentIndex]\n const trigger = currentItem.querySelector(\n '[slot=\"trigger\"]',\n ) as HTMLElement\n\n // Check if trigger is a link or any interactive element, the element can be in uppercase or lowercase\n const linkTags = [\n 'A',\n 'DAP-DS-LINK',\n 'DAP-DS-BUTTON',\n 'BUTTON',\n 'LINK',\n ]\n const isInteractive =\n linkTags.includes(trigger?.tagName.toLowerCase()) ||\n linkTags.includes(trigger?.tagName)\n\n // For links with Enter key, let the browser handle it naturally\n // Only prevent default for Space key or non-link elements\n if (!isInteractive || event.key === ' ') {\n event.preventDefault()\n event.stopPropagation()\n }\n\n if (currentItem.hasNestedItems || currentItem.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!currentItem.opened) {\n currentItem.showDropDown()\n }\n } else if (!isInteractive || event.key === ' ') {\n // For non-links or Space key, simulate click\n trigger?.click()\n }\n // For links with Enter, browser default handles navigation\n return\n }\n } else if (this.hasContent) {\n // Mega menu: navigate between focusable items with arrow keys\n const focusableItems = this._getFocusablePopupItems()\n if (focusableItems.length > 0) {\n const target = event.target as HTMLElement\n const currentIndex = focusableItems.findIndex(\n item => item === target || item.contains(target),\n )\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n event.stopPropagation()\n const nextIndex =\n currentIndex < 0\n ? 0\n : currentIndex < focusableItems.length - 1\n ? currentIndex + 1\n : 0\n this._focusPopupItem(focusableItems[nextIndex])\n return\n } else if (event.key === 'ArrowUp') {\n event.preventDefault()\n event.stopPropagation()\n const prevIndex =\n currentIndex < 0\n ? focusableItems.length - 1\n : currentIndex > 0\n ? currentIndex - 1\n : focusableItems.length - 1\n this._focusPopupItem(focusableItems[prevIndex])\n return\n } else if (event.key === 'Home') {\n event.preventDefault()\n event.stopPropagation()\n this._focusPopupItem(focusableItems[0])\n return\n } else if (event.key === 'End') {\n event.preventDefault()\n event.stopPropagation()\n this._focusPopupItem(focusableItems[focusableItems.length - 1])\n return\n } else if (\n (event.key === 'Enter' || event.key === ' ') &&\n currentIndex >= 0\n ) {\n event.preventDefault()\n event.stopPropagation()\n this._activateFocusableItem(focusableItems[currentIndex])\n return\n }\n }\n }\n }\n\n // Handle navigation when THIS item is inside a submenu (level > 0)\n if (this.level > 0) {\n const parent = this.parentElement\n if (!parent) return\n\n // Get sibling items at the same level\n const siblings = Array.from(\n parent.querySelectorAll(':scope > dap-ds-navigation-menu-item'),\n ) as DapDSNavigationMenuItem[]\n\n if (siblings.length === 0) return\n\n const currentIndex = siblings.indexOf(this)\n\n // ArrowDown: move to next sibling\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n event.stopPropagation()\n const nextIndex =\n currentIndex < siblings.length - 1 ? currentIndex + 1 : 0\n siblings[nextIndex].focus()\n }\n // ArrowUp: move to previous sibling\n else if (event.key === 'ArrowUp') {\n event.preventDefault()\n event.stopPropagation()\n const prevIndex =\n currentIndex > 0 ? currentIndex - 1 : siblings.length - 1\n siblings[prevIndex].focus()\n }\n // ArrowRight: open THIS item's submenu if it has one\n else if (event.key === 'ArrowRight') {\n if (this.hasNestedItems || this.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!this.opened) {\n this.showDropDown()\n this.updateComplete.then(() => {\n this.focusFirstDropdownChild()\n })\n } else {\n this.focusFirstDropdownChild()\n }\n }\n }\n // ArrowLeft: close parent submenu and return focus\n else if (event.key === 'ArrowLeft') {\n event.preventDefault()\n event.stopPropagation()\n // Find the parent menu-item that contains this submenu\n const parentMenuItem = parent.closest(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem\n if (parentMenuItem) {\n parentMenuItem.hideDropDown()\n parentMenuItem.focus()\n }\n }\n // Escape: close parent submenu\n else if (event.key === 'Escape') {\n event.preventDefault()\n event.stopPropagation()\n const parentMenuItem = parent.closest(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem\n if (parentMenuItem) {\n parentMenuItem.hideDropDown()\n parentMenuItem.focus()\n }\n }\n // Enter or Space: activate the link or trigger\n else if (event.key === 'Enter' || event.key === ' ') {\n const trigger = this.querySelector('[slot=\"trigger\"]') as HTMLElement\n\n // Check if trigger is a link\n const linkTags = ['A', 'DAP-DS-LINK', 'LINK']\n const isLink =\n trigger &&\n (linkTags.includes(trigger.tagName.toLowerCase()) ||\n linkTags.includes(trigger.tagName))\n\n // For links with Enter key, let the browser handle it naturally\n // Only prevent default for Space key or non-link elements\n if (!isLink || event.key === ' ') {\n event.preventDefault()\n event.stopPropagation()\n }\n\n // If item has submenu, open it\n if (this.hasNestedItems || this.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!this.opened) {\n this.showDropDown(false)\n }\n } else if (this.hasLink) {\n // slot=\"link\" pattern: delegate to the visually-hidden router link\n event.preventDefault()\n event.stopPropagation()\n const linkEl = this._getLinkElement()\n if (linkEl) {\n const href = linkEl.getAttribute('href')\n linkEl.click()\n if (href) {\n this.emit('dds-navigation-item-click', { href, event })\n }\n }\n } else if (!isLink || event.key === ' ') {\n // For non-links or Space key, simulate click\n trigger?.click()\n }\n // For links with Enter, browser default handles navigation\n }\n }\n }\n\n /** @ignore Override parent's handleDocumentMouseDown to be parent-aware for nested menus. */\n protected handleDocumentMouseDown = (event: MouseEvent): void => {\n const target = event.target as HTMLElement\n const path = event.composedPath()\n const isInsideThis = path.includes(this)\n const isInsideNestedItems = this._isWithinNestedItems(target)\n\n if (!isInsideThis && !isInsideNestedItems) {\n this.hideDropDown()\n }\n }\n\n /** Check if target is within any nested navigation menu items. */\n private _isWithinNestedItems(target: HTMLElement): boolean {\n const nestedItems = Array.from(\n this.querySelectorAll('dap-ds-navigation-menu-item'),\n ) as DapDSNavigationMenuItem[]\n\n return nestedItems.some(item => {\n return (\n item.contains(target) ||\n (item.shadowRoot && item.shadowRoot.contains(target))\n )\n })\n }\n\n focus() {\n const trigger = this._trigger?.[0]\n if (!trigger) return\n // Light-DOM wrapper hosts are not focusable themselves — focus the inner\n // focusable element instead. Shadow-root triggers (e.g. dap-ds-button)\n // delegate focus through their own focus() override.\n if (!trigger.shadowRoot) {\n const inner = this._getInnerLightDomFocusable(trigger)\n if (inner) {\n inner.focus()\n return\n }\n }\n trigger.focus()\n }\n\n /**\n * Sets this item as the active (or inactive) roving tabindex target.\n * Only the active item's trigger is in the sequential tab order (tabindex=\"0\").\n * All others are removed (tabindex=\"-1\") so Tab exits the whole nav in one step.\n */\n setRovingTabIndex(active: boolean) {\n if (active) {\n this.setAttribute('data-nav-current', '')\n } else {\n this.removeAttribute('data-nav-current')\n }\n this._isRovingActive = active\n\n const trigger = this._trigger?.[0]\n if (trigger) {\n this._applyTriggerTabIndex(trigger, active)\n } else {\n // Trigger not yet in DOM — defer until after Lit renders\n this.updateComplete.then(() => {\n const t = this._trigger?.[0]\n if (t) this._applyTriggerTabIndex(t, active)\n })\n }\n }\n\n /** Apply tabindex to a trigger element and its inner focusable element. */\n private _applyTriggerTabIndex(trigger: HTMLElement, active: boolean) {\n if (trigger.shadowRoot) {\n const inner = trigger.shadowRoot.querySelector<HTMLElement>(\n 'a[href], button:not([disabled])',\n )\n if (inner) {\n // For custom elements with a shadow root: manage tabindex on the inner\n // focusable element directly. The host must have NO tabindex attribute\n // (not even -1) to avoid creating a shadow-encapsulated tab scope that\n // would produce two consecutive Tab stops (host → inner button).\n // Without a tabindex on the host, inner elements participate directly\n // in the flat tree tab order.\n trigger.removeAttribute('tabindex')\n inner.setAttribute('tabindex', active ? '0' : '-1')\n return\n }\n } else {\n // Light-DOM wrapper without a shadow root (e.g. an Angular/Vue component\n // host rendering a native button in light DOM): putting tabindex on the\n // host would create a second tab stop next to the natively focusable\n // inner element. Manage the inner element and keep the host clean.\n const inner = this._getInnerLightDomFocusable(trigger)\n if (inner) {\n trigger.removeAttribute('tabindex')\n inner.setAttribute('tabindex', active ? '0' : '-1')\n return\n }\n }\n // Natively focusable element or no inner focusable found:\n // use the host element as the tab stop directly.\n trigger.setAttribute('tabindex', active ? '0' : '-1')\n }\n\n /**\n * Returns the inner light-DOM focusable element of a non-focusable wrapper\n * trigger, or null when the trigger itself should be the tab stop.\n */\n private _getInnerLightDomFocusable(trigger: HTMLElement): HTMLElement | null {\n if (\n ['A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA'].includes(trigger.tagName)\n ) {\n return null\n }\n return trigger.querySelector<HTMLElement>('a[href], button:not([disabled])')\n }\n\n /** Focus the first focusable element in the dropdown (supports both nested nav items and mega menu content). */\n focusFirstDropdownChild() {\n const firstNavItem = this.querySelector(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem | null\n if (firstNavItem) {\n firstNavItem.focus()\n return\n }\n const items = this._getFocusablePopupItems()\n if (items.length > 0) {\n this._focusPopupItem(items[0])\n }\n }\n\n /** Focus the last focusable element in the dropdown (supports both nested nav items and mega menu content). */\n focusLastDropdownChild() {\n const navItems = Array.from(\n this.querySelectorAll(':scope > dap-ds-navigation-menu-item'),\n ) as DapDSNavigationMenuItem[]\n if (navItems.length > 0) {\n navItems[navItems.length - 1].focus()\n return\n }\n const items = this._getFocusablePopupItems()\n if (items.length > 0) {\n this._focusPopupItem(items[items.length - 1])\n }\n }\n\n /** Get all top-level focusable items inside the popup slot content (for mega menu arrow navigation). */\n private _getFocusablePopupItems(): HTMLElement[] {\n if (!this.popup) return []\n const contentSlot = this.popup.querySelector(\n 'slot:not([name])',\n ) as HTMLSlotElement | null\n const assigned = contentSlot?.assignedElements({ flatten: true }) ?? []\n const items: HTMLElement[] = []\n for (const el of assigned) {\n this._collectFocusableItems(el as HTMLElement, items)\n }\n return items\n }\n\n private _collectFocusableItems(el: HTMLElement, result: HTMLElement[]) {\n // Custom elements with shadow roots (e.g. dap-ds-button): check if they contain a focusable inner element\n if (el.shadowRoot) {\n const inner = el.shadowRoot.querySelector<HTMLElement>(\n 'a[href]:not([tabindex=\"-1\"]), button:not([disabled]):not([tabindex=\"-1\"])',\n )\n if (inner) {\n result.push(el)\n return\n }\n }\n // Standard focusable elements\n if (\n ['A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA'].includes(el.tagName) &&\n !el.hasAttribute('disabled') &&\n el.getAttribute('tabindex') !== '-1'\n ) {\n result.push(el)\n return\n }\n // Recurse into children\n for (const child of el.children) {\n this._collectFocusableItems(child as HTMLElement, result)\n }\n }\n\n private _activateFocusableItem(item: HTMLElement) {\n if (item.shadowRoot) {\n const inner = item.shadowRoot.querySelector<HTMLElement>(\n 'a[href], button:not([disabled])',\n )\n if (inner) {\n inner.click()\n return\n }\n }\n item.click()\n }\n\n private _focusPopupItem(item: HTMLElement) {\n // For custom elements with shadow roots, focus the inner a/button directly\n if (item.shadowRoot) {\n const inner = item.shadowRoot.querySelector<HTMLElement>(\n 'a[href], button:not([disabled])',\n )\n if (inner) {\n inner.focus()\n return\n }\n }\n item.focus()\n }\n\n async showDropDown(byHover = false) {\n const hasSubmenu = this.hasContent || this.hasNestedItems\n if (this.opened || !hasSubmenu) {\n return\n }\n\n this._updatePlacementForLevel()\n this.emit('dds-navigation-dropdown-open', { item: this })\n\n this.opened = true\n this.openedByHover = byHover\n const triggerElements = this._trigger\n triggerElements[0]?.setAttribute('aria-expanded', 'true')\n\n document.addEventListener('mousedown', this.handleDocumentMouseDown)\n\n await this.updateComplete\n this._applyZIndex()\n }\n\n async hideDropDown() {\n if (!this.opened) {\n return\n }\n\n // Close all nested items first\n const nestedItems = this.querySelectorAll('dap-ds-navigation-menu-item')\n nestedItems.forEach(item => {\n if ((item as DapDSNavigationMenuItem).opened) {\n ;(item as DapDSNavigationMenuItem).hideDropDown()\n }\n })\n\n this.opened = false\n this.openedByHover = false\n const triggerElements = this._trigger\n triggerElements[0]?.setAttribute('aria-expanded', 'false')\n\n document.removeEventListener('mousedown', this.handleDocumentMouseDown)\n\n await this.updateComplete\n }\n\n /** Handle trigger slot change events. */\n private _handleTriggerSlotChange() {\n this._handleTriggerSlotChangeCallback()\n this.stopPositionUpdate()\n this.updateComplete.then(() => {\n if (this.triggerElement) {\n this.startPositionUpdate()\n }\n })\n }\n\n /** Update trigger element attributes and properties. */\n _handleTriggerSlotChangeCallback() {\n this.updateComplete.then(() => {\n const triggerElements = this._trigger\n if (triggerElements && triggerElements.length > 0) {\n this.triggerElement = triggerElements[0]\n\n triggerElements[0].setAttribute('aria-controls', 'dropdown')\n\n const hasSubmenu = this.hasContent || this.hasNestedItems\n if (hasSubmenu) {\n triggerElements[0].setAttribute(\n 'aria-expanded',\n this.opened ? 'true' : 'false',\n )\n triggerElements[0].setAttribute('aria-haspopup', 'true')\n } else {\n triggerElements[0].removeAttribute('aria-expanded')\n }\n\n triggerElements[0].style.display = 'flex'\n this._updateActiveState()\n\n // Sync roving tabindex to the (possibly new) trigger element\n this._applyTriggerTabIndex(triggerElements[0], this._isRovingActive)\n }\n })\n }\n\n private _updateActiveState() {\n const triggerElements = this._trigger\n if (\n (!triggerElements || triggerElements.length === 0 || !this.activeHref) &&\n !this.baseHref\n ) {\n this.active = false\n } else if (this.baseHref) {\n if (this.exactHref) {\n this.active = this.baseHref === this.activeHref\n } else {\n this.active = this.activeHref?.startsWith(this.baseHref) || false\n }\n } else {\n const triggerHref = triggerElements[0]?.getAttribute('href') || this.href\n this.active = triggerHref === this.activeHref\n ;(triggerElements[0] as any).active = this.active\n }\n\n // Fallback: check link slot element's href (for slot=\"link\" pattern)\n if (!this.active && this.hasLink && this.activeHref) {\n const linkEl = this._getLinkElement()\n const linkHref = linkEl?.getAttribute('href')\n if (linkHref) {\n this.active = this.exactHref\n ? linkHref === this.activeHref\n : this.activeHref.startsWith(linkHref)\n }\n }\n\n // Set aria-current=\"page\" for active navigation items\n if (triggerElements && triggerElements.length > 0) {\n if (this.active) {\n triggerElements[0].setAttribute('aria-current', 'page')\n } else {\n triggerElements[0].removeAttribute('aria-current')\n }\n }\n }\n\n _handleContentSlotChange(e: Event) {\n const slot = e.target as HTMLSlotElement\n if (slot) {\n const childNodes = slot.assignedElements()\n this.hasContent = childNodes.length > 0\n }\n this._updateNestedItems()\n }\n\n /** Render expand indicator icon based on nesting level and orientation. */\n private renderExpandIndicator() {\n if (!this.hasNestedItems && !this.hasContent) return html``\n\n return html`\n <span class=\"navigation-item__indicator\" part=\"indicator\">\n <slot name=\"indicator\">\n <dap-ds-icon\n part=\"indicator-icon\"\n exportparts=\"base:indicator-icon-base,icon:indicator-icon-icon\"\n name=${this._getDefaultIconName()}\n aria-hidden=\"true\"></dap-ds-icon>\n </slot>\n </span>\n `\n }\n\n /** Get the default icon name based on orientation and level. */\n private _getDefaultIconName(): string {\n // For vertical menus, always use right arrow (submenus open to the right)\n // For horizontal menus, use down arrow for top-level, right arrow for nested\n if (this.orientation === 'vertical') {\n return 'arrow-right-s-line'\n } else {\n return this.level === 0 ? 'arrow-down-s-line' : 'arrow-right-s-line'\n }\n }\n\n renderTrigger() {\n const hasSubmenu = this.hasContent || this.hasNestedItems\n const ariaExpanded = hasSubmenu\n ? this.opened\n ? 'true'\n : 'false'\n : undefined\n // Provide an explicit aria-label so screen readers announce the item name.\n // The label text is buried through multiple slot levels (dap-ds-button >\n // dap-ds-stack > nav-item title slot), which some screen readers don't\n // fully traverse for accessible name computation.\n const triggerAriaLabel = this._titleText || this.label || undefined\n return html`\n <dap-ds-button\n variant=\"subtle-menu\"\n tabindex=${this._isRovingActive ? '0' : '-1'}\n ?active=${this.active}\n aria-expanded=${ifDefined(ariaExpanded)}\n aria-label=${ifDefined(triggerAriaLabel)}\n href=${ifDefined(this.href)}\n target=${ifDefined(this.target)}\n rel=${ifDefined(this.rel)}\n forceRole=${ifDefined(!hasSubmenu && this.hasLink ? 'link' : undefined)}\n part=\"trigger\"\n data-testid=${this.triggerButtonTestId}\n exportparts=\"base:trigger-base,content:trigger-content,high-contrast:trigger-high-contrast\">\n <dap-ds-stack direction=\"row\" exportparts=\"base:trigger-stack-base\">\n <span part=\"title\">\n <slot name=\"title\" @slotchange=${this._handleTitleSlotChange}>\n ${this.hasTitleSlot ? nothing : this.label || nothing}\n </slot>\n </span>\n ${this.renderExpandIndicator()}\n </dap-ds-stack>\n </dap-ds-button>\n `\n }\n\n renderPopup() {\n return html`\n <slot name=\"trigger\" @slotchange=${this._handleTriggerSlotChange}>\n ${this.renderTrigger()}\n </slot>\n <!-- Link slot: outside inert popup, visually hidden, for SPA router links -->\n <div class=\"navigation-item__link-wrapper\" aria-hidden=\"true\">\n <slot name=\"link\" @slotchange=${this._handleLinkSlotChange}></slot>\n </div>\n <div\n part=\"popup\"\n id=\"popup\"\n ?inert=${!this.opened}\n class=${clsx('popup', `popup--${this.effectiveSize}`, {\n 'popup--opened': this.opened,\n 'popup--fixed': this.floatingStrategy === 'fixed',\n 'popup--has-arrow': this.hasArrow,\n 'popup--overflow': this.overflow,\n 'popup--full-width': this.fullWidth,\n })}>\n <div part=\"content\">\n <slot @slotchange=${this._handleContentSlotChange}></slot>\n </div>\n ${this.hasArrow\n ? html`<div\n part=\"arrow\"\n class=${clsx('popup__arrow')}\n role=\"presentation\"></div>`\n : ''}\n </div>\n `\n }\n\n render() {\n const hasSubmenu = this.hasContent || this.hasNestedItems\n\n return html`\n <div\n part=\"base\"\n class=${clsx('navigation-item', {\n 'navigation-item--has-content': hasSubmenu,\n 'navigation-item--opened': this.opened,\n [`navigation-item--level-${this.level}`]: true,\n })}>\n ${this.renderPopup()}\n </div>\n `\n }\n}\n"],"names":["_DapDSNavigationMenuItem","SizedMixin","DdsElement","e","slot","elements","el","nodes","node","_a","n","_b","event","triggerElements","path","trigger","tag","linkEl","href","ancestor","_c","parent","item","siblingItem","_event","nestedItems","target","currentIndex","nextIndex","prevIndex","currentItem","firstNested","linkTags","isInteractive","focusableItems","siblings","parentMenuItem","isLink","isInsideThis","isInsideNestedItems","SubmenuController","directTriggers","defaultButton","changedProperties","__async","__superGet","allNestedItems","zIndex","autoUpdate","boundary","x","y","computePosition","offset","flip","shift","size","availableHeight","rects","inner","active","t","firstNavItem","items","navItems","contentSlot","assigned","result","child","byHover","hasSubmenu","triggerHref","linkHref","childNodes","html","ariaExpanded","triggerAriaLabel","ifDefined","nothing","clsx","DapDSIcon","DapDSButton","DapDSStack","unsafeCSS","styles","popupStyles","DapDSNavigationMenuItem","__decorateClass","query","queryAssignedElements","property","state","watch"],"mappings":"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"}
1
+ {"version":3,"file":"navigation-menu-item.component.js","sources":["../../../src/components/navigation-menu/navigation-menu-item.component.ts"],"sourcesContent":["import {\n autoUpdate,\n computePosition,\n flip,\n offset,\n shift,\n size,\n} from '@floating-ui/dom'\nimport clsx from 'clsx'\nimport { nothing, unsafeCSS } from 'lit'\nimport {\n property,\n query,\n queryAssignedElements,\n state,\n} from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { html } from 'lit/static-html.js'\n\nimport { watch } from '../../common/decorators'\nimport {\n FloatingStrategy,\n LinkTarget,\n PopupPlacement,\n TabNavigationMode,\n} from '../../common/types'\nimport { DdsElement } from '../../internal/dds-hu-element'\nimport { SizedMixin } from '../../internal/mixin/sizedMixin'\nimport DapDSButton from '../button/button.component'\nimport DapDSIcon from '../icon/icon.component'\nimport popupStyles from '../popup/popup.scss?inline'\nimport DapDSStack from '../stack/stack.component'\nimport styles from './navigation-menu-item.scss?inline'\nimport { SubmenuController } from './submenu-controller'\n\n/**\n * `dap-ds-navigation-menu-item`\n * @summary A navigation menu item that can contain either a simple link or dropdown content.\n * Supports nested items with cascading flyout behavior. Part of the navigation menu system.\n * This is for NAVIGATION (website menus), not application menus.\n *\n * @element dap-ds-navigation-menu-item\n * @title - Navigation Menu Item\n * @group navigation-menu\n *\n * @property {string} label - The label text for the navigation item. This will be displayed in the title slot if no custom title slot content is provided.\n * @property {'xs' | 'sm' | 'lg'} size - The size of the popup. Default is 'sm'.\n * @property {boolean} disabled - The disabled state of the popup. Default is false.\n * @property {boolean} opened - The open state of the popup. Default is false.\n * @property {'top' | 'right' | 'bottom' | 'left' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end' | 'right-start' | 'right-end'} placement - The placement of the popup (automatically adjusted based on nesting level). Default is 'bottom-start'.\n * @property {'absolute' | 'fixed'} floatingStrategy - The floating strategy of the popup. Default is 'fixed'.\n * @property {number} offset - The offset of the popup. Default is 0.\n * @property {boolean} sync - Whether the popup should sync its width with the trigger. Default is false.\n * @property {number | 'auto'} maxHeight - The maximum height of the popup. Default is 250.\n * @property {number | 'auto'} maxWidth - The maximum width of the popup. Default is 'auto'.\n * @property {boolean} hasArrow - Whether the popup has an arrow. Default is false.\n * @property {boolean} overflow - Whether the popup should overflow. Default is true.\n * @property {boolean} fullWidth - Whether the popup should take full width of the screen. Default is false.\n * @property {boolean} exactHref - Whether the navigation item should be active if the href is exactly the same as the activeHref. Default is false.\n * @property {string} icon - The name of the icon to display in the trigger.\n * @property {string} ariaLabelledBy - The name of the element that labels the navigation dropdown.\n * @property {string} activeHref - The href of the navigation item that is active (receives aria-current=\"page\").\n * @property {string} baseHref - The href of the navigation item. If provided, the navigation item will be active if the href is a substring of the activeHref.\n * @property {string} href - The href URL for the navigation item link. When provided, the default trigger renders as a link.\n * @property {'_blank' | '_self' | '_parent' | '_top'} target - The target attribute for link navigation.\n * @property {string} rel - The rel attribute for link security and behavior.\n * @property {number} level - The nesting level of this navigation item (0 = top-level, automatically set for nested items). Default is 0.\n * @property {'horizontal' | 'vertical'} orientation - The orientation of the parent navigation menu (automatically inherited). Default is 'horizontal'.\n * @property {'group' | 'items'} tabMode - Controls how Tab key navigates through top-level items. Default is 'group'.\n *\n * @event {{ href: string, event: Event }} dds-navigation-item-click - Fired when a navigation item is clicked.\n * @event {{ item: DapDSNavigationMenuItem }} dds-navigation-dropdown-open - Fired when a navigation dropdown is opened.\n *\n * @slot trigger - The trigger element (link, button, etc.) for this navigation item.\n * @slot title - The title of the navigation item.\n * @slot indicator - The expand indicator icon (defaults to arrow icon based on orientation and level).\n * @slot link - A router link element (e.g. Next.js Link) used for SPA navigation.\n * Rendered outside the popup so it is always accessible to programmatic clicks.\n * @slot - The dropdown content (can contain nested dap-ds-navigation-menu-item elements).\n *\n * @csspart base - The base part of the navigation item.\n * @csspart trigger - The trigger element part.\n * @csspart trigger-base - The base part of the trigger button (from dap-ds-button).\n * @csspart trigger-content - The content part of the trigger button (from dap-ds-button).\n * @csspart trigger-high-contrast - The high contrast part of the trigger button (from dap-ds-button).\n * @csspart trigger-stack-base - The base part of the trigger stack (from dap-ds-stack).\n * @csspart title - The title slot wrapper.\n * @csspart indicator - The expand indicator container.\n * @csspart indicator-icon - The expand indicator icon part.\n * @csspart indicator-icon-base - The base part of the indicator icon (from dap-ds-icon).\n * @csspart indicator-icon-icon - The icon part of the indicator icon (from dap-ds-icon).\n * @csspart popup - The dropdown popup container.\n * @csspart content - The dropdown content wrapper (default slot).\n * @csspart arrow - The dropdown arrow part.\n *\n * @cssproperty --dds-navigation-menu-item-spacing - The padding/spacing of the navigation menu item content. (default: var(--dds-spacing-200)).\n * @cssproperty --dds-navigation-menu-item-border-width - The border width of the navigation menu item content. (default: var(--dds-border-width-base)).\n * @cssproperty --dds-navigation-menu-item-border-color - The border color of the navigation menu item content. (default: var(--dds-border-neutral-subtle)).\n * @cssproperty --dds-navigation-menu-item-border-radius - The border radius of the navigation menu item content. (default: var(--dds-radius-base)).\n * @cssproperty --dds-navigation-menu-item-background - The background color of the navigation menu item content. (default: var(--dds-background-neutral-base)).\n * @cssproperty --dds-navigation-menu-item-shadow - The box shadow of the navigation menu item content. (default: var(--dds-shadow-base)).\n *\n * @accessibility\n * - Active navigation items marked with `aria-current=\"page\"`\n * - Dropdowns use `aria-expanded` and `aria-haspopup`\n * - No menu/menuitem roles (this is navigation, not an application menu)\n */\nexport default class DapDSNavigationMenuItem extends SizedMixin(DdsElement) {\n static tagName = 'dap-ds-navigation-menu-item'\n\n static dependencies = {\n 'dap-ds-icon': DapDSIcon,\n 'dap-ds-button': DapDSButton,\n 'dap-ds-stack': DapDSStack,\n }\n\n static readonly styles = unsafeCSS(`${styles}${popupStyles}`)\n\n /** @ignore */\n @query('.popup') readonly popup!: HTMLDivElement\n\n /** @ignore */\n @queryAssignedElements({ slot: 'trigger' })\n private readonly _assignedTrigger!: HTMLElement[]\n\n // Popup properties\n /** @ignore */\n protected triggerElement: Element | null = null\n private cleanup: ReturnType<typeof autoUpdate> | undefined\n public readonly submenuController: SubmenuController\n\n /** The disabled state of the menu item. */\n @property({ reflect: true, type: Boolean }) disabled = false\n\n /** The open state of the dropdown menu. */\n @property({ reflect: true, type: Boolean }) opened = false\n\n /** The placement of the dropdown. */\n @property({ reflect: true }) placement: PopupPlacement = 'bottom-start'\n\n /** The floating strategy of the dropdown. */\n @property({ reflect: true }) floatingStrategy: FloatingStrategy = 'fixed'\n\n /** The offset of the dropdown from the trigger. */\n @property({ type: Number }) offset = 0\n\n /** Whether the dropdown should sync its width with the trigger. */\n @property({ type: Boolean }) sync = false\n\n /** The maximum height of the dropdown. */\n @property({ type: Number }) maxHeight: number | 'auto' = 250\n\n /** The maximum width of the dropdown. */\n @property({ type: Number }) maxWidth: number | 'auto' = 'auto'\n\n /** Whether the dropdown has an arrow. */\n @property({ type: Boolean }) hasArrow = false\n\n /** Whether the dropdown should overflow. */\n @property({ type: Boolean }) overflow = true\n\n /** Whether the dropdown should take full width of the screen. */\n @property({ type: Boolean }) fullWidth = false\n\n /** The name of the icon to display in the trigger. */\n @property({ type: String, reflect: true }) icon?: string\n\n /** ID of element that labels the navigation dropdown. */\n @property({ type: String, attribute: 'aria-labelledby' })\n ariaLabelledBy?: string\n\n /** The href of the navigation item that is active. */\n @property({ type: String, reflect: true }) activeHref?: string\n\n /** The href of the navigation item for prefix matching. */\n @property({ type: String, reflect: true }) baseHref?: string\n\n /** Whether the navigation item should use exact href matching. */\n @property({ type: Boolean, reflect: true }) exactHref = false\n\n /** The href URL for the navigation item link. When provided, the default trigger renders as a link. */\n @property({ type: String, reflect: true }) href?: string\n\n /** The target attribute for link navigation. */\n @property({ type: String, reflect: true }) target?: LinkTarget\n\n /** The rel attribute for link security and behavior. */\n @property({ type: String, reflect: true }) rel?: string\n\n /** The label text for the navigation item, displayed in the title slot when no slot content is provided. */\n @property({ type: String }) label?: string\n\n /** The nesting level of this navigation item (0 = top-level). */\n @property({ type: Number, reflect: true }) level = 0\n\n /** The orientation of the parent navigation menu. */\n @property({ reflect: true }) orientation: 'horizontal' | 'vertical' =\n 'horizontal'\n\n /** Controls tab key behavior (propagated from parent navigation menu). */\n @property({ type: String }) tabMode: TabNavigationMode = 'group'\n\n /** `data-testid` for the default menu trigger button. */\n @property() triggerButtonTestId = 'navigation-menu-item-trigger-button'\n\n @state() hasContent = false\n @state() private hasLink = false\n @state() private hasTitleSlot = false\n @state() private _titleText = ''\n @state() private active = false\n @state() private openedByHover = false\n @state() private _isRovingActive = false\n\n /** Computed property to detect if this item contains nested navigation menu items. */\n get hasNestedItems(): boolean {\n const nestedItems = this.querySelectorAll('dap-ds-navigation-menu-item')\n return nestedItems.length > 0\n }\n\n private get _trigger(): HTMLElement[] {\n // If there are assigned elements in the trigger slot, use only DIRECT children\n if (this._assignedTrigger && this._assignedTrigger.length > 0) {\n const directTriggers = this._assignedTrigger.filter(\n el => el.parentElement === this,\n )\n if (directTriggers.length > 0) {\n return directTriggers\n }\n }\n // Otherwise, find the default button in the shadow DOM\n // When slot has no assigned content, the fallback content (button) is rendered\n // The button is rendered as part of the slot's fallback content in the shadow DOM\n const defaultButton = this.shadowRoot?.querySelector('dap-ds-button')\n return defaultButton ? [defaultButton as HTMLElement] : []\n }\n\n /**\n * The element keyboard activation should act on: the element slotted into\n * `trigger` when one is provided, otherwise the default trigger button\n * rendered in the shadow root.\n */\n get activationTrigger(): HTMLElement | null {\n return this._trigger[0] ?? null\n }\n\n /**\n * Activate the trigger the way a mouse click would. Custom element triggers\n * -- including the default `dap-ds-button` -- keep the real interactive\n * element inside their shadow root, so clicking the host alone does nothing.\n */\n activateTrigger() {\n const trigger = this.activationTrigger\n if (trigger) {\n this._activateFocusableItem(trigger)\n }\n }\n\n /** Get the element slotted into the `link` slot, if any. */\n private _getLinkElement(): HTMLElement | null {\n const slot = this.shadowRoot?.querySelector(\n 'slot[name=\"link\"]',\n ) as HTMLSlotElement\n if (!slot) return null\n const elements = slot.assignedElements()\n return elements.length > 0 ? (elements[0] as HTMLElement) : null\n }\n\n /** Handle slot change for the `link` slot. */\n private _handleLinkSlotChange = (e: Event) => {\n const slot = e.target as HTMLSlotElement\n if (slot) {\n const elements = slot.assignedElements()\n this.hasLink = elements.length > 0\n // Remove link element from tab order — the trigger is the tab stop\n elements.forEach(el => el.setAttribute('tabindex', '-1'))\n }\n this._updateActiveState()\n }\n\n /** Handle slot change for the `title` slot. */\n private _handleTitleSlotChange = (e: Event) => {\n const slot = e.target as HTMLSlotElement\n if (slot) {\n const nodes = slot.assignedNodes({ flatten: true })\n // Check if slot has any content (elements or text nodes)\n this.hasTitleSlot = nodes.some(\n node =>\n (node.nodeType === Node.ELEMENT_NODE ||\n (node.nodeType === Node.TEXT_NODE &&\n node.textContent?.trim().length)) &&\n node !== slot,\n )\n // Extract text for aria-label on the trigger button. Screen readers may\n // not traverse the multi-level slot chain (dap-ds-button > dap-ds-stack >\n // nav-item slot > title slot), so we provide an explicit label.\n this._titleText = nodes\n .map(n => n.textContent?.trim() ?? '')\n .join(' ')\n .trim()\n }\n }\n\n constructor() {\n super()\n this.submenuController = new SubmenuController(this)\n }\n\n connectedCallback() {\n super.connectedCallback()\n this.addEventListener('click', this._handleClick)\n this.addEventListener('mouseover', this._handleMouseOver)\n this.addEventListener('mouseleave', this._handleMouseLeave)\n this.addEventListener('keydown', this._handleKeyDown)\n this.handleDocumentMouseDown = this.handleDocumentMouseDown.bind(this)\n this._updatePlacementForLevel()\n this.startPositionUpdate()\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n this.removeEventListener('click', this._handleClick)\n this.removeEventListener('mouseover', this._handleMouseOver)\n this.removeEventListener('mouseleave', this._handleMouseLeave)\n this.removeEventListener('keydown', this._handleKeyDown)\n document.removeEventListener('mousedown', this.handleDocumentMouseDown)\n this.stopPositionUpdate()\n }\n\n async firstUpdated(changedProperties: Map<string, unknown>) {\n super.firstUpdated(changedProperties)\n this._updateNestedItems()\n // Ensure trigger element is initialized even if slotchange didn't fire\n this._handleTriggerSlotChangeCallback()\n }\n\n @watch('opened')\n handleOpenedChange() {\n if (this.opened && (this.hasNestedItems || this.hasContent)) {\n this._applyZIndex()\n this.updateComplete.then(() => {\n this.updatePosition()\n // Update safe triangle coordinates after position update\n this.submenuController.updateSafeTriangle()\n })\n }\n }\n\n @watch('activeHref')\n handleActiveHrefChange() {\n this._updateActiveState()\n this._updateNestedItems()\n }\n\n @watch('href')\n handleHrefChange() {\n this._updateActiveState()\n }\n\n @watch(['level', 'orientation'])\n handleLayoutChange() {\n this._updateNestedItems()\n this._updatePlacementForLevel()\n }\n\n /** Update nested navigation menu items with current properties. */\n private _updateNestedItems() {\n const allNestedItems = this.querySelectorAll(\n 'dap-ds-navigation-menu-item',\n ) as NodeListOf<DapDSNavigationMenuItem>\n\n const nestedItems = Array.from(allNestedItems).filter(item => {\n const parentNavItem = item.parentElement?.closest(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem | null\n return parentNavItem === this\n })\n\n nestedItems.forEach(item => {\n item.level = this.level + 1\n item.orientation = this.orientation\n if (this.activeHref) {\n item.activeHref = this.activeHref\n }\n })\n }\n\n /** Update placement based on nesting level and orientation. */\n private _updatePlacementForLevel() {\n if (this.level === 0) {\n this.placement =\n this.orientation === 'horizontal' ? 'bottom-start' : 'right-start'\n } else {\n this.placement = 'right-start'\n }\n }\n\n /** Calculate z-index based on nesting level. */\n private _calculateZIndex(): number {\n const baseZIndex = 1000\n return baseZIndex + this.level * 10\n }\n\n /** Apply z-index based on nesting level. */\n private _applyZIndex() {\n if (this.popup) {\n const zIndex = this._calculateZIndex()\n this.popup.style.zIndex = String(zIndex)\n }\n }\n\n /** Start automatic position updates using Floating UI. */\n private startPositionUpdate() {\n if (!this.triggerElement || !this.popup) return\n\n this.cleanup = autoUpdate(this.triggerElement, this.popup, () => {\n this.updatePosition()\n })\n }\n\n /** Stop automatic position updates. */\n private stopPositionUpdate() {\n if (this.cleanup) {\n this.cleanup()\n this.cleanup = undefined\n }\n }\n\n /** Update popup position using Floating UI. */\n async updatePosition() {\n if (!this.triggerElement || !this.popup) return\n\n // For fixed positioning, use viewport as boundary to allow popups to escape constrained containers\n // For absolute positioning, use the navigation menu container as boundary\n const boundary =\n this.floatingStrategy === 'fixed'\n ? undefined // undefined means viewport for fixed positioning\n : this.closest('dap-ds-navigation-menu') || undefined\n\n const { x, y } = await computePosition(this.triggerElement, this.popup, {\n placement: this.placement,\n strategy: this.floatingStrategy,\n middleware: [\n offset(this.offset),\n flip({\n boundary: boundary,\n }),\n shift({\n padding: this.fullWidth ? 0 : 8,\n boundary: boundary,\n }),\n size({\n apply: ({ availableHeight, rects }) => {\n if (this.sync) {\n this.popup.style.width = `${rects.reference.width}px`\n }\n if (this.maxHeight !== 'auto') {\n this.popup.style.maxHeight = `${Math.min(this.maxHeight, availableHeight)}px`\n }\n if (this.maxWidth !== 'auto') {\n this.popup.style.maxWidth = `${this.maxWidth}px`\n }\n if (this.fullWidth) {\n this.popup.style.width = '100vw'\n }\n },\n }),\n ],\n })\n\n Object.assign(this.popup.style, {\n left: this.fullWidth ? '0px' : `${x}px`,\n top: `${y}px`,\n })\n }\n\n private _handleClick = (event: Event) => {\n // Prevent disabled items from being clicked\n if (this.disabled) {\n event.preventDefault()\n event.stopImmediatePropagation()\n return\n }\n\n const hasSubmenu = this.hasContent || this.hasNestedItems\n if (hasSubmenu) {\n // Check if click was on trigger element\n const triggerElements = this._trigger\n const path = event.composedPath()\n const isClickOnTrigger = triggerElements.some(trigger =>\n path.includes(trigger),\n )\n\n if (isClickOnTrigger) {\n event.preventDefault()\n event.stopPropagation()\n\n // If submenu was opened by hover, clicking should keep it open\n // Otherwise, toggle the submenu state\n if (this.opened && this.openedByHover) {\n // Clear the hover flag so future clicks will toggle normally\n this.openedByHover = false\n } else {\n // Normal toggle behavior\n this.opened ? this.hideDropDown() : this.showDropDown(false)\n }\n } else if (this.opened) {\n // Click is inside the open popup content (not on the trigger).\n // If a navigable element is in the composed path, it's a SPA link\n // click — close the dropdown so the menu doesn't stay open after\n // client-side navigation.\n const isNavClick = path.some(el => {\n if (!(el instanceof Element)) return false\n const tag = el.tagName.toUpperCase()\n return tag === 'A' || tag === 'DAP-DS-LINK'\n })\n if (isNavClick) {\n this.hideDropDown()\n }\n }\n } else if (this.hasLink) {\n // SPA router link — delegate click to the slotted link element\n const triggerElements = this._trigger\n const path = event.composedPath()\n const isClickOnTrigger = triggerElements.some(trigger =>\n path.includes(trigger),\n )\n if (isClickOnTrigger) {\n event.preventDefault()\n const linkEl = this._getLinkElement()\n if (linkEl) {\n const href = linkEl.getAttribute('href')\n linkEl.click()\n if (href) {\n this.emit('dds-navigation-item-click', { href, event })\n }\n }\n // Close all ancestor open navigation menu items so SPA navigation\n // doesn't leave the dropdown open after a client-side route change.\n let ancestor = this.parentElement?.closest(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem | null\n while (ancestor) {\n if (ancestor.opened) {\n ancestor.hideDropDown()\n }\n ancestor = ancestor.parentElement?.closest(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem | null\n }\n }\n } else {\n // Simple link - emit navigation event\n const triggerElements = this._trigger\n const href = triggerElements[0]?.getAttribute('href')\n if (href) {\n this.emit('dds-navigation-item-click', {\n href,\n event,\n })\n }\n }\n }\n\n private _handleMouseOver = (event: MouseEvent) => {\n // Close sibling items when hovering over a different item\n // This ensures only one item's submenu is open at a time on hover\n // Also cancel any pending timers to prevent race conditions when moving mouse quickly\n const parent = this.parentElement\n if (parent) {\n const siblings =\n parent.querySelectorAll(':scope > dap-ds-navigation-menu-item') || []\n\n siblings.forEach(item => {\n if (item !== this) {\n const siblingItem = item as DapDSNavigationMenuItem\n // Cancel any pending submenu opening timer\n siblingItem.submenuController.cancelPendingOpen()\n // Close if already open\n if (siblingItem.opened) {\n siblingItem.hideDropDown()\n }\n }\n })\n }\n\n event.stopPropagation()\n }\n\n private _handleMouseLeave = (_event: MouseEvent) => {\n // Cancel pending submenu opening timer when mouse leaves the item\n // This prevents the submenu from opening if the mouse leaves before the delay completes\n // Only cancel if the submenu is not already open\n if (!this.opened) {\n this.submenuController.cancelPendingOpen()\n }\n }\n\n /** Handle keyboard navigation for submenu items */\n private _handleKeyDown = (event: KeyboardEvent) => {\n // Handle navigation within THIS item's open submenu\n if (this.opened && (this.hasNestedItems || this.hasContent)) {\n const nestedItems = Array.from(\n this.querySelectorAll(':scope > dap-ds-navigation-menu-item'),\n ) as DapDSNavigationMenuItem[]\n\n if (nestedItems.length > 0) {\n const target = event.target as HTMLElement\n const currentIndex = nestedItems.findIndex(\n item => item.contains(target) || item === target,\n )\n\n // ArrowDown: move to next item in submenu\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n event.stopPropagation()\n const nextIndex =\n currentIndex < nestedItems.length - 1 ? currentIndex + 1 : 0\n nestedItems[nextIndex].focus()\n return\n }\n // ArrowUp: move to previous item in submenu\n else if (event.key === 'ArrowUp') {\n event.preventDefault()\n event.stopPropagation()\n const prevIndex =\n currentIndex > 0 ? currentIndex - 1 : nestedItems.length - 1\n nestedItems[prevIndex].focus()\n return\n }\n // ArrowRight: open nested submenu if current item has one\n else if (event.key === 'ArrowRight' && currentIndex >= 0) {\n const currentItem = nestedItems[currentIndex]\n if (currentItem.hasNestedItems || currentItem.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!currentItem.opened) {\n currentItem.showDropDown()\n currentItem.updateComplete.then(() => {\n const firstNested = currentItem.querySelector(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem\n if (firstNested) {\n firstNested.focus()\n }\n })\n }\n return\n }\n }\n // Enter or Space: activate the current focused item\n else if (\n (event.key === 'Enter' || event.key === ' ') &&\n currentIndex >= 0\n ) {\n const currentItem = nestedItems[currentIndex]\n const trigger = currentItem.activationTrigger\n\n // Check if trigger is a link or any interactive element, the element can be in uppercase or lowercase\n const linkTags = [\n 'A',\n 'DAP-DS-LINK',\n 'DAP-DS-BUTTON',\n 'BUTTON',\n 'LINK',\n ]\n const isInteractive = linkTags.includes(\n (trigger?.tagName ?? '').toUpperCase(),\n )\n\n // For links with Enter key, let the browser handle it naturally\n // Only prevent default for Space key or non-link elements\n if (!isInteractive || event.key === ' ') {\n event.preventDefault()\n event.stopPropagation()\n }\n\n if (currentItem.hasNestedItems || currentItem.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!currentItem.opened) {\n currentItem.showDropDown()\n }\n } else if (!isInteractive || event.key === ' ') {\n // For non-links or Space key, simulate click\n currentItem.activateTrigger()\n }\n // For links with Enter, browser default handles navigation\n return\n }\n } else if (this.hasContent) {\n // Mega menu: navigate between focusable items with arrow keys\n const focusableItems = this._getFocusablePopupItems()\n if (focusableItems.length > 0) {\n const target = event.target as HTMLElement\n const currentIndex = focusableItems.findIndex(\n item => item === target || item.contains(target),\n )\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n event.stopPropagation()\n const nextIndex =\n currentIndex < 0\n ? 0\n : currentIndex < focusableItems.length - 1\n ? currentIndex + 1\n : 0\n this._focusPopupItem(focusableItems[nextIndex])\n return\n } else if (event.key === 'ArrowUp') {\n event.preventDefault()\n event.stopPropagation()\n const prevIndex =\n currentIndex < 0\n ? focusableItems.length - 1\n : currentIndex > 0\n ? currentIndex - 1\n : focusableItems.length - 1\n this._focusPopupItem(focusableItems[prevIndex])\n return\n } else if (event.key === 'Home') {\n event.preventDefault()\n event.stopPropagation()\n this._focusPopupItem(focusableItems[0])\n return\n } else if (event.key === 'End') {\n event.preventDefault()\n event.stopPropagation()\n this._focusPopupItem(focusableItems[focusableItems.length - 1])\n return\n } else if (\n (event.key === 'Enter' || event.key === ' ') &&\n currentIndex >= 0\n ) {\n event.preventDefault()\n event.stopPropagation()\n this._activateFocusableItem(focusableItems[currentIndex])\n return\n }\n }\n }\n }\n\n // Handle navigation when THIS item is inside a submenu (level > 0)\n if (this.level > 0) {\n const parent = this.parentElement\n if (!parent) return\n\n // Get sibling items at the same level\n const siblings = Array.from(\n parent.querySelectorAll(':scope > dap-ds-navigation-menu-item'),\n ) as DapDSNavigationMenuItem[]\n\n if (siblings.length === 0) return\n\n const currentIndex = siblings.indexOf(this)\n\n // ArrowDown: move to next sibling\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n event.stopPropagation()\n const nextIndex =\n currentIndex < siblings.length - 1 ? currentIndex + 1 : 0\n siblings[nextIndex].focus()\n }\n // ArrowUp: move to previous sibling\n else if (event.key === 'ArrowUp') {\n event.preventDefault()\n event.stopPropagation()\n const prevIndex =\n currentIndex > 0 ? currentIndex - 1 : siblings.length - 1\n siblings[prevIndex].focus()\n }\n // ArrowRight: open THIS item's submenu if it has one\n else if (event.key === 'ArrowRight') {\n if (this.hasNestedItems || this.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!this.opened) {\n this.showDropDown()\n this.updateComplete.then(() => {\n this.focusFirstDropdownChild()\n })\n } else {\n this.focusFirstDropdownChild()\n }\n }\n }\n // ArrowLeft: close parent submenu and return focus\n else if (event.key === 'ArrowLeft') {\n event.preventDefault()\n event.stopPropagation()\n // Find the parent menu-item that contains this submenu\n const parentMenuItem = parent.closest(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem\n if (parentMenuItem) {\n parentMenuItem.hideDropDown()\n parentMenuItem.focus()\n }\n }\n // Escape: close parent submenu\n else if (event.key === 'Escape') {\n event.preventDefault()\n event.stopPropagation()\n const parentMenuItem = parent.closest(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem\n if (parentMenuItem) {\n parentMenuItem.hideDropDown()\n parentMenuItem.focus()\n }\n }\n // Enter or Space: activate the link or trigger\n else if (event.key === 'Enter' || event.key === ' ') {\n const trigger = this.activationTrigger\n\n // Check if trigger is a link\n const linkTags = ['A', 'DAP-DS-LINK', 'LINK']\n const isLink =\n trigger &&\n (linkTags.includes(trigger.tagName.toLowerCase()) ||\n linkTags.includes(trigger.tagName))\n\n // For links with Enter key, let the browser handle it naturally\n // Only prevent default for Space key or non-link elements\n if (!isLink || event.key === ' ') {\n event.preventDefault()\n event.stopPropagation()\n }\n\n // If item has submenu, open it\n if (this.hasNestedItems || this.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!this.opened) {\n this.showDropDown(false)\n }\n } else if (this.hasLink) {\n // slot=\"link\" pattern: delegate to the visually-hidden router link\n event.preventDefault()\n event.stopPropagation()\n const linkEl = this._getLinkElement()\n if (linkEl) {\n const href = linkEl.getAttribute('href')\n linkEl.click()\n if (href) {\n this.emit('dds-navigation-item-click', { href, event })\n }\n }\n } else if (!isLink || event.key === ' ') {\n // For non-links or Space key, simulate click\n this.activateTrigger()\n }\n // For links with Enter, browser default handles navigation\n }\n }\n }\n\n /** @ignore Override parent's handleDocumentMouseDown to be parent-aware for nested menus. */\n protected handleDocumentMouseDown = (event: MouseEvent): void => {\n const target = event.target as HTMLElement\n const path = event.composedPath()\n const isInsideThis = path.includes(this)\n const isInsideNestedItems = this._isWithinNestedItems(target)\n\n if (!isInsideThis && !isInsideNestedItems) {\n this.hideDropDown()\n }\n }\n\n /** Check if target is within any nested navigation menu items. */\n private _isWithinNestedItems(target: HTMLElement): boolean {\n const nestedItems = Array.from(\n this.querySelectorAll('dap-ds-navigation-menu-item'),\n ) as DapDSNavigationMenuItem[]\n\n return nestedItems.some(item => {\n return (\n item.contains(target) ||\n (item.shadowRoot && item.shadowRoot.contains(target))\n )\n })\n }\n\n focus() {\n const trigger = this._trigger?.[0]\n if (!trigger) return\n // Light-DOM wrapper hosts are not focusable themselves — focus the inner\n // focusable element instead. Shadow-root triggers (e.g. dap-ds-button)\n // delegate focus through their own focus() override.\n if (!trigger.shadowRoot) {\n const inner = this._getInnerLightDomFocusable(trigger)\n if (inner) {\n inner.focus()\n return\n }\n }\n trigger.focus()\n }\n\n /**\n * Sets this item as the active (or inactive) roving tabindex target.\n * Only the active item's trigger is in the sequential tab order (tabindex=\"0\").\n * All others are removed (tabindex=\"-1\") so Tab exits the whole nav in one step.\n */\n setRovingTabIndex(active: boolean) {\n if (active) {\n this.setAttribute('data-nav-current', '')\n } else {\n this.removeAttribute('data-nav-current')\n }\n this._isRovingActive = active\n\n const trigger = this._trigger?.[0]\n if (trigger) {\n this._applyTriggerTabIndex(trigger, active)\n } else {\n // Trigger not yet in DOM — defer until after Lit renders\n this.updateComplete.then(() => {\n const t = this._trigger?.[0]\n if (t) this._applyTriggerTabIndex(t, active)\n })\n }\n }\n\n /** Apply tabindex to a trigger element and its inner focusable element. */\n private _applyTriggerTabIndex(trigger: HTMLElement, active: boolean) {\n if (trigger.shadowRoot) {\n const inner = trigger.shadowRoot.querySelector<HTMLElement>(\n 'a[href], button:not([disabled])',\n )\n if (inner) {\n // For custom elements with a shadow root: manage tabindex on the inner\n // focusable element directly. The host must have NO tabindex attribute\n // (not even -1) to avoid creating a shadow-encapsulated tab scope that\n // would produce two consecutive Tab stops (host → inner button).\n // Without a tabindex on the host, inner elements participate directly\n // in the flat tree tab order.\n trigger.removeAttribute('tabindex')\n inner.setAttribute('tabindex', active ? '0' : '-1')\n return\n }\n } else {\n // Light-DOM wrapper without a shadow root (e.g. an Angular/Vue component\n // host rendering a native button in light DOM): putting tabindex on the\n // host would create a second tab stop next to the natively focusable\n // inner element. Manage the inner element and keep the host clean.\n const inner = this._getInnerLightDomFocusable(trigger)\n if (inner) {\n trigger.removeAttribute('tabindex')\n inner.setAttribute('tabindex', active ? '0' : '-1')\n return\n }\n }\n // Natively focusable element or no inner focusable found:\n // use the host element as the tab stop directly.\n trigger.setAttribute('tabindex', active ? '0' : '-1')\n }\n\n /**\n * Returns the inner light-DOM focusable element of a non-focusable wrapper\n * trigger, or null when the trigger itself should be the tab stop.\n */\n private _getInnerLightDomFocusable(trigger: HTMLElement): HTMLElement | null {\n if (\n ['A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA'].includes(trigger.tagName)\n ) {\n return null\n }\n return trigger.querySelector<HTMLElement>('a[href], button:not([disabled])')\n }\n\n /** Focus the first focusable element in the dropdown (supports both nested nav items and mega menu content). */\n focusFirstDropdownChild() {\n const firstNavItem = this.querySelector(\n 'dap-ds-navigation-menu-item',\n ) as DapDSNavigationMenuItem | null\n if (firstNavItem) {\n firstNavItem.focus()\n return\n }\n const items = this._getFocusablePopupItems()\n if (items.length > 0) {\n this._focusPopupItem(items[0])\n }\n }\n\n /** Focus the last focusable element in the dropdown (supports both nested nav items and mega menu content). */\n focusLastDropdownChild() {\n const navItems = Array.from(\n this.querySelectorAll(':scope > dap-ds-navigation-menu-item'),\n ) as DapDSNavigationMenuItem[]\n if (navItems.length > 0) {\n navItems[navItems.length - 1].focus()\n return\n }\n const items = this._getFocusablePopupItems()\n if (items.length > 0) {\n this._focusPopupItem(items[items.length - 1])\n }\n }\n\n /** Get all top-level focusable items inside the popup slot content (for mega menu arrow navigation). */\n private _getFocusablePopupItems(): HTMLElement[] {\n if (!this.popup) return []\n const contentSlot = this.popup.querySelector(\n 'slot:not([name])',\n ) as HTMLSlotElement | null\n const assigned = contentSlot?.assignedElements({ flatten: true }) ?? []\n const items: HTMLElement[] = []\n for (const el of assigned) {\n this._collectFocusableItems(el as HTMLElement, items)\n }\n return items\n }\n\n private _collectFocusableItems(el: HTMLElement, result: HTMLElement[]) {\n // Custom elements with shadow roots (e.g. dap-ds-button): check if they contain a focusable inner element\n if (el.shadowRoot) {\n const inner = el.shadowRoot.querySelector<HTMLElement>(\n 'a[href]:not([tabindex=\"-1\"]), button:not([disabled]):not([tabindex=\"-1\"])',\n )\n if (inner) {\n result.push(el)\n return\n }\n }\n // Standard focusable elements\n if (\n ['A', 'BUTTON', 'INPUT', 'SELECT', 'TEXTAREA'].includes(el.tagName) &&\n !el.hasAttribute('disabled') &&\n el.getAttribute('tabindex') !== '-1'\n ) {\n result.push(el)\n return\n }\n // Recurse into children\n for (const child of el.children) {\n this._collectFocusableItems(child as HTMLElement, result)\n }\n }\n\n private _activateFocusableItem(item: HTMLElement) {\n if (item.shadowRoot) {\n const inner = item.shadowRoot.querySelector<HTMLElement>(\n 'a[href], button:not([disabled])',\n )\n if (inner) {\n inner.click()\n return\n }\n }\n item.click()\n }\n\n private _focusPopupItem(item: HTMLElement) {\n // For custom elements with shadow roots, focus the inner a/button directly\n if (item.shadowRoot) {\n const inner = item.shadowRoot.querySelector<HTMLElement>(\n 'a[href], button:not([disabled])',\n )\n if (inner) {\n inner.focus()\n return\n }\n }\n item.focus()\n }\n\n async showDropDown(byHover = false) {\n const hasSubmenu = this.hasContent || this.hasNestedItems\n if (this.opened || !hasSubmenu) {\n return\n }\n\n this._updatePlacementForLevel()\n this.emit('dds-navigation-dropdown-open', { item: this })\n\n this.opened = true\n this.openedByHover = byHover\n const triggerElements = this._trigger\n triggerElements[0]?.setAttribute('aria-expanded', 'true')\n\n document.addEventListener('mousedown', this.handleDocumentMouseDown)\n\n await this.updateComplete\n this._applyZIndex()\n }\n\n async hideDropDown() {\n if (!this.opened) {\n return\n }\n\n // Close all nested items first\n const nestedItems = this.querySelectorAll('dap-ds-navigation-menu-item')\n nestedItems.forEach(item => {\n if ((item as DapDSNavigationMenuItem).opened) {\n ;(item as DapDSNavigationMenuItem).hideDropDown()\n }\n })\n\n this.opened = false\n this.openedByHover = false\n const triggerElements = this._trigger\n triggerElements[0]?.setAttribute('aria-expanded', 'false')\n\n document.removeEventListener('mousedown', this.handleDocumentMouseDown)\n\n await this.updateComplete\n }\n\n /** Handle trigger slot change events. */\n private _handleTriggerSlotChange() {\n this._handleTriggerSlotChangeCallback()\n this.stopPositionUpdate()\n this.updateComplete.then(() => {\n if (this.triggerElement) {\n this.startPositionUpdate()\n }\n })\n }\n\n /** Update trigger element attributes and properties. */\n _handleTriggerSlotChangeCallback() {\n this.updateComplete.then(() => {\n const triggerElements = this._trigger\n if (triggerElements && triggerElements.length > 0) {\n this.triggerElement = triggerElements[0]\n\n triggerElements[0].setAttribute('aria-controls', 'dropdown')\n\n const hasSubmenu = this.hasContent || this.hasNestedItems\n if (hasSubmenu) {\n triggerElements[0].setAttribute(\n 'aria-expanded',\n this.opened ? 'true' : 'false',\n )\n triggerElements[0].setAttribute('aria-haspopup', 'true')\n } else {\n triggerElements[0].removeAttribute('aria-expanded')\n }\n\n triggerElements[0].style.display = 'flex'\n this._updateActiveState()\n\n // Sync roving tabindex to the (possibly new) trigger element\n this._applyTriggerTabIndex(triggerElements[0], this._isRovingActive)\n }\n })\n }\n\n private _updateActiveState() {\n const triggerElements = this._trigger\n if (\n (!triggerElements || triggerElements.length === 0 || !this.activeHref) &&\n !this.baseHref\n ) {\n this.active = false\n } else if (this.baseHref) {\n if (this.exactHref) {\n this.active = this.baseHref === this.activeHref\n } else {\n this.active = this.activeHref?.startsWith(this.baseHref) || false\n }\n } else {\n const triggerHref = triggerElements[0]?.getAttribute('href') || this.href\n this.active = triggerHref === this.activeHref\n ;(triggerElements[0] as any).active = this.active\n }\n\n // Fallback: check link slot element's href (for slot=\"link\" pattern)\n if (!this.active && this.hasLink && this.activeHref) {\n const linkEl = this._getLinkElement()\n const linkHref = linkEl?.getAttribute('href')\n if (linkHref) {\n this.active = this.exactHref\n ? linkHref === this.activeHref\n : this.activeHref.startsWith(linkHref)\n }\n }\n\n // Set aria-current=\"page\" for active navigation items\n if (triggerElements && triggerElements.length > 0) {\n if (this.active) {\n triggerElements[0].setAttribute('aria-current', 'page')\n } else {\n triggerElements[0].removeAttribute('aria-current')\n }\n }\n }\n\n _handleContentSlotChange(e: Event) {\n const slot = e.target as HTMLSlotElement\n if (slot) {\n const childNodes = slot.assignedElements()\n this.hasContent = childNodes.length > 0\n }\n this._updateNestedItems()\n }\n\n /** Render expand indicator icon based on nesting level and orientation. */\n private renderExpandIndicator() {\n if (!this.hasNestedItems && !this.hasContent) return html``\n\n return html`\n <span class=\"navigation-item__indicator\" part=\"indicator\">\n <slot name=\"indicator\">\n <dap-ds-icon\n part=\"indicator-icon\"\n exportparts=\"base:indicator-icon-base,icon:indicator-icon-icon\"\n name=${this._getDefaultIconName()}\n aria-hidden=\"true\"></dap-ds-icon>\n </slot>\n </span>\n `\n }\n\n /** Get the default icon name based on orientation and level. */\n private _getDefaultIconName(): string {\n // For vertical menus, always use right arrow (submenus open to the right)\n // For horizontal menus, use down arrow for top-level, right arrow for nested\n if (this.orientation === 'vertical') {\n return 'arrow-right-s-line'\n } else {\n return this.level === 0 ? 'arrow-down-s-line' : 'arrow-right-s-line'\n }\n }\n\n renderTrigger() {\n const hasSubmenu = this.hasContent || this.hasNestedItems\n const ariaExpanded = hasSubmenu\n ? this.opened\n ? 'true'\n : 'false'\n : undefined\n // Provide an explicit aria-label so screen readers announce the item name.\n // The label text is buried through multiple slot levels (dap-ds-button >\n // dap-ds-stack > nav-item title slot), which some screen readers don't\n // fully traverse for accessible name computation.\n const triggerAriaLabel = this._titleText || this.label || undefined\n return html`\n <dap-ds-button\n variant=\"subtle-menu\"\n tabindex=${this._isRovingActive ? '0' : '-1'}\n ?active=${this.active}\n aria-expanded=${ifDefined(ariaExpanded)}\n aria-label=${ifDefined(triggerAriaLabel)}\n href=${ifDefined(this.href)}\n target=${ifDefined(this.target)}\n rel=${ifDefined(this.rel)}\n forceRole=${ifDefined(!hasSubmenu && this.hasLink ? 'link' : undefined)}\n part=\"trigger\"\n data-testid=${this.triggerButtonTestId}\n exportparts=\"base:trigger-base,content:trigger-content,high-contrast:trigger-high-contrast\">\n <dap-ds-stack direction=\"row\" exportparts=\"base:trigger-stack-base\">\n <span part=\"title\">\n <slot name=\"title\" @slotchange=${this._handleTitleSlotChange}>\n ${this.hasTitleSlot ? nothing : this.label || nothing}\n </slot>\n </span>\n ${this.renderExpandIndicator()}\n </dap-ds-stack>\n </dap-ds-button>\n `\n }\n\n renderPopup() {\n return html`\n <slot name=\"trigger\" @slotchange=${this._handleTriggerSlotChange}>\n ${this.renderTrigger()}\n </slot>\n <!-- Link slot: outside inert popup, visually hidden, for SPA router links -->\n <div class=\"navigation-item__link-wrapper\" aria-hidden=\"true\">\n <slot name=\"link\" @slotchange=${this._handleLinkSlotChange}></slot>\n </div>\n <div\n part=\"popup\"\n id=\"popup\"\n ?inert=${!this.opened}\n class=${clsx('popup', `popup--${this.effectiveSize}`, {\n 'popup--opened': this.opened,\n 'popup--fixed': this.floatingStrategy === 'fixed',\n 'popup--has-arrow': this.hasArrow,\n 'popup--overflow': this.overflow,\n 'popup--full-width': this.fullWidth,\n })}>\n <div part=\"content\">\n <slot @slotchange=${this._handleContentSlotChange}></slot>\n </div>\n ${this.hasArrow\n ? html`<div\n part=\"arrow\"\n class=${clsx('popup__arrow')}\n role=\"presentation\"></div>`\n : ''}\n </div>\n `\n }\n\n render() {\n const hasSubmenu = this.hasContent || this.hasNestedItems\n\n return html`\n <div\n part=\"base\"\n class=${clsx('navigation-item', {\n 'navigation-item--has-content': hasSubmenu,\n 'navigation-item--opened': this.opened,\n [`navigation-item--level-${this.level}`]: true,\n })}>\n ${this.renderPopup()}\n </div>\n `\n }\n}\n"],"names":["_DapDSNavigationMenuItem","SizedMixin","DdsElement","e","slot","elements","el","nodes","node","_a","n","_b","event","triggerElements","path","trigger","tag","linkEl","href","ancestor","_c","parent","item","siblingItem","_event","nestedItems","target","currentIndex","nextIndex","prevIndex","currentItem","firstNested","isInteractive","focusableItems","siblings","parentMenuItem","linkTags","isLink","isInsideThis","isInsideNestedItems","SubmenuController","directTriggers","defaultButton","changedProperties","__async","__superGet","allNestedItems","zIndex","autoUpdate","boundary","x","y","computePosition","offset","flip","shift","size","availableHeight","rects","inner","active","t","firstNavItem","items","navItems","contentSlot","assigned","result","child","byHover","hasSubmenu","triggerHref","linkHref","childNodes","html","ariaExpanded","triggerAriaLabel","ifDefined","nothing","clsx","DapDSIcon","DapDSButton","DapDSStack","unsafeCSS","styles","popupStyles","DapDSNavigationMenuItem","__decorateClass","query","queryAssignedElements","property","state","watch"],"mappings":"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"}
@@ -79,10 +79,8 @@ const d = class d extends _ {
79
79
  }), !l) {
80
80
  if (t.key === "Enter" || t.key === " ") {
81
81
  if (i) {
82
- const o = i.querySelector(
83
- '[slot="trigger"]'
84
- ), r = (o == null ? void 0 : o.tagName.toLowerCase()) === "a" || (o == null ? void 0 : o.tagName.toLowerCase()) === "dap-ds-link";
85
- (!r || t.key === " ") && (t.preventDefault(), t.stopPropagation()), i.hasNestedItems || i.hasContent ? (t.preventDefault(), t.stopPropagation(), i.opened || i.showDropDown()) : (!r || t.key === " ") && (o == null || o.click());
82
+ const o = i.activationTrigger, r = (o == null ? void 0 : o.tagName.toLowerCase()) === "a" || (o == null ? void 0 : o.tagName.toLowerCase()) === "dap-ds-link";
83
+ (!r || t.key === " ") && (t.preventDefault(), t.stopPropagation()), i.hasNestedItems || i.hasContent ? (t.preventDefault(), t.stopPropagation(), i.opened || i.showDropDown()) : (!r || t.key === " ") && i.activateTrigger();
86
84
  }
87
85
  } else if ([
88
86
  "ArrowDown",
@@ -1 +1 @@
1
- {"version":3,"file":"navigation-menu.component.js","sources":["../../../src/components/navigation-menu/navigation-menu.component.ts"],"sourcesContent":["import clsx from 'clsx'\nimport { unsafeCSS } from 'lit'\nimport { property, query } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { html } from 'lit/static-html.js'\n\nimport { TabNavigationMode } from '@/common/types'\n\nimport { DdsElement } from '../../internal/dds-hu-element'\nimport styles from './navigation-menu.scss?inline'\nimport type DapDSNavigationMenuItem from './navigation-menu-item.component'\n\n/**\n * `dap-ds-navigation-menu`\n * @summary A navigation menu for website/application navigation. Supports nested dropdowns with unlimited depth.\n * This is a NAVIGATION component, not an application menu (like dropdowns or context menus).\n * Uses semantic HTML (`<nav>`) and proper navigation ARIA attributes.\n *\n * @element dap-ds-navigation-menu\n * @title - Navigation Menu\n *\n * @property {string} activeHref - The currently active href for highlighting active navigation items with aria-current=\"page\". Defaults to window.location.pathname if not provided.\n * @property {'horizontal' | 'vertical'} orientation - The orientation of the navigation menu. Default is 'horizontal'.\n * @property {boolean} fullWidth - Whether the navigation menu should take full width of the screen. Default is false.\n * @property {boolean} allowMultipleOpen - Whether multiple dropdown branches can stay open simultaneously (accordion mode). Default is true.\n * @property {'group' | 'items'} tabMode - Controls how Tab key navigates through top-level items. Default is 'group'. Group mode will have the first item in the tab order, and items mode will have all items in the tab order.\n *\n * @event {{ href: string, event: Event }} dds-navigation-item-click - Fired when a navigation item is clicked.\n *\n * @slot - The navigation menu list and items.\n *\n * @csspart base - The main navigation menu container (nav element).\n *\n * @cssproperty --dds-navigation-menu-item-gap - The gap between navigation menu items. (default: var(--dds-spacing-100)).\n *\n * @accessibility\n * - Uses semantic `<nav>` element (no menu/menubar roles)\n * - Active items marked with `aria-current=\"page\"`\n * - Keyboard navigation: Tab, Arrow keys, Enter, Escape\n * - Screen readers announce as navigation landmark\n */\nexport default class DapDSNavigationMenu extends DdsElement {\n static tagName = 'dap-ds-navigation-menu'\n\n static readonly styles = unsafeCSS(styles)\n\n /** @ignore */\n @query('slot') defaultSlot: HTMLSlotElement\n\n /** The currently active href for highlighting active navigation items. */\n @property({ type: String }) activeHref?: string\n\n /** The orientation of the navigation menu.\n * @type {'horizontal' | 'vertical'}\n */\n @property({ reflect: true }) orientation: 'horizontal' | 'vertical' =\n 'horizontal'\n\n /** Whether the navigation menu should take full width of the screen. */\n @property({ type: Boolean }) fullWidth = false\n\n /** Whether multiple dropdown branches can stay open simultaneously (accordion mode). */\n @property({ type: Boolean }) allowMultipleOpen = true\n\n /**\n * Controls how Tab key navigates through top-level items.\n * - 'group' (default): Roving tab index — only one item in the tab order, arrow keys move between items.\n * - 'items': All top-level items have tabindex=\"0\" — Tab moves through each item individually.\n * @type {'group' | 'items'}\n */\n @property({ type: String }) tabMode: TabNavigationMode = 'group'\n\n connectedCallback() {\n super.connectedCallback()\n\n if (!this.activeHref) {\n this.activeHref = window.location.pathname\n }\n }\n\n updated(changedProperties: Map<string, unknown>) {\n super.updated(changedProperties)\n\n if (changedProperties.has('activeHref')) {\n this._updateActiveHref()\n }\n\n if (changedProperties.has('fullWidth')) {\n this._updateChildFullWidth()\n }\n\n if (changedProperties.has('orientation')) {\n this._updateOrientation()\n }\n\n if (changedProperties.has('tabMode')) {\n this._applyTabMode()\n this._updateTabMode()\n }\n }\n\n async firstUpdated(changedProperties: Map<string, unknown>) {\n super.firstUpdated(changedProperties)\n this._updateChildFullWidth()\n this._updateOrientation()\n\n // Wait for child items to be fully initialized\n await this.updateComplete\n requestAnimationFrame(() => {\n this._handleSlotChange()\n })\n }\n\n /** Handle keyboard navigation for top-level menubar items only */\n private handleKeyDown(event: KeyboardEvent) {\n const items = this.getAllItems()\n const activeItem = this.getCurrentItem()\n\n // Only handle if we have items\n if (items.length === 0) return\n\n // Check if event is from a nested submenu item (not a direct child)\n // If so, let the submenu handle it\n const target = event.target as HTMLElement\n\n // Check if target is inside a nested menu item (level > 0)\n const allMenuItems = this.querySelectorAll('dap-ds-navigation-menu-item')\n let isFromNestedItem = false\n\n allMenuItems.forEach(item => {\n // If the item is not a direct child (it's nested), and contains the target\n if (\n !items.includes(item as DapDSNavigationMenuItem) &&\n item.contains(target)\n ) {\n isFromNestedItem = true\n }\n })\n\n if (isFromNestedItem) {\n // Event is from nested submenu, let the menu-item handle it\n return\n }\n\n // Enter or Space: activate current item (click trigger or open submenu)\n if (event.key === 'Enter' || event.key === ' ') {\n if (activeItem) {\n const trigger = activeItem.querySelector(\n '[slot=\"trigger\"]',\n ) as HTMLElement\n\n // Check if trigger is a link\n const isLink =\n trigger?.tagName.toLowerCase() === 'a' ||\n trigger?.tagName.toLowerCase() === 'dap-ds-link'\n\n // For links with Enter key, let the browser handle it naturally\n // Only prevent default for Space key or non-link elements\n if (!isLink || event.key === ' ') {\n event.preventDefault()\n event.stopPropagation()\n }\n\n // If item has submenu, open it\n if (activeItem.hasNestedItems || activeItem.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!activeItem.opened) {\n activeItem.showDropDown()\n }\n } else if (!isLink || event.key === ' ') {\n // For non-links or Space key, simulate click\n trigger?.click()\n }\n // For links with Enter, browser default handles navigation\n }\n }\n\n // Arrow keys: navigate between items or open submenus\n else if (\n [\n 'ArrowDown',\n 'ArrowUp',\n 'ArrowLeft',\n 'ArrowRight',\n 'Home',\n 'End',\n ].includes(event.key)\n ) {\n let index = activeItem ? items.indexOf(activeItem) : 0\n\n // Horizontal menubar (top-level navigation)\n if (this.orientation === 'horizontal') {\n // ArrowLeft/Right: navigate between top-level items\n if (event.key === 'ArrowLeft') {\n event.preventDefault()\n event.stopPropagation()\n index--\n if (index < 0) index = items.length - 1\n this.setCurrentItem(items[index])\n items[index].focus()\n } else if (event.key === 'ArrowRight') {\n event.preventDefault()\n event.stopPropagation()\n index++\n if (index > items.length - 1) index = 0\n this.setCurrentItem(items[index])\n items[index].focus()\n }\n // ArrowDown/ArrowUp: open submenu if current item has one, then move focus into it\n else if (\n (event.key === 'ArrowDown' || event.key === 'ArrowUp') &&\n activeItem\n ) {\n if (activeItem.hasNestedItems || activeItem.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!activeItem.opened) {\n activeItem.showDropDown()\n this.updateComplete.then(() => {\n if (event.key === 'ArrowDown') {\n activeItem.focusFirstDropdownChild()\n } else {\n activeItem.focusLastDropdownChild()\n }\n })\n } else {\n // Menu already open — move focus into it\n if (event.key === 'ArrowDown') {\n activeItem.focusFirstDropdownChild()\n } else {\n activeItem.focusLastDropdownChild()\n }\n }\n }\n }\n // Home/End\n else if (event.key === 'Home') {\n event.preventDefault()\n event.stopPropagation()\n this.setCurrentItem(items[0])\n items[0].focus()\n } else if (event.key === 'End') {\n event.preventDefault()\n event.stopPropagation()\n this.setCurrentItem(items[items.length - 1])\n items[items.length - 1].focus()\n }\n }\n // Vertical menubar\n else {\n // ArrowUp/Down: navigate between top-level items\n if (event.key === 'ArrowUp') {\n event.preventDefault()\n event.stopPropagation()\n index--\n if (index < 0) index = items.length - 1\n this.setCurrentItem(items[index])\n items[index].focus()\n } else if (event.key === 'ArrowDown') {\n event.preventDefault()\n event.stopPropagation()\n index++\n if (index > items.length - 1) index = 0\n this.setCurrentItem(items[index])\n items[index].focus()\n }\n // ArrowRight: open submenu if current item has one\n else if (event.key === 'ArrowRight' && activeItem) {\n if (activeItem.hasNestedItems || activeItem.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!activeItem.opened) {\n activeItem.showDropDown()\n this.updateComplete.then(() => {\n activeItem.focusFirstDropdownChild()\n })\n } else {\n activeItem.focusFirstDropdownChild()\n }\n }\n }\n // Home/End\n else if (event.key === 'Home') {\n event.preventDefault()\n event.stopPropagation()\n this.setCurrentItem(items[0])\n items[0].focus()\n } else if (event.key === 'End') {\n event.preventDefault()\n event.stopPropagation()\n this.setCurrentItem(items[items.length - 1])\n items[items.length - 1].focus()\n }\n }\n }\n }\n\n private handleMouseDown(event: MouseEvent) {\n const target = event.target as HTMLElement\n\n if (this.isMenuItem(target)) {\n this.setCurrentItem(target as DapDSNavigationMenuItem)\n }\n }\n\n private handleSlotChange() {\n const items = this.getAllItems()\n\n // Reset the roving tab index when the slotted items change\n if (items.length > 0) {\n this.setCurrentItem(items[0])\n }\n\n // Update properties on all items\n this._updateActiveHref()\n this._updateChildFullWidth()\n this._updateOrientation()\n this._updateTabMode()\n this._applyTabMode()\n }\n\n private isMenuItem(item: HTMLElement) {\n return item.tagName.toLowerCase() === 'dap-ds-navigation-menu-item'\n }\n\n /** Gets all slotted menu items, ignoring disabled elements */\n getAllItems() {\n return [...this.defaultSlot.assignedElements({ flatten: true })].filter(\n (el: Element) => {\n const htmlEl = el as HTMLElement\n if (htmlEl.inert || !this.isMenuItem(htmlEl)) {\n return false\n }\n return true\n },\n ) as DapDSNavigationMenuItem[]\n }\n\n /**\n * Gets the current menu item (the one marked with `data-nav-current`).\n * The menu item may or may not have focus, but for keyboard interaction purposes it's considered the \"active\" item.\n */\n getCurrentItem() {\n return this.getAllItems().find(i => i.hasAttribute('data-nav-current'))\n }\n\n /**\n * Sets the current menu item. In 'group' mode (default), applies roving tabindex so only the\n * active item's trigger is in the sequential tab order (tabindex=\"0\"). In 'items' mode, all\n * top-level items remain in the tab order — only the data-nav-current marker is updated.\n */\n setCurrentItem(item: DapDSNavigationMenuItem) {\n const items = this.getAllItems()\n if (this.tabMode === 'items') {\n // items mode: keep all tabindex=\"0\", only track current for keyboard nav\n items.forEach(i => {\n if (i === item) {\n i.setAttribute('data-nav-current', '')\n } else {\n i.removeAttribute('data-nav-current')\n }\n })\n } else {\n // group mode: roving tabindex — only active item in tab order\n items.forEach(i => {\n i.setRovingTabIndex(i === item)\n })\n }\n }\n\n private _updateChildFullWidth() {\n if (this.fullWidth) {\n this._updatePropertyRecursive('fullWidth', true)\n }\n }\n\n /** Recursively update activeHref property for all navigation items. */\n private _updateActiveHref() {\n this._updatePropertyRecursive('activeHref', this.activeHref)\n }\n\n /** Recursively update orientation property for all navigation items. */\n private _updateOrientation() {\n this._updatePropertyRecursive('orientation', this.orientation)\n }\n\n /** Update tabMode property for all top-level navigation items. */\n private _updateTabMode() {\n this.getAllItems().forEach(i => {\n i.tabMode = this.tabMode\n })\n }\n\n /**\n * Applies tab behavior based on the current tabMode:\n * - 'items': All top-level item triggers get tabindex=\"0\".\n * - 'group': Restore roving tabindex — only the current/first item gets tabindex=\"0\".\n */\n private _applyTabMode() {\n const items = this.getAllItems()\n if (items.length === 0) return\n\n if (this.tabMode === 'items') {\n // Determine which item is current before modifying state\n const currentItem =\n items.find(i => i.hasAttribute('data-nav-current')) ?? items[0]\n // Give all items tabindex=\"0\" (setRovingTabIndex also sets data-nav-current on all)\n items.forEach(i => i.setRovingTabIndex(true))\n // Restore single data-nav-current marker\n items.forEach(i => {\n if (i !== currentItem) i.removeAttribute('data-nav-current')\n })\n } else {\n // Restore roving tabindex: only current (or first) item in tab order\n const current =\n items.find(i => i.hasAttribute('data-nav-current')) ?? items[0]\n items.forEach(i => i.setRovingTabIndex(i === current))\n }\n }\n\n /** Helper method to recursively update properties on nested items. */\n private _updatePropertyRecursive(\n property: string,\n value: any,\n element: Element = this,\n ) {\n const navigationItems = element.querySelectorAll(\n ':scope > dap-ds-navigation-menu-item',\n ) as NodeListOf<DapDSNavigationMenuItem>\n\n navigationItems.forEach(item => {\n ;(item as any)[property] = value\n\n this._updatePropertyRecursive(property, value, item)\n })\n }\n\n private _handleNavigationItemClick = (event: Event) => {\n const customEvent = event as CustomEvent\n // Re-emit the event to parent components if needed\n this.emit('dds-navigation-item-click', customEvent.detail)\n }\n\n private _handleDropdownOpen = (event: Event) => {\n // If multiple dropdowns can be open, don't close others\n if (this.allowMultipleOpen) {\n return\n }\n\n const openingItem = event.target as DapDSNavigationMenuItem\n\n // Only close siblings at the same level, not nested items\n const parent = openingItem.parentElement\n const siblings =\n parent?.querySelectorAll(':scope > dap-ds-navigation-menu-item') || []\n\n siblings.forEach(item => {\n if (item !== openingItem && (item as DapDSNavigationMenuItem).opened) {\n ;(item as DapDSNavigationMenuItem).hideDropDown()\n }\n })\n }\n\n private _handleSlotChange = () => {\n this.handleSlotChange()\n }\n\n /**\n * In `tabMode=\"items\"`, keep `data-nav-current` in sync with the element that\n * received focus so that arrow-key navigation always targets the right item.\n */\n private _handleFocusIn = (event: FocusEvent) => {\n if (this.tabMode !== 'items') return\n\n const target = event.target as HTMLElement\n const items = this.getAllItems()\n\n const focusedItem = items.find(\n item => item === target || item.contains(target),\n )\n\n if (focusedItem) {\n this.setCurrentItem(focusedItem)\n }\n }\n\n render() {\n return html`\n <nav\n part=\"base\"\n aria-orientation=${this.orientation === 'vertical'\n ? 'vertical'\n : 'horizontal'}\n class=${clsx('navigation-menu', {\n 'navigation-menu--vertical': this.orientation === 'vertical',\n })}\n aria-label=${ifDefined(this.ariaLabel || 'Main navigation')}>\n <slot\n @slotchange=${this._handleSlotChange}\n @click=${this._handleNavigationItemClick}\n @dds-navigation-dropdown-open=${this._handleDropdownOpen}\n @keydown=${this.handleKeyDown}\n @mousedown=${this.handleMouseDown}\n @focusin=${this._handleFocusIn}></slot>\n </nav>\n `\n }\n}\n"],"names":["_DapDSNavigationMenu","DdsElement","event","customEvent","openingItem","parent","item","target","focusedItem","changedProperties","__async","__superGet","items","activeItem","allMenuItems","isFromNestedItem","trigger","isLink","index","el","htmlEl","i","currentItem","_a","current","_b","property","value","element","html","clsx","ifDefined","unsafeCSS","styles","DapDSNavigationMenu","__decorateClass","query"],"mappings":"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"}
1
+ {"version":3,"file":"navigation-menu.component.js","sources":["../../../src/components/navigation-menu/navigation-menu.component.ts"],"sourcesContent":["import clsx from 'clsx'\nimport { unsafeCSS } from 'lit'\nimport { property, query } from 'lit/decorators.js'\nimport { ifDefined } from 'lit/directives/if-defined.js'\nimport { html } from 'lit/static-html.js'\n\nimport { TabNavigationMode } from '@/common/types'\n\nimport { DdsElement } from '../../internal/dds-hu-element'\nimport styles from './navigation-menu.scss?inline'\nimport type DapDSNavigationMenuItem from './navigation-menu-item.component'\n\n/**\n * `dap-ds-navigation-menu`\n * @summary A navigation menu for website/application navigation. Supports nested dropdowns with unlimited depth.\n * This is a NAVIGATION component, not an application menu (like dropdowns or context menus).\n * Uses semantic HTML (`<nav>`) and proper navigation ARIA attributes.\n *\n * @element dap-ds-navigation-menu\n * @title - Navigation Menu\n *\n * @property {string} activeHref - The currently active href for highlighting active navigation items with aria-current=\"page\". Defaults to window.location.pathname if not provided.\n * @property {'horizontal' | 'vertical'} orientation - The orientation of the navigation menu. Default is 'horizontal'.\n * @property {boolean} fullWidth - Whether the navigation menu should take full width of the screen. Default is false.\n * @property {boolean} allowMultipleOpen - Whether multiple dropdown branches can stay open simultaneously (accordion mode). Default is true.\n * @property {'group' | 'items'} tabMode - Controls how Tab key navigates through top-level items. Default is 'group'. Group mode will have the first item in the tab order, and items mode will have all items in the tab order.\n *\n * @event {{ href: string, event: Event }} dds-navigation-item-click - Fired when a navigation item is clicked.\n *\n * @slot - The navigation menu list and items.\n *\n * @csspart base - The main navigation menu container (nav element).\n *\n * @cssproperty --dds-navigation-menu-item-gap - The gap between navigation menu items. (default: var(--dds-spacing-100)).\n *\n * @accessibility\n * - Uses semantic `<nav>` element (no menu/menubar roles)\n * - Active items marked with `aria-current=\"page\"`\n * - Keyboard navigation: Tab, Arrow keys, Enter, Escape\n * - Screen readers announce as navigation landmark\n */\nexport default class DapDSNavigationMenu extends DdsElement {\n static tagName = 'dap-ds-navigation-menu'\n\n static readonly styles = unsafeCSS(styles)\n\n /** @ignore */\n @query('slot') defaultSlot: HTMLSlotElement\n\n /** The currently active href for highlighting active navigation items. */\n @property({ type: String }) activeHref?: string\n\n /** The orientation of the navigation menu.\n * @type {'horizontal' | 'vertical'}\n */\n @property({ reflect: true }) orientation: 'horizontal' | 'vertical' =\n 'horizontal'\n\n /** Whether the navigation menu should take full width of the screen. */\n @property({ type: Boolean }) fullWidth = false\n\n /** Whether multiple dropdown branches can stay open simultaneously (accordion mode). */\n @property({ type: Boolean }) allowMultipleOpen = true\n\n /**\n * Controls how Tab key navigates through top-level items.\n * - 'group' (default): Roving tab index — only one item in the tab order, arrow keys move between items.\n * - 'items': All top-level items have tabindex=\"0\" — Tab moves through each item individually.\n * @type {'group' | 'items'}\n */\n @property({ type: String }) tabMode: TabNavigationMode = 'group'\n\n connectedCallback() {\n super.connectedCallback()\n\n if (!this.activeHref) {\n this.activeHref = window.location.pathname\n }\n }\n\n updated(changedProperties: Map<string, unknown>) {\n super.updated(changedProperties)\n\n if (changedProperties.has('activeHref')) {\n this._updateActiveHref()\n }\n\n if (changedProperties.has('fullWidth')) {\n this._updateChildFullWidth()\n }\n\n if (changedProperties.has('orientation')) {\n this._updateOrientation()\n }\n\n if (changedProperties.has('tabMode')) {\n this._applyTabMode()\n this._updateTabMode()\n }\n }\n\n async firstUpdated(changedProperties: Map<string, unknown>) {\n super.firstUpdated(changedProperties)\n this._updateChildFullWidth()\n this._updateOrientation()\n\n // Wait for child items to be fully initialized\n await this.updateComplete\n requestAnimationFrame(() => {\n this._handleSlotChange()\n })\n }\n\n /** Handle keyboard navigation for top-level menubar items only */\n private handleKeyDown(event: KeyboardEvent) {\n const items = this.getAllItems()\n const activeItem = this.getCurrentItem()\n\n // Only handle if we have items\n if (items.length === 0) return\n\n // Check if event is from a nested submenu item (not a direct child)\n // If so, let the submenu handle it\n const target = event.target as HTMLElement\n\n // Check if target is inside a nested menu item (level > 0)\n const allMenuItems = this.querySelectorAll('dap-ds-navigation-menu-item')\n let isFromNestedItem = false\n\n allMenuItems.forEach(item => {\n // If the item is not a direct child (it's nested), and contains the target\n if (\n !items.includes(item as DapDSNavigationMenuItem) &&\n item.contains(target)\n ) {\n isFromNestedItem = true\n }\n })\n\n if (isFromNestedItem) {\n // Event is from nested submenu, let the menu-item handle it\n return\n }\n\n // Enter or Space: activate current item (click trigger or open submenu)\n if (event.key === 'Enter' || event.key === ' ') {\n if (activeItem) {\n const trigger = activeItem.activationTrigger\n\n // Check if trigger is a link\n const isLink =\n trigger?.tagName.toLowerCase() === 'a' ||\n trigger?.tagName.toLowerCase() === 'dap-ds-link'\n\n // For links with Enter key, let the browser handle it naturally\n // Only prevent default for Space key or non-link elements\n if (!isLink || event.key === ' ') {\n event.preventDefault()\n event.stopPropagation()\n }\n\n // If item has submenu, open it\n if (activeItem.hasNestedItems || activeItem.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!activeItem.opened) {\n activeItem.showDropDown()\n }\n } else if (!isLink || event.key === ' ') {\n // For non-links or Space key, simulate click\n activeItem.activateTrigger()\n }\n // For links with Enter, browser default handles navigation\n }\n }\n\n // Arrow keys: navigate between items or open submenus\n else if (\n [\n 'ArrowDown',\n 'ArrowUp',\n 'ArrowLeft',\n 'ArrowRight',\n 'Home',\n 'End',\n ].includes(event.key)\n ) {\n let index = activeItem ? items.indexOf(activeItem) : 0\n\n // Horizontal menubar (top-level navigation)\n if (this.orientation === 'horizontal') {\n // ArrowLeft/Right: navigate between top-level items\n if (event.key === 'ArrowLeft') {\n event.preventDefault()\n event.stopPropagation()\n index--\n if (index < 0) index = items.length - 1\n this.setCurrentItem(items[index])\n items[index].focus()\n } else if (event.key === 'ArrowRight') {\n event.preventDefault()\n event.stopPropagation()\n index++\n if (index > items.length - 1) index = 0\n this.setCurrentItem(items[index])\n items[index].focus()\n }\n // ArrowDown/ArrowUp: open submenu if current item has one, then move focus into it\n else if (\n (event.key === 'ArrowDown' || event.key === 'ArrowUp') &&\n activeItem\n ) {\n if (activeItem.hasNestedItems || activeItem.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!activeItem.opened) {\n activeItem.showDropDown()\n this.updateComplete.then(() => {\n if (event.key === 'ArrowDown') {\n activeItem.focusFirstDropdownChild()\n } else {\n activeItem.focusLastDropdownChild()\n }\n })\n } else {\n // Menu already open — move focus into it\n if (event.key === 'ArrowDown') {\n activeItem.focusFirstDropdownChild()\n } else {\n activeItem.focusLastDropdownChild()\n }\n }\n }\n }\n // Home/End\n else if (event.key === 'Home') {\n event.preventDefault()\n event.stopPropagation()\n this.setCurrentItem(items[0])\n items[0].focus()\n } else if (event.key === 'End') {\n event.preventDefault()\n event.stopPropagation()\n this.setCurrentItem(items[items.length - 1])\n items[items.length - 1].focus()\n }\n }\n // Vertical menubar\n else {\n // ArrowUp/Down: navigate between top-level items\n if (event.key === 'ArrowUp') {\n event.preventDefault()\n event.stopPropagation()\n index--\n if (index < 0) index = items.length - 1\n this.setCurrentItem(items[index])\n items[index].focus()\n } else if (event.key === 'ArrowDown') {\n event.preventDefault()\n event.stopPropagation()\n index++\n if (index > items.length - 1) index = 0\n this.setCurrentItem(items[index])\n items[index].focus()\n }\n // ArrowRight: open submenu if current item has one\n else if (event.key === 'ArrowRight' && activeItem) {\n if (activeItem.hasNestedItems || activeItem.hasContent) {\n event.preventDefault()\n event.stopPropagation()\n if (!activeItem.opened) {\n activeItem.showDropDown()\n this.updateComplete.then(() => {\n activeItem.focusFirstDropdownChild()\n })\n } else {\n activeItem.focusFirstDropdownChild()\n }\n }\n }\n // Home/End\n else if (event.key === 'Home') {\n event.preventDefault()\n event.stopPropagation()\n this.setCurrentItem(items[0])\n items[0].focus()\n } else if (event.key === 'End') {\n event.preventDefault()\n event.stopPropagation()\n this.setCurrentItem(items[items.length - 1])\n items[items.length - 1].focus()\n }\n }\n }\n }\n\n private handleMouseDown(event: MouseEvent) {\n const target = event.target as HTMLElement\n\n if (this.isMenuItem(target)) {\n this.setCurrentItem(target as DapDSNavigationMenuItem)\n }\n }\n\n private handleSlotChange() {\n const items = this.getAllItems()\n\n // Reset the roving tab index when the slotted items change\n if (items.length > 0) {\n this.setCurrentItem(items[0])\n }\n\n // Update properties on all items\n this._updateActiveHref()\n this._updateChildFullWidth()\n this._updateOrientation()\n this._updateTabMode()\n this._applyTabMode()\n }\n\n private isMenuItem(item: HTMLElement) {\n return item.tagName.toLowerCase() === 'dap-ds-navigation-menu-item'\n }\n\n /** Gets all slotted menu items, ignoring disabled elements */\n getAllItems() {\n return [...this.defaultSlot.assignedElements({ flatten: true })].filter(\n (el: Element) => {\n const htmlEl = el as HTMLElement\n if (htmlEl.inert || !this.isMenuItem(htmlEl)) {\n return false\n }\n return true\n },\n ) as DapDSNavigationMenuItem[]\n }\n\n /**\n * Gets the current menu item (the one marked with `data-nav-current`).\n * The menu item may or may not have focus, but for keyboard interaction purposes it's considered the \"active\" item.\n */\n getCurrentItem() {\n return this.getAllItems().find(i => i.hasAttribute('data-nav-current'))\n }\n\n /**\n * Sets the current menu item. In 'group' mode (default), applies roving tabindex so only the\n * active item's trigger is in the sequential tab order (tabindex=\"0\"). In 'items' mode, all\n * top-level items remain in the tab order — only the data-nav-current marker is updated.\n */\n setCurrentItem(item: DapDSNavigationMenuItem) {\n const items = this.getAllItems()\n if (this.tabMode === 'items') {\n // items mode: keep all tabindex=\"0\", only track current for keyboard nav\n items.forEach(i => {\n if (i === item) {\n i.setAttribute('data-nav-current', '')\n } else {\n i.removeAttribute('data-nav-current')\n }\n })\n } else {\n // group mode: roving tabindex — only active item in tab order\n items.forEach(i => {\n i.setRovingTabIndex(i === item)\n })\n }\n }\n\n private _updateChildFullWidth() {\n if (this.fullWidth) {\n this._updatePropertyRecursive('fullWidth', true)\n }\n }\n\n /** Recursively update activeHref property for all navigation items. */\n private _updateActiveHref() {\n this._updatePropertyRecursive('activeHref', this.activeHref)\n }\n\n /** Recursively update orientation property for all navigation items. */\n private _updateOrientation() {\n this._updatePropertyRecursive('orientation', this.orientation)\n }\n\n /** Update tabMode property for all top-level navigation items. */\n private _updateTabMode() {\n this.getAllItems().forEach(i => {\n i.tabMode = this.tabMode\n })\n }\n\n /**\n * Applies tab behavior based on the current tabMode:\n * - 'items': All top-level item triggers get tabindex=\"0\".\n * - 'group': Restore roving tabindex — only the current/first item gets tabindex=\"0\".\n */\n private _applyTabMode() {\n const items = this.getAllItems()\n if (items.length === 0) return\n\n if (this.tabMode === 'items') {\n // Determine which item is current before modifying state\n const currentItem =\n items.find(i => i.hasAttribute('data-nav-current')) ?? items[0]\n // Give all items tabindex=\"0\" (setRovingTabIndex also sets data-nav-current on all)\n items.forEach(i => i.setRovingTabIndex(true))\n // Restore single data-nav-current marker\n items.forEach(i => {\n if (i !== currentItem) i.removeAttribute('data-nav-current')\n })\n } else {\n // Restore roving tabindex: only current (or first) item in tab order\n const current =\n items.find(i => i.hasAttribute('data-nav-current')) ?? items[0]\n items.forEach(i => i.setRovingTabIndex(i === current))\n }\n }\n\n /** Helper method to recursively update properties on nested items. */\n private _updatePropertyRecursive(\n property: string,\n value: any,\n element: Element = this,\n ) {\n const navigationItems = element.querySelectorAll(\n ':scope > dap-ds-navigation-menu-item',\n ) as NodeListOf<DapDSNavigationMenuItem>\n\n navigationItems.forEach(item => {\n ;(item as any)[property] = value\n\n this._updatePropertyRecursive(property, value, item)\n })\n }\n\n private _handleNavigationItemClick = (event: Event) => {\n const customEvent = event as CustomEvent\n // Re-emit the event to parent components if needed\n this.emit('dds-navigation-item-click', customEvent.detail)\n }\n\n private _handleDropdownOpen = (event: Event) => {\n // If multiple dropdowns can be open, don't close others\n if (this.allowMultipleOpen) {\n return\n }\n\n const openingItem = event.target as DapDSNavigationMenuItem\n\n // Only close siblings at the same level, not nested items\n const parent = openingItem.parentElement\n const siblings =\n parent?.querySelectorAll(':scope > dap-ds-navigation-menu-item') || []\n\n siblings.forEach(item => {\n if (item !== openingItem && (item as DapDSNavigationMenuItem).opened) {\n ;(item as DapDSNavigationMenuItem).hideDropDown()\n }\n })\n }\n\n private _handleSlotChange = () => {\n this.handleSlotChange()\n }\n\n /**\n * In `tabMode=\"items\"`, keep `data-nav-current` in sync with the element that\n * received focus so that arrow-key navigation always targets the right item.\n */\n private _handleFocusIn = (event: FocusEvent) => {\n if (this.tabMode !== 'items') return\n\n const target = event.target as HTMLElement\n const items = this.getAllItems()\n\n const focusedItem = items.find(\n item => item === target || item.contains(target),\n )\n\n if (focusedItem) {\n this.setCurrentItem(focusedItem)\n }\n }\n\n render() {\n return html`\n <nav\n part=\"base\"\n aria-orientation=${this.orientation === 'vertical'\n ? 'vertical'\n : 'horizontal'}\n class=${clsx('navigation-menu', {\n 'navigation-menu--vertical': this.orientation === 'vertical',\n })}\n aria-label=${ifDefined(this.ariaLabel || 'Main navigation')}>\n <slot\n @slotchange=${this._handleSlotChange}\n @click=${this._handleNavigationItemClick}\n @dds-navigation-dropdown-open=${this._handleDropdownOpen}\n @keydown=${this.handleKeyDown}\n @mousedown=${this.handleMouseDown}\n @focusin=${this._handleFocusIn}></slot>\n </nav>\n `\n }\n}\n"],"names":["_DapDSNavigationMenu","DdsElement","event","customEvent","openingItem","parent","item","target","focusedItem","changedProperties","__async","__superGet","items","activeItem","allMenuItems","isFromNestedItem","trigger","isLink","index","el","htmlEl","i","currentItem","_a","current","_b","property","value","element","html","clsx","ifDefined","unsafeCSS","styles","DapDSNavigationMenu","__decorateClass","query"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { AriaCurrent, SidenavSpacing } from '../../common/types';
1
+ import { AriaCurrent, LinkTarget, SidenavSpacing } from '../../common/types';
2
2
  import { DdsElement } from '../../internal/dds-hu-element';
3
3
  /**
4
4
  * `dap-ds-sidenav-item`
@@ -53,6 +53,14 @@ export default class DapDSSideNavItem extends DdsElement {
53
53
  spacing: SidenavSpacing;
54
54
  /** The size of the side navigation item */
55
55
  size: 'xs' | 'sm' | 'lg';
56
+ /** The target of the link.
57
+ * @type {'_blank' | '_self' | '_parent' | '_top'}
58
+ */
59
+ target: LinkTarget;
60
+ /** The rel of the link */
61
+ rel: string;
62
+ /** The text for the target blank link, applicable when target is _blank. PRO TIP: Use parenthesis to wrap the text */
63
+ targetBlankText: string;
56
64
  static readonly styles: import('lit').CSSResult;
57
65
  render(): import('lit-html').TemplateResult;
58
66
  }