@fusion.dev/helix-headless 0.165.0 → 0.166.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 +578 -54
- package/dist/callout/root/callout-root.d.ts +8 -2
- package/dist/callout/root/callout-root.js +14 -1
- package/dist/code-block/root/code-block-root.d.ts +63 -0
- package/dist/code-block/root/code-block-root.js +117 -6
- package/dist/element-events.generated.js +15 -2
- package/dist/filter-input/menu/filter-menu.d.ts +1 -0
- package/dist/filter-input/menu/filter-menu.js +1 -1
- package/dist/listbox/root/listbox-root.js +2 -5
- package/dist/menu/item/menu-item.d.ts +20 -0
- package/dist/menu/item/menu-item.js +53 -20
- package/dist/menu/root/menu-root.d.ts +84 -1
- package/dist/menu/root/menu-root.js +187 -44
- package/dist/object-inspector/root/object-inspector-root.d.ts +5 -0
- package/dist/object-inspector/root/object-inspector-root.js +5 -0
- package/dist/steps/root/steps-root.d.ts +7 -0
- package/dist/steps/root/steps-root.js +7 -0
- package/dist/video/root/video-root.d.ts +2 -0
- package/dist/video/root/video-root.js +4 -2
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +1 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +1 -1
- package/dist/video-playlist/root/video-playlist-root.js +15 -1
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +262 -20
- package/types/vue.d.ts +59 -5
- package/types/words.d.ts +18 -0
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { AriaForwardController, anchorElement, customElement, DrilldownController, deepActiveElement, deepContains, focusTarget, HelixElement, inlineStep, KeyboardNavigationController, linkDescription, MixinCollection, MixinControllerOpen, onUnlessFalse, PopoverController, scrollItemIntoView, sideOf, slottedWords, tellDisclosure, typeaheadBy, unlinkDescription, words, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, anchorElement, customElement, DrilldownController, deepActiveElement, deepContains, filterKeeps, focusTarget, HelixElement, HelixFilterEvent, inlineStep, KeyboardNavigationController, linkDescription, MixinCollection, MixinControllerOpen, markMatches, onUnlessFalse, PopoverController, scrollItemIntoView, sideOf, slottedWords, tellDisclosure, typeaheadBy, unlinkDescription, words, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretLeft } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
@@ -33,8 +33,12 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
33
33
|
this.backLabel = 'Back';
|
|
34
34
|
this.closeOnSelect = true;
|
|
35
35
|
this.context = false;
|
|
36
|
+
this.filter = '';
|
|
37
|
+
this.filterable = false;
|
|
38
|
+
this.filterLabel = 'Filter';
|
|
36
39
|
this.label = '';
|
|
37
40
|
this.longPressLabel = 'Long press or press Alt+Down to show the menu';
|
|
41
|
+
this.noResultsText = 'No matches';
|
|
38
42
|
this.offset = 4;
|
|
39
43
|
this.longPress = new LongPress(this, {
|
|
40
44
|
onLongPress: () => {
|
|
@@ -68,7 +72,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
68
72
|
});
|
|
69
73
|
this.aria = new AriaForwardController(this, {
|
|
70
74
|
label: true,
|
|
71
|
-
target: () => this.
|
|
75
|
+
target: () => this.menuBox,
|
|
72
76
|
});
|
|
73
77
|
this.panel = new PopoverController(this, {
|
|
74
78
|
anchor: () => this.context && this.point
|
|
@@ -89,6 +93,11 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
89
93
|
surface: () => this.partNamed('surface'),
|
|
90
94
|
});
|
|
91
95
|
this.settledOnce = false;
|
|
96
|
+
this.filterPage = null;
|
|
97
|
+
this.handleFilterInput = (event) => {
|
|
98
|
+
event.stopPropagation();
|
|
99
|
+
this.filterBy(event.target.value);
|
|
100
|
+
};
|
|
92
101
|
this.handleContextMenu = (event) => {
|
|
93
102
|
if (!this.context) {
|
|
94
103
|
return;
|
|
@@ -129,14 +138,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
129
138
|
};
|
|
130
139
|
this.handleFocusIn = (event) => {
|
|
131
140
|
const item = this.items.find((row) => row.contains(event.target));
|
|
132
|
-
if (
|
|
133
|
-
|
|
141
|
+
if (item) {
|
|
142
|
+
this.revealRow(item);
|
|
134
143
|
}
|
|
135
|
-
const holder = this.flies ? this.holderOf(item) : null;
|
|
136
|
-
const surface = holder
|
|
137
|
-
? holder.shadowRoot?.querySelector('[part="surface"]')
|
|
138
|
-
: this.partNamed('surface');
|
|
139
|
-
scrollItemIntoView(item, { padding: 4, ...(surface ? { scroller: surface } : {}) });
|
|
140
144
|
};
|
|
141
145
|
this.handleKeydown = (event) => {
|
|
142
146
|
if (!this.open) {
|
|
@@ -146,9 +150,23 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
146
150
|
const items = this.items;
|
|
147
151
|
const at = items.findIndex((item) => item.active);
|
|
148
152
|
const along = inlineStep(this, event.key);
|
|
153
|
+
const typing = this.filterable && event.composedPath()[0] === this.field;
|
|
154
|
+
const step = event.key === 'ArrowDown' ? 1 : event.key === 'ArrowUp' ? -1 : 0;
|
|
149
155
|
if (event.key === 'Escape') {
|
|
150
156
|
event.stopPropagation();
|
|
151
|
-
this.
|
|
157
|
+
if (!this.filterable || this.filter === '') {
|
|
158
|
+
this.leave();
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
this.filterBy('');
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
else if (typing && step !== 0) {
|
|
165
|
+
const count = items.length;
|
|
166
|
+
this.reach(items[at < 0 ? (step > 0 ? 0 : count - 1) : (at + step + count) % count]);
|
|
167
|
+
}
|
|
168
|
+
else if (typing && event.key === 'Enter') {
|
|
169
|
+
items[at]?.renderRoot.querySelector('[part="item"]')?.click();
|
|
152
170
|
}
|
|
153
171
|
else if (along === 1 && items[at]?.hasSubmenu) {
|
|
154
172
|
this.enter(items[at]);
|
|
@@ -188,6 +206,14 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
188
206
|
this.longPress.down(event);
|
|
189
207
|
}
|
|
190
208
|
};
|
|
209
|
+
this.handleMouseDown = (event) => {
|
|
210
|
+
if (this.filterable &&
|
|
211
|
+
this.open &&
|
|
212
|
+
event.composedPath()[0] !== this.field &&
|
|
213
|
+
!this.fromTrigger(event)) {
|
|
214
|
+
event.preventDefault();
|
|
215
|
+
}
|
|
216
|
+
};
|
|
191
217
|
this.handlePointerMove = (event) => {
|
|
192
218
|
this.longPress.move(event);
|
|
193
219
|
};
|
|
@@ -209,7 +235,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
209
235
|
}
|
|
210
236
|
};
|
|
211
237
|
this.handleHover = (event) => {
|
|
212
|
-
if (!this.flies || !this.open || event.pointerType !== 'mouse') {
|
|
238
|
+
if (!(this.flies || this.filterable) || !this.open || event.pointerType !== 'mouse') {
|
|
213
239
|
return;
|
|
214
240
|
}
|
|
215
241
|
const row = event
|
|
@@ -221,7 +247,10 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
221
247
|
this.hovered = row;
|
|
222
248
|
this.grace = undefined;
|
|
223
249
|
if (!row.disabled) {
|
|
224
|
-
|
|
250
|
+
this.reach(row);
|
|
251
|
+
}
|
|
252
|
+
if (!this.flies) {
|
|
253
|
+
return;
|
|
225
254
|
}
|
|
226
255
|
clearTimeout(this.hoverTimer);
|
|
227
256
|
this.hoverTimer = setTimeout(() => {
|
|
@@ -334,7 +363,53 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
334
363
|
}
|
|
335
364
|
get items() {
|
|
336
365
|
const rows = this.flies ? this.rowsOf(this.keyPage) : this.drilldown.rows;
|
|
337
|
-
return rows.filter((row) => !row.disabled);
|
|
366
|
+
return rows.filter((row) => !row.disabled && this.kept(row));
|
|
367
|
+
}
|
|
368
|
+
get menuBox() {
|
|
369
|
+
return this.filterable
|
|
370
|
+
? (this.renderRoot?.querySelector('#items') ?? null)
|
|
371
|
+
: this.partNamed('surface');
|
|
372
|
+
}
|
|
373
|
+
get field() {
|
|
374
|
+
return this.partNamed('search-field');
|
|
375
|
+
}
|
|
376
|
+
get filtering() {
|
|
377
|
+
return this.filterable && this.filter.trim() !== '' && this.filter !== this.refused;
|
|
378
|
+
}
|
|
379
|
+
kept(row) {
|
|
380
|
+
return (!this.filtering ||
|
|
381
|
+
this.holderOf(row) !== this.filterPage ||
|
|
382
|
+
filterKeeps(slottedWords(row, ['']), this.filter.trim(), this.filterMatch));
|
|
383
|
+
}
|
|
384
|
+
requestFilter(value) {
|
|
385
|
+
if (value === this.filter) {
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
this.filterPage = this.flies ? this.keyPage : this.drilldown.page;
|
|
389
|
+
this.refused = this.dispatchEvent(new HelixFilterEvent({ value })) ? undefined : value;
|
|
390
|
+
this.filter = value;
|
|
391
|
+
}
|
|
392
|
+
filterBy(value) {
|
|
393
|
+
this.requestFilter(value);
|
|
394
|
+
void this.updateComplete.then(() => this.reach(this.items[0]));
|
|
395
|
+
}
|
|
396
|
+
reach(row) {
|
|
397
|
+
if (!this.filterable) {
|
|
398
|
+
row?.focus();
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
if (this.highlighted && this.highlighted !== row) {
|
|
402
|
+
this.highlighted.highlighted = false;
|
|
403
|
+
}
|
|
404
|
+
this.highlighted = row;
|
|
405
|
+
const field = this.field;
|
|
406
|
+
if (field && 'ariaActiveDescendantElement' in field) {
|
|
407
|
+
field.ariaActiveDescendantElement = row ?? null;
|
|
408
|
+
}
|
|
409
|
+
if (row) {
|
|
410
|
+
row.highlighted = true;
|
|
411
|
+
this.revealRow(row);
|
|
412
|
+
}
|
|
338
413
|
}
|
|
339
414
|
show() {
|
|
340
415
|
this.openAt('first');
|
|
@@ -345,7 +420,8 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
345
420
|
}
|
|
346
421
|
this.updateComplete.then(() => {
|
|
347
422
|
const items = this.items;
|
|
348
|
-
|
|
423
|
+
this.field?.focus();
|
|
424
|
+
this.reach(end === 'first' ? items[0] : items[items.length - 1]);
|
|
349
425
|
});
|
|
350
426
|
}
|
|
351
427
|
hide() {
|
|
@@ -355,6 +431,8 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
355
431
|
this.panel.hide();
|
|
356
432
|
this.drilldown.reset();
|
|
357
433
|
this.stopHover();
|
|
434
|
+
this.requestFilter('');
|
|
435
|
+
this.reach(undefined);
|
|
358
436
|
if (deepContains(this, deepActiveElement())) {
|
|
359
437
|
;
|
|
360
438
|
(this.context ? (this.returnTo ?? this.trigger) : this.trigger).focus();
|
|
@@ -377,18 +455,20 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
377
455
|
if (!this.drilldown.enter(item)) {
|
|
378
456
|
return;
|
|
379
457
|
}
|
|
458
|
+
this.requestFilter('');
|
|
380
459
|
void this.updateComplete.then(async () => {
|
|
381
460
|
if (!this.flies) {
|
|
382
|
-
this.items[0]
|
|
461
|
+
this.reach(this.items[0]);
|
|
383
462
|
return;
|
|
384
463
|
}
|
|
385
464
|
await item.updateComplete;
|
|
386
465
|
const first = this.rowsOf(item).find((row) => !row.disabled);
|
|
387
466
|
await first?.updateComplete;
|
|
388
|
-
first
|
|
467
|
+
this.reach(first);
|
|
389
468
|
});
|
|
390
469
|
}
|
|
391
470
|
leave() {
|
|
471
|
+
this.requestFilter('');
|
|
392
472
|
if (this.flies) {
|
|
393
473
|
const holder = this.keyPage;
|
|
394
474
|
if (!holder) {
|
|
@@ -396,7 +476,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
396
476
|
return;
|
|
397
477
|
}
|
|
398
478
|
this.openPage(this.holderOf(holder));
|
|
399
|
-
this.updateComplete.then(() =>
|
|
479
|
+
this.updateComplete.then(() => this.reach(holder));
|
|
400
480
|
return;
|
|
401
481
|
}
|
|
402
482
|
if (this.drilldown.atRoot) {
|
|
@@ -405,7 +485,14 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
405
485
|
}
|
|
406
486
|
const leaving = this.drilldown.page;
|
|
407
487
|
this.drilldown.back();
|
|
408
|
-
this.updateComplete.then(() => leaving
|
|
488
|
+
this.updateComplete.then(() => this.reach(leaving ?? undefined));
|
|
489
|
+
}
|
|
490
|
+
revealRow(item) {
|
|
491
|
+
const holder = this.flies ? this.holderOf(item) : null;
|
|
492
|
+
const surface = holder
|
|
493
|
+
? holder.shadowRoot?.querySelector('[part="surface"]')
|
|
494
|
+
: this.partNamed('surface');
|
|
495
|
+
scrollItemIntoView(item, { padding: 4, ...(surface ? { scroller: surface } : {}) });
|
|
409
496
|
}
|
|
410
497
|
handleClosedKeydown(event) {
|
|
411
498
|
if (this.context && event.shiftKey && event.key === 'F10' && this.fromTrigger(event)) {
|
|
@@ -462,6 +549,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
462
549
|
this.addEventListener('focusin', this.handleFocusIn);
|
|
463
550
|
this.addEventListener('contextmenu', this.handleContextMenu);
|
|
464
551
|
this.addEventListener('pointerdown', this.handlePointerDown);
|
|
552
|
+
this.addEventListener('mousedown', this.handleMouseDown);
|
|
465
553
|
this.addEventListener('pointermove', this.handlePointerMove);
|
|
466
554
|
this.addEventListener('pointerup', this.handlePointerUp);
|
|
467
555
|
this.addEventListener('pointercancel', this.handlePointerCancel);
|
|
@@ -484,6 +572,10 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
484
572
|
this.removeEventListener('focusin', this.handleFocusIn);
|
|
485
573
|
this.removeEventListener('contextmenu', this.handleContextMenu);
|
|
486
574
|
this.removeEventListener('pointerdown', this.handlePointerDown);
|
|
575
|
+
this.removeEventListener('mousedown', this.handleMouseDown);
|
|
576
|
+
if (this.filterable) {
|
|
577
|
+
markMatches(this, [], '');
|
|
578
|
+
}
|
|
487
579
|
this.removeEventListener('pointermove', this.handlePointerMove);
|
|
488
580
|
this.removeEventListener('pointerup', this.handlePointerUp);
|
|
489
581
|
this.removeEventListener('pointercancel', this.handlePointerCancel);
|
|
@@ -505,7 +597,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
505
597
|
const top = this.flies || this.drilldown.atRoot;
|
|
506
598
|
for (const child of this.children) {
|
|
507
599
|
if (isSection(child)) {
|
|
508
|
-
child.onPage =
|
|
600
|
+
child.onPage =
|
|
601
|
+
top &&
|
|
602
|
+
(!this.filtering || [...child.children].some((row) => isItem(row) && this.kept(row)));
|
|
509
603
|
for (const row of child.children) {
|
|
510
604
|
if (row.isMenuItem === true) {
|
|
511
605
|
this.mark(row, top);
|
|
@@ -522,9 +616,18 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
522
616
|
this.toggleState('drilled', !this.flies && !this.drilldown.atRoot);
|
|
523
617
|
this.markColumns();
|
|
524
618
|
this.nameSurface();
|
|
619
|
+
if (this.filterable) {
|
|
620
|
+
markMatches(this, this.rowsOf(this.filterPage).filter((row) => this.kept(row)), this.filtering ? this.filter.trim() : '');
|
|
621
|
+
const items = this.items;
|
|
622
|
+
if (changed.has('filter') &&
|
|
623
|
+
this.open &&
|
|
624
|
+
!items.includes(this.highlighted)) {
|
|
625
|
+
this.reach(items[0]);
|
|
626
|
+
}
|
|
627
|
+
}
|
|
525
628
|
}
|
|
526
629
|
nameSurface() {
|
|
527
|
-
const surface = this.
|
|
630
|
+
const surface = this.menuBox;
|
|
528
631
|
if (!surface || !('ariaLabelledByElements' in surface)) {
|
|
529
632
|
return;
|
|
530
633
|
}
|
|
@@ -544,7 +647,8 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
544
647
|
}
|
|
545
648
|
mark(item, onPage) {
|
|
546
649
|
const page = this.drilldown.page;
|
|
547
|
-
item.onPage = onPage;
|
|
650
|
+
item.onPage = onPage && this.kept(item);
|
|
651
|
+
item.virtual = this.filterable;
|
|
548
652
|
const holds = page !== null && item.contains(page);
|
|
549
653
|
item.flyout = this.flies;
|
|
550
654
|
item.expanded = this.flies && holds;
|
|
@@ -553,7 +657,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
553
657
|
for (const child of item.children) {
|
|
554
658
|
const nested = child;
|
|
555
659
|
if (nested.isMenuItem === true && child.slot === 'submenu') {
|
|
556
|
-
this.mark(nested, onPage && holds);
|
|
660
|
+
this.mark(nested, item.onPage && holds);
|
|
557
661
|
}
|
|
558
662
|
}
|
|
559
663
|
return;
|
|
@@ -568,6 +672,32 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
568
672
|
}
|
|
569
673
|
render() {
|
|
570
674
|
const point = this.context && this.point;
|
|
675
|
+
const filtering = this.filtering;
|
|
676
|
+
const none = filtering && !this.rowsOf(this.filterPage).some((row) => this.kept(row));
|
|
677
|
+
this.announced = none ? this.noResultsText : '';
|
|
678
|
+
const rows = html `${this.flies || this.drilldown.atRoot
|
|
679
|
+
? nothing
|
|
680
|
+
: html `<div part="header">
|
|
681
|
+
<button
|
|
682
|
+
part="back"
|
|
683
|
+
type="button"
|
|
684
|
+
role="menuitem"
|
|
685
|
+
tabindex="-1"
|
|
686
|
+
aria-label=${this.backLabel}
|
|
687
|
+
@click=${() => this.leave()}
|
|
688
|
+
>
|
|
689
|
+
<svg part="back-mark" data-mirror fill="currentColor" viewBox=${caretLeft.viewBox} aria-hidden="true">
|
|
690
|
+
${unsafeSVG(caretLeft.content)}
|
|
691
|
+
</svg>
|
|
692
|
+
</button>
|
|
693
|
+
<span part="title">${this.drilldown.label}</span>
|
|
694
|
+
</div>`}
|
|
695
|
+
<slot @slotchange=${(event) => this.countRows(event)}></slot>
|
|
696
|
+
${none
|
|
697
|
+
? html `<p part="empty"><slot name="no-results">${this.noResultsText}</slot></p>`
|
|
698
|
+
: this.renderStatus(this.hasRows)}`;
|
|
699
|
+
const busy = this.loading ? 'true' : nothing;
|
|
700
|
+
const label = this.label || nothing;
|
|
571
701
|
return html `<slot name="trigger" @click=${this.handleTriggerClick}></slot>${point
|
|
572
702
|
? html `<span
|
|
573
703
|
id="point"
|
|
@@ -578,31 +708,27 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
578
708
|
<div
|
|
579
709
|
part="surface"
|
|
580
710
|
popover="manual"
|
|
581
|
-
role
|
|
582
|
-
aria-busy=${this.
|
|
583
|
-
aria-label=${this.
|
|
711
|
+
role=${this.filterable ? nothing : 'menu'}
|
|
712
|
+
aria-busy=${this.filterable ? nothing : busy}
|
|
713
|
+
aria-label=${this.filterable ? nothing : label}
|
|
584
714
|
data-drilled=${this.flies || this.drilldown.atRoot ? nothing : ''}
|
|
715
|
+
data-filtered=${filtering ? '' : nothing}
|
|
585
716
|
?hidden=${!this.open}
|
|
586
717
|
>
|
|
587
|
-
${this.
|
|
588
|
-
?
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
aria-label=${this.
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
</button>
|
|
602
|
-
<span part="title">${this.drilldown.label}</span>
|
|
603
|
-
</div>`}
|
|
604
|
-
<slot @slotchange=${(event) => this.countRows(event)}></slot>
|
|
605
|
-
${this.renderStatus(this.hasRows)}
|
|
718
|
+
${this.filterable
|
|
719
|
+
? html `<input
|
|
720
|
+
part="search-field"
|
|
721
|
+
type="text"
|
|
722
|
+
autocomplete="off"
|
|
723
|
+
spellcheck="false"
|
|
724
|
+
.value=${this.filter}
|
|
725
|
+
placeholder=${this.filterLabel}
|
|
726
|
+
aria-label=${this.filterLabel}
|
|
727
|
+
aria-autocomplete="list"
|
|
728
|
+
aria-controls="items"
|
|
729
|
+
@input=${this.handleFilterInput}
|
|
730
|
+
/><div id="items" role="menu" aria-busy=${busy} aria-label=${label}>${rows}</div>`
|
|
731
|
+
: rows}
|
|
606
732
|
</div>${this.renderLive(this.hasRows)}`;
|
|
607
733
|
}
|
|
608
734
|
};
|
|
@@ -616,6 +742,19 @@ __decorate([
|
|
|
616
742
|
__decorate([
|
|
617
743
|
property({ reflect: true, type: Boolean })
|
|
618
744
|
], HelixHeadlessMenu.prototype, "context", void 0);
|
|
745
|
+
__decorate([
|
|
746
|
+
property()
|
|
747
|
+
], HelixHeadlessMenu.prototype, "filter", void 0);
|
|
748
|
+
__decorate([
|
|
749
|
+
property({ type: Boolean })
|
|
750
|
+
], HelixHeadlessMenu.prototype, "filterable", void 0);
|
|
751
|
+
__decorate([
|
|
752
|
+
words,
|
|
753
|
+
property({ attribute: 'filter-label' })
|
|
754
|
+
], HelixHeadlessMenu.prototype, "filterLabel", void 0);
|
|
755
|
+
__decorate([
|
|
756
|
+
property({ attribute: false })
|
|
757
|
+
], HelixHeadlessMenu.prototype, "filterMatch", void 0);
|
|
619
758
|
__decorate([
|
|
620
759
|
property()
|
|
621
760
|
], HelixHeadlessMenu.prototype, "label", void 0);
|
|
@@ -623,6 +762,10 @@ __decorate([
|
|
|
623
762
|
words,
|
|
624
763
|
property({ attribute: 'long-press-label' })
|
|
625
764
|
], HelixHeadlessMenu.prototype, "longPressLabel", void 0);
|
|
765
|
+
__decorate([
|
|
766
|
+
words,
|
|
767
|
+
property({ attribute: 'no-results-text' })
|
|
768
|
+
], HelixHeadlessMenu.prototype, "noResultsText", void 0);
|
|
626
769
|
__decorate([
|
|
627
770
|
property({ type: Number })
|
|
628
771
|
], HelixHeadlessMenu.prototype, "offset", void 0);
|
|
@@ -390,6 +390,11 @@ export declare class HelixHeadlessObjectInspector extends HelixElement {
|
|
|
390
390
|
private counted;
|
|
391
391
|
/** Says how many entries the filter matched, and nothing for an empty one. */
|
|
392
392
|
private tell;
|
|
393
|
+
/**
|
|
394
|
+
* Moves focus to the row the keys move from, or to the tree while that row
|
|
395
|
+
* is scrolled out of the window, as Tab reaches them.
|
|
396
|
+
*/
|
|
397
|
+
focus(options?: FocusOptions): void;
|
|
393
398
|
protected firstUpdated(changed: PropertyValues): void;
|
|
394
399
|
protected updated(changed: PropertyValues): void;
|
|
395
400
|
/**
|
|
@@ -268,6 +268,11 @@ let HelixHeadlessObjectInspector = class HelixHeadlessObjectInspector extends He
|
|
|
268
268
|
this.status.say(this.counted('result', this.found.size));
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
|
+
focus(options) {
|
|
272
|
+
this.renderRoot
|
|
273
|
+
?.querySelector('#tree[tabindex="0"], #tree [tabindex="0"]')
|
|
274
|
+
?.focus(options);
|
|
275
|
+
}
|
|
271
276
|
firstUpdated(changed) {
|
|
272
277
|
super.firstUpdated(changed);
|
|
273
278
|
this.finishHydration();
|
|
@@ -158,6 +158,13 @@ export declare class HelixHeadlessSteps extends HelixHeadlessSteps_base {
|
|
|
158
158
|
* calls to `next()` in one task then move two stages.
|
|
159
159
|
*/
|
|
160
160
|
private get at();
|
|
161
|
+
/**
|
|
162
|
+
* Requests a new current stage, and returns whether it moved.
|
|
163
|
+
*
|
|
164
|
+
* Where only a step's `current` says where the reader is, `active` is first
|
|
165
|
+
* written with that step, so `helix-activate` names it as `previous`.
|
|
166
|
+
*/
|
|
167
|
+
requestActive(next: string, cause?: string): boolean;
|
|
161
168
|
/**
|
|
162
169
|
* Moves to the next stage that can be gone to, as Ark UI's `goToNextStep`
|
|
163
170
|
* does. Returns whether it moved: not past the last stage, not into a stage
|
|
@@ -65,6 +65,13 @@ let HelixHeadlessSteps = class HelixHeadlessSteps extends MixinControllerActive(
|
|
|
65
65
|
const item = this.resolveActive(steps);
|
|
66
66
|
return item ? steps.indexOf(item) : -1;
|
|
67
67
|
}
|
|
68
|
+
requestActive(next, cause) {
|
|
69
|
+
const here = this.active === '' ? this.steps[this.at]?.value : undefined;
|
|
70
|
+
if (here) {
|
|
71
|
+
this.active = here;
|
|
72
|
+
}
|
|
73
|
+
return super.requestActive(next, cause);
|
|
74
|
+
}
|
|
68
75
|
next() {
|
|
69
76
|
return this.step(1);
|
|
70
77
|
}
|
|
@@ -115,6 +115,7 @@ import '../../menu/index.js';
|
|
|
115
115
|
* @csspart captions-menu-header - The bar above a submenu, holding the way back and its name.
|
|
116
116
|
* @csspart captions-menu-live - The inner menu's `live` part, a live region that repeats the empty and loading text for screen readers.
|
|
117
117
|
* @csspart captions-menu-loading - The text shown while the items are loading.
|
|
118
|
+
* @csspart captions-menu-search-field - The inner menu's filter field, drawn with `filterable`.
|
|
118
119
|
* @csspart captions-menu-surface - The floating panel the menu is drawn on.
|
|
119
120
|
* @csspart captions-menu-title - The name of the submenu that is showing.
|
|
120
121
|
* @csspart controls - The control bar along the bottom.
|
|
@@ -148,6 +149,7 @@ import '../../menu/index.js';
|
|
|
148
149
|
* @csspart overflow-header - The bar above a submenu, holding the way back and its name.
|
|
149
150
|
* @csspart overflow-live - The inner menu's `live` part, a live region that repeats the empty and loading text for screen readers.
|
|
150
151
|
* @csspart overflow-loading - The text shown while the items are loading.
|
|
152
|
+
* @csspart overflow-search-field - The inner menu's filter field, drawn with `filterable`.
|
|
151
153
|
* @csspart overflow-surface - The floating panel the menu is drawn on.
|
|
152
154
|
* @csspart overflow-title - The name of the submenu that is showing.
|
|
153
155
|
* @csspart pip - The picture-in-picture button, when `extra-controls` includes it and the browser supports it.
|
|
@@ -594,7 +594,8 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
594
594
|
}
|
|
595
595
|
return html `<${this.tag('menu')} part="captions-menu"
|
|
596
596
|
exportparts="back: captions-menu-back, back-mark: captions-menu-back-mark, empty: captions-menu-empty,
|
|
597
|
-
header: captions-menu-header, live: captions-menu-live, loading: captions-menu-loading,
|
|
597
|
+
header: captions-menu-header, live: captions-menu-live, loading: captions-menu-loading,
|
|
598
|
+
search-field: captions-menu-search-field, surface: captions-menu-surface,
|
|
598
599
|
title: captions-menu-title" label=${this.subtitlesLabel} placement="top-end"
|
|
599
600
|
@toggle=${(event) => this.heardMenu('captions', event)}>
|
|
600
601
|
<button
|
|
@@ -804,7 +805,8 @@ let HelixHeadlessVideo = class HelixHeadlessVideo extends HelixElement {
|
|
|
804
805
|
? nothing
|
|
805
806
|
: html `<${this.tag('menu')} part="overflow"
|
|
806
807
|
exportparts="back: overflow-back, back-mark: overflow-back-mark, empty: overflow-empty,
|
|
807
|
-
header: overflow-header, live: overflow-live, loading: overflow-loading,
|
|
808
|
+
header: overflow-header, live: overflow-live, loading: overflow-loading,
|
|
809
|
+
search-field: overflow-search-field, surface: overflow-surface,
|
|
808
810
|
title: overflow-title" label=${this.moreLabel} placement="top-end"
|
|
809
811
|
@toggle=${(event) => this.heardMenu('overflow', event)}>
|
|
810
812
|
<button
|
|
@@ -38,6 +38,7 @@ import '../../menu/index.js';
|
|
|
38
38
|
* @csspart menu-header - The bar above a submenu, holding the back button and the submenu's name.
|
|
39
39
|
* @csspart menu-live - The inner menu's `live` part, the region screen readers announce its empty and loading messages from.
|
|
40
40
|
* @csspart menu-loading - Shown while the items are loading.
|
|
41
|
+
* @csspart menu-search-field - The inner menu's filter field, drawn with `filterable`.
|
|
41
42
|
* @csspart menu-surface - The floating panel the menu is drawn on.
|
|
42
43
|
* @csspart menu-title - The name of the submenu that is shown.
|
|
43
44
|
* @csspart poster - An entry's poster image, if it has one.
|
|
@@ -84,7 +84,7 @@ let HelixHeadlessVideoPlaylistMenu = class HelixHeadlessVideoPlaylistMenu extend
|
|
|
84
84
|
renderMenu() {
|
|
85
85
|
return html `<${this.tag('menu')} part="menu"
|
|
86
86
|
exportparts="back: menu-back, back-mark: menu-back-mark, empty: menu-empty, header: menu-header,
|
|
87
|
-
live: menu-live, loading: menu-loading, surface: menu-surface, title: menu-title" label=${this.label} placement=${this.placement}
|
|
87
|
+
live: menu-live, loading: menu-loading, search-field: menu-search-field, surface: menu-surface, title: menu-title" label=${this.label} placement=${this.placement}
|
|
88
88
|
@toggle=${this.heardToggle}>
|
|
89
89
|
<slot name="trigger" slot="trigger">
|
|
90
90
|
<button
|
|
@@ -47,8 +47,16 @@ let HelixHeadlessVideoPlaylist = class HelixHeadlessVideoPlaylist extends MixinC
|
|
|
47
47
|
if (event.defaultPrevented) {
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
|
+
const value = event.detail.value;
|
|
51
|
+
const player = this.player;
|
|
52
|
+
if (value === this.active) {
|
|
53
|
+
if (player && player.paused !== false) {
|
|
54
|
+
void Promise.resolve(player.play()).catch(() => { });
|
|
55
|
+
}
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
50
58
|
this.chased = true;
|
|
51
|
-
this.requestActive(
|
|
59
|
+
this.requestActive(value, 'press');
|
|
52
60
|
};
|
|
53
61
|
this.handleFocusIn = (event) => {
|
|
54
62
|
const entry = event.target;
|
|
@@ -259,6 +267,12 @@ let HelixHeadlessVideoPlaylist = class HelixHeadlessVideoPlaylist extends MixinC
|
|
|
259
267
|
if (changed.has('shuffle') && !this.shuffle) {
|
|
260
268
|
this.dealt = undefined;
|
|
261
269
|
}
|
|
270
|
+
if (this.active === '' && this.childrenKnown) {
|
|
271
|
+
const opening = this.resolveActive(this.items);
|
|
272
|
+
if (opening) {
|
|
273
|
+
this.active = opening.value;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
262
276
|
}
|
|
263
277
|
updated(changed) {
|
|
264
278
|
super.updated?.(changed);
|