@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,59 +4,15 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { AriaForwardController, countLabel, customElement, DelayController, DisabledCascadeController, endInSight, HelixFilterEvent, HelixFormElement, HelixLoadMoreEvent, hostAria, MixinCollection, MixinControllerValue, MixinField, rangeAdd, reportValues, requestChange, scrollItemIntoView, selectsAll, Typeahead, typesCharacter, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, centerInView, columnStep, countLabel, customElement, DelayController, DisabledCascadeController, drawAutofill, endInSight, fillTemplate, HelixFilterEvent, HelixFormElement, HelixLoadMoreEvent, hostAria, inlineStep, MixinCollection, MixinControllerValue, MixinField, markMatches, OptionWindowController, onApple, pageRows, rangeAdd, reportValues, requestChange, scrollItemIntoView, selectsAll, Typeahead, toggleEvery, 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
|
-
import { HelixHeadlessOptionGroup } from '../../option/group/option-group.js';
|
|
13
12
|
import { HelixHeadlessOption } from '../../option/root/option-root.js';
|
|
14
|
-
const MOVES = new Set(['ArrowDown', 'ArrowUp', 'End', 'Home', 'PageDown', 'PageUp']);
|
|
15
13
|
const FIELD_MOVES = new Set(['ArrowDown', 'ArrowUp', 'PageDown', 'PageUp']);
|
|
14
|
+
const MOVES = new Set([...FIELD_MOVES, 'End', 'Home']);
|
|
16
15
|
const PAGE = 10;
|
|
17
|
-
const matched = new Map();
|
|
18
|
-
const HIGHLIGHT = 'helix-filter-match';
|
|
19
|
-
const paintable = () => typeof CSS !== 'undefined' && 'highlights' in CSS && typeof Highlight !== 'undefined';
|
|
20
|
-
const paintMatches = () => {
|
|
21
|
-
if (!paintable()) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
const all = [...matched.values()].flat();
|
|
25
|
-
if (all.length === 0) {
|
|
26
|
-
CSS.highlights.delete(HIGHLIGHT);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
|
-
CSS.highlights.set(HIGHLIGHT, new Highlight(...all));
|
|
30
|
-
};
|
|
31
|
-
const rangeFor = (root, needle) => {
|
|
32
|
-
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
|
|
33
|
-
const nodes = [];
|
|
34
|
-
let whole = '';
|
|
35
|
-
for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {
|
|
36
|
-
nodes.push(node);
|
|
37
|
-
whole += node.nodeValue ?? '';
|
|
38
|
-
}
|
|
39
|
-
const at = whole.toLowerCase().indexOf(needle);
|
|
40
|
-
if (at < 0) {
|
|
41
|
-
return [];
|
|
42
|
-
}
|
|
43
|
-
const range = document.createRange();
|
|
44
|
-
let seen = 0;
|
|
45
|
-
let started = false;
|
|
46
|
-
for (const node of nodes) {
|
|
47
|
-
const length = node.nodeValue?.length ?? 0;
|
|
48
|
-
if (!started && at < seen + length) {
|
|
49
|
-
range.setStart(node, at - seen);
|
|
50
|
-
started = true;
|
|
51
|
-
}
|
|
52
|
-
if (started && at + needle.length <= seen + length) {
|
|
53
|
-
range.setEnd(node, at + needle.length - seen);
|
|
54
|
-
return [range];
|
|
55
|
-
}
|
|
56
|
-
seen += length;
|
|
57
|
-
}
|
|
58
|
-
return [];
|
|
59
|
-
};
|
|
60
16
|
let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(MixinControllerValue(MixinField(HelixFormElement))) {
|
|
61
17
|
constructor() {
|
|
62
18
|
super(...arguments);
|
|
@@ -70,13 +26,20 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
70
26
|
this.filterable = false;
|
|
71
27
|
this.filterDelay = 0;
|
|
72
28
|
this.filterLabel = 'Filter';
|
|
29
|
+
this.items = undefined;
|
|
30
|
+
this.data = new OptionWindowController(this, {
|
|
31
|
+
current: () => this.currentValue,
|
|
32
|
+
items: () => this.items,
|
|
33
|
+
});
|
|
73
34
|
this.loadError = '';
|
|
74
35
|
this.manual = false;
|
|
75
36
|
this.multiple = false;
|
|
76
37
|
this.resultLabel = '{count} result';
|
|
77
38
|
this.resultsLabel = '{count} results';
|
|
39
|
+
this.selectedLabel = '{name}, selected';
|
|
78
40
|
this.activeValue = '';
|
|
79
41
|
this.parked = false;
|
|
42
|
+
this.anchor = '';
|
|
80
43
|
this.typeahead = new Typeahead();
|
|
81
44
|
this.seen = new Set();
|
|
82
45
|
this.forwarded = false;
|
|
@@ -85,6 +48,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
85
48
|
this.cascade = new DisabledCascadeController(this, {
|
|
86
49
|
items: () => this.options,
|
|
87
50
|
});
|
|
51
|
+
this.chosenAgain = undefined;
|
|
88
52
|
this.handleSelection = (event) => {
|
|
89
53
|
if (event.detail.href !== undefined) {
|
|
90
54
|
return;
|
|
@@ -102,11 +66,17 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
102
66
|
return;
|
|
103
67
|
}
|
|
104
68
|
const typing = this.forwarded || event.composedPath()[0] === this.partNamed('search-field');
|
|
69
|
+
if (this.multiple && event.key === ' ' && event.shiftKey && !typing) {
|
|
70
|
+
event.preventDefault();
|
|
71
|
+
this.extend(this.activeValue);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
105
74
|
if (event.key === 'Enter' || (event.key === ' ' && !typing && !this.typeahead.typing())) {
|
|
106
75
|
const link = shown.find((option) => option.value === this.activeValue && Boolean(option.href));
|
|
107
76
|
if (link !== undefined) {
|
|
108
77
|
event.preventDefault();
|
|
109
78
|
if (event.key === 'Enter') {
|
|
79
|
+
;
|
|
110
80
|
link.select(event);
|
|
111
81
|
}
|
|
112
82
|
}
|
|
@@ -121,10 +91,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
121
91
|
}
|
|
122
92
|
if (this.multiple && !typing && selectsAll(event)) {
|
|
123
93
|
event.preventDefault();
|
|
124
|
-
|
|
125
|
-
const all = reachable.every((value) => this.values.includes(value));
|
|
126
|
-
const kept = this.values.filter((value) => !reachable.includes(value));
|
|
127
|
-
this.requestValue((all ? kept : [...kept, ...reachable]).join(','));
|
|
94
|
+
this.requestValue(toggleEvery(this.values, shown.map((option) => option.value)).join(','));
|
|
128
95
|
return;
|
|
129
96
|
}
|
|
130
97
|
if (!typing && typesCharacter(event)) {
|
|
@@ -140,7 +107,9 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
140
107
|
event.shiftKey &&
|
|
141
108
|
(event.ctrlKey || event.metaKey) &&
|
|
142
109
|
(event.key === 'Home' || event.key === 'End');
|
|
143
|
-
|
|
110
|
+
const grid = this.layout === 'grid' && !this.data.records;
|
|
111
|
+
const along = grid && !typing ? inlineStep(this, event.key) : 0;
|
|
112
|
+
if (!fieldRange && !along && !(typing ? FIELD_MOVES : MOVES).has(event.key)) {
|
|
144
113
|
return;
|
|
145
114
|
}
|
|
146
115
|
event.preventDefault();
|
|
@@ -149,7 +118,13 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
149
118
|
const at = shown.findIndex((option) => option.value === from);
|
|
150
119
|
const last = shown.length - 1;
|
|
151
120
|
let next = at;
|
|
152
|
-
if (
|
|
121
|
+
if (along) {
|
|
122
|
+
next = Math.min(Math.max(at + along, 0), last);
|
|
123
|
+
}
|
|
124
|
+
else if (grid && at >= 0 && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
|
|
125
|
+
next = columnStep(shown.map((option) => option.getBoundingClientRect().left), at, event.key === 'ArrowDown' ? 1 : -1);
|
|
126
|
+
}
|
|
127
|
+
else if (event.key === 'ArrowDown') {
|
|
153
128
|
next = at < 0 ? 0 : (at + 1) % shown.length;
|
|
154
129
|
}
|
|
155
130
|
else if (event.key === 'ArrowUp') {
|
|
@@ -197,7 +172,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
197
172
|
this.askedAt = -1;
|
|
198
173
|
this.handleScroll = (event) => {
|
|
199
174
|
const items = event.currentTarget;
|
|
200
|
-
const count = this.
|
|
175
|
+
const count = this.entries.length;
|
|
201
176
|
if (this.loading ||
|
|
202
177
|
!endInSight({
|
|
203
178
|
askedAt: this.askedAt,
|
|
@@ -241,43 +216,52 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
241
216
|
this.requestUpdate('filter', previous);
|
|
242
217
|
}
|
|
243
218
|
get selectedIndex() {
|
|
244
|
-
return this.
|
|
219
|
+
return this.entries.findIndex((option) => option.selected);
|
|
245
220
|
}
|
|
246
221
|
set selectedIndex(at) {
|
|
247
|
-
const option = this.
|
|
222
|
+
const option = this.entries[at];
|
|
248
223
|
this.value = option?.value ?? '';
|
|
249
224
|
}
|
|
250
225
|
highlight(where) {
|
|
251
226
|
const shown = this.shown.filter((option) => !option.disabled);
|
|
252
227
|
this.typeahead.reset();
|
|
253
228
|
this.parked = where === 'none';
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
260
|
-
else if (where === 'last') {
|
|
261
|
-
this.activeValue = shown.at(-1)?.value ?? '';
|
|
262
|
-
}
|
|
263
|
-
else {
|
|
264
|
-
const chosen = shown.find((option) => this.values.includes(option.value));
|
|
265
|
-
this.activeValue = (chosen ?? shown[0])?.value ?? '';
|
|
266
|
-
}
|
|
229
|
+
const chosen = where === 'selected' ? shown.find((option) => this.values.includes(option.value)) : undefined;
|
|
230
|
+
this.activeValue =
|
|
231
|
+
where === 'none'
|
|
232
|
+
? ''
|
|
233
|
+
: ((where === 'last' ? shown.at(-1) : (chosen ?? shown[0]))?.value ?? '');
|
|
267
234
|
if (this.childrenKnown) {
|
|
268
235
|
this.place();
|
|
269
236
|
}
|
|
270
237
|
}
|
|
271
238
|
tell(changed) {
|
|
272
|
-
if (!
|
|
239
|
+
if (!this.hasUpdated) {
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
if (!changed.has('filter')) {
|
|
243
|
+
this.tellActive(changed);
|
|
273
244
|
return;
|
|
274
245
|
}
|
|
275
246
|
const count = this.shown.length;
|
|
276
|
-
|
|
277
|
-
this.
|
|
247
|
+
this.announced =
|
|
248
|
+
this.filter.trim() && count
|
|
249
|
+
? countLabel(count, this.resultLabel, this.resultsLabel, this.lang)
|
|
250
|
+
: '';
|
|
251
|
+
}
|
|
252
|
+
tellActive(changed) {
|
|
253
|
+
if (!changed.has('activeValue') ||
|
|
254
|
+
!this.filterable ||
|
|
255
|
+
!onApple() ||
|
|
256
|
+
this.renderRoot.activeElement?.getAttribute('part') !== 'search-field') {
|
|
278
257
|
return;
|
|
279
258
|
}
|
|
280
|
-
|
|
259
|
+
const active = this.entries.find((option) => option.value === this.activeValue);
|
|
260
|
+
if (active) {
|
|
261
|
+
this.announced = active.selected
|
|
262
|
+
? fillTemplate(this.selectedLabel, { name: active.text })
|
|
263
|
+
: active.text;
|
|
264
|
+
}
|
|
281
265
|
}
|
|
282
266
|
typeaheadTo(key) {
|
|
283
267
|
const shown = this.shown.filter((option) => !option.disabled);
|
|
@@ -315,16 +299,25 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
315
299
|
return found;
|
|
316
300
|
}
|
|
317
301
|
get groups() {
|
|
318
|
-
return this.among((node) => node
|
|
302
|
+
return this.among((node) => node.localName.endsWith('-option-group'), this.children);
|
|
303
|
+
}
|
|
304
|
+
get entries() {
|
|
305
|
+
return this.data.records ?? this.options;
|
|
306
|
+
}
|
|
307
|
+
get elements() {
|
|
308
|
+
return this.data.records ? this.data.drawn : this.options;
|
|
319
309
|
}
|
|
320
310
|
get shown() {
|
|
321
|
-
return this.
|
|
311
|
+
return this.entries.filter((option) => !option.hidden);
|
|
322
312
|
}
|
|
323
313
|
get values() {
|
|
324
314
|
return this.value === '' ? [] : this.value.split(',');
|
|
325
315
|
}
|
|
326
316
|
choose(value) {
|
|
327
317
|
const chosen = this.values;
|
|
318
|
+
if (!chosen.includes(value)) {
|
|
319
|
+
this.anchor = value;
|
|
320
|
+
}
|
|
328
321
|
const next = this.multiple
|
|
329
322
|
? chosen.includes(value)
|
|
330
323
|
? chosen.filter((each) => each !== value)
|
|
@@ -332,23 +325,31 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
332
325
|
: [value];
|
|
333
326
|
const joined = next.join(',');
|
|
334
327
|
if (joined === this.value) {
|
|
328
|
+
this.chosenAgain?.();
|
|
335
329
|
return;
|
|
336
330
|
}
|
|
337
331
|
this.requestValue(joined);
|
|
338
332
|
}
|
|
333
|
+
extend(to) {
|
|
334
|
+
const reach = this.shown.filter((option) => !option.disabled).map((option) => option.value);
|
|
335
|
+
const taken = rangeAdd(this.values, reach, reach.indexOf(this.anchor), reach.indexOf(to));
|
|
336
|
+
if (taken) {
|
|
337
|
+
this.requestValue(taken.join(','));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
339
340
|
arrive(value) {
|
|
340
341
|
this.parked = false;
|
|
341
342
|
this.activeValue = value;
|
|
342
|
-
const link = this.
|
|
343
|
+
const link = this.entries.some((option) => option.value === value && Boolean(option.href));
|
|
343
344
|
if (!this.multiple && !this.manual && !this.forwarded && !link) {
|
|
344
345
|
this.choose(value);
|
|
345
346
|
}
|
|
346
347
|
}
|
|
347
348
|
pageSize() {
|
|
348
349
|
const items = this.partNamed('items');
|
|
349
|
-
const row = this.
|
|
350
|
+
const row = this.elements.find((option) => !option.hidden)?.getBoundingClientRect().height ?? 0;
|
|
350
351
|
const height = items?.clientHeight ?? 0;
|
|
351
|
-
return row > 0 && height > 0 ?
|
|
352
|
+
return row > 0 && height > 0 ? pageRows(height, row) : PAGE;
|
|
352
353
|
}
|
|
353
354
|
navigate(event) {
|
|
354
355
|
this.forwarded = true;
|
|
@@ -360,29 +361,21 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
360
361
|
}
|
|
361
362
|
}
|
|
362
363
|
reveal() {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
if (!items || !chosen) {
|
|
364
|
+
if (this.data.records) {
|
|
365
|
+
this.data.center(this.values[0] ?? '');
|
|
366
366
|
return;
|
|
367
367
|
}
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
return;
|
|
373
|
-
}
|
|
374
|
-
const off = row.top + row.height / 2 - (box.top + box.height / 2);
|
|
375
|
-
if (Math.abs(off) < 1) {
|
|
376
|
-
return;
|
|
377
|
-
}
|
|
378
|
-
items.scrollTop += off;
|
|
368
|
+
const items = this.partNamed('items');
|
|
369
|
+
const chosen = this.options.find((option) => option.selected && !option.hidden);
|
|
370
|
+
if (items && chosen) {
|
|
371
|
+
centerInView(items, chosen);
|
|
379
372
|
}
|
|
380
373
|
}
|
|
381
374
|
place() {
|
|
382
375
|
this.forgetRemoved();
|
|
383
376
|
const needle = this.filter.trim().toLowerCase();
|
|
384
377
|
const chosen = new Set(this.values);
|
|
385
|
-
for (const option of this.
|
|
378
|
+
for (const option of this.entries) {
|
|
386
379
|
option.hidden = needle !== '' && !option.text.toLowerCase().includes(needle);
|
|
387
380
|
option.selected = chosen.has(option.value);
|
|
388
381
|
}
|
|
@@ -398,20 +391,10 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
398
391
|
if (rescue && !shown.some((option) => option.value === this.activeValue)) {
|
|
399
392
|
this.activeValue = shown.find((option) => !option.disabled)?.value ?? '';
|
|
400
393
|
}
|
|
401
|
-
for (const option of this.
|
|
394
|
+
for (const option of this.entries) {
|
|
402
395
|
option.active = option.value === this.activeValue;
|
|
403
396
|
}
|
|
404
|
-
|
|
405
|
-
matched.delete(this);
|
|
406
|
-
}
|
|
407
|
-
else {
|
|
408
|
-
matched.set(this, shown.flatMap((option) => rangeFor(option, needle)));
|
|
409
|
-
}
|
|
410
|
-
paintMatches();
|
|
411
|
-
const anyShown = shown.length > 0;
|
|
412
|
-
if (anyShown !== this.hasMatches) {
|
|
413
|
-
this.hasMatches = anyShown;
|
|
414
|
-
}
|
|
397
|
+
this.hasMatches = shown.length > 0;
|
|
415
398
|
this.counted = true;
|
|
416
399
|
}
|
|
417
400
|
get owned() {
|
|
@@ -422,15 +405,19 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
422
405
|
if (this.owned) {
|
|
423
406
|
return;
|
|
424
407
|
}
|
|
425
|
-
const present = new Set(this.
|
|
408
|
+
const present = new Set(this.entries.map((option) => option.value));
|
|
426
409
|
const gone = this.values.filter((value) => this.seen.has(value) && !present.has(value));
|
|
427
410
|
this.seen = present;
|
|
428
411
|
if (gone.length > 0) {
|
|
429
412
|
this.value = this.values.filter((value) => !gone.includes(value)).join(',');
|
|
430
413
|
}
|
|
431
414
|
}
|
|
432
|
-
followActive() {
|
|
433
|
-
|
|
415
|
+
followActive(changed) {
|
|
416
|
+
if (this.data.records &&
|
|
417
|
+
!this.data.follow(changed.has('activeValue') || changed.has('filter'))) {
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const active = this.elements.find((option) => !option.hidden && option.value === this.activeValue);
|
|
434
421
|
if (active) {
|
|
435
422
|
const items = this.partNamed('items');
|
|
436
423
|
scrollItemIntoView(active, { padding: 4, ...(items ? { scroller: items } : {}) });
|
|
@@ -454,8 +441,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
454
441
|
super.disconnectedCallback();
|
|
455
442
|
this.removeEventListener('helix-select', this.handleSelection);
|
|
456
443
|
this.removeEventListener('keydown', this.handleKeydown);
|
|
457
|
-
|
|
458
|
-
paintMatches();
|
|
444
|
+
markMatches(this, [], '');
|
|
459
445
|
}
|
|
460
446
|
willUpdate(changed) {
|
|
461
447
|
super.willUpdate(changed);
|
|
@@ -476,7 +462,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
476
462
|
}
|
|
477
463
|
this.toggleState('empty', !this.showsOptions);
|
|
478
464
|
this.toggleState('loading', this.loading);
|
|
479
|
-
this.toggleState('error', this.
|
|
465
|
+
this.toggleState('error', this.failed);
|
|
480
466
|
this.toggleState('no-results', this.noResults);
|
|
481
467
|
}
|
|
482
468
|
seedDeclared() {
|
|
@@ -498,14 +484,15 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
498
484
|
if (!list || !('ariaActiveDescendantElement' in list)) {
|
|
499
485
|
return;
|
|
500
486
|
}
|
|
501
|
-
const active = this.
|
|
487
|
+
const active = this.elements.find((option) => option.value === this.currentValue);
|
|
502
488
|
list.ariaActiveDescendantElement = active ?? null;
|
|
503
489
|
}
|
|
504
490
|
updated(changed) {
|
|
505
491
|
super.updated(changed);
|
|
506
|
-
this.followActive();
|
|
492
|
+
this.followActive(changed);
|
|
507
493
|
this.sync();
|
|
508
494
|
this.linkActive();
|
|
495
|
+
markMatches(this, this.elements.filter((option) => !option.hidden), this.filter.trim());
|
|
509
496
|
}
|
|
510
497
|
takeFilter(control) {
|
|
511
498
|
this.filtering.cancel();
|
|
@@ -547,12 +534,12 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
547
534
|
get showsOptions() {
|
|
548
535
|
return this.counted && !this.loading
|
|
549
536
|
? this.filter === ''
|
|
550
|
-
? this.
|
|
537
|
+
? this.entries.length > 0
|
|
551
538
|
: this.hasMatches
|
|
552
539
|
: true;
|
|
553
540
|
}
|
|
554
541
|
renderStatus(hasContent) {
|
|
555
|
-
if (this.
|
|
542
|
+
if (this.failed) {
|
|
556
543
|
return html `<p part="error"><slot name="error">${this.loadError}</slot></p>`;
|
|
557
544
|
}
|
|
558
545
|
if (!this.loading && hasContent) {
|
|
@@ -571,17 +558,17 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
571
558
|
return (this.counted &&
|
|
572
559
|
!this.loading &&
|
|
573
560
|
this.filter !== '' &&
|
|
574
|
-
this.
|
|
561
|
+
this.entries.length > 0 &&
|
|
575
562
|
!this.hasMatches);
|
|
576
563
|
}
|
|
564
|
+
get failed() {
|
|
565
|
+
return Boolean(this.loadError);
|
|
566
|
+
}
|
|
577
567
|
renderLive(hasContent) {
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
return html `<span part="live" role="status">${this.noResultsText}</span>`;
|
|
583
|
-
}
|
|
584
|
-
return super.renderLive(hasContent);
|
|
568
|
+
const words = this.loadError || (this.noResults ? this.noResultsText : undefined);
|
|
569
|
+
return words === undefined
|
|
570
|
+
? super.renderLive(hasContent)
|
|
571
|
+
: html `<span part="live" role="status">${words}</span>`;
|
|
585
572
|
}
|
|
586
573
|
render() {
|
|
587
574
|
const shown = this.showsOptions;
|
|
@@ -594,7 +581,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
594
581
|
<input
|
|
595
582
|
part="search-field"
|
|
596
583
|
type="text"
|
|
597
|
-
autocomplete
|
|
584
|
+
autocomplete="off"
|
|
598
585
|
spellcheck="false"
|
|
599
586
|
.value=${this.filter}
|
|
600
587
|
placeholder=${this.filterLabel}
|
|
@@ -617,14 +604,22 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
617
604
|
aria-labelledby=${this.labeled ? this.labelId : nothing}
|
|
618
605
|
aria-multiselectable=${this.multiple ? 'true' : nothing}
|
|
619
606
|
aria-required=${this.required ? 'true' : nothing}
|
|
620
|
-
${''}
|
|
621
607
|
tabindex=${this.filterable ? nothing : this.isDisabled ? -1 : 0}
|
|
622
608
|
@scroll=${this.handleScroll}
|
|
623
609
|
>
|
|
624
|
-
|
|
610
|
+
${this.data.render() ?? html `<slot @slotchange=${() => this.requestUpdate()}></slot>`}
|
|
625
611
|
${this.renderStatus(shown)}
|
|
626
612
|
</div>
|
|
627
|
-
${this.renderLive(shown)}${this.renderHint()}${this.renderFeedback()}
|
|
613
|
+
${this.renderLive(shown)}${this.renderHint()}${this.renderFeedback()}${this.autocomplete === 'off'
|
|
614
|
+
? nothing
|
|
615
|
+
: drawAutofill({
|
|
616
|
+
autocomplete: this.autocomplete,
|
|
617
|
+
disabled: this.isDisabled,
|
|
618
|
+
multiple: this.multiple,
|
|
619
|
+
onFill: (value) => this.requestValue(value),
|
|
620
|
+
options: this.childrenKnown ? this.entries : [],
|
|
621
|
+
value: this.value,
|
|
622
|
+
})}`;
|
|
628
623
|
}
|
|
629
624
|
};
|
|
630
625
|
__decorate([
|
|
@@ -648,6 +643,12 @@ __decorate([
|
|
|
648
643
|
__decorate([
|
|
649
644
|
property({ attribute: 'filter-label' })
|
|
650
645
|
], HelixHeadlessListbox.prototype, "filterLabel", void 0);
|
|
646
|
+
__decorate([
|
|
647
|
+
property({ attribute: false })
|
|
648
|
+
], HelixHeadlessListbox.prototype, "items", void 0);
|
|
649
|
+
__decorate([
|
|
650
|
+
property({ reflect: true })
|
|
651
|
+
], HelixHeadlessListbox.prototype, "layout", void 0);
|
|
651
652
|
__decorate([
|
|
652
653
|
property({ attribute: 'load-error' })
|
|
653
654
|
], HelixHeadlessListbox.prototype, "loadError", void 0);
|
|
@@ -667,14 +668,11 @@ __decorate([
|
|
|
667
668
|
property({ attribute: 'results-label' })
|
|
668
669
|
], HelixHeadlessListbox.prototype, "resultsLabel", void 0);
|
|
669
670
|
__decorate([
|
|
670
|
-
|
|
671
|
-
], HelixHeadlessListbox.prototype, "
|
|
671
|
+
property({ attribute: 'selected-label' })
|
|
672
|
+
], HelixHeadlessListbox.prototype, "selectedLabel", void 0);
|
|
672
673
|
__decorate([
|
|
673
674
|
state()
|
|
674
|
-
], HelixHeadlessListbox.prototype, "
|
|
675
|
-
__decorate([
|
|
676
|
-
state()
|
|
677
|
-
], HelixHeadlessListbox.prototype, "counted", void 0);
|
|
675
|
+
], HelixHeadlessListbox.prototype, "activeValue", void 0);
|
|
678
676
|
HelixHeadlessListbox = __decorate([
|
|
679
677
|
customElement('helix-headless-listbox')
|
|
680
678
|
], HelixHeadlessListbox);
|
|
@@ -12,7 +12,8 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
12
12
|
* `name`, or its `label` if it has no name.
|
|
13
13
|
*
|
|
14
14
|
* All the markers in a map share one tab stop. The arrow keys move between
|
|
15
|
-
* them in the order they are written.
|
|
15
|
+
* them in the order they are written. Taking away the marker that has focus
|
|
16
|
+
* moves focus to the next one, or to the one before where it was the last.
|
|
16
17
|
*
|
|
17
18
|
* @since 0.105.0
|
|
18
19
|
* @status experimental
|
|
@@ -67,8 +67,20 @@ declare const HelixHeadlessMap_base: (new (...args: any[]) => import("@fusion.de
|
|
|
67
67
|
*
|
|
68
68
|
* @slot - The element your renderer draws the map in, and the map's markers, routes, areas, positions, and points layers.
|
|
69
69
|
* @slot attribution - The map credit, which most tile licenses require.
|
|
70
|
+
* @slot face-north-icon - Replaces the compass needle. It inherits `--map-needle-turn`, so `rotate: var(--map-needle-turn)` keeps it pointing north.
|
|
70
71
|
* @slot footer - Content below the map, such as a legend or a scale.
|
|
72
|
+
* @slot fullscreen-icon - Replaces the glyph inside the fullscreen button.
|
|
71
73
|
* @slot header - Content above the map, such as a title or a search field.
|
|
74
|
+
* @slot layers-icon - Replaces the glyph inside the layers button.
|
|
75
|
+
* @slot pan-down-icon - Replaces the glyph inside the pan down button.
|
|
76
|
+
* @slot pan-end-icon - Replaces the glyph inside the button that pans toward the end of a line of text.
|
|
77
|
+
* @slot pan-start-icon - Replaces the glyph inside the button that pans toward the start of a line of text.
|
|
78
|
+
* @slot pan-up-icon - Replaces the glyph inside the pan up button.
|
|
79
|
+
* @slot rotate-left-icon - Replaces the glyph inside the rotate left button.
|
|
80
|
+
* @slot rotate-right-icon - Replaces the glyph inside the rotate right button.
|
|
81
|
+
* @slot tilt-icon - Replaces the "3D" inside the 3D button.
|
|
82
|
+
* @slot zoom-in-icon - Replaces the glyph inside the zoom-in button.
|
|
83
|
+
* @slot zoom-out-icon - Replaces the glyph inside the zoom-out button.
|
|
72
84
|
*
|
|
73
85
|
* @event {Event} change - The layers menu changed the map type, which `map-type` now holds.
|
|
74
86
|
* @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.
|
|
@@ -122,8 +134,11 @@ declare const HelixHeadlessMap_base: (new (...args: any[]) => import("@fusion.de
|
|
|
122
134
|
*
|
|
123
135
|
* @cssstate fullscreen - The map fills the screen.
|
|
124
136
|
* @cssstate idle - The user has been still long enough for the header and footer to fade.
|
|
137
|
+
* @cssstate layers-open - The layers menu is open.
|
|
125
138
|
* @cssstate ready - The map has been drawn whole, after `helix-map-ready`.
|
|
139
|
+
* @cssstate rotated - The map is turned away from north, by `bearing`.
|
|
126
140
|
* @cssstate sharing - The page keeps the plain wheel and one finger, with `gestures="cooperative"` or while a map with `gestures="activate"` waits to be pressed.
|
|
141
|
+
* @cssstate tilted - The map is tilted by `pitch`, so it no longer looks straight down.
|
|
127
142
|
* @cssstate using - A map with `gestures="activate"` has been pressed and has the gestures.
|
|
128
143
|
*/
|
|
129
144
|
export declare class HelixHeadlessMap extends HelixHeadlessMap_base {
|
|
@@ -323,8 +338,31 @@ export declare class HelixHeadlessMap extends HelixHeadlessMap_base {
|
|
|
323
338
|
protected readonly keys: KeyboardNavigationController;
|
|
324
339
|
/** The marker a press or a click came from, where it came from one. */
|
|
325
340
|
private markerOf;
|
|
341
|
+
/**
|
|
342
|
+
* The marker focus is on, while it is.
|
|
343
|
+
*
|
|
344
|
+
* **Kept so a marker the page takes away hands focus on.** A delivery done
|
|
345
|
+
* or a filter changed removes a marker, and the one a reader was on went
|
|
346
|
+
* with focus still in it: the browser dropped focus to the page, and the
|
|
347
|
+
* reader was put back at its top with nothing said.
|
|
348
|
+
*/
|
|
349
|
+
private focused;
|
|
326
350
|
/** Moves the tab stop to the marker focus arrived at. */
|
|
327
351
|
private readonly handleFocusIn;
|
|
352
|
+
/**
|
|
353
|
+
* Forgets the marker focus left, unless the page took it away.
|
|
354
|
+
*
|
|
355
|
+
* Focus leaving for nothing is a press on the page or the marker removed,
|
|
356
|
+
* and which one is known once the removal has finished: a marker still in
|
|
357
|
+
* the page was left, and one gone is owed a place for focus to land.
|
|
358
|
+
*/
|
|
359
|
+
private readonly handleFocusOut;
|
|
360
|
+
/**
|
|
361
|
+
* Gives focus to the marker that took the stop of one the page took away
|
|
362
|
+
* with focus on it: the next, the last where it was the last, its cluster
|
|
363
|
+
* where it is gathered, and the region where none is left.
|
|
364
|
+
*/
|
|
365
|
+
private refocus;
|
|
328
366
|
/**
|
|
329
367
|
* Says a marker was pressed, by click, Enter or Space: a place by its name,
|
|
330
368
|
* and a cluster as a cluster, from the marker it is drawn as.
|
|
@@ -376,7 +414,7 @@ export declare class HelixHeadlessMap extends HelixHeadlessMap_base {
|
|
|
376
414
|
* order they are written, with its picture and name, pressed while it is
|
|
377
415
|
* shown. A group's tile is pressed while any of its layers is shown.
|
|
378
416
|
*/
|
|
379
|
-
|
|
417
|
+
protected renderLayersMenu(): TemplateResult | typeof nothing;
|
|
380
418
|
/**
|
|
381
419
|
* The map types, as cards with a picture of the map in each: Standard,
|
|
382
420
|
* Hybrid, and Satellite. One is chosen, so they are radio buttons, and the
|
|
@@ -392,7 +430,7 @@ export declare class HelixHeadlessMap extends HelixHeadlessMap_base {
|
|
|
392
430
|
* arrows around it are the way to move and turn the map without dragging,
|
|
393
431
|
* which a pointer otherwise needs.
|
|
394
432
|
*/
|
|
395
|
-
|
|
433
|
+
protected renderCompass(pan: boolean, rotate: boolean): TemplateResult;
|
|
396
434
|
/**
|
|
397
435
|
* The controls, in one column in the order they are read: fullscreen, the
|
|
398
436
|
* layers, 3D, zoom, and the compass with the arrows round it, last, where
|