@vielzeug/refine 2.0.3 → 2.1.0

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.
Files changed (57) hide show
  1. package/dist/content/text/text.css.cjs +1 -1
  2. package/dist/content/text/text.css.cjs.map +1 -1
  3. package/dist/content/text/text.css.js +1 -1
  4. package/dist/content/text/text.css.js.map +1 -1
  5. package/dist/content/text/text.d.ts +1 -1
  6. package/dist/content/text/text.d.ts.map +1 -1
  7. package/dist/core/overlay.cjs.map +1 -1
  8. package/dist/core/overlay.d.ts +2 -2
  9. package/dist/core/overlay.d.ts.map +1 -1
  10. package/dist/core/overlay.js.map +1 -1
  11. package/dist/core/positioner.cjs +1 -1
  12. package/dist/core/positioner.cjs.map +1 -1
  13. package/dist/core/positioner.d.ts +6 -1
  14. package/dist/core/positioner.d.ts.map +1 -1
  15. package/dist/core/positioner.js +11 -11
  16. package/dist/core/positioner.js.map +1 -1
  17. package/dist/custom-elements.json +5635 -5387
  18. package/dist/frameworks/elements.d.ts +86 -0
  19. package/dist/frameworks/react.d.ts +18 -0
  20. package/dist/frameworks/vue.d.ts +16 -0
  21. package/dist/inputs/button/button.css.cjs +1 -1
  22. package/dist/inputs/button/button.css.cjs.map +1 -1
  23. package/dist/inputs/button/button.css.js +1 -1
  24. package/dist/inputs/button/button.css.js.map +1 -1
  25. package/dist/menu.cjs +1 -1
  26. package/dist/menu.cjs.map +1 -1
  27. package/dist/menu.js +2 -2
  28. package/dist/menu.js.map +1 -1
  29. package/dist/navigation-menu.cjs +11 -0
  30. package/dist/navigation-menu.cjs.map +1 -0
  31. package/dist/navigation-menu.js +139 -0
  32. package/dist/navigation-menu.js.map +1 -0
  33. package/dist/overlay/index.d.ts +2 -0
  34. package/dist/overlay/index.d.ts.map +1 -1
  35. package/dist/overlay/navigation-menu/navigation-menu-item.css.cjs +2 -0
  36. package/dist/overlay/navigation-menu/navigation-menu-item.css.cjs.map +1 -0
  37. package/dist/overlay/navigation-menu/navigation-menu-item.css.js +6 -0
  38. package/dist/overlay/navigation-menu/navigation-menu-item.css.js.map +1 -0
  39. package/dist/overlay/navigation-menu/navigation-menu-panel.css.cjs +2 -0
  40. package/dist/overlay/navigation-menu/navigation-menu-panel.css.cjs.map +1 -0
  41. package/dist/overlay/navigation-menu/navigation-menu-panel.css.js +6 -0
  42. package/dist/overlay/navigation-menu/navigation-menu-panel.css.js.map +1 -0
  43. package/dist/overlay/navigation-menu/navigation-menu.css.cjs +2 -0
  44. package/dist/overlay/navigation-menu/navigation-menu.css.cjs.map +1 -0
  45. package/dist/overlay/navigation-menu/navigation-menu.css.js +6 -0
  46. package/dist/overlay/navigation-menu/navigation-menu.css.js.map +1 -0
  47. package/dist/overlay/navigation-menu/navigation-menu.d.ts +75 -0
  48. package/dist/overlay/navigation-menu/navigation-menu.d.ts.map +1 -0
  49. package/dist/refine.cjs +15 -6
  50. package/dist/refine.cjs.map +1 -1
  51. package/dist/refine.iife.js +15 -6
  52. package/dist/refine.iife.js.map +1 -1
  53. package/dist/refine.js +15 -6
  54. package/dist/refine.js.map +1 -1
  55. package/dist/text.cjs.map +1 -1
  56. package/dist/text.js.map +1 -1
  57. package/package.json +29 -2
package/dist/menu.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"menu.js","names":[],"sources":["../src/overlay/menu/menu.ts"],"sourcesContent":["import type { Placement } from '@vielzeug/orbit';\n\nimport {\n createStableId,\n define,\n html,\n prop,\n bind,\n getHost,\n onCleanup,\n onMounted,\n useEmit,\n useSlots,\n watchEffect,\n} from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { watch as rippleWatch } from '@vielzeug/ripple/watch';\n\nimport type { ComponentSize } from '../../types';\n\nimport {\n lifecycleSignal,\n createDropdownPositioner,\n createInteraction,\n createListControl,\n createOutsidePointerDismissal,\n restoreTriggerFocus,\n type DropdownCloseReason,\n type OverlayOpenChangeDetail,\n type OverlayOpenReason,\n} from '../../core';\nimport { disablableBundle, MENU_SIZE_PRESET, sizableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, sizeVariantMixin } from '../../styles';\nimport menuItemStyles from './menu-item.css?inline';\nimport menuSeparatorStyles from './menu-separator.css?inline';\nimport componentStyles from './menu.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\nexport interface MenuSelectDetail {\n value: string;\n checked?: boolean;\n}\n\nexport type OreMenuItemType = 'checkbox' | 'radio';\n\nexport type OreMenuEvents = {\n 'open-change': OverlayOpenChangeDetail;\n select: MenuSelectDetail;\n};\n\nexport type OreMenuItemProps = {\n checked?: boolean;\n disabled?: boolean;\n type?: OreMenuItemType;\n value?: string;\n};\n\nexport type OreMenuProps = {\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n disabled?: boolean;\n /** Controlled open state. */\n open?: boolean;\n placement?: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end';\n size?: ComponentSize;\n};\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Menu Item Component ─────────────────────────────────────────────────────────────\n\n/**\n * A selectable action item used inside `<ore-menu>`.\n *\n * @element ore-menu-item\n *\n * @attr {boolean} checked - Checked state for `checkbox` and `radio` item types\n * @attr {boolean} disabled - Disables selection and pointer interaction\n * @attr {'checkbox'|'radio'} type - Optional checkable menu item mode\n * @attr {string} value - Value emitted by parent menu on selection\n *\n * @slot - Item label/content\n * @slot icon - Optional leading icon content\n *\n * @cssprop --menu-item-hover-bg - Background on hover\n * @cssprop --menu-item-focus-color - Text color when keyboard-focused\n * @cssprop --menu-item-focus-bg - Background when keyboard-focused\n * @cssprop --menu-item-selection-bg - Background for checkbox/radio items (unselected)\n * @cssprop --menu-item-checked-color - Text color when checked\n * @cssprop --menu-item-checked-bg - Background when checked\n *\n * @part item - Root item container element.\n * @part item-label - Label text container.\n * @part icon-slot - Leading icon slot container.\n *\n * @example\n * ```html\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\" disabled>Delete</ore-menu-item>\n * <ore-menu-item type=\"checkbox\" value=\"wrap\" checked>Word wrap</ore-menu-item>\n * <ore-menu-item type=\"radio\" value=\"left\">Align left</ore-menu-item>\n * ```\n */\nexport const MENU_ITEM_TAG = 'ore-menu-item' as const;\ndefine<OreMenuItemProps>(MENU_ITEM_TAG, {\n props: {\n checked: prop.bool(false),\n disabled: prop.bool(false),\n type: prop.string<OreMenuItemType>(),\n value: prop.string(),\n },\n setup(props) {\n const isCheckable = () => props.type.value === 'checkbox' || props.type.value === 'radio';\n const isChecked = () => isCheckable() && props.checked.value;\n const itemRole = () => {\n if (props.type.value === 'checkbox') return 'menuitemcheckbox';\n\n if (props.type.value === 'radio') return 'menuitemradio';\n\n return 'menuitem';\n };\n const itemClass = () => {\n const type = props.type.value;\n\n return [\n 'item',\n type === 'checkbox' ? 'is-checkbox' : '',\n type === 'radio' ? 'is-radio' : '',\n isChecked() ? 'is-checked' : '',\n ]\n .filter(Boolean)\n .join(' ');\n };\n\n return isCheckable()\n ? html`\n <div\n class=\"${itemClass}\"\n tabindex=\"-1\"\n role=\"${itemRole}\"\n aria-checked=\"${() => String(isChecked())}\"\n aria-disabled=\"${props.disabled}\">\n <span class=\"item-check\" aria-hidden=\"true\"></span>\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `\n : html`\n <div class=\"item\" tabindex=\"-1\" role=\"menuitem\" aria-disabled=\"${props.disabled}\">\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `;\n },\n styles: [colorThemeMixin, menuItemStyles],\n});\n\n// ── Menu Separator ─────────────────────────────────────────────────────────────\n\n/**\n * Visual separator used to group menu items inside `<ore-menu>`.\n *\n * @element ore-menu-separator\n *\n * @example\n * ```html\n * <ore-menu-item value=\"cut\">Cut</ore-menu-item>\n * <ore-menu-separator></ore-menu-separator>\n * <ore-menu-item value=\"paste\">Paste</ore-menu-item>\n * ```\n */\nexport const SEPARATOR_TAG = 'ore-menu-separator' as const;\ndefine(SEPARATOR_TAG, {\n setup() {\n return html``;\n },\n styles: [menuSeparatorStyles],\n});\n\n// ── Menu Component ─────────────────────────────────────────────────────────────\n\nconst isCheckableItemType = (value: string | null): value is OreMenuItemType =>\n value === 'checkbox' || value === 'radio';\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\n/**\n * Action dropdown menu triggered by a slotted trigger element.\n *\n * @element ore-menu\n * @element ore-menu-item - Clickable menu option (place in default slot)\n * @element ore-menu-separator - Visual divider between menu groups\n *\n * @attr {boolean} disabled - Disables opening and keyboard interaction\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} placement - Panel placement: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end' (default: 'bottom-start')\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n *\n * @fires open-change - Fired when the menu state changes. detail: { open, reason }\n * @fires select - Fired when an item is selected. detail: { value: string, checked?: boolean }\n *\n * @slot trigger - Trigger element that toggles menu visibility\n * @slot - Menu content (`<ore-menu-item>` and `<ore-menu-separator>`)\n *\n * @part panel - Floating menu panel container\n *\n * @cssprop --menu-panel-bg - Background of the floating panel\n * @cssprop --menu-panel-border-color - Border color of the floating panel\n * @cssprop --menu-panel-shadow - Box shadow of the floating panel\n * @cssprop --menu-panel-blur - Backdrop blur amount for the floating panel\n * @cssprop --menu-panel-min-width - Minimum width of the floating panel\n * @cssprop --menu-panel-max-height - Maximum height of the floating panel before it scrolls\n * @cssprop --menu-panel-radius - Border radius of the floating panel\n *\n * @example\n * ```html\n * <ore-menu>\n * <button slot=\"trigger\">Actions</button>\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\">Delete</ore-menu-item>\n * </ore-menu>\n * ```\n */\nexport const MENU_TAG = 'ore-menu' as const;\ndefine<OreMenuProps>(MENU_TAG, {\n props: {\n ...sizableBundle,\n ...disablableBundle,\n 'default-open': prop.bool(false),\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(\n ['bottom', 'bottom-start', 'bottom-end', 'top', 'top-start', 'top-end'] as const,\n 'bottom-start',\n ),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreMenuEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const menuId = createStableId('menu');\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const abortSignal = lifecycleSignal(onCleanup);\n let triggerEl: HTMLElement | null = null;\n let panelEl: HTMLElement | null = null;\n let cleanupTrigger: (() => void) | null = null;\n\n // ── Helpers ───────────────────────────────────────────────────────────────\n function getItems(): HTMLElement[] {\n return Array.from(el.querySelectorAll<HTMLElement>('ore-menu-item:not([disabled])'));\n }\n\n function getItemFocusable(item: HTMLElement | null | undefined): HTMLElement | null {\n if (!item) return null;\n\n return item.shadowRoot?.querySelector<HTMLElement>('[role^=\"menuitem\"]') ?? item;\n }\n\n function getFocusedItemIndex(): number {\n const items = getItems();\n\n return items.findIndex((item) => {\n const focusable = getItemFocusable(item);\n\n return item === document.activeElement || focusable === document.activeElement;\n });\n }\n\n const isOpenSignal = signal(false);\n let stopPositioning: (() => void) | null = null;\n const positioner = createDropdownPositioner({\n getFloating: () => panelEl,\n getPlacement: () => (props.placement.value ?? 'bottom-start') as Placement,\n getReference: () => triggerEl,\n matchWidth: false,\n offsetPx: 4,\n padding: 6,\n });\n const list = createListControl<HTMLElement>({\n disabled: computed(() => !isOpenSignal.value),\n getItems: getItems,\n isItemDisabled: (item) => item.hasAttribute('disabled'),\n onNavigate: (_action, index) => {\n const nextItem = getItems()[index];\n\n getItemFocusable(nextItem)?.focus();\n },\n signal: abortSignal,\n });\n\n const close = (reason: DropdownCloseReason = 'programmatic', shouldRestoreFocus = true): void => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n\n if (shouldRestoreFocus) restoreTriggerFocus(() => triggerEl);\n\n emit('open-change', { open: false, reason });\n };\n\n const open = (reason: OverlayOpenReason = 'programmatic'): void => {\n if (isDisabled.value || isOpenSignal.value) return;\n\n isOpenSignal.value = true;\n positioner.update();\n stopPositioning = positioner.startAutoUpdate?.() ?? null;\n emit('open-change', { open: true, reason });\n };\n\n const toggle = (): void => {\n if (isOpenSignal.value) close('trigger');\n else open('click');\n };\n\n createOutsidePointerDismissal({\n getTargets: () => [el, panelEl],\n isActive: () => isOpenSignal.value,\n onDismiss: () => close('outsideClick'),\n signal: abortSignal,\n });\n\n let initialized = false;\n\n rippleWatch(\n props.open,\n (value) => {\n if (value === undefined) {\n if (!initialized) {\n if (props['default-open'].value) open('programmatic');\n } else {\n close('programmatic');\n }\n } else if (value) {\n open('programmatic');\n } else {\n close('programmatic');\n }\n\n initialized = true;\n },\n { immediate: true },\n );\n abortSignal.addEventListener(\n 'abort',\n () => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n },\n { once: true },\n );\n\n const activateItem = (item: HTMLElement): void => {\n const type = item.getAttribute('type');\n const isCheckable = isCheckableItemType(type);\n\n if (type === 'checkbox') {\n item.toggleAttribute('checked', !item.hasAttribute('checked'));\n } else if (type === 'radio') {\n for (const radio of el.querySelectorAll<HTMLElement>('ore-menu-item[type=\"radio\"]')) {\n radio.toggleAttribute('checked', radio === item);\n }\n }\n\n const value = item.getAttribute('value') ?? '';\n const checked = isCheckable ? item.hasAttribute('checked') : undefined;\n\n emit('select', { checked, value });\n\n if (!isCheckable) {\n close('programmatic');\n }\n };\n\n const openFromKeyboardPress = createInteraction({\n keys: ['Enter', ' ', 'ArrowDown'],\n onPress: () => {\n open('keyboard');\n requestAnimationFrame(() => list.set(0));\n },\n });\n\n const activateFocusedFromKeyboardPress = createInteraction({\n onPress: () => {\n const focused = list.getActiveItem();\n\n if (focused) activateItem(focused);\n },\n });\n\n // ── Keyboard Navigation ───────────────────────────────────────────────────\n function handleMenuKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n const open = isOpenSignal.value;\n\n // When closed: open on Enter / Space / ArrowDown\n if (!open) {\n openFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n const currentFocusedIndex = getFocusedItemIndex();\n\n if (currentFocusedIndex >= 0) list.set(currentFocusedIndex);\n\n if (e.key === 'Escape') {\n e.preventDefault();\n close('escape');\n\n return;\n }\n\n if (list.handleKeydown(e)) return;\n\n // When open: navigate and activate\n if (e.key === ' ' || e.key === 'Enter') {\n activateFocusedFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n if (e.key === 'Tab') {\n close('programmatic');\n }\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n bind({\n on: {\n click: (e: MouseEvent) => {\n const path = e.composedPath();\n\n if (!isOpenSignal.value) return;\n\n const itemFromPath = path.find(\n (node): node is HTMLElement => node instanceof HTMLElement && node.tagName === 'ORE-MENU-ITEM',\n );\n const item = itemFromPath ?? (e.target as HTMLElement | null)?.closest<HTMLElement>('ore-menu-item') ?? null;\n\n if (!item || item.hasAttribute('disabled')) return;\n\n activateItem(item);\n },\n },\n });\n\n watch(() => {\n const open = isOpenSignal.value;\n\n if (!panelEl) return;\n\n panelEl.toggleAttribute('data-open', open);\n });\n\n function resolveTrigger() {\n cleanupTrigger?.();\n cleanupTrigger = null;\n\n const assigned = slots.elements('trigger').value;\n\n triggerEl = (assigned?.[0] as HTMLElement | undefined) ?? null;\n\n if (!triggerEl) return;\n\n const cleanups: Array<() => void> = [];\n const removeAria = bind(\n {\n aria: {\n controls: () => menuId,\n disabled: () => isDisabled.value,\n expanded: () => String(isOpenSignal.value),\n haspopup: 'menu',\n },\n },\n { target: triggerEl },\n );\n\n const onTriggerClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled.value) return;\n\n toggle();\n };\n const onTriggerKeydown = (event: KeyboardEvent) => {\n handleMenuKeydown(event);\n };\n\n triggerEl.addEventListener('click', onTriggerClick);\n triggerEl.addEventListener('keydown', onTriggerKeydown);\n cleanups.push(() => triggerEl?.removeEventListener('click', onTriggerClick));\n cleanups.push(() => triggerEl?.removeEventListener('keydown', onTriggerKeydown));\n\n cleanupTrigger = () => {\n removeAria();\n\n for (const cleanup of cleanups) cleanup();\n };\n }\n\n rippleWatch(slots.elements('trigger'), resolveTrigger, { immediate: true });\n\n onMounted(() => {\n return () => {\n cleanupTrigger?.();\n cleanupTrigger = null;\n };\n });\n\n return html`\n <slot name=\"trigger\"></slot>\n <div\n class=\"menu-panel\"\n part=\"panel\"\n id=\"${menuId}\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n @keydown=\"${handleMenuKeydown}\"\n ref=\"${(el: HTMLElement | null) => {\n panelEl = el;\n panelEl?.toggleAttribute('data-open', isOpenSignal.value);\n }}\">\n <slot></slot>\n </div>\n `;\n },\n styles: [componentStyles, sizeVariantMixin(MENU_SIZE_PRESET), forcedColorsMixin],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"menu.js","names":[],"sources":["../src/overlay/menu/menu.ts"],"sourcesContent":["import type { Placement } from '@vielzeug/orbit';\n\nimport {\n createStableId,\n define,\n html,\n prop,\n bind,\n getHost,\n onCleanup,\n onMounted,\n useEmit,\n useSlots,\n watchEffect,\n} from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { watch as rippleWatch } from '@vielzeug/ripple/watch';\n\nimport type { ComponentSize } from '../../types';\n\nimport {\n lifecycleSignal,\n createDropdownPositioner,\n createInteraction,\n createListControl,\n createOutsidePointerDismissal,\n restoreTriggerFocus,\n type DropdownCloseReason,\n type OverlayOpenChangeDetail,\n type OverlayOpenReason,\n} from '../../core';\nimport { disablableBundle, MENU_SIZE_PRESET, sizableBundle } from '../../shared';\nimport { colorThemeMixin, forcedColorsMixin, sizeVariantMixin } from '../../styles';\nimport menuItemStyles from './menu-item.css?inline';\nimport menuSeparatorStyles from './menu-separator.css?inline';\nimport componentStyles from './menu.css?inline';\n\n// ── Types ─────────────────────────────────────────────────────────────\n\nexport interface MenuSelectDetail {\n value: string;\n checked?: boolean;\n}\n\nexport type OreMenuItemType = 'checkbox' | 'radio';\n\nexport type OreMenuEvents = {\n 'open-change': OverlayOpenChangeDetail;\n select: MenuSelectDetail;\n};\n\nexport type OreMenuItemProps = {\n checked?: boolean;\n disabled?: boolean;\n type?: OreMenuItemType;\n value?: string;\n};\n\nexport type OreMenuProps = {\n /** Initial uncontrolled open state. Ignored when `open` is set. */\n 'default-open'?: boolean;\n disabled?: boolean;\n /** Controlled open state. */\n open?: boolean;\n placement?: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end';\n size?: ComponentSize;\n};\n\n// ── Styles ─────────────────────────────────────────────────────────────\n\n// ── Menu Item Component ─────────────────────────────────────────────────────────────\n\n/**\n * A selectable action item used inside `<ore-menu>`.\n *\n * @element ore-menu-item\n *\n * @attr {boolean} checked - Checked state for `checkbox` and `radio` item types\n * @attr {boolean} disabled - Disables selection and pointer interaction\n * @attr {'checkbox'|'radio'} type - Optional checkable menu item mode\n * @attr {string} value - Value emitted by parent menu on selection\n *\n * @slot - Item label/content\n * @slot icon - Optional leading icon content\n *\n * @cssprop --menu-item-hover-bg - Background on hover\n * @cssprop --menu-item-focus-color - Text color when keyboard-focused\n * @cssprop --menu-item-focus-bg - Background when keyboard-focused\n * @cssprop --menu-item-selection-bg - Background for checkbox/radio items (unselected)\n * @cssprop --menu-item-checked-color - Text color when checked\n * @cssprop --menu-item-checked-bg - Background when checked\n *\n * @part item - Root item container element.\n * @part item-label - Label text container.\n * @part icon-slot - Leading icon slot container.\n *\n * @example\n * ```html\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\" disabled>Delete</ore-menu-item>\n * <ore-menu-item type=\"checkbox\" value=\"wrap\" checked>Word wrap</ore-menu-item>\n * <ore-menu-item type=\"radio\" value=\"left\">Align left</ore-menu-item>\n * ```\n */\nexport const MENU_ITEM_TAG = 'ore-menu-item' as const;\ndefine<OreMenuItemProps>(MENU_ITEM_TAG, {\n props: {\n checked: prop.bool(false),\n disabled: prop.bool(false),\n type: prop.string<OreMenuItemType>(),\n value: prop.string(),\n },\n setup(props) {\n const isCheckable = () => props.type.value === 'checkbox' || props.type.value === 'radio';\n const isChecked = () => isCheckable() && props.checked.value;\n const itemRole = () => {\n if (props.type.value === 'checkbox') return 'menuitemcheckbox';\n\n if (props.type.value === 'radio') return 'menuitemradio';\n\n return 'menuitem';\n };\n const itemClass = () => {\n const type = props.type.value;\n\n return [\n 'item',\n type === 'checkbox' ? 'is-checkbox' : '',\n type === 'radio' ? 'is-radio' : '',\n isChecked() ? 'is-checked' : '',\n ]\n .filter(Boolean)\n .join(' ');\n };\n\n return isCheckable()\n ? html`\n <div\n class=\"${itemClass}\"\n tabindex=\"-1\"\n role=\"${itemRole}\"\n aria-checked=\"${() => String(isChecked())}\"\n aria-disabled=\"${props.disabled}\">\n <span class=\"item-check\" aria-hidden=\"true\"></span>\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `\n : html`\n <div class=\"item\" tabindex=\"-1\" role=\"menuitem\" aria-disabled=\"${props.disabled}\">\n <span class=\"icon-slot\"><slot name=\"icon\"></slot></span>\n <span class=\"item-label\"><slot></slot></span>\n </div>\n `;\n },\n styles: [colorThemeMixin, menuItemStyles],\n});\n\n// ── Menu Separator ─────────────────────────────────────────────────────────────\n\n/**\n * Visual separator used to group menu items inside `<ore-menu>`.\n *\n * @element ore-menu-separator\n *\n * @example\n * ```html\n * <ore-menu-item value=\"cut\">Cut</ore-menu-item>\n * <ore-menu-separator></ore-menu-separator>\n * <ore-menu-item value=\"paste\">Paste</ore-menu-item>\n * ```\n */\nexport const SEPARATOR_TAG = 'ore-menu-separator' as const;\ndefine(SEPARATOR_TAG, {\n setup() {\n return html``;\n },\n styles: [menuSeparatorStyles],\n});\n\n// ── Menu Component ─────────────────────────────────────────────────────────────\n\nconst isCheckableItemType = (value: string | null): value is OreMenuItemType =>\n value === 'checkbox' || value === 'radio';\n\nconst parseOptionalBool = (value: string | null): boolean | undefined =>\n value == null ? undefined : value === '' || value === 'true';\n\n/**\n * Action dropdown menu triggered by a slotted trigger element.\n *\n * @element ore-menu\n * @element ore-menu-item - Clickable menu option (place in default slot)\n * @element ore-menu-separator - Visual divider between menu groups\n *\n * @attr {boolean} disabled - Disables opening and keyboard interaction\n * @attr {boolean} open - Controlled open state\n * @attr {boolean} default-open - Initial uncontrolled open state\n * @attr {string} placement - Panel placement: 'bottom' | 'bottom-start' | 'bottom-end' | 'top' | 'top-start' | 'top-end' (default: 'bottom-start')\n * @attr {string} size - Size: 'sm' | 'md' | 'lg'\n *\n * @fires open-change - Fired when the menu state changes. detail: { open, reason }\n * @fires select - Fired when an item is selected. detail: { value: string, checked?: boolean }\n *\n * @slot trigger - Trigger element that toggles menu visibility\n * @slot - Menu content (`<ore-menu-item>` and `<ore-menu-separator>`)\n *\n * @part panel - Floating menu panel container\n *\n * @cssprop --menu-panel-bg - Background of the floating panel\n * @cssprop --menu-panel-border-color - Border color of the floating panel\n * @cssprop --menu-panel-shadow - Box shadow of the floating panel\n * @cssprop --menu-panel-blur - Backdrop blur amount for the floating panel\n * @cssprop --menu-panel-min-width - Minimum width of the floating panel\n * @cssprop --menu-panel-max-height - Maximum height of the floating panel before it scrolls\n * @cssprop --menu-panel-radius - Border radius of the floating panel\n *\n * @example\n * ```html\n * <ore-menu>\n * <button slot=\"trigger\">Actions</button>\n * <ore-menu-item value=\"edit\">Edit</ore-menu-item>\n * <ore-menu-item value=\"delete\">Delete</ore-menu-item>\n * </ore-menu>\n * ```\n */\nexport const MENU_TAG = 'ore-menu' as const;\ndefine<OreMenuProps>(MENU_TAG, {\n props: {\n ...sizableBundle,\n ...disablableBundle,\n 'default-open': prop.bool(false),\n open: { default: undefined as boolean | undefined, parse: parseOptionalBool },\n placement: prop.oneOf(\n ['bottom', 'bottom-start', 'bottom-end', 'top', 'top-start', 'top-end'] as const,\n 'bottom-start',\n ),\n },\n setup(props) {\n const el = getHost();\n const emit = useEmit<OreMenuEvents>();\n const slots = useSlots();\n const watch = watchEffect;\n\n const menuId = createStableId('menu');\n const isDisabled = computed(() => Boolean(props.disabled.value));\n const abortSignal = lifecycleSignal(onCleanup);\n let triggerEl: HTMLElement | null = null;\n let panelEl: HTMLElement | null = null;\n let cleanupTrigger: (() => void) | null = null;\n\n // ── Helpers ───────────────────────────────────────────────────────────────\n function getItems(): HTMLElement[] {\n return Array.from(el.querySelectorAll<HTMLElement>('ore-menu-item:not([disabled])'));\n }\n\n function getItemFocusable(item: HTMLElement | null | undefined): HTMLElement | null {\n if (!item) return null;\n\n return item.shadowRoot?.querySelector<HTMLElement>('[role^=\"menuitem\"]') ?? item;\n }\n\n function getFocusedItemIndex(): number {\n const items = getItems();\n\n return items.findIndex((item) => {\n const focusable = getItemFocusable(item);\n\n return item === document.activeElement || focusable === document.activeElement;\n });\n }\n\n const isOpenSignal = signal(false);\n let stopPositioning: (() => void) | null = null;\n const positioner = createDropdownPositioner({\n getFloating: () => panelEl,\n getPlacement: () => (props.placement.value ?? 'bottom-start') as Placement,\n getReference: () => triggerEl,\n matchWidth: false,\n offsetPx: 4,\n padding: 6,\n });\n const list = createListControl<HTMLElement>({\n disabled: computed(() => !isOpenSignal.value),\n getItems: getItems,\n isItemDisabled: (item) => item.hasAttribute('disabled'),\n onNavigate: (_action, index) => {\n const nextItem = getItems()[index];\n\n getItemFocusable(nextItem)?.focus();\n },\n signal: abortSignal,\n });\n\n const close = (reason: DropdownCloseReason = 'programmatic', shouldRestoreFocus = true): void => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n\n if (shouldRestoreFocus) restoreTriggerFocus(() => triggerEl);\n\n emit('open-change', { open: false, reason });\n };\n\n const open = (reason: OverlayOpenReason = 'programmatic'): void => {\n if (isDisabled.value || isOpenSignal.value) return;\n\n isOpenSignal.value = true;\n positioner.update();\n stopPositioning = positioner.startAutoUpdate?.() ?? null;\n emit('open-change', { open: true, reason });\n };\n\n const toggle = (): void => {\n if (isOpenSignal.value) close('trigger');\n else open('click');\n };\n\n createOutsidePointerDismissal({\n getTargets: () => [el, panelEl],\n isActive: () => isOpenSignal.value,\n onDismiss: () => close('outsideClick'),\n signal: abortSignal,\n });\n\n let initialized = false;\n\n rippleWatch(\n props.open,\n (value) => {\n if (value === undefined) {\n if (!initialized) {\n if (props['default-open'].value) open('programmatic');\n } else {\n close('programmatic');\n }\n } else if (value) {\n open('programmatic');\n } else {\n close('programmatic');\n }\n\n initialized = true;\n },\n { immediate: true },\n );\n abortSignal.addEventListener(\n 'abort',\n () => {\n if (!isOpenSignal.value) return;\n\n isOpenSignal.value = false;\n list.reset();\n stopPositioning?.();\n stopPositioning = null;\n },\n { once: true },\n );\n\n const activateItem = (item: HTMLElement): void => {\n const type = item.getAttribute('type');\n const isCheckable = isCheckableItemType(type);\n\n if (type === 'checkbox') {\n item.toggleAttribute('checked', !item.hasAttribute('checked'));\n } else if (type === 'radio') {\n for (const radio of el.querySelectorAll<HTMLElement>('ore-menu-item[type=\"radio\"]')) {\n radio.toggleAttribute('checked', radio === item);\n }\n }\n\n const value = item.getAttribute('value') ?? '';\n const checked = isCheckable ? item.hasAttribute('checked') : undefined;\n\n emit('select', { checked, value });\n\n if (!isCheckable) {\n close('programmatic');\n }\n };\n\n const openFromKeyboardPress = createInteraction({\n keys: ['Enter', ' ', 'ArrowDown'],\n onPress: () => {\n open('keyboard');\n requestAnimationFrame(() => list.set(0));\n },\n });\n\n const activateFocusedFromKeyboardPress = createInteraction({\n onPress: () => {\n const focused = list.getActiveItem();\n\n if (focused) activateItem(focused);\n },\n });\n\n // ── Keyboard Navigation ───────────────────────────────────────────────────\n function handleMenuKeydown(e: KeyboardEvent) {\n if (isDisabled.value) return;\n\n const open = isOpenSignal.value;\n\n // When closed: open on Enter / Space / ArrowDown\n if (!open) {\n openFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n const currentFocusedIndex = getFocusedItemIndex();\n\n if (currentFocusedIndex >= 0) list.set(currentFocusedIndex);\n\n if (e.key === 'Escape') {\n e.preventDefault();\n close('escape');\n\n return;\n }\n\n if (list.handleKeydown(e)) return;\n\n // When open: navigate and activate\n if (e.key === ' ' || e.key === 'Enter') {\n activateFocusedFromKeyboardPress.handleKeydown(e);\n\n return;\n }\n\n if (e.key === 'Tab') {\n close('programmatic');\n }\n }\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n bind({\n on: {\n click: (e: MouseEvent) => {\n const path = e.composedPath();\n\n if (!isOpenSignal.value) return;\n\n const itemFromPath = path.find(\n (node): node is HTMLElement => node instanceof HTMLElement && node.tagName === 'ORE-MENU-ITEM',\n );\n const item = itemFromPath ?? (e.target as HTMLElement | null)?.closest<HTMLElement>('ore-menu-item') ?? null;\n\n if (!item || item.hasAttribute('disabled')) return;\n\n activateItem(item);\n },\n },\n });\n\n watch(() => {\n const open = isOpenSignal.value;\n\n if (!panelEl) return;\n\n panelEl.toggleAttribute('data-open', open);\n });\n\n function resolveTrigger() {\n cleanupTrigger?.();\n cleanupTrigger = null;\n\n const assigned = slots.elements('trigger').value;\n\n triggerEl = (assigned?.[0] as HTMLElement | undefined) ?? null;\n\n if (!triggerEl) return;\n\n const cleanups: Array<() => void> = [];\n const removeAria = bind(\n {\n aria: {\n controls: () => menuId,\n disabled: () => isDisabled.value,\n expanded: () => String(isOpenSignal.value),\n haspopup: 'menu',\n },\n },\n { target: triggerEl },\n );\n\n const onTriggerClick = (event: MouseEvent) => {\n event.stopPropagation();\n\n if (isDisabled.value) return;\n\n toggle();\n };\n const onTriggerKeydown = (event: KeyboardEvent) => {\n handleMenuKeydown(event);\n };\n\n triggerEl.addEventListener('click', onTriggerClick);\n triggerEl.addEventListener('keydown', onTriggerKeydown);\n cleanups.push(() => triggerEl?.removeEventListener('click', onTriggerClick));\n cleanups.push(() => triggerEl?.removeEventListener('keydown', onTriggerKeydown));\n\n cleanupTrigger = () => {\n removeAria();\n\n for (const cleanup of cleanups) cleanup();\n };\n }\n\n rippleWatch(slots.elements('trigger'), resolveTrigger, { immediate: true });\n\n onMounted(() => {\n resolveTrigger();\n\n return () => {\n cleanupTrigger?.();\n cleanupTrigger = null;\n };\n });\n\n return html`\n <slot name=\"trigger\"></slot>\n <div\n class=\"menu-panel\"\n part=\"panel\"\n id=\"${menuId}\"\n role=\"menu\"\n aria-orientation=\"vertical\"\n @keydown=\"${handleMenuKeydown}\"\n ref=\"${(el: HTMLElement | null) => {\n panelEl = el;\n panelEl?.toggleAttribute('data-open', isOpenSignal.value);\n }}\">\n <slot></slot>\n </div>\n `;\n },\n styles: [componentStyles, sizeVariantMixin(MENU_SIZE_PRESET), forcedColorsMixin],\n});\n"],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("./core/ore.cjs"),t=require("./core/overlay.cjs"),n=require("./styles/mixins/accessibility.css.cjs"),r=require("./core/positioner.cjs"),i=require("./shared/prop-bundles.cjs"),a=require("./overlay/navigation-menu/navigation-menu-item.css.cjs"),o=require("./overlay/navigation-menu/navigation-menu-panel.css.cjs"),s=require("./overlay/navigation-menu/navigation-menu.css.cjs");let c=require("@vielzeug/ore"),l=require("@vielzeug/ripple"),u=require("@vielzeug/ripple/watch");var d=e=>e??void 0,f=`ore-navigation-menu-item`;(0,c.define)(f,{props:{disabled:c.prop.bool(!1),value:c.prop.string(``)},setup(e){return c.html`
2
+ <button class="trigger" type="button" ?disabled=${e.disabled}><slot></slot></button>
3
+ `},styles:[a.default]});var p=`ore-navigation-menu-panel`;(0,c.define)(p,{props:{for:c.prop.string()},setup(){let e=(0,c.useSlots)();return c.html`
4
+ <div class="content" part="content"><slot></slot></div>
5
+ <div class="footer" part="footer" ?hidden=${()=>!e.has(`footer`).value}><slot name="footer"></slot></div>
6
+ `},styles:[o.default]});var m=`ore-navigation-menu`;(0,c.define)(m,{props:{...i.disablableBundle,"close-on-select":c.prop.bool(!0),columns:c.prop.number(),"default-open":c.prop.string(),label:c.prop.string(`Navigation menu`),open:{default:void 0,parse:d},placement:c.prop.oneOf([`bottom-end`,`bottom-start`],`bottom-start`)},setup(n){let i=(0,c.getHost)(),a=(0,c.useEmit)(),o=e.lifecycleSignal(c.onCleanup),s=(0,c.createStableId)(`navigation-menu`),d=(0,l.computed)(()=>n.disabled.value),m=(0,l.signal)(null),h=null,g=null,_=null,v=()=>Array.from(i.querySelectorAll(`${f}:not([disabled])`)),y=e=>e.getAttribute(`value`)??``,b=()=>Array.from(i.querySelectorAll(p)),x=e=>b().find(t=>t.getAttribute(`for`)===e)??null,S=()=>n.open.value!==void 0,C=e=>e.id||=(0,c.createStableId)(`navigation-menu-panel`),w=r.createDropdownPositioner({getFloating:()=>g,getPlacement:()=>n.placement.value??`bottom-start`,getReference:()=>h?.shadowRoot?.querySelector(`.trigger`)??h,matchWidth:!1,offsetPx:8,useClippingAncestor:!1}),T=()=>{let e=n.columns.value;return e===void 0?void 0:Math.max(1,Math.trunc(e))},E=e=>{if(e.hidden=!1,e.dataset.open=``,`showPopover`in e)try{e.matches(`:popover-open`)||e.showPopover()}catch{}},D=e=>{if(delete e.dataset.open,`hidePopover`in e)try{e.matches(`:popover-open`)&&e.hidePopover()}catch{}e.hidden=!0},O=e=>{let t=e===null?null:x(e);_?.(),_=null,m.value=e,h=e?v().find(t=>y(t)===e)??null:null,g=t;for(let t of v()){let n=y(t)===e,r=t.shadowRoot?.querySelector(`.trigger`);t.setAttribute(`aria-expanded`,String(n)),r?.setAttribute(`aria-expanded`,String(n))}for(let e of b())e!==t&&D(e);if(t){let e=T();e!==void 0&&t.style.setProperty(`--navigation-menu-panel-columns`,String(e)),t.setAttribute(`aria-labelledby`,h?.id??``),E(t),w.update(),_=w.startAutoUpdate?.()??null}},k=(e,t)=>{d.value||m.value===e||e!==null&&!x(e)||(S()||O(e),a(`open-change`,{open:e!==null,reason:t,value:e}))};return(0,c.onCleanup)(()=>{_?.();for(let e of b())D(e)}),t.createOutsidePointerDismissal({getTargets:()=>[i,g],isActive:()=>m.value!==null,onDismiss:()=>k(null,`outsideClick`),signal:o}),(0,c.onMounted)(()=>{let e=new Set;for(let e of b())e.setAttribute(`popover`,`manual`),e.setAttribute(`role`,`region`),C(e),D(e),e.addEventListener(`click`,t=>{let r=t.target instanceof Element?t.target.closest(`a[href]`):null;if(!r||!e.contains(r))return;let i=m.value;i&&(a(`select`,{href:r.href,value:i}),n[`close-on-select`].value&&!r.closest(`[data-navigation-menu-keep-open]`)&&k(null,`select`))},{signal:o});document.addEventListener(`keydown`,e=>{e.key===`Escape`&&m.value!==null&&(e.preventDefault(),k(null,`escape`),h?.shadowRoot?.querySelector(`.trigger`)?.focus())},{signal:o});for(let t of v()){let n=y(t),r=x(n);if(!n||e.has(n)||!r)continue;e.add(n),t.id||=(0,c.createStableId)(`navigation-menu-trigger`);let i=t.shadowRoot?.querySelector(`.trigger`);i&&(i.setAttribute(`aria-controls`,C(r)),i.setAttribute(`aria-haspopup`,`true`),i.setAttribute(`aria-expanded`,`false`),t.setAttribute(`aria-expanded`,`false`),i.addEventListener(`click`,()=>k(m.value===n?null:n,`click`),{signal:o}),i.addEventListener(`keydown`,e=>{let r=v(),i=r.indexOf(t);e.key===`ArrowLeft`||e.key===`ArrowRight`||e.key===`Home`||e.key===`End`?(e.preventDefault(),(e.key===`Home`?r[0]:e.key===`End`?r.at(-1):r[(i+(e.key===`ArrowRight`?1:r.length-1))%r.length])?.shadowRoot?.querySelector(`.trigger`)?.focus()):e.key===`ArrowDown`&&(e.preventDefault(),k(n,`keyboard`),requestAnimationFrame(()=>g?.querySelector(`a, button, input, [tabindex]:not([tabindex="-1"])`)?.focus()))},{signal:o}))}n.open.value===void 0?n[`default-open`].value&&O(n[`default-open`].value):O(n.open.value)}),(0,u.watch)(n.open,e=>{e!==void 0&&O(e)}),(0,u.watch)(n.disabled,e=>{e&&O(null)}),c.html`
7
+ <nav class="triggers" aria-label="${n.label}" id="${s}"><slot></slot></nav>
8
+ <slot name="panel"></slot>
9
+ <slot name="footer"></slot>
10
+ `},styles:[n.reducedMotionMixin,s.default]}),exports.NAVIGATION_MENU_ITEM_TAG=f,exports.NAVIGATION_MENU_PANEL_TAG=p,exports.NAVIGATION_MENU_TAG=m;
11
+ //# sourceMappingURL=navigation-menu.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-menu.cjs","names":[],"sources":["../src/overlay/navigation-menu/navigation-menu.ts"],"sourcesContent":["import { createStableId, define, getHost, html, onCleanup, onMounted, prop, useEmit, useSlots } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { watch } from '@vielzeug/ripple/watch';\n\nimport type { OverlayOpenChangeDetail } from '../../core';\n\nimport { createDropdownPositioner, createOutsidePointerDismissal, lifecycleSignal } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { reducedMotionMixin } from '../../styles';\nimport itemStyles from './navigation-menu-item.css?inline';\nimport panelStyles from './navigation-menu-panel.css?inline';\nimport hostStyles from './navigation-menu.css?inline';\n\nexport type OreNavigationMenuEvents = {\n 'open-change': OverlayOpenChangeDetail & { value: string | null };\n select: NavigationMenuSelectDetail;\n};\n\nexport type NavigationMenuSelectDetail = {\n href: string;\n value: string;\n};\n\nexport type OreNavigationMenuItemProps = {\n disabled?: boolean;\n value: string;\n};\n\nexport type OreNavigationMenuProps = {\n /** Close after activating a panel link. */\n 'close-on-select'?: boolean;\n columns?: number;\n 'default-open'?: string;\n disabled?: boolean;\n /** Accessible label for the trigger region. */\n label?: string;\n open?: string;\n placement?: 'bottom-end' | 'bottom-start';\n};\n\nconst parseOptionalString = (value: string | null): string | undefined => value ?? undefined;\n\n/**\n * A trigger for an associated navigation menu panel.\n *\n * @element ore-navigation-menu-item\n *\n * @attr {boolean} disabled - Disables panel activation\n * @attr {string} value - Unique value matched by a panel's `for` attribute\n *\n * @slot - Trigger label and optional icon\n */\nexport const NAVIGATION_MENU_ITEM_TAG = 'ore-navigation-menu-item' as const;\ndefine<OreNavigationMenuItemProps>(NAVIGATION_MENU_ITEM_TAG, {\n props: { disabled: prop.bool(false), value: prop.string('') },\n setup(props) {\n return html`\n <button class=\"trigger\" type=\"button\" ?disabled=${props.disabled}><slot></slot></button>\n `;\n },\n styles: [itemStyles],\n});\n\n/**\n * An anchored navigation menu panel associated with an item.\n *\n * @element ore-navigation-menu-panel\n *\n * @attr {string} for - Value of the associated navigation menu item\n *\n * @slot - Panel content\n * @slot footer - Optional panel footer\n *\n * @part content - Grid container for panel content\n * @part footer - Container for optional footer content\n */\nexport const NAVIGATION_MENU_PANEL_TAG = 'ore-navigation-menu-panel' as const;\ndefine<{ for?: string }>(NAVIGATION_MENU_PANEL_TAG, {\n props: { for: prop.string() },\n setup() {\n const slots = useSlots();\n\n return html`\n <div class=\"content\" part=\"content\"><slot></slot></div>\n <div class=\"footer\" part=\"footer\" ?hidden=${() => !slots.has('footer').value}><slot name=\"footer\"></slot></div>\n `;\n },\n styles: [panelStyles],\n});\n\n/**\n * A horizontal set of triggers with anchored, non-modal navigation panels.\n *\n * @element ore-navigation-menu\n *\n * @attr {string} open - Controlled active trigger value\n * @attr {string} default-open - Initial uncontrolled active trigger value\n * @attr {boolean} close-on-select - Closes after activating a panel link\n * @attr {number} columns - Number of panel content columns\n * @attr {boolean} disabled - Disables all triggers\n * @attr {string} label - Accessible navigation region label\n * @attr {'bottom-start'|'bottom-end'} placement - Panel placement relative to its trigger\n *\n * @slot - Navigation menu items and panels\n *\n * @event open-change - Requested active panel change\n * @event select - A panel link was activated\n *\n * @cssprop --navigation-menu-panel-width - Maximum panel width\n * @cssprop --navigation-menu-panel-columns - Fallback number of panel content columns\n * @cssprop --navigation-menu-backdrop-blur - Frosted panel backdrop blur\n */\nexport const NAVIGATION_MENU_TAG = 'ore-navigation-menu' as const;\ndefine<OreNavigationMenuProps>(NAVIGATION_MENU_TAG, {\n props: {\n ...disablableBundle,\n 'close-on-select': prop.bool(true),\n columns: prop.number(),\n 'default-open': prop.string(),\n label: prop.string('Navigation menu'),\n open: { default: undefined as string | undefined, parse: parseOptionalString },\n placement: prop.oneOf(['bottom-end', 'bottom-start'] as const, 'bottom-start'),\n },\n setup(props) {\n const host = getHost();\n const emit = useEmit<OreNavigationMenuEvents>();\n const abortSignal = lifecycleSignal(onCleanup);\n const panelId = createStableId('navigation-menu');\n const isDisabled = computed(() => props.disabled.value);\n const activeValue = signal<string | null>(null);\n let activeTrigger: HTMLElement | null = null;\n let activePanel: HTMLElement | null = null;\n let stopPositioning: (() => void) | null = null;\n\n const items = () => Array.from(host.querySelectorAll<HTMLElement>(`${NAVIGATION_MENU_ITEM_TAG}:not([disabled])`));\n const valueOf = (item: HTMLElement) => item.getAttribute('value') ?? '';\n const panels = () => Array.from(host.querySelectorAll<HTMLElement>(NAVIGATION_MENU_PANEL_TAG));\n const panelFor = (value: string) => panels().find((panel) => panel.getAttribute('for') === value) ?? null;\n const isControlled = () => props.open.value !== undefined;\n const panelIdFor = (panel: HTMLElement) => (panel.id ||= createStableId('navigation-menu-panel'));\n\n const positioner = createDropdownPositioner({\n getFloating: () => activePanel,\n getPlacement: () => props.placement.value ?? 'bottom-start',\n getReference: () => activeTrigger?.shadowRoot?.querySelector<HTMLElement>('.trigger') ?? activeTrigger,\n matchWidth: false,\n offsetPx: 8,\n useClippingAncestor: false,\n });\n\n const panelColumns = (): number | undefined => {\n const columns = props.columns.value;\n\n return columns === undefined ? undefined : Math.max(1, Math.trunc(columns));\n };\n\n const showPanel = (panel: HTMLElement): void => {\n panel.hidden = false;\n panel.dataset.open = '';\n\n if ('showPopover' in panel) {\n try {\n if (!panel.matches(':popover-open')) panel.showPopover();\n } catch {\n // Sandboxed documents can reject the Popover API; data-open remains the fixed-position fallback.\n }\n }\n };\n\n const hidePanel = (panel: HTMLElement): void => {\n delete panel.dataset.open;\n\n if ('hidePopover' in panel) {\n try {\n if (panel.matches(':popover-open')) panel.hidePopover();\n } catch {\n // The fallback visibility state is still cleared below.\n }\n }\n\n panel.hidden = true;\n };\n\n const applyActive = (value: string | null): void => {\n const nextPanel = value === null ? null : panelFor(value);\n\n stopPositioning?.();\n stopPositioning = null;\n activeValue.value = value;\n activeTrigger = value ? (items().find((item) => valueOf(item) === value) ?? null) : null;\n activePanel = nextPanel;\n\n for (const item of items()) {\n const expanded = valueOf(item) === value;\n const trigger = item.shadowRoot?.querySelector<HTMLElement>('.trigger');\n\n item.setAttribute('aria-expanded', String(expanded));\n trigger?.setAttribute('aria-expanded', String(expanded));\n }\n for (const panel of panels()) {\n if (panel !== nextPanel) hidePanel(panel);\n }\n\n if (nextPanel) {\n const columns = panelColumns();\n\n if (columns !== undefined) nextPanel.style.setProperty('--navigation-menu-panel-columns', String(columns));\n\n nextPanel.setAttribute('aria-labelledby', activeTrigger?.id ?? '');\n showPanel(nextPanel);\n positioner.update();\n stopPositioning = positioner.startAutoUpdate?.() ?? null;\n }\n };\n\n const requestActive = (value: string | null, reason: OverlayOpenChangeDetail['reason']): void => {\n if (isDisabled.value || activeValue.value === value) return;\n\n if (value !== null && !panelFor(value)) return;\n\n if (!isControlled()) applyActive(value);\n\n emit('open-change', { open: value !== null, reason, value });\n };\n\n onCleanup(() => {\n stopPositioning?.();\n\n for (const panel of panels()) hidePanel(panel);\n });\n\n createOutsidePointerDismissal({\n getTargets: () => [host, activePanel],\n isActive: () => activeValue.value !== null,\n onDismiss: () => requestActive(null, 'outsideClick'),\n signal: abortSignal,\n });\n\n onMounted(() => {\n const values = new Set<string>();\n\n for (const panel of panels()) {\n panel.setAttribute('popover', 'manual');\n panel.setAttribute('role', 'region');\n panelIdFor(panel);\n hidePanel(panel);\n\n panel.addEventListener(\n 'click',\n (event) => {\n const link = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>('a[href]') : null;\n\n if (!link || !panel.contains(link)) return;\n\n const value = activeValue.value;\n\n if (!value) return;\n\n emit('select', { href: link.href, value });\n\n if (props['close-on-select'].value && !link.closest('[data-navigation-menu-keep-open]')) {\n requestActive(null, 'select');\n }\n },\n { signal: abortSignal },\n );\n }\n\n document.addEventListener(\n 'keydown',\n (event) => {\n if (event.key !== 'Escape' || activeValue.value === null) return;\n\n event.preventDefault();\n requestActive(null, 'escape');\n activeTrigger?.shadowRoot?.querySelector<HTMLElement>('.trigger')?.focus();\n },\n { signal: abortSignal },\n );\n\n for (const item of items()) {\n const value = valueOf(item);\n const panel = panelFor(value);\n\n if (!value || values.has(value) || !panel) continue;\n\n values.add(value);\n item.id ||= createStableId('navigation-menu-trigger');\n\n const trigger = item.shadowRoot?.querySelector<HTMLButtonElement>('.trigger');\n\n if (!trigger) continue;\n\n trigger.setAttribute('aria-controls', panelIdFor(panel));\n trigger.setAttribute('aria-haspopup', 'true');\n trigger.setAttribute('aria-expanded', 'false');\n item.setAttribute('aria-expanded', 'false');\n trigger.addEventListener('click', () => requestActive(activeValue.value === value ? null : value, 'click'), {\n signal: abortSignal,\n });\n trigger.addEventListener(\n 'keydown',\n (event) => {\n const all = items();\n const index = all.indexOf(item);\n\n if (\n event.key === 'ArrowLeft' ||\n event.key === 'ArrowRight' ||\n event.key === 'Home' ||\n event.key === 'End'\n ) {\n event.preventDefault();\n\n const next =\n event.key === 'Home'\n ? all[0]\n : event.key === 'End'\n ? all.at(-1)\n : all[(index + (event.key === 'ArrowRight' ? 1 : all.length - 1)) % all.length];\n\n next?.shadowRoot?.querySelector<HTMLElement>('.trigger')?.focus();\n } else if (event.key === 'ArrowDown') {\n event.preventDefault();\n requestActive(value, 'keyboard');\n requestAnimationFrame(() =>\n activePanel?.querySelector<HTMLElement>('a, button, input, [tabindex]:not([tabindex=\"-1\"])')?.focus(),\n );\n }\n },\n { signal: abortSignal },\n );\n }\n\n if (props.open.value !== undefined) applyActive(props.open.value);\n else if (props['default-open'].value) applyActive(props['default-open'].value);\n });\n\n watch(props.open, (value) => {\n if (value !== undefined) applyActive(value);\n });\n\n watch(props.disabled, (disabled) => {\n if (disabled) applyActive(null);\n });\n\n return html`\n <nav class=\"triggers\" aria-label=\"${props.label}\" id=\"${panelId}\"><slot></slot></nav>\n <slot name=\"panel\"></slot>\n <slot name=\"footer\"></slot>\n `;\n },\n styles: [reducedMotionMixin, hostStyles],\n});\n"],"mappings":"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"}
@@ -0,0 +1,139 @@
1
+ import { lifecycleSignal as e } from "./core/ore.js";
2
+ import { createOutsidePointerDismissal as t } from "./core/overlay.js";
3
+ import { reducedMotionMixin as n } from "./styles/mixins/accessibility.css.js";
4
+ import { createDropdownPositioner as r } from "./core/positioner.js";
5
+ import { disablableBundle as i } from "./shared/prop-bundles.js";
6
+ import a from "./overlay/navigation-menu/navigation-menu-item.css.js";
7
+ import o from "./overlay/navigation-menu/navigation-menu-panel.css.js";
8
+ import s from "./overlay/navigation-menu/navigation-menu.css.js";
9
+ import { createStableId as c, define as l, getHost as u, html as d, onCleanup as f, onMounted as p, prop as m, useEmit as h, useSlots as g } from "@vielzeug/ore";
10
+ import { computed as _, signal as v } from "@vielzeug/ripple";
11
+ import { watch as y } from "@vielzeug/ripple/watch";
12
+ //#region src/overlay/navigation-menu/navigation-menu.ts
13
+ var b = (e) => e ?? void 0, x = "ore-navigation-menu-item";
14
+ l(x, {
15
+ props: {
16
+ disabled: m.bool(!1),
17
+ value: m.string("")
18
+ },
19
+ setup(e) {
20
+ return d`
21
+ <button class="trigger" type="button" ?disabled=${e.disabled}><slot></slot></button>
22
+ `;
23
+ },
24
+ styles: [a]
25
+ });
26
+ var S = "ore-navigation-menu-panel";
27
+ l(S, {
28
+ props: { for: m.string() },
29
+ setup() {
30
+ let e = g();
31
+ return d`
32
+ <div class="content" part="content"><slot></slot></div>
33
+ <div class="footer" part="footer" ?hidden=${() => !e.has("footer").value}><slot name="footer"></slot></div>
34
+ `;
35
+ },
36
+ styles: [o]
37
+ });
38
+ var C = "ore-navigation-menu";
39
+ l(C, {
40
+ props: {
41
+ ...i,
42
+ "close-on-select": m.bool(!0),
43
+ columns: m.number(),
44
+ "default-open": m.string(),
45
+ label: m.string("Navigation menu"),
46
+ open: {
47
+ default: void 0,
48
+ parse: b
49
+ },
50
+ placement: m.oneOf(["bottom-end", "bottom-start"], "bottom-start")
51
+ },
52
+ setup(n) {
53
+ let i = u(), a = h(), o = e(f), s = c("navigation-menu"), l = _(() => n.disabled.value), m = v(null), g = null, b = null, C = null, w = () => Array.from(i.querySelectorAll(`${x}:not([disabled])`)), T = (e) => e.getAttribute("value") ?? "", E = () => Array.from(i.querySelectorAll(S)), D = (e) => E().find((t) => t.getAttribute("for") === e) ?? null, O = () => n.open.value !== void 0, k = (e) => e.id ||= c("navigation-menu-panel"), A = r({
54
+ getFloating: () => b,
55
+ getPlacement: () => n.placement.value ?? "bottom-start",
56
+ getReference: () => g?.shadowRoot?.querySelector(".trigger") ?? g,
57
+ matchWidth: !1,
58
+ offsetPx: 8,
59
+ useClippingAncestor: !1
60
+ }), j = () => {
61
+ let e = n.columns.value;
62
+ return e === void 0 ? void 0 : Math.max(1, Math.trunc(e));
63
+ }, M = (e) => {
64
+ if (e.hidden = !1, e.dataset.open = "", "showPopover" in e) try {
65
+ e.matches(":popover-open") || e.showPopover();
66
+ } catch {}
67
+ }, N = (e) => {
68
+ if (delete e.dataset.open, "hidePopover" in e) try {
69
+ e.matches(":popover-open") && e.hidePopover();
70
+ } catch {}
71
+ e.hidden = !0;
72
+ }, P = (e) => {
73
+ let t = e === null ? null : D(e);
74
+ C?.(), C = null, m.value = e, g = e ? w().find((t) => T(t) === e) ?? null : null, b = t;
75
+ for (let t of w()) {
76
+ let n = T(t) === e, r = t.shadowRoot?.querySelector(".trigger");
77
+ t.setAttribute("aria-expanded", String(n)), r?.setAttribute("aria-expanded", String(n));
78
+ }
79
+ for (let e of E()) e !== t && N(e);
80
+ if (t) {
81
+ let e = j();
82
+ e !== void 0 && t.style.setProperty("--navigation-menu-panel-columns", String(e)), t.setAttribute("aria-labelledby", g?.id ?? ""), M(t), A.update(), C = A.startAutoUpdate?.() ?? null;
83
+ }
84
+ }, F = (e, t) => {
85
+ l.value || m.value === e || e !== null && !D(e) || (O() || P(e), a("open-change", {
86
+ open: e !== null,
87
+ reason: t,
88
+ value: e
89
+ }));
90
+ };
91
+ return f(() => {
92
+ C?.();
93
+ for (let e of E()) N(e);
94
+ }), t({
95
+ getTargets: () => [i, b],
96
+ isActive: () => m.value !== null,
97
+ onDismiss: () => F(null, "outsideClick"),
98
+ signal: o
99
+ }), p(() => {
100
+ let e = /* @__PURE__ */ new Set();
101
+ for (let e of E()) e.setAttribute("popover", "manual"), e.setAttribute("role", "region"), k(e), N(e), e.addEventListener("click", (t) => {
102
+ let r = t.target instanceof Element ? t.target.closest("a[href]") : null;
103
+ if (!r || !e.contains(r)) return;
104
+ let i = m.value;
105
+ i && (a("select", {
106
+ href: r.href,
107
+ value: i
108
+ }), n["close-on-select"].value && !r.closest("[data-navigation-menu-keep-open]") && F(null, "select"));
109
+ }, { signal: o });
110
+ document.addEventListener("keydown", (e) => {
111
+ e.key === "Escape" && m.value !== null && (e.preventDefault(), F(null, "escape"), g?.shadowRoot?.querySelector(".trigger")?.focus());
112
+ }, { signal: o });
113
+ for (let t of w()) {
114
+ let n = T(t), r = D(n);
115
+ if (!n || e.has(n) || !r) continue;
116
+ e.add(n), t.id ||= c("navigation-menu-trigger");
117
+ let i = t.shadowRoot?.querySelector(".trigger");
118
+ i && (i.setAttribute("aria-controls", k(r)), i.setAttribute("aria-haspopup", "true"), i.setAttribute("aria-expanded", "false"), t.setAttribute("aria-expanded", "false"), i.addEventListener("click", () => F(m.value === n ? null : n, "click"), { signal: o }), i.addEventListener("keydown", (e) => {
119
+ let r = w(), i = r.indexOf(t);
120
+ e.key === "ArrowLeft" || e.key === "ArrowRight" || e.key === "Home" || e.key === "End" ? (e.preventDefault(), (e.key === "Home" ? r[0] : e.key === "End" ? r.at(-1) : r[(i + (e.key === "ArrowRight" ? 1 : r.length - 1)) % r.length])?.shadowRoot?.querySelector(".trigger")?.focus()) : e.key === "ArrowDown" && (e.preventDefault(), F(n, "keyboard"), requestAnimationFrame(() => b?.querySelector("a, button, input, [tabindex]:not([tabindex=\"-1\"])")?.focus()));
121
+ }, { signal: o }));
122
+ }
123
+ n.open.value === void 0 ? n["default-open"].value && P(n["default-open"].value) : P(n.open.value);
124
+ }), y(n.open, (e) => {
125
+ e !== void 0 && P(e);
126
+ }), y(n.disabled, (e) => {
127
+ e && P(null);
128
+ }), d`
129
+ <nav class="triggers" aria-label="${n.label}" id="${s}"><slot></slot></nav>
130
+ <slot name="panel"></slot>
131
+ <slot name="footer"></slot>
132
+ `;
133
+ },
134
+ styles: [n, s]
135
+ });
136
+ //#endregion
137
+ export { x as NAVIGATION_MENU_ITEM_TAG, S as NAVIGATION_MENU_PANEL_TAG, C as NAVIGATION_MENU_TAG };
138
+
139
+ //# sourceMappingURL=navigation-menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-menu.js","names":[],"sources":["../src/overlay/navigation-menu/navigation-menu.ts"],"sourcesContent":["import { createStableId, define, getHost, html, onCleanup, onMounted, prop, useEmit, useSlots } from '@vielzeug/ore';\nimport { computed, signal } from '@vielzeug/ripple';\nimport { watch } from '@vielzeug/ripple/watch';\n\nimport type { OverlayOpenChangeDetail } from '../../core';\n\nimport { createDropdownPositioner, createOutsidePointerDismissal, lifecycleSignal } from '../../core';\nimport { disablableBundle } from '../../shared';\nimport { reducedMotionMixin } from '../../styles';\nimport itemStyles from './navigation-menu-item.css?inline';\nimport panelStyles from './navigation-menu-panel.css?inline';\nimport hostStyles from './navigation-menu.css?inline';\n\nexport type OreNavigationMenuEvents = {\n 'open-change': OverlayOpenChangeDetail & { value: string | null };\n select: NavigationMenuSelectDetail;\n};\n\nexport type NavigationMenuSelectDetail = {\n href: string;\n value: string;\n};\n\nexport type OreNavigationMenuItemProps = {\n disabled?: boolean;\n value: string;\n};\n\nexport type OreNavigationMenuProps = {\n /** Close after activating a panel link. */\n 'close-on-select'?: boolean;\n columns?: number;\n 'default-open'?: string;\n disabled?: boolean;\n /** Accessible label for the trigger region. */\n label?: string;\n open?: string;\n placement?: 'bottom-end' | 'bottom-start';\n};\n\nconst parseOptionalString = (value: string | null): string | undefined => value ?? undefined;\n\n/**\n * A trigger for an associated navigation menu panel.\n *\n * @element ore-navigation-menu-item\n *\n * @attr {boolean} disabled - Disables panel activation\n * @attr {string} value - Unique value matched by a panel's `for` attribute\n *\n * @slot - Trigger label and optional icon\n */\nexport const NAVIGATION_MENU_ITEM_TAG = 'ore-navigation-menu-item' as const;\ndefine<OreNavigationMenuItemProps>(NAVIGATION_MENU_ITEM_TAG, {\n props: { disabled: prop.bool(false), value: prop.string('') },\n setup(props) {\n return html`\n <button class=\"trigger\" type=\"button\" ?disabled=${props.disabled}><slot></slot></button>\n `;\n },\n styles: [itemStyles],\n});\n\n/**\n * An anchored navigation menu panel associated with an item.\n *\n * @element ore-navigation-menu-panel\n *\n * @attr {string} for - Value of the associated navigation menu item\n *\n * @slot - Panel content\n * @slot footer - Optional panel footer\n *\n * @part content - Grid container for panel content\n * @part footer - Container for optional footer content\n */\nexport const NAVIGATION_MENU_PANEL_TAG = 'ore-navigation-menu-panel' as const;\ndefine<{ for?: string }>(NAVIGATION_MENU_PANEL_TAG, {\n props: { for: prop.string() },\n setup() {\n const slots = useSlots();\n\n return html`\n <div class=\"content\" part=\"content\"><slot></slot></div>\n <div class=\"footer\" part=\"footer\" ?hidden=${() => !slots.has('footer').value}><slot name=\"footer\"></slot></div>\n `;\n },\n styles: [panelStyles],\n});\n\n/**\n * A horizontal set of triggers with anchored, non-modal navigation panels.\n *\n * @element ore-navigation-menu\n *\n * @attr {string} open - Controlled active trigger value\n * @attr {string} default-open - Initial uncontrolled active trigger value\n * @attr {boolean} close-on-select - Closes after activating a panel link\n * @attr {number} columns - Number of panel content columns\n * @attr {boolean} disabled - Disables all triggers\n * @attr {string} label - Accessible navigation region label\n * @attr {'bottom-start'|'bottom-end'} placement - Panel placement relative to its trigger\n *\n * @slot - Navigation menu items and panels\n *\n * @event open-change - Requested active panel change\n * @event select - A panel link was activated\n *\n * @cssprop --navigation-menu-panel-width - Maximum panel width\n * @cssprop --navigation-menu-panel-columns - Fallback number of panel content columns\n * @cssprop --navigation-menu-backdrop-blur - Frosted panel backdrop blur\n */\nexport const NAVIGATION_MENU_TAG = 'ore-navigation-menu' as const;\ndefine<OreNavigationMenuProps>(NAVIGATION_MENU_TAG, {\n props: {\n ...disablableBundle,\n 'close-on-select': prop.bool(true),\n columns: prop.number(),\n 'default-open': prop.string(),\n label: prop.string('Navigation menu'),\n open: { default: undefined as string | undefined, parse: parseOptionalString },\n placement: prop.oneOf(['bottom-end', 'bottom-start'] as const, 'bottom-start'),\n },\n setup(props) {\n const host = getHost();\n const emit = useEmit<OreNavigationMenuEvents>();\n const abortSignal = lifecycleSignal(onCleanup);\n const panelId = createStableId('navigation-menu');\n const isDisabled = computed(() => props.disabled.value);\n const activeValue = signal<string | null>(null);\n let activeTrigger: HTMLElement | null = null;\n let activePanel: HTMLElement | null = null;\n let stopPositioning: (() => void) | null = null;\n\n const items = () => Array.from(host.querySelectorAll<HTMLElement>(`${NAVIGATION_MENU_ITEM_TAG}:not([disabled])`));\n const valueOf = (item: HTMLElement) => item.getAttribute('value') ?? '';\n const panels = () => Array.from(host.querySelectorAll<HTMLElement>(NAVIGATION_MENU_PANEL_TAG));\n const panelFor = (value: string) => panels().find((panel) => panel.getAttribute('for') === value) ?? null;\n const isControlled = () => props.open.value !== undefined;\n const panelIdFor = (panel: HTMLElement) => (panel.id ||= createStableId('navigation-menu-panel'));\n\n const positioner = createDropdownPositioner({\n getFloating: () => activePanel,\n getPlacement: () => props.placement.value ?? 'bottom-start',\n getReference: () => activeTrigger?.shadowRoot?.querySelector<HTMLElement>('.trigger') ?? activeTrigger,\n matchWidth: false,\n offsetPx: 8,\n useClippingAncestor: false,\n });\n\n const panelColumns = (): number | undefined => {\n const columns = props.columns.value;\n\n return columns === undefined ? undefined : Math.max(1, Math.trunc(columns));\n };\n\n const showPanel = (panel: HTMLElement): void => {\n panel.hidden = false;\n panel.dataset.open = '';\n\n if ('showPopover' in panel) {\n try {\n if (!panel.matches(':popover-open')) panel.showPopover();\n } catch {\n // Sandboxed documents can reject the Popover API; data-open remains the fixed-position fallback.\n }\n }\n };\n\n const hidePanel = (panel: HTMLElement): void => {\n delete panel.dataset.open;\n\n if ('hidePopover' in panel) {\n try {\n if (panel.matches(':popover-open')) panel.hidePopover();\n } catch {\n // The fallback visibility state is still cleared below.\n }\n }\n\n panel.hidden = true;\n };\n\n const applyActive = (value: string | null): void => {\n const nextPanel = value === null ? null : panelFor(value);\n\n stopPositioning?.();\n stopPositioning = null;\n activeValue.value = value;\n activeTrigger = value ? (items().find((item) => valueOf(item) === value) ?? null) : null;\n activePanel = nextPanel;\n\n for (const item of items()) {\n const expanded = valueOf(item) === value;\n const trigger = item.shadowRoot?.querySelector<HTMLElement>('.trigger');\n\n item.setAttribute('aria-expanded', String(expanded));\n trigger?.setAttribute('aria-expanded', String(expanded));\n }\n for (const panel of panels()) {\n if (panel !== nextPanel) hidePanel(panel);\n }\n\n if (nextPanel) {\n const columns = panelColumns();\n\n if (columns !== undefined) nextPanel.style.setProperty('--navigation-menu-panel-columns', String(columns));\n\n nextPanel.setAttribute('aria-labelledby', activeTrigger?.id ?? '');\n showPanel(nextPanel);\n positioner.update();\n stopPositioning = positioner.startAutoUpdate?.() ?? null;\n }\n };\n\n const requestActive = (value: string | null, reason: OverlayOpenChangeDetail['reason']): void => {\n if (isDisabled.value || activeValue.value === value) return;\n\n if (value !== null && !panelFor(value)) return;\n\n if (!isControlled()) applyActive(value);\n\n emit('open-change', { open: value !== null, reason, value });\n };\n\n onCleanup(() => {\n stopPositioning?.();\n\n for (const panel of panels()) hidePanel(panel);\n });\n\n createOutsidePointerDismissal({\n getTargets: () => [host, activePanel],\n isActive: () => activeValue.value !== null,\n onDismiss: () => requestActive(null, 'outsideClick'),\n signal: abortSignal,\n });\n\n onMounted(() => {\n const values = new Set<string>();\n\n for (const panel of panels()) {\n panel.setAttribute('popover', 'manual');\n panel.setAttribute('role', 'region');\n panelIdFor(panel);\n hidePanel(panel);\n\n panel.addEventListener(\n 'click',\n (event) => {\n const link = event.target instanceof Element ? event.target.closest<HTMLAnchorElement>('a[href]') : null;\n\n if (!link || !panel.contains(link)) return;\n\n const value = activeValue.value;\n\n if (!value) return;\n\n emit('select', { href: link.href, value });\n\n if (props['close-on-select'].value && !link.closest('[data-navigation-menu-keep-open]')) {\n requestActive(null, 'select');\n }\n },\n { signal: abortSignal },\n );\n }\n\n document.addEventListener(\n 'keydown',\n (event) => {\n if (event.key !== 'Escape' || activeValue.value === null) return;\n\n event.preventDefault();\n requestActive(null, 'escape');\n activeTrigger?.shadowRoot?.querySelector<HTMLElement>('.trigger')?.focus();\n },\n { signal: abortSignal },\n );\n\n for (const item of items()) {\n const value = valueOf(item);\n const panel = panelFor(value);\n\n if (!value || values.has(value) || !panel) continue;\n\n values.add(value);\n item.id ||= createStableId('navigation-menu-trigger');\n\n const trigger = item.shadowRoot?.querySelector<HTMLButtonElement>('.trigger');\n\n if (!trigger) continue;\n\n trigger.setAttribute('aria-controls', panelIdFor(panel));\n trigger.setAttribute('aria-haspopup', 'true');\n trigger.setAttribute('aria-expanded', 'false');\n item.setAttribute('aria-expanded', 'false');\n trigger.addEventListener('click', () => requestActive(activeValue.value === value ? null : value, 'click'), {\n signal: abortSignal,\n });\n trigger.addEventListener(\n 'keydown',\n (event) => {\n const all = items();\n const index = all.indexOf(item);\n\n if (\n event.key === 'ArrowLeft' ||\n event.key === 'ArrowRight' ||\n event.key === 'Home' ||\n event.key === 'End'\n ) {\n event.preventDefault();\n\n const next =\n event.key === 'Home'\n ? all[0]\n : event.key === 'End'\n ? all.at(-1)\n : all[(index + (event.key === 'ArrowRight' ? 1 : all.length - 1)) % all.length];\n\n next?.shadowRoot?.querySelector<HTMLElement>('.trigger')?.focus();\n } else if (event.key === 'ArrowDown') {\n event.preventDefault();\n requestActive(value, 'keyboard');\n requestAnimationFrame(() =>\n activePanel?.querySelector<HTMLElement>('a, button, input, [tabindex]:not([tabindex=\"-1\"])')?.focus(),\n );\n }\n },\n { signal: abortSignal },\n );\n }\n\n if (props.open.value !== undefined) applyActive(props.open.value);\n else if (props['default-open'].value) applyActive(props['default-open'].value);\n });\n\n watch(props.open, (value) => {\n if (value !== undefined) applyActive(value);\n });\n\n watch(props.disabled, (disabled) => {\n if (disabled) applyActive(null);\n });\n\n return html`\n <nav class=\"triggers\" aria-label=\"${props.label}\" id=\"${panelId}\"><slot></slot></nav>\n <slot name=\"panel\"></slot>\n <slot name=\"footer\"></slot>\n `;\n },\n styles: [reducedMotionMixin, hostStyles],\n});\n"],"mappings":"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"}
@@ -5,6 +5,8 @@ export type { OreDialogEvents, OreDialogProps } from './dialog/dialog';
5
5
  export { DRAWER_TAG } from './drawer/drawer';
6
6
  export type { DrawerElement, OreDrawerEvents, OreDrawerProps } from './drawer/drawer';
7
7
  export { MENU_ITEM_TAG, MENU_TAG } from './menu/menu';
8
+ export { NAVIGATION_MENU_ITEM_TAG, NAVIGATION_MENU_PANEL_TAG, NAVIGATION_MENU_TAG, } from './navigation-menu/navigation-menu';
9
+ export type { OreNavigationMenuEvents, OreNavigationMenuItemProps, OreNavigationMenuProps, } from './navigation-menu/navigation-menu';
8
10
  export type { OreMenuEvents, OreMenuItemProps, OreMenuItemType, OreMenuProps, MenuSelectDetail } from './menu/menu';
9
11
  export { POPOVER_TAG } from './popover/popover';
10
12
  export type { OrePopoverEvents, OrePopoverProps } from './popover/popover';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/overlay/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAClG,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACtD,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/overlay/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAClG,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,YAAY,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtF,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EACL,wBAAwB,EACxB,yBAAyB,EACzB,mBAAmB,GACpB,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EACV,uBAAuB,EACvB,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,mCAAmC,CAAC;AAC3C,YAAY,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,2 @@
1
+ var e=`@layer refine.base{:host{display:inline-flex}.trigger{all:unset;box-sizing:border-box;gap:var(--size-1);min-height:var(--_touch-target,var(--size-9));padding:var(--size-1-5) var(--size-2-5);font-size:var(--text-sm);font-weight:var(--font-medium);color:var(--navbar-item-color,var(--color-contrast-700));cursor:pointer;border-radius:var(--rounded-md);align-items:center;display:inline-flex}.trigger:hover,.trigger[aria-expanded=true]{color:var(--color-primary);background:var(--color-contrast-100)}.trigger:focus-visible{outline:var(--focus-ring);outline-offset:var(--size-0-5)}.trigger:disabled{cursor:not-allowed;opacity:.6}::slotted(ore-icon){transition:transform var(--transition-fast);flex:none}:host([aria-expanded=true]) ::slotted(ore-icon){transform:rotate(180deg)}}`;exports.default=e;
2
+ //# sourceMappingURL=navigation-menu-item.css.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-menu-item.css.cjs","names":[],"sources":["../../../src/overlay/navigation-menu/navigation-menu-item.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n display: inline-flex;\n }\n\n .trigger {\n all: unset;\n box-sizing: border-box;\n display: inline-flex;\n gap: var(--size-1);\n align-items: center;\n min-height: var(--_touch-target, var(--size-9));\n padding: var(--size-1-5) var(--size-2-5);\n font-size: var(--text-sm);\n font-weight: var(--font-medium);\n color: var(--navbar-item-color, var(--color-contrast-700));\n cursor: pointer;\n border-radius: var(--rounded-md);\n }\n\n .trigger:hover,\n .trigger[aria-expanded='true'] {\n color: var(--color-primary);\n background: var(--color-contrast-100);\n }\n\n .trigger:focus-visible {\n outline: var(--focus-ring);\n outline-offset: var(--size-0-5);\n }\n\n .trigger:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n }\n\n ::slotted(ore-icon) {\n flex: none;\n transition: transform var(--transition-fast);\n }\n\n :host([aria-expanded='true']) ::slotted(ore-icon) {\n transform: rotate(180deg);\n }\n}\n"],"mappings":""}
@@ -0,0 +1,6 @@
1
+ //#region src/overlay/navigation-menu/navigation-menu-item.css?inline
2
+ var e = "@layer refine.base{:host{display:inline-flex}.trigger{all:unset;box-sizing:border-box;gap:var(--size-1);min-height:var(--_touch-target,var(--size-9));padding:var(--size-1-5) var(--size-2-5);font-size:var(--text-sm);font-weight:var(--font-medium);color:var(--navbar-item-color,var(--color-contrast-700));cursor:pointer;border-radius:var(--rounded-md);align-items:center;display:inline-flex}.trigger:hover,.trigger[aria-expanded=true]{color:var(--color-primary);background:var(--color-contrast-100)}.trigger:focus-visible{outline:var(--focus-ring);outline-offset:var(--size-0-5)}.trigger:disabled{cursor:not-allowed;opacity:.6}::slotted(ore-icon){transition:transform var(--transition-fast);flex:none}:host([aria-expanded=true]) ::slotted(ore-icon){transform:rotate(180deg)}}";
3
+ //#endregion
4
+ export { e as default };
5
+
6
+ //# sourceMappingURL=navigation-menu-item.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-menu-item.css.js","names":[],"sources":["../../../src/overlay/navigation-menu/navigation-menu-item.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n display: inline-flex;\n }\n\n .trigger {\n all: unset;\n box-sizing: border-box;\n display: inline-flex;\n gap: var(--size-1);\n align-items: center;\n min-height: var(--_touch-target, var(--size-9));\n padding: var(--size-1-5) var(--size-2-5);\n font-size: var(--text-sm);\n font-weight: var(--font-medium);\n color: var(--navbar-item-color, var(--color-contrast-700));\n cursor: pointer;\n border-radius: var(--rounded-md);\n }\n\n .trigger:hover,\n .trigger[aria-expanded='true'] {\n color: var(--color-primary);\n background: var(--color-contrast-100);\n }\n\n .trigger:focus-visible {\n outline: var(--focus-ring);\n outline-offset: var(--size-0-5);\n }\n\n .trigger:disabled {\n cursor: not-allowed;\n opacity: 0.6;\n }\n\n ::slotted(ore-icon) {\n flex: none;\n transition: transform var(--transition-fast);\n }\n\n :host([aria-expanded='true']) ::slotted(ore-icon) {\n transform: rotate(180deg);\n }\n}\n"],"mappings":""}
@@ -0,0 +1,2 @@
1
+ var e=`@layer refine.base{:host{inset:unset;z-index:var(--z-popover);box-sizing:border-box;width:min(var(--navigation-menu-panel-width,48rem), calc(100vw - var(--size-8)));max-height:min(var(--navigation-menu-panel-max-height,42rem), calc(100dvh - var(--size-12)));overscroll-behavior:contain;background:var(--navigation-menu-bg,var(--color-canvas));border:var(--border) solid var(--navigation-menu-border-color,var(--color-divider));border-radius:var(--navigation-menu-radius,var(--rounded-lg));box-shadow:var(--navigation-menu-shadow,var(--shadow-xl));-webkit-backdrop-filter:blur(var(--navigation-menu-backdrop-blur,var(--blur-xl))) saturate(180%);backdrop-filter:blur(var(--navigation-menu-backdrop-blur,var(--blur-xl))) saturate(180%);margin:0;display:none;position:fixed;overflow:auto}:host([hidden]){display:none}:host(:popover-open),:host([data-open]){display:block}.content{grid-template-columns:repeat(var(--navigation-menu-panel-columns,2), minmax(0, 1fr));gap:var(--size-3);padding:var(--size-5);grid-auto-rows:max-content;align-content:start;display:grid}.footer[hidden]{display:none}::slotted(a){min-width:0;padding:var(--size-3);font-size:var(--text-sm);line-height:var(--leading-normal);color:var(--color-contrast-700);border-radius:var(--rounded-md);transition:background var(--transition-fast), color var(--transition-fast);text-decoration:none}::slotted(a:hover),::slotted(a:focus-visible){color:var(--color-primary);background:var(--color-contrast-100)}::slotted(a:focus-visible){outline:var(--focus-ring);outline-offset:var(--size-0-5)}::slotted(a[slot=footer]){gap:var(--size-2);padding:var(--size-3) var(--size-5);font-size:var(--text-sm);font-weight:var(--font-medium);color:var(--color-primary);border-top:var(--border) solid var(--color-divider);justify-content:space-between;align-items:center;text-decoration:none;display:flex}::slotted(a[slot=footer]:hover),::slotted(a[slot=footer]:focus-visible){background:var(--color-contrast-100)}}`;exports.default=e;
2
+ //# sourceMappingURL=navigation-menu-panel.css.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-menu-panel.css.cjs","names":[],"sources":["../../../src/overlay/navigation-menu/navigation-menu-panel.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n position: fixed;\n inset: unset;\n z-index: var(--z-popover);\n box-sizing: border-box;\n display: none;\n width: min(var(--navigation-menu-panel-width, 48rem), calc(100vw - var(--size-8)));\n max-height: min(var(--navigation-menu-panel-max-height, 42rem), calc(100dvh - var(--size-12)));\n margin: 0;\n overflow: auto;\n overscroll-behavior: contain;\n background: var(--navigation-menu-bg, var(--color-canvas));\n border: var(--border) solid var(--navigation-menu-border-color, var(--color-divider));\n border-radius: var(--navigation-menu-radius, var(--rounded-lg));\n box-shadow: var(--navigation-menu-shadow, var(--shadow-xl));\n backdrop-filter: blur(var(--navigation-menu-backdrop-blur, var(--blur-xl))) saturate(180%);\n }\n\n :host([hidden]) {\n display: none;\n }\n\n :host(:popover-open),\n :host([data-open]) {\n display: block;\n }\n\n .content {\n display: grid;\n grid-template-columns: repeat(var(--navigation-menu-panel-columns, 2), minmax(0, 1fr));\n grid-auto-rows: max-content;\n gap: var(--size-3);\n align-content: start;\n padding: var(--size-5);\n }\n\n .footer[hidden] {\n display: none;\n }\n\n ::slotted(a) {\n min-width: 0;\n padding: var(--size-3);\n font-size: var(--text-sm);\n line-height: var(--leading-normal);\n color: var(--color-contrast-700);\n text-decoration: none;\n border-radius: var(--rounded-md);\n transition:\n background var(--transition-fast),\n color var(--transition-fast);\n }\n\n ::slotted(a:hover),\n ::slotted(a:focus-visible) {\n color: var(--color-primary);\n background: var(--color-contrast-100);\n }\n\n ::slotted(a:focus-visible) {\n outline: var(--focus-ring);\n outline-offset: var(--size-0-5);\n }\n\n ::slotted(a[slot='footer']) {\n display: flex;\n gap: var(--size-2);\n align-items: center;\n justify-content: space-between;\n padding: var(--size-3) var(--size-5);\n font-size: var(--text-sm);\n font-weight: var(--font-medium);\n color: var(--color-primary);\n text-decoration: none;\n border-top: var(--border) solid var(--color-divider);\n }\n\n ::slotted(a[slot='footer']:hover),\n ::slotted(a[slot='footer']:focus-visible) {\n background: var(--color-contrast-100);\n }\n}\n"],"mappings":""}
@@ -0,0 +1,6 @@
1
+ //#region src/overlay/navigation-menu/navigation-menu-panel.css?inline
2
+ var e = "@layer refine.base{:host{inset:unset;z-index:var(--z-popover);box-sizing:border-box;width:min(var(--navigation-menu-panel-width,48rem), calc(100vw - var(--size-8)));max-height:min(var(--navigation-menu-panel-max-height,42rem), calc(100dvh - var(--size-12)));overscroll-behavior:contain;background:var(--navigation-menu-bg,var(--color-canvas));border:var(--border) solid var(--navigation-menu-border-color,var(--color-divider));border-radius:var(--navigation-menu-radius,var(--rounded-lg));box-shadow:var(--navigation-menu-shadow,var(--shadow-xl));-webkit-backdrop-filter:blur(var(--navigation-menu-backdrop-blur,var(--blur-xl))) saturate(180%);backdrop-filter:blur(var(--navigation-menu-backdrop-blur,var(--blur-xl))) saturate(180%);margin:0;display:none;position:fixed;overflow:auto}:host([hidden]){display:none}:host(:popover-open),:host([data-open]){display:block}.content{grid-template-columns:repeat(var(--navigation-menu-panel-columns,2), minmax(0, 1fr));gap:var(--size-3);padding:var(--size-5);grid-auto-rows:max-content;align-content:start;display:grid}.footer[hidden]{display:none}::slotted(a){min-width:0;padding:var(--size-3);font-size:var(--text-sm);line-height:var(--leading-normal);color:var(--color-contrast-700);border-radius:var(--rounded-md);transition:background var(--transition-fast), color var(--transition-fast);text-decoration:none}::slotted(a:hover),::slotted(a:focus-visible){color:var(--color-primary);background:var(--color-contrast-100)}::slotted(a:focus-visible){outline:var(--focus-ring);outline-offset:var(--size-0-5)}::slotted(a[slot=footer]){gap:var(--size-2);padding:var(--size-3) var(--size-5);font-size:var(--text-sm);font-weight:var(--font-medium);color:var(--color-primary);border-top:var(--border) solid var(--color-divider);justify-content:space-between;align-items:center;text-decoration:none;display:flex}::slotted(a[slot=footer]:hover),::slotted(a[slot=footer]:focus-visible){background:var(--color-contrast-100)}}";
3
+ //#endregion
4
+ export { e as default };
5
+
6
+ //# sourceMappingURL=navigation-menu-panel.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-menu-panel.css.js","names":[],"sources":["../../../src/overlay/navigation-menu/navigation-menu-panel.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n position: fixed;\n inset: unset;\n z-index: var(--z-popover);\n box-sizing: border-box;\n display: none;\n width: min(var(--navigation-menu-panel-width, 48rem), calc(100vw - var(--size-8)));\n max-height: min(var(--navigation-menu-panel-max-height, 42rem), calc(100dvh - var(--size-12)));\n margin: 0;\n overflow: auto;\n overscroll-behavior: contain;\n background: var(--navigation-menu-bg, var(--color-canvas));\n border: var(--border) solid var(--navigation-menu-border-color, var(--color-divider));\n border-radius: var(--navigation-menu-radius, var(--rounded-lg));\n box-shadow: var(--navigation-menu-shadow, var(--shadow-xl));\n backdrop-filter: blur(var(--navigation-menu-backdrop-blur, var(--blur-xl))) saturate(180%);\n }\n\n :host([hidden]) {\n display: none;\n }\n\n :host(:popover-open),\n :host([data-open]) {\n display: block;\n }\n\n .content {\n display: grid;\n grid-template-columns: repeat(var(--navigation-menu-panel-columns, 2), minmax(0, 1fr));\n grid-auto-rows: max-content;\n gap: var(--size-3);\n align-content: start;\n padding: var(--size-5);\n }\n\n .footer[hidden] {\n display: none;\n }\n\n ::slotted(a) {\n min-width: 0;\n padding: var(--size-3);\n font-size: var(--text-sm);\n line-height: var(--leading-normal);\n color: var(--color-contrast-700);\n text-decoration: none;\n border-radius: var(--rounded-md);\n transition:\n background var(--transition-fast),\n color var(--transition-fast);\n }\n\n ::slotted(a:hover),\n ::slotted(a:focus-visible) {\n color: var(--color-primary);\n background: var(--color-contrast-100);\n }\n\n ::slotted(a:focus-visible) {\n outline: var(--focus-ring);\n outline-offset: var(--size-0-5);\n }\n\n ::slotted(a[slot='footer']) {\n display: flex;\n gap: var(--size-2);\n align-items: center;\n justify-content: space-between;\n padding: var(--size-3) var(--size-5);\n font-size: var(--text-sm);\n font-weight: var(--font-medium);\n color: var(--color-primary);\n text-decoration: none;\n border-top: var(--border) solid var(--color-divider);\n }\n\n ::slotted(a[slot='footer']:hover),\n ::slotted(a[slot='footer']:focus-visible) {\n background: var(--color-contrast-100);\n }\n}\n"],"mappings":""}
@@ -0,0 +1,2 @@
1
+ var e=`@layer refine.base{:host{--_panel-bg:var(--navigation-menu-bg,var(--color-canvas));--_panel-border:var(--navigation-menu-border-color,var(--color-divider));--_panel-shadow:var(--navigation-menu-shadow,var(--shadow-xl));display:inline-block;position:relative}.triggers{gap:var(--navigation-menu-trigger-gap,var(--size-1));align-items:center;display:flex}}`;exports.default=e;
2
+ //# sourceMappingURL=navigation-menu.css.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-menu.css.cjs","names":[],"sources":["../../../src/overlay/navigation-menu/navigation-menu.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n --_panel-bg: var(--navigation-menu-bg, var(--color-canvas));\n --_panel-border: var(--navigation-menu-border-color, var(--color-divider));\n --_panel-shadow: var(--navigation-menu-shadow, var(--shadow-xl));\n\n position: relative;\n display: inline-block;\n }\n\n .triggers {\n display: flex;\n gap: var(--navigation-menu-trigger-gap, var(--size-1));\n align-items: center;\n }\n}\n"],"mappings":""}
@@ -0,0 +1,6 @@
1
+ //#region src/overlay/navigation-menu/navigation-menu.css?inline
2
+ var e = "@layer refine.base{:host{--_panel-bg:var(--navigation-menu-bg,var(--color-canvas));--_panel-border:var(--navigation-menu-border-color,var(--color-divider));--_panel-shadow:var(--navigation-menu-shadow,var(--shadow-xl));display:inline-block;position:relative}.triggers{gap:var(--navigation-menu-trigger-gap,var(--size-1));align-items:center;display:flex}}";
3
+ //#endregion
4
+ export { e as default };
5
+
6
+ //# sourceMappingURL=navigation-menu.css.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-menu.css.js","names":[],"sources":["../../../src/overlay/navigation-menu/navigation-menu.css?inline"],"sourcesContent":["@layer refine.base {\n :host {\n --_panel-bg: var(--navigation-menu-bg, var(--color-canvas));\n --_panel-border: var(--navigation-menu-border-color, var(--color-divider));\n --_panel-shadow: var(--navigation-menu-shadow, var(--shadow-xl));\n\n position: relative;\n display: inline-block;\n }\n\n .triggers {\n display: flex;\n gap: var(--navigation-menu-trigger-gap, var(--size-1));\n align-items: center;\n }\n}\n"],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import type { OverlayOpenChangeDetail } from '../../core';
2
+ export type OreNavigationMenuEvents = {
3
+ 'open-change': OverlayOpenChangeDetail & {
4
+ value: string | null;
5
+ };
6
+ select: NavigationMenuSelectDetail;
7
+ };
8
+ export type NavigationMenuSelectDetail = {
9
+ href: string;
10
+ value: string;
11
+ };
12
+ export type OreNavigationMenuItemProps = {
13
+ disabled?: boolean;
14
+ value: string;
15
+ };
16
+ export type OreNavigationMenuProps = {
17
+ /** Close after activating a panel link. */
18
+ 'close-on-select'?: boolean;
19
+ columns?: number;
20
+ 'default-open'?: string;
21
+ disabled?: boolean;
22
+ /** Accessible label for the trigger region. */
23
+ label?: string;
24
+ open?: string;
25
+ placement?: 'bottom-end' | 'bottom-start';
26
+ };
27
+ /**
28
+ * A trigger for an associated navigation menu panel.
29
+ *
30
+ * @element ore-navigation-menu-item
31
+ *
32
+ * @attr {boolean} disabled - Disables panel activation
33
+ * @attr {string} value - Unique value matched by a panel's `for` attribute
34
+ *
35
+ * @slot - Trigger label and optional icon
36
+ */
37
+ export declare const NAVIGATION_MENU_ITEM_TAG: "ore-navigation-menu-item";
38
+ /**
39
+ * An anchored navigation menu panel associated with an item.
40
+ *
41
+ * @element ore-navigation-menu-panel
42
+ *
43
+ * @attr {string} for - Value of the associated navigation menu item
44
+ *
45
+ * @slot - Panel content
46
+ * @slot footer - Optional panel footer
47
+ *
48
+ * @part content - Grid container for panel content
49
+ * @part footer - Container for optional footer content
50
+ */
51
+ export declare const NAVIGATION_MENU_PANEL_TAG: "ore-navigation-menu-panel";
52
+ /**
53
+ * A horizontal set of triggers with anchored, non-modal navigation panels.
54
+ *
55
+ * @element ore-navigation-menu
56
+ *
57
+ * @attr {string} open - Controlled active trigger value
58
+ * @attr {string} default-open - Initial uncontrolled active trigger value
59
+ * @attr {boolean} close-on-select - Closes after activating a panel link
60
+ * @attr {number} columns - Number of panel content columns
61
+ * @attr {boolean} disabled - Disables all triggers
62
+ * @attr {string} label - Accessible navigation region label
63
+ * @attr {'bottom-start'|'bottom-end'} placement - Panel placement relative to its trigger
64
+ *
65
+ * @slot - Navigation menu items and panels
66
+ *
67
+ * @event open-change - Requested active panel change
68
+ * @event select - A panel link was activated
69
+ *
70
+ * @cssprop --navigation-menu-panel-width - Maximum panel width
71
+ * @cssprop --navigation-menu-panel-columns - Fallback number of panel content columns
72
+ * @cssprop --navigation-menu-backdrop-blur - Frosted panel backdrop blur
73
+ */
74
+ export declare const NAVIGATION_MENU_TAG: "ore-navigation-menu";
75
+ //# sourceMappingURL=navigation-menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-menu.d.ts","sourceRoot":"","sources":["../../../src/overlay/navigation-menu/navigation-menu.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAS1D,MAAM,MAAM,uBAAuB,GAAG;IACpC,aAAa,EAAE,uBAAuB,GAAG;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAClE,MAAM,EAAE,0BAA0B,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,2CAA2C;IAC3C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,YAAY,GAAG,cAAc,CAAC;CAC3C,CAAC;AAIF;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB,EAAG,0BAAmC,CAAC;AAW5E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,yBAAyB,EAAG,2BAAoC,CAAC;AAc9E;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,mBAAmB,EAAG,qBAA8B,CAAC"}