@fusion.dev/helix-headless 0.0.0-dev → 0.0.3

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 (210) hide show
  1. package/custom-elements.json +4513 -4483
  2. package/dist/accordion/item/accordion-item.d.ts +13 -15
  3. package/dist/accordion/item/accordion-item.js +15 -17
  4. package/dist/announcement/root/announcement-root.d.ts +7 -25
  5. package/dist/announcement/root/announcement-root.js +7 -20
  6. package/dist/app-header/root/app-header-root.d.ts +10 -17
  7. package/dist/app-header/root/app-header-root.js +9 -18
  8. package/dist/avatar/group/avatar-group.d.ts +10 -19
  9. package/dist/avatar/group/avatar-group.js +12 -17
  10. package/dist/avatar/root/avatar-root.d.ts +8 -8
  11. package/dist/avatar/root/avatar-root.js +19 -20
  12. package/dist/badge/root/badge-root.d.ts +6 -6
  13. package/dist/badge/root/badge-root.js +13 -13
  14. package/dist/bar-chart/root/bar-chart-root.d.ts +21 -29
  15. package/dist/bar-chart/root/bar-chart-root.js +42 -57
  16. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +12 -18
  17. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +13 -16
  18. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -28
  19. package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -28
  20. package/dist/button/root/button-root.d.ts +84 -94
  21. package/dist/button/root/button-root.js +82 -92
  22. package/dist/callout/root/callout-root.d.ts +4 -5
  23. package/dist/carousel/root/carousel-root.d.ts +59 -71
  24. package/dist/carousel/root/carousel-root.js +73 -101
  25. package/dist/chat/composer/chat-composer.d.ts +29 -33
  26. package/dist/chat/composer/chat-composer.js +40 -44
  27. package/dist/chat/message/chat-message.d.ts +25 -25
  28. package/dist/chat/message/chat-message.js +26 -26
  29. package/dist/chat/root/chat-root.d.ts +28 -41
  30. package/dist/chat/root/chat-root.js +27 -40
  31. package/dist/checkbox/root/checkbox-root.d.ts +10 -12
  32. package/dist/checkbox/root/checkbox-root.js +29 -35
  33. package/dist/checkbox-group/root/checkbox-group-root.d.ts +32 -45
  34. package/dist/checkbox-group/root/checkbox-group-root.js +53 -79
  35. package/dist/code-block/root/code-block-root.d.ts +3 -4
  36. package/dist/code-block/root/code-block-root.js +8 -12
  37. package/dist/color-input/root/color-input-root.d.ts +36 -37
  38. package/dist/color-input/root/color-input-root.js +29 -34
  39. package/dist/color-picker/color.d.ts +7 -8
  40. package/dist/color-picker/color.js +7 -8
  41. package/dist/color-picker/root/color-picker-root.d.ts +55 -57
  42. package/dist/color-picker/root/color-picker-root.js +60 -64
  43. package/dist/combobox/root/combobox-root.d.ts +53 -58
  44. package/dist/combobox/root/combobox-root.js +85 -94
  45. package/dist/command/root/command-root.d.ts +8 -8
  46. package/dist/command/root/command-root.js +29 -33
  47. package/dist/copy-button/root/copy-button-root.d.ts +21 -24
  48. package/dist/copy-button/root/copy-button-root.js +25 -35
  49. package/dist/data-table/root/data-table-root.d.ts +77 -76
  50. package/dist/data-table/root/data-table-root.js +95 -84
  51. package/dist/data-table/root/order.d.ts +2 -2
  52. package/dist/data-table/root/order.js +1 -3
  53. package/dist/date-input/root/date-input-root.d.ts +88 -93
  54. package/dist/date-input/root/date-input-root.js +147 -158
  55. package/dist/date-picker/root/date-picker-root.d.ts +75 -83
  56. package/dist/date-picker/root/date-picker-root.js +120 -143
  57. package/dist/dialog/root/dialog-root.d.ts +41 -24
  58. package/dist/dialog/root/dialog-root.js +47 -24
  59. package/dist/divider/root/divider-root.d.ts +5 -6
  60. package/dist/divider/root/divider-root.js +4 -5
  61. package/dist/donut-chart/root/donut-chart-root.d.ts +22 -25
  62. package/dist/donut-chart/root/donut-chart-root.js +37 -51
  63. package/dist/drawer/root/drawer-root.d.ts +24 -29
  64. package/dist/drawer/root/drawer-root.js +15 -22
  65. package/dist/drilldown/item/drilldown-item.d.ts +14 -14
  66. package/dist/drilldown/item/drilldown-item.js +24 -26
  67. package/dist/drilldown/root/drilldown-root.d.ts +8 -10
  68. package/dist/drilldown/root/drilldown-root.js +6 -7
  69. package/dist/element-events.generated.js +1 -1
  70. package/dist/file-input/root/file-input-root.d.ts +20 -24
  71. package/dist/file-input/root/file-input-root.js +42 -57
  72. package/dist/format-date/root/format-date-root.js +1 -1
  73. package/dist/heatmap/root/buckets.d.ts +8 -8
  74. package/dist/heatmap/root/buckets.js +8 -8
  75. package/dist/heatmap/root/heatmap-root.d.ts +57 -63
  76. package/dist/heatmap/root/heatmap-root.js +72 -83
  77. package/dist/icon/root/icon-root.d.ts +4 -4
  78. package/dist/icon/root/icon-root.js +9 -9
  79. package/dist/icon-button/root/icon-button-root.d.ts +4 -6
  80. package/dist/icon-button/root/icon-button-root.js +4 -6
  81. package/dist/image/root/image-root.d.ts +49 -59
  82. package/dist/image/root/image-root.js +55 -65
  83. package/dist/index.d.ts +5 -5
  84. package/dist/index.js +5 -5
  85. package/dist/input/root/input-root.d.ts +61 -85
  86. package/dist/input/root/input-root.js +79 -106
  87. package/dist/kbd/root/kbd-root.d.ts +8 -7
  88. package/dist/kbd/root/kbd-root.js +71 -11
  89. package/dist/legend/root/legend-root.d.ts +1 -1
  90. package/dist/legend/root/legend-root.js +4 -5
  91. package/dist/line-chart/root/line-chart-root.d.ts +26 -30
  92. package/dist/line-chart/root/line-chart-root.js +10 -10
  93. package/dist/list/item/list-item.d.ts +14 -18
  94. package/dist/list/item/list-item.js +18 -22
  95. package/dist/list/root/list-root.d.ts +4 -4
  96. package/dist/list/root/list-root.js +3 -3
  97. package/dist/listbox/root/listbox-root.d.ts +31 -58
  98. package/dist/listbox/root/listbox-root.js +66 -109
  99. package/dist/megamenu/root/megamenu-root.d.ts +34 -35
  100. package/dist/megamenu/root/megamenu-root.js +53 -58
  101. package/dist/menu/item/menu-item.d.ts +39 -53
  102. package/dist/menu/item/menu-item.js +50 -64
  103. package/dist/menu/root/menu-root.d.ts +30 -40
  104. package/dist/menu/root/menu-root.js +49 -82
  105. package/dist/meter/root/meter-root.d.ts +49 -53
  106. package/dist/meter/root/meter-root.js +22 -27
  107. package/dist/navigation/root/navigation-root.js +11 -19
  108. package/dist/notifications/notification/notification.d.ts +16 -22
  109. package/dist/notifications/notification/notification.js +21 -27
  110. package/dist/notifications/root/notifications-root.d.ts +31 -39
  111. package/dist/notifications/root/notifications-root.js +41 -52
  112. package/dist/number-input/root/number-input-root.d.ts +31 -33
  113. package/dist/number-input/root/number-input-root.js +37 -39
  114. package/dist/option/root/option-root.d.ts +73 -74
  115. package/dist/option/root/option-root.js +62 -64
  116. package/dist/outline/root/outline-root.d.ts +38 -44
  117. package/dist/outline/root/outline-root.js +66 -82
  118. package/dist/pagination/root/pagination-root.d.ts +87 -92
  119. package/dist/pagination/root/pagination-root.js +116 -123
  120. package/dist/pagination/size/pagination-size.d.ts +31 -50
  121. package/dist/pagination/size/pagination-size.js +35 -55
  122. package/dist/pagination/summary/pagination-summary.d.ts +12 -12
  123. package/dist/pagination/summary/pagination-summary.js +18 -18
  124. package/dist/pin-input/root/pin-input-root.d.ts +53 -70
  125. package/dist/pin-input/root/pin-input-root.js +74 -94
  126. package/dist/popover/root/popover-root.d.ts +15 -20
  127. package/dist/popover/root/popover-root.js +19 -36
  128. package/dist/progress/root/progress-root.d.ts +12 -14
  129. package/dist/progress/root/progress-root.js +22 -25
  130. package/dist/qr-code/root/qr-code-root.d.ts +11 -11
  131. package/dist/qr-code/root/qr-code-root.js +12 -14
  132. package/dist/radio/group/radio-group.js +19 -26
  133. package/dist/radio/root/radio-root.d.ts +12 -13
  134. package/dist/radio/root/radio-root.js +12 -13
  135. package/dist/rating/root/rating-root.d.ts +25 -30
  136. package/dist/rating/root/rating-root.js +43 -50
  137. package/dist/scroll-area/root/scroll-area-root.d.ts +11 -14
  138. package/dist/scroll-area/root/scroll-area-root.js +39 -33
  139. package/dist/select/root/select-root.d.ts +7 -12
  140. package/dist/select/root/select-root.js +40 -55
  141. package/dist/slider/root/slider-root.d.ts +53 -60
  142. package/dist/slider/root/slider-root.js +74 -85
  143. package/dist/sparkline/root/sparkline-root.d.ts +43 -47
  144. package/dist/sparkline/root/sparkline-root.js +23 -32
  145. package/dist/speed-dial/item/speed-dial-item.d.ts +6 -6
  146. package/dist/speed-dial/item/speed-dial-item.js +9 -9
  147. package/dist/speed-dial/root/speed-dial-root.d.ts +21 -25
  148. package/dist/speed-dial/root/speed-dial-root.js +32 -40
  149. package/dist/splitter/root/splitter-root.d.ts +98 -111
  150. package/dist/splitter/root/splitter-root.js +96 -123
  151. package/dist/stat/root/stat-root.d.ts +2 -7
  152. package/dist/stat/root/stat-root.js +0 -5
  153. package/dist/steps/step/step.d.ts +19 -24
  154. package/dist/steps/step/step.js +27 -32
  155. package/dist/switch/root/switch-root.js +2 -2
  156. package/dist/table/column/table-column.d.ts +54 -60
  157. package/dist/table/column/table-column.js +95 -68
  158. package/dist/table/root/table-root.d.ts +5 -6
  159. package/dist/table/root/table-root.js +7 -10
  160. package/dist/tabs/panel/tab-panel.d.ts +21 -25
  161. package/dist/tabs/panel/tab-panel.js +25 -29
  162. package/dist/tabs/root/tabs-root.d.ts +25 -34
  163. package/dist/tabs/root/tabs-root.js +22 -28
  164. package/dist/tabs/tab/tab.d.ts +12 -12
  165. package/dist/tabs/tab/tab.js +19 -20
  166. package/dist/textarea/root/textarea-root.d.ts +36 -36
  167. package/dist/textarea/root/textarea-root.js +43 -47
  168. package/dist/time-input/root/time-input-root.d.ts +58 -68
  169. package/dist/time-input/root/time-input-root.js +62 -77
  170. package/dist/time-picker/root/time-picker-root.d.ts +73 -79
  171. package/dist/time-picker/root/time-picker-root.js +72 -84
  172. package/dist/timeline/item/timeline-item.d.ts +8 -11
  173. package/dist/timeline/item/timeline-item.js +8 -11
  174. package/dist/timeline/root/timeline-root.d.ts +5 -7
  175. package/dist/timeline/root/timeline-root.js +5 -7
  176. package/dist/toast/item/toast-item.d.ts +9 -27
  177. package/dist/toast/item/toast-item.js +19 -41
  178. package/dist/toast/root/toast-root.d.ts +10 -14
  179. package/dist/toast/root/toast-root.js +4 -5
  180. package/dist/toggle/group/toggle-group.d.ts +6 -15
  181. package/dist/toggle/group/toggle-group.js +21 -36
  182. package/dist/toggle/root/toggle-root.d.ts +26 -27
  183. package/dist/toggle/root/toggle-root.js +30 -31
  184. package/dist/toolbar/root/toolbar-root.d.ts +7 -10
  185. package/dist/toolbar/root/toolbar-root.js +10 -14
  186. package/dist/tooltip/root/tooltip-root.d.ts +52 -59
  187. package/dist/tooltip/root/tooltip-root.js +98 -93
  188. package/dist/tour/root/tour-root.d.ts +19 -23
  189. package/dist/tour/root/tour-root.js +31 -41
  190. package/dist/tour/stop/tour-stop.d.ts +14 -15
  191. package/dist/tour/stop/tour-stop.js +31 -34
  192. package/dist/tree/item/tree-item.d.ts +30 -35
  193. package/dist/tree/item/tree-item.js +43 -55
  194. package/dist/tree/root/tree-root.d.ts +7 -10
  195. package/dist/tree/root/tree-root.js +33 -42
  196. package/dist/trend/root/trend-root.d.ts +3 -5
  197. package/dist/trend/root/trend-root.js +5 -9
  198. package/dist/video/root/video-root.d.ts +100 -124
  199. package/dist/video/root/video-root.js +142 -176
  200. package/dist/video-playlist/item/video-playlist-item.d.ts +16 -16
  201. package/dist/video-playlist/item/video-playlist-item.js +24 -24
  202. package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -8
  203. package/dist/video-playlist/menu/video-playlist-menu.js +20 -29
  204. package/dist/video-playlist/root/video-playlist-root.d.ts +16 -11
  205. package/dist/video-playlist/root/video-playlist-root.js +21 -25
  206. package/dist/virtual-list/root/virtual-list-root.d.ts +8 -12
  207. package/dist/virtual-list/root/virtual-list-root.js +11 -16
  208. package/jsx.d.ts +9797 -12561
  209. package/package.json +6 -6
  210. package/vue.d.ts +2684 -3228
@@ -56,42 +56,35 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
56
56
  constructor() {
57
57
  super(...arguments);
58
58
  /**
59
- * Preferred side.
60
- *
61
- * It moves if that side does not fit.
62
- */
63
- this.placement = 'bottom-start';
64
- /**
65
- * Space between the trigger and the surface, in pixels.
59
+ * What the row returning from a submenu reads.
66
60
  */
67
- this.offset = 4;
61
+ this.backLabel = 'Back';
68
62
  /**
69
63
  * Accessible name for the surface.
70
64
  */
71
65
  this.label = 'Menu';
72
66
  /**
73
- * What the row returning from a submenu reads.
67
+ * Space between the trigger and the surface, in pixels.
74
68
  */
75
- this.backLabel = 'Back';
69
+ this.offset = 4;
70
+ /**
71
+ * Preferred side.
72
+ *
73
+ * It moves if that side does not fit.
74
+ */
75
+ this.placement = 'bottom-start';
76
76
  /**
77
77
  * Which page is showing, and what is on it.
78
78
  *
79
- * This was a `page` field, a title getter and an items getter written here.
80
- * None of them were about menus: a settings panel or a navigation tree wants
81
- * the same thing, and could not have it without being a menu. The controller
82
- * holds the same shape, so the port is a rename rather than a rewrite, and it
83
- * adds a real stack: `back()` returns one level instead of to the root, which
84
- * this could not do because it only ever went two deep.
79
+ * A controller rather than fields here, because none of this is about menus:
80
+ * a settings panel or a navigation tree wants the same shape. It holds a real
81
+ * stack, so `back()` returns one level rather than to the root.
85
82
  */
86
83
  this.drilldown = new DrilldownController(this, {
87
84
  isRow: (element) => 'isMenuItem' in element && element.isMenuItem === true,
88
85
  root: () => [...this.children].filter((child) => child.slot !== 'trigger'),
89
86
  slot: 'submenu',
90
87
  });
91
- /* One controller where there were two and a hand-written sequence between
92
- them. It is the same three things in the same order; what it is not is a
93
- third copy of them, and the second copy is how `Select` ended up never
94
- reaching the top layer at all. */
95
88
  /**
96
89
  * Moving between rows, which is not this element's own business any more.
97
90
  *
@@ -99,14 +92,12 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
99
92
  * choosing are one act in a radio group and two acts here, which is the
100
93
  * distinction the controller was already drawing for `Tabs`.
101
94
  *
102
- * The origin is the selection, which took a wrong turn first and is worth
103
- * recording. `focus` looks like the right reading, since a menu's current row
104
- * is the focused one, but that origin also carries a rule a menu must not
105
- * follow: a press that did not come from the set moves nothing. That rule is
106
- * there for a tab panel, which is a tab stop beside the tabs; a menu's panel
107
- * holds the rows and nothing else, and Down on a menu that has just opened is
108
- * how a reader gets to the first row at all. It moved nothing, and the specs
109
- * written alongside this are what said so.
95
+ * The origin is the selection, and `focus` is the wrong reading however right
96
+ * it looks: that origin also carries a rule a menu must not follow, that a
97
+ * press which did not come from the set moves nothing. That rule is there for
98
+ * a tab panel, which is a tab stop beside the tabs; a menu's panel holds the
99
+ * rows and nothing else, and Down on a menu that has just opened is how a
100
+ * reader gets to the first row at all.
110
101
  *
111
102
  * The horizontal pair is reserved rather than released. Right opens a
112
103
  * submenu and left comes back, which are the platform's own bindings for a
@@ -144,30 +135,12 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
144
135
  }
145
136
  this.hide();
146
137
  };
147
- /*
148
- * Moves over the page, in the direction the key points.
149
- *
150
- * The arrows wrap, because a menu is a ring rather than a list with ends:
151
- * pressing down on the last item to reach the first is what every menu on
152
- * every platform does.
153
- */
154
- /*
155
- * Focuses an item and brings it into the surface, which is not the same act.
156
- *
157
- * A menu long enough to scroll had the tree's problem: the arrow keys moved
158
- * focus past the bottom of the panel and the panel stayed where it was.
159
- * Scrolled here rather than by the browser, because `scrollIntoView` would
160
- * take the page behind the menu with it.
161
- */
162
138
  /**
163
139
  * Keeps whatever has focus in sight, however it got there.
164
140
  *
165
- * This was done in the arrow branches, which meant it was true of the arrow
166
- * keys and of nothing else: a row reached by Tab, or focused by the drilldown
167
- * on the way into a page, could sit below the fold of a scrolled panel. On
168
- * `focusin` it is one rule about focus rather than a line repeated in every
169
- * branch that moves it, and it survived the arrow keys moving out to a shared
170
- * controller that knows nothing about this panel.
141
+ * On `focusin` rather than in the branches that move focus: a row reached by
142
+ * Tab, or focused by the drilldown on the way into a page, can otherwise sit
143
+ * below the fold of a scrolled panel.
171
144
  */
172
145
  this.handleFocusIn = (event) => {
173
146
  const item = this.items.find((row) => row.contains(event.target));
@@ -177,14 +150,10 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
177
150
  /* `surface`, which is the part this template renders and the name the
178
151
  whole library spells this box with.
179
152
 
180
- *Rewritten 28 Aug 2026, because it had come to say the reverse.* The
181
- fault it records is real and was the other way round: the lookup asked
182
- for a name the template did not render, found null, and `scrollItemIntoView`
183
- ran with no scroller and took the page behind the menu with it, which is
184
- the one thing that method exists to prevent. What the comment could not
185
- know is that `check:vocabulary` later renamed the part *to* `surface`, so
186
- a note naming `menu` as the right answer now teaches the opposite of the
187
- rule that settled it. The lookup and the part have agreed since. */
153
+ Keep the two in step. A lookup asking for a name the template does not
154
+ render finds null, and `scrollItemIntoView` then runs with no scroller and
155
+ takes the page behind the menu with it, which is the one thing that method
156
+ exists to prevent. */
188
157
  const surface = this.renderRoot.querySelector('[part="surface"]');
189
158
  scrollItemIntoView(item, { padding: 4, ...(surface ? { scroller: surface } : {}) });
190
159
  };
@@ -204,9 +173,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
204
173
  else if (event.key === 'Tab') {
205
174
  /* Out, and the panel goes with it.
206
175
  *
207
- * Nothing closed the menu when focus left it, so tabbing out of an open
208
- * one left a shadowed panel in the top layer sitting over whatever the
209
- * reader had tabbed to. Deliberately not prevented: focus should carry on
176
+ * Nothing else closes the menu when focus leaves it, so tabbing out of an
177
+ * open one would leave a shadowed panel in the top layer sitting over
178
+ * whatever the reader tabbed to. Deliberately not prevented: focus carries on
210
179
  * outward, which is what the reader asked for. And deliberately not a
211
180
  * focus trap, because a menu is not a modal and Tab is a way out of one. */
212
181
  this.hide();
@@ -229,11 +198,10 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
229
198
  /**
230
199
  * Tells a slotted trigger the disclosure state, by property.
231
200
  *
232
- * This menu wrote nothing onto its trigger, which was the right call and cost
233
- * a reader the one thing they needed: a control that opens a menu and never
234
- * says so. The class note above already gives the mechanism for the way out,
235
- * that items are "told by property, not by attribute", and `tellDisclosure`
236
- * is that argument applied one level up. See #322.
201
+ * A control that opens a menu has to say so. By property rather than by
202
+ * attribute, which is the class note's rule about items applied one level up:
203
+ * an attribute written onto a consumer's element after it upgrades is a
204
+ * hydration mismatch waiting to happen.
237
205
  */
238
206
  tellTrigger() {
239
207
  const slot = this.renderRoot?.querySelector('slot[name="trigger"]');
@@ -248,9 +216,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
248
216
  /* Disabled rows are not there for the keyboard.
249
217
  *
250
218
  * A disabled row renders no `tabindex` and cannot take focus, so leaving it
251
- * in the list meant the arrow keys computed a move onto it, called `focus()`
252
- * on something unfocusable, and stopped: the keyboard was stuck one row
253
- * above every disabled item in the menu. `Drilldown` filters for the same
219
+ * in the list has the arrow keys compute a move onto it, call `focus()` on
220
+ * something unfocusable, and stop: the keyboard is then stuck one row above
221
+ * every disabled item in the menu. `Drilldown` filters for the same
254
222
  * reason. */
255
223
  return this.drilldown.rows.filter((row) => !row.disabled);
256
224
  }
@@ -322,10 +290,10 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
322
290
  super.updated(changed);
323
291
  // Every update, so a trigger slotted after the first render is told too.
324
292
  this.tellTrigger();
325
- /* Put the panel where `open` says, however it got there. `show()` and
326
- `hide()` raised and lowered it and nothing else did, so a menu opened by
327
- declaring `open` rendered visible, out of the top layer and unanchored:
328
- every imperative path worked and every declarative one was half-open. */
293
+ /* Put the panel where `open` says, however it got there. Raising it in
294
+ `show()` and lowering it in `hide()` alone leaves a menu opened by
295
+ declaring `open` visible, out of the top layer and unanchored: every
296
+ imperative path works and every declarative one is half-open. */
329
297
  if (changed.has('open')) {
330
298
  /* Here rather than a microtask later: `updated()` runs after the render,
331
299
  so the panel is no longer `display: none` and `showPopover` is safe. */
@@ -350,11 +318,10 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
350
318
  /**
351
319
  * Walks the tree marking which rows are on the page showing.
352
320
  *
353
- * Two levels were marked by hand and nothing wrote `showingSubmenu` on a
354
- * nested row, so drilling into a third-level submenu rendered the header over
355
- * an empty panel: the page existed, its rows were still marked as belonging
356
- * to the level above, and none of them rendered. `Drilldown.mark()` is the
357
- * same walk and was already recursive.
321
+ * Recursive rather than two levels by hand: without `showingSubmenu` on a
322
+ * nested row, drilling into a third-level submenu renders the header over an
323
+ * empty panel, the page existing while its rows are still marked as belonging
324
+ * to the level above. `Drilldown.mark()` is the same walk.
358
325
  *
359
326
  * `slot === 'submenu'` rather than every child, because a row's other
360
327
  * children are its label and its icons.
@@ -404,18 +371,18 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
404
371
  </div>`;
405
372
  }
406
373
  };
374
+ __decorate([
375
+ property({ attribute: 'back-label' })
376
+ ], HelixHeadlessMenu.prototype, "backLabel", void 0);
407
377
  __decorate([
408
378
  property()
409
- ], HelixHeadlessMenu.prototype, "placement", void 0);
379
+ ], HelixHeadlessMenu.prototype, "label", void 0);
410
380
  __decorate([
411
381
  property({ type: Number })
412
382
  ], HelixHeadlessMenu.prototype, "offset", void 0);
413
383
  __decorate([
414
384
  property()
415
- ], HelixHeadlessMenu.prototype, "label", void 0);
416
- __decorate([
417
- property({ attribute: 'back-label' })
418
- ], HelixHeadlessMenu.prototype, "backLabel", void 0);
385
+ ], HelixHeadlessMenu.prototype, "placement", void 0);
419
386
  HelixHeadlessMenu = __decorate([
420
387
  customElement('helix-headless-menu')
421
388
  ], HelixHeadlessMenu);
@@ -53,50 +53,6 @@ export type MeterBand = 'fair' | 'good' | 'poor';
53
53
  * @cssproperty --meter-sweep - How much of the circle the arc covers, as a path length.
54
54
  */
55
55
  export declare class HelixHeadlessMeter extends HelixElement {
56
- /**
57
- * Accessible name for the reading.
58
- */
59
- label: string;
60
- /**
61
- * Bottom of the range.
62
- */
63
- min: number;
64
- /**
65
- * Top of the range.
66
- *
67
- * A hundred rather than the platform's one, which is what `Progress` already
68
- * takes and what a consumer writing `value="72"` means. A range of zero to one
69
- * is a fraction, and a component that reads `value="72"` as seventy-two times
70
- * over its maximum is a trap that costs nothing to avoid.
71
- */
72
- max: number;
73
- /**
74
- * Where the reading sits between `min` and `max`.
75
- *
76
- * Outside them, it clamps.
77
- */
78
- value: number;
79
- /**
80
- * Top of the low band.
81
- *
82
- * Absent leaves the range unbanded.
83
- */
84
- low?: number;
85
- /**
86
- * Bottom of the high band.
87
- *
88
- * Absent leaves the range unbanded.
89
- */
90
- high?: number;
91
- /**
92
- * Where in the range it is best to be.
93
- *
94
- * Defaults to the middle of whatever bands are declared, which is the
95
- * platform's own default and the right one for a score. A meter where low is
96
- * good, like disk usage, says `optimum="0"`; one where high is good, like a
97
- * battery, says `optimum="100"`.
98
- */
99
- optimum?: number;
100
56
  /**
101
57
  * The band, said outright, where the three thresholds cannot say it.
102
58
  *
@@ -121,10 +77,47 @@ export declare class HelixHeadlessMeter extends HelixElement {
121
77
  *
122
78
  * Not reflected. Nothing selects on it: the band reaches the stylesheet as
123
79
  * `data-band` on the fill, because that is the element being colored, so
124
- * reflecting here would write an attribute onto the host for no reader. Third
125
- * time this rule has caught something today.
80
+ * reflecting here would write an attribute onto the host for no reader.
126
81
  */
127
82
  band?: MeterBand;
83
+ /**
84
+ * Bottom of the high band.
85
+ *
86
+ * Absent leaves the range unbanded.
87
+ */
88
+ high?: number;
89
+ /**
90
+ * Accessible name for the reading.
91
+ */
92
+ label: string;
93
+ /**
94
+ * Top of the low band.
95
+ *
96
+ * Absent leaves the range unbanded.
97
+ */
98
+ low?: number;
99
+ /**
100
+ * Top of the range.
101
+ *
102
+ * A hundred rather than the platform's one, which is what `Progress` already
103
+ * takes and what a consumer writing `value="72"` means. A range of zero to one
104
+ * is a fraction, and a component that reads `value="72"` as seventy-two times
105
+ * over its maximum is a trap that costs nothing to avoid.
106
+ */
107
+ max: number;
108
+ /**
109
+ * Bottom of the range.
110
+ */
111
+ min: number;
112
+ /**
113
+ * Where in the range it is best to be.
114
+ *
115
+ * Defaults to the middle of whatever bands are declared, which is the
116
+ * platform's own default and the right one for a score. A meter where low is
117
+ * good, like disk usage, says `optimum="0"`; one where high is good, like a
118
+ * battery, says `optimum="100"`.
119
+ */
120
+ optimum?: number;
128
121
  /**
129
122
  * Whether the reading is drawn as a bar, a ring or an arc.
130
123
  *
@@ -148,6 +141,12 @@ export declare class HelixHeadlessMeter extends HelixElement {
148
141
  * Whether the reading is shown beside the bar.
149
142
  */
150
143
  showValue: boolean;
144
+ /**
145
+ * Where the reading sits between `min` and `max`.
146
+ *
147
+ * Outside them, it clamps.
148
+ */
149
+ value: number;
151
150
  /**
152
151
  * What the reading says, where a number is not the whole story.
153
152
  *
@@ -170,15 +169,12 @@ export declare class HelixHeadlessMeter extends HelixElement {
170
169
  /**
171
170
  * Where the value really sits, which is what the words report.
172
171
  *
173
- * **A value past the end used to be swallowed twice.** The bar filled and the
174
- * reading said "100%", so 110 and 250 were indistinguishable from exactly
175
- * full, measured. A meter that cannot say "you are over" is worse than no
176
- * meter for the one case anybody checks it in, and it is the same fault as a
177
- * pagination reporting a page it is not on: the number shown and the number
178
- * given disagree, quietly.
172
+ * **Unclamped, so a value past the end is not swallowed.** Clamped as well as
173
+ * the bar is, 110 and 250 read as exactly full, and a meter that cannot say
174
+ * "you are over" is worse than no meter for the one case anybody checks it in.
179
175
  *
180
176
  * The bar still stops at its end, because that is what an end is. The words
181
- * and the accessible reading carry the truth, and `data-over` is on the fill
177
+ * and the accessible reading carry the truth, and `data-beyond` is on the fill
182
178
  * so a consumer can say more about it.
183
179
  */
184
180
  private get ratio();
@@ -64,10 +64,6 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
64
64
  * Accessible name for the reading.
65
65
  */
66
66
  this.label = 'Meter';
67
- /**
68
- * Bottom of the range.
69
- */
70
- this.min = 0;
71
67
  /**
72
68
  * Top of the range.
73
69
  *
@@ -78,15 +74,19 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
78
74
  */
79
75
  this.max = 100;
80
76
  /**
81
- * Where the reading sits between `min` and `max`.
82
- *
83
- * Outside them, it clamps.
77
+ * Bottom of the range.
84
78
  */
85
- this.value = 0;
79
+ this.min = 0;
86
80
  /**
87
81
  * Whether the reading is shown beside the bar.
88
82
  */
89
83
  this.showValue = false;
84
+ /**
85
+ * Where the reading sits between `min` and `max`.
86
+ *
87
+ * Outside them, it clamps.
88
+ */
89
+ this.value = 0;
90
90
  /**
91
91
  * What the reading says, where a number is not the whole story.
92
92
  *
@@ -120,15 +120,12 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
120
120
  /**
121
121
  * Where the value really sits, which is what the words report.
122
122
  *
123
- * **A value past the end used to be swallowed twice.** The bar filled and the
124
- * reading said "100%", so 110 and 250 were indistinguishable from exactly
125
- * full, measured. A meter that cannot say "you are over" is worse than no
126
- * meter for the one case anybody checks it in, and it is the same fault as a
127
- * pagination reporting a page it is not on: the number shown and the number
128
- * given disagree, quietly.
123
+ * **Unclamped, so a value past the end is not swallowed.** Clamped as well as
124
+ * the bar is, 110 and 250 read as exactly full, and a meter that cannot say
125
+ * "you are over" is worse than no meter for the one case anybody checks it in.
129
126
  *
130
127
  * The bar still stops at its end, because that is what an end is. The words
131
- * and the accessible reading carry the truth, and `data-over` is on the fill
128
+ * and the accessible reading carry the truth, and `data-beyond` is on the fill
132
129
  * so a consumer can say more about it.
133
130
  */
134
131
  get ratio() {
@@ -195,8 +192,6 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
195
192
  this.internals.ariaValueMin = String(min);
196
193
  this.internals.ariaValueMax = String(max);
197
194
  this.internals.ariaValueNow = String(this.reading);
198
- /* Spoken instead of the number wherever the consumer gave words, which is
199
- what `value-text` is for: "18 GB of 32 GB" rather than "56". */
200
195
  /* The consumer's words where they gave any, and otherwise nothing at all
201
196
  *unless* the value is past an end. `ariaValueNow` has to sit inside the
202
197
  range, so it is the only place a reader can be told that 250 is not 100. */
@@ -279,34 +274,34 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
279
274
  };
280
275
  __decorate([
281
276
  property()
282
- ], HelixHeadlessMeter.prototype, "label", void 0);
277
+ ], HelixHeadlessMeter.prototype, "band", void 0);
283
278
  __decorate([
284
279
  property({ type: Number })
285
- ], HelixHeadlessMeter.prototype, "min", void 0);
280
+ ], HelixHeadlessMeter.prototype, "high", void 0);
286
281
  __decorate([
287
- property({ type: Number })
288
- ], HelixHeadlessMeter.prototype, "max", void 0);
282
+ property()
283
+ ], HelixHeadlessMeter.prototype, "label", void 0);
289
284
  __decorate([
290
285
  property({ type: Number })
291
- ], HelixHeadlessMeter.prototype, "value", void 0);
286
+ ], HelixHeadlessMeter.prototype, "low", void 0);
292
287
  __decorate([
293
288
  property({ type: Number })
294
- ], HelixHeadlessMeter.prototype, "low", void 0);
289
+ ], HelixHeadlessMeter.prototype, "max", void 0);
295
290
  __decorate([
296
291
  property({ type: Number })
297
- ], HelixHeadlessMeter.prototype, "high", void 0);
292
+ ], HelixHeadlessMeter.prototype, "min", void 0);
298
293
  __decorate([
299
294
  property({ type: Number })
300
295
  ], HelixHeadlessMeter.prototype, "optimum", void 0);
301
- __decorate([
302
- property()
303
- ], HelixHeadlessMeter.prototype, "band", void 0);
304
296
  __decorate([
305
297
  property({ reflect: true })
306
298
  ], HelixHeadlessMeter.prototype, "shape", void 0);
307
299
  __decorate([
308
300
  property({ attribute: 'show-value', reflect: true, type: Boolean })
309
301
  ], HelixHeadlessMeter.prototype, "showValue", void 0);
302
+ __decorate([
303
+ property({ type: Number })
304
+ ], HelixHeadlessMeter.prototype, "value", void 0);
310
305
  __decorate([
311
306
  property({ attribute: 'value-text' })
312
307
  ], HelixHeadlessMeter.prototype, "valueText", void 0);
@@ -41,10 +41,9 @@ import { property } from 'lit/decorators.js';
41
41
  let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement {
42
42
  constructor() {
43
43
  super(...arguments);
44
- /* The mark, and the RTL sign and border correction that came with it. This
45
- was hand-written and had neither: the distance was measured from the
46
- physical left and applied from the inline-start edge, so it traveled the
47
- wrong way in a right-to-left document. */
44
+ /* The controller carries the RTL sign and border correction: a distance
45
+ measured from the physical left and applied from the inline-start edge
46
+ travels the wrong way in a right-to-left document. */
48
47
  this.indicator = new IndicatorController(this, {
49
48
  active: () => this.items.find((item) => item.getAttribute('aria-current') === 'page'),
50
49
  indicator: () => this.renderRoot?.querySelector('[part="indicator"]'),
@@ -64,20 +63,13 @@ let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement
64
63
  watch() {
65
64
  this.observer?.disconnect();
66
65
  this.current?.disconnect();
67
- /* Nothing is written onto the items any more.
68
- *
69
- * `data-navigation-item` used to be put here, because the base layer styled a
70
- * destination with it and forgetting it was silent and total: the links
71
- * kept working and came out as bare underlined anchors. Writing it fixed
72
- * that and bought two problems. It happened after upgrade, so a
73
- * server-rendered nav arrived unstyled and restyled itself a frame later;
74
- * and a React consumer who wrote the attribute themselves got
75
- * `data-navigation-item="true"` from JSX, which this then had to be careful not to
76
- * overwrite or hydration reported a mismatch.
77
- *
78
- * The base layer selects `helix-navigation a` as well now, so the styling is
79
- * true the moment the markup is parsed, on the server and on the client,
80
- * and there is nothing to write or to be careful about. */
66
+ /* Nothing is written onto the items, and `data-navigation-item` must not be
67
+ * written here: it would land after upgrade, so a server-rendered nav would
68
+ * arrive unstyled and restyle itself a frame later, and a React consumer
69
+ * who wrote the attribute themselves gets `data-navigation-item="true"`
70
+ * from JSX, which overwriting reports as a hydration mismatch. The base
71
+ * layer selects `helix-navigation a`, so the styling is true the moment the
72
+ * markup is parsed, on the server and on the client. */
81
73
  this.indicator.place();
82
74
  this.observer = new ResizeObserver(() => this.indicator.place());
83
75
  this.observer.observe(this);
@@ -98,7 +90,7 @@ let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement
98
90
  * a list left this permanently dead: the observer gone, nothing to rebuild
99
91
  * it, and the component still rendering as though it were watching. Guarded
100
92
  * on `hasUpdated`, because the first connection happens before the first
101
- * render and there is nothing to watch yet. `check:observers` holds it. */
93
+ * render and there is nothing to watch yet. */
102
94
  connectedCallback() {
103
95
  super.connectedCallback();
104
96
  if (this.hasUpdated) {
@@ -73,18 +73,13 @@ export declare class HelixHeadlessNotification extends HelixElement {
73
73
  * changes nothing until a new value arrives. `default-read` seeds a state
74
74
  * this element then owns.
75
75
  *
76
- * **Not reflected, and it was until 27 Aug 2026.** The reason given was that
77
- * unread is a visual state and a stylesheet has no other way to know, which
78
- * is the same reason the four mixins mirror theirs, and the mirror may not be
79
- * the property's own attribute: `<helix-notification default-read>`
80
- * came back from a server without `read` and gained it on the first update,
81
- * which React reports as a hydration mismatch, and a copy of the serialized
82
- * element re-parses that attribute as a declaration. `:state(read)` is what
83
- * the stylesheet reads now. Found by `hydration.dom.spec.ts` on the day it
84
- * learned to mount an element a consumer had configured rather than a bare
85
- * one.
86
- *
87
- *
76
+ * **Not reflected.** Unread is a visual state, which is why the four mixins
77
+ * mirror theirs, but the mirror may not be the property's own attribute:
78
+ * `<helix-notification default-read>` comes back from a server without `read`
79
+ * and would gain it on the first update, which React reports as a hydration
80
+ * mismatch, and which a copy of the serialized element re-parses as a
81
+ * declaration. `:state(read)` is what the stylesheet reads.
82
+ * `hydration.dom.spec.ts` holds it.
88
83
  */
89
84
  get read(): boolean;
90
85
  set read(next: boolean);
@@ -96,16 +91,16 @@ export declare class HelixHeadlessNotification extends HelixElement {
96
91
  * Whether a reader may remove it.
97
92
  */
98
93
  dismissible: boolean;
94
+ /**
95
+ * Accessible name for the dismiss control.
96
+ */
97
+ dismissLabel: string;
99
98
  /**
100
99
  * Locale for the timestamp.
101
100
  *
102
101
  * Empty is the runtime's own.
103
102
  */
104
103
  locale: string;
105
- /**
106
- * Accessible name for the dismiss control.
107
- */
108
- dismissLabel: string;
109
104
  /**
110
105
  * @internal Read by the list to identify its children across the light DOM,
111
106
  * which is cheaper than `instanceof` and is why this is public rather than
@@ -141,11 +136,11 @@ export declare class HelixHeadlessNotification extends HelixElement {
141
136
  * it.** A fallback answers a consumer and a seam answers the tier above, which
142
137
  * are different people: the styled tier wants an icon here, and with the slot
143
138
  * written inline the only way to change it is to reimplement the whole
144
- * template. `check:fallbacks` holds that, and moving only the fallback out was
145
- * not enough, which is the right rule: the slot is the thing a tier redraws.
139
+ * template. Moving only the fallback out is not enough: the slot is the thing
140
+ * a tier redraws.
146
141
  *
147
- * **The mark is drawn rather than typed, which is what lets it align.** It was
148
- * `&times;`, and a character is placed by its font rather than by its box:
142
+ * **The mark is drawn rather than typed, which is what lets it align.** A
143
+ * character such as `&times;` is placed by its font rather than by its box:
149
144
  * measured against the ghost button beside it at 8x, the cross carried 6
150
145
  * pixels of ink to the label's 9.5 and sat 1.5 pixels below its center, in two
151
146
  * boxes whose own centers agreed to a tenth of a pixel. No stylesheet can
@@ -160,8 +155,7 @@ export declare class HelixHeadlessNotification extends HelixElement {
160
155
  *
161
156
  * The tag is interpolated rather than written, so each tier renders its own:
162
157
  * the base tier may not name a styled element, and a styled item inherits this
163
- * template without having a tag of its own to remind anybody. `check:composed`
164
- * holds both halves.
158
+ * template without having a tag of its own to remind anybody.
165
159
  *
166
160
  * `exportparts` and no `part` of its own, which is the rule about a part
167
161
  * already named for its role: the child publishes `time`, the role here is