@fusion.dev/helix-headless 0.183.0 → 0.184.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 +483 -76
- package/dist/code-block/root/code-block-root.d.ts +42 -1
- package/dist/code-block/root/code-block-root.js +25 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/menu/filter/index.d.ts +1 -0
- package/dist/menu/filter/index.js +4 -0
- package/dist/menu/filter/menu-filter.d.ts +114 -0
- package/dist/menu/filter/menu-filter.js +172 -0
- package/dist/menu/root/menu-root.d.ts +28 -29
- package/dist/menu/root/menu-root.js +32 -107
- package/dist/time-input/root/time-input-root.d.ts +11 -0
- package/dist/time-input/root/time-input-root.js +11 -0
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +124 -10
- package/types/vue.d.ts +27 -4
- package/types/words.d.ts +7 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { AriaForwardController, anchorElement, customElement, DrilldownController, deepActiveElement, deepContains,
|
|
2
|
+
import { AriaForwardController, anchorElement, auditEntry, customElement, DrilldownController, deepActiveElement, deepContains, focusTarget, HelixElement, inlineStep, KeyboardNavigationController, linkDescription, MIRROR_RULE, MixinCollection, MixinControllerOpen, OpenPhaseController, onUnlessFalse, PopoverController, scrollItemIntoView, sideOf, slottedWords, tellDisclosure, typeaheadBy, unlinkDescription, words, } from '@fusion.dev/helix-core';
|
|
3
3
|
import { caretLeft } from '@fusion.dev/helix-icons';
|
|
4
4
|
import { html, nothing } from 'lit';
|
|
5
5
|
import { property } from 'lit/decorators.js';
|
|
@@ -98,18 +98,13 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
98
98
|
surface: () => this.partNamed('surface'),
|
|
99
99
|
});
|
|
100
100
|
this.settledOnce = false;
|
|
101
|
-
this.filterPage = null;
|
|
102
|
-
this.handleFilterInput = (event) => {
|
|
103
|
-
event.stopPropagation();
|
|
104
|
-
this.filterBy(event.target.value);
|
|
105
|
-
};
|
|
106
101
|
this.followRemoved = (records) => {
|
|
107
102
|
if (!this.open) {
|
|
108
103
|
return;
|
|
109
104
|
}
|
|
110
105
|
const active = deepActiveElement();
|
|
111
106
|
const lost = active === null || active === document.body || !active.isConnected;
|
|
112
|
-
const record = records.find((one) => [...one.removedNodes].some((node) => isItem(node) && (this.
|
|
107
|
+
const record = records.find((one) => [...one.removedNodes].some((node) => isItem(node) && (this.filters ? node === this.filters.highlighted : lost)));
|
|
113
108
|
if (!record) {
|
|
114
109
|
return;
|
|
115
110
|
}
|
|
@@ -125,7 +120,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
125
120
|
const next = after(record.nextSibling, 'nextSibling') ??
|
|
126
121
|
after(record.previousSibling, 'previousSibling') ??
|
|
127
122
|
items.at(-1);
|
|
128
|
-
if (this.
|
|
123
|
+
if (this.filters || next) {
|
|
129
124
|
this.reach(next);
|
|
130
125
|
return;
|
|
131
126
|
}
|
|
@@ -188,23 +183,13 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
188
183
|
const items = this.items;
|
|
189
184
|
const at = items.findIndex((item) => item.active);
|
|
190
185
|
const along = inlineStep(this, event.key);
|
|
191
|
-
|
|
192
|
-
|
|
186
|
+
if (this.filters?.keydown(event, items, at)) {
|
|
187
|
+
event.preventDefault();
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
193
190
|
if (event.key === 'Escape') {
|
|
194
191
|
event.stopPropagation();
|
|
195
|
-
|
|
196
|
-
this.leave();
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
this.filterBy('');
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
else if (typing && step !== 0) {
|
|
203
|
-
const count = items.length;
|
|
204
|
-
this.reach(items[at < 0 ? (step > 0 ? 0 : count - 1) : (at + step + count) % count]);
|
|
205
|
-
}
|
|
206
|
-
else if (typing && event.key === 'Enter') {
|
|
207
|
-
items[at]?.renderRoot.querySelector('[part="item"]')?.click();
|
|
192
|
+
this.leave();
|
|
208
193
|
}
|
|
209
194
|
else if (along === 1 && items[at]?.hasSubmenu) {
|
|
210
195
|
this.enter(items[at]);
|
|
@@ -244,14 +229,6 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
244
229
|
this.longPress.down(event);
|
|
245
230
|
}
|
|
246
231
|
};
|
|
247
|
-
this.handleMouseDown = (event) => {
|
|
248
|
-
if (this.filterable &&
|
|
249
|
-
this.open &&
|
|
250
|
-
event.composedPath()[0] !== this.field &&
|
|
251
|
-
!this.fromTrigger(event)) {
|
|
252
|
-
event.preventDefault();
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
232
|
this.handlePointerMove = (event) => {
|
|
256
233
|
this.longPress.move(event);
|
|
257
234
|
};
|
|
@@ -406,48 +383,27 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
406
383
|
return rows.filter((row) => !row.disabled && this.kept(row));
|
|
407
384
|
}
|
|
408
385
|
get menuBox() {
|
|
409
|
-
return this.
|
|
386
|
+
return this.filters
|
|
410
387
|
? (this.renderRoot?.querySelector('#items') ?? null)
|
|
411
388
|
: this.partNamed('surface');
|
|
412
389
|
}
|
|
413
|
-
get
|
|
414
|
-
return this.
|
|
415
|
-
}
|
|
416
|
-
get filtering() {
|
|
417
|
-
return this.filterable && this.filter.trim() !== '' && this.filter !== this.refused;
|
|
390
|
+
get filters() {
|
|
391
|
+
return this.filterable ? this.filterer : undefined;
|
|
418
392
|
}
|
|
419
393
|
kept(row) {
|
|
420
|
-
return
|
|
421
|
-
this.holderOf(row) !== this.filterPage ||
|
|
422
|
-
filterKeeps(slottedWords(row, ['']), this.filter.trim(), this.filterMatch));
|
|
394
|
+
return this.filters?.kept(row) ?? true;
|
|
423
395
|
}
|
|
424
396
|
requestFilter(value) {
|
|
425
|
-
|
|
426
|
-
return;
|
|
427
|
-
}
|
|
428
|
-
this.filterPage = this.flies ? this.keyPage : this.drilldown.page;
|
|
429
|
-
this.refused = this.dispatchEvent(new HelixFilterEvent({ value })) ? undefined : value;
|
|
430
|
-
this.filter = value;
|
|
431
|
-
}
|
|
432
|
-
filterBy(value) {
|
|
433
|
-
this.requestFilter(value);
|
|
434
|
-
void this.updateComplete.then(() => this.reach(this.items[0]));
|
|
397
|
+
this.filterer?.request(value);
|
|
435
398
|
}
|
|
436
399
|
reach(row) {
|
|
437
|
-
|
|
400
|
+
const filters = this.filters;
|
|
401
|
+
if (!filters) {
|
|
438
402
|
row?.focus();
|
|
439
403
|
return;
|
|
440
404
|
}
|
|
441
|
-
|
|
442
|
-
this.highlighted.highlighted = false;
|
|
443
|
-
}
|
|
444
|
-
this.highlighted = row;
|
|
445
|
-
const field = this.field;
|
|
446
|
-
if (field && 'ariaActiveDescendantElement' in field) {
|
|
447
|
-
field.ariaActiveDescendantElement = row ?? null;
|
|
448
|
-
}
|
|
405
|
+
filters.highlight(row);
|
|
449
406
|
if (row) {
|
|
450
|
-
row.highlighted = true;
|
|
451
407
|
this.revealRow(row);
|
|
452
408
|
}
|
|
453
409
|
}
|
|
@@ -460,7 +416,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
460
416
|
}
|
|
461
417
|
this.updateComplete.then(() => {
|
|
462
418
|
const items = this.items;
|
|
463
|
-
this.field?.focus();
|
|
419
|
+
this.filters?.field?.focus();
|
|
464
420
|
this.reach(end === 'first' ? items[0] : items[items.length - 1]);
|
|
465
421
|
});
|
|
466
422
|
}
|
|
@@ -610,7 +566,6 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
610
566
|
this.addEventListener('focusin', this.handleFocusIn);
|
|
611
567
|
this.addEventListener('contextmenu', this.handleContextMenu);
|
|
612
568
|
this.addEventListener('pointerdown', this.handlePointerDown);
|
|
613
|
-
this.addEventListener('mousedown', this.handleMouseDown);
|
|
614
569
|
this.addEventListener('pointermove', this.handlePointerMove);
|
|
615
570
|
this.addEventListener('pointerup', this.handlePointerUp);
|
|
616
571
|
this.addEventListener('pointercancel', this.handlePointerCancel);
|
|
@@ -635,10 +590,6 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
635
590
|
this.removeEventListener('focusin', this.handleFocusIn);
|
|
636
591
|
this.removeEventListener('contextmenu', this.handleContextMenu);
|
|
637
592
|
this.removeEventListener('pointerdown', this.handlePointerDown);
|
|
638
|
-
this.removeEventListener('mousedown', this.handleMouseDown);
|
|
639
|
-
if (this.filterable) {
|
|
640
|
-
markMatches(this, [], '');
|
|
641
|
-
}
|
|
642
593
|
this.removeEventListener('pointermove', this.handlePointerMove);
|
|
643
594
|
this.removeEventListener('pointerup', this.handlePointerUp);
|
|
644
595
|
this.removeEventListener('pointercancel', this.handlePointerCancel);
|
|
@@ -667,7 +618,8 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
667
618
|
if (isSection(child)) {
|
|
668
619
|
child.onPage =
|
|
669
620
|
top &&
|
|
670
|
-
(!this.filtering ||
|
|
621
|
+
(!this.filters?.filtering ||
|
|
622
|
+
[...child.children].some((row) => isItem(row) && this.kept(row)));
|
|
671
623
|
for (const row of child.children) {
|
|
672
624
|
if (row.isMenuItem === true) {
|
|
673
625
|
this.mark(row, top);
|
|
@@ -684,14 +636,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
684
636
|
this.toggleState('drilled', !this.flies && !this.drilldown.atRoot);
|
|
685
637
|
this.markColumns();
|
|
686
638
|
this.nameSurface();
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
if (changed.has('filter') &&
|
|
691
|
-
this.open &&
|
|
692
|
-
!items.includes(this.highlighted)) {
|
|
693
|
-
this.reach(items[0]);
|
|
694
|
-
}
|
|
639
|
+
this.filterer?.updated();
|
|
640
|
+
if (this.filterable && !this.filterer) {
|
|
641
|
+
auditEntry(this, 'filterable', 'menu/filter', 'it shows no filter field', () => this.filterable && !this.filterer);
|
|
695
642
|
}
|
|
696
643
|
}
|
|
697
644
|
nameSurface() {
|
|
@@ -729,7 +676,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
729
676
|
mark(item, onPage) {
|
|
730
677
|
const page = this.drilldown.page;
|
|
731
678
|
item.onPage = onPage && this.kept(item);
|
|
732
|
-
item.virtual = this.
|
|
679
|
+
item.virtual = this.filters !== undefined;
|
|
733
680
|
const holds = page !== null && item.contains(page);
|
|
734
681
|
item.flyout = this.flies;
|
|
735
682
|
item.expanded = this.flies && holds;
|
|
@@ -753,16 +700,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
753
700
|
}
|
|
754
701
|
render() {
|
|
755
702
|
const point = this.context && this.point;
|
|
756
|
-
const
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
: 0;
|
|
760
|
-
const none = filtering && count === 0;
|
|
761
|
-
this.announced = none
|
|
762
|
-
? this.noResultsText
|
|
763
|
-
: filtering
|
|
764
|
-
? formatWords(this, 'resultsLabel', { count })
|
|
765
|
-
: '';
|
|
703
|
+
const filters = this.filters;
|
|
704
|
+
this.announced = '';
|
|
705
|
+
const none = filters?.status();
|
|
766
706
|
const rows = html `${this.flies || this.drilldown.atRoot
|
|
767
707
|
? nothing
|
|
768
708
|
: html `<div part="header">
|
|
@@ -781,9 +721,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
781
721
|
<span part="title" id="title">${this.drilldown.label}</span>
|
|
782
722
|
</div>`}
|
|
783
723
|
<slot @slotchange=${(event) => this.countRows(event)}></slot>
|
|
784
|
-
${none
|
|
785
|
-
? html `<p part="empty"><slot name="no-results">${this.noResultsText}</slot></p>`
|
|
786
|
-
: this.renderStatus(this.hasRows)}`;
|
|
724
|
+
${none ?? this.renderStatus(this.hasRows)}`;
|
|
787
725
|
const busy = this.loading ? 'true' : nothing;
|
|
788
726
|
const label = this.label || nothing;
|
|
789
727
|
return html `<slot name="trigger" @click=${this.handleTriggerClick}></slot>${point
|
|
@@ -796,27 +734,14 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
796
734
|
<div
|
|
797
735
|
part="surface"
|
|
798
736
|
popover="manual"
|
|
799
|
-
role=${
|
|
800
|
-
aria-busy=${
|
|
801
|
-
aria-label=${
|
|
737
|
+
role=${filters ? nothing : 'menu'}
|
|
738
|
+
aria-busy=${filters ? nothing : busy}
|
|
739
|
+
aria-label=${filters ? nothing : label}
|
|
802
740
|
data-drilled=${this.flies || this.drilldown.atRoot ? nothing : ''}
|
|
803
|
-
data-filtered=${filtering ? '' : nothing}
|
|
741
|
+
data-filtered=${filters?.filtering ? '' : nothing}
|
|
804
742
|
?hidden=${!this.open}
|
|
805
743
|
>
|
|
806
|
-
${
|
|
807
|
-
? html `<input
|
|
808
|
-
part="search-field"
|
|
809
|
-
type="text"
|
|
810
|
-
autocomplete="off"
|
|
811
|
-
spellcheck="false"
|
|
812
|
-
.value=${this.filter}
|
|
813
|
-
placeholder=${this.filterLabel}
|
|
814
|
-
aria-label=${this.filterLabel}
|
|
815
|
-
aria-autocomplete="list"
|
|
816
|
-
aria-controls="items"
|
|
817
|
-
@input=${this.handleFilterInput}
|
|
818
|
-
/><div id="items" role="menu" aria-busy=${busy} aria-label=${label}>${rows}</div>`
|
|
819
|
-
: rows}
|
|
744
|
+
${filters ? filters.drawFilter(rows, busy) : rows}
|
|
820
745
|
</div>${this.renderLive(this.hasRows)}`;
|
|
821
746
|
}
|
|
822
747
|
};
|
|
@@ -217,6 +217,11 @@ export declare class HelixHeadlessTimeInput extends HelixHeadlessTimeInput_base
|
|
|
217
217
|
* on why a wheel cannot do either.
|
|
218
218
|
*/
|
|
219
219
|
mode?: 'multiple' | 'range';
|
|
220
|
+
/**
|
|
221
|
+
* The words on the list's button that chooses the current time, drawn with
|
|
222
|
+
* `show-now`.
|
|
223
|
+
*/
|
|
224
|
+
nowLabel: string;
|
|
220
225
|
/**
|
|
221
226
|
* Placeholder text shown before a time is entered.
|
|
222
227
|
*/
|
|
@@ -252,6 +257,12 @@ export declare class HelixHeadlessTimeInput extends HelixHeadlessTimeInput_base
|
|
|
252
257
|
* See Time Picker's `seconds`.
|
|
253
258
|
*/
|
|
254
259
|
seconds: boolean;
|
|
260
|
+
/**
|
|
261
|
+
* Draws a button under the times in the list that chooses the current time,
|
|
262
|
+
* moved to the nearest time on offer. See Time Picker's `show-now`. Its words
|
|
263
|
+
* are `now-label`.
|
|
264
|
+
*/
|
|
265
|
+
showNow: boolean;
|
|
255
266
|
/**
|
|
256
267
|
* How far apart the offered times are, in minutes, or in seconds with
|
|
257
268
|
* `seconds`.
|
|
@@ -21,12 +21,14 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinSegmented
|
|
|
21
21
|
this.locale = '';
|
|
22
22
|
this.max = '23:59';
|
|
23
23
|
this.min = '00:00';
|
|
24
|
+
this.nowLabel = 'Now';
|
|
24
25
|
this.placeholder = 'HH:mm';
|
|
25
26
|
this.rangeLengthMessage = 'A range is two times.';
|
|
26
27
|
this.rangeOverflowMessage = 'Choose a time at or before {max}.';
|
|
27
28
|
this.rangeUnderflowMessage = 'Choose a time at or after {min}.';
|
|
28
29
|
this.removeLabel = 'Remove {name}';
|
|
29
30
|
this.seconds = false;
|
|
31
|
+
this.showNow = false;
|
|
30
32
|
this.step = 15;
|
|
31
33
|
this.timeStyle = 'local';
|
|
32
34
|
this.triggerLabel = 'Choose a time';
|
|
@@ -246,7 +248,9 @@ let HelixHeadlessTimeInput = class HelixHeadlessTimeInput extends MixinSegmented
|
|
|
246
248
|
locale=${handedLocale(this) || nothing}
|
|
247
249
|
max=${this.max}
|
|
248
250
|
min=${this.min}
|
|
251
|
+
now-label=${this.nowLabel}
|
|
249
252
|
?seconds=${this.seconds}
|
|
253
|
+
?show-now=${this.showNow}
|
|
250
254
|
step=${this.step}
|
|
251
255
|
.value=${this.picked}
|
|
252
256
|
@helix-before-change=${this.handlePicked}
|
|
@@ -400,6 +404,10 @@ __decorate([
|
|
|
400
404
|
__decorate([
|
|
401
405
|
property({ reflect: true })
|
|
402
406
|
], HelixHeadlessTimeInput.prototype, "mode", void 0);
|
|
407
|
+
__decorate([
|
|
408
|
+
words,
|
|
409
|
+
property({ attribute: 'now-label' })
|
|
410
|
+
], HelixHeadlessTimeInput.prototype, "nowLabel", void 0);
|
|
403
411
|
__decorate([
|
|
404
412
|
words,
|
|
405
413
|
property()
|
|
@@ -423,6 +431,9 @@ __decorate([
|
|
|
423
431
|
__decorate([
|
|
424
432
|
property({ type: Boolean })
|
|
425
433
|
], HelixHeadlessTimeInput.prototype, "seconds", void 0);
|
|
434
|
+
__decorate([
|
|
435
|
+
property({ attribute: 'show-now', type: Boolean })
|
|
436
|
+
], HelixHeadlessTimeInput.prototype, "showNow", void 0);
|
|
426
437
|
__decorate([
|
|
427
438
|
property({ type: Number })
|
|
428
439
|
], HelixHeadlessTimeInput.prototype, "step", void 0);
|