@helixui/library 3.6.0 → 3.8.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 (280) hide show
  1. package/custom-elements.json +2633 -805
  2. package/dist/components/hx-action-bar/hx-action-bar.d.ts +18 -0
  3. package/dist/components/hx-action-bar/hx-action-bar.d.ts.map +1 -1
  4. package/dist/components/hx-action-bar/hx-action-bar.styles.d.ts.map +1 -1
  5. package/dist/components/hx-action-bar/index.js +1 -1
  6. package/dist/components/hx-alert/hx-alert.d.ts +18 -0
  7. package/dist/components/hx-alert/hx-alert.d.ts.map +1 -1
  8. package/dist/components/hx-badge/index.js +1 -1
  9. package/dist/components/hx-banner/hx-banner.d.ts +19 -0
  10. package/dist/components/hx-banner/hx-banner.d.ts.map +1 -1
  11. package/dist/components/hx-breadcrumb/hx-breadcrumb-item.d.ts.map +1 -1
  12. package/dist/components/hx-breadcrumb/hx-breadcrumb-item.styles.d.ts.map +1 -1
  13. package/dist/components/hx-breadcrumb/hx-breadcrumb.d.ts +18 -0
  14. package/dist/components/hx-breadcrumb/hx-breadcrumb.d.ts.map +1 -1
  15. package/dist/components/hx-breadcrumb/index.js +1 -1
  16. package/dist/components/hx-button/hx-button.d.ts +18 -0
  17. package/dist/components/hx-button/hx-button.d.ts.map +1 -1
  18. package/dist/components/hx-button/hx-button.styles.d.ts.map +1 -1
  19. package/dist/components/hx-button/index.js +1 -1
  20. package/dist/components/hx-button-group/hx-button-group.d.ts +47 -0
  21. package/dist/components/hx-button-group/hx-button-group.d.ts.map +1 -1
  22. package/dist/components/hx-button-group/index.js +1 -1
  23. package/dist/components/hx-checkbox/hx-checkbox.d.ts +18 -0
  24. package/dist/components/hx-checkbox/hx-checkbox.d.ts.map +1 -1
  25. package/dist/components/hx-checkbox/hx-checkbox.styles.d.ts.map +1 -1
  26. package/dist/components/hx-checkbox/index.js +1 -1
  27. package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts +36 -0
  28. package/dist/components/hx-checkbox-group/hx-checkbox-group.d.ts.map +1 -1
  29. package/dist/components/hx-checkbox-group/hx-checkbox-group.styles.d.ts.map +1 -1
  30. package/dist/components/hx-checkbox-group/index.js +1 -1
  31. package/dist/components/hx-clinical-status/hx-clinical-status.d.ts +19 -0
  32. package/dist/components/hx-clinical-status/hx-clinical-status.d.ts.map +1 -1
  33. package/dist/components/hx-color-picker/hx-color-picker.d.ts +18 -0
  34. package/dist/components/hx-color-picker/hx-color-picker.d.ts.map +1 -1
  35. package/dist/components/hx-color-picker/hx-color-picker.styles.d.ts.map +1 -1
  36. package/dist/components/hx-color-picker/index.js +1 -1
  37. package/dist/components/hx-combobox/hx-combobox.d.ts +18 -0
  38. package/dist/components/hx-combobox/hx-combobox.d.ts.map +1 -1
  39. package/dist/components/hx-copy-button/hx-copy-button.d.ts +18 -0
  40. package/dist/components/hx-copy-button/hx-copy-button.d.ts.map +1 -1
  41. package/dist/components/hx-copy-button/hx-copy-button.styles.d.ts.map +1 -1
  42. package/dist/components/hx-copy-button/index.js +1 -1
  43. package/dist/components/hx-date-picker/hx-date-picker.d.ts +18 -0
  44. package/dist/components/hx-date-picker/hx-date-picker.d.ts.map +1 -1
  45. package/dist/components/hx-date-picker/hx-date-picker.styles.d.ts.map +1 -1
  46. package/dist/components/hx-date-picker/index.js +1 -1
  47. package/dist/components/hx-dialog/hx-dialog.d.ts +18 -0
  48. package/dist/components/hx-dialog/hx-dialog.d.ts.map +1 -1
  49. package/dist/components/hx-drawer/hx-drawer.d.ts +18 -0
  50. package/dist/components/hx-drawer/hx-drawer.d.ts.map +1 -1
  51. package/dist/components/hx-dropdown/hx-dropdown.d.ts +18 -0
  52. package/dist/components/hx-dropdown/hx-dropdown.d.ts.map +1 -1
  53. package/dist/components/hx-dropdown/hx-dropdown.styles.d.ts.map +1 -1
  54. package/dist/components/hx-dropdown/index.js +1 -1
  55. package/dist/components/hx-field/hx-field.d.ts +17 -0
  56. package/dist/components/hx-field/hx-field.d.ts.map +1 -1
  57. package/dist/components/hx-field-label/hx-field-label.d.ts +17 -0
  58. package/dist/components/hx-field-label/hx-field-label.d.ts.map +1 -1
  59. package/dist/components/hx-file-upload/hx-file-upload.d.ts +18 -0
  60. package/dist/components/hx-file-upload/hx-file-upload.d.ts.map +1 -1
  61. package/dist/components/hx-form/hx-form.d.ts +19 -0
  62. package/dist/components/hx-form/hx-form.d.ts.map +1 -1
  63. package/dist/components/hx-help-text/hx-help-text.d.ts +17 -0
  64. package/dist/components/hx-help-text/hx-help-text.d.ts.map +1 -1
  65. package/dist/components/hx-icon-button/hx-icon-button.d.ts +18 -0
  66. package/dist/components/hx-icon-button/hx-icon-button.d.ts.map +1 -1
  67. package/dist/components/hx-icon-button/hx-icon-button.styles.d.ts.map +1 -1
  68. package/dist/components/hx-icon-button/index.js +1 -1
  69. package/dist/components/hx-menu/hx-menu.d.ts +18 -0
  70. package/dist/components/hx-menu/hx-menu.d.ts.map +1 -1
  71. package/dist/components/hx-nav/hx-nav.d.ts +18 -0
  72. package/dist/components/hx-nav/hx-nav.d.ts.map +1 -1
  73. package/dist/components/hx-nav/hx-nav.styles.d.ts.map +1 -1
  74. package/dist/components/hx-nav/index.js +1 -1
  75. package/dist/components/hx-number-input/hx-number-input.d.ts +18 -0
  76. package/dist/components/hx-number-input/hx-number-input.d.ts.map +1 -1
  77. package/dist/components/hx-number-input/index.js +1 -1
  78. package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts +18 -0
  79. package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts.map +1 -1
  80. package/dist/components/hx-pagination/hx-pagination.styles.d.ts.map +1 -1
  81. package/dist/components/hx-pagination/index.js +1 -1
  82. package/dist/components/hx-popover/hx-popover.d.ts +18 -0
  83. package/dist/components/hx-popover/hx-popover.d.ts.map +1 -1
  84. package/dist/components/hx-popover/hx-popover.styles.d.ts.map +1 -1
  85. package/dist/components/hx-popover/index.js +1 -1
  86. package/dist/components/hx-popup/hx-popup.d.ts +18 -0
  87. package/dist/components/hx-popup/hx-popup.d.ts.map +1 -1
  88. package/dist/components/hx-popup/hx-popup.styles.d.ts.map +1 -1
  89. package/dist/components/hx-popup/index.js +1 -1
  90. package/dist/components/hx-radio-group/hx-radio-group.d.ts +18 -0
  91. package/dist/components/hx-radio-group/hx-radio-group.d.ts.map +1 -1
  92. package/dist/components/hx-radio-group/hx-radio-group.styles.d.ts.map +1 -1
  93. package/dist/components/hx-radio-group/hx-radio.styles.d.ts.map +1 -1
  94. package/dist/components/hx-radio-group/index.js +1 -1
  95. package/dist/components/hx-rating/hx-rating.d.ts +19 -0
  96. package/dist/components/hx-rating/hx-rating.d.ts.map +1 -1
  97. package/dist/components/hx-select/hx-select.d.ts +18 -0
  98. package/dist/components/hx-select/hx-select.d.ts.map +1 -1
  99. package/dist/components/hx-side-nav/hx-side-nav.d.ts +18 -0
  100. package/dist/components/hx-side-nav/hx-side-nav.d.ts.map +1 -1
  101. package/dist/components/hx-side-nav/hx-side-nav.styles.d.ts.map +1 -1
  102. package/dist/components/hx-side-nav/index.js +1 -1
  103. package/dist/components/hx-slider/hx-slider.d.ts +19 -0
  104. package/dist/components/hx-slider/hx-slider.d.ts.map +1 -1
  105. package/dist/components/hx-split-button/hx-split-button.d.ts +18 -0
  106. package/dist/components/hx-split-button/hx-split-button.d.ts.map +1 -1
  107. package/dist/components/hx-split-button/hx-split-button.styles.d.ts.map +1 -1
  108. package/dist/components/hx-split-button/index.js +1 -1
  109. package/dist/components/hx-steps/index.js +1 -1
  110. package/dist/components/hx-switch/hx-switch.d.ts +18 -0
  111. package/dist/components/hx-switch/hx-switch.d.ts.map +1 -1
  112. package/dist/components/hx-switch/hx-switch.styles.d.ts.map +1 -1
  113. package/dist/components/hx-switch/index.js +1 -1
  114. package/dist/components/hx-tabs/hx-tab.styles.d.ts.map +1 -1
  115. package/dist/components/hx-tabs/hx-tabs.d.ts +18 -0
  116. package/dist/components/hx-tabs/hx-tabs.d.ts.map +1 -1
  117. package/dist/components/hx-tabs/index.js +1 -1
  118. package/dist/components/hx-text-input/hx-text-input.d.ts +18 -0
  119. package/dist/components/hx-text-input/hx-text-input.d.ts.map +1 -1
  120. package/dist/components/hx-text-input/hx-text-input.styles.d.ts.map +1 -1
  121. package/dist/components/hx-text-input/index.js +1 -1
  122. package/dist/components/hx-textarea/hx-textarea.d.ts +18 -0
  123. package/dist/components/hx-textarea/hx-textarea.d.ts.map +1 -1
  124. package/dist/components/hx-time-picker/hx-time-picker.d.ts +18 -0
  125. package/dist/components/hx-time-picker/hx-time-picker.d.ts.map +1 -1
  126. package/dist/components/hx-time-picker/hx-time-picker.styles.d.ts.map +1 -1
  127. package/dist/components/hx-time-picker/index.js +1 -1
  128. package/dist/components/hx-toast/hx-toast.d.ts +19 -0
  129. package/dist/components/hx-toast/hx-toast.d.ts.map +1 -1
  130. package/dist/components/hx-toggle-button/hx-toggle-button.d.ts +18 -0
  131. package/dist/components/hx-toggle-button/hx-toggle-button.d.ts.map +1 -1
  132. package/dist/components/hx-toggle-button/hx-toggle-button.styles.d.ts.map +1 -1
  133. package/dist/components/hx-toggle-button/index.js +1 -1
  134. package/dist/components/hx-tooltip/hx-tooltip.d.ts +18 -0
  135. package/dist/components/hx-tooltip/hx-tooltip.d.ts.map +1 -1
  136. package/dist/components/hx-tooltip/hx-tooltip.styles.d.ts.map +1 -1
  137. package/dist/components/hx-tooltip/index.js +1 -1
  138. package/dist/components/hx-top-nav/hx-top-nav.d.ts +18 -0
  139. package/dist/components/hx-top-nav/hx-top-nav.d.ts.map +1 -1
  140. package/dist/components/hx-top-nav/hx-top-nav.styles.d.ts.map +1 -1
  141. package/dist/components/hx-top-nav/index.js +1 -1
  142. package/dist/css/helix-all.css +298 -64
  143. package/dist/css/helix-core.css +24 -15
  144. package/dist/css/helix-forms.css +133 -32
  145. package/dist/css/helix-navigation.css +49 -5
  146. package/dist/css/helix-overlay.css +53 -0
  147. package/dist/css/helix-tokens.css +15 -13
  148. package/dist/css/helix-utility.css +39 -12
  149. package/dist/css/hx-action-bar.css +12 -0
  150. package/dist/css/hx-badge.css +5 -5
  151. package/dist/css/hx-button.css +15 -5
  152. package/dist/css/hx-checkbox-group.css +11 -0
  153. package/dist/css/hx-checkbox.css +20 -4
  154. package/dist/css/hx-color-picker.css +14 -1
  155. package/dist/css/hx-copy-button.css +5 -2
  156. package/dist/css/hx-date-picker.css +11 -3
  157. package/dist/css/hx-dropdown.css +13 -0
  158. package/dist/css/hx-icon-button.css +4 -5
  159. package/dist/css/hx-nav.css +24 -2
  160. package/dist/css/hx-number-input.css +8 -8
  161. package/dist/css/hx-pagination.css +6 -3
  162. package/dist/css/hx-popover.css +13 -0
  163. package/dist/css/hx-popup.css +14 -0
  164. package/dist/css/hx-radio-group.css +10 -0
  165. package/dist/css/hx-side-nav.css +7 -0
  166. package/dist/css/hx-split-button.css +22 -10
  167. package/dist/css/hx-switch.css +19 -1
  168. package/dist/css/hx-text-input.css +4 -1
  169. package/dist/css/hx-time-picker.css +7 -2
  170. package/dist/css/hx-toggle-button.css +29 -12
  171. package/dist/css/hx-tooltip.css +13 -0
  172. package/dist/css/hx-top-nav.css +12 -0
  173. package/dist/css/index.css +1 -1
  174. package/dist/css/manifest.json +57 -20
  175. package/dist/index.js +28 -28
  176. package/dist/shared/{hx-action-bar-CitgcpGv.js → hx-action-bar-BlEG4aZv.js} +41 -29
  177. package/dist/shared/hx-action-bar-BlEG4aZv.js.map +1 -0
  178. package/dist/shared/hx-alert-Bto8-TIi.js.map +1 -1
  179. package/dist/shared/{hx-badge-JlFtAdxS.js → hx-badge-DFL35nzi.js} +16 -16
  180. package/dist/shared/hx-badge-DFL35nzi.js.map +1 -0
  181. package/dist/shared/hx-banner-fpRnciIO.js.map +1 -1
  182. package/dist/shared/{hx-breadcrumb-item-3tKppF9h.js → hx-breadcrumb-item-D8xYqe3s.js} +56 -43
  183. package/dist/shared/hx-breadcrumb-item-D8xYqe3s.js.map +1 -0
  184. package/dist/shared/{hx-button-BOwAEcF1.js → hx-button-DOZTZnz-.js} +29 -19
  185. package/dist/shared/hx-button-DOZTZnz-.js.map +1 -0
  186. package/dist/shared/hx-button-group-D3QUmSzl.js +248 -0
  187. package/dist/shared/hx-button-group-D3QUmSzl.js.map +1 -0
  188. package/dist/shared/{hx-checkbox-CYd0YV_u.js → hx-checkbox-DcgyGS9V.js} +27 -11
  189. package/dist/shared/hx-checkbox-DcgyGS9V.js.map +1 -0
  190. package/dist/shared/{hx-checkbox-group-D5piJLY8.js → hx-checkbox-group-C0q6HDqn.js} +101 -58
  191. package/dist/shared/hx-checkbox-group-C0q6HDqn.js.map +1 -0
  192. package/dist/shared/hx-clinical-status-D3XQIOqX.js.map +1 -1
  193. package/dist/shared/{hx-color-picker-DBwJzT5f.js → hx-color-picker-CYjx8i8R.js} +97 -84
  194. package/dist/shared/hx-color-picker-CYjx8i8R.js.map +1 -0
  195. package/dist/shared/hx-combobox-NgJaLbs2.js.map +1 -1
  196. package/dist/shared/{hx-copy-button-sUVuikyH.js → hx-copy-button-DJirFCUL.js} +18 -15
  197. package/dist/shared/hx-copy-button-DJirFCUL.js.map +1 -0
  198. package/dist/shared/{hx-date-picker-B49yo4Vm.js → hx-date-picker-0PtEav0K.js} +71 -63
  199. package/dist/shared/hx-date-picker-0PtEav0K.js.map +1 -0
  200. package/dist/shared/hx-dialog-B4weoj_1.js.map +1 -1
  201. package/dist/shared/hx-drawer-CM_upadk.js.map +1 -1
  202. package/dist/shared/{hx-dropdown-D626S2ZG.js → hx-dropdown-xHwTJecv.js} +44 -31
  203. package/dist/shared/hx-dropdown-xHwTJecv.js.map +1 -0
  204. package/dist/shared/hx-field-label-BVRyyKeh.js.map +1 -1
  205. package/dist/shared/hx-field-zw0U1KVi.js.map +1 -1
  206. package/dist/shared/hx-file-upload-D3rKROK5.js.map +1 -1
  207. package/dist/shared/hx-form-CkChEATa.js.map +1 -1
  208. package/dist/shared/hx-help-text-Xb2Yr8x2.js.map +1 -1
  209. package/dist/shared/{hx-icon-button-a6OpeQz5.js → hx-icon-button-B2BdVdyK.js} +10 -11
  210. package/dist/shared/hx-icon-button-B2BdVdyK.js.map +1 -0
  211. package/dist/shared/hx-menu-divider-A6Guuzi_.js.map +1 -1
  212. package/dist/shared/{hx-nav-ldFM3Fle.js → hx-nav-ChMTfn7o.js} +66 -44
  213. package/dist/shared/hx-nav-ChMTfn7o.js.map +1 -0
  214. package/dist/shared/{hx-nav-item-CODtUlew.js → hx-nav-item-ClN17f1y.js} +62 -55
  215. package/dist/shared/hx-nav-item-ClN17f1y.js.map +1 -0
  216. package/dist/shared/{hx-number-input-yUzFOSC1.js → hx-number-input-MggsT7F0.js} +13 -13
  217. package/dist/shared/hx-number-input-MggsT7F0.js.map +1 -0
  218. package/dist/shared/hx-overflow-menu-DFjJAziP.js.map +1 -1
  219. package/dist/shared/{hx-pagination-C7y8GVyU.js → hx-pagination-D726PyTM.js} +7 -4
  220. package/dist/shared/hx-pagination-D726PyTM.js.map +1 -0
  221. package/dist/shared/{hx-popover-BAlAFOH9.js → hx-popover-BjB0nkcq.js} +51 -38
  222. package/dist/shared/hx-popover-BjB0nkcq.js.map +1 -0
  223. package/dist/shared/{hx-popup-COUXXZ9X.js → hx-popup-BiV_2evC.js} +59 -45
  224. package/dist/shared/hx-popup-BiV_2evC.js.map +1 -0
  225. package/dist/shared/{hx-radio-C7eTj5YI.js → hx-radio-BY4zpwdh.js} +81 -63
  226. package/dist/shared/hx-radio-BY4zpwdh.js.map +1 -0
  227. package/dist/shared/hx-rating-C3QP53k9.js.map +1 -1
  228. package/dist/shared/hx-select-DahFehiZ.js.map +1 -1
  229. package/dist/shared/hx-slider-Blmv_rwS.js.map +1 -1
  230. package/dist/shared/{hx-split-button-Ddle8iVx.js → hx-split-button-CdNz1XAu.js} +62 -50
  231. package/dist/shared/hx-split-button-CdNz1XAu.js.map +1 -0
  232. package/dist/shared/{hx-step-R2rjp1fT.js → hx-step-CUzliIK_.js} +3 -3
  233. package/dist/shared/hx-step-CUzliIK_.js.map +1 -0
  234. package/dist/shared/{hx-switch-TvKGvZJz.js → hx-switch-BCXuNxEH.js} +42 -24
  235. package/dist/shared/hx-switch-BCXuNxEH.js.map +1 -0
  236. package/dist/shared/{hx-tab-panel-DzsX8BHV.js → hx-tab-panel-BfisavKo.js} +47 -32
  237. package/dist/shared/hx-tab-panel-BfisavKo.js.map +1 -0
  238. package/dist/shared/{hx-text-input-D6FlOZM-.js → hx-text-input-V5sQOpDh.js} +5 -2
  239. package/dist/shared/hx-text-input-V5sQOpDh.js.map +1 -0
  240. package/dist/shared/hx-textarea-CNG590KY.js.map +1 -1
  241. package/dist/shared/{hx-time-picker-Bo7FWzmf.js → hx-time-picker-DfJkBwcX.js} +41 -36
  242. package/dist/shared/hx-time-picker-DfJkBwcX.js.map +1 -0
  243. package/dist/shared/{hx-toggle-button-DwBers3A.js → hx-toggle-button-xNVYeA3X.js} +64 -47
  244. package/dist/shared/hx-toggle-button-xNVYeA3X.js.map +1 -0
  245. package/dist/shared/{hx-tooltip-DVqtKPCD.js → hx-tooltip-CamO-9nd.js} +24 -11
  246. package/dist/shared/hx-tooltip-CamO-9nd.js.map +1 -0
  247. package/dist/shared/{hx-top-nav-DP6OFS8C.js → hx-top-nav-CsTxOtVI.js} +26 -14
  248. package/dist/shared/hx-top-nav-CsTxOtVI.js.map +1 -0
  249. package/dist/shared/toast-factory-Dht3pVsw.js.map +1 -1
  250. package/figma-inventory.json +1258 -386
  251. package/package.json +2 -2
  252. package/dist/shared/hx-action-bar-CitgcpGv.js.map +0 -1
  253. package/dist/shared/hx-badge-JlFtAdxS.js.map +0 -1
  254. package/dist/shared/hx-breadcrumb-item-3tKppF9h.js.map +0 -1
  255. package/dist/shared/hx-button-BOwAEcF1.js.map +0 -1
  256. package/dist/shared/hx-button-group-4NUBpkyC.js +0 -181
  257. package/dist/shared/hx-button-group-4NUBpkyC.js.map +0 -1
  258. package/dist/shared/hx-checkbox-CYd0YV_u.js.map +0 -1
  259. package/dist/shared/hx-checkbox-group-D5piJLY8.js.map +0 -1
  260. package/dist/shared/hx-color-picker-DBwJzT5f.js.map +0 -1
  261. package/dist/shared/hx-copy-button-sUVuikyH.js.map +0 -1
  262. package/dist/shared/hx-date-picker-B49yo4Vm.js.map +0 -1
  263. package/dist/shared/hx-dropdown-D626S2ZG.js.map +0 -1
  264. package/dist/shared/hx-icon-button-a6OpeQz5.js.map +0 -1
  265. package/dist/shared/hx-nav-item-CODtUlew.js.map +0 -1
  266. package/dist/shared/hx-nav-ldFM3Fle.js.map +0 -1
  267. package/dist/shared/hx-number-input-yUzFOSC1.js.map +0 -1
  268. package/dist/shared/hx-pagination-C7y8GVyU.js.map +0 -1
  269. package/dist/shared/hx-popover-BAlAFOH9.js.map +0 -1
  270. package/dist/shared/hx-popup-COUXXZ9X.js.map +0 -1
  271. package/dist/shared/hx-radio-C7eTj5YI.js.map +0 -1
  272. package/dist/shared/hx-split-button-Ddle8iVx.js.map +0 -1
  273. package/dist/shared/hx-step-R2rjp1fT.js.map +0 -1
  274. package/dist/shared/hx-switch-TvKGvZJz.js.map +0 -1
  275. package/dist/shared/hx-tab-panel-DzsX8BHV.js.map +0 -1
  276. package/dist/shared/hx-text-input-D6FlOZM-.js.map +0 -1
  277. package/dist/shared/hx-time-picker-Bo7FWzmf.js.map +0 -1
  278. package/dist/shared/hx-toggle-button-DwBers3A.js.map +0 -1
  279. package/dist/shared/hx-tooltip-DVqtKPCD.js.map +0 -1
  280. package/dist/shared/hx-top-nav-DP6OFS8C.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"hx-combobox-NgJaLbs2.js","sources":["../../src/components/hx-combobox/hx-combobox.styles.ts","../../src/components/hx-combobox/hx-combobox.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixComboboxStyles = css`\n :host {\n display: block;\n }\n :host([disabled]) {\n opacity: var(--hx-opacity-disabled, 0.5);\n pointer-events: none;\n }\n * {\n box-sizing: border-box;\n }\n .field {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n font-family: var(--hx-combobox-font-family, var(--hx-font-family-sans, sans-serif));\n position: relative;\n }\n .field__label {\n display: flex;\n align-items: baseline;\n gap: var(--hx-space-1, 0.25rem);\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n color: var(--hx-combobox-label-color, var(--hx-color-text-strong, #202b39));\n line-height: var(--hx-line-height-normal, 1.5);\n }\n .field__required-marker {\n color: var(--hx-combobox-error-color, var(--hx-color-error-text, #c92a2a));\n font-weight: var(--hx-font-weight-bold, 700);\n }\n .field__input-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-combobox-border-color, var(--hx-color-border-strong, #66787b));\n border-radius: var(--hx-combobox-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-combobox-bg, var(--hx-color-surface-default, #ffffff));\n transition:\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n }\n .field__input-wrapper:focus-within {\n border-color: var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)\n color-mix(\n in srgb,\n var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078))\n calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n .field--error .field__input-wrapper {\n border-color: var(--hx-combobox-error-color, var(--hx-color-error-500, #e5493e));\n }\n .field--error .field__input-wrapper:focus-within {\n border-color: var(--hx-combobox-error-color, var(--hx-color-error-500, #e5493e));\n box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)\n color-mix(\n in srgb,\n var(--hx-combobox-error-color, var(--hx-color-error-500, #e5493e))\n calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n .field__prefix,\n .field__suffix {\n display: flex;\n align-items: center;\n padding: 0 var(--hx-space-2, 0.5rem);\n color: var(--hx-color-text-muted, #4a5362);\n flex-shrink: 0;\n }\n .field__input {\n flex: 1;\n min-width: 0;\n min-height: var(--hx-input-height-md, var(--hx-size-10, 2.5rem));\n border: none;\n background: transparent;\n outline: none;\n font-family: inherit;\n font-size: var(--hx-font-size-md, 1rem);\n line-height: var(--hx-line-height-normal, 1.5);\n color: var(--hx-combobox-color, var(--hx-color-text-strong, #202b39));\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n }\n .field__input::placeholder {\n color: var(--hx-color-text-placeholder, #66787b);\n }\n .field__input--sm {\n min-height: var(--hx-input-height-sm, var(--hx-size-8, 2rem));\n font-size: var(--hx-font-size-sm, 0.875rem);\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-3, 0.75rem);\n }\n .field__input--lg {\n min-height: var(--hx-input-height-lg, var(--hx-size-12, 3rem));\n font-size: var(--hx-font-size-lg, 1.125rem);\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n }\n .field__clear-button,\n .field__loading-indicator {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-inline-end: var(--hx-space-2, 0.5rem);\n flex-shrink: 0;\n color: var(--hx-color-text-placeholder, #66787b);\n }\n .field__clear-button {\n width: 1.25rem;\n height: 1.25rem;\n border: none;\n background: transparent;\n cursor: pointer;\n padding: 0;\n border-radius: var(--hx-border-radius-full, 9999px);\n transition: color var(--hx-transition-fast, 150ms ease);\n }\n .field__clear-button:hover {\n color: var(--hx-color-text-strong, #202b39);\n }\n .field__clear-button:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n .field__loading-indicator {\n width: 1rem;\n height: 1rem;\n }\n .field__loading-spinner {\n width: 1rem;\n height: 1rem;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: hx-spin 0.7s linear infinite;\n }\n @keyframes hx-spin {\n to {\n transform: rotate(360deg);\n }\n }\n @media (prefers-reduced-motion: reduce) {\n .field__loading-spinner {\n animation: none;\n }\n }\n .field__listbox {\n position: absolute;\n top: calc(100% + var(--hx-space-1, 0.25rem));\n left: 0;\n right: 0;\n z-index: var(--hx-z-index-dropdown, 1000);\n background-color: var(--hx-combobox-listbox-bg, var(--hx-color-surface-default, #ffffff));\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-combobox-border-color, var(--hx-color-border-strong, #66787b));\n border-radius: var(--hx-combobox-border-radius, var(--hx-border-radius-md, 0.375rem));\n box-shadow: var(\n --hx-combobox-listbox-shadow,\n 0 4px 16px color-mix(in srgb, var(--hx-color-neutral-900, #0d1825) 12%, transparent)\n );\n max-height: var(--hx-combobox-listbox-max-height, 16rem);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n .field__listbox[hidden] {\n display: none;\n }\n .field__options {\n overflow-y: auto;\n flex: 1;\n padding: var(--hx-space-1, 0.25rem) 0;\n }\n .field__option {\n display: flex;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-md, 1rem);\n color: var(--hx-combobox-color, var(--hx-color-text-strong, #202b39));\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n transition: background-color var(--hx-transition-fast, 150ms ease);\n }\n .field__option:hover {\n background-color: var(--hx-combobox-option-hover-bg, var(--hx-color-primary-50, #ebf8f8));\n }\n .field__option--selected {\n background-color: var(--hx-combobox-option-selected-bg, var(--hx-color-primary-100, #dbf0f0));\n font-weight: var(--hx-font-weight-medium, 500);\n }\n .field__option--focused {\n background-color: var(--hx-combobox-option-hover-bg, var(--hx-color-primary-50, #ebf8f8));\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-combobox-option-focus-ring-offset, -2px);\n }\n .field__option--focused.field__option--selected {\n background-color: var(--hx-combobox-option-selected-bg, var(--hx-color-primary-100, #dbf0f0));\n }\n .field__option--disabled {\n opacity: var(--hx-opacity-disabled, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n .field__option-label {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .field__no-options {\n padding: var(--hx-space-3, 0.75rem);\n text-align: center;\n color: var(--hx-color-text-placeholder, #66787b);\n font-size: var(--hx-font-size-sm, 0.875rem);\n }\n .field__sr-only {\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 .field__help-text,\n .field__error {\n font-size: var(--hx-font-size-xs, 0.75rem);\n line-height: var(--hx-line-height-normal, 1.5);\n }\n .field__help-text {\n color: var(--hx-color-text-muted, #4a5362);\n }\n .field__error {\n color: var(--hx-combobox-error-color, var(--hx-color-error-text, #c92a2a));\n }\n @media (prefers-reduced-motion: reduce) {\n .field__input-wrapper,\n .field__option,\n .field__clear-button,\n .field__chip-remove {\n transition: none;\n }\n }\n @media (forced-colors: active) {\n .field__input-wrapper {\n forced-color-adjust: none;\n background-color: Field;\n color: FieldText;\n border: 2px solid ButtonText;\n }\n .field__input {\n color: FieldText;\n }\n .field__input::placeholder {\n color: GrayText;\n }\n .field__input-wrapper:focus-within {\n border-color: Highlight;\n box-shadow: none;\n }\n .field__listbox {\n forced-color-adjust: none;\n background-color: Canvas;\n border: 2px solid CanvasText;\n box-shadow: none;\n }\n .field__option {\n color: CanvasText;\n }\n .field__option:hover {\n background-color: Highlight;\n color: HighlightText;\n }\n .field__option--selected {\n background-color: Highlight;\n color: HighlightText;\n }\n .field__option--focused {\n outline-color: Highlight;\n background-color: Highlight;\n color: HighlightText;\n }\n .field__option--disabled {\n color: GrayText;\n opacity: 1;\n }\n .field__chip {\n forced-color-adjust: none;\n background-color: Highlight;\n color: HighlightText;\n border: 1px solid HighlightText;\n }\n .field__chip-remove:focus-visible {\n outline-color: Highlight;\n }\n .field__clear-button:focus-visible {\n outline-color: Highlight;\n }\n .field--error .field__input-wrapper {\n border-color: LinkText;\n }\n :host([disabled]) {\n opacity: 1;\n }\n :host([disabled]) .field__input-wrapper {\n border-color: GrayText;\n color: GrayText;\n }\n :host([disabled]) .field__input {\n color: GrayText;\n }\n .field__label {\n color: CanvasText;\n }\n .field__help-text {\n color: GrayText;\n }\n .field__error {\n color: LinkText;\n }\n }\n :host([multiple]) .field__input-wrapper {\n flex-wrap: wrap;\n padding: var(--hx-space-1, 0.25rem);\n gap: var(--hx-space-1, 0.25rem);\n align-items: center;\n }\n :host([multiple]) .field__input {\n min-width: 8rem;\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-2, 0.5rem);\n flex-shrink: 1;\n }\n .field__chip {\n display: inline-flex;\n align-items: center;\n gap: var(--hx-space-1, 0.25rem);\n padding: 0 var(--hx-space-1, 0.25rem) 0 var(--hx-space-2, 0.5rem);\n height: 1.5rem;\n background-color: var(--hx-combobox-chip-bg, var(--hx-color-primary-100, #dbf0f0));\n color: var(--hx-combobox-chip-color, var(--hx-color-primary-800, #07494a));\n border-radius: var(--hx-border-radius-full, 9999px);\n font-size: var(--hx-font-size-sm, 0.875rem);\n white-space: nowrap;\n max-width: 12rem;\n flex-shrink: 0;\n }\n .field__chip-label {\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 8rem;\n }\n .field__chip-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 1rem;\n height: 1rem;\n border: none;\n background: none;\n cursor: pointer;\n padding: 0;\n color: inherit;\n opacity: 0.7;\n border-radius: 50%;\n line-height: 1;\n transition: opacity var(--hx-transition-fast, 150ms ease);\n }\n .field__chip-remove:hover {\n opacity: 1;\n background-color: var(--hx-combobox-chip-remove-hover-bg, var(--hx-color-primary-200, #bce1e1));\n }\n .field__chip-remove:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n opacity: 1;\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 { HelixElement, createIdCounter } from '../../base/index.js';\nimport { FormMixin } from '../../mixins/FormMixin.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { helixComboboxStyles } from './hx-combobox.styles.js';\nimport { forcedColorsField } from '../../styles/forced-colors.js';\nimport { devWarn } from '../../utils/dev-warn.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\n\n// PERF: hx-combobox exceeds 5KB budget (6.87kb gzipped) -- typeahead filtering, multi-select chips, async loading\n\n// ─── Internal option model ───\n\n// P1-7: Exported so TypeScript consumers can type option arrays programmatically\nexport interface ComboboxOption {\n value: string;\n label: string;\n disabled: boolean;\n}\n\n// P2-13: Exported size type for TypeScript consumers\nexport type HxComboboxSize = 'sm' | 'md' | 'lg';\n\nconst _nextComboboxId = createIdCounter('hx-combobox');\n\n/**\n * AccName-aware text flattener. Walks the subtree of `root` and concatenates\n * text-node content, REJECTING any element subtree carrying `aria-hidden=\"true\"`\n * or the `hidden` attribute per W3C AccName 1.2 §4.3.10. Used by hx-combobox\n * for both external IDREF flatten (host aria-labelledby/aria-describedby\n * targets) and slotted-label aggregation, so nested decorative content like\n * `<svg aria-hidden=\"true\"><title>icon</title></svg>` does not leak into the\n * inner input's announced name/description.\n *\n * Round-11 F1/F2 (P2): the TreeWalker filter only inspects elements VISITED\n * during the walk — it never tests the root itself, so a hidden ROOT (e.g.\n * `<span slot=\"label\" hidden>Secret</span>` or\n * `<span slot=\"help-text\" aria-hidden=\"true\">stale</span>`) would still\n * contribute its descendants' text. Per AccName 1.2 §4.3.10, a hidden root\n * contributes the empty string. Gate the walk here so every caller (slotted\n * label/help/error and external IDREF flatten) honors the rule symmetrically.\n */\nfunction flattenAccName(root: Element): string {\n if (root.getAttribute('aria-hidden') === 'true' || root.hasAttribute('hidden')) {\n return '';\n }\n let result = '';\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, {\n acceptNode(node) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as Element;\n if (el.getAttribute('aria-hidden') === 'true') {\n return NodeFilter.FILTER_REJECT;\n }\n if (el.hasAttribute('hidden')) {\n return NodeFilter.FILTER_REJECT;\n }\n return NodeFilter.FILTER_SKIP;\n }\n return NodeFilter.FILTER_ACCEPT;\n },\n });\n let textNode: Node | null = walker.nextNode();\n while (textNode) {\n result += textNode.textContent ?? '';\n textNode = walker.nextNode();\n }\n return result.replace(/\\s+/g, ' ').trim();\n}\n\n/** Detail for hx-input and hx-change events dispatched by hx-combobox. */\nexport interface HxComboboxDetail {\n value: string;\n}\n\n/**\n * A form-associated combobox component combining a text input with a listbox\n * for autocomplete and typeahead. Supports filtering, free-text entry,\n * keyboard navigation, and async option loading.\n *\n * @summary Form-associated combobox with autocomplete, filtering, and keyboard navigation.\n *\n * @tag hx-combobox\n *\n * @slot option - Slot for `<option>` elements that populate the listbox.\n * @slot prefix - Content to display before the text input.\n * @slot suffix - Content to display after the text input.\n * @slot empty-label - Content shown when no options match the filter.\n * @slot label - Custom label content (overrides the label property).\n * @slot error - Custom error content (overrides the error property).\n * @slot help-text - Custom help text content (overrides the helpText property).\n *\n * @fires {CustomEvent<{value: string}>} hx-input - Dispatched on each keystroke as the user types.\n * @fires {CustomEvent<{value: string}>} hx-change - Dispatched when an option is selected.\n * @fires {CustomEvent<void>} hx-clear - Dispatched when the clear button is activated.\n * @fires {CustomEvent<void>} hx-show - Dispatched when the listbox opens.\n * @fires {CustomEvent<void>} hx-hide - Dispatched when the listbox closes.\n *\n * @csspart input - The native text input element.\n * @csspart listbox - The dropdown panel containing options.\n * @csspart trigger - The input wrapper element acting as the combobox trigger.\n * @csspart clear-button - The button that clears the current value.\n * @csspart loading-indicator - The loading spinner shown during async operations.\n * @csspart field - The outer field wrapper element.\n * @csspart label - The label element.\n * @csspart option - An individual option item in the listbox.\n * @csspart error - The error message element.\n * @csspart help-text - The help text element.\n *\n * @cssprop [--hx-combobox-bg=var(--hx-color-neutral-0)] - Input background color.\n * @cssprop [--hx-combobox-color=var(--hx-color-neutral-800)] - Input text color.\n * @cssprop [--hx-combobox-border-color=var(--hx-color-neutral-300)] - Border color.\n * @cssprop [--hx-combobox-border-radius=var(--hx-border-radius-md)] - Border radius.\n * @cssprop [--hx-combobox-font-family=var(--hx-font-family-sans)] - Font family.\n * @cssprop [--hx-combobox-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-combobox-error-color=var(--hx-color-error-500)] - Error state color.\n * @cssprop [--hx-combobox-label-color=var(--hx-color-neutral-700)] - Label text color.\n * @cssprop [--hx-combobox-listbox-bg=var(--hx-color-neutral-0)] - Listbox background color.\n * @cssprop [--hx-combobox-option-hover-bg=var(--hx-color-primary-50)] - Option hover background.\n * @cssprop [--hx-combobox-option-selected-bg=var(--hx-color-primary-100)] - Selected option background.\n * @cssprop [--hx-opacity-disabled] - Opacity.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-font-family-sans] - Font family.\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-error-text] - Color.\n * @cssprop [--hx-font-weight-bold] - Font weight.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-color-neutral-300] - Color.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-opacity] - CSS custom property.\n * @cssprop [--hx-color-error-500] - Color.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-color-neutral-500] - Color.\n * @cssprop [--hx-input-height-md] - Height.\n * @cssprop [--hx-size-10] - Size token.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-color-neutral-800] - Color.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-color-neutral-400] - Color.\n * @cssprop [--hx-input-height-sm] - Height.\n * @cssprop [--hx-size-8] - Size token.\n * @cssprop [--hx-input-height-lg] - Height.\n * @cssprop [--hx-size-12] - Size token.\n * @cssprop [--hx-font-size-lg] - Font size.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-border-radius-full] - CSS custom property.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-z-index-dropdown] - Z-index layer.\n * @cssprop [--hx-combobox-listbox-shadow] - CSS custom property.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-combobox-listbox-max-height=16rem] - Height.\n * @cssprop [--hx-color-primary-50] - Color.\n * @cssprop [--hx-color-primary-100] - Color.\n * @cssprop [--hx-combobox-option-focus-ring-offset=-2px] - Focus ring styling.\n * @cssprop [--hx-font-size-xs] - Font size.\n * @cssprop [--hx-combobox-chip-bg=var(--hx-color-primary-100)] - Background color.\n * @cssprop [--hx-combobox-chip-color=var(--hx-color-primary-800)] - Color.\n * @cssprop [--hx-color-primary-800] - Color.\n * @cssprop [--hx-combobox-chip-remove-hover-bg=var(--hx-color-primary-200)] - Background color.\n * @cssprop [--hx-color-primary-200] - Color.\n */\n@customElement('hx-combobox')\nexport class HelixCombobox extends FormMixin(HelixElement) {\n static override styles = [helixComboboxStyles, forcedColorsField];\n\n // ─── Form Association ───\n\n /** Marks this element as form-associated for ElementInternals support. @internal */\n static override formAssociated = true;\n\n /**\n * Test seam (round-3 finding 4): when set to `true` or `false`, overrides\n * the platform `supportsIdrefElementReferences` probe before\n * `connectedCallback` seeds `_supportsIdrefRefs`. Mid-life flag flips on a\n * connected instance allowed stale modern internals (set during connect)\n * to leak into the fallback branch — tests must select the path BEFORE\n * the host connects so the synthetic environment matches a legacy engine.\n *\n * Production code MUST NOT touch this field. It is a `static` so the test\n * stub cleanup is global and obvious.\n * @internal\n */\n static __testSupportsIdrefRefsOverride: boolean | null = null;\n\n // ─── Stable IDs ───\n\n /** @internal */\n private _id = _nextComboboxId();\n /** @internal */\n private _listboxId = `${this._id}-listbox`;\n /** @internal */\n private _helpTextId = `${this._id}-help`;\n /** @internal */\n private _errorId = `${this._id}-error`;\n /** @internal */\n private _labelId = `${this._id}-label`;\n /** @internal */\n private _liveRegionId = `${this._id}-live`;\n /**\n * Round-5 F1 (P1): id of the synthesized in-shadow span that mirrors the\n * consumer-resolved description text. This id is appended to the inner\n * input's `aria-describedby` so AT picks the consumer description up\n * through the standard described-by channel — `aria-description` is\n * intentionally NOT written, because the W3C AccName algorithm ignores\n * `aria-description` whenever `aria-describedby` is also present.\n * @internal\n */\n private _consumerDescId = `${this._id}-consumer-desc`;\n\n // ─── Public Properties ───\n\n /**\n * The visible label text for the combobox.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Placeholder text shown in the input when no value is entered.\n * @attr placeholder\n */\n @property({ type: String })\n placeholder = '';\n\n /**\n * The current value of the combobox.\n * @attr value\n */\n @property({ type: String, reflect: true })\n value = '';\n\n /**\n * Whether the combobox is required for form submission.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /**\n * Whether the combobox is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * The name used for form submission.\n * @attr name\n */\n @property({ type: String, reflect: true })\n name = '';\n\n /**\n * Error message to display. When set, the field enters an error state.\n * @attr error\n */\n @property({ type: String })\n error = '';\n\n /**\n * Help text displayed below the combobox for guidance.\n * @attr help-text\n */\n @property({ type: String, attribute: 'help-text' })\n helpText = '';\n\n /**\n * Size variant of the combobox.\n * @attr hx-size\n */\n @property({ type: String, attribute: 'hx-size', reflect: true })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Whether multiple options can be selected.\n * @attr multiple\n */\n @property({ type: Boolean, reflect: true })\n multiple = false;\n\n /**\n * Whether the combobox shows a clear button when a value is set.\n * @attr clearable\n */\n @property({ type: Boolean, reflect: true })\n clearable = false;\n\n /**\n * Whether the combobox is in a loading state (shows spinner).\n * @attr loading\n */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n /**\n * Debounce delay in milliseconds for the filter input event.\n * @attr filter-debounce\n */\n @property({ type: Number, attribute: 'filter-debounce' })\n filterDebounce = 0;\n\n /**\n * Accessible name for screen readers, if different from the visible label.\n * Uses `accessible-label` attribute instead of `aria-label` to avoid\n * ARIAMixin shadowing on the host element.\n *\n * Note: `mixinDelegatesAria` is not applied to this component because form\n * inputs with associated labels delegate accessible naming via `<label>`\n * association and `aria-labelledby`, not host-level ARIA delegation. The\n * `accessible-label` attribute is a fallback for label-free usage. The value is forwarded to the\n * host's `internals.ariaLabel` on the modern path.\n * @attr accessible-label\n */\n @property({ type: String, attribute: 'accessible-label' })\n accessibleLabel: string | null = null;\n\n /**\n * Text shown when no options match the current filter.\n * @attr label-no-options\n */\n @property({ type: String, attribute: 'label-no-options' })\n labelNoOptions = 'No options found';\n\n /**\n * Validation message shown when the field is required but empty.\n * @attr label-required\n */\n @property({ type: String, attribute: 'label-required' })\n labelRequired = 'Please select an option.';\n\n /**\n * Generates the accessible label for multi-select chip remove buttons.\n * @param label - the option label text\n */\n @property({ attribute: false })\n labelRemoveOption: (label: string) => string = (label) => `Remove ${label}`;\n\n // ─── Internal State ───\n\n /** Parsed option models derived from slotted `<option>` and `<optgroup>` elements. @internal */\n @state() private _options: ComboboxOption[] = [];\n /** Current text typed in the input, used to filter the option list. @internal */\n @state() private _filterText = '';\n /** Whether the listbox dropdown is currently visible. @internal */\n @state() private _open = false;\n /** Zero-based index of the keyboard-focused option within the filtered list; -1 means none. @internal */\n @state() private _focusedOptionIndex = -1;\n /** Whether the named error slot contains projected content. @internal */\n @state() private _hasErrorSlot = false;\n /** Whether the named help-text slot contains projected content. @internal */\n @state() private _hasHelpSlot = false;\n /** Live-region announcement text describing the current number of filtered options. @internal */\n @state() private _filterAnnouncement = '';\n /**\n * Source of the accessible name. Discriminated union replaces the magic\n * `'*slotted*'` sentinel so a future caller setting `label=\"*slotted*\"`\n * literally cannot be confused with a slotted label.\n * @internal\n */\n @state() private _labelSource: 'string' | 'slot' | 'none' = 'none';\n /**\n * Flattened, trimmed text content of any text nodes in the label slot —\n * used to drive `internals.ariaLabel` when the consumer projects only a\n * text node (no element to add to `labelEls`).\n * @internal\n */\n @state() private _labelSlotText = '';\n /**\n * Whether the named label slot contributes a useful name. Requires either\n * a labellable element OR non-empty trimmed text content (whitespace-only\n * does NOT count).\n * @internal\n */\n @state() private _hasLabelSlot = false;\n /**\n * Whether the platform supports IDL element references on `ElementInternals`.\n * Drives the cross-shadow naming strategy for the inner `<input>`: modern\n * path resolves consumer light-DOM IDREFs and writes them as cloned/proxied\n * ids into the inner input's `aria-labelledby` / `aria-describedby`;\n * fallback path mirrors only consumer `aria-labelledby` / `aria-describedby`\n * tokens (resolved through the IDREF resolver) onto the inner input.\n *\n * ARCHITECTURE — W3C APG editable combobox (option I):\n * `role=\"combobox\"` lives on the inner `<input>` (replaces the implicit\n * textbox role). All combobox state ARIA — `aria-expanded`, `aria-controls`,\n * `aria-activedescendant`, `aria-autocomplete`, `aria-haspopup`,\n * `aria-required`, `aria-invalid`, `aria-disabled`, `aria-busy` — lives on\n * the inner input. The host carries no role and no tabindex; it is not a\n * tab stop and not an announced AT surface.\n * @internal\n */\n @state() private _supportsIdrefRefs = true;\n /**\n * Cached invalidity flag derived from `internals.validity.valid` after the\n * latest `setValidity()` call. Drives the inner input's `aria-invalid`.\n * @internal\n */\n @state() private _invalid = false;\n /**\n * Deferred copy of `error` driven through reactive state so the persistent\n * live region can re-announce on transitions without direct DOM mutation.\n * @internal\n */\n @state() private _announcedError = '';\n\n // ─── Queries ───\n\n /** Reference to the native text input element inside the shadow DOM. @internal */\n @query('.field__input')\n private _input: HTMLInputElement | undefined;\n\n // ─── Debounce timer ───\n\n /** @internal */\n private _debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n // ─── Multiple Selection ───\n\n // P0-1: Derive selected values Set from the comma-separated value property\n /** @internal */\n private get _selectedValuesSet(): Set<string> {\n if (!this.multiple || !this.value) return new Set();\n return new Set(this.value.split(',').filter(Boolean));\n }\n\n // ─── Filtered options ───\n\n /** @internal */\n private get _filteredOptions(): ComboboxOption[] {\n if (!this._filterText) return this._options;\n const lower = this._filterText.toLowerCase();\n return this._options.filter((o) => o.label.toLowerCase().includes(lower));\n }\n\n // ─── Host-canonical ARIA bookkeeping ───\n\n /**\n * Handle for the shared IDREF observer. See `installAriaIdrefMirror()`.\n * @internal\n */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n /**\n * Watches assigned `<slot name=\"help-text\">` nodes for in-place text\n * mutations so the no-IDL-ref fallback `internals.ariaDescription` stays in sync.\n * @internal\n */\n private _helpSlotTextObserver: MutationObserver | null = null;\n /**\n * Watches assigned `<slot name=\"error\">` nodes for in-place text mutations.\n * @internal\n */\n private _errorSlotTextObserver: MutationObserver | null = null;\n /**\n * Round-10 finding 1: dedicated host observer scoped to `aria-describedby`\n * with `attributeOldValue: true`. Governed by the disconnect-during-strip\n * discipline. See `_syncHostAriaSemantics` fallback branch.\n * @internal\n */\n private _hostDescribedByObserver: MutationObserver | null = null;\n /**\n * Most recently observed *consumer-supplied* `aria-labelledby` baseline.\n * Refreshed only when the host attribute changes via an external write.\n * On the modern path the host attribute is preserved; on the legacy\n * fallback the attribute is stripped during sync, so this baseline is the\n * only durable record of what the consumer asked for.\n * @internal\n */\n private _consumerLabelledBy: string | null = null;\n /** @internal — see `_consumerLabelledBy`. */\n private _consumerDescribedBy: string | null = null;\n /**\n * Direct references to ALL labellable elements projected into\n * `<slot name=\"label\">`. Round-4 F1 (P2): aggregating every assigned element\n * — not just the first — preserves composed labels such as\n * `<svg slot=\"label\" aria-hidden=\"true\">…</svg><span slot=\"label\">Patient</span>`\n * or `<span slot=\"label\">First</span><span slot=\"label\">name</span>`. The\n * modern path passes the full array to `internals.ariaLabelledByElements`\n * and the fallback path text-flattens every node into `_labelSlotText` per\n * AccName 1.2. Avoids mutating consumer light-DOM and survives nested\n * shadow roots without fragile getElementById chains.\n * @internal\n */\n private _slottedLabelEls: Element[] = [];\n /**\n * Round-4 F2 (P2): observes in-place text mutations on the assigned slotted\n * label nodes (e.g. consumer i18n re-renders that mutate the same\n * `<span slot=\"label\">` `textContent` instead of replacing it). Mirrors the\n * round-23 P2 pattern from `_helpSlotTextObserver` / `_errorSlotTextObserver`.\n * `slotchange` does NOT fire when only the descendant text mutates, so this\n * observer is the only signal that keeps the no-IDL-ref fallback\n * `aria-label` and the announced name in sync with the visible label.\n * @internal\n */\n private _labelSlotTextObserver: MutationObserver | null = null;\n /**\n * Round-7 F1 (P2): observes in-place text mutations on consumer light-DOM\n * elements resolved from host `aria-labelledby` / `aria-describedby`. When a\n * consumer keeps the same `<label id=\"...\">` but mutates its `textContent`\n * (e.g. an i18n rerender), `slotchange` does not fire and the host\n * attribute does not change — so without this observer the inner input's\n * `aria-label` and the synthesized description span keep announcing the\n * old flattened text indefinitely. Reinstalled on every sync against the\n * deduped union of resolved label/desc elements; disconnects automatically\n * when the consumer retracts both attribute chains.\n * @internal\n */\n private _externalRefsObserver: MutationObserver | null = null;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Round-3 finding 4: honour the static test override so synthetic\n // environments choose the path BEFORE connect runs.\n const ctor = this.constructor as typeof HelixCombobox;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n\n // Round-10 finding 1: install the dedicated `aria-describedby` retraction\n // observer BEFORE the seeded `_syncHostAriaSemantics()` call below, then\n // govern its lifetime with the disconnect-during-strip discipline.\n this._hostDescribedByObserver = new MutationObserver((records) => {\n let consumerCleared = false;\n for (const record of records) {\n if (record.attributeName !== 'aria-describedby') continue;\n const oldValue = record.oldValue;\n const newValue = this.getAttribute('aria-describedby');\n if (oldValue !== null && newValue === null) {\n // Consumer authentically retracted `aria-describedby`.\n this._consumerDescribedBy = null;\n consumerCleared = true;\n }\n }\n if (consumerCleared) {\n this._syncHostAriaSemantics();\n }\n });\n this._hostDescribedByObserver.observe(this, {\n attributes: true,\n attributeFilter: ['aria-describedby'],\n attributeOldValue: true,\n });\n\n // Seed root-independent semantics from connect so the host announces\n // combobox role 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 // Safety net: remove listener if component is removed while dropdown is open\n if (typeof document !== 'undefined') {\n document.removeEventListener('click', this._handleOutsideClick);\n }\n if (this._debounceTimer !== null) {\n clearTimeout(this._debounceTimer);\n }\n // Reset open state to prevent persisted open state on reconnect\n if (this._open) {\n this._open = false;\n }\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n this._helpSlotTextObserver?.disconnect();\n this._helpSlotTextObserver = null;\n this._errorSlotTextObserver?.disconnect();\n this._errorSlotTextObserver = null;\n this._labelSlotTextObserver?.disconnect();\n this._labelSlotTextObserver = null;\n this._hostDescribedByObserver?.disconnect();\n this._hostDescribedByObserver = null;\n this._externalRefsObserver?.disconnect();\n this._externalRefsObserver = null;\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('value')) {\n this._updateFormValue();\n }\n if (changedProperties.has('label')) {\n this._refreshLabelSource();\n }\n // Host-elevated ARIA semantics — see _syncHostAriaSemantics.\n this._syncHostAriaSemantics();\n // Drive re-announcement from reactive state so the persistent live region\n // stays in the shadow tree across error transitions.\n if (changedProperties.has('error')) {\n const previousError = changedProperties.get('error') as string;\n if (previousError && this.error) {\n // Error→error: clear then re-set after rAF so AT re-announces.\n this._announcedError = '';\n requestAnimationFrame(() => {\n this._announcedError = this.error;\n });\n } else {\n this._announcedError = this.error;\n }\n }\n }\n\n override willUpdate(changedProperties: PropertyValues<this>): void {\n super.willUpdate(changedProperties);\n // Round-7 F2 (P2) / round-10 F2 (P2): seed `_announcedError` BEFORE render\n // so the persistent live region renders with the error text in the SAME\n // frame that removes `hidden` from the alert container.\n //\n // Round-7 covered first paint (initial property/attribute). Round-10\n // extended this to RUNTIME transitions: when `error` flips from \"\" to\n // \"Server rejected\" via async/server-side validation, updating\n // `_announcedError` only in `updated()` left one frame where the alert\n // container was visible but empty — `aria-describedby` also pointed at an\n // empty error node for that cycle. Seeding here keeps the first visible\n // frame populated.\n //\n // The error-to-error rAF toggle in `updated()` still owns re-announcement\n // semantics for subsequent transitions (clearing then re-setting to force\n // AT to re-read role=\"alert\" content).\n if (changedProperties.has('error') || !this.hasUpdated) {\n this._announcedError = this.error ?? '';\n }\n }\n\n override firstUpdated(changedProperties: PropertyValues<this>): void {\n super.firstUpdated(changedProperties);\n // Round-5 F2 (P2): `slotchange` fires as a microtask after the initial\n // synchronous render. Without proactive seeding, the first\n // `_syncHostAriaSemantics()` call (driven from `updated()` in this same\n // cycle, AFTER firstUpdated returns) would observe stale `false` /\n // empty state for `_hasLabelSlot`, `_slottedLabelEls`, `_labelSlotText`,\n // `_hasHelpSlot`, and `_hasErrorSlot`. That would break flows that\n // mount a combobox with slot-only label/help/error and then focus\n // immediately — AT would announce an unnamed control until the\n // microtask `slotchange` corrected the state on the second update.\n //\n // Seed the slot-derived state synchronously here by reading the\n // assigned-nodes lists directly. The slot-change handlers remain wired\n // for subsequent slot mutations; this is purely a first-paint fix.\n this._seedSlotStateSync();\n // WCAG 4.1.2: warn when no accessible name is available. Now that the\n // label-slot state is seeded above, this check sees the same surface\n // area the next sync will, so the warning matches AT-observed reality.\n if (\n !this.label &&\n !this.accessibleLabel &&\n !this._hasLabelSlot &&\n !this.getAttribute('aria-label') &&\n !this.getAttribute('aria-labelledby')\n ) {\n devWarn(\n 'hx-combobox',\n 'No accessible label provided. Set the `label` attribute, `accessible-label`, `aria-label`, `aria-labelledby`, or project a `<slot name=\"label\">` child. An unlabeled combobox violates WCAG 2.1 AA (4.1.2 Name, Role, Value).',\n );\n }\n }\n\n /**\n * Round-5 F2 (P2): synchronous slot-state seed. Mirrors the side effects of\n * the three `_handle*SlotChange` handlers (label / help-text / error) but\n * is driven by direct `slot.assignedNodes()` reads so we can populate the\n * state BEFORE the microtask `slotchange` events fire after the first\n * render. Idempotent — calling it later is a no-op when state already\n * matches the slot contents.\n *\n * Also installs the label slot text observer so consumer in-place text\n * mutations on slotted label nodes are tracked even if the slotchange\n * event has not yet fired.\n * @internal\n */\n private _seedSlotStateSync(): void {\n const root = this.shadowRoot;\n if (!root) return;\n // Label slot — use the existing _readLabelSlotState helper to capture\n // the discriminated state (elements + flattened text + has-useful-name).\n const labelSlot = root.querySelector<HTMLSlotElement>('slot[name=\"label\"]');\n if (labelSlot) {\n const state = this._readLabelSlotState(labelSlot);\n this._hasLabelSlot = state.hasUsefulName;\n this._slottedLabelEls = state.elements;\n this._labelSlotText = state.text;\n // Install the text-mutation observer now so consumer i18n re-renders\n // that mutate the same slotted node's textContent are picked up even\n // before the first slotchange event lands.\n this._installLabelSlotTextObserver(state.elements);\n this._refreshLabelSource();\n }\n // Help-text slot — match `_handleHelpSlotChange` exactly.\n const helpSlot = root.querySelector<HTMLSlotElement>('slot[name=\"help-text\"]');\n if (helpSlot) {\n // Round-6 F1 (P2): use the effective-text reader so first-paint state\n // matches the MO's re-read logic. An empty/whitespace-only slot is NOT\n // a usable help text.\n this._hasHelpSlot = this._readHelpSlotStateSync(helpSlot);\n this._installHelpSlotTextObserver(helpSlot);\n }\n // Error slot — match `_handleErrorSlotChange` exactly.\n const errorSlot = root.querySelector<HTMLSlotElement>('slot[name=\"error\"]');\n if (errorSlot) {\n // Round-6 F1 (P2): use the effective-text reader so first-paint state\n // matches the MO's re-read logic.\n this._hasErrorSlot = this._readErrorSlotStateSync(errorSlot);\n this._installErrorSlotTextObserver(errorSlot);\n }\n }\n\n /**\n * Reads the label slot's assigned nodes and computes the discriminated\n * naming state. An empty whitespace-only slot does NOT count as a useful\n * name.\n *\n * Round-4 F1 (P2): aggregates ALL assigned elements (not just the first) and\n * concatenates `textContent` from every assigned node — element OR text —\n * trimmed and space-joined per AccName 1.2 text-flatten rules. This preserves\n * composed labels such as\n * `<svg slot=\"label\" aria-hidden=\"true\">…</svg><span slot=\"label\">Patient</span>`\n * or `<span slot=\"label\">First</span><span slot=\"label\">name</span>` on both\n * the modern (`internals.ariaLabelledByElements`) path and the no-IDL-ref\n * fallback (`aria-label`) path.\n *\n * Round-6 F2 (P2): per AccName 1.2 §4.3.10, `aria-hidden=\"true\"` elements\n * contribute zero to the accessible name. They are still tracked in\n * `elements` (so the modern `internals.ariaLabelledByElements` path projects\n * the FULL visible label — icon + text — for AT that walks IDL refs), but\n * they are skipped during text flattening. `hasUsefulName` is gated on the\n * flattened text length, so a slot containing ONLY decorative elements (or\n * empty wrappers) is NOT considered usable: `_labelSource` falls through to\n * the next naming source and the firstUpdated() devWarn fires for unnamed\n * controls. A composed `<svg aria-hidden><span>Patient</span>` slot still\n * resolves: text = \"Patient\" → usable; both elements still project on the\n * modern path.\n * @internal\n */\n private _readLabelSlotState(slot: HTMLSlotElement): {\n hasUsefulName: boolean;\n elements: Element[];\n text: string;\n } {\n const nodes = slot.assignedNodes({ flatten: true });\n const elements: Element[] = [];\n const fragments: string[] = [];\n for (const node of nodes) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as Element;\n elements.push(el);\n // Per AccName 1.2 §4.3.10, aria-hidden elements contribute zero to the\n // accessible name. Skip their text in the flatten — the element itself\n // remains in `elements` so the modern path still projects it via\n // `internals.ariaLabelledByElements` (full visible-label fidelity).\n if (el.getAttribute('aria-hidden') === 'true') continue;\n // Round-8 F2 (P2): use the deep walker so NESTED aria-hidden / hidden\n // subtrees inside a slotted parent element (e.g. an inline decorative\n // `<svg aria-hidden><title>icon</title></svg>` inside a slotted\n // `<span>Patient</span>`) are skipped per AccName 1.2 §4.3.10.\n const elText = flattenAccName(el);\n if (elText) fragments.push(elText);\n } else if (node.nodeType === Node.TEXT_NODE) {\n const txt = (node.textContent ?? '').trim();\n if (txt) fragments.push(txt);\n }\n }\n const trimmedText = fragments.join(' ').replace(/\\s+/g, ' ').trim();\n return {\n // Round-6 F2 (P2): gate on flattened TEXT, not element presence. A slot\n // with only decorative/aria-hidden elements (or empty wrappers) yields\n // text === '' and is NOT a usable name.\n hasUsefulName: trimmedText.length > 0,\n elements,\n text: trimmedText,\n };\n }\n\n /**\n * Round-6 F1 (P2): re-evaluate the help-text slot's \"has meaningful content\"\n * state from its current effective text. Mirrors the slotchange-handler\n * logic but is invocable from the in-place mutation observer so that\n * clearing `textContent` on the same slotted node flips `_hasHelpSlot`\n * back to `false` (without this, the help wrapper stays visible, the help\n * id stays in the inner input's `aria-describedby`, and AT keeps announcing\n * stale guidance).\n * @internal\n */\n private _readHelpSlotStateSync(slot: HTMLSlotElement): boolean {\n const nodes = slot.assignedNodes({ flatten: true });\n for (const node of nodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n if ((node.textContent ?? '').trim().length > 0) return true;\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n // Round-10 F3 (P3): use AccName-aware flatten so descendants carrying\n // `aria-hidden=\"true\"` or the `hidden` attribute do NOT count toward\n // \"has meaningful content\". Raw `textContent` would treat\n // `<span hidden>foo</span>` as non-empty, leaving an empty help\n // description attached to the inner input. The slot-text observer\n // (round-9 F2) watches characterData/childList/attributes so toggling\n // `hidden` on a descendant correctly flips `_hasHelpSlot` to false.\n if (flattenAccName(node as Element).length > 0) return true;\n }\n }\n return false;\n }\n\n /**\n * Round-6 F1 (P2): re-evaluate the error slot's \"has meaningful content\"\n * state from its current effective text. Mirrors the slotchange-handler\n * logic but is invocable from the in-place mutation observer so that\n * clearing `textContent` on the same slotted node flips `_hasErrorSlot`\n * back to `false` (without this, the combobox stays in its error state\n * indefinitely: `aria-invalid` stays `true`, the error id stays in\n * `aria-describedby`, and help text stays hidden).\n * @internal\n */\n private _readErrorSlotStateSync(slot: HTMLSlotElement): boolean {\n const nodes = slot.assignedNodes({ flatten: true });\n for (const node of nodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n if ((node.textContent ?? '').trim().length > 0) return true;\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n // Round-10 F3 (P3): same AccName-aware flatten as\n // `_readHelpSlotStateSync` — `<span hidden>foo</span>` or\n // `<span aria-hidden=\"true\">foo</span>` must not keep the combobox\n // in its error state once they are the sole descendants.\n if (flattenAccName(node as Element).length > 0) return true;\n }\n }\n return false;\n }\n\n // ─── Inner-input ARIA sync (W3C APG editable combobox) ───\n\n /**\n * Resolves consumer-supplied label/description IDREFs on the host and\n * writes the canonical combobox ARIA onto the **inner `<input>`** per W3C\n * APG editable combobox pattern. The inner input owns `role=\"combobox\"`\n * (replacing its implicit textbox role) and all combobox state ARIA so\n * AT sees a single announced + focused surface.\n *\n * Cross-shadow naming uses a belt-and-suspenders strategy:\n *\n * 1. **Modern path** (`_supportsIdrefRefs === true`): consumer-resolved\n * label/description elements are written onto\n * `internals.ariaLabelledByElements` / `internals.ariaDescribedByElements`\n * on the host. AT that walks up from the focused inner input for naming\n * finds them through ElementInternals. Host-level `aria-labelledby` /\n * `aria-describedby` attributes are LEFT IN PLACE so AT walking up the\n * DOM also sees them. The text content of the resolved elements is also\n * flattened onto the inner input as `aria-label` / `aria-description`\n * so AT that does not walk up still announces the right name.\n *\n * 2. **Legacy fallback** (`_supportsIdrefRefs === false`): host attrs are\n * stripped (AccName precedence cleanup) and the resolved-element text\n * is flattened onto the inner input as `aria-label` /\n * `aria-description`. Live updates to the consumer-referenced elements\n * do not propagate, but the initial accessible name resolves on every\n * AT — closing the cross-shadow naming gap that broke this on engines\n * without IDL element references.\n *\n * Writing `aria-labelledby=\"<light-DOM id>\"` directly on the shadow-DOM\n * inner input is INTENTIONALLY avoided: light-DOM ids do not resolve from\n * inside a shadow root, so that pattern leaves the control AT-anonymous.\n * Internal label ids (in the same shadow root) ARE written via\n * `aria-labelledby`.\n * @internal\n */\n /**\n * Round-7 F1 (P2): (re)install a `MutationObserver` against the deduped\n * union of consumer-resolved label/description elements. Watches\n * `characterData`, `childList`, and `subtree` so any in-place text\n * mutation on the referenced light-DOM nodes triggers a fresh sync —\n * keeping the inner input's flattened `aria-label` and the synthesized\n * description span aligned with the live consumer text. Blanket\n * disconnect-and-reinstall on every sync; if the consumer retracts both\n * IDREF chains the union is empty and the observer is disconnected.\n * @internal\n */\n private _installExternalRefsObserver(elements: Element[]): void {\n if (this._externalRefsObserver) {\n this._externalRefsObserver.disconnect();\n this._externalRefsObserver = null;\n }\n if (elements.length === 0) return;\n // Dedupe references in case the same element is referenced from both\n // `aria-labelledby` and `aria-describedby` — observing it once is enough.\n const unique = new Set<Element>(elements);\n const observer = new MutationObserver(() => {\n // External text changed — re-sync, which re-flattens the resolved\n // elements onto the inner input and the synthesized description span.\n this._syncHostAriaSemantics();\n });\n for (const el of unique) {\n // Round-9 F2 (P2): also observe `aria-hidden` / `hidden` toggles on the\n // referenced element AND its descendants. `flattenAccName` skips\n // aria-hidden subtrees per AccName 1.2 §4.3.10, so a consumer flipping\n // visibility in place changes the flattened text — but without attribute\n // observation the inner input keeps its stale mirrored `aria-label` /\n // synthesized description. `subtree: true` combined with `attributes: true`\n // covers descendant attribute mutations too.\n observer.observe(el, {\n characterData: true,\n subtree: true,\n childList: true,\n attributes: true,\n attributeFilter: ['aria-hidden', 'hidden'],\n });\n }\n this._externalRefsObserver = observer;\n }\n\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n\n const input = this._input;\n if (!input) {\n // Inner input not yet rendered; defer. The post-render `updated()` call\n // will re-invoke this sync once the input exists.\n // Round-12 F3: still derive `_invalid` so `aria-invalid` first-paint\n // is correct once the input renders.\n const isInvalidEarly = !internals.validity.valid || !!(this.error || this._hasErrorSlot);\n this._invalid = isInvalidEarly;\n return;\n }\n\n // The host carries no `aria-label` we wrote — any live value is purely\n // a consumer override. Forwarded onto the inner input below.\n const liveAriaLabel = this.getAttribute('aria-label');\n const hostAriaLabel = liveAriaLabel !== null ? liveAriaLabel.trim() || '' : '';\n\n // Resolve the candidate label/desc element references once.\n const internalLabel = this.shadowRoot?.getElementById(this._labelId) ?? null;\n // Round-4 F1 (P2): aggregate ALL assigned label-slot elements so composed\n // labels (icon + text, multi-span) name the inner input fully.\n const slottedLabelEls = this._slottedLabelEls;\n const helpEl = this.shadowRoot?.getElementById(this._helpTextId) ?? null;\n const errorEl = this.shadowRoot?.getElementById(this._errorId) ?? null;\n\n // Refresh the consumer baseline. The host attribute is the live source\n // of truth on BOTH paths (round-12 F4: legacy no longer strips, so the\n // observer-cached fallback is no longer required). A `null` live value\n // authentically represents consumer retraction.\n const liveLabelledBy = this.getAttribute('aria-labelledby');\n this._consumerLabelledBy = liveLabelledBy;\n const liveDescribedBy = this.getAttribute('aria-describedby');\n this._consumerDescribedBy = liveDescribedBy;\n const externalLabelTokens = this._consumerLabelledBy;\n const externalDescTokens = this._consumerDescribedBy;\n\n const consumerLabelEls = resolveIdrefTokens(this, externalLabelTokens);\n const hasEffectiveLabelledBy = consumerLabelEls.length > 0;\n\n const consumerDescEls = resolveIdrefTokens(this, externalDescTokens);\n\n // Round-7 F1 (P2): observe in-place text mutations on the resolved\n // external IDREF targets. Without this, a consumer that mutates\n // `<label id=\"ext\">Patient</label>` → \"Member\" in place leaves the\n // inner input's flattened `aria-label` stuck on \"Patient\". Blanket\n // disconnect-and-reinstall keeps the bookkeeping trivial and matches\n // the slotted-label observer pattern.\n this._installExternalRefsObserver([...consumerLabelEls, ...consumerDescEls]);\n\n const hasError = !!(this.error || this._hasErrorSlot);\n\n // Round-12 F3: `aria-invalid` reflects EVERY signal the consumer can use\n // to express invalidity. setValidity() drives the required-empty case;\n // an explicit `error` property/slot is a server-/async-validation signal\n // that AT must announce as invalid, not just \"described by an alert\".\n const isInvalid = !internals.validity.valid || hasError;\n this._invalid = isInvalid;\n\n // Round-12 F2: `accessibleLabel` is documented as the screen-reader name\n // when it should differ from the visible label. When the consumer\n // explicitly sets it (non-empty), it is the canonical AT name and must\n // override visible label / aria-labelledby — both for the modern path's\n // ElementInternals references and for the inner input's aria-label.\n const explicitAccessibleLabel =\n typeof this.accessibleLabel === 'string' && this.accessibleLabel.trim().length > 0\n ? this.accessibleLabel\n : null;\n\n // Round-9 F1 (P2): top-level `aria-hidden=\"true\"` / `hidden` elements MUST\n // NOT be forwarded to `internals.ariaLabelledByElements` /\n // `ariaDescribedByElements`. On engines with IDL element refs, AT walks\n // those references and would recursively read e.g. an\n // `<svg aria-hidden=\"true\"><title>icon</title></svg>` slotted alongside a\n // visible `<span slot=\"label\">Patient</span>` — yielding \"icon Patient\".\n // The fallback text-flatten path already strips these via `flattenAccName`,\n // so the filter aligns the modern path with AccName 1.2 §4.3.10.\n const isVisibleForAccName = (el: Element): boolean =>\n el.getAttribute('aria-hidden') !== 'true' && !el.hasAttribute('hidden');\n\n // Build the augmented element lists used by the modern (IDL-refs) path.\n // When `accessibleLabel` is the chosen name we omit element references\n // entirely so AT does not double-announce against the explicit override.\n const labelElsForInternals: Element[] = [];\n if (!explicitAccessibleLabel) {\n labelElsForInternals.push(...consumerLabelEls.filter(isVisibleForAccName));\n if (!hasEffectiveLabelledBy && !hostAriaLabel) {\n if (this._labelSource === 'slot' && slottedLabelEls.length > 0) {\n // Round-4 F1 (P2): expose every assigned element so AT can compose\n // the full visible label across icon + text fragments.\n // Round-9 F1 (P2): filter top-level aria-hidden / hidden so the\n // modern path matches the fallback path's AccName behavior. The\n // unfiltered `_slottedLabelEls` is still used downstream by the\n // text-flatten fallback (its TreeWalker handles nested visibility).\n labelElsForInternals.push(...slottedLabelEls.filter(isVisibleForAccName));\n } else if (this._labelSource === 'string' && internalLabel) {\n labelElsForInternals.push(internalLabel);\n }\n }\n }\n\n // Round-9 F1 (P2): same hidden-filter for description element refs. A\n // consumer-referenced `aria-describedby` target that flips to\n // `aria-hidden=\"true\"` must not name through the modern path.\n const descElsForInternals: Element[] = [...consumerDescEls.filter(isVisibleForAccName)];\n if (helpEl && !hasError && (this.helpText || this._hasHelpSlot)) {\n descElsForInternals.push(helpEl);\n }\n if (errorEl && hasError) {\n descElsForInternals.push(errorEl);\n }\n\n // ─── Modern-path: ElementInternals IDL element references ───\n // Set when supported so AT walking up from the focused inner input picks\n // up the host's referenced labels/descriptions across the shadow boundary.\n type InternalsWithIdrefRefs = ElementInternals & {\n ariaLabelledByElements: Element[] | null;\n ariaDescribedByElements: Element[] | null;\n };\n if (this._supportsIdrefRefs) {\n const refsInternals = internals as InternalsWithIdrefRefs;\n refsInternals.ariaLabelledByElements =\n labelElsForInternals.length > 0 ? labelElsForInternals : null;\n refsInternals.ariaDescribedByElements =\n descElsForInternals.length > 0 ? descElsForInternals : null;\n // Modern path: forward `accessibleLabel` to `internals.ariaLabel` so AT\n // walking the host (or reading internals) sees the explicit override.\n // Round-8 F1 (P2): when `accessibleLabel` is absent, CLEAR the override\n // with `null` (not `''`). Per W3C AccName, an empty-string `aria-label`\n // STILL has higher precedence than `aria-labelledby`, so writing `''`\n // would erase the name resolved from `ariaLabelledByElements`, the\n // `label` property, the slotted label, or host `aria-labelledby`. `null`\n // removes the override entirely so element references / fallbacks win.\n if (explicitAccessibleLabel) {\n internals.ariaLabel = explicitAccessibleLabel;\n } else {\n internals.ariaLabel = null;\n }\n }\n\n // Round-12 F4: the host's `aria-labelledby` / `aria-describedby` are\n // intentionally LEFT IN PLACE on both paths. The inner input owns the\n // canonical AT surface (role=\"combobox\") and consumes the consumer's\n // intent via text-flatten + (modern path) ElementInternals references.\n // The host is roleless on both paths, so leaving these attributes in\n // place has no AT effect — and importantly, lets consumers retract them\n // dynamically: the live attribute IS the cache, so `removeAttribute` is\n // observable in the next sync (it returns `null` from `getAttribute`).\n\n // ─── Compute the inner input's accessible name (text-flatten path) ───\n // We never write `aria-labelledby=\"<light-DOM id>\"` to the inner input —\n // light-DOM ids do not resolve from inside a shadow root, so that pattern\n // would leave the control AT-anonymous. Internal label ids (same shadow\n // root) ARE allowed via `aria-labelledby`. For consumer-referenced\n // light-DOM elements we flatten their textContent into `aria-label`.\n // Round-8 F2 (P2): use the module-level `flattenAccName` walker which\n // REJECTS `aria-hidden=\"true\"` and `hidden` subtrees per AccName 1.2\n // §4.3.10. Without this, a consumer label like\n // `<label id=\"x\"><svg aria-hidden=\"true\"><title>icon</title></svg>Search</label>`\n // would flatten to \"icon Search\" and leak the decorative title into the\n // inner input's aria-label / synthesized description span.\n // Round-9 F2 (P2): also strip top-level aria-hidden / hidden roots before\n // flattening. `flattenAccName`'s TreeWalker checks DESCENDANTS, not the\n // root itself, so without this filter a consumer flipping aria-hidden on\n // a referenced label root would leave the mirrored aria-label / consumer\n // description span stale. Mirrors the F1 modern-path filter so both\n // surfaces agree per AccName 1.2 §4.3.10.\n const flattenText = (els: Element[]): string =>\n els\n .filter(isVisibleForAccName)\n .map((el) => flattenAccName(el))\n .filter((t) => t.length > 0)\n .join(' ');\n\n let inputAriaLabel: string | null = null;\n let inputAriaLabelledBy: string | null = null;\n // Round-13 F1 (P2) precedence — aligns with W3C AccName 1.2 §4.3.1, with\n // one helix-specific deviation called out below:\n // 1. `accessibleLabel` (HELIX-SPECIFIC public-API override; documented\n // contract — see Round-3 F2 from the round-3 push-gate. The property\n // is the explicit AT-only name and intentionally outranks both\n // `aria-labelledby` and `aria-label`. The matching modern-path write\n // above clears `internals.ariaLabel` to `null` when this is unset so\n // we never erase a labelledby resolution.)\n // 2. consumer `aria-labelledby` resolves → text-flatten (AccName winner\n // over `aria-label`; previously incorrectly demoted below it, which\n // meant a consumer setting both saw the inner input announce the\n // `aria-label` string instead of the referenced label's text)\n // 3. consumer `aria-label` on the host (consumer escape hatch; only\n // reached when labelledby is absent or unresolvable)\n // 4. slotted label → text content (NEVER cross-shadow id reference)\n // 5. `label` property → internal `<label>` id (same shadow root) or text\n // 6. else: unnamed\n // Round-13 F1 (P2): the labelledby branch is allowed to fall through to\n // the next strategy when `flattenText` returns empty (e.g. the resolved\n // elements are visible-but-empty or filtered by AccName visibility).\n // Without this, an aria-labelledby pointing at an empty target would\n // park `inputAriaLabel` at `null` AND skip the host aria-label fallback,\n // leaving the control AT-anonymous.\n let labelledByFlat = '';\n if (!explicitAccessibleLabel && hasEffectiveLabelledBy) {\n labelledByFlat = flattenText(consumerLabelEls);\n }\n if (explicitAccessibleLabel) {\n inputAriaLabel = explicitAccessibleLabel;\n } else if (labelledByFlat) {\n // Consumer aria-labelledby resolved to one or more elements. Flatten\n // their text into aria-label so the inner input announces correctly\n // regardless of cross-shadow id resolution. The modern-path\n // ElementInternals write above gives AT the live IDREF chain in\n // addition to this flattened text. Round-13 F1 (P2): this branch sits\n // ABOVE the host `aria-label` branch so AccName 1.2 §4.3.1 precedence\n // is preserved when the consumer sets both attributes.\n inputAriaLabel = labelledByFlat;\n } else if (hostAriaLabel) {\n // Round-13 F1 (P2): host aria-label is the next fallback after\n // accessibleLabel + a *resolved* aria-labelledby. Reaching this branch\n // means either no aria-labelledby was set, or its IDREFs did not\n // resolve to any element (e.g. typo, target removed, empty content) —\n // in which case AccName 1.2 falls through to aria-label.\n inputAriaLabel = hostAriaLabel;\n } else if (this._labelSource === 'slot') {\n // Round-12 F1: the slotted label may carry a light-DOM id. We MUST NOT\n // write that id as `aria-labelledby` on the inner input — light-DOM\n // ids do not resolve from inside a shadow root, so on engines without\n // ElementInternals IDL refs the control would be AT-anonymous. Always\n // text-flatten on the legacy/fallback path; the modern path already\n // carries the live element reference via `ariaLabelledByElements`.\n if (this._labelSlotText) {\n inputAriaLabel = this._labelSlotText;\n } else if (slottedLabelEls.length > 0) {\n // Round-4 F1 (P2): flatten textContent across every assigned element.\n // Round-8 F2 (P2): use the deep walker so nested `aria-hidden=\"true\"`\n // (e.g. an inline `<svg aria-hidden><title>icon</title></svg>` inside a\n // slotted `<span>`) does not leak into the inner input's aria-label.\n // The top-level slotted-element aria-hidden filter is already applied\n // by `_readLabelSlotState` when populating `_labelSlotText`; this fall-\n // through aggregator handles the case where text wasn't pre-flattened.\n const flat = flattenText(slottedLabelEls);\n if (flat) inputAriaLabel = flat;\n }\n } else if (this._labelSource === 'string') {\n if (internalLabel?.id) {\n inputAriaLabelledBy = internalLabel.id;\n } else if (this.label) {\n inputAriaLabel = this.label;\n }\n }\n\n // Apply the resolved name to the inner input via attribute writes.\n if (inputAriaLabelledBy) {\n if (input.getAttribute('aria-labelledby') !== inputAriaLabelledBy) {\n input.setAttribute('aria-labelledby', inputAriaLabelledBy);\n }\n if (input.hasAttribute('aria-label')) input.removeAttribute('aria-label');\n } else if (inputAriaLabel) {\n if (input.getAttribute('aria-label') !== inputAriaLabel) {\n input.setAttribute('aria-label', inputAriaLabel);\n }\n if (input.hasAttribute('aria-labelledby')) input.removeAttribute('aria-labelledby');\n } else {\n if (input.hasAttribute('aria-label')) input.removeAttribute('aria-label');\n if (input.hasAttribute('aria-labelledby')) input.removeAttribute('aria-labelledby');\n }\n\n // ─── Write the inner input's aria-describedby chain ───\n // Round-5 F1 (P1): unify ALL descriptions through a single\n // `aria-describedby` channel on the inner input. The W3C AccName algorithm\n // ignores `aria-description` whenever `aria-describedby` is also present,\n // so the previous split (internal ids on `aria-describedby`, consumer text\n // on `aria-description`) silently dropped consumer descriptions whenever\n // help/error text was present.\n //\n // For consumer-referenced light-DOM elements we cannot point inner-input\n // `aria-describedby` directly at the consumer ids (light-DOM ids do not\n // resolve from inside a shadow root), so the consumer text is mirrored\n // into a synthesized in-shadow span and that same-root id is added to\n // the chain. The synthesized span is rendered unconditionally with the\n // visually-hidden style and updated here on every sync (idempotent).\n const consumerDescSpan = this.shadowRoot?.getElementById(this._consumerDescId) ?? null;\n const consumerDescText = flattenText(consumerDescEls);\n if (consumerDescSpan && consumerDescSpan.textContent !== consumerDescText) {\n consumerDescSpan.textContent = consumerDescText;\n }\n\n const describedByIds: string[] = [];\n if (consumerDescText && consumerDescSpan) {\n describedByIds.push(this._consumerDescId);\n }\n if (helpEl && !hasError && (this.helpText || this._hasHelpSlot)) {\n describedByIds.push(this._helpTextId);\n }\n if (errorEl && hasError) {\n describedByIds.push(this._errorId);\n }\n if (describedByIds.length > 0) {\n const value = describedByIds.join(' ');\n if (input.getAttribute('aria-describedby') !== value) {\n input.setAttribute('aria-describedby', value);\n }\n } else if (input.hasAttribute('aria-describedby')) {\n input.removeAttribute('aria-describedby');\n }\n\n // Round-5 F1 (P1): never write `aria-description` on the inner input.\n // It is silently dropped when `aria-describedby` is also present (a\n // common case once help/error text exists), and we now route consumer\n // descriptions through the synthesized in-shadow span instead. Strip\n // any legacy value defensively in case an earlier sync wrote one.\n if (input.hasAttribute('aria-description')) {\n input.removeAttribute('aria-description');\n }\n }\n\n /**\n * (Re-)installs the mutation observer over the current set of assigned\n * help-text-slot nodes.\n * @internal\n */\n private _installHelpSlotTextObserver(slot: HTMLSlotElement | null): void {\n this._helpSlotTextObserver?.disconnect();\n if (!slot) {\n this._helpSlotTextObserver = null;\n return;\n }\n // Round-6 F1 (P2): capture the slot reference so the MO callback can\n // re-evaluate `_hasHelpSlot` from the slot's current effective text. An\n // in-place `textContent = ''` on the same slotted node leaves\n // `assignedNodes().length > 0` true but yields empty effective text, so\n // we must re-read on every mutation, not just on slotchange.\n const observer = new MutationObserver(() => {\n this._hasHelpSlot = this._readHelpSlotStateSync(slot);\n this._syncHostAriaSemantics();\n });\n slot.assignedNodes().forEach((node) => {\n if (node.nodeType !== Node.ELEMENT_NODE) {\n observer.observe(node, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n return;\n }\n // Round-9 F2 (P2): observe aria-hidden / hidden toggles so a consumer\n // flipping visibility on the slotted help-text node (or a descendant)\n // re-evaluates effective text and re-syncs the inner input.\n observer.observe(node, {\n characterData: true,\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['aria-hidden', 'hidden'],\n });\n });\n this._helpSlotTextObserver = observer;\n }\n\n /**\n * (Re-)installs the mutation observer over the current set of assigned\n * error-slot nodes.\n * @internal\n */\n private _installErrorSlotTextObserver(slot: HTMLSlotElement | null): void {\n this._errorSlotTextObserver?.disconnect();\n if (!slot) {\n this._errorSlotTextObserver = null;\n return;\n }\n // Round-6 F1 (P2): capture the slot reference so the MO callback can\n // re-evaluate `_hasErrorSlot` from the slot's current effective text. If\n // a consumer keeps the same `<span slot=\"error\">` node and clears its\n // `textContent`, only the MO fires (no slotchange). Without re-reading the\n // slot state, the combobox stays stuck in its error state: `aria-invalid`\n // remains true, the error id stays in `aria-describedby`, and the help\n // text stays hidden.\n const observer = new MutationObserver(() => {\n this._hasErrorSlot = this._readErrorSlotStateSync(slot);\n this._syncHostAriaSemantics();\n });\n slot.assignedNodes().forEach((node) => {\n if (node.nodeType !== Node.ELEMENT_NODE) {\n observer.observe(node, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n return;\n }\n // Round-9 F2 (P2): observe aria-hidden / hidden toggles so a consumer\n // flipping visibility on the slotted error node (or a descendant)\n // re-evaluates effective text and re-syncs the inner input.\n observer.observe(node, {\n characterData: true,\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['aria-hidden', 'hidden'],\n });\n });\n this._errorSlotTextObserver = observer;\n }\n\n // ─── Form Integration ───\n\n /** @internal */\n private _updateFormValue(): void {\n this._internals.setFormValue(this.value || null);\n }\n\n /** @internal */\n override _updateValidity(): void {\n if (this.required && !this.value) {\n // W3C APG editable combobox: the inner `<input>` is the canonical\n // announced + focused combobox surface, so anchor `setValidity()` to\n // the inner input. Native validation popups attach to the focusable\n // form-control surface.\n this._internals.setValidity(\n { valueMissing: true },\n this.error || this.labelRequired,\n this._input,\n );\n } else {\n this._internals.setValidity({});\n }\n // Re-sync ARIA after every setValidity() so `aria-invalid` on the inner\n // input reflects the freshly computed validity state. The render template\n // binds `aria-invalid` from `_invalid`; mutating `_invalid` (a `@state`)\n // inside sync schedules a Lit update if the value actually changed.\n this._syncHostAriaSemantics();\n }\n\n /** @internal */\n protected override _onFormReset(): void {\n this.value = '';\n this._filterText = '';\n this._internals.setFormValue(null);\n this._resetInteractionState();\n }\n\n /** @internal */\n // P1-6: Correct signature per WHATWG spec — includes mode param and all state types\n protected override _onFormStateRestore(\n state: File | string | FormData | null,\n _mode: 'restore' | 'autocomplete',\n ): void {\n if (typeof state === 'string') {\n this.value = state;\n }\n }\n\n /** @internal */\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Option Syncing from Slot ───\n\n /** @internal */\n private _handleSlotChange(): void {\n this._readOptions();\n }\n\n /** @internal */\n private _parseOption(el: HTMLOptionElement): ComboboxOption {\n return { value: el.value, label: el.textContent?.trim() ?? el.value, disabled: el.disabled };\n }\n\n /** @internal */\n private _readOptions(): void {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"option\"]');\n if (!slot) return;\n\n const parsed: ComboboxOption[] = [];\n\n for (const el of slot.assignedElements({ flatten: true })) {\n if (el instanceof HTMLOptionElement) {\n parsed.push(this._parseOption(el));\n } else if (el instanceof HTMLOptGroupElement) {\n for (const child of Array.from(el.children)) {\n if (child instanceof HTMLOptionElement) parsed.push(this._parseOption(child));\n }\n }\n }\n\n this._options = parsed;\n }\n\n // ─── Slot Change Handlers ───\n\n /**\n * Tracks the slotted label so projected `<span slot=\"label\">` content joins\n * the accessible-name chain.\n * @internal\n */\n private _handleLabelSlotChange(e: Event): void {\n if (!(e.target instanceof HTMLSlotElement)) return;\n const state = this._readLabelSlotState(e.target);\n this._hasLabelSlot = state.hasUsefulName;\n this._slottedLabelEls = state.elements;\n this._labelSlotText = state.text;\n // Round-4 F2 (P2): re-install the in-place text-mutation observer on the\n // current set of slotted elements. `slotchange` covers ADD/REMOVE/REPLACE\n // of assigned nodes; this MO covers `node.textContent = '…'` updates on\n // an unchanged node (e.g. consumer i18n re-render keeping the same span).\n this._installLabelSlotTextObserver(state.elements);\n this._refreshLabelSource();\n this._syncHostAriaSemantics();\n }\n\n /**\n * (Re-)installs the mutation observer over the current set of slotted label\n * elements. Round-4 F2 (P2): mirrors the round-23 P2 pattern from\n * `_helpSlotTextObserver` / `_errorSlotTextObserver`. On any descendant text\n * change we re-read the slot state (to refresh `_labelSlotText` and the\n * element list) and re-sync host ARIA so the inner input's `aria-label`\n * tracks the live label text.\n * @internal\n */\n private _installLabelSlotTextObserver(elements: Element[]): void {\n this._labelSlotTextObserver?.disconnect();\n if (elements.length === 0) {\n this._labelSlotTextObserver = null;\n return;\n }\n const observer = new MutationObserver(() => {\n // Re-aggregate text from the same elements (the MO does not give us a\n // slot reference). The element list itself only changes on `slotchange`,\n // which re-installs this observer with the new list.\n //\n // Round-6 F2 (P2): mirror `_readLabelSlotState` — skip aria-hidden\n // elements per AccName 1.2 §4.3.10, and gate `_hasLabelSlot` on the\n // flattened TEXT (not element presence). An in-place clear of the\n // visible label's textContent must flip `_hasLabelSlot` back to false\n // so `_labelSource` falls through to other naming sources or the host\n // becomes unnamed (consumer responsibility).\n const fragments: string[] = [];\n for (const el of elements) {\n if (el.getAttribute('aria-hidden') === 'true') continue;\n // Round-8 F2 (P2): use the deep walker so nested aria-hidden / hidden\n // subtrees inside slotted parents are skipped per AccName 1.2 §4.3.10.\n const t = flattenAccName(el);\n if (t) fragments.push(t);\n }\n const trimmed = fragments.join(' ').replace(/\\s+/g, ' ').trim();\n this._labelSlotText = trimmed;\n this._hasLabelSlot = trimmed.length > 0;\n this._refreshLabelSource();\n this._syncHostAriaSemantics();\n });\n for (const el of elements) {\n // Round-9 F2 (P2): observe `aria-hidden` / `hidden` toggles on the\n // slotted label root AND its descendants. The MO callback above re-runs\n // `flattenAccName` and re-derives `_hasLabelSlot` from effective text —\n // so an in-place visibility flip on a child must trigger a fresh sync.\n observer.observe(el, {\n characterData: true,\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['aria-hidden', 'hidden'],\n });\n }\n this._labelSlotTextObserver = observer;\n }\n\n /**\n * Recomputes the discriminated label source.\n * @internal\n */\n private _refreshLabelSource(): void {\n if (this.label) {\n this._labelSource = 'string';\n } else if (this._hasLabelSlot) {\n this._labelSource = 'slot';\n } else {\n this._labelSource = 'none';\n }\n }\n\n /** @internal */\n private _handleErrorSlotChange(e: Event): void {\n if (!(e.target instanceof HTMLSlotElement)) return;\n // Round-6 F1 (P2): single-source-of-truth state read.\n this._hasErrorSlot = this._readErrorSlotStateSync(e.target);\n this._installErrorSlotTextObserver(e.target);\n this._syncHostAriaSemantics();\n }\n\n /** @internal */\n private _handleHelpSlotChange(e: Event): void {\n if (!(e.target instanceof HTMLSlotElement)) return;\n // Round-6 F1 (P2): single-source-of-truth state read.\n this._hasHelpSlot = this._readHelpSlotStateSync(e.target);\n this._installHelpSlotTextObserver(e.target);\n this._syncHostAriaSemantics();\n }\n\n // ─── Dropdown Control ───\n\n /** @internal */\n private _openDropdown(): void {\n if (this.disabled || this._open) return;\n this._open = true;\n this._focusedOptionIndex = -1;\n if (typeof document !== 'undefined') {\n document.addEventListener('click', this._handleOutsideClick);\n }\n this.dispatchEvent(new CustomEvent<void>('hx-show', { bubbles: true, composed: true }));\n }\n\n /** @internal */\n private _closeDropdown(): void {\n if (!this._open) return;\n this._open = false;\n this._focusedOptionIndex = -1;\n this._handleInteractionBlur();\n if (typeof document !== 'undefined') {\n document.removeEventListener('click', this._handleOutsideClick);\n }\n this.dispatchEvent(new CustomEvent<void>('hx-hide', { bubbles: true, composed: true }));\n }\n\n // ─── Input Handling ───\n\n /** @internal */\n private _handleInput(e: Event): void {\n const input = e.target as HTMLInputElement;\n this._filterText = input.value;\n\n if (!this._open) {\n this._openDropdown();\n }\n\n this._focusedOptionIndex = -1;\n\n if (this.filterDebounce > 0) {\n if (this._debounceTimer !== null) {\n clearTimeout(this._debounceTimer);\n }\n this._debounceTimer = setTimeout(() => {\n this._emitInput();\n this._announceFilterResults();\n }, this.filterDebounce);\n } else {\n this._emitInput();\n this._announceFilterResults();\n }\n }\n\n /** @internal */\n private _announceFilterResults(): void {\n const count = this._filteredOptions.length;\n this._filterAnnouncement =\n count === 0\n ? 'No matching options'\n : `${count} ${count === 1 ? 'option' : 'options'} available`;\n }\n\n /** @internal */\n private _emitInput(): void {\n this.dispatchEvent(\n new CustomEvent<{ value: string }>('hx-input', {\n bubbles: true,\n composed: true,\n detail: { value: this._filterText },\n }),\n );\n }\n\n /** @internal */\n private _handleFocus(): void {\n this._openDropdown();\n }\n\n // ─── Keyboard Navigation ───\n\n /** @internal */\n private _handleKeydown(e: KeyboardEvent): void {\n if (this.disabled) return;\n\n const filtered = this._filteredOptions;\n const enabledIndices = filtered\n .map((o, i) => ({ o, i }))\n .filter(({ o }) => !o.disabled)\n .map(({ i }) => i);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n if (!this._open) {\n this._openDropdown();\n this._focusedOptionIndex = enabledIndices.length > 0 ? (enabledIndices[0] ?? 0) : -1;\n break;\n }\n const nextDown = enabledIndices.find((i) => i > this._focusedOptionIndex);\n this._focusedOptionIndex =\n nextDown !== undefined ? nextDown : (enabledIndices[0] ?? this._focusedOptionIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n if (!this._open) {\n this._openDropdown();\n const lastEnabled = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex = lastEnabled !== undefined ? lastEnabled : -1;\n break;\n }\n const prevUp = [...enabledIndices].reverse().find((i) => i < this._focusedOptionIndex);\n const lastEnabledUp = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex =\n prevUp !== undefined ? prevUp : (lastEnabledUp ?? this._focusedOptionIndex);\n break;\n }\n case 'Enter': {\n e.preventDefault();\n if (!this._open) {\n this._openDropdown();\n break;\n }\n if (this._focusedOptionIndex >= 0 && this._focusedOptionIndex < filtered.length) {\n const opt = filtered[this._focusedOptionIndex];\n if (opt) this._selectOption(opt);\n }\n break;\n }\n case 'Escape': {\n e.preventDefault();\n this._closeDropdown();\n this._filterText = '';\n if (this._input) this._input.value = '';\n // Note: do NOT call this.focus() here — the inner <input> already has\n // focus when Escape is pressed and refocusing would re-trigger\n // _handleFocus → _openDropdown, immediately re-opening the listbox.\n // The input remains focused so the user can continue typing.\n break;\n }\n case 'Tab': {\n this._closeDropdown();\n break;\n }\n // P1-1: Home/End keyboard navigation for option list\n case 'Home': {\n e.preventDefault();\n if (!this._open) this._openDropdown();\n this._focusedOptionIndex = enabledIndices.length > 0 ? (enabledIndices[0] ?? -1) : -1;\n break;\n }\n case 'End': {\n e.preventDefault();\n if (!this._open) this._openDropdown();\n this._focusedOptionIndex =\n enabledIndices.length > 0 ? (enabledIndices[enabledIndices.length - 1] ?? -1) : -1;\n break;\n }\n default:\n break;\n }\n }\n\n // ─── Selection ───\n\n // P0-1: Handle both single and multiple selection modes\n /** @internal */\n private _selectOption(option: ComboboxOption): void {\n if (option.disabled) return;\n if (this.multiple) {\n const current = this._selectedValuesSet;\n const next = new Set(current);\n if (next.has(option.value)) {\n next.delete(option.value);\n } else {\n next.add(option.value);\n }\n this.value = [...next].join(',');\n // Keep dropdown open for multiple selection so user can pick more\n } else {\n this.value = option.value;\n this._closeDropdown();\n }\n this._handleInteractionInput();\n this._filterText = '';\n if (this._input) this._input.value = '';\n this._dispatchChange();\n }\n\n // P0-1: Remove a single value from multi-selection\n /** @internal */\n private _removeValue(val: string): void {\n const next = this._selectedValuesSet;\n next.delete(val);\n this.value = [...next].join(',');\n this._dispatchChange();\n }\n\n // ─── Clear ───\n\n /** @internal */\n private _handleClear(e: Event): void {\n e.stopPropagation();\n this.value = '';\n this._filterText = '';\n if (this._input) {\n this._input.value = '';\n this._input.focus();\n }\n this._internals.setFormValue(null);\n this._updateValidity();\n this.dispatchEvent(new CustomEvent<void>('hx-clear', { bubbles: true, composed: true }));\n }\n\n // ─── Event Dispatchers ───\n\n /** @internal */\n private _dispatchChange(): void {\n this.dispatchEvent(\n new CustomEvent<{ value: string }>('hx-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n // ─── Outside Click Handler ───\n\n /** @internal */\n private _handleOutsideClick = (e: MouseEvent): void => {\n if (this._open && !e.composedPath().includes(this)) {\n this._closeDropdown();\n }\n };\n\n // ─── Public Methods ───\n\n /**\n * Routes programmatic focus to the inner text input. Per W3C APG editable\n * combobox pattern, the inner `<input>` carries `role=\"combobox\"` (replacing\n * its implicit textbox role) so it IS the canonical announced + focused\n * surface. Shadow DOM focus causes `document.activeElement` to report the\n * host externally, but the input retains focus inside the shadow root and\n * AT announces its role/state.\n */\n override focus(options?: FocusOptions): void {\n this._input?.focus(options);\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _optionId(index: number): string {\n return `${this._id}-option-${index}`;\n }\n\n /** @internal */\n private get _displayValue(): string {\n // P0-1: In multiple mode, chips render selected values — input shows only filter text\n if (this.multiple) return '';\n if (!this.value) return '';\n const opt = this._options.find((o) => o.value === this.value);\n return opt ? opt.label : this.value;\n }\n\n /** @internal */\n private _renderOptions() {\n const filtered = this._filteredOptions;\n\n if (filtered.length === 0) {\n return html`\n <slot name=\"empty-label\">\n <div class=\"field__no-options\">${this.labelNoOptions}</div>\n </slot>\n `;\n }\n\n return repeat(\n filtered,\n (opt) => opt.value,\n (opt, index) => {\n // P0-1: Use Set membership for multiple mode, direct equality for single mode\n const isSelected = this.multiple\n ? this._selectedValuesSet.has(opt.value)\n : opt.value === this.value;\n const isFocused = index === this._focusedOptionIndex;\n\n return html`\n <div\n id=${this._optionId(index)}\n part=\"option\"\n role=\"option\"\n class=${classMap({\n field__option: true,\n 'field__option--selected': isSelected,\n 'field__option--focused': isFocused,\n 'field__option--disabled': opt.disabled,\n })}\n aria-selected=${this.multiple\n ? isSelected\n ? 'true'\n : 'false'\n : isSelected\n ? 'true'\n : nothing}\n aria-disabled=${opt.disabled ? 'true' : nothing}\n @click=${() => this._selectOption(opt)}\n >\n <span class=\"field__option-label\">${opt.label}</span>\n </div>\n `;\n },\n );\n }\n\n // ─── Main Render ───\n\n override render() {\n const hasError = !!this.error || this._hasErrorSlot;\n const hasHelp = !!this.helpText || this._hasHelpSlot;\n const showClear = this.clearable && !!this.value && !this.disabled;\n\n const fieldClasses = {\n field: true,\n 'field--error': hasError,\n 'field--disabled': this.disabled,\n 'field--required': this.required,\n 'field--open': this._open,\n };\n\n const inputClasses = {\n field__input: true,\n [`field__input--${this.size}`]: true,\n };\n\n // W3C APG editable combobox (option I): role=\"combobox\" lives on the\n // inner <input>, replacing the implicit textbox role so AT sees a single\n // canonical announced + focused surface. All combobox state ARIA —\n // aria-expanded, aria-controls, aria-activedescendant, aria-autocomplete,\n // aria-haspopup, aria-required, aria-invalid, aria-disabled, aria-busy —\n // is bound on the input via Lit. aria-label / aria-labelledby /\n // aria-describedby are written imperatively by _syncHostAriaSemantics\n // after consumer-IDREF resolution.\n const activeOptionId =\n this._open && this._focusedOptionIndex >= 0 ? this._optionId(this._focusedOptionIndex) : '';\n\n return html`\n <div part=\"field\" class=${classMap(fieldClasses)}>\n <!-- Label -->\n <slot name=\"label\" @slotchange=${this._handleLabelSlotChange}>\n ${this.label\n ? html`<label id=${this._labelId} for=${this._id} part=\"label\" class=\"field__label\">\n ${this.label}\n ${this.required\n ? html`<span class=\"field__required-marker\" aria-hidden=\"true\">*</span>`\n : nothing}\n </label>`\n : nothing}\n </slot>\n\n <!-- Input Wrapper -->\n <div part=\"trigger\" class=\"field__input-wrapper\">\n <!-- Prefix Slot -->\n <slot name=\"prefix\" class=\"field__prefix\"></slot>\n\n <!-- P0-1: Selected value chips for multiple mode -->\n ${this.multiple && this._selectedValuesSet.size > 0\n ? [...this._selectedValuesSet].map((val) => {\n const opt = this._options.find((o) => o.value === val);\n const label = opt ? opt.label : val;\n return html`\n <span class=\"field__chip\">\n <span class=\"field__chip-label\">${label}</span>\n <button\n type=\"button\"\n class=\"field__chip-remove\"\n aria-label=${this.labelRemoveOption(label)}\n @click=${(e: Event) => {\n e.stopPropagation();\n this._removeValue(val);\n }}\n >\n <svg\n width=\"8\"\n height=\"8\"\n viewBox=\"0 0 8 8\"\n fill=\"none\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path\n d=\"M1 1L7 7M7 1L1 7\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n </span>\n `;\n })\n : nothing}\n\n <!--\n Text input — W3C APG editable combobox (option I).\n role=\"combobox\" REPLACES the implicit textbox role; all combobox\n state ARIA lives here so AT sees one canonical surface.\n aria-label / aria-labelledby / aria-describedby are written\n imperatively by _syncHostAriaSemantics after consumer IDREF\n resolution and are not bound here.\n -->\n <input\n part=\"input\"\n type=\"text\"\n id=${this._id}\n role=\"combobox\"\n class=${classMap(inputClasses)}\n .value=${this._filterText || (this._open ? '' : this._displayValue)}\n placeholder=${ifDefined(this.placeholder || undefined)}\n ?disabled=${this.disabled}\n ?required=${this.required}\n name=${ifDefined(this.name || undefined)}\n autocomplete=\"off\"\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-controls=${this._listboxId}\n aria-expanded=${this._open ? 'true' : 'false'}\n aria-activedescendant=${ifDefined(activeOptionId || undefined)}\n aria-required=${this.required ? 'true' : 'false'}\n aria-invalid=${this._invalid ? 'true' : 'false'}\n aria-busy=${this.loading ? 'true' : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n @input=${this._handleInput}\n @focus=${this._handleFocus}\n @keydown=${this._handleKeydown}\n />\n\n <!-- Loading Indicator -->\n ${this.loading\n ? html`\n <div part=\"loading-indicator\" class=\"field__loading-indicator\" aria-hidden=\"true\">\n <div class=\"field__loading-spinner\"></div>\n </div>\n `\n : nothing}\n\n <!-- Clear Button -->\n ${showClear\n ? html`\n <button\n part=\"clear-button\"\n type=\"button\"\n class=\"field__clear-button\"\n aria-label=${`Clear ${this.label || this.accessibleLabel || 'selection'}`}\n tabindex=\"0\"\n @click=${this._handleClear}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path\n d=\"M1 1L11 11M11 1L1 11\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n `\n : nothing}\n\n <!-- Suffix Slot -->\n <slot name=\"suffix\" class=\"field__suffix\"></slot>\n </div>\n\n <!-- Listbox -->\n <div\n part=\"listbox\"\n role=\"listbox\"\n id=${this._listboxId}\n class=\"field__listbox\"\n aria-label=${ifDefined(this.label || this.accessibleLabel || undefined)}\n aria-multiselectable=${this.multiple ? 'true' : nothing}\n ?hidden=${!this._open}\n >\n <div class=\"field__options\">${this._renderOptions()}</div>\n </div>\n\n <!-- Hidden slot (options read from here) -->\n <slot name=\"option\" @slotchange=${this._handleSlotChange} style=\"display:none;\"></slot>\n\n <!--\n Persistent error live region. role=\"alert\" is set from first paint\n so the WAI-ARIA contract for live updates is honoured.\n -->\n <div\n part=\"error\"\n class=\"field__error\"\n id=${this._errorId}\n role=\"alert\"\n ?hidden=${!hasError}\n >\n <slot name=\"error\" @slotchange=${this._handleErrorSlotChange}\n >${this._announcedError}</slot\n >\n </div>\n\n <!--\n Persistent help-text container. Rendered whenever the property OR\n the slot has content; hidden when an error is present.\n -->\n <div\n part=\"help-text\"\n class=\"field__help-text\"\n id=${this._helpTextId}\n ?hidden=${!hasHelp || hasError}\n >\n <slot name=\"help-text\" @slotchange=${this._handleHelpSlotChange}>${this.helpText}</slot>\n </div>\n\n <!-- Filter results live region -->\n <div id=${this._liveRegionId} aria-live=\"polite\" aria-atomic=\"true\" class=\"field__sr-only\">\n ${this._filterAnnouncement}\n </div>\n\n <!--\n Round-5 F1 (P1): synthesized in-shadow mirror of the consumer-\n resolved description text. Its id is appended to the inner input's\n aria-describedby chain so AT picks the consumer description up\n through the standard described-by channel without needing\n aria-description (which W3C AccName drops whenever\n aria-describedby is also present). Same-root id resolves from\n inside the shadow tree; consumer light-DOM ids do not. The text\n content is updated by _syncHostAriaSemantics on every sync.\n -->\n <span id=${this._consumerDescId} class=\"field__sr-only\" aria-hidden=\"false\"></span>\n </div>\n `;\n }\n}\n\n/**\n * Per-component event map for type-safe addEventListener on hx-combobox.\n * The `hx-change` detail is `{ value: string }` only — no `checked` property.\n */\nexport interface HxComboboxEventMap {\n 'hx-input': CustomEvent<{ value: string }>;\n 'hx-change': CustomEvent<{ value: string }>;\n 'hx-clear': CustomEvent<void>;\n 'hx-show': CustomEvent<void>;\n 'hx-hide': CustomEvent<void>;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-combobox': HelixCombobox;\n }\n interface HTMLElementEventMap {\n 'hx-input': CustomEvent<{ value: string }>;\n // hx-change is also declared by hx-checkbox with a wider union; both\n // declarations must agree — the union covers all components that fire it.\n 'hx-change': CustomEvent<{ value: string } | { checked: boolean; value: string }>;\n 'hx-clear': CustomEvent<void>;\n 'hx-show': CustomEvent<void>;\n 'hx-hide': CustomEvent<void>;\n }\n}\n\nexport type { HelixCombobox as HxCombobox };\n"],"names":["helixComboboxStyles","css","_nextComboboxId","createIdCounter","flattenAccName","root","result","walker","node","el","textNode","HelixCombobox","FormMixin","HelixElement","label","lower","o","ctor","supportsIdrefElementReferences","records","consumerCleared","record","oldValue","newValue","installAriaIdrefMirror","_a","_b","_c","_d","_e","_f","changedProperties","labelSlot","state","helpSlot","errorSlot","slot","nodes","elements","fragments","elText","txt","trimmedText","unique","observer","internals","input","isInvalidEarly","liveAriaLabel","hostAriaLabel","internalLabel","slottedLabelEls","helpEl","errorEl","liveLabelledBy","liveDescribedBy","externalLabelTokens","externalDescTokens","consumerLabelEls","resolveIdrefTokens","hasEffectiveLabelledBy","consumerDescEls","hasError","isInvalid","explicitAccessibleLabel","isVisibleForAccName","labelElsForInternals","descElsForInternals","refsInternals","flattenText","els","t","inputAriaLabel","inputAriaLabelledBy","labelledByFlat","flat","consumerDescSpan","consumerDescText","describedByIds","value","_mode","disabled","parsed","child","trimmed","count","filtered","enabledIndices","i","nextDown","lastEnabled","prevUp","lastEnabledUp","opt","option","current","next","val","options","index","html","repeat","isSelected","isFocused","classMap","nothing","hasHelp","showClear","fieldClasses","inputClasses","activeOptionId","e","ifDefined","forcedColorsField","__decorateClass","property","query","customElement"],"mappings":";;;;;;;;;;AAEO,MAAMA,KAAsBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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"}
1
+ {"version":3,"file":"hx-combobox-NgJaLbs2.js","sources":["../../src/components/hx-combobox/hx-combobox.styles.ts","../../src/components/hx-combobox/hx-combobox.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixComboboxStyles = css`\n :host {\n display: block;\n }\n :host([disabled]) {\n opacity: var(--hx-opacity-disabled, 0.5);\n pointer-events: none;\n }\n * {\n box-sizing: border-box;\n }\n .field {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n font-family: var(--hx-combobox-font-family, var(--hx-font-family-sans, sans-serif));\n position: relative;\n }\n .field__label {\n display: flex;\n align-items: baseline;\n gap: var(--hx-space-1, 0.25rem);\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n color: var(--hx-combobox-label-color, var(--hx-color-text-strong, #202b39));\n line-height: var(--hx-line-height-normal, 1.5);\n }\n .field__required-marker {\n color: var(--hx-combobox-error-color, var(--hx-color-error-text, #c92a2a));\n font-weight: var(--hx-font-weight-bold, 700);\n }\n .field__input-wrapper {\n position: relative;\n display: flex;\n align-items: center;\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-combobox-border-color, var(--hx-color-border-strong, #66787b));\n border-radius: var(--hx-combobox-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-combobox-bg, var(--hx-color-surface-default, #ffffff));\n transition:\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n }\n .field__input-wrapper:focus-within {\n border-color: var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)\n color-mix(\n in srgb,\n var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078))\n calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n .field--error .field__input-wrapper {\n border-color: var(--hx-combobox-error-color, var(--hx-color-error-500, #e5493e));\n }\n .field--error .field__input-wrapper:focus-within {\n border-color: var(--hx-combobox-error-color, var(--hx-color-error-500, #e5493e));\n box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)\n color-mix(\n in srgb,\n var(--hx-combobox-error-color, var(--hx-color-error-500, #e5493e))\n calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n .field__prefix,\n .field__suffix {\n display: flex;\n align-items: center;\n padding: 0 var(--hx-space-2, 0.5rem);\n color: var(--hx-color-text-muted, #4a5362);\n flex-shrink: 0;\n }\n .field__input {\n flex: 1;\n min-width: 0;\n min-height: var(--hx-input-height-md, var(--hx-size-10, 2.5rem));\n border: none;\n background: transparent;\n outline: none;\n font-family: inherit;\n font-size: var(--hx-font-size-md, 1rem);\n line-height: var(--hx-line-height-normal, 1.5);\n color: var(--hx-combobox-color, var(--hx-color-text-strong, #202b39));\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n }\n .field__input::placeholder {\n color: var(--hx-color-text-placeholder, #66787b);\n }\n .field__input--sm {\n min-height: var(--hx-input-height-sm, var(--hx-size-8, 2rem));\n font-size: var(--hx-font-size-sm, 0.875rem);\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-3, 0.75rem);\n }\n .field__input--lg {\n min-height: var(--hx-input-height-lg, var(--hx-size-12, 3rem));\n font-size: var(--hx-font-size-lg, 1.125rem);\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n }\n .field__clear-button,\n .field__loading-indicator {\n display: flex;\n align-items: center;\n justify-content: center;\n margin-inline-end: var(--hx-space-2, 0.5rem);\n flex-shrink: 0;\n color: var(--hx-color-text-placeholder, #66787b);\n }\n .field__clear-button {\n width: 1.25rem;\n height: 1.25rem;\n border: none;\n background: transparent;\n cursor: pointer;\n padding: 0;\n border-radius: var(--hx-border-radius-full, 9999px);\n transition: color var(--hx-transition-fast, 150ms ease);\n }\n .field__clear-button:hover {\n color: var(--hx-color-text-strong, #202b39);\n }\n .field__clear-button:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n .field__loading-indicator {\n width: 1rem;\n height: 1rem;\n }\n .field__loading-spinner {\n width: 1rem;\n height: 1rem;\n border: 2px solid currentColor;\n border-top-color: transparent;\n border-radius: 50%;\n animation: hx-spin 0.7s linear infinite;\n }\n @keyframes hx-spin {\n to {\n transform: rotate(360deg);\n }\n }\n @media (prefers-reduced-motion: reduce) {\n .field__loading-spinner {\n animation: none;\n }\n }\n .field__listbox {\n position: absolute;\n top: calc(100% + var(--hx-space-1, 0.25rem));\n left: 0;\n right: 0;\n z-index: var(--hx-z-index-dropdown, 1000);\n background-color: var(--hx-combobox-listbox-bg, var(--hx-color-surface-default, #ffffff));\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-combobox-border-color, var(--hx-color-border-strong, #66787b));\n border-radius: var(--hx-combobox-border-radius, var(--hx-border-radius-md, 0.375rem));\n box-shadow: var(\n --hx-combobox-listbox-shadow,\n 0 4px 16px color-mix(in srgb, var(--hx-color-neutral-900, #0d1825) 12%, transparent)\n );\n max-height: var(--hx-combobox-listbox-max-height, 16rem);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n .field__listbox[hidden] {\n display: none;\n }\n .field__options {\n overflow-y: auto;\n flex: 1;\n padding: var(--hx-space-1, 0.25rem) 0;\n }\n .field__option {\n display: flex;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-md, 1rem);\n color: var(--hx-combobox-color, var(--hx-color-text-strong, #202b39));\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n transition: background-color var(--hx-transition-fast, 150ms ease);\n }\n .field__option:hover {\n background-color: var(--hx-combobox-option-hover-bg, var(--hx-color-primary-50, #ebf8f8));\n }\n .field__option--selected {\n background-color: var(--hx-combobox-option-selected-bg, var(--hx-color-primary-100, #dbf0f0));\n font-weight: var(--hx-font-weight-medium, 500);\n }\n .field__option--focused {\n background-color: var(--hx-combobox-option-hover-bg, var(--hx-color-primary-50, #ebf8f8));\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-combobox-option-focus-ring-offset, -2px);\n }\n .field__option--focused.field__option--selected {\n background-color: var(--hx-combobox-option-selected-bg, var(--hx-color-primary-100, #dbf0f0));\n }\n .field__option--disabled {\n opacity: var(--hx-opacity-disabled, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n .field__option-label {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n .field__no-options {\n padding: var(--hx-space-3, 0.75rem);\n text-align: center;\n color: var(--hx-color-text-placeholder, #66787b);\n font-size: var(--hx-font-size-sm, 0.875rem);\n }\n .field__sr-only {\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 .field__help-text,\n .field__error {\n font-size: var(--hx-font-size-xs, 0.75rem);\n line-height: var(--hx-line-height-normal, 1.5);\n }\n .field__help-text {\n color: var(--hx-color-text-muted, #4a5362);\n }\n .field__error {\n color: var(--hx-combobox-error-color, var(--hx-color-error-text, #c92a2a));\n }\n @media (prefers-reduced-motion: reduce) {\n .field__input-wrapper,\n .field__option,\n .field__clear-button,\n .field__chip-remove {\n transition: none;\n }\n }\n @media (forced-colors: active) {\n .field__input-wrapper {\n forced-color-adjust: none;\n background-color: Field;\n color: FieldText;\n border: 2px solid ButtonText;\n }\n .field__input {\n color: FieldText;\n }\n .field__input::placeholder {\n color: GrayText;\n }\n .field__input-wrapper:focus-within {\n border-color: Highlight;\n box-shadow: none;\n }\n .field__listbox {\n forced-color-adjust: none;\n background-color: Canvas;\n border: 2px solid CanvasText;\n box-shadow: none;\n }\n .field__option {\n color: CanvasText;\n }\n .field__option:hover {\n background-color: Highlight;\n color: HighlightText;\n }\n .field__option--selected {\n background-color: Highlight;\n color: HighlightText;\n }\n .field__option--focused {\n outline-color: Highlight;\n background-color: Highlight;\n color: HighlightText;\n }\n .field__option--disabled {\n color: GrayText;\n opacity: 1;\n }\n .field__chip {\n forced-color-adjust: none;\n background-color: Highlight;\n color: HighlightText;\n border: 1px solid HighlightText;\n }\n .field__chip-remove:focus-visible {\n outline-color: Highlight;\n }\n .field__clear-button:focus-visible {\n outline-color: Highlight;\n }\n .field--error .field__input-wrapper {\n border-color: LinkText;\n }\n :host([disabled]) {\n opacity: 1;\n }\n :host([disabled]) .field__input-wrapper {\n border-color: GrayText;\n color: GrayText;\n }\n :host([disabled]) .field__input {\n color: GrayText;\n }\n .field__label {\n color: CanvasText;\n }\n .field__help-text {\n color: GrayText;\n }\n .field__error {\n color: LinkText;\n }\n }\n :host([multiple]) .field__input-wrapper {\n flex-wrap: wrap;\n padding: var(--hx-space-1, 0.25rem);\n gap: var(--hx-space-1, 0.25rem);\n align-items: center;\n }\n :host([multiple]) .field__input {\n min-width: 8rem;\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-2, 0.5rem);\n flex-shrink: 1;\n }\n .field__chip {\n display: inline-flex;\n align-items: center;\n gap: var(--hx-space-1, 0.25rem);\n padding: 0 var(--hx-space-1, 0.25rem) 0 var(--hx-space-2, 0.5rem);\n height: 1.5rem;\n background-color: var(--hx-combobox-chip-bg, var(--hx-color-primary-100, #dbf0f0));\n color: var(--hx-combobox-chip-color, var(--hx-color-primary-800, #07494a));\n border-radius: var(--hx-border-radius-full, 9999px);\n font-size: var(--hx-font-size-sm, 0.875rem);\n white-space: nowrap;\n max-width: 12rem;\n flex-shrink: 0;\n }\n .field__chip-label {\n overflow: hidden;\n text-overflow: ellipsis;\n max-width: 8rem;\n }\n .field__chip-remove {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n width: 1rem;\n height: 1rem;\n border: none;\n background: none;\n cursor: pointer;\n padding: 0;\n color: inherit;\n opacity: 0.7;\n border-radius: 50%;\n line-height: 1;\n transition: opacity var(--hx-transition-fast, 150ms ease);\n }\n .field__chip-remove:hover {\n opacity: 1;\n background-color: var(--hx-combobox-chip-remove-hover-bg, var(--hx-color-primary-200, #bce1e1));\n }\n .field__chip-remove:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-combobox-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n opacity: 1;\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 { HelixElement, createIdCounter } from '../../base/index.js';\nimport { FormMixin } from '../../mixins/FormMixin.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { helixComboboxStyles } from './hx-combobox.styles.js';\nimport { forcedColorsField } from '../../styles/forced-colors.js';\nimport { devWarn } from '../../utils/dev-warn.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\n\n// PERF: hx-combobox exceeds 5KB budget (6.87kb gzipped) -- typeahead filtering, multi-select chips, async loading\n\n// ─── Internal option model ───\n\n// P1-7: Exported so TypeScript consumers can type option arrays programmatically\nexport interface ComboboxOption {\n value: string;\n label: string;\n disabled: boolean;\n}\n\n// P2-13: Exported size type for TypeScript consumers\nexport type HxComboboxSize = 'sm' | 'md' | 'lg';\n\nconst _nextComboboxId = createIdCounter('hx-combobox');\n\n/**\n * AccName-aware text flattener. Walks the subtree of `root` and concatenates\n * text-node content, REJECTING any element subtree carrying `aria-hidden=\"true\"`\n * or the `hidden` attribute per W3C AccName 1.2 §4.3.10. Used by hx-combobox\n * for both external IDREF flatten (host aria-labelledby/aria-describedby\n * targets) and slotted-label aggregation, so nested decorative content like\n * `<svg aria-hidden=\"true\"><title>icon</title></svg>` does not leak into the\n * inner input's announced name/description.\n *\n * Round-11 F1/F2 (P2): the TreeWalker filter only inspects elements VISITED\n * during the walk — it never tests the root itself, so a hidden ROOT (e.g.\n * `<span slot=\"label\" hidden>Secret</span>` or\n * `<span slot=\"help-text\" aria-hidden=\"true\">stale</span>`) would still\n * contribute its descendants' text. Per AccName 1.2 §4.3.10, a hidden root\n * contributes the empty string. Gate the walk here so every caller (slotted\n * label/help/error and external IDREF flatten) honors the rule symmetrically.\n */\nfunction flattenAccName(root: Element): string {\n if (root.getAttribute('aria-hidden') === 'true' || root.hasAttribute('hidden')) {\n return '';\n }\n let result = '';\n const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, {\n acceptNode(node) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as Element;\n if (el.getAttribute('aria-hidden') === 'true') {\n return NodeFilter.FILTER_REJECT;\n }\n if (el.hasAttribute('hidden')) {\n return NodeFilter.FILTER_REJECT;\n }\n return NodeFilter.FILTER_SKIP;\n }\n return NodeFilter.FILTER_ACCEPT;\n },\n });\n let textNode: Node | null = walker.nextNode();\n while (textNode) {\n result += textNode.textContent ?? '';\n textNode = walker.nextNode();\n }\n return result.replace(/\\s+/g, ' ').trim();\n}\n\n/** Detail for hx-input and hx-change events dispatched by hx-combobox. */\nexport interface HxComboboxDetail {\n value: string;\n}\n\n/**\n * A form-associated combobox component combining a text input with a listbox\n * for autocomplete and typeahead. Supports filtering, free-text entry,\n * keyboard navigation, and async option loading.\n *\n * @summary Form-associated combobox with autocomplete, filtering, and keyboard navigation.\n *\n * @tag hx-combobox\n *\n * @slot option - Slot for `<option>` elements that populate the listbox.\n * @slot prefix - Content to display before the text input.\n * @slot suffix - Content to display after the text input.\n * @slot empty-label - Content shown when no options match the filter.\n * @slot label - Custom label content (overrides the label property).\n * @slot error - Custom error content (overrides the error property).\n * @slot help-text - Custom help text content (overrides the helpText property).\n *\n * @fires {CustomEvent<{value: string}>} hx-input - Dispatched on each keystroke as the user types.\n * @fires {CustomEvent<{value: string}>} hx-change - Dispatched when an option is selected.\n * @fires {CustomEvent<void>} hx-clear - Dispatched when the clear button is activated.\n * @fires {CustomEvent<void>} hx-show - Dispatched when the listbox opens.\n * @fires {CustomEvent<void>} hx-hide - Dispatched when the listbox closes.\n *\n * @csspart input - The native text input element.\n * @csspart listbox - The dropdown panel containing options.\n * @csspart trigger - The input wrapper element acting as the combobox trigger.\n * @csspart clear-button - The button that clears the current value.\n * @csspart loading-indicator - The loading spinner shown during async operations.\n * @csspart field - The outer field wrapper element.\n * @csspart label - The label element.\n * @csspart option - An individual option item in the listbox.\n * @csspart error - The error message element.\n * @csspart help-text - The help text element.\n *\n * @cssprop [--hx-combobox-bg=var(--hx-color-neutral-0)] - Input background color.\n * @cssprop [--hx-combobox-color=var(--hx-color-neutral-800)] - Input text color.\n * @cssprop [--hx-combobox-border-color=var(--hx-color-neutral-300)] - Border color.\n * @cssprop [--hx-combobox-border-radius=var(--hx-border-radius-md)] - Border radius.\n * @cssprop [--hx-combobox-font-family=var(--hx-font-family-sans)] - Font family.\n * @cssprop [--hx-combobox-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-combobox-error-color=var(--hx-color-error-500)] - Error state color.\n * @cssprop [--hx-combobox-label-color=var(--hx-color-neutral-700)] - Label text color.\n * @cssprop [--hx-combobox-listbox-bg=var(--hx-color-neutral-0)] - Listbox background color.\n * @cssprop [--hx-combobox-option-hover-bg=var(--hx-color-primary-50)] - Option hover background.\n * @cssprop [--hx-combobox-option-selected-bg=var(--hx-color-primary-100)] - Selected option background.\n * @cssprop [--hx-opacity-disabled] - Opacity.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-font-family-sans] - Font family.\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-error-text] - Color.\n * @cssprop [--hx-font-weight-bold] - Font weight.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-color-neutral-300] - Color.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-opacity] - CSS custom property.\n * @cssprop [--hx-color-error-500] - Color.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-color-neutral-500] - Color.\n * @cssprop [--hx-input-height-md] - Height.\n * @cssprop [--hx-size-10] - Size token.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-color-neutral-800] - Color.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-color-neutral-400] - Color.\n * @cssprop [--hx-input-height-sm] - Height.\n * @cssprop [--hx-size-8] - Size token.\n * @cssprop [--hx-input-height-lg] - Height.\n * @cssprop [--hx-size-12] - Size token.\n * @cssprop [--hx-font-size-lg] - Font size.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-border-radius-full] - CSS custom property.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-z-index-dropdown] - Z-index layer.\n * @cssprop [--hx-combobox-listbox-shadow] - CSS custom property.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-combobox-listbox-max-height=16rem] - Height.\n * @cssprop [--hx-color-primary-50] - Color.\n * @cssprop [--hx-color-primary-100] - Color.\n * @cssprop [--hx-combobox-option-focus-ring-offset=-2px] - Focus ring styling.\n * @cssprop [--hx-font-size-xs] - Font size.\n * @cssprop [--hx-combobox-chip-bg=var(--hx-color-primary-100)] - Background color.\n * @cssprop [--hx-combobox-chip-color=var(--hx-color-primary-800)] - Color.\n * @cssprop [--hx-color-primary-800] - Color.\n * @cssprop [--hx-combobox-chip-remove-hover-bg=var(--hx-color-primary-200)] - Background color.\n * @cssprop [--hx-color-primary-200] - Color.\n * @aaa-certified 2026-05-08\n * @aaa-criteria 1.4.6, 1.4.9, 2.1.3, 2.3.3, 2.4.12, 2.4.13, 2.5.5, 3.2.5, 3.3.6, forced-colors, apg-keyboard\n * @aaa-audit src/components/hx-combobox/AAA-AUDIT.md\n * @keyboard-contract navigate=Arrow,Home,End; activate=Enter; dismiss=Escape; disabled-suppresses=true\n * @aria-pattern combobox\n * @aria-pattern-source https://www.w3.org/WAI/ARIA/apg/patterns/combobox/\n * @forced-colors-supported true\n * @stability stable\n * @since 3.7.0\n * @form-associated true\n * @theme-aware true\n * @brand-aware true\n * @drupal-sdc-eligible true\n * @react-wrapper-status complete\n * @figma-component-name hx-combobox\n * @priority-tier P0\n * @phi-handles false\n * @clinical-context none\n */\n@customElement('hx-combobox')\nexport class HelixCombobox extends FormMixin(HelixElement) {\n static override styles = [helixComboboxStyles, forcedColorsField];\n\n // ─── Form Association ───\n\n /** Marks this element as form-associated for ElementInternals support. @internal */\n static override formAssociated = true;\n\n /**\n * Test seam (round-3 finding 4): when set to `true` or `false`, overrides\n * the platform `supportsIdrefElementReferences` probe before\n * `connectedCallback` seeds `_supportsIdrefRefs`. Mid-life flag flips on a\n * connected instance allowed stale modern internals (set during connect)\n * to leak into the fallback branch — tests must select the path BEFORE\n * the host connects so the synthetic environment matches a legacy engine.\n *\n * Production code MUST NOT touch this field. It is a `static` so the test\n * stub cleanup is global and obvious.\n * @internal\n */\n static __testSupportsIdrefRefsOverride: boolean | null = null;\n\n // ─── Stable IDs ───\n\n /** @internal */\n private _id = _nextComboboxId();\n /** @internal */\n private _listboxId = `${this._id}-listbox`;\n /** @internal */\n private _helpTextId = `${this._id}-help`;\n /** @internal */\n private _errorId = `${this._id}-error`;\n /** @internal */\n private _labelId = `${this._id}-label`;\n /** @internal */\n private _liveRegionId = `${this._id}-live`;\n /**\n * Round-5 F1 (P1): id of the synthesized in-shadow span that mirrors the\n * consumer-resolved description text. This id is appended to the inner\n * input's `aria-describedby` so AT picks the consumer description up\n * through the standard described-by channel — `aria-description` is\n * intentionally NOT written, because the W3C AccName algorithm ignores\n * `aria-description` whenever `aria-describedby` is also present.\n * @internal\n */\n private _consumerDescId = `${this._id}-consumer-desc`;\n\n // ─── Public Properties ───\n\n /**\n * The visible label text for the combobox.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Placeholder text shown in the input when no value is entered.\n * @attr placeholder\n */\n @property({ type: String })\n placeholder = '';\n\n /**\n * The current value of the combobox.\n * @attr value\n */\n @property({ type: String, reflect: true })\n value = '';\n\n /**\n * Whether the combobox is required for form submission.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /**\n * Whether the combobox is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * The name used for form submission.\n * @attr name\n */\n @property({ type: String, reflect: true })\n name = '';\n\n /**\n * Error message to display. When set, the field enters an error state.\n * @attr error\n */\n @property({ type: String })\n error = '';\n\n /**\n * Help text displayed below the combobox for guidance.\n * @attr help-text\n */\n @property({ type: String, attribute: 'help-text' })\n helpText = '';\n\n /**\n * Size variant of the combobox.\n * @attr hx-size\n */\n @property({ type: String, attribute: 'hx-size', reflect: true })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Whether multiple options can be selected.\n * @attr multiple\n */\n @property({ type: Boolean, reflect: true })\n multiple = false;\n\n /**\n * Whether the combobox shows a clear button when a value is set.\n * @attr clearable\n */\n @property({ type: Boolean, reflect: true })\n clearable = false;\n\n /**\n * Whether the combobox is in a loading state (shows spinner).\n * @attr loading\n */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n /**\n * Debounce delay in milliseconds for the filter input event.\n * @attr filter-debounce\n */\n @property({ type: Number, attribute: 'filter-debounce' })\n filterDebounce = 0;\n\n /**\n * Accessible name for screen readers, if different from the visible label.\n * Uses `accessible-label` attribute instead of `aria-label` to avoid\n * ARIAMixin shadowing on the host element.\n *\n * Note: `mixinDelegatesAria` is not applied to this component because form\n * inputs with associated labels delegate accessible naming via `<label>`\n * association and `aria-labelledby`, not host-level ARIA delegation. The\n * `accessible-label` attribute is a fallback for label-free usage. The value is forwarded to the\n * host's `internals.ariaLabel` on the modern path.\n * @attr accessible-label\n */\n @property({ type: String, attribute: 'accessible-label' })\n accessibleLabel: string | null = null;\n\n /**\n * Text shown when no options match the current filter.\n * @attr label-no-options\n */\n @property({ type: String, attribute: 'label-no-options' })\n labelNoOptions = 'No options found';\n\n /**\n * Validation message shown when the field is required but empty.\n * @attr label-required\n */\n @property({ type: String, attribute: 'label-required' })\n labelRequired = 'Please select an option.';\n\n /**\n * Generates the accessible label for multi-select chip remove buttons.\n * @param label - the option label text\n */\n @property({ attribute: false })\n labelRemoveOption: (label: string) => string = (label) => `Remove ${label}`;\n\n // ─── Internal State ───\n\n /** Parsed option models derived from slotted `<option>` and `<optgroup>` elements. @internal */\n @state() private _options: ComboboxOption[] = [];\n /** Current text typed in the input, used to filter the option list. @internal */\n @state() private _filterText = '';\n /** Whether the listbox dropdown is currently visible. @internal */\n @state() private _open = false;\n /** Zero-based index of the keyboard-focused option within the filtered list; -1 means none. @internal */\n @state() private _focusedOptionIndex = -1;\n /** Whether the named error slot contains projected content. @internal */\n @state() private _hasErrorSlot = false;\n /** Whether the named help-text slot contains projected content. @internal */\n @state() private _hasHelpSlot = false;\n /** Live-region announcement text describing the current number of filtered options. @internal */\n @state() private _filterAnnouncement = '';\n /**\n * Source of the accessible name. Discriminated union replaces the magic\n * `'*slotted*'` sentinel so a future caller setting `label=\"*slotted*\"`\n * literally cannot be confused with a slotted label.\n * @internal\n */\n @state() private _labelSource: 'string' | 'slot' | 'none' = 'none';\n /**\n * Flattened, trimmed text content of any text nodes in the label slot —\n * used to drive `internals.ariaLabel` when the consumer projects only a\n * text node (no element to add to `labelEls`).\n * @internal\n */\n @state() private _labelSlotText = '';\n /**\n * Whether the named label slot contributes a useful name. Requires either\n * a labellable element OR non-empty trimmed text content (whitespace-only\n * does NOT count).\n * @internal\n */\n @state() private _hasLabelSlot = false;\n /**\n * Whether the platform supports IDL element references on `ElementInternals`.\n * Drives the cross-shadow naming strategy for the inner `<input>`: modern\n * path resolves consumer light-DOM IDREFs and writes them as cloned/proxied\n * ids into the inner input's `aria-labelledby` / `aria-describedby`;\n * fallback path mirrors only consumer `aria-labelledby` / `aria-describedby`\n * tokens (resolved through the IDREF resolver) onto the inner input.\n *\n * ARCHITECTURE — W3C APG editable combobox (option I):\n * `role=\"combobox\"` lives on the inner `<input>` (replaces the implicit\n * textbox role). All combobox state ARIA — `aria-expanded`, `aria-controls`,\n * `aria-activedescendant`, `aria-autocomplete`, `aria-haspopup`,\n * `aria-required`, `aria-invalid`, `aria-disabled`, `aria-busy` — lives on\n * the inner input. The host carries no role and no tabindex; it is not a\n * tab stop and not an announced AT surface.\n * @internal\n */\n @state() private _supportsIdrefRefs = true;\n /**\n * Cached invalidity flag derived from `internals.validity.valid` after the\n * latest `setValidity()` call. Drives the inner input's `aria-invalid`.\n * @internal\n */\n @state() private _invalid = false;\n /**\n * Deferred copy of `error` driven through reactive state so the persistent\n * live region can re-announce on transitions without direct DOM mutation.\n * @internal\n */\n @state() private _announcedError = '';\n\n // ─── Queries ───\n\n /** Reference to the native text input element inside the shadow DOM. @internal */\n @query('.field__input')\n private _input: HTMLInputElement | undefined;\n\n // ─── Debounce timer ───\n\n /** @internal */\n private _debounceTimer: ReturnType<typeof setTimeout> | null = null;\n\n // ─── Multiple Selection ───\n\n // P0-1: Derive selected values Set from the comma-separated value property\n /** @internal */\n private get _selectedValuesSet(): Set<string> {\n if (!this.multiple || !this.value) return new Set();\n return new Set(this.value.split(',').filter(Boolean));\n }\n\n // ─── Filtered options ───\n\n /** @internal */\n private get _filteredOptions(): ComboboxOption[] {\n if (!this._filterText) return this._options;\n const lower = this._filterText.toLowerCase();\n return this._options.filter((o) => o.label.toLowerCase().includes(lower));\n }\n\n // ─── Host-canonical ARIA bookkeeping ───\n\n /**\n * Handle for the shared IDREF observer. See `installAriaIdrefMirror()`.\n * @internal\n */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n /**\n * Watches assigned `<slot name=\"help-text\">` nodes for in-place text\n * mutations so the no-IDL-ref fallback `internals.ariaDescription` stays in sync.\n * @internal\n */\n private _helpSlotTextObserver: MutationObserver | null = null;\n /**\n * Watches assigned `<slot name=\"error\">` nodes for in-place text mutations.\n * @internal\n */\n private _errorSlotTextObserver: MutationObserver | null = null;\n /**\n * Round-10 finding 1: dedicated host observer scoped to `aria-describedby`\n * with `attributeOldValue: true`. Governed by the disconnect-during-strip\n * discipline. See `_syncHostAriaSemantics` fallback branch.\n * @internal\n */\n private _hostDescribedByObserver: MutationObserver | null = null;\n /**\n * Most recently observed *consumer-supplied* `aria-labelledby` baseline.\n * Refreshed only when the host attribute changes via an external write.\n * On the modern path the host attribute is preserved; on the legacy\n * fallback the attribute is stripped during sync, so this baseline is the\n * only durable record of what the consumer asked for.\n * @internal\n */\n private _consumerLabelledBy: string | null = null;\n /** @internal — see `_consumerLabelledBy`. */\n private _consumerDescribedBy: string | null = null;\n /**\n * Direct references to ALL labellable elements projected into\n * `<slot name=\"label\">`. Round-4 F1 (P2): aggregating every assigned element\n * — not just the first — preserves composed labels such as\n * `<svg slot=\"label\" aria-hidden=\"true\">…</svg><span slot=\"label\">Patient</span>`\n * or `<span slot=\"label\">First</span><span slot=\"label\">name</span>`. The\n * modern path passes the full array to `internals.ariaLabelledByElements`\n * and the fallback path text-flattens every node into `_labelSlotText` per\n * AccName 1.2. Avoids mutating consumer light-DOM and survives nested\n * shadow roots without fragile getElementById chains.\n * @internal\n */\n private _slottedLabelEls: Element[] = [];\n /**\n * Round-4 F2 (P2): observes in-place text mutations on the assigned slotted\n * label nodes (e.g. consumer i18n re-renders that mutate the same\n * `<span slot=\"label\">` `textContent` instead of replacing it). Mirrors the\n * round-23 P2 pattern from `_helpSlotTextObserver` / `_errorSlotTextObserver`.\n * `slotchange` does NOT fire when only the descendant text mutates, so this\n * observer is the only signal that keeps the no-IDL-ref fallback\n * `aria-label` and the announced name in sync with the visible label.\n * @internal\n */\n private _labelSlotTextObserver: MutationObserver | null = null;\n /**\n * Round-7 F1 (P2): observes in-place text mutations on consumer light-DOM\n * elements resolved from host `aria-labelledby` / `aria-describedby`. When a\n * consumer keeps the same `<label id=\"...\">` but mutates its `textContent`\n * (e.g. an i18n rerender), `slotchange` does not fire and the host\n * attribute does not change — so without this observer the inner input's\n * `aria-label` and the synthesized description span keep announcing the\n * old flattened text indefinitely. Reinstalled on every sync against the\n * deduped union of resolved label/desc elements; disconnects automatically\n * when the consumer retracts both attribute chains.\n * @internal\n */\n private _externalRefsObserver: MutationObserver | null = null;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Round-3 finding 4: honour the static test override so synthetic\n // environments choose the path BEFORE connect runs.\n const ctor = this.constructor as typeof HelixCombobox;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n\n // Round-10 finding 1: install the dedicated `aria-describedby` retraction\n // observer BEFORE the seeded `_syncHostAriaSemantics()` call below, then\n // govern its lifetime with the disconnect-during-strip discipline.\n this._hostDescribedByObserver = new MutationObserver((records) => {\n let consumerCleared = false;\n for (const record of records) {\n if (record.attributeName !== 'aria-describedby') continue;\n const oldValue = record.oldValue;\n const newValue = this.getAttribute('aria-describedby');\n if (oldValue !== null && newValue === null) {\n // Consumer authentically retracted `aria-describedby`.\n this._consumerDescribedBy = null;\n consumerCleared = true;\n }\n }\n if (consumerCleared) {\n this._syncHostAriaSemantics();\n }\n });\n this._hostDescribedByObserver.observe(this, {\n attributes: true,\n attributeFilter: ['aria-describedby'],\n attributeOldValue: true,\n });\n\n // Seed root-independent semantics from connect so the host announces\n // combobox role 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 // Safety net: remove listener if component is removed while dropdown is open\n if (typeof document !== 'undefined') {\n document.removeEventListener('click', this._handleOutsideClick);\n }\n if (this._debounceTimer !== null) {\n clearTimeout(this._debounceTimer);\n }\n // Reset open state to prevent persisted open state on reconnect\n if (this._open) {\n this._open = false;\n }\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n this._helpSlotTextObserver?.disconnect();\n this._helpSlotTextObserver = null;\n this._errorSlotTextObserver?.disconnect();\n this._errorSlotTextObserver = null;\n this._labelSlotTextObserver?.disconnect();\n this._labelSlotTextObserver = null;\n this._hostDescribedByObserver?.disconnect();\n this._hostDescribedByObserver = null;\n this._externalRefsObserver?.disconnect();\n this._externalRefsObserver = null;\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('value')) {\n this._updateFormValue();\n }\n if (changedProperties.has('label')) {\n this._refreshLabelSource();\n }\n // Host-elevated ARIA semantics — see _syncHostAriaSemantics.\n this._syncHostAriaSemantics();\n // Drive re-announcement from reactive state so the persistent live region\n // stays in the shadow tree across error transitions.\n if (changedProperties.has('error')) {\n const previousError = changedProperties.get('error') as string;\n if (previousError && this.error) {\n // Error→error: clear then re-set after rAF so AT re-announces.\n this._announcedError = '';\n requestAnimationFrame(() => {\n this._announcedError = this.error;\n });\n } else {\n this._announcedError = this.error;\n }\n }\n }\n\n override willUpdate(changedProperties: PropertyValues<this>): void {\n super.willUpdate(changedProperties);\n // Round-7 F2 (P2) / round-10 F2 (P2): seed `_announcedError` BEFORE render\n // so the persistent live region renders with the error text in the SAME\n // frame that removes `hidden` from the alert container.\n //\n // Round-7 covered first paint (initial property/attribute). Round-10\n // extended this to RUNTIME transitions: when `error` flips from \"\" to\n // \"Server rejected\" via async/server-side validation, updating\n // `_announcedError` only in `updated()` left one frame where the alert\n // container was visible but empty — `aria-describedby` also pointed at an\n // empty error node for that cycle. Seeding here keeps the first visible\n // frame populated.\n //\n // The error-to-error rAF toggle in `updated()` still owns re-announcement\n // semantics for subsequent transitions (clearing then re-setting to force\n // AT to re-read role=\"alert\" content).\n if (changedProperties.has('error') || !this.hasUpdated) {\n this._announcedError = this.error ?? '';\n }\n }\n\n override firstUpdated(changedProperties: PropertyValues<this>): void {\n super.firstUpdated(changedProperties);\n // Round-5 F2 (P2): `slotchange` fires as a microtask after the initial\n // synchronous render. Without proactive seeding, the first\n // `_syncHostAriaSemantics()` call (driven from `updated()` in this same\n // cycle, AFTER firstUpdated returns) would observe stale `false` /\n // empty state for `_hasLabelSlot`, `_slottedLabelEls`, `_labelSlotText`,\n // `_hasHelpSlot`, and `_hasErrorSlot`. That would break flows that\n // mount a combobox with slot-only label/help/error and then focus\n // immediately — AT would announce an unnamed control until the\n // microtask `slotchange` corrected the state on the second update.\n //\n // Seed the slot-derived state synchronously here by reading the\n // assigned-nodes lists directly. The slot-change handlers remain wired\n // for subsequent slot mutations; this is purely a first-paint fix.\n this._seedSlotStateSync();\n // WCAG 4.1.2: warn when no accessible name is available. Now that the\n // label-slot state is seeded above, this check sees the same surface\n // area the next sync will, so the warning matches AT-observed reality.\n if (\n !this.label &&\n !this.accessibleLabel &&\n !this._hasLabelSlot &&\n !this.getAttribute('aria-label') &&\n !this.getAttribute('aria-labelledby')\n ) {\n devWarn(\n 'hx-combobox',\n 'No accessible label provided. Set the `label` attribute, `accessible-label`, `aria-label`, `aria-labelledby`, or project a `<slot name=\"label\">` child. An unlabeled combobox violates WCAG 2.1 AA (4.1.2 Name, Role, Value).',\n );\n }\n }\n\n /**\n * Round-5 F2 (P2): synchronous slot-state seed. Mirrors the side effects of\n * the three `_handle*SlotChange` handlers (label / help-text / error) but\n * is driven by direct `slot.assignedNodes()` reads so we can populate the\n * state BEFORE the microtask `slotchange` events fire after the first\n * render. Idempotent — calling it later is a no-op when state already\n * matches the slot contents.\n *\n * Also installs the label slot text observer so consumer in-place text\n * mutations on slotted label nodes are tracked even if the slotchange\n * event has not yet fired.\n * @internal\n */\n private _seedSlotStateSync(): void {\n const root = this.shadowRoot;\n if (!root) return;\n // Label slot — use the existing _readLabelSlotState helper to capture\n // the discriminated state (elements + flattened text + has-useful-name).\n const labelSlot = root.querySelector<HTMLSlotElement>('slot[name=\"label\"]');\n if (labelSlot) {\n const state = this._readLabelSlotState(labelSlot);\n this._hasLabelSlot = state.hasUsefulName;\n this._slottedLabelEls = state.elements;\n this._labelSlotText = state.text;\n // Install the text-mutation observer now so consumer i18n re-renders\n // that mutate the same slotted node's textContent are picked up even\n // before the first slotchange event lands.\n this._installLabelSlotTextObserver(state.elements);\n this._refreshLabelSource();\n }\n // Help-text slot — match `_handleHelpSlotChange` exactly.\n const helpSlot = root.querySelector<HTMLSlotElement>('slot[name=\"help-text\"]');\n if (helpSlot) {\n // Round-6 F1 (P2): use the effective-text reader so first-paint state\n // matches the MO's re-read logic. An empty/whitespace-only slot is NOT\n // a usable help text.\n this._hasHelpSlot = this._readHelpSlotStateSync(helpSlot);\n this._installHelpSlotTextObserver(helpSlot);\n }\n // Error slot — match `_handleErrorSlotChange` exactly.\n const errorSlot = root.querySelector<HTMLSlotElement>('slot[name=\"error\"]');\n if (errorSlot) {\n // Round-6 F1 (P2): use the effective-text reader so first-paint state\n // matches the MO's re-read logic.\n this._hasErrorSlot = this._readErrorSlotStateSync(errorSlot);\n this._installErrorSlotTextObserver(errorSlot);\n }\n }\n\n /**\n * Reads the label slot's assigned nodes and computes the discriminated\n * naming state. An empty whitespace-only slot does NOT count as a useful\n * name.\n *\n * Round-4 F1 (P2): aggregates ALL assigned elements (not just the first) and\n * concatenates `textContent` from every assigned node — element OR text —\n * trimmed and space-joined per AccName 1.2 text-flatten rules. This preserves\n * composed labels such as\n * `<svg slot=\"label\" aria-hidden=\"true\">…</svg><span slot=\"label\">Patient</span>`\n * or `<span slot=\"label\">First</span><span slot=\"label\">name</span>` on both\n * the modern (`internals.ariaLabelledByElements`) path and the no-IDL-ref\n * fallback (`aria-label`) path.\n *\n * Round-6 F2 (P2): per AccName 1.2 §4.3.10, `aria-hidden=\"true\"` elements\n * contribute zero to the accessible name. They are still tracked in\n * `elements` (so the modern `internals.ariaLabelledByElements` path projects\n * the FULL visible label — icon + text — for AT that walks IDL refs), but\n * they are skipped during text flattening. `hasUsefulName` is gated on the\n * flattened text length, so a slot containing ONLY decorative elements (or\n * empty wrappers) is NOT considered usable: `_labelSource` falls through to\n * the next naming source and the firstUpdated() devWarn fires for unnamed\n * controls. A composed `<svg aria-hidden><span>Patient</span>` slot still\n * resolves: text = \"Patient\" → usable; both elements still project on the\n * modern path.\n * @internal\n */\n private _readLabelSlotState(slot: HTMLSlotElement): {\n hasUsefulName: boolean;\n elements: Element[];\n text: string;\n } {\n const nodes = slot.assignedNodes({ flatten: true });\n const elements: Element[] = [];\n const fragments: string[] = [];\n for (const node of nodes) {\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as Element;\n elements.push(el);\n // Per AccName 1.2 §4.3.10, aria-hidden elements contribute zero to the\n // accessible name. Skip their text in the flatten — the element itself\n // remains in `elements` so the modern path still projects it via\n // `internals.ariaLabelledByElements` (full visible-label fidelity).\n if (el.getAttribute('aria-hidden') === 'true') continue;\n // Round-8 F2 (P2): use the deep walker so NESTED aria-hidden / hidden\n // subtrees inside a slotted parent element (e.g. an inline decorative\n // `<svg aria-hidden><title>icon</title></svg>` inside a slotted\n // `<span>Patient</span>`) are skipped per AccName 1.2 §4.3.10.\n const elText = flattenAccName(el);\n if (elText) fragments.push(elText);\n } else if (node.nodeType === Node.TEXT_NODE) {\n const txt = (node.textContent ?? '').trim();\n if (txt) fragments.push(txt);\n }\n }\n const trimmedText = fragments.join(' ').replace(/\\s+/g, ' ').trim();\n return {\n // Round-6 F2 (P2): gate on flattened TEXT, not element presence. A slot\n // with only decorative/aria-hidden elements (or empty wrappers) yields\n // text === '' and is NOT a usable name.\n hasUsefulName: trimmedText.length > 0,\n elements,\n text: trimmedText,\n };\n }\n\n /**\n * Round-6 F1 (P2): re-evaluate the help-text slot's \"has meaningful content\"\n * state from its current effective text. Mirrors the slotchange-handler\n * logic but is invocable from the in-place mutation observer so that\n * clearing `textContent` on the same slotted node flips `_hasHelpSlot`\n * back to `false` (without this, the help wrapper stays visible, the help\n * id stays in the inner input's `aria-describedby`, and AT keeps announcing\n * stale guidance).\n * @internal\n */\n private _readHelpSlotStateSync(slot: HTMLSlotElement): boolean {\n const nodes = slot.assignedNodes({ flatten: true });\n for (const node of nodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n if ((node.textContent ?? '').trim().length > 0) return true;\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n // Round-10 F3 (P3): use AccName-aware flatten so descendants carrying\n // `aria-hidden=\"true\"` or the `hidden` attribute do NOT count toward\n // \"has meaningful content\". Raw `textContent` would treat\n // `<span hidden>foo</span>` as non-empty, leaving an empty help\n // description attached to the inner input. The slot-text observer\n // (round-9 F2) watches characterData/childList/attributes so toggling\n // `hidden` on a descendant correctly flips `_hasHelpSlot` to false.\n if (flattenAccName(node as Element).length > 0) return true;\n }\n }\n return false;\n }\n\n /**\n * Round-6 F1 (P2): re-evaluate the error slot's \"has meaningful content\"\n * state from its current effective text. Mirrors the slotchange-handler\n * logic but is invocable from the in-place mutation observer so that\n * clearing `textContent` on the same slotted node flips `_hasErrorSlot`\n * back to `false` (without this, the combobox stays in its error state\n * indefinitely: `aria-invalid` stays `true`, the error id stays in\n * `aria-describedby`, and help text stays hidden).\n * @internal\n */\n private _readErrorSlotStateSync(slot: HTMLSlotElement): boolean {\n const nodes = slot.assignedNodes({ flatten: true });\n for (const node of nodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n if ((node.textContent ?? '').trim().length > 0) return true;\n } else if (node.nodeType === Node.ELEMENT_NODE) {\n // Round-10 F3 (P3): same AccName-aware flatten as\n // `_readHelpSlotStateSync` — `<span hidden>foo</span>` or\n // `<span aria-hidden=\"true\">foo</span>` must not keep the combobox\n // in its error state once they are the sole descendants.\n if (flattenAccName(node as Element).length > 0) return true;\n }\n }\n return false;\n }\n\n // ─── Inner-input ARIA sync (W3C APG editable combobox) ───\n\n /**\n * Resolves consumer-supplied label/description IDREFs on the host and\n * writes the canonical combobox ARIA onto the **inner `<input>`** per W3C\n * APG editable combobox pattern. The inner input owns `role=\"combobox\"`\n * (replacing its implicit textbox role) and all combobox state ARIA so\n * AT sees a single announced + focused surface.\n *\n * Cross-shadow naming uses a belt-and-suspenders strategy:\n *\n * 1. **Modern path** (`_supportsIdrefRefs === true`): consumer-resolved\n * label/description elements are written onto\n * `internals.ariaLabelledByElements` / `internals.ariaDescribedByElements`\n * on the host. AT that walks up from the focused inner input for naming\n * finds them through ElementInternals. Host-level `aria-labelledby` /\n * `aria-describedby` attributes are LEFT IN PLACE so AT walking up the\n * DOM also sees them. The text content of the resolved elements is also\n * flattened onto the inner input as `aria-label` / `aria-description`\n * so AT that does not walk up still announces the right name.\n *\n * 2. **Legacy fallback** (`_supportsIdrefRefs === false`): host attrs are\n * stripped (AccName precedence cleanup) and the resolved-element text\n * is flattened onto the inner input as `aria-label` /\n * `aria-description`. Live updates to the consumer-referenced elements\n * do not propagate, but the initial accessible name resolves on every\n * AT — closing the cross-shadow naming gap that broke this on engines\n * without IDL element references.\n *\n * Writing `aria-labelledby=\"<light-DOM id>\"` directly on the shadow-DOM\n * inner input is INTENTIONALLY avoided: light-DOM ids do not resolve from\n * inside a shadow root, so that pattern leaves the control AT-anonymous.\n * Internal label ids (in the same shadow root) ARE written via\n * `aria-labelledby`.\n * @internal\n */\n /**\n * Round-7 F1 (P2): (re)install a `MutationObserver` against the deduped\n * union of consumer-resolved label/description elements. Watches\n * `characterData`, `childList`, and `subtree` so any in-place text\n * mutation on the referenced light-DOM nodes triggers a fresh sync —\n * keeping the inner input's flattened `aria-label` and the synthesized\n * description span aligned with the live consumer text. Blanket\n * disconnect-and-reinstall on every sync; if the consumer retracts both\n * IDREF chains the union is empty and the observer is disconnected.\n * @internal\n */\n private _installExternalRefsObserver(elements: Element[]): void {\n if (this._externalRefsObserver) {\n this._externalRefsObserver.disconnect();\n this._externalRefsObserver = null;\n }\n if (elements.length === 0) return;\n // Dedupe references in case the same element is referenced from both\n // `aria-labelledby` and `aria-describedby` — observing it once is enough.\n const unique = new Set<Element>(elements);\n const observer = new MutationObserver(() => {\n // External text changed — re-sync, which re-flattens the resolved\n // elements onto the inner input and the synthesized description span.\n this._syncHostAriaSemantics();\n });\n for (const el of unique) {\n // Round-9 F2 (P2): also observe `aria-hidden` / `hidden` toggles on the\n // referenced element AND its descendants. `flattenAccName` skips\n // aria-hidden subtrees per AccName 1.2 §4.3.10, so a consumer flipping\n // visibility in place changes the flattened text — but without attribute\n // observation the inner input keeps its stale mirrored `aria-label` /\n // synthesized description. `subtree: true` combined with `attributes: true`\n // covers descendant attribute mutations too.\n observer.observe(el, {\n characterData: true,\n subtree: true,\n childList: true,\n attributes: true,\n attributeFilter: ['aria-hidden', 'hidden'],\n });\n }\n this._externalRefsObserver = observer;\n }\n\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n\n const input = this._input;\n if (!input) {\n // Inner input not yet rendered; defer. The post-render `updated()` call\n // will re-invoke this sync once the input exists.\n // Round-12 F3: still derive `_invalid` so `aria-invalid` first-paint\n // is correct once the input renders.\n const isInvalidEarly = !internals.validity.valid || !!(this.error || this._hasErrorSlot);\n this._invalid = isInvalidEarly;\n return;\n }\n\n // The host carries no `aria-label` we wrote — any live value is purely\n // a consumer override. Forwarded onto the inner input below.\n const liveAriaLabel = this.getAttribute('aria-label');\n const hostAriaLabel = liveAriaLabel !== null ? liveAriaLabel.trim() || '' : '';\n\n // Resolve the candidate label/desc element references once.\n const internalLabel = this.shadowRoot?.getElementById(this._labelId) ?? null;\n // Round-4 F1 (P2): aggregate ALL assigned label-slot elements so composed\n // labels (icon + text, multi-span) name the inner input fully.\n const slottedLabelEls = this._slottedLabelEls;\n const helpEl = this.shadowRoot?.getElementById(this._helpTextId) ?? null;\n const errorEl = this.shadowRoot?.getElementById(this._errorId) ?? null;\n\n // Refresh the consumer baseline. The host attribute is the live source\n // of truth on BOTH paths (round-12 F4: legacy no longer strips, so the\n // observer-cached fallback is no longer required). A `null` live value\n // authentically represents consumer retraction.\n const liveLabelledBy = this.getAttribute('aria-labelledby');\n this._consumerLabelledBy = liveLabelledBy;\n const liveDescribedBy = this.getAttribute('aria-describedby');\n this._consumerDescribedBy = liveDescribedBy;\n const externalLabelTokens = this._consumerLabelledBy;\n const externalDescTokens = this._consumerDescribedBy;\n\n const consumerLabelEls = resolveIdrefTokens(this, externalLabelTokens);\n const hasEffectiveLabelledBy = consumerLabelEls.length > 0;\n\n const consumerDescEls = resolveIdrefTokens(this, externalDescTokens);\n\n // Round-7 F1 (P2): observe in-place text mutations on the resolved\n // external IDREF targets. Without this, a consumer that mutates\n // `<label id=\"ext\">Patient</label>` → \"Member\" in place leaves the\n // inner input's flattened `aria-label` stuck on \"Patient\". Blanket\n // disconnect-and-reinstall keeps the bookkeeping trivial and matches\n // the slotted-label observer pattern.\n this._installExternalRefsObserver([...consumerLabelEls, ...consumerDescEls]);\n\n const hasError = !!(this.error || this._hasErrorSlot);\n\n // Round-12 F3: `aria-invalid` reflects EVERY signal the consumer can use\n // to express invalidity. setValidity() drives the required-empty case;\n // an explicit `error` property/slot is a server-/async-validation signal\n // that AT must announce as invalid, not just \"described by an alert\".\n const isInvalid = !internals.validity.valid || hasError;\n this._invalid = isInvalid;\n\n // Round-12 F2: `accessibleLabel` is documented as the screen-reader name\n // when it should differ from the visible label. When the consumer\n // explicitly sets it (non-empty), it is the canonical AT name and must\n // override visible label / aria-labelledby — both for the modern path's\n // ElementInternals references and for the inner input's aria-label.\n const explicitAccessibleLabel =\n typeof this.accessibleLabel === 'string' && this.accessibleLabel.trim().length > 0\n ? this.accessibleLabel\n : null;\n\n // Round-9 F1 (P2): top-level `aria-hidden=\"true\"` / `hidden` elements MUST\n // NOT be forwarded to `internals.ariaLabelledByElements` /\n // `ariaDescribedByElements`. On engines with IDL element refs, AT walks\n // those references and would recursively read e.g. an\n // `<svg aria-hidden=\"true\"><title>icon</title></svg>` slotted alongside a\n // visible `<span slot=\"label\">Patient</span>` — yielding \"icon Patient\".\n // The fallback text-flatten path already strips these via `flattenAccName`,\n // so the filter aligns the modern path with AccName 1.2 §4.3.10.\n const isVisibleForAccName = (el: Element): boolean =>\n el.getAttribute('aria-hidden') !== 'true' && !el.hasAttribute('hidden');\n\n // Build the augmented element lists used by the modern (IDL-refs) path.\n // When `accessibleLabel` is the chosen name we omit element references\n // entirely so AT does not double-announce against the explicit override.\n const labelElsForInternals: Element[] = [];\n if (!explicitAccessibleLabel) {\n labelElsForInternals.push(...consumerLabelEls.filter(isVisibleForAccName));\n if (!hasEffectiveLabelledBy && !hostAriaLabel) {\n if (this._labelSource === 'slot' && slottedLabelEls.length > 0) {\n // Round-4 F1 (P2): expose every assigned element so AT can compose\n // the full visible label across icon + text fragments.\n // Round-9 F1 (P2): filter top-level aria-hidden / hidden so the\n // modern path matches the fallback path's AccName behavior. The\n // unfiltered `_slottedLabelEls` is still used downstream by the\n // text-flatten fallback (its TreeWalker handles nested visibility).\n labelElsForInternals.push(...slottedLabelEls.filter(isVisibleForAccName));\n } else if (this._labelSource === 'string' && internalLabel) {\n labelElsForInternals.push(internalLabel);\n }\n }\n }\n\n // Round-9 F1 (P2): same hidden-filter for description element refs. A\n // consumer-referenced `aria-describedby` target that flips to\n // `aria-hidden=\"true\"` must not name through the modern path.\n const descElsForInternals: Element[] = [...consumerDescEls.filter(isVisibleForAccName)];\n if (helpEl && !hasError && (this.helpText || this._hasHelpSlot)) {\n descElsForInternals.push(helpEl);\n }\n if (errorEl && hasError) {\n descElsForInternals.push(errorEl);\n }\n\n // ─── Modern-path: ElementInternals IDL element references ───\n // Set when supported so AT walking up from the focused inner input picks\n // up the host's referenced labels/descriptions across the shadow boundary.\n type InternalsWithIdrefRefs = ElementInternals & {\n ariaLabelledByElements: Element[] | null;\n ariaDescribedByElements: Element[] | null;\n };\n if (this._supportsIdrefRefs) {\n const refsInternals = internals as InternalsWithIdrefRefs;\n refsInternals.ariaLabelledByElements =\n labelElsForInternals.length > 0 ? labelElsForInternals : null;\n refsInternals.ariaDescribedByElements =\n descElsForInternals.length > 0 ? descElsForInternals : null;\n // Modern path: forward `accessibleLabel` to `internals.ariaLabel` so AT\n // walking the host (or reading internals) sees the explicit override.\n // Round-8 F1 (P2): when `accessibleLabel` is absent, CLEAR the override\n // with `null` (not `''`). Per W3C AccName, an empty-string `aria-label`\n // STILL has higher precedence than `aria-labelledby`, so writing `''`\n // would erase the name resolved from `ariaLabelledByElements`, the\n // `label` property, the slotted label, or host `aria-labelledby`. `null`\n // removes the override entirely so element references / fallbacks win.\n if (explicitAccessibleLabel) {\n internals.ariaLabel = explicitAccessibleLabel;\n } else {\n internals.ariaLabel = null;\n }\n }\n\n // Round-12 F4: the host's `aria-labelledby` / `aria-describedby` are\n // intentionally LEFT IN PLACE on both paths. The inner input owns the\n // canonical AT surface (role=\"combobox\") and consumes the consumer's\n // intent via text-flatten + (modern path) ElementInternals references.\n // The host is roleless on both paths, so leaving these attributes in\n // place has no AT effect — and importantly, lets consumers retract them\n // dynamically: the live attribute IS the cache, so `removeAttribute` is\n // observable in the next sync (it returns `null` from `getAttribute`).\n\n // ─── Compute the inner input's accessible name (text-flatten path) ───\n // We never write `aria-labelledby=\"<light-DOM id>\"` to the inner input —\n // light-DOM ids do not resolve from inside a shadow root, so that pattern\n // would leave the control AT-anonymous. Internal label ids (same shadow\n // root) ARE allowed via `aria-labelledby`. For consumer-referenced\n // light-DOM elements we flatten their textContent into `aria-label`.\n // Round-8 F2 (P2): use the module-level `flattenAccName` walker which\n // REJECTS `aria-hidden=\"true\"` and `hidden` subtrees per AccName 1.2\n // §4.3.10. Without this, a consumer label like\n // `<label id=\"x\"><svg aria-hidden=\"true\"><title>icon</title></svg>Search</label>`\n // would flatten to \"icon Search\" and leak the decorative title into the\n // inner input's aria-label / synthesized description span.\n // Round-9 F2 (P2): also strip top-level aria-hidden / hidden roots before\n // flattening. `flattenAccName`'s TreeWalker checks DESCENDANTS, not the\n // root itself, so without this filter a consumer flipping aria-hidden on\n // a referenced label root would leave the mirrored aria-label / consumer\n // description span stale. Mirrors the F1 modern-path filter so both\n // surfaces agree per AccName 1.2 §4.3.10.\n const flattenText = (els: Element[]): string =>\n els\n .filter(isVisibleForAccName)\n .map((el) => flattenAccName(el))\n .filter((t) => t.length > 0)\n .join(' ');\n\n let inputAriaLabel: string | null = null;\n let inputAriaLabelledBy: string | null = null;\n // Round-13 F1 (P2) precedence — aligns with W3C AccName 1.2 §4.3.1, with\n // one helix-specific deviation called out below:\n // 1. `accessibleLabel` (HELIX-SPECIFIC public-API override; documented\n // contract — see Round-3 F2 from the round-3 push-gate. The property\n // is the explicit AT-only name and intentionally outranks both\n // `aria-labelledby` and `aria-label`. The matching modern-path write\n // above clears `internals.ariaLabel` to `null` when this is unset so\n // we never erase a labelledby resolution.)\n // 2. consumer `aria-labelledby` resolves → text-flatten (AccName winner\n // over `aria-label`; previously incorrectly demoted below it, which\n // meant a consumer setting both saw the inner input announce the\n // `aria-label` string instead of the referenced label's text)\n // 3. consumer `aria-label` on the host (consumer escape hatch; only\n // reached when labelledby is absent or unresolvable)\n // 4. slotted label → text content (NEVER cross-shadow id reference)\n // 5. `label` property → internal `<label>` id (same shadow root) or text\n // 6. else: unnamed\n // Round-13 F1 (P2): the labelledby branch is allowed to fall through to\n // the next strategy when `flattenText` returns empty (e.g. the resolved\n // elements are visible-but-empty or filtered by AccName visibility).\n // Without this, an aria-labelledby pointing at an empty target would\n // park `inputAriaLabel` at `null` AND skip the host aria-label fallback,\n // leaving the control AT-anonymous.\n let labelledByFlat = '';\n if (!explicitAccessibleLabel && hasEffectiveLabelledBy) {\n labelledByFlat = flattenText(consumerLabelEls);\n }\n if (explicitAccessibleLabel) {\n inputAriaLabel = explicitAccessibleLabel;\n } else if (labelledByFlat) {\n // Consumer aria-labelledby resolved to one or more elements. Flatten\n // their text into aria-label so the inner input announces correctly\n // regardless of cross-shadow id resolution. The modern-path\n // ElementInternals write above gives AT the live IDREF chain in\n // addition to this flattened text. Round-13 F1 (P2): this branch sits\n // ABOVE the host `aria-label` branch so AccName 1.2 §4.3.1 precedence\n // is preserved when the consumer sets both attributes.\n inputAriaLabel = labelledByFlat;\n } else if (hostAriaLabel) {\n // Round-13 F1 (P2): host aria-label is the next fallback after\n // accessibleLabel + a *resolved* aria-labelledby. Reaching this branch\n // means either no aria-labelledby was set, or its IDREFs did not\n // resolve to any element (e.g. typo, target removed, empty content) —\n // in which case AccName 1.2 falls through to aria-label.\n inputAriaLabel = hostAriaLabel;\n } else if (this._labelSource === 'slot') {\n // Round-12 F1: the slotted label may carry a light-DOM id. We MUST NOT\n // write that id as `aria-labelledby` on the inner input — light-DOM\n // ids do not resolve from inside a shadow root, so on engines without\n // ElementInternals IDL refs the control would be AT-anonymous. Always\n // text-flatten on the legacy/fallback path; the modern path already\n // carries the live element reference via `ariaLabelledByElements`.\n if (this._labelSlotText) {\n inputAriaLabel = this._labelSlotText;\n } else if (slottedLabelEls.length > 0) {\n // Round-4 F1 (P2): flatten textContent across every assigned element.\n // Round-8 F2 (P2): use the deep walker so nested `aria-hidden=\"true\"`\n // (e.g. an inline `<svg aria-hidden><title>icon</title></svg>` inside a\n // slotted `<span>`) does not leak into the inner input's aria-label.\n // The top-level slotted-element aria-hidden filter is already applied\n // by `_readLabelSlotState` when populating `_labelSlotText`; this fall-\n // through aggregator handles the case where text wasn't pre-flattened.\n const flat = flattenText(slottedLabelEls);\n if (flat) inputAriaLabel = flat;\n }\n } else if (this._labelSource === 'string') {\n if (internalLabel?.id) {\n inputAriaLabelledBy = internalLabel.id;\n } else if (this.label) {\n inputAriaLabel = this.label;\n }\n }\n\n // Apply the resolved name to the inner input via attribute writes.\n if (inputAriaLabelledBy) {\n if (input.getAttribute('aria-labelledby') !== inputAriaLabelledBy) {\n input.setAttribute('aria-labelledby', inputAriaLabelledBy);\n }\n if (input.hasAttribute('aria-label')) input.removeAttribute('aria-label');\n } else if (inputAriaLabel) {\n if (input.getAttribute('aria-label') !== inputAriaLabel) {\n input.setAttribute('aria-label', inputAriaLabel);\n }\n if (input.hasAttribute('aria-labelledby')) input.removeAttribute('aria-labelledby');\n } else {\n if (input.hasAttribute('aria-label')) input.removeAttribute('aria-label');\n if (input.hasAttribute('aria-labelledby')) input.removeAttribute('aria-labelledby');\n }\n\n // ─── Write the inner input's aria-describedby chain ───\n // Round-5 F1 (P1): unify ALL descriptions through a single\n // `aria-describedby` channel on the inner input. The W3C AccName algorithm\n // ignores `aria-description` whenever `aria-describedby` is also present,\n // so the previous split (internal ids on `aria-describedby`, consumer text\n // on `aria-description`) silently dropped consumer descriptions whenever\n // help/error text was present.\n //\n // For consumer-referenced light-DOM elements we cannot point inner-input\n // `aria-describedby` directly at the consumer ids (light-DOM ids do not\n // resolve from inside a shadow root), so the consumer text is mirrored\n // into a synthesized in-shadow span and that same-root id is added to\n // the chain. The synthesized span is rendered unconditionally with the\n // visually-hidden style and updated here on every sync (idempotent).\n const consumerDescSpan = this.shadowRoot?.getElementById(this._consumerDescId) ?? null;\n const consumerDescText = flattenText(consumerDescEls);\n if (consumerDescSpan && consumerDescSpan.textContent !== consumerDescText) {\n consumerDescSpan.textContent = consumerDescText;\n }\n\n const describedByIds: string[] = [];\n if (consumerDescText && consumerDescSpan) {\n describedByIds.push(this._consumerDescId);\n }\n if (helpEl && !hasError && (this.helpText || this._hasHelpSlot)) {\n describedByIds.push(this._helpTextId);\n }\n if (errorEl && hasError) {\n describedByIds.push(this._errorId);\n }\n if (describedByIds.length > 0) {\n const value = describedByIds.join(' ');\n if (input.getAttribute('aria-describedby') !== value) {\n input.setAttribute('aria-describedby', value);\n }\n } else if (input.hasAttribute('aria-describedby')) {\n input.removeAttribute('aria-describedby');\n }\n\n // Round-5 F1 (P1): never write `aria-description` on the inner input.\n // It is silently dropped when `aria-describedby` is also present (a\n // common case once help/error text exists), and we now route consumer\n // descriptions through the synthesized in-shadow span instead. Strip\n // any legacy value defensively in case an earlier sync wrote one.\n if (input.hasAttribute('aria-description')) {\n input.removeAttribute('aria-description');\n }\n }\n\n /**\n * (Re-)installs the mutation observer over the current set of assigned\n * help-text-slot nodes.\n * @internal\n */\n private _installHelpSlotTextObserver(slot: HTMLSlotElement | null): void {\n this._helpSlotTextObserver?.disconnect();\n if (!slot) {\n this._helpSlotTextObserver = null;\n return;\n }\n // Round-6 F1 (P2): capture the slot reference so the MO callback can\n // re-evaluate `_hasHelpSlot` from the slot's current effective text. An\n // in-place `textContent = ''` on the same slotted node leaves\n // `assignedNodes().length > 0` true but yields empty effective text, so\n // we must re-read on every mutation, not just on slotchange.\n const observer = new MutationObserver(() => {\n this._hasHelpSlot = this._readHelpSlotStateSync(slot);\n this._syncHostAriaSemantics();\n });\n slot.assignedNodes().forEach((node) => {\n if (node.nodeType !== Node.ELEMENT_NODE) {\n observer.observe(node, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n return;\n }\n // Round-9 F2 (P2): observe aria-hidden / hidden toggles so a consumer\n // flipping visibility on the slotted help-text node (or a descendant)\n // re-evaluates effective text and re-syncs the inner input.\n observer.observe(node, {\n characterData: true,\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['aria-hidden', 'hidden'],\n });\n });\n this._helpSlotTextObserver = observer;\n }\n\n /**\n * (Re-)installs the mutation observer over the current set of assigned\n * error-slot nodes.\n * @internal\n */\n private _installErrorSlotTextObserver(slot: HTMLSlotElement | null): void {\n this._errorSlotTextObserver?.disconnect();\n if (!slot) {\n this._errorSlotTextObserver = null;\n return;\n }\n // Round-6 F1 (P2): capture the slot reference so the MO callback can\n // re-evaluate `_hasErrorSlot` from the slot's current effective text. If\n // a consumer keeps the same `<span slot=\"error\">` node and clears its\n // `textContent`, only the MO fires (no slotchange). Without re-reading the\n // slot state, the combobox stays stuck in its error state: `aria-invalid`\n // remains true, the error id stays in `aria-describedby`, and the help\n // text stays hidden.\n const observer = new MutationObserver(() => {\n this._hasErrorSlot = this._readErrorSlotStateSync(slot);\n this._syncHostAriaSemantics();\n });\n slot.assignedNodes().forEach((node) => {\n if (node.nodeType !== Node.ELEMENT_NODE) {\n observer.observe(node, {\n characterData: true,\n childList: true,\n subtree: true,\n });\n return;\n }\n // Round-9 F2 (P2): observe aria-hidden / hidden toggles so a consumer\n // flipping visibility on the slotted error node (or a descendant)\n // re-evaluates effective text and re-syncs the inner input.\n observer.observe(node, {\n characterData: true,\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['aria-hidden', 'hidden'],\n });\n });\n this._errorSlotTextObserver = observer;\n }\n\n // ─── Form Integration ───\n\n /** @internal */\n private _updateFormValue(): void {\n this._internals.setFormValue(this.value || null);\n }\n\n /** @internal */\n override _updateValidity(): void {\n if (this.required && !this.value) {\n // W3C APG editable combobox: the inner `<input>` is the canonical\n // announced + focused combobox surface, so anchor `setValidity()` to\n // the inner input. Native validation popups attach to the focusable\n // form-control surface.\n this._internals.setValidity(\n { valueMissing: true },\n this.error || this.labelRequired,\n this._input,\n );\n } else {\n this._internals.setValidity({});\n }\n // Re-sync ARIA after every setValidity() so `aria-invalid` on the inner\n // input reflects the freshly computed validity state. The render template\n // binds `aria-invalid` from `_invalid`; mutating `_invalid` (a `@state`)\n // inside sync schedules a Lit update if the value actually changed.\n this._syncHostAriaSemantics();\n }\n\n /** @internal */\n protected override _onFormReset(): void {\n this.value = '';\n this._filterText = '';\n this._internals.setFormValue(null);\n this._resetInteractionState();\n }\n\n /** @internal */\n // P1-6: Correct signature per WHATWG spec — includes mode param and all state types\n protected override _onFormStateRestore(\n state: File | string | FormData | null,\n _mode: 'restore' | 'autocomplete',\n ): void {\n if (typeof state === 'string') {\n this.value = state;\n }\n }\n\n /** @internal */\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Option Syncing from Slot ───\n\n /** @internal */\n private _handleSlotChange(): void {\n this._readOptions();\n }\n\n /** @internal */\n private _parseOption(el: HTMLOptionElement): ComboboxOption {\n return { value: el.value, label: el.textContent?.trim() ?? el.value, disabled: el.disabled };\n }\n\n /** @internal */\n private _readOptions(): void {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot[name=\"option\"]');\n if (!slot) return;\n\n const parsed: ComboboxOption[] = [];\n\n for (const el of slot.assignedElements({ flatten: true })) {\n if (el instanceof HTMLOptionElement) {\n parsed.push(this._parseOption(el));\n } else if (el instanceof HTMLOptGroupElement) {\n for (const child of Array.from(el.children)) {\n if (child instanceof HTMLOptionElement) parsed.push(this._parseOption(child));\n }\n }\n }\n\n this._options = parsed;\n }\n\n // ─── Slot Change Handlers ───\n\n /**\n * Tracks the slotted label so projected `<span slot=\"label\">` content joins\n * the accessible-name chain.\n * @internal\n */\n private _handleLabelSlotChange(e: Event): void {\n if (!(e.target instanceof HTMLSlotElement)) return;\n const state = this._readLabelSlotState(e.target);\n this._hasLabelSlot = state.hasUsefulName;\n this._slottedLabelEls = state.elements;\n this._labelSlotText = state.text;\n // Round-4 F2 (P2): re-install the in-place text-mutation observer on the\n // current set of slotted elements. `slotchange` covers ADD/REMOVE/REPLACE\n // of assigned nodes; this MO covers `node.textContent = '…'` updates on\n // an unchanged node (e.g. consumer i18n re-render keeping the same span).\n this._installLabelSlotTextObserver(state.elements);\n this._refreshLabelSource();\n this._syncHostAriaSemantics();\n }\n\n /**\n * (Re-)installs the mutation observer over the current set of slotted label\n * elements. Round-4 F2 (P2): mirrors the round-23 P2 pattern from\n * `_helpSlotTextObserver` / `_errorSlotTextObserver`. On any descendant text\n * change we re-read the slot state (to refresh `_labelSlotText` and the\n * element list) and re-sync host ARIA so the inner input's `aria-label`\n * tracks the live label text.\n * @internal\n */\n private _installLabelSlotTextObserver(elements: Element[]): void {\n this._labelSlotTextObserver?.disconnect();\n if (elements.length === 0) {\n this._labelSlotTextObserver = null;\n return;\n }\n const observer = new MutationObserver(() => {\n // Re-aggregate text from the same elements (the MO does not give us a\n // slot reference). The element list itself only changes on `slotchange`,\n // which re-installs this observer with the new list.\n //\n // Round-6 F2 (P2): mirror `_readLabelSlotState` — skip aria-hidden\n // elements per AccName 1.2 §4.3.10, and gate `_hasLabelSlot` on the\n // flattened TEXT (not element presence). An in-place clear of the\n // visible label's textContent must flip `_hasLabelSlot` back to false\n // so `_labelSource` falls through to other naming sources or the host\n // becomes unnamed (consumer responsibility).\n const fragments: string[] = [];\n for (const el of elements) {\n if (el.getAttribute('aria-hidden') === 'true') continue;\n // Round-8 F2 (P2): use the deep walker so nested aria-hidden / hidden\n // subtrees inside slotted parents are skipped per AccName 1.2 §4.3.10.\n const t = flattenAccName(el);\n if (t) fragments.push(t);\n }\n const trimmed = fragments.join(' ').replace(/\\s+/g, ' ').trim();\n this._labelSlotText = trimmed;\n this._hasLabelSlot = trimmed.length > 0;\n this._refreshLabelSource();\n this._syncHostAriaSemantics();\n });\n for (const el of elements) {\n // Round-9 F2 (P2): observe `aria-hidden` / `hidden` toggles on the\n // slotted label root AND its descendants. The MO callback above re-runs\n // `flattenAccName` and re-derives `_hasLabelSlot` from effective text —\n // so an in-place visibility flip on a child must trigger a fresh sync.\n observer.observe(el, {\n characterData: true,\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['aria-hidden', 'hidden'],\n });\n }\n this._labelSlotTextObserver = observer;\n }\n\n /**\n * Recomputes the discriminated label source.\n * @internal\n */\n private _refreshLabelSource(): void {\n if (this.label) {\n this._labelSource = 'string';\n } else if (this._hasLabelSlot) {\n this._labelSource = 'slot';\n } else {\n this._labelSource = 'none';\n }\n }\n\n /** @internal */\n private _handleErrorSlotChange(e: Event): void {\n if (!(e.target instanceof HTMLSlotElement)) return;\n // Round-6 F1 (P2): single-source-of-truth state read.\n this._hasErrorSlot = this._readErrorSlotStateSync(e.target);\n this._installErrorSlotTextObserver(e.target);\n this._syncHostAriaSemantics();\n }\n\n /** @internal */\n private _handleHelpSlotChange(e: Event): void {\n if (!(e.target instanceof HTMLSlotElement)) return;\n // Round-6 F1 (P2): single-source-of-truth state read.\n this._hasHelpSlot = this._readHelpSlotStateSync(e.target);\n this._installHelpSlotTextObserver(e.target);\n this._syncHostAriaSemantics();\n }\n\n // ─── Dropdown Control ───\n\n /** @internal */\n private _openDropdown(): void {\n if (this.disabled || this._open) return;\n this._open = true;\n this._focusedOptionIndex = -1;\n if (typeof document !== 'undefined') {\n document.addEventListener('click', this._handleOutsideClick);\n }\n this.dispatchEvent(new CustomEvent<void>('hx-show', { bubbles: true, composed: true }));\n }\n\n /** @internal */\n private _closeDropdown(): void {\n if (!this._open) return;\n this._open = false;\n this._focusedOptionIndex = -1;\n this._handleInteractionBlur();\n if (typeof document !== 'undefined') {\n document.removeEventListener('click', this._handleOutsideClick);\n }\n this.dispatchEvent(new CustomEvent<void>('hx-hide', { bubbles: true, composed: true }));\n }\n\n // ─── Input Handling ───\n\n /** @internal */\n private _handleInput(e: Event): void {\n const input = e.target as HTMLInputElement;\n this._filterText = input.value;\n\n if (!this._open) {\n this._openDropdown();\n }\n\n this._focusedOptionIndex = -1;\n\n if (this.filterDebounce > 0) {\n if (this._debounceTimer !== null) {\n clearTimeout(this._debounceTimer);\n }\n this._debounceTimer = setTimeout(() => {\n this._emitInput();\n this._announceFilterResults();\n }, this.filterDebounce);\n } else {\n this._emitInput();\n this._announceFilterResults();\n }\n }\n\n /** @internal */\n private _announceFilterResults(): void {\n const count = this._filteredOptions.length;\n this._filterAnnouncement =\n count === 0\n ? 'No matching options'\n : `${count} ${count === 1 ? 'option' : 'options'} available`;\n }\n\n /** @internal */\n private _emitInput(): void {\n this.dispatchEvent(\n new CustomEvent<{ value: string }>('hx-input', {\n bubbles: true,\n composed: true,\n detail: { value: this._filterText },\n }),\n );\n }\n\n /** @internal */\n private _handleFocus(): void {\n this._openDropdown();\n }\n\n // ─── Keyboard Navigation ───\n\n /** @internal */\n private _handleKeydown(e: KeyboardEvent): void {\n if (this.disabled) return;\n\n const filtered = this._filteredOptions;\n const enabledIndices = filtered\n .map((o, i) => ({ o, i }))\n .filter(({ o }) => !o.disabled)\n .map(({ i }) => i);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n if (!this._open) {\n this._openDropdown();\n this._focusedOptionIndex = enabledIndices.length > 0 ? (enabledIndices[0] ?? 0) : -1;\n break;\n }\n const nextDown = enabledIndices.find((i) => i > this._focusedOptionIndex);\n this._focusedOptionIndex =\n nextDown !== undefined ? nextDown : (enabledIndices[0] ?? this._focusedOptionIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n if (!this._open) {\n this._openDropdown();\n const lastEnabled = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex = lastEnabled !== undefined ? lastEnabled : -1;\n break;\n }\n const prevUp = [...enabledIndices].reverse().find((i) => i < this._focusedOptionIndex);\n const lastEnabledUp = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex =\n prevUp !== undefined ? prevUp : (lastEnabledUp ?? this._focusedOptionIndex);\n break;\n }\n case 'Enter': {\n e.preventDefault();\n if (!this._open) {\n this._openDropdown();\n break;\n }\n if (this._focusedOptionIndex >= 0 && this._focusedOptionIndex < filtered.length) {\n const opt = filtered[this._focusedOptionIndex];\n if (opt) this._selectOption(opt);\n }\n break;\n }\n case 'Escape': {\n e.preventDefault();\n this._closeDropdown();\n this._filterText = '';\n if (this._input) this._input.value = '';\n // Note: do NOT call this.focus() here — the inner <input> already has\n // focus when Escape is pressed and refocusing would re-trigger\n // _handleFocus → _openDropdown, immediately re-opening the listbox.\n // The input remains focused so the user can continue typing.\n break;\n }\n case 'Tab': {\n this._closeDropdown();\n break;\n }\n // P1-1: Home/End keyboard navigation for option list\n case 'Home': {\n e.preventDefault();\n if (!this._open) this._openDropdown();\n this._focusedOptionIndex = enabledIndices.length > 0 ? (enabledIndices[0] ?? -1) : -1;\n break;\n }\n case 'End': {\n e.preventDefault();\n if (!this._open) this._openDropdown();\n this._focusedOptionIndex =\n enabledIndices.length > 0 ? (enabledIndices[enabledIndices.length - 1] ?? -1) : -1;\n break;\n }\n default:\n break;\n }\n }\n\n // ─── Selection ───\n\n // P0-1: Handle both single and multiple selection modes\n /** @internal */\n private _selectOption(option: ComboboxOption): void {\n if (option.disabled) return;\n if (this.multiple) {\n const current = this._selectedValuesSet;\n const next = new Set(current);\n if (next.has(option.value)) {\n next.delete(option.value);\n } else {\n next.add(option.value);\n }\n this.value = [...next].join(',');\n // Keep dropdown open for multiple selection so user can pick more\n } else {\n this.value = option.value;\n this._closeDropdown();\n }\n this._handleInteractionInput();\n this._filterText = '';\n if (this._input) this._input.value = '';\n this._dispatchChange();\n }\n\n // P0-1: Remove a single value from multi-selection\n /** @internal */\n private _removeValue(val: string): void {\n const next = this._selectedValuesSet;\n next.delete(val);\n this.value = [...next].join(',');\n this._dispatchChange();\n }\n\n // ─── Clear ───\n\n /** @internal */\n private _handleClear(e: Event): void {\n e.stopPropagation();\n this.value = '';\n this._filterText = '';\n if (this._input) {\n this._input.value = '';\n this._input.focus();\n }\n this._internals.setFormValue(null);\n this._updateValidity();\n this.dispatchEvent(new CustomEvent<void>('hx-clear', { bubbles: true, composed: true }));\n }\n\n // ─── Event Dispatchers ───\n\n /** @internal */\n private _dispatchChange(): void {\n this.dispatchEvent(\n new CustomEvent<{ value: string }>('hx-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n // ─── Outside Click Handler ───\n\n /** @internal */\n private _handleOutsideClick = (e: MouseEvent): void => {\n if (this._open && !e.composedPath().includes(this)) {\n this._closeDropdown();\n }\n };\n\n // ─── Public Methods ───\n\n /**\n * Routes programmatic focus to the inner text input. Per W3C APG editable\n * combobox pattern, the inner `<input>` carries `role=\"combobox\"` (replacing\n * its implicit textbox role) so it IS the canonical announced + focused\n * surface. Shadow DOM focus causes `document.activeElement` to report the\n * host externally, but the input retains focus inside the shadow root and\n * AT announces its role/state.\n */\n override focus(options?: FocusOptions): void {\n this._input?.focus(options);\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _optionId(index: number): string {\n return `${this._id}-option-${index}`;\n }\n\n /** @internal */\n private get _displayValue(): string {\n // P0-1: In multiple mode, chips render selected values — input shows only filter text\n if (this.multiple) return '';\n if (!this.value) return '';\n const opt = this._options.find((o) => o.value === this.value);\n return opt ? opt.label : this.value;\n }\n\n /** @internal */\n private _renderOptions() {\n const filtered = this._filteredOptions;\n\n if (filtered.length === 0) {\n return html`\n <slot name=\"empty-label\">\n <div class=\"field__no-options\">${this.labelNoOptions}</div>\n </slot>\n `;\n }\n\n return repeat(\n filtered,\n (opt) => opt.value,\n (opt, index) => {\n // P0-1: Use Set membership for multiple mode, direct equality for single mode\n const isSelected = this.multiple\n ? this._selectedValuesSet.has(opt.value)\n : opt.value === this.value;\n const isFocused = index === this._focusedOptionIndex;\n\n return html`\n <div\n id=${this._optionId(index)}\n part=\"option\"\n role=\"option\"\n class=${classMap({\n field__option: true,\n 'field__option--selected': isSelected,\n 'field__option--focused': isFocused,\n 'field__option--disabled': opt.disabled,\n })}\n aria-selected=${this.multiple\n ? isSelected\n ? 'true'\n : 'false'\n : isSelected\n ? 'true'\n : nothing}\n aria-disabled=${opt.disabled ? 'true' : nothing}\n @click=${() => this._selectOption(opt)}\n >\n <span class=\"field__option-label\">${opt.label}</span>\n </div>\n `;\n },\n );\n }\n\n // ─── Main Render ───\n\n override render() {\n const hasError = !!this.error || this._hasErrorSlot;\n const hasHelp = !!this.helpText || this._hasHelpSlot;\n const showClear = this.clearable && !!this.value && !this.disabled;\n\n const fieldClasses = {\n field: true,\n 'field--error': hasError,\n 'field--disabled': this.disabled,\n 'field--required': this.required,\n 'field--open': this._open,\n };\n\n const inputClasses = {\n field__input: true,\n [`field__input--${this.size}`]: true,\n };\n\n // W3C APG editable combobox (option I): role=\"combobox\" lives on the\n // inner <input>, replacing the implicit textbox role so AT sees a single\n // canonical announced + focused surface. All combobox state ARIA —\n // aria-expanded, aria-controls, aria-activedescendant, aria-autocomplete,\n // aria-haspopup, aria-required, aria-invalid, aria-disabled, aria-busy —\n // is bound on the input via Lit. aria-label / aria-labelledby /\n // aria-describedby are written imperatively by _syncHostAriaSemantics\n // after consumer-IDREF resolution.\n const activeOptionId =\n this._open && this._focusedOptionIndex >= 0 ? this._optionId(this._focusedOptionIndex) : '';\n\n return html`\n <div part=\"field\" class=${classMap(fieldClasses)}>\n <!-- Label -->\n <slot name=\"label\" @slotchange=${this._handleLabelSlotChange}>\n ${this.label\n ? html`<label id=${this._labelId} for=${this._id} part=\"label\" class=\"field__label\">\n ${this.label}\n ${this.required\n ? html`<span class=\"field__required-marker\" aria-hidden=\"true\">*</span>`\n : nothing}\n </label>`\n : nothing}\n </slot>\n\n <!-- Input Wrapper -->\n <div part=\"trigger\" class=\"field__input-wrapper\">\n <!-- Prefix Slot -->\n <slot name=\"prefix\" class=\"field__prefix\"></slot>\n\n <!-- P0-1: Selected value chips for multiple mode -->\n ${this.multiple && this._selectedValuesSet.size > 0\n ? [...this._selectedValuesSet].map((val) => {\n const opt = this._options.find((o) => o.value === val);\n const label = opt ? opt.label : val;\n return html`\n <span class=\"field__chip\">\n <span class=\"field__chip-label\">${label}</span>\n <button\n type=\"button\"\n class=\"field__chip-remove\"\n aria-label=${this.labelRemoveOption(label)}\n @click=${(e: Event) => {\n e.stopPropagation();\n this._removeValue(val);\n }}\n >\n <svg\n width=\"8\"\n height=\"8\"\n viewBox=\"0 0 8 8\"\n fill=\"none\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path\n d=\"M1 1L7 7M7 1L1 7\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n </span>\n `;\n })\n : nothing}\n\n <!--\n Text input — W3C APG editable combobox (option I).\n role=\"combobox\" REPLACES the implicit textbox role; all combobox\n state ARIA lives here so AT sees one canonical surface.\n aria-label / aria-labelledby / aria-describedby are written\n imperatively by _syncHostAriaSemantics after consumer IDREF\n resolution and are not bound here.\n -->\n <input\n part=\"input\"\n type=\"text\"\n id=${this._id}\n role=\"combobox\"\n class=${classMap(inputClasses)}\n .value=${this._filterText || (this._open ? '' : this._displayValue)}\n placeholder=${ifDefined(this.placeholder || undefined)}\n ?disabled=${this.disabled}\n ?required=${this.required}\n name=${ifDefined(this.name || undefined)}\n autocomplete=\"off\"\n aria-haspopup=\"listbox\"\n aria-autocomplete=\"list\"\n aria-controls=${this._listboxId}\n aria-expanded=${this._open ? 'true' : 'false'}\n aria-activedescendant=${ifDefined(activeOptionId || undefined)}\n aria-required=${this.required ? 'true' : 'false'}\n aria-invalid=${this._invalid ? 'true' : 'false'}\n aria-busy=${this.loading ? 'true' : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n @input=${this._handleInput}\n @focus=${this._handleFocus}\n @keydown=${this._handleKeydown}\n />\n\n <!-- Loading Indicator -->\n ${this.loading\n ? html`\n <div part=\"loading-indicator\" class=\"field__loading-indicator\" aria-hidden=\"true\">\n <div class=\"field__loading-spinner\"></div>\n </div>\n `\n : nothing}\n\n <!-- Clear Button -->\n ${showClear\n ? html`\n <button\n part=\"clear-button\"\n type=\"button\"\n class=\"field__clear-button\"\n aria-label=${`Clear ${this.label || this.accessibleLabel || 'selection'}`}\n tabindex=\"0\"\n @click=${this._handleClear}\n >\n <svg\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 12 12\"\n fill=\"none\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <path\n d=\"M1 1L11 11M11 1L1 11\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n />\n </svg>\n </button>\n `\n : nothing}\n\n <!-- Suffix Slot -->\n <slot name=\"suffix\" class=\"field__suffix\"></slot>\n </div>\n\n <!-- Listbox -->\n <div\n part=\"listbox\"\n role=\"listbox\"\n id=${this._listboxId}\n class=\"field__listbox\"\n aria-label=${ifDefined(this.label || this.accessibleLabel || undefined)}\n aria-multiselectable=${this.multiple ? 'true' : nothing}\n ?hidden=${!this._open}\n >\n <div class=\"field__options\">${this._renderOptions()}</div>\n </div>\n\n <!-- Hidden slot (options read from here) -->\n <slot name=\"option\" @slotchange=${this._handleSlotChange} style=\"display:none;\"></slot>\n\n <!--\n Persistent error live region. role=\"alert\" is set from first paint\n so the WAI-ARIA contract for live updates is honoured.\n -->\n <div\n part=\"error\"\n class=\"field__error\"\n id=${this._errorId}\n role=\"alert\"\n ?hidden=${!hasError}\n >\n <slot name=\"error\" @slotchange=${this._handleErrorSlotChange}\n >${this._announcedError}</slot\n >\n </div>\n\n <!--\n Persistent help-text container. Rendered whenever the property OR\n the slot has content; hidden when an error is present.\n -->\n <div\n part=\"help-text\"\n class=\"field__help-text\"\n id=${this._helpTextId}\n ?hidden=${!hasHelp || hasError}\n >\n <slot name=\"help-text\" @slotchange=${this._handleHelpSlotChange}>${this.helpText}</slot>\n </div>\n\n <!-- Filter results live region -->\n <div id=${this._liveRegionId} aria-live=\"polite\" aria-atomic=\"true\" class=\"field__sr-only\">\n ${this._filterAnnouncement}\n </div>\n\n <!--\n Round-5 F1 (P1): synthesized in-shadow mirror of the consumer-\n resolved description text. Its id is appended to the inner input's\n aria-describedby chain so AT picks the consumer description up\n through the standard described-by channel without needing\n aria-description (which W3C AccName drops whenever\n aria-describedby is also present). Same-root id resolves from\n inside the shadow tree; consumer light-DOM ids do not. The text\n content is updated by _syncHostAriaSemantics on every sync.\n -->\n <span id=${this._consumerDescId} class=\"field__sr-only\" aria-hidden=\"false\"></span>\n </div>\n `;\n }\n}\n\n/**\n * Per-component event map for type-safe addEventListener on hx-combobox.\n * The `hx-change` detail is `{ value: string }` only — no `checked` property.\n */\nexport interface HxComboboxEventMap {\n 'hx-input': CustomEvent<{ value: string }>;\n 'hx-change': CustomEvent<{ value: string }>;\n 'hx-clear': CustomEvent<void>;\n 'hx-show': CustomEvent<void>;\n 'hx-hide': CustomEvent<void>;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-combobox': HelixCombobox;\n }\n interface HTMLElementEventMap {\n 'hx-input': CustomEvent<{ value: string }>;\n // hx-change is also declared by hx-checkbox with a wider union; both\n // declarations must agree — the union covers all components that fire it.\n 'hx-change': CustomEvent<{ value: string } | { checked: boolean; value: string }>;\n 'hx-clear': CustomEvent<void>;\n 'hx-show': CustomEvent<void>;\n 'hx-hide': CustomEvent<void>;\n }\n}\n\nexport type { HelixCombobox as HxCombobox };\n"],"names":["helixComboboxStyles","css","_nextComboboxId","createIdCounter","flattenAccName","root","result","walker","node","el","textNode","HelixCombobox","FormMixin","HelixElement","label","lower","o","ctor","supportsIdrefElementReferences","records","consumerCleared","record","oldValue","newValue","installAriaIdrefMirror","_a","_b","_c","_d","_e","_f","changedProperties","labelSlot","state","helpSlot","errorSlot","slot","nodes","elements","fragments","elText","txt","trimmedText","unique","observer","internals","input","isInvalidEarly","liveAriaLabel","hostAriaLabel","internalLabel","slottedLabelEls","helpEl","errorEl","liveLabelledBy","liveDescribedBy","externalLabelTokens","externalDescTokens","consumerLabelEls","resolveIdrefTokens","hasEffectiveLabelledBy","consumerDescEls","hasError","isInvalid","explicitAccessibleLabel","isVisibleForAccName","labelElsForInternals","descElsForInternals","refsInternals","flattenText","els","t","inputAriaLabel","inputAriaLabelledBy","labelledByFlat","flat","consumerDescSpan","consumerDescText","describedByIds","value","_mode","disabled","parsed","child","trimmed","count","filtered","enabledIndices","i","nextDown","lastEnabled","prevUp","lastEnabledUp","opt","option","current","next","val","options","index","html","repeat","isSelected","isFocused","classMap","nothing","hasHelp","showClear","fieldClasses","inputClasses","activeOptionId","e","ifDefined","forcedColorsField","__decorateClass","property","query","customElement"],"mappings":";;;;;;;;;;AAEO,MAAMA,KAAsBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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"}