@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,14 +4,16 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { AriaForwardController, customElement, DisabledCascadeController, HelixFilterEvent, HelixFormElement, hostAria, MixinCollection, MixinControllerValue, MixinField, reportValues, requestChange, scrollItemIntoView, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, customElement, DisabledCascadeController, HelixFilterEvent, HelixFormElement, hostAria, MixinCollection, MixinControllerValue, MixinField, reportValues, requestChange, scrollItemIntoView, Typeahead, typesCharacter, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { magnifyingGlass } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
12
|
import { HelixHeadlessOptionGroup } from '../../option/group/option-group.js';
|
|
13
13
|
import { HelixHeadlessOption } from '../../option/root/option-root.js';
|
|
14
|
-
const MOVES = new Set(['ArrowDown', 'ArrowUp', 'End', 'Home']);
|
|
14
|
+
const MOVES = new Set(['ArrowDown', 'ArrowUp', 'End', 'Home', 'PageDown', 'PageUp']);
|
|
15
|
+
const FIELD_MOVES = new Set(['ArrowDown', 'ArrowUp', 'PageDown', 'PageUp']);
|
|
16
|
+
const PAGE = 10;
|
|
15
17
|
const matched = new Map();
|
|
16
18
|
const HIGHLIGHT = 'helix-filter-match';
|
|
17
19
|
const paintable = () => typeof CSS !== 'undefined' && 'highlights' in CSS && typeof Highlight !== 'undefined';
|
|
@@ -67,8 +69,12 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
67
69
|
this.filterState = undefined;
|
|
68
70
|
this.filterable = false;
|
|
69
71
|
this.filterLabel = 'Filter';
|
|
72
|
+
this.manual = false;
|
|
70
73
|
this.multiple = false;
|
|
71
74
|
this.activeValue = '';
|
|
75
|
+
this.parked = false;
|
|
76
|
+
this.typeahead = new Typeahead();
|
|
77
|
+
this.seen = new Set();
|
|
72
78
|
this.forwarded = false;
|
|
73
79
|
this.hasMatches = true;
|
|
74
80
|
this.counted = false;
|
|
@@ -88,39 +94,70 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
88
94
|
if (shown.length === 0) {
|
|
89
95
|
return;
|
|
90
96
|
}
|
|
91
|
-
|
|
92
|
-
|
|
97
|
+
const typing = this.forwarded || event.composedPath()[0] === this.partNamed('search-field');
|
|
98
|
+
if (event.key === 'Enter' || (event.key === ' ' && !typing && !this.typeahead.typing())) {
|
|
93
99
|
if (this.activeValue !== '') {
|
|
100
|
+
event.preventDefault();
|
|
94
101
|
this.choose(this.activeValue);
|
|
95
102
|
}
|
|
103
|
+
else if (event.key === ' ') {
|
|
104
|
+
event.preventDefault();
|
|
105
|
+
}
|
|
96
106
|
return;
|
|
97
107
|
}
|
|
98
|
-
if (
|
|
108
|
+
if (this.multiple &&
|
|
109
|
+
!typing &&
|
|
110
|
+
event.key.toLowerCase() === 'a' &&
|
|
111
|
+
(event.ctrlKey || event.metaKey) &&
|
|
112
|
+
!event.altKey) {
|
|
113
|
+
event.preventDefault();
|
|
114
|
+
const reachable = shown.map((option) => option.value);
|
|
115
|
+
const all = reachable.every((value) => this.values.includes(value));
|
|
116
|
+
const kept = this.values.filter((value) => !reachable.includes(value));
|
|
117
|
+
this.requestValue((all ? kept : [...kept, ...reachable]).join(','));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!typing && typesCharacter(event)) {
|
|
121
|
+
event.preventDefault();
|
|
122
|
+
const value = this.typeaheadTo(event.key);
|
|
123
|
+
if (value !== undefined) {
|
|
124
|
+
this.arrive(value);
|
|
125
|
+
}
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (!(typing ? FIELD_MOVES : MOVES).has(event.key)) {
|
|
99
129
|
return;
|
|
100
130
|
}
|
|
101
131
|
event.preventDefault();
|
|
132
|
+
this.typeahead.reset();
|
|
102
133
|
const from = this.currentValue;
|
|
103
134
|
const at = shown.findIndex((option) => option.value === from);
|
|
135
|
+
const last = shown.length - 1;
|
|
104
136
|
let next = at;
|
|
105
137
|
if (event.key === 'ArrowDown') {
|
|
106
138
|
next = at < 0 ? 0 : (at + 1) % shown.length;
|
|
107
139
|
}
|
|
108
140
|
else if (event.key === 'ArrowUp') {
|
|
109
|
-
next = at < 0 ?
|
|
141
|
+
next = at < 0 ? last : (at - 1 + shown.length) % shown.length;
|
|
110
142
|
}
|
|
111
143
|
else if (event.key === 'Home') {
|
|
112
144
|
next = 0;
|
|
113
145
|
}
|
|
146
|
+
else if (event.key === 'End') {
|
|
147
|
+
next = last;
|
|
148
|
+
}
|
|
149
|
+
else if (event.key === 'PageDown') {
|
|
150
|
+
next = at < 0 ? 0 : Math.min(at + this.pageSize(), last);
|
|
151
|
+
}
|
|
114
152
|
else {
|
|
115
|
-
next =
|
|
153
|
+
next = at < 0 ? last : Math.max(at - this.pageSize(), 0);
|
|
116
154
|
}
|
|
117
155
|
const target = shown[next];
|
|
118
|
-
if (
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
this.choose(target.value);
|
|
156
|
+
if (target) {
|
|
157
|
+
this.arrive(target.value);
|
|
158
|
+
if (this.multiple && !typing && event.shiftKey && !this.values.includes(target.value)) {
|
|
159
|
+
this.choose(target.value);
|
|
160
|
+
}
|
|
124
161
|
}
|
|
125
162
|
};
|
|
126
163
|
this.handleFilter = (event) => {
|
|
@@ -138,7 +175,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
138
175
|
this.requestFilter('');
|
|
139
176
|
return;
|
|
140
177
|
}
|
|
141
|
-
if (!
|
|
178
|
+
if (!FIELD_MOVES.has(event.key)) {
|
|
142
179
|
return;
|
|
143
180
|
}
|
|
144
181
|
event.stopPropagation();
|
|
@@ -160,6 +197,42 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
160
197
|
const option = this.options[at];
|
|
161
198
|
this.value = option?.value ?? '';
|
|
162
199
|
}
|
|
200
|
+
highlight(where) {
|
|
201
|
+
const shown = this.shown.filter((option) => !option.disabled);
|
|
202
|
+
this.typeahead.reset();
|
|
203
|
+
this.parked = where === 'none';
|
|
204
|
+
if (where === 'none') {
|
|
205
|
+
this.activeValue = '';
|
|
206
|
+
}
|
|
207
|
+
else if (where === 'first') {
|
|
208
|
+
this.activeValue = shown[0]?.value ?? '';
|
|
209
|
+
}
|
|
210
|
+
else if (where === 'last') {
|
|
211
|
+
this.activeValue = shown.at(-1)?.value ?? '';
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
const chosen = shown.find((option) => this.values.includes(option.value));
|
|
215
|
+
this.activeValue = (chosen ?? shown[0])?.value ?? '';
|
|
216
|
+
}
|
|
217
|
+
if (this.childrenKnown) {
|
|
218
|
+
this.place();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
typeaheadTo(key) {
|
|
222
|
+
const shown = this.shown.filter((option) => !option.disabled);
|
|
223
|
+
const from = shown.findIndex((option) => option.value === this.currentValue);
|
|
224
|
+
const at = this.typeahead.match(key, shown.map((option) => option.text), from);
|
|
225
|
+
const target = shown[at];
|
|
226
|
+
if (!target) {
|
|
227
|
+
return undefined;
|
|
228
|
+
}
|
|
229
|
+
this.parked = false;
|
|
230
|
+
this.activeValue = target.value;
|
|
231
|
+
return target.value;
|
|
232
|
+
}
|
|
233
|
+
get typing() {
|
|
234
|
+
return this.typeahead.typing();
|
|
235
|
+
}
|
|
163
236
|
get type() {
|
|
164
237
|
return this.multiple ? 'select-multiple' : 'select-one';
|
|
165
238
|
}
|
|
@@ -218,6 +291,19 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
218
291
|
}
|
|
219
292
|
this.requestValue(joined);
|
|
220
293
|
}
|
|
294
|
+
arrive(value) {
|
|
295
|
+
this.parked = false;
|
|
296
|
+
this.activeValue = value;
|
|
297
|
+
if (!this.multiple && !this.manual && !this.forwarded) {
|
|
298
|
+
this.choose(value);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
pageSize() {
|
|
302
|
+
const items = this.partNamed('items');
|
|
303
|
+
const row = this.shown[0]?.getBoundingClientRect().height ?? 0;
|
|
304
|
+
const height = items?.clientHeight ?? 0;
|
|
305
|
+
return row > 0 && height > 0 ? Math.max(1, Math.floor(height / row) - 1) : PAGE;
|
|
306
|
+
}
|
|
221
307
|
navigate(event) {
|
|
222
308
|
this.forwarded = true;
|
|
223
309
|
try {
|
|
@@ -247,6 +333,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
247
333
|
}
|
|
248
334
|
}
|
|
249
335
|
place() {
|
|
336
|
+
this.forgetRemoved();
|
|
250
337
|
const needle = this.filter.trim().toLowerCase();
|
|
251
338
|
const chosen = new Set(this.values);
|
|
252
339
|
for (const option of this.options) {
|
|
@@ -258,7 +345,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
258
345
|
group.hidden = inside.length > 0 && inside.every((option) => option.hidden);
|
|
259
346
|
}
|
|
260
347
|
const shown = this.shown;
|
|
261
|
-
const rescue = needle !== '' || this.activeValue !== '';
|
|
348
|
+
const rescue = !this.parked && (needle !== '' || this.activeValue !== '');
|
|
262
349
|
if (rescue && !shown.some((option) => option.value === this.activeValue)) {
|
|
263
350
|
this.activeValue = shown.find((option) => !option.disabled)?.value ?? '';
|
|
264
351
|
}
|
|
@@ -278,6 +365,21 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
278
365
|
}
|
|
279
366
|
this.counted = true;
|
|
280
367
|
}
|
|
368
|
+
get owned() {
|
|
369
|
+
const root = this.getRootNode();
|
|
370
|
+
return root instanceof ShadowRoot && root.host.localName.startsWith('helix-');
|
|
371
|
+
}
|
|
372
|
+
forgetRemoved() {
|
|
373
|
+
if (this.owned) {
|
|
374
|
+
return;
|
|
375
|
+
}
|
|
376
|
+
const present = new Set(this.options.map((option) => option.value));
|
|
377
|
+
const gone = this.values.filter((value) => this.seen.has(value) && !present.has(value));
|
|
378
|
+
this.seen = present;
|
|
379
|
+
if (gone.length > 0) {
|
|
380
|
+
this.value = this.values.filter((value) => !gone.includes(value)).join(',');
|
|
381
|
+
}
|
|
382
|
+
}
|
|
281
383
|
followActive() {
|
|
282
384
|
const active = this.shown.find((option) => option.value === this.activeValue);
|
|
283
385
|
if (active) {
|
|
@@ -309,10 +411,31 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
309
411
|
willUpdate(changed) {
|
|
310
412
|
super.willUpdate(changed);
|
|
311
413
|
hostAria(this.internals, { role: '' });
|
|
414
|
+
if (changed.has('value') &&
|
|
415
|
+
!this.multiple &&
|
|
416
|
+
this.activeValue !== '' &&
|
|
417
|
+
!this.values.includes(this.activeValue)) {
|
|
418
|
+
this.activeValue = '';
|
|
419
|
+
this.typeahead.reset();
|
|
420
|
+
}
|
|
421
|
+
if (this.childrenKnown) {
|
|
422
|
+
this.seedDeclared();
|
|
423
|
+
}
|
|
312
424
|
if (this.childrenKnown) {
|
|
313
425
|
this.place();
|
|
314
426
|
}
|
|
315
427
|
}
|
|
428
|
+
seedDeclared() {
|
|
429
|
+
if (this.owned || this.defaultValue !== '' || this.hasAttribute('default-value')) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
const declared = this.options
|
|
433
|
+
.filter((option) => option.defaultSelected)
|
|
434
|
+
.map((option) => option.value);
|
|
435
|
+
if (declared.length > 0) {
|
|
436
|
+
this.defaultValue = this.multiple ? declared.join(',') : (declared.at(-1) ?? '');
|
|
437
|
+
}
|
|
438
|
+
}
|
|
316
439
|
get currentValue() {
|
|
317
440
|
return this.activeValue || (this.value.split(',')[0] ?? '');
|
|
318
441
|
}
|
|
@@ -338,6 +461,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
338
461
|
apply: (value) => {
|
|
339
462
|
const previous = this.filter;
|
|
340
463
|
this.filterState = value;
|
|
464
|
+
this.parked = false;
|
|
341
465
|
this.requestUpdate('filter', previous);
|
|
342
466
|
},
|
|
343
467
|
event: (value) => new HelixFilterEvent({ value }),
|
|
@@ -376,6 +500,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
376
500
|
.value=${this.filter}
|
|
377
501
|
placeholder=${this.filterLabel}
|
|
378
502
|
aria-label=${this.filterLabel}
|
|
503
|
+
aria-autocomplete="list"
|
|
379
504
|
aria-controls="items"
|
|
380
505
|
?disabled=${this.isDisabled}
|
|
381
506
|
@input=${this.handleFilter}
|
|
@@ -394,7 +519,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
394
519
|
aria-multiselectable=${this.multiple ? 'true' : nothing}
|
|
395
520
|
aria-required=${this.required ? 'true' : nothing}
|
|
396
521
|
${''}
|
|
397
|
-
tabindex=${this.isDisabled ? -1 : 0}
|
|
522
|
+
tabindex=${this.filterable ? nothing : this.isDisabled ? -1 : 0}
|
|
398
523
|
>
|
|
399
524
|
<slot @slotchange=${() => this.place()}></slot>
|
|
400
525
|
${this.renderStatus(shown)}
|
|
@@ -420,6 +545,9 @@ __decorate([
|
|
|
420
545
|
__decorate([
|
|
421
546
|
property({ attribute: 'filter-label' })
|
|
422
547
|
], HelixHeadlessListbox.prototype, "filterLabel", void 0);
|
|
548
|
+
__decorate([
|
|
549
|
+
property({ type: Boolean })
|
|
550
|
+
], HelixHeadlessListbox.prototype, "manual", void 0);
|
|
423
551
|
__decorate([
|
|
424
552
|
property({ reflect: true, type: Boolean })
|
|
425
553
|
], HelixHeadlessListbox.prototype, "multiple", void 0);
|
|
@@ -43,14 +43,17 @@ declare const HelixHeadlessMap_base: (new (...args: any[]) => import("@fusion.de
|
|
|
43
43
|
*
|
|
44
44
|
* Add `layers` to `controls` for a layers button. It opens a menu with a tile
|
|
45
45
|
* for each layer, which sets the layer's `hidden` attribute. Layers with the
|
|
46
|
-
* same `group`, such as a route and its dotted legs, share one tile.
|
|
46
|
+
* same `group`, such as a route and its dotted legs, share one tile. A tile
|
|
47
|
+
* sends `helix-before-toggle` from the layer first, so you can store the
|
|
48
|
+
* choice or refuse it.
|
|
47
49
|
*
|
|
48
50
|
* Imagery, a `helix-map-raster` with `ground`, is a map type and not a tile.
|
|
49
51
|
* The menu opens with a card for each type, Standard, Hybrid, and Satellite,
|
|
50
52
|
* with a picture of the map in it, and `map-type` says which is chosen.
|
|
51
53
|
* Standard hides the imagery, Hybrid draws it under the roads and names, and
|
|
52
|
-
* Satellite draws it alone.
|
|
53
|
-
* `
|
|
54
|
+
* Satellite draws it alone. Choosing one sends `helix-before-change` with its
|
|
55
|
+
* name, and `change` once `map-type` holds it. `connectMap` does not draw a
|
|
56
|
+
* hidden layer, so a layer you write with `hidden` starts turned off.
|
|
54
57
|
*
|
|
55
58
|
* Markers, routes, areas, live positions, and points layers go inside the
|
|
56
59
|
* frame as child elements.
|
|
@@ -66,7 +69,10 @@ declare const HelixHeadlessMap_base: (new (...args: any[]) => import("@fusion.de
|
|
|
66
69
|
* @slot footer - Content below the map, such as a legend or a scale.
|
|
67
70
|
* @slot header - Content above the map, such as a title or a search field.
|
|
68
71
|
*
|
|
72
|
+
* @event {Event} change - The layers menu changed the map type, which `map-type` now holds.
|
|
69
73
|
* @event {HelixActivateEvent} helix-activate - A marker was pressed. The value is the marker's `name`, or its `label` if it has no name. A cluster sends `helix-map-cluster` instead.
|
|
74
|
+
* @event {HelixBeforeChangeEvent} helix-before-change - A map type was chosen in the layers menu, with its name: `standard`, `hybrid`, or `satellite`. Cancelable: cancel it to keep the current type.
|
|
75
|
+
* @event {HelixBeforeToggleEvent} helix-before-toggle - A layer's tile in the layers menu was pressed. Sent from the layer, with `checked` true when it is to be shown. Cancelable: cancel it to keep the layer as it is.
|
|
70
76
|
* @event {HelixMapClusterEvent} helix-map-cluster - A cluster was pressed. Sent from the marker that shows the cluster, with the names of its places.
|
|
71
77
|
* @event {HelixMapPanEvent} helix-map-pan - A pan button or arrow key was pressed. Move your map in response.
|
|
72
78
|
* @event {HelixMapPartChangeEvent} helix-map-part-change - Clustering was turned on or off. Used by `connectMap`; pages do not need to listen for it.
|
|
@@ -279,8 +285,17 @@ export declare class HelixHeadlessMap extends HelixHeadlessMap_base {
|
|
|
279
285
|
private shown;
|
|
280
286
|
/** A map type's name on its card. */
|
|
281
287
|
private nameOf;
|
|
282
|
-
/**
|
|
288
|
+
/**
|
|
289
|
+
* Shows or hides layers, which `connectMap` draws or takes off the map.
|
|
290
|
+
*
|
|
291
|
+
* **Asked first, from the layer.** The tile wrote `hidden` onto the
|
|
292
|
+
* consumer's element and said nothing, so a page could neither keep the
|
|
293
|
+
* choice nor keep its own state in step. The request comes from the first
|
|
294
|
+
* layer of the tile, which is the element the page wrote.
|
|
295
|
+
*/
|
|
283
296
|
private showLayers;
|
|
297
|
+
/** Asks for a map type, and sends `change` once it holds. */
|
|
298
|
+
private chooseMapType;
|
|
284
299
|
/**
|
|
285
300
|
* The layers menu's entries, in the order the layers are written: a layer
|
|
286
301
|
* of its own, or every layer in a group, at the place of the first.
|
|
@@ -4,10 +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, fillTemplate, formatNumbers, HelixActivateEvent, HelixElement, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, hostAria, KeyboardNavigationController, MixinViewport, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, fillTemplate, formatNumbers, HelixActivateEvent, HelixBeforeChangeEvent, HelixBeforeToggleEvent, HelixElement, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, hostAria, KeyboardNavigationController, MixinViewport, requestChange, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { buildings, cloudRain, dotsNine, leaf, mountains, path, polygon, stack, target, } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
|
+
import { live } from 'lit/directives/live.js';
|
|
11
12
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
13
|
const MAP_TYPES = ['standard', 'hybrid', 'satellite'];
|
|
13
14
|
const iconOf = (layer) => {
|
|
@@ -205,10 +206,37 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
|
|
|
205
206
|
: this.standardLabel;
|
|
206
207
|
}
|
|
207
208
|
showLayers(layers, shown) {
|
|
208
|
-
|
|
209
|
-
|
|
209
|
+
const first = layers[0];
|
|
210
|
+
if (!first) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
requestChange({
|
|
214
|
+
apply: () => {
|
|
215
|
+
for (const layer of layers) {
|
|
216
|
+
layer.hidden = !shown;
|
|
217
|
+
}
|
|
218
|
+
this.requestUpdate();
|
|
219
|
+
},
|
|
220
|
+
event: (checked) => new HelixBeforeToggleEvent({ checked }),
|
|
221
|
+
host: first,
|
|
222
|
+
next: shown,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
chooseMapType(type) {
|
|
226
|
+
const applied = requestChange({
|
|
227
|
+
apply: (value) => {
|
|
228
|
+
this.mapType = value === 'standard' ? undefined : value;
|
|
229
|
+
},
|
|
230
|
+
event: (value) => new HelixBeforeChangeEvent({ value }),
|
|
231
|
+
host: this,
|
|
232
|
+
next: type,
|
|
233
|
+
});
|
|
234
|
+
if (applied) {
|
|
235
|
+
this.dispatchEvent(new Event('change', { bubbles: true }));
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
this.requestUpdate();
|
|
210
239
|
}
|
|
211
|
-
this.requestUpdate();
|
|
212
240
|
}
|
|
213
241
|
get layerEntries() {
|
|
214
242
|
const entries = [];
|
|
@@ -382,9 +410,10 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
|
|
|
382
410
|
<input
|
|
383
411
|
type="radio"
|
|
384
412
|
name="map-type"
|
|
385
|
-
.checked=${chosen === type}
|
|
386
|
-
@change=${() => {
|
|
387
|
-
|
|
413
|
+
.checked=${live(chosen === type)}
|
|
414
|
+
@change=${(event) => {
|
|
415
|
+
event.stopPropagation();
|
|
416
|
+
this.chooseMapType(type);
|
|
388
417
|
}}
|
|
389
418
|
/>
|
|
390
419
|
${preview
|
|
@@ -31,7 +31,7 @@ declare const HelixHeadlessMegamenu_base: (new (...args: any[]) => import("@fusi
|
|
|
31
31
|
*
|
|
32
32
|
* @event {HelixBeforeCloseEvent} helix-before-close - The panel is about to close. Cancelable.
|
|
33
33
|
* @event {HelixBeforeOpenEvent} helix-before-open - The panel is about to open. Cancelable.
|
|
34
|
-
* @event {
|
|
34
|
+
* @event {ToggleEvent} toggle - The panel opened or closed. Carries `newState` and `oldState`.
|
|
35
35
|
*
|
|
36
36
|
* @csspart surface - The floating panel that opens.
|
|
37
37
|
* @csspart trigger - The default trigger button, shown when the `trigger` slot is empty.
|
|
@@ -194,6 +194,15 @@ export declare class HelixHeadlessMegamenu extends HelixHeadlessMegamenu_base {
|
|
|
194
194
|
private readonly handlePointerDown;
|
|
195
195
|
private readonly handlePointerEnter;
|
|
196
196
|
private readonly handlePointerLeave;
|
|
197
|
+
/**
|
|
198
|
+
* Closes the panel when keyboard focus leaves it for the page.
|
|
199
|
+
*
|
|
200
|
+
* Only when focus went somewhere: a `relatedTarget` of null is focus leaving
|
|
201
|
+
* the document, such as a switch to another window, and a reader who comes
|
|
202
|
+
* back expects the panel as they left it. `requestOpen` rather than `close`,
|
|
203
|
+
* because focus has already gone where the reader sent it.
|
|
204
|
+
*/
|
|
205
|
+
private readonly handleFocusOut;
|
|
197
206
|
private readonly handleTriggerClick;
|
|
198
207
|
/**
|
|
199
208
|
* Shuts the panel when a reader takes one of the destinations in it.
|
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
var HelixHeadlessMegamenu_1;
|
|
8
|
-
import { anchorElement, customElement, HelixElement, MixinControllerOpen, PopoverController, tellDisclosure, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { anchorElement, customElement, deepContains, HelixElement, MixinControllerOpen, PopoverController, tellDisclosure, } from '@fusion.dev/helix-core';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
let showing;
|
|
@@ -57,6 +57,13 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
57
57
|
this.requestOpen(false);
|
|
58
58
|
});
|
|
59
59
|
};
|
|
60
|
+
this.handleFocusOut = (event) => {
|
|
61
|
+
const next = event.relatedTarget;
|
|
62
|
+
if (!this.open || next === null || deepContains(this, next)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
this.requestOpen(false);
|
|
66
|
+
};
|
|
60
67
|
this.handleTriggerClick = (event) => {
|
|
61
68
|
this.stop();
|
|
62
69
|
if (this.openOn !== 'hover') {
|
|
@@ -154,6 +161,7 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
154
161
|
this.addEventListener('click', this.handleContentClick);
|
|
155
162
|
this.addEventListener('pointerenter', this.handlePointerEnter);
|
|
156
163
|
this.addEventListener('pointerleave', this.handlePointerLeave);
|
|
164
|
+
this.addEventListener('focusout', this.handleFocusOut);
|
|
157
165
|
}
|
|
158
166
|
disconnectedCallback() {
|
|
159
167
|
super.disconnectedCallback();
|
|
@@ -164,6 +172,7 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
164
172
|
this.removeEventListener('click', this.handleContentClick);
|
|
165
173
|
this.removeEventListener('pointerenter', this.handlePointerEnter);
|
|
166
174
|
this.removeEventListener('pointerleave', this.handlePointerLeave);
|
|
175
|
+
this.removeEventListener('focusout', this.handleFocusOut);
|
|
167
176
|
this.stop();
|
|
168
177
|
if (showing === this) {
|
|
169
178
|
showing = undefined;
|
|
@@ -14,6 +14,11 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
14
14
|
* only one can be on. A row that opens a page keeps `menuitem` and sets
|
|
15
15
|
* `aria-haspopup`.
|
|
16
16
|
*
|
|
17
|
+
* Choosing a choice row checks or unchecks it before `helix-select` is sent,
|
|
18
|
+
* so a listener reads the new `checked`. An `exclusive` row turns on and turns
|
|
19
|
+
* off the `exclusive` rows next to it. Cancel `helix-before-toggle` to keep a
|
|
20
|
+
* row as it is and set `checked` yourself.
|
|
21
|
+
*
|
|
17
22
|
* The menu sets whether the row's page is showing as a property, never as an
|
|
18
23
|
* attribute. An attribute written onto your element after it upgrades causes a
|
|
19
24
|
* hydration mismatch.
|
|
@@ -27,12 +32,15 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
27
32
|
* @slot start - Content before the label, such as an icon.
|
|
28
33
|
* @slot submenu - The rows of a submenu that this row opens.
|
|
29
34
|
*
|
|
35
|
+
* @event {HelixBeforeToggleEvent} helix-before-toggle - A choice row is about to be checked or unchecked, carrying the state asked for. Cancelable: cancel it to keep the row as it is.
|
|
30
36
|
* @event {HelixSelectEvent} helix-select - The row was chosen. Cancelable: cancel it to keep the menu open.
|
|
31
37
|
*
|
|
32
38
|
* @csspart item - The row, which is an `<a>` where `href` is set.
|
|
33
39
|
* @csspart mark - The trailing mark: a check mark when the row is checked, or a caret
|
|
34
40
|
* when it opens a submenu. A row never shows both, so they share one column.
|
|
35
41
|
* @csspart start - The leading column that holds the `start` slot. It is always rendered.
|
|
42
|
+
*
|
|
43
|
+
* @cssstate checked - The row is checked.
|
|
36
44
|
*/
|
|
37
45
|
export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
38
46
|
/**
|
|
@@ -45,10 +53,16 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
45
53
|
* thing they are not.
|
|
46
54
|
*
|
|
47
55
|
* `checked` implies it, so a row that is on never has to say both.
|
|
56
|
+
*
|
|
57
|
+
* Choosing the row checks or unchecks it, after a `helix-before-toggle` that
|
|
58
|
+
* you can cancel.
|
|
48
59
|
*/
|
|
49
60
|
checkable: boolean;
|
|
50
61
|
/**
|
|
51
62
|
* Whether the row is checked.
|
|
63
|
+
*
|
|
64
|
+
* The row changes it when it is chosen. Not reflected: the attribute is the
|
|
65
|
+
* state you start the row in, and `:state(checked)` carries the current one.
|
|
52
66
|
*/
|
|
53
67
|
checked: boolean;
|
|
54
68
|
/**
|
|
@@ -66,11 +80,11 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
66
80
|
/**
|
|
67
81
|
* Whether only one row in its set can be checked at a time.
|
|
68
82
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
83
|
+
* The set is the run of `exclusive` rows next to this one, up to the first
|
|
84
|
+
* element that is not one, such as a divider. Choosing a row in it checks
|
|
85
|
+
* that row and unchecks the others. Choosing the row that is checked leaves
|
|
86
|
+
* it checked. `menuitemradio` tells a reader which kind of set they are in,
|
|
87
|
+
* where `menuitemcheckbox` says every row is independent.
|
|
74
88
|
*
|
|
75
89
|
* Meaningless without `checkable`, since a row that cannot be ticked is not
|
|
76
90
|
* one of a set of anything.
|
|
@@ -225,16 +239,31 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
225
239
|
/** Chooses the row, the same as pressing it. */
|
|
226
240
|
select(): void;
|
|
227
241
|
/**
|
|
228
|
-
* Whether the row has focus, which
|
|
242
|
+
* Whether the row has focus, which makes it the row the keyboard is on.
|
|
243
|
+
*
|
|
244
|
+
* `Option` calls the same thing `active`. A menu holds no answer the way a
|
|
245
|
+
* radio group does, only a row the reader has walked to, so focus is the
|
|
246
|
+
* whole of what "the current one" can mean here. Read from the shadow root
|
|
247
|
+
* rather than kept as state, because focus moves for reasons this element is
|
|
248
|
+
* not told about: a press, a Tab, the drilldown putting the reader on the
|
|
249
|
+
* first row of a page it has just opened.
|
|
250
|
+
*/
|
|
251
|
+
get active(): boolean;
|
|
252
|
+
/**
|
|
253
|
+
* Whether the row has focus, the same as `active`.
|
|
229
254
|
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
* one" can mean here. Read from the shadow root rather than kept as state,
|
|
233
|
-
* because focus moves for reasons this element is not told about: a press, a
|
|
234
|
-
* Tab, the drilldown putting the reader on the first row of a page it has
|
|
235
|
-
* just opened.
|
|
255
|
+
* @deprecated Read `active`. Everywhere else in the library `selected` means
|
|
256
|
+
* chosen out of a set, and a menu row is never chosen that way.
|
|
236
257
|
*/
|
|
237
258
|
get selected(): boolean;
|
|
259
|
+
/**
|
|
260
|
+
* Checks or unchecks a choice row.
|
|
261
|
+
*
|
|
262
|
+
* An `exclusive` row only turns on, and turning on turns its set off.
|
|
263
|
+
*/
|
|
264
|
+
private tick;
|
|
265
|
+
/** The other `exclusive` rows in this row's run of siblings. */
|
|
266
|
+
private exclusivePeers;
|
|
238
267
|
private choose;
|
|
239
268
|
private readonly handleClick;
|
|
240
269
|
/**
|
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, HelixElement, HelixSelectEvent } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, deepActiveElement, HelixBeforeToggleEvent, HelixElement, HelixSelectEvent, requestChange, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretRight, check } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -58,6 +58,7 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
58
58
|
}
|
|
59
59
|
willUpdate(changed) {
|
|
60
60
|
super.willUpdate(changed);
|
|
61
|
+
this.toggleState('checked', this.checked);
|
|
61
62
|
if (!this.childrenKnown) {
|
|
62
63
|
return;
|
|
63
64
|
}
|
|
@@ -78,13 +79,55 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
78
79
|
select() {
|
|
79
80
|
this.choose();
|
|
80
81
|
}
|
|
82
|
+
get active() {
|
|
83
|
+
const active = deepActiveElement();
|
|
84
|
+
return active !== null && active.getRootNode() === this.renderRoot;
|
|
85
|
+
}
|
|
81
86
|
get selected() {
|
|
82
|
-
return this.
|
|
87
|
+
return this.active;
|
|
88
|
+
}
|
|
89
|
+
tick() {
|
|
90
|
+
if (!(this.checkable || this.checked) || this.hasSubmenu) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const next = this.exclusive ? true : !this.checked;
|
|
94
|
+
if (next === this.checked) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const applied = requestChange({
|
|
98
|
+
apply: (checked) => {
|
|
99
|
+
this.checked = checked;
|
|
100
|
+
},
|
|
101
|
+
event: (checked) => new HelixBeforeToggleEvent({ checked }),
|
|
102
|
+
host: this,
|
|
103
|
+
next,
|
|
104
|
+
});
|
|
105
|
+
if (applied && this.exclusive) {
|
|
106
|
+
for (const peer of this.exclusivePeers()) {
|
|
107
|
+
peer.checked = false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exclusivePeers() {
|
|
112
|
+
const peers = [];
|
|
113
|
+
const inSet = (node) => node !== null &&
|
|
114
|
+
node.isMenuItem === true &&
|
|
115
|
+
node.exclusive &&
|
|
116
|
+
node.slot === this.slot;
|
|
117
|
+
for (const step of ['previousElementSibling', 'nextElementSibling']) {
|
|
118
|
+
let node = this[step];
|
|
119
|
+
while (inSet(node)) {
|
|
120
|
+
peers.push(node);
|
|
121
|
+
node = node[step];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return peers;
|
|
83
125
|
}
|
|
84
126
|
choose() {
|
|
85
127
|
if (this.disabled) {
|
|
86
128
|
return;
|
|
87
129
|
}
|
|
130
|
+
this.tick();
|
|
88
131
|
this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
|
|
89
132
|
}
|
|
90
133
|
render() {
|
|
@@ -155,7 +198,7 @@ __decorate([
|
|
|
155
198
|
property({ reflect: true, type: Boolean })
|
|
156
199
|
], HelixHeadlessMenuItem.prototype, "checkable", void 0);
|
|
157
200
|
__decorate([
|
|
158
|
-
property({
|
|
201
|
+
property({ type: Boolean })
|
|
159
202
|
], HelixHeadlessMenuItem.prototype, "checked", void 0);
|
|
160
203
|
__decorate([
|
|
161
204
|
property({ reflect: true, type: Boolean })
|