@fusion.dev/helix-headless 0.147.0 → 0.148.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 +4512 -790
- package/dist/accordion/item/accordion-item.d.ts +5 -2
- package/dist/accordion/item/accordion-item.js +11 -7
- package/dist/accordion/root/accordion-root.js +4 -6
- package/dist/announcement/root/announcement-root.d.ts +56 -5
- package/dist/announcement/root/announcement-root.js +124 -21
- package/dist/area-chart/root/area-chart-root.js +3 -4
- package/dist/badge/count.d.ts +14 -0
- package/dist/badge/count.js +20 -0
- package/dist/badge/root/badge-root.js +8 -22
- package/dist/blockquote/root/blockquote-root.d.ts +66 -8
- package/dist/blockquote/root/blockquote-root.js +85 -8
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +2 -2
- package/dist/button-group/arrows.d.ts +14 -0
- package/dist/button-group/arrows.js +10 -0
- package/dist/button-group/root/button-group-root.d.ts +141 -3
- package/dist/button-group/root/button-group-root.js +142 -2
- package/dist/canvas/edge-pan.d.ts +61 -0
- package/dist/canvas/edge-pan.js +63 -0
- package/dist/canvas/node/canvas-node.d.ts +12 -2
- package/dist/canvas/node/canvas-node.js +6 -2
- package/dist/canvas/root/canvas-document.d.ts +10 -0
- package/dist/canvas/root/canvas-document.js +1 -0
- package/dist/canvas/root/canvas-root.d.ts +107 -5
- package/dist/canvas/root/canvas-root.js +140 -36
- package/dist/canvas/snap.d.ts +42 -0
- package/dist/canvas/snap.js +32 -0
- package/dist/carousel/root/carousel-root.d.ts +4 -3
- package/dist/carousel/root/carousel-root.js +2 -6
- package/dist/chat/root/chat-root.d.ts +13 -3
- package/dist/chat/root/chat-root.js +2 -6
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +13 -0
- package/dist/checkbox-group/root/checkbox-group-root.js +18 -10
- package/dist/checkbox-group/select-all.d.ts +11 -0
- package/dist/checkbox-group/select-all.js +5 -0
- package/dist/code-block/root/code-block-root.d.ts +8 -6
- package/dist/code-block/root/code-block-root.js +4 -3
- package/dist/color-picker/root/color-picker-root.js +6 -12
- package/dist/color-picker/wheel.d.ts +11 -0
- package/dist/color-picker/wheel.js +9 -0
- package/dist/combobox/root/combobox-root.d.ts +70 -11
- package/dist/combobox/root/combobox-root.js +68 -18
- package/dist/command/root/command-root.d.ts +4 -3
- package/dist/data-table/root/data-table-root.js +17 -44
- package/dist/description-list/item/description-list-item.d.ts +4 -0
- package/dist/description-list/item/description-list-item.js +7 -1
- package/dist/divider/root/divider-root.d.ts +45 -16
- package/dist/divider/root/divider-root.js +28 -4
- package/dist/drilldown/item/drilldown-item.js +3 -4
- package/dist/element-events.generated.js +1 -0
- package/dist/empty/root/empty-root.d.ts +17 -3
- package/dist/empty/root/empty-root.js +29 -5
- package/dist/file-input/root/file-input-root.js +3 -4
- package/dist/file-input/status.js +2 -1
- package/dist/filter-input/chip/filter-chip.js +2 -3
- package/dist/format-date/fields.d.ts +20 -0
- package/dist/format-date/fields.js +14 -0
- package/dist/format-date/options.d.ts +2 -1
- package/dist/format-date/options.js +9 -38
- package/dist/format-date/root/format-date-root.d.ts +35 -3
- package/dist/format-date/root/format-date-root.js +24 -32
- package/dist/graph/root/graph-root.d.ts +23 -5
- package/dist/graph/root/graph-root.js +17 -20
- package/dist/heatmap/root/heatmap-root.d.ts +12 -0
- package/dist/heatmap/root/heatmap-root.js +26 -11
- package/dist/image/root/image-root.d.ts +11 -0
- package/dist/kbd/root/kbd-root.js +1 -2
- package/dist/legend/root/legend-root.js +4 -17
- package/dist/list/root/list-root.js +8 -22
- package/dist/listbox/root/listbox-root.d.ts +119 -24
- package/dist/listbox/root/listbox-root.js +130 -132
- package/dist/map/marker/map-marker.d.ts +2 -1
- package/dist/map/root/map-root.d.ts +40 -2
- package/dist/map/root/map-root.js +64 -23
- package/dist/megamenu/root/megamenu-root.js +4 -11
- package/dist/menu/root/menu-root.d.ts +2 -2
- package/dist/navigation/root/navigation-root.js +5 -8
- package/dist/notifications/group/notification-group.d.ts +8 -1
- package/dist/notifications/group/notification-group.js +12 -6
- package/dist/notifications/notification/notification.d.ts +12 -1
- package/dist/notifications/notification/notification.js +3 -1
- package/dist/notifications/root/notifications-root.d.ts +41 -5
- package/dist/notifications/root/notifications-root.js +27 -7
- package/dist/object-inspector/root/object-inspector-root.d.ts +5 -1
- package/dist/object-inspector/root/object-inspector-root.js +21 -11
- package/dist/pagination/size/pagination-size.d.ts +1 -0
- package/dist/pagination/size/pagination-size.js +1 -1
- package/dist/pin-input/code.d.ts +23 -0
- package/dist/pin-input/code.js +25 -0
- package/dist/pin-input/root/pin-input-root.js +9 -23
- package/dist/qr-code/root/qr-code-root.d.ts +14 -3
- package/dist/qr-code/root/qr-code-root.js +19 -5
- package/dist/scatter-chart/measures.d.ts +22 -0
- package/dist/scatter-chart/measures.js +11 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +2 -6
- package/dist/scatter-chart/root/scatter-chart-root.js +6 -19
- package/dist/select/root/select-root.d.ts +56 -8
- package/dist/select/root/select-root.js +33 -9
- package/dist/speed-dial/group/speed-dial-group.d.ts +48 -0
- package/dist/speed-dial/group/speed-dial-group.js +43 -0
- package/dist/speed-dial/index.d.ts +1 -0
- package/dist/speed-dial/index.js +1 -0
- package/dist/speed-dial/item/speed-dial-item.d.ts +26 -1
- package/dist/speed-dial/item/speed-dial-item.js +41 -3
- package/dist/speed-dial/long-press.d.ts +50 -0
- package/dist/speed-dial/long-press.js +48 -0
- package/dist/speed-dial/root/speed-dial-root.d.ts +80 -1
- package/dist/speed-dial/root/speed-dial-root.js +114 -5
- package/dist/splitter/root/splitter-root.d.ts +7 -3
- package/dist/splitter/root/splitter-root.js +16 -3
- package/dist/table/cell/table-cell.d.ts +8 -1
- package/dist/table/cell/table-cell.js +6 -2
- package/dist/table/grid-controller.d.ts +117 -0
- package/dist/table/grid-controller.js +293 -0
- package/dist/table/root/table-root.d.ts +47 -3
- package/dist/table/root/table-root.js +81 -24
- package/dist/table/row/table-row.d.ts +13 -1
- package/dist/table/row/table-row.js +20 -6
- package/dist/tag/group/tag-group.js +6 -15
- package/dist/time-picker/root/time-picker-root.d.ts +1 -0
- package/dist/time-picker/root/time-picker-root.js +3 -0
- package/dist/toast/item/toast-item.d.ts +6 -3
- package/dist/toast/item/toast-item.js +1 -0
- package/dist/toast/root/toast-root.d.ts +13 -1
- package/dist/toast/root/toast-root.js +20 -14
- package/dist/toggle/group/toggle-group.js +3 -5
- package/dist/toolbar/root/toolbar-root.d.ts +31 -0
- package/dist/toolbar/root/toolbar-root.js +39 -8
- package/dist/tooltip/root/tooltip-root.js +1 -2
- package/dist/video/root/video-root.d.ts +11 -0
- package/dist/video/root/video-root.js +15 -1
- package/dist/virtual-list/root/virtual-list-root.js +6 -18
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +2005 -266
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +338 -62
- package/dist/kbd/keys.d.ts +0 -29
- package/dist/kbd/keys.js +0 -52
- package/dist/tooltip/focus-target.d.ts +0 -6
- package/dist/tooltip/focus-target.js +0 -9
|
@@ -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 { commaList, customElement, deepActiveElement, deepContains,
|
|
7
|
+
import { commaList, customElement, deepActiveElement, deepContains, focusItemOf, HelixElement, hostAria, KeyboardNavigationController, pressedValue, prunedValue, requestValue, rovingStop, slottedWords, typeaheadByWords, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { HelixHeadlessTag } from '../root/tag-root.js';
|
|
@@ -107,14 +107,11 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
|
|
|
107
107
|
return this.tags.filter((tag) => !tag.disabled);
|
|
108
108
|
}
|
|
109
109
|
navigable(tag) {
|
|
110
|
-
return {
|
|
111
|
-
contains: (node) => tag.contains(node),
|
|
110
|
+
return focusItemOf(tag, {
|
|
112
111
|
disabled: tag.disabled,
|
|
113
|
-
|
|
114
|
-
select: () => { },
|
|
115
|
-
selected: false,
|
|
112
|
+
focus: () => tag.focusItem(),
|
|
116
113
|
words: tag.words,
|
|
117
|
-
};
|
|
114
|
+
});
|
|
118
115
|
}
|
|
119
116
|
valueFor(tag) {
|
|
120
117
|
return tag.value || slottedWords(tag, ['start', '']);
|
|
@@ -146,14 +143,8 @@ let HelixHeadlessTagGroup = class HelixHeadlessTagGroup extends HelixElement {
|
|
|
146
143
|
if (mode === 'none' || tag.disabled) {
|
|
147
144
|
return;
|
|
148
145
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
this.value = value;
|
|
152
|
-
this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
|
153
|
-
},
|
|
154
|
-
event: (value) => new HelixBeforeChangeEvent({ value }),
|
|
155
|
-
host: this,
|
|
156
|
-
next: pressedValue(mode, this.written, this.valueFor(tag)),
|
|
146
|
+
requestValue(this, pressedValue(mode, this.written, this.valueFor(tag)), (value) => {
|
|
147
|
+
this.value = value;
|
|
157
148
|
});
|
|
158
149
|
}
|
|
159
150
|
connectedCallback() {
|
|
@@ -82,6 +82,7 @@ declare const HelixHeadlessTimePicker_base: (new (...args: any[]) => import("@fu
|
|
|
82
82
|
* @csspart option-label - The time's label.
|
|
83
83
|
* @csspart option-text - The label and the caption, as one column.
|
|
84
84
|
*
|
|
85
|
+
* @cssstate blank - While no time is chosen.
|
|
85
86
|
* @cssstate invalid - While `invalid` is set or `feedback` says what is wrong.
|
|
86
87
|
*/
|
|
87
88
|
export declare class HelixHeadlessTimePicker extends HelixHeadlessTimePicker_base {
|
|
@@ -256,6 +256,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
|
|
|
256
256
|
willUpdate(changed) {
|
|
257
257
|
super.willUpdate(changed);
|
|
258
258
|
this.report();
|
|
259
|
+
this.toggleState('blank', this.value === '');
|
|
259
260
|
}
|
|
260
261
|
updated(changed) {
|
|
261
262
|
super.updated(changed);
|
|
@@ -277,6 +278,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
|
|
|
277
278
|
return html `<${this.tag('listbox')}
|
|
278
279
|
part="column"
|
|
279
280
|
data-column=${part}
|
|
281
|
+
aria-describedby=${this.feedback === '' ? nothing : 'feedback'}
|
|
280
282
|
aria-invalid=${this.marked ? 'true' : nothing}
|
|
281
283
|
exportparts="empty: column-empty, error: column-error, feedback: column-feedback, filter-icon: column-filter-icon,
|
|
282
284
|
filter-mark: column-filter-mark, hint: column-hint, items: column-items, label: column-label,
|
|
@@ -328,6 +330,7 @@ let HelixHeadlessTimePicker = class HelixHeadlessTimePicker extends MixinPickerF
|
|
|
328
330
|
renderList() {
|
|
329
331
|
return html `<${this.tag('listbox')}
|
|
330
332
|
part="list"
|
|
333
|
+
aria-describedby=${this.feedback === '' ? nothing : 'feedback'}
|
|
331
334
|
aria-invalid=${this.marked ? 'true' : nothing}
|
|
332
335
|
exportparts="empty: list-empty, error: list-error, feedback: list-feedback, filter-icon: list-filter-icon,
|
|
333
336
|
filter-mark: list-filter-mark, hint: list-hint, items: list-items, label: list-label,
|
|
@@ -10,7 +10,8 @@ declare const HelixHeadlessToastItem_base: (new (...args: any[]) => import("@fus
|
|
|
10
10
|
*
|
|
11
11
|
* **Each item runs its own timer.** A timer held by the region would restart
|
|
12
12
|
* with each new message, and the last of three messages would stay for nine
|
|
13
|
-
* seconds.
|
|
13
|
+
* seconds. It pauses while the pointer or focus is on the message, and while
|
|
14
|
+
* the page is hidden, so a message is not spent in a background tab.
|
|
14
15
|
*
|
|
15
16
|
* **Each message is an `alertdialog` named by its words**, which is how a reader
|
|
16
17
|
* who moves into the stack hears which message they are on. Give it a
|
|
@@ -85,8 +86,10 @@ export declare class HelixHeadlessToastItem extends HelixHeadlessToastItem_base
|
|
|
85
86
|
/** Writes how far a swipe has moved the message toward the end of the line. */
|
|
86
87
|
private slide;
|
|
87
88
|
/**
|
|
88
|
-
* The dismiss timer, which pauses while a reader is on the message and
|
|
89
|
-
* continues from what was left.
|
|
89
|
+
* The dismiss timer, which pauses while a reader is on the message, and
|
|
90
|
+
* while the page is hidden, and continues from what was left. A message that
|
|
91
|
+
* arrives in a background tab waits for the reader to come back, as React
|
|
92
|
+
* Aria's toast queue does.
|
|
90
93
|
*
|
|
91
94
|
* Paused is said on the host so the indicator can freeze with the clock. A
|
|
92
95
|
* `data-` attribute rather than a property, because it is written after
|
|
@@ -106,12 +106,24 @@ export declare class HelixHeadlessToast extends HelixElement {
|
|
|
106
106
|
/** What the assertive region is saying. */
|
|
107
107
|
private urgent;
|
|
108
108
|
private readonly hush;
|
|
109
|
+
/**
|
|
110
|
+
* Words waiting for the next frame: the polite ones and the urgent ones.
|
|
111
|
+
*
|
|
112
|
+
* Collected rather than written straight in, because the accessibility tree
|
|
113
|
+
* is built once a frame: two messages that arrive in separate tasks of one
|
|
114
|
+
* frame would otherwise each overwrite the region, and only the second
|
|
115
|
+
* would be heard.
|
|
116
|
+
*/
|
|
117
|
+
private readonly pending;
|
|
118
|
+
/** Whether a frame is already coming to say what is pending. */
|
|
119
|
+
private filling;
|
|
109
120
|
/**
|
|
110
121
|
* Says messages that have just arrived, each once, `danger` ones assertively.
|
|
111
122
|
*
|
|
112
123
|
* Emptied first and filled a frame later, so a message with the same words
|
|
113
124
|
* as the one before is still a change, and so a region the stack has just
|
|
114
|
-
* shown is in the accessibility tree before its words land.
|
|
125
|
+
* shown is in the accessibility tree before its words land. Every message
|
|
126
|
+
* that arrives before that frame is said in it, each as its own sentence.
|
|
115
127
|
*/
|
|
116
128
|
private announce;
|
|
117
129
|
/**
|
|
@@ -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, DelayController, deepActiveElement, deepContains, FocusScopeController, fillTemplate, focusableElements, HelixElement, hostAria, scrollHolders, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { animationsFinished, customElement, DelayController, deepActiveElement, deepContains, FocusScopeController, fillTemplate, focusableElements, HelixElement, hostAria, scrollHolders, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { matchesHotkey, parseHotkey } from '../hotkey.js';
|
|
11
|
-
import { messageWords } from '../words.js';
|
|
11
|
+
import { joinSaid, messageWords } from '../words.js';
|
|
12
12
|
let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
|
|
13
13
|
constructor() {
|
|
14
14
|
super(...arguments);
|
|
@@ -17,6 +17,8 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
|
|
|
17
17
|
this.said = '';
|
|
18
18
|
this.urgent = '';
|
|
19
19
|
this.hush = new DelayController(this, { renders: false });
|
|
20
|
+
this.pending = { said: [], urgent: [] };
|
|
21
|
+
this.filling = false;
|
|
20
22
|
this.scope = new FocusScopeController(this, {
|
|
21
23
|
contents: () => this.showing.flatMap((one) => {
|
|
22
24
|
const target = focusTarget(one);
|
|
@@ -91,19 +93,25 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
|
|
|
91
93
|
});
|
|
92
94
|
}
|
|
93
95
|
announce(arrived) {
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
for (const one of arrived) {
|
|
97
|
+
const words = messageWords(one);
|
|
98
|
+
if (words !== '') {
|
|
99
|
+
;
|
|
100
|
+
(isDanger(one) ? this.pending.urgent : this.pending.said).push(words);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (this.filling || (this.pending.said.length === 0 && this.pending.urgent.length === 0)) {
|
|
100
104
|
return;
|
|
101
105
|
}
|
|
106
|
+
this.filling = true;
|
|
102
107
|
this.said = '';
|
|
103
108
|
this.urgent = '';
|
|
104
109
|
const fill = () => {
|
|
105
|
-
this.
|
|
106
|
-
this.
|
|
110
|
+
this.filling = false;
|
|
111
|
+
this.said = joinSaid(this.pending.said);
|
|
112
|
+
this.urgent = joinSaid(this.pending.urgent);
|
|
113
|
+
this.pending.said = [];
|
|
114
|
+
this.pending.urgent = [];
|
|
107
115
|
this.hush.start(1000, () => {
|
|
108
116
|
this.said = '';
|
|
109
117
|
this.urgent = '';
|
|
@@ -161,8 +169,7 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
|
|
|
161
169
|
continue;
|
|
162
170
|
}
|
|
163
171
|
this.made.delete(one);
|
|
164
|
-
|
|
165
|
-
void Promise.allSettled(running.map((animation) => animation.finished)).then(() => one.remove());
|
|
172
|
+
void animationsFinished(one).then(() => one.remove());
|
|
166
173
|
}
|
|
167
174
|
}
|
|
168
175
|
get showing() {
|
|
@@ -194,8 +201,7 @@ let HelixHeadlessToast = class HelixHeadlessToast extends HelixElement {
|
|
|
194
201
|
}
|
|
195
202
|
}
|
|
196
203
|
lowerWhenStill(region) {
|
|
197
|
-
|
|
198
|
-
void Promise.allSettled(running.map((one) => one.finished)).then(() => {
|
|
204
|
+
void animationsFinished(this).then(() => {
|
|
199
205
|
if (this.showing.length === 0 && popoverOpen(region)) {
|
|
200
206
|
region.hidePopover();
|
|
201
207
|
}
|
|
@@ -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 { commaList, customElement, DisabledCascadeController, HelixFormElement, hostAria, IndicatorController, KeyboardNavigationController, MixinControllerValue, MixinField, reportValues, rovingStop, toggleValue, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { commaList, customElement, DisabledCascadeController, HelixFormElement, hostAria, IndicatorController, KeyboardNavigationController, MixinControllerValue, MixinField, reportValues, rovingStop, toggleValue, toolbarAround, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { HelixHeadlessToggle } from '../root/toggle-root.js';
|
|
@@ -139,9 +139,7 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
139
139
|
if (!this.multiple) {
|
|
140
140
|
return 'radiogroup';
|
|
141
141
|
}
|
|
142
|
-
return this
|
|
143
|
-
? 'group'
|
|
144
|
-
: 'toolbar';
|
|
142
|
+
return toolbarAround(this) ? 'group' : 'toolbar';
|
|
145
143
|
}
|
|
146
144
|
willUpdate(changed) {
|
|
147
145
|
super.willUpdate(changed);
|
|
@@ -152,7 +150,7 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
152
150
|
this.internals.setFormValue(null);
|
|
153
151
|
}
|
|
154
152
|
else if (this.multiple) {
|
|
155
|
-
reportValues(this.internals, this.name, this.values);
|
|
153
|
+
reportValues(this.internals, this.name, this.values, { state: 'entries' });
|
|
156
154
|
}
|
|
157
155
|
else {
|
|
158
156
|
this.internals.setFormValue(this.value);
|
|
@@ -12,6 +12,10 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
12
12
|
* focus counts as a control, including your own elements. A child that takes no
|
|
13
13
|
* focus, such as a divider, is skipped. A menu is reached at its trigger.
|
|
14
14
|
*
|
|
15
|
+
* A Divider in the toolbar is a separator across the toolbar's axis, as React
|
|
16
|
+
* Aria's is: vertical in a horizontal toolbar and horizontal in a vertical
|
|
17
|
+
* one, without an `orientation` of its own.
|
|
18
|
+
*
|
|
15
19
|
* Controls inside a plain wrapper, such as a `Button Group`, are each a stop
|
|
16
20
|
* of the toolbar's own, as React Aria's toolbar flattens a group: the arrows
|
|
17
21
|
* walk through the group's buttons and on past it, and the group takes no tab
|
|
@@ -20,6 +24,28 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
20
24
|
* The arrows wrap from the last control to the first. Set `stop-at-ends` to
|
|
21
25
|
* keep them at the ends, as Radix's `loop` set to false does.
|
|
22
26
|
*
|
|
27
|
+
* **Keyboard.** Tab enters the toolbar on the control that last had focus, the
|
|
28
|
+
* first control at the start, and the next Tab leaves it.
|
|
29
|
+
*
|
|
30
|
+
* | Key | What it does |
|
|
31
|
+
* |---|---|
|
|
32
|
+
* | Right | Moves to the next control in a horizontal toolbar, from the last back to the first. |
|
|
33
|
+
* | Left | Moves to the control before in a horizontal toolbar, from the first round to the last. |
|
|
34
|
+
* | Down, Up | The same in a vertical toolbar. |
|
|
35
|
+
* | Home, End | Moves to the first or the last control. |
|
|
36
|
+
*
|
|
37
|
+
* Left and Right swap on a right-to-left page, where the first control is on
|
|
38
|
+
* the right. The arrows across the toolbar's axis are left to the control that
|
|
39
|
+
* has focus, so a radio-style toggle group or a select answers them itself.
|
|
40
|
+
* The toolbar is `role="toolbar"` with `aria-orientation`, named by `label`.
|
|
41
|
+
*
|
|
42
|
+
* The stop moves through a control's own `focusable` property where it has
|
|
43
|
+
* one, as Button, Select and Toggle Group do. A control without one has
|
|
44
|
+
* `tabindex` written on the element that takes focus: a native element
|
|
45
|
+
* itself, or the control inside a custom element's open shadow root, so the
|
|
46
|
+
* host keeps the markup you rendered. Only a custom element whose shadow root
|
|
47
|
+
* is closed takes it on the host.
|
|
48
|
+
*
|
|
23
49
|
* A toggle group of pressed buttons, `selection-mode="multiple"`, is walked
|
|
24
50
|
* through the same way, each toggle a stop on the toolbar's axis, as React
|
|
25
51
|
* Aria's toolbar walks its toggle buttons. Another nested composite, such as a
|
|
@@ -44,6 +70,10 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
44
70
|
* @slot - The toolbar's controls.
|
|
45
71
|
*
|
|
46
72
|
* @csspart toolbar - The toolbar container.
|
|
73
|
+
*
|
|
74
|
+
* @cssstate horizontal - The controls run along a row, which is the default.
|
|
75
|
+
* @cssstate nested - The toolbar is a group inside another toolbar, which owns the keys and the tab stop.
|
|
76
|
+
* @cssstate vertical - The controls run down a column, under `orientation="vertical"`.
|
|
47
77
|
*/
|
|
48
78
|
export declare class HelixHeadlessToolbar extends HelixElement {
|
|
49
79
|
/**
|
|
@@ -159,6 +189,7 @@ export declare class HelixHeadlessToolbar extends HelixElement {
|
|
|
159
189
|
connectedCallback(): void;
|
|
160
190
|
disconnectedCallback(): void;
|
|
161
191
|
protected firstUpdated(changed: PropertyValues): void;
|
|
192
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
162
193
|
protected render(): TemplateResult;
|
|
163
194
|
}
|
|
164
195
|
declare global {
|
|
@@ -5,13 +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 HelixHeadlessToolbar_1;
|
|
8
|
-
import { AriaForwardController, closestInstance, customElement, HelixElement, inlineStep, keyClaimed, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { AriaForwardController, closestInstance, customElement, HelixElement, inlineStep, keyClaimed, toolbarAround, } from '@fusion.dev/helix-core';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
11
11
|
const KEYS = new Set(['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End']);
|
|
12
12
|
const ownsTabStop = (node) => 'focusable' in node;
|
|
13
13
|
const NATIVE = 'a[href], button, input, select, textarea, [tabindex], [contenteditable=""], [contenteditable="true"]';
|
|
14
14
|
const TABBABLE = NATIVE.replace('[tabindex]', '[tabindex]:not([tabindex="-1"])');
|
|
15
|
+
const innerStops = new WeakMap();
|
|
15
16
|
const takesFocus = (node) => {
|
|
16
17
|
if (!(node instanceof HTMLElement) ||
|
|
17
18
|
node.hasAttribute('disabled') ||
|
|
@@ -21,7 +22,25 @@ const takesFocus = (node) => {
|
|
|
21
22
|
return (node.matches(NATIVE) ||
|
|
22
23
|
ownsTabStop(node) ||
|
|
23
24
|
node.shadowRoot?.delegatesFocus === true ||
|
|
24
|
-
node.shadowRoot?.querySelector(TABBABLE) != null
|
|
25
|
+
node.shadowRoot?.querySelector(TABBABLE) != null ||
|
|
26
|
+
innerStops.get(node)?.isConnected === true);
|
|
27
|
+
};
|
|
28
|
+
const stopOf = (node) => {
|
|
29
|
+
if (node.hasAttribute('tabindex')) {
|
|
30
|
+
return node;
|
|
31
|
+
}
|
|
32
|
+
const held = innerStops.get(node);
|
|
33
|
+
if (held?.isConnected && held.getRootNode() === node.shadowRoot) {
|
|
34
|
+
return held;
|
|
35
|
+
}
|
|
36
|
+
const inner = node.localName.includes('-')
|
|
37
|
+
? node.shadowRoot?.querySelector(TABBABLE)
|
|
38
|
+
: null;
|
|
39
|
+
if (!inner) {
|
|
40
|
+
return node;
|
|
41
|
+
}
|
|
42
|
+
innerStops.set(node, inner);
|
|
43
|
+
return inner;
|
|
25
44
|
};
|
|
26
45
|
const flattens = (node) => ownsTabStop(node) &&
|
|
27
46
|
node.selectionMode === 'multiple';
|
|
@@ -58,7 +77,7 @@ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar e
|
|
|
58
77
|
if (ownsTabStop(element)) {
|
|
59
78
|
return element.focusable;
|
|
60
79
|
}
|
|
61
|
-
return composite || element.tabIndex === 0;
|
|
80
|
+
return composite || stopOf(element).tabIndex === 0;
|
|
62
81
|
});
|
|
63
82
|
if (controls.length > 0 && !held) {
|
|
64
83
|
this.setTabStop(controls[0], false);
|
|
@@ -116,8 +135,9 @@ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar e
|
|
|
116
135
|
if (element && 'focusItem' in element && typeof element.focusItem === 'function') {
|
|
117
136
|
element.focusItem();
|
|
118
137
|
}
|
|
119
|
-
else {
|
|
120
|
-
|
|
138
|
+
else if (element) {
|
|
139
|
+
;
|
|
140
|
+
(ownsTabStop(element) ? element : stopOf(element)).focus();
|
|
121
141
|
}
|
|
122
142
|
};
|
|
123
143
|
}
|
|
@@ -189,7 +209,7 @@ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar e
|
|
|
189
209
|
element.focusable = stop;
|
|
190
210
|
}
|
|
191
211
|
else if (foreign || this.wroteForeign) {
|
|
192
|
-
element.tabIndex = stop ? 0 : -1;
|
|
212
|
+
stopOf(element).tabIndex = stop ? 0 : -1;
|
|
193
213
|
}
|
|
194
214
|
}
|
|
195
215
|
}
|
|
@@ -206,8 +226,7 @@ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar e
|
|
|
206
226
|
if (!parent) {
|
|
207
227
|
return false;
|
|
208
228
|
}
|
|
209
|
-
return
|
|
210
|
-
parent.closest('[role="toolbar"]') !== null);
|
|
229
|
+
return closestInstance(parent, HelixHeadlessToolbar_1) !== null || toolbarAround(this) !== null;
|
|
211
230
|
}
|
|
212
231
|
get axis() {
|
|
213
232
|
return this.orientation ?? 'horizontal';
|
|
@@ -237,6 +256,18 @@ let HelixHeadlessToolbar = HelixHeadlessToolbar_1 = class HelixHeadlessToolbar e
|
|
|
237
256
|
super.firstUpdated(changed);
|
|
238
257
|
void this.claimTabStop();
|
|
239
258
|
}
|
|
259
|
+
willUpdate(changed) {
|
|
260
|
+
super.willUpdate(changed);
|
|
261
|
+
this.toggleState('nested', this.nested);
|
|
262
|
+
this.toggleState('horizontal', this.axis === 'horizontal');
|
|
263
|
+
this.toggleState('vertical', this.axis === 'vertical');
|
|
264
|
+
if (this.hasUpdated && changed.has('orientation')) {
|
|
265
|
+
for (const child of this.children) {
|
|
266
|
+
;
|
|
267
|
+
child.requestUpdate?.();
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
240
271
|
render() {
|
|
241
272
|
const nested = this.nested;
|
|
242
273
|
return html `<div
|
|
@@ -4,10 +4,9 @@ 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 { anchorElement, arrowReach, customElement, elementById, HelixElement, hostAria, linkDescription, MixinControllerOpen, OpenPhaseController, onUnlessFalse, PopoverController, reportRuntime, sideOf, unlinkDescription, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { anchorElement, arrowReach, customElement, elementById, focusTarget, HelixElement, hostAria, linkDescription, MixinControllerOpen, OpenPhaseController, onUnlessFalse, PopoverController, reportRuntime, sideOf, unlinkDescription, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
|
-
import { focusTarget } from '../focus-target.js';
|
|
11
10
|
const GENERIC = new Set(['div', 'p', 'section', 'span']);
|
|
12
11
|
const WARMTH = Symbol.for('fusion.helix.tooltip.warmth');
|
|
13
12
|
const warmth = () => {
|
|
@@ -161,6 +161,15 @@ import '../../menu/index.js';
|
|
|
161
161
|
* @cssproperty --video-intrinsic-ratio - The media's own aspect ratio, once it is known. `--video-aspect-ratio` overrides it.
|
|
162
162
|
* @cssproperty --video-level - The current volume, 0 to 1.
|
|
163
163
|
* @cssproperty --video-progress - How far playback has reached, as a fraction of the duration.
|
|
164
|
+
*
|
|
165
|
+
* @cssstate ended - Playback reached the end, until it starts again or the source changes.
|
|
166
|
+
* @cssstate error - The source could not be played, and `failure` shows.
|
|
167
|
+
* @cssstate fullscreen - The player fills the screen.
|
|
168
|
+
* @cssstate idle - The video plays and the user has been still for `idle-delay`, so the bar hides.
|
|
169
|
+
* @cssstate muted - The sound is off.
|
|
170
|
+
* @cssstate paused - Playback is paused, which is where every player starts.
|
|
171
|
+
* @cssstate playing - Playback runs, waiting for data included.
|
|
172
|
+
* @cssstate waiting - Playback stopped to wait for more data, and `loading` shows.
|
|
164
173
|
*/
|
|
165
174
|
export declare class HelixHeadlessVideo extends HelixElement {
|
|
166
175
|
/**
|
|
@@ -452,6 +461,8 @@ export declare class HelixHeadlessVideo extends HelixElement {
|
|
|
452
461
|
*/
|
|
453
462
|
private failed;
|
|
454
463
|
private playing;
|
|
464
|
+
/** Whether playback reached the end, for `:state(ended)`. */
|
|
465
|
+
private finished;
|
|
455
466
|
private position;
|
|
456
467
|
private knownDuration;
|
|
457
468
|
private loudness;
|
|
@@ -72,6 +72,7 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
72
72
|
this.buffering = false;
|
|
73
73
|
this.failed = false;
|
|
74
74
|
this.playing = false;
|
|
75
|
+
this.finished = false;
|
|
75
76
|
this.position = 0;
|
|
76
77
|
this.knownDuration = 0;
|
|
77
78
|
this.loudness = 1;
|
|
@@ -127,6 +128,7 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
127
128
|
};
|
|
128
129
|
this.handleTime = () => {
|
|
129
130
|
this.position = this.video?.currentTime ?? 0;
|
|
131
|
+
this.finished = this.video?.ended ?? false;
|
|
130
132
|
};
|
|
131
133
|
this.handleWaiting = () => {
|
|
132
134
|
this.buffering = true;
|
|
@@ -144,7 +146,8 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
144
146
|
this.handleState = (event) => {
|
|
145
147
|
const video = this.video;
|
|
146
148
|
this.playing = video ? !video.paused : false;
|
|
147
|
-
|
|
149
|
+
this.finished = video?.ended ?? false;
|
|
150
|
+
if (event.type === 'emptied' || event.type === 'ended' || event.type === 'pause') {
|
|
148
151
|
this.buffering = false;
|
|
149
152
|
}
|
|
150
153
|
if (event.type === 'play') {
|
|
@@ -438,6 +441,14 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
438
441
|
super.updated?.(changed);
|
|
439
442
|
this.toggleAttribute('data-playing', this.playing);
|
|
440
443
|
this.toggleAttribute('data-idle', this.idle && this.playing);
|
|
444
|
+
this.toggleState('ended', this.finished);
|
|
445
|
+
this.toggleState('error', this.failed);
|
|
446
|
+
this.toggleState('fullscreen', this.full);
|
|
447
|
+
this.toggleState('idle', this.idle && this.playing);
|
|
448
|
+
this.toggleState('muted', this.silent);
|
|
449
|
+
this.toggleState('paused', !this.playing);
|
|
450
|
+
this.toggleState('playing', this.playing);
|
|
451
|
+
this.toggleState('waiting', this.buffering);
|
|
441
452
|
if (changed.has('media')) {
|
|
442
453
|
this.video?.load();
|
|
443
454
|
}
|
|
@@ -1010,6 +1021,9 @@ __decorate([
|
|
|
1010
1021
|
__decorate([
|
|
1011
1022
|
state()
|
|
1012
1023
|
], HelixHeadlessVideo.prototype, "playing", void 0);
|
|
1024
|
+
__decorate([
|
|
1025
|
+
state()
|
|
1026
|
+
], HelixHeadlessVideo.prototype, "finished", void 0);
|
|
1013
1027
|
__decorate([
|
|
1014
1028
|
state()
|
|
1015
1029
|
], HelixHeadlessVideo.prototype, "position", void 0);
|
|
@@ -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, commaList, customElement, elementById,
|
|
7
|
+
import { AriaForwardController, anchorAt, commaList, customElement, elementById, HelixElement, HelixLoadMoreEvent, HelixRangeChangeEvent, inRowOrder, isRtl, pressedOwnControl, rangeAdd, requestValue, searchableById, selectsAll, Typeahead, toggleValue, typesCharacter, VirtualizeController, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing, render } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { holdControls, releaseControls } from '../controls.js';
|
|
@@ -98,9 +98,7 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
|
|
|
98
98
|
if (at === undefined) {
|
|
99
99
|
return;
|
|
100
100
|
}
|
|
101
|
-
|
|
102
|
-
if (inner.some((node) => node instanceof HTMLElement &&
|
|
103
|
-
node.matches('a[href], button, input, select, textarea, label'))) {
|
|
101
|
+
if (pressedOwnControl(event, row, 'a[href], button, input, select, textarea, label')) {
|
|
104
102
|
return;
|
|
105
103
|
}
|
|
106
104
|
this.press(at, event.shiftKey && this.selectionMode === 'multiple');
|
|
@@ -270,8 +268,7 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
|
|
|
270
268
|
const now = commaList(this.value);
|
|
271
269
|
if (extend && mode === 'multiple') {
|
|
272
270
|
const keys = this.keys();
|
|
273
|
-
const
|
|
274
|
-
const range = rangeAdd(now, keys, from, at);
|
|
271
|
+
const range = rangeAdd(now, keys, anchorAt(keys, this.anchor, at).anchor, at);
|
|
275
272
|
if (range) {
|
|
276
273
|
this.choose(this.inOrder(range));
|
|
277
274
|
}
|
|
@@ -285,23 +282,14 @@ let HelixHeadlessVirtualList = class HelixHeadlessVirtualList extends HelixEleme
|
|
|
285
282
|
this.choose(this.inOrder(toggleValue(now, key)));
|
|
286
283
|
}
|
|
287
284
|
inOrder(keys) {
|
|
288
|
-
|
|
289
|
-
const ordered = this.keys().filter((key) => wanted.has(key));
|
|
290
|
-
const placed = new Set(ordered);
|
|
291
|
-
return [...ordered, ...keys.filter((key) => !placed.has(key))].join(',');
|
|
285
|
+
return inRowOrder(keys, this.keys()).join(',');
|
|
292
286
|
}
|
|
293
287
|
choose(next) {
|
|
294
288
|
if (next === this.value) {
|
|
295
289
|
return;
|
|
296
290
|
}
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
this.value = value;
|
|
300
|
-
this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
|
301
|
-
},
|
|
302
|
-
event: (value) => new HelixBeforeChangeEvent({ value }),
|
|
303
|
-
host: this,
|
|
304
|
-
next,
|
|
291
|
+
requestValue(this, next, (value) => {
|
|
292
|
+
this.value = value;
|
|
305
293
|
});
|
|
306
294
|
}
|
|
307
295
|
async focusIndex(index) {
|