@fusion.dev/helix-headless 0.145.0 → 0.146.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 +7373 -3849
- package/dist/accordion/item/accordion-item.d.ts +14 -0
- package/dist/accordion/item/accordion-item.js +16 -6
- package/dist/accordion/root/accordion-root.d.ts +8 -5
- package/dist/announcement/root/announcement-root.d.ts +3 -2
- package/dist/announcement/root/announcement-root.js +3 -1
- package/dist/app-header/root/app-header-root.d.ts +7 -2
- package/dist/app-header/root/app-header-root.js +9 -1
- package/dist/app-header/sectioning.d.ts +3 -1
- package/dist/app-header/sectioning.js +3 -2
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/badge/root/badge-root.d.ts +3 -1
- package/dist/badge/root/badge-root.js +2 -2
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +52 -15
- package/dist/bar-chart/stack.d.ts +15 -0
- package/dist/bar-chart/stack.js +19 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.js +50 -3
- package/dist/button/root/button-root.d.ts +26 -0
- package/dist/button/root/button-root.js +38 -18
- package/dist/button-group/root/button-group-root.d.ts +2 -1
- package/dist/button-group/root/button-group-root.js +5 -1
- package/dist/canvas/node/canvas-node.d.ts +4 -3
- package/dist/canvas/node/canvas-node.js +3 -2
- package/dist/canvas/root/canvas-root.js +2 -2
- package/dist/card/root/card-root.d.ts +24 -3
- package/dist/card/root/card-root.js +20 -8
- package/dist/carousel/root/carousel-root.d.ts +43 -4
- package/dist/carousel/root/carousel-root.js +40 -12
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/message/chat-message.js +5 -4
- package/dist/chat/naming.d.ts +5 -1
- package/dist/chat/naming.js +4 -2
- package/dist/chat/root/chat-root.d.ts +25 -3
- package/dist/chat/root/chat-root.js +22 -5
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +14 -1
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
- package/dist/checkbox-group/select-all.d.ts +27 -0
- package/dist/checkbox-group/select-all.js +12 -0
- package/dist/code-block/highlight.d.ts +15 -0
- package/dist/code-block/highlight.js +4 -0
- package/dist/code-block/root/code-block-root.d.ts +49 -1
- package/dist/code-block/root/code-block-root.js +58 -3
- package/dist/color-input/root/color-input-root.d.ts +3 -0
- package/dist/color-input/root/color-input-root.js +6 -3
- package/dist/color-picker/root/color-picker-root.d.ts +33 -4
- package/dist/color-picker/root/color-picker-root.js +80 -21
- package/dist/color-picker/swatches.d.ts +12 -0
- package/dist/color-picker/swatches.js +26 -0
- package/dist/combobox/root/combobox-root.d.ts +43 -0
- package/dist/combobox/root/combobox-root.js +79 -15
- package/dist/command/root/command-root.d.ts +16 -1
- package/dist/command/root/command-root.js +22 -4
- package/dist/copy-button/root/copy-button-root.d.ts +5 -0
- package/dist/copy-button/root/copy-button-root.js +10 -3
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +24 -0
- package/dist/data-table/keys.js +24 -0
- package/dist/data-table/root/data-table-root.d.ts +27 -18
- package/dist/data-table/root/data-table-root.js +20 -52
- package/dist/data-table/tree.d.ts +16 -1
- package/dist/data-table/tree.js +2 -3
- package/dist/date-input/root/date-input-root.d.ts +3 -1
- package/dist/date-input/root/date-input-root.js +18 -7
- package/dist/date-picker/root/date-picker-root.js +12 -6
- package/dist/dialog/description.js +15 -1
- package/dist/dialog/root/dialog-root.d.ts +8 -2
- package/dist/dialog/root/dialog-root.js +16 -1
- package/dist/divider/root/divider-root.d.ts +3 -0
- package/dist/divider/root/divider-root.js +2 -1
- package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
- package/dist/donut-chart/root/donut-chart-root.js +48 -1
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +59 -0
- package/dist/drawer/root/drawer-root.js +63 -4
- package/dist/drilldown/item/drilldown-item.js +1 -1
- package/dist/drilldown/root/drilldown-root.d.ts +21 -3
- package/dist/drilldown/root/drilldown-root.js +21 -3
- package/dist/element-events.generated.js +31 -5
- package/dist/empty/root/empty-root.d.ts +3 -1
- package/dist/empty/root/empty-root.js +3 -2
- package/dist/file-input/root/file-input-root.d.ts +69 -6
- package/dist/file-input/root/file-input-root.js +82 -19
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/filter-input/menu/filter-menu.d.ts +2 -0
- package/dist/filter-input/menu/filter-menu.js +12 -4
- package/dist/filter-input/root/filter-input-root.d.ts +30 -6
- package/dist/filter-input/root/filter-input-root.js +1 -1
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/root/format-date-root.d.ts +9 -16
- package/dist/format-date/root/format-date-root.js +10 -27
- package/dist/heatmap/root/heatmap-root.d.ts +24 -13
- package/dist/heatmap/root/heatmap-root.js +34 -12
- package/dist/icon/root/icon-root.d.ts +12 -1
- package/dist/icon/root/icon-root.js +21 -10
- package/dist/icon/settle.d.ts +7 -0
- package/dist/icon/settle.js +10 -0
- package/dist/icon-button/root/icon-button-root.d.ts +2 -0
- package/dist/image/root/image-root.d.ts +5 -1
- package/dist/image/root/image-root.js +1 -1
- package/dist/input/root/input-root.d.ts +12 -2
- package/dist/input/root/input-root.js +11 -2
- package/dist/kbd/root/kbd-root.d.ts +35 -1
- package/dist/kbd/root/kbd-root.js +23 -4
- package/dist/legend/root/legend-root.d.ts +55 -8
- package/dist/legend/root/legend-root.js +55 -13
- package/dist/lightbox/root/lightbox-root.d.ts +49 -6
- package/dist/lightbox/root/lightbox-root.js +86 -19
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +22 -0
- package/dist/lightbox/zoom.js +16 -0
- package/dist/line-chart/root/line-chart-root.d.ts +22 -1
- package/dist/line-chart/root/line-chart-root.js +21 -1
- package/dist/list/item/list-item.d.ts +2 -0
- package/dist/list/item/list-item.js +11 -2
- package/dist/list/root/list-root.d.ts +62 -13
- package/dist/list/root/list-root.js +70 -13
- package/dist/list/selection.d.ts +37 -7
- package/dist/list/selection.js +16 -7
- package/dist/listbox/root/listbox-root.d.ts +37 -1
- package/dist/listbox/root/listbox-root.js +49 -3
- package/dist/loader/busy.d.ts +10 -0
- package/dist/loader/busy.js +11 -0
- package/dist/loader/root/loader-root.d.ts +9 -2
- package/dist/loader/root/loader-root.js +23 -3
- package/dist/megamenu/root/megamenu-root.d.ts +51 -10
- package/dist/megamenu/root/megamenu-root.js +76 -5
- package/dist/menu/item/menu-item.d.ts +51 -2
- package/dist/menu/item/menu-item.js +47 -23
- package/dist/menu/root/menu-root.d.ts +14 -0
- package/dist/menu/root/menu-root.js +2 -2
- package/dist/meter/root/meter-root.d.ts +20 -1
- package/dist/meter/root/meter-root.js +11 -15
- package/dist/navigation/root/navigation-root.d.ts +2 -1
- package/dist/navigation/root/navigation-root.js +2 -2
- package/dist/notifications/root/notifications-root.d.ts +10 -3
- package/dist/notifications/root/notifications-root.js +19 -7
- package/dist/number-input/root/number-input-root.d.ts +17 -8
- package/dist/number-input/root/number-input-root.js +2 -7
- package/dist/object-inspector/root/object-inspector-root.d.ts +75 -27
- package/dist/object-inspector/root/object-inspector-root.js +117 -76
- package/dist/object-inspector/rows.d.ts +18 -0
- package/dist/object-inspector/rows.js +33 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/outline/root/outline-root.d.ts +18 -0
- package/dist/outline/root/outline-root.js +23 -5
- 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 +10 -0
- package/dist/pin-input/code.js +13 -0
- package/dist/pin-input/root/pin-input-root.d.ts +25 -1
- package/dist/pin-input/root/pin-input-root.js +10 -11
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +41 -0
- package/dist/popover/root/popover-root.d.ts +57 -7
- package/dist/popover/root/popover-root.js +58 -3
- package/dist/progress/root/progress-root.d.ts +20 -0
- package/dist/progress/root/progress-root.js +15 -15
- package/dist/qr-code/export.d.ts +26 -1
- package/dist/qr-code/export.js +14 -0
- package/dist/qr-code/root/qr-code-root.d.ts +19 -5
- package/dist/qr-code/root/qr-code-root.js +58 -9
- package/dist/quote/marks.d.ts +8 -0
- package/dist/quote/marks.js +5 -0
- package/dist/quote/root/quote-root.d.ts +14 -2
- package/dist/quote/root/quote-root.js +23 -1
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +6 -1
- package/dist/rating/root/rating-root.d.ts +9 -4
- package/dist/rating/root/rating-root.js +31 -7
- package/dist/rating/steps.d.ts +7 -0
- package/dist/rating/steps.js +9 -0
- package/dist/scatter-chart/fit.d.ts +15 -0
- package/dist/scatter-chart/fit.js +35 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
- package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
- package/dist/scroll-area/root/scroll-area-root.js +57 -173
- package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
- package/dist/scroll-area/scrollbar-controller.js +172 -0
- package/dist/scroll-area/scrollbar.d.ts +27 -0
- package/dist/scroll-area/scrollbar.js +9 -0
- package/dist/select/root/select-root.d.ts +15 -0
- package/dist/select/root/select-root.js +18 -6
- package/dist/skeleton/root/skeleton-root.d.ts +3 -0
- package/dist/skeleton/root/skeleton-root.js +4 -2
- package/dist/skip-link/root/skip-link-root.js +2 -2
- package/dist/slider/root/slider-root.d.ts +41 -4
- package/dist/slider/root/slider-root.js +23 -3
- package/dist/sparkline/readings.d.ts +18 -0
- package/dist/sparkline/readings.js +19 -0
- package/dist/sparkline/root/sparkline-root.d.ts +78 -7
- package/dist/sparkline/root/sparkline-root.js +118 -23
- package/dist/speed-dial/root/speed-dial-root.js +2 -2
- package/dist/splitter/root/splitter-root.d.ts +7 -12
- package/dist/splitter/root/splitter-root.js +209 -204
- package/dist/stat/root/stat-root.d.ts +14 -5
- package/dist/stat/root/stat-root.js +21 -5
- package/dist/steps/reach.d.ts +5 -0
- package/dist/steps/reach.js +3 -0
- package/dist/steps/root/steps-root.d.ts +49 -3
- package/dist/steps/root/steps-root.js +44 -5
- package/dist/steps/step/step.d.ts +7 -0
- package/dist/steps/step/step.js +7 -2
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +0 -10
- package/dist/table/column/table-column.js +3 -19
- package/dist/table/root/table-root.d.ts +31 -10
- package/dist/table/root/table-root.js +2 -13
- package/dist/tabs/panel/tab-panel.d.ts +16 -3
- package/dist/tabs/panel/tab-panel.js +34 -5
- package/dist/tabs/root/tabs-root.d.ts +12 -0
- package/dist/tabs/root/tabs-root.js +1 -1
- package/dist/tabs/tab/tab.d.ts +5 -0
- package/dist/tabs/tab/tab.js +5 -2
- package/dist/tag/group/tag-group.d.ts +31 -4
- package/dist/tag/group/tag-group.js +46 -7
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +28 -1
- package/dist/textarea/root/textarea-root.js +40 -1
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +16 -8
- package/dist/time-picker/root/time-picker-root.d.ts +18 -4
- package/dist/time-picker/root/time-picker-root.js +7 -10
- package/dist/time-picker/wheel-name.d.ts +9 -0
- package/dist/time-picker/wheel-name.js +15 -0
- package/dist/timeline/group/timeline-group.js +2 -2
- package/dist/toast/item/toast-item.d.ts +14 -1
- package/dist/toast/item/toast-item.js +22 -5
- package/dist/toast/root/toast-root.d.ts +6 -0
- package/dist/toast/root/toast-root.js +16 -1
- package/dist/toggle/group/toggle-group.d.ts +24 -3
- package/dist/toggle/group/toggle-group.js +34 -5
- package/dist/tooltip/root/tooltip-root.d.ts +13 -2
- package/dist/tooltip/root/tooltip-root.js +9 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +30 -2
- package/dist/tour/root/tour-root.js +34 -8
- package/dist/tree/item/tree-item.d.ts +7 -3
- package/dist/tree/item/tree-item.js +3 -0
- package/dist/tree/root/tree-root.d.ts +24 -3
- package/dist/tree/root/tree-root.js +32 -13
- package/dist/tree/selection.js +2 -15
- package/dist/trend/root/trend-root.d.ts +43 -18
- package/dist/trend/root/trend-root.js +31 -6
- package/dist/video/media-events.d.ts +13 -18
- package/dist/video/media-events.js +1 -5
- package/dist/video/root/video-root.d.ts +18 -5
- package/dist/video/root/video-root.js +19 -10
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +7 -1
- package/dist/virtual-list/fill.d.ts +0 -8
- package/dist/virtual-list/fill.js +1 -17
- package/dist/virtual-list/plan.d.ts +49 -0
- package/dist/virtual-list/plan.js +16 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +114 -13
- package/dist/virtual-list/root/virtual-list-root.js +183 -40
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +4577 -835
- package/types/vue.d.ts +926 -168
- package/dist/chat/relative-clock.d.ts +0 -39
- package/dist/chat/relative-clock.js +0 -31
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -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, countLabel, customElement, DelayController, DisabledCascadeController, HelixFilterEvent, HelixFormElement, hostAria, MixinCollection, MixinControllerValue, MixinField, rangeAdd, reportValues, requestChange, scrollItemIntoView, Typeahead, typesCharacter, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, countLabel, customElement, DelayController, DisabledCascadeController, HelixFilterEvent, HelixFormElement, HelixLoadMoreEvent, hostAria, MixinCollection, MixinControllerValue, MixinField, rangeAdd, 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';
|
|
@@ -70,6 +70,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
70
70
|
this.filterable = false;
|
|
71
71
|
this.filterDelay = 0;
|
|
72
72
|
this.filterLabel = 'Filter';
|
|
73
|
+
this.loadError = '';
|
|
73
74
|
this.manual = false;
|
|
74
75
|
this.multiple = false;
|
|
75
76
|
this.resultLabel = '{count} result';
|
|
@@ -192,6 +193,18 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
192
193
|
this.takeFilter(control);
|
|
193
194
|
};
|
|
194
195
|
this.filtering = new DelayController(this, { renders: false });
|
|
196
|
+
this.askedAt = -1;
|
|
197
|
+
this.handleScroll = (event) => {
|
|
198
|
+
const items = event.currentTarget;
|
|
199
|
+
const count = this.options.length;
|
|
200
|
+
if (this.loading || count === this.askedAt || items.clientHeight === 0) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (items.scrollHeight - items.scrollTop - items.clientHeight <= items.clientHeight) {
|
|
204
|
+
this.askedAt = count;
|
|
205
|
+
this.dispatchEvent(new HelixLoadMoreEvent());
|
|
206
|
+
}
|
|
207
|
+
};
|
|
195
208
|
this.handleFilterKeydown = (event) => {
|
|
196
209
|
if (event.key === 'Enter' || FIELD_MOVES.has(event.key)) {
|
|
197
210
|
this.flushFilter();
|
|
@@ -471,6 +484,8 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
471
484
|
}
|
|
472
485
|
this.toggleState('empty', !this.showsOptions);
|
|
473
486
|
this.toggleState('loading', this.loading);
|
|
487
|
+
this.toggleState('error', this.loadError !== '');
|
|
488
|
+
this.toggleState('no-results', this.noResults);
|
|
474
489
|
}
|
|
475
490
|
seedDeclared() {
|
|
476
491
|
if (this.owned || this.defaultValue !== '' || this.hasAttribute('default-value')) {
|
|
@@ -545,13 +560,37 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
545
560
|
: true;
|
|
546
561
|
}
|
|
547
562
|
renderStatus(hasContent) {
|
|
563
|
+
if (this.loadError !== '') {
|
|
564
|
+
return html `<p part="error"><slot name="error">${this.loadError}</slot></p>`;
|
|
565
|
+
}
|
|
548
566
|
if (!this.loading && hasContent) {
|
|
549
567
|
return nothing;
|
|
550
568
|
}
|
|
551
|
-
|
|
552
|
-
|
|
569
|
+
if (this.loading) {
|
|
570
|
+
return html `<p part="loading"><slot name="loading">${this.loadingText}</slot></p>`;
|
|
571
|
+
}
|
|
572
|
+
const given = this.noResultsText !== undefined ||
|
|
573
|
+
this.querySelector?.(':scope > [slot="no-results"]') != null;
|
|
574
|
+
return this.noResults && given
|
|
575
|
+
? html `<p part="empty"><slot name="no-results">${this.noResultsText ?? this.emptyText}</slot></p>`
|
|
553
576
|
: html `<p part="empty"><slot name="empty">${this.emptyText}</slot></p>`;
|
|
554
577
|
}
|
|
578
|
+
get noResults() {
|
|
579
|
+
return (this.counted &&
|
|
580
|
+
!this.loading &&
|
|
581
|
+
this.filter !== '' &&
|
|
582
|
+
this.options.length > 0 &&
|
|
583
|
+
!this.hasMatches);
|
|
584
|
+
}
|
|
585
|
+
renderLive(hasContent) {
|
|
586
|
+
if (this.loadError !== '') {
|
|
587
|
+
return html `<span part="live" role="status">${this.loadError}</span>`;
|
|
588
|
+
}
|
|
589
|
+
if (this.noResults && this.noResultsText !== undefined) {
|
|
590
|
+
return html `<span part="live" role="status">${this.noResultsText}</span>`;
|
|
591
|
+
}
|
|
592
|
+
return super.renderLive(hasContent);
|
|
593
|
+
}
|
|
555
594
|
render() {
|
|
556
595
|
const shown = this.showsOptions;
|
|
557
596
|
return html `${this.renderGroupLabel()}
|
|
@@ -588,6 +627,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
588
627
|
aria-required=${this.required ? 'true' : nothing}
|
|
589
628
|
${''}
|
|
590
629
|
tabindex=${this.filterable ? nothing : this.isDisabled ? -1 : 0}
|
|
630
|
+
@scroll=${this.handleScroll}
|
|
591
631
|
>
|
|
592
632
|
<slot @slotchange=${() => this.place()}></slot>
|
|
593
633
|
${this.renderStatus(shown)}
|
|
@@ -616,12 +656,18 @@ __decorate([
|
|
|
616
656
|
__decorate([
|
|
617
657
|
property({ attribute: 'filter-label' })
|
|
618
658
|
], HelixHeadlessListbox.prototype, "filterLabel", void 0);
|
|
659
|
+
__decorate([
|
|
660
|
+
property({ attribute: 'load-error' })
|
|
661
|
+
], HelixHeadlessListbox.prototype, "loadError", void 0);
|
|
619
662
|
__decorate([
|
|
620
663
|
property({ type: Boolean })
|
|
621
664
|
], HelixHeadlessListbox.prototype, "manual", void 0);
|
|
622
665
|
__decorate([
|
|
623
666
|
property({ reflect: true, type: Boolean })
|
|
624
667
|
], HelixHeadlessListbox.prototype, "multiple", void 0);
|
|
668
|
+
__decorate([
|
|
669
|
+
property({ attribute: 'no-results-text' })
|
|
670
|
+
], HelixHeadlessListbox.prototype, "noResultsText", void 0);
|
|
625
671
|
__decorate([
|
|
626
672
|
property({ attribute: 'result-label' })
|
|
627
673
|
], HelixHeadlessListbox.prototype, "resultLabel", void 0);
|
package/dist/loader/busy.d.ts
CHANGED
|
@@ -15,3 +15,13 @@
|
|
|
15
15
|
export declare const claimBusy: (region: Element) => void;
|
|
16
16
|
/** Takes a claim back, and the attribute with the last one. */
|
|
17
17
|
export declare const releaseBusy: (region: Element) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Calls `found` with the region `find` answers once it is in `root`, and
|
|
20
|
+
* returns the call that stops waiting.
|
|
21
|
+
*
|
|
22
|
+
* For a loader whose region is not on the page yet: a framework often draws
|
|
23
|
+
* the loader before the list it stands for, and a region looked up once, a
|
|
24
|
+
* frame after connecting, was never marked. Watches for children and ids being
|
|
25
|
+
* written, and stops at the first answer.
|
|
26
|
+
*/
|
|
27
|
+
export declare const awaitRegion: (root: Node, find: () => Element | null, found: (region: Element) => void) => (() => void);
|
package/dist/loader/busy.js
CHANGED
|
@@ -22,3 +22,14 @@ export const releaseBusy = (region) => {
|
|
|
22
22
|
CLAIMS.set(region, held - 1);
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
|
+
export const awaitRegion = (root, find, found) => {
|
|
26
|
+
const observer = new MutationObserver(() => {
|
|
27
|
+
const region = find();
|
|
28
|
+
if (region) {
|
|
29
|
+
observer.disconnect();
|
|
30
|
+
found(region);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
observer.observe(root, { attributeFilter: ['id'], childList: true, subtree: true });
|
|
34
|
+
return () => observer.disconnect();
|
|
35
|
+
};
|
|
@@ -22,11 +22,12 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
22
22
|
* **`for` names the region being loaded**, and the loader sets
|
|
23
23
|
* `aria-busy="true"` on it for as long as the loader is on the page, so a
|
|
24
24
|
* screen reader waits for the region rather than reading it half filled. Two
|
|
25
|
-
* loaders in one region hold it busy until the last one leaves.
|
|
25
|
+
* loaders in one region hold it busy until the last one leaves. A region drawn
|
|
26
|
+
* after the loader is marked when it arrives.
|
|
26
27
|
*
|
|
27
28
|
* **`delay` keeps a quick load from flashing a loader.** The loader stays
|
|
28
29
|
* hidden, and silent, for that many milliseconds, and appears only if the work
|
|
29
|
-
* is still going.
|
|
30
|
+
* is still going. While it waits it carries `:state(waiting)`.
|
|
30
31
|
*
|
|
31
32
|
* @since 0.1.0
|
|
32
33
|
* @status stable
|
|
@@ -40,6 +41,8 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
40
41
|
* @csspart mark - The region that holds the slotted content at the center.
|
|
41
42
|
* @csspart svg - The rotating circle pair.
|
|
42
43
|
* @csspart track - The full circle behind the indicator.
|
|
44
|
+
*
|
|
45
|
+
* @cssstate waiting - The loader is waiting out its `delay`, hidden and silent.
|
|
43
46
|
*/
|
|
44
47
|
export declare class HelixHeadlessLoader extends HelixElement {
|
|
45
48
|
/**
|
|
@@ -67,6 +70,10 @@ export declare class HelixHeadlessLoader extends HelixElement {
|
|
|
67
70
|
private readonly due;
|
|
68
71
|
/** The region this loader marked busy, so it is the one released. */
|
|
69
72
|
private region;
|
|
73
|
+
/** Stops waiting for a region `for` names that is not on the page yet. */
|
|
74
|
+
private stopAwaiting;
|
|
75
|
+
/** Whether `for` has named an element while the loader was on the page. */
|
|
76
|
+
private found;
|
|
70
77
|
/** Whether the loader is still waiting out its `delay`. */
|
|
71
78
|
private get waiting();
|
|
72
79
|
connectedCallback(): void;
|
|
@@ -4,10 +4,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, DelayController, elementById, HelixElement, hostAria, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, DelayController, elementById, HelixElement, hostAria, reportRuntime, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
-
import { claimBusy, releaseBusy } from '../busy.js';
|
|
10
|
+
import { awaitRegion, claimBusy, releaseBusy } from '../busy.js';
|
|
11
11
|
let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
12
12
|
constructor() {
|
|
13
13
|
super(...arguments);
|
|
@@ -16,6 +16,7 @@ let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
|
16
16
|
this.label = 'Loading';
|
|
17
17
|
this.due = new DelayController(this);
|
|
18
18
|
this.region = null;
|
|
19
|
+
this.found = false;
|
|
19
20
|
}
|
|
20
21
|
get waiting() {
|
|
21
22
|
return this.delay > 0 && !this.due.elapsed;
|
|
@@ -29,10 +30,26 @@ let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
|
29
30
|
}
|
|
30
31
|
disconnectedCallback() {
|
|
31
32
|
super.disconnectedCallback();
|
|
33
|
+
if (this.stopAwaiting && !this.found) {
|
|
34
|
+
reportRuntime({
|
|
35
|
+
kind: 'missing-target',
|
|
36
|
+
message: `<${this.localName} for="${this.for}"> named no element in its tree while it was on ` +
|
|
37
|
+
'the page, so no region was marked busy. Give the region that id.',
|
|
38
|
+
tag: this.localName,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
this.stopAwaiting?.();
|
|
42
|
+
this.stopAwaiting = undefined;
|
|
32
43
|
this.release();
|
|
33
44
|
}
|
|
34
45
|
mark() {
|
|
35
|
-
|
|
46
|
+
this.stopAwaiting?.();
|
|
47
|
+
this.stopAwaiting = undefined;
|
|
48
|
+
const named = this.isConnected && this.for !== '';
|
|
49
|
+
const region = named ? elementById(this, this.for) : null;
|
|
50
|
+
if (named && !region) {
|
|
51
|
+
this.stopAwaiting = awaitRegion(this.getRootNode(), () => elementById(this, this.for), () => this.mark());
|
|
52
|
+
}
|
|
36
53
|
if (region === this.region) {
|
|
37
54
|
return;
|
|
38
55
|
}
|
|
@@ -40,6 +57,7 @@ let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
|
40
57
|
if (region) {
|
|
41
58
|
claimBusy(region);
|
|
42
59
|
this.region = region;
|
|
60
|
+
this.found = true;
|
|
43
61
|
}
|
|
44
62
|
}
|
|
45
63
|
release() {
|
|
@@ -51,6 +69,7 @@ let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
|
51
69
|
updated(changed) {
|
|
52
70
|
super.updated(changed);
|
|
53
71
|
if (changed.has('for') && changed.get('for') !== undefined) {
|
|
72
|
+
this.found = false;
|
|
54
73
|
this.mark();
|
|
55
74
|
}
|
|
56
75
|
}
|
|
@@ -59,6 +78,7 @@ let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
|
59
78
|
hostAria(this.internals, { label: this.label, role: 'progressbar' });
|
|
60
79
|
this.internals.ariaBusy = 'true';
|
|
61
80
|
this.internals.ariaHidden = this.waiting ? 'true' : null;
|
|
81
|
+
this.toggleState('waiting', this.waiting);
|
|
62
82
|
}
|
|
63
83
|
render() {
|
|
64
84
|
return html `<svg part="svg" viewBox="0 0 24 24" aria-hidden="true" ?hidden=${this.waiting}>
|
|
@@ -21,11 +21,27 @@ declare const HelixHeadlessMegamenu_base: (new (...args: any[]) => import("@fusi
|
|
|
21
21
|
* along the row and see each section.
|
|
22
22
|
*
|
|
23
23
|
* When one panel opens in place of another, each says which way the reader
|
|
24
|
-
* moved, as Radix's `data-motion` does
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* stylesheet slides them on that.
|
|
28
|
-
*
|
|
24
|
+
* moved, as Radix's `data-motion` does. Moving toward the end of the bar, the
|
|
25
|
+
* one opening is `:state(from-end)` and the one closing is `:state(to-start)`;
|
|
26
|
+
* moving back, they are `:state(from-start)` and `:state(to-end)`. A
|
|
27
|
+
* stylesheet slides them on that. Start and end follow the reading direction,
|
|
28
|
+
* so on a right-to-left page the end is on the left. A panel that opens or
|
|
29
|
+
* closes on its own carries none of the four. A press on another megamenu's
|
|
30
|
+
* trigger hands over the same way as hovering it.
|
|
31
|
+
*
|
|
32
|
+
* While a panel is open its surface carries its own size, as
|
|
33
|
+
* `--megamenu-surface-inline-size` and `--megamenu-surface-block-size`, and a
|
|
34
|
+
* panel that took over from another also carries that one's size, as
|
|
35
|
+
* `--megamenu-from-inline-size` and `--megamenu-from-block-size`. Radix's
|
|
36
|
+
* navigation menu publishes the same pair from its shared viewport, so a
|
|
37
|
+
* stylesheet can grow or shrink one panel into the next.
|
|
38
|
+
*
|
|
39
|
+
* Put megamenus in a `Navigation` with `arrows` and the arrow keys move
|
|
40
|
+
* between their triggers. Down Arrow on the trigger of an open panel moves
|
|
41
|
+
* focus to the panel's first link, Escape closes the panel and returns focus
|
|
42
|
+
* to its trigger, and Tab moves through the panel's links and closes it on the
|
|
43
|
+
* way out. The trigger says `aria-expanded`, and the panel is a group named by
|
|
44
|
+
* `label`.
|
|
29
45
|
*
|
|
30
46
|
* @since 0.1.0
|
|
31
47
|
* @status stable
|
|
@@ -43,14 +59,18 @@ declare const HelixHeadlessMegamenu_base: (new (...args: any[]) => import("@fusi
|
|
|
43
59
|
* @csspart surface - The floating panel that opens.
|
|
44
60
|
* @csspart trigger - The default trigger button, shown when the `trigger` slot is empty.
|
|
45
61
|
*
|
|
62
|
+
* @cssproperty --megamenu-from-block-size - The height of the panel this one took over from, written on the surface while it is open.
|
|
63
|
+
* @cssproperty --megamenu-from-inline-size - The width of the panel this one took over from, written on the surface while it is open.
|
|
64
|
+
* @cssproperty --megamenu-surface-block-size - The panel's own height, written on the surface while it is open.
|
|
65
|
+
* @cssproperty --megamenu-surface-inline-size - The panel's own width, written on the surface while it is open.
|
|
46
66
|
* @cssproperty --megamenu-top - Where the panel starts, measured from the bar above it.
|
|
47
67
|
*
|
|
48
|
-
* @cssstate from-end - The panel opened in place of one
|
|
49
|
-
* @cssstate from-start - The panel opened in place of one
|
|
68
|
+
* @cssstate from-end - The panel opened in place of one earlier in the bar, so it can enter from the end side.
|
|
69
|
+
* @cssstate from-start - The panel opened in place of one later in the bar, so it can enter from the start side.
|
|
50
70
|
* @cssstate narrow - The page is narrower than `band-below`, so the panel is shown as a band whatever its variant.
|
|
51
71
|
* @cssstate open - The panel is open, and the trigger is shown as current.
|
|
52
|
-
* @cssstate to-end - The panel closed because one
|
|
53
|
-
* @cssstate to-start - The panel closed because one
|
|
72
|
+
* @cssstate to-end - The panel closed because one earlier in the bar opened, so it can leave toward the end.
|
|
73
|
+
* @cssstate to-start - The panel closed because one later in the bar opened, so it can leave toward the start.
|
|
54
74
|
*/
|
|
55
75
|
export declare class HelixHeadlessMegamenu extends HelixHeadlessMegamenu_base {
|
|
56
76
|
/**
|
|
@@ -135,6 +155,11 @@ export declare class HelixHeadlessMegamenu extends HelixHeadlessMegamenu_base {
|
|
|
135
155
|
* the consumer slotted, or the button drawn in its place.
|
|
136
156
|
*/
|
|
137
157
|
get navigationControl(): HTMLElement;
|
|
158
|
+
/**
|
|
159
|
+
* Down Arrow on the trigger of an open panel moves focus to the panel's first
|
|
160
|
+
* link or control, as Radix's navigation menu does.
|
|
161
|
+
*/
|
|
162
|
+
private readonly handleKeyDown;
|
|
138
163
|
/** Shuts it and puts the reader back where they were. */
|
|
139
164
|
private close;
|
|
140
165
|
/**
|
|
@@ -257,9 +282,25 @@ export declare class HelixHeadlessMegamenu extends HelixHeadlessMegamenu_base {
|
|
|
257
282
|
* overruled.
|
|
258
283
|
*/
|
|
259
284
|
protected willUpdate(changed: PropertyValues): void;
|
|
285
|
+
/**
|
|
286
|
+
* Clears the direction of every panel but the two in a hand-over, so only
|
|
287
|
+
* the latest move is ever described.
|
|
288
|
+
*/
|
|
289
|
+
private static settle;
|
|
290
|
+
/** Whether the panel is closing because another one opened in its place. */
|
|
291
|
+
private handedOver;
|
|
292
|
+
/** The panel's size the last time it was open, in pixels. */
|
|
293
|
+
private size;
|
|
294
|
+
/** The size of the panel this one took over from, if it took over. */
|
|
295
|
+
private from;
|
|
296
|
+
/**
|
|
297
|
+
* Writes the panel's size onto its surface, and the size of the panel it
|
|
298
|
+
* took over from, for a stylesheet that grows one into the next.
|
|
299
|
+
*/
|
|
300
|
+
private measure;
|
|
260
301
|
/**
|
|
261
302
|
* Says which way the reader moved when one panel took over from another.
|
|
262
|
-
* Nothing clears all four, for a panel opened on its own.
|
|
303
|
+
* Nothing clears all four, for a panel opened or closed on its own.
|
|
263
304
|
*/
|
|
264
305
|
private motion;
|
|
265
306
|
protected updated(changed: PropertyValues): void;
|
|
@@ -5,10 +5,17 @@ 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, deepContains, HelixElement, MixinControllerOpen, PopoverController, tellDisclosure, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { anchorElement, customElement, deepContains, focusableElements, 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;
|
|
12
|
+
const connected = new Set();
|
|
13
|
+
let pressed;
|
|
14
|
+
const release = () => {
|
|
15
|
+
setTimeout(() => {
|
|
16
|
+
pressed = undefined;
|
|
17
|
+
});
|
|
18
|
+
};
|
|
12
19
|
let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerOpen(HelixElement) {
|
|
13
20
|
constructor() {
|
|
14
21
|
super(...arguments);
|
|
@@ -21,13 +28,27 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
21
28
|
};
|
|
22
29
|
this.panel = new PopoverController(this, {
|
|
23
30
|
anchor: () => this.trigger,
|
|
24
|
-
boundary: () =>
|
|
31
|
+
boundary: () => [...connected],
|
|
25
32
|
onDismiss: () => this.close(),
|
|
26
33
|
open: () => this.open,
|
|
27
34
|
place: () => !this.banded,
|
|
28
35
|
placement: () => 'bottom-start',
|
|
29
36
|
surface: () => this.partNamed('surface'),
|
|
30
37
|
});
|
|
38
|
+
this.handleKeyDown = (event) => {
|
|
39
|
+
if (event.key !== 'ArrowDown' || !this.open || event.defaultPrevented) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const trigger = this.trigger;
|
|
43
|
+
if (!event.composedPath().includes(trigger)) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const first = focusableElements(this).find((element) => element !== trigger && !element.closest('[slot="trigger"]'));
|
|
47
|
+
if (first) {
|
|
48
|
+
event.preventDefault();
|
|
49
|
+
first.focus();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
31
52
|
this.handleScroll = () => {
|
|
32
53
|
if (!this.open || !this.banded) {
|
|
33
54
|
return;
|
|
@@ -40,6 +61,9 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
40
61
|
};
|
|
41
62
|
this.handlePointerDown = (event) => {
|
|
42
63
|
this.pointer = event.pointerType;
|
|
64
|
+
pressed = this;
|
|
65
|
+
window.addEventListener('pointerup', release, { capture: true, once: true });
|
|
66
|
+
window.addEventListener('pointercancel', release, { capture: true, once: true });
|
|
43
67
|
};
|
|
44
68
|
this.handlePointerEnter = (event) => {
|
|
45
69
|
if (this.openOn !== 'hover' || event.pointerType !== 'mouse') {
|
|
@@ -62,6 +86,9 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
62
86
|
if (!this.open || next === null || deepContains(this, next)) {
|
|
63
87
|
return;
|
|
64
88
|
}
|
|
89
|
+
if (pressed !== undefined && pressed !== this && deepContains(pressed, next)) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
65
92
|
this.requestOpen(false);
|
|
66
93
|
};
|
|
67
94
|
this.handleTriggerClick = (event) => {
|
|
@@ -72,6 +99,10 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
72
99
|
}
|
|
73
100
|
if (event.detail === 0 || (this.pointer !== undefined && this.pointer !== 'mouse')) {
|
|
74
101
|
this.requestOpen(!this.open);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (!this.open) {
|
|
105
|
+
this.requestOpen(true);
|
|
75
106
|
}
|
|
76
107
|
};
|
|
77
108
|
this.handleContentClick = (event) => {
|
|
@@ -88,6 +119,7 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
88
119
|
}
|
|
89
120
|
this.requestOpen(false);
|
|
90
121
|
};
|
|
122
|
+
this.handedOver = false;
|
|
91
123
|
}
|
|
92
124
|
static { HelixHeadlessMegamenu_1 = this; }
|
|
93
125
|
get banded() {
|
|
@@ -159,12 +191,14 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
159
191
|
connectedCallback() {
|
|
160
192
|
super.connectedCallback();
|
|
161
193
|
this.watchWidth();
|
|
194
|
+
connected.add(this);
|
|
162
195
|
window.addEventListener('scroll', this.handleScroll, { capture: true, passive: true });
|
|
163
196
|
this.addEventListener('pointerdown', this.handlePointerDown);
|
|
164
197
|
this.addEventListener('click', this.handleContentClick);
|
|
165
198
|
this.addEventListener('pointerenter', this.handlePointerEnter);
|
|
166
199
|
this.addEventListener('pointerleave', this.handlePointerLeave);
|
|
167
200
|
this.addEventListener('focusout', this.handleFocusOut);
|
|
201
|
+
this.addEventListener('keydown', this.handleKeyDown);
|
|
168
202
|
}
|
|
169
203
|
disconnectedCallback() {
|
|
170
204
|
super.disconnectedCallback();
|
|
@@ -176,6 +210,8 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
176
210
|
this.removeEventListener('pointerenter', this.handlePointerEnter);
|
|
177
211
|
this.removeEventListener('pointerleave', this.handlePointerLeave);
|
|
178
212
|
this.removeEventListener('focusout', this.handleFocusOut);
|
|
213
|
+
this.removeEventListener('keydown', this.handleKeyDown);
|
|
214
|
+
connected.delete(this);
|
|
179
215
|
this.stop();
|
|
180
216
|
if (showing === this) {
|
|
181
217
|
showing = undefined;
|
|
@@ -191,15 +227,49 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
191
227
|
const forward = previous !== undefined &&
|
|
192
228
|
(previous.compareDocumentPosition(this) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
|
|
193
229
|
this.motion(previous ? (forward ? 'from-end' : 'from-start') : undefined);
|
|
230
|
+
this.from = previous?.size;
|
|
231
|
+
HelixHeadlessMegamenu_1.settle(this, previous);
|
|
194
232
|
if (previous) {
|
|
195
|
-
previous.motion(forward ? 'to-
|
|
196
|
-
previous.
|
|
233
|
+
previous.motion(forward ? 'to-start' : 'to-end');
|
|
234
|
+
previous.handedOver = true;
|
|
235
|
+
if (!previous.requestOpen(false)) {
|
|
236
|
+
previous.handedOver = false;
|
|
237
|
+
previous.motion(undefined);
|
|
238
|
+
}
|
|
197
239
|
}
|
|
198
240
|
showing = this;
|
|
241
|
+
return;
|
|
199
242
|
}
|
|
200
|
-
|
|
243
|
+
if (showing === this) {
|
|
201
244
|
showing = undefined;
|
|
202
245
|
}
|
|
246
|
+
if (!this.handedOver) {
|
|
247
|
+
HelixHeadlessMegamenu_1.settle();
|
|
248
|
+
}
|
|
249
|
+
this.handedOver = false;
|
|
250
|
+
}
|
|
251
|
+
static settle(...moving) {
|
|
252
|
+
for (const megamenu of connected) {
|
|
253
|
+
if (!moving.includes(megamenu)) {
|
|
254
|
+
megamenu.motion(undefined);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
measure() {
|
|
259
|
+
const surface = this.partNamed('surface');
|
|
260
|
+
if (!surface) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
surface.style.removeProperty('--megamenu-from-inline-size');
|
|
264
|
+
surface.style.removeProperty('--megamenu-from-block-size');
|
|
265
|
+
const box = surface.getBoundingClientRect();
|
|
266
|
+
this.size = { block: Math.round(box.height), inline: Math.round(box.width) };
|
|
267
|
+
surface.style.setProperty('--megamenu-surface-inline-size', `${this.size.inline}px`);
|
|
268
|
+
surface.style.setProperty('--megamenu-surface-block-size', `${this.size.block}px`);
|
|
269
|
+
if (this.from) {
|
|
270
|
+
surface.style.setProperty('--megamenu-from-inline-size', `${this.from.inline}px`);
|
|
271
|
+
surface.style.setProperty('--megamenu-from-block-size', `${this.from.block}px`);
|
|
272
|
+
}
|
|
203
273
|
}
|
|
204
274
|
motion(to) {
|
|
205
275
|
this.toggleState('from-end', to === 'from-end');
|
|
@@ -216,6 +286,7 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
216
286
|
this.tellTrigger();
|
|
217
287
|
if (this.open) {
|
|
218
288
|
this.band();
|
|
289
|
+
this.measure();
|
|
219
290
|
}
|
|
220
291
|
}
|
|
221
292
|
renderTrigger() {
|
|
@@ -29,13 +29,25 @@ import '../../kbd/index.js';
|
|
|
29
29
|
* nothing: the shortcut is the page's to bind. Other trailing words, such as a
|
|
30
30
|
* count, go in the `end` slot.
|
|
31
31
|
*
|
|
32
|
+
* The row is named by its label alone. Words in `description`, a line under the
|
|
33
|
+
* label, and in `end` describe it instead, through `aria-describedby`, as
|
|
34
|
+
* React Aria's menu item does with its description: a reader hears "Copy",
|
|
35
|
+
* then "Copies the selection".
|
|
36
|
+
*
|
|
37
|
+
* The check mark and the caret are the fallbacks of the `check` and `chevron`
|
|
38
|
+
* slots, so a mark of your own replaces either by being slotted. Neither is
|
|
39
|
+
* read as part of the row's name.
|
|
40
|
+
*
|
|
32
41
|
* @since 0.1.0
|
|
33
42
|
* @status stable
|
|
34
43
|
* @aliases Menu option, Menu row
|
|
35
44
|
* @documentation https://fusion.dev/helix/components/menu
|
|
36
45
|
*
|
|
37
46
|
* @slot - The label.
|
|
38
|
-
* @slot
|
|
47
|
+
* @slot check - Replaces the check mark of a checked row, such as with your own icon.
|
|
48
|
+
* @slot chevron - Replaces the caret of a row that opens a submenu.
|
|
49
|
+
* @slot description - A line under the label that describes the row. It describes the row to a screen reader and is not part of its name.
|
|
50
|
+
* @slot end - Words after the label, such as a count or a detail, beside any `shortcut`. They describe the row and are not part of its name.
|
|
39
51
|
* @slot start - Content before the label, such as an icon.
|
|
40
52
|
* @slot submenu - The rows of a submenu that this row opens.
|
|
41
53
|
*
|
|
@@ -48,6 +60,8 @@ import '../../kbd/index.js';
|
|
|
48
60
|
* when it opens a submenu. A row never shows both, so they share one column.
|
|
49
61
|
* @csspart shortcut - The key drawn for `shortcut`.
|
|
50
62
|
* @csspart shortcut-kbd - The key inside it.
|
|
63
|
+
* @csspart shortcut-key - One key of the shortcut's chord, such as `Ctrl`.
|
|
64
|
+
* @csspart shortcut-separator - The `+` between two keys of the shortcut, where the platform writes one.
|
|
51
65
|
* @csspart start - The leading column that holds the `start` slot. It is always rendered.
|
|
52
66
|
*
|
|
53
67
|
* @cssstate checked - The row is checked.
|
|
@@ -201,6 +215,8 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
201
215
|
private start;
|
|
202
216
|
/** Whether anything is slotted after the label, read the way `start` is. */
|
|
203
217
|
private end;
|
|
218
|
+
/** Whether anything is slotted under the label, read the way `start` is. */
|
|
219
|
+
private description;
|
|
204
220
|
/**
|
|
205
221
|
* Both answers, from the children, before each render.
|
|
206
222
|
*
|
|
@@ -223,13 +239,25 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
223
239
|
private readonly readStart;
|
|
224
240
|
/** Re-reads whether anything is after the label, as `readStart` does before it. */
|
|
225
241
|
private readonly readEnd;
|
|
242
|
+
/** Re-reads whether anything is under the label, as `readStart` does before it. */
|
|
243
|
+
private readonly readDescription;
|
|
244
|
+
/**
|
|
245
|
+
* The line under the label. The slot is hidden from the row's name and named
|
|
246
|
+
* by the row's `aria-describedby`, which reads it all the same: a description
|
|
247
|
+
* is read from what it points at, hidden or not. No box of its own, so a row
|
|
248
|
+
* with no description lays out as it did; `data-empty` says which it is.
|
|
249
|
+
*/
|
|
250
|
+
protected renderDescription(): TemplateResult;
|
|
251
|
+
/** What describes the row: the line under its label and the words after it. */
|
|
252
|
+
private get describedBy();
|
|
226
253
|
/**
|
|
227
254
|
* The trailing column: the shortcut's key, then whatever is slotted in `end`.
|
|
228
255
|
* Drawn by `Kbd`, interpolated so each tier draws its own.
|
|
229
256
|
*
|
|
230
257
|
* The key is hidden from the accessibility tree, since the row's
|
|
231
258
|
* `aria-keyshortcuts` says it in words a screen reader reads as keys: inside
|
|
232
|
-
* the row its glyphs became part of the row's name.
|
|
259
|
+
* the row its glyphs became part of the row's name. The `end` words are
|
|
260
|
+
* hidden from the name too, and describe the row instead.
|
|
233
261
|
*/
|
|
234
262
|
protected renderEnd(): TemplateResult;
|
|
235
263
|
/**
|
|
@@ -311,6 +339,27 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
311
339
|
* both announces and navigates.
|
|
312
340
|
*/
|
|
313
341
|
private readonly handleKeydown;
|
|
342
|
+
/**
|
|
343
|
+
* The trailing mark: the caret of a row that opens a page, or the tick of a
|
|
344
|
+
* checked one, each the fallback of a slot a mark of your own replaces.
|
|
345
|
+
*
|
|
346
|
+
* One trailing column, and a row is never both: a way into a page has nothing
|
|
347
|
+
* to tick, and a choice opens nothing. The tick sits after the label rather
|
|
348
|
+
* than before it, so the labels start at the edge of the row and the marks
|
|
349
|
+
* line up down the side they are read from.
|
|
350
|
+
*
|
|
351
|
+
* `data-mirror` is what tells the two apart. They share a part name because
|
|
352
|
+
* they share a column, and only one of them is directional: a caret has to
|
|
353
|
+
* mirror in a right-to-left document and a tick must not, which Unicode's own
|
|
354
|
+
* mirroring list agrees on. The attribute is on an element in this shadow
|
|
355
|
+
* root rather than on the host, so it is the divider's `data-empty` and not a
|
|
356
|
+
* hydration hazard.
|
|
357
|
+
*
|
|
358
|
+
* Nothing to mark, so nothing is drawn. The column this would have sat in is
|
|
359
|
+
* reserved by the menu when some row on the page needs one, so the labels
|
|
360
|
+
* still line up without every row carrying an empty box to line them up with.
|
|
361
|
+
*/
|
|
362
|
+
protected renderMark(submenu: boolean): TemplateResult | typeof nothing;
|
|
314
363
|
protected render(): TemplateResult | typeof nothing;
|
|
315
364
|
}
|
|
316
365
|
declare global {
|