@fusion.dev/helix-headless 0.103.3 → 0.104.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/custom-elements.json +9260 -880
  2. package/dist/announcement/root/announcement-root.d.ts +9 -2
  3. package/dist/announcement/root/announcement-root.js +9 -6
  4. package/dist/badge/root/badge-root.js +2 -3
  5. package/dist/canvas/edge/canvas-edge.d.ts +112 -0
  6. package/dist/canvas/edge/canvas-edge.js +66 -0
  7. package/dist/canvas/index.d.ts +4 -0
  8. package/dist/canvas/index.js +3 -0
  9. package/dist/canvas/node/canvas-node.d.ts +211 -0
  10. package/dist/canvas/node/canvas-node.js +148 -0
  11. package/dist/canvas/root/canvas-document.d.ts +215 -0
  12. package/dist/canvas/root/canvas-document.js +284 -0
  13. package/dist/canvas/root/canvas-root.d.ts +924 -0
  14. package/dist/canvas/root/canvas-root.js +1831 -0
  15. package/dist/carousel/root/carousel-root.d.ts +53 -16
  16. package/dist/carousel/root/carousel-root.js +46 -11
  17. package/dist/chat/root/chat-root.d.ts +4 -0
  18. package/dist/chat/root/chat-root.js +11 -7
  19. package/dist/checkbox/root/checkbox-root.js +1 -0
  20. package/dist/checkbox-group/root/checkbox-group-root.d.ts +10 -0
  21. package/dist/checkbox-group/root/checkbox-group-root.js +5 -0
  22. package/dist/color-input/root/color-input-root.js +21 -5
  23. package/dist/color-picker/root/color-picker-root.d.ts +55 -0
  24. package/dist/color-picker/root/color-picker-root.js +61 -12
  25. package/dist/combobox/root/combobox-root.d.ts +21 -2
  26. package/dist/combobox/root/combobox-root.js +23 -9
  27. package/dist/command/root/command-root.d.ts +1 -0
  28. package/dist/command/root/command-root.js +1 -1
  29. package/dist/data-table/root/data-table-root.d.ts +43 -42
  30. package/dist/data-table/root/data-table-root.js +35 -34
  31. package/dist/date-input/root/date-input-root.d.ts +27 -0
  32. package/dist/date-input/root/date-input-root.js +38 -9
  33. package/dist/date-picker/root/date-picker-root.d.ts +28 -16
  34. package/dist/date-picker/root/date-picker-root.js +17 -15
  35. package/dist/drilldown/root/drilldown-root.d.ts +1 -0
  36. package/dist/drilldown/root/drilldown-root.js +5 -2
  37. package/dist/element-events.generated.js +15 -0
  38. package/dist/empty/root/empty-root.d.ts +12 -7
  39. package/dist/empty/root/empty-root.js +13 -10
  40. package/dist/file-input/root/file-input-root.d.ts +5 -1
  41. package/dist/file-input/root/file-input-root.js +6 -4
  42. package/dist/filter-input/menu/filter-menu.d.ts +1 -0
  43. package/dist/filter-input/menu/filter-menu.js +1 -1
  44. package/dist/filter-input/root/filter-input-root.js +5 -0
  45. package/dist/index.d.ts +1 -0
  46. package/dist/index.js +1 -0
  47. package/dist/input/root/input-root.js +1 -1
  48. package/dist/lightbox/root/lightbox-root.d.ts +9 -1
  49. package/dist/lightbox/root/lightbox-root.js +17 -7
  50. package/dist/listbox/root/listbox-root.d.ts +16 -14
  51. package/dist/listbox/root/listbox-root.js +24 -15
  52. package/dist/map/root/map-root.d.ts +6 -3
  53. package/dist/map/root/map-root.js +8 -2
  54. package/dist/menu/root/menu-root.d.ts +1 -0
  55. package/dist/menu/root/menu-root.js +1 -1
  56. package/dist/notifications/group/notification-group.js +5 -4
  57. package/dist/notifications/notification/notification.d.ts +10 -10
  58. package/dist/notifications/notification/notification.js +3 -3
  59. package/dist/notifications/root/notifications-root.d.ts +1 -0
  60. package/dist/notifications/root/notifications-root.js +1 -0
  61. package/dist/number-input/root/number-input-root.d.ts +17 -0
  62. package/dist/number-input/root/number-input-root.js +22 -6
  63. package/dist/object-inspector/root/object-inspector-root.d.ts +10 -0
  64. package/dist/object-inspector/root/object-inspector-root.js +10 -2
  65. package/dist/outline/root/outline-root.d.ts +15 -0
  66. package/dist/outline/root/outline-root.js +12 -7
  67. package/dist/pagination/root/pagination-root.d.ts +18 -18
  68. package/dist/pagination/root/pagination-root.js +5 -5
  69. package/dist/pagination/size/pagination-size.d.ts +10 -9
  70. package/dist/pagination/size/pagination-size.js +4 -4
  71. package/dist/pagination/summary/pagination-summary.js +6 -5
  72. package/dist/pin-input/root/pin-input-root.d.ts +5 -0
  73. package/dist/pin-input/root/pin-input-root.js +10 -6
  74. package/dist/rating/root/rating-root.js +3 -2
  75. package/dist/select/root/select-root.d.ts +1 -0
  76. package/dist/select/root/select-root.js +8 -3
  77. package/dist/slider/root/slider-root.d.ts +12 -0
  78. package/dist/slider/root/slider-root.js +13 -1
  79. package/dist/splitter/root/splitter-root.d.ts +44 -35
  80. package/dist/splitter/root/splitter-root.js +27 -22
  81. package/dist/switch/root/switch-root.js +1 -0
  82. package/dist/table/column/table-column.d.ts +17 -0
  83. package/dist/table/column/table-column.js +16 -4
  84. package/dist/table/root/table-root.d.ts +1 -0
  85. package/dist/table/root/table-root.js +1 -1
  86. package/dist/textarea/root/textarea-root.js +1 -1
  87. package/dist/time-input/root/time-input-root.d.ts +29 -0
  88. package/dist/time-input/root/time-input-root.js +31 -10
  89. package/dist/time-picker/root/time-picker-root.d.ts +14 -0
  90. package/dist/time-picker/root/time-picker-root.js +16 -14
  91. package/dist/toast/item/toast-item.d.ts +12 -11
  92. package/dist/toast/item/toast-item.js +11 -5
  93. package/dist/toolbar/root/toolbar-root.js +2 -16
  94. package/dist/tooltip/root/tooltip-root.d.ts +1 -0
  95. package/dist/tooltip/root/tooltip-root.js +6 -0
  96. package/dist/tour/root/tour-root.d.ts +10 -10
  97. package/dist/tour/root/tour-root.js +5 -5
  98. package/dist/tree/root/tree-root.d.ts +1 -0
  99. package/dist/tree/root/tree-root.js +1 -1
  100. package/dist/video/root/video-root.d.ts +84 -0
  101. package/dist/video/root/video-root.js +116 -41
  102. package/dist/video-playlist/menu/video-playlist-menu.d.ts +1 -0
  103. package/dist/video-playlist/menu/video-playlist-menu.js +4 -3
  104. package/package.json +5 -5
  105. package/types/jsx.d.ts +5419 -716
  106. package/types/svelte.d.ts +3 -0
  107. package/types/vue.d.ts +1607 -213
@@ -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 { CopyController, capturePointer, customElement, drawIcon, formatColor, HelixFormElement, HelixSampleEndEvent, HelixSampleStartEvent, isRtl, MixinControllerValue, parseColor, splitValues, toCss, } from '@fusion.dev/helix-core';
7
+ import { CopyController, capturePointer, customElement, drawIcon, fillTemplate, formatColor, HelixFormElement, HelixSampleEndEvent, HelixSampleStartEvent, isRtl, MixinControllerValue, parseColor, splitValues, toCss, } from '@fusion.dev/helix-core';
8
8
  import { eyedropper } from '@fusion.dev/helix-icons';
9
9
  import { nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -19,13 +19,24 @@ let HelixHeadlessColorPicker = class HelixHeadlessColorPicker extends MixinContr
19
19
  super(...arguments);
20
20
  this.alpha = false;
21
21
  this.autocomplete = 'off';
22
+ this.brightnessLabel = 'Brightness';
23
+ this.copiedLabel = 'Copied';
24
+ this.copyLabel = 'Copy {value}';
25
+ this.eyedropperLabel = 'Sample a color from the screen';
26
+ this.formatLabel = 'Syntax: {format}. Change it.';
27
+ this.hueLabel = 'Hue';
22
28
  this.invalid = false;
23
29
  this.noEyedropper = false;
24
30
  this.noFormat = false;
25
31
  this.noValue = false;
32
+ this.opacityLabel = 'Opacity';
33
+ this.presetsLabel = 'Presets';
26
34
  this.readOnly = false;
27
35
  this.required = false;
36
+ this.saturationLabel = 'Saturation';
28
37
  this.swatches = '';
38
+ this.toolsLabel = 'Color tools';
39
+ this.valueLabel = 'Color';
29
40
  this.sampling = false;
30
41
  this.owned = false;
31
42
  this.settled = '';
@@ -131,7 +142,7 @@ let HelixHeadlessColorPicker = class HelixHeadlessColorPicker extends MixinContr
131
142
  }
132
143
  reportRequired() {
133
144
  if (this.required && this.value === '') {
134
- this.internals.setValidity({ valueMissing: true }, 'Choose a color.', this.partNamed('grid') ?? undefined);
145
+ this.internals.setValidity({ valueMissing: true }, this.valueMissingMessage || 'Choose a color.', this.partNamed('grid') ?? undefined);
135
146
  return;
136
147
  }
137
148
  this.internals.setValidity({});
@@ -199,12 +210,12 @@ let HelixHeadlessColorPicker = class HelixHeadlessColorPicker extends MixinContr
199
210
  }
200
211
  }
201
212
  renderTools() {
202
- return html `<${this.tag('button-group')} part="actions" label="Color tools">
213
+ return html `<${this.tag('button-group')} part="actions" label=${this.toolsLabel}>
203
214
  ${this.sampling && !this.noEyedropper
204
215
  ? html `<${this.tag('button')}
205
216
  part="eyedropper"
206
217
  exportparts="button: eyedropper-button"
207
- aria-label="Sample a color from the screen"
218
+ aria-label=${this.eyedropperLabel}
208
219
  ?disabled=${this.isDisabled}
209
220
  @click=${this.handleEyeDropper}
210
221
  >
@@ -216,7 +227,7 @@ let HelixHeadlessColorPicker = class HelixHeadlessColorPicker extends MixinContr
216
227
  : html `<${this.tag('button')}
217
228
  part="format"
218
229
  exportparts="button: format-button"
219
- aria-label=${`Syntax: ${this.format ?? 'hex'}. Change it.`}
230
+ aria-label=${fillTemplate(this.formatLabel, { format: this.format ?? 'hex' })}
220
231
  ?disabled=${this.isDisabled}
221
232
  @click=${this.handleFormat}
222
233
  >
@@ -238,7 +249,7 @@ let HelixHeadlessColorPicker = class HelixHeadlessColorPicker extends MixinContr
238
249
  type="range"
239
250
  min="0"
240
251
  max="100"
241
- aria-label="Saturation"
252
+ aria-label=${this.saturationLabel}
242
253
  .value=${String(color.saturation)}
243
254
  ?disabled=${this.isDisabled}
244
255
  @input=${(event) => this.takeArea('saturation', event)}
@@ -248,7 +259,7 @@ let HelixHeadlessColorPicker = class HelixHeadlessColorPicker extends MixinContr
248
259
  type="range"
249
260
  min="0"
250
261
  max="100"
251
- aria-label="Brightness"
262
+ aria-label=${this.brightnessLabel}
252
263
  .value=${String(color.brightness)}
253
264
  ?disabled=${this.isDisabled}
254
265
  @input=${(event) => this.takeArea('brightness', event)}
@@ -259,14 +270,16 @@ let HelixHeadlessColorPicker = class HelixHeadlessColorPicker extends MixinContr
259
270
  <button
260
271
  part="sample"
261
272
  type="button"
262
- aria-label=${this.copier.copied ? 'Copied' : `Copy ${this.value || 'the color'}`}
273
+ aria-label=${this.copier.copied
274
+ ? this.copiedLabel
275
+ : fillTemplate(this.copyLabel, { value: this.value }).trim()}
263
276
  data-copied=${this.copier.copied ? '' : nothing}
264
277
  ?disabled=${this.isDisabled || this.value === ''}
265
278
  @click=${() => this.copier.copy(this.value)}
266
279
  ></button>
267
280
  <div part="channels">
268
- ${this.renderChannel('hue', 'Hue', 360, color.hue)}
269
- ${this.alpha ? this.renderChannel('alpha', 'Opacity', 100, color.alpha) : nothing}
281
+ ${this.renderChannel('hue', this.hueLabel, 360, color.hue)}
282
+ ${this.alpha ? this.renderChannel('alpha', this.opacityLabel, 100, color.alpha) : nothing}
270
283
  </div>
271
284
  </div>
272
285
 
@@ -280,7 +293,7 @@ let HelixHeadlessColorPicker = class HelixHeadlessColorPicker extends MixinContr
280
293
  : html `<input
281
294
  part="value"
282
295
  type="text"
283
- aria-label="Color"
296
+ aria-label=${this.valueLabel}
284
297
  autocomplete=${this.autocomplete || nothing}
285
298
  spellcheck="false"
286
299
  .value=${this.value}
@@ -293,7 +306,7 @@ let HelixHeadlessColorPicker = class HelixHeadlessColorPicker extends MixinContr
293
306
 
294
307
  ${this.presets.length === 0
295
308
  ? nothing
296
- : html `<div part="swatches" role="group" aria-label="Presets">
309
+ : html `<div part="swatches" role="group" aria-label=${this.presetsLabel}>
297
310
  ${this.presets.map((preset) => {
298
311
  const parsed = parseColor(preset);
299
312
  return html `<button
@@ -315,9 +328,27 @@ __decorate([
315
328
  __decorate([
316
329
  property()
317
330
  ], HelixHeadlessColorPicker.prototype, "autocomplete", void 0);
331
+ __decorate([
332
+ property({ attribute: 'brightness-label' })
333
+ ], HelixHeadlessColorPicker.prototype, "brightnessLabel", void 0);
334
+ __decorate([
335
+ property({ attribute: 'copied-label' })
336
+ ], HelixHeadlessColorPicker.prototype, "copiedLabel", void 0);
337
+ __decorate([
338
+ property({ attribute: 'copy-label' })
339
+ ], HelixHeadlessColorPicker.prototype, "copyLabel", void 0);
340
+ __decorate([
341
+ property({ attribute: 'eyedropper-label' })
342
+ ], HelixHeadlessColorPicker.prototype, "eyedropperLabel", void 0);
318
343
  __decorate([
319
344
  property({ reflect: true })
320
345
  ], HelixHeadlessColorPicker.prototype, "format", void 0);
346
+ __decorate([
347
+ property({ attribute: 'format-label' })
348
+ ], HelixHeadlessColorPicker.prototype, "formatLabel", void 0);
349
+ __decorate([
350
+ property({ attribute: 'hue-label' })
351
+ ], HelixHeadlessColorPicker.prototype, "hueLabel", void 0);
321
352
  __decorate([
322
353
  property({ reflect: true, type: Boolean })
323
354
  ], HelixHeadlessColorPicker.prototype, "invalid", void 0);
@@ -330,15 +361,33 @@ __decorate([
330
361
  __decorate([
331
362
  property({ attribute: 'no-value', type: Boolean })
332
363
  ], HelixHeadlessColorPicker.prototype, "noValue", void 0);
364
+ __decorate([
365
+ property({ attribute: 'opacity-label' })
366
+ ], HelixHeadlessColorPicker.prototype, "opacityLabel", void 0);
367
+ __decorate([
368
+ property({ attribute: 'presets-label' })
369
+ ], HelixHeadlessColorPicker.prototype, "presetsLabel", void 0);
333
370
  __decorate([
334
371
  property({ attribute: 'readonly', reflect: true, type: Boolean })
335
372
  ], HelixHeadlessColorPicker.prototype, "readOnly", void 0);
336
373
  __decorate([
337
374
  property({ reflect: true, type: Boolean })
338
375
  ], HelixHeadlessColorPicker.prototype, "required", void 0);
376
+ __decorate([
377
+ property({ attribute: 'saturation-label' })
378
+ ], HelixHeadlessColorPicker.prototype, "saturationLabel", void 0);
339
379
  __decorate([
340
380
  property()
341
381
  ], HelixHeadlessColorPicker.prototype, "swatches", void 0);
382
+ __decorate([
383
+ property({ attribute: 'tools-label' })
384
+ ], HelixHeadlessColorPicker.prototype, "toolsLabel", void 0);
385
+ __decorate([
386
+ property({ attribute: 'value-label' })
387
+ ], HelixHeadlessColorPicker.prototype, "valueLabel", void 0);
388
+ __decorate([
389
+ property({ attribute: 'value-missing-message' })
390
+ ], HelixHeadlessColorPicker.prototype, "valueMissingMessage", void 0);
342
391
  __decorate([
343
392
  state()
344
393
  ], HelixHeadlessColorPicker.prototype, "moved", void 0);
@@ -68,6 +68,7 @@ declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusi
68
68
  * @csspart listbox-hint - Help under the list.
69
69
  * @csspart listbox-items - The list itself.
70
70
  * @csspart listbox-label - The question, over the list.
71
+ * @csspart listbox-live - The inner list's `live`, the region a screen reader hears its empty and loading lines from.
71
72
  * @csspart listbox-loading - Shown while the options are still on their way.
72
73
  * @csspart listbox-search - The region holding the field that narrows the list.
73
74
  * @csspart listbox-search-field - The field itself.
@@ -150,7 +151,10 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
150
151
  */
151
152
  placeholder: string;
152
153
  /**
153
- * What a tag's remove control is called, since the mark has no name.
154
+ * What the control removing one chosen option is called, with `{name}` filled in.
155
+ *
156
+ * **The name goes in**, so a row of them is heard as which one each
157
+ * removes rather than as "Remove" said once per chosen option.
154
158
  */
155
159
  removeLabel: string;
156
160
  /**
@@ -282,6 +286,22 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
282
286
  * the panel rather than about the options in it.
283
287
  */
284
288
  private readonly handleKeydown;
289
+ /**
290
+ * Tells the input which option is highlighted.
291
+ *
292
+ * **The input is where focus stays**, so it is what a screen reader asks.
293
+ * The listbox points its own list at the option, which is right for a
294
+ * listbox a reader is in and says nothing here: arrowing through a combobox
295
+ * moved the highlight in silence. The list's highlight is its own state, so
296
+ * this runs once the list has drawn the move, after an arrow and after a
297
+ * keystroke narrows it, as well as on every update of this element.
298
+ *
299
+ * Through `ariaActiveDescendantElement`, as `FilterInput` does, because the
300
+ * option is in the light DOM and the input in this shadow root, which an id
301
+ * cannot cross. Feature-tested, the assignment being a silent no-op where it
302
+ * is missing.
303
+ */
304
+ private linkActive;
285
305
  /**
286
306
  * Takes what the list announced and stops it there.
287
307
  *
@@ -331,7 +351,6 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
331
351
  */
332
352
  private sync;
333
353
  protected firstUpdated(changed: PropertyValues): void;
334
- protected willUpdate(changed: PropertyValues): void;
335
354
  protected updated(changed: PropertyValues): void;
336
355
  /**
337
356
  * The list the field filters, behind a seam the styled tier can move.
@@ -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, customElement, HelixCreateEvent, HelixFilterEvent, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, PopoverController, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, customElement, fillTemplate, HelixCreateEvent, HelixFilterEvent, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, PopoverController, reportValues, } from '@fusion.dev/helix-core';
8
8
  import { caretDown } from '@fusion.dev/helix-icons';
9
9
  import { nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -30,7 +30,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
30
30
  this.loadingText = 'Loading';
31
31
  this.multiple = false;
32
32
  this.placeholder = '';
33
- this.removeLabel = 'Remove';
33
+ this.removeLabel = 'Remove {name}';
34
34
  this.suggest = false;
35
35
  this.typed = '';
36
36
  this.suggestion = '';
@@ -53,6 +53,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
53
53
  const narrowing = new HelixFilterEvent({ value: typed });
54
54
  if (this.dispatchEvent(narrowing)) {
55
55
  this.listbox?.requestFilter(typed);
56
+ void this.listbox?.updateComplete.then(() => this.linkActive());
56
57
  }
57
58
  this.suggestion = this.suggest && isInsertion(event) ? this.completionFor(typed) : '';
58
59
  if (!this.open) {
@@ -88,6 +89,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
88
89
  this.requestOpen(true);
89
90
  }
90
91
  this.listbox?.navigate(event);
92
+ void this.listbox?.updateComplete.then(() => this.linkActive());
91
93
  };
92
94
  this.handleChange = (event) => {
93
95
  event.stopPropagation();
@@ -208,6 +210,16 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
208
210
  const match = (this.listbox?.options ?? []).find((option) => !option.hidden && !option.disabled && option.text.toLowerCase().startsWith(needle));
209
211
  return match && match.text.length > typed.length ? match.text : '';
210
212
  }
213
+ linkActive() {
214
+ const control = this.partNamed('control');
215
+ if (!control || !('ariaActiveDescendantElement' in control)) {
216
+ return;
217
+ }
218
+ const active = this.open
219
+ ? (this.listbox?.options ?? []).find((option) => option.active && !option.hidden)
220
+ : undefined;
221
+ control.ariaActiveDescendantElement = active ?? null;
222
+ }
211
223
  removeLastToken() {
212
224
  const last = this.values.at(-1);
213
225
  if (last !== undefined) {
@@ -215,20 +227,22 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
215
227
  }
216
228
  }
217
229
  sync() {
218
- this.internals.setFormValue(this.value === '' ? null : this.value);
230
+ if (this.multiple) {
231
+ reportValues(this.internals, this.name, this.value === '' ? [] : this.value.split(','));
232
+ }
233
+ else {
234
+ this.internals.setFormValue(this.value === '' ? null : this.value);
235
+ }
219
236
  this.reportRequired(this.value === '', 'Choose one to continue.', 'control');
220
237
  }
221
238
  firstUpdated(changed) {
222
239
  super.firstUpdated(changed);
223
240
  this.finishHydration();
224
241
  }
225
- willUpdate(changed) {
226
- super.willUpdate(changed);
227
- this.internals.ariaExpanded = this.open ? 'true' : 'false';
228
- }
229
242
  updated(changed) {
230
243
  super.updated?.(changed);
231
244
  this.sync();
245
+ this.linkActive();
232
246
  const control = this.partNamed('control');
233
247
  const wanted = this.multiple || this.open ? this.suggestion || this.typed : this.word;
234
248
  if (control && control.value !== wanted) {
@@ -249,7 +263,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
249
263
  id="listbox"
250
264
  exportparts="empty: listbox-empty, feedback: listbox-feedback, filter-icon: listbox-filter-icon,
251
265
  filter-mark: listbox-filter-mark, hint: listbox-hint, items: listbox-items,
252
- label: listbox-label, loading: listbox-loading, search: listbox-search,
266
+ label: listbox-label, live: listbox-live, loading: listbox-loading, search: listbox-search,
253
267
  search-field: listbox-search-field"
254
268
  aria-label=${this.listLabel}
255
269
  empty-text=${this.emptyText}
@@ -275,7 +289,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
275
289
  part="tag"
276
290
  exportparts="dismiss: tag-dismiss, dismiss-mark: tag-dismiss-mark, start: tag-start"
277
291
  data-value=${option.value}
278
- dismiss-label=${this.removeLabel}
292
+ dismiss-label=${fillTemplate(this.removeLabel, { name: option.text })}
279
293
  ?dismissible=${!this.isDisabled}
280
294
  @helix-dismiss=${this.handleDismiss}
281
295
  >${option.text}</${this.tag('tag')}
@@ -53,6 +53,7 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
53
53
  * @csspart listbox-hint - Help under the list.
54
54
  * @csspart listbox-items - The list itself.
55
55
  * @csspart listbox-label - The question, over the list.
56
+ * @csspart listbox-live - The inner list's `live`, the region a screen reader hears its empty and loading lines from.
56
57
  * @csspart listbox-loading - Shown while the options are still on their way.
57
58
  * @csspart listbox-search - The region holding the field that narrows the list.
58
59
  * @csspart listbox-search-field - The field itself.
@@ -134,7 +134,7 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
134
134
  part="listbox"
135
135
  exportparts="empty: listbox-empty, feedback: listbox-feedback, filter-icon: listbox-filter-icon,
136
136
  filter-mark: listbox-filter-mark, hint: listbox-hint, items: listbox-items,
137
- label: listbox-label, loading: listbox-loading, search: listbox-search,
137
+ label: listbox-label, live: listbox-live, loading: listbox-loading, search: listbox-search,
138
138
  search-field: listbox-search-field"
139
139
  aria-label=${this.label}
140
140
  empty-text=${this.emptyText}
@@ -94,6 +94,7 @@ declare const HelixHeadlessDataTable_base: (new (...args: any[]) => import("@fus
94
94
  * @csspart empty - Shown when the result has nothing in it, whether it arrived empty or a filter emptied it. A result still on its way is `loading` instead, which wins over this.
95
95
  * @csspart footer - The region below the grid.
96
96
  * @csspart head - The row the column headings sit in. `display: contents`, so it takes no space.
97
+ * @csspart live - The empty and loading lines again, in a region a screen reader hears when they change. Visually hidden in the styled tier.
97
98
  * @csspart loading - Shown while the rows are still on their way.
98
99
  * @csspart pagination - The pagination, where this draws one.
99
100
  * @csspart pagination-first - The pagination's control that jumps to the first page, under `ends`.
@@ -164,19 +165,6 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
164
165
  * been measured.
165
166
  */
166
167
  estimate: number;
167
- /**
168
- * The order, as `field:direction`.
169
- *
170
- * Set it and this element defers: a reader's click fires `helix-sort` and
171
- * changes nothing until a new value arrives. `default-sort` seeds an order this
172
- * element then owns.
173
- */
174
- get sort(): string;
175
- set sort(next: string);
176
- /**
177
- * Accessible name for the grid.
178
- */
179
- label: string;
180
168
  /**
181
169
  * What the rows are narrowed to, as one query across every column.
182
170
  *
@@ -186,6 +174,10 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
186
174
  */
187
175
  get filter(): string;
188
176
  set filter(next: string);
177
+ /**
178
+ * Accessible name for the grid.
179
+ */
180
+ label: string;
189
181
  /**
190
182
  * Whether this element does the work or asks the consumer to.
191
183
  *
@@ -197,6 +189,17 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
197
189
  * inverts the data flow.
198
190
  */
199
191
  mode: 'client' | 'server';
192
+ /**
193
+ * The columns' order, as their fields separated by spaces.
194
+ *
195
+ * A reader's move fires `helix-reorder` first, and refusing it leaves the
196
+ * columns where they were, which is how a consumer who stores the order takes
197
+ * the decision. `default-order` seeds an order this element then owns. A field not named
198
+ * keeps its place after the named ones, and a column with no field never
199
+ * moves.
200
+ */
201
+ get order(): string;
202
+ set order(next: string);
200
203
  /**
201
204
  * The page on show, from 1.
202
205
  *
@@ -206,6 +209,27 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
206
209
  */
207
210
  get page(): number;
208
211
  set page(next: number);
212
+ /**
213
+ * How many rows a page holds. Zero is every row, which is what "no paging" means.
214
+ *
215
+ * **It announces nothing, and that is not an omission.** Nothing in this
216
+ * element ever asks for a different page size: a size selector is
217
+ * `PaginationSize`, which a consumer puts in the `footer` slot and answers
218
+ * themselves. Routing this through `requestChange` would announce an event
219
+ * the element never has cause to fire.
220
+ */
221
+ get pageSize(): number;
222
+ set pageSize(next: number);
223
+ /**
224
+ * Whether to draw a pagination under the grid.
225
+ *
226
+ * On by default once a page size is set, because a paged table with no way to
227
+ * change pages shows a reader the first twenty rows and no way to know there
228
+ * are more. Off for a consumer supplying their own through the `footer` slot,
229
+ * which is why the slot replaces this rather than sitting beside it.
230
+ */
231
+ get paginated(): boolean;
232
+ set paginated(next: boolean);
209
233
  /**
210
234
  * Whether a reader may move the columns.
211
235
  *
@@ -213,17 +237,6 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
213
237
  * place at a time with the arrow keys once it has focus.
214
238
  */
215
239
  reorderable: boolean;
216
- /**
217
- * The columns' order, as their fields separated by spaces.
218
- *
219
- * A reader's move fires `helix-reorder` first, and refusing it leaves the
220
- * columns where they were, which is how a consumer who stores the order takes
221
- * the decision. `default-order` seeds an order this element then owns. A field not named
222
- * keeps its place after the named ones, and a column with no field never
223
- * moves.
224
- */
225
- get order(): string;
226
- set order(next: string);
227
240
  /**
228
241
  * The field naming a row's stable identity.
229
242
  *
@@ -270,16 +283,14 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
270
283
  get selected(): string;
271
284
  set selected(next: string);
272
285
  /**
273
- * How many rows a page holds. Zero is every row, which is what "no paging" means.
286
+ * The order, as `field:direction`.
274
287
  *
275
- * **It announces nothing, and that is not an omission.** Nothing in this
276
- * element ever asks for a different page size: a size selector is
277
- * `PaginationSize`, which a consumer puts in the `footer` slot and answers
278
- * themselves. Routing this through `requestChange` would announce an event
279
- * the element never has cause to fire.
288
+ * Set it and this element defers: a reader's click fires `helix-sort` and
289
+ * changes nothing until a new value arrives. `default-sort` seeds an order this
290
+ * element then owns.
280
291
  */
281
- get pageSize(): number;
282
- set pageSize(next: number);
292
+ get sort(): string;
293
+ set sort(next: string);
283
294
  /**
284
295
  * How many rows the whole result has, where this element cannot count them.
285
296
  *
@@ -309,16 +320,6 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
309
320
  * should pay none of them.
310
321
  */
311
322
  windowed: boolean;
312
- /**
313
- * Whether to draw a pagination under the grid.
314
- *
315
- * On by default once a page size is set, because a paged table with no way to
316
- * change pages shows a reader the first twenty rows and no way to know there
317
- * are more. Off for a consumer supplying their own through the `footer` slot,
318
- * which is why the slot replaces this rather than sitting beside it.
319
- */
320
- get paginated(): boolean;
321
- set paginated(next: boolean);
322
323
  private sortState;
323
324
  private filterState;
324
325
  private pageState;
@@ -169,14 +169,6 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
169
169
  ...HelixElement.shadowRootOptions,
170
170
  slotAssignment: 'manual',
171
171
  }; }
172
- get sort() {
173
- return this.sortState ?? this.defaultSort;
174
- }
175
- set sort(next) {
176
- const previous = this.sort;
177
- this.sortState = next;
178
- this.requestUpdate('sort', previous);
179
- }
180
172
  get filter() {
181
173
  return this.filterState ?? this.defaultFilter;
182
174
  }
@@ -185,15 +177,6 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
185
177
  this.filterState = next;
186
178
  this.requestUpdate('filter', previous);
187
179
  }
188
- get page() {
189
- const asked = this.pageState ?? this.defaultPage;
190
- return Math.min(this.pages, Math.max(1, Math.floor(asked) || 1));
191
- }
192
- set page(next) {
193
- const previous = this.page;
194
- this.pageState = next;
195
- this.requestUpdate('page', previous);
196
- }
197
180
  get order() {
198
181
  return this.orderState ?? this.defaultOrder;
199
182
  }
@@ -202,13 +185,14 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
202
185
  this.orderState = next;
203
186
  this.requestUpdate('order', previous);
204
187
  }
205
- get selected() {
206
- return this.selectedState ?? this.defaultSelected;
188
+ get page() {
189
+ const asked = this.pageState ?? this.defaultPage;
190
+ return Math.min(this.pages, Math.max(1, Math.floor(asked) || 1));
207
191
  }
208
- set selected(next) {
209
- const previous = this.selected;
210
- this.selectedState = next;
211
- this.requestUpdate('selected', previous);
192
+ set page(next) {
193
+ const previous = this.page;
194
+ this.pageState = next;
195
+ this.requestUpdate('page', previous);
212
196
  }
213
197
  get pageSize() {
214
198
  return Math.max(0, Math.floor(this.pageSizeState ?? this.defaultPageSize) || 0);
@@ -226,6 +210,22 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
226
210
  this.paginatedState = next;
227
211
  this.requestUpdate('paginated', previous);
228
212
  }
213
+ get selected() {
214
+ return this.selectedState ?? this.defaultSelected;
215
+ }
216
+ set selected(next) {
217
+ const previous = this.selected;
218
+ this.selectedState = next;
219
+ this.requestUpdate('selected', previous);
220
+ }
221
+ get sort() {
222
+ return this.sortState ?? this.defaultSort;
223
+ }
224
+ set sort(next) {
225
+ const previous = this.sort;
226
+ this.sortState = next;
227
+ this.requestUpdate('sort', previous);
228
+ }
229
229
  drawn() {
230
230
  return [...this.renderRoot.querySelectorAll('[part="row"][data-index]')].map((element) => ({ element, index: Number(element.dataset.index) }));
231
231
  }
@@ -641,6 +641,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
641
641
  ${this.renderSpacer('before')}${this.renderRows(rows)}${this.renderSpacer('after')}
642
642
  ${this.renderStatus(filled)}
643
643
  </div>
644
+ ${this.renderLive(filled)}
644
645
  <div part="footer">
645
646
  <slot name="footer"></slot>
646
647
  ${this.paginated
@@ -719,25 +720,28 @@ __decorate([
719
720
  ], HelixHeadlessDataTable.prototype, "estimate", void 0);
720
721
  __decorate([
721
722
  property()
722
- ], HelixHeadlessDataTable.prototype, "sort", null);
723
+ ], HelixHeadlessDataTable.prototype, "filter", null);
723
724
  __decorate([
724
725
  property()
725
726
  ], HelixHeadlessDataTable.prototype, "label", void 0);
726
727
  __decorate([
727
728
  property()
728
- ], HelixHeadlessDataTable.prototype, "filter", null);
729
+ ], HelixHeadlessDataTable.prototype, "mode", void 0);
729
730
  __decorate([
730
731
  property()
731
- ], HelixHeadlessDataTable.prototype, "mode", void 0);
732
+ ], HelixHeadlessDataTable.prototype, "order", null);
732
733
  __decorate([
733
734
  property({ type: Number })
734
735
  ], HelixHeadlessDataTable.prototype, "page", null);
736
+ __decorate([
737
+ property({ attribute: 'page-size', type: Number })
738
+ ], HelixHeadlessDataTable.prototype, "pageSize", null);
735
739
  __decorate([
736
740
  property({ type: Boolean })
737
- ], HelixHeadlessDataTable.prototype, "reorderable", void 0);
741
+ ], HelixHeadlessDataTable.prototype, "paginated", null);
738
742
  __decorate([
739
- property()
740
- ], HelixHeadlessDataTable.prototype, "order", null);
743
+ property({ type: Boolean })
744
+ ], HelixHeadlessDataTable.prototype, "reorderable", void 0);
741
745
  __decorate([
742
746
  property({ attribute: 'row-key' })
743
747
  ], HelixHeadlessDataTable.prototype, "rowKey", void 0);
@@ -751,17 +755,14 @@ __decorate([
751
755
  property()
752
756
  ], HelixHeadlessDataTable.prototype, "selected", null);
753
757
  __decorate([
754
- property({ attribute: 'page-size', type: Number })
755
- ], HelixHeadlessDataTable.prototype, "pageSize", null);
758
+ property()
759
+ ], HelixHeadlessDataTable.prototype, "sort", null);
756
760
  __decorate([
757
761
  property({ type: Number })
758
762
  ], HelixHeadlessDataTable.prototype, "total", void 0);
759
763
  __decorate([
760
764
  property({ reflect: true, type: Boolean })
761
765
  ], HelixHeadlessDataTable.prototype, "windowed", void 0);
762
- __decorate([
763
- property({ type: Boolean })
764
- ], HelixHeadlessDataTable.prototype, "paginated", null);
765
766
  __decorate([
766
767
  state()
767
768
  ], HelixHeadlessDataTable.prototype, "sortState", void 0);
@@ -185,6 +185,31 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
185
185
  * What the field says before a date is in it.
186
186
  */
187
187
  placeholder: string;
188
+ /**
189
+ * What a reader is told when a range holds more than two dates.
190
+ *
191
+ * **Every sentence a control raises in the browser's bubble is a property**,
192
+ * so a form in another language speaks it. Absent is the control's own
193
+ * sentence, in English.
194
+ */
195
+ rangeLengthMessage?: string;
196
+ /**
197
+ * What a reader is told when a date is after `max`, with `{max}` filled in
198
+ * as the field writes it.
199
+ */
200
+ rangeOverflowMessage?: string;
201
+ /**
202
+ * What a reader is told when a date is before `min`, with `{min}` filled
203
+ * in as the field writes it.
204
+ */
205
+ rangeUnderflowMessage?: string;
206
+ /**
207
+ * What the control removing one date is called, with `{name}` filled in.
208
+ *
209
+ * **The name goes in**, so a row of them is heard as which one each
210
+ * removes rather than as "Remove" said once per date.
211
+ */
212
+ removeLabel: string;
188
213
  /**
189
214
  * How far apart the selectable dates are, in days.
190
215
  *
@@ -227,6 +252,8 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
227
252
  /** Takes one date back out of the set. */
228
253
  private readonly removeDate;
229
254
  private readonly handleCalendarChange;
255
+ /** Each date, where `mode` holds several, sent one entry each. */
256
+ protected get answers(): readonly string[] | undefined;
230
257
  /** What is wrong with the dates, which the text input cannot say. */
231
258
  protected validate(): string;
232
259
  /**