@fusion.dev/helix-headless 0.178.0 → 0.180.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 +543 -145
- package/dist/button/root/button-root.d.ts +12 -0
- package/dist/button/root/button-root.js +9 -0
- package/dist/chat/composer/chat-composer.d.ts +2 -1
- package/dist/chat/composer/chat-composer.js +1 -1
- package/dist/combobox/root/combobox-root.d.ts +12 -0
- package/dist/combobox/root/combobox-root.js +3 -2
- package/dist/command/root/command-root.d.ts +12 -0
- package/dist/command/root/command-root.js +3 -2
- package/dist/data-table/root/data-table-root.d.ts +13 -1
- package/dist/data-table/root/data-table-root.js +18 -15
- package/dist/date-input/root/date-input-root.d.ts +7 -0
- package/dist/date-input/root/date-input-root.js +12 -0
- package/dist/date-picker/root/date-picker-root.d.ts +7 -1
- package/dist/date-picker/root/date-picker-root.js +12 -0
- package/dist/drilldown/item/drilldown-item.d.ts +6 -0
- package/dist/drilldown/item/drilldown-item.js +9 -0
- package/dist/drilldown/root/drilldown-root.js +9 -0
- package/dist/element-events.generated.js +7 -1
- package/dist/filter-input/root/filter-input-root.d.ts +13 -0
- package/dist/filter-input/root/filter-input-root.js +2 -1
- package/dist/heatmap/root/heatmap-root.d.ts +54 -42
- package/dist/heatmap/root/heatmap-root.js +72 -54
- package/dist/listbox/root/listbox-root.d.ts +16 -2
- package/dist/listbox/root/listbox-root.js +8 -4
- package/dist/menu/item/menu-item.d.ts +6 -0
- package/dist/menu/item/menu-item.js +9 -0
- package/dist/meter/root/meter-root.js +1 -2
- package/dist/notifications/notification/notification.d.ts +37 -9
- package/dist/notifications/notification/notification.js +35 -5
- package/dist/option/among.d.ts +23 -0
- package/dist/option/among.js +2 -0
- package/dist/option/root/option-root.d.ts +1 -17
- package/dist/option/root/option-root.js +1 -4
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +5 -4
- package/dist/scatter-chart/root/scatter-chart-root.js +1 -0
- package/dist/select/root/select-root.d.ts +13 -2
- package/dist/select/root/select-root.js +3 -3
- package/dist/speed-dial/item/speed-dial-item.d.ts +6 -0
- package/dist/speed-dial/item/speed-dial-item.js +9 -0
- package/dist/table/column/table-column.d.ts +1 -10
- package/dist/table/column/table-column.js +1 -2
- package/dist/table/edge.d.ts +10 -0
- package/dist/table/edge.js +2 -0
- package/dist/tabs/root/tabs-root.d.ts +1 -0
- package/dist/tabs/root/tabs-root.js +13 -0
- package/dist/tabs/tab/tab.d.ts +6 -0
- package/dist/tabs/tab/tab.js +9 -0
- package/dist/tooltip/root/tooltip-root.js +1 -0
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +472 -130
- package/types/vue.d.ts +71 -50
- package/types/words.d.ts +27 -6
|
@@ -256,6 +256,18 @@ export declare class HelixHeadlessButton extends HelixFormElement {
|
|
|
256
256
|
*/
|
|
257
257
|
protected announcePress(click: Event): void;
|
|
258
258
|
private readonly handleClick;
|
|
259
|
+
/**
|
|
260
|
+
* Presses the button, as `click()` presses a native one: the command is sent,
|
|
261
|
+
* the form submits or resets, and `helix-press` says `virtual`.
|
|
262
|
+
*
|
|
263
|
+
* **Passed to the inner control, because a click on the host reaches nothing
|
|
264
|
+
* that acts.** The control in the shadow root is what answers a click, so
|
|
265
|
+
* `click()` from a script, an automation or a test, dispatched on the host,
|
|
266
|
+
* submitted nothing and sent no `helix-press`. The control's own click reaches
|
|
267
|
+
* the host's listeners once, retargeted, as one from a native button does. A
|
|
268
|
+
* disabled button does nothing, and a pending one refuses the press.
|
|
269
|
+
*/
|
|
270
|
+
click(): void;
|
|
259
271
|
/** What a press does: sends the command, and submits or resets the form. */
|
|
260
272
|
private act;
|
|
261
273
|
/**
|
|
@@ -89,6 +89,15 @@ let HelixHeadlessButton = class HelixHeadlessButton extends HelixFormElement {
|
|
|
89
89
|
this.recent = {};
|
|
90
90
|
this.dispatchEvent(new HelixPressEvent({ pointerType }));
|
|
91
91
|
}
|
|
92
|
+
click() {
|
|
93
|
+
const control = this.partNamed('button');
|
|
94
|
+
if (control) {
|
|
95
|
+
control.click();
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
super.click();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
92
101
|
act() {
|
|
93
102
|
this.linkCommand();
|
|
94
103
|
this.sendCommand();
|
|
@@ -15,7 +15,8 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
15
15
|
* The composer clears only when no listener cancels the send, so the text is
|
|
16
16
|
* kept when you cancel a send that failed.
|
|
17
17
|
*
|
|
18
|
-
* **In a form, the draft is the composer's value**, submitted under `name
|
|
18
|
+
* **In a form, the draft is the composer's value**, submitted under `name`,
|
|
19
|
+
* and an empty draft submits an empty entry, as a native textarea does. A
|
|
19
20
|
* form reset puts back the `value` the markup declared, and a `<fieldset
|
|
20
21
|
* disabled>` turns the composer off. Sending is still `helix-send`, and it
|
|
21
22
|
* does not submit the form.
|
|
@@ -124,7 +124,7 @@ let HelixHeadlessChatComposer = class HelixHeadlessChatComposer extends HelixFor
|
|
|
124
124
|
super.updated(changed);
|
|
125
125
|
this.markEmpty();
|
|
126
126
|
if (changed.has('value')) {
|
|
127
|
-
this.internals.setFormValue(this.value
|
|
127
|
+
this.internals.setFormValue(this.value, this.value);
|
|
128
128
|
}
|
|
129
129
|
const field = this.partNamed('field');
|
|
130
130
|
if (field?.validity) {
|
|
@@ -59,6 +59,18 @@ declare const HelixHeadlessCombobox_base: (new (...args: any[]) => import("@fusi
|
|
|
59
59
|
* framework would re-render over an element the combobox inserted, so add the
|
|
60
60
|
* option in your event handler.
|
|
61
61
|
*
|
|
62
|
+
* **The options are an import of their own.** An option is the Option family's,
|
|
63
|
+
* which the combobox does not register, so a page that writes one imports it
|
|
64
|
+
* beside the combobox:
|
|
65
|
+
*
|
|
66
|
+
* ```js
|
|
67
|
+
* import '@fusion.dev/helix/combobox'
|
|
68
|
+
* import '@fusion.dev/helix/option'
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* In development, a combobox holding an option nobody registered says so once
|
|
72
|
+
* the page has loaded, with the line to add.
|
|
73
|
+
*
|
|
62
74
|
* @since 0.1.0
|
|
63
75
|
* @status stable
|
|
64
76
|
* @category forms
|
|
@@ -4,13 +4,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { AriaForwardController, afterLinkFollowed, chosenValues, countLabel, customElement, DelayController, drawAutofill, drawStatus, formatWords, HelixCreateEvent, HelixFilterEvent, HelixFormElement, handedLocale, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, onApple, PopoverController, reportValues, StatusController, submitImplicitly, UpgradeController, words, wordsLocale, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, afterLinkFollowed, auditChildren, chosenValues, countLabel, customElement, DelayController, drawAutofill, drawStatus, formatWords, HelixCreateEvent, HelixFilterEvent, HelixFormElement, handedLocale, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, onApple, PopoverController, reportValues, StatusController, submitImplicitly, UpgradeController, words, wordsLocale, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretDown } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
12
|
import { html } from 'lit/static-html.js';
|
|
13
|
-
import { optionsAmong } from '../../option/
|
|
13
|
+
import { optionsAmong } from '../../option/among.js';
|
|
14
14
|
import { HelixHeadlessTag } from '../../tag/root/tag-root.js';
|
|
15
15
|
import '../../listbox/index.js';
|
|
16
16
|
import '../../tag/root/index.js';
|
|
@@ -507,6 +507,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
|
|
|
507
507
|
}
|
|
508
508
|
connectedCallback() {
|
|
509
509
|
super.connectedCallback();
|
|
510
|
+
auditChildren(this, 'option', 'option', 'it suggests nothing');
|
|
510
511
|
this.addEventListener('helix-select', this.handleLinkFollowed);
|
|
511
512
|
this.watcher = new MutationObserver(() => this.requestUpdate());
|
|
512
513
|
this.watcher.observe(this, {
|
|
@@ -72,6 +72,18 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
|
|
|
72
72
|
* Aria's `Autocomplete` is. The commands are a `listbox` of `option`s. How many commands typing left, the empty text and
|
|
73
73
|
* the loading text are said in a polite live region.
|
|
74
74
|
*
|
|
75
|
+
* **The commands are an import of their own.** A command is an option, the
|
|
76
|
+
* Option family's, which the palette does not register, so a page that writes
|
|
77
|
+
* one imports it beside the palette:
|
|
78
|
+
*
|
|
79
|
+
* ```js
|
|
80
|
+
* import '@fusion.dev/helix/command'
|
|
81
|
+
* import '@fusion.dev/helix/option'
|
|
82
|
+
* ```
|
|
83
|
+
*
|
|
84
|
+
* In development, a palette holding an option nobody registered says so once
|
|
85
|
+
* the page has loaded, with the line to add.
|
|
86
|
+
*
|
|
75
87
|
* @since 0.1.0
|
|
76
88
|
* @status stable
|
|
77
89
|
* @category navigation
|
|
@@ -4,11 +4,11 @@ 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, drawStatus, HelixElement, HelixSelectEvent, MixinControllerOpen, matchesChord, StatusController, words, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { auditChildren, customElement, drawStatus, HelixElement, HelixSelectEvent, MixinControllerOpen, matchesChord, StatusController, words, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { html } from 'lit/static-html.js';
|
|
11
|
-
import { optionsAmong } from '../../option/
|
|
11
|
+
import { optionsAmong } from '../../option/among.js';
|
|
12
12
|
import '../../dialog/index.js';
|
|
13
13
|
import '../../listbox/index.js';
|
|
14
14
|
const says = (element, state) => {
|
|
@@ -145,6 +145,7 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
|
|
|
145
145
|
}
|
|
146
146
|
connectedCallback() {
|
|
147
147
|
super.connectedCallback();
|
|
148
|
+
auditChildren(this, 'option', 'option', 'the palette lists no commands');
|
|
148
149
|
this.addEventListener('helix-select', this.swallowOptionSelect);
|
|
149
150
|
this.addEventListener('keydown', this.handleAlternate, { capture: true });
|
|
150
151
|
this.addEventListener('keydown', this.handleBack);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type DataRow, HelixElement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
-
import {
|
|
3
|
+
import type { HelixHeadlessTableColumn } from '../../table/column/table-column.js';
|
|
4
4
|
import '../../checkbox/index.js';
|
|
5
5
|
import '../../pagination/index.js';
|
|
6
6
|
declare const HelixHeadlessDataTable_base: (new (...args: any[]) => import("@fusion.dev/helix-core").CollectionElement) & typeof HelixElement;
|
|
@@ -131,6 +131,18 @@ declare const HelixHeadlessDataTable_base: (new (...args: any[]) => import("@fus
|
|
|
131
131
|
* Written on `DataTable`, `columns` has no effect, so watch for it when you
|
|
132
132
|
* move a table from `Table` to `DataTable`.
|
|
133
133
|
*
|
|
134
|
+
* **The columns are an import of their own.** A column is the Table family's
|
|
135
|
+
* `TableColumn`, which the data table does not register, so a page that writes
|
|
136
|
+
* one imports the Table entry beside the data table:
|
|
137
|
+
*
|
|
138
|
+
* ```js
|
|
139
|
+
* import '@fusion.dev/helix/data-table'
|
|
140
|
+
* import '@fusion.dev/helix/table'
|
|
141
|
+
* ```
|
|
142
|
+
*
|
|
143
|
+
* In development, a data table holding a column nobody registered says so once
|
|
144
|
+
* the page has loaded, with the line to add.
|
|
145
|
+
*
|
|
134
146
|
* @since 0.1.0
|
|
135
147
|
* @status stable
|
|
136
148
|
* @category data
|
|
@@ -5,14 +5,14 @@ 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 HelixHeadlessDataTable_1;
|
|
8
|
-
import { anchorAt, arranged, auditServed, commaList, countLabel, customElement, cycle, deepActiveElement, deepContains, everyState, format, formatWords, gridMove, HelixActivateEvent, HelixElement, HelixExpandEvent, HelixFilterEvent, HelixFilteredEvent, HelixLoadMoreEvent, HelixNavigateEvent, HelixReorderEvent, HelixReorderedEvent, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, handedLocale, hostAria, inlineStep, inRowOrder, MixinCollection, markRegion, onAndroid, ordered, pageRows, parse, placeKey, ReorderController, rangeAdd, reportRuntime, requestChange, requestReorder, scrollingAncestor, scrollRoom, selectsAll, Typeahead, toggleEvery, treeArrow, typesCharacter, VirtualizeController, valueAt, window_, words, wordsLocale, writtenList, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { anchorAt, arranged, auditChildren, auditServed, commaList, countLabel, customElement, cycle, deepActiveElement, deepContains, everyState, format, formatWords, gridMove, HelixActivateEvent, HelixElement, HelixExpandEvent, HelixFilterEvent, HelixFilteredEvent, HelixLoadMoreEvent, HelixNavigateEvent, HelixReorderEvent, HelixReorderedEvent, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, handedLocale, hostAria, inlineStep, inRowOrder, MixinCollection, markRegion, onAndroid, ordered, pageRows, parse, placeKey, ReorderController, rangeAdd, reportRuntime, requestChange, requestReorder, scrollingAncestor, scrollRoom, selectsAll, Typeahead, toggleEvery, treeArrow, typesCharacter, VirtualizeController, valueAt, whenHydrated, window_, words, wordsLocale, writtenList, } from '@fusion.dev/helix-core';
|
|
9
9
|
import { caretDown, caretRight, dotsSixVertical } from '@fusion.dev/helix-icons';
|
|
10
10
|
import { nothing } from 'lit';
|
|
11
11
|
import { property, state } from 'lit/decorators.js';
|
|
12
12
|
import { repeat } from 'lit/directives/repeat.js';
|
|
13
13
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
14
14
|
import { html } from 'lit/static-html.js';
|
|
15
|
-
import { edgeOf } from '../../table/
|
|
15
|
+
import { edgeOf } from '../../table/edge.js';
|
|
16
16
|
import '../../checkbox/index.js';
|
|
17
17
|
import '../../pagination/index.js';
|
|
18
18
|
import { toggledOpen } from '../keys.js';
|
|
@@ -1021,19 +1021,21 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
1021
1021
|
const shown = this.shownColumns;
|
|
1022
1022
|
const android = onAndroid();
|
|
1023
1023
|
for (const column of this.tableColumns) {
|
|
1024
|
-
column
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
? '
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1024
|
+
whenHydrated(column, () => {
|
|
1025
|
+
column.movable = this.reorderable && column.field !== '';
|
|
1026
|
+
column.gridCell = true;
|
|
1027
|
+
column.tabStop = shown.indexOf(column) + offset === stop;
|
|
1028
|
+
column.sorted =
|
|
1029
|
+
current && column.canSort && column.field === current.field
|
|
1030
|
+
? current.direction === 'asc'
|
|
1031
|
+
? 'ascending'
|
|
1032
|
+
: 'descending'
|
|
1033
|
+
: undefined;
|
|
1034
|
+
column.sortWords =
|
|
1035
|
+
android && column.sorted
|
|
1036
|
+
? this.sortSaid(column.textContent?.trim() || column.field, column.sorted)
|
|
1037
|
+
: '';
|
|
1038
|
+
});
|
|
1037
1039
|
}
|
|
1038
1040
|
}
|
|
1039
1041
|
renderCell(column, row, picked, place, stop, header, id) {
|
|
@@ -1276,6 +1278,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
1276
1278
|
}
|
|
1277
1279
|
connectedCallback() {
|
|
1278
1280
|
super.connectedCallback();
|
|
1281
|
+
auditChildren(this, 'table-column', 'table', 'the table draws no columns');
|
|
1279
1282
|
this.addEventListener('click', this.handleHeadClick);
|
|
1280
1283
|
this.addEventListener('click', this.handleRowClick);
|
|
1281
1284
|
this.addEventListener('pointerdown', this.notePress, true);
|
|
@@ -33,6 +33,8 @@ declare const HelixHeadlessDateInput_base: (new (...args: any[]) => import("@fus
|
|
|
33
33
|
* digits or the arrow keys. Alt+Down opens the calendar from a segment. A
|
|
34
34
|
* `range` is two rows with a dash between them, the start and the end, as
|
|
35
35
|
* React Aria's DateRangePicker draws them, and `multiple` keeps the text.
|
|
36
|
+
* A range whose end is before its start reports `rangeUnderflow`, as Date
|
|
37
|
+
* Picker does, with `range-order-message`.
|
|
36
38
|
*
|
|
37
39
|
* Text that is not a date gives the form an empty value, as a native date
|
|
38
40
|
* field does, and `value` keeps the text so it can be corrected.
|
|
@@ -359,6 +361,11 @@ export declare class HelixHeadlessDateInput extends HelixHeadlessDateInput_base
|
|
|
359
361
|
* for the page's language, then the English.
|
|
360
362
|
*/
|
|
361
363
|
rangeLengthMessage: string;
|
|
364
|
+
/**
|
|
365
|
+
* The message shown when a range ends before it starts. `{start}` is
|
|
366
|
+
* replaced with the start, written the way the field writes dates.
|
|
367
|
+
*/
|
|
368
|
+
rangeOrderMessage: string;
|
|
362
369
|
/**
|
|
363
370
|
* The message shown when a date is after `max`. `{max}` is replaced with
|
|
364
371
|
* `max`, written the way the field writes dates.
|
|
@@ -47,6 +47,7 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinSegmented
|
|
|
47
47
|
this.previousYearLabel = 'Previous year';
|
|
48
48
|
this.previousYearsLabel = 'Earlier years';
|
|
49
49
|
this.rangeLengthMessage = 'A range is two dates.';
|
|
50
|
+
this.rangeOrderMessage = 'Choose an end on or after {start}.';
|
|
50
51
|
this.rangeOverflowMessage = 'Choose a date on or before {max}.';
|
|
51
52
|
this.rangeUnderflowMessage = 'Choose a date on or after {min}.';
|
|
52
53
|
this.removeLabel = 'Remove {name}';
|
|
@@ -263,6 +264,13 @@ let HelixHeadlessDateInput = class HelixHeadlessDateInput extends MixinSegmented
|
|
|
263
264
|
if (this.mode === 'range' && held.length > 2) {
|
|
264
265
|
return this.rangeLengthMessage;
|
|
265
266
|
}
|
|
267
|
+
const [start, end] = held;
|
|
268
|
+
if (this.mode === 'range' && start !== undefined && end !== undefined && end < start) {
|
|
269
|
+
return [
|
|
270
|
+
'rangeUnderflow',
|
|
271
|
+
formatWords(this, 'rangeOrderMessage', { start: this.written(start) }),
|
|
272
|
+
];
|
|
273
|
+
}
|
|
266
274
|
return '';
|
|
267
275
|
}
|
|
268
276
|
renderPicker() {
|
|
@@ -547,6 +555,10 @@ __decorate([
|
|
|
547
555
|
words,
|
|
548
556
|
property({ attribute: 'range-length-message' })
|
|
549
557
|
], HelixHeadlessDateInput.prototype, "rangeLengthMessage", void 0);
|
|
558
|
+
__decorate([
|
|
559
|
+
words,
|
|
560
|
+
property({ attribute: 'range-order-message' })
|
|
561
|
+
], HelixHeadlessDateInput.prototype, "rangeOrderMessage", void 0);
|
|
550
562
|
__decorate([
|
|
551
563
|
words,
|
|
552
564
|
property({ attribute: 'range-overflow-message' })
|
|
@@ -48,7 +48,8 @@ declare const HelixHeadlessDatePicker_base: (new (...args: any[]) => import("@fu
|
|
|
48
48
|
* when Previous or Next is pressed. Neither moves past `min` or `max`, and the
|
|
49
49
|
* keys stop at them too. A value outside the bounds, on a barred day, or off
|
|
50
50
|
* `step` reports `rangeUnderflow`, `rangeOverflow`, `badInput` or
|
|
51
|
-
* `stepMismatch`, so a form does not submit it.
|
|
51
|
+
* `stepMismatch`, so a form does not submit it. A range set from a script
|
|
52
|
+
* whose end is before its start reports `rangeUnderflow` as well.
|
|
52
53
|
*
|
|
53
54
|
* @since 0.1.0
|
|
54
55
|
* @status stable
|
|
@@ -278,6 +279,11 @@ export declare class HelixHeadlessDatePicker extends HelixHeadlessDatePicker_bas
|
|
|
278
279
|
* Accessible name for the control that moves back a page, in the years.
|
|
279
280
|
*/
|
|
280
281
|
previousYearsLabel: string;
|
|
282
|
+
/**
|
|
283
|
+
* The validation message for a range that ends before it starts. `{start}`
|
|
284
|
+
* is replaced with the start, written as a date in `locale`.
|
|
285
|
+
*/
|
|
286
|
+
rangeOrderMessage: string;
|
|
281
287
|
/**
|
|
282
288
|
* The validation message for a date after `max`. `{max}` is replaced with
|
|
283
289
|
* `max`, written as a date in `locale`.
|
|
@@ -44,6 +44,7 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinPickerF
|
|
|
44
44
|
this.previousLabel = 'Previous month';
|
|
45
45
|
this.previousYearLabel = 'Previous year';
|
|
46
46
|
this.previousYearsLabel = 'Earlier years';
|
|
47
|
+
this.rangeOrderMessage = 'Choose an end on or after {start}.';
|
|
47
48
|
this.rangeOverflowMessage = 'Choose a date on or before {max}.';
|
|
48
49
|
this.focused = '';
|
|
49
50
|
this.choosing = false;
|
|
@@ -504,6 +505,13 @@ let HelixHeadlessDatePicker = class HelixHeadlessDatePicker extends MixinPickerF
|
|
|
504
505
|
return [{ [fault[0]]: true }, fault[1]];
|
|
505
506
|
}
|
|
506
507
|
}
|
|
508
|
+
const [start, end] = held;
|
|
509
|
+
if (this.mode === 'range' && start !== undefined && end !== undefined && end < start) {
|
|
510
|
+
return [
|
|
511
|
+
{ rangeUnderflow: true },
|
|
512
|
+
formatWords(this, 'rangeOrderMessage', { start: this.spoken(start) }),
|
|
513
|
+
];
|
|
514
|
+
}
|
|
507
515
|
return undefined;
|
|
508
516
|
}
|
|
509
517
|
get failure() {
|
|
@@ -855,6 +863,10 @@ __decorate([
|
|
|
855
863
|
words,
|
|
856
864
|
property({ attribute: 'previous-years-label' })
|
|
857
865
|
], HelixHeadlessDatePicker.prototype, "previousYearsLabel", void 0);
|
|
866
|
+
__decorate([
|
|
867
|
+
words,
|
|
868
|
+
property({ attribute: 'range-order-message' })
|
|
869
|
+
], HelixHeadlessDatePicker.prototype, "rangeOrderMessage", void 0);
|
|
858
870
|
__decorate([
|
|
859
871
|
words,
|
|
860
872
|
property({ attribute: 'range-overflow-message' })
|
|
@@ -207,6 +207,12 @@ export declare class HelixHeadlessDrilldownItem extends HelixElement {
|
|
|
207
207
|
* an icon of your own replaces it by being slotted.
|
|
208
208
|
*/
|
|
209
209
|
protected renderMark(): TemplateResult;
|
|
210
|
+
/**
|
|
211
|
+
* Presses the row, as `click()` presses a native button: passed to the
|
|
212
|
+
* control inside, which is what answers a click, so a script's `click()`
|
|
213
|
+
* chooses the row, or follows its link, once.
|
|
214
|
+
*/
|
|
215
|
+
click(): void;
|
|
210
216
|
protected render(): TemplateResult | typeof nothing;
|
|
211
217
|
}
|
|
212
218
|
declare global {
|
|
@@ -104,6 +104,15 @@ let HelixHeadlessDrilldownItem = class HelixHeadlessDrilldownItem extends HelixE
|
|
|
104
104
|
</svg></slot
|
|
105
105
|
>`;
|
|
106
106
|
}
|
|
107
|
+
click() {
|
|
108
|
+
const control = this.partNamed('item');
|
|
109
|
+
if (control) {
|
|
110
|
+
control.click();
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
super.click();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
107
116
|
render() {
|
|
108
117
|
if (this.showingPage || this.onPath) {
|
|
109
118
|
return html `<slot name="page" @slotchange=${this.readPage}></slot>`;
|
|
@@ -158,8 +158,17 @@ let HelixHeadlessDrilldown = class HelixHeadlessDrilldown extends MixinCollectio
|
|
|
158
158
|
willUpdate(changed) {
|
|
159
159
|
super.willUpdate(changed);
|
|
160
160
|
if (changed.has('page') && (this.drilldown.page?.value ?? '') !== this.page) {
|
|
161
|
+
const leaving = this.drilldown.page;
|
|
162
|
+
const focused = this.contains(document.activeElement);
|
|
161
163
|
this.showPage(this.page);
|
|
162
164
|
this.page = this.drilldown.page?.value ?? '';
|
|
165
|
+
if (focused) {
|
|
166
|
+
this.updateComplete.then(() => {
|
|
167
|
+
const items = this.items;
|
|
168
|
+
const to = leaving && items.includes(leaving) ? leaving : items[0];
|
|
169
|
+
to?.focusItem();
|
|
170
|
+
});
|
|
171
|
+
}
|
|
163
172
|
}
|
|
164
173
|
hostAria(this.internals, {
|
|
165
174
|
label: this.navigation ? this.label : '',
|
|
@@ -137,7 +137,13 @@ registerElementEvents({
|
|
|
137
137
|
'helix-graph-signal',
|
|
138
138
|
'helix-graph-zoom',
|
|
139
139
|
],
|
|
140
|
-
'helix-headless-heatmap': [
|
|
140
|
+
'helix-headless-heatmap': [
|
|
141
|
+
'change',
|
|
142
|
+
'helix-before-change',
|
|
143
|
+
'helix-reading-change',
|
|
144
|
+
'helix-reading-press',
|
|
145
|
+
'helix-resize',
|
|
146
|
+
],
|
|
141
147
|
'helix-headless-icon': ['error', 'load'],
|
|
142
148
|
'helix-headless-icon-button': ['helix-press'],
|
|
143
149
|
'helix-headless-image': ['error', 'load'],
|
|
@@ -128,6 +128,19 @@ declare const HelixHeadlessFilterInput_base: (new (...args: any[]) => import("@f
|
|
|
128
128
|
* filter goes. Set `chips` and the field adds, updates, and removes those
|
|
129
129
|
* chips itself, from every `helix-facet` you do not cancel.
|
|
130
130
|
*
|
|
131
|
+
* **The suggestions you write are an import of their own.** A suggestion is an
|
|
132
|
+
* option, the Option family's, which the field does not register, so a page
|
|
133
|
+
* that slots one imports it beside the field:
|
|
134
|
+
*
|
|
135
|
+
* ```js
|
|
136
|
+
* import '@fusion.dev/helix/filter-input'
|
|
137
|
+
* import '@fusion.dev/helix/option'
|
|
138
|
+
* ```
|
|
139
|
+
*
|
|
140
|
+
* In development, a field holding an option nobody registered says so once the
|
|
141
|
+
* page has loaded, with the line to add. The options `source` gives are drawn
|
|
142
|
+
* as this Option too, and need the same import.
|
|
143
|
+
*
|
|
131
144
|
* @since 0.1.0
|
|
132
145
|
* @status stable
|
|
133
146
|
* @category forms
|
|
@@ -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, countLabel, customElement, DelayController, drawIcon, drawStatus, formatWords, HelixFacetEvent, HelixFormElement, holdCaret, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, PopoverController, reportRuntime, restoreValue, StatusController, scrollItemIntoView, words, wordsLocale, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, auditChildren, countLabel, customElement, DelayController, drawIcon, drawStatus, formatWords, HelixFacetEvent, HelixFormElement, holdCaret, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, PopoverController, reportRuntime, restoreValue, StatusController, scrollItemIntoView, words, wordsLocale, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { x } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -552,6 +552,7 @@ let HelixHeadlessFilterInput = class HelixHeadlessFilterInput extends MixinContr
|
|
|
552
552
|
}
|
|
553
553
|
connectedCallback() {
|
|
554
554
|
super.connectedCallback();
|
|
555
|
+
auditChildren(this, 'option', 'option', 'the field suggests nothing');
|
|
555
556
|
this.addEventListener('helix-dismiss', this.handleDismiss, { capture: true });
|
|
556
557
|
this.addEventListener(HelixFacetEvent.eventName, this.handleFacet);
|
|
557
558
|
this.addEventListener('helix-select', this.handleSourcedSelect);
|
|
@@ -2,7 +2,7 @@ import { AriaForwardController, HelixElement } from '@fusion.dev/helix-core';
|
|
|
2
2
|
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import '../../tooltip/index.js';
|
|
4
4
|
import { type Reading } from './buckets.js';
|
|
5
|
-
declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinChartSourceInterface);
|
|
5
|
+
declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinChartSourceInterface) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinChartStatusInterface);
|
|
6
6
|
/**
|
|
7
7
|
* @summary A strip of cells, each colored by its reading, for uptime, contributions, or activity.
|
|
8
8
|
*
|
|
@@ -50,6 +50,25 @@ declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: an
|
|
|
50
50
|
* `helix-before-change` and tells with `change`, and the `selection` part says
|
|
51
51
|
* how many are selected, in `selection-label`.
|
|
52
52
|
*
|
|
53
|
+
* **Under `selection-mode` the strip is a grid**, so the selection is state a
|
|
54
|
+
* reader is told rather than words alone: each column of the strip is a `row`,
|
|
55
|
+
* a week with `rows="7"`, and each cell a `gridcell` named by its row in the
|
|
56
|
+
* table and carrying `aria-selected`. The strip says
|
|
57
|
+
* `aria-multiselectable` under `multiple` and points at the cell the keys rest
|
|
58
|
+
* on with `aria-activedescendant`, so a screen reader reads that cell, and the
|
|
59
|
+
* `live` part stays quiet. Without `selection-mode` nothing is selectable, and
|
|
60
|
+
* the strip is an application with the readout, as every chart's plot is.
|
|
61
|
+
*
|
|
62
|
+
* **Readings are sent as every chart sends them.** `helix-reading-change`
|
|
63
|
+
* says each move of the reading, by pointer, tap or key, and
|
|
64
|
+
* `helix-reading-press` a reading clicked, tapped, or pressed with Enter or
|
|
65
|
+
* Space, each with the row of the table in `index`.
|
|
66
|
+
*
|
|
67
|
+
* **Nothing to draw.** A table with no readings shows `empty-text`, "No
|
|
68
|
+
* readings", under the strip, and `loading` shows `loading-text` there until
|
|
69
|
+
* readings arrive. The `empty` and `loading` slots take markup in place of
|
|
70
|
+
* either, as on every chart.
|
|
71
|
+
*
|
|
53
72
|
* **Keyboard.** The strip is one tab stop once it has cells.
|
|
54
73
|
*
|
|
55
74
|
* | Key | What it does |
|
|
@@ -59,7 +78,7 @@ declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: an
|
|
|
59
78
|
* | Right, Left | Moves a column on or back, a week with `rows="7"`. On a right-to-left page, Left moves on. |
|
|
60
79
|
* | Home, End | Moves to the first or the last cell. |
|
|
61
80
|
* | Page Down, Page Up | Moves a month on or back where the rows carry dates, and four columns otherwise. |
|
|
62
|
-
* | Enter, Space |
|
|
81
|
+
* | Enter, Space | Presses the cell, which sends `helix-reading-press`, and selects it or lets it go under `selection-mode`. |
|
|
63
82
|
* | Shift with an arrow, Home, End, Page Up or Page Down | Selects every cell from the last one pressed to where the key went, under `selection-mode="multiple"`. |
|
|
64
83
|
* | Escape | Puts the cell's tooltip away. |
|
|
65
84
|
*
|
|
@@ -69,23 +88,30 @@ declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: an
|
|
|
69
88
|
* @aliases Contribution graph, Uptime strip, Calendar heatmap, Activity graph
|
|
70
89
|
* @documentation https://fusion.dev/helix/components/heatmap
|
|
71
90
|
*
|
|
91
|
+
* @slot empty - Content shown under the strip when the table has no readings, such as a link to add the first. Falls back to `empty-text`.
|
|
72
92
|
* @slot end - Below the strip, at the trailing edge: usually the newest date.
|
|
93
|
+
* @slot loading - Content shown under the strip while `loading` is set and there are no readings yet. Falls back to `loading-text`.
|
|
73
94
|
* @slot start - Below the strip, at the leading edge: usually the oldest date.
|
|
74
95
|
* @slot summary - Below the strip, in the middle: a summary of the range shown.
|
|
75
96
|
*
|
|
76
97
|
* @event {Event} change - Fired once a press or a key has changed which cells are selected.
|
|
77
98
|
* @event {HelixBeforeChangeEvent} helix-before-change - Fired before a press or a key changes which cells are selected, with the `value` it would leave. Cancelable.
|
|
99
|
+
* @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.
|
|
100
|
+
* @event {HelixReadingPressEvent} helix-reading-press - A reading was clicked, tapped, or pressed with Enter or Space, with the same detail as `helix-reading-change`.
|
|
78
101
|
* @event {HelixResizeEvent} helix-resize - Fired when the number of cells drawn changes, with the new number.
|
|
79
102
|
*
|
|
80
103
|
* @csspart cell - One reading.
|
|
81
104
|
* @csspart cell-active - The cell the pointer or the keys rest on. Set alongside `cell`.
|
|
82
105
|
* @csspart cell-selected - A cell that is selected, under `selection-mode`. Set alongside `cell`.
|
|
83
|
-
* @csspart empty -
|
|
106
|
+
* @csspart empty - The words under the strip when the table has no readings: the `empty` slot, falling back to `empty-text`. Not drawn while the table cannot be read yet, on the server and during hydration, there being no document to resolve `for` in.
|
|
84
107
|
* @csspart end - The trailing slot's box.
|
|
85
108
|
* @csspart footer - The three-slot row under the strip.
|
|
86
109
|
* @csspart live - The readout: a polite live region that says the cell the keys moved to. Hide it visually.
|
|
110
|
+
* @csspart loading - The words under the strip while `loading` is set and there are no readings: the `loading` slot, falling back to `loading-text`.
|
|
87
111
|
* @csspart mark - The invisible point the tooltip is anchored to.
|
|
88
112
|
* @csspart overview - The busiest reading and the total of the readings drawn, written as a sentence for screen readers, which describes the strip. Rendered once there are cells. Hide it visually.
|
|
113
|
+
* @csspart plot - The same element as `strip`, under the name every chart gives the drawing that takes focus.
|
|
114
|
+
* @csspart row - A column of cells, which a grid reads as a row, under `selection-mode`. It draws no box.
|
|
89
115
|
* @csspart selection - A polite region that says how many cells are selected after a change, rendered from the first change. Hide it visually.
|
|
90
116
|
* @csspart start - The leading slot's box.
|
|
91
117
|
* @csspart strip - The grid of cells, which takes focus to be read by key. It is named by the host's `aria-labelledby` or `aria-label`, then by `label`, then by the caption of the table.
|
|
@@ -125,6 +151,7 @@ declare const HelixHeadlessHeatmap_base: typeof HelixElement & (new (...args: an
|
|
|
125
151
|
*
|
|
126
152
|
* @cssstate active - While a cell is shown, under the pointer or the keys, with its tooltip open.
|
|
127
153
|
* @cssstate empty - While the `empty` part stands in place of the cells.
|
|
154
|
+
* @cssstate loading - While the `loading` part stands in place of the cells.
|
|
128
155
|
*/
|
|
129
156
|
export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
130
157
|
/**
|
|
@@ -137,13 +164,6 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
137
164
|
* `overview-label`.
|
|
138
165
|
*/
|
|
139
166
|
busiestLabel: string;
|
|
140
|
-
/**
|
|
141
|
-
* Shown when the table has no readings in it.
|
|
142
|
-
*
|
|
143
|
-
* Never shown while the table cannot be read at all, which is a server render
|
|
144
|
-
* and the hydrating one after it: see `sourceKnown`.
|
|
145
|
-
*/
|
|
146
|
-
emptyText: string;
|
|
147
167
|
/**
|
|
148
168
|
* Space between cells, in CSS pixels. It is a number for the same reason
|
|
149
169
|
* `min-cell` is.
|
|
@@ -187,9 +207,11 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
187
207
|
*/
|
|
188
208
|
rows: number;
|
|
189
209
|
/**
|
|
190
|
-
* What the readout
|
|
191
|
-
*
|
|
192
|
-
*
|
|
210
|
+
* What the readout added for a selected cell, under `selection-mode`.
|
|
211
|
+
*
|
|
212
|
+
* @deprecated The strip is a grid under `selection-mode`, and each cell says
|
|
213
|
+
* whether it is selected with `aria-selected`, in the reader's own words, so
|
|
214
|
+
* the readout says nothing there and this is not read.
|
|
193
215
|
*/
|
|
194
216
|
selectedLabel: string;
|
|
195
217
|
/**
|
|
@@ -334,28 +356,6 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
334
356
|
* the one under the pointer.
|
|
335
357
|
*/
|
|
336
358
|
private get points();
|
|
337
|
-
/**
|
|
338
|
-
* Whether this render can tell a table with no readings from one it has not
|
|
339
|
-
* resolved yet.
|
|
340
|
-
*
|
|
341
|
-
* **Unknown is not empty, which is what an empty state must never say.**
|
|
342
|
-
* `for` names an id and resolving an id wants a document, so a server has
|
|
343
|
-
* none and a hydrating render must not look either. Without this the server
|
|
344
|
-
* drew "No readings" over a table holding ninety days of them, a crawler read
|
|
345
|
-
* that sentence, and the strip flipped to a full one on hydration: the fault
|
|
346
|
-
* `MixinCollection` names for a slotted collection, arriving through the one
|
|
347
|
-
* channel that mixin cannot see.
|
|
348
|
-
*
|
|
349
|
-
* The same shape as `childrenKnown`, asked of a tree that can answer about
|
|
350
|
-
* ids rather than of one that holds children. An id that resolves to nothing
|
|
351
|
-
* in a browser is still known, and still empty: a `for` naming no table
|
|
352
|
-
* should say so rather than sit blank, which is why this asks
|
|
353
|
-
* `searchableById` and not `elementById`.
|
|
354
|
-
*
|
|
355
|
-
* `readingsKnown` asks it for every chart, and for `data` too, which a
|
|
356
|
-
* server does not draw.
|
|
357
|
-
*/
|
|
358
|
-
private get sourceKnown();
|
|
359
359
|
/**
|
|
360
360
|
* `rows` as a usable count, which is not always what the attribute says.
|
|
361
361
|
*
|
|
@@ -432,6 +432,23 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
432
432
|
private markEmpty;
|
|
433
433
|
protected updated(changed: PropertyValues): void;
|
|
434
434
|
protected render(): TemplateResult;
|
|
435
|
+
/**
|
|
436
|
+
* The cells as a grid's rows, one for each column of the strip, so a week
|
|
437
|
+
* is a row with `rows="7"` and a status strip is one row.
|
|
438
|
+
*
|
|
439
|
+
* **A column, because that is the order the cells are in.** The strip fills
|
|
440
|
+
* down the column and then across, so a row wrapping a column keeps every
|
|
441
|
+
* cell where it was, and `display: contents` keeps the wrapper out of the
|
|
442
|
+
* strip's grid, drawing no box, which is a mechanism and not a look. A row
|
|
443
|
+
* across the strip would have taken cells out of order and moved them.
|
|
444
|
+
*/
|
|
445
|
+
private renderRows;
|
|
446
|
+
/**
|
|
447
|
+
* One cell under `selection-mode`: a `gridcell` named by its row in the
|
|
448
|
+
* table, its reading and its place, and saying whether it is selected, which
|
|
449
|
+
* a reader hears on reaching it as the strip's active descendant.
|
|
450
|
+
*/
|
|
451
|
+
private renderGridCell;
|
|
435
452
|
/**
|
|
436
453
|
* What the strip shows, in a sentence: the busiest reading drawn, as the
|
|
437
454
|
* table writes it, and the total of them all, in `locale`. The strip is
|
|
@@ -461,13 +478,7 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
461
478
|
* that is usually wider, so a percentage of the box lands between cells. The
|
|
462
479
|
* pitch is `cell + gap` and both are measured.
|
|
463
480
|
*/
|
|
464
|
-
protected renderTooltip(): TemplateResult | typeof nothing;
|
|
465
|
-
/**
|
|
466
|
-
* The readout's cursor: the pointer, with the selected word after where a
|
|
467
|
-
* selected cell stands, so a reader moving through the strip hears which
|
|
468
|
-
* cells are in the selection and not only how many.
|
|
469
|
-
*/
|
|
470
|
-
private reading;
|
|
481
|
+
protected renderTooltip(grid?: boolean): TemplateResult | typeof nothing;
|
|
471
482
|
/**
|
|
472
483
|
* Which drawn cell the pointer is over, or -1.
|
|
473
484
|
*
|
|
@@ -476,6 +487,7 @@ export declare class HelixHeadlessHeatmap extends HelixHeadlessHeatmap_base {
|
|
|
476
487
|
* `mouseover` it is delivered for a pen.
|
|
477
488
|
*/
|
|
478
489
|
private readonly onPointerOver;
|
|
490
|
+
private readonly onPointerUp;
|
|
479
491
|
private readonly onPointerLeave;
|
|
480
492
|
}
|
|
481
493
|
declare global {
|