@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,12 +4,12 @@ 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 { customElement, formatNumbers, HelixElement, HelixNavigateEvent, hostAria, requestChange, } from '@fusion.dev/helix-core';
7
+ import { customElement, fillTemplate, formatNumbers, HelixElement, HelixNavigateEvent, hostAria, requestChange, } from '@fusion.dev/helix-core';
8
8
  import { caretDoubleLeft, caretDoubleRight, caretLeft, caretRight, } from '@fusion.dev/helix-icons';
9
9
  import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
11
11
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
12
- const fill = (template, page, pages, format = String) => template.replaceAll('{page}', format(page)).replaceAll('{pages}', format(pages));
12
+ const fill = (template, page, pages, format = String) => fillTemplate(template, { page: format(page), pages: format(pages) });
13
13
  let HelixHeadlessPagination = class HelixHeadlessPagination extends HelixElement {
14
14
  constructor() {
15
15
  super(...arguments);
@@ -273,9 +273,6 @@ __decorate([
273
273
  __decorate([
274
274
  property({ type: Boolean })
275
275
  ], HelixHeadlessPagination.prototype, "ends", void 0);
276
- __decorate([
277
- property({ type: Number })
278
- ], HelixHeadlessPagination.prototype, "page", null);
279
276
  __decorate([
280
277
  property({ attribute: 'first-label' })
281
278
  ], HelixHeadlessPagination.prototype, "firstLabel", void 0);
@@ -297,6 +294,9 @@ __decorate([
297
294
  __decorate([
298
295
  property({ attribute: 'next-label' })
299
296
  ], HelixHeadlessPagination.prototype, "nextLabel", void 0);
297
+ __decorate([
298
+ property({ type: Number })
299
+ ], HelixHeadlessPagination.prototype, "page", null);
300
300
  __decorate([
301
301
  property({ attribute: 'page-label' })
302
302
  ], HelixHeadlessPagination.prototype, "pageLabel", void 0);
@@ -53,6 +53,7 @@ import '../../select/index.js';
53
53
  * @csspart control-listbox-hint - Help under the list.
54
54
  * @csspart control-listbox-items - The list itself.
55
55
  * @csspart control-listbox-label - The question, over the list.
56
+ * @csspart control-listbox-live - The inner listbox's `live`, the region a screen reader hears its empty and loading lines from.
56
57
  * @csspart control-listbox-loading - Shown while the options are still on their way.
57
58
  * @csspart control-listbox-search - The region holding the field that narrows the list.
58
59
  * @csspart control-listbox-search-field - The field itself.
@@ -74,15 +75,6 @@ export declare class HelixHeadlessPaginationSize extends HelixElement {
74
75
  * Size to start on, where nothing declared one.
75
76
  */
76
77
  defaultValue: number;
77
- /**
78
- * The size in force.
79
- *
80
- * Reading gives the real one; writing declares it the consumer's, and
81
- * `default-value` seeds one this element owns. Same accessor pair as
82
- * `Pagination.page` and the calendar's `month`.
83
- */
84
- get value(): number;
85
- set value(next: number);
86
78
  /**
87
79
  * The words beside the control.
88
80
  */
@@ -101,6 +93,15 @@ export declare class HelixHeadlessPaginationSize extends HelixElement {
101
93
  * is dropped rather than rendered as an option that cannot mean anything.
102
94
  */
103
95
  sizes: string;
96
+ /**
97
+ * The size in force.
98
+ *
99
+ * Reading gives the real one; writing declares it the consumer's, and
100
+ * `default-value` seeds one this element owns. Same accessor pair as
101
+ * `Pagination.page` and the calendar's `month`.
102
+ */
103
+ get value(): number;
104
+ set value(next: number);
104
105
  /** The size, whoever set it, and `undefined` until somebody has. */
105
106
  private valueState;
106
107
  /** Held across every component asking for the same locale. */
@@ -77,7 +77,7 @@ let HelixHeadlessPaginationSize = class HelixHeadlessPaginationSize extends Heli
77
77
  listbox-feedback: control-listbox-feedback, listbox-filter-icon: control-listbox-filter-icon,
78
78
  listbox-filter-mark: control-listbox-filter-mark, listbox-hint: control-listbox-hint,
79
79
  listbox-items: control-listbox-items, listbox-label: control-listbox-label,
80
- listbox-loading: control-listbox-loading, listbox-search: control-listbox-search,
80
+ listbox-live: control-listbox-live, listbox-loading: control-listbox-loading, listbox-search: control-listbox-search,
81
81
  listbox-search-field: control-listbox-search-field, surface: control-surface,
82
82
  trigger: control-trigger, value: control-value"
83
83
  label=${this.label}
@@ -104,9 +104,6 @@ let HelixHeadlessPaginationSize = class HelixHeadlessPaginationSize extends Heli
104
104
  __decorate([
105
105
  property({ attribute: 'default-value', type: Number })
106
106
  ], HelixHeadlessPaginationSize.prototype, "defaultValue", void 0);
107
- __decorate([
108
- property({ type: Number })
109
- ], HelixHeadlessPaginationSize.prototype, "value", null);
110
107
  __decorate([
111
108
  property()
112
109
  ], HelixHeadlessPaginationSize.prototype, "label", void 0);
@@ -116,6 +113,9 @@ __decorate([
116
113
  __decorate([
117
114
  property()
118
115
  ], HelixHeadlessPaginationSize.prototype, "sizes", void 0);
116
+ __decorate([
117
+ property({ type: Number })
118
+ ], HelixHeadlessPaginationSize.prototype, "value", null);
119
119
  HelixHeadlessPaginationSize = __decorate([
120
120
  customElement('helix-headless-pagination-size')
121
121
  ], HelixHeadlessPaginationSize);
@@ -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 { customElement, formatNumbers, HelixElement } from '@fusion.dev/helix-core';
7
+ import { customElement, fillTemplate, formatNumbers, HelixElement } from '@fusion.dev/helix-core';
8
8
  import { html } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  let HelixHeadlessPaginationSummary = class HelixHeadlessPaginationSummary extends HelixElement {
@@ -28,10 +28,11 @@ let HelixHeadlessPaginationSummary = class HelixHeadlessPaginationSummary extend
28
28
  const page = Math.min(pages, Math.max(1, Math.floor(this.page) || 1));
29
29
  const from = (page - 1) * size + 1;
30
30
  const to = Math.min(this.total, from + size - 1);
31
- return html `${this.format
32
- .replaceAll('{from}', this.numbers(from))
33
- .replaceAll('{to}', this.numbers(to))
34
- .replaceAll('{total}', this.numbers(this.total))}`;
31
+ return html `${fillTemplate(this.format, {
32
+ from: this.numbers(from),
33
+ to: this.numbers(to),
34
+ total: this.numbers(this.total),
35
+ })}`;
35
36
  }
36
37
  };
37
38
  __decorate([
@@ -93,6 +93,11 @@ export declare class HelixHeadlessPinInput extends HelixHeadlessPinInput_base {
93
93
  * Whether the boxes refuse input while still submitting their value.
94
94
  */
95
95
  readOnly: boolean;
96
+ /**
97
+ * What a reader is told when the code is started and not finished, with
98
+ * `{length}` filled in. Absent is the control's own sentence, in English.
99
+ */
100
+ tooShortMessage?: string;
96
101
  /**
97
102
  * What a box accepts, which decides the keyboard a phone offers.
98
103
  *
@@ -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, HelixCompleteEvent, HelixFormElement, MixinControllerValue, MixinField, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, customElement, fillTemplate, HelixCompleteEvent, HelixFormElement, MixinControllerValue, MixinField, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
10
  let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerValue(MixinField(HelixFormElement)) {
@@ -165,10 +165,12 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
165
165
  return;
166
166
  }
167
167
  if (this.required && this.value === '') {
168
- this.internals.setValidity({ valueMissing: true }, 'Please fill in this field.', first);
168
+ this.internals.setValidity({ valueMissing: true }, this.valueMissingMessage || 'Please fill in this field.', first);
169
169
  }
170
170
  else if (this.value !== '' && this.value.length < this.count) {
171
- this.internals.setValidity({ tooShort: true }, `Please enter all ${this.count} characters.`, first);
171
+ this.internals.setValidity({ tooShort: true }, fillTemplate(this.tooShortMessage || 'Please enter all {length} characters.', {
172
+ length: this.count,
173
+ }), first);
172
174
  }
173
175
  else {
174
176
  this.internals.setValidity({}, '', first);
@@ -204,6 +206,7 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
204
206
  part="field"
205
207
  role="group"
206
208
  aria-describedby=${this.describedBy ?? nothing}
209
+ aria-labelledby=${this.labeled ? this.labelId : nothing}
207
210
  @focusin=${this.handleFocusIn}
208
211
  @focusout=${this.handleFocusOut}
209
212
  >
@@ -214,9 +217,7 @@ let HelixHeadlessPinInput = class HelixHeadlessPinInput extends MixinControllerV
214
217
  placeholder=${this.placeholder || nothing}
215
218
  inputmode=${this.type === 'numeric' ? 'numeric' : 'text'}
216
219
  autocomplete=${at === 0 ? this.autocomplete || nothing : 'off'}
217
- aria-label=${this.cellLabel
218
- .replaceAll('{index}', String(at + 1))
219
- .replaceAll('{length}', String(this.count))}
220
+ aria-label=${fillTemplate(this.cellLabel, { index: at + 1, length: this.count })}
220
221
  ?disabled=${this.isDisabled}
221
222
  ?readonly=${this.readOnly}
222
223
  @focus=${this.handleFocus}
@@ -246,6 +247,9 @@ __decorate([
246
247
  __decorate([
247
248
  property({ attribute: 'readonly', reflect: true, type: Boolean })
248
249
  ], HelixHeadlessPinInput.prototype, "readOnly", void 0);
250
+ __decorate([
251
+ property({ attribute: 'too-short-message' })
252
+ ], HelixHeadlessPinInput.prototype, "tooShortMessage", void 0);
249
253
  __decorate([
250
254
  property()
251
255
  ], HelixHeadlessPinInput.prototype, "type", void 0);
@@ -153,7 +153,7 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
153
153
  return nearest;
154
154
  }
155
155
  sync() {
156
- this.internals.setFormValue(this.value);
156
+ this.internals.setFormValue(this.value === '' ? null : this.value);
157
157
  this.reportRequired(this.value === '', 'Choose a rating to continue.', 'marks');
158
158
  }
159
159
  connectedCallback() {
@@ -198,7 +198,8 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
198
198
  <div
199
199
  part="marks"
200
200
  role=${this.readOnly ? 'img' : 'radiogroup'}
201
- aria-label=${this.readOnly ? said : this.label || nothing}
201
+ aria-label=${this.readOnly ? said : nothing}
202
+ aria-labelledby=${!this.readOnly && this.labeled ? this.labelId : nothing}
202
203
  aria-describedby=${this.describedBy ?? nothing}
203
204
  aria-required=${this.required && !this.readOnly ? 'true' : nothing}
204
205
  data-slotted=${this.markSource ? '' : nothing}
@@ -52,6 +52,7 @@ declare const HelixHeadlessSelect_base: (new (...args: any[]) => import("@fusion
52
52
  * @csspart listbox-hint - Help under the list.
53
53
  * @csspart listbox-items - The list itself.
54
54
  * @csspart listbox-label - The question, over the list.
55
+ * @csspart listbox-live - The inner list's `live`, the region a screen reader hears its empty and loading lines from.
55
56
  * @csspart listbox-loading - Shown while the options are still on their way.
56
57
  * @csspart listbox-search - The region holding the field that narrows the list.
57
58
  * @csspart listbox-search-field - The field itself.
@@ -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, HelixFormElement, hostAria, MixinControllerOpen, MixinControllerValue, MixinField, PopoverController, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, customElement, HelixFormElement, hostAria, MixinControllerOpen, MixinControllerValue, MixinField, 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 } from 'lit/decorators.js';
@@ -87,7 +87,12 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
87
87
  this.partNamed('trigger')?.focus();
88
88
  }
89
89
  sync() {
90
- this.internals.setFormValue(this.value === '' ? null : this.value);
90
+ if (this.multiple) {
91
+ reportValues(this.internals, this.name, this.value === '' ? [] : this.value.split(','));
92
+ }
93
+ else {
94
+ this.internals.setFormValue(this.value === '' ? null : this.value);
95
+ }
91
96
  this.reportRequired(this.value === '', 'Choose one to continue.', 'trigger');
92
97
  }
93
98
  willUpdate(changed) {
@@ -119,7 +124,7 @@ let HelixHeadlessSelect = class HelixHeadlessSelect extends MixinControllerOpen(
119
124
  part="listbox"
120
125
  exportparts="empty: listbox-empty, feedback: listbox-feedback, filter-icon: listbox-filter-icon,
121
126
  filter-mark: listbox-filter-mark, hint: listbox-hint, items: listbox-items,
122
- label: listbox-label, loading: listbox-loading, search: listbox-search,
127
+ label: listbox-label, live: listbox-live, loading: listbox-loading, search: listbox-search,
123
128
  search-field: listbox-search-field"
124
129
  .value=${this.value}
125
130
  ?multiple=${this.multiple}
@@ -85,10 +85,22 @@ export declare class HelixHeadlessSlider extends HelixHeadlessSlider_base {
85
85
  * The largest value the reader can choose.
86
86
  */
87
87
  max: number;
88
+ /**
89
+ * What the upper thumb of a range is called, after the slider's own label.
90
+ *
91
+ * **Named with the label rather than instead of it.** Each thumb was
92
+ * `aria-label="${label} maximum"`, which overrode the `<label>` and read the
93
+ * `label` string only, so a slider named by a slotted label or `aria-label`
94
+ * had thumbs called "minimum" and "maximum" and nothing else. The word is a
95
+ * property, like every other word a control speaks.
96
+ */
97
+ maximumLabel: string;
88
98
  /**
89
99
  * The smallest value the reader can choose.
90
100
  */
91
101
  min: number;
102
+ /** What the lower thumb of a range is called, after the slider's own label. */
103
+ minimumLabel: string;
92
104
  /**
93
105
  * Which way the track runs, `vertical` standing it on end.
94
106
  *
@@ -17,7 +17,9 @@ let HelixHeadlessSlider = class HelixHeadlessSlider extends MixinControllerValue
17
17
  this.markerLabels = false;
18
18
  this.markers = 0;
19
19
  this.max = 100;
20
+ this.maximumLabel = 'maximum';
20
21
  this.min = 0;
22
+ this.minimumLabel = 'minimum';
21
23
  this.range = false;
22
24
  this.showValue = false;
23
25
  this.handleInput = (event) => {
@@ -127,13 +129,17 @@ let HelixHeadlessSlider = class HelixHeadlessSlider extends MixinControllerValue
127
129
  max=${this.max}
128
130
  step=${this.step}
129
131
  .value=${String(at)}
130
- aria-label=${`${this.label} ${which === 'start' ? 'minimum' : 'maximum'}`}
132
+ aria-labelledby=${this.labeled ? `${this.labelId} ${which}-name` : `${which}-name`}
131
133
  aria-describedby=${this.describedBy ?? nothing}
132
134
  ?disabled=${this.isDisabled}
133
135
  @input=${this.handleInput}
134
136
  @change=${this.handleChange}
135
137
  />`;
136
138
  return html `${this.renderLabel()}
139
+ ${this.range
140
+ ? html `<span id="start-name" hidden>${this.minimumLabel}</span
141
+ ><span id="end-name" hidden>${this.maximumLabel}</span>`
142
+ : nothing}
137
143
  <div
138
144
  part="field"
139
145
  data-markers=${this.markerValues.length > 0 ? '' : nothing}
@@ -190,9 +196,15 @@ __decorate([
190
196
  __decorate([
191
197
  property({ type: Number })
192
198
  ], HelixHeadlessSlider.prototype, "max", void 0);
199
+ __decorate([
200
+ property({ attribute: 'maximum-label' })
201
+ ], HelixHeadlessSlider.prototype, "maximumLabel", void 0);
193
202
  __decorate([
194
203
  property({ type: Number })
195
204
  ], HelixHeadlessSlider.prototype, "min", void 0);
205
+ __decorate([
206
+ property({ attribute: 'minimum-label' })
207
+ ], HelixHeadlessSlider.prototype, "minimumLabel", void 0);
196
208
  __decorate([
197
209
  property({ reflect: true })
198
210
  ], HelixHeadlessSlider.prototype, "orientation", void 0);
@@ -55,28 +55,6 @@ import { type PropertyValues, type TemplateResult } from 'lit';
55
55
  * @cssproperty --splitter-position - Where the divider sits, as a percentage of the box.
56
56
  */
57
57
  export declare class HelixHeadlessSplitter extends HelixElement {
58
- /**
59
- * How much of a shut pane is still shown, as a percentage.
60
- *
61
- * Zero by default, which is a pane fully gone. A tab strip or a title bar
62
- * that should survive its own collapse says how much of itself to keep, and
63
- * only whoever put it there knows that, which is the same reason `min` is a
64
- * consumer's to set.
65
- */
66
- collapsedSize: number;
67
- /**
68
- * Where the divider sits, as a percentage of the whole.
69
- *
70
- * Reading gives where it is; writing declares it the consumer's, and
71
- * `default-position` seeds one this element owns. The same accessor pair
72
- * `Pagination.page` and the calendar's `month` carry.
73
- */
74
- get position(): number;
75
- set position(next: number);
76
- /**
77
- * Accessible name for the handle where two dividers cross.
78
- */
79
- cornerLabel: string;
80
58
  /**
81
59
  * Which pane is shut, if either.
82
60
  *
@@ -92,6 +70,28 @@ export declare class HelixHeadlessSplitter extends HelixElement {
92
70
  */
93
71
  get collapsed(): 'end' | 'start' | undefined;
94
72
  set collapsed(next: 'end' | 'start' | undefined);
73
+ /**
74
+ * What the divider says while a pane is shut, in place of a number.
75
+ *
76
+ * **A shut pane is off the scale the divider reports**, which is `min` to
77
+ * `max`, the sliver a drag keeps. The divider said a value outside its own
78
+ * range, 0 against a minimum of 20, which reads as broken rather than as
79
+ * shut. While shut it reports the whole 0 to 100 it sits on and says this.
80
+ */
81
+ collapsedLabel: string;
82
+ /**
83
+ * How much of a shut pane is still shown, as a percentage.
84
+ *
85
+ * Zero by default, which is a pane fully gone. A tab strip or a title bar
86
+ * that should survive its own collapse says how much of itself to keep, and
87
+ * only whoever put it there knows that, which is the same reason `min` is a
88
+ * consumer's to set.
89
+ */
90
+ collapsedSize: number;
91
+ /**
92
+ * Accessible name for the handle where two dividers cross.
93
+ */
94
+ cornerLabel: string;
95
95
  /**
96
96
  * Which pane starts shut, where nothing declared it.
97
97
  */
@@ -108,19 +108,6 @@ export declare class HelixHeadlessSplitter extends HelixElement {
108
108
  * Nearest it may come to the end, on the same terms as `min`.
109
109
  */
110
110
  max: number | string;
111
- /**
112
- * Either kind of bound as a percentage of the box.
113
- *
114
- * Measured rather than cached: a length is only meaningful against the size
115
- * the splitter is right now, and the drag that asks is already reading layout.
116
- * Falls back where there is nothing to measure, which is the server and an
117
- * element that is not displayed, so `aria-valuemin` is a number either way.
118
- */
119
- private toPercent;
120
- /** `min` as a percentage, whichever way it was written. */
121
- private get minPercent();
122
- /** `max` as a percentage, whichever way it was written. */
123
- private get maxPercent();
124
111
  /**
125
112
  * Nearest the divider may come to the start.
126
113
  *
@@ -141,6 +128,19 @@ export declare class HelixHeadlessSplitter extends HelixElement {
141
128
  * passes through.
142
129
  */
143
130
  min: number | string;
131
+ /**
132
+ * Either kind of bound as a percentage of the box.
133
+ *
134
+ * Measured rather than cached: a length is only meaningful against the size
135
+ * the splitter is right now, and the drag that asks is already reading layout.
136
+ * Falls back where there is nothing to measure, which is the server and an
137
+ * element that is not displayed, so `aria-valuemin` is a number either way.
138
+ */
139
+ private toPercent;
140
+ /** `min` as a percentage, whichever way it was written. */
141
+ private get minPercent();
142
+ /** `max` as a percentage, whichever way it was written. */
143
+ private get maxPercent();
144
144
  /**
145
145
  * Which way the panes are laid out.
146
146
  *
@@ -168,6 +168,15 @@ export declare class HelixHeadlessSplitter extends HelixElement {
168
168
  * has an honest answer.
169
169
  */
170
170
  orientation?: 'auto' | 'horizontal' | 'vertical';
171
+ /**
172
+ * Where the divider sits, as a percentage of the whole.
173
+ *
174
+ * Reading gives where it is; writing declares it the consumer's, and
175
+ * `default-position` seeds one this element owns. The same accessor pair
176
+ * `Pagination.page` and the calendar's `month` carry.
177
+ */
178
+ get position(): number;
179
+ set position(next: number);
171
180
  /**
172
181
  * How far one arrow press moves it, as a percentage.
173
182
  */
@@ -6,12 +6,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
6
6
  };
7
7
  var HelixHeadlessSplitter_1;
8
8
  import { capturePointer, closestInstance, customElement, HelixBeforeCollapseEvent, HelixBeforeResizeEvent, HelixElement, inlineStep, isRtl, requestChange, } from '@fusion.dev/helix-core';
9
- import { html } from 'lit';
9
+ import { html, nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
11
11
  const STACK_BELOW = 512;
12
12
  let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitter extends HelixElement {
13
13
  constructor() {
14
14
  super(...arguments);
15
+ this.collapsedLabel = 'Collapsed';
15
16
  this.collapsedSize = 0;
16
17
  this.cornerLabel = 'Resize both';
17
18
  this.defaultPosition = 50;
@@ -181,19 +182,6 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
181
182
  this.leaveSeparator(event);
182
183
  };
183
184
  }
184
- get position() {
185
- const shut = this.collapsed;
186
- if (shut) {
187
- return shut === 'start' ? this.sliver : 100 - this.sliver;
188
- }
189
- return this.clamp(this.positionState ?? this.defaultPosition);
190
- }
191
- set position(next) {
192
- const previous = this.position;
193
- this.positionState = next;
194
- this.reached = undefined;
195
- this.requestUpdate('position', previous);
196
- }
197
185
  get collapsed() {
198
186
  const held = this.collapsedState;
199
187
  if (held === undefined) {
@@ -236,6 +224,19 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
236
224
  get maxPercent() {
237
225
  return this.toPercent(this.max, 100);
238
226
  }
227
+ get position() {
228
+ const shut = this.collapsed;
229
+ if (shut) {
230
+ return shut === 'start' ? this.sliver : 100 - this.sliver;
231
+ }
232
+ return this.clamp(this.positionState ?? this.defaultPosition);
233
+ }
234
+ set position(next) {
235
+ const previous = this.position;
236
+ this.positionState = next;
237
+ this.reached = undefined;
238
+ this.requestUpdate('position', previous);
239
+ }
239
240
  get showing() {
240
241
  return this.reached === undefined ? this.position : this.clamp(this.reached);
241
242
  }
@@ -437,9 +438,10 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
437
438
  tabindex="0"
438
439
  aria-label=${this.label}
439
440
  aria-orientation=${this.vertical ? 'horizontal' : 'vertical'}
440
- aria-valuemax=${this.clamp(this.maxPercent)}
441
- aria-valuemin=${this.clamp(this.minPercent)}
441
+ aria-valuemax=${this.collapsed ? 100 : this.clamp(this.maxPercent)}
442
+ aria-valuemin=${this.collapsed ? 0 : this.clamp(this.minPercent)}
442
443
  aria-valuenow=${Math.round(position)}
444
+ aria-valuetext=${this.collapsed ? this.collapsedLabel : nothing}
443
445
  ?data-dragging=${this.dragging}
444
446
  ?data-flush=${this.flush}
445
447
  @dblclick=${this.handleDoubleClick}
@@ -472,18 +474,18 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
472
474
  ></div>`)}`;
473
475
  }
474
476
  };
477
+ __decorate([
478
+ property()
479
+ ], HelixHeadlessSplitter.prototype, "collapsed", null);
480
+ __decorate([
481
+ property({ attribute: 'collapsed-label' })
482
+ ], HelixHeadlessSplitter.prototype, "collapsedLabel", void 0);
475
483
  __decorate([
476
484
  property({ attribute: 'collapsed-size', type: Number })
477
485
  ], HelixHeadlessSplitter.prototype, "collapsedSize", void 0);
478
- __decorate([
479
- property({ type: Number })
480
- ], HelixHeadlessSplitter.prototype, "position", null);
481
486
  __decorate([
482
487
  property({ attribute: 'corner-label' })
483
488
  ], HelixHeadlessSplitter.prototype, "cornerLabel", void 0);
484
- __decorate([
485
- property()
486
- ], HelixHeadlessSplitter.prototype, "collapsed", null);
487
489
  __decorate([
488
490
  property({ attribute: 'default-collapsed' })
489
491
  ], HelixHeadlessSplitter.prototype, "defaultCollapsed", void 0);
@@ -502,6 +504,9 @@ __decorate([
502
504
  __decorate([
503
505
  property({ reflect: true })
504
506
  ], HelixHeadlessSplitter.prototype, "orientation", void 0);
507
+ __decorate([
508
+ property({ type: Number })
509
+ ], HelixHeadlessSplitter.prototype, "position", null);
505
510
  __decorate([
506
511
  property({ type: Number })
507
512
  ], HelixHeadlessSplitter.prototype, "step", void 0);
@@ -30,6 +30,7 @@ let HelixHeadlessSwitch = class HelixHeadlessSwitch extends MixinControllerCheck
30
30
  this.reportRequired(!this.checked, 'Turn this on to continue.', 'control');
31
31
  }
32
32
  formResetCallback() {
33
+ super.formResetCallback();
33
34
  this.resetChecked();
34
35
  }
35
36
  updated(changed) {
@@ -131,6 +131,14 @@ export declare class HelixHeadlessTableColumn extends HelixElement {
131
131
  * such a column is never sortable however it is marked.
132
132
  */
133
133
  field: string;
134
+ /**
135
+ * What the grip that moves the column is called, with the heading's words as
136
+ * `{name}`.
137
+ *
138
+ * **Every word a column speaks is a property**, so a table in another
139
+ * language hears its own rather than English around its own headings.
140
+ */
141
+ moveLabel: string;
134
142
  /**
135
143
  * Whether a reader may change this column's width.
136
144
  *
@@ -140,6 +148,11 @@ export declare class HelixHeadlessTableColumn extends HelixElement {
140
148
  * stores the widths can take the decision.
141
149
  */
142
150
  resizable: boolean;
151
+ /**
152
+ * What the separator that resizes the column is called, with the heading's
153
+ * words as `{name}`.
154
+ */
155
+ resizeLabel: string;
143
156
  /**
144
157
  * Whether a reader may reorder the set by this column.
145
158
  *
@@ -212,6 +225,10 @@ export declare class HelixHeadlessTableColumn extends HelixElement {
212
225
  * the overflow either way, that being paint, and gets the honest track list.
213
226
  */
214
227
  width: string;
228
+ /**
229
+ * How the separator reads out the column's width, with `{width}` filled in.
230
+ */
231
+ widthLabel: string;
215
232
  /**
216
233
  * @internal Read by a parent to identify its children across the light DOM,
217
234
  * which is cheaper than `instanceof` and is why this is public rather than
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
7
  var HelixHeadlessTableColumn_1;
8
- import { customElement, HelixBeforeResizeEvent, HelixElement, hostAria, inlineStep, isRtl, requestChange, } from '@fusion.dev/helix-core';
8
+ import { customElement, fillTemplate, HelixBeforeResizeEvent, HelixElement, hostAria, inlineStep, isRtl, requestChange, } from '@fusion.dev/helix-core';
9
9
  import { dotsThreeVertical } from '@fusion.dev/helix-icons';
10
10
  import { html, nothing } from 'lit';
11
11
  import { property, state } from 'lit/decorators.js';
@@ -34,9 +34,12 @@ let HelixHeadlessTableColumn = class HelixHeadlessTableColumn extends HelixEleme
34
34
  this.cell = undefined;
35
35
  this.compare = undefined;
36
36
  this.field = '';
37
+ this.moveLabel = 'Move {name}';
37
38
  this.resizable = false;
39
+ this.resizeLabel = 'Resize {name}';
38
40
  this.sortable = false;
39
41
  this.width = '';
42
+ this.widthLabel = '{width} pixels';
40
43
  this.isTableColumn = true;
41
44
  this.sorted = undefined;
42
45
  this.movable = false;
@@ -165,7 +168,7 @@ let HelixHeadlessTableColumn = class HelixHeadlessTableColumn extends HelixEleme
165
168
  render() {
166
169
  const name = this.name;
167
170
  return html `<span part="column">${this.movable
168
- ? html `<button part="grip" type="button" aria-label=${name ? `Move ${name}` : 'Move column'}>
171
+ ? html `<button part="grip" type="button" aria-label=${fillTemplate(this.moveLabel, { name: name || 'column' })}>
169
172
  <svg aria-hidden="true" fill="currentColor" part="grip-mark" viewBox=${dotsThreeVertical.viewBox}>
170
173
  ${unsafeSVG(dotsThreeVertical.content)}
171
174
  </svg>
@@ -177,12 +180,12 @@ let HelixHeadlessTableColumn = class HelixHeadlessTableColumn extends HelixEleme
177
180
  part="resizer"
178
181
  role="separator"
179
182
  tabindex="0"
180
- aria-label=${name ? `Resize ${name}` : 'Resize column'}
183
+ aria-label=${fillTemplate(this.resizeLabel, { name: name || 'column' })}
181
184
  aria-orientation="vertical"
182
185
  aria-valuemin=${HelixHeadlessTableColumn_1.NARROWEST}
183
186
  aria-valuemax="4096"
184
187
  aria-valuenow=${Math.max(HelixHeadlessTableColumn_1.NARROWEST, this.drawn)}
185
- aria-valuetext=${`${this.drawn} pixels`}
188
+ aria-valuetext=${fillTemplate(this.widthLabel, { width: this.drawn })}
186
189
  @keydown=${this.handleResizeKey}
187
190
  @pointerdown=${this.handleResizeStart}
188
191
  @pointermove=${this.handleResizeMove}
@@ -201,9 +204,15 @@ __decorate([
201
204
  __decorate([
202
205
  property()
203
206
  ], HelixHeadlessTableColumn.prototype, "field", void 0);
207
+ __decorate([
208
+ property({ attribute: 'move-label' })
209
+ ], HelixHeadlessTableColumn.prototype, "moveLabel", void 0);
204
210
  __decorate([
205
211
  property({ type: Boolean })
206
212
  ], HelixHeadlessTableColumn.prototype, "resizable", void 0);
213
+ __decorate([
214
+ property({ attribute: 'resize-label' })
215
+ ], HelixHeadlessTableColumn.prototype, "resizeLabel", void 0);
207
216
  __decorate([
208
217
  property({ reflect: true, type: Boolean })
209
218
  ], HelixHeadlessTableColumn.prototype, "sortable", void 0);
@@ -213,6 +222,9 @@ __decorate([
213
222
  __decorate([
214
223
  property()
215
224
  ], HelixHeadlessTableColumn.prototype, "width", void 0);
225
+ __decorate([
226
+ property({ attribute: 'width-label' })
227
+ ], HelixHeadlessTableColumn.prototype, "widthLabel", void 0);
216
228
  __decorate([
217
229
  state()
218
230
  ], HelixHeadlessTableColumn.prototype, "sorted", void 0);