@helixui/library 3.2.0-next.91 → 3.2.0-next.96

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 (225) hide show
  1. package/custom-elements.json +358 -358
  2. package/dist/components/hx-accordion/hx-accordion-item.styles.d.ts.map +1 -1
  3. package/dist/components/hx-accordion/index.js +1 -1
  4. package/dist/components/hx-alert/index.js +1 -1
  5. package/dist/components/hx-banner/index.js +1 -1
  6. package/dist/components/hx-breadcrumb/hx-breadcrumb-item.styles.d.ts.map +1 -1
  7. package/dist/components/hx-breadcrumb/index.js +1 -1
  8. package/dist/components/hx-button/hx-button.styles.d.ts.map +1 -1
  9. package/dist/components/hx-button/index.js +1 -1
  10. package/dist/components/hx-card/hx-card.styles.d.ts.map +1 -1
  11. package/dist/components/hx-card/index.js +1 -1
  12. package/dist/components/hx-checkbox/index.js +1 -1
  13. package/dist/components/hx-clinical-status/hx-clinical-status.styles.d.ts.map +1 -1
  14. package/dist/components/hx-clinical-status/index.js +1 -1
  15. package/dist/components/hx-code-snippet/index.js +1 -1
  16. package/dist/components/hx-color-picker/hx-color-picker.styles.d.ts.map +1 -1
  17. package/dist/components/hx-color-picker/index.js +1 -1
  18. package/dist/components/hx-combobox/index.js +1 -1
  19. package/dist/components/hx-data-table/hx-data-table.styles.d.ts.map +1 -1
  20. package/dist/components/hx-data-table/index.js +1 -1
  21. package/dist/components/hx-date-picker/index.js +1 -1
  22. package/dist/components/hx-dialog/hx-dialog.styles.d.ts.map +1 -1
  23. package/dist/components/hx-dialog/index.js +1 -1
  24. package/dist/components/hx-drawer/hx-drawer.styles.d.ts.map +1 -1
  25. package/dist/components/hx-drawer/index.js +1 -1
  26. package/dist/components/hx-file-upload/hx-file-upload.styles.d.ts.map +1 -1
  27. package/dist/components/hx-file-upload/index.js +1 -1
  28. package/dist/components/hx-icon-button/hx-icon-button.styles.d.ts.map +1 -1
  29. package/dist/components/hx-icon-button/index.js +1 -1
  30. package/dist/components/hx-link/index.js +1 -1
  31. package/dist/components/hx-menu/hx-menu-item.styles.d.ts.map +1 -1
  32. package/dist/components/hx-menu/index.js +1 -1
  33. package/dist/components/hx-meter/hx-meter.styles.d.ts.map +1 -1
  34. package/dist/components/hx-meter/index.js +1 -1
  35. package/dist/components/hx-nav/hx-nav.styles.d.ts.map +1 -1
  36. package/dist/components/hx-nav/index.js +1 -1
  37. package/dist/components/hx-overflow-menu/hx-overflow-menu.styles.d.ts.map +1 -1
  38. package/dist/components/hx-overflow-menu/index.js +1 -1
  39. package/dist/components/hx-pagination/hx-pagination.styles.d.ts.map +1 -1
  40. package/dist/components/hx-pagination/index.js +1 -1
  41. package/dist/components/hx-phi-field/hx-phi-field.styles.d.ts.map +1 -1
  42. package/dist/components/hx-phi-field/index.js +1 -1
  43. package/dist/components/hx-popover/hx-popover.styles.d.ts.map +1 -1
  44. package/dist/components/hx-popover/index.js +1 -1
  45. package/dist/components/hx-radio-group/index.js +1 -1
  46. package/dist/components/hx-rating/index.js +1 -1
  47. package/dist/components/hx-select/index.js +1 -1
  48. package/dist/components/hx-side-nav/index.js +1 -1
  49. package/dist/components/hx-slider/index.js +1 -1
  50. package/dist/components/hx-split-button/hx-split-button.d.ts +1 -1
  51. package/dist/components/hx-split-button/index.js +1 -1
  52. package/dist/components/hx-split-panel/hx-split-panel.styles.d.ts.map +1 -1
  53. package/dist/components/hx-split-panel/index.js +1 -1
  54. package/dist/components/hx-steps/hx-step.styles.d.ts.map +1 -1
  55. package/dist/components/hx-steps/index.js +1 -1
  56. package/dist/components/hx-switch/index.js +1 -1
  57. package/dist/components/hx-table/hx-table.styles.d.ts.map +1 -1
  58. package/dist/components/hx-table/index.js +1 -1
  59. package/dist/components/hx-tabs/index.js +1 -1
  60. package/dist/components/hx-text-input/index.js +1 -1
  61. package/dist/components/hx-textarea/index.js +1 -1
  62. package/dist/components/hx-time-picker/index.js +1 -1
  63. package/dist/components/hx-toggle-button/index.js +1 -1
  64. package/dist/components/hx-top-nav/hx-top-nav.styles.d.ts.map +1 -1
  65. package/dist/components/hx-top-nav/index.js +1 -1
  66. package/dist/components/hx-tree-view/hx-tree-item.styles.d.ts.map +1 -1
  67. package/dist/components/hx-tree-view/index.js +1 -1
  68. package/dist/css/helix-all.css +100 -164
  69. package/dist/css/helix-core.css +16 -12
  70. package/dist/css/helix-data.css +7 -14
  71. package/dist/css/helix-feedback.css +4 -5
  72. package/dist/css/helix-forms.css +48 -67
  73. package/dist/css/helix-layout.css +2 -8
  74. package/dist/css/helix-navigation.css +12 -33
  75. package/dist/css/helix-overlay.css +3 -12
  76. package/dist/css/helix-tokens.css +16 -5
  77. package/dist/css/helix-utility.css +5 -5
  78. package/dist/css/hx-alert.css +1 -1
  79. package/dist/css/hx-banner.css +2 -2
  80. package/dist/css/hx-button.css +12 -2
  81. package/dist/css/hx-card.css +1 -4
  82. package/dist/css/hx-checkbox.css +2 -2
  83. package/dist/css/hx-clinical-status.css +2 -4
  84. package/dist/css/hx-code-snippet.css +4 -4
  85. package/dist/css/hx-color-picker.css +3 -13
  86. package/dist/css/hx-combobox.css +7 -7
  87. package/dist/css/hx-data-table.css +2 -8
  88. package/dist/css/hx-date-picker.css +7 -7
  89. package/dist/css/hx-dialog.css +1 -4
  90. package/dist/css/hx-drawer.css +1 -4
  91. package/dist/css/hx-file-upload.css +4 -13
  92. package/dist/css/hx-icon-button.css +2 -5
  93. package/dist/css/hx-link.css +1 -1
  94. package/dist/css/hx-meter.css +1 -2
  95. package/dist/css/hx-nav.css +2 -8
  96. package/dist/css/hx-overflow-menu.css +2 -8
  97. package/dist/css/hx-pagination.css +2 -8
  98. package/dist/css/hx-phi-field.css +1 -4
  99. package/dist/css/hx-popover.css +1 -4
  100. package/dist/css/hx-rating.css +3 -3
  101. package/dist/css/hx-select.css +2 -2
  102. package/dist/css/hx-side-nav.css +4 -4
  103. package/dist/css/hx-slider.css +4 -4
  104. package/dist/css/hx-split-button.css +5 -5
  105. package/dist/css/hx-split-panel.css +2 -8
  106. package/dist/css/hx-switch.css +3 -3
  107. package/dist/css/hx-table.css +1 -2
  108. package/dist/css/hx-text-input.css +4 -4
  109. package/dist/css/hx-textarea.css +2 -2
  110. package/dist/css/hx-time-picker.css +3 -3
  111. package/dist/css/hx-toggle-button.css +4 -4
  112. package/dist/css/hx-top-nav.css +1 -4
  113. package/dist/css/hx-tree-view.css +1 -1
  114. package/dist/css/index.css +1 -1
  115. package/dist/css/manifest.json +28 -26
  116. package/dist/index.js +42 -42
  117. package/dist/shared/{hx-accordion-cnKg4_la.js → hx-accordion-ZVzgDzTG.js} +4 -5
  118. package/dist/shared/hx-accordion-ZVzgDzTG.js.map +1 -0
  119. package/dist/shared/{hx-alert-BZH8iHQf.js → hx-alert-C597yHpD.js} +2 -2
  120. package/dist/shared/{hx-alert-BZH8iHQf.js.map → hx-alert-C597yHpD.js.map} +1 -1
  121. package/dist/shared/{hx-banner-DT7Zn9Bo.js → hx-banner-Cxd7eFUP.js} +3 -3
  122. package/dist/shared/{hx-banner-DT7Zn9Bo.js.map → hx-banner-Cxd7eFUP.js.map} +1 -1
  123. package/dist/shared/{hx-breadcrumb-item-COeYcB2x.js → hx-breadcrumb-item-3tKppF9h.js} +2 -5
  124. package/dist/shared/{hx-breadcrumb-item-COeYcB2x.js.map → hx-breadcrumb-item-3tKppF9h.js.map} +1 -1
  125. package/dist/shared/{hx-button-ebUV8KhT.js → hx-button-D3gC-OJb.js} +13 -3
  126. package/dist/shared/hx-button-D3gC-OJb.js.map +1 -0
  127. package/dist/shared/{hx-card-CU1QnjNb.js → hx-card-qNAM2QNV.js} +6 -9
  128. package/dist/shared/hx-card-qNAM2QNV.js.map +1 -0
  129. package/dist/shared/{hx-checkbox-C46TyXhM.js → hx-checkbox-DBD-gMoz.js} +3 -3
  130. package/dist/shared/{hx-checkbox-C46TyXhM.js.map → hx-checkbox-DBD-gMoz.js.map} +1 -1
  131. package/dist/shared/{hx-clinical-status-BmSjfSEN.js → hx-clinical-status-D3XQIOqX.js} +3 -5
  132. package/dist/shared/hx-clinical-status-D3XQIOqX.js.map +1 -0
  133. package/dist/shared/{hx-code-snippet-CJ0FbQYG.js → hx-code-snippet-CJrFeyz0.js} +5 -5
  134. package/dist/shared/{hx-code-snippet-CJ0FbQYG.js.map → hx-code-snippet-CJrFeyz0.js.map} +1 -1
  135. package/dist/shared/{hx-color-picker-DiDLZyvK.js → hx-color-picker-uRc865FJ.js} +23 -33
  136. package/dist/shared/hx-color-picker-uRc865FJ.js.map +1 -0
  137. package/dist/shared/{hx-combobox-DaA5dBC4.js → hx-combobox-ClhNRAS5.js} +8 -8
  138. package/dist/shared/hx-combobox-ClhNRAS5.js.map +1 -0
  139. package/dist/shared/{hx-data-table-Cq3t86Ic.js → hx-data-table-CLqVqdxr.js} +3 -9
  140. package/dist/shared/hx-data-table-CLqVqdxr.js.map +1 -0
  141. package/dist/shared/{hx-date-picker-DMqRQNSB.js → hx-date-picker-BJm7Yrda.js} +8 -8
  142. package/dist/shared/{hx-date-picker-DMqRQNSB.js.map → hx-date-picker-BJm7Yrda.js.map} +1 -1
  143. package/dist/shared/{hx-dialog-eIS8tcDm.js → hx-dialog-DRN_1-Y-.js} +2 -5
  144. package/dist/shared/hx-dialog-DRN_1-Y-.js.map +1 -0
  145. package/dist/shared/{hx-drawer-DDhDz7RI.js → hx-drawer-Y1Ui2IWJ.js} +2 -5
  146. package/dist/shared/hx-drawer-Y1Ui2IWJ.js.map +1 -0
  147. package/dist/shared/{hx-file-upload-zTDbjsRw.js → hx-file-upload-D3rKROK5.js} +17 -26
  148. package/dist/shared/hx-file-upload-D3rKROK5.js.map +1 -0
  149. package/dist/shared/{hx-icon-button-BmV97nqz.js → hx-icon-button-CGNdQSFM.js} +3 -6
  150. package/dist/shared/hx-icon-button-CGNdQSFM.js.map +1 -0
  151. package/dist/shared/{hx-link-DmiV-mPw.js → hx-link-9Ig2DW6L.js} +5 -5
  152. package/dist/shared/{hx-link-DmiV-mPw.js.map → hx-link-9Ig2DW6L.js.map} +1 -1
  153. package/dist/shared/{hx-menu-divider-j__TZjH2.js → hx-menu-divider-C2omnPtj.js} +2 -5
  154. package/dist/shared/hx-menu-divider-C2omnPtj.js.map +1 -0
  155. package/dist/shared/{hx-meter-Cm7k_Ro8.js → hx-meter-BPscsw5t.js} +2 -3
  156. package/dist/shared/hx-meter-BPscsw5t.js.map +1 -0
  157. package/dist/shared/{hx-nav-item-CvTxO3Sa.js → hx-nav-item-DH2tXcj1.js} +6 -6
  158. package/dist/shared/{hx-nav-item-CvTxO3Sa.js.map → hx-nav-item-DH2tXcj1.js.map} +1 -1
  159. package/dist/shared/{hx-nav-LoyEKZQC.js → hx-nav-ldFM3Fle.js} +37 -43
  160. package/dist/shared/hx-nav-ldFM3Fle.js.map +1 -0
  161. package/dist/shared/{hx-overflow-menu-BmKyAp5D.js → hx-overflow-menu-DCLsdIBy.js} +3 -9
  162. package/dist/shared/hx-overflow-menu-DCLsdIBy.js.map +1 -0
  163. package/dist/shared/{hx-pagination-Dqw5dorC.js → hx-pagination-C7y8GVyU.js} +54 -60
  164. package/dist/shared/hx-pagination-C7y8GVyU.js.map +1 -0
  165. package/dist/shared/{hx-phi-field-Bf9TdtC1.js → hx-phi-field-C19oxlrr.js} +2 -5
  166. package/dist/shared/hx-phi-field-C19oxlrr.js.map +1 -0
  167. package/dist/shared/{hx-popover-B93rTAfr.js → hx-popover-B-FP3-wW.js} +8 -11
  168. package/dist/shared/hx-popover-B-FP3-wW.js.map +1 -0
  169. package/dist/shared/{hx-radio-N8xgDd_5.js → hx-radio-dFjUAost.js} +4 -4
  170. package/dist/shared/{hx-radio-N8xgDd_5.js.map → hx-radio-dFjUAost.js.map} +1 -1
  171. package/dist/shared/{hx-rating-i2FL1WUN.js → hx-rating-CGtsejNf.js} +4 -4
  172. package/dist/shared/{hx-rating-i2FL1WUN.js.map → hx-rating-CGtsejNf.js.map} +1 -1
  173. package/dist/shared/{hx-select-vgaBo1Ai.js → hx-select-zfIRr9qM.js} +3 -3
  174. package/dist/shared/{hx-select-vgaBo1Ai.js.map → hx-select-zfIRr9qM.js.map} +1 -1
  175. package/dist/shared/{hx-slider-ydBamYhd.js → hx-slider-m0aEClH1.js} +5 -5
  176. package/dist/shared/{hx-slider-ydBamYhd.js.map → hx-slider-m0aEClH1.js.map} +1 -1
  177. package/dist/shared/{hx-split-button-BeMsmS6N.js → hx-split-button-BxDFfx4D.js} +6 -6
  178. package/dist/shared/{hx-split-button-BeMsmS6N.js.map → hx-split-button-BxDFfx4D.js.map} +1 -1
  179. package/dist/shared/{hx-split-panel-BVG1VWNT.js → hx-split-panel-B-u0Z3mm.js} +3 -9
  180. package/dist/shared/hx-split-panel-B-u0Z3mm.js.map +1 -0
  181. package/dist/shared/{hx-step-DL3PbOzm.js → hx-step-R2rjp1fT.js} +2 -5
  182. package/dist/shared/hx-step-R2rjp1fT.js.map +1 -0
  183. package/dist/shared/{hx-switch-Dougzsgp.js → hx-switch-DvAW4YY-.js} +4 -4
  184. package/dist/shared/{hx-switch-Dougzsgp.js.map → hx-switch-DvAW4YY-.js.map} +1 -1
  185. package/dist/shared/{hx-tab-panel-CbkO9VKu.js → hx-tab-panel-SWOEHuJc.js} +3 -3
  186. package/dist/shared/{hx-tab-panel-CbkO9VKu.js.map → hx-tab-panel-SWOEHuJc.js.map} +1 -1
  187. package/dist/shared/{hx-td-1zwTFLRw.js → hx-td-DnnEMIuA.js} +2 -3
  188. package/dist/shared/hx-td-DnnEMIuA.js.map +1 -0
  189. package/dist/shared/{hx-text-input-ClrrmoE1.js → hx-text-input-Bn7Gn8CI.js} +5 -5
  190. package/dist/shared/{hx-text-input-ClrrmoE1.js.map → hx-text-input-Bn7Gn8CI.js.map} +1 -1
  191. package/dist/shared/{hx-textarea-D9O4U8cb.js → hx-textarea-Jx1xnhgv.js} +7 -7
  192. package/dist/shared/{hx-textarea-D9O4U8cb.js.map → hx-textarea-Jx1xnhgv.js.map} +1 -1
  193. package/dist/shared/{hx-time-picker-m0z4nFB-.js → hx-time-picker-BoEIZwzv.js} +4 -4
  194. package/dist/shared/{hx-time-picker-m0z4nFB-.js.map → hx-time-picker-BoEIZwzv.js.map} +1 -1
  195. package/dist/shared/{hx-toggle-button-Dd8clXB4.js → hx-toggle-button-DPAIh_Xo.js} +24 -24
  196. package/dist/shared/{hx-toggle-button-Dd8clXB4.js.map → hx-toggle-button-DPAIh_Xo.js.map} +1 -1
  197. package/dist/shared/{hx-top-nav-CchPYaiV.js → hx-top-nav-DP6OFS8C.js} +11 -14
  198. package/dist/shared/hx-top-nav-DP6OFS8C.js.map +1 -0
  199. package/dist/shared/{hx-tree-item-DtMC3DTa.js → hx-tree-item-Dt0Ozqyr.js} +4 -10
  200. package/dist/shared/hx-tree-item-Dt0Ozqyr.js.map +1 -0
  201. package/figma-inventory.json +3 -3
  202. package/package.json +2 -2
  203. package/dist/shared/hx-accordion-cnKg4_la.js.map +0 -1
  204. package/dist/shared/hx-button-ebUV8KhT.js.map +0 -1
  205. package/dist/shared/hx-card-CU1QnjNb.js.map +0 -1
  206. package/dist/shared/hx-clinical-status-BmSjfSEN.js.map +0 -1
  207. package/dist/shared/hx-color-picker-DiDLZyvK.js.map +0 -1
  208. package/dist/shared/hx-combobox-DaA5dBC4.js.map +0 -1
  209. package/dist/shared/hx-data-table-Cq3t86Ic.js.map +0 -1
  210. package/dist/shared/hx-dialog-eIS8tcDm.js.map +0 -1
  211. package/dist/shared/hx-drawer-DDhDz7RI.js.map +0 -1
  212. package/dist/shared/hx-file-upload-zTDbjsRw.js.map +0 -1
  213. package/dist/shared/hx-icon-button-BmV97nqz.js.map +0 -1
  214. package/dist/shared/hx-menu-divider-j__TZjH2.js.map +0 -1
  215. package/dist/shared/hx-meter-Cm7k_Ro8.js.map +0 -1
  216. package/dist/shared/hx-nav-LoyEKZQC.js.map +0 -1
  217. package/dist/shared/hx-overflow-menu-BmKyAp5D.js.map +0 -1
  218. package/dist/shared/hx-pagination-Dqw5dorC.js.map +0 -1
  219. package/dist/shared/hx-phi-field-Bf9TdtC1.js.map +0 -1
  220. package/dist/shared/hx-popover-B93rTAfr.js.map +0 -1
  221. package/dist/shared/hx-split-panel-BVG1VWNT.js.map +0 -1
  222. package/dist/shared/hx-step-DL3PbOzm.js.map +0 -1
  223. package/dist/shared/hx-td-1zwTFLRw.js.map +0 -1
  224. package/dist/shared/hx-top-nav-CchPYaiV.js.map +0 -1
  225. package/dist/shared/hx-tree-item-DtMC3DTa.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"hx-select-vgaBo1Ai.js","sources":["../../src/components/hx-select/hx-select.styles.ts","../../src/components/hx-select/hx-select.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSelectStyles = css`\n /* ─── 3-tier token cascade: component → semantic → hardcoded fallback ─── */\n :host {\n display: block;\n\n /* Background & foreground */\n --_bg: var(--hx-select-bg, var(--hx-color-surface-default, #ffffff));\n --_color: var(--hx-select-color, var(--hx-color-text-strong, #202b39));\n --_placeholder-color: var(\n --hx-select-placeholder-color,\n var(--hx-color-text-placeholder, #66787b)\n );\n\n /* Label */\n --_label-color: var(--hx-select-label-color, var(--hx-color-text-strong, #202b39));\n\n /* Border */\n --_border-color: var(--hx-select-border-color, var(--hx-color-border-strong, #8e9c98));\n --_border-radius: var(--hx-select-border-radius, var(--hx-border-radius-md, 0.375rem));\n\n /* Focus ring */\n --_focus-ring-color: var(\n --hx-select-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-400, #6ab1b1))\n );\n\n /* Error */\n --_error-color: var(--hx-select-error-color, var(--hx-color-error-500, #e5493e));\n\n /* Chevron */\n --_chevron-color: var(--hx-select-chevron-color, var(--hx-color-text-muted, #4a5362));\n --_chevron-size: var(--hx-select-chevron-size, 0.5rem);\n\n /* Listbox */\n --_listbox-bg: var(--hx-select-listbox-bg, var(--hx-color-surface-default, #ffffff));\n --_option-hover-bg: var(--hx-select-option-hover-bg, var(--hx-color-primary-50, #ebf8f8));\n --_option-selected-bg: var(\n --hx-select-option-selected-bg,\n var(--hx-color-primary-100, #dbf0f0)\n );\n\n /* Typography */\n --_font-family: var(--hx-select-font-family, var(--hx-font-family-sans, sans-serif));\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 .field {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n font-family: var(--_font-family);\n position: relative;\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(--_label-color);\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .field__required-marker {\n color: var(--hx-select-error-color, var(--hx-color-error-text, #c92a2a));\n font-weight: var(--hx-font-weight-bold, 700);\n }\n\n .field__select-wrapper {\n position: relative;\n display: block;\n }\n\n .field__trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--hx-space-2, 0.5rem);\n width: 100%;\n min-height: var(--hx-input-height-md, var(--hx-size-10, 2.5rem));\n border: var(--hx-border-width-thin, 1px) solid var(--_border-color);\n border-radius: var(--_border-radius);\n background-color: var(--_bg);\n color: var(--_color);\n font-family: inherit;\n font-size: var(--hx-font-size-md, 1rem);\n line-height: var(--hx-line-height-normal, 1.5);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n cursor: pointer;\n text-align: start;\n transition:\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n outline: none;\n }\n\n .field__trigger:focus-visible {\n border-color: var(--_focus-ring-color);\n box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)\n color-mix(\n in srgb,\n var(--_focus-ring-color) calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n .field__trigger[aria-disabled='true'] {\n cursor: not-allowed;\n }\n\n .field__trigger--sm {\n min-height: var(--hx-input-height-sm, var(--hx-size-8, 2rem));\n font-size: var(--hx-font-size-sm, 0.875rem);\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-3, 0.75rem);\n }\n\n .field__trigger--lg {\n min-height: var(--hx-input-height-lg, var(--hx-size-12, 3rem));\n font-size: var(--hx-font-size-lg, 1.125rem);\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n }\n\n .field__trigger-value {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .field__trigger--placeholder .field__trigger-value {\n color: var(--_placeholder-color);\n }\n\n .field__chevron {\n flex-shrink: 0;\n width: calc(var(--_chevron-size) * 1.5);\n height: var(--_chevron-size);\n position: relative;\n color: var(--_chevron-color);\n pointer-events: none;\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n .field__chevron::after {\n content: '';\n position: absolute;\n top: 0;\n left: var(--hx-space-px, 2px);\n width: var(--_chevron-size);\n height: var(--_chevron-size);\n border-inline-end: var(--hx-border-width-thin, 1.5px) solid currentColor;\n border-bottom: var(--hx-border-width-thin, 1.5px) solid currentColor;\n transform: rotate(45deg);\n }\n\n .field--open .field__chevron {\n transform: rotate(180deg);\n }\n\n .field--error .field__trigger {\n border-color: var(--_error-color);\n }\n\n .field--error .field__trigger:focus-visible {\n border-color: var(--_error-color);\n box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)\n color-mix(\n in srgb,\n var(--_error-color) calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n .field__listbox {\n position: absolute;\n top: calc(100% + var(--hx-space-1, 0.25rem));\n left: 0;\n right: 0;\n z-index: var(--hx-z-index-dropdown, 1000);\n background-color: var(--_listbox-bg);\n border: var(--hx-border-width-thin, 1px) solid var(--_border-color);\n border-radius: var(--_border-radius);\n box-shadow: var(\n --hx-select-listbox-shadow,\n 0 4px 16px var(--hx-overlay-neutral-12, rgba(13, 17, 23, 0.12))\n );\n max-height: var(--hx-select-listbox-max-height, 16rem);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .field__listbox[hidden] {\n display: none;\n }\n\n .field__options {\n overflow-y: auto;\n flex: 1;\n padding: var(--hx-space-1, 0.25rem) 0;\n }\n\n .field__option {\n display: flex;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-md, 1rem);\n color: var(--_color);\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n transition: background-color var(--hx-transition-fast, 150ms ease);\n }\n\n .field__option:hover {\n background-color: var(--_option-hover-bg);\n }\n\n .field__option--selected {\n background-color: var(--_option-selected-bg);\n font-weight: var(--hx-font-weight-medium, 500);\n }\n\n .field__option--focused {\n background-color: var(--_option-hover-bg);\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--_focus-ring-color, var(--hx-color-primary-500));\n outline-offset: var(--hx-select-option-focus-ring-offset, -2px);\n }\n\n .field__option--focused.field__option--selected {\n background-color: var(--_option-selected-bg);\n }\n\n .field__option--disabled {\n opacity: var(--hx-opacity-disabled, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .field__option-label {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .field__no-options {\n padding: var(--hx-space-3, 0.75rem);\n text-align: center;\n color: var(--_placeholder-color);\n font-size: var(--hx-font-size-sm, 0.875rem);\n }\n\n .field__select {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n opacity: 0;\n pointer-events: none;\n clip: rect(0, 0, 0, 0);\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-select-error-color, var(--hx-color-error-text, #c92a2a));\n }\n\n @media (prefers-reduced-motion: reduce) {\n .field__trigger,\n .field__chevron,\n .field__option {\n transition: none;\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .field__trigger {\n forced-color-adjust: none;\n background-color: Field;\n color: FieldText;\n border: 2px solid ButtonText;\n }\n\n .field__trigger:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n box-shadow: none;\n }\n\n .field__trigger[aria-disabled='true'] {\n color: GrayText;\n border-color: GrayText;\n }\n\n .field__trigger--placeholder .field__trigger-value {\n color: GrayText;\n }\n\n .field__chevron::after {\n border-color: FieldText;\n }\n\n .field__listbox {\n forced-color-adjust: none;\n background-color: Canvas;\n border: 2px solid CanvasText;\n box-shadow: none;\n }\n\n .field__option {\n color: CanvasText;\n }\n\n .field__option:hover {\n background-color: Highlight;\n color: HighlightText;\n }\n\n .field__option--selected {\n background-color: Highlight;\n color: HighlightText;\n }\n\n .field__option--focused {\n outline-color: Highlight;\n background-color: Highlight;\n color: HighlightText;\n }\n\n .field__option--disabled {\n color: GrayText;\n opacity: 1;\n }\n\n .field--error .field__trigger {\n border-color: LinkText;\n }\n\n :host([disabled]) {\n opacity: 1;\n }\n\n .field__label {\n color: CanvasText;\n }\n\n .field__help-text {\n color: GrayText;\n }\n\n .field__error {\n color: LinkText;\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 { ifDefined } from 'lit/directives/if-defined.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { FormMixin } from '../../mixins/FormMixin.js';\nimport { helixSelectStyles } from './hx-select.styles.js';\nimport { forcedColorsField } from '../../styles/forced-colors.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n// PERF: hx-select exceeds 5KB budget (6.31kb gzipped) -- custom listbox, keyboard navigation, grouped options\n\n// Module-level counter for stable, SSR-safe IDs (avoids Math.random() hydration mismatch)\nconst _nextSelectId = createIdCounter('hx-select');\n\n// ─── Internal option model ───\n\ninterface SelectOption {\n value: string;\n label: string;\n disabled: boolean;\n}\n\n/** Detail for the hx-change event dispatched by hx-select. */\nexport interface HxSelectChangeDetail {\n value: string;\n}\n\n/**\n * A form-associated select component with custom styling, label, error, and\n * help text. Options are provided via slotted `<option>` (and `<optgroup>`)\n * elements in the light DOM. The component wraps a hidden native `<select>`\n * for form participation and provides a combobox trigger for consistent\n * cross-browser styling.\n *\n * @remarks Multi-select is intentionally not supported. This component\n * implements a single-value select (combobox) pattern only. For multi-value\n * selection use a separate multi-select component.\n *\n * @remarks The listbox panel uses `position: absolute` and may be clipped by\n * ancestor elements with `overflow: hidden` or `overflow: auto`. This is a\n * known limitation when embedding the component inside cards, tables, or\n * dialogs. Use the CSS custom property `--hx-select-listbox-shadow` or\n * restructure the containing layout to avoid clipping.\n *\n * @summary Form-associated custom select with label, error, and help text.\n *\n * @tag hx-select\n *\n * @slot - Default slot for `<option>` and `<optgroup>` elements.\n * @slot label - Custom label content (overrides the label property).\n * @slot error - Custom error content (overrides the error property).\n * @slot help-text - Custom help text content (overrides the helpText property).\n *\n * @fires {CustomEvent<{value: string}>} hx-change - Dispatched when the selected option changes.\n *\n * @csspart field - The outer field container.\n * @csspart label - The label element.\n * @csspart select-wrapper - The wrapper containing the trigger and listbox.\n * @csspart select - The hidden native select element (kept for form participation).\n * @csspart trigger - The button that opens/closes the dropdown.\n * @csspart listbox - The dropdown panel containing options.\n * @csspart option - Individual option items in the listbox.\n * @csspart help-text - The help text container.\n * @csspart error - The error message container.\n *\n * @cssprop [--hx-select-bg=var(--hx-color-neutral-0)] - Select background color.\n * @cssprop [--hx-select-color=var(--hx-color-neutral-800)] - Select text color.\n * @cssprop [--hx-select-border-color=var(--hx-color-neutral-300)] - Select border color.\n * @cssprop [--hx-select-border-radius=var(--hx-border-radius-md)] - Select border radius.\n * @cssprop [--hx-select-font-family=var(--hx-font-family-sans)] - Select font family.\n * @cssprop [--hx-select-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-select-error-color=var(--hx-color-error-500)] - Error state color.\n * @cssprop [--hx-select-label-color=var(--hx-color-neutral-700)] - Label text color.\n * @cssprop [--hx-select-chevron-color=var(--hx-color-neutral-500)] - Chevron indicator color.\n * @cssprop [--hx-select-chevron-size=0.5rem] - Chevron indicator size (width/height base unit).\n * @cssprop [--hx-select-listbox-bg=var(--hx-color-neutral-0)] - Listbox panel background color.\n * @cssprop [--hx-select-option-hover-bg=var(--hx-color-primary-50)] - Option hover background color.\n * @cssprop [--hx-select-option-selected-bg=var(--hx-color-primary-100)] - Selected option background color.\n * @cssprop [--hx-select-placeholder-color=var(--hx-color-neutral-400)] - Placeholder text color.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-color-neutral-800] - Color.\n * @cssprop [--hx-color-neutral-400] - Color.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-color-neutral-300] - Color.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-color-error-500] - Color.\n * @cssprop [--hx-color-neutral-500] - Color.\n * @cssprop [--hx-color-primary-50] - Color.\n * @cssprop [--hx-color-primary-100] - Color.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-opacity-disabled] - Opacity.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-font-weight-medium] - Font weight.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-color-error-text] - Color.\n * @cssprop [--hx-font-weight-bold] - Font weight.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-input-height-md] - Height.\n * @cssprop [--hx-size-10] - Size token.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-opacity] - CSS custom property.\n * @cssprop [--hx-input-height-sm] - Height.\n * @cssprop [--hx-size-8] - Size token.\n * @cssprop [--hx-input-height-lg] - Height.\n * @cssprop [--hx-size-12] - Size token.\n * @cssprop [--hx-font-size-lg] - Font size.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-space-px] - Spacing token.\n * @cssprop [--hx-z-index-dropdown] - Z-index layer.\n * @cssprop [--hx-select-listbox-shadow] - CSS custom property.\n * @cssprop [--hx-overlay-neutral-12] - Overlay color.\n * @cssprop [--hx-select-listbox-max-height=16rem] - Height.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-select-option-focus-ring-offset=-2px] - Focus ring styling.\n * @cssprop [--hx-font-size-xs] - Font size.\n */\n@customElement('hx-select')\nexport class HelixSelect extends FormMixin(HelixElement) {\n static override styles = [helixSelectStyles, forcedColorsField];\n\n // ─── Form Association ───\n\n /** Marks this element as form-associated for ElementInternals support. @internal */\n static override formAssociated = true;\n\n // ─── Stable IDs ───\n\n /** @internal */\n private _selectId = _nextSelectId();\n /** @internal */\n private _listboxId = `${this._selectId}-listbox`;\n /** @internal */\n private _labelId = `${this._selectId}-label`;\n /** @internal */\n private _helpTextId = `${this._selectId}-help`;\n /** @internal */\n private _errorId = `${this._selectId}-error`;\n\n // ─── Public Properties ───\n\n /**\n * The visible label text for the select.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Placeholder text shown in the trigger when no option is selected.\n * @attr placeholder\n */\n @property({ type: String })\n placeholder = '';\n\n /**\n * The current value of the select.\n * @attr value\n */\n @property({ type: String, reflect: true })\n value = '';\n\n /**\n * Whether the select is required for form submission.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /**\n * Whether the select is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * The name used for form submission.\n * @attr name\n */\n @property({ type: String, reflect: true })\n name = '';\n\n /**\n * Error message to display. When set, the field enters an error state.\n * @attr error\n */\n @property({ type: String })\n error = '';\n\n /**\n * Help text displayed below the select for guidance.\n * @attr help-text\n */\n @property({ type: String, attribute: 'help-text' })\n helpText = '';\n\n /**\n * Size variant of the select trigger.\n * @attr hx-size\n */\n @property({ type: String, attribute: 'hx-size', reflect: true })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Accessible name for screen readers, if different from the visible label.\n * Uses `accessible-label` attribute instead of `aria-label` to avoid\n * ARIAMixin shadowing on the host element.\n *\n * Note: `mixinDelegatesAria` is not applied to this component because form\n * inputs with associated labels delegate accessible naming via `<label>`\n * association and `aria-labelledby`, not host-level ARIA delegation. The\n * `accessible-label` attribute is a fallback for label-free usage. The value is forwarded to the\n * internal trigger button's `aria-label`.\n * @attr accessible-label\n */\n @property({ type: String, attribute: 'accessible-label' })\n accessibleLabel: string | null = null;\n\n /**\n * Controls whether the dropdown listbox is open.\n * @attr open\n */\n @property({ type: Boolean, reflect: true })\n open = false;\n\n /**\n * Validation message when no option is selected. Override for i18n.\n * @attr label-required\n */\n @property({ attribute: 'label-required' }) labelRequired = 'Please select an option.';\n\n /**\n * Label shown when no options are available. Override for i18n.\n * @attr label-no-options\n */\n @property({ attribute: 'label-no-options' }) labelNoOptions = 'No options found';\n\n // ─── Internal State ───\n\n /** Parsed option models derived from slotted `<option>` and `<optgroup>` elements. @internal */\n @state() private _options: SelectOption[] = [];\n /** Whether the named error slot contains projected content. @internal */\n @state() private _hasErrorSlot = false;\n /** Zero-based index of the keyboard-focused option in the listbox; -1 means none. @internal */\n @state() private _focusedOptionIndex = -1;\n\n // ─── Queries ───\n\n /** Reference to the hidden native select element used for form participation. @internal */\n @query('.field__select')\n private _select: HTMLSelectElement | undefined;\n\n /** Reference to the visible combobox trigger element that receives keyboard focus. @internal */\n @query('.field__trigger')\n private _trigger: HTMLElement | undefined;\n\n // ─── Computed helpers ───\n\n /** @internal */\n private get _displayValue(): string {\n if (!this.value) return '';\n const opt = this._options.find((o) => o.value === this.value);\n return opt ? opt.label : this.value;\n }\n\n // ─── Lifecycle ───\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n // Safety net: remove listener if component is removed while dropdown is open\n document.removeEventListener('click', this._handleOutsideClick);\n // Reset open state to prevent persisted open state on reconnect\n if (this.open) {\n this.open = false;\n this._focusedOptionIndex = -1;\n }\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('open')) {\n if (this.open) {\n document.addEventListener('click', this._handleOutsideClick);\n } else {\n document.removeEventListener('click', this._handleOutsideClick);\n }\n }\n if (changedProperties.has('value')) {\n this._syncNativeSelect();\n this._updateFormValue();\n }\n if (changedProperties.has('size')) {\n const validSizes: string[] = ['sm', 'md', 'lg'];\n if (!validSizes.includes(this.size)) {\n devWarn(\n 'hx-select',\n `Invalid size \"${this.size}\". Expected one of: ${validSizes.join(', ')}.`,\n );\n }\n }\n // Force screen reader re-announcement when error text changes (a11y-v3-005)\n if (changedProperties.has('error') && this.error) {\n const errorEl = this.shadowRoot?.querySelector('[role=\"alert\"]');\n if (errorEl) {\n const msg = this.error;\n requestAnimationFrame(() => {\n errorEl.textContent = '';\n requestAnimationFrame(() => {\n errorEl.textContent = msg;\n });\n });\n }\n }\n }\n\n // ─── Form Integration ───\n\n /** @internal */\n private _updateFormValue(): void {\n this._internals.setFormValue(this.value || null);\n }\n\n /** @internal */\n override _updateValidity(): void {\n if (this.required && !this.value) {\n this._internals.setValidity(\n { valueMissing: true },\n this.error || this.labelRequired,\n this._trigger ?? this._select,\n );\n } else {\n this._internals.setValidity({});\n }\n }\n\n // ─── Form Lifecycle Hooks ───\n\n protected override _onFormReset(): void {\n this.value = '';\n this._internals.setFormValue(null);\n this._resetInteractionState();\n }\n\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 protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Native Select Sync ───\n\n /** @internal */\n private _syncNativeSelect(): void {\n if (!this._select) return;\n if (this.value) {\n this._select.value = this.value;\n }\n }\n\n // ─── Option Syncing from Slot ───\n\n /** @internal */\n private _parseOption(el: HTMLOptionElement): SelectOption {\n return { value: el.value, label: el.textContent?.trim() ?? el.value, disabled: el.disabled };\n }\n\n /**\n * Single-pass slot handler: reads options into _options for the custom\n * listbox AND clones them into the native <select> for form participation.\n * Handles both top-level <option> and <optgroup> children.\n */\n /** @internal */\n private _handleSlotChange(): void {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) return;\n\n const parsed: SelectOption[] = [];\n\n // Remove previously cloned options from native select\n if (this._select) {\n this._select.querySelectorAll('option[data-cloned]').forEach((opt) => opt.remove());\n }\n\n const cloneIntoSelect = (optEl: HTMLOptionElement): void => {\n if (!this._select) return;\n const clone = optEl.cloneNode(true) as HTMLOptionElement;\n clone.setAttribute('data-cloned', '');\n this._select.appendChild(clone);\n };\n\n for (const el of slot.assignedElements({ flatten: true })) {\n if (el instanceof HTMLOptionElement) {\n parsed.push(this._parseOption(el));\n cloneIntoSelect(el);\n } else if (el instanceof HTMLOptGroupElement) {\n for (const child of Array.from(el.children)) {\n if (child instanceof HTMLOptionElement) {\n parsed.push(this._parseOption(child));\n cloneIntoSelect(child);\n }\n }\n }\n }\n\n this._options = parsed;\n\n if (parsed.length === 0) {\n devWarn(\n 'hx-select',\n 'hx-select has no options — add <option> or <optgroup> elements as children.',\n );\n }\n\n if (this._select) {\n if (this.value) {\n this._select.value = this.value;\n } else if (!this.placeholder && parsed.length > 0) {\n this.value = this._select.value;\n this._updateFormValue();\n }\n }\n }\n\n // ─── Slot Change Handlers ───\n\n /** @internal */\n private _handleErrorSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasErrorSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n // ─── Dropdown Control ───\n\n /** @internal */\n private _toggleDropdown(): void {\n if (!this.disabled) {\n this.open = !this.open;\n if (this.open) {\n // Pre-focus the currently selected option (or first enabled) when opening\n const selectedIndex = this._options.findIndex((o) => o.value === this.value);\n this._focusedOptionIndex = selectedIndex >= 0 ? selectedIndex : 0;\n } else {\n this._focusedOptionIndex = -1;\n }\n }\n }\n\n // ─── Keyboard Navigation ───\n\n /** @internal */\n private _handleKeydown(e: KeyboardEvent): void {\n if (this.disabled) return;\n\n const enabledIndices = this._options\n .map((o, i) => ({ o, i }))\n .filter(({ o }) => !o.disabled)\n .map(({ i }) => i);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n this._focusedOptionIndex = enabledIndices.length > 0 ? (enabledIndices[0] ?? 0) : 0;\n break;\n }\n const nextDown = enabledIndices.find((i) => i > this._focusedOptionIndex);\n this._focusedOptionIndex =\n nextDown !== undefined ? nextDown : (enabledIndices[0] ?? this._focusedOptionIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n const lastEnabled = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex = lastEnabled !== undefined ? lastEnabled : 0;\n break;\n }\n const prevUp = [...enabledIndices].reverse().find((i) => i < this._focusedOptionIndex);\n const lastEnabledUp = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex =\n prevUp !== undefined ? prevUp : (lastEnabledUp ?? this._focusedOptionIndex);\n break;\n }\n case 'Home': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n }\n this._focusedOptionIndex = enabledIndices.length > 0 ? (enabledIndices[0] ?? 0) : 0;\n break;\n }\n case 'End': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n }\n const lastEnabled = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex = lastEnabled !== undefined ? lastEnabled : 0;\n break;\n }\n case 'Enter':\n case ' ': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n const selIdx = this._options.findIndex((o) => o.value === this.value);\n this._focusedOptionIndex = selIdx >= 0 ? selIdx : (enabledIndices[0] ?? 0);\n break;\n }\n if (this._focusedOptionIndex >= 0 && this._focusedOptionIndex < this._options.length) {\n const opt = this._options[this._focusedOptionIndex];\n if (opt) this._selectOption(opt);\n }\n break;\n }\n case 'Escape': {\n e.preventDefault();\n this.open = false;\n this._focusedOptionIndex = -1;\n this._trigger?.focus();\n break;\n }\n case 'Tab': {\n // Close the dropdown but allow Tab to move focus naturally\n if (this.open) {\n this.open = false;\n this._focusedOptionIndex = -1;\n }\n break;\n }\n default: {\n // Typeahead: single printable character jumps to first matching option\n if (!e.ctrlKey && !e.metaKey && !e.altKey && e.key.length === 1) {\n const char = e.key.toLowerCase();\n const startIndex = this.open ? this._focusedOptionIndex + 1 : 0;\n const matching = this._options\n .map((o, i) => ({ o, i }))\n .filter(({ o }) => !o.disabled && o.label.toLowerCase().startsWith(char));\n const afterCurrent = matching.find(({ i }) => i >= startIndex);\n const target = afterCurrent ?? matching[0];\n if (target) {\n if (!this.open) {\n this.open = true;\n }\n this._focusedOptionIndex = target.i;\n e.preventDefault();\n }\n }\n break;\n }\n }\n }\n\n // ─── Selection ───\n\n /** @internal */\n private _selectOption(option: SelectOption): void {\n if (option.disabled) return;\n this.value = option.value; // triggers updated() → sync + formValue + validity\n this._handleInteractionInput();\n this._handleInteractionBlur();\n this._dispatchChange();\n this.open = false;\n this._focusedOptionIndex = -1;\n }\n\n // ─── Event Dispatchers ───\n\n /** @internal */\n private _dispatchChange(): void {\n this.dispatchEvent(\n new CustomEvent<{ value: string }>('hx-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n /** @internal */\n private _handleNativeChange(e: Event): void {\n this.value = (e.target as HTMLSelectElement).value; // triggers updated()\n this._handleInteractionInput();\n this._handleInteractionBlur();\n this._dispatchChange();\n }\n\n // ─── Outside Click Handler ───\n\n /** @internal */\n private _handleOutsideClick = (e: MouseEvent): void => {\n if (this.open && !e.composedPath().includes(this)) {\n this.open = false;\n }\n };\n\n // ─── Public Methods ───\n\n /** Moves focus to the visible trigger button. */\n override focus(options?: FocusOptions): void {\n this._trigger?.focus(options);\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _optionId(index: number): string {\n return `hx-select-option-${this._selectId}-${index}`;\n }\n\n /** @internal */\n private _renderOptions() {\n if (this._options.length === 0) {\n return html`<div class=\"field__no-options\">${this.labelNoOptions}</div>`;\n }\n\n return repeat(\n this._options,\n (opt) => opt.value,\n (opt, index) => {\n const isSelected = opt.value === this.value;\n const isFocused = index === this._focusedOptionIndex;\n\n return html`\n <div\n id=${this._optionId(index)}\n part=\"option\"\n role=\"option\"\n class=${classMap({\n field__option: true,\n 'field__option--selected': isSelected,\n 'field__option--focused': isFocused,\n 'field__option--disabled': opt.disabled,\n })}\n aria-selected=${isSelected ? 'true' : 'false'}\n aria-disabled=${opt.disabled ? 'true' : nothing}\n @click=${() => this._selectOption(opt)}\n >\n <span class=\"field__option-label\">${opt.label}</span>\n </div>\n `;\n },\n );\n }\n\n // ─── Main Render ───\n\n override render() {\n const hasError = !!this.error || this._hasErrorSlot;\n\n const fieldClasses = {\n field: true,\n 'field--error': hasError,\n 'field--disabled': this.disabled,\n 'field--required': this.required,\n 'field--open': this.open,\n };\n\n const triggerClasses = {\n field__trigger: true,\n [`field__trigger--${this.size}`]: true,\n 'field__trigger--placeholder': !this.value,\n };\n\n const selectClasses = {\n field__select: true,\n [`field__select--${this.size}`]: true,\n };\n\n const describedBy =\n [\n hasError || this._hasErrorSlot ? this._errorId : null,\n this.helpText ? this._helpTextId : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n\n return html`\n <div part=\"field\" class=${classMap(fieldClasses)}>\n <!-- Label -->\n <slot name=\"label\">\n ${this.label\n ? html`<label\n part=\"label\"\n class=\"field__label\"\n id=${this._labelId}\n for=${this._selectId}\n >\n ${this.label}\n ${this.required\n ? html`<span class=\"field__required-marker\" aria-hidden=\"true\">*</span>`\n : nothing}\n </label>`\n : nothing}\n </slot>\n\n <!-- Select Wrapper: trigger + listbox -->\n <div part=\"select-wrapper\" class=\"field__select-wrapper\">\n <!-- Custom Trigger (combobox — div to avoid native role conflicts per APG) -->\n <div\n part=\"trigger\"\n id=${this._selectId}\n class=${classMap(triggerClasses)}\n role=\"combobox\"\n tabindex=${this.disabled ? '-1' : '0'}\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-haspopup=\"listbox\"\n aria-controls=${this._listboxId}\n aria-activedescendant=${this.open && this._focusedOptionIndex >= 0\n ? this._optionId(this._focusedOptionIndex)\n : nothing}\n aria-invalid=${hasError ? 'true' : nothing}\n aria-describedby=${ifDefined(describedBy)}\n aria-required=${this.required ? 'true' : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-labelledby=${ifDefined(this.label ? this._labelId : undefined)}\n aria-label=${ifDefined(this.accessibleLabel ?? undefined)}\n @click=${this._toggleDropdown}\n @keydown=${this._handleKeydown}\n >\n <span class=\"field__trigger-value\"\n >${this._displayValue || this.placeholder || nothing}</span\n >\n <span class=\"field__chevron\" aria-hidden=\"true\"></span>\n </div>\n\n <!-- Custom Listbox Panel -->\n <div\n part=\"listbox\"\n role=\"listbox\"\n id=${this._listboxId}\n class=\"field__listbox\"\n aria-label=${ifDefined(this.label || this.accessibleLabel || undefined)}\n ?hidden=${!this.open}\n >\n <div class=\"field__options\">${this._renderOptions()}</div>\n </div>\n\n <!-- Hidden native select (form participation + test compat) -->\n <select\n part=\"select\"\n class=${classMap(selectClasses)}\n tabindex=\"-1\"\n aria-hidden=\"true\"\n ?required=${this.required}\n ?disabled=${this.disabled}\n name=${ifDefined(this.name || undefined)}\n aria-label=${ifDefined(this.accessibleLabel ?? undefined)}\n aria-invalid=${hasError ? 'true' : nothing}\n aria-describedby=${ifDefined(describedBy)}\n aria-required=${this.required ? 'true' : nothing}\n @change=${this._handleNativeChange}\n >\n ${this.placeholder\n ? html`<option value=\"\" disabled selected>${this.placeholder}</option>`\n : nothing}\n </select>\n </div>\n\n <!-- Hidden slot (options are read from here) -->\n <slot @slotchange=${this._handleSlotChange} style=\"display:none;\"></slot>\n\n <!-- Error -->\n <slot name=\"error\" @slotchange=${this._handleErrorSlotChange}>\n ${hasError\n ? html`<div part=\"error\" class=\"field__error\" id=${this._errorId} role=\"alert\">\n ${this.error}\n </div>`\n : nothing}\n </slot>\n\n <!-- Help Text -->\n ${this.helpText && !hasError\n ? html`\n <div part=\"help-text\" class=\"field__help-text\" id=${this._helpTextId}>\n <slot name=\"help-text\">${this.helpText}</slot>\n </div>\n `\n : nothing}\n </div>\n `;\n }\n}\n\n/**\n * Per-component event map for type-safe addEventListener on hx-select.\n * The `hx-change` detail is `{ value: string }` only — no `checked` property.\n */\nexport interface HxSelectEventMap {\n 'hx-change': CustomEvent<{ value: string }>;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-select': HelixSelect;\n }\n}\n\nexport type { HelixSelect as HxSelect };\n"],"names":["helixSelectStyles","css","_nextSelectId","createIdCounter","HelixSelect","FormMixin","HelixElement","opt","o","changedProperties","validSizes","devWarn","errorEl","_a","msg","state","_mode","disabled","el","slot","parsed","cloneIntoSelect","optEl","clone","child","selectedIndex","enabledIndices","i","nextDown","lastEnabled","prevUp","lastEnabledUp","selIdx","char","startIndex","matching","target","option","options","index","html","repeat","isSelected","isFocused","classMap","nothing","hasError","fieldClasses","triggerClasses","selectClasses","describedBy","ifDefined","forcedColorsField","__decorateClass","property","query","customElement"],"mappings":";;;;;;;;;;AAEO,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;AA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"}
1
+ {"version":3,"file":"hx-select-zfIRr9qM.js","sources":["../../src/components/hx-select/hx-select.styles.ts","../../src/components/hx-select/hx-select.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSelectStyles = css`\n /* ─── 3-tier token cascade: component → semantic → hardcoded fallback ─── */\n :host {\n display: block;\n\n /* Background & foreground */\n --_bg: var(--hx-select-bg, var(--hx-color-surface-default, #ffffff));\n --_color: var(--hx-select-color, var(--hx-color-text-strong, #202b39));\n --_placeholder-color: var(\n --hx-select-placeholder-color,\n var(--hx-color-text-placeholder, #66787b)\n );\n\n /* Label */\n --_label-color: var(--hx-select-label-color, var(--hx-color-text-strong, #202b39));\n\n /* Border */\n --_border-color: var(--hx-select-border-color, var(--hx-color-border-strong, #66787b));\n --_border-radius: var(--hx-select-border-radius, var(--hx-border-radius-md, 0.375rem));\n\n /* Focus ring */\n --_focus-ring-color: var(\n --hx-select-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))\n );\n\n /* Error */\n --_error-color: var(--hx-select-error-color, var(--hx-color-error-500, #e5493e));\n\n /* Chevron */\n --_chevron-color: var(--hx-select-chevron-color, var(--hx-color-text-muted, #4a5362));\n --_chevron-size: var(--hx-select-chevron-size, 0.5rem);\n\n /* Listbox */\n --_listbox-bg: var(--hx-select-listbox-bg, var(--hx-color-surface-default, #ffffff));\n --_option-hover-bg: var(--hx-select-option-hover-bg, var(--hx-color-primary-50, #ebf8f8));\n --_option-selected-bg: var(\n --hx-select-option-selected-bg,\n var(--hx-color-primary-100, #dbf0f0)\n );\n\n /* Typography */\n --_font-family: var(--hx-select-font-family, var(--hx-font-family-sans, sans-serif));\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 .field {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n font-family: var(--_font-family);\n position: relative;\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(--_label-color);\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .field__required-marker {\n color: var(--hx-select-error-color, var(--hx-color-error-text, #c92a2a));\n font-weight: var(--hx-font-weight-bold, 700);\n }\n\n .field__select-wrapper {\n position: relative;\n display: block;\n }\n\n .field__trigger {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--hx-space-2, 0.5rem);\n width: 100%;\n min-height: var(--hx-input-height-md, var(--hx-size-10, 2.5rem));\n border: var(--hx-border-width-thin, 1px) solid var(--_border-color);\n border-radius: var(--_border-radius);\n background-color: var(--_bg);\n color: var(--_color);\n font-family: inherit;\n font-size: var(--hx-font-size-md, 1rem);\n line-height: var(--hx-line-height-normal, 1.5);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n cursor: pointer;\n text-align: start;\n transition:\n border-color var(--hx-transition-fast, 150ms ease),\n box-shadow var(--hx-transition-fast, 150ms ease);\n outline: none;\n }\n\n .field__trigger:focus-visible {\n border-color: var(--_focus-ring-color);\n box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)\n color-mix(\n in srgb,\n var(--_focus-ring-color) calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n .field__trigger[aria-disabled='true'] {\n cursor: not-allowed;\n }\n\n .field__trigger--sm {\n min-height: var(--hx-input-height-sm, var(--hx-size-8, 2rem));\n font-size: var(--hx-font-size-sm, 0.875rem);\n padding: var(--hx-space-1, 0.25rem) var(--hx-space-3, 0.75rem);\n }\n\n .field__trigger--lg {\n min-height: var(--hx-input-height-lg, var(--hx-size-12, 3rem));\n font-size: var(--hx-font-size-lg, 1.125rem);\n padding: var(--hx-space-3, 0.75rem) var(--hx-space-4, 1rem);\n }\n\n .field__trigger-value {\n flex: 1;\n min-width: 0;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .field__trigger--placeholder .field__trigger-value {\n color: var(--_placeholder-color);\n }\n\n .field__chevron {\n flex-shrink: 0;\n width: calc(var(--_chevron-size) * 1.5);\n height: var(--_chevron-size);\n position: relative;\n color: var(--_chevron-color);\n pointer-events: none;\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n .field__chevron::after {\n content: '';\n position: absolute;\n top: 0;\n left: var(--hx-space-px, 2px);\n width: var(--_chevron-size);\n height: var(--_chevron-size);\n border-inline-end: var(--hx-border-width-thin, 1.5px) solid currentColor;\n border-bottom: var(--hx-border-width-thin, 1.5px) solid currentColor;\n transform: rotate(45deg);\n }\n\n .field--open .field__chevron {\n transform: rotate(180deg);\n }\n\n .field--error .field__trigger {\n border-color: var(--_error-color);\n }\n\n .field--error .field__trigger:focus-visible {\n border-color: var(--_error-color);\n box-shadow: 0 0 0 var(--hx-focus-ring-width, 2px)\n color-mix(\n in srgb,\n var(--_error-color) calc(var(--hx-focus-ring-opacity, 0.25) * 100%),\n transparent\n );\n }\n\n .field__listbox {\n position: absolute;\n top: calc(100% + var(--hx-space-1, 0.25rem));\n left: 0;\n right: 0;\n z-index: var(--hx-z-index-dropdown, 1000);\n background-color: var(--_listbox-bg);\n border: var(--hx-border-width-thin, 1px) solid var(--_border-color);\n border-radius: var(--_border-radius);\n box-shadow: var(\n --hx-select-listbox-shadow,\n 0 4px 16px var(--hx-overlay-neutral-12, rgba(13, 17, 23, 0.12))\n );\n max-height: var(--hx-select-listbox-max-height, 16rem);\n overflow: hidden;\n display: flex;\n flex-direction: column;\n }\n\n .field__listbox[hidden] {\n display: none;\n }\n\n .field__options {\n overflow-y: auto;\n flex: 1;\n padding: var(--hx-space-1, 0.25rem) 0;\n }\n\n .field__option {\n display: flex;\n align-items: center;\n gap: var(--hx-space-2, 0.5rem);\n padding: var(--hx-space-2, 0.5rem) var(--hx-space-3, 0.75rem);\n font-size: var(--hx-font-size-md, 1rem);\n color: var(--_color);\n cursor: pointer;\n user-select: none;\n -webkit-user-select: none;\n transition: background-color var(--hx-transition-fast, 150ms ease);\n }\n\n .field__option:hover {\n background-color: var(--_option-hover-bg);\n }\n\n .field__option--selected {\n background-color: var(--_option-selected-bg);\n font-weight: var(--hx-font-weight-medium, 500);\n }\n\n .field__option--focused {\n background-color: var(--_option-hover-bg);\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--_focus-ring-color, var(--hx-color-primary-500));\n outline-offset: var(--hx-select-option-focus-ring-offset, -2px);\n }\n\n .field__option--focused.field__option--selected {\n background-color: var(--_option-selected-bg);\n }\n\n .field__option--disabled {\n opacity: var(--hx-opacity-disabled, 0.5);\n cursor: not-allowed;\n pointer-events: none;\n }\n\n .field__option-label {\n flex: 1;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n }\n\n .field__no-options {\n padding: var(--hx-space-3, 0.75rem);\n text-align: center;\n color: var(--_placeholder-color);\n font-size: var(--hx-font-size-sm, 0.875rem);\n }\n\n .field__select {\n position: absolute;\n width: 1px;\n height: 1px;\n overflow: hidden;\n opacity: 0;\n pointer-events: none;\n clip: rect(0, 0, 0, 0);\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-select-error-color, var(--hx-color-error-text, #c92a2a));\n }\n\n @media (prefers-reduced-motion: reduce) {\n .field__trigger,\n .field__chevron,\n .field__option {\n transition: none;\n }\n }\n\n /* ─── High Contrast Mode (forced-colors) ─── */\n\n @media (forced-colors: active) {\n .field__trigger {\n forced-color-adjust: none;\n background-color: Field;\n color: FieldText;\n border: 2px solid ButtonText;\n }\n\n .field__trigger:focus-visible {\n outline: 3px solid Highlight;\n outline-offset: 2px;\n box-shadow: none;\n }\n\n .field__trigger[aria-disabled='true'] {\n color: GrayText;\n border-color: GrayText;\n }\n\n .field__trigger--placeholder .field__trigger-value {\n color: GrayText;\n }\n\n .field__chevron::after {\n border-color: FieldText;\n }\n\n .field__listbox {\n forced-color-adjust: none;\n background-color: Canvas;\n border: 2px solid CanvasText;\n box-shadow: none;\n }\n\n .field__option {\n color: CanvasText;\n }\n\n .field__option:hover {\n background-color: Highlight;\n color: HighlightText;\n }\n\n .field__option--selected {\n background-color: Highlight;\n color: HighlightText;\n }\n\n .field__option--focused {\n outline-color: Highlight;\n background-color: Highlight;\n color: HighlightText;\n }\n\n .field__option--disabled {\n color: GrayText;\n opacity: 1;\n }\n\n .field--error .field__trigger {\n border-color: LinkText;\n }\n\n :host([disabled]) {\n opacity: 1;\n }\n\n .field__label {\n color: CanvasText;\n }\n\n .field__help-text {\n color: GrayText;\n }\n\n .field__error {\n color: LinkText;\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 { ifDefined } from 'lit/directives/if-defined.js';\nimport { repeat } from 'lit/directives/repeat.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { FormMixin } from '../../mixins/FormMixin.js';\nimport { helixSelectStyles } from './hx-select.styles.js';\nimport { forcedColorsField } from '../../styles/forced-colors.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n// PERF: hx-select exceeds 5KB budget (6.31kb gzipped) -- custom listbox, keyboard navigation, grouped options\n\n// Module-level counter for stable, SSR-safe IDs (avoids Math.random() hydration mismatch)\nconst _nextSelectId = createIdCounter('hx-select');\n\n// ─── Internal option model ───\n\ninterface SelectOption {\n value: string;\n label: string;\n disabled: boolean;\n}\n\n/** Detail for the hx-change event dispatched by hx-select. */\nexport interface HxSelectChangeDetail {\n value: string;\n}\n\n/**\n * A form-associated select component with custom styling, label, error, and\n * help text. Options are provided via slotted `<option>` (and `<optgroup>`)\n * elements in the light DOM. The component wraps a hidden native `<select>`\n * for form participation and provides a combobox trigger for consistent\n * cross-browser styling.\n *\n * @remarks Multi-select is intentionally not supported. This component\n * implements a single-value select (combobox) pattern only. For multi-value\n * selection use a separate multi-select component.\n *\n * @remarks The listbox panel uses `position: absolute` and may be clipped by\n * ancestor elements with `overflow: hidden` or `overflow: auto`. This is a\n * known limitation when embedding the component inside cards, tables, or\n * dialogs. Use the CSS custom property `--hx-select-listbox-shadow` or\n * restructure the containing layout to avoid clipping.\n *\n * @summary Form-associated custom select with label, error, and help text.\n *\n * @tag hx-select\n *\n * @slot - Default slot for `<option>` and `<optgroup>` elements.\n * @slot label - Custom label content (overrides the label property).\n * @slot error - Custom error content (overrides the error property).\n * @slot help-text - Custom help text content (overrides the helpText property).\n *\n * @fires {CustomEvent<{value: string}>} hx-change - Dispatched when the selected option changes.\n *\n * @csspart field - The outer field container.\n * @csspart label - The label element.\n * @csspart select-wrapper - The wrapper containing the trigger and listbox.\n * @csspart select - The hidden native select element (kept for form participation).\n * @csspart trigger - The button that opens/closes the dropdown.\n * @csspart listbox - The dropdown panel containing options.\n * @csspart option - Individual option items in the listbox.\n * @csspart help-text - The help text container.\n * @csspart error - The error message container.\n *\n * @cssprop [--hx-select-bg=var(--hx-color-neutral-0)] - Select background color.\n * @cssprop [--hx-select-color=var(--hx-color-neutral-800)] - Select text color.\n * @cssprop [--hx-select-border-color=var(--hx-color-neutral-300)] - Select border color.\n * @cssprop [--hx-select-border-radius=var(--hx-border-radius-md)] - Select border radius.\n * @cssprop [--hx-select-font-family=var(--hx-font-family-sans)] - Select font family.\n * @cssprop [--hx-select-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-select-error-color=var(--hx-color-error-500)] - Error state color.\n * @cssprop [--hx-select-label-color=var(--hx-color-neutral-700)] - Label text color.\n * @cssprop [--hx-select-chevron-color=var(--hx-color-neutral-500)] - Chevron indicator color.\n * @cssprop [--hx-select-chevron-size=0.5rem] - Chevron indicator size (width/height base unit).\n * @cssprop [--hx-select-listbox-bg=var(--hx-color-neutral-0)] - Listbox panel background color.\n * @cssprop [--hx-select-option-hover-bg=var(--hx-color-primary-50)] - Option hover background color.\n * @cssprop [--hx-select-option-selected-bg=var(--hx-color-primary-100)] - Selected option background color.\n * @cssprop [--hx-select-placeholder-color=var(--hx-color-neutral-400)] - Placeholder text color.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-color-neutral-800] - Color.\n * @cssprop [--hx-color-neutral-400] - Color.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-color-neutral-300] - Color.\n * @cssprop [--hx-border-radius-md] - CSS custom property.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-color-error-500] - Color.\n * @cssprop [--hx-color-neutral-500] - Color.\n * @cssprop [--hx-color-primary-50] - Color.\n * @cssprop [--hx-color-primary-100] - Color.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-opacity-disabled] - Opacity.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-font-weight-medium] - Font weight.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-color-error-text] - Color.\n * @cssprop [--hx-font-weight-bold] - Font weight.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-input-height-md] - Height.\n * @cssprop [--hx-size-10] - Size token.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-font-size-md] - Font size.\n * @cssprop [--hx-space-3] - Spacing token.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-opacity] - CSS custom property.\n * @cssprop [--hx-input-height-sm] - Height.\n * @cssprop [--hx-size-8] - Size token.\n * @cssprop [--hx-input-height-lg] - Height.\n * @cssprop [--hx-size-12] - Size token.\n * @cssprop [--hx-font-size-lg] - Font size.\n * @cssprop [--hx-space-4] - Spacing token.\n * @cssprop [--hx-space-px] - Spacing token.\n * @cssprop [--hx-z-index-dropdown] - Z-index layer.\n * @cssprop [--hx-select-listbox-shadow] - CSS custom property.\n * @cssprop [--hx-overlay-neutral-12] - Overlay color.\n * @cssprop [--hx-select-listbox-max-height=16rem] - Height.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-select-option-focus-ring-offset=-2px] - Focus ring styling.\n * @cssprop [--hx-font-size-xs] - Font size.\n */\n@customElement('hx-select')\nexport class HelixSelect extends FormMixin(HelixElement) {\n static override styles = [helixSelectStyles, forcedColorsField];\n\n // ─── Form Association ───\n\n /** Marks this element as form-associated for ElementInternals support. @internal */\n static override formAssociated = true;\n\n // ─── Stable IDs ───\n\n /** @internal */\n private _selectId = _nextSelectId();\n /** @internal */\n private _listboxId = `${this._selectId}-listbox`;\n /** @internal */\n private _labelId = `${this._selectId}-label`;\n /** @internal */\n private _helpTextId = `${this._selectId}-help`;\n /** @internal */\n private _errorId = `${this._selectId}-error`;\n\n // ─── Public Properties ───\n\n /**\n * The visible label text for the select.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Placeholder text shown in the trigger when no option is selected.\n * @attr placeholder\n */\n @property({ type: String })\n placeholder = '';\n\n /**\n * The current value of the select.\n * @attr value\n */\n @property({ type: String, reflect: true })\n value = '';\n\n /**\n * Whether the select is required for form submission.\n * @attr required\n */\n @property({ type: Boolean, reflect: true })\n required = false;\n\n /**\n * Whether the select is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * The name used for form submission.\n * @attr name\n */\n @property({ type: String, reflect: true })\n name = '';\n\n /**\n * Error message to display. When set, the field enters an error state.\n * @attr error\n */\n @property({ type: String })\n error = '';\n\n /**\n * Help text displayed below the select for guidance.\n * @attr help-text\n */\n @property({ type: String, attribute: 'help-text' })\n helpText = '';\n\n /**\n * Size variant of the select trigger.\n * @attr hx-size\n */\n @property({ type: String, attribute: 'hx-size', reflect: true })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Accessible name for screen readers, if different from the visible label.\n * Uses `accessible-label` attribute instead of `aria-label` to avoid\n * ARIAMixin shadowing on the host element.\n *\n * Note: `mixinDelegatesAria` is not applied to this component because form\n * inputs with associated labels delegate accessible naming via `<label>`\n * association and `aria-labelledby`, not host-level ARIA delegation. The\n * `accessible-label` attribute is a fallback for label-free usage. The value is forwarded to the\n * internal trigger button's `aria-label`.\n * @attr accessible-label\n */\n @property({ type: String, attribute: 'accessible-label' })\n accessibleLabel: string | null = null;\n\n /**\n * Controls whether the dropdown listbox is open.\n * @attr open\n */\n @property({ type: Boolean, reflect: true })\n open = false;\n\n /**\n * Validation message when no option is selected. Override for i18n.\n * @attr label-required\n */\n @property({ attribute: 'label-required' }) labelRequired = 'Please select an option.';\n\n /**\n * Label shown when no options are available. Override for i18n.\n * @attr label-no-options\n */\n @property({ attribute: 'label-no-options' }) labelNoOptions = 'No options found';\n\n // ─── Internal State ───\n\n /** Parsed option models derived from slotted `<option>` and `<optgroup>` elements. @internal */\n @state() private _options: SelectOption[] = [];\n /** Whether the named error slot contains projected content. @internal */\n @state() private _hasErrorSlot = false;\n /** Zero-based index of the keyboard-focused option in the listbox; -1 means none. @internal */\n @state() private _focusedOptionIndex = -1;\n\n // ─── Queries ───\n\n /** Reference to the hidden native select element used for form participation. @internal */\n @query('.field__select')\n private _select: HTMLSelectElement | undefined;\n\n /** Reference to the visible combobox trigger element that receives keyboard focus. @internal */\n @query('.field__trigger')\n private _trigger: HTMLElement | undefined;\n\n // ─── Computed helpers ───\n\n /** @internal */\n private get _displayValue(): string {\n if (!this.value) return '';\n const opt = this._options.find((o) => o.value === this.value);\n return opt ? opt.label : this.value;\n }\n\n // ─── Lifecycle ───\n\n override disconnectedCallback(): void {\n super.disconnectedCallback();\n // Safety net: remove listener if component is removed while dropdown is open\n document.removeEventListener('click', this._handleOutsideClick);\n // Reset open state to prevent persisted open state on reconnect\n if (this.open) {\n this.open = false;\n this._focusedOptionIndex = -1;\n }\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n if (changedProperties.has('open')) {\n if (this.open) {\n document.addEventListener('click', this._handleOutsideClick);\n } else {\n document.removeEventListener('click', this._handleOutsideClick);\n }\n }\n if (changedProperties.has('value')) {\n this._syncNativeSelect();\n this._updateFormValue();\n }\n if (changedProperties.has('size')) {\n const validSizes: string[] = ['sm', 'md', 'lg'];\n if (!validSizes.includes(this.size)) {\n devWarn(\n 'hx-select',\n `Invalid size \"${this.size}\". Expected one of: ${validSizes.join(', ')}.`,\n );\n }\n }\n // Force screen reader re-announcement when error text changes (a11y-v3-005)\n if (changedProperties.has('error') && this.error) {\n const errorEl = this.shadowRoot?.querySelector('[role=\"alert\"]');\n if (errorEl) {\n const msg = this.error;\n requestAnimationFrame(() => {\n errorEl.textContent = '';\n requestAnimationFrame(() => {\n errorEl.textContent = msg;\n });\n });\n }\n }\n }\n\n // ─── Form Integration ───\n\n /** @internal */\n private _updateFormValue(): void {\n this._internals.setFormValue(this.value || null);\n }\n\n /** @internal */\n override _updateValidity(): void {\n if (this.required && !this.value) {\n this._internals.setValidity(\n { valueMissing: true },\n this.error || this.labelRequired,\n this._trigger ?? this._select,\n );\n } else {\n this._internals.setValidity({});\n }\n }\n\n // ─── Form Lifecycle Hooks ───\n\n protected override _onFormReset(): void {\n this.value = '';\n this._internals.setFormValue(null);\n this._resetInteractionState();\n }\n\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 protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Native Select Sync ───\n\n /** @internal */\n private _syncNativeSelect(): void {\n if (!this._select) return;\n if (this.value) {\n this._select.value = this.value;\n }\n }\n\n // ─── Option Syncing from Slot ───\n\n /** @internal */\n private _parseOption(el: HTMLOptionElement): SelectOption {\n return { value: el.value, label: el.textContent?.trim() ?? el.value, disabled: el.disabled };\n }\n\n /**\n * Single-pass slot handler: reads options into _options for the custom\n * listbox AND clones them into the native <select> for form participation.\n * Handles both top-level <option> and <optgroup> children.\n */\n /** @internal */\n private _handleSlotChange(): void {\n const slot = this.shadowRoot?.querySelector<HTMLSlotElement>('slot:not([name])');\n if (!slot) return;\n\n const parsed: SelectOption[] = [];\n\n // Remove previously cloned options from native select\n if (this._select) {\n this._select.querySelectorAll('option[data-cloned]').forEach((opt) => opt.remove());\n }\n\n const cloneIntoSelect = (optEl: HTMLOptionElement): void => {\n if (!this._select) return;\n const clone = optEl.cloneNode(true) as HTMLOptionElement;\n clone.setAttribute('data-cloned', '');\n this._select.appendChild(clone);\n };\n\n for (const el of slot.assignedElements({ flatten: true })) {\n if (el instanceof HTMLOptionElement) {\n parsed.push(this._parseOption(el));\n cloneIntoSelect(el);\n } else if (el instanceof HTMLOptGroupElement) {\n for (const child of Array.from(el.children)) {\n if (child instanceof HTMLOptionElement) {\n parsed.push(this._parseOption(child));\n cloneIntoSelect(child);\n }\n }\n }\n }\n\n this._options = parsed;\n\n if (parsed.length === 0) {\n devWarn(\n 'hx-select',\n 'hx-select has no options — add <option> or <optgroup> elements as children.',\n );\n }\n\n if (this._select) {\n if (this.value) {\n this._select.value = this.value;\n } else if (!this.placeholder && parsed.length > 0) {\n this.value = this._select.value;\n this._updateFormValue();\n }\n }\n }\n\n // ─── Slot Change Handlers ───\n\n /** @internal */\n private _handleErrorSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasErrorSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n // ─── Dropdown Control ───\n\n /** @internal */\n private _toggleDropdown(): void {\n if (!this.disabled) {\n this.open = !this.open;\n if (this.open) {\n // Pre-focus the currently selected option (or first enabled) when opening\n const selectedIndex = this._options.findIndex((o) => o.value === this.value);\n this._focusedOptionIndex = selectedIndex >= 0 ? selectedIndex : 0;\n } else {\n this._focusedOptionIndex = -1;\n }\n }\n }\n\n // ─── Keyboard Navigation ───\n\n /** @internal */\n private _handleKeydown(e: KeyboardEvent): void {\n if (this.disabled) return;\n\n const enabledIndices = this._options\n .map((o, i) => ({ o, i }))\n .filter(({ o }) => !o.disabled)\n .map(({ i }) => i);\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n this._focusedOptionIndex = enabledIndices.length > 0 ? (enabledIndices[0] ?? 0) : 0;\n break;\n }\n const nextDown = enabledIndices.find((i) => i > this._focusedOptionIndex);\n this._focusedOptionIndex =\n nextDown !== undefined ? nextDown : (enabledIndices[0] ?? this._focusedOptionIndex);\n break;\n }\n case 'ArrowUp': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n const lastEnabled = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex = lastEnabled !== undefined ? lastEnabled : 0;\n break;\n }\n const prevUp = [...enabledIndices].reverse().find((i) => i < this._focusedOptionIndex);\n const lastEnabledUp = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex =\n prevUp !== undefined ? prevUp : (lastEnabledUp ?? this._focusedOptionIndex);\n break;\n }\n case 'Home': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n }\n this._focusedOptionIndex = enabledIndices.length > 0 ? (enabledIndices[0] ?? 0) : 0;\n break;\n }\n case 'End': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n }\n const lastEnabled = enabledIndices[enabledIndices.length - 1];\n this._focusedOptionIndex = lastEnabled !== undefined ? lastEnabled : 0;\n break;\n }\n case 'Enter':\n case ' ': {\n e.preventDefault();\n if (!this.open) {\n this.open = true;\n const selIdx = this._options.findIndex((o) => o.value === this.value);\n this._focusedOptionIndex = selIdx >= 0 ? selIdx : (enabledIndices[0] ?? 0);\n break;\n }\n if (this._focusedOptionIndex >= 0 && this._focusedOptionIndex < this._options.length) {\n const opt = this._options[this._focusedOptionIndex];\n if (opt) this._selectOption(opt);\n }\n break;\n }\n case 'Escape': {\n e.preventDefault();\n this.open = false;\n this._focusedOptionIndex = -1;\n this._trigger?.focus();\n break;\n }\n case 'Tab': {\n // Close the dropdown but allow Tab to move focus naturally\n if (this.open) {\n this.open = false;\n this._focusedOptionIndex = -1;\n }\n break;\n }\n default: {\n // Typeahead: single printable character jumps to first matching option\n if (!e.ctrlKey && !e.metaKey && !e.altKey && e.key.length === 1) {\n const char = e.key.toLowerCase();\n const startIndex = this.open ? this._focusedOptionIndex + 1 : 0;\n const matching = this._options\n .map((o, i) => ({ o, i }))\n .filter(({ o }) => !o.disabled && o.label.toLowerCase().startsWith(char));\n const afterCurrent = matching.find(({ i }) => i >= startIndex);\n const target = afterCurrent ?? matching[0];\n if (target) {\n if (!this.open) {\n this.open = true;\n }\n this._focusedOptionIndex = target.i;\n e.preventDefault();\n }\n }\n break;\n }\n }\n }\n\n // ─── Selection ───\n\n /** @internal */\n private _selectOption(option: SelectOption): void {\n if (option.disabled) return;\n this.value = option.value; // triggers updated() → sync + formValue + validity\n this._handleInteractionInput();\n this._handleInteractionBlur();\n this._dispatchChange();\n this.open = false;\n this._focusedOptionIndex = -1;\n }\n\n // ─── Event Dispatchers ───\n\n /** @internal */\n private _dispatchChange(): void {\n this.dispatchEvent(\n new CustomEvent<{ value: string }>('hx-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n /** @internal */\n private _handleNativeChange(e: Event): void {\n this.value = (e.target as HTMLSelectElement).value; // triggers updated()\n this._handleInteractionInput();\n this._handleInteractionBlur();\n this._dispatchChange();\n }\n\n // ─── Outside Click Handler ───\n\n /** @internal */\n private _handleOutsideClick = (e: MouseEvent): void => {\n if (this.open && !e.composedPath().includes(this)) {\n this.open = false;\n }\n };\n\n // ─── Public Methods ───\n\n /** Moves focus to the visible trigger button. */\n override focus(options?: FocusOptions): void {\n this._trigger?.focus(options);\n }\n\n // ─── Render Helpers ───\n\n /** @internal */\n private _optionId(index: number): string {\n return `hx-select-option-${this._selectId}-${index}`;\n }\n\n /** @internal */\n private _renderOptions() {\n if (this._options.length === 0) {\n return html`<div class=\"field__no-options\">${this.labelNoOptions}</div>`;\n }\n\n return repeat(\n this._options,\n (opt) => opt.value,\n (opt, index) => {\n const isSelected = opt.value === this.value;\n const isFocused = index === this._focusedOptionIndex;\n\n return html`\n <div\n id=${this._optionId(index)}\n part=\"option\"\n role=\"option\"\n class=${classMap({\n field__option: true,\n 'field__option--selected': isSelected,\n 'field__option--focused': isFocused,\n 'field__option--disabled': opt.disabled,\n })}\n aria-selected=${isSelected ? 'true' : 'false'}\n aria-disabled=${opt.disabled ? 'true' : nothing}\n @click=${() => this._selectOption(opt)}\n >\n <span class=\"field__option-label\">${opt.label}</span>\n </div>\n `;\n },\n );\n }\n\n // ─── Main Render ───\n\n override render() {\n const hasError = !!this.error || this._hasErrorSlot;\n\n const fieldClasses = {\n field: true,\n 'field--error': hasError,\n 'field--disabled': this.disabled,\n 'field--required': this.required,\n 'field--open': this.open,\n };\n\n const triggerClasses = {\n field__trigger: true,\n [`field__trigger--${this.size}`]: true,\n 'field__trigger--placeholder': !this.value,\n };\n\n const selectClasses = {\n field__select: true,\n [`field__select--${this.size}`]: true,\n };\n\n const describedBy =\n [\n hasError || this._hasErrorSlot ? this._errorId : null,\n this.helpText ? this._helpTextId : null,\n ]\n .filter(Boolean)\n .join(' ') || undefined;\n\n return html`\n <div part=\"field\" class=${classMap(fieldClasses)}>\n <!-- Label -->\n <slot name=\"label\">\n ${this.label\n ? html`<label\n part=\"label\"\n class=\"field__label\"\n id=${this._labelId}\n for=${this._selectId}\n >\n ${this.label}\n ${this.required\n ? html`<span class=\"field__required-marker\" aria-hidden=\"true\">*</span>`\n : nothing}\n </label>`\n : nothing}\n </slot>\n\n <!-- Select Wrapper: trigger + listbox -->\n <div part=\"select-wrapper\" class=\"field__select-wrapper\">\n <!-- Custom Trigger (combobox — div to avoid native role conflicts per APG) -->\n <div\n part=\"trigger\"\n id=${this._selectId}\n class=${classMap(triggerClasses)}\n role=\"combobox\"\n tabindex=${this.disabled ? '-1' : '0'}\n aria-expanded=${this.open ? 'true' : 'false'}\n aria-haspopup=\"listbox\"\n aria-controls=${this._listboxId}\n aria-activedescendant=${this.open && this._focusedOptionIndex >= 0\n ? this._optionId(this._focusedOptionIndex)\n : nothing}\n aria-invalid=${hasError ? 'true' : nothing}\n aria-describedby=${ifDefined(describedBy)}\n aria-required=${this.required ? 'true' : nothing}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-labelledby=${ifDefined(this.label ? this._labelId : undefined)}\n aria-label=${ifDefined(this.accessibleLabel ?? undefined)}\n @click=${this._toggleDropdown}\n @keydown=${this._handleKeydown}\n >\n <span class=\"field__trigger-value\"\n >${this._displayValue || this.placeholder || nothing}</span\n >\n <span class=\"field__chevron\" aria-hidden=\"true\"></span>\n </div>\n\n <!-- Custom Listbox Panel -->\n <div\n part=\"listbox\"\n role=\"listbox\"\n id=${this._listboxId}\n class=\"field__listbox\"\n aria-label=${ifDefined(this.label || this.accessibleLabel || undefined)}\n ?hidden=${!this.open}\n >\n <div class=\"field__options\">${this._renderOptions()}</div>\n </div>\n\n <!-- Hidden native select (form participation + test compat) -->\n <select\n part=\"select\"\n class=${classMap(selectClasses)}\n tabindex=\"-1\"\n aria-hidden=\"true\"\n ?required=${this.required}\n ?disabled=${this.disabled}\n name=${ifDefined(this.name || undefined)}\n aria-label=${ifDefined(this.accessibleLabel ?? undefined)}\n aria-invalid=${hasError ? 'true' : nothing}\n aria-describedby=${ifDefined(describedBy)}\n aria-required=${this.required ? 'true' : nothing}\n @change=${this._handleNativeChange}\n >\n ${this.placeholder\n ? html`<option value=\"\" disabled selected>${this.placeholder}</option>`\n : nothing}\n </select>\n </div>\n\n <!-- Hidden slot (options are read from here) -->\n <slot @slotchange=${this._handleSlotChange} style=\"display:none;\"></slot>\n\n <!-- Error -->\n <slot name=\"error\" @slotchange=${this._handleErrorSlotChange}>\n ${hasError\n ? html`<div part=\"error\" class=\"field__error\" id=${this._errorId} role=\"alert\">\n ${this.error}\n </div>`\n : nothing}\n </slot>\n\n <!-- Help Text -->\n ${this.helpText && !hasError\n ? html`\n <div part=\"help-text\" class=\"field__help-text\" id=${this._helpTextId}>\n <slot name=\"help-text\">${this.helpText}</slot>\n </div>\n `\n : nothing}\n </div>\n `;\n }\n}\n\n/**\n * Per-component event map for type-safe addEventListener on hx-select.\n * The `hx-change` detail is `{ value: string }` only — no `checked` property.\n */\nexport interface HxSelectEventMap {\n 'hx-change': CustomEvent<{ value: string }>;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-select': HelixSelect;\n }\n}\n\nexport type { HelixSelect as HxSelect };\n"],"names":["helixSelectStyles","css","_nextSelectId","createIdCounter","HelixSelect","FormMixin","HelixElement","opt","o","changedProperties","validSizes","devWarn","errorEl","_a","msg","state","_mode","disabled","el","slot","parsed","cloneIntoSelect","optEl","clone","child","selectedIndex","enabledIndices","i","nextDown","lastEnabled","prevUp","lastEnabledUp","selIdx","char","startIndex","matching","target","option","options","index","html","repeat","isSelected","isFocused","classMap","nothing","hasError","fieldClasses","triggerClasses","selectClasses","describedBy","ifDefined","forcedColorsField","__decorateClass","property","query","customElement"],"mappings":";;;;;;;;;;AAEO,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;AA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"}
@@ -212,7 +212,7 @@ const z = b`
212
212
  0 0 0 var(--hx-focus-ring-width, 2px)
213
213
  var(
214
214
  --hx-slider-focus-ring-color,
215
- var(--hx-focus-ring-color, var(--hx-color-primary-400, #6ab1b1))
215
+ var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
216
216
  ),
217
217
  var(--hx-slider-thumb-shadow, var(--hx-shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05)));
218
218
  }
@@ -269,7 +269,7 @@ const z = b`
269
269
  top: 0;
270
270
  width: var(--hx-border-width-thin, 1px);
271
271
  height: 100%;
272
- background-color: var(--hx-slider-tick-color, var(--hx-color-border-strong, #8e9c98));
272
+ background-color: var(--hx-slider-tick-color, var(--hx-color-border-strong, #66787b));
273
273
  transform: translateX(-50%);
274
274
  }
275
275
 
@@ -295,13 +295,13 @@ const z = b`
295
295
  /* ─── Disabled state ─── */
296
296
 
297
297
  .slider--disabled .slider__fill {
298
- background-color: var(--hx-slider-disabled-fill-bg, var(--hx-color-border-strong, #8e9c98));
298
+ background-color: var(--hx-slider-disabled-fill-bg, var(--hx-color-border-strong, #66787b));
299
299
  }
300
300
 
301
301
  .slider--disabled .slider__thumb-visual {
302
302
  border-color: var(
303
303
  --hx-slider-disabled-thumb-border-color,
304
- var(--hx-color-border-strong, #8e9c98)
304
+ var(--hx-color-border-strong, #66787b)
305
305
  );
306
306
  }
307
307
  `;
@@ -576,4 +576,4 @@ i = s([
576
576
  export {
577
577
  i as H
578
578
  };
579
- //# sourceMappingURL=hx-slider-ydBamYhd.js.map
579
+ //# sourceMappingURL=hx-slider-m0aEClH1.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"hx-slider-ydBamYhd.js","sources":["../../src/components/hx-slider/hx-slider.styles.ts","../../src/components/hx-slider/hx-slider.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSliderStyles = css`\n :host {\n display: block;\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 /* ─── Container ─── */\n\n .slider {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n font-family: var(--hx-slider-font-family, var(--hx-font-family-sans, sans-serif));\n }\n\n /* ─── Label Row ─── */\n\n .slider__label-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--hx-space-2, 0.5rem);\n }\n\n .slider__label {\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n color: var(--hx-slider-label-color, var(--hx-color-text-strong, #202b39));\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .slider__value-display {\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n color: var(--hx-slider-value-color, var(--hx-color-text-secondary, #313e4b));\n line-height: var(--hx-line-height-normal, 1.5);\n font-variant-numeric: tabular-nums;\n min-width: var(--hx-size-8, 2rem);\n text-align: end;\n }\n\n /* ─── Track Container ─── */\n\n .slider__track-container {\n position: relative;\n width: 100%;\n }\n\n .slider__track {\n position: relative;\n width: 100%;\n border-radius: var(--hx-border-radius-full, 9999px);\n background-color: var(--hx-slider-track-bg, var(--hx-color-border-default, #d6dbd5));\n overflow: visible;\n }\n\n /* ─── Size: sm ─── */\n\n .slider--sm .slider__track {\n height: var(--hx-slider-track-height-sm, var(--hx-size-1, 0.25rem));\n }\n\n .slider--sm .slider__input {\n height: var(--hx-slider-track-height-sm, var(--hx-size-1, 0.25rem));\n }\n\n /* ─── Size: md ─── */\n\n .slider--md .slider__track {\n height: var(--hx-slider-track-height-md, var(--hx-size-1-5, 0.375rem));\n }\n\n .slider--md .slider__input {\n height: var(--hx-slider-track-height-md, var(--hx-size-1-5, 0.375rem));\n }\n\n /* ─── Size: lg ─── */\n\n .slider--lg .slider__track {\n height: var(--hx-slider-track-height-lg, var(--hx-space-2, 0.5rem));\n }\n\n .slider--lg .slider__input {\n height: var(--hx-slider-track-height-lg, var(--hx-space-2, 0.5rem));\n }\n\n /* ─── Fill ─── */\n\n .slider__fill {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n border-radius: var(--hx-border-radius-full, 9999px);\n background-color: var(--hx-slider-fill-bg, var(--hx-color-primary-500, #429797));\n pointer-events: none;\n transform-origin: left center;\n transform: scaleX(var(--_fill-ratio, 0));\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n /* Suppress fill animation on initial render — only animate on user interaction */\n :host(:not([data-ready])) .slider__fill {\n transition: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .slider__fill {\n transition: none;\n }\n }\n\n /* ─── Native Range Input ─── */\n\n .slider__input {\n position: absolute;\n top: 50%;\n left: 0;\n transform: translateY(-50%);\n width: 100%;\n margin: 0;\n padding: 0;\n opacity: 0;\n cursor: pointer;\n -webkit-appearance: none;\n appearance: none;\n background: transparent;\n border: none;\n outline: none;\n /* Expand the hit area so the thumb meets WCAG 2.5.8 touch target (44px).\n The input's total height = track height + 2 * padding-block. With 0.75rem\n (~12px) padding on each side and a track of ~6px, the total target area is\n ~30px. We increase to 1rem (~16px) per side for a ~38px minimum, supplemented\n by the visual thumb size. */\n padding-block: var(--hx-slider-input-padding-block, 1rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n }\n\n /* In forced-color mode, restore native outline so the input remains focusable */\n @media (forced-colors: active) {\n .slider__input {\n outline: revert;\n opacity: 1;\n }\n .slider__input:focus-visible {\n outline: 2px solid ButtonText;\n }\n }\n\n .slider__input:disabled {\n cursor: not-allowed;\n }\n\n /* ─── Thumb (visual, :before on a wrapper or via ::after on track) ─── */\n /*\n * The native thumb is hidden (opacity 0 on the input). We render a visible\n * thumb element positioned by --fill-pct (a raw 0–100 number set in JS).\n *\n * Correct alignment formula keeps the thumb centered within the track at\n * both extremes, preventing the left/right halves from clipping outside:\n * left = fillPct% * (1 – thumbSize/100%) + thumbSize * (1 – fillPct/100)\n * Simplified: left = calc(var(--fill-pct,0)*1% + var(--_thumb-size)*(1 - var(--fill-pct,0)/100))\n * Combined with translate(-50%,-50%) this places the thumb center correctly\n * at every position from min to max.\n */\n\n .slider__thumb-visual {\n position: absolute;\n top: 50%;\n /* Corrected position: thumb stays within track at all fill values */\n left: calc(var(--fill-pct, 0) * 1% + var(--_thumb-size, 1rem) * (1 - var(--fill-pct, 0) / 100));\n transform: translate(-50%, -50%);\n border-radius: var(--hx-border-radius-full, 9999px);\n background-color: var(--hx-slider-thumb-bg, var(--hx-color-surface-default, #ffffff));\n border: var(--hx-slider-thumb-border-width, 2px) solid\n var(--hx-slider-thumb-border-color, var(--hx-color-primary-500, #429797));\n box-shadow: var(--hx-slider-thumb-shadow, var(--hx-shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05)));\n pointer-events: none;\n transition:\n box-shadow var(--hx-transition-fast, 150ms ease),\n transform var(--hx-transition-fast, 150ms ease);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .slider__thumb-visual {\n transition: none;\n }\n }\n\n .slider__input:focus-visible ~ .slider__thumb-visual {\n box-shadow:\n 0 0 0 var(--hx-focus-ring-width, 2px)\n var(\n --hx-slider-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-400, #6ab1b1))\n ),\n var(--hx-slider-thumb-shadow, var(--hx-shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05)));\n }\n\n /* ─── Thumb sizes ─── */\n\n .slider--sm .slider__thumb-visual {\n --_thumb-size: var(--hx-slider-thumb-size-sm, var(--hx-size-3, 0.75rem));\n width: var(--_thumb-size);\n height: var(--_thumb-size);\n }\n\n .slider--md .slider__thumb-visual {\n --_thumb-size: var(--hx-slider-thumb-size-md, var(--hx-size-4, 1rem));\n width: var(--_thumb-size);\n height: var(--_thumb-size);\n }\n\n .slider--lg .slider__thumb-visual {\n --_thumb-size: var(--hx-slider-thumb-size-lg, var(--hx-size-5, 1.25rem));\n width: var(--_thumb-size);\n height: var(--_thumb-size);\n }\n\n /* ─── Forced colors (Windows High Contrast) ─── */\n @media (forced-colors: active) {\n .slider__fill {\n background-color: Highlight;\n }\n .slider__track {\n background-color: ButtonFace;\n border: 1px solid ButtonText;\n }\n .slider__thumb-visual {\n background-color: ButtonText;\n border-color: ButtonText;\n }\n .slider__input:focus-visible ~ .slider__thumb-visual {\n outline: 2px solid Highlight;\n }\n }\n\n /* ─── Ticks ─── */\n\n .slider__ticks {\n position: relative;\n width: 100%;\n height: var(--hx-space-2, 0.5rem);\n margin-top: var(--hx-space-1, 0.25rem);\n }\n\n .slider__tick {\n position: absolute;\n top: 0;\n width: var(--hx-border-width-thin, 1px);\n height: 100%;\n background-color: var(--hx-slider-tick-color, var(--hx-color-border-strong, #8e9c98));\n transform: translateX(-50%);\n }\n\n /* ─── Range Labels ─── */\n\n .slider__range-labels {\n display: flex;\n justify-content: space-between;\n font-size: var(--hx-font-size-xs, 0.75rem);\n color: var(--hx-slider-range-label-color, var(--hx-color-text-muted, #4a5362));\n line-height: var(--hx-line-height-normal, 1.5);\n margin-top: var(--hx-space-0-5, 0.125rem);\n }\n\n /* ─── Help Text ─── */\n\n .slider__help-text {\n font-size: var(--hx-font-size-xs, 0.75rem);\n color: var(--hx-slider-help-text-color, var(--hx-color-text-muted, #4a5362));\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n /* ─── Disabled state ─── */\n\n .slider--disabled .slider__fill {\n background-color: var(--hx-slider-disabled-fill-bg, var(--hx-color-border-strong, #8e9c98));\n }\n\n .slider--disabled .slider__thumb-visual {\n border-color: var(\n --hx-slider-disabled-thumb-border-color,\n var(--hx-color-border-strong, #8e9c98)\n );\n }\n`;\n","import { TemplateResult, 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 { ifDefined } from 'lit/directives/if-defined.js';\nimport { live } from 'lit/directives/live.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { FormMixin } from '../../mixins/FormMixin.js';\nimport { helixSliderStyles } from './hx-slider.styles.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\nconst _nextSliderId = createIdCounter('hx-slider');\n\n/** Detail for hx-input and hx-change events dispatched by hx-slider. */\nexport interface HxSliderDetail {\n value: number;\n}\n\n/**\n * A range slider component for selecting a numeric value within a min/max boundary.\n * Supports tick marks, value display, range labels, and native form participation\n * via ElementInternals.\n *\n * The native `<input type=\"range\">` receives `role=\"slider\"` with `aria-valuenow`,\n * `aria-valuemin`, and `aria-valuemax`. Label association uses `aria-labelledby`\n * when a label is present, or `aria-label` as a fallback. Help text is linked via\n * `aria-describedby`. Keyboard navigation follows the native range behavior:\n * Arrow keys increment/decrement by step, Home jumps to min, End jumps to max.\n *\n * @summary Form-associated range slider with label, ticks, and value display.\n *\n * @tag hx-slider\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 min-label - Label rendered at the minimum end of the slider.\n * @slot max-label - Label rendered at the maximum end of the slider.\n *\n * @fires {CustomEvent<{value: number}>} hx-input - Dispatched continuously while the user drags.\n * @fires {CustomEvent<{value: number}>} hx-change - Dispatched when the user releases the thumb.\n *\n * @csspart slider - The outer container element.\n * @csspart track - The track background element.\n * @csspart fill - The filled portion of the track showing progress.\n * @csspart thumb - The draggable thumb overlay element.\n * @csspart label - The label element.\n * @csspart value-display - The element displaying the current numeric value.\n * @csspart tick - Each individual tick mark element.\n * @csspart help-text - The help text element displayed below the slider.\n *\n * @cssprop [--hx-slider-track-bg=var(--hx-color-neutral-200)] - Track background color.\n * @cssprop [--hx-slider-fill-bg=var(--hx-color-primary-500)] - Fill/progress color.\n * @cssprop [--hx-slider-thumb-bg=var(--hx-color-neutral-0)] - Thumb background color.\n * @cssprop [--hx-slider-thumb-border-color=var(--hx-color-primary-500)] - Thumb border color.\n * @cssprop [--hx-slider-thumb-border-width=2px] - Thumb border width.\n * @cssprop [--hx-slider-thumb-shadow=var(--hx-shadow-sm)] - Thumb box shadow.\n * @cssprop [--hx-slider-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-slider-label-color=var(--hx-color-neutral-700)] - Label text color.\n * @cssprop [--hx-slider-value-color=var(--hx-color-neutral-600)] - Value display text color.\n * @cssprop [--hx-slider-tick-color=var(--hx-color-neutral-400)] - Tick mark color.\n * @cssprop [--hx-slider-range-label-color=var(--hx-color-neutral-500)] - Range label text color.\n * @cssprop [--hx-slider-help-text-color=var(--hx-color-neutral-500)] - Help text color.\n * @cssprop [--hx-opacity-disabled] - Opacity.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-slider-font-family=var(--hx-font-family-sans)] - CSS custom property.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-font-weight-medium] - Font weight.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-color-neutral-600] - Color.\n * @cssprop [--hx-size-8] - Size token.\n * @cssprop [--hx-border-radius-full] - CSS custom property.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-slider-track-height-sm=var(--hx-size-1)] - Height.\n * @cssprop [--hx-size-1] - Size token.\n * @cssprop [--hx-slider-track-height-md=var(--hx-size-1-5)] - Height.\n * @cssprop [--hx-size-1-5] - Size token.\n * @cssprop [--hx-slider-track-height-lg=var(--hx-space-2)] - Height.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-slider-input-padding-block=1rem] - Padding.\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-shadow-sm] - Box shadow.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-slider-thumb-size-sm=var(--hx-size-3)] - CSS custom property.\n * @cssprop [--hx-size-3] - Size token.\n * @cssprop [--hx-slider-thumb-size-md=var(--hx-size-4)] - CSS custom property.\n * @cssprop [--hx-size-4] - Size token.\n * @cssprop [--hx-slider-thumb-size-lg=var(--hx-size-5)] - CSS custom property.\n * @cssprop [--hx-size-5] - Size token.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-color-neutral-400] - Color.\n * @cssprop [--hx-font-size-xs] - Font size.\n * @cssprop [--hx-color-neutral-500] - Color.\n * @cssprop [--hx-space-0-5] - Spacing token.\n */\n@customElement('hx-slider')\nexport class HelixSlider extends FormMixin(HelixElement) {\n static override styles = [helixSliderStyles, forcedColorsInteractive];\n\n // ─── Form Association ───\n\n /** @internal */\n static override formAssociated = true;\n\n // ─── Properties ───\n\n /**\n * The name submitted with the form.\n * @attr name\n */\n @property({ type: String, reflect: true })\n name = '';\n\n /**\n * The current numeric value of the slider.\n * @attr value\n */\n @property({ type: Number, reflect: true })\n value = 0;\n\n /**\n * The minimum allowed value.\n * @attr min\n */\n @property({ type: Number })\n min = 0;\n\n /**\n * The maximum allowed value.\n * @attr max\n */\n @property({ type: Number })\n max = 100;\n\n /**\n * The stepping interval between values.\n * @attr step\n */\n @property({ type: Number })\n step = 1;\n\n /**\n * Whether the slider is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * The visible label text for the slider.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Help text displayed below the slider for guidance.\n * @attr help-text\n */\n @property({ type: String, attribute: 'help-text' })\n helpText = '';\n\n /**\n * When true, the current value is shown next to the label.\n * @attr show-value\n */\n @property({ type: Boolean, attribute: 'show-value' })\n showValue = false;\n\n /**\n * When true, tick marks are rendered at each step interval.\n * @attr show-ticks\n */\n @property({ type: Boolean, attribute: 'show-ticks' })\n showTicks = false;\n\n /**\n * The size variant of the slider.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Human-readable text alternative for the current value, announced by screen readers\n * instead of the numeric value. For example, on a pain scale: \"7 — Moderate-Severe\".\n * @attr aria-valuetext\n */\n @property({ type: String, attribute: 'aria-valuetext' })\n valueText = '';\n\n // ─── Internal State ───\n\n /** Whether the label slot has assigned content. */\n /** @internal */\n @state() private _hasLabelSlot = false;\n /** Whether the min-label slot has assigned content. */\n /** @internal */\n @state() private _hasMinLabelSlot = false;\n /** Whether the max-label slot has assigned content. */\n /** @internal */\n @state() private _hasMaxLabelSlot = false;\n /** Whether the help slot has assigned content. */\n /** @internal */\n @state() private _hasHelpSlot = false;\n\n // ─── Internal References ───\n\n /**\n * Reference to the native range `<input>` inside shadow DOM.\n * @internal\n */\n @query('.slider__input')\n private _input: HTMLInputElement | undefined;\n\n // ─── Unique IDs ───\n\n /** Unique ID for the native range input element. */\n /** @internal */\n private readonly _sliderId = _nextSliderId();\n /** Unique ID for the label element, derived from _sliderId. */\n /** @internal */\n private readonly _labelId = `${this._sliderId}-label`;\n /** Unique ID for the help text element, derived from _sliderId. */\n /** @internal */\n private readonly _helpId = `${this._sliderId}-help`;\n\n /** Stored default value for form reset (captured in firstUpdated). */\n /** @internal */\n private _defaultValue: number | null = null;\n\n // ─── Computed Values ───\n\n /** @internal */\n private _clamp(v: number): number {\n return Math.min(Math.max(v, this.min), this.max);\n }\n\n /** @internal */\n private _fillPercent(): number {\n const clamped = this._clamp(this.value);\n const range = this.max - this.min;\n if (range === 0) return 0;\n return ((clamped - this.min) / range) * 100;\n }\n\n // Cached tick array — recomputed only when showTicks, min, max, or step change.\n // Avoids redundant array allocation on every render during continuous drag updates.\n /** @internal */\n private _cachedTicks: number[] = [];\n\n /** @internal */\n private _computeTicks(): number[] {\n if (!this.showTicks) return [];\n const ticks: number[] = [];\n const range = this.max - this.min;\n if (range <= 0 || this.step <= 0) return ticks;\n const count = Math.round(range / this.step);\n for (let i = 0; i <= count; i++) {\n ticks.push((i / count) * 100);\n }\n return ticks;\n }\n\n // ─── Lifecycle ───\n\n override willUpdate(changedProperties: PropertyValues<this>): void {\n super.willUpdate(changedProperties);\n if (\n changedProperties.has('showTicks') ||\n changedProperties.has('min') ||\n changedProperties.has('max') ||\n changedProperties.has('step')\n ) {\n this._cachedTicks = this._computeTicks();\n }\n }\n\n override firstUpdated(): void {\n // Capture the initial value for form reset (before any user interaction)\n this._defaultValue = this.value;\n // Enable fill transition after initial render to suppress animation on mount\n requestAnimationFrame(() => this.setAttribute('data-ready', ''));\n // WCAG 4.1.2: warn when no accessible name is available for the range input\n if (!this.label && !this._hasLabelSlot) {\n devWarn(\n 'hx-slider',\n 'No accessible label provided. Set the `label` attribute or use the label slot. An unlabeled slider violates WCAG 2.1 AA (4.1.2 Name, Role, Value).',\n );\n }\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n // Guard: min must be less than max\n if (changedProperties.has('min') || changedProperties.has('max')) {\n if (this.min >= this.max) {\n devWarn(\n 'hx-slider',\n `Invalid configuration: min (${this.min}) must be less than max (${this.max}). Slider behavior is undefined when min >= max.`,\n );\n }\n }\n // Clamp value to [min, max] after any relevant property change\n if (\n changedProperties.has('value') ||\n changedProperties.has('min') ||\n changedProperties.has('max')\n ) {\n const clamped = this._clamp(this.value);\n if (clamped !== this.value) {\n this.value = clamped;\n return;\n }\n this._internals.setFormValue(String(this.value));\n } else if (changedProperties.has('name')) {\n this._internals.setFormValue(String(this.value));\n }\n // Reflect aria-disabled on host for AT traversal\n if (changedProperties.has('disabled')) {\n if (this.disabled) {\n this.setAttribute('aria-disabled', 'true');\n } else {\n this.removeAttribute('aria-disabled');\n }\n }\n }\n\n // ─── Form Integration ───\n\n /** @internal */\n protected override _onFormReset(): void {\n const resetTo = this._clamp(this._defaultValue ?? this.min);\n this.value = resetTo;\n this._internals.setFormValue(String(resetTo));\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' || state === null) return;\n const parsed = parseFloat(state);\n if (!isNaN(parsed)) {\n this.value = this._clamp(parsed);\n }\n }\n\n /** @internal */\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Public Methods ───\n\n /** Moves focus to the native range input. */\n override focus(options?: FocusOptions): void {\n this._input?.focus(options);\n }\n\n // ─── Slot Handlers ───\n\n /** @internal */\n private _handleLabelSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasLabelSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n /** @internal */\n private _handleHelpSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasHelpSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n /** @internal */\n private _handleMinLabelSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasMinLabelSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n /** @internal */\n private _handleMaxLabelSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasMaxLabelSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleInput(e: Event): void {\n if (this.disabled) return;\n const target = e.target as HTMLInputElement;\n this.value = parseFloat(target.value);\n this._internals.setFormValue(String(this.value));\n this._handleInteractionInput();\n\n /**\n * Dispatched continuously while the user drags the thumb.\n * @event hx-input\n */\n this.dispatchEvent(\n new CustomEvent<{ value: number }>('hx-input', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n /** @internal */\n private _handleChange(e: Event): void {\n if (this.disabled) return;\n const target = e.target as HTMLInputElement;\n this.value = parseFloat(target.value);\n this._internals.setFormValue(String(this.value));\n this._handleInteractionBlur();\n\n /**\n * Dispatched when the user releases the thumb after dragging.\n * @event hx-change\n */\n this.dispatchEvent(\n new CustomEvent<{ value: number }>('hx-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n // ─── Render ───\n\n override render(): TemplateResult {\n const fillPct = this._fillPercent();\n const ticks = this._cachedTicks;\n const hasLabel = !!this.label || this._hasLabelSlot;\n const showRangeLabels = this._hasMinLabelSlot || this._hasMaxLabelSlot;\n\n const containerClasses = {\n slider: true,\n [`slider--${this.size}`]: true,\n 'slider--disabled': this.disabled,\n 'slider--has-ticks': this.showTicks,\n };\n\n const describedBy =\n [this.helpText || this._hasHelpSlot ? this._helpId : null].filter(Boolean).join(' ') ||\n undefined;\n\n return html`\n <div part=\"slider\" class=${classMap(containerClasses)}>\n <!-- Label row -->\n <div class=\"slider__label-row\">\n ${hasLabel\n ? html`<label\n part=\"label\"\n class=\"slider__label\"\n id=${this._labelId}\n for=${this._sliderId}\n >\n <slot name=\"label\" @slotchange=${this._handleLabelSlotChange}>${this.label}</slot>\n </label>`\n : html`<slot name=\"label\" @slotchange=${this._handleLabelSlotChange}></slot>`}\n ${this.showValue\n ? html`<span part=\"value-display\" class=\"slider__value-display\"> ${this.value} </span>`\n : nothing}\n </div>\n\n <!-- Track -->\n <div class=\"slider__track-container\">\n <div part=\"track\" class=\"slider__track\">\n <div\n part=\"fill\"\n class=\"slider__fill\"\n style=${styleMap({ '--_fill-ratio': String(fillPct / 100) })}\n ></div>\n\n <input\n class=\"slider__input\"\n id=${this._sliderId}\n type=\"range\"\n .value=${live(String(this.value))}\n min=${this.min}\n max=${this.max}\n step=${this.step}\n ?disabled=${this.disabled}\n name=${ifDefined(this.name || undefined)}\n aria-labelledby=${ifDefined(hasLabel ? this._labelId : undefined)}\n aria-label=${ifDefined(!hasLabel ? 'Slider' : undefined)}\n aria-valuetext=${ifDefined(this.valueText || undefined)}\n aria-describedby=${ifDefined(describedBy)}\n @input=${this._handleInput}\n @change=${this._handleChange}\n />\n\n <!-- Visual thumb positioned by fill percentage (--fill-pct drives CSS calc) -->\n <span\n part=\"thumb\"\n class=\"slider__thumb-visual\"\n style=${styleMap({ '--fill-pct': String(fillPct) })}\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n\n <!-- Tick marks -->\n ${this.showTicks && ticks.length > 0\n ? html`<div class=\"slider__ticks\">\n ${ticks.map(\n (pct) =>\n html`<span\n part=\"tick\"\n class=\"slider__tick\"\n style=${styleMap({ left: `${pct}%` })}\n ></span>`,\n )}\n </div>`\n : nothing}\n\n <!-- Range labels -->\n ${showRangeLabels\n ? html`<div class=\"slider__range-labels\">\n <slot name=\"min-label\" @slotchange=${this._handleMinLabelSlotChange}></slot>\n <slot name=\"max-label\" @slotchange=${this._handleMaxLabelSlotChange}></slot>\n </div>`\n : html`\n <!-- Always observe slot changes even when not rendered -->\n <slot name=\"min-label\" hidden @slotchange=${this._handleMinLabelSlotChange}></slot>\n <slot name=\"max-label\" hidden @slotchange=${this._handleMaxLabelSlotChange}></slot>\n `}\n\n <!-- Help text -->\n <!-- WCAG 1.3.1: wrap slot in a persistent container so _helpId stays stable\n regardless of whether help content comes from the slot or the property. -->\n <div id=${this._helpId}>\n <slot name=\"help-text\" @slotchange=${this._handleHelpSlotChange}>\n ${this.helpText\n ? html`<div part=\"help-text\" class=\"slider__help-text\">${this.helpText}</div>`\n : nothing}\n </slot>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-slider': HelixSlider;\n }\n}\n"],"names":["helixSliderStyles","css","_nextSliderId","createIdCounter","HelixSlider","FormMixin","HelixElement","v","clamped","range","ticks","count","i","changedProperties","devWarn","resetTo","state","_mode","parsed","disabled","options","_a","slot","target","fillPct","hasLabel","showRangeLabels","containerClasses","describedBy","html","classMap","nothing","styleMap","live","ifDefined","pct","forcedColorsInteractive","__decorateClass","property","query","customElement"],"mappings":";;;;;;;;;;;AAEO,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;A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"}
1
+ {"version":3,"file":"hx-slider-m0aEClH1.js","sources":["../../src/components/hx-slider/hx-slider.styles.ts","../../src/components/hx-slider/hx-slider.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixSliderStyles = css`\n :host {\n display: block;\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 /* ─── Container ─── */\n\n .slider {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-1, 0.25rem);\n font-family: var(--hx-slider-font-family, var(--hx-font-family-sans, sans-serif));\n }\n\n /* ─── Label Row ─── */\n\n .slider__label-row {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--hx-space-2, 0.5rem);\n }\n\n .slider__label {\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n color: var(--hx-slider-label-color, var(--hx-color-text-strong, #202b39));\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .slider__value-display {\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n color: var(--hx-slider-value-color, var(--hx-color-text-secondary, #313e4b));\n line-height: var(--hx-line-height-normal, 1.5);\n font-variant-numeric: tabular-nums;\n min-width: var(--hx-size-8, 2rem);\n text-align: end;\n }\n\n /* ─── Track Container ─── */\n\n .slider__track-container {\n position: relative;\n width: 100%;\n }\n\n .slider__track {\n position: relative;\n width: 100%;\n border-radius: var(--hx-border-radius-full, 9999px);\n background-color: var(--hx-slider-track-bg, var(--hx-color-border-default, #d6dbd5));\n overflow: visible;\n }\n\n /* ─── Size: sm ─── */\n\n .slider--sm .slider__track {\n height: var(--hx-slider-track-height-sm, var(--hx-size-1, 0.25rem));\n }\n\n .slider--sm .slider__input {\n height: var(--hx-slider-track-height-sm, var(--hx-size-1, 0.25rem));\n }\n\n /* ─── Size: md ─── */\n\n .slider--md .slider__track {\n height: var(--hx-slider-track-height-md, var(--hx-size-1-5, 0.375rem));\n }\n\n .slider--md .slider__input {\n height: var(--hx-slider-track-height-md, var(--hx-size-1-5, 0.375rem));\n }\n\n /* ─── Size: lg ─── */\n\n .slider--lg .slider__track {\n height: var(--hx-slider-track-height-lg, var(--hx-space-2, 0.5rem));\n }\n\n .slider--lg .slider__input {\n height: var(--hx-slider-track-height-lg, var(--hx-space-2, 0.5rem));\n }\n\n /* ─── Fill ─── */\n\n .slider__fill {\n position: absolute;\n top: 0;\n left: 0;\n height: 100%;\n width: 100%;\n border-radius: var(--hx-border-radius-full, 9999px);\n background-color: var(--hx-slider-fill-bg, var(--hx-color-primary-500, #429797));\n pointer-events: none;\n transform-origin: left center;\n transform: scaleX(var(--_fill-ratio, 0));\n transition: transform var(--hx-transition-fast, 150ms ease);\n }\n\n /* Suppress fill animation on initial render — only animate on user interaction */\n :host(:not([data-ready])) .slider__fill {\n transition: none;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .slider__fill {\n transition: none;\n }\n }\n\n /* ─── Native Range Input ─── */\n\n .slider__input {\n position: absolute;\n top: 50%;\n left: 0;\n transform: translateY(-50%);\n width: 100%;\n margin: 0;\n padding: 0;\n opacity: 0;\n cursor: pointer;\n -webkit-appearance: none;\n appearance: none;\n background: transparent;\n border: none;\n outline: none;\n /* Expand the hit area so the thumb meets WCAG 2.5.8 touch target (44px).\n The input's total height = track height + 2 * padding-block. With 0.75rem\n (~12px) padding on each side and a track of ~6px, the total target area is\n ~30px. We increase to 1rem (~16px) per side for a ~38px minimum, supplemented\n by the visual thumb size. */\n padding-block: var(--hx-slider-input-padding-block, 1rem);\n min-height: var(--hx-touch-target-min, 2.75rem);\n }\n\n /* In forced-color mode, restore native outline so the input remains focusable */\n @media (forced-colors: active) {\n .slider__input {\n outline: revert;\n opacity: 1;\n }\n .slider__input:focus-visible {\n outline: 2px solid ButtonText;\n }\n }\n\n .slider__input:disabled {\n cursor: not-allowed;\n }\n\n /* ─── Thumb (visual, :before on a wrapper or via ::after on track) ─── */\n /*\n * The native thumb is hidden (opacity 0 on the input). We render a visible\n * thumb element positioned by --fill-pct (a raw 0–100 number set in JS).\n *\n * Correct alignment formula keeps the thumb centered within the track at\n * both extremes, preventing the left/right halves from clipping outside:\n * left = fillPct% * (1 – thumbSize/100%) + thumbSize * (1 – fillPct/100)\n * Simplified: left = calc(var(--fill-pct,0)*1% + var(--_thumb-size)*(1 - var(--fill-pct,0)/100))\n * Combined with translate(-50%,-50%) this places the thumb center correctly\n * at every position from min to max.\n */\n\n .slider__thumb-visual {\n position: absolute;\n top: 50%;\n /* Corrected position: thumb stays within track at all fill values */\n left: calc(var(--fill-pct, 0) * 1% + var(--_thumb-size, 1rem) * (1 - var(--fill-pct, 0) / 100));\n transform: translate(-50%, -50%);\n border-radius: var(--hx-border-radius-full, 9999px);\n background-color: var(--hx-slider-thumb-bg, var(--hx-color-surface-default, #ffffff));\n border: var(--hx-slider-thumb-border-width, 2px) solid\n var(--hx-slider-thumb-border-color, var(--hx-color-primary-500, #429797));\n box-shadow: var(--hx-slider-thumb-shadow, var(--hx-shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05)));\n pointer-events: none;\n transition:\n box-shadow var(--hx-transition-fast, 150ms ease),\n transform var(--hx-transition-fast, 150ms ease);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .slider__thumb-visual {\n transition: none;\n }\n }\n\n .slider__input:focus-visible ~ .slider__thumb-visual {\n box-shadow:\n 0 0 0 var(--hx-focus-ring-width, 2px)\n var(\n --hx-slider-focus-ring-color,\n var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))\n ),\n var(--hx-slider-thumb-shadow, var(--hx-shadow-sm, 0 1px 2px 0 rgb(0 0 0 / 0.05)));\n }\n\n /* ─── Thumb sizes ─── */\n\n .slider--sm .slider__thumb-visual {\n --_thumb-size: var(--hx-slider-thumb-size-sm, var(--hx-size-3, 0.75rem));\n width: var(--_thumb-size);\n height: var(--_thumb-size);\n }\n\n .slider--md .slider__thumb-visual {\n --_thumb-size: var(--hx-slider-thumb-size-md, var(--hx-size-4, 1rem));\n width: var(--_thumb-size);\n height: var(--_thumb-size);\n }\n\n .slider--lg .slider__thumb-visual {\n --_thumb-size: var(--hx-slider-thumb-size-lg, var(--hx-size-5, 1.25rem));\n width: var(--_thumb-size);\n height: var(--_thumb-size);\n }\n\n /* ─── Forced colors (Windows High Contrast) ─── */\n @media (forced-colors: active) {\n .slider__fill {\n background-color: Highlight;\n }\n .slider__track {\n background-color: ButtonFace;\n border: 1px solid ButtonText;\n }\n .slider__thumb-visual {\n background-color: ButtonText;\n border-color: ButtonText;\n }\n .slider__input:focus-visible ~ .slider__thumb-visual {\n outline: 2px solid Highlight;\n }\n }\n\n /* ─── Ticks ─── */\n\n .slider__ticks {\n position: relative;\n width: 100%;\n height: var(--hx-space-2, 0.5rem);\n margin-top: var(--hx-space-1, 0.25rem);\n }\n\n .slider__tick {\n position: absolute;\n top: 0;\n width: var(--hx-border-width-thin, 1px);\n height: 100%;\n background-color: var(--hx-slider-tick-color, var(--hx-color-border-strong, #66787b));\n transform: translateX(-50%);\n }\n\n /* ─── Range Labels ─── */\n\n .slider__range-labels {\n display: flex;\n justify-content: space-between;\n font-size: var(--hx-font-size-xs, 0.75rem);\n color: var(--hx-slider-range-label-color, var(--hx-color-text-muted, #4a5362));\n line-height: var(--hx-line-height-normal, 1.5);\n margin-top: var(--hx-space-0-5, 0.125rem);\n }\n\n /* ─── Help Text ─── */\n\n .slider__help-text {\n font-size: var(--hx-font-size-xs, 0.75rem);\n color: var(--hx-slider-help-text-color, var(--hx-color-text-muted, #4a5362));\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n /* ─── Disabled state ─── */\n\n .slider--disabled .slider__fill {\n background-color: var(--hx-slider-disabled-fill-bg, var(--hx-color-border-strong, #66787b));\n }\n\n .slider--disabled .slider__thumb-visual {\n border-color: var(\n --hx-slider-disabled-thumb-border-color,\n var(--hx-color-border-strong, #66787b)\n );\n }\n`;\n","import { TemplateResult, 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 { ifDefined } from 'lit/directives/if-defined.js';\nimport { live } from 'lit/directives/live.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { HelixElement, createIdCounter } from '../../base/index.js';\nimport { FormMixin } from '../../mixins/FormMixin.js';\nimport { helixSliderStyles } from './hx-slider.styles.js';\nimport { forcedColorsInteractive } from '../../styles/forced-colors.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\nconst _nextSliderId = createIdCounter('hx-slider');\n\n/** Detail for hx-input and hx-change events dispatched by hx-slider. */\nexport interface HxSliderDetail {\n value: number;\n}\n\n/**\n * A range slider component for selecting a numeric value within a min/max boundary.\n * Supports tick marks, value display, range labels, and native form participation\n * via ElementInternals.\n *\n * The native `<input type=\"range\">` receives `role=\"slider\"` with `aria-valuenow`,\n * `aria-valuemin`, and `aria-valuemax`. Label association uses `aria-labelledby`\n * when a label is present, or `aria-label` as a fallback. Help text is linked via\n * `aria-describedby`. Keyboard navigation follows the native range behavior:\n * Arrow keys increment/decrement by step, Home jumps to min, End jumps to max.\n *\n * @summary Form-associated range slider with label, ticks, and value display.\n *\n * @tag hx-slider\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 min-label - Label rendered at the minimum end of the slider.\n * @slot max-label - Label rendered at the maximum end of the slider.\n *\n * @fires {CustomEvent<{value: number}>} hx-input - Dispatched continuously while the user drags.\n * @fires {CustomEvent<{value: number}>} hx-change - Dispatched when the user releases the thumb.\n *\n * @csspart slider - The outer container element.\n * @csspart track - The track background element.\n * @csspart fill - The filled portion of the track showing progress.\n * @csspart thumb - The draggable thumb overlay element.\n * @csspart label - The label element.\n * @csspart value-display - The element displaying the current numeric value.\n * @csspart tick - Each individual tick mark element.\n * @csspart help-text - The help text element displayed below the slider.\n *\n * @cssprop [--hx-slider-track-bg=var(--hx-color-neutral-200)] - Track background color.\n * @cssprop [--hx-slider-fill-bg=var(--hx-color-primary-500)] - Fill/progress color.\n * @cssprop [--hx-slider-thumb-bg=var(--hx-color-neutral-0)] - Thumb background color.\n * @cssprop [--hx-slider-thumb-border-color=var(--hx-color-primary-500)] - Thumb border color.\n * @cssprop [--hx-slider-thumb-border-width=2px] - Thumb border width.\n * @cssprop [--hx-slider-thumb-shadow=var(--hx-shadow-sm)] - Thumb box shadow.\n * @cssprop [--hx-slider-focus-ring-color=var(--hx-focus-ring-color)] - Focus ring color.\n * @cssprop [--hx-slider-label-color=var(--hx-color-neutral-700)] - Label text color.\n * @cssprop [--hx-slider-value-color=var(--hx-color-neutral-600)] - Value display text color.\n * @cssprop [--hx-slider-tick-color=var(--hx-color-neutral-400)] - Tick mark color.\n * @cssprop [--hx-slider-range-label-color=var(--hx-color-neutral-500)] - Range label text color.\n * @cssprop [--hx-slider-help-text-color=var(--hx-color-neutral-500)] - Help text color.\n * @cssprop [--hx-opacity-disabled] - Opacity.\n * @cssprop [--hx-space-1] - Spacing token.\n * @cssprop [--hx-slider-font-family=var(--hx-font-family-sans)] - CSS custom property.\n * @cssprop [--hx-font-family-sans] - Font family.\n * @cssprop [--hx-space-2] - Spacing token.\n * @cssprop [--hx-font-size-sm] - Font size.\n * @cssprop [--hx-font-weight-medium] - Font weight.\n * @cssprop [--hx-color-neutral-700] - Color.\n * @cssprop [--hx-line-height-normal] - Line height.\n * @cssprop [--hx-color-neutral-600] - Color.\n * @cssprop [--hx-size-8] - Size token.\n * @cssprop [--hx-border-radius-full] - CSS custom property.\n * @cssprop [--hx-color-neutral-200] - Color.\n * @cssprop [--hx-slider-track-height-sm=var(--hx-size-1)] - Height.\n * @cssprop [--hx-size-1] - Size token.\n * @cssprop [--hx-slider-track-height-md=var(--hx-size-1-5)] - Height.\n * @cssprop [--hx-size-1-5] - Size token.\n * @cssprop [--hx-slider-track-height-lg=var(--hx-space-2)] - Height.\n * @cssprop [--hx-color-primary-500] - Color.\n * @cssprop [--hx-transition-fast] - Transition timing.\n * @cssprop [--hx-slider-input-padding-block=1rem] - Padding.\n * @cssprop [--hx-touch-target-min] - Minimum touch target size.\n * @cssprop [--hx-color-neutral-0] - Color.\n * @cssprop [--hx-shadow-sm] - Box shadow.\n * @cssprop [--hx-focus-ring-width] - Width.\n * @cssprop [--hx-focus-ring-color] - Color.\n * @cssprop [--hx-color-primary-400] - Color.\n * @cssprop [--hx-slider-thumb-size-sm=var(--hx-size-3)] - CSS custom property.\n * @cssprop [--hx-size-3] - Size token.\n * @cssprop [--hx-slider-thumb-size-md=var(--hx-size-4)] - CSS custom property.\n * @cssprop [--hx-size-4] - Size token.\n * @cssprop [--hx-slider-thumb-size-lg=var(--hx-size-5)] - CSS custom property.\n * @cssprop [--hx-size-5] - Size token.\n * @cssprop [--hx-border-width-thin] - Width.\n * @cssprop [--hx-color-neutral-400] - Color.\n * @cssprop [--hx-font-size-xs] - Font size.\n * @cssprop [--hx-color-neutral-500] - Color.\n * @cssprop [--hx-space-0-5] - Spacing token.\n */\n@customElement('hx-slider')\nexport class HelixSlider extends FormMixin(HelixElement) {\n static override styles = [helixSliderStyles, forcedColorsInteractive];\n\n // ─── Form Association ───\n\n /** @internal */\n static override formAssociated = true;\n\n // ─── Properties ───\n\n /**\n * The name submitted with the form.\n * @attr name\n */\n @property({ type: String, reflect: true })\n name = '';\n\n /**\n * The current numeric value of the slider.\n * @attr value\n */\n @property({ type: Number, reflect: true })\n value = 0;\n\n /**\n * The minimum allowed value.\n * @attr min\n */\n @property({ type: Number })\n min = 0;\n\n /**\n * The maximum allowed value.\n * @attr max\n */\n @property({ type: Number })\n max = 100;\n\n /**\n * The stepping interval between values.\n * @attr step\n */\n @property({ type: Number })\n step = 1;\n\n /**\n * Whether the slider is disabled.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * The visible label text for the slider.\n * @attr label\n */\n @property({ type: String })\n label = '';\n\n /**\n * Help text displayed below the slider for guidance.\n * @attr help-text\n */\n @property({ type: String, attribute: 'help-text' })\n helpText = '';\n\n /**\n * When true, the current value is shown next to the label.\n * @attr show-value\n */\n @property({ type: Boolean, attribute: 'show-value' })\n showValue = false;\n\n /**\n * When true, tick marks are rendered at each step interval.\n * @attr show-ticks\n */\n @property({ type: Boolean, attribute: 'show-ticks' })\n showTicks = false;\n\n /**\n * The size variant of the slider.\n * @attr hx-size\n */\n @property({ type: String, reflect: true, attribute: 'hx-size' })\n size: 'sm' | 'md' | 'lg' = 'md';\n\n /**\n * Human-readable text alternative for the current value, announced by screen readers\n * instead of the numeric value. For example, on a pain scale: \"7 — Moderate-Severe\".\n * @attr aria-valuetext\n */\n @property({ type: String, attribute: 'aria-valuetext' })\n valueText = '';\n\n // ─── Internal State ───\n\n /** Whether the label slot has assigned content. */\n /** @internal */\n @state() private _hasLabelSlot = false;\n /** Whether the min-label slot has assigned content. */\n /** @internal */\n @state() private _hasMinLabelSlot = false;\n /** Whether the max-label slot has assigned content. */\n /** @internal */\n @state() private _hasMaxLabelSlot = false;\n /** Whether the help slot has assigned content. */\n /** @internal */\n @state() private _hasHelpSlot = false;\n\n // ─── Internal References ───\n\n /**\n * Reference to the native range `<input>` inside shadow DOM.\n * @internal\n */\n @query('.slider__input')\n private _input: HTMLInputElement | undefined;\n\n // ─── Unique IDs ───\n\n /** Unique ID for the native range input element. */\n /** @internal */\n private readonly _sliderId = _nextSliderId();\n /** Unique ID for the label element, derived from _sliderId. */\n /** @internal */\n private readonly _labelId = `${this._sliderId}-label`;\n /** Unique ID for the help text element, derived from _sliderId. */\n /** @internal */\n private readonly _helpId = `${this._sliderId}-help`;\n\n /** Stored default value for form reset (captured in firstUpdated). */\n /** @internal */\n private _defaultValue: number | null = null;\n\n // ─── Computed Values ───\n\n /** @internal */\n private _clamp(v: number): number {\n return Math.min(Math.max(v, this.min), this.max);\n }\n\n /** @internal */\n private _fillPercent(): number {\n const clamped = this._clamp(this.value);\n const range = this.max - this.min;\n if (range === 0) return 0;\n return ((clamped - this.min) / range) * 100;\n }\n\n // Cached tick array — recomputed only when showTicks, min, max, or step change.\n // Avoids redundant array allocation on every render during continuous drag updates.\n /** @internal */\n private _cachedTicks: number[] = [];\n\n /** @internal */\n private _computeTicks(): number[] {\n if (!this.showTicks) return [];\n const ticks: number[] = [];\n const range = this.max - this.min;\n if (range <= 0 || this.step <= 0) return ticks;\n const count = Math.round(range / this.step);\n for (let i = 0; i <= count; i++) {\n ticks.push((i / count) * 100);\n }\n return ticks;\n }\n\n // ─── Lifecycle ───\n\n override willUpdate(changedProperties: PropertyValues<this>): void {\n super.willUpdate(changedProperties);\n if (\n changedProperties.has('showTicks') ||\n changedProperties.has('min') ||\n changedProperties.has('max') ||\n changedProperties.has('step')\n ) {\n this._cachedTicks = this._computeTicks();\n }\n }\n\n override firstUpdated(): void {\n // Capture the initial value for form reset (before any user interaction)\n this._defaultValue = this.value;\n // Enable fill transition after initial render to suppress animation on mount\n requestAnimationFrame(() => this.setAttribute('data-ready', ''));\n // WCAG 4.1.2: warn when no accessible name is available for the range input\n if (!this.label && !this._hasLabelSlot) {\n devWarn(\n 'hx-slider',\n 'No accessible label provided. Set the `label` attribute or use the label slot. An unlabeled slider violates WCAG 2.1 AA (4.1.2 Name, Role, Value).',\n );\n }\n }\n\n override updated(changedProperties: PropertyValues<this>): void {\n super.updated(changedProperties);\n // Guard: min must be less than max\n if (changedProperties.has('min') || changedProperties.has('max')) {\n if (this.min >= this.max) {\n devWarn(\n 'hx-slider',\n `Invalid configuration: min (${this.min}) must be less than max (${this.max}). Slider behavior is undefined when min >= max.`,\n );\n }\n }\n // Clamp value to [min, max] after any relevant property change\n if (\n changedProperties.has('value') ||\n changedProperties.has('min') ||\n changedProperties.has('max')\n ) {\n const clamped = this._clamp(this.value);\n if (clamped !== this.value) {\n this.value = clamped;\n return;\n }\n this._internals.setFormValue(String(this.value));\n } else if (changedProperties.has('name')) {\n this._internals.setFormValue(String(this.value));\n }\n // Reflect aria-disabled on host for AT traversal\n if (changedProperties.has('disabled')) {\n if (this.disabled) {\n this.setAttribute('aria-disabled', 'true');\n } else {\n this.removeAttribute('aria-disabled');\n }\n }\n }\n\n // ─── Form Integration ───\n\n /** @internal */\n protected override _onFormReset(): void {\n const resetTo = this._clamp(this._defaultValue ?? this.min);\n this.value = resetTo;\n this._internals.setFormValue(String(resetTo));\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' || state === null) return;\n const parsed = parseFloat(state);\n if (!isNaN(parsed)) {\n this.value = this._clamp(parsed);\n }\n }\n\n /** @internal */\n protected override _onFormDisabled(disabled: boolean): void {\n this.disabled = disabled;\n }\n\n // ─── Public Methods ───\n\n /** Moves focus to the native range input. */\n override focus(options?: FocusOptions): void {\n this._input?.focus(options);\n }\n\n // ─── Slot Handlers ───\n\n /** @internal */\n private _handleLabelSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasLabelSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n /** @internal */\n private _handleHelpSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasHelpSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n /** @internal */\n private _handleMinLabelSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasMinLabelSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n /** @internal */\n private _handleMaxLabelSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasMaxLabelSlot = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n // ─── Event Handling ───\n\n /** @internal */\n private _handleInput(e: Event): void {\n if (this.disabled) return;\n const target = e.target as HTMLInputElement;\n this.value = parseFloat(target.value);\n this._internals.setFormValue(String(this.value));\n this._handleInteractionInput();\n\n /**\n * Dispatched continuously while the user drags the thumb.\n * @event hx-input\n */\n this.dispatchEvent(\n new CustomEvent<{ value: number }>('hx-input', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n /** @internal */\n private _handleChange(e: Event): void {\n if (this.disabled) return;\n const target = e.target as HTMLInputElement;\n this.value = parseFloat(target.value);\n this._internals.setFormValue(String(this.value));\n this._handleInteractionBlur();\n\n /**\n * Dispatched when the user releases the thumb after dragging.\n * @event hx-change\n */\n this.dispatchEvent(\n new CustomEvent<{ value: number }>('hx-change', {\n bubbles: true,\n composed: true,\n detail: { value: this.value },\n }),\n );\n }\n\n // ─── Render ───\n\n override render(): TemplateResult {\n const fillPct = this._fillPercent();\n const ticks = this._cachedTicks;\n const hasLabel = !!this.label || this._hasLabelSlot;\n const showRangeLabels = this._hasMinLabelSlot || this._hasMaxLabelSlot;\n\n const containerClasses = {\n slider: true,\n [`slider--${this.size}`]: true,\n 'slider--disabled': this.disabled,\n 'slider--has-ticks': this.showTicks,\n };\n\n const describedBy =\n [this.helpText || this._hasHelpSlot ? this._helpId : null].filter(Boolean).join(' ') ||\n undefined;\n\n return html`\n <div part=\"slider\" class=${classMap(containerClasses)}>\n <!-- Label row -->\n <div class=\"slider__label-row\">\n ${hasLabel\n ? html`<label\n part=\"label\"\n class=\"slider__label\"\n id=${this._labelId}\n for=${this._sliderId}\n >\n <slot name=\"label\" @slotchange=${this._handleLabelSlotChange}>${this.label}</slot>\n </label>`\n : html`<slot name=\"label\" @slotchange=${this._handleLabelSlotChange}></slot>`}\n ${this.showValue\n ? html`<span part=\"value-display\" class=\"slider__value-display\"> ${this.value} </span>`\n : nothing}\n </div>\n\n <!-- Track -->\n <div class=\"slider__track-container\">\n <div part=\"track\" class=\"slider__track\">\n <div\n part=\"fill\"\n class=\"slider__fill\"\n style=${styleMap({ '--_fill-ratio': String(fillPct / 100) })}\n ></div>\n\n <input\n class=\"slider__input\"\n id=${this._sliderId}\n type=\"range\"\n .value=${live(String(this.value))}\n min=${this.min}\n max=${this.max}\n step=${this.step}\n ?disabled=${this.disabled}\n name=${ifDefined(this.name || undefined)}\n aria-labelledby=${ifDefined(hasLabel ? this._labelId : undefined)}\n aria-label=${ifDefined(!hasLabel ? 'Slider' : undefined)}\n aria-valuetext=${ifDefined(this.valueText || undefined)}\n aria-describedby=${ifDefined(describedBy)}\n @input=${this._handleInput}\n @change=${this._handleChange}\n />\n\n <!-- Visual thumb positioned by fill percentage (--fill-pct drives CSS calc) -->\n <span\n part=\"thumb\"\n class=\"slider__thumb-visual\"\n style=${styleMap({ '--fill-pct': String(fillPct) })}\n aria-hidden=\"true\"\n ></span>\n </div>\n </div>\n\n <!-- Tick marks -->\n ${this.showTicks && ticks.length > 0\n ? html`<div class=\"slider__ticks\">\n ${ticks.map(\n (pct) =>\n html`<span\n part=\"tick\"\n class=\"slider__tick\"\n style=${styleMap({ left: `${pct}%` })}\n ></span>`,\n )}\n </div>`\n : nothing}\n\n <!-- Range labels -->\n ${showRangeLabels\n ? html`<div class=\"slider__range-labels\">\n <slot name=\"min-label\" @slotchange=${this._handleMinLabelSlotChange}></slot>\n <slot name=\"max-label\" @slotchange=${this._handleMaxLabelSlotChange}></slot>\n </div>`\n : html`\n <!-- Always observe slot changes even when not rendered -->\n <slot name=\"min-label\" hidden @slotchange=${this._handleMinLabelSlotChange}></slot>\n <slot name=\"max-label\" hidden @slotchange=${this._handleMaxLabelSlotChange}></slot>\n `}\n\n <!-- Help text -->\n <!-- WCAG 1.3.1: wrap slot in a persistent container so _helpId stays stable\n regardless of whether help content comes from the slot or the property. -->\n <div id=${this._helpId}>\n <slot name=\"help-text\" @slotchange=${this._handleHelpSlotChange}>\n ${this.helpText\n ? html`<div part=\"help-text\" class=\"slider__help-text\">${this.helpText}</div>`\n : nothing}\n </slot>\n </div>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-slider': HelixSlider;\n }\n}\n"],"names":["helixSliderStyles","css","_nextSliderId","createIdCounter","HelixSlider","FormMixin","HelixElement","v","clamped","range","ticks","count","i","changedProperties","devWarn","resetTo","state","_mode","parsed","disabled","options","_a","slot","target","fillPct","hasLabel","showRangeLabels","containerClasses","describedBy","html","classMap","nothing","styleMap","live","ifDefined","pct","forcedColorsInteractive","__decorateClass","property","query","customElement"],"mappings":";;;;;;;;;;;AAEO,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;A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"}
@@ -56,7 +56,7 @@ const w = m`
56
56
  outline: var(--hx-focus-ring-width, 2px) solid
57
57
  var(
58
58
  --hx-split-button-focus-ring-color,
59
- var(--hx-focus-ring-color, var(--hx-color-primary-400, #6ab1b1))
59
+ var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
60
60
  );
61
61
  outline-offset: var(--hx-focus-ring-offset, 2px);
62
62
  z-index: 1;
@@ -84,7 +84,7 @@ const w = m`
84
84
  flex-shrink: 0;
85
85
  border: var(--hx-border-width-thin, 1px) solid var(--hx-split-button-border-color, transparent);
86
86
  border-inline-start: var(--hx-border-width-thin, 1px) solid
87
- var(--hx-split-button-divider-color, var(--hx-color-primary-400, #6ab1b1));
87
+ var(--hx-split-button-divider-color, var(--hx-color-primary-900, #0b3232));
88
88
  border-radius: 0 var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem))
89
89
  var(--hx-split-button-border-radius, var(--hx-border-radius-md, 0.375rem)) 0;
90
90
  background-color: var(--hx-split-button-bg, var(--hx-color-primary-500, #429797));
@@ -101,7 +101,7 @@ const w = m`
101
101
  outline: var(--hx-focus-ring-width, 2px) solid
102
102
  var(
103
103
  --hx-split-button-focus-ring-color,
104
- var(--hx-focus-ring-color, var(--hx-color-primary-400, #6ab1b1))
104
+ var(--hx-focus-ring-color, var(--hx-color-primary-600, #0f7078))
105
105
  );
106
106
  outline-offset: var(--hx-focus-ring-offset, 2px);
107
107
  z-index: 1;
@@ -178,7 +178,7 @@ const w = m`
178
178
  --hx-split-button-bg: var(--hx-color-primary-500, #429797);
179
179
  --hx-split-button-color: var(--hx-color-text-on-primary, #ffffff);
180
180
  --hx-split-button-border-color: transparent;
181
- --hx-split-button-divider-color: var(--hx-color-primary-400, #6ab1b1);
181
+ --hx-split-button-divider-color: var(--hx-color-primary-900, #0b3232);
182
182
  }
183
183
 
184
184
  /* primary:hover — replace the universal brightness(0.9) filter (which would
@@ -265,7 +265,7 @@ const w = m`
265
265
  .split-button--outline .split-button__trigger {
266
266
  --hx-split-button-bg: transparent;
267
267
  --hx-split-button-color: var(--hx-color-text-primary, #0d1825);
268
- --hx-split-button-border-color: var(--hx-color-border-strong, #8e9c98);
268
+ --hx-split-button-border-color: var(--hx-color-border-strong, #66787b);
269
269
  --hx-split-button-divider-color: var(--hx-color-border-default, #d6dbd5);
270
270
  }
271
271
 
@@ -612,4 +612,4 @@ i = n([
612
612
  export {
613
613
  i as H
614
614
  };
615
- //# sourceMappingURL=hx-split-button-BeMsmS6N.js.map
615
+ //# sourceMappingURL=hx-split-button-BxDFfx4D.js.map