@helixui/library 1.0.0 → 1.0.1

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 (208) hide show
  1. package/custom-elements.json +213 -22
  2. package/dist/components/hx-accordion/hx-accordion-item.d.ts +20 -0
  3. package/dist/components/hx-accordion/hx-accordion-item.d.ts.map +1 -1
  4. package/dist/components/hx-accordion/index.js +1 -1
  5. package/dist/components/hx-alert/hx-alert.d.ts +10 -0
  6. package/dist/components/hx-alert/hx-alert.d.ts.map +1 -1
  7. package/dist/components/hx-alert/hx-alert.styles.d.ts.map +1 -1
  8. package/dist/components/hx-alert/index.js +1 -1
  9. package/dist/components/hx-badge/hx-badge.d.ts +2 -0
  10. package/dist/components/hx-badge/hx-badge.d.ts.map +1 -1
  11. package/dist/components/hx-badge/hx-badge.styles.d.ts.map +1 -1
  12. package/dist/components/hx-badge/index.js +1 -1
  13. package/dist/components/hx-banner/hx-banner.d.ts +6 -0
  14. package/dist/components/hx-banner/hx-banner.d.ts.map +1 -1
  15. package/dist/components/hx-banner/index.js +1 -1
  16. package/dist/components/hx-breadcrumb/hx-breadcrumb-item.styles.d.ts.map +1 -1
  17. package/dist/components/hx-breadcrumb/index.js +1 -1
  18. package/dist/components/hx-card/hx-card.d.ts +1 -0
  19. package/dist/components/hx-card/hx-card.d.ts.map +1 -1
  20. package/dist/components/hx-card/hx-card.styles.d.ts.map +1 -1
  21. package/dist/components/hx-card/index.js +1 -1
  22. package/dist/components/hx-carousel/hx-carousel.styles.d.ts.map +1 -1
  23. package/dist/components/hx-carousel/index.js +1 -1
  24. package/dist/components/hx-checkbox/hx-checkbox.styles.d.ts.map +1 -1
  25. package/dist/components/hx-checkbox/index.js +1 -1
  26. package/dist/components/hx-code-snippet/index.js +1 -1
  27. package/dist/components/hx-color-picker/hx-color-picker.d.ts +44 -10
  28. package/dist/components/hx-color-picker/hx-color-picker.d.ts.map +1 -1
  29. package/dist/components/hx-color-picker/index.js +1 -1
  30. package/dist/components/hx-combobox/hx-combobox.styles.d.ts.map +1 -1
  31. package/dist/components/hx-combobox/index.js +1 -1
  32. package/dist/components/hx-data-table/hx-data-table.styles.d.ts.map +1 -1
  33. package/dist/components/hx-data-table/index.js +1 -1
  34. package/dist/components/hx-date-picker/hx-date-picker.styles.d.ts.map +1 -1
  35. package/dist/components/hx-date-picker/index.js +1 -1
  36. package/dist/components/hx-dialog/hx-dialog.styles.d.ts.map +1 -1
  37. package/dist/components/hx-dialog/index.js +1 -1
  38. package/dist/components/hx-drawer/hx-drawer.d.ts.map +1 -1
  39. package/dist/components/hx-drawer/hx-drawer.styles.d.ts.map +1 -1
  40. package/dist/components/hx-drawer/index.js +1 -1
  41. package/dist/components/hx-dropdown/hx-dropdown.d.ts +20 -5
  42. package/dist/components/hx-dropdown/hx-dropdown.d.ts.map +1 -1
  43. package/dist/components/hx-dropdown/index.js +1 -1
  44. package/dist/components/hx-file-upload/hx-file-upload.styles.d.ts.map +1 -1
  45. package/dist/components/hx-file-upload/index.js +1 -1
  46. package/dist/components/hx-icon-button/hx-icon-button.styles.d.ts.map +1 -1
  47. package/dist/components/hx-icon-button/index.js +1 -1
  48. package/dist/components/hx-menu/hx-menu-item.d.ts +1 -0
  49. package/dist/components/hx-menu/hx-menu-item.d.ts.map +1 -1
  50. package/dist/components/hx-menu/hx-menu.d.ts +1 -0
  51. package/dist/components/hx-menu/hx-menu.d.ts.map +1 -1
  52. package/dist/components/hx-menu/index.js +1 -1
  53. package/dist/components/hx-meter/hx-meter.d.ts +1 -0
  54. package/dist/components/hx-meter/hx-meter.d.ts.map +1 -1
  55. package/dist/components/hx-meter/hx-meter.styles.d.ts.map +1 -1
  56. package/dist/components/hx-meter/index.js +1 -1
  57. package/dist/components/hx-nav/hx-nav.styles.d.ts.map +1 -1
  58. package/dist/components/hx-nav/index.js +1 -1
  59. package/dist/components/hx-overflow-menu/hx-overflow-menu.styles.d.ts.map +1 -1
  60. package/dist/components/hx-overflow-menu/index.js +1 -1
  61. package/dist/components/hx-pagination/hx-pagination.styles.d.ts.map +1 -1
  62. package/dist/components/hx-pagination/index.js +1 -1
  63. package/dist/components/hx-popover/hx-popover.d.ts +41 -9
  64. package/dist/components/hx-popover/hx-popover.d.ts.map +1 -1
  65. package/dist/components/hx-popover/hx-popover.styles.d.ts.map +1 -1
  66. package/dist/components/hx-popover/index.js +1 -1
  67. package/dist/components/hx-progress-bar/hx-progress-bar.d.ts +2 -0
  68. package/dist/components/hx-progress-bar/hx-progress-bar.d.ts.map +1 -1
  69. package/dist/components/hx-progress-bar/index.js +1 -1
  70. package/dist/components/hx-radio-group/hx-radio.styles.d.ts.map +1 -1
  71. package/dist/components/hx-radio-group/index.js +1 -1
  72. package/dist/components/hx-select/hx-select.styles.d.ts.map +1 -1
  73. package/dist/components/hx-select/index.js +1 -1
  74. package/dist/components/hx-slider/hx-slider.d.ts.map +1 -1
  75. package/dist/components/hx-slider/index.js +1 -1
  76. package/dist/components/hx-split-button/index.js +1 -1
  77. package/dist/components/hx-split-panel/hx-split-panel.d.ts +44 -11
  78. package/dist/components/hx-split-panel/hx-split-panel.d.ts.map +1 -1
  79. package/dist/components/hx-split-panel/hx-split-panel.styles.d.ts.map +1 -1
  80. package/dist/components/hx-split-panel/index.js +1 -1
  81. package/dist/components/hx-tabs/hx-tabs.d.ts.map +1 -1
  82. package/dist/components/hx-tabs/index.js +1 -1
  83. package/dist/components/hx-tag/hx-tag.d.ts +2 -0
  84. package/dist/components/hx-tag/hx-tag.d.ts.map +1 -1
  85. package/dist/components/hx-tag/hx-tag.styles.d.ts.map +1 -1
  86. package/dist/components/hx-tag/index.js +1 -1
  87. package/dist/components/hx-text-input/hx-text-input.d.ts +1 -1
  88. package/dist/components/hx-text-input/index.js +1 -1
  89. package/dist/components/hx-time-picker/hx-time-picker.d.ts +80 -19
  90. package/dist/components/hx-time-picker/hx-time-picker.d.ts.map +1 -1
  91. package/dist/components/hx-time-picker/index.js +1 -1
  92. package/dist/components/hx-toast/hx-toast.d.ts +10 -0
  93. package/dist/components/hx-toast/hx-toast.d.ts.map +1 -1
  94. package/dist/components/hx-toast/hx-toast.styles.d.ts.map +1 -1
  95. package/dist/components/hx-toast/index.js +1 -1
  96. package/dist/components/hx-top-nav/index.js +1 -1
  97. package/dist/components/hx-tree-view/hx-tree-item.d.ts +11 -1
  98. package/dist/components/hx-tree-view/hx-tree-item.d.ts.map +1 -1
  99. package/dist/components/hx-tree-view/hx-tree-item.styles.d.ts.map +1 -1
  100. package/dist/components/hx-tree-view/hx-tree-view.d.ts +1 -0
  101. package/dist/components/hx-tree-view/hx-tree-view.d.ts.map +1 -1
  102. package/dist/components/hx-tree-view/index.js +1 -1
  103. package/dist/index.js +37 -37
  104. package/dist/shared/{hx-accordion-Cyswa6J3.js → hx-accordion-DT8qHOay.js} +54 -37
  105. package/dist/shared/hx-accordion-DT8qHOay.js.map +1 -0
  106. package/dist/shared/{hx-alert-Cg-zxRiU.js → hx-alert-D6uok29t.js} +95 -28
  107. package/dist/shared/hx-alert-D6uok29t.js.map +1 -0
  108. package/dist/shared/{hx-badge-CjT0d8NK.js → hx-badge-BeuWuUj_.js} +57 -31
  109. package/dist/shared/hx-badge-BeuWuUj_.js.map +1 -0
  110. package/dist/shared/{hx-banner-lxAIJ2kR.js → hx-banner-DnCBJtRR.js} +27 -23
  111. package/dist/shared/{hx-banner-lxAIJ2kR.js.map → hx-banner-DnCBJtRR.js.map} +1 -1
  112. package/dist/shared/{hx-breadcrumb-item-C0rz0fzV.js → hx-breadcrumb-item-Bj2UqhzR.js} +12 -8
  113. package/dist/shared/{hx-breadcrumb-item-C0rz0fzV.js.map → hx-breadcrumb-item-Bj2UqhzR.js.map} +1 -1
  114. package/dist/shared/{hx-card-Bg4W4uXC.js → hx-card-B9j2SHyI.js} +15 -11
  115. package/dist/shared/hx-card-B9j2SHyI.js.map +1 -0
  116. package/dist/shared/{hx-carousel-item-BKpmFbUT.js → hx-carousel-item-Be0bC-7o.js} +91 -77
  117. package/dist/shared/hx-carousel-item-Be0bC-7o.js.map +1 -0
  118. package/dist/shared/{hx-checkbox-BMayOpAM.js → hx-checkbox-CuaJqEo7.js} +3 -1
  119. package/dist/shared/hx-checkbox-CuaJqEo7.js.map +1 -0
  120. package/dist/shared/{hx-code-snippet-B4hV7rWG.js → hx-code-snippet-DBwIjl5p.js} +11 -11
  121. package/dist/shared/{hx-code-snippet-B4hV7rWG.js.map → hx-code-snippet-DBwIjl5p.js.map} +1 -1
  122. package/dist/shared/{hx-color-picker-BvfJ_h16.js → hx-color-picker-Bb2UPVc3.js} +2 -2
  123. package/dist/shared/hx-color-picker-Bb2UPVc3.js.map +1 -0
  124. package/dist/shared/{hx-combobox-BBi3izKJ.js → hx-combobox-CNvY-es8.js} +42 -39
  125. package/dist/shared/hx-combobox-CNvY-es8.js.map +1 -0
  126. package/dist/shared/{hx-data-table-DNiDVWR2.js → hx-data-table-BwoJCFgs.js} +9 -8
  127. package/dist/shared/hx-data-table-BwoJCFgs.js.map +1 -0
  128. package/dist/shared/{hx-date-picker-D7yCK0nk.js → hx-date-picker-DDcIBJir.js} +43 -37
  129. package/dist/shared/hx-date-picker-DDcIBJir.js.map +1 -0
  130. package/dist/shared/{hx-dialog-Z7Ou_AZ9.js → hx-dialog-M7so0sRT.js} +41 -34
  131. package/dist/shared/hx-dialog-M7so0sRT.js.map +1 -0
  132. package/dist/shared/{hx-drawer-Dk-_xzy0.js → hx-drawer-CYxuhIQ0.js} +50 -43
  133. package/dist/shared/hx-drawer-CYxuhIQ0.js.map +1 -0
  134. package/dist/shared/{hx-dropdown-DnjLnkTj.js → hx-dropdown-7cfowTWv.js} +30 -30
  135. package/dist/shared/hx-dropdown-7cfowTWv.js.map +1 -0
  136. package/dist/shared/{hx-file-upload-CUORgnKc.js → hx-file-upload-9HbONfqt.js} +49 -43
  137. package/dist/shared/hx-file-upload-9HbONfqt.js.map +1 -0
  138. package/dist/shared/{hx-icon-button-C83bCR0K.js → hx-icon-button-iu0i_faq.js} +39 -29
  139. package/dist/shared/hx-icon-button-iu0i_faq.js.map +1 -0
  140. package/dist/shared/{hx-menu-divider-11Dp2VfM.js → hx-menu-divider-DR8klkFT.js} +32 -26
  141. package/dist/shared/hx-menu-divider-DR8klkFT.js.map +1 -0
  142. package/dist/shared/{hx-meter-UinDQjl6.js → hx-meter-CZ7lnMra.js} +67 -35
  143. package/dist/shared/hx-meter-CZ7lnMra.js.map +1 -0
  144. package/dist/shared/{hx-nav-DSpwWYUX.js → hx-nav-DM6-cGKF.js} +49 -47
  145. package/dist/shared/hx-nav-DM6-cGKF.js.map +1 -0
  146. package/dist/shared/{hx-overflow-menu-C7k5wlZy.js → hx-overflow-menu-CobkjAb8.js} +17 -9
  147. package/dist/shared/{hx-overflow-menu-C7k5wlZy.js.map → hx-overflow-menu-CobkjAb8.js.map} +1 -1
  148. package/dist/shared/{hx-pagination-BQ0cLTuB.js → hx-pagination-10dpXS95.js} +14 -12
  149. package/dist/shared/hx-pagination-10dpXS95.js.map +1 -0
  150. package/dist/shared/hx-popover-ULjonbaO.js +269 -0
  151. package/dist/shared/hx-popover-ULjonbaO.js.map +1 -0
  152. package/dist/shared/{hx-progress-bar-C_mdPVF-.js → hx-progress-bar-CnTibV63.js} +67 -57
  153. package/dist/shared/{hx-progress-bar-C_mdPVF-.js.map → hx-progress-bar-CnTibV63.js.map} +1 -1
  154. package/dist/shared/{hx-radio-Bqyi8re3.js → hx-radio-BnKcRuQu.js} +10 -8
  155. package/dist/shared/{hx-radio-Bqyi8re3.js.map → hx-radio-BnKcRuQu.js.map} +1 -1
  156. package/dist/shared/{hx-select-BBae2LqN.js → hx-select-C50lD7NS.js} +4 -3
  157. package/dist/shared/hx-select-C50lD7NS.js.map +1 -0
  158. package/dist/shared/{hx-slider-CpnxH2UP.js → hx-slider-CprSNrRi.js} +3 -2
  159. package/dist/shared/hx-slider-CprSNrRi.js.map +1 -0
  160. package/dist/shared/{hx-split-button-BvwoG8h2.js → hx-split-button-CHGy4FUc.js} +11 -11
  161. package/dist/shared/{hx-split-button-BvwoG8h2.js.map → hx-split-button-CHGy4FUc.js.map} +1 -1
  162. package/dist/shared/{hx-split-panel-Cxkeauwe.js → hx-split-panel-DYtB45Tr.js} +16 -8
  163. package/dist/shared/hx-split-panel-DYtB45Tr.js.map +1 -0
  164. package/dist/shared/{hx-tab-panel-CHB0u1zF.js → hx-tab-panel-BRNcLICw.js} +55 -52
  165. package/dist/shared/hx-tab-panel-BRNcLICw.js.map +1 -0
  166. package/dist/shared/{hx-tag-SJJtMlOS.js → hx-tag-B3N-vZ6B.js} +80 -55
  167. package/dist/shared/hx-tag-B3N-vZ6B.js.map +1 -0
  168. package/dist/shared/{hx-text-input-BrCjo4fJ.js → hx-text-input-CCZZbWQ9.js} +6 -6
  169. package/dist/shared/hx-text-input-CCZZbWQ9.js.map +1 -0
  170. package/dist/shared/{hx-time-picker-DRRAFuVd.js → hx-time-picker-CJcIjH3C.js} +5 -2
  171. package/dist/shared/hx-time-picker-CJcIjH3C.js.map +1 -0
  172. package/dist/shared/{hx-top-nav-DzW7XLv-.js → hx-top-nav-D2bQpns3.js} +2 -2
  173. package/dist/shared/{hx-top-nav-DzW7XLv-.js.map → hx-top-nav-D2bQpns3.js.map} +1 -1
  174. package/dist/shared/{hx-tree-item-DdH6RbMs.js → hx-tree-item-BobGN76x.js} +119 -96
  175. package/dist/shared/hx-tree-item-BobGN76x.js.map +1 -0
  176. package/dist/shared/{toast-factory-B8jicczW.js → toast-factory-MvMMreTu.js} +178 -94
  177. package/dist/shared/toast-factory-MvMMreTu.js.map +1 -0
  178. package/package.json +1 -1
  179. package/dist/shared/hx-accordion-Cyswa6J3.js.map +0 -1
  180. package/dist/shared/hx-alert-Cg-zxRiU.js.map +0 -1
  181. package/dist/shared/hx-badge-CjT0d8NK.js.map +0 -1
  182. package/dist/shared/hx-card-Bg4W4uXC.js.map +0 -1
  183. package/dist/shared/hx-carousel-item-BKpmFbUT.js.map +0 -1
  184. package/dist/shared/hx-checkbox-BMayOpAM.js.map +0 -1
  185. package/dist/shared/hx-color-picker-BvfJ_h16.js.map +0 -1
  186. package/dist/shared/hx-combobox-BBi3izKJ.js.map +0 -1
  187. package/dist/shared/hx-data-table-DNiDVWR2.js.map +0 -1
  188. package/dist/shared/hx-date-picker-D7yCK0nk.js.map +0 -1
  189. package/dist/shared/hx-dialog-Z7Ou_AZ9.js.map +0 -1
  190. package/dist/shared/hx-drawer-Dk-_xzy0.js.map +0 -1
  191. package/dist/shared/hx-dropdown-DnjLnkTj.js.map +0 -1
  192. package/dist/shared/hx-file-upload-CUORgnKc.js.map +0 -1
  193. package/dist/shared/hx-icon-button-C83bCR0K.js.map +0 -1
  194. package/dist/shared/hx-menu-divider-11Dp2VfM.js.map +0 -1
  195. package/dist/shared/hx-meter-UinDQjl6.js.map +0 -1
  196. package/dist/shared/hx-nav-DSpwWYUX.js.map +0 -1
  197. package/dist/shared/hx-pagination-BQ0cLTuB.js.map +0 -1
  198. package/dist/shared/hx-popover-BQsgrJCW.js +0 -226
  199. package/dist/shared/hx-popover-BQsgrJCW.js.map +0 -1
  200. package/dist/shared/hx-select-BBae2LqN.js.map +0 -1
  201. package/dist/shared/hx-slider-CpnxH2UP.js.map +0 -1
  202. package/dist/shared/hx-split-panel-Cxkeauwe.js.map +0 -1
  203. package/dist/shared/hx-tab-panel-CHB0u1zF.js.map +0 -1
  204. package/dist/shared/hx-tag-SJJtMlOS.js.map +0 -1
  205. package/dist/shared/hx-text-input-BrCjo4fJ.js.map +0 -1
  206. package/dist/shared/hx-time-picker-DRRAFuVd.js.map +0 -1
  207. package/dist/shared/hx-tree-item-DdH6RbMs.js.map +0 -1
  208. package/dist/shared/toast-factory-B8jicczW.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { css as p, LitElement as f, nothing as h, html as c } from "lit";
1
+ import { css as p, LitElement as f, html as c, nothing as h } from "lit";
2
2
  import { property as u, customElement as x, state as _ } from "lit/decorators.js";
3
3
  import { tokenStyles as v } from "@helixui/tokens/lit";
4
4
  import { d as g } from "./dev-warn-YlwPHjtX.js";
@@ -25,10 +25,10 @@ const k = p`
25
25
  outline: none;
26
26
  }
27
27
  `;
28
- var I = Object.defineProperty, w = Object.getOwnPropertyDescriptor, b = (e, t, s, n) => {
29
- for (var i = n > 1 ? void 0 : n ? w(t, s) : t, r = e.length - 1, o; r >= 0; r--)
30
- (o = e[r]) && (i = (n ? o(t, s, i) : o(i)) || i);
31
- return n && i && I(t, s, i), i;
28
+ var I = Object.defineProperty, w = Object.getOwnPropertyDescriptor, b = (e, t, s, i) => {
29
+ for (var n = i > 1 ? void 0 : i ? w(t, s) : t, r = e.length - 1, o; r >= 0; r--)
30
+ (o = e[r]) && (n = (i ? o(t, s, n) : o(n)) || n);
31
+ return i && n && I(t, s, n), n;
32
32
  };
33
33
  let d = class extends f {
34
34
  constructor() {
@@ -45,8 +45,8 @@ let d = class extends f {
45
45
  */
46
46
  _syncRovingTabIndex() {
47
47
  const e = this._getItems(), t = this._focusedIndex >= 0 ? this._focusedIndex : 0;
48
- e.forEach((s, n) => {
49
- s.setRovingTabIndex(n === t ? 0 : -1);
48
+ e.forEach((s, i) => {
49
+ s.setRovingTabIndex(i === t ? 0 : -1);
50
50
  });
51
51
  }
52
52
  /** Focus the first menu item. */
@@ -67,8 +67,8 @@ let d = class extends f {
67
67
  s !== void 0 && s.focus();
68
68
  }
69
69
  _updateFocusedIndex() {
70
- var n;
71
- const e = this._getItems(), t = ((n = this.shadowRoot) == null ? void 0 : n.activeElement) ?? document.activeElement, s = e.findIndex((i) => i.matches(":focus-within") || i === t);
70
+ var i;
71
+ const e = this._getItems(), t = ((i = this.shadowRoot) == null ? void 0 : i.activeElement) ?? document.activeElement, s = e.findIndex((n) => n.matches(":focus-within") || n === t);
72
72
  s !== -1 && (this._focusedIndex = s);
73
73
  }
74
74
  _handleKeyDown(e) {
@@ -100,19 +100,19 @@ let d = class extends f {
100
100
  clearTimeout(this._typeaheadTimeout), this._typeaheadBuffer += e.toLowerCase(), this._typeaheadTimeout = setTimeout(() => {
101
101
  this._typeaheadBuffer = "";
102
102
  }, 500);
103
- const s = t.findIndex((n) => {
103
+ const s = t.findIndex((i) => {
104
104
  var r;
105
- return n.disabled || n.hasAttribute("disabled") ? !1 : (((r = n.textContent) == null ? void 0 : r.trim().toLowerCase()) ?? "").startsWith(this._typeaheadBuffer);
105
+ return i.disabled || i.hasAttribute("disabled") ? !1 : (((r = i.textContent) == null ? void 0 : r.trim().toLowerCase()) ?? "").startsWith(this._typeaheadBuffer);
106
106
  });
107
107
  s !== -1 && this._focusItem(s);
108
108
  }
109
109
  _handleSlotChange(e) {
110
110
  const t = e.target;
111
111
  if (!(t instanceof HTMLSlotElement)) return;
112
- const s = /* @__PURE__ */ new Set(["hx-menu-item", "hx-menu-divider"]), n = t.assignedElements().filter((i) => !s.has(i.tagName.toLowerCase()));
113
- n.length > 0 && g(
112
+ const s = /* @__PURE__ */ new Set(["hx-menu-item", "hx-menu-divider"]), i = t.assignedElements().filter((n) => !s.has(n.tagName.toLowerCase()));
113
+ i.length > 0 && g(
114
114
  "hx-menu",
115
- `Default slot expects <hx-menu-item> or <hx-menu-divider> elements. Found unexpected: ${n.map((i) => `<${i.tagName.toLowerCase()}>`).join(", ")}`
115
+ `Default slot expects <hx-menu-item> or <hx-menu-divider> elements. Found unexpected: ${i.map((n) => `<${n.tagName.toLowerCase()}>`).join(", ")}`
116
116
  ), this._syncRovingTabIndex();
117
117
  }
118
118
  _handleItemSelect(e) {
@@ -125,13 +125,16 @@ let d = class extends f {
125
125
  })
126
126
  );
127
127
  }
128
+ firstUpdated() {
129
+ this.label;
130
+ }
128
131
  render() {
129
132
  return c`
130
133
  <div
131
134
  part="base"
132
135
  class="menu"
133
136
  role="menu"
134
- aria-label=${this.label || h}
137
+ aria-label=${this.label || "Menu"}
135
138
  @keydown=${this._handleKeyDown}
136
139
  @hx-item-select=${this._handleItemSelect}
137
140
  >
@@ -184,8 +187,8 @@ const S = p`
184
187
 
185
188
  .menu-item:focus-visible {
186
189
  outline: var(--hx-focus-ring-width, 2px) solid
187
- var(--hx-focus-ring-color, var(--hx-color-primary-500, #3b82f6));
188
- outline-offset: 0px;
190
+ var(--hx-menu-item-focus-ring-color, var(--hx-focus-ring-color, var(--hx-color-primary-500)));
191
+ outline-offset: var(--hx-menu-item-focus-ring-offset, 0px);
189
192
  }
190
193
 
191
194
  .menu-item__prefix,
@@ -239,10 +242,10 @@ const S = p`
239
242
  }
240
243
  }
241
244
  `;
242
- var C = Object.defineProperty, $ = Object.getOwnPropertyDescriptor, l = (e, t, s, n) => {
243
- for (var i = n > 1 ? void 0 : n ? $(t, s) : t, r = e.length - 1, o; r >= 0; r--)
244
- (o = e[r]) && (i = (n ? o(t, s, i) : o(i)) || i);
245
- return n && i && C(t, s, i), i;
245
+ var C = Object.defineProperty, $ = Object.getOwnPropertyDescriptor, l = (e, t, s, i) => {
246
+ for (var n = i > 1 ? void 0 : i ? $(t, s) : t, r = e.length - 1, o; r >= 0; r--)
247
+ (o = e[r]) && (n = (i ? o(t, s, n) : o(n)) || n);
248
+ return i && n && C(t, s, n), n;
246
249
  };
247
250
  let a = class extends f {
248
251
  constructor() {
@@ -257,6 +260,9 @@ let a = class extends f {
257
260
  var t, s;
258
261
  (s = (t = this.shadowRoot) == null ? void 0 : t.querySelector(".menu-item")) == null || s.focus(e);
259
262
  }
263
+ connectedCallback() {
264
+ super.connectedCallback(), this.closest('hx-menu, hx-split-button, [role="menu"], [role="menubar"]');
265
+ }
260
266
  _handleSubmenuSlotChange(e) {
261
267
  const t = e.target;
262
268
  this._hasSubmenu = t.assignedElements().length > 0;
@@ -430,10 +436,10 @@ const D = p`
430
436
  margin: var(--hx-space-1, 0.25rem) calc(-1 * var(--hx-space-1, 0.25rem));
431
437
  }
432
438
  `;
433
- var E = Object.getOwnPropertyDescriptor, T = (e, t, s, n) => {
434
- for (var i = n > 1 ? void 0 : n ? E(t, s) : t, r = e.length - 1, o; r >= 0; r--)
435
- (o = e[r]) && (i = o(i) || i);
436
- return i;
439
+ var E = Object.getOwnPropertyDescriptor, T = (e, t, s, i) => {
440
+ for (var n = i > 1 ? void 0 : i ? E(t, s) : t, r = e.length - 1, o; r >= 0; r--)
441
+ (o = e[r]) && (n = o(n) || n);
442
+ return n;
437
443
  };
438
444
  let m = class extends f {
439
445
  render() {
@@ -454,4 +460,4 @@ export {
454
460
  m as a,
455
461
  a as b
456
462
  };
457
- //# sourceMappingURL=hx-menu-divider-11Dp2VfM.js.map
463
+ //# sourceMappingURL=hx-menu-divider-DR8klkFT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hx-menu-divider-DR8klkFT.js","sources":["../../src/components/hx-menu/hx-menu.styles.ts","../../src/components/hx-menu/hx-menu.ts","../../src/components/hx-menu/hx-menu-item.styles.ts","../../src/components/hx-menu/hx-menu-item.ts","../../src/components/hx-menu/hx-menu-divider.styles.ts","../../src/components/hx-menu/hx-menu-divider.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixMenuStyles = css`\n :host {\n display: block;\n }\n\n .menu {\n display: flex;\n flex-direction: column;\n padding: var(--hx-space-1, 0.25rem);\n background: var(--hx-menu-bg, var(--hx-color-neutral-0, #ffffff));\n border: var(--hx-border-width-thin, 1px) solid\n var(--hx-menu-border-color, var(--hx-color-neutral-200, #e2e8f0));\n border-radius: var(--hx-menu-border-radius, var(--hx-border-radius-md, 0.375rem));\n box-shadow: var(\n --hx-menu-shadow,\n 0 4px 6px -1px rgb(0 0 0 / 0.1),\n 0 2px 4px -2px rgb(0 0 0 / 0.1)\n );\n min-width: var(--hx-menu-min-width, 10rem);\n outline: none;\n }\n`;\n","import { LitElement, html } from 'lit';\nimport { customElement, property } from 'lit/decorators.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixMenuStyles } from './hx-menu.styles.js';\nimport type { HelixMenuItem } from './hx-menu-item.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n/**\n * A menu container that manages keyboard navigation over a list of menu items.\n * Use with `hx-menu-item` and `hx-menu-divider`.\n *\n * @summary Context/action menu with keyboard-navigable items.\n *\n * @tag hx-menu\n *\n * @slot - Default slot for hx-menu-item and hx-menu-divider elements.\n *\n * @fires {CustomEvent<{item: HelixMenuItem, value: string}>} hx-select - Dispatched when an item is selected.\n * @fires {CustomEvent<void>} hx-close - Dispatched when Escape is pressed.\n *\n * @csspart base - The root menu element.\n *\n * @cssprop [--hx-menu-bg=var(--hx-color-neutral-0)] - Menu background color.\n * @cssprop [--hx-menu-border-color=var(--hx-color-neutral-200)] - Menu border color.\n * @cssprop [--hx-menu-border-radius=var(--hx-border-radius-md)] - Menu border radius.\n * @cssprop [--hx-menu-shadow] - Menu box shadow.\n * @cssprop [--hx-menu-min-width=10rem] - Minimum menu width.\n */\n@customElement('hx-menu')\nexport class HelixMenu extends LitElement {\n static override styles = [tokenStyles, helixMenuStyles];\n\n /**\n * Accessible label for the menu. Rendered as `aria-label` on the inner\n * `role=\"menu\"` element when set.\n * @attr label\n */\n @property({ type: String, reflect: true })\n label = '';\n\n /**\n * Index of the currently focused menu item within the list of enabled items.\n * @internal\n */\n private _focusedIndex = -1;\n\n /**\n * Accumulated character buffer for typeahead search within menu items.\n * @internal\n */\n private _typeaheadBuffer = '';\n\n /**\n * Timer handle that clears the typeahead buffer after a period of inactivity.\n * @internal\n */\n private _typeaheadTimeout: ReturnType<typeof setTimeout> | undefined;\n\n private _getItems(): HelixMenuItem[] {\n return Array.from(this.querySelectorAll<HelixMenuItem>('hx-menu-item')).filter(\n (item) => !item.disabled && !item.loading,\n );\n }\n\n /**\n * Synchronize roving tabindex across all enabled items.\n * Only the active item (or first item if none active) gets tabindex=0.\n */\n private _syncRovingTabIndex(): void {\n const items = this._getItems();\n const activeIndex = this._focusedIndex >= 0 ? this._focusedIndex : 0;\n items.forEach((item, i) => {\n item.setRovingTabIndex(i === activeIndex ? 0 : -1);\n });\n }\n\n /** Focus the first menu item. */\n focusFirst(): void {\n const items = this._getItems();\n const first = items[0];\n if (first !== undefined) {\n this._focusedIndex = 0;\n this._syncRovingTabIndex();\n first.focus();\n }\n }\n\n /** Focus the last menu item. */\n focusLast(): void {\n const items = this._getItems();\n const last = items[items.length - 1];\n if (last !== undefined) {\n this._focusedIndex = items.length - 1;\n this._syncRovingTabIndex();\n last.focus();\n }\n }\n\n private _focusItem(index: number): void {\n const items = this._getItems();\n if (items.length === 0) return;\n this._focusedIndex = Math.max(0, Math.min(index, items.length - 1));\n this._syncRovingTabIndex();\n const target = items[this._focusedIndex];\n if (target !== undefined) target.focus();\n }\n\n private _updateFocusedIndex(): void {\n const items = this._getItems();\n const active = this.shadowRoot?.activeElement ?? document.activeElement;\n // Find the active item by checking if any item's shadow root contains the active element\n const idx = items.findIndex((item) => item.matches(':focus-within') || item === active);\n if (idx !== -1) this._focusedIndex = idx;\n }\n\n private _handleKeyDown(e: KeyboardEvent): void {\n this._updateFocusedIndex();\n const items = this._getItems();\n if (items.length === 0) return;\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault();\n this._focusItem(this._focusedIndex + 1 < items.length ? this._focusedIndex + 1 : 0);\n break;\n case 'ArrowUp':\n e.preventDefault();\n this._focusItem(this._focusedIndex > 0 ? this._focusedIndex - 1 : items.length - 1);\n break;\n case 'Home':\n e.preventDefault();\n this._focusItem(0);\n break;\n case 'End':\n e.preventDefault();\n this._focusItem(items.length - 1);\n break;\n case 'Escape':\n e.preventDefault();\n this.dispatchEvent(new CustomEvent('hx-close', { bubbles: true, composed: true }));\n break;\n default:\n if (e.key.length === 1 && e.key !== ' ' && !e.ctrlKey && !e.metaKey && !e.altKey) {\n this._handleTypeahead(e.key, items);\n }\n break;\n }\n }\n\n private _handleTypeahead(char: string, items: HelixMenuItem[]): void {\n clearTimeout(this._typeaheadTimeout);\n this._typeaheadBuffer += char.toLowerCase();\n this._typeaheadTimeout = setTimeout(() => {\n this._typeaheadBuffer = '';\n }, 500);\n\n const match = items.findIndex((item) => {\n if (item.disabled || item.hasAttribute('disabled')) return false;\n const text = item.textContent?.trim().toLowerCase() ?? '';\n return text.startsWith(this._typeaheadBuffer);\n });\n\n if (match !== -1) {\n this._focusItem(match);\n }\n }\n\n private _handleSlotChange(e: Event): void {\n const slot = e.target;\n if (!(slot instanceof HTMLSlotElement)) return;\n const validTags = new Set(['hx-menu-item', 'hx-menu-divider']);\n const invalid = slot\n .assignedElements()\n .filter((el) => !validTags.has(el.tagName.toLowerCase()));\n if (invalid.length > 0) {\n devWarn(\n 'hx-menu',\n `Default slot expects <hx-menu-item> or <hx-menu-divider> elements. Found unexpected: ${invalid.map((el) => `<${el.tagName.toLowerCase()}>`).join(', ')}`,\n );\n }\n // Initialize roving tabindex when items are slotted\n this._syncRovingTabIndex();\n }\n\n private _handleItemSelect(e: Event): void {\n const detail = (e as CustomEvent<{ item: HelixMenuItem; value: string }>).detail;\n const items = this._getItems();\n this._focusedIndex = items.indexOf(detail.item);\n\n this.dispatchEvent(\n new CustomEvent('hx-select', {\n bubbles: true,\n composed: true,\n detail: { item: detail.item, value: detail.value },\n }),\n );\n }\n\n override firstUpdated(): void {\n if (!this.label) {\n devWarn(\n 'hx-menu',\n 'No accessible label provided. Set the `label` attribute on hx-menu so screen readers can identify this menu (WCAG 4.1.2).',\n );\n }\n }\n\n override render() {\n return html`\n <div\n part=\"base\"\n class=\"menu\"\n role=\"menu\"\n aria-label=${this.label || 'Menu'}\n @keydown=${this._handleKeyDown}\n @hx-item-select=${this._handleItemSelect}\n >\n <slot @slotchange=${this._handleSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu': HelixMenu;\n }\n}\n","import { css } from 'lit';\n\nexport const helixMenuItemStyles = css`\n :host {\n display: block;\n }\n\n :host([disabled]) {\n pointer-events: none;\n opacity: var(--hx-opacity-disabled, 0.5);\n }\n\n .menu-item {\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 border-radius: var(--hx-border-radius-sm, 0.25rem);\n cursor: pointer;\n color: var(--hx-menu-item-color, var(--hx-color-neutral-900, #0f172a));\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-family: var(--hx-font-family-sans, sans-serif);\n line-height: var(--hx-line-height-tight, 1.25);\n user-select: none;\n -webkit-user-select: none;\n outline: none;\n background: none;\n width: 100%;\n box-sizing: border-box;\n transition: background-color var(--hx-transition-fast, 150ms ease);\n }\n\n .menu-item:hover,\n .menu-item:focus-visible {\n background-color: var(--hx-menu-item-hover-bg, var(--hx-color-neutral-100, #f1f5f9));\n }\n\n .menu-item:focus-visible {\n outline: var(--hx-focus-ring-width, 2px) solid\n var(--hx-menu-item-focus-ring-color, var(--hx-focus-ring-color, var(--hx-color-primary-500)));\n outline-offset: var(--hx-menu-item-focus-ring-offset, 0px);\n }\n\n .menu-item__prefix,\n .menu-item__suffix {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n }\n\n .menu-item__label {\n flex: 1 1 auto;\n }\n\n .menu-item__checked-icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n width: 1em;\n opacity: 0;\n transition: opacity var(--hx-transition-fast, 150ms ease);\n }\n\n .menu-item--checked .menu-item__checked-icon {\n opacity: 1;\n }\n\n .menu-item__submenu-icon {\n display: inline-flex;\n align-items: center;\n flex-shrink: 0;\n margin-inline-start: auto;\n }\n\n .menu-item__spinner {\n width: 1em;\n height: 1em;\n flex-shrink: 0;\n animation: hx-menu-spin var(--hx-duration-spinner, 750ms) linear infinite;\n }\n\n @keyframes hx-menu-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .menu-item__spinner {\n animation: none;\n opacity: var(--hx-opacity-muted, 0.6);\n }\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixMenuItemStyles } from './hx-menu-item.styles.js';\nimport { devWarn } from '../../utils/dev-warn.js';\n\n/**\n * A single interactive item for use inside `hx-menu`. Supports normal, checkbox,\n * and radio types, loading state, prefix/suffix slots, and submenu nesting.\n * Use `aria-label` on the parent `hx-menu` to provide an accessible name.\n *\n * @summary Interactive item within an hx-menu.\n *\n * @tag hx-menu-item\n *\n * @slot - Default slot for the item label.\n * @slot prefix - Icon or content rendered before the label.\n * @slot suffix - Shortcut text or icon rendered after the label.\n * @slot submenu - A nested hx-menu for submenu content.\n *\n * @fires {CustomEvent<{item: HelixMenuItem, value: string}>} hx-item-select - Dispatched when the item is activated via click, Enter, or Space.\n * @fires {CustomEvent<{item: HelixMenuItem}>} hx-item-submenu-open - Dispatched when ArrowRight is pressed on an item with a submenu.\n *\n * @csspart base - The root item element.\n * @csspart prefix - Prefix slot wrapper.\n * @csspart label - Label slot wrapper.\n * @csspart suffix - Suffix slot wrapper.\n * @csspart submenu-icon - The chevron icon indicating a submenu.\n * @csspart checked-icon - The checkmark icon for checkbox-type items.\n *\n * @cssprop [--hx-menu-item-color=var(--hx-color-neutral-900)] - Item text color.\n * @cssprop [--hx-menu-item-hover-bg=var(--hx-color-neutral-100)] - Item hover/focus background.\n */\n@customElement('hx-menu-item')\nexport class HelixMenuItem extends LitElement {\n static override styles = [tokenStyles, helixMenuItemStyles];\n\n /**\n * @internal Managed by parent hx-menu for roving tabindex.\n * Only the active item in the menu has tabindex=0; all others have -1.\n */\n @state()\n private _rovingTabIndex = -1;\n\n /** @internal Set the roving tabindex value. Called by parent hx-menu. */\n setRovingTabIndex(value: number): void {\n this._rovingTabIndex = value;\n }\n\n /**\n * The value associated with this item, emitted in the hx-select event.\n * @attr value\n */\n @property({ type: String })\n value = '';\n\n /**\n * Whether the item is disabled. Prevents interaction and event dispatch.\n * @attr disabled\n */\n @property({ type: Boolean, reflect: true })\n disabled = false;\n\n /**\n * Whether the item is checked. Only meaningful when type=\"checkbox\".\n * @attr checked\n */\n @property({ type: Boolean, reflect: true })\n checked = false;\n\n /**\n * The type of menu item. \"checkbox\" renders a checkmark and toggles checked state.\n * \"radio\" renders a checkmark and emits selection for radio-group behavior.\n * @attr type\n */\n @property({ type: String, reflect: true })\n type: 'normal' | 'checkbox' | 'radio' = 'normal';\n\n /**\n * Whether the item is in a loading state. Shows a spinner and prevents interaction.\n * @attr loading\n */\n @property({ type: Boolean, reflect: true })\n loading = false;\n\n @state()\n private _hasSubmenu = false;\n\n /** Focus the inner interactive element. */\n override focus(options?: FocusOptions): void {\n this.shadowRoot?.querySelector<HTMLElement>('.menu-item')?.focus(options);\n }\n\n override connectedCallback(): void {\n super.connectedCallback();\n // WCAG 4.1.2: menuitem role is only valid inside a role=\"menu\" or role=\"menubar\" container.\n // Check the closest ancestor with a menu role.\n const menuHost = this.closest('hx-menu, hx-split-button, [role=\"menu\"], [role=\"menubar\"]');\n if (!menuHost) {\n devWarn(\n 'hx-menu-item',\n 'hx-menu-item must be used inside an hx-menu or an element with role=\"menu\". ' +\n 'An orphaned menuitem violates WCAG 1.3.1 (Info and Relationships).',\n );\n }\n }\n\n private _handleSubmenuSlotChange(e: Event): void {\n const slot = e.target as HTMLSlotElement;\n this._hasSubmenu = slot.assignedElements().length > 0;\n }\n\n private _activate(): void {\n if (this.disabled || this.loading) return;\n\n if (this.type === 'checkbox') {\n this.checked = !this.checked;\n } else if (this.type === 'radio') {\n const menu = this.closest('hx-menu');\n if (menu) {\n menu\n .querySelectorAll<HelixMenuItem>(':scope > hx-menu-item[type=\"radio\"]')\n .forEach((sibling) => {\n sibling.checked = sibling === this;\n });\n } else {\n this.checked = true;\n }\n }\n\n this.dispatchEvent(\n new CustomEvent('hx-item-select', {\n bubbles: true,\n composed: true,\n detail: { item: this, value: this.value },\n }),\n );\n }\n\n private _handleClick(e: MouseEvent): void {\n if (this.disabled || this.loading) {\n e.preventDefault();\n e.stopPropagation();\n return;\n }\n this._activate();\n }\n\n private _handleKeyDown(e: KeyboardEvent): void {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this._activate();\n return;\n }\n\n if (e.key === 'ArrowRight' && this._hasSubmenu) {\n e.preventDefault();\n this.dispatchEvent(\n new CustomEvent('hx-item-submenu-open', {\n bubbles: true,\n composed: true,\n detail: { item: this },\n }),\n );\n }\n }\n\n private _renderCheckedIcon() {\n return html`\n <span part=\"checked-icon\" class=\"menu-item__checked-icon\" aria-hidden=\"true\">\n <svg\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </span>\n `;\n }\n\n private _renderSubmenuIcon() {\n return html`\n <span part=\"submenu-icon\" class=\"menu-item__submenu-icon\" aria-hidden=\"true\">\n <svg\n width=\"1em\"\n height=\"1em\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"9 18 15 12 9 6\" />\n </svg>\n </span>\n `;\n }\n\n private _renderSpinner() {\n return html`\n <svg class=\"menu-item__spinner\" aria-hidden=\"true\" viewBox=\"0 0 24 24\" fill=\"none\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"3\" opacity=\"0.3\" />\n <path\n d=\"M12 2a10 10 0 0 1 10 10\"\n stroke=\"currentColor\"\n stroke-width=\"3\"\n stroke-linecap=\"round\"\n />\n </svg>\n `;\n }\n\n private _getRole(): string {\n switch (this.type) {\n case 'checkbox':\n return 'menuitemcheckbox';\n case 'radio':\n return 'menuitemradio';\n default:\n return 'menuitem';\n }\n }\n\n override render() {\n const role = this._getRole();\n const hasCheckableRole = this.type === 'checkbox' || this.type === 'radio';\n const classes = {\n 'menu-item': true,\n 'menu-item--checked': this.checked,\n };\n\n return html`\n <div\n part=\"base\"\n class=${classMap(classes)}\n role=${role}\n tabindex=${this.disabled ? '-1' : String(this._rovingTabIndex)}\n aria-disabled=${this.disabled ? 'true' : nothing}\n aria-checked=${hasCheckableRole ? (this.checked ? 'true' : 'false') : nothing}\n aria-haspopup=${this._hasSubmenu ? 'true' : nothing}\n aria-busy=${this.loading ? 'true' : nothing}\n @click=${this._handleClick}\n @keydown=${this._handleKeyDown}\n >\n ${this.loading ? this._renderSpinner() : nothing}\n ${hasCheckableRole ? this._renderCheckedIcon() : nothing}\n <span part=\"prefix\" class=\"menu-item__prefix\">\n <slot name=\"prefix\"></slot>\n </span>\n <span part=\"label\" class=\"menu-item__label\">\n <slot></slot>\n </span>\n <span part=\"suffix\" class=\"menu-item__suffix\">\n <slot name=\"suffix\"></slot>\n </span>\n ${this._hasSubmenu ? this._renderSubmenuIcon() : nothing}\n <slot name=\"submenu\" @slotchange=${this._handleSubmenuSlotChange}></slot>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu-item': HelixMenuItem;\n }\n}\n","import { css } from 'lit';\n\nexport const helixMenuDividerStyles = css`\n :host {\n display: block;\n }\n\n .menu-divider {\n height: var(--hx-border-width-thin, 1px);\n background-color: var(--hx-menu-divider-color, var(--hx-color-neutral-200, #e2e8f0));\n margin: var(--hx-space-1, 0.25rem) calc(-1 * var(--hx-space-1, 0.25rem));\n }\n`;\n","import { LitElement, html } from 'lit';\nimport { customElement } from 'lit/decorators.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixMenuDividerStyles } from './hx-menu-divider.styles.js';\n\n/**\n * A visual separator for grouping items within an `hx-menu`.\n *\n * @summary Horizontal divider between menu sections.\n *\n * @tag hx-menu-divider\n *\n * @csspart base - The root separator element.\n *\n * @cssprop [--hx-menu-divider-color=var(--hx-color-neutral-200)] - Divider line color.\n */\n@customElement('hx-menu-divider')\nexport class HelixMenuDivider extends LitElement {\n static override styles = [tokenStyles, helixMenuDividerStyles];\n\n override render() {\n return html`<div\n part=\"base\"\n class=\"menu-divider\"\n role=\"separator\"\n aria-orientation=\"horizontal\"\n ></div>`;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-menu-divider': HelixMenuDivider;\n }\n}\n"],"names":["helixMenuStyles","css","HelixMenu","LitElement","item","items","activeIndex","first","last","index","target","active","_a","idx","char","match","slot","validTags","invalid","el","devWarn","detail","html","tokenStyles","__decorateClass","property","customElement","helixMenuItemStyles","HelixMenuItem","value","options","_b","menu","sibling","role","hasCheckableRole","classes","classMap","nothing","state","helixMenuDividerStyles","HelixMenuDivider"],"mappings":"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"}
@@ -1,9 +1,9 @@
1
- import { css as f, LitElement as x, html as g } from "lit";
2
- import { property as h, state as _, customElement as b } from "lit/decorators.js";
1
+ import { css as x, LitElement as f, nothing as _, html as v } from "lit";
2
+ import { property as h, state as b, customElement as w } from "lit/decorators.js";
3
3
  import { ifDefined as m } from "lit/directives/if-defined.js";
4
- import { styleMap as w } from "lit/directives/style-map.js";
4
+ import { styleMap as y } from "lit/directives/style-map.js";
5
5
  import { tokenStyles as $ } from "@helixui/tokens/lit";
6
- const y = f`
6
+ const S = x`
7
7
  :host {
8
8
  display: block;
9
9
  width: 100%;
@@ -64,6 +64,30 @@ const y = f`
64
64
  --_indicator-color: var(--hx-meter-color-danger, var(--hx-color-danger-500, #ef4444));
65
65
  }
66
66
 
67
+ /* ─── State Label (WCAG 1.4.1) ─── */
68
+ /* Visible text label rendered below the track when a semantic state is active. */
69
+ /* Ensures the meter state is not conveyed by fill color alone. */
70
+ /* aria-hidden="true" because aria-valuetext already includes the state for AT. */
71
+
72
+ .meter__state-label {
73
+ font-size: var(--hx-font-size-xs, 0.75rem);
74
+ font-weight: var(--hx-font-weight-medium, 500);
75
+ line-height: var(--hx-line-height-tight, 1.25);
76
+ font-family: var(--hx-font-family-sans, sans-serif);
77
+ }
78
+
79
+ .meter__state-label[data-state='optimum'] {
80
+ color: var(--hx-meter-color-optimum, var(--hx-color-success-700, #15803d));
81
+ }
82
+
83
+ .meter__state-label[data-state='warning'] {
84
+ color: var(--hx-meter-color-warning, var(--hx-color-warning-700, #b45309));
85
+ }
86
+
87
+ .meter__state-label[data-state='danger'] {
88
+ color: var(--hx-meter-color-danger, var(--hx-color-danger-700, #b91c1c));
89
+ }
90
+
67
91
  /* ─── Native meter hidden (we use custom rendering) ─── */
68
92
 
69
93
  .meter__native {
@@ -78,12 +102,12 @@ const y = f`
78
102
  border: 0;
79
103
  }
80
104
  `;
81
- var S = Object.defineProperty, V = Object.getOwnPropertyDescriptor, n = (r, t, i, s) => {
82
- for (var a = s > 1 ? void 0 : s ? V(t, i) : t, o = r.length - 1, l; o >= 0; o--)
83
- (l = r[o]) && (a = (s ? l(t, i, a) : l(a)) || a);
84
- return s && a && S(t, i, a), a;
105
+ var L = Object.defineProperty, V = Object.getOwnPropertyDescriptor, l = (r, t, a, s) => {
106
+ for (var i = s > 1 ? void 0 : s ? V(t, a) : t, o = r.length - 1, n; o >= 0; o--)
107
+ (n = r[o]) && (i = (s ? n(t, a, i) : n(i)) || i);
108
+ return s && i && L(t, a, i), i;
85
109
  };
86
- let e = class extends x {
110
+ let e = class extends f {
87
111
  constructor() {
88
112
  super(...arguments), this._uid = `hx-meter-${++e._counter}`, this.value = 0, this.min = 0, this.max = 100, this._hasSlotContent = !1;
89
113
  }
@@ -95,13 +119,13 @@ let e = class extends x {
95
119
  return r === 0 ? 0 : (this._clampedValue() - this.min) / r * 100;
96
120
  }
97
121
  _resolveState() {
98
- const r = this._clampedValue(), t = this.low !== void 0, i = this.high !== void 0, s = this.optimum !== void 0;
99
- if (!t && !i && !s) return "default";
100
- const a = this.low ?? 0, o = this.high ?? this.max, l = t && r < a, c = i && r > o, u = !l && !c;
122
+ const r = this._clampedValue(), t = this.low !== void 0, a = this.high !== void 0, s = this.optimum !== void 0;
123
+ if (!t && !a && !s) return "default";
124
+ const i = this.low ?? 0, o = this.high ?? this.max, n = t && r < i, c = a && r > o, d = !n && !c;
101
125
  if (!s)
102
- return l || c ? "warning" : "optimum";
103
- const d = this.optimum ?? this.min, p = t && d < a, v = i && d > o;
104
- return !p && !v ? u ? "optimum" : "warning" : p ? l ? "optimum" : u ? "warning" : "danger" : c ? "optimum" : u ? "warning" : "danger";
126
+ return n || c ? "warning" : "optimum";
127
+ const u = this.optimum ?? this.min, p = t && u < i, g = a && u > o;
128
+ return !p && !g ? d ? "optimum" : "warning" : p ? n ? "optimum" : d ? "warning" : "danger" : c ? "optimum" : d ? "warning" : "danger";
105
129
  }
106
130
  _onLabelSlotChange(r) {
107
131
  const t = r.target;
@@ -111,18 +135,18 @@ let e = class extends x {
111
135
  this.dataset.state = this._resolveState();
112
136
  }
113
137
  render() {
114
- const r = this._percentage(), t = this._resolveState(), i = this._clampedValue(), s = t !== "default" ? ` — ${t}` : "", a = `${i} of ${this.max}${s}`, o = this.label !== void 0 || this._hasSlotContent;
115
- return g`
138
+ const r = this._percentage(), t = this._resolveState(), a = this._clampedValue(), s = t !== "default" ? ` — ${t}` : "", i = `${a} of ${this.max}${s}`, o = this.label !== void 0 || this._hasSlotContent, n = e._STATE_LABELS[t];
139
+ return v`
116
140
  <div
117
141
  part="base"
118
142
  class="meter"
119
143
  role="meter"
120
144
  tabindex="0"
121
- aria-valuenow=${i}
145
+ aria-valuenow=${a}
122
146
  aria-valuemin=${this.min}
123
147
  aria-valuemax=${this.max}
124
- aria-valuetext=${a}
125
- aria-label=${m(o ? void 0 : `${i} of ${this.max}`)}
148
+ aria-valuetext=${i}
149
+ aria-label=${m(o ? void 0 : `${a} of ${this.max}`)}
126
150
  aria-labelledby=${m(o ? `${this._uid}-label` : void 0)}
127
151
  >
128
152
  <span
@@ -137,12 +161,15 @@ let e = class extends x {
137
161
  <div
138
162
  part="indicator"
139
163
  class="meter__indicator"
140
- style=${w({ width: `${r}%` })}
164
+ style=${y({ width: `${r}%` })}
141
165
  ></div>
142
166
  </div>
167
+ ${n ? v`<span class="meter__state-label" data-state=${t} aria-hidden="true"
168
+ >${n}</span
169
+ >` : _}
143
170
  <meter
144
171
  class="meter__native"
145
- value=${i}
172
+ value=${a}
146
173
  min=${this.min}
147
174
  max=${this.max}
148
175
  low=${m(this.low)}
@@ -155,36 +182,41 @@ let e = class extends x {
155
182
  `;
156
183
  }
157
184
  };
158
- e.styles = [$, y];
185
+ e.styles = [$, S];
159
186
  e._counter = 0;
160
- n([
187
+ e._STATE_LABELS = {
188
+ optimum: "Optimum",
189
+ warning: "Warning",
190
+ danger: "Danger"
191
+ };
192
+ l([
161
193
  h({ type: Number, reflect: !0 })
162
194
  ], e.prototype, "value", 2);
163
- n([
195
+ l([
164
196
  h({ type: Number, reflect: !0 })
165
197
  ], e.prototype, "min", 2);
166
- n([
198
+ l([
167
199
  h({ type: Number, reflect: !0 })
168
200
  ], e.prototype, "max", 2);
169
- n([
201
+ l([
170
202
  h({ type: Number, reflect: !0 })
171
203
  ], e.prototype, "low", 2);
172
- n([
204
+ l([
173
205
  h({ type: Number, reflect: !0 })
174
206
  ], e.prototype, "high", 2);
175
- n([
207
+ l([
176
208
  h({ type: Number, reflect: !0 })
177
209
  ], e.prototype, "optimum", 2);
178
- n([
210
+ l([
179
211
  h({ type: String })
180
212
  ], e.prototype, "label", 2);
181
- n([
182
- _()
213
+ l([
214
+ b()
183
215
  ], e.prototype, "_hasSlotContent", 2);
184
- e = n([
185
- b("hx-meter")
216
+ e = l([
217
+ w("hx-meter")
186
218
  ], e);
187
219
  export {
188
220
  e as H
189
221
  };
190
- //# sourceMappingURL=hx-meter-UinDQjl6.js.map
222
+ //# sourceMappingURL=hx-meter-CZ7lnMra.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hx-meter-CZ7lnMra.js","sources":["../../src/components/hx-meter/hx-meter.styles.ts","../../src/components/hx-meter/hx-meter.ts"],"sourcesContent":["import { css } from 'lit';\n\nexport const helixMeterStyles = css`\n :host {\n display: block;\n width: 100%;\n }\n\n .meter {\n display: flex;\n flex-direction: column;\n gap: var(--hx-space-2, 0.5rem);\n width: 100%;\n }\n\n .meter__label {\n font-size: var(--hx-font-size-sm, 0.875rem);\n font-weight: var(--hx-font-weight-medium, 500);\n color: var(--hx-meter-label-color, var(--hx-color-neutral-700, #374151));\n line-height: var(--hx-line-height-normal, 1.5);\n }\n\n .meter__track {\n position: relative;\n width: 100%;\n height: var(--hx-meter-track-height, var(--hx-size-2, 0.5rem));\n background-color: var(--hx-meter-track-color, var(--hx-color-neutral-200, #e5e7eb));\n border-radius: var(--hx-meter-track-radius, var(--hx-radius-full, 9999px));\n overflow: hidden;\n }\n\n .meter__indicator {\n position: absolute;\n inset-block: 0;\n inset-inline-start: 0;\n height: 100%;\n border-radius: inherit;\n background-color: var(--_indicator-color);\n transition:\n width var(--hx-duration-fast, 150ms) ease,\n background-color var(--hx-duration-fast, 150ms) ease;\n }\n\n /* ─── Default (no thresholds configured) ─── */\n\n :host {\n --_indicator-color: var(--hx-meter-indicator-color, var(--hx-color-primary-500, #3b82f6));\n }\n\n /* ─── Semantic state colors ─── */\n\n :host([data-state='optimum']) {\n --_indicator-color: var(--hx-meter-color-optimum, var(--hx-color-success-500, #22c55e));\n }\n\n :host([data-state='warning']) {\n --_indicator-color: var(--hx-meter-color-warning, var(--hx-color-warning-500, #f59e0b));\n }\n\n :host([data-state='danger']) {\n --_indicator-color: var(--hx-meter-color-danger, var(--hx-color-danger-500, #ef4444));\n }\n\n /* ─── State Label (WCAG 1.4.1) ─── */\n /* Visible text label rendered below the track when a semantic state is active. */\n /* Ensures the meter state is not conveyed by fill color alone. */\n /* aria-hidden=\"true\" because aria-valuetext already includes the state for AT. */\n\n .meter__state-label {\n font-size: var(--hx-font-size-xs, 0.75rem);\n font-weight: var(--hx-font-weight-medium, 500);\n line-height: var(--hx-line-height-tight, 1.25);\n font-family: var(--hx-font-family-sans, sans-serif);\n }\n\n .meter__state-label[data-state='optimum'] {\n color: var(--hx-meter-color-optimum, var(--hx-color-success-700, #15803d));\n }\n\n .meter__state-label[data-state='warning'] {\n color: var(--hx-meter-color-warning, var(--hx-color-warning-700, #b45309));\n }\n\n .meter__state-label[data-state='danger'] {\n color: var(--hx-meter-color-danger, var(--hx-color-danger-700, #b91c1c));\n }\n\n /* ─── Native meter hidden (we use custom rendering) ─── */\n\n .meter__native {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip: rect(0, 0, 0, 0);\n white-space: nowrap;\n border: 0;\n }\n`;\n","import { LitElement, html, nothing } from 'lit';\nimport { customElement, property, state } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { styleMap } from 'lit/directives/style-map.js';\nimport { tokenStyles } from '@helixui/tokens/lit';\nimport { helixMeterStyles } from './hx-meter.styles.js';\n\ntype MeterState = 'optimum' | 'warning' | 'danger' | 'default';\n\n/**\n * A scalar measurement within a known range — e.g., disk usage, health score,\n * or any numeric value with defined min/max bounds. Supports low/high/optimum\n * threshold markers for semantic color feedback.\n *\n * @summary Scalar measurement gauge within a defined range.\n *\n * @tag hx-meter\n *\n * @slot label - Visible label rendered above the meter track. When using this\n * slot without the `label` attribute, the accessible name is derived from the\n * slot content via `aria-labelledby`. The `label` attribute is NOT required\n * when slot content is provided — the component detects slot content and\n * switches to `aria-labelledby` automatically.\n *\n * @csspart base - The outer wrapper element.\n * @csspart track - The unfilled track bar element.\n * @csspart indicator - The filled bar indicating the current value.\n * @csspart label - The label wrapper element.\n *\n * @cssprop [--hx-meter-track-height] - Height of the track bar.\n * @cssprop [--hx-meter-track-color] - Background color of the unfilled track.\n * @cssprop [--hx-meter-track-radius] - Border radius of the track.\n * @cssprop [--hx-meter-indicator-color] - Default filled bar color (no thresholds).\n * @cssprop [--hx-meter-color-optimum] - Color when value is in the optimum zone.\n * @cssprop [--hx-meter-color-warning] - Color when value is in a warning zone.\n * @cssprop [--hx-meter-color-danger] - Color when value is in the danger zone.\n * @cssprop [--hx-meter-label-color] - Label text color.\n */\n@customElement('hx-meter')\nexport class HelixMeter extends LitElement {\n static override styles = [tokenStyles, helixMeterStyles];\n\n private static _counter = 0;\n private _uid = `hx-meter-${++HelixMeter._counter}`;\n\n /**\n * Current value of the meter.\n * @attr value\n */\n @property({ type: Number, reflect: true })\n value = 0;\n\n /**\n * Minimum value of the range.\n * @attr min\n */\n @property({ type: Number, reflect: true })\n min = 0;\n\n /**\n * Maximum value of the range.\n * @attr max\n */\n @property({ type: Number, reflect: true })\n max = 100;\n\n /**\n * Threshold below which the value is considered suboptimal (lower range warning).\n * @attr low\n */\n @property({ type: Number, reflect: true })\n low?: number;\n\n /**\n * Threshold above which the value is considered suboptimal (upper range warning).\n * @attr high\n */\n @property({ type: Number, reflect: true })\n high?: number;\n\n /**\n * The optimal value within the range. Used to determine which zone is \"good\".\n * @attr optimum\n */\n @property({ type: Number, reflect: true })\n optimum?: number;\n\n /**\n * Accessible label for the meter. Used as the visible label text and as\n * the source for `aria-labelledby`. When only slot content is provided\n * (no `label` attribute), the slot content is used for the accessible name.\n * @attr label\n */\n @property({ type: String })\n label?: string;\n\n @state()\n private _hasSlotContent = false;\n\n private _clampedValue(): number {\n return Math.min(Math.max(this.value, this.min), this.max);\n }\n\n private _percentage(): number {\n const range = this.max - this.min;\n if (range === 0) return 0;\n return ((this._clampedValue() - this.min) / range) * 100;\n }\n\n private _resolveState(): MeterState {\n const v = this._clampedValue();\n const hasLow = this.low !== undefined;\n const hasHigh = this.high !== undefined;\n const hasOptimum = this.optimum !== undefined;\n\n if (!hasLow && !hasHigh && !hasOptimum) return 'default';\n\n // When hasLow/hasHigh/hasOptimum are true, the corresponding property is defined.\n // Use nullish coalescing to satisfy the type checker while preserving the runtime logic.\n const lowVal = this.low ?? 0;\n const highVal = this.high ?? this.max;\n const inLowZone = hasLow && v < lowVal;\n const inHighZone = hasHigh && v > highVal;\n const inMiddleZone = !inLowZone && !inHighZone;\n\n if (!hasOptimum) {\n if (inLowZone || inHighZone) return 'warning';\n return 'optimum';\n }\n\n const opt = this.optimum ?? this.min;\n const optimumInLow = hasLow && opt < lowVal;\n const optimumInHigh = hasHigh && opt > highVal;\n const optimumInMiddle = !optimumInLow && !optimumInHigh;\n\n if (optimumInMiddle) {\n if (inMiddleZone) return 'optimum';\n return 'warning';\n } else if (optimumInLow) {\n if (inLowZone) return 'optimum';\n if (inMiddleZone) return 'warning';\n return 'danger';\n } else {\n // optimumInHigh\n if (inHighZone) return 'optimum';\n if (inMiddleZone) return 'warning';\n return 'danger';\n }\n }\n\n private _onLabelSlotChange(e: Event) {\n const slot = e.target as HTMLSlotElement;\n this._hasSlotContent = slot.assignedNodes({ flatten: true }).length > 0;\n }\n\n override updated() {\n // Set data-state on host so :host([data-state]) CSS selectors work\n this.dataset['state'] = this._resolveState();\n }\n\n // ─── WCAG 1.4.1: State label map ───\n // The indicator bar color alone is insufficient for color-blind users.\n // A visible state label is rendered below the track when a semantic state\n // (optimum/warning/danger) is active, providing a non-color visual cue.\n // aria-valuetext already embeds the state for AT users.\n\n private static readonly _STATE_LABELS: Partial<Record<MeterState, string>> = {\n optimum: 'Optimum',\n warning: 'Warning',\n danger: 'Danger',\n };\n\n override render() {\n const pct = this._percentage();\n const state = this._resolveState();\n const clampedValue = this._clampedValue();\n const stateLabel = state !== 'default' ? ` — ${state}` : '';\n const ariaValuetext = `${clampedValue} of ${this.max}${stateLabel}`;\n const hasVisibleLabel = this.label !== undefined || this._hasSlotContent;\n const visibleStateLabel = HelixMeter._STATE_LABELS[state];\n\n return html`\n <div\n part=\"base\"\n class=\"meter\"\n role=\"meter\"\n tabindex=\"0\"\n aria-valuenow=${clampedValue}\n aria-valuemin=${this.min}\n aria-valuemax=${this.max}\n aria-valuetext=${ariaValuetext}\n aria-label=${ifDefined(!hasVisibleLabel ? `${clampedValue} of ${this.max}` : undefined)}\n aria-labelledby=${ifDefined(hasVisibleLabel ? `${this._uid}-label` : undefined)}\n >\n <span\n id=${`${this._uid}-label`}\n part=\"label\"\n class=\"meter__label\"\n ?hidden=${!hasVisibleLabel}\n >\n <slot name=\"label\" @slotchange=${this._onLabelSlotChange}>${this.label ?? ''}</slot>\n </span>\n <div class=\"meter__track\" part=\"track\">\n <div\n part=\"indicator\"\n class=\"meter__indicator\"\n style=${styleMap({ width: `${pct}%` })}\n ></div>\n </div>\n ${visibleStateLabel\n ? html`<span class=\"meter__state-label\" data-state=${state} aria-hidden=\"true\"\n >${visibleStateLabel}</span\n >`\n : nothing}\n <meter\n class=\"meter__native\"\n value=${clampedValue}\n min=${this.min}\n max=${this.max}\n low=${ifDefined(this.low)}\n high=${ifDefined(this.high)}\n optimum=${ifDefined(this.optimum)}\n aria-hidden=\"true\"\n tabindex=\"-1\"\n ></meter>\n </div>\n `;\n }\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'hx-meter': HelixMeter;\n }\n}\n"],"names":["helixMeterStyles","css","HelixMeter","LitElement","range","v","hasLow","hasHigh","hasOptimum","lowVal","highVal","inLowZone","inHighZone","inMiddleZone","opt","optimumInLow","optimumInHigh","e","slot","pct","state","clampedValue","stateLabel","ariaValuetext","hasVisibleLabel","visibleStateLabel","html","ifDefined","styleMap","nothing","tokenStyles","__decorateClass","property","customElement"],"mappings":"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"}