@helixui/library 3.8.0 → 3.9.0-next.150

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (250) hide show
  1. package/README.md +41 -0
  2. package/aaa-verdicts.json +2036 -0
  3. package/custom-elements.json +532 -569
  4. package/dist/components/hx-accordion/hx-accordion-item.d.ts.map +1 -1
  5. package/dist/components/hx-accordion/hx-accordion-item.styles.d.ts.map +1 -1
  6. package/dist/components/hx-accordion/index.js +1 -1
  7. package/dist/components/hx-alert/hx-alert.d.ts +0 -8
  8. package/dist/components/hx-alert/hx-alert.d.ts.map +1 -1
  9. package/dist/components/hx-alert/hx-alert.styles.d.ts.map +1 -1
  10. package/dist/components/hx-alert/index.js +1 -1
  11. package/dist/components/hx-avatar/hx-avatar.d.ts +4 -1
  12. package/dist/components/hx-avatar/hx-avatar.d.ts.map +1 -1
  13. package/dist/components/hx-avatar/hx-avatar.styles.d.ts.map +1 -1
  14. package/dist/components/hx-avatar/index.js +1 -1
  15. package/dist/components/hx-badge/hx-badge.d.ts.map +1 -1
  16. package/dist/components/hx-badge/hx-badge.styles.d.ts.map +1 -1
  17. package/dist/components/hx-badge/index.js +1 -1
  18. package/dist/components/hx-banner/hx-banner.d.ts +0 -8
  19. package/dist/components/hx-banner/hx-banner.d.ts.map +1 -1
  20. package/dist/components/hx-banner/hx-banner.styles.d.ts.map +1 -1
  21. package/dist/components/hx-banner/index.js +1 -1
  22. package/dist/components/hx-carousel/hx-carousel.d.ts.map +1 -1
  23. package/dist/components/hx-carousel/hx-carousel.styles.d.ts.map +1 -1
  24. package/dist/components/hx-carousel/index.js +1 -1
  25. package/dist/components/hx-checkbox/hx-checkbox.d.ts.map +1 -1
  26. package/dist/components/hx-checkbox/hx-checkbox.styles.d.ts.map +1 -1
  27. package/dist/components/hx-checkbox/index.js +1 -1
  28. package/dist/components/hx-clinical-status/hx-clinical-status.d.ts +7 -9
  29. package/dist/components/hx-clinical-status/hx-clinical-status.d.ts.map +1 -1
  30. package/dist/components/hx-clinical-status/hx-clinical-status.styles.d.ts.map +1 -1
  31. package/dist/components/hx-clinical-status/index.js +1 -1
  32. package/dist/components/hx-combobox/hx-combobox.d.ts.map +1 -1
  33. package/dist/components/hx-combobox/hx-combobox.styles.d.ts.map +1 -1
  34. package/dist/components/hx-combobox/index.js +1 -1
  35. package/dist/components/hx-date-picker/hx-date-picker.d.ts.map +1 -1
  36. package/dist/components/hx-date-picker/hx-date-picker.styles.d.ts.map +1 -1
  37. package/dist/components/hx-date-picker/index.js +1 -1
  38. package/dist/components/hx-drawer/hx-drawer.d.ts.map +1 -1
  39. package/dist/components/hx-drawer/hx-drawer.styles.d.ts.map +1 -1
  40. package/dist/components/hx-drawer/index.js +1 -1
  41. package/dist/components/hx-dropdown/hx-dropdown.styles.d.ts.map +1 -1
  42. package/dist/components/hx-dropdown/index.js +1 -1
  43. package/dist/components/hx-file-upload/hx-file-upload.d.ts +28 -0
  44. package/dist/components/hx-file-upload/hx-file-upload.d.ts.map +1 -1
  45. package/dist/components/hx-file-upload/hx-file-upload.styles.d.ts.map +1 -1
  46. package/dist/components/hx-file-upload/index.js +1 -1
  47. package/dist/components/hx-help-text/hx-help-text.d.ts.map +1 -1
  48. package/dist/components/hx-help-text/hx-help-text.styles.d.ts.map +1 -1
  49. package/dist/components/hx-help-text/index.js +1 -1
  50. package/dist/components/hx-icon/hx-icon.d.ts +108 -12
  51. package/dist/components/hx-icon/hx-icon.d.ts.map +1 -1
  52. package/dist/components/hx-icon/hx-icon.styles.d.ts.map +1 -1
  53. package/dist/components/hx-icon/index.js +1 -1
  54. package/dist/components/hx-link/hx-link.d.ts.map +1 -1
  55. package/dist/components/hx-link/hx-link.styles.d.ts.map +1 -1
  56. package/dist/components/hx-link/index.js +1 -1
  57. package/dist/components/hx-menu/hx-menu-item.d.ts.map +1 -1
  58. package/dist/components/hx-menu/hx-menu-item.styles.d.ts.map +1 -1
  59. package/dist/components/hx-menu/index.js +1 -1
  60. package/dist/components/hx-nav/hx-nav.d.ts.map +1 -1
  61. package/dist/components/hx-nav/hx-nav.styles.d.ts.map +1 -1
  62. package/dist/components/hx-nav/index.js +1 -1
  63. package/dist/components/hx-number-input/hx-number-input.d.ts.map +1 -1
  64. package/dist/components/hx-number-input/hx-number-input.styles.d.ts.map +1 -1
  65. package/dist/components/hx-number-input/index.js +1 -1
  66. package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts +5 -1
  67. package/dist/components/hx-overflow-menu/hx-overflow-menu.d.ts.map +1 -1
  68. package/dist/components/hx-overflow-menu/hx-overflow-menu.styles.d.ts.map +1 -1
  69. package/dist/components/hx-overflow-menu/index.js +1 -1
  70. package/dist/components/hx-phi-field/hx-phi-field.d.ts.map +1 -1
  71. package/dist/components/hx-phi-field/hx-phi-field.styles.d.ts.map +1 -1
  72. package/dist/components/hx-phi-field/index.js +1 -1
  73. package/dist/components/hx-radio-group/hx-radio-group.d.ts.map +1 -1
  74. package/dist/components/hx-radio-group/index.js +1 -1
  75. package/dist/components/hx-rating/hx-rating.d.ts.map +1 -1
  76. package/dist/components/hx-rating/hx-rating.styles.d.ts.map +1 -1
  77. package/dist/components/hx-rating/index.js +1 -1
  78. package/dist/components/hx-side-nav/hx-nav-item.d.ts.map +1 -1
  79. package/dist/components/hx-side-nav/hx-nav-item.styles.d.ts.map +1 -1
  80. package/dist/components/hx-side-nav/hx-side-nav.d.ts.map +1 -1
  81. package/dist/components/hx-side-nav/hx-side-nav.styles.d.ts.map +1 -1
  82. package/dist/components/hx-side-nav/index.js +1 -1
  83. package/dist/components/hx-slider/hx-slider.d.ts +28 -0
  84. package/dist/components/hx-slider/hx-slider.d.ts.map +1 -1
  85. package/dist/components/hx-slider/index.js +1 -1
  86. package/dist/components/hx-split-button/hx-split-button.d.ts.map +1 -1
  87. package/dist/components/hx-split-button/hx-split-button.styles.d.ts.map +1 -1
  88. package/dist/components/hx-split-button/index.js +1 -1
  89. package/dist/components/hx-stat/hx-stat.d.ts.map +1 -1
  90. package/dist/components/hx-stat/hx-stat.styles.d.ts.map +1 -1
  91. package/dist/components/hx-stat/index.js +1 -1
  92. package/dist/components/hx-steps/hx-step.d.ts.map +1 -1
  93. package/dist/components/hx-steps/hx-step.styles.d.ts.map +1 -1
  94. package/dist/components/hx-steps/index.js +1 -1
  95. package/dist/components/hx-tag/hx-tag.d.ts.map +1 -1
  96. package/dist/components/hx-tag/hx-tag.styles.d.ts.map +1 -1
  97. package/dist/components/hx-tag/index.js +1 -1
  98. package/dist/components/hx-time-picker/hx-time-picker.d.ts.map +1 -1
  99. package/dist/components/hx-time-picker/hx-time-picker.styles.d.ts.map +1 -1
  100. package/dist/components/hx-time-picker/index.js +1 -1
  101. package/dist/components/hx-toast/hx-toast.d.ts +0 -8
  102. package/dist/components/hx-toast/hx-toast.d.ts.map +1 -1
  103. package/dist/components/hx-toast/hx-toast.styles.d.ts.map +1 -1
  104. package/dist/components/hx-toast/index.js +1 -1
  105. package/dist/components/hx-top-nav/hx-top-nav.d.ts.map +1 -1
  106. package/dist/components/hx-top-nav/hx-top-nav.styles.d.ts.map +1 -1
  107. package/dist/components/hx-top-nav/index.js +1 -1
  108. package/dist/components/hx-tree-view/hx-tree-item.d.ts.map +1 -1
  109. package/dist/components/hx-tree-view/hx-tree-item.styles.d.ts.map +1 -1
  110. package/dist/components/hx-tree-view/index.js +1 -1
  111. package/dist/css/helix-all.css +116 -54
  112. package/dist/css/helix-core.css +19 -4
  113. package/dist/css/helix-feedback.css +15 -18
  114. package/dist/css/helix-forms.css +39 -12
  115. package/dist/css/helix-media.css +6 -3
  116. package/dist/css/helix-navigation.css +16 -7
  117. package/dist/css/helix-overlay.css +10 -0
  118. package/dist/css/helix-tokens.css +3 -2
  119. package/dist/css/helix-utility.css +5 -0
  120. package/dist/css/hx-alert.css +4 -8
  121. package/dist/css/hx-avatar.css +1 -2
  122. package/dist/css/hx-badge.css +5 -0
  123. package/dist/css/hx-banner.css +4 -8
  124. package/dist/css/hx-carousel.css +6 -3
  125. package/dist/css/hx-checkbox.css +4 -9
  126. package/dist/css/hx-clinical-status.css +4 -7
  127. package/dist/css/hx-combobox.css +8 -0
  128. package/dist/css/hx-date-picker.css +5 -0
  129. package/dist/css/hx-drawer.css +5 -0
  130. package/dist/css/hx-dropdown.css +5 -0
  131. package/dist/css/hx-file-upload.css +4 -0
  132. package/dist/css/hx-help-text.css +5 -0
  133. package/dist/css/hx-icon.css +7 -0
  134. package/dist/css/hx-link.css +1 -2
  135. package/dist/css/hx-nav.css +7 -0
  136. package/dist/css/hx-number-input.css +2 -3
  137. package/dist/css/hx-overflow-menu.css +5 -0
  138. package/dist/css/hx-phi-field.css +2 -3
  139. package/dist/css/hx-rating.css +6 -0
  140. package/dist/css/hx-side-nav.css +3 -5
  141. package/dist/css/hx-split-button.css +5 -0
  142. package/dist/css/hx-stat.css +1 -2
  143. package/dist/css/hx-tag.css +5 -0
  144. package/dist/css/hx-time-picker.css +5 -0
  145. package/dist/css/hx-toast.css +6 -0
  146. package/dist/css/hx-top-nav.css +1 -2
  147. package/dist/css/index.css +1 -1
  148. package/dist/css/manifest.json +4 -1
  149. package/dist/index.js +33 -33
  150. package/dist/shared/{hx-accordion-ZVzgDzTG.js → hx-accordion-DR--Ev4t.js} +48 -54
  151. package/dist/shared/hx-accordion-DR--Ev4t.js.map +1 -0
  152. package/dist/shared/{hx-alert-Bto8-TIi.js → hx-alert-C0axS32J.js} +40 -79
  153. package/dist/shared/hx-alert-C0axS32J.js.map +1 -0
  154. package/dist/shared/{hx-avatar-C9hOmlAb.js → hx-avatar-ChAYWnK8.js} +22 -24
  155. package/dist/shared/hx-avatar-ChAYWnK8.js.map +1 -0
  156. package/dist/shared/{hx-badge-DFL35nzi.js → hx-badge-vX-1cuLA.js} +16 -11
  157. package/dist/shared/hx-badge-vX-1cuLA.js.map +1 -0
  158. package/dist/shared/{hx-banner-fpRnciIO.js → hx-banner-PbHwFNSb.js} +51 -90
  159. package/dist/shared/hx-banner-PbHwFNSb.js.map +1 -0
  160. package/dist/shared/{hx-carousel-item-z1Lc24op.js → hx-carousel-item-BVIKgQ4i.js} +72 -102
  161. package/dist/shared/hx-carousel-item-BVIKgQ4i.js.map +1 -0
  162. package/dist/shared/{hx-checkbox-DcgyGS9V.js → hx-checkbox-DDSXXhps.js} +31 -38
  163. package/dist/shared/hx-checkbox-DDSXXhps.js.map +1 -0
  164. package/dist/shared/{hx-clinical-status-D3XQIOqX.js → hx-clinical-status-ZSVEc3Qg.js} +68 -87
  165. package/dist/shared/hx-clinical-status-ZSVEc3Qg.js.map +1 -0
  166. package/dist/shared/{hx-combobox-NgJaLbs2.js → hx-combobox-Be-mqOv4.js} +35 -45
  167. package/dist/shared/hx-combobox-Be-mqOv4.js.map +1 -0
  168. package/dist/shared/{hx-date-picker-0PtEav0K.js → hx-date-picker-CziP3Hm1.js} +15 -22
  169. package/dist/shared/hx-date-picker-CziP3Hm1.js.map +1 -0
  170. package/dist/shared/{hx-drawer-CM_upadk.js → hx-drawer-BlU2oX8-.js} +32 -36
  171. package/dist/shared/hx-drawer-BlU2oX8-.js.map +1 -0
  172. package/dist/shared/{hx-dropdown-xHwTJecv.js → hx-dropdown-DREqpIpm.js} +16 -11
  173. package/dist/shared/hx-dropdown-DREqpIpm.js.map +1 -0
  174. package/dist/shared/{hx-file-upload-D3rKROK5.js → hx-file-upload-CU5QGZSP.js} +137 -80
  175. package/dist/shared/hx-file-upload-CU5QGZSP.js.map +1 -0
  176. package/dist/shared/hx-help-text-CNaZ82LT.js +137 -0
  177. package/dist/shared/hx-help-text-CNaZ82LT.js.map +1 -0
  178. package/dist/shared/hx-icon-bxz9eB9a.js +386 -0
  179. package/dist/shared/hx-icon-bxz9eB9a.js.map +1 -0
  180. package/dist/shared/{hx-link-CMnZRUtQ.js → hx-link-BURSdYLp.js} +19 -26
  181. package/dist/shared/hx-link-BURSdYLp.js.map +1 -0
  182. package/dist/shared/{hx-menu-divider-A6Guuzi_.js → hx-menu-divider-g0grbWV9.js} +19 -31
  183. package/dist/shared/hx-menu-divider-g0grbWV9.js.map +1 -0
  184. package/dist/shared/{hx-nav-ChMTfn7o.js → hx-nav-GTsAZGOx.js} +46 -59
  185. package/dist/shared/hx-nav-GTsAZGOx.js.map +1 -0
  186. package/dist/shared/{hx-nav-item-ClN17f1y.js → hx-nav-item-CxE7Mp3M.js} +62 -64
  187. package/dist/shared/hx-nav-item-CxE7Mp3M.js.map +1 -0
  188. package/dist/shared/{hx-number-input-MggsT7F0.js → hx-number-input-Bvyc9kOi.js} +48 -53
  189. package/dist/shared/hx-number-input-Bvyc9kOi.js.map +1 -0
  190. package/dist/shared/{hx-overflow-menu-DFjJAziP.js → hx-overflow-menu-LrTteeR1.js} +32 -39
  191. package/dist/shared/hx-overflow-menu-LrTteeR1.js.map +1 -0
  192. package/dist/shared/{hx-phi-field-C19oxlrr.js → hx-phi-field-sZt_rYIL.js} +46 -66
  193. package/dist/shared/hx-phi-field-sZt_rYIL.js.map +1 -0
  194. package/dist/shared/{hx-radio-BY4zpwdh.js → hx-radio-BD_c9NJy.js} +51 -56
  195. package/dist/shared/{hx-radio-BY4zpwdh.js.map → hx-radio-BD_c9NJy.js.map} +1 -1
  196. package/dist/shared/{hx-rating-C3QP53k9.js → hx-rating-BGK4AxvI.js} +45 -71
  197. package/dist/shared/hx-rating-BGK4AxvI.js.map +1 -0
  198. package/dist/shared/{hx-slider-Blmv_rwS.js → hx-slider-CkOk5BCY.js} +83 -23
  199. package/dist/shared/{hx-slider-Blmv_rwS.js.map → hx-slider-CkOk5BCY.js.map} +1 -1
  200. package/dist/shared/{hx-split-button-CdNz1XAu.js → hx-split-button-Bg9FHrFK.js} +12 -16
  201. package/dist/shared/hx-split-button-Bg9FHrFK.js.map +1 -0
  202. package/dist/shared/{hx-stat-Gtw_SpK8.js → hx-stat-wKxbyep6.js} +22 -55
  203. package/dist/shared/hx-stat-wKxbyep6.js.map +1 -0
  204. package/dist/shared/{hx-step-CUzliIK_.js → hx-step-CyGQAuiB.js} +5 -25
  205. package/dist/shared/hx-step-CyGQAuiB.js.map +1 -0
  206. package/dist/shared/{hx-tag-C5aCUpVi.js → hx-tag-BqO6HY6V.js} +26 -21
  207. package/dist/shared/hx-tag-BqO6HY6V.js.map +1 -0
  208. package/dist/shared/{hx-time-picker-DfJkBwcX.js → hx-time-picker-if5Cl0Ei.js} +32 -38
  209. package/dist/shared/hx-time-picker-if5Cl0Ei.js.map +1 -0
  210. package/dist/shared/{hx-top-nav-CsTxOtVI.js → hx-top-nav-vP6oDWMV.js} +24 -38
  211. package/dist/shared/hx-top-nav-vP6oDWMV.js.map +1 -0
  212. package/dist/shared/{hx-tree-item-CXyspGxI.js → hx-tree-item-D8hwKd5m.js} +54 -57
  213. package/dist/shared/hx-tree-item-D8hwKd5m.js.map +1 -0
  214. package/dist/shared/{toast-factory-Dht3pVsw.js → toast-factory-DgnbFxVs.js} +127 -153
  215. package/dist/shared/toast-factory-DgnbFxVs.js.map +1 -0
  216. package/figma-inventory.json +283 -304
  217. package/package.json +8 -4
  218. package/dist/shared/hx-accordion-ZVzgDzTG.js.map +0 -1
  219. package/dist/shared/hx-alert-Bto8-TIi.js.map +0 -1
  220. package/dist/shared/hx-avatar-C9hOmlAb.js.map +0 -1
  221. package/dist/shared/hx-badge-DFL35nzi.js.map +0 -1
  222. package/dist/shared/hx-banner-fpRnciIO.js.map +0 -1
  223. package/dist/shared/hx-carousel-item-z1Lc24op.js.map +0 -1
  224. package/dist/shared/hx-checkbox-DcgyGS9V.js.map +0 -1
  225. package/dist/shared/hx-clinical-status-D3XQIOqX.js.map +0 -1
  226. package/dist/shared/hx-combobox-NgJaLbs2.js.map +0 -1
  227. package/dist/shared/hx-date-picker-0PtEav0K.js.map +0 -1
  228. package/dist/shared/hx-drawer-CM_upadk.js.map +0 -1
  229. package/dist/shared/hx-dropdown-xHwTJecv.js.map +0 -1
  230. package/dist/shared/hx-file-upload-D3rKROK5.js.map +0 -1
  231. package/dist/shared/hx-help-text-Xb2Yr8x2.js +0 -156
  232. package/dist/shared/hx-help-text-Xb2Yr8x2.js.map +0 -1
  233. package/dist/shared/hx-icon-fuVm4-bk.js +0 -283
  234. package/dist/shared/hx-icon-fuVm4-bk.js.map +0 -1
  235. package/dist/shared/hx-link-CMnZRUtQ.js.map +0 -1
  236. package/dist/shared/hx-menu-divider-A6Guuzi_.js.map +0 -1
  237. package/dist/shared/hx-nav-ChMTfn7o.js.map +0 -1
  238. package/dist/shared/hx-nav-item-ClN17f1y.js.map +0 -1
  239. package/dist/shared/hx-number-input-MggsT7F0.js.map +0 -1
  240. package/dist/shared/hx-overflow-menu-DFjJAziP.js.map +0 -1
  241. package/dist/shared/hx-phi-field-C19oxlrr.js.map +0 -1
  242. package/dist/shared/hx-rating-C3QP53k9.js.map +0 -1
  243. package/dist/shared/hx-split-button-CdNz1XAu.js.map +0 -1
  244. package/dist/shared/hx-stat-Gtw_SpK8.js.map +0 -1
  245. package/dist/shared/hx-step-CUzliIK_.js.map +0 -1
  246. package/dist/shared/hx-tag-C5aCUpVi.js.map +0 -1
  247. package/dist/shared/hx-time-picker-DfJkBwcX.js.map +0 -1
  248. package/dist/shared/hx-top-nav-CsTxOtVI.js.map +0 -1
  249. package/dist/shared/hx-tree-item-CXyspGxI.js.map +0 -1
  250. package/dist/shared/toast-factory-Dht3pVsw.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"hx-date-picker-0PtEav0K.js","sources":["../../src/components/hx-date-picker/hx-date-picker.styles.ts","../../src/components/hx-date-picker/hx-date-picker.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixDatePickerStyles = css`\n /* ============================================================\n Host\n ============================================================ */\n\n :host {\n display: block;\n position: relative;\n }\n\n :host([disabled]) {\n opacity: var(--hx-opacity-disabled, 0.5);\n pointer-events: none;\n }\n\n * {\n box-sizing: border-box;\n }\n\n /* ============================================================\n Field layout\n ============================================================ */\n\n .field {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n font-family: var(--hx-date-picker-font-family, var(--hx-font-family-sans, sans-serif));\n position: relative;\n }\n\n .field__label-wrapper {\n display: contents;\n }\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-date-picker-label-color, var(--hx-color-text-strong, #202b39));\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .field__required-marker {\n color: var(--hx-date-picker-error-color, var(--hx-color-error-text, #c92a2a));\n font-weight: var(--hx-font-weight-bold, 700);\n }\n\n /* ============================================================\n Input wrapper\n ============================================================ */\n\n .field__input-wrapper {\n display: flex;\n align-items: stretch;\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-date-picker-border-color, var(--hx-color-border-strong, #66787b));\n border-radius: var(--hx-date-picker-border-radius, var(--hx-border-radius-md, 0.375rem));\n background-color: var(--hx-date-picker-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 overflow: hidden;\n }\n\n .field__input-wrapper:focus-within {\n border-color: var(--hx-date-picker-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-date-picker-focus-ring-color, var(--hx-focus-ring-color, #0f7078))\n calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n .field--error .field__input-wrapper {\n border-color: var(--hx-date-picker-error-color, var(--hx-color-error-500, #e5493e));\n }\n\n .field--error .field__input-wrapper:focus-within {\n border-color: var(--hx-date-picker-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-date-picker-error-color, var(--hx-color-error-500, #e5493e))\n calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n /* ============================================================\n Input element\n ============================================================ */\n\n .field__input {\n flex: 1;\n border: none;\n outline: none;\n background: transparent;\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n font-family: inherit;\n font-size: var(--hx-font-size-md, 1rem);\n color: var(--hx-date-picker-color, var(--hx-color-text-strong, #202b39));\n line-height: var(--hx-line-height-normal, 1.5);\n /* WCAG 2.5.5 (Enhanced) AAA — primary input surface must meet 44×44. */\n min-height: var(--hx-touch-target-min, 2.75rem);\n width: 100%;\n cursor: default;\n }\n\n .field__input::placeholder {\n color: var(--hx-color-text-placeholder, #66787b);\n }\n\n .field__input:disabled {\n cursor: not-allowed;\n }\n\n /* ============================================================\n Calendar trigger button\n ============================================================ */\n\n .field__trigger {\n display: flex;\n align-items: center;\n justify-content: center;\n /* WCAG 2.5.5 (Enhanced) AAA — calendar trigger must clear 44×44.\n Without min-width the icon button collapses to ~41 px wide. */\n min-width: var(--hx-touch-target-min, 2.75rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n padding: 0 var(--hx-space-3, 0.75rem);\n border: none;\n border-left: var(--hx-border-width-thin, 1px) solid\n var(--hx-date-picker-border-color, var(--hx-color-border-strong, #66787b));\n background: transparent;\n color: var(--hx-date-picker-trigger-color, var(--hx-color-text-muted, #4a5362));\n cursor: pointer;\n flex-shrink: 0;\n transition: color var(--hx-transition-fast, 150ms ease);\n outline: none;\n }\n\n .field__trigger:focus-visible {\n color: var(--hx-date-picker-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n background-color: color-mix(\n in srgb,\n var(--hx-date-picker-focus-ring-color, var(--hx-focus-ring-color, #0f7078)) 8%,\n transparent\n );\n }\n\n .field__trigger:hover:not(:disabled) {\n color: var(--hx-date-picker-trigger-hover-color, var(--hx-color-text-strong, #202b39));\n background-color: color-mix(in srgb, var(--hx-color-neutral-900, #0d1825) 4%, transparent);\n }\n\n .field__trigger:disabled {\n cursor: not-allowed;\n }\n\n /* ============================================================\n Calendar popover\n ============================================================ */\n\n .calendar {\n position: absolute;\n top: calc(100% + var(--hx-space-1, 0.25rem));\n left: 0;\n z-index: var(--hx-z-index-dropdown, 1000);\n min-width: var(--hx-date-picker-calendar-min-width, 18rem);\n background-color: var(--hx-date-picker-calendar-bg, var(--hx-color-surface-default, #ffffff));\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-date-picker-calendar-border-color, var(--hx-color-border-default, #d6dbd5));\n border-radius: var(--hx-date-picker-calendar-border-radius, var(--hx-border-radius-lg, 0.5rem));\n box-shadow: var(\n --hx-date-picker-calendar-shadow,\n var(--hx-shadow-md, 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1))\n );\n padding: var(--hx-space-3, 0.75rem);\n outline: none;\n }\n\n @media (prefers-reduced-motion: no-preference) {\n .calendar {\n animation: calendar-appear var(--hx-transition-fast, 150ms ease) forwards;\n }\n }\n\n @keyframes calendar-appear {\n 0% {\n opacity: 0;\n transform: translateY(-0.25rem);\n }\n\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n /* ============================================================\n Calendar navigation\n ============================================================ */\n\n .calendar__nav {\n display: flex;\n align-items: center;\n justify-content: space-between;\n margin-bottom: var(--hx-space-3, 0.75rem);\n }\n\n :is(.calendar__nav-btn, .calendar__day, .calendar__day-cell, .calendar__weekday) {\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n :is(.calendar__nav-btn, .calendar__day) {\n width: var(--hx-touch-target-min, 2.75rem);\n height: var(--hx-touch-target-min, 2.75rem);\n border: none;\n border-radius: var(--hx-border-radius-sm, 0.25rem);\n background: transparent;\n cursor: pointer;\n outline: none;\n transition:\n background-color var(--hx-transition-fast, 150ms ease),\n color var(--hx-transition-fast, 150ms ease);\n }\n\n .calendar__nav-btn {\n color: var(--hx-color-text-secondary, #313e4b);\n font-size: var(--hx-font-size-lg, 1.125rem);\n line-height: 1;\n }\n\n .calendar__nav-btn:hover {\n background-color: var(--hx-date-picker-day-hover-bg, var(--hx-color-surface-sunken, #ebeee9));\n color: var(--hx-color-text-primary, #0d1825);\n }\n\n :is(.calendar__nav-btn, .calendar__day):focus-visible {\n box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)\n var(--hx-date-picker-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n z-index: 1;\n }\n\n .calendar__nav-btn:disabled {\n opacity: var(--hx-opacity-disabled, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .calendar__month-label {\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-semibold, 600);\n color: var(--hx-color-text-strong, #202b39);\n flex: 1;\n text-align: center;\n }\n\n /* ============================================================\n Calendar grid\n ============================================================ */\n\n .calendar__grid {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n }\n\n .calendar__row {\n display: grid;\n grid-template-columns: repeat(7, 1fr);\n gap: var(--hx-space-1, 0.25rem);\n }\n\n .calendar__weekday {\n height: var(--hx-size-8, 2rem);\n font-size: var(--hx-font-size-xs, 0.75rem);\n font-weight: var(--hx-font-weight-semibold, 600);\n color: var(--hx-color-text-muted, #4a5362);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n /* ============================================================\n Calendar day cells\n ============================================================ */\n\n .calendar__day {\n color: var(--hx-color-text-strong, #202b39);\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-family: inherit;\n position: relative;\n }\n\n .calendar__day:hover:not(.calendar__day--disabled):not(.calendar__day--selected) {\n background-color: var(--hx-date-picker-day-hover-bg, var(--hx-color-surface-sunken, #ebeee9));\n color: var(--hx-color-text-primary, #0d1825);\n }\n\n .calendar__day--selected {\n background-color: var(--hx-date-picker-selected-bg, var(--hx-color-action-primary-bg, #0f7078));\n color: var(--hx-date-picker-selected-color, var(--hx-color-text-on-primary, #ffffff));\n font-weight: var(--hx-font-weight-semibold, 600);\n }\n\n .calendar__day--selected:hover {\n background-color: var(\n --hx-date-picker-selected-hover-bg,\n var(--hx-color-action-primary-bg-hover, #0f6363)\n );\n }\n\n .calendar__day--today:not(.calendar__day--selected) {\n font-weight: var(--hx-font-weight-bold, 700);\n color: var(--hx-date-picker-today-color, var(--hx-color-primary-600, #0f7078));\n }\n\n .calendar__day--today:not(.calendar__day--selected)::after {\n content: '';\n position: absolute;\n bottom: 0.2rem;\n left: 50%;\n transform: translate(-50%);\n width: 0.25rem;\n height: 0.25rem;\n border-radius: 50%;\n background-color: currentColor;\n }\n\n .calendar__day--disabled {\n opacity: var(--hx-opacity-disabled, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n\n /* ============================================================\n Live region (screen reader announcements)\n ============================================================ */\n\n .calendar__live-region,\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\n /* ============================================================\n Help text and error message\n ============================================================ */\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\n .field__help-text {\n color: var(--hx-color-text-muted, #4a5362);\n }\n\n .field__error {\n color: var(--hx-date-picker-error-color, var(--hx-color-error-text, #c92a2a));\n }\n\n /* ============================================================\n Reduced motion\n ============================================================ */\n\n @media (prefers-reduced-motion: reduce) {\n .field__input-wrapper,\n .field__trigger,\n .calendar__nav-btn,\n .calendar__day {\n transition: none;\n }\n }\n\n /* ============================================================\n Forced colors (Windows High Contrast)\n ============================================================ */\n\n @media (forced-colors: active) {\n .field__input-wrapper {\n border: 1px solid ButtonText;\n }\n\n .field__input-wrapper:focus-within {\n outline: 2px solid Highlight;\n outline-offset: 1px;\n box-shadow: none;\n }\n\n :is(.calendar__day:focus-visible, .calendar__nav-btn:focus-visible) {\n outline: 2px solid Highlight;\n box-shadow: none;\n }\n\n .calendar__day--selected {\n background-color: Highlight;\n color: HighlightText;\n border: 1px solid Highlight;\n }\n\n .calendar__day--today:not(.calendar__day--selected) {\n border: 2px solid LinkText;\n }\n\n .calendar__day--today:not(.calendar__day--selected)::after {\n display: none;\n }\n\n .calendar__day--disabled {\n color: GrayText;\n }\n\n .field--error .field__input-wrapper {\n border-color: LinkText;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, state, query } 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 { helixDatePickerStyles } from './hx-date-picker.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';\nimport { flattenAccName } from '../../utils/aria-flatten.js';\n\n// PERF: hx-date-picker exceeds 5KB budget (7.98kb gzipped) -- calendar grid, date parsing, keyboard navigation, localization\n\nconst _nextDatePickerId = createIdCounter('hx-date-picker');\n\n/** Detail for the hx-change event dispatched by hx-date-picker. */\nexport interface HxDatePickerChangeDetail {\n value: string;\n date: Date | null;\n}\n\n/**\n * Date picker component for selecting dates with keyboard-accessible calendar popup.\n *\n * @summary Form-associated date picker with calendar popup and WCAG 2.1 AA accessibility.\n *\n * @tag hx-date-picker\n *\n * @slot label - Custom label content (overrides the label property).\n * @slot help-text - Custom help text content (overrides the helpText property).\n * @slot error - Custom error content (overrides the error property).\n *\n * @fires {CustomEvent<{value: string, date: Date | null}>} hx-change - Emitted when the selected date changes.\n *\n * @csspart field - The outer field container.\n * @csspart label - The label element.\n * @csspart input-wrapper - The wrapper around input and trigger.\n * @csspart input - The readonly text input displaying the formatted date.\n * @csspart trigger - The calendar icon button.\n * @csspart calendar - The calendar popup dialog.\n * @csspart month-nav - The month navigation header.\n * @csspart day - An individual day button in the calendar grid.\n * @csspart help-text - The help text container.\n * @csspart error - The error message container.\n *\n * @cssprop [--hx-date-picker-bg=var(--hx-color-neutral-0)] - Input background color.\n * @cssprop [--hx-date-picker-color=var(--hx-color-neutral-800)] - Input text color.\n * @cssprop [--hx-date-picker-border-color=var(--hx-color-neutral-300)] - Border color.\n * @cssprop [--hx-date-picker-border-radius=var(--hx-border-radius-md)] - Border radius.\n * @cssprop [--hx-date-picker-font-family=var(--hx-font-family-sans)] - Font family.\n * @cssprop [--hx-date-picker-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-date-picker-error-color=var(--hx-color-error-500)] - Error state color.\n * @cssprop [--hx-date-picker-label-color=var(--hx-color-neutral-700)] - Label text color.\n * @cssprop [--hx-date-picker-trigger-color=var(--hx-color-neutral-500)] - Trigger icon color.\n * @cssprop [--hx-date-picker-calendar-bg=var(--hx-color-neutral-0)] - Calendar background color.\n * @cssprop [--hx-date-picker-calendar-border-color=var(--hx-color-neutral-200)] - Calendar border color.\n * @cssprop [--hx-date-picker-calendar-min-width=18rem] - Calendar minimum width.\n * @cssprop [--hx-date-picker-selected-bg=var(--hx-color-primary-500)] - Selected day background.\n * @cssprop [--hx-date-picker-selected-color=var(--hx-color-neutral-0)] - Selected day text color.\n * @cssprop [--hx-date-picker-today-color=var(--hx-color-primary-600)] - Today indicator color.\n * @cssprop [--hx-date-picker-calendar-shadow=0 4px 6px -1px rgba(0,0,0,0.1),0 2px 4px -2px rgba(0,0,0,0.1)] - Calendar popup box shadow.\n * @cssprop [--hx-date-picker-calendar-border-radius=var(--hx-border-radius-lg)] - Border radius.\n * @cssprop [--hx-date-picker-selected-hover-bg=var(--hx-color-primary-600)] - Background color.\n * @cssprop [--hx-date-picker-trigger-hover-color=var(--hx-color-neutral-700)] - Color.\n * @cssprop [--hx-border-radius-lg] - CSS custom property.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-border-radius-sm] - CSS custom property.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-color-error-500] - Color.\n * @cssprop [--hx-color-error-text] - Color.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-color-neutral-100] - Color.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-color-neutral-300] - Color.\n * @cssprop [--hx-color-neutral-400] - Color.\n * @cssprop [--hx-color-neutral-500] - Color.\n * @cssprop [--hx-color-neutral-600] - Color.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-color-neutral-800] - Color.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-color-primary-600] - Color.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-focus-ring-opacity] - CSS custom property.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-size-lg] - Font size.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-font-size-xs] - Font size.\n * @cssprop [--hx-font-weight-bold] - Font weight.\n * @cssprop [--hx-font-weight-medium] - Font weight.\n * @cssprop [--hx-font-weight-semibold] - Font weight.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-opacity-disabled] - Opacity.\n * @cssprop [--hx-shadow-md] - Box shadow.\n * @cssprop [--hx-size-10] - Size token.\n * @cssprop [--hx-size-8] - Size token.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-z-index-dropdown] - Z-index layer.\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-date-picker/AAA-AUDIT.md\n * @keyboard-contract dismiss=Escape; trap-focus=true\n * @aria-pattern dialog\n * @aria-pattern-source https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/\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-date-picker\n * @priority-tier P0\n * @phi-handles false\n * @clinical-context none\n */\n@customElement('hx-date-picker')\nexport class HelixDatePicker extends FormMixin(HelixElement) {\n static override styles = [helixDatePickerStyles, forcedColorsField];\n\n // ─── Form Association ───\n\n /**\n * Marks this component as form-associated for native form participation.\n * @internal\n */\n static override formAssociated = true;\n\n /**\n * Test seam: when set to `true` or `false`, overrides the platform\n * `supportsIdrefElementReferences` probe before `connectedCallback` seeds\n * `_supportsIdrefRefs`. Production code MUST NOT touch this field. It is a\n * `static` so the test stub cleanup is global and obvious.\n * @internal\n */\n static __testSupportsIdrefRefsOverride: boolean | null = null;\n\n // ─── Properties ───\n\n /**\n * The name of the field, used for form submission.\n * @attr name\n */\n @property({ type: String, reflect: true })\n name = '';\n\n /**\n * The current value as an ISO 8601 date string (e.g. 2026-03-04).\n * @attr value\n */\n @property({ type: String })\n value = '';\n\n /**\n * The minimum selectable date as an ISO 8601 string.\n * @attr min\n */\n @property({ type: String })\n min = '';\n\n /**\n * The maximum selectable date as an ISO 8601 string.\n * @attr max\n */\n @property({ type: String })\n max = '';\n\n /**\n * The visible label text.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Whether the field is required for form submission.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /**\n * Whether the field is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\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 field for guidance.\n * @attr help-text\n */\n @property({ type: String, attribute: 'help-text' })\n helpText = '';\n\n /**\n * Display format hint shown as placeholder (e.g. MM/DD/YYYY).\n * @attr format\n */\n @property({ type: String })\n format = 'MM/DD/YYYY';\n\n /**\n * Locale string used for formatting the display value.\n * @attr locale\n */\n @property({ type: String })\n locale = 'en-US';\n\n /**\n * Validation message shown when the field is required but empty.\n * @attr required-message\n */\n @property({ type: String, attribute: 'required-message' })\n requiredMessage = 'This field is required.';\n\n /**\n * Accessible label for the calendar dialog.\n * @attr choose-date-label\n */\n @property({ type: String, attribute: 'choose-date-label' })\n chooseDateLabel = 'Choose a date';\n\n /**\n * Accessible label for the calendar trigger button when the calendar is closed.\n * @attr open-calendar-label\n */\n @property({ type: String, attribute: 'open-calendar-label' })\n openCalendarLabel = 'Open calendar';\n\n /**\n * Accessible label for the calendar trigger button when the calendar is open.\n * @attr close-calendar-label\n */\n @property({ type: String, attribute: 'close-calendar-label' })\n closeCalendarLabel = 'Close calendar';\n\n /**\n * Accessible label for the previous month navigation button.\n * @attr previous-month-label\n */\n @property({ type: String, attribute: 'previous-month-label' })\n previousMonthLabel = 'Previous month';\n\n /**\n * Accessible label for the next month navigation button.\n * @attr next-month-label\n */\n @property({ type: String, attribute: 'next-month-label' })\n nextMonthLabel = 'Next month';\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. Highest-precedence naming source.\n * @attr accessible-label\n */\n @property({ type: String, attribute: 'accessible-label' })\n accessibleLabel: string | null = null;\n\n // ─── Internal State ───\n\n /**\n * Tracks whether the calendar popup is currently visible.\n * @internal\n */\n @state() private _isOpen = false;\n /**\n * The year currently displayed in the calendar view.\n * @internal\n */\n @state() private _viewYear: number = new Date().getFullYear();\n /**\n * The month (0-indexed) currently displayed in the calendar view.\n * @internal\n */\n @state() private _viewMonth: number = new Date().getMonth();\n /**\n * The day number currently focused within the calendar grid, or null when the calendar is closed.\n * @internal\n */\n @state() private _focusedDay: number | null = null;\n /**\n * The message announced to screen readers when the calendar month changes.\n * @internal\n */\n @state() private _liveMessage = '';\n\n /**\n * Cached calendar day grid for the current view month/year.\n * Recomputed in willUpdate() only when _viewMonth or _viewYear changes.\n * @internal\n */\n private _dayGrid: (Date | null)[] = [];\n\n /**\n * Cached aria-label strings for each date in the current grid, keyed by ISO date string.\n * Recomputed in willUpdate() alongside _dayGrid.\n * @internal\n */\n private _dayAriaLabels: Map<string, string> = new Map();\n\n // ─── Memoized formatters ───\n\n /** @internal */\n private _weekdayFormatter: Intl.DateTimeFormat | null = null;\n /** @internal */\n private _monthFormatter: Intl.DateTimeFormat | null = null;\n /** @internal */\n private _formatterLocale = '';\n /** @internal */\n private _cachedWeekdayNames: string[] | null = null;\n\n // ─── Internal References ───\n\n /** @internal */\n @query('.field__input')\n private _input: HTMLInputElement | undefined;\n\n /** @internal */\n @query('.field__trigger')\n private _trigger: HTMLButtonElement | undefined;\n\n /** @internal */\n @query('.calendar')\n private _calendar: HTMLDialogElement | undefined;\n\n // ─── Unique IDs ───\n\n /** @internal */\n private _id = _nextDatePickerId();\n /** @internal */\n private _inputId = `${this._id}-input`;\n /** @internal */\n private _helpTextId = `${this._id}-help`;\n /** @internal */\n private _errorId = `${this._id}-error`;\n /** @internal */\n private _calendarId = `${this._id}-calendar`;\n /** @internal */\n private _liveRegionId = `${this._id}-live`;\n /** @internal */\n private _labelId = `${this._id}-label`;\n /**\n * Id of the synthesized in-shadow span that mirrors the consumer-resolved\n * description text. Appended to the inner input's `aria-describedby` so AT\n * picks the consumer description up through the standard described-by\n * channel — `aria-description` is intentionally NOT written, because the\n * W3C AccName algorithm ignores `aria-description` whenever\n * `aria-describedby` is also present.\n * @internal\n */\n private _consumerDescId = `${this._id}-consumer-desc`;\n\n // ─── Slot Tracking (host-canonical naming) ───\n\n /**\n * Whether the label slot has any assigned elements with a useful name.\n * Per AccName 1.2 §4.3.10, an empty/whitespace-only slot does NOT count.\n * @internal\n */\n @state() private _hasLabelSlot = false;\n /**\n * Whether the error slot has any meaningful (non-empty, non-hidden) content.\n * @internal\n */\n @state() private _hasErrorSlot = false;\n /**\n * Whether the help-text slot has any meaningful (non-empty, non-hidden) content.\n * @internal\n */\n @state() private _hasHelpSlot = false;\n /**\n * Discriminated label source — drives precedence between slotted label,\n * `label` property, and unnamed.\n * @internal\n */\n @state() private _labelSource: 'string' | 'slot' | 'none' = 'none';\n /**\n * Flattened, trimmed text content from all label-slot nodes — used to drive\n * the inner input's `aria-label` on the no-IDL-ref fallback path and to\n * gate `_hasLabelSlot` per AccName 1.2.\n * @internal\n */\n @state() private _labelSlotText = '';\n /**\n * Whether the platform supports IDL element references on `ElementInternals`.\n * Drives the cross-shadow naming strategy for the inner `<input>`.\n * @internal\n */\n @state() private _supportsIdrefRefs = true;\n /**\n * Cached invalidity flag derived from `internals.validity.valid`, the\n * `error` property, and the slotted error content. Drives `aria-invalid`\n * on the inner input.\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 // ─── Host-canonical ARIA bookkeeping ───\n\n /** Handle for the shared IDREF observer. @internal */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n /** @internal */\n private _helpSlotTextObserver: MutationObserver | null = null;\n /** @internal */\n private _errorSlotTextObserver: MutationObserver | null = null;\n /** @internal */\n private _hostDescribedByObserver: MutationObserver | null = null;\n /** @internal */\n private _consumerLabelledBy: string | null = null;\n /** @internal */\n private _consumerDescribedBy: string | null = null;\n /**\n * Direct references to ALL labellable elements projected into\n * `<slot name=\"label\">`. Aggregating every assigned element preserves\n * composed labels such as\n * `<svg slot=\"label\" aria-hidden=\"true\">…</svg><span slot=\"label\">Date</span>`.\n * @internal\n */\n private _slottedLabelEls: Element[] = [];\n /** @internal */\n private _labelSlotTextObserver: MutationObserver | null = null;\n /** @internal */\n private _externalRefsObserver: MutationObserver | null = null;\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n // Honour the static test override so synthetic environments choose the\n // path BEFORE connect runs.\n const ctor = this.constructor as typeof HelixDatePicker;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n\n // Install the dedicated `aria-describedby` retraction observer BEFORE\n // the seeded `_syncHostAriaSemantics()` call below.\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 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 inner input\n // resolves naming 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 document.removeEventListener('click', this._handleDocumentClick, true);\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 willUpdate(changedProperties: PropertyValues<this>): void {\n super.willUpdate(changedProperties);\n\n // Sync form state before render so the browser form participation is\n // always up-to-date without causing an extra render cycle.\n if (changedProperties.has('value')) {\n this._internals.setFormValue(this.value);\n }\n\n // Seed `_announcedError` BEFORE render so the persistent live region\n // renders with the error text in the SAME frame that the alert container\n // appears. Covers first paint AND runtime transitions to a non-empty error.\n if (changedProperties.has('error') || !this.hasUpdated) {\n this._announcedError = this.error ?? '';\n }\n\n if (changedProperties.has('label')) {\n this._refreshLabelSource();\n }\n\n // Recompute the day grid and aria-labels only when the viewed month/year\n // or locale changes — not on every render.\n const gridChanged =\n (changedProperties as Map<PropertyKey, unknown>).has('_viewMonth') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_viewYear') ||\n changedProperties.has('locale') ||\n this._dayGrid.length === 0;\n\n if (gridChanged) {\n this._dayGrid = this._getDaysInGrid();\n this._dayAriaLabels = new Map(\n this._dayGrid\n .filter((d): d is Date => d !== null)\n .map((d) => [\n this._toISO(d),\n d.toLocaleDateString(this.locale, {\n weekday: 'long',\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n }),\n ]),\n );\n }\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n\n // Host-elevated ARIA semantics — runs after every render so the inner\n // input's announced name/description follow consumer-IDREF / slot /\n // property changes within the same frame.\n this._syncHostAriaSemantics();\n\n // Drive re-announcement from reactive state on error→error transitions\n // (rAF clear-and-re-set forces AT to re-read role=\"alert\" content).\n if (changedProperties.has('error')) {\n const previousError = changedProperties.get('error') as string | undefined;\n if (previousError && this.error) {\n this._announcedError = '';\n requestAnimationFrame(() => {\n this._announcedError = this.error;\n });\n } else {\n this._announcedError = this.error;\n }\n }\n\n if ((changedProperties as Map<PropertyKey, unknown>).has('_isOpen')) {\n if (this._isOpen) {\n // Sync view to the currently selected date when opening.\n const selected = this._parseISODate(this.value);\n if (selected) {\n this._viewYear = selected.getFullYear();\n this._viewMonth = selected.getMonth();\n }\n void this.updateComplete.then(() => {\n this._calendar?.show();\n this._focusActiveDay();\n document.addEventListener('click', this._handleDocumentClick, true);\n });\n } else {\n this._calendar?.close();\n this._focusedDay = null;\n document.removeEventListener('click', this._handleDocumentClick, true);\n }\n }\n\n if (\n (changedProperties as Map<PropertyKey, unknown>).has('_viewMonth') ||\n (changedProperties as Map<PropertyKey, unknown>).has('_viewYear')\n ) {\n if (this._isOpen) {\n const monthName = this._getMonthName(this._viewMonth);\n this._liveMessage = `${monthName} ${this._viewYear}`;\n void this.updateComplete.then(() => {\n this._focusActiveDay();\n });\n }\n }\n }\n\n override firstUpdated(changed: PropertyValues<this>): void {\n super.firstUpdated(changed);\n // `slotchange` fires as a microtask after the initial synchronous render.\n // Without proactive seeding, the first `_syncHostAriaSemantics()` call\n // (driven from `updated()`) observes stale empty slot state. Seed\n // synchronously here so first paint announces the correct name/description.\n this._seedSlotStateSync();\n this._syncHostAriaSemantics();\n\n // WCAG 4.1.2: warn when no accessible name is available.\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-date-picker',\n 'No accessible label provided. Set the `label` attribute, `accessible-label`, `aria-label`, `aria-labelledby`, or project a `<slot name=\"label\">` child. An unlabeled date picker violates WCAG 2.1 AA (4.1.2 Name, Role, Value).',\n );\n }\n }\n\n /**\n * Synchronous slot-state seed. Mirrors the side effects of the three\n * `_handle*SlotChange` handlers (label / help-text / error) but is driven by\n * direct `slot.assignedNodes()` reads so we can populate state BEFORE the\n * microtask `slotchange` events fire after the first render.\n * @internal\n */\n private _seedSlotStateSync(): void {\n const root = this.shadowRoot;\n if (!root) return;\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 this._installLabelSlotTextObserver(state.elements);\n this._refreshLabelSource();\n }\n const helpSlot = root.querySelector<HTMLSlotElement>('slot[name=\"help-text\"]');\n if (helpSlot) {\n this._hasHelpSlot = this._readHelpSlotStateSync(helpSlot);\n this._installHelpSlotTextObserver(helpSlot);\n }\n const errorSlot = root.querySelector<HTMLSlotElement>('slot[name=\"error\"]');\n if (errorSlot) {\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. Per AccName 1.2 §4.3.10, `aria-hidden=\"true\"` and `[hidden]`\n * elements contribute zero to the accessible name.\n * @internal\n */\n private _readLabelSlotState(slot: HTMLSlotElement): {\n hasUsefulName: boolean;\n elements: Element[];\n text: string;\n } {\n // Use `assignedNodes()` WITHOUT `flatten: true` so we read only consumer-\n // projected nodes — never the slot's fallback content (the rendered\n // internal `<label>` element when `this.label` is set). Conflating\n // fallback content with consumer slot content makes `_hasLabelSlot`\n // truthy in the label-only case.\n const nodes = slot.assignedNodes();\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 if (el.getAttribute('aria-hidden') === 'true') continue;\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 hasUsefulName: trimmedText.length > 0,\n elements,\n text: trimmedText,\n };\n }\n\n /**\n * Re-evaluate the help-text slot's \"has meaningful content\" state from its\n * current effective text. AccName-aware so descendants carrying\n * `aria-hidden=\"true\"` or `hidden` do NOT count.\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 if (flattenAccName(node as Element).length > 0) return true;\n }\n }\n return false;\n }\n\n /**\n * Re-evaluate the error slot's \"has meaningful content\" state from its\n * current effective text.\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 if (flattenAccName(node as Element).length > 0) return true;\n }\n }\n return false;\n }\n\n /**\n * Recomputes the discriminated label source. Slot takes precedence over\n * the `label` property because the render path suppresses the internal\n * `<label>` when slotted content is present.\n * @internal\n */\n private _refreshLabelSource(): void {\n if (this._hasLabelSlot) {\n this._labelSource = 'slot';\n } else if (this.label) {\n this._labelSource = 'string';\n } else {\n this._labelSource = 'none';\n }\n }\n\n /**\n * (Re-)installs a `MutationObserver` against the deduped union of\n * consumer-resolved label/description elements.\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 const unique = new Set<Element>(elements);\n const observer = new MutationObserver(() => {\n this._syncHostAriaSemantics();\n });\n for (const el of unique) {\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 /**\n * Resolves consumer-supplied label/description IDREFs on the host and\n * writes the canonical ARIA onto the **inner readonly `<input>`** for the\n * W3C APG date-picker dialog pattern.\n *\n * The inner input is INTENTIONALLY NOT a `role=\"combobox\"` — it is a\n * readonly text input with `aria-haspopup=\"dialog\"` per W3C APG date picker\n * dialog. A separate trigger button owns `aria-expanded` /\n * `aria-controls=${calendarId}` for the dialog. (Cross-shadow `aria-controls`\n * referencing an in-shadow id is a documented limitation, mirrored from\n * hx-popover and hx-dropdown.)\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` / `ariaDescribedByElements` on\n * the host. Host-level `aria-labelledby` / `aria-describedby`\n * attributes are LEFT IN PLACE so AT walking up the DOM also sees them.\n * Resolved-element text is also flattened onto the inner input as\n * `aria-label` so AT that does NOT walk up still announces the right\n * name.\n *\n * 2. **Legacy fallback** (`_supportsIdrefRefs === false`): the resolved-\n * element text is flattened onto the inner input as `aria-label` and\n * mirrored into a synthesized in-shadow span pointed at by the inner\n * input's `aria-describedby`.\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.\n * @internal\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. Still derive `_invalid` so\n // `aria-invalid` first-paint is correct once the input renders.\n const isInvalidEarly = !internals.validity.valid || !!(this.error || this._hasErrorSlot);\n if (this._invalid !== isInvalidEarly) this._invalid = isInvalidEarly;\n return;\n }\n\n const liveAriaLabel = this.getAttribute('aria-label');\n const hostAriaLabel = liveAriaLabel !== null ? liveAriaLabel.trim() || '' : '';\n\n const internalLabel = this.shadowRoot?.getElementById(this._labelId) ?? null;\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 const liveLabelledBy = this.getAttribute('aria-labelledby');\n this._consumerLabelledBy = liveLabelledBy;\n const liveDescribedBy = this.getAttribute('aria-describedby');\n this._consumerDescribedBy = liveDescribedBy;\n\n const consumerLabelEls = resolveIdrefTokens(this, this._consumerLabelledBy);\n const hasEffectiveLabelledBy = consumerLabelEls.length > 0;\n\n const consumerDescEls = resolveIdrefTokens(this, this._consumerDescribedBy);\n\n // Observe in-place text mutations on the resolved external IDREF targets.\n this._installExternalRefsObserver([...consumerLabelEls, ...consumerDescEls]);\n\n const hasError = !!(this.error || this._hasErrorSlot);\n\n // `aria-invalid` reflects EVERY signal the consumer can use to express\n // invalidity: `setValidity()` (required-empty), explicit `error` property,\n // and slotted error content.\n const isInvalid = !internals.validity.valid || hasError;\n if (this._invalid !== isInvalid) this._invalid = isInvalid;\n\n // `accessibleLabel` is the canonical AT name when explicitly set; it\n // outranks visible label / aria-labelledby per the helix override.\n const explicitAccessibleLabel =\n typeof this.accessibleLabel === 'string' && this.accessibleLabel.trim().length > 0\n ? this.accessibleLabel\n : null;\n\n // Top-level `aria-hidden=\"true\"` / `hidden` elements MUST NOT be forwarded\n // to `internals.ariaLabelledByElements` / `ariaDescribedByElements`.\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 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 labelElsForInternals.push(...slottedLabelEls.filter(isVisibleForAccName));\n } else if (this._labelSource === 'string' && internalLabel) {\n labelElsForInternals.push(internalLabel);\n }\n }\n }\n\n const descElsForInternals: Element[] = [...consumerDescEls.filter(isVisibleForAccName)];\n if (helpEl && !hasError && 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 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 // Forward `accessibleLabel` to `internals.ariaLabel` when set; CLEAR\n // with `null` (NOT `''`) when absent, because per W3C AccName an empty\n // `aria-label` STILL outranks `aria-labelledby` and would erase the\n // name resolved from element references / fallbacks.\n if (explicitAccessibleLabel) {\n internals.ariaLabel = explicitAccessibleLabel;\n } else {\n internals.ariaLabel = null;\n }\n }\n\n // ─── Compute the inner input's accessible name (text-flatten path) ───\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\n // Precedence (per AccName 1.2 §4.3.1 with helix override):\n // 1. accessibleLabel (helix-specific override)\n // 2. consumer aria-labelledby resolves → text-flatten\n // 3. consumer aria-label on the host\n // 4. slotted label → text content (NEVER cross-shadow id reference)\n // 5. label property → internal `<label>` id (same shadow root)\n // 6. else: unnamed\n let labelledByFlat = '';\n if (!explicitAccessibleLabel && hasEffectiveLabelledBy) {\n labelledByFlat = flattenText(consumerLabelEls);\n }\n if (explicitAccessibleLabel) {\n inputAriaLabel = explicitAccessibleLabel;\n } else if (labelledByFlat) {\n inputAriaLabel = labelledByFlat;\n } else if (hostAriaLabel) {\n inputAriaLabel = hostAriaLabel;\n } else if (this._labelSource === 'slot') {\n // Light-DOM ids do not resolve from inside a shadow root, so we MUST\n // text-flatten on the legacy/fallback path.\n if (this._labelSlotText) {\n inputAriaLabel = this._labelSlotText;\n } else if (slottedLabelEls.length > 0) {\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 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 // Unify ALL descriptions through a single `aria-describedby` channel.\n // The W3C AccName algorithm ignores `aria-description` whenever\n // `aria-describedby` is also present, so consumer descriptions are\n // mirrored into a synthesized in-shadow span and that same-root id is\n // added to the chain.\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._hasHelpSlot) {\n describedByIds.push(this._helpTextId);\n }\n if (errorEl && hasError) {\n describedByIds.push(this._errorId);\n }\n // The component's own helpText property renders an in-shadow help div;\n // chain that id when no slotted help is present (it's the same id and\n // the fallback content lives in the same div).\n if (\n !this._hasHelpSlot &&\n this.helpText &&\n !hasError &&\n helpEl &&\n !describedByIds.includes(this._helpTextId)\n ) {\n describedByIds.push(this._helpTextId);\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 // Never write `aria-description` on the inner input — silently dropped by\n // AccName whenever `aria-describedby` is also present. Strip defensively.\n if (input.hasAttribute('aria-description')) {\n input.removeAttribute('aria-description');\n }\n }\n\n /**\n * (Re-)installs the help-text slot text/visibility observer.\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 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 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 error slot text/visibility observer.\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 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 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 /**\n * (Re-)installs the label slot text/visibility observer over the current\n * set of slotted label elements.\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 const fragments: string[] = [];\n for (const el of elements) {\n if (el.getAttribute('aria-hidden') === 'true') continue;\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 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 // ─── Slot Change Handlers ───\n\n /** @internal */\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 // Preserve back-compat: if the first slotted label element lacks an id,\n // assign a stable one — earlier callers relied on this for `for=…`-style\n // associations.\n if (state.elements.length > 0) {\n const slottedLabel = state.elements[0];\n if (slottedLabel && !slottedLabel.id) {\n slottedLabel.id = `${this._inputId}-slotted-label`;\n }\n }\n this._installLabelSlotTextObserver(state.elements);\n this._refreshLabelSource();\n this._syncHostAriaSemantics();\n }\n\n /** @internal */\n private _handleErrorSlotChange(e: Event): void {\n if (!(e.target instanceof HTMLSlotElement)) return;\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 this._hasHelpSlot = this._readHelpSlotStateSync(e.target);\n this._installHelpSlotTextObserver(e.target);\n this._syncHostAriaSemantics();\n }\n\n // ─── Document Click ───\n\n private readonly _handleDocumentClick = (e: MouseEvent): void => {\n if (!this._isOpen) return;\n const path = e.composedPath();\n if (!path.includes(this)) {\n this._closeCalendar();\n }\n };\n\n // ─── Form Integration ───\n\n /** @internal */\n override _updateValidity(): void {\n if (this.required && !this.value) {\n this._internals.setValidity(\n { valueMissing: true },\n this.error || this.requiredMessage,\n this._input,\n );\n } else {\n this._internals.setValidity({});\n }\n // Re-sync ARIA after every setValidity() so `aria-invalid` reflects\n // freshly computed validity.\n this._syncHostAriaSemantics();\n }\n\n /** @internal */\n protected override _onFormReset(): void {\n this.value = '';\n this._internals.setFormValue(null);\n this._isOpen = false;\n this._resetInteractionState();\n }\n\n /** @internal */\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 // ─── Public Methods ───\n\n override focus(options?: FocusOptions): void {\n this._trigger?.focus(options);\n }\n\n // ─── Date Utilities ───\n\n /** @internal */\n private _parseISODate(iso: string): Date | null {\n if (!iso) return null;\n const d = new Date(iso + 'T00:00:00');\n return isNaN(d.getTime()) ? null : d;\n }\n\n /** @internal */\n private _toISO(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, '0');\n const d = String(date.getDate()).padStart(2, '0');\n return `${y}-${m}-${d}`;\n }\n\n /** @internal */\n private _formatForDisplay(iso: string): string {\n const date = this._parseISODate(iso);\n if (!date) return '';\n return date.toLocaleDateString(this.locale, {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n });\n }\n\n /** @internal */\n private _isDateDisabled(date: Date): boolean {\n const iso = this._toISO(date);\n if (this.min && iso < this.min) return true;\n if (this.max && iso > this.max) return true;\n return false;\n }\n\n /** @internal */\n private _isSameDay(a: Date, b: Date): boolean {\n return (\n a.getFullYear() === b.getFullYear() &&\n a.getMonth() === b.getMonth() &&\n a.getDate() === b.getDate()\n );\n }\n\n /** @internal */\n private _isToday(date: Date): boolean {\n return this._isSameDay(date, new Date());\n }\n\n /** @internal */\n private _ensureFormatters(): void {\n if (this._formatterLocale === this.locale && this._weekdayFormatter && this._monthFormatter) {\n return;\n }\n this._weekdayFormatter = new Intl.DateTimeFormat(this.locale, { weekday: 'short' });\n this._monthFormatter = new Intl.DateTimeFormat(this.locale, { month: 'long' });\n this._formatterLocale = this.locale;\n this._cachedWeekdayNames = null;\n }\n\n /** @internal */\n private _getMonthName(month: number): string {\n this._ensureFormatters();\n const fmt = this._monthFormatter ?? new Intl.DateTimeFormat(this.locale, { month: 'long' });\n return fmt.format(new Date(2000, month, 1));\n }\n\n /** @internal */\n private _getDayName(dayIndex: number): string {\n this._ensureFormatters();\n const fmt =\n this._weekdayFormatter ?? new Intl.DateTimeFormat(this.locale, { weekday: 'short' });\n return fmt.format(new Date(2000, 0, 2 + dayIndex));\n }\n\n /** @internal */\n private _getWeekdayNames(): string[] {\n this._ensureFormatters();\n if (!this._cachedWeekdayNames) {\n this._cachedWeekdayNames = Array.from({ length: 7 }, (_, i) => this._getDayName(i));\n }\n return this._cachedWeekdayNames;\n }\n\n // ─── Calendar Grid ───\n\n /** @internal */\n private _getDaysInGrid(): (Date | null)[] {\n const firstOfMonth = new Date(this._viewYear, this._viewMonth, 1);\n const leadingBlanks = firstOfMonth.getDay(); // 0=Sun\n const daysInMonth = new Date(this._viewYear, this._viewMonth + 1, 0).getDate();\n\n const cells: (Date | null)[] = [];\n\n for (let i = 0; i < leadingBlanks; i++) {\n cells.push(null);\n }\n\n for (let d = 1; d <= daysInMonth; d++) {\n cells.push(new Date(this._viewYear, this._viewMonth, d));\n }\n\n const remainder = cells.length % 7;\n if (remainder !== 0) {\n for (let i = 0; i < 7 - remainder; i++) {\n cells.push(null);\n }\n }\n\n return cells;\n }\n\n // ─── Calendar Open/Close ───\n\n /** @internal */\n private _openCalendar(): void {\n if (this.disabled) return;\n this._isOpen = true;\n }\n\n /** @internal */\n private _closeCalendar(): void {\n this._isOpen = false;\n void this.updateComplete.then(() => {\n this._trigger?.focus();\n });\n }\n\n /** @internal */\n private _toggleCalendar(): void {\n if (this._isOpen) {\n this._closeCalendar();\n } else {\n this._openCalendar();\n }\n }\n\n // ─── Focus Management ───\n\n /** @internal */\n private _focusActiveDay(): void {\n if (!this._calendar) return;\n\n const selectedISO = this.value;\n const selected = this._parseISODate(selectedISO);\n\n let targetDay: number | null = null;\n\n if (\n selected &&\n selected.getFullYear() === this._viewYear &&\n selected.getMonth() === this._viewMonth\n ) {\n targetDay = selected.getDate();\n } else {\n const today = new Date();\n if (today.getFullYear() === this._viewYear && today.getMonth() === this._viewMonth) {\n const todayDate = new Date(this._viewYear, this._viewMonth, today.getDate());\n if (!this._isDateDisabled(todayDate)) {\n targetDay = today.getDate();\n }\n }\n }\n\n if (targetDay === null) {\n const daysInMonth = new Date(this._viewYear, this._viewMonth + 1, 0).getDate();\n for (let d = 1; d <= daysInMonth; d++) {\n const date = new Date(this._viewYear, this._viewMonth, d);\n if (!this._isDateDisabled(date)) {\n targetDay = d;\n break;\n }\n }\n }\n\n if (targetDay !== null) {\n this._focusedDay = targetDay;\n void this.updateComplete.then(() => {\n const btn = this._calendar?.querySelector<HTMLButtonElement>(`[data-day=\"${targetDay}\"]`);\n btn?.focus();\n });\n }\n }\n\n // ─── Month Navigation ───\n\n /** @internal */\n private _prevMonth(): void {\n if (this._viewMonth === 0) {\n this._viewMonth = 11;\n this._viewYear = this._viewYear - 1;\n } else {\n this._viewMonth = this._viewMonth - 1;\n }\n }\n\n /** @internal */\n private _nextMonth(): void {\n if (this._viewMonth === 11) {\n this._viewMonth = 0;\n this._viewYear = this._viewYear + 1;\n } else {\n this._viewMonth = this._viewMonth + 1;\n }\n }\n\n // ─── Day Selection ───\n\n /** @internal */\n private _selectDay(date: Date): void {\n if (this._isDateDisabled(date)) return;\n\n const iso = this._toISO(date);\n this.value = iso;\n this._internals.setFormValue(iso);\n this._handleInteractionInput();\n this._handleInteractionBlur();\n\n this.dispatchEvent(\n new CustomEvent<{ value: string; date: Date }>('hx-change', {\n bubbles: true,\n composed: true,\n detail: { value: iso, date },\n }),\n );\n\n this._closeCalendar();\n }\n\n /** @internal */\n private readonly _handleGridClick = (e: Event): void => {\n const target = (e.target as Element).closest<HTMLElement>('[data-date]');\n if (!target) return;\n const iso = target.dataset['date'];\n if (!iso) return;\n const date = this._parseISODate(iso);\n if (date) {\n this._selectDay(date);\n }\n };\n\n // ─── Calendar Keyboard Navigation ───\n\n /** @internal */\n private _handleCalendarKeydown(e: KeyboardEvent): void {\n const { key } = e;\n\n if (key === 'Tab') {\n this._handleCalendarTab(e);\n return;\n }\n\n if (key === 'Escape') {\n e.stopPropagation();\n this._closeCalendar();\n return;\n }\n\n if (\n key !== 'ArrowLeft' &&\n key !== 'ArrowRight' &&\n key !== 'ArrowUp' &&\n key !== 'ArrowDown' &&\n key !== 'Enter' &&\n key !== ' ' &&\n key !== 'Home' &&\n key !== 'End' &&\n key !== 'PageUp' &&\n key !== 'PageDown'\n ) {\n return;\n }\n\n e.preventDefault();\n\n const currentFocused = this._focusedDay ?? 1;\n const daysInMonth = new Date(this._viewYear, this._viewMonth + 1, 0).getDate();\n\n if (key === 'Enter' || key === ' ') {\n const date = new Date(this._viewYear, this._viewMonth, currentFocused);\n if (!this._isDateDisabled(date)) {\n this._selectDay(date);\n }\n return;\n }\n\n if (key === 'PageUp') {\n this._prevMonth();\n return;\n }\n\n if (key === 'PageDown') {\n this._nextMonth();\n return;\n }\n\n if (key === 'Home') {\n const currentDate = new Date(this._viewYear, this._viewMonth, currentFocused);\n const dayOfWeek = currentDate.getDay();\n const newDay = currentFocused - dayOfWeek;\n if (newDay >= 1) {\n this._focusedDay = newDay;\n void this.updateComplete.then(() => {\n this._calendar?.querySelector<HTMLButtonElement>(`[data-day=\"${newDay}\"]`)?.focus();\n });\n }\n return;\n }\n\n if (key === 'End') {\n const currentDate = new Date(this._viewYear, this._viewMonth, currentFocused);\n const dayOfWeek = currentDate.getDay();\n const daysToSaturday = 6 - dayOfWeek;\n const newDay = currentFocused + daysToSaturday;\n if (newDay <= daysInMonth) {\n this._focusedDay = newDay;\n void this.updateComplete.then(() => {\n this._calendar?.querySelector<HTMLButtonElement>(`[data-day=\"${newDay}\"]`)?.focus();\n });\n }\n return;\n }\n\n let newDay = currentFocused;\n\n if (key === 'ArrowLeft') newDay = currentFocused - 1;\n if (key === 'ArrowRight') newDay = currentFocused + 1;\n if (key === 'ArrowUp') newDay = currentFocused - 7;\n if (key === 'ArrowDown') newDay = currentFocused + 7;\n\n if (newDay < 1) {\n this._prevMonth();\n const prevDaysInMonth = new Date(this._viewYear, this._viewMonth + 1, 0).getDate();\n this._focusedDay = prevDaysInMonth + newDay;\n void this.updateComplete.then(() => {\n const day = this._focusedDay;\n this._calendar?.querySelector<HTMLButtonElement>(`[data-day=\"${day}\"]`)?.focus();\n });\n return;\n }\n\n if (newDay > daysInMonth) {\n const overflow = newDay - daysInMonth;\n this._nextMonth();\n this._focusedDay = overflow;\n void this.updateComplete.then(() => {\n const day = this._focusedDay;\n this._calendar?.querySelector<HTMLButtonElement>(`[data-day=\"${day}\"]`)?.focus();\n });\n return;\n }\n\n this._focusedDay = newDay;\n void this.updateComplete.then(() => {\n this._calendar?.querySelector<HTMLButtonElement>(`[data-day=\"${newDay}\"]`)?.focus();\n });\n }\n\n // ─── Navigation Boundary Checks ───\n\n /** @internal */\n private _isPrevMonthDisabled(): boolean {\n if (!this.min) return false;\n const firstOfCurrentView = new Date(this._viewYear, this._viewMonth, 1);\n const minDate = this._parseISODate(this.min);\n if (!minDate) return false;\n return firstOfCurrentView <= minDate;\n }\n\n /** @internal */\n private _isNextMonthDisabled(): boolean {\n if (!this.max) return false;\n const lastOfCurrentView = new Date(this._viewYear, this._viewMonth + 1, 0);\n const maxDate = this._parseISODate(this.max);\n if (!maxDate) return false;\n return lastOfCurrentView >= maxDate;\n }\n\n // ─── Focus Trap ───\n\n /** @internal */\n private _handleCalendarTab(e: KeyboardEvent): void {\n if (e.key !== 'Tab' || !this._isOpen) return;\n\n const focusableEls = this._calendar?.querySelectorAll<HTMLElement>(\n 'button:not([disabled]), [tabindex=\"0\"]',\n );\n if (!focusableEls || focusableEls.length === 0) return;\n\n const first = focusableEls[0];\n const last = focusableEls[focusableEls.length - 1];\n\n // In shadow DOM, document.activeElement returns the host element, not the\n // focused inner element. Use shadowRoot.activeElement exclusively so the\n // comparison is accurate and the trap cannot malfunction and strand users.\n const shadowActive = this.shadowRoot?.activeElement;\n\n if (e.shiftKey) {\n if (shadowActive === first) {\n e.preventDefault();\n last?.focus();\n }\n } else {\n if (shadowActive === last) {\n e.preventDefault();\n first?.focus();\n }\n }\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderWeekdayHeaders() {\n const names = this._getWeekdayNames();\n const headers = names.map(\n (name) =>\n html`<div class=\"calendar__weekday\" role=\"columnheader\" aria-label=${name}>\n ${name.slice(0, 2)}\n </div>`,\n );\n return html`<div class=\"calendar__row\" role=\"row\">${headers}</div>`;\n }\n\n /** @internal */\n private _renderDayGrid() {\n const cells = this._dayGrid;\n const selectedDate = this._parseISODate(this.value);\n const today = new Date();\n\n const rows: ReturnType<typeof html>[] = [];\n\n for (let rowStart = 0; rowStart < cells.length; rowStart += 7) {\n const rowCells = cells.slice(rowStart, rowStart + 7).map((date) => {\n if (date === null) {\n return html`<div class=\"calendar__day-cell\" role=\"gridcell\" aria-hidden=\"true\"></div>`;\n }\n\n const isSelected = selectedDate ? this._isSameDay(date, selectedDate) : false;\n const isToday = this._isSameDay(date, today);\n const isDisabled = this._isDateDisabled(date);\n const isFocused = this._focusedDay === date.getDate();\n const dayNumber = date.getDate();\n const iso = this._toISO(date);\n const ariaLabel = this._dayAriaLabels.get(iso) ?? iso;\n\n const dayClasses = {\n calendar__day: true,\n 'calendar__day--selected': isSelected,\n 'calendar__day--today': isToday,\n 'calendar__day--disabled': isDisabled,\n };\n\n return html`<div\n class=\"calendar__day-cell\"\n role=\"gridcell\"\n aria-selected=${isSelected ? 'true' : 'false'}\n aria-disabled=${isDisabled ? 'true' : nothing}\n aria-current=${isToday ? 'date' : nothing}\n >\n <button\n part=\"day\"\n class=${classMap(dayClasses)}\n type=\"button\"\n data-day=${dayNumber}\n data-date=${iso}\n aria-label=${ariaLabel}\n tabindex=${isFocused ? '0' : '-1'}\n ?disabled=${isDisabled}\n >\n ${dayNumber}\n </button>\n </div>`;\n });\n\n rows.push(html`<div class=\"calendar__row\" role=\"row\">${rowCells}</div>`);\n }\n\n return rows;\n }\n\n // ─── Render ───\n\n override render() {\n const hasError = !!this.error || this._hasErrorSlot;\n const displayValue = this._formatForDisplay(this.value);\n const monthName = this._getMonthName(this._viewMonth);\n\n const fieldClasses = {\n field: true,\n 'field--error': hasError,\n 'field--disabled': this.disabled,\n 'field--required': this.required,\n };\n\n return html`\n <div part=\"field\" class=${classMap(fieldClasses)}>\n <!-- Label -->\n <div class=\"field__label-wrapper\">\n <slot name=\"label\" @slotchange=${this._handleLabelSlotChange}>\n ${this.label\n ? html`\n <label part=\"label\" id=${this._labelId} class=\"field__label\" for=${this._inputId}>\n ${this.label}\n ${this.required\n ? html`<span class=\"field__required-marker\" aria-hidden=\"true\">*</span>`\n : nothing}\n </label>\n `\n : nothing}\n </slot>\n </div>\n\n <!-- Input + Trigger -->\n <!--\n W3C APG date picker dialog pattern: the inner input is a readonly\n text input, NOT a combobox. Users do not type — they open the dialog\n via the trigger button (or by clicking the input). The trigger button\n owns aria-expanded and aria-controls (pointed at the in-shadow\n calendar id) for the dialog. Cross-shadow aria-controls referencing\n an in-shadow id is a documented limitation and matches the precedent\n set by hx-popover and hx-dropdown.\n -->\n <div part=\"input-wrapper\" class=\"field__input-wrapper\">\n <input\n part=\"input\"\n class=\"field__input\"\n id=${this._inputId}\n type=\"text\"\n readonly\n .value=${displayValue}\n placeholder=${ifDefined(this.format || undefined)}\n ?disabled=${this.disabled}\n aria-invalid=${this._invalid ? 'true' : 'false'}\n aria-required=${this.required ? 'true' : 'false'}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-haspopup=\"dialog\"\n @click=${this._openCalendar}\n />\n <button\n part=\"trigger\"\n class=\"field__trigger\"\n type=\"button\"\n aria-label=${this._isOpen ? this.closeCalendarLabel : this.openCalendarLabel}\n aria-haspopup=\"dialog\"\n aria-expanded=${this._isOpen ? 'true' : 'false'}\n aria-controls=${this._calendarId}\n ?disabled=${this.disabled}\n @click=${this._toggleCalendar}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n focusable=\"false\"\n >\n <rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"></rect>\n <line x1=\"16\" y1=\"2\" x2=\"16\" y2=\"6\"></line>\n <line x1=\"8\" y1=\"2\" x2=\"8\" y2=\"6\"></line>\n <line x1=\"3\" y1=\"10\" x2=\"21\" y2=\"10\"></line>\n </svg>\n </button>\n </div>\n\n <!-- Calendar Popup -->\n <dialog\n part=\"calendar\"\n class=\"calendar\"\n id=${this._calendarId}\n aria-label=${this.chooseDateLabel}\n @keydown=${this._handleCalendarKeydown}\n >\n <!-- Screen reader live region -->\n <div\n id=${this._liveRegionId}\n class=\"calendar__live-region\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n >\n ${this._liveMessage}\n </div>\n\n <!-- Month Navigation -->\n <div part=\"month-nav\" class=\"calendar__nav\">\n <button\n class=\"calendar__nav-btn\"\n type=\"button\"\n aria-label=${this.previousMonthLabel}\n ?disabled=${this._isPrevMonthDisabled()}\n @click=${this._prevMonth}\n >\n &#8249;\n </button>\n <span class=\"calendar__month-label\" aria-hidden=\"true\">\n ${monthName} ${this._viewYear}\n </span>\n <button\n class=\"calendar__nav-btn\"\n type=\"button\"\n aria-label=${this.nextMonthLabel}\n ?disabled=${this._isNextMonthDisabled()}\n @click=${this._nextMonth}\n >\n &#8250;\n </button>\n </div>\n\n <!-- Day Grid -->\n <div\n class=\"calendar__grid\"\n role=\"grid\"\n aria-label=\"${monthName} ${this._viewYear}\"\n @click=${this._handleGridClick}\n >\n ${this._renderWeekdayHeaders()} ${this._renderDayGrid()}\n </div>\n </dialog>\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 <!-- Help Text -->\n <div\n part=\"help-text\"\n class=\"field__help-text\"\n id=${this._helpTextId}\n ?hidden=${(!this.helpText && !this._hasHelpSlot) || hasError}\n >\n <slot name=\"help-text\" @slotchange=${this._handleHelpSlotChange}>${this.helpText}</slot>\n </div>\n\n <!--\n Synthesized in-shadow mirror of the consumer-resolved description\n text. Its id is appended to the inner input's aria-describedby chain\n so AT picks the consumer description up through the standard\n described-by channel without needing aria-description (which W3C\n AccName drops whenever aria-describedby is also present).\n -->\n <span id=${this._consumerDescId} class=\"field__sr-only\" aria-hidden=\"false\"></span>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-date-picker': HelixDatePicker;\n }\n}\n"],"names":["helixDatePickerStyles","css","_nextDatePickerId","createIdCounter","HelixDatePicker","FormMixin","HelixElement","e","target","iso","date","ctor","supportsIdrefElementReferences","records","consumerCleared","record","oldValue","newValue","installAriaIdrefMirror","_a","_b","_c","_d","_e","_f","changedProperties","d","selected","monthName","changed","root","labelSlot","state","helpSlot","errorSlot","slot","nodes","elements","fragments","node","el","elText","flattenAccName","txt","trimmedText","unique","observer","internals","input","isInvalidEarly","liveAriaLabel","hostAriaLabel","internalLabel","slottedLabelEls","helpEl","errorEl","liveLabelledBy","liveDescribedBy","consumerLabelEls","resolveIdrefTokens","hasEffectiveLabelledBy","consumerDescEls","hasError","isInvalid","explicitAccessibleLabel","isVisibleForAccName","labelElsForInternals","descElsForInternals","refsInternals","flattenText","els","t","inputAriaLabel","inputAriaLabelledBy","labelledByFlat","flat","consumerDescSpan","consumerDescText","describedByIds","value","trimmed","slottedLabel","_mode","disabled","options","y","m","a","b","month","dayIndex","_","i","leadingBlanks","daysInMonth","cells","remainder","selectedISO","targetDay","today","todayDate","btn","key","currentFocused","dayOfWeek","newDay","daysToSaturday","prevDaysInMonth","day","overflow","firstOfCurrentView","minDate","lastOfCurrentView","maxDate","focusableEls","first","last","shadowActive","headers","name","html","selectedDate","rows","rowStart","rowCells","isSelected","isToday","isDisabled","isFocused","dayNumber","ariaLabel","nothing","classMap","displayValue","fieldClasses","ifDefined","forcedColorsField","__decorateClass","property","query","customElement"],"mappings":";;;;;;;;;;AAEO,MAAMA,IAAwBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;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 +0,0 @@
1
- {"version":3,"file":"hx-drawer-CM_upadk.js","sources":["../../src/components/hx-drawer/hx-drawer.styles.ts","../../src/components/hx-drawer/hx-drawer.ts"],"sourcesContent":["import { css } from 'lit';\n\n/**\n * hx-drawer styles.\n *\n * Component-tier tokens with two-level var() fallback:\n * var(--hx-drawer-{prop}, var(--hx-color-{semantic}, #hex))\n * Inner hex fallbacks track the \"precision cool\" palette (3.2.0):\n * neutral-0 = #FFFFFF, neutral-100 = #EBEEE9, neutral-200 = #D6DBD5,\n * neutral-500 = #66787B, neutral-800 = #202B39, neutral-900 = #0D1825,\n * primary-500 = #429797.\n */\nexport const helixDrawerStyles = css`\n /* P2-03: Explicit [hidden] rule to survive CSS resets that may override the UA stylesheet. */\n [hidden] {\n display: none !important;\n }\n\n :host {\n display: contents;\n }\n\n :host([contained]) {\n display: block;\n position: relative;\n overflow: hidden;\n }\n\n /* ─── Overlay ─── */\n\n .drawer-overlay {\n position: fixed;\n inset: 0;\n z-index: var(--hx-z-index-modal, 1400);\n display: flex;\n pointer-events: none;\n visibility: hidden;\n }\n\n :host([contained]) .drawer-overlay {\n position: absolute;\n }\n\n .drawer-overlay.is-open {\n pointer-events: auto;\n visibility: visible;\n }\n\n /* ─── Backdrop ─── */\n\n .drawer-backdrop {\n position: absolute;\n inset: 0;\n background-color: var(\n --hx-drawer-backdrop-color,\n var(--hx-color-surface-overlay, rgba(0, 0, 0, 0.75))\n );\n opacity: 0;\n transition: opacity var(--hx-duration-slow, 300ms) var(--hx-easing-out, ease-out);\n }\n\n .drawer-overlay.is-open .drawer-backdrop {\n opacity: var(--hx-drawer-backdrop-opacity, 0.5);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .drawer-backdrop {\n transition: none;\n }\n }\n\n /* ─── Panel ─── */\n\n .drawer-panel {\n position: absolute;\n display: flex;\n flex-direction: column;\n background-color: var(--hx-drawer-bg, var(--hx-color-surface-default, #ffffff));\n color: var(--hx-drawer-color, var(--hx-color-text-primary, #0d1825));\n box-shadow: var(--hx-drawer-shadow, var(--hx-shadow-xl, 0 20px 25px -5px rgb(0 0 0 / 0.1)));\n overflow: hidden;\n outline: none;\n z-index: 1; /* local stacking context: panel above backdrop within overlay container */\n transition:\n transform var(--hx-duration-slow, 300ms) var(--hx-easing-out, ease-out),\n opacity var(--hx-duration-slow, 300ms) var(--hx-easing-out, ease-out);\n opacity: 0;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .drawer-panel {\n transition: none;\n }\n\n .drawer-close-button {\n transition: none;\n }\n }\n\n /* ─── Placement: end (default — right) ─── */\n\n :host([placement='end']) .drawer-panel,\n :host(:not([placement])) .drawer-panel {\n top: 0;\n inset-inline-end: 0;\n bottom: 0;\n width: var(--_drawer-size, var(--hx-drawer-size-md, 30rem));\n max-width: 100%;\n transform: translateX(100%);\n }\n\n :host([placement='end']) .drawer-overlay.is-open .drawer-panel,\n :host(:not([placement])) .drawer-overlay.is-open .drawer-panel {\n transform: translateX(0);\n opacity: 1;\n }\n\n /* ─── Placement: start (left) ─── */\n\n :host([placement='start']) .drawer-panel {\n top: 0;\n inset-inline-start: 0;\n bottom: 0;\n width: var(--_drawer-size, var(--hx-drawer-size-md, 30rem));\n max-width: 100%;\n transform: translateX(-100%);\n }\n\n :host([placement='start']) .drawer-overlay.is-open .drawer-panel {\n transform: translateX(0);\n opacity: 1;\n }\n\n /* ─── Placement: top ─── */\n\n :host([placement='top']) .drawer-panel {\n top: 0;\n inset-inline-start: 0;\n inset-inline-end: 0;\n height: var(--_drawer-size, var(--hx-drawer-size-md, 30rem));\n max-height: 100%;\n width: 100%;\n transform: translateY(-100%);\n }\n\n :host([placement='top']) .drawer-overlay.is-open .drawer-panel {\n transform: translateY(0);\n opacity: 1;\n }\n\n /* ─── Placement: bottom ─── */\n\n :host([placement='bottom']) .drawer-panel {\n bottom: 0;\n inset-inline-start: 0;\n inset-inline-end: 0;\n height: var(--_drawer-size, var(--hx-drawer-size-md, 30rem));\n max-height: 100%;\n width: 100%;\n transform: translateY(100%);\n }\n\n :host([placement='bottom']) .drawer-overlay.is-open .drawer-panel {\n transform: translateY(0);\n opacity: 1;\n }\n\n /* ─── Header ─── */\n\n .drawer-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--hx-space-4, 1rem);\n padding: var(--hx-drawer-header-padding, var(--hx-space-5, 1.25rem) var(--hx-space-6, 1.5rem));\n border-bottom: var(--hx-border-width-thin, 1px) solid\n var(--hx-drawer-header-border-color, var(--hx-color-border-default, #d6dbd5));\n flex-shrink: 0;\n }\n\n .drawer-title {\n margin: 0;\n flex: 1 1 auto;\n font-family: var(--hx-drawer-font-family, var(--hx-font-family-sans, sans-serif));\n font-size: var(--hx-font-size-lg, 1.125rem);\n font-weight: var(--hx-font-weight-semibold, 600);\n line-height: var(--hx-line-height-tight, 1.25);\n color: var(--hx-drawer-title-color, var(--hx-color-text-primary, #0d1825));\n }\n\n .drawer-header-actions {\n display: flex;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n flex-shrink: 0;\n }\n\n .drawer-close-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n /* WCAG 2.5.5 (healthcare mandate): minimum 44x44px touch target */\n min-width: var(--hx-touch-target-min, 2.75rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n width: var(--hx-touch-target-min, 2.75rem);\n height: var(--hx-touch-target-min, 2.75rem);\n padding: 0;\n border: none;\n border-radius: var(--hx-border-radius-md, 0.375rem);\n background: transparent;\n color: var(--hx-drawer-close-btn-color, var(--hx-color-text-muted, #4a5362));\n cursor: pointer;\n flex-shrink: 0;\n transition: background-color var(--hx-duration-fast, 100ms) var(--hx-easing-default, ease);\n }\n\n .drawer-close-button:hover {\n background-color: var(--hx-drawer-close-btn-hover-bg, var(--hx-color-surface-sunken, #ebeee9));\n color: var(--hx-drawer-close-btn-hover-color, var(--hx-color-text-primary, #0d1825));\n }\n\n .drawer-close-button:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-drawer-close-btn-focus-ring-color, var(--hx-focus-ring-color, #0f7078));\n outline-offset: var(--hx-focus-ring-offset, 2px);\n }\n\n /* ─── Visually-hidden close button (no-header mode, WCAG 4.1.2) ─── */\n /* Keeps the button reachable by keyboard/AT but invisible to sighted users. */\n\n .drawer-close-button--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\n /* When focused via keyboard, restore visibility so users know where focus is. */\n .drawer-close-button--sr-only:focus-visible {\n position: static;\n width: auto;\n height: auto;\n clip: auto;\n white-space: normal;\n overflow: visible;\n margin: 0;\n }\n\n /* ─── Synthesized consumer-description span ─── */\n /* Visually hidden mirror of consumer-resolved aria-describedby text used by */\n /* the host-canonical ARIA pipeline. Always present in the shadow tree so AT */\n /* can resolve the same-root id even when the description is currently empty. */\n\n .drawer-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\n /* ─── Body ─── */\n\n .drawer-body {\n flex: 1 1 auto;\n padding: var(--hx-drawer-body-padding, var(--hx-space-6, 1.5rem));\n overflow-y: auto;\n overscroll-behavior: contain;\n }\n\n /* ─── Footer ─── */\n\n .drawer-footer {\n display: flex;\n align-items: center;\n justify-content: flex-end;\n gap: var(--hx-space-3, 0.75rem);\n padding: var(--hx-drawer-footer-padding, var(--hx-space-4, 1rem) var(--hx-space-6, 1.5rem));\n border-top: var(--hx-border-width-thin, 1px) solid\n var(--hx-drawer-footer-border-color, var(--hx-color-border-default, #d6dbd5));\n flex-shrink: 0;\n }\n\n /* ─── Forced Colors (Windows High Contrast) ─── */\n\n @media (forced-colors: active) {\n .drawer-panel {\n border: 1px solid CanvasText;\n }\n\n .drawer-header {\n border-bottom-color: CanvasText;\n }\n\n .drawer-footer {\n border-top-color: CanvasText;\n }\n\n .drawer-close-button {\n color: ButtonText;\n border: 1px solid ButtonText;\n }\n }\n`;\n","import { html, nothing, type PropertyValues } from 'lit';\nimport '../../utilities/document-token-adoption.js';\nimport { customElement, property, query, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { lockBodyScroll, unlockBodyScroll } from '../../utils/body-scroll-lock.js';\nimport { devWarn } from '../../utils/dev-warn.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { helixDrawerStyles } from './hx-drawer.styles.js';\nimport { forcedColorsSurface } from '../../styles/forced-colors.js';\nimport { flattenAccName } from '../../utils/aria-flatten.js';\nimport {\n installAriaIdrefMirror,\n resolveIdrefTokens,\n supportsIdrefElementReferences,\n type AriaIdrefMirrorHandle,\n} from '../../utils/aria-idref.js';\n\nconst _nextDrawerId = createIdCounter('hx-drawer');\n\ntype DrawerSizePreset = 'sm' | 'md' | 'lg' | 'full';\ntype DrawerSize = DrawerSizePreset | (string & Record<never, never>);\n\nconst DRAWER_SIZE_MAP: Record<DrawerSizePreset, string> = {\n sm: '20rem',\n md: '30rem',\n lg: '40rem',\n full: '100%',\n};\n\nconst FOCUSABLE_SELECTORS = [\n 'a[href]',\n 'area[href]',\n 'button:not([disabled])',\n 'input:not([disabled])',\n 'select:not([disabled])',\n 'textarea:not([disabled])',\n '[tabindex]:not([tabindex=\"-1\"])',\n 'details > summary',\n].join(',');\n\n/**\n * A slide-in drawer panel that can appear from any edge of the viewport.\n * Supports focus trapping, overlay backdrop, keyboard navigation, and full\n * ARIA labelling for enterprise healthcare accessibility requirements.\n *\n * ## Architecture Note: Host-Canonical ARIA (group-4 round-1, Path A)\n *\n * The host carries the announced dialog semantics via `ElementInternals`:\n *\n * - `internals.role = 'dialog'` (the host IS the dialog surface)\n * - `internals.ariaModal = 'true'` (modality declared on host)\n * - `internals.ariaLabelledByElements` / `internals.ariaDescribedByElements`\n * project consumer light-DOM IDREFs across the shadow boundary.\n * - `internals.ariaLabel` carries the resolved fallback name when no\n * IDREF chain or slotted title exists.\n *\n * The inner `<div part=\"overlay\">` no longer carries `role`, `aria-modal`,\n * `aria-labelledby`, or `aria-label` — those would create a nested-dialog\n * announcement above the host's canonical surface. Belt-and-suspenders\n * fallback: when the runtime does NOT expose IDL element references on\n * `ElementInternals` (older Firefox / Safari builds), the resolved label\n * text is text-flattened and written to the inner overlay's `aria-label`\n * so AT walking down from the host still finds an announceable name.\n *\n * Naming precedence (W3C AccName 1.2 §4.3.1):\n *\n * 1. Consumer `aria-labelledby` on the host — IDREFs resolved across the\n * shadow boundary via `resolveIdrefTokens` (same scope walk used by\n * every host-canonical hx-* control: own root → ancestor shadow hosts\n * → owner document → slot owners).\n * 2. Consumer `aria-label` on the host.\n * 3. `<slot name=\"label\">` text content (multi-node aggregation per\n * AccName 1.2 §4.3.10 — decorative `aria-hidden` / `[hidden]` subtrees\n * contribute zero to the name).\n * 4. `label` property — explicit author fallback string.\n * 5. Hard-coded literal `\"Drawer\"` (last-resort accessible name).\n *\n * Description channel: a synthesized `<span id=\"${id}-consumer-desc\">` is\n * rendered inside the shadow root and updated to mirror consumer-resolved\n * description text. The host's `internals.ariaDescribedByElements` carries\n * the live element references on the modern path; the in-shadow span is the\n * fallback target for AT that does not walk IDL refs. `aria-description` is\n * intentionally NEVER written — the W3C AccName algorithm ignores it\n * whenever `aria-describedby` is also present.\n *\n * Slot mutation observers track:\n * 1. The label slot's text content (in-place i18n re-renders).\n * 2. Consumer-resolved external IDREF targets (so a consumer mutating\n * `<label id=\"x\">Patient</label>` in place re-flows the name).\n * 3. Host attribute mutations (delegated to `installAriaIdrefMirror`,\n * which also catches late-inserted IDREF targets and id renames in\n * every relevant root).\n *\n * Focus trap, ESC dismiss, focus-restore, and the inert-outside-content\n * sibling-walk are unchanged from the pre-host-canonical implementation —\n * they operate against the shadow-internal panel which is still the focus\n * target for keyboard users.\n *\n * ## Architecture Note: Native `<dialog>` Migration\n *\n * This component currently uses `role=\"dialog\"` + `aria-modal=\"true\"` on a\n * `<div>` rather than the native `<dialog>` element. This is intentional for\n * the current release because:\n *\n * 1. **SSR compatibility**: Native `<dialog>` requires `showModal()` to activate\n * its modal behavior (focus trapping, backdrop, top-layer). This JavaScript\n * call is not available during server-side rendering, which is a primary\n * consumption pattern for Drupal/Twig templates.\n *\n * 2. **Contained mode**: The `contained` property constrains the drawer to a\n * positioned parent. Native `<dialog>` in modal mode renders in the top layer\n * and cannot be constrained to a parent element.\n *\n * 3. **Animation control**: The current CSS transition approach provides precise\n * control over slide-in/slide-out animations. Native `<dialog>` `::backdrop`\n * animations have inconsistent cross-browser support.\n *\n * Migration to native `<dialog>` is tracked as a future enhancement. When browser\n * support for `CloseWatcher`, `::backdrop` transitions, and declarative dialog\n * opening stabilizes, this component will be migrated to native semantics.\n *\n * @summary Slide-in panel overlay from any viewport edge.\n *\n * @tag hx-drawer\n *\n * @slot label - The drawer title text.\n * @slot header-actions - Action buttons displayed in the header near the close button.\n * @slot - Default slot for the drawer body content.\n * @slot footer - Action buttons or footer content.\n *\n * @fires {CustomEvent<void>} hx-show - Fired when the drawer begins to open.\n * @fires {CustomEvent<void>} hx-after-show - Fired after the drawer open animation completes.\n * @fires {CustomEvent<void>} hx-hide - Fired when the drawer begins to close.\n * @fires {CustomEvent<void>} hx-after-hide - Fired after the drawer close animation completes.\n * @fires {CustomEvent<void>} hx-initial-focus - Fired when initial focus is set inside the drawer. Cancelable to override focus behavior.\n *\n * **Event naming rationale:** hx-drawer uses the `hx-show`/`hx-hide`/`hx-after-show`/`hx-after-hide`\n * pattern shared by all overlay components (hx-popover, hx-tooltip, hx-dropdown). This differs from\n * hx-dialog's `hx-open`/`hx-close`/`hx-cancel` events, which align with native `<dialog>` semantics.\n * The distinction is intentional: overlays are transient visibility toggles, while dialog is a stateful\n * container with cancel semantics.\n *\n * @csspart overlay - The full-screen overlay container (includes backdrop and panel).\n * @csspart panel - The drawer panel itself.\n * @csspart header - The header region containing the title and actions.\n * @csspart title - The drawer title element.\n * @csspart close-button - The built-in close button.\n * @csspart close-btn - The visually-hidden close button rendered when noHeader is true.\n * @csspart body - The scrollable body region.\n * @csspart footer - The footer region.\n *\n * @attr [label] - Accessible label for the dialog when no visible label slot is provided.\n *\n * @cssprop [--hx-drawer-bg=var(--hx-color-neutral-0)] - Drawer panel background color.\n * @cssprop [--hx-drawer-color=var(--hx-color-neutral-900)] - Drawer panel text color.\n * @cssprop [--hx-drawer-shadow=var(--hx-shadow-xl)] - Drawer panel box shadow.\n * @cssprop [--hx-drawer-backdrop-color=var(--hx-color-neutral-900)] - Backdrop color.\n * @cssprop [--hx-drawer-backdrop-opacity=0.5] - Backdrop opacity.\n * @cssprop [--hx-drawer-header-padding] - Padding inside the header.\n * @cssprop [--hx-drawer-header-border-color=var(--hx-color-neutral-200)] - Header border color.\n * @cssprop [--hx-drawer-title-color=var(--hx-color-neutral-900)] - Title text color.\n * @cssprop [--hx-drawer-body-padding] - Padding inside the body.\n * @cssprop [--hx-drawer-footer-padding] - Padding inside the footer.\n * @cssprop [--hx-drawer-footer-border-color=var(--hx-color-neutral-200)] - Footer border color.\n * @cssprop [--hx-z-index-modal] - Z-index layer.\n * @cssprop [--hx-color-neutral-900] - Color.\n * @cssprop [--hx-duration-slow] - Animation duration.\n * @cssprop [--hx-easing-out] - CSS custom property.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-shadow-xl] - Box shadow.\n * @cssprop [--hx-drawer-size-md=30rem] - CSS custom property.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-space-5] - Spacing token.\n * @cssprop [--hx-space-6] - Spacing token.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-drawer-font-family=var(--hx-font-family-sans)] - CSS custom property.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-font-size-lg] - Font size.\n * @cssprop [--hx-font-weight-semibold] - Font weight.\n * @cssprop [--hx-line-height-tight] - Line height.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-color-neutral-500] - Color.\n * @cssprop [--hx-duration-fast] - Animation duration.\n * @cssprop [--hx-easing-default] - CSS custom property.\n * @cssprop [--hx-color-neutral-100] - Color.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-drawer-close-btn-focus-ring-color] - Color.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-focus-ring-offset] - CSS custom property.\n * @cssprop [--hx-space-3] - Spacing token.\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-drawer/AAA-AUDIT.md\n * @keyboard-contract dismiss=Escape; trap-focus=true\n * @aria-pattern dialog\n * @aria-pattern-source https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/\n * @forced-colors-supported true\n * @stability stable\n * @since 3.7.0\n * @form-associated false\n * @theme-aware true\n * @brand-aware true\n * @drupal-sdc-eligible true\n * @react-wrapper-status complete\n * @figma-component-name hx-drawer\n * @priority-tier P0\n * @phi-handles false\n * @clinical-context none\n */\n@customElement('hx-drawer')\nexport class HelixDrawer extends HelixElement {\n static override styles = [helixDrawerStyles, forcedColorsSurface];\n\n // ─── Queries ───\n\n /**\n * Reference to the overlay element that wraps the backdrop and panel.\n * @internal\n */\n @query('.drawer-overlay')\n private _overlayEl: HTMLElement | null | undefined;\n\n /**\n * Reference to the drawer panel element used for focus management.\n * @internal\n */\n @query('.drawer-panel')\n private _panelEl: HTMLElement | null | undefined;\n\n // ─── Internal state ───\n\n /**\n * Whether the drawer is in the open state and visible to the user.\n * @internal\n */\n @state()\n private _isOpen = false;\n\n /**\n * Whether the header-actions slot has any assigned content.\n * @internal\n */\n @state()\n private _hasHeaderActionsSlot = false;\n\n /**\n * Whether the footer slot has any assigned content.\n * @internal\n */\n @state()\n private _hasFooterSlot = false;\n\n /**\n * Whether the label slot has any assigned content.\n * @internal\n */\n @state()\n private _hasLabelSlot = false;\n\n /**\n * Cached list of focusable elements within the drawer, used for focus trapping.\n * @internal\n */\n private _cachedFocusableElements: HTMLElement[] = [];\n /**\n * The element that triggered the drawer to open, restored focus when the drawer closes.\n * @internal\n */\n private _triggerElement: HTMLElement | null = null;\n /**\n * Handle for the pending animation end timeout, cleared when the drawer opens or closes again.\n * @internal\n */\n private _animationTimeout: ReturnType<typeof setTimeout> | null = null;\n /** Whether this drawer instance currently holds a body-scroll lock. */\n /** @internal */\n private _hasScrollLock = false;\n /**\n * Elements outside the drawer that were given aria-hidden during open, restored on close.\n * @internal\n */\n private _siblingAriaHiddenElements: Element[] = [];\n\n /**\n * Unique ID for the title element, used by aria-labelledby to link the dialog to its label.\n * @internal\n */\n private readonly _id = _nextDrawerId();\n /** @internal */\n private readonly _titleId = `${this._id}-title`;\n /**\n * Id of the synthesized in-shadow span that mirrors consumer-resolved\n * description text. Belt-and-suspenders: the host's\n * `internals.ariaDescribedByElements` carries the live element references\n * on the modern path; this in-shadow span is the fallback referenced via\n * `aria-describedby` on the inner overlay so AT that does not walk IDL refs\n * still finds an announceable description.\n * @internal\n */\n private readonly _consumerDescId = `${this._id}-consumer-desc`;\n\n // ─── Host-canonical ARIA state ───\n\n /**\n * Test seam: when set to `true` or `false`, overrides the platform\n * `supportsIdrefElementReferences` probe before `connectedCallback`\n * seeds `_supportsIdrefRefs`. Mirrors hx-combobox round-3 finding 4 —\n * tests must select the path BEFORE the host connects so the synthetic\n * environment matches a legacy engine. Production code MUST NOT touch\n * this field. It is `static` so the cleanup is global and obvious.\n * @internal\n */\n static __testSupportsIdrefRefsOverride: boolean | null = null;\n\n /**\n * Whether the runtime exposes IDL element references on ElementInternals.\n * Drives the modern-vs-fallback ARIA projection in `_syncHostAriaSemantics`.\n * @internal\n */\n @state() private _supportsIdrefRefs = true;\n\n /**\n * Direct references to ALL labellable elements projected into\n * `<slot name=\"label\">`. Aggregates every assigned element so composed\n * labels (e.g. `<svg slot=\"label\" aria-hidden=\"true\">…</svg><span slot=\"label\">Patient</span>`)\n * project the FULL visible label via `internals.ariaLabelledByElements`\n * while `flattenAccName` strips the decorative subtree per AccName 1.2.\n * @internal\n */\n private _slottedLabelEls: Element[] = [];\n\n /**\n * Flattened text content of the slotted label nodes, used for the no-IDL-ref\n * fallback `internals.ariaLabel` and the legacy inner-overlay `aria-label`.\n * @internal\n */\n @state() private _labelSlotText = '';\n\n /**\n * Most recently observed consumer-supplied `aria-labelledby` token list on\n * the host. Refreshed every sync via `getAttribute()` — the host attribute\n * IS the live source of truth, so `removeAttribute` is observable on the\n * next sync (it returns `null`).\n * @internal\n */\n private _consumerLabelledBy: string | null = null;\n /** @internal — see `_consumerLabelledBy`. */\n private _consumerDescribedBy: string | null = null;\n\n /**\n * Handle for the shared IDREF mirror. See `installAriaIdrefMirror()`.\n * @internal\n */\n private _ariaMirror: AriaIdrefMirrorHandle | null = null;\n\n /**\n * Watches in-place text mutations on the assigned slotted label nodes\n * (e.g. consumer i18n re-renders that mutate `textContent` instead of\n * replacing the node). `slotchange` does NOT fire on descendant text\n * mutations, so this observer is the only signal that keeps the host's\n * accessible name synchronized with the visible label.\n * @internal\n */\n private _labelSlotTextObserver: MutationObserver | null = null;\n\n /**\n * Watches in-place text / visibility mutations on consumer light-DOM\n * elements resolved from host `aria-labelledby` / `aria-describedby`.\n * Reinstalled on every sync against the deduped union of resolved\n * elements; disconnects automatically when the consumer retracts both\n * IDREF chains.\n * @internal\n */\n private _externalRefsObserver: MutationObserver | null = null;\n\n /**\n * Dedicated host observer scoped to `aria-describedby` with\n * `attributeOldValue: true`. Catches authentic consumer retraction\n * (oldValue !== null && newValue === null) so the cached baseline\n * follows the live attribute.\n * @internal\n */\n private _hostDescribedByObserver: MutationObserver | null = null;\n\n // ─── Public Properties ───\n\n /**\n * Controls whether the drawer is open.\n * @attr open\n */\n @property({ type: Boolean, reflect: true })\n open = false;\n\n /**\n * Which edge of the viewport the drawer slides in from.\n * @attr placement\n */\n @property({ type: String, reflect: true })\n placement: 'start' | 'end' | 'top' | 'bottom' = 'end';\n\n /**\n * The size of the drawer panel. Use 'sm', 'md', 'lg', 'full', or any valid CSS length.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' | 'full' | (string & Record<never, never>) = 'md';\n\n /**\n * When true, the drawer is constrained to its positioned parent instead of the viewport.\n * The host element must have `position: relative` (or the library handles it via :host).\n * @attr contained\n */\n @property({ type: Boolean, reflect: true })\n contained = false;\n\n /**\n * When true, the header (title, header-actions, close button) is hidden.\n * @attr no-header\n */\n @property({ type: Boolean, reflect: true, attribute: 'no-header' })\n noHeader = false;\n\n /**\n * When true, the footer slot is hidden.\n * @attr no-footer\n */\n @property({ type: Boolean, reflect: true, attribute: 'no-footer' })\n noFooter = false;\n\n /**\n * Accessible label for the dialog when the `label` slot is not populated.\n * When the `label` slot is used, `aria-labelledby` takes precedence.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /** Accessible label for the built-in close button. Override for localized text. */\n @property({ type: String, attribute: 'label-close' })\n labelClose = 'Close drawer';\n\n // ─── Lifecycle ───\n\n override connectedCallback(): void {\n super.connectedCallback();\n // Backward compat: accept legacy `size` attribute. When present and `hx-size`\n // is not set, map the value and emit a deprecation warning.\n const legacySize = this.getAttribute('size');\n if (legacySize !== null && !this.hasAttribute('hx-size')) {\n devWarn('hx-drawer', 'The \"size\" attribute is deprecated. Use \"hx-size\" instead.');\n this.size = legacySize as DrawerSize;\n }\n\n // Honour the static test override so synthetic environments choose the\n // path BEFORE connect runs.\n const ctor = this.constructor as typeof HelixDrawer;\n this._supportsIdrefRefs =\n ctor.__testSupportsIdrefRefsOverride !== null\n ? ctor.__testSupportsIdrefRefsOverride\n : supportsIdrefElementReferences(this._internals);\n\n // Establish host-canonical ARIA semantics BEFORE first paint. The host\n // carries `role=\"dialog\"` and `aria-modal=\"true\"` via ElementInternals,\n // but ONLY while the drawer is open — a CLOSED drawer is invisible to AT\n // and must not surface a \"modal dialog\" announcement before the consumer\n // ever flips `open`. Initial state is gated through\n // `_syncHostDialogSemantics()`, which is called from `connectedCallback`\n // (here) and on every `open` change in `updated()`.\n this._syncHostDialogSemantics();\n\n // Install the dedicated `aria-describedby` retraction observer BEFORE the\n // seeded `_syncHostAriaSemantics()` call below — mirrors hx-combobox\n // round-10 finding 1 — so authentic consumer clears propagate immediately.\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 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 its\n // dialog role + accessible name before first paint. The mirror's initial\n // sync also fires synchronously inside `installAriaIdrefMirror`.\n this._syncHostAriaSemantics();\n this._ariaMirror = installAriaIdrefMirror(this, () => {\n this._syncHostAriaSemantics();\n });\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n this._removeListeners();\n if (this._animationTimeout !== null) {\n clearTimeout(this._animationTimeout);\n }\n this._restoreBodyScroll();\n this._ariaMirror?.disconnect();\n this._ariaMirror = null;\n this._labelSlotTextObserver?.disconnect();\n this._labelSlotTextObserver = null;\n this._externalRefsObserver?.disconnect();\n this._externalRefsObserver = null;\n this._hostDescribedByObserver?.disconnect();\n this._hostDescribedByObserver = null;\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n\n if (changedProperties.has('open')) {\n // Lift role=dialog + aria-modal onto the host BEFORE the open animation\n // begins so AT announces the dialog surface as it appears; retract\n // them after close so a closed drawer is invisible to the AT tree.\n this._syncHostDialogSemantics();\n if (this.open) {\n this._openDrawer();\n } else {\n this._closeDrawer();\n }\n }\n\n if (changedProperties.has('size')) {\n this._applySizeVar();\n }\n\n // Re-sync host ARIA on every update — `label` / `_hasLabelSlot` /\n // `_slottedLabelEls` / `_labelSlotText` / consumer attributes can all\n // change between renders and the projection is the SSOT for AT.\n this._syncHostAriaSemantics();\n }\n\n override firstUpdated(changedProperties: PropertyValues<this>): void {\n super.firstUpdated(changedProperties);\n // The native `slotchange` event fires as a microtask after the initial\n // synchronous render. We deliberately do NOT proactively seed\n // `_hasLabelSlot` / `_labelSlotText` from `firstUpdated` because doing so\n // schedules an additional Lit re-render that subtly reorders the\n // promise-chain inside `_openDrawer` (`updateComplete.then(...) →\n // _isOpen = true → updateComplete.then(...) → _setInitialFocus()`). On\n // Chromium that reordering interleaves the inner `is-open` visibility\n // flip with `_setInitialFocus()` and breaks slotted-children focus for\n // consumer test code that calls `.focus()` immediately after the first\n // `updateComplete` (regression: `Focus Trap > traps forward Tab at the\n // last focusable element`). The slotchange handler runs one microtask\n // later and the `_syncHostAriaSemantics()` call from `updated()` picks\n // up the resolved state on the very next paint — close enough that AT\n // never observes the unnamed window. If a future round needs the seed\n // for a stricter timing requirement, re-introduce it here AND update the\n // open-drawer chain to await `_isOpen` activation before the focus\n // restoration test runs (likely needs an extra `updateComplete`).\n }\n\n // ─── Public Methods ───\n\n /** Opens the drawer. */\n show(): void {\n this.open = true;\n }\n\n /** Closes the drawer. */\n hide(): void {\n this.open = false;\n }\n\n // ─── Private: Size CSS variable ───\n\n /** @internal */\n private _applySizeVar(): void {\n const resolvedSize = DRAWER_SIZE_MAP[this.size as DrawerSizePreset] ?? this.size;\n this.style.setProperty('--_drawer-size', resolvedSize);\n }\n\n // ─── Private: Open / Close ───\n\n /** @internal */\n private _lockBodyScroll(): void {\n if (this.contained || this._hasScrollLock) return;\n // Uses a shared reference-counted lock so that simultaneous hx-dialog / hx-drawer\n // instances don't clobber each other when one closes before the other\n // (see utils/body-scroll-lock.ts).\n lockBodyScroll();\n this._hasScrollLock = true;\n }\n\n /** @internal */\n private _restoreBodyScroll(): void {\n if (!this._hasScrollLock) return;\n unlockBodyScroll();\n this._hasScrollLock = false;\n }\n\n /** @internal */\n private _openDrawer(): void {\n // Capture trigger for focus restoration (P2-04: use instanceof guard)\n const active = document.activeElement;\n this._triggerElement = active instanceof HTMLElement ? active : null;\n\n // P1-05: clear any pending animation timeout before scheduling a new one\n if (this._animationTimeout !== null) {\n clearTimeout(this._animationTimeout);\n this._animationTimeout = null;\n }\n\n this._applySizeVar();\n this._lockBodyScroll();\n this._hideBackgroundFromScreenReaders();\n\n // Dispatch hx-show before visual update\n this.dispatchEvent(new CustomEvent<void>('hx-show', { bubbles: true, composed: true }));\n\n // Transition to open state\n void this.updateComplete\n .then(() => {\n this._isOpen = true;\n this._addListeners();\n\n // Set initial focus after next render\n return this.updateComplete;\n })\n .then(() => {\n this._cachedFocusableElements = this._getFocusableElements();\n this._setInitialFocus();\n\n // Dispatch hx-after-show when the panel's CSS transition completes.\n // If prefers-reduced-motion is active (duration === 0) or the element\n // is missing, fire immediately — transitionend will never fire.\n const duration = this._getAnimationDuration();\n const panel = this._panelEl;\n if (duration === 0 || !panel) {\n this.dispatchEvent(\n new CustomEvent<void>('hx-after-show', { bubbles: true, composed: true }),\n );\n } else {\n const emitAfterShow = () => {\n if (this._animationTimeout !== null) {\n clearTimeout(this._animationTimeout);\n this._animationTimeout = null;\n }\n this.dispatchEvent(\n new CustomEvent<void>('hx-after-show', { bubbles: true, composed: true }),\n );\n };\n panel.addEventListener('transitionend', emitAfterShow, { once: true });\n // Safety fallback: if transitionend never fires (e.g. transition\n // cancelled, element removed), ensure the event is still dispatched.\n this._animationTimeout = setTimeout(emitAfterShow, duration + 50);\n }\n })\n .catch(console.error);\n }\n\n /** @internal */\n private _closeDrawer(): void {\n // P1-05: clear any pending animation timeout before scheduling a new one\n if (this._animationTimeout !== null) {\n clearTimeout(this._animationTimeout);\n this._animationTimeout = null;\n }\n\n this._isOpen = false;\n this._removeListeners();\n this._cachedFocusableElements = [];\n this._restoreBodyScroll();\n this._restoreBackgroundForScreenReaders();\n\n this.dispatchEvent(new CustomEvent<void>('hx-hide', { bubbles: true, composed: true }));\n\n // Restore focus to the trigger immediately — before any animation timeout.\n // WCAG 2.4.3: focus must never remain on invisible or inert content.\n if (this._triggerElement && typeof this._triggerElement.focus === 'function') {\n this._triggerElement.focus();\n }\n this._triggerElement = null;\n\n // Dispatch hx-after-hide when the panel's CSS transition completes.\n // If prefers-reduced-motion is active (duration === 0) or the element\n // is missing, fire immediately — transitionend will never fire.\n const duration = this._getAnimationDuration();\n const panel = this._panelEl;\n if (duration === 0 || !panel) {\n this.dispatchEvent(new CustomEvent<void>('hx-after-hide', { bubbles: true, composed: true }));\n } else {\n const emitAfterHide = () => {\n if (this._animationTimeout !== null) {\n clearTimeout(this._animationTimeout);\n this._animationTimeout = null;\n }\n this.dispatchEvent(\n new CustomEvent<void>('hx-after-hide', { bubbles: true, composed: true }),\n );\n };\n panel.addEventListener('transitionend', emitAfterHide, { once: true });\n // Safety fallback: if transitionend never fires (e.g. transition\n // cancelled, element removed), ensure the event is still dispatched.\n this._animationTimeout = setTimeout(emitAfterHide, duration + 50);\n }\n }\n\n /** @internal */\n private _getAnimationDuration(): number {\n if (typeof window === 'undefined') return 0;\n if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return 0;\n return 300;\n }\n\n // ─── Background aria-hidden management (P1-03) ───\n\n /** @internal */\n private _hideBackgroundFromScreenReaders(): void {\n if (this.contained) return;\n this._siblingAriaHiddenElements = [];\n // Walk the parent chain once to find which body child is an ancestor of this component.\n // This avoids calling child.contains(this) in a loop (which is O(n * depth)).\n // Starting from parentElement avoids aliasing `this` to a local variable.\n let ancestorBodyChild: Element | null = null;\n let el: Element | null = this.parentElement;\n while (el && el.parentElement !== document.body) {\n el = el.parentElement;\n }\n if (el && el.parentElement === document.body) {\n ancestorBodyChild = el;\n }\n Array.from(document.body.children).forEach((child) => {\n if (child === this || child === ancestorBodyChild) return;\n if (!child.hasAttribute('aria-hidden')) {\n child.setAttribute('aria-hidden', 'true');\n this._siblingAriaHiddenElements.push(child);\n }\n });\n }\n\n /** @internal */\n private _restoreBackgroundForScreenReaders(): void {\n this._siblingAriaHiddenElements.forEach((el) => {\n el.removeAttribute('aria-hidden');\n });\n this._siblingAriaHiddenElements = [];\n }\n\n // ─── Event Listeners (P1-01: use only document listener, not overlay) ───\n\n /** @internal */\n private _addListeners(): void {\n document.addEventListener('keydown', this._handleKeyDown);\n }\n\n /** @internal */\n private _removeListeners(): void {\n document.removeEventListener('keydown', this._handleKeyDown);\n }\n\n // ─── Keyboard Handler ───\n\n /**\n * Handles keyboard events on the document to trap focus and close the drawer on Escape.\n * @internal\n */\n private _handleKeyDown = (e: KeyboardEvent): void => {\n if (!this._isOpen) return;\n\n if (e.key === 'Escape') {\n e.preventDefault();\n this.open = false;\n return;\n }\n\n if (e.key === 'Tab') {\n this._trapFocus(e);\n }\n };\n\n // ─── Focus ───\n\n /** @internal */\n private _setInitialFocus(): void {\n const event = new CustomEvent<void>('hx-initial-focus', {\n bubbles: true,\n composed: true,\n cancelable: true,\n });\n this.dispatchEvent(event);\n\n if (!event.defaultPrevented) {\n const focusable = this._cachedFocusableElements;\n if (focusable.length > 0 && focusable[0]) {\n focusable[0].focus();\n } else {\n this._panelEl?.focus();\n }\n }\n }\n\n /** @internal */\n private _getFocusableElements(): HTMLElement[] {\n const shadowFocusable = Array.from(\n this.shadowRoot?.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTORS) ?? [],\n );\n\n const slots = this.shadowRoot?.querySelectorAll<HTMLSlotElement>('slot') ?? [];\n const lightFocusable: HTMLElement[] = [];\n\n slots.forEach((slot) => {\n slot.assignedElements({ flatten: true }).forEach((el) => {\n if (el instanceof HTMLElement) {\n if (el.matches(FOCUSABLE_SELECTORS)) {\n lightFocusable.push(el);\n }\n el.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTORS).forEach((child) => {\n lightFocusable.push(child);\n });\n }\n });\n });\n\n return [...shadowFocusable, ...lightFocusable].filter(\n (el) => !el.hasAttribute('disabled') && el.getAttribute('tabindex') !== '-1',\n );\n }\n\n /** @internal */\n private _trapFocus(e: KeyboardEvent): void {\n const focusable =\n this._cachedFocusableElements.length > 0\n ? this._cachedFocusableElements\n : this._getFocusableElements();\n\n if (focusable.length === 0) {\n e.preventDefault();\n return;\n }\n\n const [first, ...rest] = focusable;\n const last = rest.length > 0 ? rest[rest.length - 1] : first;\n\n if (!first || !last) return;\n\n // P1-02: Use document.activeElement for reliable detection of slotted (light DOM) elements.\n // shadowRoot.activeElement returns the <slot> host for slotted content, not the actual element.\n const active = document.activeElement as HTMLElement | null;\n\n if (e.shiftKey) {\n if (active === first) {\n e.preventDefault();\n last.focus();\n }\n } else {\n if (active === last) {\n e.preventDefault();\n first.focus();\n }\n }\n }\n\n // ─── Overlay Click ───\n\n /**\n * Handles clicks on the overlay backdrop to close the drawer when the user clicks outside the panel.\n * @internal\n */\n private _handleOverlayClick = (e: MouseEvent): void => {\n // Only close when clicking the overlay itself (backdrop), not the panel\n const target = e.target as HTMLElement;\n if (target === this._overlayEl || target.classList.contains('drawer-backdrop')) {\n this.open = false;\n }\n };\n\n // ─── Slot change handlers ───\n\n /** @internal */\n private _handleHeaderActionsSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasHeaderActionsSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n /** @internal */\n private _handleFooterSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasFooterSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n /** @internal */\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 this._installLabelSlotTextObserver(state.elements);\n this._syncHostAriaSemantics();\n }\n\n // ─── Host-canonical ARIA helpers ───\n\n /**\n * Reads the label slot's assigned nodes and computes the discriminated\n * naming state. Aggregates ALL assigned elements (not just the first) so\n * composed labels project the FULL visible label via\n * `internals.ariaLabelledByElements`. Per AccName 1.2 §4.3.10,\n * `aria-hidden=\"true\"` / `[hidden]` elements contribute zero to the\n * accessible name but stay in `elements` so AT walking IDL refs sees the\n * full visible group. `hasUsefulName` is gated on the flattened text\n * length: a slot containing only decorative wrappers does NOT name the\n * dialog, and the host falls through to the next naming source.\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 if (el.getAttribute('aria-hidden') === 'true') continue;\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 hasUsefulName: trimmedText.length > 0,\n elements,\n text: trimmedText,\n };\n }\n\n /**\n * (Re-)installs the mutation observer over the current set of slotted label\n * elements. On any descendant text/visibility mutation we re-flatten and\n * re-sync so the host's accessible name tracks the visible label.\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 const fragments: string[] = [];\n for (const el of elements) {\n if (el.getAttribute('aria-hidden') === 'true') continue;\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._syncHostAriaSemantics();\n });\n for (const el of elements) {\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 * (Re-)installs a `MutationObserver` against the deduped union of\n * consumer-resolved label/description elements. Watches `characterData`,\n * `childList`, `subtree`, and `aria-hidden` / `hidden` attributes so any\n * in-place mutation on the referenced light-DOM nodes triggers a fresh\n * sync — keeping the modern-path IDL refs and the fallback-path text\n * flatten aligned with the live consumer text.\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 const unique = new Set<Element>(elements);\n const observer = new MutationObserver(() => {\n this._syncHostAriaSemantics();\n });\n for (const el of unique) {\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 /**\n * Gates `role=\"dialog\"` + `aria-modal=\"true\"` on the host's\n * `ElementInternals` behind the `open` boolean. A closed drawer must NOT\n * surface as a modal dialog to the accessibility tree — otherwise screen\n * readers announce an invisible modal before the consumer ever opens it\n * (regression introduced when the ARIA surface moved from the inner\n * overlay to the host in group-4 round-1).\n *\n * Open → `role = 'dialog'`, `ariaModal = 'true'`\n * Closed → `role = null`, `ariaModal = null` (cleared from the AT tree)\n *\n * Called from `connectedCallback()` (initial state) and from `updated()`\n * whenever `open` changes. Idempotent: writing the same value twice is a\n * no-op for both AT and the accessibility tree builder.\n * @internal\n */\n private _syncHostDialogSemantics(): void {\n if (this.open) {\n this._internals.role = 'dialog';\n this._internals.ariaModal = 'true';\n } else {\n this._internals.role = null;\n this._internals.ariaModal = null;\n }\n }\n\n /**\n * Resolves consumer-supplied label/description IDREFs on the host and\n * projects the canonical dialog ARIA onto the **host** via\n * `ElementInternals` (modern path) and onto the inner overlay via attribute\n * writes (fallback path).\n *\n * Cross-shadow naming is belt-and-suspenders:\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 walking the host's accessibility tree finds them\n * across the shadow boundary. `internals.ariaLabel` carries the\n * flattened text fallback (only when no labelledby resolves) so AT\n * that does not walk IDL refs still announces a name.\n * 2. **Fallback path** (`_supportsIdrefRefs === false`): the resolved\n * element text is flattened and written to `internals.ariaLabel` AND\n * mirrored to the inner overlay's `aria-label`.\n *\n * The synthesized `<span id=\"${_consumerDescId}\">` mirrors the resolved\n * description text on every sync. The inner overlay's `aria-describedby`\n * chains the in-shadow span. `aria-description` is intentionally NEVER\n * written — W3C AccName ignores it whenever `aria-describedby` is set.\n *\n * Naming precedence (W3C AccName 1.2 §4.3.1):\n * 1. Consumer `aria-labelledby` (resolved IDREFs, text-flattened)\n * 2. Consumer `aria-label`\n * 3. Slotted `<slot name=\"label\">` text\n * 4. `label` property\n * 5. Hard-coded `\"Drawer\"`\n * @internal\n */\n private _syncHostAriaSemantics(): void {\n const internals = this._internals;\n // The host's canonical role + modal flag are managed separately by\n // `_syncHostDialogSemantics()` — they are gated on `this.open` so a\n // CLOSED drawer is invisible to the accessibility tree (no orphan\n // `role=\"dialog\"` / `aria-modal=\"true\"` before the consumer flips open).\n // Naming/description state below is independent of open-state because\n // the resolved label still composes correctly while closed and the\n // dialog surface only becomes visible to AT when role/aria-modal lift.\n\n // Refresh the consumer baseline. The host attribute IS the live source\n // of truth — `null` 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\n const consumerLabelEls = resolveIdrefTokens(this, this._consumerLabelledBy);\n const hasEffectiveLabelledBy = consumerLabelEls.length > 0;\n const consumerDescEls = resolveIdrefTokens(this, this._consumerDescribedBy);\n\n // Observe in-place mutations on the resolved external IDREF targets.\n // Without this a consumer mutating `<h2 id=\"x\">Patient</h2>` → \"Member\"\n // in place leaves the host's flattened `aria-label` stuck on \"Patient\".\n this._installExternalRefsObserver([...consumerLabelEls, ...consumerDescEls]);\n\n // Per AccName 1.2 §4.3.10, top-level aria-hidden / hidden elements\n // contribute zero to the name. Filter them from the IDL-refs path so the\n // modern path matches the fallback path's text-flatten behavior.\n const isVisibleForAccName = (el: Element): boolean =>\n el.getAttribute('aria-hidden') !== 'true' && !el.hasAttribute('hidden');\n\n const liveAriaLabel = this.getAttribute('aria-label');\n const hostAriaLabel = liveAriaLabel !== null ? liveAriaLabel.trim() : '';\n\n // Build the augmented label-elements list used by the modern path.\n // Slotted-title elements feed in only when no consumer aria-labelledby\n // resolved (AccName 1.2 precedence: external > slot > property).\n const labelElsForInternals: Element[] = [];\n labelElsForInternals.push(...consumerLabelEls.filter(isVisibleForAccName));\n if (!hasEffectiveLabelledBy && !hostAriaLabel && this._hasLabelSlot) {\n // Aggregate every slotted label element so AT composes icon + text.\n labelElsForInternals.push(...this._slottedLabelEls.filter(isVisibleForAccName));\n }\n\n const descElsForInternals: Element[] = [...consumerDescEls.filter(isVisibleForAccName)];\n\n // ─── Compute the resolved accessible name (text-flatten path) ───\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 resolvedName = '';\n if (hasEffectiveLabelledBy) {\n resolvedName = flattenText(consumerLabelEls);\n }\n if (!resolvedName && hostAriaLabel) {\n resolvedName = hostAriaLabel;\n }\n if (!resolvedName && this._hasLabelSlot && this._labelSlotText) {\n resolvedName = this._labelSlotText;\n }\n if (!resolvedName && this.label) {\n resolvedName = this.label;\n }\n if (!resolvedName) {\n // Last-resort literal — preserves the pre-host-canonical default so an\n // unlabeled drawer still has SOME announced name. Consumer responsibility\n // to provide a meaningful one in real usage.\n resolvedName = 'Drawer';\n }\n\n // ─── Modern-path: ElementInternals IDL element references ───\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 // Forward `aria-label` to `internals.ariaLabel` ONLY when no labelledby\n // resolved — per AccName 1.2 a non-empty aria-label outranks\n // aria-labelledby, and we never want to silently erase the IDL-ref\n // resolution. When labelledby is present, `null` removes the override\n // so element references win.\n if (hasEffectiveLabelledBy) {\n internals.ariaLabel = null;\n } else {\n internals.ariaLabel = resolvedName;\n }\n } else {\n // Fallback path: write the flattened name directly to internals.\n // Older engines without IDL refs use this as the canonical name.\n internals.ariaLabel = resolvedName;\n }\n\n // ─── Synthesized in-shadow consumer-description span ───\n // Mirror consumer-resolved description text into a same-root span so the\n // inner overlay's `aria-describedby` resolves cross-shadow without\n // pointing at light-DOM ids (which do not resolve from inside a shadow\n // root). `aria-description` is intentionally NEVER written.\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 // ─── Inner overlay attribute reconciliation ───\n // The overlay no longer carries `role` / `aria-modal` / `aria-labelledby`\n // / `aria-label` on the modern path — the host owns those via internals.\n // Strip stale attributes defensively in case an earlier sync wrote them\n // and reconcile the fallback `aria-label` only when IDL refs are not\n // supported (so screen readers walking the inner overlay still find a\n // name on legacy engines).\n const overlay = this._overlayEl ?? null;\n if (overlay) {\n // Belt-and-suspenders: never write `role` / `aria-modal` to the inner\n // overlay on either path — that would create nested-dialog semantics\n // above the host's canonical surface.\n if (overlay.hasAttribute('role')) overlay.removeAttribute('role');\n if (overlay.hasAttribute('aria-modal')) overlay.removeAttribute('aria-modal');\n // Internal slotted-title id on the SAME shadow root resolves cleanly,\n // so we project it onto the overlay's `aria-labelledby` only on the\n // fallback path. The modern path uses `internals.ariaLabelledByElements`.\n const wantOverlayLabelledBy =\n !this._supportsIdrefRefs && this._hasLabelSlot ? this._titleId : null;\n const wantOverlayLabel =\n !this._supportsIdrefRefs && !wantOverlayLabelledBy ? resolvedName : null;\n if (wantOverlayLabelledBy) {\n if (overlay.getAttribute('aria-labelledby') !== wantOverlayLabelledBy) {\n overlay.setAttribute('aria-labelledby', wantOverlayLabelledBy);\n }\n } else if (overlay.hasAttribute('aria-labelledby')) {\n overlay.removeAttribute('aria-labelledby');\n }\n if (wantOverlayLabel) {\n if (overlay.getAttribute('aria-label') !== wantOverlayLabel) {\n overlay.setAttribute('aria-label', wantOverlayLabel);\n }\n } else if (overlay.hasAttribute('aria-label')) {\n overlay.removeAttribute('aria-label');\n }\n\n // Inner overlay's `aria-describedby` chains the in-shadow consumer-desc\n // span. Same-root id resolves cleanly; cross-shadow consumer ids are\n // ignored at the AT level (light-DOM ids do not resolve from inside a\n // shadow root) so we never write them directly.\n if (consumerDescText && consumerDescSpan) {\n const value = this._consumerDescId;\n if (overlay.getAttribute('aria-describedby') !== value) {\n overlay.setAttribute('aria-describedby', value);\n }\n } else if (overlay.hasAttribute('aria-describedby')) {\n overlay.removeAttribute('aria-describedby');\n }\n\n // Forced-colors: the host has display: contents so :host(:focus-visible)\n // has no painting surface — focus is on the inner panel. The existing\n // `forcedColorsSurface` mixin paints the host CanvasText border which\n // the panel inherits via the parent box. No change owed here, but if a\n // future change makes the host focusable directly we'd add the rule.\n }\n\n // Strip `aria-description` defensively — never written on either path.\n if (overlay && overlay.hasAttribute('aria-description')) {\n overlay.removeAttribute('aria-description');\n }\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _renderHeader() {\n if (this.noHeader) {\n // WCAG 4.1.2: When the header is hidden there must still be a reachable close\n // mechanism for keyboard and mouse/touch users. Render a visually-hidden close\n // button that is focusable and announced by screen readers.\n return html`\n <button\n part=\"close-btn\"\n class=\"drawer-close-button drawer-close-button--sr-only\"\n aria-label=${this.labelClose}\n @click=${() => {\n this.open = false;\n }}\n ></button>\n `;\n }\n\n return html`\n <div part=\"header\" class=\"drawer-header\">\n <h2 part=\"title\" id=${this._titleId} class=\"drawer-title\">\n <slot name=\"label\" @slotchange=${this._handleLabelSlotChange}></slot>\n </h2>\n <div class=\"drawer-header-actions\">\n ${this._hasHeaderActionsSlot\n ? html`<slot\n name=\"header-actions\"\n @slotchange=${this._handleHeaderActionsSlotChange}\n ></slot>`\n : html`<slot\n name=\"header-actions\"\n @slotchange=${this._handleHeaderActionsSlotChange}\n style=\"display:none\"\n ></slot>`}\n <button\n part=\"close-button\"\n class=\"drawer-close-button\"\n aria-label=${this.labelClose}\n @click=${() => {\n this.open = false;\n }}\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n aria-hidden=\"true\"\n >\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n </div>\n </div>\n `;\n }\n\n /** @internal */\n private _renderFooter() {\n if (this.noFooter) return nothing;\n\n return html`\n <div part=\"footer\" class=\"drawer-footer\" ?hidden=${!this._hasFooterSlot}>\n <slot name=\"footer\" @slotchange=${this._handleFooterSlotChange}></slot>\n </div>\n `;\n }\n\n // ─── Render ───\n\n override render() {\n const overlayClasses = {\n 'drawer-overlay': true,\n 'is-open': this._isOpen,\n };\n\n // Host-canonical: the inner overlay carries NO `role` / `aria-modal` /\n // `aria-labelledby` / `aria-label` here. Those are projected onto the\n // host via `ElementInternals` in `_syncHostAriaSemantics()`. On the\n // legacy (no-IDL-ref) fallback path the sync method imperatively writes\n // `aria-label` / `aria-labelledby` onto the overlay so AT walking down\n // from the host still finds an announceable name.\n return html`\n <div\n part=\"overlay\"\n class=${classMap(overlayClasses)}\n tabindex=\"-1\"\n @click=${this._handleOverlayClick}\n >\n <div class=\"drawer-backdrop\" aria-hidden=\"true\"></div>\n <div part=\"panel\" class=\"drawer-panel\" tabindex=\"-1\">\n ${this._renderHeader()}\n <div part=\"body\" class=\"drawer-body\">\n <slot></slot>\n </div>\n ${this._renderFooter()}\n </div>\n <!--\n Synthesized in-shadow span carrying consumer-resolved description\n text. Updated imperatively on every sync. The inner overlay's\n \\`aria-describedby\\` references this span so cross-shadow consumer\n descriptions resolve through the standard described-by channel\n without writing light-DOM ids that cannot resolve from inside a\n shadow root. \\`aria-description\\` is intentionally NEVER written —\n AccName ignores it whenever \\`aria-describedby\\` is present.\n -->\n <span id=${this._consumerDescId} class=\"drawer-sr-only\" aria-hidden=\"false\"></span>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-drawer': HelixDrawer;\n }\n interface HTMLElementEventMap {\n 'hx-show': CustomEvent<void>;\n 'hx-after-show': CustomEvent<void>;\n 'hx-hide': CustomEvent<void>;\n 'hx-after-hide': CustomEvent<void>;\n 'hx-initial-focus': CustomEvent<void>;\n }\n}\n"],"names":["helixDrawerStyles","css","_nextDrawerId","createIdCounter","DRAWER_SIZE_MAP","FOCUSABLE_SELECTORS","HelixDrawer","HelixElement","target","legacySize","ctor","supportsIdrefElementReferences","records","consumerCleared","record","oldValue","newValue","installAriaIdrefMirror","_a","_b","_c","_d","changedProperties","resolvedSize","lockBodyScroll","unlockBodyScroll","active","duration","panel","emitAfterShow","emitAfterHide","ancestorBodyChild","el","child","event","focusable","shadowFocusable","slots","lightFocusable","slot","first","rest","last","state","nodes","elements","fragments","node","elText","flattenAccName","txt","trimmedText","observer","t","trimmed","unique","internals","liveLabelledBy","liveDescribedBy","consumerLabelEls","resolveIdrefTokens","hasEffectiveLabelledBy","consumerDescEls","isVisibleForAccName","liveAriaLabel","hostAriaLabel","labelElsForInternals","descElsForInternals","flattenText","els","resolvedName","refsInternals","consumerDescSpan","consumerDescText","overlay","wantOverlayLabelledBy","wantOverlayLabel","value","html","nothing","overlayClasses","classMap","forcedColorsSurface","__decorateClass","query","property","customElement"],"mappings":";;;;;;;;;AAYO,MAAMA,IAAoBC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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"}