@helixui/library 3.3.1 → 3.4.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 (321) hide show
  1. package/custom-elements.json +340 -71
  2. package/dist/components/hx-accordion/hx-accordion-item.d.ts +35 -0
  3. package/dist/components/hx-accordion/hx-accordion-item.d.ts.map +1 -1
  4. package/dist/components/hx-alert/hx-alert.d.ts +11 -0
  5. package/dist/components/hx-alert/hx-alert.d.ts.map +1 -1
  6. package/dist/components/hx-alert/hx-alert.styles.d.ts.map +1 -1
  7. package/dist/components/hx-alert/index.js +1 -1
  8. package/dist/components/hx-badge/hx-badge.styles.d.ts.map +1 -1
  9. package/dist/components/hx-badge/index.js +1 -1
  10. package/dist/components/hx-banner/hx-banner.d.ts +9 -1
  11. package/dist/components/hx-banner/hx-banner.d.ts.map +1 -1
  12. package/dist/components/hx-banner/index.js +1 -1
  13. package/dist/components/hx-button/hx-button.d.ts +11 -1
  14. package/dist/components/hx-button/hx-button.d.ts.map +1 -1
  15. package/dist/components/hx-button/index.js +1 -1
  16. package/dist/components/hx-button-group/hx-button-group.d.ts +13 -0
  17. package/dist/components/hx-button-group/hx-button-group.d.ts.map +1 -1
  18. package/dist/components/hx-button-group/index.js +1 -1
  19. package/dist/components/hx-checkbox/hx-checkbox.d.ts +153 -1
  20. package/dist/components/hx-checkbox/hx-checkbox.d.ts.map +1 -1
  21. package/dist/components/hx-checkbox/hx-checkbox.styles.d.ts.map +1 -1
  22. package/dist/components/hx-checkbox/index.js +1 -1
  23. package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts +151 -2
  24. package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts.map +1 -1
  25. package/dist/components/hx-checkbox-group/index.js +1 -1
  26. package/dist/components/hx-color-picker/hx-color-picker.d.ts +163 -1
  27. package/dist/components/hx-color-picker/hx-color-picker.d.ts.map +1 -1
  28. package/dist/components/hx-color-picker/hx-color-picker.styles.d.ts.map +1 -1
  29. package/dist/components/hx-color-picker/index.js +1 -1
  30. package/dist/components/hx-combobox/hx-combobox.d.ts +311 -2
  31. package/dist/components/hx-combobox/hx-combobox.d.ts.map +1 -1
  32. package/dist/components/hx-combobox/index.js +1 -1
  33. package/dist/components/hx-data-table/hx-data-table.d.ts.map +1 -1
  34. package/dist/components/hx-data-table/index.js +1 -1
  35. package/dist/components/hx-date-picker/hx-date-picker.d.ts +182 -56
  36. package/dist/components/hx-date-picker/hx-date-picker.d.ts.map +1 -1
  37. package/dist/components/hx-date-picker/hx-date-picker.styles.d.ts.map +1 -1
  38. package/dist/components/hx-date-picker/index.js +1 -1
  39. package/dist/components/hx-dialog/hx-dialog.d.ts +240 -0
  40. package/dist/components/hx-dialog/hx-dialog.d.ts.map +1 -1
  41. package/dist/components/hx-dialog/index.js +1 -1
  42. package/dist/components/hx-drawer/hx-drawer.d.ts +201 -0
  43. package/dist/components/hx-drawer/hx-drawer.d.ts.map +1 -1
  44. package/dist/components/hx-drawer/hx-drawer.styles.d.ts.map +1 -1
  45. package/dist/components/hx-drawer/index.js +1 -1
  46. package/dist/components/hx-dropdown/hx-dropdown.d.ts +168 -0
  47. package/dist/components/hx-dropdown/hx-dropdown.d.ts.map +1 -1
  48. package/dist/components/hx-dropdown/index.js +1 -1
  49. package/dist/components/hx-field/hx-field.d.ts +109 -0
  50. package/dist/components/hx-field/hx-field.d.ts.map +1 -1
  51. package/dist/components/hx-field/index.js +1 -1
  52. package/dist/components/hx-icon-button/hx-icon-button.d.ts +16 -3
  53. package/dist/components/hx-icon-button/hx-icon-button.d.ts.map +1 -1
  54. package/dist/components/hx-icon-button/hx-icon-button.styles.d.ts.map +1 -1
  55. package/dist/components/hx-icon-button/index.js +1 -1
  56. package/dist/components/hx-link/hx-link.d.ts +10 -1
  57. package/dist/components/hx-link/hx-link.d.ts.map +1 -1
  58. package/dist/components/hx-link/index.js +1 -1
  59. package/dist/components/hx-list/hx-list-item.d.ts +27 -1
  60. package/dist/components/hx-list/hx-list-item.d.ts.map +1 -1
  61. package/dist/components/hx-list/hx-list.d.ts +28 -0
  62. package/dist/components/hx-list/hx-list.d.ts.map +1 -1
  63. package/dist/components/hx-list/index.js +1 -1
  64. package/dist/components/hx-menu/hx-menu-divider.d.ts +10 -0
  65. package/dist/components/hx-menu/hx-menu-divider.d.ts.map +1 -1
  66. package/dist/components/hx-menu/hx-menu-item.d.ts +99 -2
  67. package/dist/components/hx-menu/hx-menu-item.d.ts.map +1 -1
  68. package/dist/components/hx-menu/hx-menu-item.styles.d.ts.map +1 -1
  69. package/dist/components/hx-menu/hx-menu.d.ts +117 -2
  70. package/dist/components/hx-menu/hx-menu.d.ts.map +1 -1
  71. package/dist/components/hx-menu/index.js +1 -1
  72. package/dist/components/hx-meter/hx-meter.d.ts +39 -0
  73. package/dist/components/hx-meter/hx-meter.d.ts.map +1 -1
  74. package/dist/components/hx-meter/hx-meter.styles.d.ts.map +1 -1
  75. package/dist/components/hx-meter/index.js +1 -1
  76. package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts +132 -1
  77. package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts.map +1 -1
  78. package/dist/components/hx-overflow-menu/index.js +1 -1
  79. package/dist/components/hx-phi-field/hx-phi-field.d.ts +0 -1
  80. package/dist/components/hx-phi-field/hx-phi-field.d.ts.map +1 -1
  81. package/dist/components/hx-popover/hx-popover.d.ts +91 -0
  82. package/dist/components/hx-popover/hx-popover.d.ts.map +1 -1
  83. package/dist/components/hx-popover/index.js +1 -1
  84. package/dist/components/hx-progress-bar/hx-progress-bar.d.ts +33 -0
  85. package/dist/components/hx-progress-bar/hx-progress-bar.d.ts.map +1 -1
  86. package/dist/components/hx-progress-bar/index.js +1 -1
  87. package/dist/components/hx-radio-group/hx-radio-group.d.ts +152 -1
  88. package/dist/components/hx-radio-group/hx-radio-group.d.ts.map +1 -1
  89. package/dist/components/hx-radio-group/hx-radio.d.ts +14 -0
  90. package/dist/components/hx-radio-group/hx-radio.d.ts.map +1 -1
  91. package/dist/components/hx-radio-group/index.js +1 -1
  92. package/dist/components/hx-select/hx-select.d.ts +304 -2
  93. package/dist/components/hx-select/hx-select.d.ts.map +1 -1
  94. package/dist/components/hx-select/hx-select.styles.d.ts.map +1 -1
  95. package/dist/components/hx-select/index.js +1 -1
  96. package/dist/components/hx-side-nav/hx-nav-item.styles.d.ts.map +1 -1
  97. package/dist/components/hx-side-nav/index.js +1 -1
  98. package/dist/components/hx-spinner/hx-spinner.d.ts +14 -0
  99. package/dist/components/hx-spinner/hx-spinner.d.ts.map +1 -1
  100. package/dist/components/hx-spinner/index.js +1 -1
  101. package/dist/components/hx-split-button/hx-split-button.d.ts +94 -7
  102. package/dist/components/hx-split-button/hx-split-button.d.ts.map +1 -1
  103. package/dist/components/hx-split-button/index.js +1 -1
  104. package/dist/components/hx-stat/hx-stat.d.ts +28 -0
  105. package/dist/components/hx-stat/hx-stat.d.ts.map +1 -1
  106. package/dist/components/hx-stat/index.js +1 -1
  107. package/dist/components/hx-switch/hx-switch.d.ts +78 -1
  108. package/dist/components/hx-switch/hx-switch.d.ts.map +1 -1
  109. package/dist/components/hx-switch/hx-switch.styles.d.ts.map +1 -1
  110. package/dist/components/hx-switch/index.js +1 -1
  111. package/dist/components/hx-table/hx-td.d.ts +30 -3
  112. package/dist/components/hx-table/hx-td.d.ts.map +1 -1
  113. package/dist/components/hx-table/hx-th.d.ts +39 -3
  114. package/dist/components/hx-table/hx-th.d.ts.map +1 -1
  115. package/dist/components/hx-table/hx-tr.d.ts +26 -0
  116. package/dist/components/hx-table/hx-tr.d.ts.map +1 -1
  117. package/dist/components/hx-table/index.js +1 -1
  118. package/dist/components/hx-tabs/hx-tab-panel.d.ts +34 -0
  119. package/dist/components/hx-tabs/hx-tab-panel.d.ts.map +1 -1
  120. package/dist/components/hx-tabs/hx-tab.d.ts +45 -2
  121. package/dist/components/hx-tabs/hx-tab.d.ts.map +1 -1
  122. package/dist/components/hx-tabs/hx-tab.styles.d.ts.map +1 -1
  123. package/dist/components/hx-tabs/hx-tabs.d.ts +32 -2
  124. package/dist/components/hx-tabs/hx-tabs.d.ts.map +1 -1
  125. package/dist/components/hx-tabs/index.js +1 -1
  126. package/dist/components/hx-tag/hx-tag.styles.d.ts.map +1 -1
  127. package/dist/components/hx-tag/index.js +1 -1
  128. package/dist/components/hx-theme/hx-theme.d.ts +10 -5
  129. package/dist/components/hx-theme/hx-theme.d.ts.map +1 -1
  130. package/dist/components/hx-time-picker/hx-time-picker.d.ts +210 -2
  131. package/dist/components/hx-time-picker/hx-time-picker.d.ts.map +1 -1
  132. package/dist/components/hx-time-picker/hx-time-picker.styles.d.ts.map +1 -1
  133. package/dist/components/hx-time-picker/index.js +1 -1
  134. package/dist/components/hx-toast/hx-toast-stack.d.ts +14 -0
  135. package/dist/components/hx-toast/hx-toast-stack.d.ts.map +1 -1
  136. package/dist/components/hx-toast/hx-toast.d.ts +22 -3
  137. package/dist/components/hx-toast/hx-toast.d.ts.map +1 -1
  138. package/dist/components/hx-toast/index.js +1 -1
  139. package/dist/components/hx-toast/toast-factory.d.ts.map +1 -1
  140. package/dist/components/hx-toggle-button/hx-toggle-button.d.ts +110 -0
  141. package/dist/components/hx-toggle-button/hx-toggle-button.d.ts.map +1 -1
  142. package/dist/components/hx-toggle-button/hx-toggle-button.styles.d.ts.map +1 -1
  143. package/dist/components/hx-toggle-button/index.js +1 -1
  144. package/dist/components/hx-tooltip/hx-tooltip.d.ts +52 -0
  145. package/dist/components/hx-tooltip/hx-tooltip.d.ts.map +1 -1
  146. package/dist/components/hx-tooltip/index.js +1 -1
  147. package/dist/components/hx-tree-view/hx-tree-item.d.ts +117 -12
  148. package/dist/components/hx-tree-view/hx-tree-item.d.ts.map +1 -1
  149. package/dist/components/hx-tree-view/hx-tree-view.d.ts +87 -7
  150. package/dist/components/hx-tree-view/hx-tree-view.d.ts.map +1 -1
  151. package/dist/components/hx-tree-view/index.js +1 -1
  152. package/dist/css/helix-all.css +221 -1
  153. package/dist/css/helix-core.css +81 -0
  154. package/dist/css/helix-feedback.css +14 -0
  155. package/dist/css/helix-forms.css +109 -1
  156. package/dist/css/helix-overlay.css +17 -0
  157. package/dist/css/hx-alert.css +9 -0
  158. package/dist/css/hx-badge.css +28 -0
  159. package/dist/css/hx-checkbox.css +18 -0
  160. package/dist/css/hx-color-picker.css +25 -0
  161. package/dist/css/hx-date-picker.css +2 -1
  162. package/dist/css/hx-drawer.css +17 -0
  163. package/dist/css/hx-icon-button.css +30 -0
  164. package/dist/css/hx-meter.css +5 -0
  165. package/dist/css/hx-select.css +19 -0
  166. package/dist/css/hx-switch.css +17 -0
  167. package/dist/css/hx-tag.css +23 -0
  168. package/dist/css/hx-time-picker.css +11 -0
  169. package/dist/css/hx-toggle-button.css +17 -0
  170. package/dist/css/index.css +1 -1
  171. package/dist/css/manifest.json +4 -1
  172. package/dist/index.js +38 -38
  173. package/dist/shared/aria-flatten-DY6v2vah.js +22 -0
  174. package/dist/shared/aria-flatten-DY6v2vah.js.map +1 -0
  175. package/dist/shared/aria-idref-CxvyzfQS.js +126 -0
  176. package/dist/shared/aria-idref-CxvyzfQS.js.map +1 -0
  177. package/dist/shared/hx-accordion-ZVzgDzTG.js.map +1 -1
  178. package/dist/shared/{hx-alert-CLn7CstP.js → hx-alert-Bto8-TIi.js} +55 -37
  179. package/dist/shared/hx-alert-Bto8-TIi.js.map +1 -0
  180. package/dist/shared/{hx-badge-CQXgOXJM.js → hx-badge-JlFtAdxS.js} +37 -9
  181. package/dist/shared/hx-badge-JlFtAdxS.js.map +1 -0
  182. package/dist/shared/{hx-banner-D3DzpfcP.js → hx-banner-fpRnciIO.js} +13 -5
  183. package/dist/shared/hx-banner-fpRnciIO.js.map +1 -0
  184. package/dist/shared/{hx-button-DPY6SPVT.js → hx-button-BOwAEcF1.js} +108 -85
  185. package/dist/shared/{hx-button-DPY6SPVT.js.map → hx-button-BOwAEcF1.js.map} +1 -1
  186. package/dist/shared/{hx-button-group-BI-QBqmO.js → hx-button-group-DcHP5MBv.js} +15 -16
  187. package/dist/shared/{hx-button-group-BI-QBqmO.js.map → hx-button-group-DcHP5MBv.js.map} +1 -1
  188. package/dist/shared/hx-checkbox-C48KYKFq.js +696 -0
  189. package/dist/shared/hx-checkbox-C48KYKFq.js.map +1 -0
  190. package/dist/shared/hx-checkbox-group-BJIAX3zU.js +496 -0
  191. package/dist/shared/hx-checkbox-group-BJIAX3zU.js.map +1 -0
  192. package/dist/shared/hx-color-picker-Dk4cBwYQ.js +1221 -0
  193. package/dist/shared/hx-color-picker-Dk4cBwYQ.js.map +1 -0
  194. package/dist/shared/hx-combobox-BTLO9qiK.js +1359 -0
  195. package/dist/shared/hx-combobox-BTLO9qiK.js.map +1 -0
  196. package/dist/shared/{hx-data-table-CLqVqdxr.js → hx-data-table-Ct3gQ6ya.js} +3 -2
  197. package/dist/shared/{hx-data-table-CLqVqdxr.js.map → hx-data-table-Ct3gQ6ya.js.map} +1 -1
  198. package/dist/shared/{hx-date-picker-2iRG1p74.js → hx-date-picker-CiR7FVnR.js} +542 -206
  199. package/dist/shared/hx-date-picker-CiR7FVnR.js.map +1 -0
  200. package/dist/shared/hx-dialog-AOZpHSuF.js +717 -0
  201. package/dist/shared/hx-dialog-AOZpHSuF.js.map +1 -0
  202. package/dist/shared/{hx-drawer-Y1Ui2IWJ.js → hx-drawer-DH6CdAN1.js} +300 -98
  203. package/dist/shared/hx-drawer-DH6CdAN1.js.map +1 -0
  204. package/dist/shared/hx-dropdown-DiLd40Lm.js +401 -0
  205. package/dist/shared/hx-dropdown-DiLd40Lm.js.map +1 -0
  206. package/dist/shared/{hx-field-B3Qo8OLS.js → hx-field-zw0U1KVi.js} +99 -38
  207. package/dist/shared/hx-field-zw0U1KVi.js.map +1 -0
  208. package/dist/shared/{hx-icon-button-CGNdQSFM.js → hx-icon-button-a6OpeQz5.js} +149 -68
  209. package/dist/shared/hx-icon-button-a6OpeQz5.js.map +1 -0
  210. package/dist/shared/{hx-link-C-O6vq0Q.js → hx-link-CMnZRUtQ.js} +55 -43
  211. package/dist/shared/hx-link-CMnZRUtQ.js.map +1 -0
  212. package/dist/shared/{hx-list-MyEhh8c7.js → hx-list-De66EtAP.js} +163 -107
  213. package/dist/shared/hx-list-De66EtAP.js.map +1 -0
  214. package/dist/shared/hx-menu-divider-BjiRIWKq.js +797 -0
  215. package/dist/shared/hx-menu-divider-BjiRIWKq.js.map +1 -0
  216. package/dist/shared/{hx-meter-BPscsw5t.js → hx-meter-BJdh6nrF.js} +105 -64
  217. package/dist/shared/hx-meter-BJdh6nrF.js.map +1 -0
  218. package/dist/shared/{hx-nav-item-xqRPOCWX.js → hx-nav-item-CODtUlew.js} +13 -9
  219. package/dist/shared/{hx-nav-item-xqRPOCWX.js.map → hx-nav-item-CODtUlew.js.map} +1 -1
  220. package/dist/shared/hx-overflow-menu-BQ4fiMYu.js +492 -0
  221. package/dist/shared/hx-overflow-menu-BQ4fiMYu.js.map +1 -0
  222. package/dist/shared/hx-phi-field-C19oxlrr.js.map +1 -1
  223. package/dist/shared/{hx-popover-B-FP3-wW.js → hx-popover-B9W8-tC0.js} +123 -66
  224. package/dist/shared/hx-popover-B9W8-tC0.js.map +1 -0
  225. package/dist/shared/hx-progress-bar-C8nDMdYa.js +290 -0
  226. package/dist/shared/hx-progress-bar-C8nDMdYa.js.map +1 -0
  227. package/dist/shared/hx-radio-Z1lV1zTO.js +822 -0
  228. package/dist/shared/hx-radio-Z1lV1zTO.js.map +1 -0
  229. package/dist/shared/hx-select-D18CnJ0e.js +1089 -0
  230. package/dist/shared/hx-select-D18CnJ0e.js.map +1 -0
  231. package/dist/shared/{hx-spinner-DL5AYr16.js → hx-spinner-BB0h2hKZ.js} +62 -34
  232. package/dist/shared/hx-spinner-BB0h2hKZ.js.map +1 -0
  233. package/dist/shared/{hx-split-button-Djnc5Aeg.js → hx-split-button-BoABoEm5.js} +153 -82
  234. package/dist/shared/hx-split-button-BoABoEm5.js.map +1 -0
  235. package/dist/shared/{hx-stat-WOcNV1Ry.js → hx-stat-Dtf9lz-O.js} +77 -47
  236. package/dist/shared/hx-stat-Dtf9lz-O.js.map +1 -0
  237. package/dist/shared/hx-switch-B6kr-EwE.js +540 -0
  238. package/dist/shared/hx-switch-B6kr-EwE.js.map +1 -0
  239. package/dist/shared/{hx-tab-panel-DspCrKqo.js → hx-tab-panel-BQtBXKLD.js} +255 -131
  240. package/dist/shared/hx-tab-panel-BQtBXKLD.js.map +1 -0
  241. package/dist/shared/{hx-tag-CNSmdyaK.js → hx-tag-C5aCUpVi.js} +63 -40
  242. package/dist/shared/hx-tag-C5aCUpVi.js.map +1 -0
  243. package/dist/shared/{hx-td-DnnEMIuA.js → hx-td-BGkFOJEK.js} +267 -123
  244. package/dist/shared/hx-td-BGkFOJEK.js.map +1 -0
  245. package/dist/shared/hx-theme-BsefFWTO.js.map +1 -1
  246. package/dist/shared/hx-time-picker-iwCD7rzW.js +1038 -0
  247. package/dist/shared/hx-time-picker-iwCD7rzW.js.map +1 -0
  248. package/dist/shared/{hx-toggle-button-iLiYrMbD.js → hx-toggle-button-BQ81EDkl.js} +226 -65
  249. package/dist/shared/hx-toggle-button-BQ81EDkl.js.map +1 -0
  250. package/dist/shared/{hx-tooltip-nYOv9OLu.js → hx-tooltip-DVqtKPCD.js} +68 -46
  251. package/dist/shared/hx-tooltip-DVqtKPCD.js.map +1 -0
  252. package/dist/shared/hx-tree-item-CHrUhuZL.js +925 -0
  253. package/dist/shared/hx-tree-item-CHrUhuZL.js.map +1 -0
  254. package/dist/shared/menu-roving-DmMnzJhn.js +14 -0
  255. package/dist/shared/menu-roving-DmMnzJhn.js.map +1 -0
  256. package/dist/shared/menu-tree-BNM0SYYq.js +42 -0
  257. package/dist/shared/menu-tree-BNM0SYYq.js.map +1 -0
  258. package/dist/shared/{toast-factory-YSznocIV.js → toast-factory-CL2BzdSB.js} +128 -77
  259. package/dist/shared/toast-factory-CL2BzdSB.js.map +1 -0
  260. package/dist/utils/aria-flatten.d.ts +56 -0
  261. package/dist/utils/aria-flatten.d.ts.map +1 -0
  262. package/dist/utils/aria-idref.d.ts +127 -0
  263. package/dist/utils/aria-idref.d.ts.map +1 -0
  264. package/dist/utils/menu-label.d.ts +18 -0
  265. package/dist/utils/menu-label.d.ts.map +1 -0
  266. package/dist/utils/menu-roving.d.ts +28 -0
  267. package/dist/utils/menu-roving.d.ts.map +1 -0
  268. package/dist/utils/menu-tree.d.ts +41 -0
  269. package/dist/utils/menu-tree.d.ts.map +1 -0
  270. package/dist/utils/tree-walk.d.ts +53 -0
  271. package/dist/utils/tree-walk.d.ts.map +1 -0
  272. package/figma-inventory.json +132 -20
  273. package/package.json +1 -1
  274. package/dist/shared/hx-alert-CLn7CstP.js.map +0 -1
  275. package/dist/shared/hx-badge-CQXgOXJM.js.map +0 -1
  276. package/dist/shared/hx-banner-D3DzpfcP.js.map +0 -1
  277. package/dist/shared/hx-checkbox-D7xma9YH.js +0 -524
  278. package/dist/shared/hx-checkbox-D7xma9YH.js.map +0 -1
  279. package/dist/shared/hx-checkbox-group-C9n315Ju.js +0 -323
  280. package/dist/shared/hx-checkbox-group-C9n315Ju.js.map +0 -1
  281. package/dist/shared/hx-color-picker-uRc865FJ.js +0 -882
  282. package/dist/shared/hx-color-picker-uRc865FJ.js.map +0 -1
  283. package/dist/shared/hx-combobox-DDzqNKEW.js +0 -924
  284. package/dist/shared/hx-combobox-DDzqNKEW.js.map +0 -1
  285. package/dist/shared/hx-date-picker-2iRG1p74.js.map +0 -1
  286. package/dist/shared/hx-dialog-DRN_1-Y-.js +0 -514
  287. package/dist/shared/hx-dialog-DRN_1-Y-.js.map +0 -1
  288. package/dist/shared/hx-drawer-Y1Ui2IWJ.js.map +0 -1
  289. package/dist/shared/hx-dropdown-LyaRc8Rf.js +0 -263
  290. package/dist/shared/hx-dropdown-LyaRc8Rf.js.map +0 -1
  291. package/dist/shared/hx-field-B3Qo8OLS.js.map +0 -1
  292. package/dist/shared/hx-icon-button-CGNdQSFM.js.map +0 -1
  293. package/dist/shared/hx-link-C-O6vq0Q.js.map +0 -1
  294. package/dist/shared/hx-list-MyEhh8c7.js.map +0 -1
  295. package/dist/shared/hx-menu-divider-C2omnPtj.js +0 -558
  296. package/dist/shared/hx-menu-divider-C2omnPtj.js.map +0 -1
  297. package/dist/shared/hx-meter-BPscsw5t.js.map +0 -1
  298. package/dist/shared/hx-overflow-menu-DCLsdIBy.js +0 -374
  299. package/dist/shared/hx-overflow-menu-DCLsdIBy.js.map +0 -1
  300. package/dist/shared/hx-popover-B-FP3-wW.js.map +0 -1
  301. package/dist/shared/hx-progress-bar-Bn3JEPUf.js +0 -258
  302. package/dist/shared/hx-progress-bar-Bn3JEPUf.js.map +0 -1
  303. package/dist/shared/hx-radio-CJvNU2yP.js +0 -621
  304. package/dist/shared/hx-radio-CJvNU2yP.js.map +0 -1
  305. package/dist/shared/hx-select-C8fEHQhC.js +0 -807
  306. package/dist/shared/hx-select-C8fEHQhC.js.map +0 -1
  307. package/dist/shared/hx-spinner-DL5AYr16.js.map +0 -1
  308. package/dist/shared/hx-split-button-Djnc5Aeg.js.map +0 -1
  309. package/dist/shared/hx-stat-WOcNV1Ry.js.map +0 -1
  310. package/dist/shared/hx-switch-BrZFaRue.js +0 -420
  311. package/dist/shared/hx-switch-BrZFaRue.js.map +0 -1
  312. package/dist/shared/hx-tab-panel-DspCrKqo.js.map +0 -1
  313. package/dist/shared/hx-tag-CNSmdyaK.js.map +0 -1
  314. package/dist/shared/hx-td-DnnEMIuA.js.map +0 -1
  315. package/dist/shared/hx-time-picker-BoEIZwzv.js +0 -688
  316. package/dist/shared/hx-time-picker-BoEIZwzv.js.map +0 -1
  317. package/dist/shared/hx-toggle-button-iLiYrMbD.js.map +0 -1
  318. package/dist/shared/hx-tooltip-nYOv9OLu.js.map +0 -1
  319. package/dist/shared/hx-tree-item-C2CiWuDE.js +0 -703
  320. package/dist/shared/hx-tree-item-C2CiWuDE.js.map +0 -1
  321. package/dist/shared/toast-factory-YSznocIV.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hx-menu-divider-BjiRIWKq.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 */\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 .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 { 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 <svg\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\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 <svg\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\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,12 @@
1
- import { css as x, nothing as g, html as v } from "lit";
2
- import { property as h, state as _, customElement as b } from "lit/decorators.js";
3
- import { ifDefined as m } from "lit/directives/if-defined.js";
4
- import { a as w } from "./forced-colors-CTEDFRGa.js";
5
- import { H as y } from "./helix-element-BNEYeiys.js";
6
- import { c as $ } from "./id-counter-DuX8vsui.js";
7
- const S = x`
1
+ import { css as b, nothing as x, html as v } from "lit";
2
+ import { property as m, state as g, customElement as w } from "lit/decorators.js";
3
+ import { ifDefined as f } from "lit/directives/if-defined.js";
4
+ import { a as y } from "./forced-colors-CTEDFRGa.js";
5
+ import { s as S, i as $, r as L } from "./aria-idref-CxvyzfQS.js";
6
+ import { f as I } from "./aria-flatten-DY6v2vah.js";
7
+ import { H as V } from "./helix-element-BNEYeiys.js";
8
+ import { c as M } from "./id-counter-DuX8vsui.js";
9
+ const A = b`
8
10
  :host {
9
11
  display: block;
10
12
  width: 100%;
@@ -122,6 +124,11 @@ const S = x`
122
124
  /* ─── Forced Colors (Windows High Contrast) ─── */
123
125
 
124
126
  @media (forced-colors: active) {
127
+ .meter:focus-visible {
128
+ outline: 2px solid Highlight;
129
+ outline-offset: var(--hx-focus-ring-offset, 2px);
130
+ }
131
+
125
132
  .meter__track {
126
133
  border: 1px solid CanvasText;
127
134
  }
@@ -132,15 +139,15 @@ const S = x`
132
139
  }
133
140
  }
134
141
  `;
135
- var C = Object.defineProperty, L = Object.getOwnPropertyDescriptor, n = (e, t, o, i) => {
136
- for (var r = i > 1 ? void 0 : i ? L(t, o) : t, s = e.length - 1, l; s >= 0; s--)
137
- (l = e[s]) && (r = (i ? l(t, o, r) : l(r)) || r);
138
- return i && r && C(t, o, r), r;
142
+ var C = Object.defineProperty, H = Object.getOwnPropertyDescriptor, h = (e, t, s, o) => {
143
+ for (var r = o > 1 ? void 0 : o ? H(t, s) : t, a = e.length - 1, n; a >= 0; a--)
144
+ (n = e[a]) && (r = (o ? n(t, s, r) : n(r)) || r);
145
+ return o && r && C(t, s, r), r;
139
146
  };
140
- const M = $("hx-meter");
141
- let a = class extends y {
147
+ const k = M("hx-meter");
148
+ let i = class extends V {
142
149
  constructor() {
143
- super(...arguments), this._uid = M(), this.value = 0, this.min = 0, this.max = 100, this._hasSlotContent = !1;
150
+ super(...arguments), this._uid = k(), this.value = 0, this.min = 0, this.max = 100, this._hasSlotContent = !1, this._supportsIdrefRefs = !0, this._ariaMirror = null, this._resolvedAccessibleName = "";
144
151
  }
145
152
  /** @internal */
146
153
  _clampedValue() {
@@ -153,26 +160,59 @@ let a = class extends y {
153
160
  }
154
161
  /** @internal */
155
162
  _resolveState() {
156
- const e = this._clampedValue(), t = this.low !== void 0, o = this.high !== void 0, i = this.optimum !== void 0;
157
- if (!t && !o && !i) return "default";
158
- const r = this.low ?? 0, s = this.high ?? this.max, l = t && e < r, c = o && e > s, d = !l && !c;
159
- if (!i)
160
- return l || c ? "warning" : "optimum";
161
- const u = this.optimum ?? this.min, p = t && u < r, f = o && u > s;
162
- return !p && !f ? d ? "optimum" : "warning" : p ? l ? "optimum" : d ? "warning" : "danger" : c ? "optimum" : d ? "warning" : "danger";
163
+ const e = this._clampedValue(), t = this.low !== void 0, s = this.high !== void 0, o = this.optimum !== void 0;
164
+ if (!t && !s && !o) return "default";
165
+ const r = this.low ?? 0, a = this.high ?? this.max, n = t && e < r, c = s && e > a, u = !n && !c;
166
+ if (!o)
167
+ return n || c ? "warning" : "optimum";
168
+ const l = this.optimum ?? this.min, d = t && l < r, p = s && l > a;
169
+ return !d && !p ? u ? "optimum" : "warning" : d ? n ? "optimum" : u ? "warning" : "danger" : c ? "optimum" : u ? "warning" : "danger";
163
170
  }
164
171
  /** @internal */
165
172
  _onLabelSlotChange(e) {
166
173
  const t = e.target;
167
- this._hasSlotContent = t.assignedNodes({ flatten: !0 }).length > 0;
174
+ this._hasSlotContent = t.assignedNodes({ flatten: !0 }).length > 0, this._syncHostAriaSemantics();
175
+ }
176
+ // ─── Lifecycle ───
177
+ connectedCallback() {
178
+ super.connectedCallback();
179
+ const e = this.constructor;
180
+ this._supportsIdrefRefs = e.__testSupportsIdrefRefsOverride !== null ? e.__testSupportsIdrefRefsOverride : S(this._internals), this._syncHostAriaSemantics(), this._ariaMirror = $(this, () => {
181
+ this._syncHostAriaSemantics();
182
+ });
183
+ }
184
+ disconnectedCallback() {
185
+ var e;
186
+ super.disconnectedCallback(), (e = this._ariaMirror) == null || e.disconnect(), this._ariaMirror = null;
168
187
  }
169
188
  updated(e) {
170
189
  super.updated(e), this.dataset.state = this._resolveState();
171
190
  const t = this._percentage() / 100;
172
- this.style.setProperty("--_value-ratio", String(Math.max(0, Math.min(1, t))));
191
+ this.style.setProperty("--_value-ratio", String(Math.max(0, Math.min(1, t)))), (e.has("value") || e.has("min") || e.has("max") || e.has("low") || e.has("high") || e.has("optimum") || e.has("label")) && this._syncHostAriaSemantics();
192
+ }
193
+ /**
194
+ * Mirror meter semantics onto the host via ElementInternals. The inner
195
+ * `[role="meter"]` keeps its existing surface — this method ADDS a host-
196
+ * level surface via internals.* so consumer-supplied `aria-labelledby` /
197
+ * `aria-describedby` on the host project through `ariaLabelledByElements`
198
+ * (cross-shadow IDREF) on engines that support it. Mirrors hx-progress-ring's
199
+ * dual-surface pattern (Group 7 gold-standard exemplar).
200
+ * @internal
201
+ */
202
+ _syncHostAriaSemantics() {
203
+ var d;
204
+ const e = this._internals, t = this._clampedValue(), s = this._resolveState(), o = s !== "default" ? ` — ${s}` : "", r = `${t} of ${this.max}${o}`;
205
+ this._supportsIdrefRefs ? (e.role = "meter", e.ariaValueNow = String(t), e.ariaValueMin = String(this.min), e.ariaValueMax = String(this.max), e.ariaValueText = r) : (e.role = null, e.ariaLabel = null, e.ariaValueNow = null, e.ariaValueMin = null, e.ariaValueMax = null, e.ariaValueText = null);
206
+ const a = ((d = this.getAttribute("aria-label")) == null ? void 0 : d.trim()) || "", n = this.getAttribute("aria-labelledby"), c = L(this, n), u = c.length > 0;
207
+ if (this._supportsIdrefRefs) {
208
+ const p = e;
209
+ p.ariaLabelledByElements = u ? c : null;
210
+ }
211
+ let l = "";
212
+ u ? (l = c.map((_) => I(_)).filter(Boolean).join(" ") || a || this.label || "" || r, this._supportsIdrefRefs && (e.ariaLabel = null)) : a ? (l = a, this._supportsIdrefRefs && (e.ariaLabel = a)) : this._hasSlotContent || this.label !== void 0 ? (l = this.label ?? "", this._supportsIdrefRefs && (e.ariaLabel = l || null)) : (l = r, this._supportsIdrefRefs && (e.ariaLabel = l)), this._resolvedAccessibleName = l;
173
213
  }
174
214
  render() {
175
- const e = this._resolveState(), t = this._clampedValue(), o = e !== "default" ? ` — ${e}` : "", i = `${t} of ${this.max}${o}`, r = this.label !== void 0 || this._hasSlotContent, s = a._STATE_LABELS[e];
215
+ const e = this._resolveState(), t = this._clampedValue(), s = e !== "default" ? ` — ${e}` : "", o = `${t} of ${this.max}${s}`, r = this.label !== void 0 || this._hasSlotContent, a = i._STATE_LABELS[e];
176
216
  return v`
177
217
  <div
178
218
  part="base"
@@ -182,9 +222,9 @@ let a = class extends y {
182
222
  aria-valuenow=${t}
183
223
  aria-valuemin=${this.min}
184
224
  aria-valuemax=${this.max}
185
- aria-valuetext=${i}
186
- aria-label=${m(r ? void 0 : `${t} of ${this.max}`)}
187
- aria-labelledby=${m(r ? `${this._uid}-label` : void 0)}
225
+ aria-valuetext=${o}
226
+ aria-label=${f(r ? void 0 : `${t} of ${this.max}`)}
227
+ aria-labelledby=${f(r ? `${this._uid}-label` : void 0)}
188
228
  >
189
229
  <span
190
230
  id=${`${this._uid}-label`}
@@ -197,17 +237,17 @@ let a = class extends y {
197
237
  <div class="meter__track" part="track">
198
238
  <div part="indicator" class="meter__indicator"></div>
199
239
  </div>
200
- ${s ? v`<span class="meter__state-label" data-state=${e} aria-hidden="true"
201
- >${s}</span
202
- >` : g}
240
+ ${a ? v`<span class="meter__state-label" data-state=${e} aria-hidden="true"
241
+ >${a}</span
242
+ >` : x}
203
243
  <meter
204
244
  class="meter__native"
205
245
  value=${t}
206
246
  min=${this.min}
207
247
  max=${this.max}
208
- low=${m(this.low)}
209
- high=${m(this.high)}
210
- optimum=${m(this.optimum)}
248
+ low=${f(this.low)}
249
+ high=${f(this.high)}
250
+ optimum=${f(this.optimum)}
211
251
  aria-hidden="true"
212
252
  tabindex="-1"
213
253
  ></meter>
@@ -215,40 +255,41 @@ let a = class extends y {
215
255
  `;
216
256
  }
217
257
  };
218
- a.styles = [S, w];
219
- a._STATE_LABELS = {
258
+ i.styles = [A, y];
259
+ i.__testSupportsIdrefRefsOverride = null;
260
+ i._STATE_LABELS = {
220
261
  optimum: "Optimum",
221
262
  warning: "Warning",
222
263
  danger: "Danger"
223
264
  };
224
- n([
225
- h({ type: Number, reflect: !0 })
226
- ], a.prototype, "value", 2);
227
- n([
228
- h({ type: Number, reflect: !0 })
229
- ], a.prototype, "min", 2);
230
- n([
231
- h({ type: Number, reflect: !0 })
232
- ], a.prototype, "max", 2);
233
- n([
234
- h({ type: Number, reflect: !0 })
235
- ], a.prototype, "low", 2);
236
- n([
237
- h({ type: Number, reflect: !0 })
238
- ], a.prototype, "high", 2);
239
- n([
240
- h({ type: Number, reflect: !0 })
241
- ], a.prototype, "optimum", 2);
242
- n([
243
- h({ type: String })
244
- ], a.prototype, "label", 2);
245
- n([
246
- _()
247
- ], a.prototype, "_hasSlotContent", 2);
248
- a = n([
249
- b("hx-meter")
250
- ], a);
265
+ h([
266
+ m({ type: Number, reflect: !0 })
267
+ ], i.prototype, "value", 2);
268
+ h([
269
+ m({ type: Number, reflect: !0 })
270
+ ], i.prototype, "min", 2);
271
+ h([
272
+ m({ type: Number, reflect: !0 })
273
+ ], i.prototype, "max", 2);
274
+ h([
275
+ m({ type: Number, reflect: !0 })
276
+ ], i.prototype, "low", 2);
277
+ h([
278
+ m({ type: Number, reflect: !0 })
279
+ ], i.prototype, "high", 2);
280
+ h([
281
+ m({ type: Number, reflect: !0 })
282
+ ], i.prototype, "optimum", 2);
283
+ h([
284
+ m({ type: String })
285
+ ], i.prototype, "label", 2);
286
+ h([
287
+ g()
288
+ ], i.prototype, "_hasSlotContent", 2);
289
+ i = h([
290
+ w("hx-meter")
291
+ ], i);
251
292
  export {
252
- a as H
293
+ i as H
253
294
  };
254
- //# sourceMappingURL=hx-meter-BPscsw5t.js.map
295
+ //# sourceMappingURL=hx-meter-BJdh6nrF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hx-meter-BJdh6nrF.js","sources":["../../src/components/hx-meter/hx-meter.styles.ts","../../src/components/hx-meter/hx-meter.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixMeterStyles = css`\n :host {\n display: block;\n width: 100%;\n }\n\n .meter {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-2, 0.5rem);\n width: 100%;\n outline: none;\n border-radius: var(--hx-border-radius-md, 0.375rem);\n }\n\n .meter:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid var(--hx-focus-ring-color, #0f7078);\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .meter__label {\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n color: var(--hx-meter-label-color, var(--hx-color-neutral-700, #313e4b));\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .meter__track {\n position: relative;\n width: 100%;\n height: var(--hx-meter-track-height, var(--hx-space-2, 0.5rem));\n background-color: var(--hx-meter-track-color, var(--hx-color-neutral-200, #d6dbd5));\n border-radius: var(--hx-meter-track-radius, var(--hx-border-radius-full, 9999px));\n overflow: hidden;\n }\n\n .meter__indicator {\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n height: 100%;\n width: 100%;\n border-radius: inherit;\n background-color: var(--_indicator-color);\n transform-origin: left center;\n transform: scaleX(var(--_value-ratio, 0));\n transition:\n transform var(--hx-transition-fast, 150ms ease),\n background-color var(--hx-transition-fast, 150ms ease);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .meter__indicator {\n transition: none;\n }\n }\n\n /* ─── Default (no thresholds configured) ─── */\n\n :host {\n --_indicator-color: var(--hx-meter-indicator-color, var(--hx-color-primary-500, #429797));\n }\n\n /* ─── Semantic state colors ─── */\n\n :host([data-state='optimum']) {\n --_indicator-color: var(--hx-meter-color-optimum, var(--hx-color-success-500, #3b9e58));\n }\n\n :host([data-state='warning']) {\n --_indicator-color: var(--hx-meter-color-warning, var(--hx-color-warning-500, #c2711c));\n }\n\n :host([data-state='danger']) {\n --_indicator-color: var(--hx-meter-color-danger, var(--hx-color-error-500, #e5493e));\n }\n\n /* ─── State Label (WCAG 1.4.1) ─── */\n /* Visible text label rendered below the track when a semantic state is active. */\n /* Ensures the meter state is not conveyed by fill color alone. */\n /* aria-hidden=\"true\" because aria-valuetext already includes the state for AT. */\n\n .meter__state-label {\n font-size: var(--hx-font-size-xs, 0.75rem);\n font-weight: var(--hx-font-weight-medium, 500);\n line-height: var(--hx-line-height-tight, 1.25);\n font-family: var(--hx-meter-font-family, var(--hx-font-family-sans, sans-serif));\n }\n\n .meter__state-label[data-state='optimum'] {\n color: var(--hx-meter-color-optimum, var(--hx-color-success-700, #146831));\n }\n\n .meter__state-label[data-state='warning'] {\n color: var(--hx-meter-color-warning, var(--hx-color-warning-700, #804605));\n }\n\n .meter__state-label[data-state='danger'] {\n color: var(--hx-meter-color-danger, var(--hx-color-error-700, #a21312));\n }\n\n /* ─── Native meter hidden (we use custom rendering) ─── */\n\n .meter__native {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .meter:focus-visible {\n outline: 2px solid Highlight;\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n .meter__track {\n border: 1px solid CanvasText;\n }\n\n .meter__indicator {\n forced-color-adjust: none;\n background-color: Highlight;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { helixMeterStyles } from './hx-meter.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\nimport { flattenAccName } from '../../utils/aria-flatten.js';\n\ntype MeterState = 'optimum' | 'warning' | 'danger' | 'default';\n\nconst _nextMeterId = createIdCounter('hx-meter');\n\n/**\n * A scalar measurement within a known range — e.g., disk usage, health score,\n * or any numeric value with defined min/max bounds. Supports low/high/optimum\n * threshold markers for semantic color feedback.\n *\n * Group 7 host-canonical: `role=\"meter\"` is mirrored onto the **host** via\n * `_internals.role` AND kept on the inner `[role=\"meter\"]` element. The dual\n * surface is the hx-progress-ring pattern (Group 7 gold-standard exemplar):\n * the host carries the cross-shadow IDREF wiring (`ariaLabelledByElements`\n * resolves through the shared mirror) while the inner element keeps its\n * existing role/state surface so legacy AT and consumer queries continue to\n * work. AccName 1.2 §4.3.1 precedence is implemented uniformly: consumer\n * host `aria-labelledby` (flattened) > consumer host `aria-label` >\n * `label` property / slotted label > derived value-text fallback.\n *\n * @summary Scalar measurement gauge within a defined range.\n *\n * @tag hx-meter\n *\n * @slot label - Visible label rendered above the meter track. When using this\n * slot without the `label` attribute, the accessible name is derived from the\n * slot content via `aria-labelledby`. The `label` attribute is NOT required\n * when slot content is provided — the component detects slot content and\n * switches to `aria-labelledby` automatically.\n *\n * @csspart base - The outer wrapper element.\n * @csspart track - The unfilled track bar element.\n * @csspart indicator - The filled bar indicating the current value.\n * @csspart label - The label wrapper element.\n *\n * @cssprop [--hx-meter-track-height] - Height of the track bar.\n * @cssprop [--hx-meter-track-color] - Background color of the unfilled track.\n * @cssprop [--hx-meter-track-radius] - Border radius of the track.\n * @cssprop [--hx-meter-indicator-color] - Default filled bar color (no thresholds).\n * @cssprop [--hx-meter-color-optimum] - Color when value is in the optimum zone.\n * @cssprop [--hx-meter-color-warning] - Color when value is in a warning zone.\n * @cssprop [--hx-meter-color-danger] - Color when value is in the danger zone.\n * @cssprop [--hx-meter-label-color] - Label text color.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-font-weight-medium] - Font weight.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-border-radius-full] - CSS custom property.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-color-success-500] - Color.\n * @cssprop [--hx-color-warning-500] - Color.\n * @cssprop [--hx-color-error-500] - Color.\n * @cssprop [--hx-font-size-xs] - Font size.\n * @cssprop [--hx-line-height-tight] - Line height.\n * @cssprop [--hx-meter-font-family=var(--hx-font-family-sans)] - CSS custom property.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-color-success-700] - Color.\n * @cssprop [--hx-color-warning-700] - Color.\n * @cssprop [--hx-color-error-700] - Color.\n */\n@customElement('hx-meter')\nexport class HelixMeter extends HelixElement {\n static override styles = [helixMeterStyles, forcedColorsSurface];\n\n /**\n * Test seam (Group 7 host-canonical migration): when set to `true` or\n * `false`, overrides the platform `supportsIdrefElementReferences` probe\n * before `connectedCallback` seeds `_supportsIdrefRefs`. Tests that need\n * to verify the legacy fallback path may opt in by setting this static\n * to `false` before fixture creation.\n *\n * Production code MUST NOT touch this field.\n * @internal\n */\n static __testSupportsIdrefRefsOverride: boolean | null = null;\n\n /** @internal */\n private _uid = _nextMeterId();\n\n /**\n * Current value of the meter.\n * @attr value\n */\n @property({ type: Number, reflect: true })\n value = 0;\n\n /**\n * Minimum value of the range.\n * @attr min\n */\n @property({ type: Number, reflect: true })\n min = 0;\n\n /**\n * Maximum value of the range.\n * @attr max\n */\n @property({ type: Number, reflect: true })\n max = 100;\n\n /**\n * Threshold below which the value is considered suboptimal (lower range warning).\n * @attr low\n */\n @property({ type: Number, reflect: true })\n low?: number;\n\n /**\n * Threshold above which the value is considered suboptimal (upper range warning).\n * @attr high\n */\n @property({ type: Number, reflect: true })\n high?: number;\n\n /**\n * The optimal value within the range. Used to determine which zone is \"good\".\n * @attr optimum\n */\n @property({ type: Number, reflect: true })\n optimum?: number;\n\n /**\n * Accessible label for the meter. Used as the visible label text and as\n * the source for `aria-labelledby`. When only slot content is provided\n * (no `label` attribute), the slot content is used for the accessible name.\n * @attr label\n */\n @property({ type: String })\n label?: string;\n\n /** @internal */\n @state()\n private _hasSlotContent = false;\n\n // ─── Host-canonical ARIA bookkeeping ───\n\n /** @internal */\n private _supportsIdrefRefs = true;\n\n /** @internal */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n\n /** @internal */\n private _resolvedAccessibleName = '';\n\n /** @internal */\n private _clampedValue(): number {\n return Math.min(Math.max(this.value, this.min), this.max);\n }\n\n /** @internal */\n private _percentage(): number {\n const range = this.max - this.min;\n if (range === 0) return 0;\n return ((this._clampedValue() - this.min) / range) * 100;\n }\n\n /** @internal */\n private _resolveState(): MeterState {\n const v = this._clampedValue();\n const hasLow = this.low !== undefined;\n const hasHigh = this.high !== undefined;\n const hasOptimum = this.optimum !== undefined;\n\n if (!hasLow && !hasHigh && !hasOptimum) return 'default';\n\n const lowVal = this.low ?? 0;\n const highVal = this.high ?? this.max;\n const inLowZone = hasLow && v < lowVal;\n const inHighZone = hasHigh && v > highVal;\n const inMiddleZone = !inLowZone && !inHighZone;\n\n if (!hasOptimum) {\n if (inLowZone || inHighZone) return 'warning';\n return 'optimum';\n }\n\n const opt = this.optimum ?? this.min;\n const optimumInLow = hasLow && opt < lowVal;\n const optimumInHigh = hasHigh && opt > highVal;\n const optimumInMiddle = !optimumInLow && !optimumInHigh;\n\n if (optimumInMiddle) {\n if (inMiddleZone) return 'optimum';\n return 'warning';\n } else if (optimumInLow) {\n if (inLowZone) return 'optimum';\n if (inMiddleZone) return 'warning';\n return 'danger';\n } else {\n // optimumInHigh\n if (inHighZone) return 'optimum';\n if (inMiddleZone) return 'warning';\n return 'danger';\n }\n }\n\n /** @internal */\n private _onLabelSlotChange(e: Event) {\n const slot = e.target as HTMLSlotElement;\n this._hasSlotContent = slot.assignedNodes({ flatten: true }).length > 0;\n this._syncHostAriaSemantics();\n }\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n const ctor = this.constructor as typeof HelixMeter;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n this._syncHostAriaSemantics();\n this._ariaMirror = installAriaIdrefMirror(this, () => {\n this._syncHostAriaSemantics();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n this.dataset['state'] = this._resolveState();\n const ratio = this._percentage() / 100;\n this.style.setProperty('--_value-ratio', String(Math.max(0, Math.min(1, ratio))));\n if (\n changedProperties.has('value') ||\n changedProperties.has('min') ||\n changedProperties.has('max') ||\n changedProperties.has('low') ||\n changedProperties.has('high') ||\n changedProperties.has('optimum') ||\n changedProperties.has('label')\n ) {\n this._syncHostAriaSemantics();\n }\n }\n\n /**\n * Mirror meter semantics onto the host via ElementInternals. The inner\n * `[role=\"meter\"]` keeps its existing surface — this method ADDS a host-\n * level surface via internals.* so consumer-supplied `aria-labelledby` /\n * `aria-describedby` on the host project through `ariaLabelledByElements`\n * (cross-shadow IDREF) on engines that support it. Mirrors hx-progress-ring's\n * dual-surface pattern (Group 7 gold-standard exemplar).\n * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n const clampedValue = this._clampedValue();\n const state = this._resolveState();\n const stateLabel = state !== 'default' ? ` — ${state}` : '';\n const ariaValuetext = `${clampedValue} of ${this.max}${stateLabel}`;\n\n if (this._supportsIdrefRefs) {\n internals.role = 'meter';\n internals.ariaValueNow = String(clampedValue);\n internals.ariaValueMin = String(this.min);\n internals.ariaValueMax = String(this.max);\n internals.ariaValueText = ariaValuetext;\n } else {\n // Legacy engines: clear host-internals so the inner [role=\"meter\"] is\n // the only announced surface (avoids the duplicate-surface problem).\n internals.role = null;\n internals.ariaLabel = null;\n internals.ariaValueNow = null;\n internals.ariaValueMin = null;\n internals.ariaValueMax = null;\n internals.ariaValueText = 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 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 '';\n resolved = flattened || ariaValuetext;\n if (this._supportsIdrefRefs) {\n // Modern path: element refs win; clear ariaLabel so they aren't\n // shadowed by a stale string on the host.\n internals.ariaLabel = null;\n }\n } else if (hostAriaLabel) {\n resolved = hostAriaLabel;\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = hostAriaLabel;\n }\n } else if (this._hasSlotContent || this.label !== undefined) {\n resolved = this.label ?? '';\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = resolved || null;\n }\n } else {\n resolved = ariaValuetext;\n if (this._supportsIdrefRefs) {\n internals.ariaLabel = resolved;\n }\n }\n\n this._resolvedAccessibleName = resolved;\n }\n\n // ─── WCAG 1.4.1: State label map ───\n\n /** @internal */\n private static readonly _STATE_LABELS: Partial<Record<MeterState, string>> = {\n optimum: 'Optimum',\n warning: 'Warning',\n danger: 'Danger',\n };\n\n override render() {\n const state = this._resolveState();\n const clampedValue = this._clampedValue();\n const stateLabel = state !== 'default' ? ` — ${state}` : '';\n const ariaValuetext = `${clampedValue} of ${this.max}${stateLabel}`;\n const hasVisibleLabel = this.label !== undefined || this._hasSlotContent;\n const visibleStateLabel = HelixMeter._STATE_LABELS[state];\n\n // Inner element keeps role + value-state surface for legacy AT and\n // existing consumer queries. The host carries the cross-shadow IDREF\n // wiring via internals.* (see _syncHostAriaSemantics).\n return html`\n <div\n part=\"base\"\n class=\"meter\"\n role=\"meter\"\n tabindex=\"0\"\n aria-valuenow=${clampedValue}\n aria-valuemin=${this.min}\n aria-valuemax=${this.max}\n aria-valuetext=${ariaValuetext}\n aria-label=${ifDefined(!hasVisibleLabel ? `${clampedValue} of ${this.max}` : undefined)}\n aria-labelledby=${ifDefined(hasVisibleLabel ? `${this._uid}-label` : undefined)}\n >\n <span\n id=${`${this._uid}-label`}\n part=\"label\"\n class=\"meter__label\"\n ?hidden=${!hasVisibleLabel}\n >\n <slot name=\"label\" @slotchange=${this._onLabelSlotChange}>${this.label ?? ''}</slot>\n </span>\n <div class=\"meter__track\" part=\"track\">\n <div part=\"indicator\" class=\"meter__indicator\"></div>\n </div>\n ${visibleStateLabel\n ? html`<span class=\"meter__state-label\" data-state=${state} aria-hidden=\"true\"\n >${visibleStateLabel}</span\n >`\n : nothing}\n <meter\n class=\"meter__native\"\n value=${clampedValue}\n min=${this.min}\n max=${this.max}\n low=${ifDefined(this.low)}\n high=${ifDefined(this.high)}\n optimum=${ifDefined(this.optimum)}\n aria-hidden=\"true\"\n tabindex=\"-1\"\n ></meter>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-meter': HelixMeter;\n }\n}\n"],"names":["helixMeterStyles","css","_nextMeterId","createIdCounter","HelixMeter","HelixElement","range","v","hasLow","hasHigh","hasOptimum","lowVal","highVal","inLowZone","inHighZone","inMiddleZone","opt","optimumInLow","optimumInHigh","slot","ctor","supportsIdrefElementReferences","installAriaIdrefMirror","_a","changedProperties","ratio","internals","clampedValue","state","stateLabel","ariaValuetext","hostAriaLabel","consumerLabelledBy","labelEls","resolveIdrefTokens","hasEffectiveLabelledBy","refsInternals","resolved","el","flattenAccName","hasVisibleLabel","visibleStateLabel","html","ifDefined","nothing","forcedColorsSurface","__decorateClass","property","customElement"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { css as A, html as h, nothing as c } from "lit";
2
2
  import { property as p, customElement as T, state as $ } from "lit/decorators.js";
3
3
  import { H as I } from "./helix-element-BNEYeiys.js";
4
4
  import { c as E } from "./id-counter-DuX8vsui.js";
5
- const H = A`
5
+ const S = A`
6
6
  :host {
7
7
  display: block;
8
8
  height: 100%;
@@ -207,10 +207,10 @@ const H = A`
207
207
  }
208
208
  }
209
209
  `;
210
- var S = Object.defineProperty, B = Object.getOwnPropertyDescriptor, u = (e, o, a, i) => {
210
+ var H = Object.defineProperty, B = Object.getOwnPropertyDescriptor, u = (e, o, a, i) => {
211
211
  for (var t = i > 1 ? void 0 : i ? B(o, a) : o, l = e.length - 1, n; l >= 0; l--)
212
212
  (n = e[l]) && (t = (i ? n(o, a, t) : n(t)) || t);
213
- return i && t && S(o, a, t), t;
213
+ return i && t && H(o, a, t), t;
214
214
  };
215
215
  let x = class extends I {
216
216
  constructor() {
@@ -367,7 +367,7 @@ let x = class extends I {
367
367
  `;
368
368
  }
369
369
  };
370
- x.styles = [H];
370
+ x.styles = [S];
371
371
  u([
372
372
  p({ type: Boolean, reflect: !0 })
373
373
  ], x.prototype, "collapsed", 2);
@@ -656,11 +656,15 @@ const D = A`
656
656
  border-color: Highlight;
657
657
  }
658
658
 
659
- :host([disabled]) {
660
- opacity: 1;
661
- }
662
-
659
+ /*
660
+ * Reset opacity on the SAME selector that sets it (.nav-item__link, line
661
+ * 109) — the original :host([disabled]) reset was scoped to the host and
662
+ * therefore had no effect on the link's 0.5 opacity. In forced-colors mode
663
+ * GrayText must render at full opacity to preserve the system contrast
664
+ * contract (WCAG 2.1 AA non-text contrast).
665
+ */
663
666
  :host([disabled]) .nav-item__link {
667
+ opacity: 1;
664
668
  color: GrayText;
665
669
  border-color: GrayText;
666
670
  }
@@ -809,4 +813,4 @@ export {
809
813
  d as H,
810
814
  x as a
811
815
  };
812
- //# sourceMappingURL=hx-nav-item-xqRPOCWX.js.map
816
+ //# sourceMappingURL=hx-nav-item-CODtUlew.js.map