@helixui/library 3.4.0 → 3.4.1-next.125

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 (105) hide show
  1. package/dist/components/hx-button-group/hx-button-group.d.ts +9 -0
  2. package/dist/components/hx-button-group/hx-button-group.d.ts.map +1 -1
  3. package/dist/components/hx-button-group/index.js +1 -1
  4. package/dist/components/hx-card/hx-card.d.ts +68 -0
  5. package/dist/components/hx-card/hx-card.d.ts.map +1 -1
  6. package/dist/components/hx-card/hx-card.styles.d.ts.map +1 -1
  7. package/dist/components/hx-card/index.js +1 -1
  8. package/dist/components/hx-checkbox/index.js +1 -1
  9. package/dist/components/hx-checkbox-group/index.js +1 -1
  10. package/dist/components/hx-color-picker/index.js +1 -1
  11. package/dist/components/hx-combobox/index.js +1 -1
  12. package/dist/components/hx-date-picker/index.js +1 -1
  13. package/dist/components/hx-dialog/index.js +1 -1
  14. package/dist/components/hx-drawer/index.js +1 -1
  15. package/dist/components/hx-dropdown/index.js +1 -1
  16. package/dist/components/hx-list/index.js +1 -1
  17. package/dist/components/hx-menu/index.js +1 -1
  18. package/dist/components/hx-meter/hx-meter.d.ts.map +1 -1
  19. package/dist/components/hx-meter/index.js +1 -1
  20. package/dist/components/hx-overflow-menu/index.js +1 -1
  21. package/dist/components/hx-popover/index.js +1 -1
  22. package/dist/components/hx-progress-bar/index.js +1 -1
  23. package/dist/components/hx-radio-group/index.js +1 -1
  24. package/dist/components/hx-select/index.js +1 -1
  25. package/dist/components/hx-spinner/hx-spinner.d.ts.map +1 -1
  26. package/dist/components/hx-spinner/index.js +1 -1
  27. package/dist/components/hx-split-button/index.js +1 -1
  28. package/dist/components/hx-stat/index.js +1 -1
  29. package/dist/components/hx-switch/index.js +1 -1
  30. package/dist/components/hx-table/hx-td.d.ts.map +1 -1
  31. package/dist/components/hx-table/hx-th.d.ts +9 -0
  32. package/dist/components/hx-table/hx-th.d.ts.map +1 -1
  33. package/dist/components/hx-table/index.js +1 -1
  34. package/dist/components/hx-tabs/index.js +1 -1
  35. package/dist/components/hx-time-picker/index.js +1 -1
  36. package/dist/components/hx-toggle-button/index.js +1 -1
  37. package/dist/components/hx-tree-view/index.js +1 -1
  38. package/dist/css/helix-all.css +14 -1
  39. package/dist/css/helix-core.css +14 -1
  40. package/dist/css/hx-card.css +14 -1
  41. package/dist/css/index.css +1 -1
  42. package/dist/css/manifest.json +1 -1
  43. package/dist/index.js +27 -27
  44. package/dist/shared/aria-idref-DCuEaknC.js +131 -0
  45. package/dist/shared/{aria-idref-CxvyzfQS.js.map → aria-idref-DCuEaknC.js.map} +1 -1
  46. package/dist/shared/{hx-button-group-DcHP5MBv.js → hx-button-group-4NUBpkyC.js} +22 -22
  47. package/dist/shared/{hx-button-group-DcHP5MBv.js.map → hx-button-group-4NUBpkyC.js.map} +1 -1
  48. package/dist/shared/{hx-card-qNAM2QNV.js → hx-card-CswtnYvj.js} +142 -85
  49. package/dist/shared/hx-card-CswtnYvj.js.map +1 -0
  50. package/dist/shared/{hx-checkbox-C48KYKFq.js → hx-checkbox-CYd0YV_u.js} +2 -2
  51. package/dist/shared/{hx-checkbox-C48KYKFq.js.map → hx-checkbox-CYd0YV_u.js.map} +1 -1
  52. package/dist/shared/{hx-checkbox-group-BJIAX3zU.js → hx-checkbox-group-D5piJLY8.js} +2 -2
  53. package/dist/shared/{hx-checkbox-group-BJIAX3zU.js.map → hx-checkbox-group-D5piJLY8.js.map} +1 -1
  54. package/dist/shared/{hx-color-picker-Dk4cBwYQ.js → hx-color-picker-DBwJzT5f.js} +2 -2
  55. package/dist/shared/{hx-color-picker-Dk4cBwYQ.js.map → hx-color-picker-DBwJzT5f.js.map} +1 -1
  56. package/dist/shared/{hx-combobox-BTLO9qiK.js → hx-combobox-NgJaLbs2.js} +2 -2
  57. package/dist/shared/{hx-combobox-BTLO9qiK.js.map → hx-combobox-NgJaLbs2.js.map} +1 -1
  58. package/dist/shared/{hx-date-picker-CiR7FVnR.js → hx-date-picker-B49yo4Vm.js} +2 -2
  59. package/dist/shared/{hx-date-picker-CiR7FVnR.js.map → hx-date-picker-B49yo4Vm.js.map} +1 -1
  60. package/dist/shared/{hx-dialog-AOZpHSuF.js → hx-dialog-B4weoj_1.js} +2 -2
  61. package/dist/shared/{hx-dialog-AOZpHSuF.js.map → hx-dialog-B4weoj_1.js.map} +1 -1
  62. package/dist/shared/{hx-drawer-DH6CdAN1.js → hx-drawer-D81tb4BD.js} +2 -2
  63. package/dist/shared/{hx-drawer-DH6CdAN1.js.map → hx-drawer-D81tb4BD.js.map} +1 -1
  64. package/dist/shared/{hx-dropdown-DiLd40Lm.js → hx-dropdown-D626S2ZG.js} +2 -2
  65. package/dist/shared/{hx-dropdown-DiLd40Lm.js.map → hx-dropdown-D626S2ZG.js.map} +1 -1
  66. package/dist/shared/{hx-list-De66EtAP.js → hx-list-Bp8HeLHh.js} +2 -2
  67. package/dist/shared/{hx-list-De66EtAP.js.map → hx-list-Bp8HeLHh.js.map} +1 -1
  68. package/dist/shared/{hx-menu-divider-BjiRIWKq.js → hx-menu-divider-A6Guuzi_.js} +2 -2
  69. package/dist/shared/{hx-menu-divider-BjiRIWKq.js.map → hx-menu-divider-A6Guuzi_.js.map} +1 -1
  70. package/dist/shared/{hx-meter-BJdh6nrF.js → hx-meter-BnpmF3Vx.js} +57 -36
  71. package/dist/shared/{hx-meter-BJdh6nrF.js.map → hx-meter-BnpmF3Vx.js.map} +1 -1
  72. package/dist/shared/{hx-overflow-menu-BQ4fiMYu.js → hx-overflow-menu-DFjJAziP.js} +2 -2
  73. package/dist/shared/{hx-overflow-menu-BQ4fiMYu.js.map → hx-overflow-menu-DFjJAziP.js.map} +1 -1
  74. package/dist/shared/{hx-popover-B9W8-tC0.js → hx-popover-BAlAFOH9.js} +2 -2
  75. package/dist/shared/{hx-popover-B9W8-tC0.js.map → hx-popover-BAlAFOH9.js.map} +1 -1
  76. package/dist/shared/{hx-progress-bar-C8nDMdYa.js → hx-progress-bar-CYz9U721.js} +2 -2
  77. package/dist/shared/{hx-progress-bar-C8nDMdYa.js.map → hx-progress-bar-CYz9U721.js.map} +1 -1
  78. package/dist/shared/{hx-radio-Z1lV1zTO.js → hx-radio-C7eTj5YI.js} +2 -2
  79. package/dist/shared/{hx-radio-Z1lV1zTO.js.map → hx-radio-C7eTj5YI.js.map} +1 -1
  80. package/dist/shared/{hx-select-D18CnJ0e.js → hx-select-DahFehiZ.js} +2 -2
  81. package/dist/shared/{hx-select-D18CnJ0e.js.map → hx-select-DahFehiZ.js.map} +1 -1
  82. package/dist/shared/{hx-spinner-BB0h2hKZ.js → hx-spinner-3qBp4jeN.js} +11 -11
  83. package/dist/shared/{hx-spinner-BB0h2hKZ.js.map → hx-spinner-3qBp4jeN.js.map} +1 -1
  84. package/dist/shared/{hx-split-button-BoABoEm5.js → hx-split-button-Ddle8iVx.js} +2 -2
  85. package/dist/shared/{hx-split-button-BoABoEm5.js.map → hx-split-button-Ddle8iVx.js.map} +1 -1
  86. package/dist/shared/{hx-stat-Dtf9lz-O.js → hx-stat-Gtw_SpK8.js} +2 -2
  87. package/dist/shared/{hx-stat-Dtf9lz-O.js.map → hx-stat-Gtw_SpK8.js.map} +1 -1
  88. package/dist/shared/{hx-switch-B6kr-EwE.js → hx-switch-TvKGvZJz.js} +2 -2
  89. package/dist/shared/{hx-switch-B6kr-EwE.js.map → hx-switch-TvKGvZJz.js.map} +1 -1
  90. package/dist/shared/{hx-tab-panel-BQtBXKLD.js → hx-tab-panel-Cu--8psg.js} +2 -2
  91. package/dist/shared/{hx-tab-panel-BQtBXKLD.js.map → hx-tab-panel-Cu--8psg.js.map} +1 -1
  92. package/dist/shared/{hx-td-BGkFOJEK.js → hx-td-BPsb6OaG.js} +141 -138
  93. package/dist/shared/hx-td-BPsb6OaG.js.map +1 -0
  94. package/dist/shared/{hx-time-picker-iwCD7rzW.js → hx-time-picker-Bo7FWzmf.js} +2 -2
  95. package/dist/shared/{hx-time-picker-iwCD7rzW.js.map → hx-time-picker-Bo7FWzmf.js.map} +1 -1
  96. package/dist/shared/{hx-toggle-button-BQ81EDkl.js → hx-toggle-button-DwBers3A.js} +2 -2
  97. package/dist/shared/{hx-toggle-button-BQ81EDkl.js.map → hx-toggle-button-DwBers3A.js.map} +1 -1
  98. package/dist/shared/{hx-tree-item-CHrUhuZL.js → hx-tree-item-CXyspGxI.js} +2 -2
  99. package/dist/shared/{hx-tree-item-CHrUhuZL.js.map → hx-tree-item-CXyspGxI.js.map} +1 -1
  100. package/dist/utils/aria-idref.d.ts.map +1 -1
  101. package/figma-inventory.json +2 -2
  102. package/package.json +2 -2
  103. package/dist/shared/aria-idref-CxvyzfQS.js +0 -126
  104. package/dist/shared/hx-card-qNAM2QNV.js.map +0 -1
  105. package/dist/shared/hx-td-BGkFOJEK.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"hx-tree-item-CHrUhuZL.js","sources":["../../src/components/hx-tree-view/hx-tree-view.styles.ts","../../src/utils/tree-walk.ts","../../src/components/hx-tree-view/hx-tree-view.ts","../../src/components/hx-tree-view/hx-tree-item.styles.ts","../../src/components/hx-tree-view/hx-tree-item.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixTreeViewStyles = css`\n :host {\n display: block;\n contain: layout style;\n font-family: var(--hx-tree-font-family, var(--hx-font-family-sans, sans-serif));\n }\n\n * {\n box-sizing: border-box;\n }\n\n .tree {\n display: block;\n outline: none;\n }\n\n .tree:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid var(--hx-focus-ring-color, #0f7078);\n outline-offset: var(--hx-focus-ring-offset, 2px);\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .tree:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n }\n`;\n","/**\n * Composed-tree walkers for the `hx-tree-view` family.\n *\n * Mirrors the `menu-tree.ts` utilities (codex push-gate round-9 extraction\n * for the menu family), but specialized for `hx-tree-view` / `hx-tree-item`\n * where nesting is structural rather than slot-based — child items live in a\n * named `slot=\"children\"` projected into the parent item's shadow root,\n * and any number of nesting levels are legal.\n *\n * Group 5c (codex push-gate round-1 lift): `hx-tree-view`'s host-bound\n * keydown / select handlers receive bubbled events from EVERY descendant\n * tree-item, including ones that legitimately belong to an inner\n * `hx-tree-view`. The same guard pattern that `hx-menu` uses (act only when\n * THIS host is the closest enclosing surface of the dispatching item) is\n * required for trees too. `hx-tree-item._handleClick` /\n * `_handleKeyDown` need to ignore bubbled events from a CHILD `hx-tree-item`\n * — otherwise selecting Child also activates Parent and Enter on Child\n * re-fires Parent's handler.\n *\n * @module\n */\n\n/**\n * Walks the composed tree from `start` outward and returns the closest\n * enclosing `<hx-tree-view>` element, or `null` if none exists. Crosses\n * shadow boundaries (`getRootNode().host`) and slot boundaries\n * (`assignedSlot`) so that an item nested inside a child tree-item — which\n * lives in the parent item's `slot=\"children\"`, projected into the parent's\n * shadow root — resolves to the correct enclosing tree.\n *\n * Returned as `Element` to avoid a circular import between `hx-tree-view`\n * and this util; callers narrow with `instanceof HelixTreeView` if needed.\n *\n * @internal\n */\nexport function findClosestTreeView(start: Element): Element | null {\n let node: Node | null = start;\n while (node) {\n if (node instanceof Element && node.tagName.toLowerCase() === 'hx-tree-view') {\n return node;\n }\n if (node instanceof Element && node.assignedSlot) {\n node = node.assignedSlot;\n continue;\n }\n const parentNode: Node | null = node.parentNode;\n if (parentNode) {\n node = parentNode;\n continue;\n }\n if (node instanceof ShadowRoot) {\n node = node.host;\n continue;\n }\n break;\n }\n return null;\n}\n\n/**\n * Walks the composed tree from `start` outward and returns the closest\n * enclosing `<hx-tree-item>` element, or `null` if none exists. Includes\n * `start` itself when it is an `hx-tree-item`.\n *\n * Used by `hx-tree-item`'s `_isOwnEvent` origin guard: a click or keydown\n * is \"ours\" iff the closest `hx-tree-item` ancestor of the original event\n * target is THIS item (not a child item slotted into our `children` slot).\n * The walk crosses shadow + slot boundaries so a deeply nested child item\n * resolves correctly.\n *\n * Returned as `Element` to avoid a circular import; callers narrow with\n * `instanceof HelixTreeItem` if needed.\n *\n * @internal\n */\nexport function findClosestTreeItem(start: Element): Element | null {\n let node: Node | null = start;\n while (node) {\n if (node instanceof Element && node.tagName.toLowerCase() === 'hx-tree-item') {\n return node;\n }\n if (node instanceof Element && node.assignedSlot) {\n node = node.assignedSlot;\n continue;\n }\n const parentNode: Node | null = node.parentNode;\n if (parentNode) {\n node = parentNode;\n continue;\n }\n if (node instanceof ShadowRoot) {\n node = node.host;\n continue;\n }\n break;\n }\n return null;\n}\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixTreeViewStyles } from './hx-tree-view.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\nimport type { HelixTreeItem, HxTreeItemSelectDetail } from './hx-tree-item.js';\nimport { devWarn } from '../../utils/dev-warn.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\nimport { flattenAccName } from '../../utils/aria-flatten.js';\nimport { findClosestTreeView } from '../../utils/tree-walk.js';\n\n/** Selection mode for the tree. */\nexport type TreeSelection = 'none' | 'single' | 'multiple';\n\n/** Detail type for the `hx-select` event. */\nexport interface HxSelectDetail {\n /** The tree item that was selected or deselected. */\n item: HelixTreeItem;\n /** Whether the item is now selected. */\n selected: boolean;\n}\n\n/**\n * A hierarchical tree component for navigating nested data structures.\n * Used in healthcare applications for org charts, ICD-10 code hierarchies, and department navigation.\n *\n * Group 5c host-canonical: `role=\"tree\"` lives on the **host** via\n * `_internals.role` on the modern path. The host carries the announced\n * surface so AT walks `<hx-tree-view>` (role=tree) → slotted\n * `<hx-tree-item>` (role=treeitem on host) directly without two layers of\n * indirection. Consumer-supplied `aria-label` / `aria-labelledby` on the\n * host are resolved via the shared IDREF mirror; cross-shadow naming uses\n * `ariaLabelledByElements` (modern) with a flattened-string fallback\n * (legacy). On the legacy fallback path the inner `[role=\"tree\"]` carries\n * the role + accessible name and the host role is suppressed so AT only\n * sees one tree per logical surface (mirrors `hx-menu` round-8).\n *\n * Full keyboard navigation: Arrow keys for movement, Enter/Space for\n * selection, Home/End for first/last item, ArrowRight/Left for\n * expand/collapse + parent/child traversal, typeahead.\n *\n * ## Scale Limits\n *\n * This component renders all tree items simultaneously in the DOM. It is suitable for\n * trees with up to ~500 visible items. For large taxonomies (e.g., ICD-10 with 70,000+\n * codes), use async/lazy loading: only render top-level nodes initially and populate\n * child nodes on `hx-select` or expand events. The component exposes the `expanded`\n * property on `hx-tree-item` for programmatic control of subtrees, enabling consumer-level\n * virtualization strategies without requiring changes to this component.\n *\n * @summary Hierarchical tree view with expand/collapse and keyboard navigation.\n *\n * @tag hx-tree-view\n *\n * @slot - Default slot for hx-tree-item elements.\n *\n * @fires {CustomEvent<HxSelectDetail>} hx-select - Dispatched when a tree item is selected or deselected.\n *\n * @csspart tree - The tree container element with role=\"tree\" (legacy fallback path) or the inner shadow surface (modern path; role lives on the host).\n *\n * @cssprop [--hx-tree-font-family=var(--hx-font-family-sans)] - Tree font family.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n */\n@customElement('hx-tree-view')\nexport class HelixTreeView extends HelixElement {\n static override styles = [helixTreeViewStyles, forcedColorsSurface];\n\n // ─── Properties ───\n\n /**\n * Accessible label for the tree. Used as a fallback when no\n * consumer-supplied `aria-label` / `aria-labelledby` is present on the\n * host. On the modern host-canonical path this projects onto\n * `internals.ariaLabel`; on the legacy fallback path it appears as\n * `aria-label` on the inner `[role=\"tree\"]` element.\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = '';\n\n /**\n * Selection mode for the tree.\n * - `none` — items cannot be selected\n * - `single` — only one item can be selected at a time\n * - `multiple` — multiple items can be selected\n * @attr selection\n */\n @property({ type: String, reflect: true })\n selection: 'none' | 'single' | 'multiple' = 'none';\n\n // ─── Internal State ───\n\n /** @internal */\n @state() private _currentIndex = 0;\n\n /** Tracks whether the tree has any visible items, to decide the container tabindex. */\n /** @internal */\n @state() private _hasVisibleItems = false;\n\n // ─── Host-canonical ARIA bookkeeping ───\n\n /**\n * Test seam (codex push-gate round-1 lift from group 5b): when set to\n * `true` or `false`, overrides the platform `supportsIdrefElementReferences`\n * probe before `connectedCallback` seeds `_supportsIdrefRefs`. Mirrors the\n * hx-menu / hx-menu-item / hx-select seam — required so tests can\n * deterministically exercise the legacy fallback render branch.\n *\n * Production code MUST NOT touch this field. It is `static` so the test\n * stub cleanup is global and obvious.\n * @internal\n */\n static __testSupportsIdrefRefsOverride: boolean | null = null;\n\n /** @internal */\n private _supportsIdrefRefs = true;\n\n /** @internal */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n\n /**\n * Resolved accessible name for the tree — the single source of truth read\n * by `_syncHostAriaSemantics()` (modern path: writes to\n * `internals.ariaLabel`) and the fallback `render()` branch (legacy path:\n * writes to inner `div[role=\"tree\"]` `aria-label`). AccName 1.2 §4.3.1\n * precedence: consumer host `aria-labelledby` (resolved + flattened) >\n * consumer host `aria-label` > `label` property > literal \"Tree\".\n * @internal\n */\n private _resolvedAccessibleName = '';\n\n // ─── Visible items cache ───\n\n /**\n * Cached flat list of visible items (depth-first, respects collapsed nodes).\n * Set to null to invalidate; rebuilt on next access.\n * @internal\n */\n private _cachedVisibleItems: HelixTreeItem[] | null = null;\n\n /**\n * Invalidate the visible-items cache. Call after any expand/collapse or structural change.\n * @internal\n */\n private _invalidateVisibleItemsCache(): void {\n this._cachedVisibleItems = null;\n }\n\n // ─── Internal Helpers ───\n\n /**\n * Returns a flat ordered list of all visible (not inside a collapsed item) hx-tree-items\n * in depth-first order. Result is cached; invalidated on expand/collapse/slotchange.\n */\n /** @internal */\n private _getVisibleItems(): HelixTreeItem[] {\n if (!this._cachedVisibleItems) {\n this._cachedVisibleItems = this._collectVisibleItems(this);\n }\n return this._cachedVisibleItems;\n }\n\n /** @internal */\n private _collectVisibleItems(container: Element): HelixTreeItem[] {\n const items: HelixTreeItem[] = [];\n for (const child of Array.from(container.children)) {\n if (child.tagName.toLowerCase() === 'hx-tree-item') {\n const item = child as HelixTreeItem;\n items.push(item);\n if (item.expanded) {\n items.push(...this._collectVisibleItems(item));\n }\n } else {\n items.push(...this._collectVisibleItems(child));\n }\n }\n return items;\n }\n\n /** @internal */\n private _getSelectedItems(): HelixTreeItem[] {\n return Array.from(this.querySelectorAll<HelixTreeItem>('hx-tree-item[selected]'));\n }\n\n /**\n * Updates the roving tabindex across all visible items so that only the\n * item at `activeIndex` has `tabindex=\"0\"`. All others receive `tabindex=\"-1\"`.\n * This is called whenever the active item changes (navigation, initial render).\n */\n /** @internal */\n private _updateRovingTabindex(items: HelixTreeItem[], activeIndex: number): void {\n items.forEach((item, i) => {\n item.setRovingActive(i === activeIndex);\n });\n }\n\n /** @internal */\n private _focusItem(index: number): void {\n const items = this._getVisibleItems();\n if (items.length === 0) return;\n const clamped = Math.max(0, Math.min(index, items.length - 1));\n this._currentIndex = clamped;\n this._updateRovingTabindex(items, clamped);\n items[clamped]?.focus();\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleTreeItemSelect(e: Event): void {\n if (!(e instanceof CustomEvent)) return;\n const event = e as CustomEvent<HxTreeItemSelectDetail>;\n const item = event.detail.item;\n\n if (this.selection === 'none') return;\n\n if (this.selection === 'single') {\n const wasSelected = item.selected;\n this._getSelectedItems().forEach((i) => {\n i.selected = false;\n });\n item.selected = !wasSelected;\n } else if (this.selection === 'multiple') {\n item.selected = !item.selected;\n }\n\n this.dispatchEvent(\n new CustomEvent<HxSelectDetail>('hx-select', {\n bubbles: true,\n composed: true,\n detail: { item, selected: item.selected },\n }),\n );\n }\n\n /**\n * Codex push-gate round-1 lift (mirrors hx-menu round-7 finding 2):\n * `hx-tree-item-select` bubbles composed through every enclosing\n * `hx-tree-view`. The outer tree would otherwise corrupt `_currentIndex`\n * to `-1` (the bubbled item is not in its top-level list) and re-emit a\n * duplicate `hx-select`. Only act when THIS tree is the closest\n * enclosing tree of the dispatching item.\n * @internal\n */\n private _handleItemSelectHost = (e: Event): void => {\n if (!(e instanceof CustomEvent)) return;\n const detail = (e as CustomEvent<HxTreeItemSelectDetail>).detail;\n const item = detail?.item;\n if (item && findClosestTreeView(item) !== this) {\n return;\n }\n this._handleTreeItemSelect(e);\n };\n\n /** @internal */\n private _handleKeyDown(e: KeyboardEvent): void {\n const items = this._getVisibleItems();\n if (items.length === 0) return;\n\n let currentIndex = this._currentIndex;\n const focused = document.activeElement;\n\n for (let i = 0; i < items.length; i++) {\n if (items[i] === focused || items[i]?.shadowRoot?.activeElement) {\n currentIndex = i;\n break;\n }\n }\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n // Intentional design: wrap-around from last to first item provides\n // a continuous navigation loop, consistent with the component's\n // circular keyboard navigation model.\n const next = currentIndex < items.length - 1 ? currentIndex + 1 : 0;\n this._focusItem(next);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n // Intentional design: wrap-around from first to last item (see ArrowDown note).\n const prev = currentIndex > 0 ? currentIndex - 1 : items.length - 1;\n this._focusItem(prev);\n break;\n }\n case 'ArrowLeft': {\n e.preventDefault();\n const currentItem = items[currentIndex];\n if (!currentItem) break;\n if (currentItem.disabled) break;\n if (currentItem.expanded && currentItem.hasChildItems) {\n currentItem.expanded = false;\n this._invalidateVisibleItemsCache();\n } else {\n const parentItem = currentItem.parentElement?.closest('hx-tree-item') as\n | HelixTreeItem\n | undefined;\n if (parentItem) {\n const parentIndex = items.indexOf(parentItem);\n if (parentIndex >= 0) {\n this._focusItem(parentIndex);\n }\n }\n }\n break;\n }\n case 'ArrowRight': {\n e.preventDefault();\n const currentItem = items[currentIndex];\n if (!currentItem) break;\n if (currentItem.disabled) break;\n if (currentItem.hasChildItems) {\n if (!currentItem.expanded) {\n currentItem.expanded = true;\n this._invalidateVisibleItemsCache();\n } else {\n this._focusItem(currentIndex + 1);\n }\n }\n break;\n }\n case 'Home': {\n e.preventDefault();\n this._focusItem(0);\n break;\n }\n case 'End': {\n e.preventDefault();\n this._focusItem(items.length - 1);\n break;\n }\n default: {\n // WAI-ARIA APG typeahead: a printable character moves focus to the next visible\n // item whose label starts with that character (case-insensitive).\n if (e.key.length === 1) {\n e.preventDefault();\n const matchIndex = this._findTypeaheadMatch(e.key.toLowerCase(), currentIndex);\n if (matchIndex !== -1) {\n this._focusItem(matchIndex);\n }\n }\n break;\n }\n }\n }\n\n /**\n * Codex push-gate round-1 lift (mirrors hx-menu round-7 finding 1):\n * keydown bound on the host receives events bubbled out of nested\n * tree-views. Without this guard the outer tree would run `_focusItem`\n * over its own top-level items and steal focus back out of the inner\n * tree. Only act when THIS tree is the closest enclosing tree of the\n * keydown target.\n * @internal\n */\n private _handleHostKeyDown = (e: KeyboardEvent): void => {\n const target = e.target;\n if (target instanceof Element && findClosestTreeView(target) !== this) {\n return;\n }\n this._handleKeyDown(e);\n };\n\n /**\n * Finds the next visible item (starting after `currentIndex`, wrapping around) whose\n * label text begins with the given lowercase character. Returns -1 if no match.\n * @internal\n */\n private _findTypeaheadMatch(char: string, currentIndex: number): number {\n const items = this._getVisibleItems();\n if (items.length === 0) return -1;\n for (let i = 1; i <= items.length; i++) {\n const index = (currentIndex + i) % items.length;\n const item = items[index];\n if (item && item.labelText.toLowerCase().startsWith(char)) {\n return index;\n }\n }\n return -1;\n }\n\n /** @internal */\n private _handleFocusIn(e: FocusEvent): void {\n // With roving tabindex, the tree container (tabindex=\"-1\") should only receive\n // focus when the tree is empty. If focus does land on the container (e.g. the\n // tree is empty or programmatic focus), redirect to the active item if present.\n if (e.target === e.currentTarget) {\n const items = this._getVisibleItems();\n if (items.length > 0) {\n this._focusItem(this._currentIndex);\n }\n }\n }\n\n /**\n * Compute and push ARIA position metadata (level, posInSet, setSize, selectable) to all\n * direct hx-tree-item children of a container in a single O(n) pass.\n * Each item also recurses for its own children, building the full tree in O(total-items) total.\n * @internal\n */\n private _updateAriaMetadataForContainer(container: Element, level: number): void {\n const selectable = this.selection === 'single' || this.selection === 'multiple';\n const children = Array.from(container.children).filter(\n (c) => c.tagName.toLowerCase() === 'hx-tree-item',\n ) as HelixTreeItem[];\n const setSize = children.length;\n children.forEach((item, index) => {\n item.setAriaMetadata(level, index + 1, setSize, selectable);\n // Recurse into child items so the full tree is updated in one traversal\n this._updateAriaMetadataForContainer(item, level + 1);\n });\n }\n\n /**\n * Initializes the roving tabindex after items are first slotted in.\n * Ensures the active item (index 0 by default) has tabindex=\"0\" from the start,\n * so a Tab into the tree lands directly on the first item without a redirect.\n * Also updates `_hasVisibleItems` so the container tabindex re-renders correctly.\n * Pushes O(n) ARIA metadata to all items to replace the O(n^2) per-item ancestor walk.\n */\n /** @internal */\n private _handleSlotChange(): void {\n this._invalidateVisibleItemsCache();\n // Push ARIA metadata from parent in a single O(n) traversal\n this._updateAriaMetadataForContainer(this, 1);\n const items = this._getVisibleItems();\n this._hasVisibleItems = items.length > 0;\n if (items.length === 0) return;\n // Clamp _currentIndex in case items were removed.\n const clamped = Math.min(this._currentIndex, items.length - 1);\n this._currentIndex = clamped;\n this._updateRovingTabindex(items, clamped);\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Honour the static test override so synthetic environments choose the\n // path BEFORE connect runs — the fallback render branch needs to be\n // selected at first paint so the inner `[role=\"tree\"]` carries the\n // resolved accessible name without a mid-life flag flip.\n const ctor = this.constructor as typeof HelixTreeView;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n // Keydown + select are bound on the HOST so events from focused\n // host-canonical tree-items (which keep keydown out of this tree's\n // shadow DOM on the modern path) still reach the navigation handler.\n // Both handlers carry composed-tree origin guards that ignore events\n // bubbled out of a NESTED `<hx-tree-view>`.\n this.addEventListener('keydown', this._handleHostKeyDown);\n this.addEventListener('hx-tree-item-select', this._handleItemSelectHost);\n // Seed host-canonical semantics so role/label appear before first paint.\n this._syncHostAriaSemantics();\n this._ariaMirror = installAriaIdrefMirror(this, () => {\n this._syncHostAriaSemantics();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('keydown', this._handleHostKeyDown);\n this.removeEventListener('hx-tree-item-select', this._handleItemSelectHost);\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n // CodeRabbit MUST-FIX: `selection` change must re-sync host\n // semantics so `aria-multiselectable` reflects the new mode\n // (single → false, multiple → true, none → unset). Previously only\n // `label` triggered the resync, leaving stale aria-multiselectable.\n if (changedProperties.has('label') || changedProperties.has('selection')) {\n this._syncHostAriaSemantics();\n }\n if (changedProperties.has('selection')) {\n // Per-item _selectable flag also depends on the parent's selection\n // mode — recompute the descendants so each hx-tree-item host's\n // `aria-selected` matches the new container contract.\n this._updateAriaMetadataForContainer(this, 1);\n }\n }\n\n override firstUpdated(): void {\n const hasEffectiveLabel =\n this.hasAttribute('aria-label') ||\n this.hasAttribute('aria-labelledby') ||\n Boolean(this.label);\n if (!hasEffectiveLabel) {\n devWarn(\n 'hx-tree-view',\n 'No accessible label provided. Set the `label` attribute, or supply `aria-label` / `aria-labelledby` on hx-tree-view so screen readers can identify this tree (WCAG 4.1.2).',\n );\n }\n }\n\n /**\n * Mirror tree semantics onto the host via ElementInternals so consumer-\n * supplied `aria-label`, `aria-labelledby`, and the `label` property all\n * reach the announced control. Falls back to a flattened-string label on\n * engines that do not implement `ariaLabelledByElements`.\n *\n * Codex push-gate round-1 lift (mirrors hx-menu round-8 finding 1): on\n * the legacy fallback path the inner `<div role=\"tree\" aria-label=\"…\">`\n * is the announced surface. If we ALSO write `internals.role = 'tree'`\n * onto the host, AT sees TWO trees for one logical surface — the\n * duplicate-surface problem host-canonical migration is meant to\n * eliminate. Suppress host role + label writes on the fallback path; the\n * inner element is the canonical announced surface there. Modern path\n * keeps the host as the canonical surface and clears the inner role.\n * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n\n if (!this._supportsIdrefRefs) {\n internals.role = null;\n internals.ariaLabel = null;\n internals.ariaMultiSelectable = null;\n } else {\n internals.role = 'tree';\n internals.ariaMultiSelectable =\n this.selection === 'none' ? null : this.selection === 'multiple' ? 'true' : 'false';\n }\n\n const hostAriaLabel = this.getAttribute('aria-label')?.trim() || '';\n const consumerLabelledBy = this.getAttribute('aria-labelledby');\n const labelEls = resolveIdrefTokens(this, consumerLabelledBy);\n const hasEffectiveLabelledBy = labelEls.length > 0;\n\n type InternalsWithRefs = ElementInternals & {\n ariaLabelledByElements: Element[] | null;\n };\n\n if (this._supportsIdrefRefs) {\n const refsInternals = internals as InternalsWithRefs;\n refsInternals.ariaLabelledByElements = hasEffectiveLabelledBy ? labelEls : null;\n }\n\n // AccName 1.2 §4.3.1 precedence: consumer aria-labelledby (resolved) >\n // consumer aria-label > `label` property > literal \"Tree\" (last-resort).\n let resolved = '';\n if (hasEffectiveLabelledBy) {\n const flattened =\n labelEls\n .map((el) => flattenAccName(el))\n .filter(Boolean)\n .join(' ') ||\n hostAriaLabel ||\n this.label ||\n 'Tree';\n resolved = flattened;\n if (this._supportsIdrefRefs) {\n // Modern path: element refs win; clear ariaLabel so they aren't\n // shadowed by a stale string. Fallback branch reads\n // `_resolvedAccessibleName` for its inner-div mirror — host\n // ariaLabel is already cleared above on the fallback path.\n internals.ariaLabel = null;\n }\n } else if (hostAriaLabel) {\n resolved = hostAriaLabel;\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = hostAriaLabel;\n }\n } else {\n resolved = this.label || 'Tree';\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = resolved;\n }\n }\n\n if (this._resolvedAccessibleName !== resolved) {\n this._resolvedAccessibleName = resolved;\n if (!this._supportsIdrefRefs) {\n this.requestUpdate();\n }\n }\n }\n\n // ─── Render ───\n\n override render() {\n // Roving tabindex pattern (WCAG 2.4.3 Fix):\n // The tree container is NOT a Tab stop (tabindex=\"-1\"). Tab focus goes\n // directly to the active item, which carries tabindex=\"0\". The container\n // is only a landing target (tabindex=\"0\") when the tree is empty.\n const containerTabindex = this._hasVisibleItems ? '-1' : '0';\n\n // Modern host-canonical path: role + aria-label live on the host via\n // `_internals`. The inner div is roleless on the modern path so AT\n // does not see a duplicated container role nested inside the host.\n if (this._supportsIdrefRefs) {\n return html`\n <div part=\"tree\" class=\"tree\" tabindex=${containerTabindex} @focusin=${this._handleFocusIn}>\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n\n // Legacy fallback: keep role + aria-label on inner div for AT without\n // IDL element-references on ElementInternals. Mirror the resolved\n // accessible name (consumer aria-label / aria-labelledby flatten /\n // `label` property cascade) so menus named via the new host API still\n // announce on legacy engines.\n const fallbackLabel = this._resolvedAccessibleName || this.label || 'Tree';\n return html`\n <div\n part=\"tree\"\n class=\"tree\"\n role=\"tree\"\n tabindex=${containerTabindex}\n aria-label=${fallbackLabel}\n aria-multiselectable=${this.selection === 'none'\n ? nothing\n : this.selection === 'multiple'\n ? 'true'\n : 'false'}\n @focusin=${this._handleFocusIn}\n >\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tree-view': HelixTreeView;\n }\n}\n\n/** Canonical type alias for HelixTreeView. Use this when typing hx-tree-view element references. */\nexport type HxTreeView = HelixTreeView;\n","import { css } from 'lit';\n\nexport const helixTreeItemStyles = css`\n :host {\n display: block;\n contain: layout style;\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ─── Item Container ─── */\n\n .item {\n display: block;\n }\n\n /* ─── Item Row ─── */\n\n .item-row {\n display: flex;\n align-items: center;\n min-height: var(--hx-touch-target-min, 44px);\n gap: var(--hx-tree-item-gap, var(--hx-space-2, 0.5rem));\n padding: var(--hx-tree-item-padding-y, var(--hx-space-2, 0.5rem))\n var(--hx-tree-item-padding-x, var(--hx-space-2, 0.5rem));\n padding-inline-start: calc(\n var(--hx-tree-item-padding-x, var(--hx-space-2, 0.5rem)) + var(--_indent-level, 0) *\n var(--hx-tree-indent-size, 1.5rem)\n );\n border-radius: var(--hx-tree-item-border-radius, var(--hx-border-radius-sm, 0.25rem));\n cursor: pointer;\n outline: none;\n color: var(--hx-tree-item-color, var(--hx-color-neutral-900, #0d1825));\n font-family: var(--hx-tree-item-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-tree-item-font-size, var(--hx-font-size-sm, 0.875rem));\n line-height: var(--hx-line-height-normal, 1.5);\n transition: background-color var(--hx-transition-fast, 150ms ease);\n user-select: none;\n }\n\n .item-row:hover {\n background-color: var(--hx-tree-item-hover-bg, var(--hx-color-neutral-100, #ebeee9));\n }\n\n .item-row:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-tree-item-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, -2px);\n }\n\n /* ─── Selected State ─── */\n\n :host([selected]) .item-row {\n background-color: var(--hx-tree-item-selected-bg, var(--hx-color-primary-100, #dbf0f0));\n color: var(--hx-tree-item-selected-color, var(--hx-color-primary-800, #07494a));\n }\n\n :host([selected]) .item-row:hover {\n background-color: var(--hx-tree-item-selected-hover-bg, var(--hx-color-primary-200, #bce1e1));\n }\n\n /* ─── Disabled State ─── */\n\n :host([disabled]) .item-row {\n opacity: var(--hx-opacity-disabled, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* ─── Expand Icon ─── */\n\n .expand-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--hx-space-4, 1rem);\n height: var(--hx-space-4, 1rem);\n }\n\n .expand-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--hx-space-4, 1rem);\n height: var(--hx-space-4, 1rem);\n padding: 0;\n border: none;\n background: transparent;\n color: var(--hx-tree-item-expand-icon-color, var(--hx-color-neutral-500, #66787b));\n cursor: pointer;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n transition: transform var(--hx-transition-fast, 150ms ease);\n pointer-events: auto;\n }\n\n .expand-btn:hover {\n background-color: var(\n --hx-tree-item-expand-hover-bg,\n var(--hx-overlay-black-6, rgba(0, 0, 0, 0.06))\n );\n }\n\n .expand-btn:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-tree-item-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .expand-btn svg {\n width: var(--hx-space-3, 0.75rem);\n height: var(--hx-space-3, 0.75rem);\n stroke: currentColor;\n fill: none;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n :host([expanded]) .expand-btn svg {\n transform: rotate(90deg);\n }\n\n .expand-placeholder {\n display: block;\n width: var(--hx-space-4, 1rem);\n flex-shrink: 0;\n }\n\n /* ─── Icon Slot ─── */\n\n .item-icon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n color: var(--hx-tree-item-icon-color, var(--hx-color-neutral-500, #66787b));\n }\n\n .item-icon:empty {\n display: none;\n }\n\n /* ─── Label ─── */\n\n .item-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* ─── Children (animated) ─── */\n\n .children {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows var(--hx-transition-base, 200ms ease);\n --_indent-level: calc(var(--_indent-level, 0) + 1);\n }\n\n .children--expanded {\n grid-template-rows: 1fr;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .item-row,\n .expand-btn,\n .expand-btn svg,\n .children {\n transition: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .item-row:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: -2px;\n }\n\n .expand-btn:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n :host([selected]) .item-row {\n outline: 2px solid Highlight;\n }\n }\n\n .children-inner {\n overflow: hidden;\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixTreeItemStyles } from './hx-tree-item.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\nimport { flattenAccName } from '../../utils/aria-flatten.js';\nimport { findClosestTreeItem } from '../../utils/tree-walk.js';\n\n/** Detail type for the `hx-tree-item-select` event. */\nexport interface HxTreeItemSelectDetail {\n /** The tree item that was selected or activated. */\n item: HelixTreeItem;\n}\n\n/**\n * A tree item used within an hx-tree-view component.\n * Supports expand/collapse, selection, keyboard navigation, and icon/children slots.\n *\n * Group 5c host-canonical: `role=\"treeitem\"` lives on the **host** via\n * `_internals.role`. The roving tabindex is written to the host on the\n * modern path so the host is the focusable surface and lands directly\n * under the parent `<hx-tree-view>` (which carries `role=\"tree\"`) in the\n * AT-walked tree. The inner `.item-row` is presentational on the modern\n * path — no role, no aria-* attributes — and carries only click/keyboard\n * event handlers. Keyboard activation (Enter/Space) and expand/collapse\n * (ArrowLeft/Right at the leaf level) are owned by the host's `keydown`\n * handler; ArrowUp/Down/Home/End and typeahead bubble to the parent\n * `<hx-tree-view>` for navigation.\n *\n * The nested `[role=\"group\"]` element that wraps the `slot=\"children\"`\n * stays in the inner shadow DOM regardless of path — that group is a\n * separate sub-surface for the children, not a duplicate of the\n * treeitem role.\n *\n * On the legacy fallback path the inner `.item-row` carries\n * `role=\"treeitem\"` + aria-* state, the host role is suppressed, and the\n * roving tabindex is written to the inner element so there is only ONE\n * focusable surface per item (mirrors hx-menu-item round-8).\n *\n * @summary Individual item within an hx-tree-view hierarchical tree.\n *\n * @tag hx-tree-item\n *\n * @slot - Default slot for the item label content. This text is also used to label the children group.\n * @slot icon - Custom icon shown before the label.\n * @slot children - Nested hx-tree-item elements for sub-tree.\n *\n * @csspart item - The outer item container.\n * @csspart row - The interactive item row (presentational on the modern path; carries role=\"treeitem\" + aria-* on the legacy fallback).\n * @csspart expand-icon - The expand/collapse toggle button.\n * @csspart label - The label text content area.\n * @csspart children - The children container (always carries role=\"group\").\n *\n * @cssprop [--hx-tree-item-color=var(--hx-color-neutral-900)] - Item text color.\n * @cssprop [--hx-tree-item-hover-bg=var(--hx-color-neutral-100)] - Hover background color.\n * @cssprop [--hx-tree-item-selected-bg=var(--hx-color-primary-100)] - Selected background color.\n * @cssprop [--hx-tree-item-selected-color=var(--hx-color-primary-800)] - Selected text color.\n * @cssprop [--hx-tree-item-padding-x=var(--hx-space-2)] - Horizontal padding.\n * @cssprop [--hx-tree-item-padding-y=var(--hx-space-1)] - Vertical padding.\n * @cssprop [--hx-tree-indent-size=1.5rem] - Indentation size per level.\n *\n * @fires {CustomEvent<HxTreeItemSelectDetail>} hx-tree-item-select - Dispatched when this item is clicked or activated via keyboard.\n */\n@customElement('hx-tree-item')\nexport class HelixTreeItem extends HelixElement {\n static override styles = [helixTreeItemStyles, forcedColorsSurface];\n\n /**\n * Test seam (codex push-gate round-1 lift from group 5b): when set to\n * `true` or `false`, overrides the platform `supportsIdrefElementReferences`\n * probe before `connectedCallback` seeds `_supportsIdrefRefs`. Mirrors the\n * hx-menu-item / hx-select seam — required so tests can deterministically\n * exercise the legacy fallback render branch.\n *\n * Production code MUST NOT touch this field. It is `static` so the test\n * stub cleanup is global and obvious.\n * @internal\n */\n static __testSupportsIdrefRefsOverride: boolean | null = null;\n\n // ─── Properties ───\n\n /**\n * Whether the item is expanded (showing children).\n * @attr expanded\n */\n @property({ type: Boolean, reflect: true })\n expanded = false;\n\n /**\n * Whether the item is selected.\n * @attr selected\n */\n @property({ type: Boolean, reflect: true })\n selected = false;\n\n /**\n * Whether the item is disabled (non-interactive).\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n // ─── Internal State ───\n\n /**\n * Tracks whether any elements are assigned to the children slot, controlling expand icon visibility.\n * @internal\n */\n @state() private _hasChildren = false;\n\n /**\n * Whether this item is the roving-tabindex active item in the tree.\n * @internal\n */\n @state() private _rovingActive = false;\n\n /**\n * Text content from the default slot, used to label the children group for screen readers.\n * @internal\n */\n @state() private _labelText = '';\n\n /**\n * Cached ARIA position metadata. Computed once on connect and on slotchange\n * of the parent container, avoiding repeated DOM traversal on every render.\n * @internal\n */\n @state() private _level = 1;\n /**\n * One-based position of this item within its sibling set, set as aria-posinset.\n * @internal\n */\n @state() private _posInSet = 1;\n /**\n * Total count of sibling hx-tree-item elements at the same level, set as aria-setsize.\n * @internal\n */\n @state() private _setSize = 1;\n /**\n * Whether the owning hx-tree-view supports item selection (single or multiple mode).\n * @internal\n */\n @state() private _selectable = false;\n\n /** @internal */\n @query('.item-row') private _itemRowEl!: HTMLElement | null;\n\n // ─── Host-canonical ARIA bookkeeping ───\n\n /** @internal */\n private _supportsIdrefRefs = true;\n\n /** @internal */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n\n /**\n * Resolved accessible name override for the tree item — read by both\n * `_syncHostAriaSemantics()` (modern path: host `internals.ariaLabel`)\n * and the fallback `render()` branch (legacy path: inner\n * `div[role=\"treeitem\"]` `aria-label`). Empty string means \"no override\"\n * — slotted text content provides the implicit name through the\n * announced surface (host on modern; inner row on fallback). AccName 1.2\n * §4.3.1 precedence: consumer host `aria-labelledby` (flattened) >\n * consumer host `aria-label` > implicit slotted text.\n * @internal\n */\n private _resolvedAccessibleName = '';\n\n // ─── Computed ARIA ───\n\n /**\n * Whether this item has slotted children.\n * @returns True if one or more elements are assigned to the children slot.\n */\n get hasChildItems(): boolean {\n return this._hasChildren;\n }\n\n /**\n * The text content of the item's label slot, used for typeahead keyboard navigation.\n * Returns an empty string until the label slot has been assigned.\n */\n get labelText(): string {\n return this._labelText;\n }\n\n /**\n * Recompute all cached ARIA metadata in a single DOM pass.\n * Called on connect, slotchange, and whenever structural context may change.\n * @internal\n */\n private _updateAriaMetadata(): void {\n // Compute nesting level by counting ancestor hx-tree-item elements.\n let level = 1;\n let el: Element | null = this.parentElement;\n while (el) {\n if (el.tagName.toLowerCase() === 'hx-tree-item') level++;\n el = el.parentElement;\n }\n this._level = level;\n\n // Compute position-in-set and set-size from sibling hx-tree-item elements.\n const parent = this.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (c) => c.tagName.toLowerCase() === 'hx-tree-item',\n );\n this._posInSet = siblings.indexOf(this) + 1;\n this._setSize = siblings.length;\n } else {\n this._posInSet = 1;\n this._setSize = 1;\n }\n\n // Determine if the owning tree supports selection.\n const tree = this.closest('hx-tree-view');\n if (tree) {\n const selection = tree.getAttribute('selection');\n this._selectable = selection === 'single' || selection === 'multiple';\n } else {\n this._selectable = false;\n }\n }\n\n /**\n * Set ARIA position metadata from the parent hx-tree-view in a single O(n) pass.\n * Calling this avoids the O(n^2) ancestor-walk + sibling-iteration in _updateAriaMetadata\n * when the parent already knows the layout.\n * @internal\n */\n setAriaMetadata(level: number, posInSet: number, setSize: number, selectable: boolean): void {\n this._level = level;\n this._posInSet = posInSet;\n this._setSize = setSize;\n this._selectable = selectable;\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Honour the static test override so synthetic environments choose the\n // path BEFORE connect runs — the fallback render branch needs to be\n // selected at first paint so role + roving tabindex placement matches a\n // legacy engine for the entire lifecycle.\n const ctor = this.constructor as typeof HelixTreeItem;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n this._updateAriaMetadata();\n // Click + keydown live on the HOST so the active surface (the host on\n // the modern path; either the host or the inner div in delegating\n // engines) receives events. Origin guards (`_isOwnEvent`) reject events\n // bubbled from a CHILD `hx-tree-item` slotted into our `children`\n // slot — without that, selecting Child also activates Parent.\n this.addEventListener('click', this._handleClick);\n this.addEventListener('keydown', this._handleKeyDown);\n this._syncHostAriaSemantics();\n this._applyHostTabIndex();\n this._ariaMirror = installAriaIdrefMirror(this, () => {\n this._syncHostAriaSemantics();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('click', this._handleClick);\n this.removeEventListener('keydown', this._handleKeyDown);\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (\n changedProperties.has('disabled') ||\n changedProperties.has('selected') ||\n changedProperties.has('expanded') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_hasChildren') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_selectable') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_level') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_posInSet') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_setSize')\n ) {\n this._syncHostAriaSemantics();\n }\n if (\n (changedProperties as Map<PropertyKey, unknown>).has('_rovingActive') ||\n changedProperties.has('disabled')\n ) {\n this._applyHostTabIndex();\n }\n }\n\n /**\n * Apply the roving tabindex through the right surface for the active\n * path. On the modern host-canonical path the host carries the role +\n * tabindex; on the legacy fallback path the inner `.item-row` carries\n * both via the template, so the host MUST stay out of the tab order to\n * avoid a double-focusable per item (mirrors hx-menu-item round-1\n * finding 3).\n * @internal\n */\n private _applyHostTabIndex(): void {\n if (!this._supportsIdrefRefs) {\n // Fallback path: inner `.item-row` is the focusable surface. Keep\n // the host out of the sequential focus order entirely.\n this.tabIndex = -1;\n return;\n }\n if (this.disabled) {\n this.tabIndex = -1;\n } else {\n this.tabIndex = this._rovingActive ? 0 : -1;\n }\n }\n\n /**\n * Mirror treeitem semantics onto the host via ElementInternals so\n * consumer-supplied `aria-label`, `aria-labelledby`, expand/select state,\n * and tree position all reach the announced control.\n *\n * Codex push-gate round-1 lift (mirrors hx-menu-item round-6 finding 2):\n * on the legacy fallback path the inner `.item-row` already exposes\n * role=\"treeitem\" + aria-* via the template. If we ALSO write those onto\n * the host's ElementInternals, AT sees TWO treeitems for one logical\n * option — the duplicate-surface problem host-canonical migration is\n * meant to eliminate. Suppress all of these state writes on the host\n * when the fallback path is in effect; the inner element is the\n * canonical announced surface.\n * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n\n if (!this._supportsIdrefRefs) {\n internals.role = null;\n internals.ariaLabel = null;\n internals.ariaDisabled = null;\n internals.ariaSelected = null;\n internals.ariaExpanded = null;\n internals.ariaLevel = null;\n internals.ariaPosInSet = null;\n internals.ariaSetSize = null;\n } else {\n internals.role = 'treeitem';\n internals.ariaDisabled = this.disabled ? 'true' : null;\n internals.ariaSelected = this._selectable ? (this.selected ? 'true' : 'false') : null;\n internals.ariaExpanded = this._hasChildren ? (this.expanded ? 'true' : 'false') : null;\n internals.ariaLevel = String(this._level);\n internals.ariaPosInSet = String(this._posInSet);\n internals.ariaSetSize = String(this._setSize);\n }\n\n const hostAriaLabel = this.getAttribute('aria-label')?.trim() || '';\n const consumerLabelledBy = this.getAttribute('aria-labelledby');\n const labelEls = resolveIdrefTokens(this, consumerLabelledBy);\n const hasEffectiveLabelledBy = labelEls.length > 0;\n\n type InternalsWithRefs = ElementInternals & {\n ariaLabelledByElements: Element[] | null;\n };\n\n if (this._supportsIdrefRefs) {\n const refsInternals = internals as InternalsWithRefs;\n refsInternals.ariaLabelledByElements = hasEffectiveLabelledBy ? labelEls : null;\n }\n\n // AccName 1.2 §4.3.1 precedence: consumer aria-labelledby (resolved) >\n // consumer aria-label > implicit slotted text (left to AccName\n // computation through the host's role). When neither override is\n // supplied, ariaLabel is cleared so AT walks slotted children for the\n // accessible name.\n let resolved = '';\n if (hasEffectiveLabelledBy) {\n const flattened =\n labelEls\n .map((el) => flattenAccName(el))\n .filter(Boolean)\n .join(' ') ||\n hostAriaLabel ||\n '';\n resolved = flattened;\n if (this._supportsIdrefRefs) {\n // Modern path: element refs win; clear ariaLabel so they aren't\n // shadowed by a stale string.\n internals.ariaLabel = null;\n } else {\n internals.ariaLabel = flattened || null;\n }\n } else if (hostAriaLabel) {\n resolved = hostAriaLabel;\n internals.ariaLabel = hostAriaLabel;\n } else {\n internals.ariaLabel = null;\n }\n\n if (this._resolvedAccessibleName !== resolved) {\n this._resolvedAccessibleName = resolved;\n if (!this._supportsIdrefRefs) {\n this.requestUpdate();\n }\n }\n }\n\n // ─── Children Detection ───\n\n /**\n * Updates _hasChildren and recomputes ARIA metadata when the children slot assignment changes.\n * @internal\n */\n private _handleChildrenSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasChildren = slot.assignedElements().length > 0;\n this._updateAriaMetadata();\n this._syncHostAriaSemantics();\n }\n\n /**\n * Captures the text content from the default (label) slot for use on the children group label.\n * @internal\n */\n private _handleLabelSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n const nodes = slot.assignedNodes({ flatten: true });\n this._labelText = nodes\n .map((n) => n.textContent ?? '')\n .join('')\n .trim();\n }\n\n // ─── Event Handlers ───\n\n /**\n * Origin guard for host-bound click/keydown handlers. Returns `true` only\n * when the event originated on THIS host's surface (its shadow tree or\n * itself) and not on a nested `hx-tree-item` projected into the\n * `children` slot.\n *\n * Codex push-gate round-1 lift (mirrors hx-menu-item round-5 P1):\n * children are slotted descendants in the parent's light DOM. Click/\n * keydown events from a Child item bubble through the parent host's\n * listeners — without this guard, selecting Child also activates\n * Parent (double `hx-tree-item-select`) and Enter/Space on Child\n * re-trigger Parent's handlers.\n *\n * Uses the shared `findClosestTreeItem` walker (composed-tree, crosses\n * shadow + slot boundaries) so the test bed is reused across the\n * tree family. The event is \"ours\" iff the closest `hx-tree-item`\n * ancestor of the original target is `this`.\n * @internal\n */\n private _isOwnEvent(e: Event): boolean {\n const path = e.composedPath();\n for (const node of path) {\n if (!(node instanceof Element)) continue;\n const closest = findClosestTreeItem(node);\n if (closest) {\n return closest === this;\n }\n }\n return false;\n }\n\n /**\n * Toggles the expanded state when the expand/collapse button is clicked, stopping event propagation.\n * @internal\n */\n private _handleExpandClick(e: Event): void {\n e.stopPropagation();\n if (this.disabled) return;\n this.expanded = !this.expanded;\n }\n\n /**\n * Dispatches the hx-tree-item-select event when the item is activated via\n * click or keyboard. The host listens for click; this method is also\n * invoked from the Enter/Space keydown branch.\n * @internal\n */\n private _activate(): void {\n if (this.disabled) return;\n this.dispatchEvent(\n new CustomEvent<HxTreeItemSelectDetail>('hx-tree-item-select', {\n bubbles: true,\n composed: true,\n detail: { item: this },\n }),\n );\n }\n\n /** @internal */\n private _handleClick = (e: MouseEvent): void => {\n // Codex push-gate round-1 lift (mirrors hx-menu-item round-5 P1):\n // clicks on a nested CHILD tree-item bubble through this host. Without\n // an origin guard, both Child and Parent activate.\n if (!this._isOwnEvent(e)) return;\n // CodeRabbit MUST-FIX: a click landing inside our own children\n // container (the `[role=\"group\"]` wrapper around `<slot name=\"children\">`)\n // — i.e. on padding, between child items, on the group itself — also\n // walks back up to THIS host through `_isOwnEvent`. Treat any click\n // sourced from the children group as NOT a row activation.\n const path = e.composedPath();\n for (const node of path) {\n if (!(node instanceof Element)) continue;\n if (node === this) break;\n if (node.getAttribute && node.getAttribute('part') === 'children') return;\n }\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n this._activate();\n };\n\n /** @internal */\n private _handleKeyDown = (e: KeyboardEvent): void => {\n // Codex push-gate round-1 lift (mirrors hx-menu-item round-5 P1):\n // Enter / Space / ArrowLeft / ArrowRight at a focused CHILD bubble\n // through this host. Without an origin guard, Parent treats them as\n // its own — double activation, wrong-level expand/collapse.\n if (!this._isOwnEvent(e)) return;\n if (this.disabled) return;\n\n switch (e.key) {\n case 'ArrowRight':\n e.preventDefault();\n if (this._hasChildren && !this.expanded) {\n this.expanded = true;\n }\n break;\n case 'ArrowLeft':\n e.preventDefault();\n if (this._hasChildren && this.expanded) {\n this.expanded = false;\n }\n break;\n case 'Enter':\n case ' ':\n e.preventDefault();\n this._activate();\n break;\n case 'ArrowDown':\n case 'ArrowUp':\n case 'Home':\n case 'End':\n // Bubble up to hx-tree-view for navigation\n break;\n }\n };\n\n // ─── Public API ───\n\n /**\n * Sets the roving tabindex state for this item.\n * When `active` is true, the host (modern) or inner row (fallback) gets\n * `tabindex=\"0\"` making it the Tab-reachable surface in the tree. All\n * other items should be set to false. Called by the parent hx-tree-view\n * to manage the roving tabindex pattern.\n */\n setRovingActive(active: boolean): void {\n this._rovingActive = active;\n this._applyHostTabIndex();\n }\n\n /**\n * Focus this item. On the modern host-canonical path, focus lands on the\n * host (which carries the roving tabindex and announced role). On the\n * legacy fallback path, focus delegates to the inner `.item-row` which\n * still carries the role.\n */\n override focus(options?: FocusOptions): void {\n if (this._supportsIdrefRefs) {\n HTMLElement.prototype.focus.call(this, options);\n } else {\n this._itemRowEl?.focus(options);\n }\n }\n\n // ─── Render ───\n\n /**\n * Renders the expand/collapse chevron button, or a placeholder span when the item has no children.\n * @internal\n */\n private _renderExpandIcon() {\n if (!this._hasChildren) {\n return html`<span class=\"expand-placeholder\" aria-hidden=\"true\"></span>`;\n }\n return html`\n <button\n part=\"expand-icon\"\n class=\"expand-btn\"\n tabindex=\"-1\"\n aria-label=\"${this.expanded ? 'Collapse' : 'Expand'}\"\n @click=${this._handleExpandClick}\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <polyline points=\"6 4 10 8 6 12\" />\n </svg>\n </button>\n `;\n }\n\n override render() {\n // The nested children container always carries role=\"group\" — that is\n // a separate sub-surface for the children, not a duplicate of the\n // treeitem role, and is correct on both the modern and fallback paths.\n const childrenGroup = html`\n <div\n part=\"children\"\n class=${classMap({ children: true, 'children--expanded': this.expanded })}\n role=\"group\"\n aria-label=${this._labelText ? `${this._labelText} children` : 'children'}\n aria-hidden=${!this.expanded || nothing}\n >\n <div class=\"children-inner\">\n <slot name=\"children\" @slotchange=${this._handleChildrenSlotChange}></slot>\n </div>\n </div>\n `;\n\n // Modern host-canonical path: role/aria-* and tabindex live on the\n // host via `_internals` and the `_applyHostTabIndex()` helper. The\n // inner `.item-row` is presentational (no role, no aria-*) and carries\n // only the visual treatment + slot composition. Click + keydown\n // handlers stay on the host (see connectedCallback) so keyboard\n // activation works regardless of which surface is focused.\n if (this._supportsIdrefRefs) {\n return html`\n <div part=\"item\" class=\"item\">\n <div part=\"row\" class=\"item-row\">\n ${this._renderExpandIcon()}\n <span class=\"item-icon\">\n <slot name=\"icon\"></slot>\n </span>\n <span part=\"label\" class=\"item-label\">\n <slot @slotchange=${this._handleLabelSlotChange}></slot>\n </span>\n </div>\n ${childrenGroup}\n </div>\n `;\n }\n\n // Legacy fallback: keep role/aria-* on the inner `.item-row` for AT\n // without IDL element-references on ElementInternals. Click + keydown\n // still listen on the host (see connectedCallback) so behaviour is\n // uniform across paths. The inner element MUST mirror the same\n // accessible name resolved by `_syncHostAriaSemantics()`.\n const fallbackAriaLabel = this._resolvedAccessibleName || nothing;\n const ariaExpanded = this._hasChildren ? String(this.expanded) : nothing;\n const ariaSelected = this._selectable ? String(this.selected) : nothing;\n\n return html`\n <div part=\"item\" class=\"item\">\n <div\n part=\"row\"\n class=\"item-row\"\n role=\"treeitem\"\n tabindex=${this._rovingActive ? '0' : '-1'}\n aria-label=${fallbackAriaLabel}\n aria-expanded=${ariaExpanded}\n aria-selected=${ariaSelected}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-level=${this._level}\n aria-posinset=${this._posInSet}\n aria-setsize=${this._setSize}\n >\n ${this._renderExpandIcon()}\n <span class=\"item-icon\">\n <slot name=\"icon\"></slot>\n </span>\n <span part=\"label\" class=\"item-label\">\n <slot @slotchange=${this._handleLabelSlotChange}></slot>\n </span>\n </div>\n ${childrenGroup}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tree-item': HelixTreeItem;\n }\n}\n\n/** Canonical type alias for HelixTreeItem. Use this when typing hx-tree-item element references. */\nexport type HxTreeItem = HelixTreeItem;\n"],"names":["helixTreeViewStyles","css","findClosestTreeView","start","node","parentNode","findClosestTreeItem","HelixTreeView","HelixElement","detail","item","target","container","items","child","activeIndex","index","clamped","_a","wasSelected","i","currentIndex","focused","_b","next","prev","currentItem","parentItem","_c","parentIndex","matchIndex","char","level","selectable","children","c","setSize","ctor","supportsIdrefElementReferences","installAriaIdrefMirror","changedProperties","internals","hostAriaLabel","consumerLabelledBy","labelEls","resolveIdrefTokens","hasEffectiveLabelledBy","refsInternals","resolved","el","flattenAccName","containerTabindex","html","fallbackLabel","nothing","forcedColorsSurface","__decorateClass","property","state","customElement","helixTreeItemStyles","HelixTreeItem","path","parent","siblings","tree","selection","posInSet","flattened","slot","nodes","n","closest","active","options","childrenGroup","classMap","fallbackAriaLabel","ariaExpanded","ariaSelected","query"],"mappings":"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"}
1
+ {"version":3,"file":"hx-tree-item-CXyspGxI.js","sources":["../../src/components/hx-tree-view/hx-tree-view.styles.ts","../../src/utils/tree-walk.ts","../../src/components/hx-tree-view/hx-tree-view.ts","../../src/components/hx-tree-view/hx-tree-item.styles.ts","../../src/components/hx-tree-view/hx-tree-item.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixTreeViewStyles = css`\n :host {\n display: block;\n contain: layout style;\n font-family: var(--hx-tree-font-family, var(--hx-font-family-sans, sans-serif));\n }\n\n * {\n box-sizing: border-box;\n }\n\n .tree {\n display: block;\n outline: none;\n }\n\n .tree:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid var(--hx-focus-ring-color, #0f7078);\n outline-offset: var(--hx-focus-ring-offset, 2px);\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .tree:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n }\n`;\n","/**\n * Composed-tree walkers for the `hx-tree-view` family.\n *\n * Mirrors the `menu-tree.ts` utilities (codex push-gate round-9 extraction\n * for the menu family), but specialized for `hx-tree-view` / `hx-tree-item`\n * where nesting is structural rather than slot-based — child items live in a\n * named `slot=\"children\"` projected into the parent item's shadow root,\n * and any number of nesting levels are legal.\n *\n * Group 5c (codex push-gate round-1 lift): `hx-tree-view`'s host-bound\n * keydown / select handlers receive bubbled events from EVERY descendant\n * tree-item, including ones that legitimately belong to an inner\n * `hx-tree-view`. The same guard pattern that `hx-menu` uses (act only when\n * THIS host is the closest enclosing surface of the dispatching item) is\n * required for trees too. `hx-tree-item._handleClick` /\n * `_handleKeyDown` need to ignore bubbled events from a CHILD `hx-tree-item`\n * — otherwise selecting Child also activates Parent and Enter on Child\n * re-fires Parent's handler.\n *\n * @module\n */\n\n/**\n * Walks the composed tree from `start` outward and returns the closest\n * enclosing `<hx-tree-view>` element, or `null` if none exists. Crosses\n * shadow boundaries (`getRootNode().host`) and slot boundaries\n * (`assignedSlot`) so that an item nested inside a child tree-item — which\n * lives in the parent item's `slot=\"children\"`, projected into the parent's\n * shadow root — resolves to the correct enclosing tree.\n *\n * Returned as `Element` to avoid a circular import between `hx-tree-view`\n * and this util; callers narrow with `instanceof HelixTreeView` if needed.\n *\n * @internal\n */\nexport function findClosestTreeView(start: Element): Element | null {\n let node: Node | null = start;\n while (node) {\n if (node instanceof Element && node.tagName.toLowerCase() === 'hx-tree-view') {\n return node;\n }\n if (node instanceof Element && node.assignedSlot) {\n node = node.assignedSlot;\n continue;\n }\n const parentNode: Node | null = node.parentNode;\n if (parentNode) {\n node = parentNode;\n continue;\n }\n if (node instanceof ShadowRoot) {\n node = node.host;\n continue;\n }\n break;\n }\n return null;\n}\n\n/**\n * Walks the composed tree from `start` outward and returns the closest\n * enclosing `<hx-tree-item>` element, or `null` if none exists. Includes\n * `start` itself when it is an `hx-tree-item`.\n *\n * Used by `hx-tree-item`'s `_isOwnEvent` origin guard: a click or keydown\n * is \"ours\" iff the closest `hx-tree-item` ancestor of the original event\n * target is THIS item (not a child item slotted into our `children` slot).\n * The walk crosses shadow + slot boundaries so a deeply nested child item\n * resolves correctly.\n *\n * Returned as `Element` to avoid a circular import; callers narrow with\n * `instanceof HelixTreeItem` if needed.\n *\n * @internal\n */\nexport function findClosestTreeItem(start: Element): Element | null {\n let node: Node | null = start;\n while (node) {\n if (node instanceof Element && node.tagName.toLowerCase() === 'hx-tree-item') {\n return node;\n }\n if (node instanceof Element && node.assignedSlot) {\n node = node.assignedSlot;\n continue;\n }\n const parentNode: Node | null = node.parentNode;\n if (parentNode) {\n node = parentNode;\n continue;\n }\n if (node instanceof ShadowRoot) {\n node = node.host;\n continue;\n }\n break;\n }\n return null;\n}\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixTreeViewStyles } from './hx-tree-view.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\nimport type { HelixTreeItem, HxTreeItemSelectDetail } from './hx-tree-item.js';\nimport { devWarn } from '../../utils/dev-warn.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\nimport { flattenAccName } from '../../utils/aria-flatten.js';\nimport { findClosestTreeView } from '../../utils/tree-walk.js';\n\n/** Selection mode for the tree. */\nexport type TreeSelection = 'none' | 'single' | 'multiple';\n\n/** Detail type for the `hx-select` event. */\nexport interface HxSelectDetail {\n /** The tree item that was selected or deselected. */\n item: HelixTreeItem;\n /** Whether the item is now selected. */\n selected: boolean;\n}\n\n/**\n * A hierarchical tree component for navigating nested data structures.\n * Used in healthcare applications for org charts, ICD-10 code hierarchies, and department navigation.\n *\n * Group 5c host-canonical: `role=\"tree\"` lives on the **host** via\n * `_internals.role` on the modern path. The host carries the announced\n * surface so AT walks `<hx-tree-view>` (role=tree) → slotted\n * `<hx-tree-item>` (role=treeitem on host) directly without two layers of\n * indirection. Consumer-supplied `aria-label` / `aria-labelledby` on the\n * host are resolved via the shared IDREF mirror; cross-shadow naming uses\n * `ariaLabelledByElements` (modern) with a flattened-string fallback\n * (legacy). On the legacy fallback path the inner `[role=\"tree\"]` carries\n * the role + accessible name and the host role is suppressed so AT only\n * sees one tree per logical surface (mirrors `hx-menu` round-8).\n *\n * Full keyboard navigation: Arrow keys for movement, Enter/Space for\n * selection, Home/End for first/last item, ArrowRight/Left for\n * expand/collapse + parent/child traversal, typeahead.\n *\n * ## Scale Limits\n *\n * This component renders all tree items simultaneously in the DOM. It is suitable for\n * trees with up to ~500 visible items. For large taxonomies (e.g., ICD-10 with 70,000+\n * codes), use async/lazy loading: only render top-level nodes initially and populate\n * child nodes on `hx-select` or expand events. The component exposes the `expanded`\n * property on `hx-tree-item` for programmatic control of subtrees, enabling consumer-level\n * virtualization strategies without requiring changes to this component.\n *\n * @summary Hierarchical tree view with expand/collapse and keyboard navigation.\n *\n * @tag hx-tree-view\n *\n * @slot - Default slot for hx-tree-item elements.\n *\n * @fires {CustomEvent<HxSelectDetail>} hx-select - Dispatched when a tree item is selected or deselected.\n *\n * @csspart tree - The tree container element with role=\"tree\" (legacy fallback path) or the inner shadow surface (modern path; role lives on the host).\n *\n * @cssprop [--hx-tree-font-family=var(--hx-font-family-sans)] - Tree font family.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n */\n@customElement('hx-tree-view')\nexport class HelixTreeView extends HelixElement {\n static override styles = [helixTreeViewStyles, forcedColorsSurface];\n\n // ─── Properties ───\n\n /**\n * Accessible label for the tree. Used as a fallback when no\n * consumer-supplied `aria-label` / `aria-labelledby` is present on the\n * host. On the modern host-canonical path this projects onto\n * `internals.ariaLabel`; on the legacy fallback path it appears as\n * `aria-label` on the inner `[role=\"tree\"]` element.\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = '';\n\n /**\n * Selection mode for the tree.\n * - `none` — items cannot be selected\n * - `single` — only one item can be selected at a time\n * - `multiple` — multiple items can be selected\n * @attr selection\n */\n @property({ type: String, reflect: true })\n selection: 'none' | 'single' | 'multiple' = 'none';\n\n // ─── Internal State ───\n\n /** @internal */\n @state() private _currentIndex = 0;\n\n /** Tracks whether the tree has any visible items, to decide the container tabindex. */\n /** @internal */\n @state() private _hasVisibleItems = false;\n\n // ─── Host-canonical ARIA bookkeeping ───\n\n /**\n * Test seam (codex push-gate round-1 lift from group 5b): when set to\n * `true` or `false`, overrides the platform `supportsIdrefElementReferences`\n * probe before `connectedCallback` seeds `_supportsIdrefRefs`. Mirrors the\n * hx-menu / hx-menu-item / hx-select seam — required so tests can\n * deterministically exercise the legacy fallback render branch.\n *\n * Production code MUST NOT touch this field. It is `static` so the test\n * stub cleanup is global and obvious.\n * @internal\n */\n static __testSupportsIdrefRefsOverride: boolean | null = null;\n\n /** @internal */\n private _supportsIdrefRefs = true;\n\n /** @internal */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n\n /**\n * Resolved accessible name for the tree — the single source of truth read\n * by `_syncHostAriaSemantics()` (modern path: writes to\n * `internals.ariaLabel`) and the fallback `render()` branch (legacy path:\n * writes to inner `div[role=\"tree\"]` `aria-label`). AccName 1.2 §4.3.1\n * precedence: consumer host `aria-labelledby` (resolved + flattened) >\n * consumer host `aria-label` > `label` property > literal \"Tree\".\n * @internal\n */\n private _resolvedAccessibleName = '';\n\n // ─── Visible items cache ───\n\n /**\n * Cached flat list of visible items (depth-first, respects collapsed nodes).\n * Set to null to invalidate; rebuilt on next access.\n * @internal\n */\n private _cachedVisibleItems: HelixTreeItem[] | null = null;\n\n /**\n * Invalidate the visible-items cache. Call after any expand/collapse or structural change.\n * @internal\n */\n private _invalidateVisibleItemsCache(): void {\n this._cachedVisibleItems = null;\n }\n\n // ─── Internal Helpers ───\n\n /**\n * Returns a flat ordered list of all visible (not inside a collapsed item) hx-tree-items\n * in depth-first order. Result is cached; invalidated on expand/collapse/slotchange.\n */\n /** @internal */\n private _getVisibleItems(): HelixTreeItem[] {\n if (!this._cachedVisibleItems) {\n this._cachedVisibleItems = this._collectVisibleItems(this);\n }\n return this._cachedVisibleItems;\n }\n\n /** @internal */\n private _collectVisibleItems(container: Element): HelixTreeItem[] {\n const items: HelixTreeItem[] = [];\n for (const child of Array.from(container.children)) {\n if (child.tagName.toLowerCase() === 'hx-tree-item') {\n const item = child as HelixTreeItem;\n items.push(item);\n if (item.expanded) {\n items.push(...this._collectVisibleItems(item));\n }\n } else {\n items.push(...this._collectVisibleItems(child));\n }\n }\n return items;\n }\n\n /** @internal */\n private _getSelectedItems(): HelixTreeItem[] {\n return Array.from(this.querySelectorAll<HelixTreeItem>('hx-tree-item[selected]'));\n }\n\n /**\n * Updates the roving tabindex across all visible items so that only the\n * item at `activeIndex` has `tabindex=\"0\"`. All others receive `tabindex=\"-1\"`.\n * This is called whenever the active item changes (navigation, initial render).\n */\n /** @internal */\n private _updateRovingTabindex(items: HelixTreeItem[], activeIndex: number): void {\n items.forEach((item, i) => {\n item.setRovingActive(i === activeIndex);\n });\n }\n\n /** @internal */\n private _focusItem(index: number): void {\n const items = this._getVisibleItems();\n if (items.length === 0) return;\n const clamped = Math.max(0, Math.min(index, items.length - 1));\n this._currentIndex = clamped;\n this._updateRovingTabindex(items, clamped);\n items[clamped]?.focus();\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleTreeItemSelect(e: Event): void {\n if (!(e instanceof CustomEvent)) return;\n const event = e as CustomEvent<HxTreeItemSelectDetail>;\n const item = event.detail.item;\n\n if (this.selection === 'none') return;\n\n if (this.selection === 'single') {\n const wasSelected = item.selected;\n this._getSelectedItems().forEach((i) => {\n i.selected = false;\n });\n item.selected = !wasSelected;\n } else if (this.selection === 'multiple') {\n item.selected = !item.selected;\n }\n\n this.dispatchEvent(\n new CustomEvent<HxSelectDetail>('hx-select', {\n bubbles: true,\n composed: true,\n detail: { item, selected: item.selected },\n }),\n );\n }\n\n /**\n * Codex push-gate round-1 lift (mirrors hx-menu round-7 finding 2):\n * `hx-tree-item-select` bubbles composed through every enclosing\n * `hx-tree-view`. The outer tree would otherwise corrupt `_currentIndex`\n * to `-1` (the bubbled item is not in its top-level list) and re-emit a\n * duplicate `hx-select`. Only act when THIS tree is the closest\n * enclosing tree of the dispatching item.\n * @internal\n */\n private _handleItemSelectHost = (e: Event): void => {\n if (!(e instanceof CustomEvent)) return;\n const detail = (e as CustomEvent<HxTreeItemSelectDetail>).detail;\n const item = detail?.item;\n if (item && findClosestTreeView(item) !== this) {\n return;\n }\n this._handleTreeItemSelect(e);\n };\n\n /** @internal */\n private _handleKeyDown(e: KeyboardEvent): void {\n const items = this._getVisibleItems();\n if (items.length === 0) return;\n\n let currentIndex = this._currentIndex;\n const focused = document.activeElement;\n\n for (let i = 0; i < items.length; i++) {\n if (items[i] === focused || items[i]?.shadowRoot?.activeElement) {\n currentIndex = i;\n break;\n }\n }\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n // Intentional design: wrap-around from last to first item provides\n // a continuous navigation loop, consistent with the component's\n // circular keyboard navigation model.\n const next = currentIndex < items.length - 1 ? currentIndex + 1 : 0;\n this._focusItem(next);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n // Intentional design: wrap-around from first to last item (see ArrowDown note).\n const prev = currentIndex > 0 ? currentIndex - 1 : items.length - 1;\n this._focusItem(prev);\n break;\n }\n case 'ArrowLeft': {\n e.preventDefault();\n const currentItem = items[currentIndex];\n if (!currentItem) break;\n if (currentItem.disabled) break;\n if (currentItem.expanded && currentItem.hasChildItems) {\n currentItem.expanded = false;\n this._invalidateVisibleItemsCache();\n } else {\n const parentItem = currentItem.parentElement?.closest('hx-tree-item') as\n | HelixTreeItem\n | undefined;\n if (parentItem) {\n const parentIndex = items.indexOf(parentItem);\n if (parentIndex >= 0) {\n this._focusItem(parentIndex);\n }\n }\n }\n break;\n }\n case 'ArrowRight': {\n e.preventDefault();\n const currentItem = items[currentIndex];\n if (!currentItem) break;\n if (currentItem.disabled) break;\n if (currentItem.hasChildItems) {\n if (!currentItem.expanded) {\n currentItem.expanded = true;\n this._invalidateVisibleItemsCache();\n } else {\n this._focusItem(currentIndex + 1);\n }\n }\n break;\n }\n case 'Home': {\n e.preventDefault();\n this._focusItem(0);\n break;\n }\n case 'End': {\n e.preventDefault();\n this._focusItem(items.length - 1);\n break;\n }\n default: {\n // WAI-ARIA APG typeahead: a printable character moves focus to the next visible\n // item whose label starts with that character (case-insensitive).\n if (e.key.length === 1) {\n e.preventDefault();\n const matchIndex = this._findTypeaheadMatch(e.key.toLowerCase(), currentIndex);\n if (matchIndex !== -1) {\n this._focusItem(matchIndex);\n }\n }\n break;\n }\n }\n }\n\n /**\n * Codex push-gate round-1 lift (mirrors hx-menu round-7 finding 1):\n * keydown bound on the host receives events bubbled out of nested\n * tree-views. Without this guard the outer tree would run `_focusItem`\n * over its own top-level items and steal focus back out of the inner\n * tree. Only act when THIS tree is the closest enclosing tree of the\n * keydown target.\n * @internal\n */\n private _handleHostKeyDown = (e: KeyboardEvent): void => {\n const target = e.target;\n if (target instanceof Element && findClosestTreeView(target) !== this) {\n return;\n }\n this._handleKeyDown(e);\n };\n\n /**\n * Finds the next visible item (starting after `currentIndex`, wrapping around) whose\n * label text begins with the given lowercase character. Returns -1 if no match.\n * @internal\n */\n private _findTypeaheadMatch(char: string, currentIndex: number): number {\n const items = this._getVisibleItems();\n if (items.length === 0) return -1;\n for (let i = 1; i <= items.length; i++) {\n const index = (currentIndex + i) % items.length;\n const item = items[index];\n if (item && item.labelText.toLowerCase().startsWith(char)) {\n return index;\n }\n }\n return -1;\n }\n\n /** @internal */\n private _handleFocusIn(e: FocusEvent): void {\n // With roving tabindex, the tree container (tabindex=\"-1\") should only receive\n // focus when the tree is empty. If focus does land on the container (e.g. the\n // tree is empty or programmatic focus), redirect to the active item if present.\n if (e.target === e.currentTarget) {\n const items = this._getVisibleItems();\n if (items.length > 0) {\n this._focusItem(this._currentIndex);\n }\n }\n }\n\n /**\n * Compute and push ARIA position metadata (level, posInSet, setSize, selectable) to all\n * direct hx-tree-item children of a container in a single O(n) pass.\n * Each item also recurses for its own children, building the full tree in O(total-items) total.\n * @internal\n */\n private _updateAriaMetadataForContainer(container: Element, level: number): void {\n const selectable = this.selection === 'single' || this.selection === 'multiple';\n const children = Array.from(container.children).filter(\n (c) => c.tagName.toLowerCase() === 'hx-tree-item',\n ) as HelixTreeItem[];\n const setSize = children.length;\n children.forEach((item, index) => {\n item.setAriaMetadata(level, index + 1, setSize, selectable);\n // Recurse into child items so the full tree is updated in one traversal\n this._updateAriaMetadataForContainer(item, level + 1);\n });\n }\n\n /**\n * Initializes the roving tabindex after items are first slotted in.\n * Ensures the active item (index 0 by default) has tabindex=\"0\" from the start,\n * so a Tab into the tree lands directly on the first item without a redirect.\n * Also updates `_hasVisibleItems` so the container tabindex re-renders correctly.\n * Pushes O(n) ARIA metadata to all items to replace the O(n^2) per-item ancestor walk.\n */\n /** @internal */\n private _handleSlotChange(): void {\n this._invalidateVisibleItemsCache();\n // Push ARIA metadata from parent in a single O(n) traversal\n this._updateAriaMetadataForContainer(this, 1);\n const items = this._getVisibleItems();\n this._hasVisibleItems = items.length > 0;\n if (items.length === 0) return;\n // Clamp _currentIndex in case items were removed.\n const clamped = Math.min(this._currentIndex, items.length - 1);\n this._currentIndex = clamped;\n this._updateRovingTabindex(items, clamped);\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Honour the static test override so synthetic environments choose the\n // path BEFORE connect runs — the fallback render branch needs to be\n // selected at first paint so the inner `[role=\"tree\"]` carries the\n // resolved accessible name without a mid-life flag flip.\n const ctor = this.constructor as typeof HelixTreeView;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n // Keydown + select are bound on the HOST so events from focused\n // host-canonical tree-items (which keep keydown out of this tree's\n // shadow DOM on the modern path) still reach the navigation handler.\n // Both handlers carry composed-tree origin guards that ignore events\n // bubbled out of a NESTED `<hx-tree-view>`.\n this.addEventListener('keydown', this._handleHostKeyDown);\n this.addEventListener('hx-tree-item-select', this._handleItemSelectHost);\n // Seed host-canonical semantics so role/label appear before first paint.\n this._syncHostAriaSemantics();\n this._ariaMirror = installAriaIdrefMirror(this, () => {\n this._syncHostAriaSemantics();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('keydown', this._handleHostKeyDown);\n this.removeEventListener('hx-tree-item-select', this._handleItemSelectHost);\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n // CodeRabbit MUST-FIX: `selection` change must re-sync host\n // semantics so `aria-multiselectable` reflects the new mode\n // (single → false, multiple → true, none → unset). Previously only\n // `label` triggered the resync, leaving stale aria-multiselectable.\n if (changedProperties.has('label') || changedProperties.has('selection')) {\n this._syncHostAriaSemantics();\n }\n if (changedProperties.has('selection')) {\n // Per-item _selectable flag also depends on the parent's selection\n // mode — recompute the descendants so each hx-tree-item host's\n // `aria-selected` matches the new container contract.\n this._updateAriaMetadataForContainer(this, 1);\n }\n }\n\n override firstUpdated(): void {\n const hasEffectiveLabel =\n this.hasAttribute('aria-label') ||\n this.hasAttribute('aria-labelledby') ||\n Boolean(this.label);\n if (!hasEffectiveLabel) {\n devWarn(\n 'hx-tree-view',\n 'No accessible label provided. Set the `label` attribute, or supply `aria-label` / `aria-labelledby` on hx-tree-view so screen readers can identify this tree (WCAG 4.1.2).',\n );\n }\n }\n\n /**\n * Mirror tree semantics onto the host via ElementInternals so consumer-\n * supplied `aria-label`, `aria-labelledby`, and the `label` property all\n * reach the announced control. Falls back to a flattened-string label on\n * engines that do not implement `ariaLabelledByElements`.\n *\n * Codex push-gate round-1 lift (mirrors hx-menu round-8 finding 1): on\n * the legacy fallback path the inner `<div role=\"tree\" aria-label=\"…\">`\n * is the announced surface. If we ALSO write `internals.role = 'tree'`\n * onto the host, AT sees TWO trees for one logical surface — the\n * duplicate-surface problem host-canonical migration is meant to\n * eliminate. Suppress host role + label writes on the fallback path; the\n * inner element is the canonical announced surface there. Modern path\n * keeps the host as the canonical surface and clears the inner role.\n * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n\n if (!this._supportsIdrefRefs) {\n internals.role = null;\n internals.ariaLabel = null;\n internals.ariaMultiSelectable = null;\n } else {\n internals.role = 'tree';\n internals.ariaMultiSelectable =\n this.selection === 'none' ? null : this.selection === 'multiple' ? 'true' : 'false';\n }\n\n const hostAriaLabel = this.getAttribute('aria-label')?.trim() || '';\n const consumerLabelledBy = this.getAttribute('aria-labelledby');\n const labelEls = resolveIdrefTokens(this, consumerLabelledBy);\n const hasEffectiveLabelledBy = labelEls.length > 0;\n\n type InternalsWithRefs = ElementInternals & {\n ariaLabelledByElements: Element[] | null;\n };\n\n if (this._supportsIdrefRefs) {\n const refsInternals = internals as InternalsWithRefs;\n refsInternals.ariaLabelledByElements = hasEffectiveLabelledBy ? labelEls : null;\n }\n\n // AccName 1.2 §4.3.1 precedence: consumer aria-labelledby (resolved) >\n // consumer aria-label > `label` property > literal \"Tree\" (last-resort).\n let resolved = '';\n if (hasEffectiveLabelledBy) {\n const flattened =\n labelEls\n .map((el) => flattenAccName(el))\n .filter(Boolean)\n .join(' ') ||\n hostAriaLabel ||\n this.label ||\n 'Tree';\n resolved = flattened;\n if (this._supportsIdrefRefs) {\n // Modern path: element refs win; clear ariaLabel so they aren't\n // shadowed by a stale string. Fallback branch reads\n // `_resolvedAccessibleName` for its inner-div mirror — host\n // ariaLabel is already cleared above on the fallback path.\n internals.ariaLabel = null;\n }\n } else if (hostAriaLabel) {\n resolved = hostAriaLabel;\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = hostAriaLabel;\n }\n } else {\n resolved = this.label || 'Tree';\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = resolved;\n }\n }\n\n if (this._resolvedAccessibleName !== resolved) {\n this._resolvedAccessibleName = resolved;\n if (!this._supportsIdrefRefs) {\n this.requestUpdate();\n }\n }\n }\n\n // ─── Render ───\n\n override render() {\n // Roving tabindex pattern (WCAG 2.4.3 Fix):\n // The tree container is NOT a Tab stop (tabindex=\"-1\"). Tab focus goes\n // directly to the active item, which carries tabindex=\"0\". The container\n // is only a landing target (tabindex=\"0\") when the tree is empty.\n const containerTabindex = this._hasVisibleItems ? '-1' : '0';\n\n // Modern host-canonical path: role + aria-label live on the host via\n // `_internals`. The inner div is roleless on the modern path so AT\n // does not see a duplicated container role nested inside the host.\n if (this._supportsIdrefRefs) {\n return html`\n <div part=\"tree\" class=\"tree\" tabindex=${containerTabindex} @focusin=${this._handleFocusIn}>\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n\n // Legacy fallback: keep role + aria-label on inner div for AT without\n // IDL element-references on ElementInternals. Mirror the resolved\n // accessible name (consumer aria-label / aria-labelledby flatten /\n // `label` property cascade) so menus named via the new host API still\n // announce on legacy engines.\n const fallbackLabel = this._resolvedAccessibleName || this.label || 'Tree';\n return html`\n <div\n part=\"tree\"\n class=\"tree\"\n role=\"tree\"\n tabindex=${containerTabindex}\n aria-label=${fallbackLabel}\n aria-multiselectable=${this.selection === 'none'\n ? nothing\n : this.selection === 'multiple'\n ? 'true'\n : 'false'}\n @focusin=${this._handleFocusIn}\n >\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tree-view': HelixTreeView;\n }\n}\n\n/** Canonical type alias for HelixTreeView. Use this when typing hx-tree-view element references. */\nexport type HxTreeView = HelixTreeView;\n","import { css } from 'lit';\n\nexport const helixTreeItemStyles = css`\n :host {\n display: block;\n contain: layout style;\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ─── Item Container ─── */\n\n .item {\n display: block;\n }\n\n /* ─── Item Row ─── */\n\n .item-row {\n display: flex;\n align-items: center;\n min-height: var(--hx-touch-target-min, 44px);\n gap: var(--hx-tree-item-gap, var(--hx-space-2, 0.5rem));\n padding: var(--hx-tree-item-padding-y, var(--hx-space-2, 0.5rem))\n var(--hx-tree-item-padding-x, var(--hx-space-2, 0.5rem));\n padding-inline-start: calc(\n var(--hx-tree-item-padding-x, var(--hx-space-2, 0.5rem)) + var(--_indent-level, 0) *\n var(--hx-tree-indent-size, 1.5rem)\n );\n border-radius: var(--hx-tree-item-border-radius, var(--hx-border-radius-sm, 0.25rem));\n cursor: pointer;\n outline: none;\n color: var(--hx-tree-item-color, var(--hx-color-neutral-900, #0d1825));\n font-family: var(--hx-tree-item-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-tree-item-font-size, var(--hx-font-size-sm, 0.875rem));\n line-height: var(--hx-line-height-normal, 1.5);\n transition: background-color var(--hx-transition-fast, 150ms ease);\n user-select: none;\n }\n\n .item-row:hover {\n background-color: var(--hx-tree-item-hover-bg, var(--hx-color-neutral-100, #ebeee9));\n }\n\n .item-row:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-tree-item-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, -2px);\n }\n\n /* ─── Selected State ─── */\n\n :host([selected]) .item-row {\n background-color: var(--hx-tree-item-selected-bg, var(--hx-color-primary-100, #dbf0f0));\n color: var(--hx-tree-item-selected-color, var(--hx-color-primary-800, #07494a));\n }\n\n :host([selected]) .item-row:hover {\n background-color: var(--hx-tree-item-selected-hover-bg, var(--hx-color-primary-200, #bce1e1));\n }\n\n /* ─── Disabled State ─── */\n\n :host([disabled]) .item-row {\n opacity: var(--hx-opacity-disabled, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* ─── Expand Icon ─── */\n\n .expand-icon {\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: var(--hx-space-4, 1rem);\n height: var(--hx-space-4, 1rem);\n }\n\n .expand-btn {\n display: flex;\n align-items: center;\n justify-content: center;\n width: var(--hx-space-4, 1rem);\n height: var(--hx-space-4, 1rem);\n padding: 0;\n border: none;\n background: transparent;\n color: var(--hx-tree-item-expand-icon-color, var(--hx-color-neutral-500, #66787b));\n cursor: pointer;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n transition: transform var(--hx-transition-fast, 150ms ease);\n pointer-events: auto;\n }\n\n .expand-btn:hover {\n background-color: var(\n --hx-tree-item-expand-hover-bg,\n var(--hx-overlay-black-6, rgba(0, 0, 0, 0.06))\n );\n }\n\n .expand-btn:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-tree-item-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .expand-btn svg {\n width: var(--hx-space-3, 0.75rem);\n height: var(--hx-space-3, 0.75rem);\n stroke: currentColor;\n fill: none;\n stroke-width: 2;\n stroke-linecap: round;\n stroke-linejoin: round;\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n :host([expanded]) .expand-btn svg {\n transform: rotate(90deg);\n }\n\n .expand-placeholder {\n display: block;\n width: var(--hx-space-4, 1rem);\n flex-shrink: 0;\n }\n\n /* ─── Icon Slot ─── */\n\n .item-icon {\n display: flex;\n align-items: center;\n flex-shrink: 0;\n color: var(--hx-tree-item-icon-color, var(--hx-color-neutral-500, #66787b));\n }\n\n .item-icon:empty {\n display: none;\n }\n\n /* ─── Label ─── */\n\n .item-label {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n /* ─── Children (animated) ─── */\n\n .children {\n display: grid;\n grid-template-rows: 0fr;\n transition: grid-template-rows var(--hx-transition-base, 200ms ease);\n --_indent-level: calc(var(--_indent-level, 0) + 1);\n }\n\n .children--expanded {\n grid-template-rows: 1fr;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .item-row,\n .expand-btn,\n .expand-btn svg,\n .children {\n transition: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .item-row:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: -2px;\n }\n\n .expand-btn:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n }\n\n :host([selected]) .item-row {\n outline: 2px solid Highlight;\n }\n }\n\n .children-inner {\n overflow: hidden;\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { HelixElement } from '../../base/index.js';\nimport { helixTreeItemStyles } from './hx-tree-item.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\nimport { flattenAccName } from '../../utils/aria-flatten.js';\nimport { findClosestTreeItem } from '../../utils/tree-walk.js';\n\n/** Detail type for the `hx-tree-item-select` event. */\nexport interface HxTreeItemSelectDetail {\n /** The tree item that was selected or activated. */\n item: HelixTreeItem;\n}\n\n/**\n * A tree item used within an hx-tree-view component.\n * Supports expand/collapse, selection, keyboard navigation, and icon/children slots.\n *\n * Group 5c host-canonical: `role=\"treeitem\"` lives on the **host** via\n * `_internals.role`. The roving tabindex is written to the host on the\n * modern path so the host is the focusable surface and lands directly\n * under the parent `<hx-tree-view>` (which carries `role=\"tree\"`) in the\n * AT-walked tree. The inner `.item-row` is presentational on the modern\n * path — no role, no aria-* attributes — and carries only click/keyboard\n * event handlers. Keyboard activation (Enter/Space) and expand/collapse\n * (ArrowLeft/Right at the leaf level) are owned by the host's `keydown`\n * handler; ArrowUp/Down/Home/End and typeahead bubble to the parent\n * `<hx-tree-view>` for navigation.\n *\n * The nested `[role=\"group\"]` element that wraps the `slot=\"children\"`\n * stays in the inner shadow DOM regardless of path — that group is a\n * separate sub-surface for the children, not a duplicate of the\n * treeitem role.\n *\n * On the legacy fallback path the inner `.item-row` carries\n * `role=\"treeitem\"` + aria-* state, the host role is suppressed, and the\n * roving tabindex is written to the inner element so there is only ONE\n * focusable surface per item (mirrors hx-menu-item round-8).\n *\n * @summary Individual item within an hx-tree-view hierarchical tree.\n *\n * @tag hx-tree-item\n *\n * @slot - Default slot for the item label content. This text is also used to label the children group.\n * @slot icon - Custom icon shown before the label.\n * @slot children - Nested hx-tree-item elements for sub-tree.\n *\n * @csspart item - The outer item container.\n * @csspart row - The interactive item row (presentational on the modern path; carries role=\"treeitem\" + aria-* on the legacy fallback).\n * @csspart expand-icon - The expand/collapse toggle button.\n * @csspart label - The label text content area.\n * @csspart children - The children container (always carries role=\"group\").\n *\n * @cssprop [--hx-tree-item-color=var(--hx-color-neutral-900)] - Item text color.\n * @cssprop [--hx-tree-item-hover-bg=var(--hx-color-neutral-100)] - Hover background color.\n * @cssprop [--hx-tree-item-selected-bg=var(--hx-color-primary-100)] - Selected background color.\n * @cssprop [--hx-tree-item-selected-color=var(--hx-color-primary-800)] - Selected text color.\n * @cssprop [--hx-tree-item-padding-x=var(--hx-space-2)] - Horizontal padding.\n * @cssprop [--hx-tree-item-padding-y=var(--hx-space-1)] - Vertical padding.\n * @cssprop [--hx-tree-indent-size=1.5rem] - Indentation size per level.\n *\n * @fires {CustomEvent<HxTreeItemSelectDetail>} hx-tree-item-select - Dispatched when this item is clicked or activated via keyboard.\n */\n@customElement('hx-tree-item')\nexport class HelixTreeItem extends HelixElement {\n static override styles = [helixTreeItemStyles, forcedColorsSurface];\n\n /**\n * Test seam (codex push-gate round-1 lift from group 5b): when set to\n * `true` or `false`, overrides the platform `supportsIdrefElementReferences`\n * probe before `connectedCallback` seeds `_supportsIdrefRefs`. Mirrors the\n * hx-menu-item / hx-select seam — required so tests can deterministically\n * exercise the legacy fallback render branch.\n *\n * Production code MUST NOT touch this field. It is `static` so the test\n * stub cleanup is global and obvious.\n * @internal\n */\n static __testSupportsIdrefRefsOverride: boolean | null = null;\n\n // ─── Properties ───\n\n /**\n * Whether the item is expanded (showing children).\n * @attr expanded\n */\n @property({ type: Boolean, reflect: true })\n expanded = false;\n\n /**\n * Whether the item is selected.\n * @attr selected\n */\n @property({ type: Boolean, reflect: true })\n selected = false;\n\n /**\n * Whether the item is disabled (non-interactive).\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n // ─── Internal State ───\n\n /**\n * Tracks whether any elements are assigned to the children slot, controlling expand icon visibility.\n * @internal\n */\n @state() private _hasChildren = false;\n\n /**\n * Whether this item is the roving-tabindex active item in the tree.\n * @internal\n */\n @state() private _rovingActive = false;\n\n /**\n * Text content from the default slot, used to label the children group for screen readers.\n * @internal\n */\n @state() private _labelText = '';\n\n /**\n * Cached ARIA position metadata. Computed once on connect and on slotchange\n * of the parent container, avoiding repeated DOM traversal on every render.\n * @internal\n */\n @state() private _level = 1;\n /**\n * One-based position of this item within its sibling set, set as aria-posinset.\n * @internal\n */\n @state() private _posInSet = 1;\n /**\n * Total count of sibling hx-tree-item elements at the same level, set as aria-setsize.\n * @internal\n */\n @state() private _setSize = 1;\n /**\n * Whether the owning hx-tree-view supports item selection (single or multiple mode).\n * @internal\n */\n @state() private _selectable = false;\n\n /** @internal */\n @query('.item-row') private _itemRowEl!: HTMLElement | null;\n\n // ─── Host-canonical ARIA bookkeeping ───\n\n /** @internal */\n private _supportsIdrefRefs = true;\n\n /** @internal */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n\n /**\n * Resolved accessible name override for the tree item — read by both\n * `_syncHostAriaSemantics()` (modern path: host `internals.ariaLabel`)\n * and the fallback `render()` branch (legacy path: inner\n * `div[role=\"treeitem\"]` `aria-label`). Empty string means \"no override\"\n * — slotted text content provides the implicit name through the\n * announced surface (host on modern; inner row on fallback). AccName 1.2\n * §4.3.1 precedence: consumer host `aria-labelledby` (flattened) >\n * consumer host `aria-label` > implicit slotted text.\n * @internal\n */\n private _resolvedAccessibleName = '';\n\n // ─── Computed ARIA ───\n\n /**\n * Whether this item has slotted children.\n * @returns True if one or more elements are assigned to the children slot.\n */\n get hasChildItems(): boolean {\n return this._hasChildren;\n }\n\n /**\n * The text content of the item's label slot, used for typeahead keyboard navigation.\n * Returns an empty string until the label slot has been assigned.\n */\n get labelText(): string {\n return this._labelText;\n }\n\n /**\n * Recompute all cached ARIA metadata in a single DOM pass.\n * Called on connect, slotchange, and whenever structural context may change.\n * @internal\n */\n private _updateAriaMetadata(): void {\n // Compute nesting level by counting ancestor hx-tree-item elements.\n let level = 1;\n let el: Element | null = this.parentElement;\n while (el) {\n if (el.tagName.toLowerCase() === 'hx-tree-item') level++;\n el = el.parentElement;\n }\n this._level = level;\n\n // Compute position-in-set and set-size from sibling hx-tree-item elements.\n const parent = this.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(\n (c) => c.tagName.toLowerCase() === 'hx-tree-item',\n );\n this._posInSet = siblings.indexOf(this) + 1;\n this._setSize = siblings.length;\n } else {\n this._posInSet = 1;\n this._setSize = 1;\n }\n\n // Determine if the owning tree supports selection.\n const tree = this.closest('hx-tree-view');\n if (tree) {\n const selection = tree.getAttribute('selection');\n this._selectable = selection === 'single' || selection === 'multiple';\n } else {\n this._selectable = false;\n }\n }\n\n /**\n * Set ARIA position metadata from the parent hx-tree-view in a single O(n) pass.\n * Calling this avoids the O(n^2) ancestor-walk + sibling-iteration in _updateAriaMetadata\n * when the parent already knows the layout.\n * @internal\n */\n setAriaMetadata(level: number, posInSet: number, setSize: number, selectable: boolean): void {\n this._level = level;\n this._posInSet = posInSet;\n this._setSize = setSize;\n this._selectable = selectable;\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Honour the static test override so synthetic environments choose the\n // path BEFORE connect runs — the fallback render branch needs to be\n // selected at first paint so role + roving tabindex placement matches a\n // legacy engine for the entire lifecycle.\n const ctor = this.constructor as typeof HelixTreeItem;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n this._updateAriaMetadata();\n // Click + keydown live on the HOST so the active surface (the host on\n // the modern path; either the host or the inner div in delegating\n // engines) receives events. Origin guards (`_isOwnEvent`) reject events\n // bubbled from a CHILD `hx-tree-item` slotted into our `children`\n // slot — without that, selecting Child also activates Parent.\n this.addEventListener('click', this._handleClick);\n this.addEventListener('keydown', this._handleKeyDown);\n this._syncHostAriaSemantics();\n this._applyHostTabIndex();\n this._ariaMirror = installAriaIdrefMirror(this, () => {\n this._syncHostAriaSemantics();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this.removeEventListener('click', this._handleClick);\n this.removeEventListener('keydown', this._handleKeyDown);\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (\n changedProperties.has('disabled') ||\n changedProperties.has('selected') ||\n changedProperties.has('expanded') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_hasChildren') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_selectable') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_level') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_posInSet') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_setSize')\n ) {\n this._syncHostAriaSemantics();\n }\n if (\n (changedProperties as Map<PropertyKey, unknown>).has('_rovingActive') ||\n changedProperties.has('disabled')\n ) {\n this._applyHostTabIndex();\n }\n }\n\n /**\n * Apply the roving tabindex through the right surface for the active\n * path. On the modern host-canonical path the host carries the role +\n * tabindex; on the legacy fallback path the inner `.item-row` carries\n * both via the template, so the host MUST stay out of the tab order to\n * avoid a double-focusable per item (mirrors hx-menu-item round-1\n * finding 3).\n * @internal\n */\n private _applyHostTabIndex(): void {\n if (!this._supportsIdrefRefs) {\n // Fallback path: inner `.item-row` is the focusable surface. Keep\n // the host out of the sequential focus order entirely.\n this.tabIndex = -1;\n return;\n }\n if (this.disabled) {\n this.tabIndex = -1;\n } else {\n this.tabIndex = this._rovingActive ? 0 : -1;\n }\n }\n\n /**\n * Mirror treeitem semantics onto the host via ElementInternals so\n * consumer-supplied `aria-label`, `aria-labelledby`, expand/select state,\n * and tree position all reach the announced control.\n *\n * Codex push-gate round-1 lift (mirrors hx-menu-item round-6 finding 2):\n * on the legacy fallback path the inner `.item-row` already exposes\n * role=\"treeitem\" + aria-* via the template. If we ALSO write those onto\n * the host's ElementInternals, AT sees TWO treeitems for one logical\n * option — the duplicate-surface problem host-canonical migration is\n * meant to eliminate. Suppress all of these state writes on the host\n * when the fallback path is in effect; the inner element is the\n * canonical announced surface.\n * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n\n if (!this._supportsIdrefRefs) {\n internals.role = null;\n internals.ariaLabel = null;\n internals.ariaDisabled = null;\n internals.ariaSelected = null;\n internals.ariaExpanded = null;\n internals.ariaLevel = null;\n internals.ariaPosInSet = null;\n internals.ariaSetSize = null;\n } else {\n internals.role = 'treeitem';\n internals.ariaDisabled = this.disabled ? 'true' : null;\n internals.ariaSelected = this._selectable ? (this.selected ? 'true' : 'false') : null;\n internals.ariaExpanded = this._hasChildren ? (this.expanded ? 'true' : 'false') : null;\n internals.ariaLevel = String(this._level);\n internals.ariaPosInSet = String(this._posInSet);\n internals.ariaSetSize = String(this._setSize);\n }\n\n const hostAriaLabel = this.getAttribute('aria-label')?.trim() || '';\n const consumerLabelledBy = this.getAttribute('aria-labelledby');\n const labelEls = resolveIdrefTokens(this, consumerLabelledBy);\n const hasEffectiveLabelledBy = labelEls.length > 0;\n\n type InternalsWithRefs = ElementInternals & {\n ariaLabelledByElements: Element[] | null;\n };\n\n if (this._supportsIdrefRefs) {\n const refsInternals = internals as InternalsWithRefs;\n refsInternals.ariaLabelledByElements = hasEffectiveLabelledBy ? labelEls : null;\n }\n\n // AccName 1.2 §4.3.1 precedence: consumer aria-labelledby (resolved) >\n // consumer aria-label > implicit slotted text (left to AccName\n // computation through the host's role). When neither override is\n // supplied, ariaLabel is cleared so AT walks slotted children for the\n // accessible name.\n let resolved = '';\n if (hasEffectiveLabelledBy) {\n const flattened =\n labelEls\n .map((el) => flattenAccName(el))\n .filter(Boolean)\n .join(' ') ||\n hostAriaLabel ||\n '';\n resolved = flattened;\n if (this._supportsIdrefRefs) {\n // Modern path: element refs win; clear ariaLabel so they aren't\n // shadowed by a stale string.\n internals.ariaLabel = null;\n } else {\n internals.ariaLabel = flattened || null;\n }\n } else if (hostAriaLabel) {\n resolved = hostAriaLabel;\n internals.ariaLabel = hostAriaLabel;\n } else {\n internals.ariaLabel = null;\n }\n\n if (this._resolvedAccessibleName !== resolved) {\n this._resolvedAccessibleName = resolved;\n if (!this._supportsIdrefRefs) {\n this.requestUpdate();\n }\n }\n }\n\n // ─── Children Detection ───\n\n /**\n * Updates _hasChildren and recomputes ARIA metadata when the children slot assignment changes.\n * @internal\n */\n private _handleChildrenSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasChildren = slot.assignedElements().length > 0;\n this._updateAriaMetadata();\n this._syncHostAriaSemantics();\n }\n\n /**\n * Captures the text content from the default (label) slot for use on the children group label.\n * @internal\n */\n private _handleLabelSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n const nodes = slot.assignedNodes({ flatten: true });\n this._labelText = nodes\n .map((n) => n.textContent ?? '')\n .join('')\n .trim();\n }\n\n // ─── Event Handlers ───\n\n /**\n * Origin guard for host-bound click/keydown handlers. Returns `true` only\n * when the event originated on THIS host's surface (its shadow tree or\n * itself) and not on a nested `hx-tree-item` projected into the\n * `children` slot.\n *\n * Codex push-gate round-1 lift (mirrors hx-menu-item round-5 P1):\n * children are slotted descendants in the parent's light DOM. Click/\n * keydown events from a Child item bubble through the parent host's\n * listeners — without this guard, selecting Child also activates\n * Parent (double `hx-tree-item-select`) and Enter/Space on Child\n * re-trigger Parent's handlers.\n *\n * Uses the shared `findClosestTreeItem` walker (composed-tree, crosses\n * shadow + slot boundaries) so the test bed is reused across the\n * tree family. The event is \"ours\" iff the closest `hx-tree-item`\n * ancestor of the original target is `this`.\n * @internal\n */\n private _isOwnEvent(e: Event): boolean {\n const path = e.composedPath();\n for (const node of path) {\n if (!(node instanceof Element)) continue;\n const closest = findClosestTreeItem(node);\n if (closest) {\n return closest === this;\n }\n }\n return false;\n }\n\n /**\n * Toggles the expanded state when the expand/collapse button is clicked, stopping event propagation.\n * @internal\n */\n private _handleExpandClick(e: Event): void {\n e.stopPropagation();\n if (this.disabled) return;\n this.expanded = !this.expanded;\n }\n\n /**\n * Dispatches the hx-tree-item-select event when the item is activated via\n * click or keyboard. The host listens for click; this method is also\n * invoked from the Enter/Space keydown branch.\n * @internal\n */\n private _activate(): void {\n if (this.disabled) return;\n this.dispatchEvent(\n new CustomEvent<HxTreeItemSelectDetail>('hx-tree-item-select', {\n bubbles: true,\n composed: true,\n detail: { item: this },\n }),\n );\n }\n\n /** @internal */\n private _handleClick = (e: MouseEvent): void => {\n // Codex push-gate round-1 lift (mirrors hx-menu-item round-5 P1):\n // clicks on a nested CHILD tree-item bubble through this host. Without\n // an origin guard, both Child and Parent activate.\n if (!this._isOwnEvent(e)) return;\n // CodeRabbit MUST-FIX: a click landing inside our own children\n // container (the `[role=\"group\"]` wrapper around `<slot name=\"children\">`)\n // — i.e. on padding, between child items, on the group itself — also\n // walks back up to THIS host through `_isOwnEvent`. Treat any click\n // sourced from the children group as NOT a row activation.\n const path = e.composedPath();\n for (const node of path) {\n if (!(node instanceof Element)) continue;\n if (node === this) break;\n if (node.getAttribute && node.getAttribute('part') === 'children') return;\n }\n if (this.disabled) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n this._activate();\n };\n\n /** @internal */\n private _handleKeyDown = (e: KeyboardEvent): void => {\n // Codex push-gate round-1 lift (mirrors hx-menu-item round-5 P1):\n // Enter / Space / ArrowLeft / ArrowRight at a focused CHILD bubble\n // through this host. Without an origin guard, Parent treats them as\n // its own — double activation, wrong-level expand/collapse.\n if (!this._isOwnEvent(e)) return;\n if (this.disabled) return;\n\n switch (e.key) {\n case 'ArrowRight':\n e.preventDefault();\n if (this._hasChildren && !this.expanded) {\n this.expanded = true;\n }\n break;\n case 'ArrowLeft':\n e.preventDefault();\n if (this._hasChildren && this.expanded) {\n this.expanded = false;\n }\n break;\n case 'Enter':\n case ' ':\n e.preventDefault();\n this._activate();\n break;\n case 'ArrowDown':\n case 'ArrowUp':\n case 'Home':\n case 'End':\n // Bubble up to hx-tree-view for navigation\n break;\n }\n };\n\n // ─── Public API ───\n\n /**\n * Sets the roving tabindex state for this item.\n * When `active` is true, the host (modern) or inner row (fallback) gets\n * `tabindex=\"0\"` making it the Tab-reachable surface in the tree. All\n * other items should be set to false. Called by the parent hx-tree-view\n * to manage the roving tabindex pattern.\n */\n setRovingActive(active: boolean): void {\n this._rovingActive = active;\n this._applyHostTabIndex();\n }\n\n /**\n * Focus this item. On the modern host-canonical path, focus lands on the\n * host (which carries the roving tabindex and announced role). On the\n * legacy fallback path, focus delegates to the inner `.item-row` which\n * still carries the role.\n */\n override focus(options?: FocusOptions): void {\n if (this._supportsIdrefRefs) {\n HTMLElement.prototype.focus.call(this, options);\n } else {\n this._itemRowEl?.focus(options);\n }\n }\n\n // ─── Render ───\n\n /**\n * Renders the expand/collapse chevron button, or a placeholder span when the item has no children.\n * @internal\n */\n private _renderExpandIcon() {\n if (!this._hasChildren) {\n return html`<span class=\"expand-placeholder\" aria-hidden=\"true\"></span>`;\n }\n return html`\n <button\n part=\"expand-icon\"\n class=\"expand-btn\"\n tabindex=\"-1\"\n aria-label=\"${this.expanded ? 'Collapse' : 'Expand'}\"\n @click=${this._handleExpandClick}\n >\n <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\">\n <polyline points=\"6 4 10 8 6 12\" />\n </svg>\n </button>\n `;\n }\n\n override render() {\n // The nested children container always carries role=\"group\" — that is\n // a separate sub-surface for the children, not a duplicate of the\n // treeitem role, and is correct on both the modern and fallback paths.\n const childrenGroup = html`\n <div\n part=\"children\"\n class=${classMap({ children: true, 'children--expanded': this.expanded })}\n role=\"group\"\n aria-label=${this._labelText ? `${this._labelText} children` : 'children'}\n aria-hidden=${!this.expanded || nothing}\n >\n <div class=\"children-inner\">\n <slot name=\"children\" @slotchange=${this._handleChildrenSlotChange}></slot>\n </div>\n </div>\n `;\n\n // Modern host-canonical path: role/aria-* and tabindex live on the\n // host via `_internals` and the `_applyHostTabIndex()` helper. The\n // inner `.item-row` is presentational (no role, no aria-*) and carries\n // only the visual treatment + slot composition. Click + keydown\n // handlers stay on the host (see connectedCallback) so keyboard\n // activation works regardless of which surface is focused.\n if (this._supportsIdrefRefs) {\n return html`\n <div part=\"item\" class=\"item\">\n <div part=\"row\" class=\"item-row\">\n ${this._renderExpandIcon()}\n <span class=\"item-icon\">\n <slot name=\"icon\"></slot>\n </span>\n <span part=\"label\" class=\"item-label\">\n <slot @slotchange=${this._handleLabelSlotChange}></slot>\n </span>\n </div>\n ${childrenGroup}\n </div>\n `;\n }\n\n // Legacy fallback: keep role/aria-* on the inner `.item-row` for AT\n // without IDL element-references on ElementInternals. Click + keydown\n // still listen on the host (see connectedCallback) so behaviour is\n // uniform across paths. The inner element MUST mirror the same\n // accessible name resolved by `_syncHostAriaSemantics()`.\n const fallbackAriaLabel = this._resolvedAccessibleName || nothing;\n const ariaExpanded = this._hasChildren ? String(this.expanded) : nothing;\n const ariaSelected = this._selectable ? String(this.selected) : nothing;\n\n return html`\n <div part=\"item\" class=\"item\">\n <div\n part=\"row\"\n class=\"item-row\"\n role=\"treeitem\"\n tabindex=${this._rovingActive ? '0' : '-1'}\n aria-label=${fallbackAriaLabel}\n aria-expanded=${ariaExpanded}\n aria-selected=${ariaSelected}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-level=${this._level}\n aria-posinset=${this._posInSet}\n aria-setsize=${this._setSize}\n >\n ${this._renderExpandIcon()}\n <span class=\"item-icon\">\n <slot name=\"icon\"></slot>\n </span>\n <span part=\"label\" class=\"item-label\">\n <slot @slotchange=${this._handleLabelSlotChange}></slot>\n </span>\n </div>\n ${childrenGroup}\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-tree-item': HelixTreeItem;\n }\n}\n\n/** Canonical type alias for HelixTreeItem. Use this when typing hx-tree-item element references. */\nexport type HxTreeItem = HelixTreeItem;\n"],"names":["helixTreeViewStyles","css","findClosestTreeView","start","node","parentNode","findClosestTreeItem","HelixTreeView","HelixElement","detail","item","target","container","items","child","activeIndex","index","clamped","_a","wasSelected","i","currentIndex","focused","_b","next","prev","currentItem","parentItem","_c","parentIndex","matchIndex","char","level","selectable","children","c","setSize","ctor","supportsIdrefElementReferences","installAriaIdrefMirror","changedProperties","internals","hostAriaLabel","consumerLabelledBy","labelEls","resolveIdrefTokens","hasEffectiveLabelledBy","refsInternals","resolved","el","flattenAccName","containerTabindex","html","fallbackLabel","nothing","forcedColorsSurface","__decorateClass","property","state","customElement","helixTreeItemStyles","HelixTreeItem","path","parent","siblings","tree","selection","posInSet","flattened","slot","nodes","n","closest","active","options","childrenGroup","classMap","fallbackAriaLabel","ariaExpanded","ariaSelected","query"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"aria-idref.d.ts","sourceRoot":"","sources":["../../src/utils/aria-idref.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,EAAE,CA6BlF;AAsGD;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAOnF;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iEAAiE;IACjE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,IAAI,CAazF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,+BAA+B;IAC/B,MAAM,IAAI,IAAI,CAAC;IACf,6CAA6C;IAC7C,UAAU,IAAI,IAAI,CAAC;CACpB;AAoGD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,MAAM,IAAI,EAChB,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CAsGvB"}
1
+ {"version":3,"file":"aria-idref.d.ts","sourceRoot":"","sources":["../../src/utils/aria-idref.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,EAAE,CA6BlF;AAsGD;;;;GAIG;AACH,wBAAgB,8BAA8B,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAOnF;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,gEAAgE;IAChE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iEAAiE;IACjE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,GAAG,IAAI,CAazF;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACpC,+BAA+B;IAC/B,MAAM,IAAI,IAAI,CAAC;IACf,6CAA6C;IAC7C,UAAU,IAAI,IAAI,CAAC;CACpB;AAoGD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,OAAO,EACb,IAAI,EAAE,MAAM,IAAI,EAChB,OAAO,GAAE,sBAA2B,GACnC,qBAAqB,CA4HvB"}
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-05-06T11:01:35.731Z",
3
+ "generatedAt": "2026-05-06T14:32:03.211Z",
4
4
  "sourceCem": "custom-elements.json",
5
- "helixVersion": "3.4.0",
5
+ "helixVersion": "3.4.1",
6
6
  "tokensVersion": "3.3.1",
7
7
  "components": [
8
8
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helixui/library",
3
- "version": "3.4.0",
3
+ "version": "3.4.1-next.125",
4
4
  "description": "Enterprise Web Component Library built with Lit 3.x",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -59,7 +59,7 @@
59
59
  "customElements": "custom-elements.json",
60
60
  "dependencies": {
61
61
  "lit": "^3.3.2",
62
- "@helixui/tokens": "3.3.1"
62
+ "@helixui/tokens": "3.3.1-next.125"
63
63
  },
64
64
  "peerDependencies": {
65
65
  "@floating-ui/dom": "^1.7.6"
@@ -1,126 +0,0 @@
1
- function p(e, i) {
2
- if (!i) return [];
3
- const a = i.split(/\s+/).filter(Boolean);
4
- if (a.length === 0) return [];
5
- const t = [];
6
- w(e, t);
7
- const r = e.ownerDocument;
8
- r && !t.includes(r) && t.push(r);
9
- const c = [];
10
- for (const d of a)
11
- for (const n of t) {
12
- const s = n.getElementById(d);
13
- if (s) {
14
- c.push(s);
15
- break;
16
- }
17
- }
18
- return c;
19
- }
20
- function w(e, i) {
21
- const a = /* @__PURE__ */ new Set(), t = (s) => {
22
- a.has(s) || (a.add(s), i.push(s));
23
- }, r = /* @__PURE__ */ new Set([e]), c = [];
24
- let d = !1;
25
- const n = (s) => {
26
- let b = s, o = b.getRootNode();
27
- const l = b.assignedSlot ?? null;
28
- for (l && !r.has(l) && (r.add(l), c.push(l)); o instanceof ShadowRoot; ) {
29
- t(o);
30
- const u = o.host ?? null;
31
- if (!u) break;
32
- const f = u.assignedSlot ?? null;
33
- f && !r.has(f) && (r.add(f), c.push(f)), b = u, o = u.getRootNode();
34
- }
35
- o instanceof Document && (d = !0);
36
- };
37
- for (n(e); c.length > 0; )
38
- n(c.shift());
39
- if (d) {
40
- const s = e.ownerDocument;
41
- s && t(s);
42
- }
43
- }
44
- function R(e) {
45
- return "ariaLabelledByElements" in e && "ariaDescribedByElements" in e && typeof e.ariaLabelledByElements < "u";
46
- }
47
- const v = [
48
- "aria-label",
49
- "aria-labelledby",
50
- "aria-describedby",
51
- "data-aria-label",
52
- "data-aria-labelledby",
53
- "data-aria-describedby"
54
- ], h = /* @__PURE__ */ new WeakMap();
55
- function m(e, i) {
56
- let a = h.get(e);
57
- if (!a) {
58
- const t = /* @__PURE__ */ new Set();
59
- let r = 0;
60
- const c = () => {
61
- r = 0, Array.from(t).forEach((s) => {
62
- s();
63
- });
64
- }, d = () => {
65
- if (r !== 0) return;
66
- r = (typeof globalThis.requestAnimationFrame == "function" ? globalThis.requestAnimationFrame : (b) => globalThis.setTimeout(() => b(performance.now()), 0))(c);
67
- }, n = new MutationObserver(() => {
68
- d();
69
- });
70
- n.observe(e, {
71
- childList: !0,
72
- subtree: !0,
73
- attributes: !0,
74
- attributeFilter: ["id", "hidden", "aria-hidden", "style", "class"],
75
- characterData: !0
76
- }), a = { observer: n, subscribers: t }, h.set(e, a);
77
- }
78
- return a.subscribers.add(i), () => {
79
- const t = h.get(e);
80
- t && (t.subscribers.delete(i), t.subscribers.size === 0 && (t.observer.disconnect(), h.delete(e)));
81
- };
82
- }
83
- function S(e, i, a = {}) {
84
- const t = a.observedAttributes ?? v, r = a.observeRoot ?? !0, c = new MutationObserver(() => i());
85
- c.observe(e, {
86
- attributes: !0,
87
- attributeFilter: [...t]
88
- });
89
- const d = new MutationObserver(() => {
90
- b(), i();
91
- });
92
- d.observe(e, {
93
- attributes: !0,
94
- attributeFilter: ["slot"]
95
- });
96
- const n = /* @__PURE__ */ new Map(), s = () => {
97
- const o = [];
98
- w(e, o);
99
- const l = e.ownerDocument;
100
- return l && !o.includes(l) && o.push(l), o;
101
- }, b = () => {
102
- if (!r) return;
103
- const o = s(), l = new Set(o);
104
- for (const [u, f] of n)
105
- l.has(u) || (f(), n.delete(u));
106
- for (const u of o)
107
- n.has(u) || n.set(u, m(u, i));
108
- };
109
- return b(), i(), {
110
- resync() {
111
- b(), i();
112
- },
113
- disconnect() {
114
- c.disconnect(), d.disconnect();
115
- for (const o of n.values())
116
- o();
117
- n.clear();
118
- }
119
- };
120
- }
121
- export {
122
- S as i,
123
- p as r,
124
- R as s
125
- };
126
- //# sourceMappingURL=aria-idref-CxvyzfQS.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"hx-card-qNAM2QNV.js","sources":["../../src/components/hx-card/hx-card.styles.ts","../../src/components/hx-card/hx-card.ts"],"sourcesContent":["import { css } from 'lit';\n\n/**\n * hx-card styles.\n *\n * Component-tier tokens with two-level var() fallback:\n * var(--hx-card-{prop}, var(--hx-color-{semantic}, #hex))\n * Inner hex fallbacks track the \"precision cool\" palette (3.2.0):\n * neutral-0 = #FFFFFF, neutral-200 = #D6DBD5, neutral-800 = #202B39,\n * neutral-600 = #4A5362, primary-500 = #429797.\n */\nexport const helixCardStyles = css`\n :host {\n display: block;\n color: var(--hx-card-color, inherit);\n background-color: var(--hx-card-bg, var(--hx-color-surface-default, #ffffff));\n }\n\n .card {\n display: flex;\n flex-direction: column;\n gap: var(--hx-card-gap, var(--hx-space-4, 1rem));\n background-color: var(--hx-card-bg, var(--hx-color-surface-default, #ffffff));\n color: var(--hx-card-color, var(--hx-color-text-strong, #202b39));\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-card-border-color, var(--hx-color-border-default, #d6dbd5));\n border-radius: var(--hx-card-border-radius, var(--hx-border-radius-lg, 0.5rem));\n overflow: hidden;\n font-family: var(--hx-card-font-family, var(--hx-font-family-sans, sans-serif));\n transition:\n box-shadow var(--hx-transition-normal, 250ms ease),\n transform var(--hx-transition-normal, 250ms ease);\n }\n\n /* ─── Elevation Variants ─── */\n\n .card--flat {\n box-shadow: none;\n }\n\n .card--raised {\n box-shadow: var(--hx-card-shadow, var(--hx-shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1)));\n }\n\n .card--floating {\n box-shadow: var(\n --hx-card-shadow-floating,\n var(--hx-shadow-xl, 0 20px 25px -5px rgb(0 0 0 / 0.1))\n );\n }\n\n /* ─── Style Variants ─── */\n\n .card--default {\n /* Default styling — uses base styles */\n }\n\n .card--featured {\n border-color: var(--hx-card-featured-border-color, var(--hx-color-primary-500, #429797));\n border-width: var(--hx-card-featured-border-width, var(--hx-border-width-medium, 2px));\n }\n\n .card--compact .card__body {\n padding: var(--hx-space-3, 0.75rem);\n }\n\n .card--compact .card__heading {\n padding-top: var(--hx-space-3, 0.75rem);\n padding-inline-end: var(--hx-space-3, 0.75rem);\n padding-inline-start: var(--hx-space-3, 0.75rem);\n }\n\n .card--compact .card__footer {\n padding-inline-end: var(--hx-space-3, 0.75rem);\n padding-bottom: var(--hx-space-3, 0.75rem);\n padding-inline-start: var(--hx-space-3, 0.75rem);\n }\n\n .card--compact .card__actions {\n padding-inline-end: var(--hx-space-3, 0.75rem);\n padding-bottom: var(--hx-space-3, 0.75rem);\n padding-inline-start: var(--hx-space-3, 0.75rem);\n }\n\n /* ─── Interactive ─── */\n\n .card--interactive {\n cursor: pointer;\n }\n\n .card--interactive:hover {\n box-shadow: var(--hx-card-shadow-hover, var(--hx-shadow-lg, 0 10px 15px -3px rgb(0 0 0 / 0.1)));\n transform: translateY(var(--hx-transform-lift-md, -2px));\n }\n\n .card--interactive:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-card-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .card--interactive:active {\n transform: translateY(0);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .card {\n transition: none;\n }\n\n .card--interactive:hover {\n transform: none;\n }\n\n .card--interactive:active {\n transform: none;\n }\n }\n\n /* ─── Hidden empty slot wrappers ─── */\n\n [hidden] {\n display: none !important;\n }\n\n /* ─── Sections ─── */\n\n .card__image {\n overflow: hidden;\n line-height: 0;\n }\n\n .card__image ::slotted(img) {\n width: 100%;\n aspect-ratio: var(--hx-card-image-aspect-ratio, 16 / 9);\n display: block;\n object-fit: cover;\n }\n\n .card__heading {\n padding-top: var(--hx-card-padding, var(--hx-space-6, 1.5rem));\n padding-inline-end: var(--hx-card-padding, var(--hx-space-6, 1.5rem));\n padding-bottom: 0;\n padding-inline-start: var(--hx-card-padding, var(--hx-space-6, 1.5rem));\n font-size: var(--hx-font-size-xl, 1.25rem);\n font-weight: var(--hx-font-weight-semibold, 600);\n line-height: var(--hx-line-height-tight, 1.25);\n }\n\n .card__body {\n padding: var(--hx-card-padding, var(--hx-space-6, 1.5rem));\n flex: 1;\n font-size: var(--hx-font-size-md, 1rem);\n line-height: var(--hx-line-height-normal, 1.5);\n /*\n * Body color cascades: component-tier --hx-card-body-color overrides\n * the host-tier --hx-card-color, which falls back to text-secondary.\n * Preserves the propagation contract: setting --hx-card-color on the\n * host flows into the body slot (and through to slotted light-DOM\n * descendants via flat-tree inheritance).\n */\n color: var(--hx-card-body-color, var(--hx-card-color, var(--hx-color-text-secondary, #313e4b)));\n }\n\n .card__footer {\n padding-top: 0;\n padding-inline-end: var(--hx-card-padding, var(--hx-space-6, 1.5rem));\n padding-bottom: var(--hx-card-padding, var(--hx-space-6, 1.5rem));\n padding-inline-start: var(--hx-card-padding, var(--hx-space-6, 1.5rem));\n }\n\n .card__actions {\n display: flex;\n gap: var(--hx-space-2, 0.5rem);\n padding-top: var(--hx-space-4, 1rem);\n padding-inline-end: var(--hx-card-padding, var(--hx-space-6, 1.5rem));\n padding-bottom: var(--hx-card-padding, var(--hx-space-6, 1.5rem));\n padding-inline-start: var(--hx-card-padding, var(--hx-space-6, 1.5rem));\n border-top: var(--hx-border-width-thin, 1px) solid\n var(--hx-card-border-color, var(--hx-color-border-default, #d6dbd5));\n margin-top: auto;\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n /* Belt-and-suspenders: rich per-class HC overrides PLUS the forcedColorsSurface mixin. */\n\n @media (forced-colors: active) {\n .card {\n border-color: CanvasText;\n }\n\n .card__actions {\n border-top-color: CanvasText;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { helixCardStyles } from './hx-card.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\nconst _nextCardId = createIdCounter('hx-card');\n\n/**\n * A flexible card component for displaying grouped content.\n *\n * @summary Content container with image, heading, body, footer, and action slots.\n *\n * @tag hx-card\n *\n * @slot image - Optional image or media content at the top of the card.\n * @slot heading - The card heading/title content. Use a semantic heading element (h2, h3, etc.) for proper accessibility.\n * @slot - Default slot for the card body content.\n * @slot footer - Optional footer content below the body.\n * @slot actions - Optional action buttons, rendered with a top border separator. Do NOT use together with hx-href (interactive card + focusable actions is an ARIA anti-pattern).\n *\n * @fires {CustomEvent<{href: string, originalEvent: MouseEvent | KeyboardEvent}>} hx-click - Dispatched when an interactive card (with hx-href) is clicked.\n *\n * @csspart card - The outer card container element.\n * @csspart image - The image slot container.\n * @csspart heading - The heading slot container.\n * @csspart body - The body slot container.\n * @csspart footer - The footer slot container.\n * @csspart actions - The actions slot container.\n *\n * @cssprop [--hx-card-bg=var(--hx-color-neutral-0)] - Card background color.\n * @cssprop [--hx-card-color=var(--hx-color-neutral-800)] - Card text color.\n * @cssprop [--hx-card-border-color=var(--hx-color-neutral-200)] - Card border color.\n * @cssprop [--hx-card-border-radius=var(--hx-border-radius-lg)] - Card border radius.\n * @cssprop [--hx-card-padding=var(--hx-space-6)] - Internal padding for card sections.\n * @cssprop [--hx-card-gap=var(--hx-space-4)] - Gap between card sections.\n * @cssprop [--hx-card-image-aspect-ratio=16/9] - Aspect ratio for the image slot.\n * @cssprop [--hx-border-radius-lg] - CSS custom property.\n * @cssprop [--hx-border-width-medium] - Width.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-card-focus-ring-color=var(--hx-focus-ring-color)] - Color.\n * @cssprop [--hx-card-font-family=var(--hx-font-family-sans)] - Font family for card text content.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-color-neutral-600] - Color.\n * @cssprop [--hx-color-neutral-800] - Color.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-font-size-xl] - Font size.\n * @cssprop [--hx-font-weight-semibold] - Font weight.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-line-height-tight] - Line height.\n * @cssprop [--hx-shadow-lg] - Box shadow.\n * @cssprop [--hx-shadow-md] - Box shadow.\n * @cssprop [--hx-shadow-xl] - Box shadow.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-space-6] - Spacing token.\n * @cssprop [--hx-transform-lift-md] - Transform applied on hover to lift the card.\n * @cssprop [--hx-transition-normal] - Transition timing.\n */\n@customElement('hx-card')\nexport class HelixCard extends HelixElement {\n /** @internal */\n static override shadowRootOptions = {\n ...HelixElement.shadowRootOptions,\n delegatesFocus: true,\n };\n\n static override styles = [helixCardStyles, forcedColorsSurface];\n\n /**\n * Visual style variant of the card.\n * @attr variant\n */\n @property({ type: String, reflect: true })\n variant: 'default' | 'featured' | 'compact' = 'default';\n\n /**\n * Elevation (shadow depth) of the card.\n * @attr elevation\n */\n @property({ type: String, reflect: true })\n elevation: 'flat' | 'raised' | 'floating' = 'flat';\n\n /**\n * Optional URL. When set, the card becomes interactive (clickable)\n * and navigates to this URL on click.\n * Uses the hx-href attribute to avoid conflicting with the native HTML href attribute.\n * @attr hx-href\n */\n @property({ type: String, attribute: 'hx-href' })\n href: string | undefined = undefined;\n\n /**\n * Accessible label for interactive cards. Use this to provide a meaningful\n * description of the card's purpose rather than exposing the raw URL.\n * Only applies when hx-href is set.\n * @attr hx-label\n */\n @property({ type: String, attribute: 'hx-label' })\n label: string | undefined = undefined;\n\n // ─── Slot Detection ───\n\n /**\n * Tracks whether any content is assigned to the image slot, controlling slot container visibility.\n * @internal\n */\n @state() private _hasImage = false;\n\n /**\n * Tracks whether any content is assigned to the heading slot, controlling slot container visibility.\n * @internal\n */\n @state() private _hasHeading = false;\n\n /**\n * Tracks whether any content is assigned to the footer slot, controlling slot container visibility.\n * @internal\n */\n @state() private _hasFooter = false;\n\n /**\n * Tracks whether any content is assigned to the actions slot, controlling slot container visibility.\n * @internal\n */\n @state() private _hasActions = false;\n\n /**\n * Text content extracted from the heading slot, used as a fallback accessible\n * name for interactive cards when no explicit `hx-label` is provided.\n * @internal\n */\n @state() private _headingText = '';\n\n /**\n * Unique identifier for this card instance, used in ARIA attributes.\n * @internal\n */\n private _cardId = _nextCardId();\n /**\n * Unique identifier for the heading element, used in aria-labelledby.\n * @internal\n */\n private _headingId = `${this._cardId}-heading`;\n\n /** @internal */\n private _onImageSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasImage = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n /** @internal */\n private _onHeadingSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n const nodes = slot.assignedNodes({ flatten: true });\n this._hasHeading = nodes.length > 0;\n this._headingText = nodes\n .map((n) => n.textContent?.trim() ?? '')\n .join(' ')\n .trim();\n }\n\n /** @internal */\n private _onFooterSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasFooter = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n /** @internal */\n private _onActionsSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasActions = slot.assignedNodes({ flatten: true }).length > 0;\n if (this._hasActions && this.href) {\n devWarn(\n 'hx-card',\n 'Using hx-href (interactive card) together with the actions slot is an ARIA anti-pattern: ' +\n 'interactive controls cannot be nested inside role=\"link\". ' +\n 'Use either hx-href or the actions slot, not both.',\n );\n }\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n // WCAG 4.1.2: interactive cards (with hx-href) must have an accessible name\n if (\n (changedProperties.has('href') || changedProperties.has('label')) &&\n this.href &&\n !this.label &&\n !this._headingText\n ) {\n devWarn(\n 'hx-card',\n \"Interactive card (hx-href is set) is missing an accessible name. Set `hx-label` or provide heading slot content to describe the card's destination or purpose (WCAG 4.1.2).\",\n );\n }\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _dispatchCardClick(originalEvent: MouseEvent | KeyboardEvent): void {\n if (!this.href) return;\n\n /**\n * Dispatched when an interactive card is clicked.\n * Includes the target href in the detail.\n * @event hx-click\n */\n this.dispatchEvent(\n new CustomEvent<{ href: string; originalEvent: MouseEvent | KeyboardEvent }>('hx-click', {\n bubbles: true,\n composed: true,\n detail: { href: this.href, originalEvent },\n }),\n );\n }\n\n /** @internal */\n private _handleClick(e: MouseEvent): void {\n this._dispatchCardClick(e);\n }\n\n /** @internal */\n private _handleKeyDown(e: KeyboardEvent): void {\n if (!this.href) return;\n\n // WCAG 2.1.1 / ARIA APG: role=\"link\" activates on Enter only.\n // Space is reserved for scrolling and must not activate links.\n if (e.key === 'Enter') {\n e.preventDefault();\n this._dispatchCardClick(e);\n }\n }\n\n // ─── Render ───\n\n override render() {\n const isInteractive = !!this.href;\n\n const classes = {\n card: true,\n [`card--${this.variant}`]: true,\n [`card--${this.elevation}`]: true,\n 'card--interactive': isInteractive,\n };\n\n return html`\n <div\n part=\"card\"\n class=${classMap(classes)}\n role=${isInteractive ? 'link' : nothing}\n tabindex=${isInteractive ? '0' : nothing}\n aria-label=${isInteractive && this.label ? this.label : nothing}\n aria-labelledby=${this._hasHeading && !this.label ? this._headingId : nothing}\n @click=${this._handleClick}\n @keydown=${this._handleKeyDown}\n >\n <div class=\"card__image\" part=\"image\" ?hidden=${!this._hasImage}>\n <slot name=\"image\" @slotchange=${this._onImageSlotChange}></slot>\n </div>\n\n <div\n class=\"card__heading\"\n part=\"heading\"\n id=${this._headingId}\n ?hidden=${!this._hasHeading}\n >\n <slot name=\"heading\" @slotchange=${this._onHeadingSlotChange}></slot>\n </div>\n\n <div class=\"card__body\" part=\"body\">\n <slot></slot>\n </div>\n\n <div class=\"card__footer\" part=\"footer\" ?hidden=${!this._hasFooter}>\n <slot name=\"footer\" @slotchange=${this._onFooterSlotChange}></slot>\n </div>\n\n <div class=\"card__actions\" part=\"actions\" ?hidden=${!this._hasActions}>\n <slot name=\"actions\" @slotchange=${this._onActionsSlotChange}></slot>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-card': HelixCard;\n }\n}\n"],"names":["helixCardStyles","css","_nextCardId","createIdCounter","HelixCard","HelixElement","e","slot","nodes","n","_a","changedProperties","originalEvent","isInteractive","classes","html","classMap","nothing","forcedColorsSurface","__decorateClass","property","state","customElement"],"mappings":";;;;;;AAWO,MAAMA,IAAkBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;ACF/B,MAAMC,IAAcC,EAAgB,SAAS;AA6DtC,IAAMC,IAAN,cAAwBC,EAAa;AAAA,EAArC,cAAA;AAAA,UAAA,GAAA,SAAA,GAcL,KAAA,UAA8C,WAO9C,KAAA,YAA4C,QAS5C,KAAA,OAA2B,QAS3B,KAAA,QAA4B,QAQnB,KAAQ,YAAY,IAMpB,KAAQ,cAAc,IAMtB,KAAQ,aAAa,IAMrB,KAAQ,cAAc,IAOtB,KAAQ,eAAe,IAMhC,KAAQ,UAAUH,EAAA,GAKlB,KAAQ,aAAa,GAAG,KAAK,OAAO;AAAA,EAAA;AAAA;AAAA,EAG5B,mBAAmBI,GAAgB;AACzC,UAAMC,IAAOD,EAAE;AACf,SAAK,YAAYC,EAAK,cAAc,EAAE,SAAS,GAAA,CAAM,EAAE,SAAS;AAAA,EAClE;AAAA;AAAA,EAGQ,qBAAqBD,GAAgB;AAE3C,UAAME,IADOF,EAAE,OACI,cAAc,EAAE,SAAS,IAAM;AAClD,SAAK,cAAcE,EAAM,SAAS,GAClC,KAAK,eAAeA,EACjB,IAAI,CAACC;;AAAM,eAAAC,IAAAD,EAAE,gBAAF,gBAAAC,EAAe,WAAU;AAAA,KAAE,EACtC,KAAK,GAAG,EACR,KAAA;AAAA,EACL;AAAA;AAAA,EAGQ,oBAAoBJ,GAAgB;AAC1C,UAAMC,IAAOD,EAAE;AACf,SAAK,aAAaC,EAAK,cAAc,EAAE,SAAS,GAAA,CAAM,EAAE,SAAS;AAAA,EACnE;AAAA;AAAA,EAGQ,qBAAqBD,GAAgB;AAC3C,UAAMC,IAAOD,EAAE;AACf,SAAK,cAAcC,EAAK,cAAc,EAAE,SAAS,GAAA,CAAM,EAAE,SAAS,GAC9D,KAAK,eAAe,KAAK;AAAA,EAQ/B;AAAA,EAES,QAAQI,GAA+C;AAC9D,UAAM,QAAQA,CAAiB,IAG5BA,EAAkB,IAAI,MAAM,KAAKA,EAAkB,IAAI,OAAO,MAC/D,KAAK,QACL,CAAC,KAAK,SACL,KAAK;AAAA,EAOV;AAAA;AAAA;AAAA,EAKQ,mBAAmBC,GAAiD;AAC1E,IAAK,KAAK,QAOV,KAAK;AAAA,MACH,IAAI,YAAyE,YAAY;AAAA,QACvF,SAAS;AAAA,QACT,UAAU;AAAA,QACV,QAAQ,EAAE,MAAM,KAAK,MAAM,eAAAA,EAAA;AAAA,MAAc,CAC1C;AAAA,IAAA;AAAA,EAEL;AAAA;AAAA,EAGQ,aAAaN,GAAqB;AACxC,SAAK,mBAAmBA,CAAC;AAAA,EAC3B;AAAA;AAAA,EAGQ,eAAeA,GAAwB;AAC7C,IAAK,KAAK,QAINA,EAAE,QAAQ,YACZA,EAAE,eAAA,GACF,KAAK,mBAAmBA,CAAC;AAAA,EAE7B;AAAA;AAAA,EAIS,SAAS;AAChB,UAAMO,IAAgB,CAAC,CAAC,KAAK,MAEvBC,IAAU;AAAA,MACd,MAAM;AAAA,MACN,CAAC,SAAS,KAAK,OAAO,EAAE,GAAG;AAAA,MAC3B,CAAC,SAAS,KAAK,SAAS,EAAE,GAAG;AAAA,MAC7B,qBAAqBD;AAAA,IAAA;AAGvB,WAAOE;AAAA;AAAA;AAAA,gBAGKC,EAASF,CAAO,CAAC;AAAA,eAClBD,IAAgB,SAASI,CAAO;AAAA,mBAC5BJ,IAAgB,MAAMI,CAAO;AAAA,qBAC3BJ,KAAiB,KAAK,QAAQ,KAAK,QAAQI,CAAO;AAAA,0BAC7C,KAAK,eAAe,CAAC,KAAK,QAAQ,KAAK,aAAaA,CAAO;AAAA,iBACpE,KAAK,YAAY;AAAA,mBACf,KAAK,cAAc;AAAA;AAAA,wDAEkB,CAAC,KAAK,SAAS;AAAA,2CAC5B,KAAK,kBAAkB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAMnD,KAAK,UAAU;AAAA,oBACV,CAAC,KAAK,WAAW;AAAA;AAAA,6CAEQ,KAAK,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0DAOZ,CAAC,KAAK,UAAU;AAAA,4CAC9B,KAAK,mBAAmB;AAAA;AAAA;AAAA,4DAGR,CAAC,KAAK,WAAW;AAAA,6CAChC,KAAK,oBAAoB;AAAA;AAAA;AAAA;AAAA,EAIpE;AACF;AAjOab,EAEK,oBAAoB;AAAA,EAClC,GAAGC,EAAa;AAAA,EAChB,gBAAgB;AAClB;AALWD,EAOK,SAAS,CAACJ,GAAiBkB,CAAmB;AAO9DC,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GAb9BhB,EAcX,WAAA,WAAA,CAAA;AAOAe,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,SAAS,IAAM;AAAA,GApB9BhB,EAqBX,WAAA,aAAA,CAAA;AASAe,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,WAAW,WAAW;AAAA,GA7BrChB,EA8BX,WAAA,QAAA,CAAA;AASAe,EAAA;AAAA,EADCC,EAAS,EAAE,MAAM,QAAQ,WAAW,YAAY;AAAA,GAtCtChB,EAuCX,WAAA,SAAA,CAAA;AAQiBe,EAAA;AAAA,EAAhBE,EAAA;AAAM,GA/CIjB,EA+CM,WAAA,aAAA,CAAA;AAMAe,EAAA;AAAA,EAAhBE,EAAA;AAAM,GArDIjB,EAqDM,WAAA,eAAA,CAAA;AAMAe,EAAA;AAAA,EAAhBE,EAAA;AAAM,GA3DIjB,EA2DM,WAAA,cAAA,CAAA;AAMAe,EAAA;AAAA,EAAhBE,EAAA;AAAM,GAjEIjB,EAiEM,WAAA,eAAA,CAAA;AAOAe,EAAA;AAAA,EAAhBE,EAAA;AAAM,GAxEIjB,EAwEM,WAAA,gBAAA,CAAA;AAxENA,IAANe,EAAA;AAAA,EADNG,EAAc,SAAS;AAAA,GACXlB,CAAA;"}