@fusion.dev/helix-headless 0.153.0 → 0.155.0

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 (81) hide show
  1. package/custom-elements.json +1885 -140
  2. package/dist/accordion/item/accordion-item.d.ts +15 -0
  3. package/dist/accordion/item/accordion-item.js +12 -1
  4. package/dist/accordion/root/accordion-root.d.ts +2 -1
  5. package/dist/accordion/root/accordion-root.js +1 -0
  6. package/dist/badge/root/badge-root.d.ts +15 -2
  7. package/dist/badge/root/badge-root.js +20 -3
  8. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +36 -3
  9. package/dist/breadcrumbs/breadcrumb/breadcrumb.js +42 -2
  10. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +15 -5
  11. package/dist/breadcrumbs/root/breadcrumbs-root.js +29 -4
  12. package/dist/button-group/root/button-group-root.d.ts +2 -0
  13. package/dist/button-group/root/button-group-root.js +1 -0
  14. package/dist/card/root/card-root.d.ts +31 -11
  15. package/dist/card/root/card-root.js +25 -11
  16. package/dist/code/root/code-root.d.ts +7 -0
  17. package/dist/code/root/code-root.js +1 -1
  18. package/dist/code-block/root/code-block-root.d.ts +37 -1
  19. package/dist/code-block/root/code-block-root.js +38 -5
  20. package/dist/color-input/root/color-input-root.d.ts +9 -3
  21. package/dist/color-input/root/color-input-root.js +3 -1
  22. package/dist/color-picker/channels.d.ts +5 -3
  23. package/dist/color-picker/channels.js +79 -21
  24. package/dist/color-picker/root/color-picker-root.d.ts +58 -5
  25. package/dist/color-picker/root/color-picker-root.js +75 -13
  26. package/dist/date-input/root/date-input-root.d.ts +1 -0
  27. package/dist/date-input/root/date-input-root.js +2 -1
  28. package/dist/date-picker/root/date-picker-root.d.ts +43 -13
  29. package/dist/date-picker/root/date-picker-root.js +54 -31
  30. package/dist/element-events.generated.js +2 -1
  31. package/dist/empty/root/empty-root.d.ts +19 -1
  32. package/dist/empty/root/empty-root.js +13 -4
  33. package/dist/icon/fetch.d.ts +20 -0
  34. package/dist/icon/fetch.js +70 -0
  35. package/dist/icon/root/icon-root.d.ts +27 -5
  36. package/dist/icon/root/icon-root.js +41 -17
  37. package/dist/navigation/root/navigation-root.d.ts +26 -0
  38. package/dist/navigation/root/navigation-root.js +58 -1
  39. package/dist/quote/root/quote-root.d.ts +17 -1
  40. package/dist/quote/root/quote-root.js +15 -2
  41. package/dist/select/root/select-root.d.ts +29 -3
  42. package/dist/select/root/select-root.js +34 -9
  43. package/dist/skeleton/root/skeleton-root.d.ts +7 -0
  44. package/dist/skeleton/root/skeleton-root.js +4 -1
  45. package/dist/slider/root/slider-root.d.ts +71 -9
  46. package/dist/slider/root/slider-root.js +129 -42
  47. package/dist/speed-dial/item/speed-dial-item.d.ts +29 -1
  48. package/dist/speed-dial/item/speed-dial-item.js +48 -7
  49. package/dist/speed-dial/root/speed-dial-root.d.ts +32 -6
  50. package/dist/speed-dial/root/speed-dial-root.js +50 -5
  51. package/dist/splitter/root/splitter-root.d.ts +22 -0
  52. package/dist/splitter/root/splitter-root.js +36 -7
  53. package/dist/stat/group/stat-group.d.ts +23 -4
  54. package/dist/stat/group/stat-group.js +13 -1
  55. package/dist/stat/root/stat-root.d.ts +46 -1
  56. package/dist/stat/root/stat-root.js +29 -5
  57. package/dist/steps/reach.d.ts +5 -1
  58. package/dist/steps/reach.js +2 -2
  59. package/dist/steps/root/steps-root.d.ts +37 -2
  60. package/dist/steps/root/steps-root.js +49 -7
  61. package/dist/steps/step/step.d.ts +6 -0
  62. package/dist/steps/step/step.js +4 -0
  63. package/dist/tabs/root/tabs-root.d.ts +37 -0
  64. package/dist/tabs/root/tabs-root.js +92 -2
  65. package/dist/tabs/tab/tab.d.ts +38 -2
  66. package/dist/tabs/tab/tab.js +45 -4
  67. package/dist/tag/group/tag-group.d.ts +29 -3
  68. package/dist/tag/group/tag-group.js +42 -11
  69. package/dist/toggle/root/toggle-root.d.ts +2 -0
  70. package/dist/toggle/root/toggle-root.js +1 -1
  71. package/dist/tree/item/tree-item.d.ts +10 -0
  72. package/dist/tree/item/tree-item.js +12 -0
  73. package/dist/tree/root/tree-root.d.ts +40 -1
  74. package/dist/tree/root/tree-root.js +120 -4
  75. package/dist/tree/selection.d.ts +6 -0
  76. package/dist/tree/selection.js +11 -0
  77. package/lint.json +1 -1
  78. package/package.json +5 -5
  79. package/types/jsx.d.ts +1412 -207
  80. package/types/vue.d.ts +294 -65
  81. package/types/words.d.ts +49 -1
@@ -1,4 +1,4 @@
1
- import { AriaForwardController, HelixFormElement, PopoverController } from '@fusion.dev/helix-core';
1
+ import { AriaForwardController, type DataOptionItem, HelixFormElement, PopoverController } from '@fusion.dev/helix-core';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
3
  import { type HelixHeadlessOption } from '../../option/root/option-root.js';
4
4
  import '../../listbox/index.js';
@@ -13,7 +13,10 @@ declare const HelixHeadlessSelect_base: (new (...args: any[]) => import("@fusion
13
13
  * place for focus to return to when the list closes.
14
14
  *
15
15
  * Your options stay in your light DOM and are slotted through into the listbox,
16
- * so the listbox looks through slots to find them.
16
+ * so the listbox looks through slots to find them. For a list too long to draw
17
+ * whole, set `items` instead: the list draws only the options in sight, as
18
+ * Listbox's `items` does, and the trigger, its keys and the form read the
19
+ * whole set.
17
20
  *
18
21
  * `Select` owns the value, passes it down to the listbox, and takes changes
19
22
  * back, so the value lives in one place.
@@ -102,6 +105,8 @@ declare const HelixHeadlessSelect_base: (new (...args: any[]) => import("@fusion
102
105
  *
103
106
  * @cssstate invalid - The control has an error to show, from the browser's validation or from your `feedback`.
104
107
  * @cssstate open - While the list is open.
108
+ * @cssstate placed-bottom - While the open list sits below the trigger.
109
+ * @cssstate placed-top - While the open list sits above the trigger, where there was no room below.
105
110
  */
106
111
  export declare class HelixHeadlessSelect extends HelixHeadlessSelect_base {
107
112
  /**
@@ -145,6 +150,20 @@ export declare class HelixHeadlessSelect extends HelixHeadlessSelect_base {
145
150
  * anything a consumer sets.
146
151
  */
147
152
  focusable: boolean;
153
+ /**
154
+ * The options as data, for a list too long to draw whole: each a value,
155
+ * which is also its words, or a record with a `value`, a `label` and
156
+ * `disabled`. Passed to the list, which draws only the options in sight,
157
+ * as Listbox's `items` does. Set, the options you write as children are
158
+ * not read.
159
+ *
160
+ * The trigger shows the chosen options' labels, the letters and the Left
161
+ * and Right keys on the closed trigger choose over the whole set, and a
162
+ * chosen value whose option leaves `items` drops out of `value`.
163
+ * `value-content` is not called for `items`. Import the Option family as
164
+ * well, whose elements are drawn.
165
+ */
166
+ items: readonly DataOptionItem[] | undefined;
148
167
  /**
149
168
  * The open list's name where nothing names the Select, read by screen
150
169
  * readers. The list has no visible name.
@@ -270,8 +289,15 @@ export declare class HelixHeadlessSelect extends HelixHeadlessSelect_base {
270
289
  * the commit creates the text node it needs.
271
290
  */
272
291
  private get display();
273
- /** The chosen options, in the order they appear. None on a server or while hydrating. */
292
+ /** The chosen options, in the order they appear. None on a server or while hydrating, and none for `items`. */
274
293
  private get chosenOptions();
294
+ /** `items` as the list reads them, built once per array. */
295
+ private data;
296
+ /**
297
+ * Every option the select reads, in order: the records of `items`, or the
298
+ * option elements among its children.
299
+ */
300
+ private get entries();
275
301
  /**
276
302
  * What the trigger shows, behind a seam: what `value-content` draws for the
277
303
  * chosen options, or their words, or the placeholder.
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { AriaForwardController, afterLinkFollowed, customElement, drawAutofill, drawStatus, HelixFormElement, hostAria, hostWords, isRtl, MixinControllerOpen, MixinControllerValue, MixinField, onApple, PopoverController, reportValues, StatusController, typesCharacter, words, wordsLocale, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, afterLinkFollowed, customElement, dataOptions, drawAutofill, drawStatus, HelixFormElement, hostAria, hostWords, isRtl, MixinControllerOpen, MixinControllerValue, MixinField, onApple, PopoverController, reportValues, StatusController, sideOf, typesCharacter, words, wordsLocale, } from '@fusion.dev/helix-core';
8
8
  import { caretDown } from '@fusion.dev/helix-icons';
9
9
  import { nothing } from 'lit';
10
10
  import { property } from 'lit/decorators.js';
@@ -28,6 +28,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
28
28
  this.emptyText = 'No matches';
29
29
  this.filterable = false;
30
30
  this.focusable = true;
31
+ this.items = undefined;
31
32
  this.listLabel = 'Options';
32
33
  this.loading = false;
33
34
  this.loadingText = 'Loading';
@@ -43,6 +44,11 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
43
44
  ],
44
45
  offset: () => 4,
45
46
  onDismiss: () => this.close(),
47
+ onPlace: (placement) => {
48
+ const side = sideOf(placement);
49
+ this.toggleState('placed-bottom', side === 'bottom');
50
+ this.toggleState('placed-top', side === 'top');
51
+ },
46
52
  open: () => this.open,
47
53
  place: () => this.position !== 'item-aligned',
48
54
  placement: 'bottom-start',
@@ -124,7 +130,9 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
124
130
  const step = event.key === 'ArrowRight' ? 1 : event.key === 'ArrowLeft' ? -1 : 0;
125
131
  if (step !== 0 && !this.multiple && !(event.altKey || event.ctrlKey || event.metaKey)) {
126
132
  event.preventDefault();
127
- const reachable = listbox?.options.filter((option) => !option.hidden && !option.disabled) ?? [];
133
+ const reachable = this.items
134
+ ? this.entries.filter((option) => !option.disabled)
135
+ : (listbox?.options.filter((option) => !option.hidden && !option.disabled) ?? []);
128
136
  const next = reachable[Math.max(0, reachable.findIndex((one) => one.value === this.value) + step)];
129
137
  if (next) {
130
138
  this.choose(next.value);
@@ -165,16 +173,29 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
165
173
  return this.partNamed('listbox');
166
174
  }
167
175
  get display() {
168
- const words = this.chosenOptions.map((option) => option.text);
176
+ const chosen = new Set(this.value === '' ? [] : this.value.split(','));
177
+ const words = this.entries.filter((option) => chosen.has(option.value)).map((one) => one.text);
169
178
  if (words.length > 0) {
170
179
  return new Intl.ListFormat(wordsLocale(this), { style: 'short', type: 'unit' }).format(words);
171
180
  }
172
- return this.value !== '' && !this.childrenKnown ? nothing : this.placeholder;
181
+ return this.value !== '' && !this.childrenKnown && !this.items ? nothing : this.placeholder;
173
182
  }
174
183
  get chosenOptions() {
184
+ if (this.items) {
185
+ return [];
186
+ }
175
187
  const chosen = new Set(this.value === '' ? [] : this.value.split(','));
176
188
  return optionsAmong(this.knownChildren).filter((option) => chosen.has(option.value));
177
189
  }
190
+ get entries() {
191
+ if (!this.items) {
192
+ return optionsAmong(this.knownChildren);
193
+ }
194
+ if (this.data?.from !== this.items) {
195
+ this.data = { from: this.items, options: dataOptions(this.items) };
196
+ }
197
+ return this.data.options;
198
+ }
178
199
  renderValue() {
179
200
  const chosen = this.chosenOptions;
180
201
  return this.valueContent && chosen.length > 0 ? this.valueContent(chosen) : this.display;
@@ -226,9 +247,9 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
226
247
  }
227
248
  }
228
249
  reconcileOptions() {
229
- const options = optionsAmong(this.knownChildren);
230
- if (this.defaultValue === '' && !this.hasAttribute('default-value')) {
231
- const declared = options
250
+ const options = this.entries;
251
+ if (!this.items && this.defaultValue === '' && !this.hasAttribute('default-value')) {
252
+ const declared = optionsAmong(this.knownChildren)
232
253
  .filter((option) => option.defaultSelected)
233
254
  .map((option) => option.value);
234
255
  if (declared.length > 0) {
@@ -255,7 +276,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
255
276
  willUpdate(changed) {
256
277
  super.willUpdate(changed);
257
278
  hostAria(this.internals, { label: this.label });
258
- if (this.childrenKnown) {
279
+ if (this.childrenKnown || this.items) {
259
280
  this.reconcileOptions();
260
281
  }
261
282
  }
@@ -298,6 +319,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
298
319
  .value=${this.value}
299
320
  ?multiple=${this.multiple}
300
321
  ?filterable=${this.filterable}
322
+ .items=${this.items}
301
323
  manual
302
324
  aria-label=${this.listName || this.listLabel || nothing}
303
325
  @keydown=${this.handleListKeydown}
@@ -357,7 +379,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
357
379
  disabled: this.isDisabled,
358
380
  multiple: this.multiple,
359
381
  onFill: (value) => this.requestValue(value),
360
- options: optionsAmong(this.knownChildren),
382
+ options: this.entries,
361
383
  value: this.value,
362
384
  })}`;
363
385
  }
@@ -375,6 +397,9 @@ __decorate([
375
397
  __decorate([
376
398
  property({ attribute: false })
377
399
  ], HelixHeadlessSelect.prototype, "focusable", void 0);
400
+ __decorate([
401
+ property({ attribute: false })
402
+ ], HelixHeadlessSelect.prototype, "items", void 0);
378
403
  __decorate([
379
404
  words,
380
405
  property({ attribute: 'list-label' })
@@ -61,6 +61,13 @@ export declare class HelixHeadlessSkeleton extends HelixElement {
61
61
  protected willUpdate(changed: PropertyValues): void;
62
62
  protected firstUpdated(changed: PropertyValues): void;
63
63
  protected render(): TemplateResult;
64
+ /**
65
+ * The placeholder shape and the sheen inside it.
66
+ *
67
+ * A method, so a tier above can draw the placeholder as several shapes, as
68
+ * the styled tier draws a paragraph of lines.
69
+ */
70
+ protected renderShape(): TemplateResult;
64
71
  }
65
72
  declare global {
66
73
  interface HTMLElementTagNameMap {
@@ -38,7 +38,10 @@ let HelixHeadlessSkeleton = class HelixHeadlessSkeleton extends HelixElement {
38
38
  render() {
39
39
  return html `<span part="content" ?inert=${this.loading}
40
40
  ><slot @slotchange=${() => this.requestUpdate()}></slot></span
41
- ><span part="skeleton"><span part="sheen"></span></span>`;
41
+ >${this.renderShape()}`;
42
+ }
43
+ renderShape() {
44
+ return html `<span part="skeleton"><span part="sheen"></span></span>`;
42
45
  }
43
46
  };
44
47
  __decorate([
@@ -19,7 +19,12 @@ declare const HelixHeadlessSlider_base: (new (...args: any[]) => import("@fusion
19
19
  * does not draw a hundred and one marks by accident.
20
20
  *
21
21
  * A range with two thumbs is two inputs stacked on one track, because there is
22
- * no native two-thumb range. Each thumb keeps its own value.
22
+ * no native two-thumb range. Each thumb keeps its own value, and a named range
23
+ * submits one entry per thumb under its name, the lowest first. A range given
24
+ * more than two values, such as `default-value="20,50,80"`, has a thumb for
25
+ * each, as React Aria's slider takes any number of thumbs: each stops at its
26
+ * neighbors, and the ones between the first and the last are named by
27
+ * `thumb-label`.
23
28
  * `min-steps-between-thumbs` keeps them that many steps apart, and the readout
24
29
  * joins the two as `range-text` writes them.
25
30
  *
@@ -50,6 +55,8 @@ declare const HelixHeadlessSlider_base: (new (...args: any[]) => import("@fusion
50
55
  * | Page Up, Page Down | Moves the thumb by a larger step. |
51
56
  * | Home, End | Moves the thumb to its lowest or highest value. |
52
57
  *
58
+ * Under `readonly` none of these move the thumb, and Tab still reaches it.
59
+ *
53
60
  * Each thumb is an `<input type="range">` with `aria-valuetext` where the value
54
61
  * is formatted or worded. A range's thumbs say they stop at each other with
55
62
  * `aria-valuemin` and `aria-valuemax`.
@@ -63,12 +70,14 @@ declare const HelixHeadlessSlider_base: (new (...args: any[]) => import("@fusion
63
70
  * @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
64
71
  * @slot hint - Help under the control, for content richer than the `hint` text.
65
72
  * @slot label - The label, for content richer than the `label` text.
73
+ * @slot thumb - Content drawn on the thumb, such as a glyph: a single slider's thumb, or a range's lower one. It is decoration, hidden from a screen reader.
74
+ * @slot thumb-end - Content drawn on a range's upper thumb.
66
75
  *
67
76
  * @event {Event} change - Fired when the user releases the thumb.
68
77
  * @event {HelixBeforeChangeEvent} helix-before-change - Fired as the value changes. Cancelable: call `preventDefault()` to keep the current value.
69
78
  * @event {Event} input - Fired after the value changes.
70
79
  *
71
- * @csspart control - The range input.
80
+ * @csspart control - The range input, one per thumb. On a range each carries `data-thumb`, `start`, `middle`, or `end`, and `data-index`, its place from the lowest.
72
81
  * @csspart feedback - The error message under the track.
73
82
  * @csspart field - The row that holds the control and its readout.
74
83
  * @csspart hint - The help text under the track, shown while there is no error.
@@ -77,10 +86,12 @@ declare const HelixHeadlessSlider_base: (new (...args: any[]) => import("@fusion
77
86
  * @csspart marker-label - The value a mark stands at, when `marker-labels` is set.
78
87
  * @csspart markers - The row of marks along the track.
79
88
  * @csspart output - The current value, shown beside the track.
80
- * @csspart tooltip - One thumb's value in a bubble beside it, under `tooltip`. It carries `data-thumb` on a range, `start` or `end`, and `--slider-at`, where its thumb is as a fraction of the track.
89
+ * @csspart thumb - One thumb's own box over the track, which holds the `thumb` or `thumb-end` slot. It carries `data-thumb` on a range, `start`, `middle`, or `end`, and `--slider-at`, where its thumb is as a fraction of the track. Draw your own thumb here and hide the native one, or leave it empty.
90
+ * @csspart thumbs - The layer over the track that holds each `thumb`. It is `hidden` until a thumb slot has content, and then `[part="field"]` carries `data-thumbs`.
91
+ * @csspart tooltip - One thumb's value in a bubble beside it, under `tooltip`. It carries `data-thumb` on a range, `start`, `middle`, or `end`, and `--slider-at`, where its thumb is as a fraction of the track.
81
92
  * @csspart tooltips - The layer over the track that holds the bubbles, under `tooltip`.
82
93
  *
83
- * @cssproperty --slider-at - Where a bubble's thumb is, as a fraction of the track, 0 to 1. Set on each `tooltip` part.
94
+ * @cssproperty --slider-at - Where a bubble's or a thumb box's thumb is, as a fraction of the track, 0 to 1. Set on each `tooltip` and `thumb` part.
84
95
  * @cssproperty --slider-fraction - The value as a fraction of the range, 0 to 1.
85
96
  * @cssproperty --slider-from - Where the filled span starts, as a fraction of the track, 0 to 1: a range's lower thumb, or a single thumb's `origin`.
86
97
  * @cssproperty --slider-marker-at - Where one marker sits, as a percentage of the track.
@@ -185,9 +196,11 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
185
196
  /**
186
197
  * Adds a second thumb, so the value is a pair.
187
198
  *
188
- * The pair is one string, `"10,50"`, which is what a form submits and what
189
- * `MixinControllerValue` already holds. `valueAsNumber` reads the lower of
190
- * the two, since a range has no single number.
199
+ * The pair is one string, `"10,50"`, which is what `value` and
200
+ * `MixinControllerValue` hold. A form receives two entries under the name,
201
+ * `price=10&price=50`, as React Aria's two thumbs send theirs.
202
+ * `valueAsNumber` reads the lower of the two, since a range has no single
203
+ * number.
191
204
  */
192
205
  range: boolean;
193
206
  /**
@@ -195,12 +208,27 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
195
208
  * filled in. Write it in the page's language, such as `{start} bis {end}`.
196
209
  */
197
210
  rangeText: string;
211
+ /**
212
+ * Whether a reader can see and focus the value and cannot change it. A
213
+ * read-only slider still submits its value.
214
+ *
215
+ * React Aria's `isReadOnly`. Each thumb stays a tab stop and says
216
+ * `aria-readonly`. The arrow keys, the page keys, Home, End, and a drag
217
+ * leave the value where it is. A script can still set `value`.
218
+ */
219
+ readOnly: boolean;
198
220
  /**
199
221
  * Shows the chosen value beside the track.
200
222
  */
201
223
  showValue: boolean;
202
224
  /** How far one press of an arrow key moves the thumb. */
203
225
  step: number;
226
+ /**
227
+ * The name of a thumb between a range's first and last, read after the
228
+ * slider's label, with `{index}` filled in: its place, counted from 1. The
229
+ * first is `minimum-label` and the last `maximum-label`.
230
+ */
231
+ thumbLabel: string;
204
232
  /**
205
233
  * Whether each thumb shows its value in a bubble beside it, as Web
206
234
  * Awesome's `with-tooltip`. The styled slider shows the bubbles while the
@@ -258,12 +286,29 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
258
286
  * is what a filter with nothing filtered out looks like.
259
287
  */
260
288
  private get bounds();
289
+ /**
290
+ * A range's values, one per thumb, as numbers in order.
291
+ *
292
+ * A lone number is not a range, so it is not read as one. `willUpdate`
293
+ * seeds and sanitizes a range to two values or more, and anything else that
294
+ * arrives between the two opens fully wide, which is what "nothing filtered
295
+ * out" looks like.
296
+ */
297
+ private get points();
261
298
  /** Where one value sits along the track, as a fraction of it. */
262
299
  private along;
263
300
  private readonly handleInput;
264
301
  /** Relayed, because `change` does not cross a shadow boundary on its own. */
265
302
  private readonly handleChange;
266
- /** Reports the value. */
303
+ /**
304
+ * Keeps a read-only thumb still under the keys that move it. Tab and every
305
+ * other key pass, so focus moves on.
306
+ */
307
+ private readonly handleKeydown;
308
+ /**
309
+ * Reports the value: one entry, or for a named range one entry per thumb.
310
+ * The joined pair is the state the browser restores.
311
+ */
267
312
  private sync;
268
313
  /**
269
314
  * How far along the track the thumb sits, as a fraction.
@@ -325,18 +370,35 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
325
370
  /** What a screen reader says for one thumb, where `value-text` asks. */
326
371
  private spoken;
327
372
  protected updated(changed: PropertyValues): void;
373
+ /** Draws, once a served slider has hydrated, what its children ask for. */
374
+ protected firstUpdated(changed: PropertyValues): void;
328
375
  /**
329
376
  * What a screen reader says for a thumb's value, with `{value}` filled in,
330
377
  * such as `{value} degrees`. Empty announces the number alone.
331
378
  */
332
379
  valueText: string;
380
+ /**
381
+ * Whether a `thumb` or `thumb-end` slot has content, read off the children
382
+ * rather than heard from `slotchange`: a declarative shadow root fires that
383
+ * before anything listens, so a served slider kept its layer hidden.
384
+ */
385
+ private get thumbContent();
386
+ private readonly handleThumbSlot;
387
+ /**
388
+ * A box for each thumb, over the track at the thumb's place, holding the
389
+ * `thumb` slot: a range's upper thumb holds `thumb-end`. Hidden from the
390
+ * accessibility tree, since each thumb is already a range with a name and a
391
+ * value, and `hidden` while no slot has content, so an empty layer takes no
392
+ * room in the row.
393
+ */
394
+ protected renderThumbs(): TemplateResult;
333
395
  /**
334
396
  * A bubble for each thumb, under `tooltip`, saying its value where it is.
335
397
  * After the thumbs, so a stylesheet can reach a bubble from a focused
336
398
  * thumb, and hidden from the accessibility tree for the reason the readout
337
399
  * is: each thumb already reports its value.
338
400
  */
339
- protected renderTooltips(start: number, end: number): TemplateResult | typeof nothing;
401
+ protected renderTooltips(): TemplateResult | typeof nothing;
340
402
  protected render(): TemplateResult;
341
403
  }
342
404
  declare global {