@helixui/library 3.8.0 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/README.md +41 -0
  2. package/aaa-verdicts.json +2036 -0
  3. package/custom-elements.json +532 -569
  4. package/dist/components/hx-accordion/hx-accordion-item.d.ts.map +1 -1
  5. package/dist/components/hx-accordion/hx-accordion-item.styles.d.ts.map +1 -1
  6. package/dist/components/hx-accordion/index.js +1 -1
  7. package/dist/components/hx-alert/hx-alert.d.ts +0 -8
  8. package/dist/components/hx-alert/hx-alert.d.ts.map +1 -1
  9. package/dist/components/hx-alert/hx-alert.styles.d.ts.map +1 -1
  10. package/dist/components/hx-alert/index.js +1 -1
  11. package/dist/components/hx-avatar/hx-avatar.d.ts +4 -1
  12. package/dist/components/hx-avatar/hx-avatar.d.ts.map +1 -1
  13. package/dist/components/hx-avatar/hx-avatar.styles.d.ts.map +1 -1
  14. package/dist/components/hx-avatar/index.js +1 -1
  15. package/dist/components/hx-badge/hx-badge.d.ts.map +1 -1
  16. package/dist/components/hx-badge/hx-badge.styles.d.ts.map +1 -1
  17. package/dist/components/hx-badge/index.js +1 -1
  18. package/dist/components/hx-banner/hx-banner.d.ts +0 -8
  19. package/dist/components/hx-banner/hx-banner.d.ts.map +1 -1
  20. package/dist/components/hx-banner/hx-banner.styles.d.ts.map +1 -1
  21. package/dist/components/hx-banner/index.js +1 -1
  22. package/dist/components/hx-carousel/hx-carousel.d.ts.map +1 -1
  23. package/dist/components/hx-carousel/hx-carousel.styles.d.ts.map +1 -1
  24. package/dist/components/hx-carousel/index.js +1 -1
  25. package/dist/components/hx-checkbox/hx-checkbox.d.ts.map +1 -1
  26. package/dist/components/hx-checkbox/hx-checkbox.styles.d.ts.map +1 -1
  27. package/dist/components/hx-checkbox/index.js +1 -1
  28. package/dist/components/hx-clinical-status/hx-clinical-status.d.ts +7 -9
  29. package/dist/components/hx-clinical-status/hx-clinical-status.d.ts.map +1 -1
  30. package/dist/components/hx-clinical-status/hx-clinical-status.styles.d.ts.map +1 -1
  31. package/dist/components/hx-clinical-status/index.js +1 -1
  32. package/dist/components/hx-combobox/hx-combobox.d.ts.map +1 -1
  33. package/dist/components/hx-combobox/hx-combobox.styles.d.ts.map +1 -1
  34. package/dist/components/hx-combobox/index.js +1 -1
  35. package/dist/components/hx-date-picker/hx-date-picker.d.ts.map +1 -1
  36. package/dist/components/hx-date-picker/hx-date-picker.styles.d.ts.map +1 -1
  37. package/dist/components/hx-date-picker/index.js +1 -1
  38. package/dist/components/hx-drawer/hx-drawer.d.ts.map +1 -1
  39. package/dist/components/hx-drawer/hx-drawer.styles.d.ts.map +1 -1
  40. package/dist/components/hx-drawer/index.js +1 -1
  41. package/dist/components/hx-dropdown/hx-dropdown.styles.d.ts.map +1 -1
  42. package/dist/components/hx-dropdown/index.js +1 -1
  43. package/dist/components/hx-file-upload/hx-file-upload.d.ts +28 -0
  44. package/dist/components/hx-file-upload/hx-file-upload.d.ts.map +1 -1
  45. package/dist/components/hx-file-upload/hx-file-upload.styles.d.ts.map +1 -1
  46. package/dist/components/hx-file-upload/index.js +1 -1
  47. package/dist/components/hx-help-text/hx-help-text.d.ts.map +1 -1
  48. package/dist/components/hx-help-text/hx-help-text.styles.d.ts.map +1 -1
  49. package/dist/components/hx-help-text/index.js +1 -1
  50. package/dist/components/hx-icon/hx-icon.d.ts +108 -12
  51. package/dist/components/hx-icon/hx-icon.d.ts.map +1 -1
  52. package/dist/components/hx-icon/hx-icon.styles.d.ts.map +1 -1
  53. package/dist/components/hx-icon/index.js +1 -1
  54. package/dist/components/hx-link/hx-link.d.ts.map +1 -1
  55. package/dist/components/hx-link/hx-link.styles.d.ts.map +1 -1
  56. package/dist/components/hx-link/index.js +1 -1
  57. package/dist/components/hx-menu/hx-menu-item.d.ts.map +1 -1
  58. package/dist/components/hx-menu/hx-menu-item.styles.d.ts.map +1 -1
  59. package/dist/components/hx-menu/index.js +1 -1
  60. package/dist/components/hx-nav/hx-nav.d.ts.map +1 -1
  61. package/dist/components/hx-nav/hx-nav.styles.d.ts.map +1 -1
  62. package/dist/components/hx-nav/index.js +1 -1
  63. package/dist/components/hx-number-input/hx-number-input.d.ts.map +1 -1
  64. package/dist/components/hx-number-input/hx-number-input.styles.d.ts.map +1 -1
  65. package/dist/components/hx-number-input/index.js +1 -1
  66. package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts +5 -1
  67. package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts.map +1 -1
  68. package/dist/components/hx-overflow-menu/hx-overflow-menu.styles.d.ts.map +1 -1
  69. package/dist/components/hx-overflow-menu/index.js +1 -1
  70. package/dist/components/hx-phi-field/hx-phi-field.d.ts.map +1 -1
  71. package/dist/components/hx-phi-field/hx-phi-field.styles.d.ts.map +1 -1
  72. package/dist/components/hx-phi-field/index.js +1 -1
  73. package/dist/components/hx-radio-group/hx-radio-group.d.ts.map +1 -1
  74. package/dist/components/hx-radio-group/index.js +1 -1
  75. package/dist/components/hx-rating/hx-rating.d.ts.map +1 -1
  76. package/dist/components/hx-rating/hx-rating.styles.d.ts.map +1 -1
  77. package/dist/components/hx-rating/index.js +1 -1
  78. package/dist/components/hx-side-nav/hx-nav-item.d.ts.map +1 -1
  79. package/dist/components/hx-side-nav/hx-nav-item.styles.d.ts.map +1 -1
  80. package/dist/components/hx-side-nav/hx-side-nav.d.ts.map +1 -1
  81. package/dist/components/hx-side-nav/hx-side-nav.styles.d.ts.map +1 -1
  82. package/dist/components/hx-side-nav/index.js +1 -1
  83. package/dist/components/hx-slider/hx-slider.d.ts +28 -0
  84. package/dist/components/hx-slider/hx-slider.d.ts.map +1 -1
  85. package/dist/components/hx-slider/index.js +1 -1
  86. package/dist/components/hx-split-button/hx-split-button.d.ts.map +1 -1
  87. package/dist/components/hx-split-button/hx-split-button.styles.d.ts.map +1 -1
  88. package/dist/components/hx-split-button/index.js +1 -1
  89. package/dist/components/hx-stat/hx-stat.d.ts.map +1 -1
  90. package/dist/components/hx-stat/hx-stat.styles.d.ts.map +1 -1
  91. package/dist/components/hx-stat/index.js +1 -1
  92. package/dist/components/hx-steps/hx-step.d.ts.map +1 -1
  93. package/dist/components/hx-steps/hx-step.styles.d.ts.map +1 -1
  94. package/dist/components/hx-steps/index.js +1 -1
  95. package/dist/components/hx-tag/hx-tag.d.ts.map +1 -1
  96. package/dist/components/hx-tag/hx-tag.styles.d.ts.map +1 -1
  97. package/dist/components/hx-tag/index.js +1 -1
  98. package/dist/components/hx-time-picker/hx-time-picker.d.ts.map +1 -1
  99. package/dist/components/hx-time-picker/hx-time-picker.styles.d.ts.map +1 -1
  100. package/dist/components/hx-time-picker/index.js +1 -1
  101. package/dist/components/hx-toast/hx-toast.d.ts +0 -8
  102. package/dist/components/hx-toast/hx-toast.d.ts.map +1 -1
  103. package/dist/components/hx-toast/hx-toast.styles.d.ts.map +1 -1
  104. package/dist/components/hx-toast/index.js +1 -1
  105. package/dist/components/hx-top-nav/hx-top-nav.d.ts.map +1 -1
  106. package/dist/components/hx-top-nav/hx-top-nav.styles.d.ts.map +1 -1
  107. package/dist/components/hx-top-nav/index.js +1 -1
  108. package/dist/components/hx-tree-view/hx-tree-item.d.ts.map +1 -1
  109. package/dist/components/hx-tree-view/hx-tree-item.styles.d.ts.map +1 -1
  110. package/dist/components/hx-tree-view/index.js +1 -1
  111. package/dist/css/helix-all.css +116 -54
  112. package/dist/css/helix-core.css +19 -4
  113. package/dist/css/helix-feedback.css +15 -18
  114. package/dist/css/helix-forms.css +39 -12
  115. package/dist/css/helix-media.css +6 -3
  116. package/dist/css/helix-navigation.css +16 -7
  117. package/dist/css/helix-overlay.css +10 -0
  118. package/dist/css/helix-tokens.css +3 -2
  119. package/dist/css/helix-utility.css +5 -0
  120. package/dist/css/hx-alert.css +4 -8
  121. package/dist/css/hx-avatar.css +1 -2
  122. package/dist/css/hx-badge.css +5 -0
  123. package/dist/css/hx-banner.css +4 -8
  124. package/dist/css/hx-carousel.css +6 -3
  125. package/dist/css/hx-checkbox.css +4 -9
  126. package/dist/css/hx-clinical-status.css +4 -7
  127. package/dist/css/hx-combobox.css +8 -0
  128. package/dist/css/hx-date-picker.css +5 -0
  129. package/dist/css/hx-drawer.css +5 -0
  130. package/dist/css/hx-dropdown.css +5 -0
  131. package/dist/css/hx-file-upload.css +4 -0
  132. package/dist/css/hx-help-text.css +5 -0
  133. package/dist/css/hx-icon.css +7 -0
  134. package/dist/css/hx-link.css +1 -2
  135. package/dist/css/hx-nav.css +7 -0
  136. package/dist/css/hx-number-input.css +2 -3
  137. package/dist/css/hx-overflow-menu.css +5 -0
  138. package/dist/css/hx-phi-field.css +2 -3
  139. package/dist/css/hx-rating.css +6 -0
  140. package/dist/css/hx-side-nav.css +3 -5
  141. package/dist/css/hx-split-button.css +5 -0
  142. package/dist/css/hx-stat.css +1 -2
  143. package/dist/css/hx-tag.css +5 -0
  144. package/dist/css/hx-time-picker.css +5 -0
  145. package/dist/css/hx-toast.css +6 -0
  146. package/dist/css/hx-top-nav.css +1 -2
  147. package/dist/css/index.css +1 -1
  148. package/dist/css/manifest.json +4 -1
  149. package/dist/index.js +33 -33
  150. package/dist/shared/{hx-accordion-ZVzgDzTG.js → hx-accordion-DR--Ev4t.js} +48 -54
  151. package/dist/shared/hx-accordion-DR--Ev4t.js.map +1 -0
  152. package/dist/shared/{hx-alert-Bto8-TIi.js → hx-alert-C0axS32J.js} +40 -79
  153. package/dist/shared/hx-alert-C0axS32J.js.map +1 -0
  154. package/dist/shared/{hx-avatar-C9hOmlAb.js → hx-avatar-ChAYWnK8.js} +22 -24
  155. package/dist/shared/hx-avatar-ChAYWnK8.js.map +1 -0
  156. package/dist/shared/{hx-badge-DFL35nzi.js → hx-badge-vX-1cuLA.js} +16 -11
  157. package/dist/shared/hx-badge-vX-1cuLA.js.map +1 -0
  158. package/dist/shared/{hx-banner-fpRnciIO.js → hx-banner-PbHwFNSb.js} +51 -90
  159. package/dist/shared/hx-banner-PbHwFNSb.js.map +1 -0
  160. package/dist/shared/{hx-carousel-item-z1Lc24op.js → hx-carousel-item-BVIKgQ4i.js} +72 -102
  161. package/dist/shared/hx-carousel-item-BVIKgQ4i.js.map +1 -0
  162. package/dist/shared/{hx-checkbox-DcgyGS9V.js → hx-checkbox-DDSXXhps.js} +31 -38
  163. package/dist/shared/hx-checkbox-DDSXXhps.js.map +1 -0
  164. package/dist/shared/{hx-clinical-status-D3XQIOqX.js → hx-clinical-status-ZSVEc3Qg.js} +68 -87
  165. package/dist/shared/hx-clinical-status-ZSVEc3Qg.js.map +1 -0
  166. package/dist/shared/{hx-combobox-NgJaLbs2.js → hx-combobox-Be-mqOv4.js} +35 -45
  167. package/dist/shared/hx-combobox-Be-mqOv4.js.map +1 -0
  168. package/dist/shared/{hx-date-picker-0PtEav0K.js → hx-date-picker-CziP3Hm1.js} +15 -22
  169. package/dist/shared/hx-date-picker-CziP3Hm1.js.map +1 -0
  170. package/dist/shared/{hx-drawer-CM_upadk.js → hx-drawer-BlU2oX8-.js} +32 -36
  171. package/dist/shared/hx-drawer-BlU2oX8-.js.map +1 -0
  172. package/dist/shared/{hx-dropdown-xHwTJecv.js → hx-dropdown-DREqpIpm.js} +16 -11
  173. package/dist/shared/hx-dropdown-DREqpIpm.js.map +1 -0
  174. package/dist/shared/{hx-file-upload-D3rKROK5.js → hx-file-upload-CU5QGZSP.js} +137 -80
  175. package/dist/shared/hx-file-upload-CU5QGZSP.js.map +1 -0
  176. package/dist/shared/hx-help-text-CNaZ82LT.js +137 -0
  177. package/dist/shared/hx-help-text-CNaZ82LT.js.map +1 -0
  178. package/dist/shared/hx-icon-bxz9eB9a.js +386 -0
  179. package/dist/shared/hx-icon-bxz9eB9a.js.map +1 -0
  180. package/dist/shared/{hx-link-CMnZRUtQ.js → hx-link-BURSdYLp.js} +19 -26
  181. package/dist/shared/hx-link-BURSdYLp.js.map +1 -0
  182. package/dist/shared/{hx-menu-divider-A6Guuzi_.js → hx-menu-divider-g0grbWV9.js} +19 -31
  183. package/dist/shared/hx-menu-divider-g0grbWV9.js.map +1 -0
  184. package/dist/shared/{hx-nav-ChMTfn7o.js → hx-nav-GTsAZGOx.js} +46 -59
  185. package/dist/shared/hx-nav-GTsAZGOx.js.map +1 -0
  186. package/dist/shared/{hx-nav-item-ClN17f1y.js → hx-nav-item-CxE7Mp3M.js} +62 -64
  187. package/dist/shared/hx-nav-item-CxE7Mp3M.js.map +1 -0
  188. package/dist/shared/{hx-number-input-MggsT7F0.js → hx-number-input-Bvyc9kOi.js} +48 -53
  189. package/dist/shared/hx-number-input-Bvyc9kOi.js.map +1 -0
  190. package/dist/shared/{hx-overflow-menu-DFjJAziP.js → hx-overflow-menu-LrTteeR1.js} +32 -39
  191. package/dist/shared/hx-overflow-menu-LrTteeR1.js.map +1 -0
  192. package/dist/shared/{hx-phi-field-C19oxlrr.js → hx-phi-field-sZt_rYIL.js} +46 -66
  193. package/dist/shared/hx-phi-field-sZt_rYIL.js.map +1 -0
  194. package/dist/shared/{hx-radio-BY4zpwdh.js → hx-radio-BD_c9NJy.js} +51 -56
  195. package/dist/shared/{hx-radio-BY4zpwdh.js.map → hx-radio-BD_c9NJy.js.map} +1 -1
  196. package/dist/shared/{hx-rating-C3QP53k9.js → hx-rating-BGK4AxvI.js} +45 -71
  197. package/dist/shared/hx-rating-BGK4AxvI.js.map +1 -0
  198. package/dist/shared/{hx-slider-Blmv_rwS.js → hx-slider-CkOk5BCY.js} +83 -23
  199. package/dist/shared/{hx-slider-Blmv_rwS.js.map → hx-slider-CkOk5BCY.js.map} +1 -1
  200. package/dist/shared/{hx-split-button-CdNz1XAu.js → hx-split-button-Bg9FHrFK.js} +12 -16
  201. package/dist/shared/hx-split-button-Bg9FHrFK.js.map +1 -0
  202. package/dist/shared/{hx-stat-Gtw_SpK8.js → hx-stat-wKxbyep6.js} +22 -55
  203. package/dist/shared/hx-stat-wKxbyep6.js.map +1 -0
  204. package/dist/shared/{hx-step-CUzliIK_.js → hx-step-CyGQAuiB.js} +5 -25
  205. package/dist/shared/hx-step-CyGQAuiB.js.map +1 -0
  206. package/dist/shared/{hx-tag-C5aCUpVi.js → hx-tag-BqO6HY6V.js} +26 -21
  207. package/dist/shared/hx-tag-BqO6HY6V.js.map +1 -0
  208. package/dist/shared/{hx-time-picker-DfJkBwcX.js → hx-time-picker-if5Cl0Ei.js} +32 -38
  209. package/dist/shared/hx-time-picker-if5Cl0Ei.js.map +1 -0
  210. package/dist/shared/{hx-top-nav-CsTxOtVI.js → hx-top-nav-vP6oDWMV.js} +24 -38
  211. package/dist/shared/hx-top-nav-vP6oDWMV.js.map +1 -0
  212. package/dist/shared/{hx-tree-item-CXyspGxI.js → hx-tree-item-D8hwKd5m.js} +54 -57
  213. package/dist/shared/hx-tree-item-D8hwKd5m.js.map +1 -0
  214. package/dist/shared/{toast-factory-Dht3pVsw.js → toast-factory-DgnbFxVs.js} +127 -153
  215. package/dist/shared/toast-factory-DgnbFxVs.js.map +1 -0
  216. package/figma-inventory.json +283 -304
  217. package/package.json +8 -4
  218. package/dist/shared/hx-accordion-ZVzgDzTG.js.map +0 -1
  219. package/dist/shared/hx-alert-Bto8-TIi.js.map +0 -1
  220. package/dist/shared/hx-avatar-C9hOmlAb.js.map +0 -1
  221. package/dist/shared/hx-badge-DFL35nzi.js.map +0 -1
  222. package/dist/shared/hx-banner-fpRnciIO.js.map +0 -1
  223. package/dist/shared/hx-carousel-item-z1Lc24op.js.map +0 -1
  224. package/dist/shared/hx-checkbox-DcgyGS9V.js.map +0 -1
  225. package/dist/shared/hx-clinical-status-D3XQIOqX.js.map +0 -1
  226. package/dist/shared/hx-combobox-NgJaLbs2.js.map +0 -1
  227. package/dist/shared/hx-date-picker-0PtEav0K.js.map +0 -1
  228. package/dist/shared/hx-drawer-CM_upadk.js.map +0 -1
  229. package/dist/shared/hx-dropdown-xHwTJecv.js.map +0 -1
  230. package/dist/shared/hx-file-upload-D3rKROK5.js.map +0 -1
  231. package/dist/shared/hx-help-text-Xb2Yr8x2.js +0 -156
  232. package/dist/shared/hx-help-text-Xb2Yr8x2.js.map +0 -1
  233. package/dist/shared/hx-icon-fuVm4-bk.js +0 -283
  234. package/dist/shared/hx-icon-fuVm4-bk.js.map +0 -1
  235. package/dist/shared/hx-link-CMnZRUtQ.js.map +0 -1
  236. package/dist/shared/hx-menu-divider-A6Guuzi_.js.map +0 -1
  237. package/dist/shared/hx-nav-ChMTfn7o.js.map +0 -1
  238. package/dist/shared/hx-nav-item-ClN17f1y.js.map +0 -1
  239. package/dist/shared/hx-number-input-MggsT7F0.js.map +0 -1
  240. package/dist/shared/hx-overflow-menu-DFjJAziP.js.map +0 -1
  241. package/dist/shared/hx-phi-field-C19oxlrr.js.map +0 -1
  242. package/dist/shared/hx-rating-C3QP53k9.js.map +0 -1
  243. package/dist/shared/hx-split-button-CdNz1XAu.js.map +0 -1
  244. package/dist/shared/hx-stat-Gtw_SpK8.js.map +0 -1
  245. package/dist/shared/hx-step-CUzliIK_.js.map +0 -1
  246. package/dist/shared/hx-tag-C5aCUpVi.js.map +0 -1
  247. package/dist/shared/hx-time-picker-DfJkBwcX.js.map +0 -1
  248. package/dist/shared/hx-top-nav-CsTxOtVI.js.map +0 -1
  249. package/dist/shared/hx-tree-item-CXyspGxI.js.map +0 -1
  250. package/dist/shared/toast-factory-Dht3pVsw.js.map +0 -1
@@ -353,6 +353,11 @@ const N = _`
353
353
  margin-inline-start: auto;
354
354
  }
355
355
 
356
+ /* hx-icon glyph sizing for migrated checked / submenu indicators (1em parity). */
357
+ .menu-item__glyph {
358
+ --hx-icon-size: 1em;
359
+ }
360
+
356
361
  .menu-item__spinner {
357
362
  width: 1em;
358
363
  height: 1em;
@@ -415,10 +420,10 @@ const N = _`
415
420
  }
416
421
  }
417
422
  `;
418
- var j = Object.defineProperty, K = Object.getOwnPropertyDescriptor, h = (e, t, s, n) => {
419
- for (var i = n > 1 ? void 0 : n ? K(t, s) : t, r = e.length - 1, a; r >= 0; r--)
423
+ var K = Object.defineProperty, j = Object.getOwnPropertyDescriptor, h = (e, t, s, n) => {
424
+ for (var i = n > 1 ? void 0 : n ? j(t, s) : t, r = e.length - 1, a; r >= 0; r--)
420
425
  (a = e[r]) && (i = (n ? a(t, s, i) : a(i)) || i);
421
- return n && i && j(t, s, i), i;
426
+ return n && i && K(t, s, i), i;
422
427
  };
423
428
  let l = class extends I {
424
429
  constructor() {
@@ -598,18 +603,7 @@ let l = class extends I {
598
603
  _renderCheckedIcon() {
599
604
  return u`
600
605
  <span part="checked-icon" class="menu-item__checked-icon" aria-hidden="true">
601
- <svg
602
- width="1em"
603
- height="1em"
604
- viewBox="0 0 24 24"
605
- fill="none"
606
- stroke="currentColor"
607
- stroke-width="3"
608
- stroke-linecap="round"
609
- stroke-linejoin="round"
610
- >
611
- <polyline points="20 6 9 17 4 12" />
612
- </svg>
606
+ <hx-icon class="menu-item__glyph" library="helix" name="check" aria-hidden="true"></hx-icon>
613
607
  </span>
614
608
  `;
615
609
  }
@@ -617,18 +611,12 @@ let l = class extends I {
617
611
  _renderSubmenuIcon() {
618
612
  return u`
619
613
  <span part="submenu-icon" class="menu-item__submenu-icon" aria-hidden="true">
620
- <svg
621
- width="1em"
622
- height="1em"
623
- viewBox="0 0 24 24"
624
- fill="none"
625
- stroke="currentColor"
626
- stroke-width="2"
627
- stroke-linecap="round"
628
- stroke-linejoin="round"
629
- >
630
- <polyline points="9 18 15 12 9 6" />
631
- </svg>
614
+ <hx-icon
615
+ class="menu-item__glyph"
616
+ library="helix"
617
+ name="chevron-right"
618
+ aria-hidden="true"
619
+ ></hx-icon>
632
620
  </span>
633
621
  `;
634
622
  }
@@ -762,8 +750,8 @@ const q = _`
762
750
  }
763
751
  }
764
752
  `;
765
- var P = Object.getOwnPropertyDescriptor, U = (e, t, s, n) => {
766
- for (var i = n > 1 ? void 0 : n ? P(t, s) : t, r = e.length - 1, a; r >= 0; r--)
753
+ var z = Object.getOwnPropertyDescriptor, P = (e, t, s, n) => {
754
+ for (var i = n > 1 ? void 0 : n ? z(t, s) : t, r = e.length - 1, a; r >= 0; r--)
767
755
  (a = e[r]) && (i = a(i) || i);
768
756
  return i;
769
757
  };
@@ -786,7 +774,7 @@ let b = class extends I {
786
774
  }
787
775
  };
788
776
  b.styles = [q, g];
789
- b = U([
777
+ b = P([
790
778
  v("hx-menu-divider")
791
779
  ], b);
792
780
  export {
@@ -794,4 +782,4 @@ export {
794
782
  b as a,
795
783
  l as b
796
784
  };
797
- //# sourceMappingURL=hx-menu-divider-A6Guuzi_.js.map
785
+ //# sourceMappingURL=hx-menu-divider-g0grbWV9.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hx-menu-divider-g0grbWV9.js","sources":["../../src/components/hx-menu/hx-menu.styles.ts","../../src/components/hx-menu/hx-menu.ts","../../src/components/hx-menu/hx-menu-item.styles.ts","../../src/components/hx-menu/hx-menu-item.ts","../../src/components/hx-menu/hx-menu-divider.styles.ts","../../src/components/hx-menu/hx-menu-divider.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixMenuStyles = css`\n :host {\n display: block;\n }\n\n .menu {\n display: flex;\n flex-direction: column;\n padding: var(--hx-space-1, 0.25rem);\n background: var(--hx-menu-bg, var(--hx-color-surface-default, #ffffff));\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-menu-border-color, var(--hx-color-border-default, #d6dbd5));\n border-radius: var(--hx-menu-border-radius, var(--hx-border-radius-md, 0.375rem));\n box-shadow: var(\n --hx-menu-shadow,\n var(--hx-shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1))\n );\n min-width: var(--hx-menu-min-width, 10rem);\n max-height: var(--hx-menu-max-height, 20rem);\n overflow-y: auto;\n outline: none;\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .menu {\n background-color: Canvas;\n border: 2px solid CanvasText;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { helixMenuStyles } from './hx-menu.styles.js';\nimport type { HelixMenuItem } from './hx-menu-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 { getMenuItemTypeaheadLabel } from '../../utils/menu-label.js';\nimport {\n findClosestMenuAncestor as findClosestMenuAncestorElement,\n findOwningMenuItem as findOwningMenuItemElement,\n} from '../../utils/menu-tree.js';\n\n/**\n * Typed wrapper around the shared `findClosestMenuAncestor` walker that\n * narrows the result to `HelixMenu` for in-file consumers. Codex push-gate\n * round-4 (logic) + round-9 (extraction).\n * @internal\n */\nfunction findClosestMenuAncestor(start: Element): HelixMenu | null {\n const found = findClosestMenuAncestorElement(start);\n return found instanceof Element && found.tagName.toLowerCase() === 'hx-menu'\n ? (found as HelixMenu)\n : null;\n}\n\n/**\n * Typed wrapper around the shared `findOwningMenuItem` walker. Codex\n * push-gate round-4 (logic) + round-9 (extraction).\n * @internal\n */\nfunction findOwningMenuItem(menu: HelixMenu): HelixMenuItem | null {\n const found = findOwningMenuItemElement(menu);\n return found instanceof Element && found.tagName.toLowerCase() === 'hx-menu-item'\n ? (found as HelixMenuItem)\n : null;\n}\n\n/**\n * A menu container that manages keyboard navigation over a list of menu items.\n * Use with `hx-menu-item` and `hx-menu-divider`.\n *\n * Group 5b host-canonical: `role=\"menu\"` lives on the **host** via\n * `_internals.role`. The host carries the announced surface so AT walks\n * `<hx-menu>` (role=menu) → slotted `<hx-menu-item>` (role=menuitem on host)\n * directly without two layers of indirection. Consumer-supplied\n * `aria-label` / `aria-labelledby` on the host are resolved via the shared\n * IDREF mirror; cross-shadow naming uses `ariaLabelledByElements` (modern)\n * with a flattened-string fallback (legacy).\n *\n * Submenu coordination: when an `hx-menu-item` emits `hx-item-submenu-open`\n * or `hx-item-submenu-close`, the parent menu auto-handles the toggle by\n * calling `setSubmenuOpen()` on the item — UNLESS the consumer has called\n * `event.preventDefault()` on the bubbled event, signaling that they own the\n * submenu lifecycle. This matches APG-mandated behaviour while leaving an\n * opt-out for advanced consumers.\n *\n * @summary Context/action menu with keyboard-navigable items.\n *\n * @tag hx-menu\n *\n * @slot - Default slot for hx-menu-item and hx-menu-divider elements.\n *\n * @fires {CustomEvent<{item: HelixMenuItem, value: string}>} hx-select - Dispatched when an item is selected.\n * @fires {CustomEvent<void>} hx-close - Dispatched when Escape is pressed.\n *\n * @csspart base - The root menu element.\n *\n * @cssprop [--hx-menu-bg=var(--hx-color-neutral-0)] - Menu background color.\n * @cssprop [--hx-menu-border-color=var(--hx-color-neutral-200)] - Menu border color.\n * @cssprop [--hx-menu-border-radius=var(--hx-border-radius-md)] - Menu border radius.\n * @cssprop [--hx-menu-shadow] - Menu box shadow.\n * @cssprop [--hx-menu-min-width=10rem] - Minimum menu width.\n * @cssprop [--hx-menu-max-height=20rem] - Maximum menu height before vertical scroll is activated.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-shadow-md] - Box shadow.\n * @aaa-certified 2026-05-08\n * @aaa-criteria 1.4.6, 1.4.9, 2.1.3, 2.3.3, 2.4.12, 2.4.13, 2.5.5, 3.2.5, 3.3.6, forced-colors, apg-keyboard\n * @aaa-audit src/components/hx-menu/AAA-AUDIT.md\n * @keyboard-contract navigate=Arrow,Home,End; activate=Enter,Space; dismiss=Escape; disabled-suppresses=true\n * @aria-pattern menu\n * @aria-pattern-source https://www.w3.org/WAI/ARIA/apg/patterns/menubar/\n * @forced-colors-supported true\n * @stability stable\n * @since 3.7.0\n * @form-associated false\n * @theme-aware true\n * @brand-aware true\n * @drupal-sdc-eligible true\n * @react-wrapper-status complete\n * @figma-component-name hx-menu\n * @priority-tier P0\n * @phi-handles false\n * @clinical-context none\n */\n@customElement('hx-menu')\nexport class HelixMenu extends HelixElement {\n static override styles = [helixMenuStyles, forcedColorsInteractive];\n\n /**\n * Accessible label for the menu. Used as a fallback when no consumer-supplied\n * `aria-label` / `aria-labelledby` is present on the host. On the modern\n * host-canonical path this projects onto `internals.ariaLabel`; on the\n * legacy fallback path it appears as `aria-label` on the inner div.\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = '';\n\n /**\n * Index of the currently focused menu item within the list of enabled items.\n * @internal\n */\n private _focusedIndex = -1;\n\n /**\n * Accumulated character buffer for typeahead search within menu items.\n * @internal\n */\n private _typeaheadBuffer = '';\n\n /**\n * Timer handle that clears the typeahead buffer after a period of inactivity.\n * @internal\n */\n private _typeaheadTimer: ReturnType<typeof setTimeout> | null = null;\n\n // ─── Host-canonical ARIA bookkeeping ───\n\n /**\n * Test seam (codex push-gate round-2 finding 1): when set to `true` or\n * `false`, overrides the platform `supportsIdrefElementReferences` probe\n * before `connectedCallback` seeds `_supportsIdrefRefs`. Mirrors the\n * hx-select / hx-menu-item seam — required so tests can deterministically\n * exercise the legacy fallback render branch (where the inner\n * `div[role=\"menu\"]` is the announced surface and must mirror the\n * resolved accessible name).\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 menu — the single source of truth that\n * both `_syncHostAriaSemantics()` (modern path: writes to\n * `internals.ariaLabel`) and the fallback `render()` branch (legacy path:\n * writes to inner `div[role=\"menu\"]` `aria-label`) read. Recomputed by\n * `_syncHostAriaSemantics()` whenever host aria-* or `label` changes via\n * the shared IDREF mirror. AccName 1.2 §4.3.1 precedence: consumer host\n * `aria-labelledby` (flattened) > consumer host `aria-label` > `label`\n * property > literal \"Menu\".\n * @internal\n */\n private _resolvedAccessibleName = '';\n\n /**\n * Return the menu's enabled, top-level `hx-menu-item` children.\n *\n * Codex push-gate round-6 finding 3: `querySelectorAll('hx-menu-item')`\n * walks the entire descendant tree, which on a parent menuitem\n * includes the slotted nested `<hx-menu>` and ITS items. Treating\n * those as top-level options corrupts roving tabindex, ArrowUp/Down\n * navigation, and typeahead matching (typing the first letter of a\n * grandchild item lands focus there instead of on the next sibling).\n * Restrict to direct children of `this` so each menu owns only its\n * own items.\n *\n * @internal\n */\n private _getItems(): HelixMenuItem[] {\n return Array.from(this.children).filter(\n (el): el is HelixMenuItem =>\n el.tagName.toLowerCase() === 'hx-menu-item' &&\n !(el as HelixMenuItem).disabled &&\n !(el as HelixMenuItem).loading,\n );\n }\n\n /**\n * Synchronize roving tabindex across all enabled items.\n * Only the active item (or first item if none active) gets tabindex=0.\n */\n /** @internal */\n private _syncRovingTabIndex(): void {\n const items = this._getItems();\n const activeIndex = this._focusedIndex >= 0 ? this._focusedIndex : 0;\n items.forEach((item, i) => {\n item.setRovingTabIndex(i === activeIndex ? 0 : -1);\n });\n }\n\n /** Focus the first menu item. */\n focusFirst(): void {\n const items = this._getItems();\n const first = items[0];\n if (first !== undefined) {\n this._focusedIndex = 0;\n this._syncRovingTabIndex();\n first.focus();\n }\n }\n\n /** Focus the last menu item. */\n focusLast(): void {\n const items = this._getItems();\n const last = items[items.length - 1];\n if (last !== undefined) {\n this._focusedIndex = items.length - 1;\n this._syncRovingTabIndex();\n last.focus();\n }\n }\n\n /** @internal */\n private _focusItem(index: number): void {\n const items = this._getItems();\n if (items.length === 0) return;\n this._focusedIndex = Math.max(0, Math.min(index, items.length - 1));\n this._syncRovingTabIndex();\n const target = items[this._focusedIndex];\n if (target !== undefined) target.focus();\n }\n\n /** @internal */\n private _updateFocusedIndex(): void {\n const items = this._getItems();\n const active = this.shadowRoot?.activeElement ?? document.activeElement;\n // Find the active item by checking if any item's shadow root contains the active element\n const idx = items.findIndex((item) => item.matches(':focus-within') || item === active);\n if (idx !== -1) this._focusedIndex = idx;\n }\n\n /** @internal */\n private _handleKeyDown(e: KeyboardEvent): void {\n this._updateFocusedIndex();\n const items = this._getItems();\n if (items.length === 0) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n this._focusItem(this._focusedIndex + 1 < items.length ? this._focusedIndex + 1 : 0);\n break;\n case 'ArrowUp':\n e.preventDefault();\n this._focusItem(this._focusedIndex > 0 ? this._focusedIndex - 1 : items.length - 1);\n break;\n case 'Home':\n e.preventDefault();\n this._focusItem(0);\n break;\n case 'End':\n e.preventDefault();\n this._focusItem(items.length - 1);\n break;\n case 'Escape':\n e.preventDefault();\n this.dispatchEvent(new CustomEvent<void>('hx-close', { bubbles: true, composed: true }));\n break;\n default:\n if (e.key.length === 1 && e.key !== ' ' && !e.ctrlKey && !e.metaKey && !e.altKey) {\n this._handleTypeahead(e.key, items);\n }\n break;\n }\n }\n\n /** @internal */\n private _handleTypeahead(char: string, items: HelixMenuItem[]): void {\n if (this._typeaheadTimer !== null) {\n clearTimeout(this._typeaheadTimer);\n }\n this._typeaheadBuffer += char.toLowerCase();\n this._typeaheadTimer = setTimeout(() => {\n this._typeaheadBuffer = '';\n this._typeaheadTimer = null;\n }, 500);\n\n const match = items.findIndex((item) => {\n if (item.disabled || item.hasAttribute('disabled')) return false;\n const text = this._getTypeaheadLabel(item).toLowerCase();\n return text.startsWith(this._typeaheadBuffer);\n });\n\n if (match !== -1) {\n this._focusItem(match);\n }\n }\n\n /**\n * Read the typeahead label for an item — delegates to the shared\n * `getMenuItemTypeaheadLabel` util so all four menu-bearing components\n * (`hx-menu`, `hx-dropdown`, `hx-overflow-menu`, `hx-split-button`)\n * share one submenu-aware extractor. Codex push-gate round-7 finding 3\n * extracted this helper from its original home here in `hx-menu.ts`.\n *\n * @internal\n */\n private _getTypeaheadLabel(item: HelixMenuItem): string {\n return getMenuItemTypeaheadLabel(item);\n }\n\n /** @internal */\n private _handleSlotChange(e: Event): void {\n const slot = e.target;\n if (!(slot instanceof HTMLSlotElement)) return;\n const validTags = new Set(['hx-menu-item', 'hx-menu-divider']);\n const invalid = slot\n .assignedElements()\n .filter((el) => !validTags.has(el.tagName.toLowerCase()));\n if (invalid.length > 0) {\n devWarn(\n 'hx-menu',\n `Default slot expects <hx-menu-item> or <hx-menu-divider> elements. Found unexpected: ${invalid.map((el) => `<${el.tagName.toLowerCase()}>`).join(', ')}`,\n );\n }\n // Initialize roving tabindex when items are slotted\n this._syncRovingTabIndex();\n }\n\n /** @internal */\n private _handleItemSelect(e: Event): void {\n if (!(e instanceof CustomEvent)) return;\n const detail = (e as CustomEvent<{ item: HelixMenuItem; value: string }>).detail;\n const items = this._getItems();\n this._focusedIndex = items.indexOf(detail.item);\n\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem; value: string }>('hx-select', {\n bubbles: true,\n composed: true,\n detail: { item: detail.item, value: detail.value },\n }),\n );\n }\n\n /**\n * Auto-handle submenu open/close events emitted by child `hx-menu-item`\n * children. APG-mandated behaviour: ArrowRight on a parent item opens the\n * nested submenu and focuses its first item; ArrowLeft closes the submenu\n * and returns focus to the parent item. Consumers that own submenu\n * lifecycle themselves can `event.preventDefault()` to opt out.\n * @internal\n */\n private _handleSubmenuOpen = (e: Event): void => {\n if (!(e instanceof CustomEvent)) return;\n const detail = (e as CustomEvent<{ item: HelixMenuItem }>).detail;\n const item = detail?.item;\n if (!item) return;\n // Defer to a microtask so consumer listeners (which may be registered\n // AFTER the menu's auto-handler in event order) get a chance to call\n // `event.preventDefault()` and opt out of default submenu lifecycle\n // handling. APG-mandated default: open the nested submenu and focus\n // its first item; consumers that own this themselves cancel the\n // default by calling preventDefault on the event.\n queueMicrotask(() => {\n if (e.defaultPrevented) return;\n item.setSubmenuOpen(true);\n void item.updateComplete\n .then(() => {\n const submenuSlot =\n item.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"submenu\"]');\n const nested = submenuSlot\n ?.assignedElements({ flatten: true })\n .find((el) => el.tagName.toLowerCase() === 'hx-menu') as HelixMenu | undefined;\n nested?.focusFirst();\n })\n .catch(() => undefined);\n });\n };\n\n /** @internal */\n private _handleSubmenuClose = (e: Event): void => {\n if (!(e instanceof CustomEvent)) return;\n const detail = (e as CustomEvent<{ item: HelixMenuItem }>).detail;\n const item = detail?.item;\n if (!item) return;\n // The bubbled event reaches every enclosing `hx-menu` — outer menus\n // would otherwise re-handle a Child's ArrowLeft and stomp on the inner\n // menu's close. Only act when THIS menu is the closest enclosing menu\n // of the dispatching item; outer menus defer to whichever inner menu\n // is responsible. Codex push-gate round-4 P1: previously the outer\n // menu handled the event and called `child.setSubmenuOpen(false)` —\n // a no-op since the child has no submenu — leaving the parent's\n // submenu open and focus stuck on the child.\n const closestMenu = findClosestMenuAncestor(item);\n if (closestMenu !== this) return;\n // Determine which menu-item owns the submenu we should close. When\n // THIS menu is itself slotted into a parent menu-item's `slot=\"submenu\"`\n // (i.e. THIS is a nested submenu), the parent item is the owner —\n // ArrowLeft from any descendant closes the parent's submenu and\n // returns focus to the parent. When THIS menu has no parent menu-item\n // (top-level menu), the dispatching item itself is the only sensible\n // target: a no-op for plain items, a self-close for items with their\n // own submenu open.\n const ownerItem = findOwningMenuItem(this) ?? item;\n queueMicrotask(() => {\n if (e.defaultPrevented) return;\n ownerItem.setSubmenuOpen(false);\n ownerItem.focus();\n });\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=\"menu\"]` carries the\n // resolved accessible name without a mid-life flag flip.\n const ctor = this.constructor as typeof HelixMenu;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n // Keydown is bound on the HOST so events from focused host-canonical\n // menu items (which keep keydown out of this menu's shadow DOM)\n // still reach the navigation handler. hx-item-select bubbles\n // through the composed path and is caught here as well.\n this.addEventListener('keydown', this._handleHostKeyDown);\n this.addEventListener('hx-item-select', this._handleItemSelectHost);\n this.addEventListener('hx-item-submenu-open', this._handleSubmenuOpen);\n this.addEventListener('hx-item-submenu-close', this._handleSubmenuClose);\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 if (this._typeaheadTimer !== null) {\n clearTimeout(this._typeaheadTimer);\n this._typeaheadTimer = null;\n }\n this.removeEventListener('keydown', this._handleHostKeyDown);\n this.removeEventListener('hx-item-select', this._handleItemSelectHost);\n this.removeEventListener('hx-item-submenu-open', this._handleSubmenuOpen);\n this.removeEventListener('hx-item-submenu-close', this._handleSubmenuClose);\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n }\n\n /**\n * Codex push-gate round-7 finding 1: keydown bound on the HOST receives\n * events that bubble out of nested submenus. When a child submenu is\n * open and focus lives inside it, ArrowUp/Down/Home/End/Escape on the\n * inner item bubbles to EVERY enclosing `hx-menu`. Without this guard\n * the outer menu would run `_focusItem(...)` against its OWN top-level\n * items and steal focus back out of the child submenu, and Escape would\n * dispatch one `hx-close` per enclosing menu. Mirrors the\n * `findClosestMenuAncestor` pattern already used by the submenu\n * open/close handlers.\n * @internal\n */\n private _handleHostKeyDown = (e: KeyboardEvent): void => {\n const target = e.target;\n if (target instanceof Element && findClosestMenuAncestor(target) !== this) {\n return;\n }\n this._handleKeyDown(e);\n };\n\n /**\n * Codex push-gate round-7 finding 2: `hx-item-select` bubbles composed\n * through every enclosing `hx-menu`. The outer menu would otherwise\n * (a) corrupt `_focusedIndex` to `-1` because the bubbled item is not\n * a member of the outer menu's items, and (b) re-emit a duplicate\n * `hx-select`. Only act when THIS menu is the closest enclosing menu\n * 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<{ item: HelixMenuItem; value: string }>).detail;\n const item = detail?.item;\n if (item && findClosestMenuAncestor(item) !== this) {\n return;\n }\n this._handleItemSelect(e);\n };\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('label')) {\n this._syncHostAriaSemantics();\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-menu',\n 'No accessible label provided. Set the `label` attribute, or supply `aria-label` / `aria-labelledby` on hx-menu so screen readers can identify this menu (WCAG 4.1.2).',\n );\n }\n }\n\n /**\n * Mirror menu 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 * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n\n // Codex push-gate round-8 finding 1 (mirrors round-6 finding 2 in\n // hx-menu-item): on the legacy fallback path the inner\n // `<div role=\"menu\" aria-label=\"…\">` is the announced surface. If we\n // ALSO write `internals.role = 'menu'` (and ariaLabel) onto the host,\n // AT sees TWO menus for one logical surface — the duplicate-surface\n // problem host-canonical migration is meant to eliminate. Suppress\n // host role + label writes on the fallback path; the inner element\n // is the canonical announced surface there. Modern path keeps the\n // host as the canonical surface and clears the inner role.\n if (!this._supportsIdrefRefs) {\n internals.role = null;\n internals.ariaLabel = null;\n } else {\n internals.role = 'menu';\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 \"Menu\" (last-resort).\n // The resolved string is cached on `_resolvedAccessibleName` so the\n // fallback render branch (legacy path: AT reads inner div) can mirror\n // the same name without duplicating the precedence ladder.\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 'Menu';\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 || 'Menu';\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = resolved;\n }\n }\n\n // Codex push-gate round-2 finding 1: keep the resolved name available\n // for the legacy render branch. Request a re-render so the fallback\n // `<div role=\"menu\" aria-label=...>` picks up the new value when host\n // aria-* changes after first paint.\n if (this._resolvedAccessibleName !== resolved) {\n this._resolvedAccessibleName = resolved;\n if (!this._supportsIdrefRefs) {\n this.requestUpdate();\n }\n }\n }\n\n override render() {\n // Host-canonical Path A: `role=\"menu\"` and the resolved label live on\n // the host via `_internals`. The inner div is roleless on the modern\n // path so AT does not see a duplicated container role nested inside\n // the host. Legacy fallback keeps the inner role + aria-label so AT\n // without IDL element references still announces the menu.\n // Keydown + hx-item-select listeners are bound on the host in\n // connectedCallback() — keydown does not propagate INTO this menu's\n // shadow DOM, so events from focused host-canonical menu items\n // would never fire on inner-div bindings. hx-item-select bubbles\n // composed through the host either way; we listen on the host for\n // symmetry.\n if (this._supportsIdrefRefs) {\n return html`\n <div part=\"base\" class=\"menu\">\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n\n // Codex push-gate round-2 finding 1: AT on the fallback path announces\n // the inner div, so it MUST mirror the same accessible name resolved\n // by `_syncHostAriaSemantics()` (consumer host aria-label / aria-\n // labelledby flatten / `label` property). Fall back to `this.label`\n // if the mirror has not run yet (pre-connect render).\n const fallbackLabel = this._resolvedAccessibleName || this.label || nothing;\n return html`\n <div part=\"base\" class=\"menu\" role=\"menu\" aria-label=${fallbackLabel}>\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu': HelixMenu;\n }\n}\n","import { css } from 'lit';\n\nexport const helixMenuItemStyles = css`\n :host {\n display: block;\n /* Host carries the roving tabindex on the modern host-canonical path,\n so it becomes the focusable surface. Strip the default focus outline\n from the host so the inner .menu-item:focus-visible (and the host\n :focus-visible rule below) own the visual treatment. */\n outline: none;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n /* Host is the Tab stop on the modern path; mirror the inner focus-ring\n onto the host so keyboard focus is visible on whichever surface the\n UA paints. The inner-element rule below still applies on the legacy\n fallback path (where the inner div carries the role + tabindex). */\n :host(:focus-visible) .menu-item {\n background-color: var(--hx-menu-item-hover-bg, var(--hx-color-surface-sunken, #ebeee9));\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-menu-item-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-menu-item-focus-ring-offset, 0px);\n }\n\n .menu-item {\n display: flex;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n min-height: var(--hx-touch-target-min, 44px);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n cursor: pointer;\n color: var(--hx-menu-item-color, var(--hx-color-text-primary, #0d1825));\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-family: var(--hx-menu-item-font-family, var(--hx-font-family-sans, sans-serif));\n line-height: var(--hx-line-height-tight, 1.25);\n user-select: none;\n -webkit-user-select: none;\n outline: none;\n background: none;\n width: 100%;\n box-sizing: border-box;\n transition: background-color var(--hx-transition-fast, 150ms ease);\n }\n\n .menu-item:hover,\n .menu-item:focus-visible {\n background-color: var(--hx-menu-item-hover-bg, var(--hx-color-surface-sunken, #ebeee9));\n }\n\n .menu-item:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-menu-item-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-menu-item-focus-ring-offset, 0px);\n }\n\n .menu-item__prefix,\n .menu-item__suffix {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .menu-item__label {\n flex: 1 1 auto;\n }\n\n .menu-item__checked-icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n width: 1em;\n opacity: 0;\n transition: opacity var(--hx-transition-fast, 150ms ease);\n }\n\n .menu-item--checked .menu-item__checked-icon {\n opacity: 1;\n }\n\n .menu-item__submenu-icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n margin-inline-start: auto;\n }\n\n /* hx-icon glyph sizing for migrated checked / submenu indicators (1em parity). */\n .menu-item__glyph {\n --hx-icon-size: 1em;\n }\n\n .menu-item__spinner {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n animation: hx-menu-spin var(--hx-duration-spinner, 750ms) linear infinite;\n }\n\n @keyframes hx-menu-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .menu-item {\n transition: none;\n }\n\n .menu-item__checked-icon {\n transition: none;\n }\n\n .menu-item__spinner {\n animation: none;\n opacity: var(--hx-opacity-muted, 0.6);\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .menu-item {\n forced-color-adjust: none;\n color: CanvasText;\n background-color: Canvas;\n }\n\n .menu-item:hover,\n .menu-item:focus-visible {\n background-color: Highlight;\n color: HighlightText;\n }\n\n .menu-item:focus-visible {\n outline: 2px solid Highlight;\n outline-offset: -2px;\n }\n\n /* Host-canonical focus parity in forced-colors mode. */\n :host(:focus-visible) .menu-item {\n background-color: Highlight;\n color: HighlightText;\n outline: 2px solid Highlight;\n outline-offset: -2px;\n }\n\n :host([disabled]) .menu-item {\n color: GrayText;\n opacity: 1;\n }\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 '../hx-icon/hx-icon.js';\nimport { HelixElement } from '../../base/index.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { helixMenuItemStyles } from './hx-menu-item.styles.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';\n\n/**\n * A single interactive item for use inside `hx-menu`. Supports normal, checkbox,\n * and radio types, loading state, prefix/suffix slots, and submenu nesting.\n *\n * Group 5b host-canonical: `role=\"menuitem\"` (or `menuitemcheckbox` /\n * `menuitemradio` based on `type`) lives on the **host** via\n * `_internals.role`. The roving tabindex is written to the host, so the host\n * is the focusable surface and lands directly under the parent `<hx-menu>`\n * (which carries `role=\"menu\"`) in the AT walked tree. The inner element is\n * presentational on the modern path — no role, no aria-* attributes — and\n * carries only click/keyboard event handlers. Keyboard activation\n * (Enter/Space) is owned by the host's `keydown` handler.\n *\n * Cross-shadow naming: consumer-supplied `aria-label` / `aria-labelledby` on\n * the host project to `internals.ariaLabel` / `internals.ariaLabelledByElements`\n * via the shared IDREF mirror. The slotted text content is used as the default\n * accessible name when no override is set (AT walks slotted children\n * automatically through the host's role).\n *\n * @summary Interactive item within an hx-menu.\n *\n * @tag hx-menu-item\n *\n * @slot - Default slot for the item label.\n * @slot prefix - Icon or content rendered before the label.\n * @slot suffix - Shortcut text or icon rendered after the label.\n * @slot submenu - A nested hx-menu for submenu content.\n *\n * @fires {CustomEvent<{item: HelixMenuItem, value: string}>} hx-item-select - Dispatched when the item is activated via click, Enter, or Space.\n * @fires {CustomEvent<{item: HelixMenuItem}>} hx-item-submenu-open - Dispatched when ArrowRight is pressed on an item with a submenu.\n * @fires {CustomEvent<{item: HelixMenuItem}>} hx-item-submenu-close - Dispatched when ArrowLeft is pressed on an item, signaling the parent to close the submenu and return focus.\n *\n * @csspart base - The root item element.\n * @csspart prefix - Prefix slot wrapper.\n * @csspart label - Label slot wrapper.\n * @csspart suffix - Suffix slot wrapper.\n * @csspart submenu-icon - The chevron icon indicating a submenu.\n * @csspart checked-icon - The checkmark icon for checkbox-type items.\n *\n * @cssprop [--hx-menu-item-color=var(--hx-color-neutral-900)] - Item text color.\n * @cssprop [--hx-menu-item-hover-bg=var(--hx-color-neutral-100)] - Item hover/focus background.\n */\n@customElement('hx-menu-item')\nexport class HelixMenuItem extends HelixElement {\n static override styles = [helixMenuItemStyles, forcedColorsInteractive];\n\n /**\n * Test seam (codex push-gate round-1 finding 3 mirror of hx-select\n * pattern): when set to `true` or `false`, overrides the platform\n * `supportsIdrefElementReferences` probe before `connectedCallback`\n * seeds `_supportsIdrefRefs`. Tests that need to exercise the fallback\n * path must select it BEFORE the host connects so tabindex / role\n * placement matches a legacy engine for the entire lifecycle.\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 /**\n * @internal Managed by parent hx-menu for roving tabindex.\n * Only the active item in the menu has tabindex=0; all others have -1.\n */\n @state()\n private _rovingTabIndex = -1;\n\n /** @internal Set the roving tabindex value. Called by parent hx-menu. */\n setRovingTabIndex(value: number): void {\n this._rovingTabIndex = value;\n this._applyHostTabIndex();\n }\n\n /** Set whether the nested submenu is open. Called by the component managing submenu visibility. */\n setSubmenuOpen(open: boolean): void {\n this._submenuOpen = open;\n }\n\n /**\n * The value associated with this item, emitted in the hx-select event.\n * @attr value\n */\n @property({ type: String })\n value = '';\n\n /**\n * Whether the item is disabled. Prevents interaction and event dispatch.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Whether the item is checked. Only meaningful when type=\"checkbox\".\n * @attr checked\n */\n @property({ type: Boolean, reflect: true })\n checked = false;\n\n /**\n * The type of menu item. \"checkbox\" renders a checkmark and toggles checked state.\n * \"radio\" renders a checkmark and emits selection for radio-group behavior.\n * @attr type\n */\n @property({ type: String, reflect: true })\n type: 'normal' | 'checkbox' | 'radio' = 'normal';\n\n /**\n * Whether the item is in a loading state. Shows a spinner and prevents interaction.\n * @attr loading\n */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n /** @internal */\n @state()\n private _hasSubmenu = false;\n\n /** @internal Tracks whether the nested submenu is currently open. */\n @state()\n private _submenuOpen = false;\n\n /** @internal */\n @query('.menu-item') private _menuItemEl!: 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 for the menu item — read by both\n * `_syncHostAriaSemantics()` (modern path: host `internals.ariaLabel`)\n * and the fallback `render()` branch (legacy path: inner\n * `div[role=\"menuitem*\"]` `aria-label`). Empty string means \"no\n * override\" — slotted text content provides the implicit name through\n * the announced surface (host on modern; inner div on fallback). AccName\n * 1.2 §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 /**\n * Focus the menu item. On the modern host-canonical path, focus lands on\n * the host (which carries the roving tabindex and announced role). On the\n * legacy fallback path, focus delegates to the inner element which still\n * carries the role.\n */\n override focus(options?: FocusOptions): void {\n if (this._supportsIdrefRefs) {\n // Host is the canonical Tab stop on the modern path.\n HTMLElement.prototype.focus.call(this, options);\n } else {\n this._menuItemEl?.focus(options);\n }\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Honour the static test override so synthetic environments choose the\n // path BEFORE connect runs (mirrors hx-select's seam — codex push-gate\n // round-1 finding 3 needs deterministic fallback-path entry to assert\n // host.tabIndex stays out of the tab order).\n const ctor = this.constructor as typeof HelixMenuItem;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n // WCAG 4.1.2: menuitem role is only valid inside a role=\"menu\" or role=\"menubar\" container.\n // Check the closest ancestor with a menu role.\n const menuHost = this.closest('hx-menu, hx-split-button, [role=\"menu\"], [role=\"menubar\"]');\n if (!menuHost) {\n devWarn(\n 'hx-menu-item',\n 'hx-menu-item must be used inside an hx-menu or an element with role=\"menu\". ' +\n 'An orphaned menuitem violates WCAG 1.3.1 (Info and Relationships).',\n );\n }\n // Keyboard handling lives on the HOST so the active surface (the host\n // on the modern path; either the host or the inner div in delegating\n // engines) receives keydown events. Activation (Enter/Space) and\n // submenu navigation (ArrowLeft/ArrowRight) are routed here; the\n // parent hx-menu owns ArrowUp/ArrowDown/Home/End/typeahead.\n this.addEventListener('keydown', this._handleKeyDown);\n this.addEventListener('click', this._handleClick);\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('keydown', this._handleKeyDown);\n this.removeEventListener('click', this._handleClick);\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('checked') ||\n changedProperties.has('type') ||\n changedProperties.has('loading') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_hasSubmenu') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_submenuOpen')\n ) {\n this._syncHostAriaSemantics();\n }\n if (\n (changedProperties as Map<PropertyKey, unknown>).has('_rovingTabIndex') ||\n changedProperties.has('disabled')\n ) {\n this._applyHostTabIndex();\n }\n }\n\n /**\n * Apply the roving tabindex to the host (modern path) so the host is the\n * Tab stop. Disabled items are non-tabbable.\n *\n * Codex push-gate round-1 finding 3: on the fallback path\n * (`_supportsIdrefRefs === false`), the inner `.menu-item` element\n * carries `role=\"menuitem\"` and the roving tabindex via the template\n * (see `render()`'s legacy branch). If we ALSO assign a non-negative\n * tabindex to the host, the user gets two focusable surfaces per item —\n * Tab can land on the host even though the AT-announced role/aria-* live\n * on the inner element. The host MUST be removed from the tab order on\n * the fallback path; the inner element is the canonical Tab stop.\n * @internal\n */\n private _applyHostTabIndex(): void {\n if (!this._supportsIdrefRefs) {\n // Fallback path: inner `.menu-item` 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._rovingTabIndex;\n }\n }\n\n /**\n * Mirror menuitem semantics onto the host via ElementInternals. Role is\n * derived from `type` (normal → menuitem, checkbox → menuitemcheckbox,\n * radio → menuitemradio). aria-disabled, aria-checked, aria-haspopup,\n * aria-expanded, and aria-busy reactively follow component state.\n * Consumer-supplied `aria-label` / `aria-labelledby` on the host project\n * onto `internals.ariaLabel` / `internals.ariaLabelledByElements`.\n * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n const role = this._getRole();\n\n // Codex push-gate round-6 finding 2: on the legacy fallback path\n // (`_supportsIdrefRefs === false`) the inner `.menu-item` element\n // already exposes role=\"menuitem*\" + aria-disabled / aria-checked /\n // aria-haspopup / aria-expanded / aria-busy via the template. If we\n // ALSO write those onto the host's ElementInternals, AT sees TWO\n // menuitems for one logical option — the duplicate-surface problem\n // host-canonical migration is meant to eliminate. Suppress all of\n // these state writes on the host when the fallback path is in\n // effect; the inner element is the canonical announced surface.\n if (!this._supportsIdrefRefs) {\n internals.role = null;\n internals.ariaDisabled = null;\n internals.ariaChecked = null;\n internals.ariaHasPopup = null;\n internals.ariaExpanded = null;\n internals.ariaBusy = null;\n } else {\n internals.role = role;\n internals.ariaDisabled = this.disabled ? 'true' : null;\n\n const hasCheckableRole = this.type === 'checkbox' || this.type === 'radio';\n internals.ariaChecked = hasCheckableRole ? (this.checked ? 'true' : 'false') : null;\n\n internals.ariaHasPopup = this._hasSubmenu ? 'menu' : null;\n internals.ariaExpanded = this._hasSubmenu ? (this._submenuOpen ? 'true' : 'false') : null;\n internals.ariaBusy = this.loading ? 'true' : null;\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. The resolved string is cached on\n // `_resolvedAccessibleName` so the fallback render branch (legacy path:\n // AT reads inner div) can mirror the same override without duplicating\n // the precedence ladder.\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. Fallback branch reads\n // `_resolvedAccessibleName` for its inner-div mirror.\n internals.ariaLabel = null;\n } else {\n internals.ariaLabel = flattened || null;\n }\n } else if (hostAriaLabel) {\n resolved = hostAriaLabel;\n if (this._supportsIdrefRefs) {\n // Modern path: host carries the accessible name directly.\n internals.ariaLabel = hostAriaLabel;\n } else {\n // Fallback path: the inner [role=\"menuitem*\"] div is the named\n // surface (it mirrors `_resolvedAccessibleName` via aria-label).\n // Suppress the host aria-label so AT does not announce a second\n // duplicate name (CodeRabbit MUST-FIX: leaked duplicate name).\n internals.ariaLabel = null;\n }\n } else {\n // No override — leave the announced surface to walk slotted text.\n internals.ariaLabel = null;\n }\n\n // Codex push-gate round-2 finding 2: keep the resolved override\n // available for the legacy render branch. Request a re-render so the\n // fallback `<div role=\"menuitem*\" aria-label=...>` picks up the new\n // value when host aria-* changes after first paint.\n if (this._resolvedAccessibleName !== resolved) {\n this._resolvedAccessibleName = resolved;\n if (!this._supportsIdrefRefs) {\n this.requestUpdate();\n }\n }\n }\n\n /** @internal */\n private _handleSubmenuSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasSubmenu = slot.assignedElements().length > 0;\n }\n\n /** @internal */\n private _activate(): void {\n if (this.disabled || this.loading) return;\n\n if (this.type === 'checkbox') {\n this.checked = !this.checked;\n } else if (this.type === 'radio') {\n const menu = this.closest('hx-menu');\n if (menu) {\n menu\n .querySelectorAll<HelixMenuItem>(':scope > hx-menu-item[type=\"radio\"]')\n .forEach((sibling) => {\n sibling.checked = sibling === this;\n });\n } else {\n this.checked = true;\n }\n }\n\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem; value: string }>('hx-item-select', {\n bubbles: true,\n composed: true,\n detail: { item: this, value: this.value },\n }),\n );\n }\n\n /**\n * Origin guard for host-bound click/keydown handlers. Returns `true` only\n * when the event originated on THIS host (its shadow tree) and not on a\n * nested `hx-menu-item` projected into the `submenu` slot.\n *\n * Codex push-gate round-5 P1: nested submenu items are slotted descendants\n * in the parent's light DOM. Click/keydown events from a Child item bubble\n * through the parent host's listeners — without this guard, selecting Child\n * also activates Parent (double `hx-item-select`) and Enter/Space/ArrowRight\n * on Child re-trigger Parent's handlers (wrong-level activation, second\n * submenu reopen).\n *\n * Walks `composedPath()` and returns the closest `hx-menu-item` ancestor of\n * the original target; the event is \"ours\" iff that ancestor is `this`.\n * Mirrors the inner-vs-host origin discipline used by `hx-checkbox`,\n * `hx-switch`, and `hx-toggle-button`'s host handlers (`path[0] !== this`)\n * but adapts for hx-menu-item's nested-host case where path[0] is the\n * deepest inner element of a slotted child's own shadow tree.\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 if (node.tagName === 'HX-MENU-ITEM') {\n return node === this;\n }\n }\n return false;\n }\n\n /** @internal */\n private _handleClick = (e: MouseEvent): void => {\n // Codex push-gate round-5 finding 1 (P1): clicks on a nested submenu's\n // child item bubble through this host. Without an origin guard, both\n // Child and Parent activate — wrong value emitted, possibly closes menu.\n if (!this._isOwnEvent(e)) return;\n if (this.disabled || this.loading) {\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-5 finding 2 (P1): Enter / Space / ArrowRight\n // dispatched at a focused Child item inside an open submenu bubble\n // through this host. Without an origin guard, Parent treats them as its\n // own — double activation and wrong-level submenu reopen. The original\n // JSDoc on this handler described this guard but never enforced it.\n if (!this._isOwnEvent(e)) return;\n\n // Only handle keys whose target is THIS host (or its shadow). The\n // parent hx-menu's keydown handler runs first via bubbling and may\n // already have moved focus; we ignore events that aren't aimed at us.\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this._activate();\n return;\n }\n\n if (e.key === 'ArrowRight' && this._hasSubmenu) {\n e.preventDefault();\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem }>('hx-item-submenu-open', {\n bubbles: true,\n composed: true,\n cancelable: true,\n detail: { item: this },\n }),\n );\n return;\n }\n\n if (e.key === 'ArrowLeft') {\n e.preventDefault();\n this.dispatchEvent(\n new CustomEvent<{ item: HelixMenuItem }>('hx-item-submenu-close', {\n bubbles: true,\n composed: true,\n cancelable: true,\n detail: { item: this },\n }),\n );\n }\n };\n\n /** @internal */\n private _renderCheckedIcon() {\n return html`\n <span part=\"checked-icon\" class=\"menu-item__checked-icon\" aria-hidden=\"true\">\n <hx-icon class=\"menu-item__glyph\" library=\"helix\" name=\"check\" aria-hidden=\"true\"></hx-icon>\n </span>\n `;\n }\n\n /** @internal */\n private _renderSubmenuIcon() {\n return html`\n <span part=\"submenu-icon\" class=\"menu-item__submenu-icon\" aria-hidden=\"true\">\n <hx-icon\n class=\"menu-item__glyph\"\n library=\"helix\"\n name=\"chevron-right\"\n aria-hidden=\"true\"\n ></hx-icon>\n </span>\n `;\n }\n\n /** @internal */\n private _renderSpinner() {\n return html`\n <svg class=\"menu-item__spinner\" aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"3\" opacity=\"0.3\" />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n />\n </svg>\n `;\n }\n\n /** @internal */\n private _getRole(): 'menuitem' | 'menuitemcheckbox' | 'menuitemradio' {\n switch (this.type) {\n case 'checkbox':\n return 'menuitemcheckbox';\n case 'radio':\n return 'menuitemradio';\n default:\n return 'menuitem';\n }\n }\n\n override render() {\n const role = this._getRole();\n const hasCheckableRole = this.type === 'checkbox' || this.type === 'radio';\n const classes = {\n 'menu-item': true,\n 'menu-item--checked': this.checked,\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 element is a presentational div (ARIA 1.2 forbids\n // role=\"presentation\" on focusable elements; non-focusable plain div\n // is the cleanest strip). Click + keydown handlers stay on the host\n // via the wrapper div for delegation; this preserves keyboard\n // activation while leaving the host as the AT-announced surface.\n if (this._supportsIdrefRefs) {\n // Click + keydown handlers are bound on the host in\n // connectedCallback() — keydown does not propagate INTO shadow\n // DOM, so binding inside the template would miss host-focused\n // events on the modern path.\n return html`\n <div part=\"base\" class=${classMap(classes)}>\n ${this.loading ? this._renderSpinner() : nothing}\n ${hasCheckableRole ? this._renderCheckedIcon() : nothing}\n <span part=\"prefix\" class=\"menu-item__prefix\">\n <slot name=\"prefix\"></slot>\n </span>\n <span part=\"label\" class=\"menu-item__label\">\n <slot></slot>\n </span>\n <span part=\"suffix\" class=\"menu-item__suffix\">\n <slot name=\"suffix\"></slot>\n </span>\n ${this._hasSubmenu ? this._renderSubmenuIcon() : nothing}\n <slot name=\"submenu\" @slotchange=${this._handleSubmenuSlotChange}></slot>\n </div>\n `;\n }\n\n // Legacy fallback: keep role/aria-* on inner div for AT without IDL\n // element references on ElementInternals. Click + keydown still\n // listen on the host (see connectedCallback) so behaviour is uniform.\n //\n // Codex push-gate round-2 finding 2: AT on the fallback path\n // announces the inner div, so it MUST mirror the same accessible name\n // resolved by `_syncHostAriaSemantics()` (consumer host aria-label /\n // aria-labelledby flatten). Empty string means \"no override\" — let AT\n // walk slotted text content for the implicit name.\n const fallbackAriaLabel = this._resolvedAccessibleName || nothing;\n return html`\n <div\n part=\"base\"\n class=${classMap(classes)}\n role=${role}\n tabindex=${this.disabled ? '-1' : String(this._rovingTabIndex)}\n aria-label=${fallbackAriaLabel}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-checked=${hasCheckableRole ? (this.checked ? 'true' : 'false') : nothing}\n aria-haspopup=${this._hasSubmenu ? 'menu' : nothing}\n aria-expanded=${this._hasSubmenu ? (this._submenuOpen ? 'true' : 'false') : nothing}\n aria-busy=${this.loading ? 'true' : nothing}\n >\n ${this.loading ? this._renderSpinner() : nothing}\n ${hasCheckableRole ? this._renderCheckedIcon() : nothing}\n <span part=\"prefix\" class=\"menu-item__prefix\">\n <slot name=\"prefix\"></slot>\n </span>\n <span part=\"label\" class=\"menu-item__label\">\n <slot></slot>\n </span>\n <span part=\"suffix\" class=\"menu-item__suffix\">\n <slot name=\"suffix\"></slot>\n </span>\n ${this._hasSubmenu ? this._renderSubmenuIcon() : nothing}\n <slot name=\"submenu\" @slotchange=${this._handleSubmenuSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu-item': HelixMenuItem;\n }\n}\n","import { css } from 'lit';\n\nexport const helixMenuDividerStyles = css`\n :host {\n display: block;\n }\n\n .menu-divider {\n height: var(--hx-border-width-thin, 1px);\n background-color: var(--hx-menu-divider-color, var(--hx-color-border-default, #d6dbd5));\n margin: var(--hx-space-1, 0.25rem) calc(-1 * var(--hx-space-1, 0.25rem));\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .menu-divider {\n background-color: GrayText;\n }\n }\n`;\n","import { html } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement } from 'lit/decorators.js';\nimport { HelixElement } from '../../base/index.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { helixMenuDividerStyles } from './hx-menu-divider.styles.js';\nimport { supportsIdrefElementReferences } from '../../utils/aria-idref.js';\n\n/**\n * A visual separator for grouping items within an `hx-menu`.\n *\n * Group 5b host-canonical: `role=\"separator\"` lives on the **host** via\n * `_internals.role` so the parent `<hx-menu>` (`role=\"menu\"`) sees the\n * separator as a direct child. `aria-orientation` is mirrored onto the host\n * via `internals.ariaOrientation`. The inner div is presentational on the\n * modern path and stripped of its role; the legacy fallback keeps the\n * inner role for engines without ElementInternals IDL accessors.\n *\n * @summary Horizontal divider between menu sections.\n *\n * @tag hx-menu-divider\n *\n * @csspart base - The root separator element.\n *\n * @cssprop [--hx-menu-divider-color=var(--hx-color-neutral-200)] - Divider line color.\n */\n@customElement('hx-menu-divider')\nexport class HelixMenuDivider extends HelixElement {\n static override styles = [helixMenuDividerStyles, forcedColorsInteractive];\n\n /** @internal */\n private _supportsIdrefRefs = true;\n\n override connectedCallback(): void {\n super.connectedCallback();\n this._supportsIdrefRefs = supportsIdrefElementReferences(this._internals);\n const internals = this._internals;\n internals.role = 'separator';\n internals.ariaOrientation = 'horizontal';\n }\n\n override render() {\n if (this._supportsIdrefRefs) {\n // Modern path: role lives on host via internals; inner div is\n // presentational.\n return html`<div part=\"base\" class=\"menu-divider\"></div>`;\n }\n // Legacy fallback: keep role/aria-orientation on the inner div for AT\n // without IDL accessors on ElementInternals.\n return html`<div\n part=\"base\"\n class=\"menu-divider\"\n role=\"separator\"\n aria-orientation=\"horizontal\"\n ></div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu-divider': HelixMenuDivider;\n }\n}\n"],"names":["helixMenuStyles","css","findClosestMenuAncestor","start","found","findClosestMenuAncestorElement","findOwningMenuItem","menu","findOwningMenuItemElement","HelixMenu","HelixElement","detail","item","submenuSlot","_a","nested","el","ownerItem","target","items","activeIndex","i","first","last","index","active","idx","char","match","getMenuItemTypeaheadLabel","slot","validTags","invalid","devWarn","ctor","supportsIdrefElementReferences","installAriaIdrefMirror","changedProperties","internals","hostAriaLabel","consumerLabelledBy","labelEls","resolveIdrefTokens","hasEffectiveLabelledBy","refsInternals","resolved","flattenAccName","html","fallbackLabel","nothing","forcedColorsInteractive","__decorateClass","property","customElement","helixMenuItemStyles","HelixMenuItem","value","open","options","role","hasCheckableRole","flattened","sibling","path","node","classes","classMap","fallbackAriaLabel","state","query","helixMenuDividerStyles","HelixMenuDivider"],"mappings":"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"}
@@ -1,10 +1,10 @@
1
- import { css as y, svg as g, html as u, nothing as b } from "lit";
2
- import { property as x, state as k, customElement as w } from "lit/decorators.js";
3
- import { classMap as m } from "lit/directives/class-map.js";
4
- import { repeat as C } from "lit/directives/repeat.js";
5
- import { f as A } from "./forced-colors-CTEDFRGa.js";
6
- import { H as $ } from "./helix-element-BNEYeiys.js";
7
- const I = y`
1
+ import { css as k, html as u, nothing as b } from "lit";
2
+ import { property as m, state as g, customElement as y } from "lit/decorators.js";
3
+ import { classMap as x } from "lit/directives/class-map.js";
4
+ import { repeat as w } from "lit/directives/repeat.js";
5
+ import { f as C } from "./forced-colors-CTEDFRGa.js";
6
+ import { H as A } from "./helix-element-BNEYeiys.js";
7
+ const I = k`
8
8
  :host {
9
9
  display: block;
10
10
  font-family: var(--hx-nav-font-family, var(--hx-font-family-sans, sans-serif));
@@ -133,6 +133,7 @@ const I = y`
133
133
  /* ─── Chevron Icon ─── */
134
134
 
135
135
  .nav__chevron {
136
+ --hx-icon-size: 16px;
136
137
  transition: transform var(--hx-transition-normal, 200ms) ease;
137
138
  flex-shrink: 0;
138
139
  }
@@ -141,6 +142,12 @@ const I = y`
141
142
  transform: rotate(180deg);
142
143
  }
143
144
 
145
+ /* ─── Hamburger Icon (mobile menu trigger) ─── */
146
+
147
+ .nav__hamburger-glyph {
148
+ --hx-icon-size: 24px;
149
+ }
150
+
144
151
  /* ─── Submenu ─── */
145
152
 
146
153
  .nav__submenu {
@@ -284,12 +291,12 @@ const I = y`
284
291
  }
285
292
  }
286
293
  `;
287
- var O = Object.defineProperty, E = Object.getOwnPropertyDescriptor, p = (e, n, r, i) => {
288
- for (var t = i > 1 ? void 0 : i ? E(n, r) : n, o = e.length - 1, l; o >= 0; o--)
294
+ var $ = Object.defineProperty, O = Object.getOwnPropertyDescriptor, p = (e, n, r, i) => {
295
+ for (var t = i > 1 ? void 0 : i ? O(n, r) : n, o = e.length - 1, l; o >= 0; o--)
289
296
  (l = e[o]) && (t = (i ? l(n, r, t) : l(t)) || t);
290
- return i && t && O(n, r, t), t;
297
+ return i && t && $(n, r, t), t;
291
298
  };
292
- let c = class extends $ {
299
+ let c = class extends A {
293
300
  constructor() {
294
301
  super(...arguments), this.items = [], this.orientation = "horizontal", this.label = "Main navigation", this.labelOpenMenu = "Open navigation menu", this.labelCloseMenu = "Close navigation menu", this._mobileOpen = !1, this._expandedIndex = null, this._boundOutsideClick = this._handleOutsideClick.bind(this), this._boundFocusout = this._handleFocusout.bind(this);
295
302
  }
@@ -337,7 +344,7 @@ let c = class extends $ {
337
344
  }
338
345
  /** @internal */
339
346
  _handleKeydown(e, n, r) {
340
- var l, h, d, a, f;
347
+ var l, h, d, a, _;
341
348
  const i = (l = this.shadowRoot) == null ? void 0 : l.querySelectorAll(
342
349
  '[part="list"] > [part="item"] > [part="link"]'
343
350
  );
@@ -381,12 +388,12 @@ let c = class extends $ {
381
388
  }
382
389
  case "Enter":
383
390
  case " ": {
384
- if ((f = r.children) != null && f.length) {
391
+ if ((_ = r.children) != null && _.length) {
385
392
  e.preventDefault();
386
393
  const s = this._expandedIndex === n;
387
394
  this._expandedIndex = s ? null : n, s || this.updateComplete.then(() => {
388
- var _;
389
- const v = (_ = this.shadowRoot) == null ? void 0 : _.querySelector(
395
+ var f;
396
+ const v = (f = this.shadowRoot) == null ? void 0 : f.querySelector(
390
397
  '.nav__submenu:not([hidden]) [part="link"]'
391
398
  );
392
399
  v == null || v.focus();
@@ -450,41 +457,21 @@ let c = class extends $ {
450
457
  // ─── Render Helpers ───
451
458
  /** @internal */
452
459
  _renderHamburgerIcon() {
453
- return u`<svg
454
- width="24"
455
- height="24"
456
- viewBox="0 0 24 24"
457
- fill="none"
458
- stroke="currentColor"
459
- stroke-width="2"
460
- stroke-linecap="round"
460
+ return u`<hx-icon
461
+ class="nav__hamburger-glyph"
462
+ library="helix"
463
+ name=${this._mobileOpen ? "close" : "menu"}
461
464
  aria-hidden="true"
462
- >
463
- ${this._mobileOpen ? g`<line x1="18" y1="6" x2="6" y2="18"></line>
464
- <line x1="6" y1="6" x2="18" y2="18"></line>` : g`<line x1="3" y1="12" x2="21" y2="12"></line>
465
- <line x1="3" y1="6" x2="21" y2="6"></line>
466
- <line x1="3" y1="18" x2="21" y2="18"></line>`}
467
- </svg>`;
465
+ ></hx-icon>`;
468
466
  }
469
467
  /** @internal */
470
468
  _renderChevronIcon() {
471
- return u`<svg
469
+ return u`<hx-icon
472
470
  class="nav__chevron"
473
- width="16"
474
- height="16"
475
- viewBox="0 0 16 16"
476
- fill="currentColor"
471
+ library="helix"
472
+ name="chevron-down"
477
473
  aria-hidden="true"
478
- >
479
- <path
480
- d="M4.5 6L8 9.5 11.5 6"
481
- stroke="currentColor"
482
- stroke-width="1.5"
483
- fill="none"
484
- stroke-linecap="round"
485
- stroke-linejoin="round"
486
- />
487
- </svg>`;
474
+ ></hx-icon>`;
488
475
  }
489
476
  /** @internal */
490
477
  _renderSubMenu(e, n, r) {
@@ -497,7 +484,7 @@ let c = class extends $ {
497
484
  <a
498
485
  part="link"
499
486
  href=${this._sanitizeHref(t.href)}
500
- class=${m({
487
+ class=${x({
501
488
  nav__link: !0,
502
489
  "nav__link--active": !!t.current
503
490
  })}
@@ -524,7 +511,7 @@ let c = class extends $ {
524
511
  }, l = r ? u`
525
512
  <button
526
513
  part="link"
527
- class=${m(o)}
514
+ class=${x(o)}
528
515
  aria-expanded=${i ? "true" : "false"}
529
516
  aria-current=${t ? "true" : b}
530
517
  @click=${(a) => this._handleItemClick(e, n, a)}
@@ -537,7 +524,7 @@ let c = class extends $ {
537
524
  <a
538
525
  part="link"
539
526
  href=${this._sanitizeHref(e.href)}
540
- class=${m(o)}
527
+ class=${x(o)}
541
528
  aria-current=${e.current ? "page" : b}
542
529
  @click=${(a) => this._handleItemClick(e, n, a)}
543
530
  @keydown=${(a) => this._handleKeydown(a, n, e)}
@@ -566,8 +553,8 @@ let c = class extends $ {
566
553
  ${this._renderHamburgerIcon()}
567
554
  </button>
568
555
 
569
- <ul part="list" id="nav-list" class=${m(e)} role="list">
570
- ${C(
556
+ <ul part="list" id="nav-list" class=${x(e)} role="list">
557
+ ${w(
571
558
  this.items,
572
559
  (n, r) => r,
573
560
  (n, r) => this._renderItem(n, r)
@@ -577,9 +564,9 @@ let c = class extends $ {
577
564
  `;
578
565
  }
579
566
  };
580
- c.styles = [I, A];
567
+ c.styles = [I, C];
581
568
  p([
582
- x({
569
+ m({
583
570
  type: Array,
584
571
  converter: {
585
572
  fromAttribute(e) {
@@ -595,27 +582,27 @@ p([
595
582
  })
596
583
  ], c.prototype, "items", 2);
597
584
  p([
598
- x({ type: String, reflect: !0 })
585
+ m({ type: String, reflect: !0 })
599
586
  ], c.prototype, "orientation", 2);
600
587
  p([
601
- x({ type: String })
588
+ m({ type: String })
602
589
  ], c.prototype, "label", 2);
603
590
  p([
604
- x({ type: String, attribute: "label-open-menu" })
591
+ m({ type: String, attribute: "label-open-menu" })
605
592
  ], c.prototype, "labelOpenMenu", 2);
606
593
  p([
607
- x({ type: String, attribute: "label-close-menu" })
594
+ m({ type: String, attribute: "label-close-menu" })
608
595
  ], c.prototype, "labelCloseMenu", 2);
609
596
  p([
610
- k()
597
+ g()
611
598
  ], c.prototype, "_mobileOpen", 2);
612
599
  p([
613
- k()
600
+ g()
614
601
  ], c.prototype, "_expandedIndex", 2);
615
602
  c = p([
616
- w("hx-nav")
603
+ y("hx-nav")
617
604
  ], c);
618
605
  export {
619
606
  c as H
620
607
  };
621
- //# sourceMappingURL=hx-nav-ChMTfn7o.js.map
608
+ //# sourceMappingURL=hx-nav-GTsAZGOx.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hx-nav-GTsAZGOx.js","sources":["../../src/components/hx-nav/hx-nav.styles.ts","../../src/components/hx-nav/hx-nav.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixNavStyles = css`\n :host {\n display: block;\n font-family: var(--hx-nav-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-nav-font-size, var(--hx-font-size-sm, 0.875rem));\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ─── Nav Container ─── */\n\n [part='nav'] {\n position: relative;\n background-color: var(--hx-nav-bg, var(--hx-color-neutral-900, #0d1825));\n color: var(--hx-nav-color, var(--hx-color-neutral-100, #ebeee9));\n padding: var(--hx-nav-padding, var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem));\n }\n\n /* ─── Hamburger Toggle ─── */\n\n [part='toggle'] {\n display: none;\n align-items: center;\n justify-content: center;\n padding: var(--hx-space-2, 0.5rem);\n background: transparent;\n border: none;\n border-radius: var(--hx-nav-border-radius, var(--hx-border-radius-sm, 0.25rem));\n color: var(--hx-nav-color, var(--hx-color-neutral-100, #ebeee9));\n cursor: pointer;\n transition: background-color var(--hx-transition-fast, 150ms) ease;\n line-height: 0;\n }\n\n [part='toggle']:hover {\n background-color: var(--hx-nav-link-hover-bg, var(--hx-color-neutral-700, #313e4b));\n }\n\n [part='toggle']:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-nav-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /* ─── Navigation List ─── */\n\n [part='list'] {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n list-style: none;\n margin: 0;\n padding: 0;\n gap: var(--hx-space-1, 0.25rem);\n align-items: center;\n }\n\n /* ─── Nav Item ─── */\n\n [part='item'] {\n position: relative;\n }\n\n /* ─── Nav Link / Button ─── */\n\n .nav__link {\n display: inline-flex;\n align-items: center;\n gap: var(--hx-space-1, 0.25rem);\n padding: var(--hx-nav-item-padding, var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem));\n /*\n * WCAG 2.5.5 (Enhanced) AAA — nav links rendered with default padding\n * land at ~37 px tall (8 px + 1.5 line-height + 8 px). The link\n * content is first-party (rendered via consumer-supplied props on\n * <hx-nav-item>), so the slotted-content carve-out does not apply —\n * this is a real component obligation. Bind --hx-nav-link-min-height\n * to --hx-touch-target-min (2.75rem / 44 px) to grow the interactive\n * area without enlarging the visible label.\n */\n min-height: var(--hx-nav-link-min-height, var(--hx-touch-target-min, 2.75rem));\n color: var(--hx-nav-link-color, var(--hx-color-neutral-100, #ebeee9));\n text-decoration: none;\n border-radius: var(--hx-nav-border-radius, var(--hx-border-radius-sm, 0.25rem));\n border: none;\n background: transparent;\n cursor: pointer;\n font-family: inherit;\n font-size: inherit;\n font-weight: var(--hx-font-weight-medium, 500);\n line-height: var(--hx-line-height-normal, 1.5);\n white-space: nowrap;\n transition:\n background-color var(--hx-transition-fast, 150ms) ease,\n color var(--hx-transition-fast, 150ms) ease;\n }\n\n .nav__link:hover {\n background-color: var(--hx-nav-link-hover-bg, var(--hx-color-neutral-700, #313e4b));\n color: var(--hx-nav-link-hover-color, var(--hx-color-neutral-0, #ffffff));\n }\n\n .nav__link:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-nav-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .nav__link--active {\n background-color: var(--hx-nav-link-active-bg, var(--hx-color-action-primary-bg, #0f6363));\n /* Use --hx-color-text-on-primary so the active-link text inherits the\n * action-surface AAA-strict pairing (white on primary-700 in default\n * themes; black on lighter primary-700 in the high-contrast theme).\n * Pre-3.4.0 this consumed --hx-color-primary-600 directly which\n * resolved to Apex #0F7078 + white = 5.82:1 — AAA-large only, AAA\n * normal fail under WCAG 1.4.6 for body-text-sized link labels. The\n * Phase 4 Tier 3 chain shift moved action.primary.bg to primary-700\n * (Apex 7.03:1 with white) and consuming the action semantic here\n * picks up the AAA-strict pairing across the full 6-brand matrix.\n * Hardcoding white previously failed AAA-large in high-contrast\n * (ratio 2.54 vs. 4.5 floor); the on-primary token resolves correctly\n * in HC mode. */\n color: var(--hx-nav-link-active-color, var(--hx-color-text-on-primary, #ffffff));\n }\n\n /* ─── Chevron Icon ─── */\n\n .nav__chevron {\n --hx-icon-size: 16px;\n transition: transform var(--hx-transition-normal, 200ms) ease;\n flex-shrink: 0;\n }\n\n .nav__link--expanded .nav__chevron {\n transform: rotate(180deg);\n }\n\n /* ─── Hamburger Icon (mobile menu trigger) ─── */\n\n .nav__hamburger-glyph {\n --hx-icon-size: 24px;\n }\n\n /* ─── Submenu ─── */\n\n .nav__submenu {\n position: absolute;\n top: calc(100% + var(--hx-space-1, 0.25rem));\n left: 0;\n min-width: var(--hx-nav-submenu-min-width, 12rem);\n list-style: none;\n margin: 0;\n padding: var(--hx-space-1, 0.25rem) 0;\n background-color: var(--hx-nav-submenu-bg, var(--hx-color-neutral-800, #202b39));\n border-radius: var(--hx-border-radius-md, 0.375rem);\n box-shadow: var(\n --hx-nav-shadow,\n var(--hx-shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1))\n );\n z-index: var(--hx-z-index-dropdown, 1000);\n }\n\n .nav__submenu[hidden] {\n display: none;\n }\n\n .nav__submenu .nav__link {\n display: block;\n width: 100%;\n text-align: start;\n border-radius: 0;\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-4, 1rem);\n }\n\n /* ─── Vertical / Sidebar Orientation ─── */\n\n :host([orientation='vertical']) [part='nav'] {\n padding: var(--hx-space-4, 1rem) var(--hx-space-2, 0.5rem);\n }\n\n :host([orientation='vertical']) [part='list'] {\n flex-direction: column;\n align-items: stretch;\n gap: var(--hx-space-1, 0.25rem);\n }\n\n :host([orientation='vertical']) .nav__link {\n width: 100%;\n justify-content: flex-start;\n }\n\n :host([orientation='vertical']) .nav__submenu {\n position: static;\n box-shadow: none;\n border-radius: 0;\n background-color: transparent;\n padding: 0;\n padding-inline-start: var(--hx-space-4, 1rem);\n }\n\n :host([orientation='vertical']) .nav__submenu[hidden] {\n display: none;\n }\n\n :host([orientation='vertical']) .nav__submenu .nav__link {\n padding: var(--hx-space-1-5, 0.375rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-xs, 0.75rem);\n color: var(--hx-nav-link-color, var(--hx-color-neutral-300, #b6bfb9));\n }\n\n /* ─── Mobile Responsive ─── */\n\n @media (max-width: 768px) {\n [part='nav'] {\n display: flex;\n flex-direction: column;\n padding: var(--hx-space-2, 0.5rem);\n }\n\n [part='toggle'] {\n display: inline-flex;\n align-self: flex-end;\n }\n\n [part='list'] {\n display: none;\n flex-direction: column;\n align-items: stretch;\n width: 100%;\n margin-top: var(--hx-space-2, 0.5rem);\n gap: var(--hx-space-1, 0.25rem);\n }\n\n [part='list'].nav__list--open {\n display: flex;\n }\n\n [part='item'] {\n width: 100%;\n }\n\n .nav__link {\n width: 100%;\n justify-content: flex-start;\n }\n\n .nav__submenu {\n position: static;\n box-shadow: none;\n border-radius: 0;\n padding-inline-start: var(--hx-space-4, 1rem);\n background-color: transparent;\n }\n\n .nav__submenu .nav__link {\n padding: var(--hx-space-1-5, 0.375rem) var(--hx-space-3, 0.75rem);\n }\n }\n\n /* ─── Reduced Motion ─── */\n\n @media (prefers-reduced-motion: reduce) {\n .nav__link,\n .nav__chevron,\n [part='toggle'] {\n transition: none;\n animation: none;\n }\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n [part='nav'] {\n border: 1px solid CanvasText;\n }\n\n .nav__link--active {\n border: 1px solid Highlight;\n }\n\n .nav__submenu {\n border: 1px solid CanvasText;\n }\n }\n`;\n","import { html, nothing } 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 { repeat } from 'lit/directives/repeat.js';\nimport '../hx-icon/hx-icon.js';\nimport { HelixElement } from '../../base/index.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { helixNavStyles } from './hx-nav.styles.js';\n\n/** A single navigation item, optionally with nested children. */\nexport interface NavItem {\n /** Display label for the item. */\n label: string;\n /** Href for the item link. Required unless children are provided. */\n href?: string;\n /** Whether this item represents the current page. */\n current?: boolean;\n /** Nested sub-menu items. */\n children?: NavItem[];\n}\n\n/** Layout orientation for the navigation. */\ntype NavOrientation = 'horizontal' | 'vertical';\n\n/**\n * Primary and secondary navigation component.\n * Supports horizontal menu bar and vertical sidebar patterns.\n * Mobile responsive with hamburger toggle.\n *\n * @summary Navigation bar supporting horizontal and vertical layouts with nested submenus.\n *\n * @tag hx-nav\n *\n * @fires {CustomEvent<{item: NavItem}>} hx-nav-select - Dispatched when a nav item is activated.\n *\n * @csspart nav - The nav landmark element.\n * @csspart list - The top-level list element.\n * @csspart item - Each list item wrapper.\n * @csspart link - The anchor or button element inside each item.\n * @csspart toggle - The mobile hamburger toggle button.\n *\n * @cssprop [--hx-nav-bg=var(--hx-color-neutral-900)] - Navigation background color.\n * @cssprop [--hx-nav-color=var(--hx-color-neutral-100)] - Navigation text color.\n * @cssprop [--hx-nav-font-family=var(--hx-font-family-sans)] - Navigation font family.\n * @cssprop [--hx-nav-link-color=var(--hx-color-neutral-100)] - Link text color.\n * @cssprop [--hx-nav-link-hover-bg=var(--hx-color-neutral-700)] - Link hover background.\n * @cssprop [--hx-nav-link-hover-color=var(--hx-color-white)] - Link hover text color.\n * @cssprop [--hx-nav-link-active-bg=var(--hx-color-primary-600)] - Active link background.\n * @cssprop [--hx-nav-link-active-color=var(--hx-color-white)] - Active link text color.\n * @cssprop [--hx-nav-submenu-bg=var(--hx-color-neutral-800)] - Submenu background color.\n * @cssprop [--hx-nav-submenu-min-width=12rem] - Submenu minimum width.\n * @cssprop [--hx-nav-font-size=var(--hx-font-size-sm)] - Navigation font size.\n * @cssprop [--hx-nav-padding=var(--hx-space-2) var(--hx-space-4)] - Navigation padding.\n * @cssprop [--hx-nav-item-padding=var(--hx-space-2) var(--hx-space-3)] - Item padding.\n * @cssprop [--hx-nav-border-radius=var(--hx-border-radius-sm)] - Item border radius.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-color-neutral-100] - Color.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-nav-focus-ring-color=var(--hx-focus-ring-color)] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-font-weight-medium] - Font weight.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-color-primary-600] - Color.\n * @cssprop [--hx-transition-normal] - Transition timing.\n * @cssprop [--hx-color-neutral-800] - Color.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-nav-shadow] - CSS custom property.\n * @cssprop [--hx-shadow-md] - Box shadow.\n * @cssprop [--hx-z-index-dropdown] - Z-index layer.\n * @cssprop [--hx-space-1-5] - Spacing token.\n * @cssprop [--hx-font-size-xs] - Font size.\n * @cssprop [--hx-color-neutral-300] - Color.\n * @aaa-certified 2026-05-08\n * @aaa-criteria 1.4.6, 1.4.9, 2.1.3, 2.3.3, 2.4.12, 2.4.13, 2.5.5, 3.2.5, 3.3.6, forced-colors, apg-keyboard\n * @aaa-audit src/components/hx-nav/AAA-AUDIT.md\n * @keyboard-contract navigate=Arrow,Home,End; activate=Enter,Space\n * @aria-pattern navigation\n * @aria-pattern-source https://www.w3.org/WAI/ARIA/apg/patterns/landmarks/navigation.html\n * @forced-colors-supported true\n * @stability stable\n * @since 3.7.0\n * @form-associated false\n * @theme-aware true\n * @brand-aware true\n * @drupal-sdc-eligible true\n * @react-wrapper-status complete\n * @figma-component-name hx-nav\n * @priority-tier P0\n * @phi-handles false\n * @clinical-context none\n */\n@customElement('hx-nav')\nexport class HelixNav extends HelixElement {\n static override styles = [helixNavStyles, forcedColorsInteractive];\n\n // ─── Properties ───\n\n /**\n * Navigation items array.\n * @attr items\n */\n @property({\n type: Array,\n converter: {\n fromAttribute(value: string | null): NavItem[] {\n if (!value) return [];\n try {\n const parsed: unknown = JSON.parse(value);\n return Array.isArray(parsed) ? (parsed as NavItem[]) : [];\n } catch {\n return [];\n }\n },\n },\n })\n items: NavItem[] = [];\n\n /**\n * Layout orientation: 'horizontal' (menu bar) or 'vertical' (sidebar).\n * @attr orientation\n */\n @property({ type: String, reflect: true })\n orientation: NavOrientation = 'horizontal';\n\n /**\n * Accessible label for the nav landmark.\n * @attr label\n */\n @property({ type: String })\n label = 'Main navigation';\n\n /** Accessible label for the navigation toggle button when menu is closed. */\n @property({ type: String, attribute: 'label-open-menu' })\n labelOpenMenu = 'Open navigation menu';\n\n /** Accessible label for the navigation toggle button when menu is open. */\n @property({ type: String, attribute: 'label-close-menu' })\n labelCloseMenu = 'Close navigation menu';\n\n // ─── State ───\n\n /**\n * Tracks whether the mobile navigation menu is currently expanded.\n * @internal\n */\n @state() private _mobileOpen = false;\n /**\n * Index of the currently expanded top-level nav item with a submenu, or null if none is expanded.\n * @internal\n */\n @state() private _expandedIndex: number | null = null;\n\n // ─── Private: bound event handler reference ───\n\n /**\n * Stable bound reference to the outside-click handler, stored for addEventListener/removeEventListener symmetry.\n * @internal\n */\n private _boundOutsideClick: (e: MouseEvent) => void = this._handleOutsideClick.bind(this);\n\n /**\n * Stable bound reference to the focusout handler, stored for addEventListener/removeEventListener symmetry.\n * @internal\n */\n private _boundFocusout: (e: FocusEvent) => void = this._handleFocusout.bind(this);\n\n /**\n * Sanitizes a URL to prevent XSS via javascript: or data: URIs.\n * Only allows http:, https:, relative paths, and fragment-only links.\n */\n /** @internal */\n private _sanitizeHref(href: string | undefined): string {\n if (!href || href === '#') return '#';\n // Allow relative paths, fragments, and http(s)\n if (\n href.startsWith('/') ||\n href.startsWith('./') ||\n href.startsWith('../') ||\n href.startsWith('#')\n ) {\n return href;\n }\n if (typeof window === 'undefined') return href;\n try {\n const url = new URL(href, window.location.href);\n if (url.protocol === 'http:' || url.protocol === 'https:') {\n return href;\n }\n } catch {\n // Invalid URL — fall through to safe default\n }\n return '#';\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleToggle(): void {\n this._mobileOpen = !this._mobileOpen;\n if (!this._mobileOpen) {\n this._expandedIndex = null;\n }\n }\n\n /** @internal */\n private _handleItemClick(item: NavItem, index: number, e: Event): void {\n e.preventDefault();\n if (item.children?.length) {\n this._expandedIndex = this._expandedIndex === index ? null : index;\n } else {\n this._mobileOpen = false;\n this._expandedIndex = null;\n this.dispatchEvent(\n new CustomEvent<{ item: NavItem }>('hx-nav-select', {\n bubbles: true,\n composed: true,\n detail: { item },\n }),\n );\n }\n }\n\n /** @internal */\n private _handleSubItemClick(item: NavItem, e: Event): void {\n e.preventDefault();\n this._mobileOpen = false;\n this._expandedIndex = null;\n this.dispatchEvent(\n new CustomEvent<{ item: NavItem }>('hx-nav-select', {\n bubbles: true,\n composed: true,\n detail: { item },\n }),\n );\n }\n\n /** @internal */\n private _handleKeydown(e: KeyboardEvent, index: number, item: NavItem): void {\n const items = this.shadowRoot?.querySelectorAll<HTMLElement>(\n '[part=\"list\"] > [part=\"item\"] > [part=\"link\"]',\n );\n if (!items) return;\n const itemsArr = Array.from(items);\n const current = itemsArr[index];\n\n switch (e.key) {\n case 'ArrowRight':\n case 'ArrowDown': {\n e.preventDefault();\n if (item.children?.length && e.key === 'ArrowDown' && this.orientation === 'horizontal') {\n // open submenu and focus first item\n this._expandedIndex = index;\n void this.updateComplete.then(() => {\n const firstSub = this.shadowRoot?.querySelector<HTMLElement>(\n `.nav__submenu [part=\"link\"]`,\n );\n firstSub?.focus();\n });\n } else {\n const next = itemsArr[index + 1] ?? itemsArr[0];\n next?.focus();\n }\n break;\n }\n case 'ArrowLeft':\n case 'ArrowUp': {\n e.preventDefault();\n const prev = itemsArr[index - 1] ?? itemsArr[itemsArr.length - 1];\n prev?.focus();\n break;\n }\n case 'Home': {\n e.preventDefault();\n itemsArr[0]?.focus();\n break;\n }\n case 'End': {\n e.preventDefault();\n itemsArr[itemsArr.length - 1]?.focus();\n break;\n }\n case 'Escape': {\n this._expandedIndex = null;\n current?.focus();\n break;\n }\n case 'Enter':\n case ' ': {\n if (item.children?.length) {\n e.preventDefault();\n const wasExpanded = this._expandedIndex === index;\n this._expandedIndex = wasExpanded ? null : index;\n if (!wasExpanded) {\n void this.updateComplete.then(() => {\n const firstSub = this.shadowRoot?.querySelector<HTMLElement>(\n `.nav__submenu:not([hidden]) [part=\"link\"]`,\n );\n firstSub?.focus();\n });\n }\n }\n break;\n }\n }\n }\n\n /** @internal */\n private _handleSubKeydown(e: KeyboardEvent, parentIndex: number): void {\n const subItems = this.shadowRoot?.querySelectorAll<HTMLElement>(\n `.nav__submenu:not([hidden]) [part=\"link\"]`,\n );\n if (!subItems) return;\n const arr = Array.from(subItems);\n const focused = (e.currentTarget ?? e.target) as HTMLElement;\n const currentIdx = arr.indexOf(focused);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n const next = arr[currentIdx + 1] ?? arr[0];\n next?.focus();\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n const prev = arr[currentIdx - 1] ?? arr[arr.length - 1];\n prev?.focus();\n break;\n }\n case 'Escape': {\n e.preventDefault();\n this._expandedIndex = null;\n const parentLinks = this.shadowRoot?.querySelectorAll<HTMLElement>(\n '[part=\"list\"] > [part=\"item\"] > [part=\"link\"]',\n );\n parentLinks?.[parentIndex]?.focus();\n break;\n }\n }\n }\n\n /** @internal */\n private _handleOutsideClick(e: MouseEvent): void {\n const path = e.composedPath();\n if (!path.includes(this)) {\n this._expandedIndex = null;\n }\n }\n\n /**\n * hx-nav-008: Close expanded submenu when focus moves outside the component.\n * @internal\n */\n private _handleFocusout(e: FocusEvent): void {\n const relatedTarget = e.relatedTarget as Node | null;\n if (relatedTarget && this.contains(relatedTarget)) return;\n if (relatedTarget && this.shadowRoot?.contains(relatedTarget)) return;\n this._expandedIndex = null;\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n if (typeof document !== 'undefined') {\n document.addEventListener('click', this._boundOutsideClick);\n }\n this.addEventListener('focusout', this._boundFocusout);\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n document.removeEventListener('click', this._boundOutsideClick);\n this.removeEventListener('focusout', this._boundFocusout);\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderHamburgerIcon() {\n return html`<hx-icon\n class=\"nav__hamburger-glyph\"\n library=\"helix\"\n name=${this._mobileOpen ? 'close' : 'menu'}\n aria-hidden=\"true\"\n ></hx-icon>`;\n }\n\n /** @internal */\n private _renderChevronIcon() {\n return html`<hx-icon\n class=\"nav__chevron\"\n library=\"helix\"\n name=\"chevron-down\"\n aria-hidden=\"true\"\n ></hx-icon>`;\n }\n\n /** @internal */\n private _renderSubMenu(children: NavItem[], parentIndex: number, parentLabel: string) {\n const isExpanded = this._expandedIndex === parentIndex;\n return html`\n <ul class=\"nav__submenu\" aria-label=\"${parentLabel} submenu\" ?hidden=${!isExpanded}>\n ${children.map(\n (child) => html`\n <li class=\"nav__submenu-item\">\n <a\n part=\"link\"\n href=${this._sanitizeHref(child.href)}\n class=${classMap({\n nav__link: true,\n 'nav__link--active': !!child.current,\n })}\n aria-current=${child.current ? 'page' : nothing}\n @click=${(e: Event) => this._handleSubItemClick(child, e)}\n @keydown=${(e: KeyboardEvent) => this._handleSubKeydown(e, parentIndex)}\n >\n ${child.label}\n </a>\n </li>\n `,\n )}\n </ul>\n `;\n }\n\n /** @internal */\n private _renderItem(item: NavItem, index: number) {\n const hasChildren = !!item.children?.length;\n const isExpanded = this._expandedIndex === index;\n const hasCurrentChild = hasChildren && !!item.children?.some((child) => child.current);\n\n const linkClasses = {\n nav__link: true,\n 'nav__link--active': !!item.current || hasCurrentChild,\n 'nav__link--has-submenu': hasChildren,\n 'nav__link--expanded': isExpanded,\n };\n\n const content = hasChildren\n ? html`\n <button\n part=\"link\"\n class=${classMap(linkClasses)}\n aria-expanded=${isExpanded ? 'true' : 'false'}\n aria-current=${hasCurrentChild ? 'true' : nothing}\n @click=${(e: Event) => this._handleItemClick(item, index, e)}\n @keydown=${(e: KeyboardEvent) => this._handleKeydown(e, index, item)}\n >\n ${item.label} ${this._renderChevronIcon()}\n </button>\n ${this._renderSubMenu(item.children ?? [], index, item.label)}\n `\n : html`\n <a\n part=\"link\"\n href=${this._sanitizeHref(item.href)}\n class=${classMap(linkClasses)}\n aria-current=${item.current ? 'page' : nothing}\n @click=${(e: Event) => this._handleItemClick(item, index, e)}\n @keydown=${(e: KeyboardEvent) => this._handleKeydown(e, index, item)}\n >\n ${item.label}\n </a>\n `;\n\n return html` <li part=\"item\" class=\"nav__item\">${content}</li> `;\n }\n\n // ─── Render ───\n\n override render() {\n const listClasses = {\n nav__list: true,\n 'nav__list--open': this._mobileOpen,\n };\n\n return html`\n <nav part=\"nav\" aria-label=${this.label}>\n <button\n part=\"toggle\"\n class=\"nav__toggle\"\n aria-expanded=${this._mobileOpen ? 'true' : 'false'}\n aria-controls=\"nav-list\"\n aria-label=${this._mobileOpen ? this.labelCloseMenu : this.labelOpenMenu}\n @click=${this._handleToggle}\n >\n ${this._renderHamburgerIcon()}\n </button>\n\n <ul part=\"list\" id=\"nav-list\" class=${classMap(listClasses)} role=\"list\">\n ${repeat(\n this.items,\n (_item, i) => i,\n (item, i) => this._renderItem(item, i),\n )}\n </ul>\n </nav>\n `;\n }\n}\n\n/** Canonical type alias for the hx-nav component. */\nexport type HxNav = HelixNav;\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-nav': HelixNav;\n }\n}\n"],"names":["helixNavStyles","css","HelixNav","HelixElement","href","url","item","index","e","_a","items","itemsArr","current","_b","firstSub","next","prev","_c","_d","_e","wasExpanded","parentIndex","subItems","arr","focused","currentIdx","parentLinks","relatedTarget","html","children","parentLabel","isExpanded","child","classMap","nothing","hasChildren","hasCurrentChild","linkClasses","content","listClasses","repeat","_item","i","forcedColorsInteractive","__decorateClass","property","value","parsed","state","customElement"],"mappings":";;;;;;AAEO,MAAMA,IAAiBC;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;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;A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"}