@fusion.dev/helix-headless 0.142.1 → 0.143.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 +16710 -707
- package/dist/accordion/item/accordion-item.d.ts +38 -2
- package/dist/accordion/item/accordion-item.js +38 -6
- package/dist/accordion/root/accordion-root.d.ts +23 -1
- package/dist/accordion/root/accordion-root.js +39 -3
- package/dist/announcement/root/announcement-root.d.ts +11 -7
- package/dist/announcement/root/announcement-root.js +1 -1
- package/dist/app-header/root/app-header-root.d.ts +21 -0
- package/dist/app-header/root/app-header-root.js +31 -5
- package/dist/area-chart/root/area-chart-root.js +16 -5
- package/dist/avatar/group/avatar-group.d.ts +24 -3
- package/dist/avatar/group/avatar-group.js +34 -2
- package/dist/avatar/root/avatar-root.d.ts +3 -1
- package/dist/avatar/root/avatar-root.js +8 -1
- package/dist/badge/root/badge-root.d.ts +8 -0
- package/dist/bar-chart/root/bar-chart-root.d.ts +19 -3
- package/dist/bar-chart/root/bar-chart-root.js +43 -13
- package/dist/blockquote/root/blockquote-root.d.ts +12 -7
- package/dist/blockquote/root/blockquote-root.js +6 -4
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -3
- package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -1
- package/dist/button/root/button-root.d.ts +37 -0
- package/dist/button/root/button-root.js +44 -0
- package/dist/callout/root/callout-root.d.ts +14 -5
- package/dist/callout/root/callout-root.js +11 -3
- package/dist/canvas/root/canvas-root.d.ts +1 -0
- package/dist/canvas/root/canvas-root.js +10 -1
- package/dist/carousel/root/carousel-root.d.ts +47 -5
- package/dist/carousel/root/carousel-root.js +53 -21
- package/dist/chat/composer/chat-composer.d.ts +13 -11
- package/dist/chat/composer/chat-composer.js +6 -12
- package/dist/chat/message/chat-message.js +8 -1
- package/dist/chat/root/chat-root.d.ts +1 -0
- package/dist/chat/root/chat-root.js +2 -1
- package/dist/checkbox/root/checkbox-root.d.ts +7 -0
- package/dist/checkbox/root/checkbox-root.js +7 -3
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +65 -32
- package/dist/checkbox-group/root/checkbox-group-root.js +85 -37
- package/dist/code/root/code-root.d.ts +1 -1
- package/dist/code-block/root/code-block-root.d.ts +19 -0
- package/dist/code-block/root/code-block-root.js +21 -1
- package/dist/color-input/root/color-input-root.d.ts +26 -1
- package/dist/color-input/root/color-input-root.js +32 -3
- package/dist/color-picker/root/color-picker-root.d.ts +37 -7
- package/dist/color-picker/root/color-picker-root.js +83 -6
- package/dist/combobox/root/combobox-root.d.ts +90 -2
- package/dist/combobox/root/combobox-root.js +160 -19
- package/dist/command/root/command-root.d.ts +17 -6
- package/dist/command/root/command-root.js +12 -1
- package/dist/copy-button/root/copy-button-root.d.ts +21 -6
- package/dist/copy-button/root/copy-button-root.js +11 -1
- package/dist/data-table/root/data-table-root.d.ts +164 -10
- package/dist/data-table/root/data-table-root.js +488 -57
- package/dist/date-input/root/date-input-root.d.ts +53 -8
- package/dist/date-input/root/date-input-root.js +70 -18
- package/dist/date-picker/root/date-picker-root.d.ts +84 -17
- package/dist/date-picker/root/date-picker-root.js +125 -20
- package/dist/dialog/root/dialog-root.d.ts +38 -10
- package/dist/dialog/root/dialog-root.js +55 -2
- package/dist/donut-chart/root/donut-chart-root.d.ts +39 -15
- package/dist/donut-chart/root/donut-chart-root.js +30 -10
- package/dist/drawer/root/drawer-root.d.ts +32 -7
- package/dist/drawer/root/drawer-root.js +50 -5
- package/dist/drilldown/item/drilldown-item.d.ts +16 -13
- package/dist/drilldown/item/drilldown-item.js +6 -2
- package/dist/drilldown/root/drilldown-root.d.ts +21 -5
- package/dist/drilldown/root/drilldown-root.js +26 -10
- package/dist/element-events.generated.js +35 -9
- package/dist/file-input/root/file-input-root.d.ts +18 -1
- package/dist/file-input/root/file-input-root.js +34 -8
- package/dist/filter-input/menu/filter-menu.d.ts +9 -0
- package/dist/filter-input/menu/filter-menu.js +8 -0
- package/dist/filter-input/root/filter-input-root.d.ts +5 -2
- package/dist/filter-input/root/filter-input-root.js +22 -7
- package/dist/format-date/root/format-date-root.d.ts +11 -3
- package/dist/format-date/root/format-date-root.js +26 -5
- package/dist/graph/root/graph-root.d.ts +24 -3
- package/dist/graph/root/graph-root.js +66 -12
- package/dist/heatmap/root/buckets.d.ts +2 -1
- package/dist/heatmap/root/buckets.js +5 -1
- package/dist/heatmap/root/heatmap-root.d.ts +27 -6
- package/dist/heatmap/root/heatmap-root.js +23 -6
- package/dist/icon/root/icon-root.d.ts +24 -3
- package/dist/icon/root/icon-root.js +34 -1
- package/dist/icon-button/root/icon-button-root.d.ts +1 -1
- package/dist/image/root/image-root.d.ts +9 -2
- package/dist/image/root/image-root.js +8 -2
- package/dist/input/root/input-root.d.ts +51 -9
- package/dist/input/root/input-root.js +46 -5
- package/dist/kbd/root/kbd-root.d.ts +12 -4
- package/dist/kbd/root/kbd-root.js +10 -11
- package/dist/legend/root/legend-root.d.ts +7 -0
- package/dist/legend/root/legend-root.js +7 -2
- package/dist/lightbox/item/lightbox-item.d.ts +2 -1
- package/dist/lightbox/root/lightbox-root.d.ts +16 -5
- package/dist/lightbox/root/lightbox-root.js +24 -3
- package/dist/line-chart/root/line-chart-root.d.ts +19 -2
- package/dist/line-chart/root/line-chart-root.js +40 -13
- package/dist/list/item/list-item.d.ts +11 -5
- package/dist/list/item/list-item.js +5 -6
- package/dist/listbox/root/listbox-root.d.ts +111 -2
- package/dist/listbox/root/listbox-root.js +144 -16
- package/dist/map/root/map-root.d.ts +19 -4
- package/dist/map/root/map-root.js +36 -7
- package/dist/megamenu/root/megamenu-root.d.ts +10 -1
- package/dist/megamenu/root/megamenu-root.js +10 -1
- package/dist/menu/item/menu-item.d.ts +41 -12
- package/dist/menu/item/menu-item.js +46 -3
- package/dist/menu/root/menu-root.d.ts +32 -2
- package/dist/menu/root/menu-root.js +48 -8
- package/dist/meter/root/meter-root.d.ts +6 -0
- package/dist/meter/root/meter-root.js +18 -2
- package/dist/navigation/root/navigation-root.d.ts +10 -2
- package/dist/navigation/root/navigation-root.js +13 -2
- package/dist/notifications/group/notification-group.d.ts +1 -0
- package/dist/notifications/notification/notification.d.ts +12 -0
- package/dist/notifications/notification/notification.js +31 -2
- package/dist/notifications/root/notifications-root.d.ts +7 -0
- package/dist/notifications/root/notifications-root.js +17 -2
- package/dist/number-input/root/number-input-root.d.ts +62 -7
- package/dist/number-input/root/number-input-root.js +68 -16
- package/dist/object-inspector/root/object-inspector-root.d.ts +48 -5
- package/dist/object-inspector/root/object-inspector-root.js +91 -11
- package/dist/option/root/option-root.d.ts +4 -1
- package/dist/option/root/option-root.js +1 -0
- package/dist/outline/root/outline-root.d.ts +13 -2
- package/dist/outline/root/outline-root.js +4 -2
- package/dist/pagination/root/pagination-root.d.ts +19 -1
- package/dist/pagination/root/pagination-root.js +49 -9
- package/dist/pagination/size/pagination-size.d.ts +13 -3
- package/dist/pagination/size/pagination-size.js +7 -0
- package/dist/pin-input/root/pin-input-root.d.ts +16 -0
- package/dist/pin-input/root/pin-input-root.js +19 -5
- package/dist/popover/root/popover-root.d.ts +19 -2
- package/dist/popover/root/popover-root.js +22 -1
- package/dist/progress/root/progress-root.d.ts +16 -1
- package/dist/progress/root/progress-root.js +31 -7
- package/dist/qr-code/root/qr-code-root.d.ts +19 -0
- package/dist/qr-code/root/qr-code-root.js +29 -1
- package/dist/radio/group/radio-group.d.ts +41 -0
- package/dist/radio/group/radio-group.js +50 -14
- package/dist/radio/root/radio-root.d.ts +8 -5
- package/dist/radio/root/radio-root.js +1 -2
- package/dist/rating/root/rating-root.d.ts +24 -1
- package/dist/rating/root/rating-root.js +24 -7
- package/dist/scatter-chart/root/scatter-chart-root.js +15 -7
- package/dist/select/root/select-root.d.ts +69 -3
- package/dist/select/root/select-root.js +92 -8
- package/dist/skeleton/root/skeleton-root.d.ts +14 -3
- package/dist/skeleton/root/skeleton-root.js +17 -3
- package/dist/skip-link/root/skip-link-root.d.ts +10 -0
- package/dist/skip-link/root/skip-link-root.js +15 -1
- package/dist/slider/root/slider-root.d.ts +20 -2
- package/dist/slider/root/slider-root.js +41 -3
- package/dist/sparkline/root/sparkline-root.d.ts +9 -10
- package/dist/speed-dial/item/speed-dial-item.d.ts +11 -5
- package/dist/speed-dial/item/speed-dial-item.js +7 -2
- package/dist/speed-dial/root/speed-dial-root.d.ts +15 -4
- package/dist/speed-dial/root/speed-dial-root.js +19 -5
- package/dist/splitter/root/splitter-root.d.ts +28 -6
- package/dist/splitter/root/splitter-root.js +35 -1
- package/dist/stat/root/stat-root.d.ts +7 -1
- package/dist/stat/root/stat-root.js +14 -1
- package/dist/steps/root/steps-root.js +1 -1
- package/dist/switch/root/switch-root.d.ts +2 -0
- package/dist/switch/root/switch-root.js +1 -0
- package/dist/table/cell/table-cell.d.ts +24 -4
- package/dist/table/cell/table-cell.js +21 -1
- package/dist/table/column/table-column.d.ts +32 -6
- package/dist/table/column/table-column.js +36 -6
- package/dist/table/root/table-root.d.ts +94 -3
- package/dist/table/root/table-root.js +128 -5
- package/dist/table/row/table-row.d.ts +7 -0
- package/dist/table/row/table-row.js +9 -1
- package/dist/tabs/root/tabs-root.d.ts +6 -1
- package/dist/tabs/root/tabs-root.js +6 -2
- package/dist/tag/root/tag-root.d.ts +23 -1
- package/dist/tag/root/tag-root.js +16 -2
- package/dist/textarea/root/textarea-root.d.ts +4 -0
- package/dist/textarea/root/textarea-root.js +1 -1
- package/dist/time-input/root/time-input-root.d.ts +28 -2
- package/dist/time-input/root/time-input-root.js +46 -10
- package/dist/time-picker/root/time-picker-root.d.ts +101 -18
- package/dist/time-picker/root/time-picker-root.js +115 -16
- package/dist/toast/root/toast-root.d.ts +64 -1
- package/dist/toast/root/toast-root.js +147 -2
- package/dist/toggle/group/toggle-group.d.ts +38 -1
- package/dist/toggle/group/toggle-group.js +34 -8
- package/dist/toggle/root/toggle-root.d.ts +14 -10
- package/dist/toggle/root/toggle-root.js +3 -3
- package/dist/toolbar/root/toolbar-root.d.ts +55 -15
- package/dist/toolbar/root/toolbar-root.js +99 -16
- package/dist/tooltip/root/tooltip-root.d.ts +37 -4
- package/dist/tooltip/root/tooltip-root.js +48 -0
- package/dist/tour/root/tour-root.d.ts +34 -5
- package/dist/tour/root/tour-root.js +51 -14
- package/dist/tour/stop/tour-stop.d.ts +18 -1
- package/dist/tour/stop/tour-stop.js +25 -5
- package/dist/tree/item/tree-item.d.ts +21 -5
- package/dist/tree/item/tree-item.js +14 -4
- package/dist/tree/root/tree-root.d.ts +29 -5
- package/dist/tree/root/tree-root.js +64 -8
- package/dist/trend/root/trend-root.d.ts +23 -1
- package/dist/trend/root/trend-root.js +28 -7
- package/dist/video/root/keys.d.ts +5 -0
- package/dist/video/root/keys.js +13 -1
- package/dist/video/root/video-root.d.ts +19 -0
- package/dist/video/root/video-root.js +48 -4
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +20 -2
- package/dist/video-playlist/menu/video-playlist-menu.js +27 -5
- package/dist/video-playlist/root/video-playlist-root.js +6 -3
- package/dist/virtual-list/root/virtual-list-root.d.ts +52 -4
- package/dist/virtual-list/root/virtual-list-root.js +103 -21
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +4348 -965
- package/types/vue.d.ts +972 -232
|
@@ -4,10 +4,10 @@ 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,
|
|
7
|
+
import { customElement, deepActiveElement, deepContains, HelixActivateEvent, HelixBeforeActivateEvent, HelixCompleteEvent, HelixElement, hostAria, MixinControllerOpen, requestChange, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property, queryAssignedElements, state } from 'lit/decorators.js';
|
|
10
|
-
let HelixHeadlessTour = class HelixHeadlessTour extends HelixElement {
|
|
10
|
+
let HelixHeadlessTour = class HelixHeadlessTour extends MixinControllerOpen(HelixElement) {
|
|
11
11
|
constructor() {
|
|
12
12
|
super(...arguments);
|
|
13
13
|
this.backLabel = '';
|
|
@@ -16,7 +16,6 @@ let HelixHeadlessTour = class HelixHeadlessTour extends HelixElement {
|
|
|
16
16
|
this.indexState = undefined;
|
|
17
17
|
this.label = '';
|
|
18
18
|
this.nextLabel = '';
|
|
19
|
-
this.open = false;
|
|
20
19
|
this.skipLabel = '';
|
|
21
20
|
this.spotlightPadding = 8;
|
|
22
21
|
this.sizer = undefined;
|
|
@@ -42,6 +41,7 @@ let HelixHeadlessTour = class HelixHeadlessTour extends HelixElement {
|
|
|
42
41
|
this.handleViewport = () => {
|
|
43
42
|
this.light();
|
|
44
43
|
};
|
|
44
|
+
this.followed = false;
|
|
45
45
|
}
|
|
46
46
|
get index() {
|
|
47
47
|
return this.indexState ?? this.defaultIndex;
|
|
@@ -71,19 +71,14 @@ let HelixHeadlessTour = class HelixHeadlessTour extends HelixElement {
|
|
|
71
71
|
this.move(this.index - 1);
|
|
72
72
|
}
|
|
73
73
|
skip() {
|
|
74
|
-
|
|
75
|
-
this.dispatchEvent(event);
|
|
76
|
-
if (event.defaultPrevented) {
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
this.open = false;
|
|
74
|
+
this.requestOpen(false);
|
|
80
75
|
}
|
|
81
76
|
finish() {
|
|
82
77
|
this.dispatchEvent(new HelixCompleteEvent({ value: String(this.index) }));
|
|
83
78
|
this.open = false;
|
|
84
79
|
}
|
|
85
80
|
move(to) {
|
|
86
|
-
requestChange({
|
|
81
|
+
const moved = requestChange({
|
|
87
82
|
apply: (value) => {
|
|
88
83
|
this.index = value;
|
|
89
84
|
},
|
|
@@ -91,6 +86,9 @@ let HelixHeadlessTour = class HelixHeadlessTour extends HelixElement {
|
|
|
91
86
|
host: this,
|
|
92
87
|
next: to,
|
|
93
88
|
});
|
|
89
|
+
if (moved) {
|
|
90
|
+
this.dispatchEvent(new HelixActivateEvent({ value: String(this.index) }));
|
|
91
|
+
}
|
|
94
92
|
}
|
|
95
93
|
connectedCallback() {
|
|
96
94
|
super.connectedCallback();
|
|
@@ -113,12 +111,54 @@ let HelixHeadlessTour = class HelixHeadlessTour extends HelixElement {
|
|
|
113
111
|
}
|
|
114
112
|
willUpdate(changed) {
|
|
115
113
|
super.willUpdate(changed);
|
|
116
|
-
hostAria(this.internals, {
|
|
114
|
+
hostAria(this.internals, {
|
|
115
|
+
label: this.open ? this.label : '',
|
|
116
|
+
role: this.open ? 'region' : '',
|
|
117
|
+
});
|
|
117
118
|
}
|
|
118
119
|
updated(changed) {
|
|
119
120
|
super.updated(changed);
|
|
120
121
|
this.settle();
|
|
121
122
|
this.light();
|
|
123
|
+
this.follow(changed);
|
|
124
|
+
}
|
|
125
|
+
follow(changed) {
|
|
126
|
+
if (!this.followed) {
|
|
127
|
+
this.followed = true;
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const opened = changed.has('open') && this.open && changed.get('open') === false;
|
|
131
|
+
const closed = changed.has('open') && !this.open && changed.get('open') === true;
|
|
132
|
+
const active = deepActiveElement();
|
|
133
|
+
const inside = active === null || active === document.body || deepContains(this, active);
|
|
134
|
+
if (opened) {
|
|
135
|
+
if (active instanceof HTMLElement && !deepContains(this, active)) {
|
|
136
|
+
this.returnFocus = active;
|
|
137
|
+
}
|
|
138
|
+
this.focusCurrent();
|
|
139
|
+
}
|
|
140
|
+
else if (closed) {
|
|
141
|
+
const back = this.returnFocus;
|
|
142
|
+
this.returnFocus = undefined;
|
|
143
|
+
if (inside && back?.isConnected) {
|
|
144
|
+
back.focus();
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else if (this.open && changed.has('index') && inside) {
|
|
148
|
+
this.focusCurrent();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
focusCurrent() {
|
|
152
|
+
const stops = this.stops;
|
|
153
|
+
const stop = stops[Math.max(0, Math.min(this.index, stops.length - 1))];
|
|
154
|
+
if (!stop) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
void stop.updateComplete.then(() => {
|
|
158
|
+
if (this.open && stop.current) {
|
|
159
|
+
stop.focus();
|
|
160
|
+
}
|
|
161
|
+
});
|
|
122
162
|
}
|
|
123
163
|
settle() {
|
|
124
164
|
const stops = this.stops;
|
|
@@ -215,9 +255,6 @@ __decorate([
|
|
|
215
255
|
__decorate([
|
|
216
256
|
property({ attribute: 'next-label' })
|
|
217
257
|
], HelixHeadlessTour.prototype, "nextLabel", void 0);
|
|
218
|
-
__decorate([
|
|
219
|
-
property({ reflect: true, type: Boolean })
|
|
220
|
-
], HelixHeadlessTour.prototype, "open", void 0);
|
|
221
258
|
__decorate([
|
|
222
259
|
property({ attribute: 'skip-label' })
|
|
223
260
|
], HelixHeadlessTour.prototype, "skipLabel", void 0);
|
|
@@ -25,6 +25,10 @@ import '../../button/index.js';
|
|
|
25
25
|
* on the page from markup. It resolves against the stop's root node, so a stop
|
|
26
26
|
* inside a shadow tree points at a target in that tree.
|
|
27
27
|
*
|
|
28
|
+
* The panel is a `group`, named by the first heading in the stop's content,
|
|
29
|
+
* and only while the stop is shown. `focus()` moves focus to the panel, which
|
|
30
|
+
* is what the tour does when it opens or moves on.
|
|
31
|
+
*
|
|
28
32
|
* @since 0.1.0
|
|
29
33
|
* @status stable
|
|
30
34
|
* @category overlays
|
|
@@ -110,7 +114,20 @@ export declare class HelixHeadlessTourStop extends HelixElement {
|
|
|
110
114
|
/** The element the stop points at, or `null` when no element has the `for` id. */
|
|
111
115
|
get target(): HTMLElement | null;
|
|
112
116
|
private readonly floating;
|
|
113
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Moves focus to the panel while the stop is shown.
|
|
119
|
+
*
|
|
120
|
+
* The host draws no box and takes no focus, so focusing it did nothing. The
|
|
121
|
+
* panel takes focus without joining the `Tab` order, and a screen reader
|
|
122
|
+
* reads the group it is.
|
|
123
|
+
*/
|
|
124
|
+
focus(options?: FocusOptions): void;
|
|
125
|
+
/**
|
|
126
|
+
* Names the panel by the first heading in the content, by element
|
|
127
|
+
* reference: the heading is in the light DOM and the panel in this shadow
|
|
128
|
+
* root, which an IDREF cannot cross.
|
|
129
|
+
*/
|
|
130
|
+
private nameByHeading;
|
|
114
131
|
protected updated(changed: PropertyValues): void;
|
|
115
132
|
/**
|
|
116
133
|
* Skip, back and next, behind a seam the styled tier can move.
|
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, elementById, HelixElement, HelixTourAskEvent,
|
|
7
|
+
import { customElement, elementById, HelixElement, HelixTourAskEvent, PopoverController, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { property, state } from 'lit/decorators.js';
|
|
9
9
|
import { html } from 'lit/static-html.js';
|
|
10
10
|
import '../../button/index.js';
|
|
@@ -43,12 +43,26 @@ let HelixHeadlessTourStop = class HelixHeadlessTourStop extends HelixElement {
|
|
|
43
43
|
get target() {
|
|
44
44
|
return this.for === '' ? null : elementById(this, this.for);
|
|
45
45
|
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
focus(options) {
|
|
47
|
+
const bubble = this.partNamed('bubble');
|
|
48
|
+
if (this.current && bubble) {
|
|
49
|
+
bubble.focus(options);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
super.focus(options);
|
|
53
|
+
}
|
|
54
|
+
nameByHeading() {
|
|
55
|
+
const bubble = this.partNamed('bubble');
|
|
56
|
+
if (!bubble || !('ariaLabelledByElements' in bubble)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const heading = 'h1, h2, h3, h4, h5, h6, [role="heading"]';
|
|
60
|
+
const found = [...this.children].flatMap((one) => one.matches(heading) ? [one] : [...one.querySelectorAll(heading)])[0];
|
|
61
|
+
bubble.ariaLabelledByElements = found ? [found] : null;
|
|
49
62
|
}
|
|
50
63
|
updated(changed) {
|
|
51
64
|
super.updated(changed);
|
|
65
|
+
this.nameByHeading();
|
|
52
66
|
if (this.current) {
|
|
53
67
|
this.floating.show();
|
|
54
68
|
}
|
|
@@ -85,7 +99,13 @@ let HelixHeadlessTourStop = class HelixHeadlessTourStop extends HelixElement {
|
|
|
85
99
|
</slot>`;
|
|
86
100
|
}
|
|
87
101
|
render() {
|
|
88
|
-
return html `<div
|
|
102
|
+
return html `<div
|
|
103
|
+
part="bubble"
|
|
104
|
+
popover="manual"
|
|
105
|
+
role="group"
|
|
106
|
+
tabindex="-1"
|
|
107
|
+
?hidden=${!this.current}
|
|
108
|
+
>
|
|
89
109
|
${''}
|
|
90
110
|
<div
|
|
91
111
|
part="arrow${this.side ? { bottom: ' arrow-bottom', left: ' arrow-left', right: ' arrow-right', top: ' arrow-top' }[this.side] : ''}"
|
|
@@ -19,6 +19,10 @@ declare const HelixHeadlessTreeItem_base: (new (...args: any[]) => import("@fusi
|
|
|
19
19
|
* **`href` makes the whole row a link**, rendered as an `<a>`. Enter, middle
|
|
20
20
|
* click, and the status bar then work anywhere on the row.
|
|
21
21
|
*
|
|
22
|
+
* Pressing a branch, or Enter or Space on it, opens or closes it. A branch with
|
|
23
|
+
* a `value` is chosen as well and sends `helix-select`, unless the tree has
|
|
24
|
+
* `nesting="heading"`, where a branch names the list under it.
|
|
25
|
+
*
|
|
22
26
|
* @since 0.1.0
|
|
23
27
|
* @status stable
|
|
24
28
|
* @aliases TreeNode, Branch, Leaf
|
|
@@ -32,7 +36,7 @@ declare const HelixHeadlessTreeItem_base: (new (...args: any[]) => import("@fusi
|
|
|
32
36
|
* @event {HelixBeforeCloseEvent} helix-before-close - Fired before a branch closes, and cancelable.
|
|
33
37
|
* @event {HelixBeforeOpenEvent} helix-before-open - Fired before a branch opens, and cancelable.
|
|
34
38
|
* @event {HelixSelectEvent} helix-select - Fired when the item is chosen, and cancelable. Canceling it changes nothing.
|
|
35
|
-
* @event {
|
|
39
|
+
* @event {ToggleEvent} toggle - Sent when the branch opens or closes, with `newState` and `oldState`.
|
|
36
40
|
*
|
|
37
41
|
* @csspart group - The container for nested items.
|
|
38
42
|
* @csspart item - The node, and the focus target unless `href` moves it to the row.
|
|
@@ -46,6 +50,12 @@ declare const HelixHeadlessTreeItem_base: (new (...args: any[]) => import("@fusi
|
|
|
46
50
|
* @cssstate selected - While it is selected.
|
|
47
51
|
*/
|
|
48
52
|
export declare class HelixHeadlessTreeItem extends HelixHeadlessTreeItem_base {
|
|
53
|
+
/**
|
|
54
|
+
* @internal Set by the tree: whether a branch heads the list under it, as
|
|
55
|
+
* under `nesting="heading"`. Such a branch only opens and closes when it is
|
|
56
|
+
* pressed, because it names a list and is not a destination of its own.
|
|
57
|
+
*/
|
|
58
|
+
heads: boolean;
|
|
49
59
|
/**
|
|
50
60
|
* The URL this node links to. Setting it makes the row a link.
|
|
51
61
|
*
|
|
@@ -101,14 +111,14 @@ export declare class HelixHeadlessTreeItem extends HelixHeadlessTreeItem_base {
|
|
|
101
111
|
* Where the link opens. Use it for a row that leaves the site.
|
|
102
112
|
*/
|
|
103
113
|
target: string;
|
|
104
|
-
/**
|
|
105
|
-
* Identifies the item to your code. It is sent in `helix-select`.
|
|
106
|
-
*/
|
|
107
|
-
value: string;
|
|
108
114
|
/**
|
|
109
115
|
* Whether this item holds the tree's single tab stop.
|
|
110
116
|
*/
|
|
111
117
|
focusable: boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Identifies the item to your code. It is sent in `helix-select`.
|
|
120
|
+
*/
|
|
121
|
+
value: string;
|
|
112
122
|
/**
|
|
113
123
|
* Whether anything is slotted into `children`.
|
|
114
124
|
*
|
|
@@ -119,6 +129,12 @@ export declare class HelixHeadlessTreeItem extends HelixHeadlessTreeItem_base {
|
|
|
119
129
|
*/
|
|
120
130
|
private branch;
|
|
121
131
|
protected firstUpdated(changed: PropertyValues): void;
|
|
132
|
+
/**
|
|
133
|
+
* @internal Whether pressing this branch chooses it as well as opening or
|
|
134
|
+
* closing it: it has a value and does not head its list. Read by the tree
|
|
135
|
+
* for Enter and Space.
|
|
136
|
+
*/
|
|
137
|
+
get choosable(): boolean;
|
|
122
138
|
/**
|
|
123
139
|
* @internal Whether this row holds children, read by the tree, which moves
|
|
124
140
|
* and opens differently for a branch. Public rather than protected because
|
|
@@ -12,12 +12,13 @@ import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
|
12
12
|
let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerOpen(HelixElement) {
|
|
13
13
|
constructor() {
|
|
14
14
|
super(...arguments);
|
|
15
|
+
this.heads = false;
|
|
15
16
|
this.href = '';
|
|
16
17
|
this.rel = '';
|
|
17
18
|
this.selected = false;
|
|
18
19
|
this.target = '';
|
|
19
|
-
this.value = '';
|
|
20
20
|
this.focusable = false;
|
|
21
|
+
this.value = '';
|
|
21
22
|
this.branch = false;
|
|
22
23
|
this.handleToggleClick = (event) => {
|
|
23
24
|
event.preventDefault();
|
|
@@ -28,6 +29,9 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
|
|
|
28
29
|
const onLink = event.composedPath().some((node) => node instanceof HTMLAnchorElement);
|
|
29
30
|
if (this.branch && this.href === '') {
|
|
30
31
|
if (!onLink) {
|
|
32
|
+
if (this.choosable) {
|
|
33
|
+
this.select();
|
|
34
|
+
}
|
|
31
35
|
this.toggleOpen();
|
|
32
36
|
}
|
|
33
37
|
return;
|
|
@@ -46,6 +50,9 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
|
|
|
46
50
|
this.branch = slot.assignedElements().length > 0;
|
|
47
51
|
});
|
|
48
52
|
}
|
|
53
|
+
get choosable() {
|
|
54
|
+
return this.value !== '' && !this.heads;
|
|
55
|
+
}
|
|
49
56
|
get isBranch() {
|
|
50
57
|
return this.branch;
|
|
51
58
|
}
|
|
@@ -145,6 +152,9 @@ let HelixHeadlessTreeItem = class HelixHeadlessTreeItem extends MixinControllerO
|
|
|
145
152
|
</div>`;
|
|
146
153
|
}
|
|
147
154
|
};
|
|
155
|
+
__decorate([
|
|
156
|
+
property({ attribute: false })
|
|
157
|
+
], HelixHeadlessTreeItem.prototype, "heads", void 0);
|
|
148
158
|
__decorate([
|
|
149
159
|
property()
|
|
150
160
|
], HelixHeadlessTreeItem.prototype, "href", void 0);
|
|
@@ -160,12 +170,12 @@ __decorate([
|
|
|
160
170
|
__decorate([
|
|
161
171
|
property()
|
|
162
172
|
], HelixHeadlessTreeItem.prototype, "target", void 0);
|
|
163
|
-
__decorate([
|
|
164
|
-
property()
|
|
165
|
-
], HelixHeadlessTreeItem.prototype, "value", void 0);
|
|
166
173
|
__decorate([
|
|
167
174
|
state()
|
|
168
175
|
], HelixHeadlessTreeItem.prototype, "focusable", void 0);
|
|
176
|
+
__decorate([
|
|
177
|
+
property()
|
|
178
|
+
], HelixHeadlessTreeItem.prototype, "value", void 0);
|
|
169
179
|
__decorate([
|
|
170
180
|
state()
|
|
171
181
|
], HelixHeadlessTreeItem.prototype, "branch", void 0);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HelixElement } from '@fusion.dev/helix-core';
|
|
1
|
+
import { AriaForwardController, HelixElement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
declare const HelixHeadlessTree_base: (new (...args: any[]) => import("@fusion.dev/helix-core").CollectionElement) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerActiveInterface) & typeof HelixElement;
|
|
4
4
|
/**
|
|
@@ -13,6 +13,9 @@ declare const HelixHeadlessTree_base: (new (...args: any[]) => import("@fusion.d
|
|
|
13
13
|
* Items are found with `instanceof`, never by tag name, so the headless tier
|
|
14
14
|
* does not depend on the styled one.
|
|
15
15
|
*
|
|
16
|
+
* Typing a letter moves to the next visible item whose name starts with it,
|
|
17
|
+
* and `*` opens every branch beside the focused item.
|
|
18
|
+
*
|
|
16
19
|
* @since 0.1.0
|
|
17
20
|
* @status stable
|
|
18
21
|
* @category navigation
|
|
@@ -33,8 +36,15 @@ declare const HelixHeadlessTree_base: (new (...args: any[]) => import("@fusion.d
|
|
|
33
36
|
export declare class HelixHeadlessTree extends HelixHeadlessTree_base {
|
|
34
37
|
/**
|
|
35
38
|
* Accessible name for the tree.
|
|
39
|
+
*
|
|
40
|
+
* An `aria-label` or `aria-labelledby` on the host names the tree too, and
|
|
41
|
+
* wins over this.
|
|
36
42
|
*/
|
|
37
43
|
label: string;
|
|
44
|
+
/** Carries a host `aria-label` and `aria-labelledby` to the tree. */
|
|
45
|
+
protected readonly aria: AriaForwardController;
|
|
46
|
+
/** The letters typed so far, for moving to an item by its name. */
|
|
47
|
+
private readonly typeahead;
|
|
38
48
|
/**
|
|
39
49
|
* What a deeper level means: `peer` for no change, `subordinate` for a lower
|
|
40
50
|
* rank, or `heading` for a parent that heads the items under it.
|
|
@@ -98,16 +108,30 @@ export declare class HelixHeadlessTree extends HelixHeadlessTree_base {
|
|
|
98
108
|
* so an item moved in the tree gets the right indent without knowing it moved.
|
|
99
109
|
*/
|
|
100
110
|
private syncItems;
|
|
111
|
+
/** The nearest item around `item` that a reader can see, if any. */
|
|
112
|
+
private visibleAncestor;
|
|
113
|
+
/**
|
|
114
|
+
* Moves to the next visible item whose name starts with the letters typed,
|
|
115
|
+
* or opens every branch beside the focused item on `*`.
|
|
116
|
+
*
|
|
117
|
+
* Returns whether the press was one of those.
|
|
118
|
+
*/
|
|
119
|
+
private handleTyping;
|
|
101
120
|
private move;
|
|
102
121
|
private focusOn;
|
|
103
122
|
private readonly handleKeydown;
|
|
104
123
|
/**
|
|
105
124
|
* A branch opened or closed, whoever did it.
|
|
106
125
|
*
|
|
107
|
-
* Listening for the item's own
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
126
|
+
* Listening for the item's own `toggle` rather than calling `syncItems` from
|
|
127
|
+
* each keyboard path: that misses the pointer, and collapsing a branch by
|
|
128
|
+
* clicking its row then left the tree's one tab stop on a row inside the
|
|
129
|
+
* subtree just hidden, so Tab passed over the tree. It also covers a
|
|
130
|
+
* consumer setting `open` directly.
|
|
131
|
+
*
|
|
132
|
+
* **In capture**, because `toggle` does not bubble, which is the platform's
|
|
133
|
+
* shape for it. The `helix-before-*` pair this listened for does not bubble
|
|
134
|
+
* either, and is sent before the branch has moved.
|
|
111
135
|
*/
|
|
112
136
|
private readonly handleBranch;
|
|
113
137
|
connectedCallback(): void;
|
|
@@ -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 { closestInstance, customElement, HelixElement, inlineStep, MixinCollection, MixinControllerActive, scrollItemIntoView, whenHydrated, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, closestInstance, customElement, HelixElement, inlineStep, keyClaimed, MixinCollection, MixinControllerActive, scrollItemIntoView, slottedWords, Typeahead, typesCharacter, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { HelixHeadlessTreeItem } from '../item/tree-item.js';
|
|
@@ -22,7 +22,16 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
|
|
|
22
22
|
constructor() {
|
|
23
23
|
super(...arguments);
|
|
24
24
|
this.label = 'Tree';
|
|
25
|
+
this.aria = new AriaForwardController(this, {
|
|
26
|
+
label: true,
|
|
27
|
+
target: () => this.partNamed('tree'),
|
|
28
|
+
});
|
|
29
|
+
this.typeahead = new Typeahead();
|
|
25
30
|
this.handleSelection = (event) => {
|
|
31
|
+
const origin = event.target;
|
|
32
|
+
if (!(origin instanceof HelixHeadlessTreeItem) || !this.items.includes(origin)) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
26
35
|
if (!event.defaultPrevented) {
|
|
27
36
|
this.requestActive(event.detail.value);
|
|
28
37
|
}
|
|
@@ -30,9 +39,17 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
|
|
|
30
39
|
};
|
|
31
40
|
this.handleKeydown = (event) => {
|
|
32
41
|
const current = closestInstance(event.target, HelixHeadlessTreeItem);
|
|
33
|
-
if (!current || !this.items.includes(current)
|
|
42
|
+
if (!current || !this.items.includes(current)) {
|
|
34
43
|
return;
|
|
35
44
|
}
|
|
45
|
+
if (this.handleTyping(current, event)) {
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (!KEYS.has(event.key)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
this.typeahead.reset();
|
|
36
53
|
const along = inlineStep(this, event.key);
|
|
37
54
|
if (event.key === 'ArrowDown') {
|
|
38
55
|
this.move(current, 1);
|
|
@@ -67,6 +84,9 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
|
|
|
67
84
|
}
|
|
68
85
|
else {
|
|
69
86
|
if (current.isBranch) {
|
|
87
|
+
if (current.choosable) {
|
|
88
|
+
current.select();
|
|
89
|
+
}
|
|
70
90
|
current.toggleOpen();
|
|
71
91
|
this.syncItems();
|
|
72
92
|
}
|
|
@@ -98,8 +118,10 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
|
|
|
98
118
|
syncItems() {
|
|
99
119
|
const visible = this.visibleItems;
|
|
100
120
|
const chosen = this.resolveActive(visible);
|
|
101
|
-
const held = visible.find((item) => item.focusable)
|
|
121
|
+
const held = visible.find((item) => item.focusable) ??
|
|
122
|
+
this.visibleAncestor(this.items.find((item) => item.focusable));
|
|
102
123
|
const stop = held ?? chosen;
|
|
124
|
+
const heads = this.nesting === 'heading';
|
|
103
125
|
for (const item of this.items) {
|
|
104
126
|
const selected = item.value !== '' && item.value === this.active;
|
|
105
127
|
const focusable = item === stop;
|
|
@@ -115,9 +137,45 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
|
|
|
115
137
|
item.selected = selected;
|
|
116
138
|
item.focusable = focusable;
|
|
117
139
|
item.level = level;
|
|
140
|
+
item.heads = heads;
|
|
118
141
|
});
|
|
119
142
|
}
|
|
120
143
|
}
|
|
144
|
+
visibleAncestor(item) {
|
|
145
|
+
const visible = this.visibleItems;
|
|
146
|
+
let node = item?.parentElement ?? null;
|
|
147
|
+
while (node && node !== this) {
|
|
148
|
+
if (node instanceof HelixHeadlessTreeItem && visible.includes(node)) {
|
|
149
|
+
return node;
|
|
150
|
+
}
|
|
151
|
+
node = node.parentElement;
|
|
152
|
+
}
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
handleTyping(current, event) {
|
|
156
|
+
if (!typesCharacter(event) || keyClaimed(event)) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
if (event.key === ' ' && !this.typeahead.typing()) {
|
|
160
|
+
return false;
|
|
161
|
+
}
|
|
162
|
+
if (event.key === '*') {
|
|
163
|
+
const siblings = [...(current.parentElement?.children ?? [])].filter((node) => node instanceof HelixHeadlessTreeItem && node.slot === current.slot);
|
|
164
|
+
for (const sibling of siblings) {
|
|
165
|
+
if (sibling.isBranch && !sibling.open) {
|
|
166
|
+
sibling.requestOpen(true);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
this.syncItems();
|
|
170
|
+
return true;
|
|
171
|
+
}
|
|
172
|
+
const visible = this.visibleItems;
|
|
173
|
+
const at = this.typeahead.match(event.key, visible.map((item) => slottedWords(item, [''])), visible.indexOf(current));
|
|
174
|
+
if (at >= 0) {
|
|
175
|
+
this.focusOn(visible[at]);
|
|
176
|
+
}
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
121
179
|
move(from, delta) {
|
|
122
180
|
const visible = this.visibleItems;
|
|
123
181
|
const index = visible.indexOf(from);
|
|
@@ -137,8 +195,7 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
|
|
|
137
195
|
connectedCallback() {
|
|
138
196
|
super.connectedCallback();
|
|
139
197
|
this.addEventListener('helix-select', this.handleSelection);
|
|
140
|
-
this.addEventListener('
|
|
141
|
-
this.addEventListener('helix-before-close', this.handleBranch);
|
|
198
|
+
this.addEventListener('toggle', this.handleBranch, true);
|
|
142
199
|
this.addEventListener('keydown', this.handleKeydown);
|
|
143
200
|
this.watcher = new MutationObserver(() => this.syncItems());
|
|
144
201
|
this.watcher.observe(this, { childList: true, subtree: true });
|
|
@@ -146,8 +203,7 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
|
|
|
146
203
|
disconnectedCallback() {
|
|
147
204
|
super.disconnectedCallback();
|
|
148
205
|
this.removeEventListener('helix-select', this.handleSelection);
|
|
149
|
-
this.removeEventListener('
|
|
150
|
-
this.removeEventListener('helix-before-close', this.handleBranch);
|
|
206
|
+
this.removeEventListener('toggle', this.handleBranch, true);
|
|
151
207
|
this.removeEventListener('keydown', this.handleKeydown);
|
|
152
208
|
this.watcher?.disconnect();
|
|
153
209
|
this.watcher = undefined;
|
|
@@ -158,7 +214,7 @@ let HelixHeadlessTree = class HelixHeadlessTree extends MixinCollection(MixinCon
|
|
|
158
214
|
}
|
|
159
215
|
updated(changed) {
|
|
160
216
|
super.updated(changed);
|
|
161
|
-
if (changed.has('active')) {
|
|
217
|
+
if (changed.has('active') || changed.has('nesting')) {
|
|
162
218
|
this.syncItems();
|
|
163
219
|
}
|
|
164
220
|
}
|
|
@@ -16,7 +16,8 @@ import { type TemplateResult } from 'lit';
|
|
|
16
16
|
*
|
|
17
17
|
* The direction is also written as a word, so a screen reader reads it. The
|
|
18
18
|
* styled tier hides `part="direction"` visually and keeps it in the
|
|
19
|
-
* accessibility tree.
|
|
19
|
+
* accessibility tree. The words are properties, `up-label` through
|
|
20
|
+
* `worse-label`, so a page in another language can set its own.
|
|
20
21
|
*
|
|
21
22
|
* The metric and the label are bare slots. An element that assigned its own
|
|
22
23
|
* slot on connect would add an attribute to its host after upgrade, which the
|
|
@@ -35,6 +36,10 @@ import { type TemplateResult } from 'lit';
|
|
|
35
36
|
* @csspart icon - The arrow.
|
|
36
37
|
*/
|
|
37
38
|
export declare class HelixHeadlessTrend extends HelixElement {
|
|
39
|
+
/**
|
|
40
|
+
* The word read out after the direction when the move is an improvement.
|
|
41
|
+
*/
|
|
42
|
+
betterLabel: string;
|
|
38
43
|
/**
|
|
39
44
|
* Which way the measurement moved.
|
|
40
45
|
*
|
|
@@ -46,6 +51,10 @@ export declare class HelixHeadlessTrend extends HelixElement {
|
|
|
46
51
|
* and reports as a hydration mismatch.
|
|
47
52
|
*/
|
|
48
53
|
direction?: 'down' | 'neutral' | 'up';
|
|
54
|
+
/**
|
|
55
|
+
* The word read out for a move down.
|
|
56
|
+
*/
|
|
57
|
+
downLabel: string;
|
|
49
58
|
/**
|
|
50
59
|
* Which direction counts as an improvement for this metric.
|
|
51
60
|
*
|
|
@@ -55,6 +64,19 @@ export declare class HelixHeadlessTrend extends HelixElement {
|
|
|
55
64
|
* direction changes underneath.
|
|
56
65
|
*/
|
|
57
66
|
good?: 'down' | 'up';
|
|
67
|
+
/**
|
|
68
|
+
* The word read out for no move, or for a direction that is not one of the
|
|
69
|
+
* three.
|
|
70
|
+
*/
|
|
71
|
+
unchangedLabel: string;
|
|
72
|
+
/**
|
|
73
|
+
* The word read out for a move up.
|
|
74
|
+
*/
|
|
75
|
+
upLabel: string;
|
|
76
|
+
/**
|
|
77
|
+
* The word read out after the direction when the move is a setback.
|
|
78
|
+
*/
|
|
79
|
+
worseLabel: string;
|
|
58
80
|
protected render(): TemplateResult;
|
|
59
81
|
}
|
|
60
82
|
declare global {
|
|
@@ -10,18 +10,24 @@ import { html } from 'lit';
|
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
12
|
const DIRECTIONS = {
|
|
13
|
-
down: { icon: arrowDown, word: '
|
|
14
|
-
neutral: { icon: minus, word: '
|
|
15
|
-
up: { icon: arrowUp, word: '
|
|
13
|
+
down: { icon: arrowDown, word: 'downLabel' },
|
|
14
|
+
neutral: { icon: minus, word: 'unchangedLabel' },
|
|
15
|
+
up: { icon: arrowUp, word: 'upLabel' },
|
|
16
16
|
};
|
|
17
17
|
const readDirection = (value) => DIRECTIONS[value] ?? DIRECTIONS.neutral;
|
|
18
18
|
let HelixHeadlessTrend = class HelixHeadlessTrend extends HelixElement {
|
|
19
|
+
constructor() {
|
|
20
|
+
super(...arguments);
|
|
21
|
+
this.betterLabel = 'better';
|
|
22
|
+
this.downLabel = 'Down';
|
|
23
|
+
this.unchangedLabel = 'Unchanged';
|
|
24
|
+
this.upLabel = 'Up';
|
|
25
|
+
this.worseLabel = 'worse';
|
|
26
|
+
}
|
|
19
27
|
render() {
|
|
20
28
|
const direction = readDirection(this.direction);
|
|
21
29
|
const judgment = this.good && this.direction && this.direction !== 'neutral'
|
|
22
|
-
? this.good === this.direction
|
|
23
|
-
? ', better'
|
|
24
|
-
: ', worse'
|
|
30
|
+
? `, ${this.good === this.direction ? this.betterLabel : this.worseLabel}`
|
|
25
31
|
: '';
|
|
26
32
|
return html `<svg
|
|
27
33
|
aria-hidden="true"
|
|
@@ -32,17 +38,32 @@ let HelixHeadlessTrend = class HelixHeadlessTrend extends HelixElement {
|
|
|
32
38
|
>
|
|
33
39
|
${unsafeSVG(direction.icon.content)}
|
|
34
40
|
</svg>
|
|
35
|
-
<span part="direction">${`${direction.word}${judgment}`}</span>
|
|
41
|
+
<span part="direction">${`${this[direction.word]}${judgment}`}</span>
|
|
36
42
|
<slot></slot>
|
|
37
43
|
<slot name="label"></slot>`;
|
|
38
44
|
}
|
|
39
45
|
};
|
|
46
|
+
__decorate([
|
|
47
|
+
property({ attribute: 'better-label' })
|
|
48
|
+
], HelixHeadlessTrend.prototype, "betterLabel", void 0);
|
|
40
49
|
__decorate([
|
|
41
50
|
property({ reflect: true })
|
|
42
51
|
], HelixHeadlessTrend.prototype, "direction", void 0);
|
|
52
|
+
__decorate([
|
|
53
|
+
property({ attribute: 'down-label' })
|
|
54
|
+
], HelixHeadlessTrend.prototype, "downLabel", void 0);
|
|
43
55
|
__decorate([
|
|
44
56
|
property({ reflect: true })
|
|
45
57
|
], HelixHeadlessTrend.prototype, "good", void 0);
|
|
58
|
+
__decorate([
|
|
59
|
+
property({ attribute: 'unchanged-label' })
|
|
60
|
+
], HelixHeadlessTrend.prototype, "unchangedLabel", void 0);
|
|
61
|
+
__decorate([
|
|
62
|
+
property({ attribute: 'up-label' })
|
|
63
|
+
], HelixHeadlessTrend.prototype, "upLabel", void 0);
|
|
64
|
+
__decorate([
|
|
65
|
+
property({ attribute: 'worse-label' })
|
|
66
|
+
], HelixHeadlessTrend.prototype, "worseLabel", void 0);
|
|
46
67
|
HelixHeadlessTrend = __decorate([
|
|
47
68
|
customElement('helix-headless-trend')
|
|
48
69
|
], HelixHeadlessTrend);
|
|
@@ -21,5 +21,10 @@ export interface KeyActions {
|
|
|
21
21
|
* Nothing is taken while focus is in a range. The scrubber and the volume are
|
|
22
22
|
* real inputs and the arrows are already theirs, so intercepting would mean
|
|
23
23
|
* seeking twice for one press.
|
|
24
|
+
*
|
|
25
|
+
* **Nor a press a control already handled, nor Space on a control.** Space is
|
|
26
|
+
* how a button is pressed, so Space on Mute played the video and left it
|
|
27
|
+
* unmuted, and a menu row chosen with Space also toggled playback. A key a
|
|
28
|
+
* menu or a control took for itself arrives here already refused.
|
|
24
29
|
*/
|
|
25
30
|
export declare const takeKey: (event: KeyboardEvent, video: HTMLVideoElement, actions: KeyActions) => boolean;
|