luxen-ui 0.23.0 → 0.24.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 (173) hide show
  1. package/cdn/custom-elements.json +203 -170
  2. package/cdn/elements/combobox/combobox.d.ts +6 -1
  3. package/cdn/elements/combobox/combobox.d.ts.map +1 -1
  4. package/cdn/elements/combobox/combobox.js +19 -17
  5. package/cdn/elements/combobox/combobox.js.map +1 -1
  6. package/cdn/elements/dropdown/dropdown.d.ts +6 -7
  7. package/cdn/elements/dropdown/dropdown.d.ts.map +1 -1
  8. package/cdn/elements/dropdown/dropdown.js +2 -2
  9. package/cdn/elements/dropdown/dropdown.js.map +1 -1
  10. package/cdn/elements/dropdown-item/dropdown-item.d.ts +0 -1
  11. package/cdn/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
  12. package/cdn/elements/dropdown-item/dropdown-item.js +2 -2
  13. package/cdn/elements/dropdown-item/dropdown-item.js.map +1 -1
  14. package/cdn/elements/dropdown-label/dropdown-label.js +1 -1
  15. package/cdn/elements/dropdown-label/dropdown-label.js.map +1 -1
  16. package/cdn/elements/form-field/form-field.d.ts +1 -1
  17. package/cdn/elements/form-field/form-field.js.map +1 -1
  18. package/cdn/elements/input/input.meta.d.ts +2 -0
  19. package/cdn/elements/input/input.meta.d.ts.map +1 -1
  20. package/cdn/elements/input-otp/input-otp.d.ts +3 -3
  21. package/cdn/elements/input-otp/input-otp.js.map +1 -1
  22. package/cdn/elements/popover/popover.d.ts +3 -4
  23. package/cdn/elements/popover/popover.d.ts.map +1 -1
  24. package/cdn/elements/popover/popover.js +1 -1
  25. package/cdn/elements/popover/popover.js.map +1 -1
  26. package/cdn/elements/select/select.d.ts +6 -1
  27. package/cdn/elements/select/select.d.ts.map +1 -1
  28. package/cdn/elements/select/select.js +8 -7
  29. package/cdn/elements/select/select.js.map +1 -1
  30. package/cdn/elements/stories-viewer/stories-viewer.d.ts.map +1 -1
  31. package/cdn/elements/stories-viewer/stories-viewer.js +4 -4
  32. package/cdn/elements/stories-viewer/stories-viewer.js.map +1 -1
  33. package/cdn/elements/tooltip/tooltip.d.ts +0 -1
  34. package/cdn/elements/tooltip/tooltip.d.ts.map +1 -1
  35. package/cdn/elements/tooltip/tooltip.js +1 -1
  36. package/cdn/elements/tooltip/tooltip.js.map +1 -1
  37. package/cdn/shared/controllers/listbox-nav.d.ts +15 -1
  38. package/cdn/shared/controllers/listbox-nav.d.ts.map +1 -1
  39. package/cdn/shared/controllers/listbox-nav.js +1 -1
  40. package/cdn/shared/controllers/listbox-nav.js.map +1 -1
  41. package/cdn/shared/controllers/popover.d.ts +10 -2
  42. package/cdn/shared/controllers/popover.d.ts.map +1 -1
  43. package/cdn/shared/controllers/popover.js +1 -1
  44. package/cdn/shared/controllers/popover.js.map +1 -1
  45. package/cdn/shared/styles/checkbox-appearance.styles.js +1 -1
  46. package/cdn/shared/styles/checkbox-appearance.styles.js.map +1 -1
  47. package/cdn/shared/styles/menu-panel.styles.d.ts +8 -0
  48. package/cdn/shared/styles/menu-panel.styles.d.ts.map +1 -0
  49. package/cdn/shared/styles/menu-panel.styles.js +2 -0
  50. package/cdn/shared/styles/menu-panel.styles.js.map +1 -0
  51. package/cdn/shared/styles/picker-core.styles.d.ts +9 -0
  52. package/cdn/shared/styles/picker-core.styles.d.ts.map +1 -0
  53. package/cdn/shared/styles/picker-core.styles.js +2 -0
  54. package/cdn/shared/styles/picker-core.styles.js.map +1 -0
  55. package/cdn/shared/styles/select-item-suffix.styles.js +1 -1
  56. package/cdn/shared/styles/select-item-suffix.styles.js.map +1 -1
  57. package/cdn/shared/styles/select-item.styles.d.ts +8 -0
  58. package/cdn/shared/styles/select-item.styles.d.ts.map +1 -0
  59. package/cdn/shared/styles/select-item.styles.js +2 -0
  60. package/cdn/shared/styles/select-item.styles.js.map +1 -0
  61. package/cdn/shared/styles/visually-hidden.styles.d.ts +8 -0
  62. package/cdn/shared/styles/visually-hidden.styles.d.ts.map +1 -0
  63. package/cdn/shared/styles/visually-hidden.styles.js +2 -0
  64. package/cdn/shared/styles/visually-hidden.styles.js.map +1 -0
  65. package/cdn/standalone.css +365 -196
  66. package/cdn/standalone.js +148 -75
  67. package/cdn/standalone.js.map +1 -1
  68. package/cdn/styles/base.css +30 -20
  69. package/cdn/styles/elements/checkbox.css +2 -2
  70. package/cdn/styles/elements/form-field.css +16 -9
  71. package/cdn/styles/elements/input-otp.css +16 -9
  72. package/cdn/styles/elements/input-stepper/default.css +4 -4
  73. package/cdn/styles/elements/input-stepper/pill.css +4 -4
  74. package/cdn/styles/elements/input-stepper/rounded.css +3 -3
  75. package/cdn/styles/elements/input.css +82 -27
  76. package/cdn/styles/elements/radio.css +2 -2
  77. package/cdn/styles/elements/select.css +137 -80
  78. package/cdn/styles/elements/switch.css +3 -3
  79. package/cdn/styles/elements/textarea.css +5 -5
  80. package/cdn/styles/preset.css +92 -49
  81. package/cdn/styles/tokens/forms.css +33 -30
  82. package/cdn/styles/tokens.css +62 -29
  83. package/dist/css/base.css +30 -20
  84. package/dist/css/elements/checkbox.css +2 -2
  85. package/dist/css/elements/form-field.css +16 -9
  86. package/dist/css/elements/input-otp.css +16 -9
  87. package/dist/css/elements/input-stepper/default.css +4 -4
  88. package/dist/css/elements/input-stepper/pill.css +4 -4
  89. package/dist/css/elements/input-stepper/rounded.css +3 -3
  90. package/dist/css/elements/input.css +82 -27
  91. package/dist/css/elements/radio.css +2 -2
  92. package/dist/css/elements/select.css +137 -80
  93. package/dist/css/elements/switch.css +3 -3
  94. package/dist/css/elements/textarea.css +5 -5
  95. package/dist/css/preset.css +92 -49
  96. package/dist/css/tokens/forms.css +33 -30
  97. package/dist/css/tokens.css +62 -29
  98. package/dist/custom-elements.json +203 -170
  99. package/dist/elements/combobox/combobox.css +30 -187
  100. package/dist/elements/combobox/combobox.d.ts +6 -1
  101. package/dist/elements/combobox/combobox.d.ts.map +1 -1
  102. package/dist/elements/combobox/combobox.js +48 -20
  103. package/dist/elements/dropdown/dropdown.css +7 -30
  104. package/dist/elements/dropdown/dropdown.d.ts +6 -7
  105. package/dist/elements/dropdown/dropdown.d.ts.map +1 -1
  106. package/dist/elements/dropdown/dropdown.js +17 -14
  107. package/dist/elements/dropdown-item/dropdown-item.css +7 -36
  108. package/dist/elements/dropdown-item/dropdown-item.d.ts +0 -1
  109. package/dist/elements/dropdown-item/dropdown-item.d.ts.map +1 -1
  110. package/dist/elements/dropdown-item/dropdown-item.js +4 -7
  111. package/dist/elements/dropdown-label/dropdown-label.css +3 -3
  112. package/dist/elements/form-field/form-field.d.ts +1 -1
  113. package/dist/elements/form-field/form-field.js +2 -2
  114. package/dist/elements/input/input.meta.d.ts +2 -0
  115. package/dist/elements/input/input.meta.d.ts.map +1 -1
  116. package/dist/elements/input/input.meta.js +2 -0
  117. package/dist/elements/input-otp/input-otp.d.ts +3 -3
  118. package/dist/elements/input-otp/input-otp.js +3 -3
  119. package/dist/elements/popover/popover.css +4 -4
  120. package/dist/elements/popover/popover.d.ts +3 -4
  121. package/dist/elements/popover/popover.d.ts.map +1 -1
  122. package/dist/elements/popover/popover.js +5 -9
  123. package/dist/elements/select/select.css +24 -260
  124. package/dist/elements/select/select.d.ts +6 -1
  125. package/dist/elements/select/select.d.ts.map +1 -1
  126. package/dist/elements/select/select.js +27 -9
  127. package/dist/elements/stories-viewer/stories-viewer.css +0 -12
  128. package/dist/elements/stories-viewer/stories-viewer.d.ts.map +1 -1
  129. package/dist/elements/stories-viewer/stories-viewer.js +4 -3
  130. package/dist/elements/tooltip/tooltip.d.ts +0 -1
  131. package/dist/elements/tooltip/tooltip.d.ts.map +1 -1
  132. package/dist/elements/tooltip/tooltip.js +2 -6
  133. package/dist/metadata/combobox.json +16 -1
  134. package/dist/metadata/dropdown.json +10 -10
  135. package/dist/metadata/form-field.json +1 -1
  136. package/dist/metadata/index.json +57 -22
  137. package/dist/metadata/input-otp.json +3 -3
  138. package/dist/metadata/input.json +5 -0
  139. package/dist/metadata/popover.json +5 -5
  140. package/dist/metadata/select.json +16 -1
  141. package/dist/shared/controllers/listbox-nav.d.ts +15 -1
  142. package/dist/shared/controllers/listbox-nav.d.ts.map +1 -1
  143. package/dist/shared/controllers/listbox-nav.js +32 -1
  144. package/dist/shared/controllers/popover.d.ts +10 -2
  145. package/dist/shared/controllers/popover.d.ts.map +1 -1
  146. package/dist/shared/controllers/popover.js +16 -2
  147. package/dist/shared/styles/checkbox-appearance.css +2 -2
  148. package/dist/shared/styles/menu-panel.css +37 -0
  149. package/dist/shared/styles/menu-panel.styles.d.ts +8 -0
  150. package/dist/shared/styles/menu-panel.styles.d.ts.map +1 -0
  151. package/dist/shared/styles/menu-panel.styles.js +8 -0
  152. package/dist/shared/styles/picker-core.css +250 -0
  153. package/dist/shared/styles/picker-core.styles.d.ts +9 -0
  154. package/dist/shared/styles/picker-core.styles.d.ts.map +1 -0
  155. package/dist/shared/styles/picker-core.styles.js +9 -0
  156. package/dist/shared/styles/select-item-suffix.css +4 -4
  157. package/dist/shared/styles/select-item.css +98 -0
  158. package/dist/shared/styles/select-item.styles.d.ts +8 -0
  159. package/dist/shared/styles/select-item.styles.d.ts.map +1 -0
  160. package/dist/shared/styles/select-item.styles.js +8 -0
  161. package/dist/shared/styles/visually-hidden.css +27 -0
  162. package/dist/shared/styles/visually-hidden.styles.d.ts +8 -0
  163. package/dist/shared/styles/visually-hidden.styles.d.ts.map +1 -0
  164. package/dist/shared/styles/visually-hidden.styles.js +8 -0
  165. package/dist/templates/elements/combobox.md +26 -1
  166. package/dist/templates/elements/disclosure.md +2 -0
  167. package/dist/templates/elements/dropdown.md +6 -6
  168. package/dist/templates/elements/form-field.md +2 -2
  169. package/dist/templates/elements/input-otp.md +3 -3
  170. package/dist/templates/elements/input.md +1 -0
  171. package/dist/templates/elements/popover.md +3 -3
  172. package/dist/templates/elements/select.md +30 -1
  173. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown-item.js","names":["unsafeCSS","rawStyles","hostStyles","nothing","_decorate","property","state","r","__decorate","A","host_styles_default","styles","DropdownItem","LuxenElement","_args","PopoverController","#_value_accessor_storage","#_disabled_accessor_storage","#_type_accessor_storage","#_variant_accessor_storage","#_checked_accessor_storage","#_submenuOpen_accessor_storage","#_checkPlacement_accessor_storage","#__hasSubmenu_accessor_storage","slot","el","tagName","value","node","child","changed","parsed","prop","panel","posOpts","isCheckbox","leadingCheck","n","r$1"],"sources":["../../../src/html/elements/dropdown-item/dropdown-item.css?inline","../../../src/html/elements/dropdown-item/dropdown-item.ts"],"sourcesContent":[":host {\n display: block;\n}\n\n:host([disabled]) {\n pointer-events: none;\n opacity: 0.5;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: 8px;\n box-sizing: border-box;\n min-block-size: 36px;\n padding: 0.375rem 0.5rem;\n cursor: pointer;\n outline: none;\n border-radius: 4px;\n font-size: 0.875rem;\n line-height: 1.5;\n color: var(--l-color-text-primary);\n white-space: nowrap;\n text-align: start;\n}\n\n.item:focus-visible {\n /* A ring distinct from the hover tint (which is the same low-contrast fill).\n Negative offset keeps the 2px ring inside the row so it never collides with\n the panel edge or a neighboring item. */\n background: var(--l-color-bg-state-hover);\n outline: 2px solid var(--l-focus-ring);\n outline-offset: -2px;\n}\n\n@media (hover: hover) {\n .item:hover {\n background: var(--l-color-bg-state-hover);\n }\n}\n\n/* Parent item stays highlighted while its submenu is open. */\n:host([submenu-open]) .item {\n background: var(--l-color-bg-state-hover);\n}\n\n/* Destructive variant — a delete-style action. Red label at rest, danger-tinted\n fill and focus ring on hover/focus so the highlight reads as \"danger\" rather\n than the neutral hover tint. */\n:host([variant='destructive']) .item {\n color: var(--l-color-text-danger);\n}\n\n:host([variant='destructive']) .item:focus-visible {\n background: var(--l-color-bg-fill-danger-soft);\n outline-color: var(--l-color-text-danger);\n}\n\n@media (hover: hover) {\n :host([variant='destructive']) .item:hover {\n background: var(--l-color-bg-fill-danger-soft);\n }\n}\n\n.check {\n display: flex;\n width: 16px;\n flex-shrink: 0;\n}\n\n/* Inline-end chevron marking an item that opens a submenu. */\n.submenu-indicator {\n inline-size: 16px;\n block-size: 16px;\n flex-shrink: 0;\n background-color: currentColor;\n mask: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 4l4 4-4 4' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\")\n no-repeat center / contain;\n}\n\n:host(:dir(rtl)) .submenu-indicator {\n scale: -1 1;\n}\n\n/* Submenu panel — mirrors the l-dropdown panel. The public custom properties\n (--padding, --background, --border-radius, --shadow) inherit from the\n ancestor l-dropdown through the light DOM, so a themed dropdown themes its\n submenus too; their fallbacks repeat the dropdown defaults for standalone use. */\n.submenu {\n inset: unset;\n overflow: visible;\n box-sizing: border-box;\n width: max-content;\n padding: var(--padding, 0.25rem);\n margin: 0;\n border: 1px solid var(--l-color-border-overlay);\n border-radius: var(--border-radius, 6px);\n background: var(--background, var(--l-color-surface-overlay));\n color: var(--l-color-text-primary);\n box-shadow: var(--shadow, 0 4px 6px -1px rgb(0 0 0 / 8%), 0 2px 4px -2px rgb(0 0 0 / 6%));\n font-size: 0.875rem;\n line-height: 1.5;\n}\n\n/* Lightweight separator alternative to <l-divider> — same dimensions, no extra import. */\nslot[name='submenu']::slotted(hr) {\n display: block;\n height: 1px;\n margin-block: var(--padding, 0.25rem);\n margin-inline: calc(var(--padding, 0.25rem) * -1);\n border: 0;\n background: var(--l-color-divider);\n}\n\n:host(:not([checked])) .check svg {\n visibility: hidden;\n}\n\n::slotted([slot='prefix']),\n::slotted([slot='suffix']) {\n display: flex;\n flex-shrink: 0;\n}\n\n.label {\n flex: 1;\n}\n","import { html, nothing, unsafeCSS, type PropertyValues } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { property, state } from 'lit/decorators.js';\nimport type { Placement } from '@floating-ui/dom';\nimport { PopoverController } from '../../shared/controllers/popover.js';\nimport { tagName } from '../../registry.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './dropdown-item.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * A menu item for use inside `<l-dropdown>`.\n *\n * @slot - Label text.\n * @slot prefix - Leading content (e.g. icon). A `type=\"checkbox\"` item ignores it unless `check-placement=\"end\"` frees the leading column.\n * @slot suffix - Trailing content.\n * @slot submenu - Nested `l-dropdown-item` elements rendered in a submenu panel anchored to this item. Drop an `<hr>` between them for a separator.\n *\n * @csspart submenu - The floating submenu panel.\n *\n * @cssproperty --color - Text color.\n *\n * @attribute variant - destructive — Renders the item as a destructive action (red), for delete-style entries.\n *\n * @customElement l-dropdown-item\n */\nexport class DropdownItem extends LuxenElement {\n static override styles = [hostStyles, styles];\n\n private _submenuFloating = new PopoverController(this, {\n getTriggerElement: () => this,\n getFloatingElement: () => this._submenuEl,\n getArrowElement: () => null,\n });\n\n /** The value associated with this item. */\n @property()\n accessor value = '';\n\n /** Disables the item. */\n @property({ type: Boolean, reflect: true })\n accessor disabled = false;\n\n /** The type of item: `normal` or `checkbox`. */\n @property()\n accessor type: 'normal' | 'checkbox' = 'normal';\n\n /** Visual variant. `destructive` marks a delete-style action in red. */\n @property({ reflect: true })\n accessor variant: 'destructive' | undefined = undefined;\n\n /** Whether the checkbox item is checked. */\n @property({ type: Boolean, reflect: true })\n accessor checked = false;\n\n /** Whether this item's submenu is open. Managed by the parent `l-dropdown`. */\n @property({ type: Boolean, reflect: true, attribute: 'submenu-open' })\n accessor submenuOpen = false;\n\n /**\n * Which side of a `type=\"checkbox\"` item carries the check mark. `start` (the\n * default) puts it in the leading column, where it takes the place of any\n * `prefix`. `end` moves it to the trailing edge, freeing that column so the\n * item can show its own icon alongside the state.\n */\n @property({ reflect: true, attribute: 'check-placement' })\n accessor checkPlacement: 'start' | 'end' = 'start';\n\n @state()\n private accessor _hasSubmenu = false;\n\n /** Whether this item has nested `slot=\"submenu\"` items. */\n get hasSubmenu(): boolean {\n return this._hasSubmenu;\n }\n\n override connectedCallback() {\n super.connectedCallback();\n // The host is a generic wrapper between the `role=\"menu\"` panel and the\n // `role=\"menuitem\"` row in its shadow root; `none` removes it from the\n // accessibility tree so the menu owns its menuitems directly (ARIA\n // required-owned-elements). The inner row keeps its menuitem role.\n // Guard preserves a consumer-set role.\n if (!this.hasAttribute('role')) this.setAttribute('role', 'none');\n }\n\n private get _submenuEl(): HTMLElement | null {\n return this.shadowRoot!.querySelector<HTMLElement>('.submenu');\n }\n\n /** Returns the text label of this item (excludes nested submenu items). */\n getTextLabel(): string {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) return (this.textContent ?? '').trim();\n return slot\n .assignedNodes({ flatten: true })\n .map((node) => node.textContent ?? '')\n .join('')\n .trim();\n }\n\n /** Returns the enabled `l-dropdown-item` elements slotted into this item's submenu. */\n getSubmenuItems(): DropdownItem[] {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"submenu\"]');\n if (!slot) return [];\n return (slot.assignedElements() as DropdownItem[]).filter(\n (el) => el.tagName === tagName('dropdown-item').toUpperCase() && !el.disabled,\n );\n }\n\n /** Opens this item's submenu panel. No-op without submenu items. */\n openSubmenu() {\n if (!this._hasSubmenu || this.disabled || this.submenuOpen) return;\n this.submenuOpen = true;\n }\n\n /** Closes this item's submenu panel, including any open nested submenus. */\n closeSubmenu() {\n for (const child of this.getSubmenuItems()) child.closeSubmenu();\n if (this.submenuOpen) this.submenuOpen = false;\n }\n\n override updated(changed: PropertyValues<this>) {\n if (changed.has('submenuOpen')) {\n void this._handleSubmenuOpenChange();\n }\n }\n\n private _getDuration(prop: '--show-duration' | '--hide-duration'): number {\n const parsed = parseFloat(getComputedStyle(this).getPropertyValue(prop));\n return Number.isNaN(parsed) ? 150 : parsed;\n }\n\n private async _handleSubmenuOpenChange() {\n const panel = this._submenuEl;\n if (!panel) return;\n\n const isRTL = getComputedStyle(this).direction === 'rtl';\n const posOpts = {\n placement: (isRTL ? 'left-start' : 'right-start') as Placement,\n distance: 0,\n // Pull the panel up by its own padding so its first item lines up with this item.\n skidding: -parseFloat(getComputedStyle(panel).paddingTop || '0'),\n };\n\n if (this.submenuOpen) {\n if (!this.isConnected) return;\n panel.showPopover();\n await this._submenuFloating.updatePosition(posOpts);\n if (!this.submenuOpen) return;\n await this._submenuFloating.animateShow(panel, this._getDuration('--show-duration'));\n this._submenuFloating.startPositioning(posOpts);\n } else {\n if (!panel.matches(':popover-open')) return;\n this._submenuFloating.stopPositioning();\n await this._submenuFloating.animateHide(panel, this._getDuration('--hide-duration'));\n if (panel.matches(':popover-open')) panel.hidePopover();\n }\n }\n\n private _renderCheck() {\n return html`\n <span\n class=\"check\"\n aria-hidden=\"true\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M3.5 8.5L6.5 11.5L12.5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n `;\n }\n\n private _onSubmenuSlotChange = (e: Event) => {\n const slot = e.target as HTMLSlotElement;\n this._hasSubmenu = slot\n .assignedElements()\n .some((el) => el.tagName === tagName('dropdown-item').toUpperCase());\n };\n\n override render() {\n const isCheckbox = this.type === 'checkbox';\n const leadingCheck = isCheckbox && this.checkPlacement === 'start';\n\n return html`\n <div\n class=\"item\"\n role=${isCheckbox ? 'menuitemcheckbox' : 'menuitem'}\n aria-checked=${isCheckbox ? String(this.checked) : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-haspopup=${this._hasSubmenu ? 'menu' : nothing}\n aria-expanded=${this._hasSubmenu ? String(this.submenuOpen) : nothing}\n aria-controls=${this._hasSubmenu ? 'submenu' : nothing}\n tabindex=\"-1\"\n >\n <!-- The check owns the leading column by default, which is why a\n checkbox item has no room for a prefix there. Moving it to the\n trailing edge frees that column, so an item can carry its own icon\n and still show whether it is on — a theme row with a sun/moon, a\n Show-grid row with a grid glyph. The aria-checked above is what\n assistive tech reads, and it is unaffected by where the mark sits.\n (No backticks in this comment: it lives inside a template literal.) -->\n ${leadingCheck ? this._renderCheck() : nothing}\n ${leadingCheck ? nothing : html`<slot name=\"prefix\"></slot>`}\n <span\n class=\"label\"\n id=\"label\"\n ><slot></slot\n ></span>\n <slot name=\"suffix\"></slot>\n ${isCheckbox && this.checkPlacement === 'end' ? this._renderCheck() : nothing}\n ${\n this._hasSubmenu\n ? html`<span\n class=\"submenu-indicator\"\n aria-hidden=\"true\"\n ></span>`\n : nothing\n }\n </div>\n <div\n class=\"submenu\"\n part=\"submenu\"\n id=\"submenu\"\n popover=\"manual\"\n role=\"menu\"\n aria-labelledby=\"label\"\n >\n <slot\n name=\"submenu\"\n @slotchange=${this._onSubmenuSlotChange}\n ></slot>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"dropdown-item.js","names":["unsafeCSS","rawStyles","hostStyles","menuPanelStyles","nothing","_decorate","property","state","r","__decorate","A","host_styles_default","menu_panel_styles_default","styles","DropdownItem","LuxenElement","_args","PopoverController","#_value_accessor_storage","#_disabled_accessor_storage","#_type_accessor_storage","#_variant_accessor_storage","#_checked_accessor_storage","#_submenuOpen_accessor_storage","#_checkPlacement_accessor_storage","#__hasSubmenu_accessor_storage","slot","el","tagName","value","node","child","changed","panel","posOpts","isCheckbox","leadingCheck","n","r$1"],"sources":["../../../src/html/elements/dropdown-item/dropdown-item.css?inline","../../../src/html/elements/dropdown-item/dropdown-item.ts"],"sourcesContent":[":host {\n display: block;\n}\n\n:host([disabled]) {\n pointer-events: none;\n opacity: 0.5;\n}\n\n.item {\n display: flex;\n align-items: center;\n gap: var(--l-menu-item-gap);\n min-block-size: var(--l-menu-item-min-height);\n padding: var(--l-menu-item-padding-block) var(--l-menu-item-padding-inline);\n cursor: pointer;\n outline: none;\n border-radius: var(--l-menu-item-border-radius);\n font-size: var(--l-popover-font-size);\n line-height: var(--l-popover-line-height);\n color: var(--l-color-text-primary);\n white-space: nowrap;\n text-align: start;\n}\n\n.item:focus-visible {\n /* A ring distinct from the hover tint (which is the same low-contrast fill).\n Negative offset keeps the 2px ring inside the row so it never collides with\n the panel edge or a neighboring item. */\n background: var(--l-color-bg-state-hover);\n outline: 2px solid var(--l-focus-ring);\n outline-offset: -2px;\n}\n\n@media (hover: hover) {\n .item:hover {\n background: var(--l-color-bg-state-hover);\n }\n}\n\n/* Parent item stays highlighted while its submenu is open. */\n:host([submenu-open]) .item {\n background: var(--l-color-bg-state-hover);\n}\n\n/* Destructive variant — a delete-style action. Red label at rest, danger-tinted\n fill and focus ring on hover/focus so the highlight reads as \"danger\" rather\n than the neutral hover tint. */\n:host([variant='destructive']) .item {\n color: var(--l-color-text-danger);\n}\n\n:host([variant='destructive']) .item:focus-visible {\n background: var(--l-color-bg-fill-danger-soft);\n outline-color: var(--l-color-text-danger);\n}\n\n@media (hover: hover) {\n :host([variant='destructive']) .item:hover {\n background: var(--l-color-bg-fill-danger-soft);\n }\n}\n\n.check {\n display: flex;\n width: 16px;\n flex-shrink: 0;\n}\n\n/* Inline-end chevron marking an item that opens a submenu. */\n.submenu-indicator {\n inline-size: 16px;\n block-size: 16px;\n flex-shrink: 0;\n background-color: currentColor;\n mask: url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M6 4l4 4-4 4' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E\")\n no-repeat center / contain;\n}\n\n:host(:dir(rtl)) .submenu-indicator {\n scale: -1 1;\n}\n\n/* The submenu panel and its <hr> separators: shared/styles/menu-panel.css. */\n\n:host(:not([checked])) .check svg {\n visibility: hidden;\n}\n\n::slotted([slot='prefix']),\n::slotted([slot='suffix']) {\n display: flex;\n flex-shrink: 0;\n}\n\n.label {\n flex: 1;\n}\n","import { html, nothing, unsafeCSS, type PropertyValues } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { property, state } from 'lit/decorators.js';\nimport type { Placement } from '@floating-ui/dom';\nimport { PopoverController } from '../../shared/controllers/popover.js';\nimport { tagName } from '../../registry.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport menuPanelStyles from '../../shared/styles/menu-panel.styles.js';\nimport rawStyles from './dropdown-item.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * A menu item for use inside `<l-dropdown>`.\n *\n * @slot - Label text.\n * @slot prefix - Leading content (e.g. icon). A `type=\"checkbox\"` item ignores it unless `check-placement=\"end\"` frees the leading column.\n * @slot suffix - Trailing content.\n * @slot submenu - Nested `l-dropdown-item` elements rendered in a submenu panel anchored to this item. Drop an `<hr>` between them for a separator.\n *\n * @csspart submenu - The floating submenu panel.\n *\n * @cssproperty --color - Text color.\n *\n * @attribute variant - destructive — Renders the item as a destructive action (red), for delete-style entries.\n *\n * @customElement l-dropdown-item\n */\nexport class DropdownItem extends LuxenElement {\n static override styles = [hostStyles, menuPanelStyles, styles];\n\n private _submenuFloating = new PopoverController(this, {\n getTriggerElement: () => this,\n getFloatingElement: () => this._submenuEl,\n getArrowElement: () => null,\n });\n\n /** The value associated with this item. */\n @property()\n accessor value = '';\n\n /** Disables the item. */\n @property({ type: Boolean, reflect: true })\n accessor disabled = false;\n\n /** The type of item: `normal` or `checkbox`. */\n @property()\n accessor type: 'normal' | 'checkbox' = 'normal';\n\n /** Visual variant. `destructive` marks a delete-style action in red. */\n @property({ reflect: true })\n accessor variant: 'destructive' | undefined = undefined;\n\n /** Whether the checkbox item is checked. */\n @property({ type: Boolean, reflect: true })\n accessor checked = false;\n\n /** Whether this item's submenu is open. Managed by the parent `l-dropdown`. */\n @property({ type: Boolean, reflect: true, attribute: 'submenu-open' })\n accessor submenuOpen = false;\n\n /**\n * Which side of a `type=\"checkbox\"` item carries the check mark. `start` (the\n * default) puts it in the leading column, where it takes the place of any\n * `prefix`. `end` moves it to the trailing edge, freeing that column so the\n * item can show its own icon alongside the state.\n */\n @property({ reflect: true, attribute: 'check-placement' })\n accessor checkPlacement: 'start' | 'end' = 'start';\n\n @state()\n private accessor _hasSubmenu = false;\n\n /** Whether this item has nested `slot=\"submenu\"` items. */\n get hasSubmenu(): boolean {\n return this._hasSubmenu;\n }\n\n override connectedCallback() {\n super.connectedCallback();\n // The host is a generic wrapper between the `role=\"menu\"` panel and the\n // `role=\"menuitem\"` row in its shadow root; `none` removes it from the\n // accessibility tree so the menu owns its menuitems directly (ARIA\n // required-owned-elements). The inner row keeps its menuitem role.\n // Guard preserves a consumer-set role.\n if (!this.hasAttribute('role')) this.setAttribute('role', 'none');\n }\n\n private get _submenuEl(): HTMLElement | null {\n return this.shadowRoot!.querySelector<HTMLElement>('.submenu');\n }\n\n /** Returns the text label of this item (excludes nested submenu items). */\n getTextLabel(): string {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) return (this.textContent ?? '').trim();\n return slot\n .assignedNodes({ flatten: true })\n .map((node) => node.textContent ?? '')\n .join('')\n .trim();\n }\n\n /** Returns the enabled `l-dropdown-item` elements slotted into this item's submenu. */\n getSubmenuItems(): DropdownItem[] {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"submenu\"]');\n if (!slot) return [];\n return (slot.assignedElements() as DropdownItem[]).filter(\n (el) => el.tagName === tagName('dropdown-item').toUpperCase() && !el.disabled,\n );\n }\n\n /** Opens this item's submenu panel. No-op without submenu items. */\n openSubmenu() {\n if (!this._hasSubmenu || this.disabled || this.submenuOpen) return;\n this.submenuOpen = true;\n }\n\n /** Closes this item's submenu panel, including any open nested submenus. */\n closeSubmenu() {\n for (const child of this.getSubmenuItems()) child.closeSubmenu();\n if (this.submenuOpen) this.submenuOpen = false;\n }\n\n override updated(changed: PropertyValues<this>) {\n if (changed.has('submenuOpen')) {\n void this._handleSubmenuOpenChange();\n }\n }\n\n private async _handleSubmenuOpenChange() {\n const panel = this._submenuEl;\n if (!panel) return;\n\n const isRTL = getComputedStyle(this).direction === 'rtl';\n const posOpts = {\n placement: (isRTL ? 'left-start' : 'right-start') as Placement,\n distance: 0,\n // Pull the panel up by its own padding so its first item lines up with this item.\n skidding: -parseFloat(getComputedStyle(panel).paddingTop || '0'),\n };\n\n if (this.submenuOpen) {\n if (!this.isConnected) return;\n panel.showPopover();\n await this._submenuFloating.updatePosition(posOpts);\n if (!this.submenuOpen) return;\n await this._submenuFloating.animateShow(panel);\n this._submenuFloating.startPositioning(posOpts);\n } else {\n if (!panel.matches(':popover-open')) return;\n this._submenuFloating.stopPositioning();\n await this._submenuFloating.animateHide(panel);\n if (panel.matches(':popover-open')) panel.hidePopover();\n }\n }\n\n private _renderCheck() {\n return html`\n <span\n class=\"check\"\n aria-hidden=\"true\"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n >\n <path\n d=\"M3.5 8.5L6.5 11.5L12.5 4.5\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </span>\n `;\n }\n\n private _onSubmenuSlotChange = (e: Event) => {\n const slot = e.target as HTMLSlotElement;\n this._hasSubmenu = slot\n .assignedElements()\n .some((el) => el.tagName === tagName('dropdown-item').toUpperCase());\n };\n\n override render() {\n const isCheckbox = this.type === 'checkbox';\n const leadingCheck = isCheckbox && this.checkPlacement === 'start';\n\n return html`\n <div\n class=\"item\"\n role=${isCheckbox ? 'menuitemcheckbox' : 'menuitem'}\n aria-checked=${isCheckbox ? String(this.checked) : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-haspopup=${this._hasSubmenu ? 'menu' : nothing}\n aria-expanded=${this._hasSubmenu ? String(this.submenuOpen) : nothing}\n aria-controls=${this._hasSubmenu ? 'submenu' : nothing}\n tabindex=\"-1\"\n >\n <!-- The check owns the leading column by default, which is why a\n checkbox item has no room for a prefix there. Moving it to the\n trailing edge frees that column, so an item can carry its own icon\n and still show whether it is on — a theme row with a sun/moon, a\n Show-grid row with a grid glyph. The aria-checked above is what\n assistive tech reads, and it is unaffected by where the mark sits.\n (No backticks in this comment: it lives inside a template literal.) -->\n ${leadingCheck ? this._renderCheck() : nothing}\n ${leadingCheck ? nothing : html`<slot name=\"prefix\"></slot>`}\n <span\n class=\"label\"\n id=\"label\"\n ><slot></slot\n ></span>\n <slot name=\"suffix\"></slot>\n ${isCheckbox && this.checkPlacement === 'end' ? this._renderCheck() : nothing}\n ${\n this._hasSubmenu\n ? html`<span\n class=\"submenu-indicator\"\n aria-hidden=\"true\"\n ></span>`\n : nothing\n }\n </div>\n <div\n class=\"submenu\"\n part=\"submenu\"\n id=\"submenu\"\n popover=\"manual\"\n role=\"menu\"\n aria-labelledby=\"label\"\n >\n <slot\n name=\"submenu\"\n @slotchange=${this._onSubmenuSlotChange}\n ></slot>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import{i as e}from"../../chunks/lit.js";import{a as t}from"../../chunks/lit-html.js";import{LuxenElement as n}from"../../shared/luxen-element.js";import r from"../../shared/styles/host.styles.js";var i=e(`:host{--color:var(--l-color-text-tertiary);display:block}.label{font-size:.6875rem;font-weight:var(--l-font-weight-semibold);letter-spacing:.03em;text-transform:uppercase;color:var(--color);white-space:nowrap;-webkit-user-select:none;user-select:none;padding:.375rem .5rem .125rem;line-height:1.4}`),a=class extends n{static{this.styles=[r,i]}connectedCallback(){super.connectedCallback(),this.setAttribute(`role`,`presentation`)}render(){return t`<div class="label">
1
+ import{i as e}from"../../chunks/lit.js";import{a as t}from"../../chunks/lit-html.js";import{LuxenElement as n}from"../../shared/luxen-element.js";import r from"../../shared/styles/host.styles.js";var i=e(`:host{--color:var(--l-color-text-tertiary);display:block}.label{padding:var(--l-menu-item-padding-block) var(--l-menu-item-padding-inline) .125rem;font-size:.6875rem;font-weight:var(--l-font-weight-semibold);letter-spacing:.03em;text-transform:uppercase;color:var(--color);white-space:nowrap;-webkit-user-select:none;user-select:none;line-height:1.4}`),a=class extends n{static{this.styles=[r,i]}connectedCallback(){super.connectedCallback(),this.setAttribute(`role`,`presentation`)}render(){return t`<div class="label">
2
2
  <slot></slot>
3
3
  </div>`}};export{a as DropdownLabel};
4
4
  //# sourceMappingURL=dropdown-label.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dropdown-label.js","names":["unsafeCSS","rawStyles","hostStyles","r","b","host_styles_default","styles","DropdownLabel","LuxenElement"],"sources":["../../../src/html/elements/dropdown-label/dropdown-label.css?inline","../../../src/html/elements/dropdown-label/dropdown-label.ts"],"sourcesContent":[":host {\n display: block;\n --color: var(--l-color-text-tertiary);\n}\n\n.label {\n /* Inline padding aligns with dropdown-item's `0.375rem 0.5rem` so labels and\n items line up; extra top padding adds breathing room above each section. */\n padding: 0.375rem 0.5rem 0.125rem;\n font-size: 0.6875rem; /* 11px */\n font-weight: var(--l-font-weight-semibold);\n letter-spacing: 0.03em;\n text-transform: uppercase;\n line-height: 1.4;\n color: var(--color);\n white-space: nowrap;\n user-select: none;\n}\n","import { html, unsafeCSS, type CSSResultGroup } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './dropdown-label.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * A non-interactive section label for grouping items inside `<l-dropdown>`.\n *\n * @slot - Label text.\n *\n * @cssproperty --color - Text color. Defaults to `var(--l-color-text-tertiary)`.\n *\n * @customElement l-dropdown-label\n */\nexport class DropdownLabel extends LuxenElement {\n static override styles: CSSResultGroup = [hostStyles, styles];\n\n override connectedCallback() {\n super.connectedCallback();\n // Set the role on the host — that's the node that lands in the\n // `role=\"menu\"` light-DOM subtree (mirrors `l-divider`'s `role=\"separator\"`).\n // A role on the shadow-DOM `.label` <div> would not change how the host is\n // announced. `presentation` keeps the label out of menu-item navigation\n // while its text is still read as plain content.\n this.setAttribute('role', 'presentation');\n }\n\n override render() {\n return html`<div class=\"label\">\n <slot></slot>\n </div>`;\n }\n}\n"],"mappings":"A,oMCKA,IAAMM,EAASN,EAAUC,2SAAS,EAWrBM,EAAb,cAAmCC,CAAa,C,OACL,KAAA,OAAA,CAACN,EAAYI,CAAM,C,CAE5D,mBAA6B,CAC3B,MAAM,kBAAkB,EAMxB,KAAK,aAAa,OAAQ,cAAc,CAC1C,CAEA,QAAkB,CAChB,MAAO,EAAI;;WAGb,CACF,E"}
1
+ {"version":3,"file":"dropdown-label.js","names":["unsafeCSS","rawStyles","hostStyles","r","b","host_styles_default","styles","DropdownLabel","LuxenElement"],"sources":["../../../src/html/elements/dropdown-label/dropdown-label.css?inline","../../../src/html/elements/dropdown-label/dropdown-label.ts"],"sourcesContent":[":host {\n display: block;\n --color: var(--l-color-text-tertiary);\n}\n\n.label {\n /* Same block-start and inline padding as l-dropdown-item, so labels and items\n line up; a tighter block-end keeps each label close to its section. */\n padding: var(--l-menu-item-padding-block) var(--l-menu-item-padding-inline) 0.125rem;\n font-size: 0.6875rem; /* 11px */\n font-weight: var(--l-font-weight-semibold);\n letter-spacing: 0.03em;\n text-transform: uppercase;\n line-height: 1.4;\n color: var(--color);\n white-space: nowrap;\n user-select: none;\n}\n","import { html, unsafeCSS, type CSSResultGroup } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './dropdown-label.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * A non-interactive section label for grouping items inside `<l-dropdown>`.\n *\n * @slot - Label text.\n *\n * @cssproperty --color - Text color. Defaults to `var(--l-color-text-tertiary)`.\n *\n * @customElement l-dropdown-label\n */\nexport class DropdownLabel extends LuxenElement {\n static override styles: CSSResultGroup = [hostStyles, styles];\n\n override connectedCallback() {\n super.connectedCallback();\n // Set the role on the host — that's the node that lands in the\n // `role=\"menu\"` light-DOM subtree (mirrors `l-divider`'s `role=\"separator\"`).\n // A role on the shadow-DOM `.label` <div> would not change how the host is\n // announced. `presentation` keeps the label out of menu-item navigation\n // while its text is still read as plain content.\n this.setAttribute('role', 'presentation');\n }\n\n override render() {\n return html`<div class=\"label\">\n <slot></slot>\n </div>`;\n }\n}\n"],"mappings":"A,oMCKA,IAAMM,EAASN,EAAUC,gWAAS,EAWrBM,EAAb,cAAmCC,CAAa,C,OACL,KAAA,OAAA,CAACN,EAAYI,CAAM,C,CAE5D,mBAA6B,CAC3B,MAAM,kBAAkB,EAMxB,KAAK,aAAa,OAAQ,cAAc,CAC1C,CAEA,QAAkB,CAChB,MAAO,EAAI;;WAGb,CACF,E"}
@@ -2,7 +2,7 @@ import { LuxenElement } from '../../shared/luxen-element.js';
2
2
  /**
3
3
  * @summary Progressively enhances a label + control + messages group: wires the
4
4
  * accessibility plumbing (`id`/`for`, `aria-describedby`, `aria-invalid`,
5
- * required marker) and picks an inline or stacked layout from the control type.
5
+ * required indicator) and picks an inline or stacked layout from the control type.
6
6
  *
7
7
  * Styling stays on the control (`.l-checkbox`, …); inside a field a bare control
8
8
  * is auto-styled by the element CSS. Add `unstyled` to keep the ARIA wiring while
@@ -1 +1 @@
1
- {"version":3,"file":"form-field.js","names":["_decorate","property","n","CONTROL_SELECTOR","FormField","LuxenElement","_args","event","control","el","tag","cls","uniqueId","label","managed","id","isToggle","preInvalid","native","showError","ids","__decorate"],"sources":["../../../src/html/elements/form-field/form-field.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { cls, uniqueId } from '../../registry.js';\n\ntype NativeControl = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n/** A form-associated custom element (e.g. `l-slider`) exposes the same constraint\n * surface as a native control but doesn't match the native selector. */\ntype FormControl =\n | NativeControl\n | (HTMLElement & { checkValidity(): boolean; readonly validity?: ValidityState });\n\nconst CONTROL_SELECTOR = 'input, select, textarea';\n\n/**\n * @summary Progressively enhances a label + control + messages group: wires the\n * accessibility plumbing (`id`/`for`, `aria-describedby`, `aria-invalid`,\n * required marker) and picks an inline or stacked layout from the control type.\n *\n * Styling stays on the control (`.l-checkbox`, …); inside a field a bare control\n * is auto-styled by the element CSS. Add `unstyled` to keep the ARIA wiring while\n * opting out of that auto-styling (e.g. for a third-party control).\n *\n * @example\n * ```html\n * <l-form-field>\n * <label>Subscribe to the newsletter</label>\n * <input type=\"checkbox\" />\n * <p class=\"l-hint\">One email a month, unsubscribe anytime.</p>\n * <p class=\"l-error\">Please make a choice to continue.</p>\n * </l-form-field>\n * ```\n *\n * @slot - A `<label>`, one form control (a native `input` / `select` /\n * `textarea`, or a form-associated custom element such as `l-slider`), and\n * optional `.l-hint` / `.l-error` message elements, in any order.\n *\n * @cssClass .l-hint - Helper text element. Always visible; linked via `aria-describedby`.\n * @cssClass .l-error - Error message element. Hidden until invalid, then revealed with `role=\"alert\"` and linked via `aria-describedby`.\n *\n * @customElement l-form-field\n */\nexport class FormField extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n /** Layout, derived from the control type (`inline` for checkbox/radio/switch, otherwise `stacked`). Set one to force it. */\n @property({ reflect: true })\n layout?: 'inline' | 'stacked';\n\n /** Reflected when the control is required. Drives the label marker. */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /** Reflected when the control is not required. */\n @property({ type: Boolean, reflect: true })\n optional = false;\n\n /** Reflected once the control is invalid after interaction (or set to force the invalid state). */\n @property({ type: Boolean, reflect: true })\n invalid = false;\n\n /** Opt out of auto-styling the control; the ARIA wiring is preserved. */\n @property({ type: Boolean, reflect: true })\n unstyled = false;\n\n private _control: FormControl | null = null;\n private _hint: HTMLElement | null = null;\n private _error: HTMLElement | null = null;\n private _hasInteracted = false;\n private _wired = false;\n /** describedby ids set by the author that we must preserve. */\n private _externalDescribedby: string[] = [];\n\n override connectedCallback() {\n super.connectedCallback();\n // Run synchronously when the children are already parsed (the common case:\n // the element is defined after its markup). Fall back to a macrotask — which,\n // unlike requestAnimationFrame, still fires in a hidden tab — if the element\n // upgrades mid-parse before its children exist.\n if (this._setup()) return;\n setTimeout(() => this._setup(), 0);\n // A custom-element control (e.g. l-slider) can upgrade after us — its module\n // may load lazily — so the macrotask retry can still miss it. Re-attempt once\n // each pending custom-element child is defined. `_setup()` is idempotent via\n // `_wired`, so the earliest successful attempt wins.\n for (const el of this.querySelectorAll('*')) {\n const tag = el.localName;\n if (tag.includes('-') && !customElements.get(tag)) {\n void customElements.whenDefined(tag).then(() => this._setup());\n }\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._teardown();\n this._wired = false;\n }\n\n private _setup(): boolean {\n if (this._wired) return true;\n this._control = this._findControl();\n if (!this._control) return false;\n this._wired = true;\n const control = this._control;\n\n // Consumer-authored markup, so these carry the consumer's configured\n // `cssPrefix` — match on `cls()`, not a hardcoded `.l-hint` / `.l-error`.\n this._hint = this.querySelector(`.${cls('hint')}`);\n this._error = this.querySelector(`.${cls('error')}`);\n // The error is announced when revealed; the field owns this (the message is\n // a plain element with no JS of its own).\n if (this._error && !this._error.hasAttribute('role')) {\n this._error.setAttribute('role', 'alert');\n }\n\n // id / label[for]\n if (!control.id) control.id = uniqueId('field');\n const label = this.querySelector('label');\n if (label && !label.htmlFor && !label.contains(control)) {\n label.htmlFor = control.id;\n }\n\n // Ensure message elements have ids for aria-describedby.\n if (this._hint && !this._hint.id) this._hint.id = uniqueId('hint');\n if (this._error && !this._error.id) this._error.id = uniqueId('error');\n\n // Capture author-provided describedby ids (minus our managed ones).\n const managed = new Set([this._hint?.id, this._error?.id].filter(Boolean) as string[]);\n this._externalDescribedby = (control.getAttribute('aria-describedby') ?? '')\n .split(/\\s+/)\n .filter((id) => id && !managed.has(id));\n\n // Layout from control type (unless explicitly forced).\n if (!this.layout) {\n const isToggle =\n control.tagName === 'INPUT' &&\n (['checkbox', 'radio'].includes((control as HTMLInputElement).type) ||\n control.getAttribute('role') === 'switch');\n this.layout = isToggle ? 'inline' : 'stacked';\n }\n\n // Required marker (control is the source of truth).\n this.required = control.hasAttribute('required');\n this.optional = !this.required;\n\n // The error stays hidden until the field is invalid after interaction (or is\n // already flagged invalid by the author / server). Visibility is owned by CSS\n // off the reflected `invalid` state — the field never toggles `hidden`.\n const preInvalid = this.invalid || control.getAttribute('aria-invalid') === 'true';\n this._hasInteracted = preInvalid;\n\n control.addEventListener('invalid', this._onInvalid);\n control.addEventListener('blur', this._onInteract);\n control.addEventListener('change', this._onInteract);\n control.addEventListener('input', this._onInteract);\n\n this._updateValidity();\n return true;\n }\n\n /**\n * The field's control: a native `input`/`select`/`textarea`, or — when none is\n * present — the first form-associated custom element (e.g. `l-slider`). Those\n * expose the same `checkValidity()` / `invalid` event surface but don't match\n * the native selector, so without this fallback the field never wires up and\n * the `l-error` message stays visible on load.\n */\n private _findControl(): FormControl | null {\n const native = this.querySelector<NativeControl>(CONTROL_SELECTOR);\n if (native) return native;\n for (const el of this.querySelectorAll<HTMLElement>('*')) {\n if ((el.constructor as { formAssociated?: boolean }).formAssociated) {\n return el as FormControl;\n }\n }\n return null;\n }\n\n private _teardown() {\n const control = this._control;\n if (!control) return;\n control.removeEventListener('invalid', this._onInvalid);\n control.removeEventListener('blur', this._onInteract);\n control.removeEventListener('change', this._onInteract);\n control.removeEventListener('input', this._onInteract);\n }\n\n private _onInvalid = (event: Event) => {\n // Suppress the native validation bubble in favour of `l-error`.\n event.preventDefault();\n this._hasInteracted = true;\n const control = this._control;\n if (!control) return;\n // Never `checkValidity()` here: it fires another `invalid`, landing back\n // in this listener. `validity` reads the state without firing anything; a\n // control without it is taken at the event's word.\n this._showError(control, !(control.validity?.valid ?? false));\n };\n\n private _onInteract = () => {\n this._hasInteracted = true;\n this._updateValidity();\n };\n\n private _updateValidity() {\n const control = this._control;\n if (!control) return;\n // `validity` reads the state without firing `invalid`. `checkValidity()`\n // fires it, so it's only the fallback for a control without `validity`,\n // and only once the user has interacted: on load it would reveal the error.\n const showError = this._hasInteracted && !(control.validity?.valid ?? control.checkValidity());\n this._showError(control, showError);\n }\n\n private _showError(control: FormControl, showError: boolean) {\n // `invalid` reflects to the host; CSS reveals `.l-error` from there.\n this.invalid = showError;\n if (showError) control.setAttribute('aria-invalid', 'true');\n else control.removeAttribute('aria-invalid');\n\n this._updateDescribedby();\n }\n\n private _updateDescribedby() {\n const control = this._control;\n if (!control) return;\n const ids = [...this._externalDescribedby];\n if (this._hint?.id) ids.push(this._hint.id);\n if (this._error && this.invalid && this._error.id) ids.push(this._error.id);\n if (ids.length) control.setAttribute('aria-describedby', ids.join(' '));\n else control.removeAttribute('aria-describedby');\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"form-field.js","names":["_decorate","property","n","CONTROL_SELECTOR","FormField","LuxenElement","_args","event","control","el","tag","cls","uniqueId","label","managed","id","isToggle","preInvalid","native","showError","ids","__decorate"],"sources":["../../../src/html/elements/form-field/form-field.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { cls, uniqueId } from '../../registry.js';\n\ntype NativeControl = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;\n/** A form-associated custom element (e.g. `l-slider`) exposes the same constraint\n * surface as a native control but doesn't match the native selector. */\ntype FormControl =\n | NativeControl\n | (HTMLElement & { checkValidity(): boolean; readonly validity?: ValidityState });\n\nconst CONTROL_SELECTOR = 'input, select, textarea';\n\n/**\n * @summary Progressively enhances a label + control + messages group: wires the\n * accessibility plumbing (`id`/`for`, `aria-describedby`, `aria-invalid`,\n * required indicator) and picks an inline or stacked layout from the control type.\n *\n * Styling stays on the control (`.l-checkbox`, …); inside a field a bare control\n * is auto-styled by the element CSS. Add `unstyled` to keep the ARIA wiring while\n * opting out of that auto-styling (e.g. for a third-party control).\n *\n * @example\n * ```html\n * <l-form-field>\n * <label>Subscribe to the newsletter</label>\n * <input type=\"checkbox\" />\n * <p class=\"l-hint\">One email a month, unsubscribe anytime.</p>\n * <p class=\"l-error\">Please make a choice to continue.</p>\n * </l-form-field>\n * ```\n *\n * @slot - A `<label>`, one form control (a native `input` / `select` /\n * `textarea`, or a form-associated custom element such as `l-slider`), and\n * optional `.l-hint` / `.l-error` message elements, in any order.\n *\n * @cssClass .l-hint - Helper text element. Always visible; linked via `aria-describedby`.\n * @cssClass .l-error - Error message element. Hidden until invalid, then revealed with `role=\"alert\"` and linked via `aria-describedby`.\n *\n * @customElement l-form-field\n */\nexport class FormField extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n /** Layout, derived from the control type (`inline` for checkbox/radio/switch, otherwise `stacked`). Set one to force it. */\n @property({ reflect: true })\n layout?: 'inline' | 'stacked';\n\n /** Reflected when the control is required. Drives the label marker. */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /** Reflected when the control is not required. */\n @property({ type: Boolean, reflect: true })\n optional = false;\n\n /** Reflected once the control is invalid after interaction (or set to force the invalid state). */\n @property({ type: Boolean, reflect: true })\n invalid = false;\n\n /** Opt out of auto-styling the control; the ARIA wiring is preserved. */\n @property({ type: Boolean, reflect: true })\n unstyled = false;\n\n private _control: FormControl | null = null;\n private _hint: HTMLElement | null = null;\n private _error: HTMLElement | null = null;\n private _hasInteracted = false;\n private _wired = false;\n /** describedby ids set by the author that we must preserve. */\n private _externalDescribedby: string[] = [];\n\n override connectedCallback() {\n super.connectedCallback();\n // Run synchronously when the children are already parsed (the common case:\n // the element is defined after its markup). Fall back to a macrotask — which,\n // unlike requestAnimationFrame, still fires in a hidden tab — if the element\n // upgrades mid-parse before its children exist.\n if (this._setup()) return;\n setTimeout(() => this._setup(), 0);\n // A custom-element control (e.g. l-slider) can upgrade after us — its module\n // may load lazily — so the macrotask retry can still miss it. Re-attempt once\n // each pending custom-element child is defined. `_setup()` is idempotent via\n // `_wired`, so the earliest successful attempt wins.\n for (const el of this.querySelectorAll('*')) {\n const tag = el.localName;\n if (tag.includes('-') && !customElements.get(tag)) {\n void customElements.whenDefined(tag).then(() => this._setup());\n }\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n this._teardown();\n this._wired = false;\n }\n\n private _setup(): boolean {\n if (this._wired) return true;\n this._control = this._findControl();\n if (!this._control) return false;\n this._wired = true;\n const control = this._control;\n\n // Consumer-authored markup, so these carry the consumer's configured\n // `cssPrefix` — match on `cls()`, not a hardcoded `.l-hint` / `.l-error`.\n this._hint = this.querySelector(`.${cls('hint')}`);\n this._error = this.querySelector(`.${cls('error')}`);\n // The error is announced when revealed; the field owns this (the message is\n // a plain element with no JS of its own).\n if (this._error && !this._error.hasAttribute('role')) {\n this._error.setAttribute('role', 'alert');\n }\n\n // id / label[for]\n if (!control.id) control.id = uniqueId('field');\n const label = this.querySelector('label');\n if (label && !label.htmlFor && !label.contains(control)) {\n label.htmlFor = control.id;\n }\n\n // Ensure message elements have ids for aria-describedby.\n if (this._hint && !this._hint.id) this._hint.id = uniqueId('hint');\n if (this._error && !this._error.id) this._error.id = uniqueId('error');\n\n // Capture author-provided describedby ids (minus our managed ones).\n const managed = new Set([this._hint?.id, this._error?.id].filter(Boolean) as string[]);\n this._externalDescribedby = (control.getAttribute('aria-describedby') ?? '')\n .split(/\\s+/)\n .filter((id) => id && !managed.has(id));\n\n // Layout from control type (unless explicitly forced).\n if (!this.layout) {\n const isToggle =\n control.tagName === 'INPUT' &&\n (['checkbox', 'radio'].includes((control as HTMLInputElement).type) ||\n control.getAttribute('role') === 'switch');\n this.layout = isToggle ? 'inline' : 'stacked';\n }\n\n // Required indicator (control is the source of truth).\n this.required = control.hasAttribute('required');\n this.optional = !this.required;\n\n // The error stays hidden until the field is invalid after interaction (or is\n // already flagged invalid by the author / server). Visibility is owned by CSS\n // off the reflected `invalid` state — the field never toggles `hidden`.\n const preInvalid = this.invalid || control.getAttribute('aria-invalid') === 'true';\n this._hasInteracted = preInvalid;\n\n control.addEventListener('invalid', this._onInvalid);\n control.addEventListener('blur', this._onInteract);\n control.addEventListener('change', this._onInteract);\n control.addEventListener('input', this._onInteract);\n\n this._updateValidity();\n return true;\n }\n\n /**\n * The field's control: a native `input`/`select`/`textarea`, or — when none is\n * present — the first form-associated custom element (e.g. `l-slider`). Those\n * expose the same `checkValidity()` / `invalid` event surface but don't match\n * the native selector, so without this fallback the field never wires up and\n * the `l-error` message stays visible on load.\n */\n private _findControl(): FormControl | null {\n const native = this.querySelector<NativeControl>(CONTROL_SELECTOR);\n if (native) return native;\n for (const el of this.querySelectorAll<HTMLElement>('*')) {\n if ((el.constructor as { formAssociated?: boolean }).formAssociated) {\n return el as FormControl;\n }\n }\n return null;\n }\n\n private _teardown() {\n const control = this._control;\n if (!control) return;\n control.removeEventListener('invalid', this._onInvalid);\n control.removeEventListener('blur', this._onInteract);\n control.removeEventListener('change', this._onInteract);\n control.removeEventListener('input', this._onInteract);\n }\n\n private _onInvalid = (event: Event) => {\n // Suppress the native validation bubble in favour of `l-error`.\n event.preventDefault();\n this._hasInteracted = true;\n const control = this._control;\n if (!control) return;\n // Never `checkValidity()` here: it fires another `invalid`, landing back\n // in this listener. `validity` reads the state without firing anything; a\n // control without it is taken at the event's word.\n this._showError(control, !(control.validity?.valid ?? false));\n };\n\n private _onInteract = () => {\n this._hasInteracted = true;\n this._updateValidity();\n };\n\n private _updateValidity() {\n const control = this._control;\n if (!control) return;\n // `validity` reads the state without firing `invalid`. `checkValidity()`\n // fires it, so it's only the fallback for a control without `validity`,\n // and only once the user has interacted: on load it would reveal the error.\n const showError = this._hasInteracted && !(control.validity?.valid ?? control.checkValidity());\n this._showError(control, showError);\n }\n\n private _showError(control: FormControl, showError: boolean) {\n // `invalid` reflects to the host; CSS reveals `.l-error` from there.\n this.invalid = showError;\n if (showError) control.setAttribute('aria-invalid', 'true');\n else control.removeAttribute('aria-invalid');\n\n this._updateDescribedby();\n }\n\n private _updateDescribedby() {\n const control = this._control;\n if (!control) return;\n const ids = [...this._externalDescribedby];\n if (this._hint?.id) ids.push(this._hint.id);\n if (this._error && this.invalid && this._error.id) ids.push(this._error.id);\n if (ids.length) control.setAttribute('aria-describedby', ids.join(' '));\n else control.removeAttribute('aria-describedby');\n }\n}\n"],"mappings":"A,kKAWA,IAAMG,EAAmB,0BA8BZC,EAAb,cAA+BC,CAAa,C,8BAW/B,KAAA,SAAA,GAIA,KAAA,SAAA,GAID,KAAA,QAAA,GAIC,KAAA,SAAA,GAE4B,KAAA,SAAA,KACH,KAAA,MAAA,KACC,KAAA,OAAA,KACZ,KAAA,eAAA,GACR,KAAA,OAAA,GAEwB,KAAA,qBAAA,CAAC,EAqHpB,KAAA,WAAA,GAAiB,CAErCE,EAAM,eAAe,EACrB,KAAK,eAAiB,GACtB,IAAMC,EAAU,KAAK,SAChBA,GAIL,KAAK,WAAWA,EAAS,EAAEA,EAAQ,UAAU,OAAS,GAAM,CAC9D,EAE4B,KAAA,gBAAA,CAC1B,KAAK,eAAiB,GACtB,KAAK,gBAAgB,CACvB,C,CAlKA,kBAA4B,CAC1B,OAAO,IACT,CA8BA,mBAA6B,CAM3B,GALA,MAAM,kBAAkB,EAKpB,MAAK,OAAO,EAChB,gBAAiB,KAAK,OAAO,EAAG,CAAC,EAKjC,IAAK,IAAMC,KAAM,KAAK,iBAAiB,GAAG,EAAG,CAC3C,IAAMC,EAAMD,EAAG,UACXC,EAAI,SAAS,GAAG,GAAK,CAAC,eAAe,IAAIA,CAAG,GAC9C,eAAoB,YAAYA,CAAG,CAAC,CAAC,SAAW,KAAK,OAAO,CAAC,CAEjE,CAViC,CAWnC,CAEA,sBAAgC,CAC9B,MAAM,qBAAqB,EAC3B,KAAK,UAAU,EACf,KAAK,OAAS,EAChB,CAEA,QAA0B,CACxB,GAAI,KAAK,OAAQ,MAAO,GAExB,GADA,KAAK,SAAW,KAAK,aAAa,EAC9B,CAAC,KAAK,SAAU,MAAO,GAC3B,KAAK,OAAS,GACd,IAAMF,EAAU,KAAK,SAIrB,KAAK,MAAQ,KAAK,cAAc,IAAIG,EAAI,MAAM,GAAG,EACjD,KAAK,OAAS,KAAK,cAAc,IAAIA,EAAI,OAAO,GAAG,EAG/C,KAAK,QAAU,CAAC,KAAK,OAAO,aAAa,MAAM,GACjD,KAAK,OAAO,aAAa,OAAQ,OAAO,EAI1C,AAAiBH,EAAQ,KAAKI,EAAS,OAAO,EAC9C,IAAMC,EAAQ,KAAK,cAAc,OAAO,EACpCA,GAAS,CAACA,EAAM,SAAW,CAACA,EAAM,SAASL,CAAO,IACpD,EAAM,QAAUA,EAAQ,IAItB,KAAK,OAAS,CAAC,KAAK,MAAM,KAAI,KAAK,MAAM,GAAKI,EAAS,MAAM,GAC7D,KAAK,QAAU,CAAC,KAAK,OAAO,KAAI,KAAK,OAAO,GAAKA,EAAS,OAAO,GAGrE,IAAME,EAAU,IAAI,IAAI,CAAC,KAAK,OAAO,GAAI,KAAK,QAAQ,EAAE,CAAC,CAAC,OAAO,OAAO,CAAa,EAMrF,GALA,KAAK,sBAAwBN,EAAQ,aAAa,kBAAkB,GAAK,GAAA,CACtE,MAAM,KAAK,CAAC,CACZ,OAAQ,GAAOO,GAAM,CAACD,EAAQ,IAAIC,CAAE,CAAC,EAGpC,CAAC,KAAK,OAAQ,CAChB,IAAMC,EACJR,EAAQ,UAAY,UACnB,CAAC,WAAY,OAAO,CAAC,CAAC,SAAUA,EAA6B,IAAI,GAChEA,EAAQ,aAAa,MAAM,IAAM,UACrC,KAAK,OAASQ,EAAW,SAAW,SACtC,CAGA,KAAK,SAAWR,EAAQ,aAAa,UAAU,EAC/C,KAAK,SAAW,CAAC,KAAK,SAKtB,IAAMS,EAAa,KAAK,SAAWT,EAAQ,aAAa,cAAc,IAAM,OAS5E,MARA,MAAK,eAAiBS,EAEtBT,EAAQ,iBAAiB,UAAW,KAAK,UAAU,EACnDA,EAAQ,iBAAiB,OAAQ,KAAK,WAAW,EACjDA,EAAQ,iBAAiB,SAAU,KAAK,WAAW,EACnDA,EAAQ,iBAAiB,QAAS,KAAK,WAAW,EAElD,KAAK,gBAAgB,EACd,EACT,CASA,cAA2C,CACzC,IAAMU,EAAS,KAAK,cAA6Bf,CAAgB,EACjE,GAAIe,EAAQ,OAAOA,EACnB,IAAK,IAAMT,KAAM,KAAK,iBAA8B,GAAG,EACrD,GAAKA,EAAG,YAA6C,eACnD,OAAOA,EAGX,OAAO,IACT,CAEA,WAAoB,CAClB,IAAMD,EAAU,KAAK,SAChBA,IACLA,EAAQ,oBAAoB,UAAW,KAAK,UAAU,EACtDA,EAAQ,oBAAoB,OAAQ,KAAK,WAAW,EACpDA,EAAQ,oBAAoB,SAAU,KAAK,WAAW,EACtDA,EAAQ,oBAAoB,QAAS,KAAK,WAAW,EACvD,CAmBA,iBAA0B,CACxB,IAAMA,EAAU,KAAK,SACrB,GAAI,CAACA,EAAS,OAId,IAAMW,EAAY,KAAK,gBAAkB,EAAEX,EAAQ,UAAU,OAASA,EAAQ,cAAc,GAC5F,KAAK,WAAWA,EAASW,CAAS,CACpC,CAEA,WAAmB,EAAsB,EAAoB,CAE3D,KAAK,QAAUA,EACXA,EAAWX,EAAQ,aAAa,eAAgB,MAAM,EACrDA,EAAQ,gBAAgB,cAAc,EAE3C,KAAK,mBAAmB,CAC1B,CAEA,oBAA6B,CAC3B,IAAMA,EAAU,KAAK,SACrB,GAAI,CAACA,EAAS,OACd,IAAMY,EAAM,CAAC,GAAG,KAAK,oBAAoB,EACrC,KAAK,OAAO,IAAIA,EAAI,KAAK,KAAK,MAAM,EAAE,EACtC,KAAK,QAAU,KAAK,SAAW,KAAK,OAAO,IAAIA,EAAI,KAAK,KAAK,OAAO,EAAE,EACtEA,EAAI,OAAQZ,EAAQ,aAAa,mBAAoBY,EAAI,KAAK,GAAG,CAAC,EACjEZ,EAAQ,gBAAgB,kBAAkB,CACjD,CACF,EA3LGR,EAAA,CAAAC,EAAS,CAAE,QAAS,EAAK,CAAC,CAAA,EAAAG,EAAA,UAAA,SAAA,IAAA,EAAA,EAI1BJ,EAAA,CAAAC,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,CAAA,EAAAG,EAAA,UAAA,WAAA,IAAA,EAAA,EAIzCJ,EAAA,CAAAC,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,CAAA,EAAAG,EAAA,UAAA,WAAA,IAAA,EAAA,EAIzCJ,EAAA,CAAAC,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,CAAA,EAAAG,EAAA,UAAA,UAAA,IAAA,EAAA,EAIzCJ,EAAA,CAAAC,EAAS,CAAE,KAAM,QAAS,QAAS,EAAK,CAAC,CAAA,EAAAG,EAAA,UAAA,WAAA,IAAA,EAAA,E"}
@@ -19,6 +19,8 @@
19
19
  * @cssproperty --calendar-icon - Date picker glyph as a `url()`. Masked, so color is taken from the control, not the image.
20
20
  * @cssproperty --clock-icon - Time picker glyph as a `url()`.
21
21
  * @cssproperty --clear-icon - Search clear glyph as a `url()`.
22
+ * @cssproperty [--l-form-control-icon-size=1em] - Glyph size of the date/time picker icon and the search clear (global
23
+ * form-control token). Their hit area is a square of the control height (borders excluded).
22
24
  *
23
25
  * @example Default
24
26
  * <input type="text" class="l-input" placeholder="Placeholder text" />
@@ -1 +1 @@
1
- {"version":3,"file":"input.meta.d.ts","sourceRoot":"","sources":["../../../src/html/elements/input/input.meta.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AAIH,qBAAa,SAAS;CAAG"}
1
+ {"version":3,"file":"input.meta.d.ts","sourceRoot":"","sources":["../../../src/html/elements/input/input.meta.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAIH,qBAAa,SAAS;CAAG"}
@@ -13,9 +13,9 @@ import { LuxenElement } from '../../shared/luxen-element.js';
13
13
  * @cssproperty --digits - Number of digit boxes (default: 6). Must match input's maxlength.
14
14
  * @cssproperty --cell-size - Cell width and height (default: 2.75rem). Font size scales automatically.
15
15
  * @cssproperty --cell-gap - Space between cells (default: 0.5rem).
16
- * @cssproperty --cell-bg-color - Cell background color.
17
- * @cssproperty --cell-border-color - Cell border color.
18
- * @cssproperty --cell-border-radius - Cell border-radius.
16
+ * @cssproperty --cell-bg-color - Cell background color (default: a faint ink tint over `--l-form-control-background-color`).
17
+ * @cssproperty --cell-border-color - Cell border color (default: `var(--l-form-control-border-color)`).
18
+ * @cssproperty --cell-border-radius - Cell border-radius (default: `var(--l-form-control-border-radius)`, like the other text fields).
19
19
  * @cssproperty --cell-focus-color - Border + ring color of the active (focused) cell.
20
20
  * @cssproperty --cell-focus-ring - `box-shadow` of the active cell ring (defaults to a 1px solid ring; set to `none` to disable).
21
21
  */
@@ -1 +1 @@
1
- {"version":3,"file":"input-otp.js","names":["_decorate","property","n","InputOtp","LuxenElement","_args","value","maxLen","pos","isFocused","i","cell","span","char","input","digits","defaults","attr","cls","__decorate"],"sources":["../../../src/html/elements/input-otp/input-otp.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { cls } from '../../registry.js';\n\n/**\n * Enhances a child `<input>` with visual digit cells (Stripe-style OTP input).\n *\n * A single hidden `<input>` handles keyboard, paste, and autocomplete.\n * Visual cells are rendered as real DOM elements with individual borders and focus ring.\n *\n * @summary Stripe-style OTP input with visual digit cells over a hidden native input.\n * @customElement l-input-otp\n *\n * @attribute size - sm | lg — Cell size. Default is md.\n *\n * @cssproperty --digits - Number of digit boxes (default: 6). Must match input's maxlength.\n * @cssproperty --cell-size - Cell width and height (default: 2.75rem). Font size scales automatically.\n * @cssproperty --cell-gap - Space between cells (default: 0.5rem).\n * @cssproperty --cell-bg-color - Cell background color.\n * @cssproperty --cell-border-color - Cell border color.\n * @cssproperty --cell-border-radius - Cell border-radius.\n * @cssproperty --cell-focus-color - Border + ring color of the active (focused) cell.\n * @cssproperty --cell-focus-ring - `box-shadow` of the active cell ring (defaults to a 1px solid ring; set to `none` to disable).\n */\nexport class InputOtp extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n /** Position after which to insert a visual separator (e.g., 3 for a 3-3 grouping). */\n @property({ type: Number, reflect: true, attribute: 'separator-after' })\n separatorAfter?: number;\n\n private _input!: HTMLInputElement;\n private _container!: HTMLDivElement;\n private _cells: HTMLDivElement[] = [];\n private _separatorEl: HTMLSpanElement | null = null;\n private _initialized = false;\n private _setupTimer = 0;\n\n override connectedCallback() {\n super.connectedCallback();\n // Children may not be parsed yet when the element upgrades mid-parse: try\n // synchronously, then retry once on a macrotask. setTimeout, not rAF — rAF\n // is suspended in hidden documents, so the element would stay inert there.\n if (!this._trySetup()) {\n this._setupTimer = window.setTimeout(() => this._trySetup(), 0);\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n clearTimeout(this._setupTimer);\n this._teardown();\n }\n\n /** @returns true when setup ran or was already done; false to schedule a retry. */\n private _trySetup(): boolean {\n if (this._initialized || !this.isConnected) return true;\n if (!this.querySelector('input')) return false;\n this._setup();\n return true;\n }\n\n // --- Setup / Teardown ---\n\n private _setup() {\n const input = this.querySelector<HTMLInputElement>('input');\n if (!input) return;\n\n this._input = input;\n\n // Derive digit count from --digits CSS custom property (default 6)\n const digits = Number(getComputedStyle(this).getPropertyValue('--digits').trim()) || 6;\n\n // Set sensible defaults — author can still override via HTML attributes\n const defaults: Record<string, string> = {\n type: 'text',\n inputmode: 'numeric',\n autocomplete: 'one-time-code',\n maxlength: String(digits),\n pattern: String.raw`\\d{${digits}}`,\n };\n for (const [attr, value] of Object.entries(defaults)) {\n if (!this._input.hasAttribute(attr)) {\n this._input.setAttribute(attr, value);\n }\n }\n\n // Build visual cells container. The real <input> is moved INTO this\n // container (below), so the container itself must stay exposed to AT —\n // aria-hidden goes on each decorative cell/separator, never on the wrapper\n // (a focusable element inside an aria-hidden subtree violates WCAG 4.1.2).\n this._container = document.createElement('div');\n this._container.className = cls('input-otp-cells');\n\n for (let i = 0; i < digits; i++) {\n const cell = document.createElement('div');\n cell.className = cls('input-otp-cell');\n cell.setAttribute('aria-hidden', 'true');\n cell.appendChild(document.createElement('span'));\n this._cells.push(cell);\n this._container.appendChild(cell);\n\n // Insert separator after the specified position\n if (this.separatorAfter && i === this.separatorAfter - 1 && i < digits - 1) {\n this._separatorEl = document.createElement('span');\n this._separatorEl.className = cls('input-otp-separator');\n this._separatorEl.setAttribute('aria-hidden', 'true');\n this._container.appendChild(this._separatorEl);\n }\n }\n\n // Wrap: insert container before input, then move input inside\n this._input.replaceWith(this._container);\n this._container.appendChild(this._input);\n this._initialized = true;\n\n // Populate cells if input already has a value (e.g. disabled with prefilled value)\n this._updateCells();\n\n // Events — focus is deferred so it runs after the click that triggered it\n // (otherwise selectionStart is stale and the active cell flickers).\n this._input.addEventListener('input', this._updateCells);\n this._input.addEventListener('click', this._updateCells);\n this._input.addEventListener('keyup', this._updateCells);\n this._input.addEventListener('focus', this._scheduleUpdateCells);\n this._input.addEventListener('blur', this._clearCells);\n }\n\n private _teardown() {\n if (!this._initialized) return;\n\n this._input.removeEventListener('input', this._updateCells);\n this._input.removeEventListener('click', this._updateCells);\n this._input.removeEventListener('keyup', this._updateCells);\n this._input.removeEventListener('focus', this._scheduleUpdateCells);\n this._input.removeEventListener('blur', this._clearCells);\n\n // Restore input to direct child\n this._container.replaceWith(this._input);\n this._separatorEl?.remove();\n\n this._cells = [];\n this._separatorEl = null;\n this._initialized = false;\n }\n\n // --- Cell updates ---\n\n private _updateCells = (): void => {\n const value = this._input.value;\n const maxLen = this._input.maxLength || 6;\n const pos = Math.min(this._input.selectionStart ?? 0, maxLen - 1);\n const isFocused = document.activeElement === this._input;\n\n for (let i = 0; i < this._cells.length; i++) {\n const cell = this._cells[i];\n const span = cell.firstElementChild as HTMLSpanElement;\n const char = value[i] ?? '';\n\n span.textContent = char;\n\n if (char) {\n cell.setAttribute('data-filled', '');\n } else {\n cell.removeAttribute('data-filled');\n }\n\n if (isFocused && i === pos) {\n cell.setAttribute('data-active', '');\n } else {\n cell.removeAttribute('data-active');\n }\n }\n };\n\n private _clearCells = (): void => {\n for (const cell of this._cells) {\n cell.removeAttribute('data-active');\n }\n };\n\n private _scheduleUpdateCells = (): void => {\n requestAnimationFrame(this._updateCells);\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"input-otp.js","names":["_decorate","property","n","InputOtp","LuxenElement","_args","value","maxLen","pos","isFocused","i","cell","span","char","input","digits","defaults","attr","cls","__decorate"],"sources":["../../../src/html/elements/input-otp/input-otp.ts"],"sourcesContent":["import { property } from 'lit/decorators.js';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { cls } from '../../registry.js';\n\n/**\n * Enhances a child `<input>` with visual digit cells (Stripe-style OTP input).\n *\n * A single hidden `<input>` handles keyboard, paste, and autocomplete.\n * Visual cells are rendered as real DOM elements with individual borders and focus ring.\n *\n * @summary Stripe-style OTP input with visual digit cells over a hidden native input.\n * @customElement l-input-otp\n *\n * @attribute size - sm | lg — Cell size. Default is md.\n *\n * @cssproperty --digits - Number of digit boxes (default: 6). Must match input's maxlength.\n * @cssproperty --cell-size - Cell width and height (default: 2.75rem). Font size scales automatically.\n * @cssproperty --cell-gap - Space between cells (default: 0.5rem).\n * @cssproperty --cell-bg-color - Cell background color (default: a faint ink tint over `--l-form-control-background-color`).\n * @cssproperty --cell-border-color - Cell border color (default: `var(--l-form-control-border-color)`).\n * @cssproperty --cell-border-radius - Cell border-radius (default: `var(--l-form-control-border-radius)`, like the other text fields).\n * @cssproperty --cell-focus-color - Border + ring color of the active (focused) cell.\n * @cssproperty --cell-focus-ring - `box-shadow` of the active cell ring (defaults to a 1px solid ring; set to `none` to disable).\n */\nexport class InputOtp extends LuxenElement {\n override createRenderRoot() {\n return this;\n }\n\n /** Position after which to insert a visual separator (e.g., 3 for a 3-3 grouping). */\n @property({ type: Number, reflect: true, attribute: 'separator-after' })\n separatorAfter?: number;\n\n private _input!: HTMLInputElement;\n private _container!: HTMLDivElement;\n private _cells: HTMLDivElement[] = [];\n private _separatorEl: HTMLSpanElement | null = null;\n private _initialized = false;\n private _setupTimer = 0;\n\n override connectedCallback() {\n super.connectedCallback();\n // Children may not be parsed yet when the element upgrades mid-parse: try\n // synchronously, then retry once on a macrotask. setTimeout, not rAF — rAF\n // is suspended in hidden documents, so the element would stay inert there.\n if (!this._trySetup()) {\n this._setupTimer = window.setTimeout(() => this._trySetup(), 0);\n }\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n clearTimeout(this._setupTimer);\n this._teardown();\n }\n\n /** @returns true when setup ran or was already done; false to schedule a retry. */\n private _trySetup(): boolean {\n if (this._initialized || !this.isConnected) return true;\n if (!this.querySelector('input')) return false;\n this._setup();\n return true;\n }\n\n // --- Setup / Teardown ---\n\n private _setup() {\n const input = this.querySelector<HTMLInputElement>('input');\n if (!input) return;\n\n this._input = input;\n\n // Derive digit count from --digits CSS custom property (default 6)\n const digits = Number(getComputedStyle(this).getPropertyValue('--digits').trim()) || 6;\n\n // Set sensible defaults — author can still override via HTML attributes\n const defaults: Record<string, string> = {\n type: 'text',\n inputmode: 'numeric',\n autocomplete: 'one-time-code',\n maxlength: String(digits),\n pattern: String.raw`\\d{${digits}}`,\n };\n for (const [attr, value] of Object.entries(defaults)) {\n if (!this._input.hasAttribute(attr)) {\n this._input.setAttribute(attr, value);\n }\n }\n\n // Build visual cells container. The real <input> is moved INTO this\n // container (below), so the container itself must stay exposed to AT —\n // aria-hidden goes on each decorative cell/separator, never on the wrapper\n // (a focusable element inside an aria-hidden subtree violates WCAG 4.1.2).\n this._container = document.createElement('div');\n this._container.className = cls('input-otp-cells');\n\n for (let i = 0; i < digits; i++) {\n const cell = document.createElement('div');\n cell.className = cls('input-otp-cell');\n cell.setAttribute('aria-hidden', 'true');\n cell.appendChild(document.createElement('span'));\n this._cells.push(cell);\n this._container.appendChild(cell);\n\n // Insert separator after the specified position\n if (this.separatorAfter && i === this.separatorAfter - 1 && i < digits - 1) {\n this._separatorEl = document.createElement('span');\n this._separatorEl.className = cls('input-otp-separator');\n this._separatorEl.setAttribute('aria-hidden', 'true');\n this._container.appendChild(this._separatorEl);\n }\n }\n\n // Wrap: insert container before input, then move input inside\n this._input.replaceWith(this._container);\n this._container.appendChild(this._input);\n this._initialized = true;\n\n // Populate cells if input already has a value (e.g. disabled with prefilled value)\n this._updateCells();\n\n // Events — focus is deferred so it runs after the click that triggered it\n // (otherwise selectionStart is stale and the active cell flickers).\n this._input.addEventListener('input', this._updateCells);\n this._input.addEventListener('click', this._updateCells);\n this._input.addEventListener('keyup', this._updateCells);\n this._input.addEventListener('focus', this._scheduleUpdateCells);\n this._input.addEventListener('blur', this._clearCells);\n }\n\n private _teardown() {\n if (!this._initialized) return;\n\n this._input.removeEventListener('input', this._updateCells);\n this._input.removeEventListener('click', this._updateCells);\n this._input.removeEventListener('keyup', this._updateCells);\n this._input.removeEventListener('focus', this._scheduleUpdateCells);\n this._input.removeEventListener('blur', this._clearCells);\n\n // Restore input to direct child\n this._container.replaceWith(this._input);\n this._separatorEl?.remove();\n\n this._cells = [];\n this._separatorEl = null;\n this._initialized = false;\n }\n\n // --- Cell updates ---\n\n private _updateCells = (): void => {\n const value = this._input.value;\n const maxLen = this._input.maxLength || 6;\n const pos = Math.min(this._input.selectionStart ?? 0, maxLen - 1);\n const isFocused = document.activeElement === this._input;\n\n for (let i = 0; i < this._cells.length; i++) {\n const cell = this._cells[i];\n const span = cell.firstElementChild as HTMLSpanElement;\n const char = value[i] ?? '';\n\n span.textContent = char;\n\n if (char) {\n cell.setAttribute('data-filled', '');\n } else {\n cell.removeAttribute('data-filled');\n }\n\n if (isFocused && i === pos) {\n cell.setAttribute('data-active', '');\n } else {\n cell.removeAttribute('data-active');\n }\n }\n };\n\n private _clearCells = (): void => {\n for (const cell of this._cells) {\n cell.removeAttribute('data-active');\n }\n };\n\n private _scheduleUpdateCells = (): void => {\n requestAnimationFrame(this._updateCells);\n };\n}\n"],"mappings":"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"}
@@ -10,11 +10,11 @@ import type { Placement } from '@floating-ui/dom';
10
10
  * @csspart body - The popover container.
11
11
  * @csspart arrow - The directional arrow element.
12
12
  *
13
- * @cssproperty --background - Background color. Default: `Canvas`.
13
+ * @cssproperty --background - Background color. Default `var(--l-color-surface-overlay)`.
14
14
  * @cssproperty --color - Text color. Default: inherited.
15
- * @cssproperty --border-radius - Border radius. Default `8px`.
15
+ * @cssproperty --border-radius - Border radius. Default `var(--l-popover-border-radius)` (6px).
16
16
  * @cssproperty --max-width - Maximum width. Default `320px`.
17
- * @cssproperty --shadow - Box shadow.
17
+ * @cssproperty --shadow - Box shadow. Default `var(--l-popover-shadow)`.
18
18
  * @cssproperty --arrow-size - Arrow size. Default `8px`.
19
19
  * @cssproperty --show-duration - Show animation duration. Default `150ms`.
20
20
  * @cssproperty --hide-duration - Hide animation duration. Default `150ms`.
@@ -42,7 +42,6 @@ export declare class Popover extends LuxenElement {
42
42
  private _triggerFor;
43
43
  private get _popoverEl();
44
44
  private get _arrowEl();
45
- private _getDuration;
46
45
  connectedCallback(): void;
47
46
  disconnectedCallback(): void;
48
47
  updated(changed: PropertyValues<this>): void;
@@ -1 +1 @@
1
- {"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../../src/html/elements/popover/popover.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAQlD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,OAAQ,SAAQ,YAAY;IACvC,OAAgB,MAAM,4BAAwB;IAE9C,OAAO,CAAC,UAAU,CAAuB;IAEzC,OAAO,CAAC,SAAS,CAOd;IAEH,yDAAyD;IAEzD,QAAQ,CAAC,GAAG,SAAM;IAElB,8CAA8C;IAE9C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAY;IAEzC,sDAAsD;IAEtD,QAAQ,CAAC,QAAQ,SAAK;IAEtB,6CAA6C;IAE7C,QAAQ,CAAC,IAAI,UAAS;IAEtB,kCAAkC;IAElC,QAAQ,CAAC,YAAY,UAAS;IAE9B,wEAAwE;IAExE,QAAQ,CAAC,SAAS,UAAS;IAE3B,kFAAkF;IAElF,QAAQ,CAAC,OAAO,SAAW;IAE3B,OAAO,CAAC,WAAW;IAInB,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,CAAC,WAAW;IAQnB,OAAO,KAAK,UAAU,GAErB;IAED,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,CAAC,YAAY;IAKX,iBAAiB,SAGzB;IAEQ,oBAAoB,SAK5B;IAEQ,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC,QAc7C;IAED,IAAI,SAEH;IAED,IAAI,SAEH;IAED,MAAM,SAEL;IAED;;;;OAIG;IACG,UAAU,kBAGf;IAED;;;;;OAKG;YACW,oBAAoB;IAkBlC,OAAO,CAAC,gBAAgB;YAQV,iBAAiB;IA2B/B,OAAO,CAAC,eAAe,CAIrB;IAEF,OAAO,CAAC,eAAe,CAGrB;IAEF,OAAO,CAAC,UAAU,CAEhB;IACF,OAAO,CAAC,WAAW,CAEjB;IACF,OAAO,CAAC,QAAQ,CAEd;IAEF,OAAO,CAAC,UAAU,CAKhB;IAEF,2DAA2D;IAC3D,OAAO,CAAC,SAAS,CAKf;IAEF,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,uBAAuB;IAItB,MAAM,oCAqBd;CACF"}
1
+ {"version":3,"file":"popover.d.ts","sourceRoot":"","sources":["../../../src/html/elements/popover/popover.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4B,KAAK,cAAc,EAAE,MAAM,KAAK,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAE7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAQlD;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,OAAQ,SAAQ,YAAY;IACvC,OAAgB,MAAM,4BAAwB;IAE9C,OAAO,CAAC,UAAU,CAAuB;IAEzC,OAAO,CAAC,SAAS,CAOd;IAEH,yDAAyD;IAEzD,QAAQ,CAAC,GAAG,SAAM;IAElB,8CAA8C;IAE9C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAY;IAEzC,sDAAsD;IAEtD,QAAQ,CAAC,QAAQ,SAAK;IAEtB,6CAA6C;IAE7C,QAAQ,CAAC,IAAI,UAAS;IAEtB,kCAAkC;IAElC,QAAQ,CAAC,YAAY,UAAS;IAE9B,wEAAwE;IAExE,QAAQ,CAAC,SAAS,UAAS;IAE3B,kFAAkF;IAElF,QAAQ,CAAC,OAAO,SAAW;IAE3B,OAAO,CAAC,WAAW;IAInB,OAAO,KAAK,QAAQ,GAEnB;IAED,OAAO,CAAC,WAAW;IAQnB,OAAO,KAAK,UAAU,GAErB;IAED,OAAO,KAAK,QAAQ,GAEnB;IAEQ,iBAAiB,SAGzB;IAEQ,oBAAoB,SAK5B;IAEQ,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,IAAI,CAAC,QAc7C;IAED,IAAI,SAEH;IAED,IAAI,SAEH;IAED,MAAM,SAEL;IAED;;;;OAIG;IACG,UAAU,kBAGf;IAED;;;;;OAKG;YACW,oBAAoB;IAkBlC,OAAO,CAAC,gBAAgB;YAQV,iBAAiB;IA2B/B,OAAO,CAAC,eAAe,CAIrB;IAEF,OAAO,CAAC,eAAe,CAGrB;IAEF,OAAO,CAAC,UAAU,CAEhB;IACF,OAAO,CAAC,WAAW,CAEjB;IACF,OAAO,CAAC,QAAQ,CAEd;IAEF,OAAO,CAAC,UAAU,CAKhB;IAEF,2DAA2D;IAC3D,OAAO,CAAC,SAAS,CAKf;IAEF,OAAO,CAAC,oBAAoB;IAW5B,OAAO,CAAC,uBAAuB;IAItB,MAAM,oCAqBd;CACF"}
@@ -1,4 +1,4 @@
1
- import{i as e}from"../../chunks/lit.js";import{LuxenElement as t}from"../../shared/luxen-element.js";import{r as n,t as r}from"../../chunks/decorate.js";import{a as i,t as a}from"../../chunks/lit-html.js";import{PopoverController as o}from"../../shared/controllers/popover.js";import{uniqueId as s}from"../../registry.js";import c from"../../shared/styles/host.styles.js";var l=e(`:host{--background:var(--l-color-surface-overlay);--color:inherit;--border-radius:6px;--max-width:320px;--shadow:var(--l-shadow-md);--arrow-size:8px;--show-duration:.15s;--hide-duration:.15s;--_border-color:var(--l-color-border-overlay);display:contents}[popover]{inset:unset;isolation:isolate;box-sizing:border-box;width:max-content;max-width:var(--max-width);border:1px solid var(--_border-color);border-radius:var(--border-radius);background:var(--background);color:var(--color);box-shadow:var(--shadow);font-size:.875rem;line-height:1.5;overflow:visible}:host([full-width]) [popover]{width:100vw;max-width:none}i{width:var(--arrow-size);height:var(--arrow-size);background:var(--background);z-index:-1;display:block;position:absolute;transform:rotate(45deg)}:host([data-placement^=top]) i{border-right:1px solid var(--_border-color);border-bottom:1px solid var(--_border-color)}:host([data-placement^=bottom]) i{border-top:1px solid var(--_border-color);border-left:1px solid var(--_border-color)}:host([data-placement^=left]) i{border-right:1px solid var(--_border-color);border-top:1px solid var(--_border-color)}:host([data-placement^=right]) i{border-left:1px solid var(--_border-color);border-bottom:1px solid var(--_border-color)}`),u=class extends t{constructor(...e){super(...e),this._popoverId=s(`popover`),this._floating=new o(this,{getTriggerElement:()=>this._trigger,getFloatingElement:()=>this._popoverEl,getArrowElement:()=>this._arrowEl,onPlacementChange:e=>{this.dataset.placement=e}}),this.#e=``,this.#t=`bottom`,this.#n=8,this.#r=!1,this.#i=!1,this.#a=!1,this.#o=`click`,this._onPointerEnter=()=>{this._hasTrigger(`hover`)&&(this._floating.cleanupSafePolygon(),this.show())},this._onPointerLeave=e=>{this._hasTrigger(`hover`)&&this.open&&this._floating.handlePointerLeave(e,()=>this.hide())},this._onFocusIn=()=>{this._hasTrigger(`focus`)&&this.show()},this._onFocusOut=()=>{this._hasTrigger(`focus`)&&this.hide()},this._onClick=()=>{this._hasTrigger(`click`)&&this.toggle()},this._onKeyDown=e=>{this.open&&e.key===`Escape`&&(e.stopPropagation(),this.hide())},this._onToggle=e=>{e.newState===`closed`&&this.open&&(this.open=!1)}}static{this.styles=[c,l]}#e;get for(){return this.#e}set for(e){this.#e=e}#t;get placement(){return this.#t}set placement(e){this.#t=e}#n;get distance(){return this.#n}set distance(e){this.#n=e}#r;get open(){return this.#r}set open(e){this.#r=e}#i;get withoutArrow(){return this.#i}set withoutArrow(e){this.#i=e}#a;get fullWidth(){return this.#a}set fullWidth(e){this.#a=e}#o;get trigger(){return this.#o}set trigger(e){this.#o=e}_hasTrigger(e){return this.trigger.split(` `).includes(e)}get _trigger(){return this._triggerFor(this.for)}_triggerFor(e){if(!e)return null;let t=this.getRootNode();return t instanceof Document||t instanceof ShadowRoot?t.getElementById(e):null}get _popoverEl(){return this.shadowRoot.querySelector(`[popover]`)}get _arrowEl(){return this.withoutArrow?null:this.shadowRoot.querySelector(`i`)}_getDuration(e){let t=parseFloat(getComputedStyle(this).getPropertyValue(e));return Number.isNaN(t)?150:t}connectedCallback(){super.connectedCallback(),requestAnimationFrame(()=>this._addTriggerListeners())}disconnectedCallback(){super.disconnectedCallback(),this._removeTriggerListeners()}updated(e){e.has(`for`)&&(this._removeTriggerListeners(e.get(`for`)),this._addTriggerListeners(),this.open&&!e.has(`open`)&&this._repositionToTrigger()),e.has(`open`)&&this._handleOpenChange()}show(){this.open||=!0}hide(){this.open&&=!1}toggle(){this.open=!this.open}async reposition(){this.open&&await this._repositionToTrigger()}async _repositionToTrigger(){this._floating.cleanupSafePolygon();let e=this.for,t=await this._floating.reposition(this._positionOptions(),()=>this.open&&this.for===e);t!==`stale`&&(t===`no-anchor`?this.hide():this._floating.markTrigger(`aria-expanded`,`true`,`false`))}_positionOptions(){return{placement:this.placement,distance:this.distance,fullWidth:this.fullWidth}}async _handleOpenChange(){let e=this._popoverEl;if(!e)return;let t=this._positionOptions();if(this.open){if(e.showPopover(),await this._floating.updatePosition(t),!this.open)return;await this._floating.animateShow(e,this._getDuration(`--show-duration`)),this._floating.startPositioning(t),this._floating.markTrigger(`aria-expanded`,`true`,`false`)}else this._floating.stopPositioning(),this._floating.cleanupSafePolygon(),this._floating.releaseTrigger(`false`),await this._floating.animateHide(e,this._getDuration(`--hide-duration`)),e.matches(`:popover-open`)&&e.hidePopover()}_addTriggerListeners(){this._floating.addTriggerListeners({onPointerEnter:this._onPointerEnter,onPointerLeave:this._onPointerLeave,onFocusIn:this._onFocusIn,onFocusOut:this._onFocusOut,onClick:this._onClick,onKeyDown:this._onKeyDown})}_removeTriggerListeners(e){this._floating.removeTriggerListeners(e?this._triggerFor(e):void 0)}render(){return i`
1
+ import{i as e}from"../../chunks/lit.js";import{LuxenElement as t}from"../../shared/luxen-element.js";import{r as n,t as r}from"../../chunks/decorate.js";import{a as i,t as a}from"../../chunks/lit-html.js";import{PopoverController as o}from"../../shared/controllers/popover.js";import{uniqueId as s}from"../../registry.js";import c from"../../shared/styles/host.styles.js";var l=e(`:host{--background:var(--l-color-surface-overlay);--color:inherit;--border-radius:var(--l-popover-border-radius);--max-width:320px;--shadow:var(--l-popover-shadow);--arrow-size:8px;--show-duration:.15s;--hide-duration:.15s;--_border-color:var(--l-color-border-overlay);display:contents}[popover]{inset:unset;isolation:isolate;box-sizing:border-box;width:max-content;max-width:var(--max-width);border:1px solid var(--_border-color);border-radius:var(--border-radius);background:var(--background);color:var(--color);font-size:var(--l-popover-font-size);line-height:var(--l-popover-line-height);box-shadow:var(--shadow);overflow:visible}:host([full-width]) [popover]{width:100vw;max-width:none}i{width:var(--arrow-size);height:var(--arrow-size);background:var(--background);z-index:-1;display:block;position:absolute;transform:rotate(45deg)}:host([data-placement^=top]) i{border-right:1px solid var(--_border-color);border-bottom:1px solid var(--_border-color)}:host([data-placement^=bottom]) i{border-top:1px solid var(--_border-color);border-left:1px solid var(--_border-color)}:host([data-placement^=left]) i{border-right:1px solid var(--_border-color);border-top:1px solid var(--_border-color)}:host([data-placement^=right]) i{border-left:1px solid var(--_border-color);border-bottom:1px solid var(--_border-color)}`),u=class extends t{constructor(...e){super(...e),this._popoverId=s(`popover`),this._floating=new o(this,{getTriggerElement:()=>this._trigger,getFloatingElement:()=>this._popoverEl,getArrowElement:()=>this._arrowEl,onPlacementChange:e=>{this.dataset.placement=e}}),this.#e=``,this.#t=`bottom`,this.#n=8,this.#r=!1,this.#i=!1,this.#a=!1,this.#o=`click`,this._onPointerEnter=()=>{this._hasTrigger(`hover`)&&(this._floating.cleanupSafePolygon(),this.show())},this._onPointerLeave=e=>{this._hasTrigger(`hover`)&&this.open&&this._floating.handlePointerLeave(e,()=>this.hide())},this._onFocusIn=()=>{this._hasTrigger(`focus`)&&this.show()},this._onFocusOut=()=>{this._hasTrigger(`focus`)&&this.hide()},this._onClick=()=>{this._hasTrigger(`click`)&&this.toggle()},this._onKeyDown=e=>{this.open&&e.key===`Escape`&&(e.stopPropagation(),this.hide())},this._onToggle=e=>{e.newState===`closed`&&this.open&&(this.open=!1)}}static{this.styles=[c,l]}#e;get for(){return this.#e}set for(e){this.#e=e}#t;get placement(){return this.#t}set placement(e){this.#t=e}#n;get distance(){return this.#n}set distance(e){this.#n=e}#r;get open(){return this.#r}set open(e){this.#r=e}#i;get withoutArrow(){return this.#i}set withoutArrow(e){this.#i=e}#a;get fullWidth(){return this.#a}set fullWidth(e){this.#a=e}#o;get trigger(){return this.#o}set trigger(e){this.#o=e}_hasTrigger(e){return this.trigger.split(` `).includes(e)}get _trigger(){return this._triggerFor(this.for)}_triggerFor(e){if(!e)return null;let t=this.getRootNode();return t instanceof Document||t instanceof ShadowRoot?t.getElementById(e):null}get _popoverEl(){return this.shadowRoot.querySelector(`[popover]`)}get _arrowEl(){return this.withoutArrow?null:this.shadowRoot.querySelector(`i`)}connectedCallback(){super.connectedCallback(),requestAnimationFrame(()=>this._addTriggerListeners())}disconnectedCallback(){super.disconnectedCallback(),this._removeTriggerListeners()}updated(e){e.has(`for`)&&(this._removeTriggerListeners(e.get(`for`)),this._addTriggerListeners(),this.open&&!e.has(`open`)&&this._repositionToTrigger()),e.has(`open`)&&this._handleOpenChange()}show(){this.open||=!0}hide(){this.open&&=!1}toggle(){this.open=!this.open}async reposition(){this.open&&await this._repositionToTrigger()}async _repositionToTrigger(){this._floating.cleanupSafePolygon();let e=this.for,t=await this._floating.reposition(this._positionOptions(),()=>this.open&&this.for===e);t!==`stale`&&(t===`no-anchor`?this.hide():this._floating.markTrigger(`aria-expanded`,`true`,`false`))}_positionOptions(){return{placement:this.placement,distance:this.distance,fullWidth:this.fullWidth}}async _handleOpenChange(){let e=this._popoverEl;if(!e)return;let t=this._positionOptions();if(this.open){if(e.showPopover(),await this._floating.updatePosition(t),!this.open)return;await this._floating.animateShow(e),this._floating.startPositioning(t),this._floating.markTrigger(`aria-expanded`,`true`,`false`)}else this._floating.stopPositioning(),this._floating.cleanupSafePolygon(),this._floating.releaseTrigger(`false`),await this._floating.animateHide(e),e.matches(`:popover-open`)&&e.hidePopover()}_addTriggerListeners(){this._floating.addTriggerListeners({onPointerEnter:this._onPointerEnter,onPointerLeave:this._onPointerLeave,onFocusIn:this._onFocusIn,onFocusOut:this._onFocusOut,onClick:this._onClick,onKeyDown:this._onKeyDown})}_removeTriggerListeners(e){this._floating.removeTriggerListeners(e?this._triggerFor(e):void 0)}render(){return i`
2
2
  <div
3
3
  id=${this._popoverId}
4
4
  popover="auto"
@@ -1 +1 @@
1
- {"version":3,"file":"popover.js","names":["unsafeCSS","rawStyles","toggleEvent","hostStyles","nothing","_decorate","property","r","__decorate","b","A","host_styles_default","styles","Popover","LuxenElement","_args","uniqueId","PopoverController","p","#_for_accessor_storage","#_placement_accessor_storage","#_distance_accessor_storage","#_open_accessor_storage","#_withoutArrow_accessor_storage","#_fullWidth_accessor_storage","#_trigger_accessor_storage","value","type","id","root","parsed","prop","changed","openFor","result","popover","posOpts","forId"],"sources":["../../../src/html/elements/popover/popover.css?inline","../../../src/html/elements/popover/popover.ts"],"sourcesContent":[":host {\n --background: var(--l-color-surface-overlay);\n --color: inherit;\n --border-radius: 6px;\n --max-width: 320px;\n --shadow: var(--l-shadow-md);\n --arrow-size: 8px;\n --show-duration: 150ms;\n --hide-duration: 150ms;\n\n --_border-color: var(--l-color-border-overlay);\n\n display: contents;\n}\n\n[popover] {\n inset: unset;\n overflow: visible;\n isolation: isolate;\n box-sizing: border-box;\n width: max-content;\n max-width: var(--max-width);\n border: 1px solid var(--_border-color);\n border-radius: var(--border-radius);\n background: var(--background);\n color: var(--color);\n font-size: 0.875rem;\n line-height: 1.5;\n box-shadow: var(--shadow);\n}\n\n:host([full-width]) [popover] {\n width: 100vw;\n max-width: none;\n}\n\ni {\n position: absolute;\n display: block;\n width: var(--arrow-size);\n height: var(--arrow-size);\n background: var(--background);\n transform: rotate(45deg);\n z-index: -1;\n}\n\n:host([data-placement^='top']) i {\n border-right: 1px solid var(--_border-color);\n border-bottom: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='bottom']) i {\n border-top: 1px solid var(--_border-color);\n border-left: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='left']) i {\n border-right: 1px solid var(--_border-color);\n border-top: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='right']) i {\n border-left: 1px solid var(--_border-color);\n border-bottom: 1px solid var(--_border-color);\n}\n","import { html, nothing, unsafeCSS, type PropertyValues } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { property } from 'lit/decorators.js';\nimport type { Placement } from '@floating-ui/dom';\nimport { PopoverController } from '../../shared/controllers/popover.js';\nimport { uniqueId } from '../../registry.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './popover.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * @summary A popover that displays interactive content anchored to a trigger.\n * @customElement l-popover\n *\n * @slot - Popover content.\n *\n * @csspart body - The popover container.\n * @csspart arrow - The directional arrow element.\n *\n * @cssproperty --background - Background color. Default: `Canvas`.\n * @cssproperty --color - Text color. Default: inherited.\n * @cssproperty --border-radius - Border radius. Default `8px`.\n * @cssproperty --max-width - Maximum width. Default `320px`.\n * @cssproperty --shadow - Box shadow.\n * @cssproperty --arrow-size - Arrow size. Default `8px`.\n * @cssproperty --show-duration - Show animation duration. Default `150ms`.\n * @cssproperty --hide-duration - Hide animation duration. Default `150ms`.\n */\nexport class Popover extends LuxenElement {\n static override styles = [hostStyles, styles];\n\n private _popoverId = uniqueId('popover');\n\n private _floating = new PopoverController(this, {\n getTriggerElement: () => this._trigger,\n getFloatingElement: () => this._popoverEl,\n getArrowElement: () => this._arrowEl,\n onPlacementChange: (p) => {\n this.dataset.placement = p;\n },\n });\n\n /** The HTML id of the element triggering the popover. */\n @property()\n accessor for = '';\n\n /** The preferred placement of the popover. */\n @property()\n accessor placement: Placement = 'bottom';\n\n /** The distance in pixels from the target element. */\n @property({ type: Number })\n accessor distance = 8;\n\n /** Whether or not the popover is visible. */\n @property({ type: Boolean, reflect: true })\n accessor open = false;\n\n /** Hide the directional arrow. */\n @property({ type: Boolean, reflect: true, attribute: 'without-arrow' })\n accessor withoutArrow = false;\n\n /** Stretch the popover to the viewport width. Useful for mega menus. */\n @property({ type: Boolean, reflect: true, attribute: 'full-width' })\n accessor fullWidth = false;\n\n /** Space-separated list of trigger modes: `click`, `hover`, `focus`, `manual`. */\n @property()\n accessor trigger = 'click';\n\n private _hasTrigger(type: string) {\n return this.trigger.split(' ').includes(type);\n }\n\n private get _trigger(): HTMLElement | null {\n return this._triggerFor(this.for);\n }\n\n private _triggerFor(id: string): HTMLElement | null {\n if (!id) return null;\n // A detached popover's root is a plain element with no getElementById —\n // async open/close work may land after removal.\n const root = this.getRootNode();\n return root instanceof Document || root instanceof ShadowRoot ? root.getElementById(id) : null;\n }\n\n private get _popoverEl(): HTMLElement {\n return this.shadowRoot!.querySelector('[popover]')!;\n }\n\n private get _arrowEl(): HTMLElement | null {\n return this.withoutArrow ? null : this.shadowRoot!.querySelector('i');\n }\n\n private _getDuration(prop: '--show-duration' | '--hide-duration'): number {\n const parsed = parseFloat(getComputedStyle(this).getPropertyValue(prop));\n return Number.isNaN(parsed) ? 150 : parsed;\n }\n\n override connectedCallback() {\n super.connectedCallback();\n requestAnimationFrame(() => this._addTriggerListeners());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n // `aria-expanded` is dropped (not set to \"false\") by the controller's\n // hostDisconnected: with the panel gone the trigger expands nothing.\n this._removeTriggerListeners();\n }\n\n override updated(changed: PropertyValues<this>) {\n // `for` before `open`: retargeting an already-open panel has to settle\n // against the new anchor, and when both change in the same update the open\n // path owns the positioning outright (see the guard below).\n if (changed.has('for')) {\n this._removeTriggerListeners(changed.get('for'));\n this._addTriggerListeners();\n if (this.open && !changed.has('open')) {\n void this._repositionToTrigger();\n }\n }\n if (changed.has('open')) {\n void this._handleOpenChange();\n }\n }\n\n show() {\n if (!this.open) this.open = true;\n }\n\n hide() {\n if (this.open) this.open = false;\n }\n\n toggle() {\n this.open = !this.open;\n }\n\n /**\n * Recompute the position against the current trigger. Use it when you move\n * the anchor yourself and the panel has to follow. No-op when closed; hides\n * if the anchor is gone.\n */\n async reposition() {\n if (!this.open) return;\n await this._repositionToTrigger();\n }\n\n /**\n * Move the open panel onto whatever `for` names now — a move, not a re-open,\n * so it deliberately bypasses `_handleOpenChange` and its show animation.\n * Shared by the public `reposition()` and the retarget path so the two\n * cannot drift apart.\n */\n private async _repositionToTrigger() {\n this._floating.cleanupSafePolygon();\n const openFor = this.for;\n const result = await this._floating.reposition(\n this._positionOptions(),\n () => this.open && this.for === openFor,\n );\n // Closed or retargeted again while `computePosition` was in flight.\n if (result === 'stale') return;\n // Retargeted onto an id that resolves to nothing: a panel left floating\n // over unrelated content is worse than none.\n if (result === 'no-anchor') {\n this.hide();\n return;\n }\n this._floating.markTrigger('aria-expanded', 'true', 'false');\n }\n\n private _positionOptions() {\n return {\n placement: this.placement,\n distance: this.distance,\n fullWidth: this.fullWidth,\n };\n }\n\n private async _handleOpenChange() {\n const popover = this._popoverEl;\n if (!popover) return;\n\n const posOpts = this._positionOptions();\n\n if (this.open) {\n popover.showPopover();\n await this._floating.updatePosition(posOpts);\n if (!this.open) return;\n await this._floating.animateShow(popover, this._getDuration('--show-duration'));\n this._floating.startPositioning(posOpts);\n this._floating.markTrigger('aria-expanded', 'true', 'false');\n // No aria-controls: the panel's id lives in this element's shadow root and\n // IDREFs don't cross shadow boundaries, so the reference would never\n // resolve (invalid per WCAG 4.1.2). aria-expanded alone conveys the state.\n } else {\n this._floating.stopPositioning();\n this._floating.cleanupSafePolygon();\n this._floating.releaseTrigger('false');\n await this._floating.animateHide(popover, this._getDuration('--hide-duration'));\n if (popover.matches(':popover-open')) popover.hidePopover();\n }\n }\n\n // --- Trigger event handlers ---\n\n private _onPointerEnter = () => {\n if (!this._hasTrigger('hover')) return;\n this._floating.cleanupSafePolygon();\n this.show();\n };\n\n private _onPointerLeave = (e: PointerEvent) => {\n if (!this._hasTrigger('hover') || !this.open) return;\n this._floating.handlePointerLeave(e, () => this.hide());\n };\n\n private _onFocusIn = () => {\n if (this._hasTrigger('focus')) this.show();\n };\n private _onFocusOut = () => {\n if (this._hasTrigger('focus')) this.hide();\n };\n private _onClick = () => {\n if (this._hasTrigger('click')) this.toggle();\n };\n\n private _onKeyDown = (e: KeyboardEvent) => {\n if (this.open && e.key === 'Escape') {\n e.stopPropagation();\n this.hide();\n }\n };\n\n /** Sync `open` when popover=\"auto\" light-dismiss fires. */\n private _onToggle = (e: Event) => {\n const toggleEvent = e as ToggleEvent;\n if (toggleEvent.newState === 'closed' && this.open) {\n this.open = false;\n }\n };\n\n private _addTriggerListeners() {\n this._floating.addTriggerListeners({\n onPointerEnter: this._onPointerEnter,\n onPointerLeave: this._onPointerLeave,\n onFocusIn: this._onFocusIn,\n onFocusOut: this._onFocusOut,\n onClick: this._onClick,\n onKeyDown: this._onKeyDown,\n });\n }\n\n private _removeTriggerListeners(forId?: string) {\n this._floating.removeTriggerListeners(forId ? this._triggerFor(forId) : undefined);\n }\n\n override render() {\n return html`\n <div\n id=${this._popoverId}\n popover=\"auto\"\n part=\"body\"\n @toggle=${this._onToggle}\n >\n ${\n this.withoutArrow\n ? nothing\n : html`\n <i\n part=\"arrow\"\n role=\"presentation\"\n ></i>\n `\n }\n <slot></slot>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"popover.js","names":["unsafeCSS","rawStyles","toggleEvent","hostStyles","nothing","_decorate","property","r","__decorate","b","A","host_styles_default","styles","Popover","LuxenElement","_args","uniqueId","PopoverController","p","#_for_accessor_storage","#_placement_accessor_storage","#_distance_accessor_storage","#_open_accessor_storage","#_withoutArrow_accessor_storage","#_fullWidth_accessor_storage","#_trigger_accessor_storage","value","type","id","root","changed","openFor","result","popover","posOpts","forId"],"sources":["../../../src/html/elements/popover/popover.css?inline","../../../src/html/elements/popover/popover.ts"],"sourcesContent":[":host {\n --background: var(--l-color-surface-overlay);\n --color: inherit;\n --border-radius: var(--l-popover-border-radius);\n --max-width: 320px;\n --shadow: var(--l-popover-shadow);\n --arrow-size: 8px;\n --show-duration: 150ms;\n --hide-duration: 150ms;\n\n --_border-color: var(--l-color-border-overlay);\n\n display: contents;\n}\n\n[popover] {\n inset: unset;\n overflow: visible;\n isolation: isolate;\n box-sizing: border-box;\n width: max-content;\n max-width: var(--max-width);\n border: 1px solid var(--_border-color);\n border-radius: var(--border-radius);\n background: var(--background);\n color: var(--color);\n font-size: var(--l-popover-font-size);\n line-height: var(--l-popover-line-height);\n box-shadow: var(--shadow);\n}\n\n:host([full-width]) [popover] {\n width: 100vw;\n max-width: none;\n}\n\ni {\n position: absolute;\n display: block;\n width: var(--arrow-size);\n height: var(--arrow-size);\n background: var(--background);\n transform: rotate(45deg);\n z-index: -1;\n}\n\n:host([data-placement^='top']) i {\n border-right: 1px solid var(--_border-color);\n border-bottom: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='bottom']) i {\n border-top: 1px solid var(--_border-color);\n border-left: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='left']) i {\n border-right: 1px solid var(--_border-color);\n border-top: 1px solid var(--_border-color);\n}\n\n:host([data-placement^='right']) i {\n border-left: 1px solid var(--_border-color);\n border-bottom: 1px solid var(--_border-color);\n}\n","import { html, nothing, unsafeCSS, type PropertyValues } from 'lit';\nimport { LuxenElement } from '../../shared/luxen-element.js';\nimport { property } from 'lit/decorators.js';\nimport type { Placement } from '@floating-ui/dom';\nimport { PopoverController } from '../../shared/controllers/popover.js';\nimport { uniqueId } from '../../registry.js';\nimport hostStyles from '../../shared/styles/host.styles.js';\nimport rawStyles from './popover.css?inline';\n\nconst styles = unsafeCSS(rawStyles);\n\n/**\n * @summary A popover that displays interactive content anchored to a trigger.\n * @customElement l-popover\n *\n * @slot - Popover content.\n *\n * @csspart body - The popover container.\n * @csspart arrow - The directional arrow element.\n *\n * @cssproperty --background - Background color. Default `var(--l-color-surface-overlay)`.\n * @cssproperty --color - Text color. Default: inherited.\n * @cssproperty --border-radius - Border radius. Default `var(--l-popover-border-radius)` (6px).\n * @cssproperty --max-width - Maximum width. Default `320px`.\n * @cssproperty --shadow - Box shadow. Default `var(--l-popover-shadow)`.\n * @cssproperty --arrow-size - Arrow size. Default `8px`.\n * @cssproperty --show-duration - Show animation duration. Default `150ms`.\n * @cssproperty --hide-duration - Hide animation duration. Default `150ms`.\n */\nexport class Popover extends LuxenElement {\n static override styles = [hostStyles, styles];\n\n private _popoverId = uniqueId('popover');\n\n private _floating = new PopoverController(this, {\n getTriggerElement: () => this._trigger,\n getFloatingElement: () => this._popoverEl,\n getArrowElement: () => this._arrowEl,\n onPlacementChange: (p) => {\n this.dataset.placement = p;\n },\n });\n\n /** The HTML id of the element triggering the popover. */\n @property()\n accessor for = '';\n\n /** The preferred placement of the popover. */\n @property()\n accessor placement: Placement = 'bottom';\n\n /** The distance in pixels from the target element. */\n @property({ type: Number })\n accessor distance = 8;\n\n /** Whether or not the popover is visible. */\n @property({ type: Boolean, reflect: true })\n accessor open = false;\n\n /** Hide the directional arrow. */\n @property({ type: Boolean, reflect: true, attribute: 'without-arrow' })\n accessor withoutArrow = false;\n\n /** Stretch the popover to the viewport width. Useful for mega menus. */\n @property({ type: Boolean, reflect: true, attribute: 'full-width' })\n accessor fullWidth = false;\n\n /** Space-separated list of trigger modes: `click`, `hover`, `focus`, `manual`. */\n @property()\n accessor trigger = 'click';\n\n private _hasTrigger(type: string) {\n return this.trigger.split(' ').includes(type);\n }\n\n private get _trigger(): HTMLElement | null {\n return this._triggerFor(this.for);\n }\n\n private _triggerFor(id: string): HTMLElement | null {\n if (!id) return null;\n // A detached popover's root is a plain element with no getElementById —\n // async open/close work may land after removal.\n const root = this.getRootNode();\n return root instanceof Document || root instanceof ShadowRoot ? root.getElementById(id) : null;\n }\n\n private get _popoverEl(): HTMLElement {\n return this.shadowRoot!.querySelector('[popover]')!;\n }\n\n private get _arrowEl(): HTMLElement | null {\n return this.withoutArrow ? null : this.shadowRoot!.querySelector('i');\n }\n\n override connectedCallback() {\n super.connectedCallback();\n requestAnimationFrame(() => this._addTriggerListeners());\n }\n\n override disconnectedCallback() {\n super.disconnectedCallback();\n // `aria-expanded` is dropped (not set to \"false\") by the controller's\n // hostDisconnected: with the panel gone the trigger expands nothing.\n this._removeTriggerListeners();\n }\n\n override updated(changed: PropertyValues<this>) {\n // `for` before `open`: retargeting an already-open panel has to settle\n // against the new anchor, and when both change in the same update the open\n // path owns the positioning outright (see the guard below).\n if (changed.has('for')) {\n this._removeTriggerListeners(changed.get('for'));\n this._addTriggerListeners();\n if (this.open && !changed.has('open')) {\n void this._repositionToTrigger();\n }\n }\n if (changed.has('open')) {\n void this._handleOpenChange();\n }\n }\n\n show() {\n if (!this.open) this.open = true;\n }\n\n hide() {\n if (this.open) this.open = false;\n }\n\n toggle() {\n this.open = !this.open;\n }\n\n /**\n * Recompute the position against the current trigger. Use it when you move\n * the anchor yourself and the panel has to follow. No-op when closed; hides\n * if the anchor is gone.\n */\n async reposition() {\n if (!this.open) return;\n await this._repositionToTrigger();\n }\n\n /**\n * Move the open panel onto whatever `for` names now — a move, not a re-open,\n * so it deliberately bypasses `_handleOpenChange` and its show animation.\n * Shared by the public `reposition()` and the retarget path so the two\n * cannot drift apart.\n */\n private async _repositionToTrigger() {\n this._floating.cleanupSafePolygon();\n const openFor = this.for;\n const result = await this._floating.reposition(\n this._positionOptions(),\n () => this.open && this.for === openFor,\n );\n // Closed or retargeted again while `computePosition` was in flight.\n if (result === 'stale') return;\n // Retargeted onto an id that resolves to nothing: a panel left floating\n // over unrelated content is worse than none.\n if (result === 'no-anchor') {\n this.hide();\n return;\n }\n this._floating.markTrigger('aria-expanded', 'true', 'false');\n }\n\n private _positionOptions() {\n return {\n placement: this.placement,\n distance: this.distance,\n fullWidth: this.fullWidth,\n };\n }\n\n private async _handleOpenChange() {\n const popover = this._popoverEl;\n if (!popover) return;\n\n const posOpts = this._positionOptions();\n\n if (this.open) {\n popover.showPopover();\n await this._floating.updatePosition(posOpts);\n if (!this.open) return;\n await this._floating.animateShow(popover);\n this._floating.startPositioning(posOpts);\n this._floating.markTrigger('aria-expanded', 'true', 'false');\n // No aria-controls: the panel's id lives in this element's shadow root and\n // IDREFs don't cross shadow boundaries, so the reference would never\n // resolve (invalid per WCAG 4.1.2). aria-expanded alone conveys the state.\n } else {\n this._floating.stopPositioning();\n this._floating.cleanupSafePolygon();\n this._floating.releaseTrigger('false');\n await this._floating.animateHide(popover);\n if (popover.matches(':popover-open')) popover.hidePopover();\n }\n }\n\n // --- Trigger event handlers ---\n\n private _onPointerEnter = () => {\n if (!this._hasTrigger('hover')) return;\n this._floating.cleanupSafePolygon();\n this.show();\n };\n\n private _onPointerLeave = (e: PointerEvent) => {\n if (!this._hasTrigger('hover') || !this.open) return;\n this._floating.handlePointerLeave(e, () => this.hide());\n };\n\n private _onFocusIn = () => {\n if (this._hasTrigger('focus')) this.show();\n };\n private _onFocusOut = () => {\n if (this._hasTrigger('focus')) this.hide();\n };\n private _onClick = () => {\n if (this._hasTrigger('click')) this.toggle();\n };\n\n private _onKeyDown = (e: KeyboardEvent) => {\n if (this.open && e.key === 'Escape') {\n e.stopPropagation();\n this.hide();\n }\n };\n\n /** Sync `open` when popover=\"auto\" light-dismiss fires. */\n private _onToggle = (e: Event) => {\n const toggleEvent = e as ToggleEvent;\n if (toggleEvent.newState === 'closed' && this.open) {\n this.open = false;\n }\n };\n\n private _addTriggerListeners() {\n this._floating.addTriggerListeners({\n onPointerEnter: this._onPointerEnter,\n onPointerLeave: this._onPointerLeave,\n onFocusIn: this._onFocusIn,\n onFocusOut: this._onFocusOut,\n onClick: this._onClick,\n onKeyDown: this._onKeyDown,\n });\n }\n\n private _removeTriggerListeners(forId?: string) {\n this._floating.removeTriggerListeners(forId ? this._triggerFor(forId) : undefined);\n }\n\n override render() {\n return html`\n <div\n id=${this._popoverId}\n popover=\"auto\"\n part=\"body\"\n @toggle=${this._onToggle}\n >\n ${\n this.withoutArrow\n ? nothing\n : html`\n <i\n part=\"arrow\"\n role=\"presentation\"\n ></i>\n `\n }\n <slot></slot>\n </div>\n `;\n }\n}\n"],"mappings":"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"}
@@ -65,7 +65,12 @@ interface SelectEventMap {
65
65
  * @csspart option - Each option row.
66
66
  * @csspart empty - The "no results" message.
67
67
  *
68
- * @cssproperty [--height] - Control height. Defaults to the form-control height.
68
+ * @cssproperty [--height=var(--l-form-control-height)] - Control height. The clear button and the chevron
69
+ * each take a square of this height (borders excluded), so their hit area and spacing follow it.
70
+ * @cssproperty [--l-form-control-icon-size=1em] - Glyph size of the clear button and the chevron (global form-control
71
+ * token; set it here or on any ancestor). Changes the glyph only — the hit area follows `--height`.
72
+ * @cssproperty --chevron-icon - Chevron glyph as a `url()`. Masked, so its color comes from the control, not the image.
73
+ * @cssproperty --clear-icon - Clear button glyph as a `url()`.
69
74
  * @cssproperty [--border-radius] - Trigger + panel radius.
70
75
  * @cssproperty [--background] - Panel background.
71
76
  *
@@ -1 +1 @@
1
- {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/html/elements/select/select.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../src/html/elements/select/select.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,0BAA0B,EAAE,MAAM,+CAA+C,CAAC;AAe3F,OAAO,iBAAiB,CAAC;AAIzB,MAAM,MAAM,UAAU,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAE1D,kDAAkD;AAClD,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,+DAA+D;IAC/D,QAAQ,EAAE,OAAO,CAAC;IAClB,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,yFAAyF;AACzF,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC;AAWxE,+DAA+D;AAC/D,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,kEAAkE;IAClE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAClC,YAAY,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAGnC;CACF;AAED,wEAAwE;AACxE,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,YAAY,KAAK,EAAE,MAAM,EAGxB;CACF;AAED,UAAU,cAAc;IACtB,MAAM,EAAE,iBAAiB,CAAC;IAC1B,KAAK,EAAE,gBAAgB,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,qBAAa,MAAO,SAAQ,0BAA0B;IAOpD,OAAgB,MAAM,4BAOpB;IAEF,OAAO,CAAC,SAAS,CAAgC;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA2B;IACnD,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAyB;IAE1D,OAAO,CAAC,SAAS,CAId;IAEH,OAAO,CAAC,IAAI,CAOT;IAIH,OAAO,CAAC,QAAQ,CAAiE;IAEjF,iEAAiE;IAEjE,QAAQ,CAAC,WAAW,SAAM;IAE1B,wCAAwC;IAExC,QAAQ,CAAC,KAAK,SAAM;IAEpB,oBAAoB;IAEpB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAQ;IAEjC,qEAAqE;IAErE,QAAQ,CAAC,UAAU,UAAS;IAE5B,wCAAwC;IAExC,QAAQ,CAAC,SAAS,UAAS;IAE3B,+CAA+C;IAE/C,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAkB;IAE/C,uFAAuF;IAEvF,QAAQ,CAAC,QAAQ,UAAS;IAE1B,8DAA8D;IAC9D,MAAM,EAAE,YAAY,CAAiB;IAE5B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAgB;IACxC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAM;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoB;IAEpD,OAAO,CAAC,cAAc,CAAgB;IAEtC,2EAA2E;IAC3E,IAAI,KAAK,IAAI,MAAM,GAAG,MAAM,EAAE,CAE7B;IACD,IAAI,KAAK,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAE7B;IAED,OAAO,KAAK,UAAU,GAErB;IACD,OAAO,KAAK,QAAQ,GAEnB;IACD,OAAO,KAAK,SAAS,GAEpB;IAED,IAAa,gBAAgB,4BAE5B;IAEQ,iBAAiB,SAgBzB;IAEQ,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,QAK7C;IAEQ,iBAAiB,SAMzB;IAEQ,wBAAwB,CAAC,KAAK,EAAE,MAAM,QAG9C;IAID,OAAO,CAAC,UAAU;IAiBlB;;;;;;;OAOG;IACH,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,QAAQ;IAIhB,OAAO,KAAK,SAAS,GAEpB;IAID,qFAAqF;IACrF,OAAO,CAAC,SAAS;IAUjB,OAAO,CAAC,eAAe;IAcvB,IAAI,SAsBH;IAED,IAAI,CAAC,EAAE,YAAmB,EAAE;;KAAK,QAWhC;IAED,OAAO,CAAC,sBAAsB,CAO5B;IAIF,iFAAiF;IACjF,OAAO,CAAC,OAAO;IAgBf,4DAA4D;IAC5D,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,MAAM;IAUd,OAAO,CAAC,iBAAiB,CAMvB;IAEF,OAAO,CAAC,eAAe,CAmBrB;IAEF,OAAO,CAAC,cAAc,CAIpB;IAIF,OAAO,CAAC,kBAAkB;IAU1B,OAAO,CAAC,YAAY;IAuBpB,OAAO,CAAC,cAAc;IAwDb,MAAM,oCA+Gd;CACF;AAGD,MAAM,WAAW,MAAM;IACrB,gBAAgB,CAAC,CAAC,SAAS,MAAM,cAAc,EAC7C,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,EACvD,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,gBAAgB,CACd,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,uBAAuB,GAC1C,IAAI,CAAC;IACR,mBAAmB,CAAC,CAAC,SAAS,MAAM,cAAc,EAChD,IAAI,EAAE,CAAC,EACP,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,KAAK,IAAI,EACvD,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;IACR,mBAAmB,CACjB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,kCAAkC,EAC5C,OAAO,CAAC,EAAE,OAAO,GAAG,oBAAoB,GACvC,IAAI,CAAC;CACT"}
@@ -1,4 +1,4 @@
1
- import{i as e}from"../../chunks/lit.js";import{n as t,r as n}from"../../chunks/static-html.js";import{n as r,r as i,t as a}from"../../chunks/decorate.js";import{a as o,t as s}from"../../chunks/lit-html.js";import{t as c}from"../../chunks/unsafe-html.js";import{LuxenFormAssociatedElement as l}from"../../shared/luxen-form-associated-element.js";import{PopoverController as u}from"../../shared/controllers/popover.js";import{ListboxNavController as d}from"../../shared/controllers/listbox-nav.js";import{DatalistObserverController as f}from"../../shared/controllers/datalist-observer.js";import{LocalizeController as p}from"../../shared/localize.js";import{RichHighlighter as m,highlightText as h,normalize as g}from"../../shared/highlight.js";import{tagName as _,uniqueId as v}from"../../registry.js";import{adoptRichContentStyles as y,richOptionLabel as b}from"../../shared/rich-option.js";import x from"../../shared/styles/host.styles.js";import S from"../../shared/styles/select-item-suffix.styles.js";var C=e(`:host{--height:var(--l-form-control-height);--border-radius:var(--l-form-control-border-radius);--background:var(--l-color-surface-overlay);inline-size:100%;display:block}:host([size=xs]){--height:var(--l-size-control-xs)}:host([size=sm]){--height:var(--l-size-control-sm)}:host([size=lg]){--height:var(--l-size-control-lg)}:host([size=xl]){--height:var(--l-size-control-xl)}:host([disabled]){opacity:.5;pointer-events:none}.base{position:relative}.trigger{inline-size:100%;min-block-size:var(--height);padding-block:.25rem;padding-inline:var(--l-form-control-padding-inline);border:var(--l-form-control-border-width) solid var(--l-form-control-border-color);border-radius:var(--border-radius);background-color:var(--l-form-control-background-color);color:var(--l-form-control-value-color);font:inherit;text-align:start;cursor:pointer;align-items:center;gap:.5rem;display:flex}:host([multiple]) .trigger{padding-inline-start:.375rem}@media (hover:hover){.trigger:hover{border-color:var(--l-form-control-border-color-hover)}}.trigger:focus-visible{border-color:var(--l-focus-ring);box-shadow:0 0 0 3px color-mix(in oklab, var(--l-focus-ring) 22%, transparent);outline:none}.value{flex-wrap:wrap;flex:1;align-items:center;gap:.25rem;min-inline-size:0;display:flex;overflow:hidden}.value-text{text-overflow:ellipsis;white-space:nowrap;min-inline-size:0;overflow:hidden}[part=tag]{--height:initial;--border-radius:initial}.placeholder{color:var(--l-form-control-placeholder-color)}.chevron{block-size:1em;inline-size:1em;color:var(--l-form-control-placeholder-color);-webkit-mask:var(--_chevron-icon) center / contain no-repeat;mask:var(--_chevron-icon) center / contain no-repeat;background-color:currentColor;flex:none;transition:rotate .15s}.trigger[aria-expanded=true] .chevron{rotate:180deg}.clear{cursor:pointer;block-size:1.5rem;inline-size:1.5rem;color:var(--l-form-control-placeholder-color);-webkit-mask:var(--_x-icon) center / 1em no-repeat;mask:var(--_x-icon) center / 1em no-repeat;background-color:currentColor;border:0;margin-block:auto;padding:0;position:absolute;inset-block:0;inset-inline-end:calc(var(--l-form-control-padding-inline) + 1.25em)}@media (hover:hover){.clear:hover{color:var(--l-form-control-value-color)}}.clear:focus-visible{outline:2px solid var(--l-focus-ring);outline-offset:2px}.value .l-select-item-media{flex:none;align-items:center;font-size:1.25em;display:inline-flex}.value .l-select-item-text{flex-direction:column;min-inline-size:0;display:flex}.value .l-select-item-title{font-weight:inherit;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.value .l-select-item-description,.value .l-select-item-suffix{display:none}.panel{border:1px solid var(--l-color-border-overlay);border-radius:var(--border-radius);background-color:var(--background);color:var(--l-color-text-primary);box-shadow:var(--l-shadow-md);opacity:0;transition:opacity .12s ease, scale .12s ease, display .12s allow-discrete, overlay .12s allow-discrete;margin:0;padding:0;font-size:.875rem;line-height:1.5;inset:auto;overflow:hidden;scale:.98}.panel:popover-open{opacity:1;scale:1}@starting-style{.panel:popover-open{opacity:0;scale:.98}}.search-row{border-block-end:1px solid var(--l-color-border-overlay);padding:.375rem}.search{inline-size:100%;block-size:var(--l-size-control-sm);border:var(--l-form-control-border-width) solid var(--l-form-control-border-color);border-radius:calc(var(--border-radius) - 2px);background-color:var(--l-form-control-background-color);color:var(--l-form-control-value-color);font:inherit;padding-inline:.5rem}.search:focus-visible{border-color:var(--l-focus-ring);outline:none}.search::placeholder{color:var(--l-form-control-placeholder-color)}.listbox{overscroll-behavior:contain;max-block-size:16rem;margin:0;padding:.25rem;list-style:none;overflow-y:auto}.option{min-block-size:36px;color:var(--l-color-text-primary);cursor:pointer;border-radius:4px;align-items:start;gap:.5rem;padding-block:.5rem;padding-inline:1.75rem .5rem;display:flex;position:relative}@media (hover:hover){.option:hover{background-color:var(--l-color-bg-state-hover)}}.option[data-active]{background-color:var(--l-color-bg-state-hover)}.option[aria-disabled=true]{opacity:.4;cursor:not-allowed}.option[data-current]:after{content:"";block-size:1.3125rem;inline-size:1rem;-webkit-mask:var(--_check-icon) center / 1rem no-repeat;mask:var(--_check-icon) center / 1rem no-repeat;background-color:currentColor;position:absolute;inset-block-start:.5rem;inset-inline-start:.5rem}.option-label{text-overflow:ellipsis;white-space:nowrap;flex:1;min-inline-size:0;overflow:hidden}mark.match{background-color:var(--l-form-control-match-background-color);color:inherit;font-weight:var(--l-form-control-match-font-weight);-webkit-box-decoration-break:clone;box-decoration-break:clone;border-radius:.2em}.option-rich{flex:1;align-items:start;gap:.5rem;min-inline-size:0;display:flex}.option-rich .l-select-item-media{object-fit:cover;border-radius:4px;flex:none;align-items:center;block-size:1.5rem;inline-size:1.5rem;font-size:1.25em;display:inline-flex}.option-rich .l-select-item-text{flex-direction:column;flex:auto;min-inline-size:0;display:flex}.option-rich .l-select-item-title{text-overflow:ellipsis;white-space:nowrap;font-weight:var(--l-font-weight-semibold);overflow:hidden}.option-rich .l-select-item-description{color:var(--l-color-text-tertiary);white-space:normal;text-wrap:pretty;font-size:.75rem;line-height:1.3}.empty{color:var(--l-color-text-tertiary);text-align:center;padding:.5rem}.visually-hidden{clip-path:inset(50%);white-space:nowrap;border:0;block-size:1px;inline-size:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}:host{--_chevron-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");--_x-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M18 6 6 18M6 6l12 12'/%3E%3C/svg%3E");--_check-icon:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E")}@media (prefers-reduced-motion:reduce){.panel,.chevron{transition-duration:0s}}`),w=(e,t)=>{if(!t)return!0;let n=g(e.label);return g(t).split(/\s+/).filter(Boolean).every(e=>n.includes(e))},T=class extends Event{constructor(e){super(`change`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e}},E=class extends Event{constructor(e){super(`input`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e}},D=class extends l{constructor(...e){super(...e),this._localize=new p(this),this._listId=v(`select-list`),this._richHighlighter=new m,this._floating=new u(this,{getTriggerElement:()=>this._triggerEl,getFloatingElement:()=>this._panelEl,getArrowElement:()=>null}),this._nav=new d(this,{listboxId:this._listId,getCount:()=>this._filtered.length,isDisabled:e=>this._filtered[e]?.disabled??!1,isOpen:()=>this._open,open:()=>this.show(),getOptionElements:()=>this.shadowRoot?.querySelectorAll(`.option`)}),this._options=new f(this,()=>this._syncItems()),this.#e=``,this.#t=``,this.#n=`md`,this.#r=!1,this.#i=!1,this.#a=`bottom-start`,this.#o=!1,this.filter=w,this.#s=[],this.#c=!1,this.#l=``,this.#u=[],this._defaultValues=[],this._onDocumentPointerDown=e=>{e.composedPath().includes(this)||(this.hasInteracted=!0,this._updateValidity(),this.hide({focusTrigger:!1}))},this._onTriggerKeyDown=e=>{this._open||(e.key===`ArrowDown`||e.key===`ArrowUp`||e.key===`Enter`||e.key===` `)&&(e.preventDefault(),this.show())},this._onPanelKeyDown=e=>{if(!this._nav.onKeyDown(e))switch(e.key){case`Enter`:{e.preventDefault();let t=this._filtered[this._nav.activeIndex];t&&this._select(t);break}case`Escape`:e.preventDefault(),this.hide();break;case`Tab`:this.hide({focusTrigger:!1})}},this._onSearchInput=e=>{this._query=e.target.value,this._nav.reset(),this.dispatchEvent(new E(this._query))}}static{this.styles=[x,S,C]}#e;get placeholder(){return this.#e}set placeholder(e){this.#e=e}#t;get label(){return this.#t}set label(e){this.#t=e}#n;get size(){return this.#n}set size(e){this.#n=e}#r;get searchable(){return this.#r}set searchable(e){this.#r=e}#i;get withClear(){return this.#i}set withClear(e){this.#i=e}#a;get placement(){return this.#a}set placement(e){this.#a=e}#o;get multiple(){return this.#o}set multiple(e){this.#o=e}#s;get _values(){return this.#s}set _values(e){this.#s=e}#c;get _open(){return this.#c}set _open(e){this.#c=e}#l;get _query(){return this.#l}set _query(e){this.#l=e}#u;get _items(){return this.#u}set _items(e){this.#u=e}get value(){return this.multiple?[...this._values]:this._values[0]??``}set value(e){this._values=Array.isArray(e)?[...e]:e?[e]:[]}get _triggerEl(){return this.shadowRoot?.querySelector(`.trigger`)??null}get _panelEl(){return this.shadowRoot?.querySelector(`.panel`)??null}get _searchEl(){return this.shadowRoot?.querySelector(`.search`)??null}get validationTarget(){return this._triggerEl??void 0}connectedCallback(){if(super.connectedCallback(),this._readItems(),this._values.length===0){let e=this.getAttribute(`value`);if(e)this._values=[e];else{let e=this._items.filter(e=>e.selected).map(e=>e.value);this._values=this.multiple?e:e.slice(0,1)}}this._defaultValues=[...this._values],this._syncForm()}updated(e){(e.has(`_values`)||e.has(`multiple`))&&(this._syncForm(),this._updateValidity())}formResetCallback(){this._values=[...this._defaultValues],this._query=``,this._nav.reset(),super.formResetCallback(),this._syncForm()}formStateRestoreCallback(e){this.value=e,this._syncForm()}_readItems(){let e=this.querySelector(`datalist`),t=e?Array.from(e.options):[];this._items=t.map(e=>{let t=e.childElementCount>0,n=b(e);return{value:e.value,label:n,disabled:e.disabled,selected:e.hasAttribute(`selected`),html:t?e.innerHTML:void 0}}),y(this.shadowRoot,this._items)}_syncItems(){let e=this._open?this._filtered[this._nav.activeIndex]:void 0;this._readItems(),this._open&&this._nav.setActive(e?this._filtered.findIndex(t=>t.value===e.value):-1)}_itemFor(e){return this._items.find(t=>t.value===e)}get _filtered(){return this._items.filter(e=>this.filter(e,this._query))}_syncForm(){if(this.multiple){let e=new FormData;for(let t of this._values)e.append(this.name,t);this._internals.setFormValue(e)}else this._internals.setFormValue(this._values[0]??``)}_updateValidity(){this.required&&this._values.length===0?this.setValidity({valueMissing:!0},this._localize.term(`selectOption`),this._triggerEl??void 0):this.setValidity({})}show(){this._open||this.disabled||(this._readItems(),this.dispatchEvent(new Event(`show`,{cancelable:!0}))&&(this._open=!0,this._query=``,this._values.length&&this._nav.setActive(this._filtered.findIndex(e=>e.value===this._values[0])),this.updateComplete.then(()=>{this._panelEl?.showPopover?.(),this._floating.startPositioning({placement:this.placement,distance:4,minWidth:`trigger`}),(this._searchEl??this._panelEl?.querySelector(`.listbox`))?.focus(),document.addEventListener(`pointerdown`,this._onDocumentPointerDown,!0)})))}hide({focusTrigger:e=!0}={}){if(!this._open||!this.dispatchEvent(new Event(`hide`,{cancelable:!0})))return;this._open=!1,this._query=``,this._nav.reset();let t=this._panelEl;t?.matches?.(`:popover-open`)&&t.hidePopover?.(),this._floating.stopPositioning(),document.removeEventListener(`pointerdown`,this._onDocumentPointerDown,!0),e&&this._triggerEl?.focus()}_select(e){e.disabled||(this.hasInteracted=!0,this.multiple?(this._values=this._values.includes(e.value)?this._values.filter(t=>t!==e.value):[...this._values,e.value],this.dispatchEvent(new T(this.value)),this._searchEl?.focus()):(this._values=[e.value],this.dispatchEvent(new T(this.value)),this.hide()))}_removeValue(e){this._values=this._values.filter(t=>t!==e),this.hasInteracted=!0,this.dispatchEvent(new T(this.value))}_clear(e){e?.stopPropagation(),this._values=[],this.hasInteracted=!0,this.dispatchEvent(new T(this.value)),this._triggerEl?.focus()}_renderSingleValue(){let e=this._itemFor(this._values[0]);return e?e.html?o`${c(e.html)}`:o`<span class="value-text">${e.label}</span>`:o`<span class="value-text placeholder">${this.placeholder}</span>`}_renderChips(){if(this._values.length===0)return o`<span class="value-text placeholder">${this.placeholder}</span>`;let e=t(_(`tag`));return this._values.map(t=>{let r=this._itemFor(t);return n`<${e}
1
+ import{i as e}from"../../chunks/lit.js";import{n as t,r as n}from"../../chunks/static-html.js";import{n as r,r as i,t as a}from"../../chunks/decorate.js";import{a as o,t as s}from"../../chunks/lit-html.js";import{t as c}from"../../chunks/unsafe-html.js";import{LuxenFormAssociatedElement as l}from"../../shared/luxen-form-associated-element.js";import{PopoverController as u}from"../../shared/controllers/popover.js";import{ListboxNavController as d}from"../../shared/controllers/listbox-nav.js";import{DatalistObserverController as f}from"../../shared/controllers/datalist-observer.js";import{LocalizeController as p}from"../../shared/localize.js";import{RichHighlighter as m,highlightText as h,normalize as g}from"../../shared/highlight.js";import{cls as _,tagName as v,uniqueId as y}from"../../registry.js";import{adoptRichContentStyles as b,richOptionLabel as x}from"../../shared/rich-option.js";import S from"../../shared/styles/host.styles.js";import C from"../../shared/styles/visually-hidden.styles.js";import w from"../../shared/styles/select-item-suffix.styles.js";import T from"../../shared/styles/picker-core.styles.js";import E from"../../shared/styles/select-item.styles.js";var D=e(`.trigger{inline-size:100%;min-block-size:var(--height);color:var(--l-form-control-value-color);font:inherit;text-align:start;cursor:pointer;gap:.5rem;padding-block:.25rem}:host([multiple]) .trigger{padding-inline-start:.375rem}.trigger:focus-visible{outline:none}.value{flex-wrap:wrap;flex:1;align-items:center;gap:.25rem;min-inline-size:0;display:flex;overflow:hidden}.value-text{text-overflow:ellipsis;white-space:nowrap;min-inline-size:0;overflow:hidden}[part=tag]{--height:initial;--border-radius:initial}.placeholder{color:var(--l-form-control-placeholder-color)}.clear-button{margin-block:auto;position:absolute;inset-block:0;inset-inline-end:calc(var(--l-form-control-border-width) + var(--_action-size))}.base:has(>.clear-button) .chevron{margin-inline-start:var(--_action-size)}.value .l-select-item-title{font-weight:inherit}.value .l-select-item-description,.value .l-select-item-suffix{display:none}.search-row{border-block-end:1px solid var(--l-color-border-overlay);padding:.375rem}.search{inline-size:100%;block-size:var(--l-size-control-sm);border:var(--l-form-control-border-width) solid var(--l-form-control-border-color);border-radius:calc(var(--border-radius) - 2px);background-color:var(--l-form-control-background-color);color:var(--l-form-control-value-color);font:inherit;padding-inline:.5rem}.search:focus-visible{border-color:var(--l-focus-ring);outline:none}.search::placeholder{color:var(--l-form-control-placeholder-color)}.option[data-active]{background-color:var(--l-color-bg-state-hover)}.option[data-current]:after{content:"";inline-size:1rem;block-size:calc(var(--l-popover-font-size) * var(--l-popover-line-height));-webkit-mask:var(--_check-icon) center / 1rem no-repeat;mask:var(--_check-icon) center / 1rem no-repeat;background-color:currentColor;position:absolute;inset-block-start:var(--_row-padding-block);inset-inline-start:.5rem}.l-select-item-media{align-items:center;font-size:1.25em;display:inline-flex}`),O=(e,t)=>{if(!t)return!0;let n=g(e.label);return g(t).split(/\s+/).filter(Boolean).every(e=>n.includes(e))},k=class extends Event{constructor(e){super(`change`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e}},A=class extends Event{constructor(e){super(`input`,{bubbles:!0,composed:!1,cancelable:!1}),this.value=e}},j=class extends l{constructor(...e){super(...e),this._localize=new p(this),this._listId=y(`select-list`),this._richHighlighter=new m,this._floating=new u(this,{getTriggerElement:()=>this._triggerEl,getFloatingElement:()=>this._panelEl,getArrowElement:()=>null}),this._nav=new d(this,{listboxId:this._listId,getCount:()=>this._filtered.length,isDisabled:e=>this._filtered[e]?.disabled??!1,isOpen:()=>this._open,open:()=>this.show(),getOptionElements:()=>this.shadowRoot?.querySelectorAll(`.option`)}),this._options=new f(this,()=>this._syncItems()),this.#e=``,this.#t=``,this.#n=`md`,this.#r=!1,this.#i=!1,this.#a=`bottom-start`,this.#o=!1,this.filter=O,this.#s=[],this.#c=!1,this.#l=``,this.#u=[],this._defaultValues=[],this._onDocumentPointerDown=e=>{e.composedPath().includes(this)||(this.hasInteracted=!0,this._updateValidity(),this.hide({focusTrigger:!1}))},this._onTriggerKeyDown=e=>{this._open||(e.key===`ArrowDown`||e.key===`ArrowUp`||e.key===`Enter`||e.key===` `)&&(e.preventDefault(),this.show())},this._onPanelKeyDown=e=>{if(!this._nav.onKeyDown(e))switch(e.key){case`Enter`:{e.preventDefault();let t=this._filtered[this._nav.activeIndex];t&&this._select(t);break}case`Escape`:e.preventDefault(),this.hide();break;case`Tab`:this.hide({focusTrigger:!1})}},this._onSearchInput=e=>{this._query=e.target.value,this._nav.reset(),this.dispatchEvent(new A(this._query))}}static{this.styles=[S,C,w,E,T,D]}#e;get placeholder(){return this.#e}set placeholder(e){this.#e=e}#t;get label(){return this.#t}set label(e){this.#t=e}#n;get size(){return this.#n}set size(e){this.#n=e}#r;get searchable(){return this.#r}set searchable(e){this.#r=e}#i;get withClear(){return this.#i}set withClear(e){this.#i=e}#a;get placement(){return this.#a}set placement(e){this.#a=e}#o;get multiple(){return this.#o}set multiple(e){this.#o=e}#s;get _values(){return this.#s}set _values(e){this.#s=e}#c;get _open(){return this.#c}set _open(e){this.#c=e}#l;get _query(){return this.#l}set _query(e){this.#l=e}#u;get _items(){return this.#u}set _items(e){this.#u=e}get value(){return this.multiple?[...this._values]:this._values[0]??``}set value(e){this._values=Array.isArray(e)?[...e]:e?[e]:[]}get _triggerEl(){return this.shadowRoot?.querySelector(`.trigger`)??null}get _panelEl(){return this.shadowRoot?.querySelector(`.panel`)??null}get _searchEl(){return this.shadowRoot?.querySelector(`.search`)??null}get validationTarget(){return this._triggerEl??void 0}connectedCallback(){if(super.connectedCallback(),this._readItems(),this._values.length===0){let e=this.getAttribute(`value`);if(e)this._values=[e];else{let e=this._items.filter(e=>e.selected).map(e=>e.value);this._values=this.multiple?e:e.slice(0,1)}}this._defaultValues=[...this._values],this._syncForm()}updated(e){(e.has(`_values`)||e.has(`multiple`))&&(this._syncForm(),this._updateValidity())}formResetCallback(){this._values=[...this._defaultValues],this._query=``,this._nav.reset(),super.formResetCallback(),this._syncForm()}formStateRestoreCallback(e){this.value=e,this._syncForm()}_readItems(){let e=this.querySelector(`datalist`),t=e?Array.from(e.options):[];this._items=t.map(e=>{let t=e.childElementCount>0,n=x(e);return{value:e.value,label:n,disabled:e.disabled,selected:e.hasAttribute(`selected`),html:t?e.innerHTML:void 0}}),b(this.shadowRoot,this._items)}_syncItems(){let e=this._open?this._filtered[this._nav.activeIndex]:void 0;this._readItems(),this._open&&this._nav.setActive(e?this._filtered.findIndex(t=>t.value===e.value):-1)}_itemFor(e){return this._items.find(t=>t.value===e)}get _filtered(){return this._items.filter(e=>this.filter(e,this._query))}_syncForm(){if(this.multiple){let e=new FormData;for(let t of this._values)e.append(this.name,t);this._internals.setFormValue(e)}else this._internals.setFormValue(this._values[0]??``)}_updateValidity(){this.required&&this._values.length===0?this.setValidity({valueMissing:!0},this._localize.term(`selectOption`),this._triggerEl??void 0):this.setValidity({})}show(){this._open||this.disabled||(this._readItems(),this.dispatchEvent(new Event(`show`,{cancelable:!0}))&&(this._open=!0,this._query=``,this._values.length&&this._nav.setActive(this._filtered.findIndex(e=>e.value===this._values[0])),this.updateComplete.then(()=>{this._panelEl?.showPopover?.(),this._floating.startPositioning({placement:this.placement,distance:4,minWidth:`trigger`}),(this._searchEl??this._panelEl?.querySelector(`.listbox`))?.focus(),document.addEventListener(`pointerdown`,this._onDocumentPointerDown,!0)})))}hide({focusTrigger:e=!0}={}){if(!this._open||!this.dispatchEvent(new Event(`hide`,{cancelable:!0})))return;this._open=!1,this._query=``,this._nav.reset();let t=this._panelEl;t?.matches?.(`:popover-open`)&&t.hidePopover?.(),this._floating.stopPositioning(),document.removeEventListener(`pointerdown`,this._onDocumentPointerDown,!0),e&&this._triggerEl?.focus()}_select(e){e.disabled||(this.hasInteracted=!0,this.multiple?(this._values=this._values.includes(e.value)?this._values.filter(t=>t!==e.value):[...this._values,e.value],this.dispatchEvent(new k(this.value)),this._searchEl?.focus()):(this._values=[e.value],this.dispatchEvent(new k(this.value)),this.hide()))}_removeValue(e){this._values=this._values.filter(t=>t!==e),this.hasInteracted=!0,this.dispatchEvent(new k(this.value))}_clear(e){e?.stopPropagation(),this._values=[],this.hasInteracted=!0,this.dispatchEvent(new k(this.value)),this._triggerEl?.focus()}_renderSingleValue(){let e=this._itemFor(this._values[0]);return e?e.html?o`${c(e.html)}`:o`<span class="value-text">${e.label}</span>`:o`<span class="value-text placeholder">${this.placeholder}</span>`}_renderChips(){if(this._values.length===0)return o`<span class="value-text placeholder">${this.placeholder}</span>`;let e=t(v(`tag`));return this._values.map(t=>{let r=this._itemFor(t);return n`<${e}
2
2
  size="sm"
3
3
  removable
4
4
  part="tag"
@@ -13,6 +13,7 @@ import{i as e}from"../../chunks/lit.js";import{n as t,r as n}from"../../chunks/s
13
13
  >
14
14
  <span
15
15
  class="chevron"
16
+ part="chevron"
16
17
  aria-hidden="true"
17
18
  ></span>
18
19
  `,n=()=>this._open?this.hide():this.show();return this.multiple?o`<div
@@ -53,7 +54,7 @@ import{i as e}from"../../chunks/lit.js";import{n as t,r as n}from"../../chunks/s
53
54
  >
54
55
  ${this._renderTrigger(r)}
55
56
  ${this.withClear&&i?o`<button
56
- class="clear"
57
+ class="clear-button"
57
58
  part="clear"
58
59
  type="button"
59
60
  aria-label=${this._localize.term(`clear`)}
@@ -90,6 +91,8 @@ import{i as e}from"../../chunks/lit.js";import{n as t,r as n}from"../../chunks/s
90
91
  aria-label=${this.label||this._localize.term(`suggestions`)}
91
92
  aria-multiselectable=${this.multiple?`true`:s}
92
93
  aria-activedescendant=${this.searchable?s:t??s}
94
+ @pointermove=${this._nav.onPointerMove}
95
+ @pointerleave=${this._nav.onPointerLeave}
93
96
  >
94
97
  ${e.map((e,t)=>o`<li
95
98
  class="option"
@@ -103,9 +106,7 @@ import{i as e}from"../../chunks/lit.js";import{n as t,r as n}from"../../chunks/s
103
106
  @pointerdown=${e=>e.preventDefault()}
104
107
  @click=${()=>this._select(e)}
105
108
  >
106
- ${e.html?o`<span class="option-rich"
107
- >${c(this._richHighlighter.highlight(e.html,this._query))}</span
108
- >`:o`<span class="option-label"
109
+ ${e.html?c(this._richHighlighter.highlight(e.html,this._query)):o`<span class="option-label"
109
110
  >${h(e.label,this._query)}</span
110
111
  >`}
111
112
  </li>`)}
@@ -119,11 +120,11 @@ import{i as e}from"../../chunks/lit.js";import{n as t,r as n}from"../../chunks/s
119
120
  </div>
120
121
 
121
122
  <div
122
- class="visually-hidden"
123
+ class=${_(`visually-hidden`)}
123
124
  aria-live="polite"
124
125
  >
125
126
  ${a}
126
127
  </div>
127
128
  </div>
128
- `}};a([i()],D.prototype,`placeholder`,null),a([i()],D.prototype,`label`,null),a([i({reflect:!0})],D.prototype,`size`,null),a([i({type:Boolean,reflect:!0})],D.prototype,`searchable`,null),a([i({type:Boolean,reflect:!0,attribute:`with-clear`})],D.prototype,`withClear`,null),a([i()],D.prototype,`placement`,null),a([i({type:Boolean,reflect:!0})],D.prototype,`multiple`,null),a([r()],D.prototype,`_values`,null),a([r()],D.prototype,`_open`,null),a([r()],D.prototype,`_query`,null),a([r()],D.prototype,`_items`,null);export{D as Select,T as SelectChangeEvent,E as SelectInputEvent};
129
+ `}};a([i()],j.prototype,`placeholder`,null),a([i()],j.prototype,`label`,null),a([i({reflect:!0})],j.prototype,`size`,null),a([i({type:Boolean,reflect:!0})],j.prototype,`searchable`,null),a([i({type:Boolean,reflect:!0,attribute:`with-clear`})],j.prototype,`withClear`,null),a([i()],j.prototype,`placement`,null),a([i({type:Boolean,reflect:!0})],j.prototype,`multiple`,null),a([r()],j.prototype,`_values`,null),a([r()],j.prototype,`_open`,null),a([r()],j.prototype,`_query`,null),a([r()],j.prototype,`_items`,null);export{j as Select,k as SelectChangeEvent,A as SelectInputEvent};
129
130
  //# sourceMappingURL=select.js.map