@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
@@ -16,12 +16,12 @@ const EDGES = ['block-start', 'block-end', 'inline-start', 'inline-end'];
16
16
  * **The whole component is one fact a stylesheet cannot work out for itself:
17
17
  * which edges have content past them.** A fade at the bottom of a list is easy
18
18
  * to draw and impossible to decide, because CSS has no reading of scroll
19
- * position. So this measures and says, in `data-more`, and the styled tier
20
- * draws whatever it likes on the edges named.
19
+ * position. So this measures and says, in a custom state per edge, and the
20
+ * styled tier draws whatever it likes on the edges named.
21
21
  *
22
- * **Tokens rather than four attributes**, so a stylesheet asks
23
- * `[data-more~="block-end"]` the way it would ask about a class. Four booleans
24
- * say the same thing in four selectors and read worse at every use.
22
+ * **States rather than attributes**, so an element that upgrades after a
23
+ * framework rendered its markup does not hand that framework markup it did not
24
+ * write. A stylesheet asks `:host(:state(more-block-end))`.
25
25
  *
26
26
  * **A scrolling region takes the keyboard when it scrolls, and not before.**
27
27
  * A box a reader can only reach with a pointer is a box some readers cannot
@@ -103,17 +103,14 @@ let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement
103
103
  /**
104
104
  * The box that actually scrolls, for anything that needs to move it.
105
105
  *
106
- * **Public because the alternative is silence.** Bringing a row into view
107
- * means telling a scroll utility which box to scroll, and the scrolling box
108
- * here is inside a shadow root: a consumer holding a reference to this
109
- * element holds the host, which does not scroll, and `scrollBy` on it is a
110
- * no-op that reports nothing. That is exactly how `scrollItemIntoView`'s
111
- * `offsetParent` default fails, and the sandbox sidebar spent an afternoon
112
- * scrolled to zero because of it.
106
+ * **Public because the alternative is silence.** The scrolling box is inside
107
+ * this shadow root: a consumer holding a reference to this element holds the
108
+ * host, which does not scroll, and `scrollBy` on it is a no-op that reports
109
+ * nothing. That is how `scrollItemIntoView`'s `offsetParent` default fails
110
+ * here.
113
111
  *
114
112
  * The element rather than a method of our own, because the utilities that
115
- * want it already take one, and `Tree`, `Combobox` and anything windowing a
116
- * long list all want the same thing from it.
113
+ * want it already take one.
117
114
  */
118
115
  get scroller() {
119
116
  return this.renderRoot?.querySelector('[part="viewport"]') ?? null;
@@ -124,20 +121,14 @@ let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement
124
121
  and the content changing size is a data change, and a fade that only
125
122
  answered one of them was wrong every time a list was filtered. */
126
123
  this.watcher = new ResizeObserver(this.measure);
127
- /* And what it watches, which was registered only in `firstUpdated`.
128
- *
129
- * The observer was already rebuilt here, so this looked like the one
130
- * component that had the lifecycle right, and it was half right. A fresh
131
- * observer watches nothing until something calls `observe`, and only
132
- * `firstUpdated` did, which runs once for the life of the element. So a
133
- * scroll area moved in the DOM came back with a new observer registered on
134
- * no targets: the fades stopped answering a resize or a filtered list, and
135
- * the component went on rendering.
124
+ /* And what it watches, which rebuilding the observer does not restore. A
125
+ * fresh observer watches nothing until something calls `observe`, so a
126
+ * scroll area moved in the DOM comes back registered on no targets: the
127
+ * fades stop answering a resize or a filtered list, and the component goes
128
+ * on rendering.
136
129
  *
137
130
  * Guarded on `hasUpdated`, because the first connection happens before the
138
- * first render and there is no scroller to find yet. `check:observers`
139
- * holds it, and had to be tightened to see it: asking for `new` *or*
140
- * `observe` passed this on the half that was fine. */
131
+ * first render and there is no scroller to find yet. */
141
132
  if (this.hasUpdated) {
142
133
  this.watchContent();
143
134
  }
@@ -168,13 +159,28 @@ let HelixHeadlessScrollArea = class HelixHeadlessScrollArea extends HelixElement
168
159
  updated(changed) {
169
160
  super.updated?.(changed);
170
161
  /* On the host rather than the viewport, so a consumer can style from the
171
- outside without reaching through a part. */
172
- this.toggleAttribute('data-scrolls', this.scrolls);
173
- if (this.more.length > 0) {
174
- this.setAttribute('data-more', this.more.join(' '));
175
- }
176
- else {
177
- this.removeAttribute('data-more');
162
+ outside without reaching through a part.
163
+
164
+ **Custom states and never attributes, which is what keeps hydration
165
+ clean.** These are a reading of a laid-out box, so they are written on
166
+ upgrade, and upgrade happens before a framework hydrates the subtree
167
+ around it. Written as attributes they are markup on the host that the
168
+ framework did not render: React reported a hydration mismatch naming
169
+ `data-scrolls` and `data-more` on every load of a page holding one.
170
+ `states` is not in the DOM at all, so this element may upgrade whenever it
171
+ likes and a framework finds the markup it rendered. That is the rule the
172
+ rest of the library already keeps, `app-header`'s `scrolled` being the
173
+ clearest statement of it.
174
+
175
+ One state per edge rather than one holding tokens, because a custom state
176
+ is a name and not a value: there is no `~=` to ask with. The four
177
+ selectors are what the styled tier writes either way. */
178
+ /* Through `toggleState` for the feature test it carries. This is `updated`
179
+ rather than `willUpdate`, so the server never reaches it, but Safari
180
+ below 17.4 and Firefox below 126 do and have no `CustomStateSet`. */
181
+ this.toggleState('scrolls', this.scrolls);
182
+ for (const edge of EDGES) {
183
+ this.toggleState(`more-${edge}`, this.more.includes(edge));
178
184
  }
179
185
  }
180
186
  render() {
@@ -61,14 +61,15 @@ declare const HelixHeadlessSelect_base: (new (...args: any[]) => import("@fusion
61
61
  */
62
62
  export declare class HelixHeadlessSelect extends HelixHeadlessSelect_base {
63
63
  protected readonly aria: AriaForwardController;
64
+ /**
65
+ * What it says where there are none.
66
+ */
67
+ emptyText: string;
64
68
  /**
65
69
  * Whether the list can be narrowed by typing.
66
70
  *
67
71
  * Passed to the listbox rather than acted on here, because the listbox owns
68
- * the filtering, the empty state and the keyboard. This property existed and
69
- * was never read: it reflected, it type-checked, and nothing anywhere
70
- * rendered a field. API that does nothing is worse than API that is missing,
71
- * because a consumer sets it and believes it.
72
+ * the filtering, the empty state and the keyboard.
72
73
  */
73
74
  filterable: boolean;
74
75
  /**
@@ -83,10 +84,6 @@ export declare class HelixHeadlessSelect extends HelixHeadlessSelect_base {
83
84
  * What the list says while they are on their way.
84
85
  */
85
86
  loadingText: string;
86
- /**
87
- * What it says where there are none.
88
- */
89
- emptyText: string;
90
87
  /**
91
88
  * Whether more than one option can be the answer.
92
89
  */
@@ -112,10 +109,8 @@ export declare class HelixHeadlessSelect extends HelixHeadlessSelect_base {
112
109
  *
113
110
  * The optional chain is the server. `renderRoot` is a property Lit's element
114
111
  * shim does not carry, and this getter is reached from `display`, which is
115
- * read during `render`: without it the select threw on every server render
116
- * and could not be served at all. Found by writing its SSR spec, which is
117
- * the only thing that would have found it, because the client is where every
118
- * other path runs and the client always has a root.
112
+ * read during `render`: without it the select throws on every server render
113
+ * and cannot be served at all.
119
114
  *
120
115
  * The other reads of `renderRoot` here are inside callbacks the controllers
121
116
  * invoke, and a controller only runs on a connected element, so they cannot
@@ -79,14 +79,15 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
79
79
  this.aria = new AriaForwardController(this, {
80
80
  target: () => this.renderRoot?.querySelector('[part="trigger"]') ?? null,
81
81
  });
82
+ /**
83
+ * What it says where there are none.
84
+ */
85
+ this.emptyText = 'No matches';
82
86
  /**
83
87
  * Whether the list can be narrowed by typing.
84
88
  *
85
89
  * Passed to the listbox rather than acted on here, because the listbox owns
86
- * the filtering, the empty state and the keyboard. This property existed and
87
- * was never read: it reflected, it type-checked, and nothing anywhere
88
- * rendered a field. API that does nothing is worse than API that is missing,
89
- * because a consumer sets it and believes it.
90
+ * the filtering, the empty state and the keyboard.
90
91
  */
91
92
  this.filterable = false;
92
93
  /**
@@ -101,10 +102,6 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
101
102
  * What the list says while they are on their way.
102
103
  */
103
104
  this.loadingText = 'Loading';
104
- /**
105
- * What it says where there are none.
106
- */
107
- this.emptyText = 'No matches';
108
105
  /**
109
106
  * Whether more than one option can be the answer.
110
107
  */
@@ -113,15 +110,14 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
113
110
  * Shown on the trigger while nothing is chosen.
114
111
  */
115
112
  this.placeholder = 'Choose';
116
- /* The surface floats *and is in the top layer*, which it was not.
113
+ /* The surface floats *and is in the top layer*.
117
114
  *
118
- * It had a `FloatingController` and a `DismissController` and never called
119
- * `showPopover`, so the panel was an ordinary positioned element and the
120
- * first ancestor with `overflow: hidden` clipped it. A select inside a
121
- * scrolling card was cut off where a menu in the same place was not, and the
122
- * two are the same shape: floating panel, trigger, dismissal. That is what
115
+ * Without `showPopover` the panel is an ordinary positioned element and the
116
+ * first ancestor with `overflow: hidden` clips it, so a select inside a
117
+ * scrolling card is cut off where a menu in the same place is not. The two
118
+ * are the same shape (floating panel, trigger, dismissal), which is what
123
119
  * `PopoverController` is, and having one of them is what stops the third copy
124
- * being subtly different again.
120
+ * being subtly different.
125
121
  *
126
122
  * Held off the trigger by the controller rather than by a margin on the
127
123
  * panel. A margin is inside the box the controller measures, so it would be
@@ -133,15 +129,12 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
133
129
  *
134
130
  * A control is not always one element: the button that opens this panel is
135
131
  * part of it, and a press on it is not a press outside. Scoped to the
136
- * surface alone, `pointerdown` on the trigger closed the panel and the
137
- * trigger's own `toggleOpen` reopened it on the `click` that followed, so
138
- * the panel could never be closed by the button that opened it. Measured
139
- * across all five popover-bearing components: Menu, Popover and Tooltip
140
- * already named their invoker; this one and its three siblings did not, and
141
- * all four stayed open on a second press where Menu closed.
132
+ * surface alone, `pointerdown` on the trigger closes the panel and the
133
+ * trigger's own `toggleOpen` reopens it on the `click` that follows, so
134
+ * the panel can never be closed by the button that opened it.
142
135
  *
143
- * `DismissController` documents this exact failure and takes a list for it.
144
- * The list was the fix; using it was the part that did not happen here. */
136
+ * `DismissController` documents this exact failure and takes a list for
137
+ * it. */
145
138
  boundary: () => [
146
139
  this.renderRoot?.querySelector('[part="surface"]'),
147
140
  this.renderRoot?.querySelector('[part="trigger"]'),
@@ -156,8 +149,8 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
156
149
  *
157
150
  * The event carries the value being *proposed*, and it is dispatched before
158
151
  * it is applied, which is what makes it refusable. Reading the listbox here
159
- * therefore read the value it still held: one choice behind, and on the
160
- * first choice nothing at all.
152
+ * reads the value it still holds: one choice behind, and on the first
153
+ * choice nothing at all.
161
154
  *
162
155
  * And the listbox never applies it anyway. The select passes `.value` down,
163
156
  * which is a consumer declaring ownership, so the listbox inside the panel
@@ -165,13 +158,12 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
165
158
  * right arrangement, and it makes reading the listbox's own value the one
166
159
  * thing that can never work. */
167
160
  const next = event.detail.value;
168
- /* Nothing happens on a refusal, and everything did.
161
+ /* Nothing happens on a refusal.
169
162
  *
170
- * The panel closed and a native `change` went out whether or not the change
171
- * was taken, so a consumer calling `preventDefault()` on `helix-change`
172
- * kept the old value, watched the select shut as though it had been chosen,
173
- * and told the form it had moved. Refusing a change should leave the
174
- * control exactly where it was. */
163
+ * Without this return the panel closes and a native `change` goes out
164
+ * whether or not the change was taken, so a consumer calling
165
+ * `preventDefault()` on `helix-change` keeps the old value, watches the
166
+ * select shut as though it had been chosen, and tells the form it moved. */
175
167
  if (!this.requestValue(next)) {
176
168
  event.stopPropagation();
177
169
  return;
@@ -184,13 +176,11 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
184
176
  }
185
177
  /* The listbox's request is stopped and this element's own has already gone
186
178
  out, from `requestValue` above: two elements announcing one choice is
187
- what a consumer would have to deduplicate. The comment here used to say
188
- the listbox's was "left to travel", which the line below it has always
189
- contradicted.
179
+ what a consumer would have to deduplicate.
190
180
 
191
181
  And no `change` is dispatched here. `requestValue` announces `input` and
192
182
  `change` through the mixin, the way every other discrete control does, so
193
- a second one from this line was a second `change` per choice: measured on
183
+ a second one from this line is a second `change` per choice: measured on
194
184
  the styled tier at three, one from the mixin, one from here, and one from
195
185
  the listbox before it was stopped. */
196
186
  event.stopPropagation();
@@ -228,10 +218,8 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
228
218
  *
229
219
  * The optional chain is the server. `renderRoot` is a property Lit's element
230
220
  * shim does not carry, and this getter is reached from `display`, which is
231
- * read during `render`: without it the select threw on every server render
232
- * and could not be served at all. Found by writing its SSR spec, which is
233
- * the only thing that would have found it, because the client is where every
234
- * other path runs and the client always has a root.
221
+ * read during `render`: without it the select throws on every server render
222
+ * and cannot be served at all.
235
223
  *
236
224
  * The other reads of `renderRoot` here are inside callbacks the controllers
237
225
  * invoke, and a controller only runs on a connected element, so they cannot
@@ -284,25 +272,23 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
284
272
  costs nothing. */
285
273
  this.panel.show();
286
274
  /* Into the list, which is where the keyboard has to be for the arrows to
287
- mean anything. It reached the listbox element and stopped there, that
288
- element not being focusable, so focus stayed on the trigger and every
289
- arrow press went to the page. The listbox delegates focus now, so this
290
- lands on the list inside it.
275
+ mean anything. The listbox delegates focus, so this lands on the list
276
+ inside it rather than stopping at the listbox element, which is not
277
+ itself focusable.
291
278
  *
292
279
  * Only on the update that opened it. `updated` runs for any change while
293
280
  * the panel is up, a filter keystroke or a value arriving, and moving
294
- * focus on each of those is a focus thief: harmless while the listbox was
295
- * unfocusable, and a real one the moment it was made to work. */
281
+ * focus on each of those is a focus thief. */
296
282
  if (changed.has('open')) {
297
283
  this.listbox?.focus();
298
284
  }
299
285
  }
300
286
  else {
301
287
  this.panel.hide();
302
- /* And the filter goes with it. A filterable select reopened still narrowed
303
- with the old needle in its search box, and `hidden` still written on the
304
- options it had ruled out, so the second use of the control started from
305
- the first one's leftovers. Closing is where a search ends. */
288
+ /* And the filter goes with it. Without this a filterable select reopens
289
+ still narrowed by the old needle, with `hidden` still written on the
290
+ options it ruled out, so the second use of the control starts from the
291
+ first one's leftovers. Closing is where a search ends. */
306
292
  this.listbox?.requestFilter('');
307
293
  }
308
294
  }
@@ -380,9 +366,8 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
380
366
  ''}
381
367
  <slot name="end"></slot>
382
368
  ${
383
- /* The slot has a fallback, and had none: a select written without a
384
- hand-slotted icon drew no mark at all saying it opens, and every
385
- example in the family passes one, which is what hid it. A caret is
369
+ /* The slot has a fallback: without one a select written without a
370
+ hand-slotted icon draws no mark at all saying it opens. A caret is
386
371
  the mark, and slotting anything replaces it, which is this
387
372
  library's rule for a content property. */
388
373
  ''}
@@ -395,6 +380,9 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
395
380
  ${this.renderHint()}${this.renderFeedback()}`;
396
381
  }
397
382
  };
383
+ __decorate([
384
+ property({ attribute: 'empty-text' })
385
+ ], HelixHeadlessSelect.prototype, "emptyText", void 0);
398
386
  __decorate([
399
387
  property({ reflect: true, type: Boolean })
400
388
  ], HelixHeadlessSelect.prototype, "filterable", void 0);
@@ -404,9 +392,6 @@ __decorate([
404
392
  __decorate([
405
393
  property({ attribute: 'loading-text' })
406
394
  ], HelixHeadlessSelect.prototype, "loadingText", void 0);
407
- __decorate([
408
- property({ attribute: 'empty-text' })
409
- ], HelixHeadlessSelect.prototype, "emptyText", void 0);
410
395
  __decorate([
411
396
  property({ reflect: true, type: Boolean })
412
397
  ], HelixHeadlessSelect.prototype, "multiple", void 0);
@@ -16,13 +16,12 @@ declare const HelixHeadlessSlider_base: (new (...args: any[]) => import("@fusion
16
16
  * value rather than the value itself. `valueAsNumber` is there for anything
17
17
  * doing arithmetic on it.
18
18
  *
19
- * **Marks are drawn rather than left to `<datalist>`**, which was the first
20
- * answer and is the wrong one. A datalist's ticks cannot be styled at all, and
21
- * Firefox does not render them for a range at all, so the platform's version is
22
- * a mark that looks like someone else's design where it appears and no mark
23
- * where it does not. Drawing them costs the semantics nothing, because a mark
24
- * is decoration: what a reader can actually land on is `step`, which the input
25
- * enforces whether or not anything is drawn.
19
+ * **Marks are drawn rather than left to `<datalist>`.** A datalist's ticks
20
+ * cannot be styled at all, and Firefox does not render them for a range at all,
21
+ * so the platform's version is a mark that looks like someone else's design
22
+ * where it appears and no mark where it does not. Drawing them costs the
23
+ * semantics nothing, because a mark is decoration: what a reader can actually
24
+ * land on is `step`, which the input enforces whether or not anything is drawn.
26
25
  *
27
26
  * `markers` is a count rather than a flag tied to `step`. A flag reads well
28
27
  * until a slider from zero to a hundred stepping by one asks for a hundred and
@@ -30,11 +29,10 @@ declare const HelixHeadlessSlider_base: (new (...args: any[]) => import("@fusion
30
29
  * is what the reader sees, so it cannot surprise anyone.
31
30
  *
32
31
  * **A range is two of them, not a hand-built one.** There is no native
33
- * two-thumb range, and the answer is not to stop using the platform's: it is to
34
- * stack two of them on one track, so each thumb keeps its own drag, its own
35
- * arrow keys, its own Home and End and its own finger-sized hit area. Rebuilding
36
- * would throw away every argument this component is made of, to gain a second
37
- * handle.
32
+ * two-thumb range, so two are stacked on one track and each thumb keeps its own
33
+ * drag, its own arrow keys, its own Home and End and its own finger-sized hit
34
+ * area. Rebuilding would throw away every argument this component is made of,
35
+ * to gain a second handle.
38
36
  *
39
37
  * Crossing is stopped in the handler rather than by the bounds, and that is not
40
38
  * the obvious way round. Giving the lower input `max` of the upper reads well
@@ -78,25 +76,9 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
78
76
  /** Typed or dragged, so every edit is announced. See `announcesInput`. */
79
77
  protected readonly announcesInput = true;
80
78
  /**
81
- * Whether there are two thumbs and the value is a pair.
82
- *
83
- * The pair is one string, `"10,50"`, which is what a form submits and what
84
- * `MixinControllerValue` already holds. `valueAsNumber` reads the lower of
85
- * the two, since a range has no single number.
86
- */
87
- range: boolean;
88
- /**
89
- * The largest value the reader can choose.
90
- */
91
- max: number;
92
- /**
93
- * The smallest value the reader can choose.
94
- */
95
- min: number;
96
- /**
97
- * Whether the chosen value is shown beside the track.
79
+ * Whether each mark says which value it stands at.
98
80
  */
99
- showValue: boolean;
81
+ markerLabels: boolean;
100
82
  /**
101
83
  * How many marks to draw along the track, evenly spaced, ends included.
102
84
  *
@@ -114,11 +96,38 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
114
96
  */
115
97
  markers: number;
116
98
  /**
117
- * Whether each mark says which value it stands at.
99
+ * The largest value the reader can choose.
118
100
  */
119
- markerLabels: boolean;
120
- /** How far one press of an arrow key moves it. */
121
- step: number;
101
+ max: number;
102
+ /**
103
+ * The smallest value the reader can choose.
104
+ */
105
+ min: number;
106
+ /**
107
+ * Which way the track runs, `vertical` standing it on end.
108
+ *
109
+ * For a level rather than a quantity: a fader, a channel, anything a reader
110
+ * pictures as high and low rather than as less and more. Absent is
111
+ * horizontal, which is what almost every slider in a form wants.
112
+ *
113
+ * **A vertical track has no length of its own**, the way a horizontal one
114
+ * takes the width of the row it is in. `--slider-length` is that number and
115
+ * defaults to nine rem, so one dropped into a layout is a usable height
116
+ * rather than a thumb sitting on nothing.
117
+ */
118
+ orientation?: 'horizontal' | 'vertical';
119
+ /**
120
+ * Whether there are two thumbs and the value is a pair.
121
+ *
122
+ * The pair is one string, `"10,50"`, which is what a form submits and what
123
+ * `MixinControllerValue` already holds. `valueAsNumber` reads the lower of
124
+ * the two, since a range has no single number.
125
+ */
126
+ range: boolean;
127
+ /**
128
+ * Whether the chosen value is shown beside the track.
129
+ */
130
+ showValue: boolean;
122
131
  /**
123
132
  * How many characters the readout has to be able to hold, widest case.
124
133
  *
@@ -149,7 +158,7 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
149
158
  */
150
159
  private get precision();
151
160
  /**
152
- * How far one press of an arrow key moves it.
161
+ * The values the marks stand at, evenly spaced, each snapped to a step.
153
162
  */
154
163
  private get markerValues();
155
164
  /**
@@ -181,18 +190,13 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
181
190
  * Arithmetic rather than a measurement, because the browser already knows
182
191
  * where it drew the handle and measuring it would be a guess at that.
183
192
  *
184
- * **Sanitized here, not read back off the control.** This asked the input for
185
- * its value, on the reasoning that a range clamps and snaps whatever it is
186
- * given, so the control is the truth about where the thumb is. The reasoning
187
- * is right and the timing is not: `fraction` is evaluated inside `render()`,
188
- * and the `style` binding carrying it is committed *before* the `.value`
189
- * binding below it, so it read the value this very render was about to
190
- * replace. The fill was a render behind the thumb, and on the first pass it
191
- * read the seeded midpoint and stayed there.
192
- *
193
- * Measured on a slider from 0 to 1: after dragging to either end, the host's
194
- * `value` was `1`, the control's was `1`, and `--slider-fraction` was still
195
- * `0.5`. Off by half a track, and stable, which is what made it look like a
193
+ * **Sanitized here, never read back off the control.** Asking the input for
194
+ * its value reads well, a range clamping and snapping whatever it is given,
195
+ * and the timing defeats it: `fraction` is evaluated inside `render()` and the
196
+ * `style` binding carrying it is committed *before* the `.value` binding below
197
+ * it, so it reads the value this very render is about to replace. The fill
198
+ * ends up a render behind the thumb, and on the first pass it reads the seeded
199
+ * midpoint and stays there: stable and off by half a track, which reads as a
196
200
  * drawing bug rather than a timing one.
197
201
  *
198
202
  * So the same two operations a range performs are done here: snap to the step
@@ -212,19 +216,8 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
212
216
  private snapped;
213
217
  protected willUpdate(changed: PropertyValues): void;
214
218
  protected updated(changed: PropertyValues): void;
215
- /**
216
- * Which way the track runs, `vertical` standing it on end.
217
- *
218
- * For a level rather than a quantity: a fader, a channel, anything a reader
219
- * pictures as high and low rather than as less and more. Absent is
220
- * horizontal, which is what almost every slider in a form wants.
221
- *
222
- * **A vertical track has no length of its own**, the way a horizontal one
223
- * takes the width of the row it is in. `--slider-length` is that number and
224
- * defaults to nine rem, so one dropped into a layout is a usable height
225
- * rather than a thumb sitting on nothing.
226
- */
227
- orientation?: 'horizontal' | 'vertical';
219
+ /** How far one press of an arrow key moves it. */
220
+ step: number;
228
221
  protected render(): TemplateResult;
229
222
  }
230
223
  declare global {