@fusion.dev/helix-headless 0.149.1 → 0.151.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.
- package/custom-elements.json +1211 -110
- package/dist/area-chart/root/area-chart-root.d.ts +36 -0
- package/dist/area-chart/root/area-chart-root.js +17 -2
- package/dist/bar-chart/root/bar-chart-root.d.ts +28 -4
- package/dist/bar-chart/root/bar-chart-root.js +17 -4
- package/dist/button/root/button-root.d.ts +5 -0
- package/dist/button/root/button-root.js +3 -0
- package/dist/callout/root/callout-root.d.ts +20 -0
- package/dist/callout/root/callout-root.js +19 -4
- package/dist/chat/composer/chat-composer.d.ts +30 -0
- package/dist/chat/composer/chat-composer.js +47 -2
- package/dist/chat/root/chat-root.d.ts +10 -0
- package/dist/chat/root/chat-root.js +14 -0
- package/dist/color-input/root/color-input-root.d.ts +1 -0
- package/dist/color-picker/root/color-picker-root.js +1 -0
- package/dist/combobox/root/combobox-root.d.ts +12 -1
- package/dist/combobox/root/combobox-root.js +8 -0
- package/dist/copy-button/root/copy-button-root.d.ts +4 -3
- package/dist/copy-button/root/copy-button-root.js +5 -1
- package/dist/data-table/root/data-table-root.d.ts +34 -2
- package/dist/data-table/root/data-table-root.js +63 -2
- package/dist/date-input/root/date-input-root.d.ts +1 -0
- package/dist/divider/root/divider-root.d.ts +8 -6
- package/dist/divider/root/divider-root.js +10 -2
- package/dist/element-events.generated.js +5 -1
- package/dist/filter-input/chip/filter-chip.d.ts +2 -1
- package/dist/filter-input/root/filter-input-root.d.ts +5 -0
- package/dist/filter-input/root/filter-input-root.js +7 -0
- package/dist/kbd/root/kbd-root.d.ts +7 -1
- package/dist/kbd/root/kbd-root.js +8 -4
- package/dist/line-chart/root/line-chart-root.d.ts +36 -0
- package/dist/line-chart/root/line-chart-root.js +15 -2
- package/dist/number-input/root/number-input-root.d.ts +6 -0
- package/dist/number-input/root/number-input-root.js +14 -3
- package/dist/option/root/option-root.d.ts +17 -8
- package/dist/option/root/option-root.js +18 -4
- package/dist/radio/group/radio-group.d.ts +8 -1
- package/dist/radio/group/radio-group.js +15 -1
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +18 -0
- package/dist/scatter-chart/root/scatter-chart-root.js +38 -15
- package/dist/slider/root/slider-root.d.ts +8 -0
- package/dist/slider/root/slider-root.js +6 -3
- package/dist/table/column/table-column.js +3 -2
- package/dist/table/grid-controller.d.ts +14 -2
- package/dist/table/grid-controller.js +27 -1
- package/dist/table/root/table-root.d.ts +30 -4
- package/dist/table/root/table-root.js +45 -7
- package/dist/table/row/table-row.d.ts +12 -2
- package/dist/table/row/table-row.js +8 -2
- package/dist/tag/group/tag-group.d.ts +22 -1
- package/dist/tag/group/tag-group.js +63 -3
- package/dist/tag/root/tag-root.d.ts +9 -0
- package/dist/tag/root/tag-root.js +5 -1
- package/dist/time-input/root/time-input-root.d.ts +1 -0
- package/dist/toggle/group/toggle-group.d.ts +6 -0
- package/dist/toggle/group/toggle-group.js +16 -1
- package/dist/toggle/root/toggle-root.d.ts +21 -3
- package/dist/toggle/root/toggle-root.js +22 -5
- package/dist/video/root/video-root.d.ts +6 -0
- package/dist/video/root/video-root.js +5 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +4 -0
- package/dist/video-playlist/root/video-playlist-root.js +4 -1
- package/dist/virtual-list/root/virtual-list-root.d.ts +23 -1
- package/dist/virtual-list/root/virtual-list-root.js +21 -2
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +808 -156
- package/types/vue.d.ts +223 -59
- package/types/words.d.ts +4 -2
|
@@ -31,6 +31,9 @@ declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusi
|
|
|
31
31
|
* | Escape | Closes the list and puts the chosen words back. On a closed field, a second Escape clears a single choice. |
|
|
32
32
|
* | Tab | Closes the list and moves on. |
|
|
33
33
|
* | Backspace | With `multiple`, on an empty field, removes the last tag. |
|
|
34
|
+
* | Left | With `multiple`, with the caret at the start of the text, moves to the last tag's remove button. Right on a right-to-left page. |
|
|
35
|
+
* | Left, Right on a tag | Move between the tags, and past the last back to the text. |
|
|
36
|
+
* | Delete, Backspace on a tag | Removes the tag. |
|
|
34
37
|
* | Space, Home, End, letters | Edit the text. |
|
|
35
38
|
*
|
|
36
39
|
* **ARIA.** The input is the `combobox`, named by the label, with
|
|
@@ -46,7 +49,8 @@ declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusi
|
|
|
46
49
|
* Set `autocomplete` to let a browser's autofill choose an option.
|
|
47
50
|
*
|
|
48
51
|
* With `multiple`, each chosen option is a tag in the field with its own remove
|
|
49
|
-
* control. The
|
|
52
|
+
* control. The text is the field's one tab stop, and the arrow keys reach the
|
|
53
|
+
* tags from it. The panel stays open and the filter clears after each choice, so the
|
|
50
54
|
* next choice starts from the whole list.
|
|
51
55
|
*
|
|
52
56
|
* With `creatable`, the combobox offers a create row and fires `helix-create`.
|
|
@@ -584,6 +588,13 @@ export declare class HelixHeadlessCombobox extends HelixHeadlessCombobox_base {
|
|
|
584
588
|
* tag does.
|
|
585
589
|
*/
|
|
586
590
|
protected removeLastToken(): void;
|
|
591
|
+
/** The tags, which the arrow keys reach from the text. */
|
|
592
|
+
protected tokenElements(): HTMLElement[];
|
|
593
|
+
/**
|
|
594
|
+
* Focus goes to the text field, the one tab stop, and never to a tag's remove
|
|
595
|
+
* button ahead of it, where Enter or Space would take a choice away.
|
|
596
|
+
*/
|
|
597
|
+
protected get focusTarget(): HTMLElement | null;
|
|
587
598
|
/** One tag asking to be taken out of the set. */
|
|
588
599
|
private readonly handleDismiss;
|
|
589
600
|
/**
|
|
@@ -446,6 +446,12 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
446
446
|
this.drop(last);
|
|
447
447
|
}
|
|
448
448
|
}
|
|
449
|
+
tokenElements() {
|
|
450
|
+
return [...this.renderRoot.querySelectorAll('[part="tag"]')];
|
|
451
|
+
}
|
|
452
|
+
get focusTarget() {
|
|
453
|
+
return this.partNamed('control') ?? super.focusTarget;
|
|
454
|
+
}
|
|
449
455
|
sync() {
|
|
450
456
|
if (this.multiple) {
|
|
451
457
|
reportValues(this.internals, this.name, this.value === '' ? [] : this.value.split(','));
|
|
@@ -574,6 +580,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
574
580
|
data-value=${option.value}
|
|
575
581
|
dismiss-label=${formatWords(this, 'removeLabel', { name: option.text })}
|
|
576
582
|
?dismissible=${!this.isDisabled && !this.readOnly}
|
|
583
|
+
.dismissTabStop=${false}
|
|
577
584
|
@helix-dismiss=${this.handleDismiss}
|
|
578
585
|
>${option.text}</${this.tag('tag')}
|
|
579
586
|
>`;
|
|
@@ -619,6 +626,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
619
626
|
aria-expanded=${this.open ? 'true' : 'false'}
|
|
620
627
|
aria-describedby=${this.describedBy ?? nothing}
|
|
621
628
|
aria-invalid=${this.invalidity ?? nothing}
|
|
629
|
+
aria-required=${this.required ? 'true' : nothing}
|
|
622
630
|
placeholder=${(this.chosen.length > 0 || this.unresolved ? '' : this.placeholder) || nothing}
|
|
623
631
|
?disabled=${this.isDisabled}
|
|
624
632
|
?readonly=${this.readOnly}
|
|
@@ -29,8 +29,9 @@ import '../../tooltip/index.js';
|
|
|
29
29
|
* **Keyboard.** Enter and Space copy, as they press a native button.
|
|
30
30
|
*
|
|
31
31
|
* The button is named `label`, or the host's `aria-label`, and its name
|
|
32
|
-
* changes to `copied-label` or `error-label` for the moment after a press
|
|
33
|
-
*
|
|
32
|
+
* changes to `copied-label` or `error-label` for the moment after a press. The
|
|
33
|
+
* same words are said in a live region, so a screen reader hears the result,
|
|
34
|
+
* and the tooltip shows them.
|
|
34
35
|
*
|
|
35
36
|
* @since 0.1.0
|
|
36
37
|
* @status stable
|
|
@@ -46,7 +47,7 @@ import '../../tooltip/index.js';
|
|
|
46
47
|
* @event {HelixCopyErrorEvent} helix-copy-error - Fired when a press put nothing on the clipboard: the browser did not allow the write, or there was nothing to copy.
|
|
47
48
|
*
|
|
48
49
|
* @csspart button - The inner button.
|
|
49
|
-
* @csspart live - The live region that says `pending-label` when the button becomes pending under focus. It is rendered from the first time
|
|
50
|
+
* @csspart live - The live region that says `copied-label` or `error-label` after a press, and `pending-label` when the button becomes pending under focus. It is rendered from the first time it says anything.
|
|
50
51
|
* @csspart mark - The clipboard icon, and the confirmation icon that replaces it.
|
|
51
52
|
* @csspart spinner - The ring a pending button turns, an empty element the styled button draws over the icon. It is rendered only while the button is pending.
|
|
52
53
|
* @csspart tooltip - The tooltip bubble, forwarded from the tooltip inside the button.
|
|
@@ -37,7 +37,11 @@ let HelixHeadlessCopyButton = class HelixHeadlessCopyButton extends HelixHeadles
|
|
|
37
37
|
const copying = this.clipboard.copy(this.text);
|
|
38
38
|
this.announcePress(event);
|
|
39
39
|
const wrote = await copying;
|
|
40
|
-
if (!
|
|
40
|
+
if (!this.isConnected) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
this.sayStatus(wrote ? this.copiedLabel : this.errorLabel);
|
|
44
|
+
if (!wrote) {
|
|
41
45
|
this.dispatchEvent(new HelixCopyErrorEvent());
|
|
42
46
|
}
|
|
43
47
|
};
|
|
@@ -40,6 +40,10 @@ declare const HelixHeadlessDataTable_base: (new (...args: any[]) => import("@fus
|
|
|
40
40
|
* and shows a dash while only some are chosen.
|
|
41
41
|
* - Shift with a press on a checkbox selects every row between it and the row
|
|
42
42
|
* last chosen.
|
|
43
|
+
* - `selection-behavior="replace"` makes a press or a move select the row
|
|
44
|
+
* alone, as a file list does. Control or Command with a press adds or takes
|
|
45
|
+
* out one row, and Shift with a press selects every row from the one last
|
|
46
|
+
* chosen.
|
|
43
47
|
*
|
|
44
48
|
* To act on a single row, such as opening it, put a link or a button in a cell.
|
|
45
49
|
*
|
|
@@ -56,7 +60,8 @@ declare const HelixHeadlessDataTable_base: (new (...args: any[]) => import("@fus
|
|
|
56
60
|
* | Enter, F2 | Moves into the cell's controls. Escape moves back to the cell, and Tab moves between the controls of one cell. |
|
|
57
61
|
* | Enter, Space on a sortable heading | Sorts by the column. |
|
|
58
62
|
* | Enter, Space on the `load-more` row | Sends `helix-load-more`. |
|
|
59
|
-
* | Space on a row | Selects the row, in a `selectable` table. |
|
|
63
|
+
* | Space on a row | Selects the row, in a `selectable` table. Under `selection-behavior="replace"`, selects it alone, and Control or Command with Space adds or takes out the row. |
|
|
64
|
+
* | Down, Up, Page Down, Page Up under `selection-behavior="replace"` | Selects the row it moves to alone. Control or Command with the key moves without selecting. |
|
|
60
65
|
* | Shift with Down or Up | Selects the rows it moves across, in a `selectable` table. |
|
|
61
66
|
* | Shift with Space | Selects every row from the one last chosen, in a `selectable` table. |
|
|
62
67
|
* | Control or Command with A | Selects every row, in a `selectable` table. |
|
|
@@ -123,7 +128,9 @@ declare const HelixHeadlessDataTable_base: (new (...args: any[]) => import("@fus
|
|
|
123
128
|
* @documentation https://fusion.dev/helix/components/data-table
|
|
124
129
|
*
|
|
125
130
|
* @slot - The columns, as `TableColumn` elements.
|
|
131
|
+
* @slot empty - Content shown when there are no rows to show and none are loading, such as a picture and a link. Falls back to `empty-text`, which the live region still says.
|
|
126
132
|
* @slot footer - Content below the grid. It replaces the built-in pagination.
|
|
133
|
+
* @slot loading - Content shown while the rows load, such as a spinner. Falls back to `loading-text`, which the live region still says.
|
|
127
134
|
* @slot toolbar - Content above the grid, such as a search field or actions.
|
|
128
135
|
*
|
|
129
136
|
* @event {HelixActivateEvent} helix-activate - Fired after the page changes, with the new page as a string in `detail.value`.
|
|
@@ -216,6 +223,8 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
|
|
|
216
223
|
* `registerWords('de', { 'helix-data-table': { nextLabel: 'Nächste Seite' } })`.
|
|
217
224
|
*/
|
|
218
225
|
static words: string;
|
|
226
|
+
/** The empty and loading lines are the `empty` and `loading` slots. */
|
|
227
|
+
protected statusSlots: boolean;
|
|
219
228
|
/**
|
|
220
229
|
* The word for an ascending sort, in a `sorted-label` that writes `{order}`.
|
|
221
230
|
*
|
|
@@ -490,6 +499,15 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
|
|
|
490
499
|
* {# wybranych} other {# wybranego}}`.
|
|
491
500
|
*/
|
|
492
501
|
selectedLabel: string;
|
|
502
|
+
/**
|
|
503
|
+
* What a key or a press on a row does to the rows already selected, in a
|
|
504
|
+
* `selectable` table. `toggle`, the default, keeps them: Space adds or takes
|
|
505
|
+
* out the row. `replace` selects the row alone, as a file list does: Down and
|
|
506
|
+
* Up carry the selection with them, and a press on a row selects it. Control
|
|
507
|
+
* or Command with a press or Space adds or takes out one row, and with a move
|
|
508
|
+
* goes without selecting. The checkboxes add or take out one row either way.
|
|
509
|
+
*/
|
|
510
|
+
selectionBehavior: 'replace' | 'toggle';
|
|
493
511
|
/**
|
|
494
512
|
* The name of a row's checkbox. `{row}` is replaced with the row's value in
|
|
495
513
|
* the first column that has a field, or with its key.
|
|
@@ -954,7 +972,7 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
|
|
|
954
972
|
*/
|
|
955
973
|
toggleSort(field: string): boolean;
|
|
956
974
|
/**
|
|
957
|
-
* The columns into the header row, everything else into the
|
|
975
|
+
* The columns into the header row, everything else into the slot it names.
|
|
958
976
|
*
|
|
959
977
|
* Manual assignment, so a consumer's own markup is never written to.
|
|
960
978
|
*/
|
|
@@ -1124,6 +1142,20 @@ export declare class HelixHeadlessDataTable extends HelixHeadlessDataTable_base
|
|
|
1124
1142
|
* request carries only the state it asks for.
|
|
1125
1143
|
*/
|
|
1126
1144
|
private readonly notePress;
|
|
1145
|
+
/** Whether a press or a move on a row selects it alone. */
|
|
1146
|
+
private get replaces();
|
|
1147
|
+
/**
|
|
1148
|
+
* Selects the row at `row` on the page alone, and makes it where a range
|
|
1149
|
+
* runs from. Asks nothing where it is already the only one selected.
|
|
1150
|
+
*/
|
|
1151
|
+
private chooseOnly;
|
|
1152
|
+
/**
|
|
1153
|
+
* A press on a row under `selection-behavior="replace"`: it selects the row
|
|
1154
|
+
* alone, Control or Command adds or takes out the row, and Shift selects
|
|
1155
|
+
* every row from the one last chosen. A press on a control in a cell, or on
|
|
1156
|
+
* the checkbox or grip column, is the control's.
|
|
1157
|
+
*/
|
|
1158
|
+
private readonly handleRowClick;
|
|
1127
1159
|
/**
|
|
1128
1160
|
* A click on a sortable heading, anywhere but its grip or its edge.
|
|
1129
1161
|
*
|
|
@@ -30,6 +30,7 @@ const isControl = (element) => element.matches(CONTROL) || element.shadowRoot?.d
|
|
|
30
30
|
let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollection(HelixElement) {
|
|
31
31
|
constructor() {
|
|
32
32
|
super(...arguments);
|
|
33
|
+
this.statusSlots = true;
|
|
33
34
|
this.ascendingLabel = 'ascending';
|
|
34
35
|
this.canceledLabel = 'Canceled';
|
|
35
36
|
this.defaultExpanded = '';
|
|
@@ -64,6 +65,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
64
65
|
this.selectable = false;
|
|
65
66
|
this.selectAllLabel = 'Select every row';
|
|
66
67
|
this.selectedLabel = '{count} selected';
|
|
68
|
+
this.selectionBehavior = 'toggle';
|
|
67
69
|
this.selectRowLabel = 'Select {row}';
|
|
68
70
|
this.sortedLabel = '{direction, select, ascending {Sorted by {column}, ascending} descending {Sorted by {column}, descending} other {Sorted by {column}}}';
|
|
69
71
|
this.total = 0;
|
|
@@ -178,6 +180,30 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
178
180
|
this.notePress = (event) => {
|
|
179
181
|
this.shiftPressed = event.shiftKey;
|
|
180
182
|
};
|
|
183
|
+
this.handleRowClick = (event) => {
|
|
184
|
+
if (!this.replaces || event.defaultPrevented) {
|
|
185
|
+
return;
|
|
186
|
+
}
|
|
187
|
+
const place = this.placeOf(event);
|
|
188
|
+
if (!place || place.row < 0 || place.row >= this.drawnPage.length || place.column < this.lead) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const origin = event.composedPath()[0];
|
|
192
|
+
if (origin instanceof Node && this.controlsIn(place).some((one) => deepContains(one, origin))) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
if (event.shiftKey && this.anchorKey !== undefined) {
|
|
196
|
+
this.selectRange(place.row);
|
|
197
|
+
return;
|
|
198
|
+
}
|
|
199
|
+
if (event.ctrlKey || event.metaKey) {
|
|
200
|
+
const data = this.drawnPage[place.row];
|
|
201
|
+
const key = this.keyOf(data, this.rowIndex(place.row) - 2);
|
|
202
|
+
this.chooseRow(key, !this.chosen.has(key));
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
this.chooseOnly(place.row);
|
|
206
|
+
};
|
|
181
207
|
this.handleHeadClick = (event) => {
|
|
182
208
|
if (this.partIn(event, 'grip') || this.partIn(event, 'resizer')) {
|
|
183
209
|
return;
|
|
@@ -251,14 +277,22 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
251
277
|
}
|
|
252
278
|
const { column, row } = to;
|
|
253
279
|
event.preventDefault();
|
|
280
|
+
const onRow = row >= 0 && row < this.drawnPage.length;
|
|
254
281
|
if (event.shiftKey &&
|
|
255
282
|
this.selectable &&
|
|
256
283
|
(event.key === 'ArrowUp' || event.key === 'ArrowDown') &&
|
|
257
284
|
place.row >= 0 &&
|
|
258
|
-
|
|
259
|
-
row < this.drawnPage.length) {
|
|
285
|
+
onRow) {
|
|
260
286
|
this.selectRange(row, place.row);
|
|
261
287
|
}
|
|
288
|
+
else if (this.replaces &&
|
|
289
|
+
onRow &&
|
|
290
|
+
row !== place.row &&
|
|
291
|
+
!event.shiftKey &&
|
|
292
|
+
!event.ctrlKey &&
|
|
293
|
+
!event.metaKey) {
|
|
294
|
+
this.chooseOnly(row);
|
|
295
|
+
}
|
|
262
296
|
if (row !== place.row || column !== place.column) {
|
|
263
297
|
this.moveTo(row, column);
|
|
264
298
|
}
|
|
@@ -878,6 +912,8 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
878
912
|
for (const [name, wanted] of [
|
|
879
913
|
['toolbar', true],
|
|
880
914
|
['footer', true],
|
|
915
|
+
['empty', true],
|
|
916
|
+
['loading', true],
|
|
881
917
|
]) {
|
|
882
918
|
const slot = root.querySelector(`slot[name="${name}"]`);
|
|
883
919
|
if (slot?.assign && wanted) {
|
|
@@ -1201,6 +1237,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
1201
1237
|
connectedCallback() {
|
|
1202
1238
|
super.connectedCallback();
|
|
1203
1239
|
this.addEventListener('click', this.handleHeadClick);
|
|
1240
|
+
this.addEventListener('click', this.handleRowClick);
|
|
1204
1241
|
this.addEventListener('pointerdown', this.notePress, true);
|
|
1205
1242
|
this.addEventListener('keydown', this.notePress, true);
|
|
1206
1243
|
this.addEventListener('focusin', this.handleFocusIn);
|
|
@@ -1212,6 +1249,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
1212
1249
|
disconnectedCallback() {
|
|
1213
1250
|
super.disconnectedCallback();
|
|
1214
1251
|
this.removeEventListener('click', this.handleHeadClick);
|
|
1252
|
+
this.removeEventListener('click', this.handleRowClick);
|
|
1215
1253
|
this.removeEventListener('pointerdown', this.notePress, true);
|
|
1216
1254
|
this.removeEventListener('keydown', this.notePress, true);
|
|
1217
1255
|
this.removeEventListener('focusin', this.handleFocusIn);
|
|
@@ -1220,6 +1258,22 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
1220
1258
|
this.removeEventListener('keydown', this.handleGripKey);
|
|
1221
1259
|
this.removeEventListener('helix-before-resize', this.handleResize);
|
|
1222
1260
|
}
|
|
1261
|
+
get replaces() {
|
|
1262
|
+
return this.selectable && this.selectionBehavior === 'replace';
|
|
1263
|
+
}
|
|
1264
|
+
chooseOnly(row) {
|
|
1265
|
+
const data = this.drawnPage[row];
|
|
1266
|
+
if (!data) {
|
|
1267
|
+
return;
|
|
1268
|
+
}
|
|
1269
|
+
const key = this.keyOf(data, this.rowIndex(row) - 2);
|
|
1270
|
+
this.anchorKey = key;
|
|
1271
|
+
const now = this.chosen;
|
|
1272
|
+
if (now.size === 1 && now.has(key)) {
|
|
1273
|
+
return;
|
|
1274
|
+
}
|
|
1275
|
+
this.requestSelected(new Set([key]));
|
|
1276
|
+
}
|
|
1223
1277
|
cellAt(row, column) {
|
|
1224
1278
|
const offset = this.lead;
|
|
1225
1279
|
if (row === -1) {
|
|
@@ -1402,6 +1456,10 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
1402
1456
|
event.preventDefault();
|
|
1403
1457
|
this.selectRange(place.row);
|
|
1404
1458
|
}
|
|
1459
|
+
else if (this.replaces && row && !event.ctrlKey && !event.metaKey) {
|
|
1460
|
+
event.preventDefault();
|
|
1461
|
+
this.chooseOnly(place.row);
|
|
1462
|
+
}
|
|
1405
1463
|
else if (this.selectable && row) {
|
|
1406
1464
|
event.preventDefault();
|
|
1407
1465
|
const key = this.keyOf(row, this.rowIndex(place.row) - 2);
|
|
@@ -1595,6 +1653,9 @@ __decorate([
|
|
|
1595
1653
|
words,
|
|
1596
1654
|
property({ attribute: 'selected-label' })
|
|
1597
1655
|
], HelixHeadlessDataTable.prototype, "selectedLabel", void 0);
|
|
1656
|
+
__decorate([
|
|
1657
|
+
property({ attribute: 'selection-behavior' })
|
|
1658
|
+
], HelixHeadlessDataTable.prototype, "selectionBehavior", void 0);
|
|
1598
1659
|
__decorate([
|
|
1599
1660
|
words,
|
|
1600
1661
|
property({ attribute: 'select-row-label' })
|
|
@@ -35,6 +35,7 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
|
|
|
35
35
|
*
|
|
36
36
|
* @slot feedback - The error message under the field.
|
|
37
37
|
* @slot hint - The help text under the field.
|
|
38
|
+
* @slot label - The label, for content richer than the `label` text.
|
|
38
39
|
* @slot next-icon - The icon on the calendar's next month control.
|
|
39
40
|
* @slot panel-footer - Content in the panel under the calendar, such as a note or an action.
|
|
40
41
|
* @slot panel-header - Content in the panel above the calendar, such as a heading or a shortcut.
|
|
@@ -12,9 +12,10 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
12
12
|
* **The line is a separator**, as `<hr>` is, and as Radix Separator, React
|
|
13
13
|
* Aria Separator, and Web Awesome's divider are. It is named by any content
|
|
14
14
|
* set into it, so a screen reader says "Or, separator" where you wrote "Or" on
|
|
15
|
-
* the line
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* the line, and the words are read once, as that name. Set words into a
|
|
16
|
+
* separator and no controls, which are hidden with them. Set `decorative` on
|
|
17
|
+
* a rule that separates nothing, such as one under a heading or between the
|
|
18
|
+
* facts of a byline, and it leaves the accessibility tree.
|
|
18
19
|
*
|
|
19
20
|
* Use `orientation="vertical"` between items on one line. A vertical divider
|
|
20
21
|
* stretches to fit its flex parent and sets no height of its own.
|
|
@@ -44,9 +45,10 @@ export declare class HelixHeadlessDivider extends HelixElement {
|
|
|
44
45
|
* Whether screen readers announce the line as a separator, which they now do
|
|
45
46
|
* by default.
|
|
46
47
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
48
|
+
* @deprecated Remove it: a divider is a separator unless `decorative` is
|
|
49
|
+
* set. It dates from when the line was decorative by default, and it is
|
|
50
|
+
* still read and wins over `decorative`, so a divider written with it stays
|
|
51
|
+
* a separator.
|
|
50
52
|
*/
|
|
51
53
|
announced: boolean;
|
|
52
54
|
/**
|
|
@@ -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, HelixElement, markRegion, toolbarAround, toolbarAxis, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, HelixElement, markRegion, reportRuntime, toolbarAround, toolbarAxis, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessDivider = class HelixHeadlessDivider extends HelixElement {
|
|
@@ -38,6 +38,14 @@ let HelixHeadlessDivider = class HelixHeadlessDivider extends HelixElement {
|
|
|
38
38
|
updated(changed) {
|
|
39
39
|
super.updated(changed);
|
|
40
40
|
this.markEmpty();
|
|
41
|
+
if (changed.has('announced') && this.announced && changed.get('announced') === undefined) {
|
|
42
|
+
reportRuntime({
|
|
43
|
+
kind: 'deprecated',
|
|
44
|
+
message: `<${this.localName} announced> is deprecated: remove it. A divider is a separator ` +
|
|
45
|
+
'unless `decorative` is set.',
|
|
46
|
+
tag: this.localName,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
41
49
|
}
|
|
42
50
|
render() {
|
|
43
51
|
const separator = this.announced || !this.decorative;
|
|
@@ -47,7 +55,7 @@ let HelixHeadlessDivider = class HelixHeadlessDivider extends HelixElement {
|
|
|
47
55
|
aria-labelledby=${separator ? 'content' : nothing}
|
|
48
56
|
aria-orientation=${separator ? this.drawn : nothing}
|
|
49
57
|
></div>
|
|
50
|
-
<span id="content" part="content"><slot @slotchange=${() => this.markEmpty()}></slot></span>
|
|
58
|
+
<span id="content" part="content" aria-hidden=${separator ? 'true' : nothing}><slot @slotchange=${() => this.markEmpty()}></slot></span>
|
|
51
59
|
<div part="line" role="presentation"></div>`;
|
|
52
60
|
}
|
|
53
61
|
};
|
|
@@ -3,7 +3,9 @@ registerElementEvents({
|
|
|
3
3
|
'helix-headless-accordion-item': ['helix-before-close', 'helix-before-open', 'toggle'],
|
|
4
4
|
'helix-headless-announcement': ['helix-dismiss'],
|
|
5
5
|
'helix-headless-app-header': ['helix-scrolled'],
|
|
6
|
+
'helix-headless-area-chart': ['helix-reading-change', 'helix-reading-press'],
|
|
6
7
|
'helix-headless-avatar': ['error', 'load'],
|
|
8
|
+
'helix-headless-bar-chart': ['helix-reading-change', 'helix-reading-press'],
|
|
7
9
|
'helix-headless-button': ['helix-press'],
|
|
8
10
|
'helix-headless-button-group': ['change', 'helix-before-change'],
|
|
9
11
|
'helix-headless-callout': ['helix-dismiss'],
|
|
@@ -132,6 +134,7 @@ registerElementEvents({
|
|
|
132
134
|
'helix-before-open',
|
|
133
135
|
'toggle',
|
|
134
136
|
],
|
|
137
|
+
'helix-headless-line-chart': ['helix-reading-change', 'helix-reading-press'],
|
|
135
138
|
'helix-headless-list': [
|
|
136
139
|
'change',
|
|
137
140
|
'helix-action',
|
|
@@ -208,6 +211,7 @@ registerElementEvents({
|
|
|
208
211
|
'helix-preview',
|
|
209
212
|
'input',
|
|
210
213
|
],
|
|
214
|
+
'helix-headless-scatter-chart': ['helix-reading-change', 'helix-reading-press'],
|
|
211
215
|
'helix-headless-scroll-area': ['scroll', 'scrollend'],
|
|
212
216
|
'helix-headless-select': [
|
|
213
217
|
'change',
|
|
@@ -262,7 +266,7 @@ registerElementEvents({
|
|
|
262
266
|
'helix-headless-time-picker': ['change', 'helix-before-change', 'input'],
|
|
263
267
|
'helix-headless-toast': ['helix-dismiss'],
|
|
264
268
|
'helix-headless-toast-item': ['helix-dismiss'],
|
|
265
|
-
'helix-headless-toggle': ['helix-select'],
|
|
269
|
+
'helix-headless-toggle': ['change', 'helix-select'],
|
|
266
270
|
'helix-headless-toggle-group': ['change', 'helix-before-change', 'helix-select', 'input'],
|
|
267
271
|
'helix-headless-tooltip': ['helix-before-close', 'helix-before-open', 'toggle'],
|
|
268
272
|
'helix-headless-tour': [
|
|
@@ -29,7 +29,8 @@ declare const HelixHeadlessFilterChip_base: (new (...args: any[]) => import("@fu
|
|
|
29
29
|
*
|
|
30
30
|
* **Keyboard.** The remove button is a tab stop of its own, and Enter or Space
|
|
31
31
|
* on it asks to remove the filter. In a `FilterInput`, Backspace in the empty
|
|
32
|
-
* field asks to remove the last chip
|
|
32
|
+
* field asks to remove the last chip, the arrow keys move between the field
|
|
33
|
+
* and the chips, and Delete or Backspace on a chip asks to remove it.
|
|
33
34
|
*
|
|
34
35
|
* The remove button is named `dismiss-label` followed by the chip's words,
|
|
35
36
|
* such as "Remove filter Status is not open", so a row of chips says which
|
|
@@ -43,6 +43,9 @@ declare const HelixHeadlessFilterInput_base: (new (...args: any[]) => import("@f
|
|
|
43
43
|
* | Home, End | Highlights the first or the last suggestion while the panel is open. |
|
|
44
44
|
* | Escape | Closes the panel and stops there, so a dialog around the field stays open. |
|
|
45
45
|
* | Backspace | In an empty field, asks the last token to go. |
|
|
46
|
+
* | Left | With the caret at the start of the text, moves to the last token's remove button. Right on a right-to-left page. |
|
|
47
|
+
* | Left, Right on a token | Move between the tokens, and past the last back to the text. |
|
|
48
|
+
* | Delete, Backspace on a token | Asks the token to go. |
|
|
46
49
|
*
|
|
47
50
|
* **Typed filters.** The field parses only the fields you declare. Write
|
|
48
51
|
* `FilterField` elements, usually inside the `FilterMenu` slotted into `start`,
|
|
@@ -425,6 +428,8 @@ export declare class HelixHeadlessFilterInput extends HelixHeadlessFilterInput_b
|
|
|
425
428
|
private readonly handleLeading;
|
|
426
429
|
/** The row again, whenever what is in it changes. */
|
|
427
430
|
private readonly handleTokens;
|
|
431
|
+
/** The tokens slotted in `tags`, which the arrow keys reach from the text. */
|
|
432
|
+
protected tokenElements(): HTMLElement[];
|
|
428
433
|
/**
|
|
429
434
|
* Asks the last token to go, rather than taking it.
|
|
430
435
|
*
|
|
@@ -84,6 +84,9 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
86
|
this.handleKeydown = (event) => {
|
|
87
|
+
if (event.isComposing) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
87
90
|
if (this.tokenKeydown(event, this.value)) {
|
|
88
91
|
return;
|
|
89
92
|
}
|
|
@@ -310,6 +313,9 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
310
313
|
this.suggesting = options.length > 0;
|
|
311
314
|
this.activeAt = this.activeAt < options.length ? this.activeAt : -1;
|
|
312
315
|
}
|
|
316
|
+
tokenElements() {
|
|
317
|
+
return (this.tokens?.assignedElements({ flatten: true }) ?? []);
|
|
318
|
+
}
|
|
313
319
|
removeLastToken() {
|
|
314
320
|
const last = this.tokens
|
|
315
321
|
?.assignedElements({ flatten: true })
|
|
@@ -368,6 +374,7 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
368
374
|
const active = this.open ? options[this.activeAt] : undefined;
|
|
369
375
|
for (const [at, option] of options.entries()) {
|
|
370
376
|
option.active = this.open && at === this.activeAt;
|
|
377
|
+
option.selectionFollowsActive = true;
|
|
371
378
|
}
|
|
372
379
|
const control = this.control;
|
|
373
380
|
if (control && 'ariaActiveDescendantElement' in control) {
|
|
@@ -23,6 +23,11 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
23
23
|
* the shortcut with the control. A chord the page wrote there itself is left
|
|
24
24
|
* alone, and the key takes back only what it added.
|
|
25
25
|
*
|
|
26
|
+
* A chord is drawn with the platform's modifiers first, in its order, so one
|
|
27
|
+
* `keys` value is right everywhere: `mod+shift+p` is `⇧⌘P` on an Apple
|
|
28
|
+
* keyboard and `Ctrl+Shift+P` elsewhere. Where it is drawn in glyphs, it is
|
|
29
|
+
* read in words, such as `Shift Command P`.
|
|
30
|
+
*
|
|
26
31
|
* `caps` draws a chord as a key per key: each is a `key` part and the `+`
|
|
27
32
|
* between two a `separator` part, so a sheet can draw a cap for each.
|
|
28
33
|
* `key-labels` renames any key, on every platform, such as
|
|
@@ -141,7 +146,8 @@ export declare class HelixHeadlessKbd extends HelixElement {
|
|
|
141
146
|
/**
|
|
142
147
|
* The chord under `caps`, a part for each key and for each `+` between two,
|
|
143
148
|
* so a sheet can draw a cap per key. Written with no space between, so a
|
|
144
|
-
* chord reads as the one label it was.
|
|
149
|
+
* chord reads as the one label it was. Where the chord is said in words,
|
|
150
|
+
* the parts are hidden from a screen reader, which reads the words.
|
|
145
151
|
*/
|
|
146
152
|
protected renderChord(): TemplateResult;
|
|
147
153
|
}
|
|
@@ -135,12 +135,16 @@ let HelixHeadlessKbd = class HelixHeadlessKbd extends HelixElement {
|
|
|
135
135
|
if (this.keys === '') {
|
|
136
136
|
return html `<kbd part="kbd"><slot></slot></kbd>`;
|
|
137
137
|
}
|
|
138
|
-
const { keys, separator } = this.label;
|
|
139
|
-
|
|
138
|
+
const { keys, separator, spoken } = this.label;
|
|
139
|
+
if (spoken === '') {
|
|
140
|
+
return html `<kbd part="kbd">${this.caps ? this.renderChord() : keys.join(separator)}</kbd>`;
|
|
141
|
+
}
|
|
142
|
+
return html `<kbd part="kbd">${this.caps ? this.renderChord() : html `<span aria-hidden="true">${keys.join(separator)}</span>`}<span data-spoken>${spoken}</span></kbd>`;
|
|
140
143
|
}
|
|
141
144
|
renderChord() {
|
|
142
|
-
const { keys, separator } = this.label;
|
|
143
|
-
|
|
145
|
+
const { keys, separator, spoken } = this.label;
|
|
146
|
+
const hidden = spoken === '' ? nothing : 'true';
|
|
147
|
+
return html `${keys.map((key, index) => html `${index > 0 && separator !== '' ? html `<span part="separator" aria-hidden=${hidden}>${separator}</span>` : nothing}<span part="key" aria-hidden=${hidden}>${key}</span>`)}`;
|
|
144
148
|
}
|
|
145
149
|
};
|
|
146
150
|
__decorate([
|
|
@@ -27,6 +27,9 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
27
27
|
* `<svg>` that fills its box scales with the box, so the same `font-size` can
|
|
28
28
|
* render at 10px in a narrow chart and 43px in a wide one.
|
|
29
29
|
*
|
|
30
|
+
* `value-axis` draws the scale's numbers beside the plot, at the levels
|
|
31
|
+
* `gridlines` rules, written in `locale`.
|
|
32
|
+
*
|
|
30
33
|
* The table is the accessible representation, and the drawing is hidden from
|
|
31
34
|
* screen readers, who get the numbers. The `summary` part names the chart, from
|
|
32
35
|
* `label` or the table's caption, and gives each series' latest reading.
|
|
@@ -37,13 +40,22 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
37
40
|
* a reading. The tooltip follows, the `live` part says the reading in words,
|
|
38
41
|
* and Escape puts the tooltip away.
|
|
39
42
|
*
|
|
43
|
+
* **A tap shows the reading under it**, and keeps it until a tap lands
|
|
44
|
+
* elsewhere. `helix-reading-change` says each move of the reading, by pointer,
|
|
45
|
+
* tap or key, and `helix-reading-press` says a reading was clicked, tapped, or
|
|
46
|
+
* pressed with Enter or Space, for a page that opens what a reading stands for.
|
|
47
|
+
*
|
|
40
48
|
* @since 0.1.0
|
|
41
49
|
* @status stable
|
|
42
50
|
* @category charts
|
|
43
51
|
* @aliases Time Series, Trend Chart, Multi-line Chart
|
|
44
52
|
* @documentation https://fusion.dev/helix/components/line-chart
|
|
45
53
|
*
|
|
54
|
+
* @event {HelixReadingChangeEvent} helix-reading-change - The reading shown moved, or was put away: `index` is the row, or `-1` for none, with its `label`, the `series` the keys rest on, and the `pointerType` that moved it.
|
|
55
|
+
* @event {HelixReadingPressEvent} helix-reading-press - A reading was clicked, tapped, or pressed with Enter or Space, with the same detail as `helix-reading-change`.
|
|
56
|
+
*
|
|
46
57
|
* @csspart area - The wash under one line, where `area` is set.
|
|
58
|
+
* @csspart axis - The numbers of the scale beside the plot, under `value-axis`.
|
|
47
59
|
* @csspart band - The band around the reading under the pointer.
|
|
48
60
|
* @csspart baseline - The rule at zero, where zero is inside the range.
|
|
49
61
|
* @csspart gridline - One rule across the plot, under `gridlines`.
|
|
@@ -60,6 +72,7 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
60
72
|
* @csspart summary - The chart's name and each series' latest reading, written as a sentence for screen readers. Hide it visually.
|
|
61
73
|
* @csspart svg - The drawing surface the lines and areas sit on.
|
|
62
74
|
* @csspart terminus - The mark on one series' last reading.
|
|
75
|
+
* @csspart tick - One number on the axis, placed with `inset-block-start` at its level.
|
|
63
76
|
* @csspart tooltip - The bubble, forwarded from `Tooltip`.
|
|
64
77
|
* @csspart tooltip-anchor - The `Tooltip` element itself.
|
|
65
78
|
* @csspart tooltip-arrow - The bubble's point, forwarded from `Tooltip`.
|
|
@@ -79,6 +92,7 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
79
92
|
*
|
|
80
93
|
* @cssproperty --chart-terminus-x - Where a series' last reading sits horizontally, as a percentage. Written by the component.
|
|
81
94
|
* @cssproperty --chart-terminus-y - Where a series' last reading sits vertically, as a percentage. Written by the component.
|
|
95
|
+
* @cssproperty --line-chart-axis - The width of the axis, in `ch`, set from the widest number on it. Written by the component on the axis.
|
|
82
96
|
*/
|
|
83
97
|
export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base {
|
|
84
98
|
/**
|
|
@@ -86,6 +100,13 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
86
100
|
* `registerWords('de', { 'helix-line-chart': { positionLabel: '{position} von {count}' } })`.
|
|
87
101
|
*/
|
|
88
102
|
static words: string;
|
|
103
|
+
/**
|
|
104
|
+
* Sends the reading's moves and presses as `helix-reading-change` and
|
|
105
|
+
* `helix-reading-press`, which the pointer hears. Here and not in a
|
|
106
|
+
* constructor, where the manifest's analyzer reads the assignment as a
|
|
107
|
+
* member of this class.
|
|
108
|
+
*/
|
|
109
|
+
connectedCallback(): void;
|
|
89
110
|
/**
|
|
90
111
|
* Draws a wash under each line, down to the floor of the plot. The washes
|
|
91
112
|
* overlap and do not add up, so for parts that make a total, use
|
|
@@ -202,6 +223,15 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
202
223
|
* layers; a single `mask-image` would only ever cut the last one.
|
|
203
224
|
*/
|
|
204
225
|
terminus?: 'none' | 'ring' | 'square' | 'triangle';
|
|
226
|
+
/**
|
|
227
|
+
* Draws the scale's numbers beside the plot, the `axis` part, at the levels
|
|
228
|
+
* `gridlines` rules, so a reading can be measured off the drawing as well
|
|
229
|
+
* as read from the tooltip.
|
|
230
|
+
*
|
|
231
|
+
* Absent draws none: a line read for its shape needs no numbers beside it,
|
|
232
|
+
* and the tooltip and the table hold every reading.
|
|
233
|
+
*/
|
|
234
|
+
valueAxis: boolean;
|
|
205
235
|
/** The domain every series is drawn against, which the tooltip also needs. */
|
|
206
236
|
private range;
|
|
207
237
|
/**
|
|
@@ -223,6 +253,12 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
223
253
|
*/
|
|
224
254
|
private ends;
|
|
225
255
|
protected render(): TemplateResult;
|
|
256
|
+
/**
|
|
257
|
+
* The scale's numbers beside the plot, under `value-axis`, written in the
|
|
258
|
+
* chart's locale. A seam, so a subclass can write the numbers its own way,
|
|
259
|
+
* such as a currency.
|
|
260
|
+
*/
|
|
261
|
+
protected renderAxis(y: (value: number) => number, domain: [number, number]): TemplateResult;
|
|
226
262
|
/**
|
|
227
263
|
* What a reader who cannot see the lines is told: the chart's name and the
|
|
228
264
|
* latest reading of each series.
|