@fusion.dev/helix-headless 0.144.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 +15195 -4240
- package/dist/accordion/item/accordion-item.d.ts +62 -12
- package/dist/accordion/item/accordion-item.js +41 -10
- package/dist/accordion/root/accordion-root.d.ts +14 -5
- package/dist/accordion/root/accordion-root.js +7 -1
- package/dist/announcement/root/announcement-root.d.ts +24 -3
- package/dist/announcement/root/announcement-root.js +39 -2
- package/dist/app-header/root/app-header-root.d.ts +12 -0
- package/dist/app-header/root/app-header-root.js +13 -1
- package/dist/app-header/sectioning.d.ts +9 -0
- package/dist/app-header/sectioning.js +27 -0
- 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 +57 -1
- package/dist/breadcrumbs/root/breadcrumbs-root.js +73 -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.d.ts +38 -3
- package/dist/canvas/root/canvas-root.js +123 -42
- 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 +133 -4
- package/dist/carousel/root/carousel-root.js +174 -24
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/composer/chat-composer.d.ts +38 -6
- package/dist/chat/composer/chat-composer.js +42 -9
- package/dist/chat/message/chat-message.d.ts +32 -1
- package/dist/chat/message/chat-message.js +27 -10
- package/dist/chat/naming.d.ts +26 -0
- package/dist/chat/naming.js +14 -0
- package/dist/chat/root/chat-root.d.ts +58 -0
- package/dist/chat/root/chat-root.js +43 -3
- 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 +57 -2
- package/dist/code-block/root/code-block-root.js +63 -8
- 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 +26 -1
- package/dist/copy-button/root/copy-button-root.js +12 -5
- 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 +170 -13
- package/dist/data-table/root/data-table-root.js +294 -52
- package/dist/data-table/tree.d.ts +55 -0
- package/dist/data-table/tree.js +54 -0
- 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/description-list/item/description-list-item.d.ts +17 -2
- package/dist/description-list/item/description-list-item.js +15 -2
- package/dist/description-list/root/description-list-root.d.ts +27 -1
- package/dist/description-list/root/description-list-root.js +26 -1
- 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.d.ts +11 -6
- package/dist/drilldown/item/drilldown-item.js +8 -5
- package/dist/drilldown/root/drilldown-root.d.ts +29 -0
- package/dist/drilldown/root/drilldown-root.js +28 -5
- package/dist/element-events.generated.js +83 -12
- 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 +5 -0
- package/dist/filter-input/menu/filter-menu.js +16 -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 +10 -2
- package/dist/input/root/input-root.d.ts +13 -3
- package/dist/input/root/input-root.js +12 -3
- 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 +70 -1
- package/dist/list/item/list-item.js +77 -6
- package/dist/list/numbering.d.ts +14 -0
- package/dist/list/numbering.js +8 -0
- package/dist/list/root/list-root.d.ts +155 -9
- package/dist/list/root/list-root.js +246 -4
- package/dist/list/selection.d.ts +49 -0
- package/dist/list/selection.js +30 -0
- package/dist/listbox/root/listbox-root.d.ts +37 -1
- package/dist/listbox/root/listbox-root.js +49 -4
- 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/map/root/map-root.d.ts +6 -2
- package/dist/map/root/map-root.js +5 -2
- package/dist/megamenu/root/megamenu-root.d.ts +62 -0
- package/dist/megamenu/root/megamenu-root.js +90 -5
- package/dist/menu/index.d.ts +1 -0
- package/dist/menu/index.js +1 -0
- package/dist/menu/item/menu-item.d.ts +87 -11
- package/dist/menu/item/menu-item.js +78 -22
- package/dist/menu/root/menu-root.d.ts +39 -1
- package/dist/menu/root/menu-root.js +65 -8
- package/dist/menu/section/menu-section.d.ts +55 -0
- package/dist/menu/section/menu-section.js +60 -0
- 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 +18 -2
- package/dist/navigation/root/navigation-root.js +29 -3
- package/dist/notifications/root/notifications-root.d.ts +25 -0
- package/dist/notifications/root/notifications-root.js +33 -5
- 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 +161 -32
- package/dist/object-inspector/root/object-inspector-root.js +264 -123
- package/dist/object-inspector/rows.d.ts +75 -0
- package/dist/object-inspector/rows.js +119 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/outline/levels.d.ts +31 -0
- package/dist/outline/levels.js +23 -0
- package/dist/outline/root/outline-root.d.ts +86 -3
- package/dist/outline/root/outline-root.js +95 -12
- package/dist/pagination/size/pagination-size.d.ts +12 -2
- package/dist/pagination/size/pagination-size.js +20 -5
- 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/group/radio-group.d.ts +4 -10
- package/dist/radio/group/radio-group.js +5 -10
- 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 +10 -5
- package/dist/rating/root/rating-root.js +32 -8
- 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 +84 -0
- package/dist/scroll-area/root/scroll-area-root.js +106 -7
- 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 +92 -0
- package/dist/scroll-area/scrollbar.js +33 -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 +20 -12
- package/dist/splitter/root/splitter-root.js +226 -203
- package/dist/splitter/snap.d.ts +9 -0
- package/dist/splitter/snap.js +12 -0
- 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 +20 -0
- package/dist/steps/reach.js +15 -0
- package/dist/steps/root/steps-root.d.ts +76 -0
- package/dist/steps/root/steps-root.js +93 -1
- package/dist/steps/step/step.d.ts +45 -2
- package/dist/steps/step/step.js +33 -6
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +11 -10
- package/dist/table/column/table-column.js +8 -19
- package/dist/table/root/table-root.d.ts +126 -4
- package/dist/table/root/table-root.js +156 -6
- package/dist/table/row/table-row.d.ts +47 -1
- package/dist/table/row/table-row.js +39 -2
- package/dist/tabs/panel/tab-panel.d.ts +22 -5
- package/dist/tabs/panel/tab-panel.js +34 -6
- package/dist/tabs/root/tabs-root.d.ts +37 -1
- package/dist/tabs/root/tabs-root.js +22 -4
- package/dist/tabs/tab/tab.d.ts +41 -4
- package/dist/tabs/tab/tab.js +49 -3
- 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.d.ts +46 -0
- package/dist/timeline/group/timeline-group.js +37 -0
- package/dist/timeline/index.d.ts +1 -0
- package/dist/timeline/index.js +1 -0
- package/dist/timeline/root/timeline-root.d.ts +10 -3
- package/dist/toast/item/toast-item.d.ts +24 -18
- package/dist/toast/item/toast-item.js +36 -40
- 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/toolbar/root/toolbar-root.d.ts +13 -0
- package/dist/toolbar/root/toolbar-root.js +15 -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 +61 -4
- package/dist/tree/item/tree-item.js +92 -20
- package/dist/tree/root/tree-root.d.ts +58 -0
- package/dist/tree/root/tree-root.js +80 -16
- package/dist/tree/selection.d.ts +24 -0
- package/dist/tree/selection.js +13 -0
- 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 +44 -0
- package/dist/video/media-events.js +35 -0
- package/dist/video/root/video-root.d.ts +117 -18
- package/dist/video/root/video-root.js +93 -47
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +5 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +3 -1
- package/dist/video-playlist/order.d.ts +41 -0
- package/dist/video-playlist/order.js +34 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +77 -3
- package/dist/video-playlist/root/video-playlist-root.js +60 -16
- package/dist/virtual-list/controls.d.ts +4 -0
- package/dist/virtual-list/controls.js +30 -0
- package/dist/virtual-list/fill.d.ts +22 -0
- package/dist/virtual-list/fill.js +23 -0
- package/dist/virtual-list/keys.d.ts +15 -0
- package/dist/virtual-list/keys.js +24 -0
- 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 +259 -26
- package/dist/virtual-list/root/virtual-list-root.js +333 -49
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +8113 -1394
- package/types/svelte.d.ts +2 -0
- package/types/vue.d.ts +1678 -353
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/listbox/range.d.ts +0 -17
- package/dist/listbox/range.js +0 -5
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -4,35 +4,41 @@ 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, HelixElement, inlineStep, KeyboardNavigationController, MixinCollection, MixinControllerOpen, PopoverController, scrollItemIntoView, slottedWords, tellDisclosure, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, anchorElement, customElement, DrilldownController, deepActiveElement, deepContains, HelixElement, inlineStep, KeyboardNavigationController, MixinCollection, MixinControllerOpen, PopoverController, scrollItemIntoView, slottedWords, tellDisclosure, typeaheadBy, } 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';
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
|
+
const isSection = (element) => 'isMenuSection' in element && element.isMenuSection === true;
|
|
12
13
|
let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinControllerOpen(HelixElement)) {
|
|
13
14
|
constructor() {
|
|
14
15
|
super(...arguments);
|
|
15
16
|
this.backLabel = 'Back';
|
|
17
|
+
this.context = false;
|
|
16
18
|
this.label = '';
|
|
17
19
|
this.offset = 4;
|
|
18
20
|
this.placement = 'bottom-start';
|
|
19
21
|
this.drilldown = new DrilldownController(this, {
|
|
20
22
|
isRow: (element) => 'isMenuItem' in element && element.isMenuItem === true,
|
|
21
|
-
root: () => [...this.children]
|
|
23
|
+
root: () => [...this.children]
|
|
24
|
+
.filter((child) => child.slot !== 'trigger')
|
|
25
|
+
.flatMap((child) => (isSection(child) ? [...child.children] : [child])),
|
|
22
26
|
slot: 'submenu',
|
|
23
27
|
});
|
|
24
28
|
this.keys = new KeyboardNavigationController(this, {
|
|
25
29
|
items: () => (this.open ? this.items : []),
|
|
26
30
|
reserved: () => ['ArrowLeft', 'ArrowRight'],
|
|
27
31
|
selects: () => false,
|
|
28
|
-
typeahead: (item) => slottedWords(item, ['']),
|
|
32
|
+
typeahead: typeaheadBy((item) => slottedWords(item, [''])),
|
|
29
33
|
});
|
|
30
34
|
this.aria = new AriaForwardController(this, {
|
|
31
35
|
label: true,
|
|
32
36
|
target: () => this.partNamed('surface'),
|
|
33
37
|
});
|
|
34
38
|
this.panel = new PopoverController(this, {
|
|
35
|
-
anchor: () => this.
|
|
39
|
+
anchor: () => this.context && this.point
|
|
40
|
+
? this.renderRoot?.querySelector('#point')
|
|
41
|
+
: this.trigger,
|
|
36
42
|
boundary: () => this,
|
|
37
43
|
offset: () => this.offset,
|
|
38
44
|
onDismiss: () => this.hide(),
|
|
@@ -40,6 +46,28 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
40
46
|
placement: () => this.placement,
|
|
41
47
|
surface: () => this.partNamed('surface'),
|
|
42
48
|
});
|
|
49
|
+
this.handleContextMenu = (event) => {
|
|
50
|
+
if (!this.context) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const slot = this.renderRoot?.querySelector('slot[name="trigger"]');
|
|
54
|
+
const areas = slot?.assignedElements({ flatten: true }) ?? [];
|
|
55
|
+
if (!event.composedPath().some((node) => areas.includes(node))) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
const box = this.trigger.getBoundingClientRect();
|
|
60
|
+
const keyed = event.clientX === 0 && event.clientY === 0;
|
|
61
|
+
this.point = keyed ? { x: box.left, y: box.top } : { x: event.clientX, y: event.clientY };
|
|
62
|
+
if (this.open) {
|
|
63
|
+
this.requestUpdate();
|
|
64
|
+
this.updateComplete.then(() => this.panel.reposition());
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const active = deepActiveElement();
|
|
68
|
+
this.returnTo = active instanceof HTMLElement ? active : undefined;
|
|
69
|
+
this.show();
|
|
70
|
+
};
|
|
43
71
|
this.handleSelect = (event) => {
|
|
44
72
|
const item = event.target;
|
|
45
73
|
if (!this.items.includes(item)) {
|
|
@@ -93,6 +121,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
93
121
|
event.preventDefault();
|
|
94
122
|
};
|
|
95
123
|
this.handleTriggerClick = () => {
|
|
124
|
+
if (this.context) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
96
127
|
if (this.open) {
|
|
97
128
|
this.hide();
|
|
98
129
|
}
|
|
@@ -130,8 +161,11 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
130
161
|
this.panel.hide();
|
|
131
162
|
this.drilldown.reset();
|
|
132
163
|
if (deepContains(this, deepActiveElement())) {
|
|
133
|
-
|
|
164
|
+
;
|
|
165
|
+
(this.context ? (this.returnTo ?? this.trigger) : this.trigger).focus();
|
|
134
166
|
}
|
|
167
|
+
this.point = undefined;
|
|
168
|
+
this.returnTo = undefined;
|
|
135
169
|
}
|
|
136
170
|
enter(item) {
|
|
137
171
|
if (!this.drilldown.enter(item)) {
|
|
@@ -149,7 +183,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
149
183
|
this.updateComplete.then(() => leaving?.focus());
|
|
150
184
|
}
|
|
151
185
|
handleClosedKeydown(event) {
|
|
152
|
-
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
|
|
186
|
+
if (this.context || (event.key !== 'ArrowDown' && event.key !== 'ArrowUp')) {
|
|
153
187
|
return;
|
|
154
188
|
}
|
|
155
189
|
const slot = this.renderRoot?.querySelector('slot[name="trigger"]');
|
|
@@ -165,17 +199,30 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
165
199
|
this.addEventListener('helix-select', this.handleSelect, true);
|
|
166
200
|
this.addEventListener('keydown', this.handleKeydown);
|
|
167
201
|
this.addEventListener('focusin', this.handleFocusIn);
|
|
202
|
+
this.addEventListener('contextmenu', this.handleContextMenu);
|
|
168
203
|
}
|
|
169
204
|
disconnectedCallback() {
|
|
170
205
|
super.disconnectedCallback();
|
|
171
206
|
this.removeEventListener('helix-select', this.handleSelect, true);
|
|
172
207
|
this.removeEventListener('keydown', this.handleKeydown);
|
|
173
208
|
this.removeEventListener('focusin', this.handleFocusIn);
|
|
209
|
+
this.removeEventListener('contextmenu', this.handleContextMenu);
|
|
174
210
|
}
|
|
175
211
|
updated(changed) {
|
|
176
212
|
super.updated(changed);
|
|
177
|
-
this.
|
|
213
|
+
if (!this.context) {
|
|
214
|
+
this.tellTrigger();
|
|
215
|
+
}
|
|
178
216
|
for (const child of this.children) {
|
|
217
|
+
if (isSection(child)) {
|
|
218
|
+
child.onPage = this.drilldown.atRoot;
|
|
219
|
+
for (const row of child.children) {
|
|
220
|
+
if (row.isMenuItem === true) {
|
|
221
|
+
this.mark(row, this.drilldown.atRoot);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
179
226
|
const item = child;
|
|
180
227
|
if (item.isMenuItem !== true) {
|
|
181
228
|
continue;
|
|
@@ -217,7 +264,14 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
217
264
|
}
|
|
218
265
|
}
|
|
219
266
|
render() {
|
|
220
|
-
|
|
267
|
+
const point = this.context && this.point;
|
|
268
|
+
return html `<slot name="trigger" @click=${this.handleTriggerClick}></slot>${point
|
|
269
|
+
? html `<span
|
|
270
|
+
id="point"
|
|
271
|
+
aria-hidden="true"
|
|
272
|
+
style="position: fixed; left: 0; top: 0; translate: ${point.x}px ${point.y}px"
|
|
273
|
+
></span>`
|
|
274
|
+
: nothing}
|
|
221
275
|
<div
|
|
222
276
|
part="surface"
|
|
223
277
|
popover="manual"
|
|
@@ -250,6 +304,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
250
304
|
__decorate([
|
|
251
305
|
property({ attribute: 'back-label' })
|
|
252
306
|
], HelixHeadlessMenu.prototype, "backLabel", void 0);
|
|
307
|
+
__decorate([
|
|
308
|
+
property({ reflect: true, type: Boolean })
|
|
309
|
+
], HelixHeadlessMenu.prototype, "context", void 0);
|
|
253
310
|
__decorate([
|
|
254
311
|
property()
|
|
255
312
|
], HelixHeadlessMenu.prototype, "label", void 0);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
+
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
/**
|
|
4
|
+
* @summary A group of rows in a menu, under a heading.
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
* The rows inside it are the menu's rows: the arrow keys and typed letters move
|
|
8
|
+
* through them with the rest, and a set of `exclusive` rows is still the run
|
|
9
|
+
* of them next to each other. The section is a `group` named by its heading,
|
|
10
|
+
* as React Aria's menu section is, so a screen reader says which group a row
|
|
11
|
+
* is in as it arrives.
|
|
12
|
+
*
|
|
13
|
+
* A section goes on the menu's first page. A submenu's page takes rows and
|
|
14
|
+
* dividers.
|
|
15
|
+
*
|
|
16
|
+
* @since 0.1.0
|
|
17
|
+
* @status stable
|
|
18
|
+
* @aliases Menu group, Menu heading
|
|
19
|
+
* @documentation https://fusion.dev/helix/components/menu
|
|
20
|
+
*
|
|
21
|
+
* @slot - The rows.
|
|
22
|
+
* @slot heading - The heading, for content richer than `label`.
|
|
23
|
+
*
|
|
24
|
+
* @csspart heading - The words that name the section.
|
|
25
|
+
* @csspart section - The group that holds the heading and the rows.
|
|
26
|
+
*/
|
|
27
|
+
export declare class HelixHeadlessMenuSection extends HelixElement {
|
|
28
|
+
/**
|
|
29
|
+
* The heading's words, when they are plain text. Content in the `heading`
|
|
30
|
+
* slot replaces it.
|
|
31
|
+
*/
|
|
32
|
+
label: string;
|
|
33
|
+
/**
|
|
34
|
+
* @internal Set by the menu: whether the section is on the page showing. A
|
|
35
|
+
* property, because the menu writes it after the section upgrades.
|
|
36
|
+
*/
|
|
37
|
+
onPage: boolean;
|
|
38
|
+
/** @internal What a menu reads to tell a section from a row. */
|
|
39
|
+
readonly isMenuSection = true;
|
|
40
|
+
/**
|
|
41
|
+
* Whether anything is slotted as the heading, read from the children before
|
|
42
|
+
* each render and from the slot after. A section with neither this nor a
|
|
43
|
+
* `label` draws no heading.
|
|
44
|
+
*/
|
|
45
|
+
private heading;
|
|
46
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
47
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
48
|
+
private readonly readHeading;
|
|
49
|
+
protected render(): TemplateResult | typeof nothing;
|
|
50
|
+
}
|
|
51
|
+
declare global {
|
|
52
|
+
interface HTMLElementTagNameMap {
|
|
53
|
+
'helix-headless-menu-section': HelixHeadlessMenuSection;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
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
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { customElement, HelixElement } from '@fusion.dev/helix-core';
|
|
8
|
+
import { html, nothing } from 'lit';
|
|
9
|
+
import { property, state } from 'lit/decorators.js';
|
|
10
|
+
let HelixHeadlessMenuSection = class HelixHeadlessMenuSection extends HelixElement {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.label = '';
|
|
14
|
+
this.onPage = true;
|
|
15
|
+
this.isMenuSection = true;
|
|
16
|
+
this.heading = false;
|
|
17
|
+
this.readHeading = (event) => {
|
|
18
|
+
this.heading = event.target.assignedNodes().length > 0;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
willUpdate(changed) {
|
|
22
|
+
super.willUpdate(changed);
|
|
23
|
+
if (this.childrenKnown) {
|
|
24
|
+
this.heading = this.knownChildren.some((child) => child.slot === 'heading');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
firstUpdated(changed) {
|
|
28
|
+
super.firstUpdated(changed);
|
|
29
|
+
this.finishHydration();
|
|
30
|
+
}
|
|
31
|
+
render() {
|
|
32
|
+
if (!this.onPage) {
|
|
33
|
+
return nothing;
|
|
34
|
+
}
|
|
35
|
+
return html `<div part="section" role="group" aria-labelledby="heading">
|
|
36
|
+
<div
|
|
37
|
+
id="heading"
|
|
38
|
+
part="heading"
|
|
39
|
+
role="presentation"
|
|
40
|
+
?hidden=${this.label === '' && !this.heading}
|
|
41
|
+
>
|
|
42
|
+
<slot name="heading" @slotchange=${this.readHeading}>${this.label}</slot>
|
|
43
|
+
</div>
|
|
44
|
+
<slot></slot>
|
|
45
|
+
</div>`;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
__decorate([
|
|
49
|
+
property()
|
|
50
|
+
], HelixHeadlessMenuSection.prototype, "label", void 0);
|
|
51
|
+
__decorate([
|
|
52
|
+
property({ attribute: false })
|
|
53
|
+
], HelixHeadlessMenuSection.prototype, "onPage", void 0);
|
|
54
|
+
__decorate([
|
|
55
|
+
state()
|
|
56
|
+
], HelixHeadlessMenuSection.prototype, "heading", void 0);
|
|
57
|
+
HelixHeadlessMenuSection = __decorate([
|
|
58
|
+
customElement('helix-headless-menu-section')
|
|
59
|
+
], HelixHeadlessMenuSection);
|
|
60
|
+
export { HelixHeadlessMenuSection };
|
|
@@ -71,6 +71,21 @@ export declare class HelixHeadlessMeter extends HelixElement {
|
|
|
71
71
|
* no reader.
|
|
72
72
|
*/
|
|
73
73
|
band?: MeterBand;
|
|
74
|
+
/**
|
|
75
|
+
* `Intl.NumberFormat` options the reading is written with, as React Aria's
|
|
76
|
+
* Meter and ProgressBar take them: a unit, a currency, or a number of
|
|
77
|
+
* decimals. Written as JSON in the attribute.
|
|
78
|
+
*
|
|
79
|
+
* ```html
|
|
80
|
+
* <helix-meter value="18" max="32" format-options='{"style":"unit","unit":"gigabyte"}'></helix-meter>
|
|
81
|
+
* ```
|
|
82
|
+
*
|
|
83
|
+
* A `percent` style writes the share of the range, and any other the value
|
|
84
|
+
* itself, so the example says "18 GB", and a value past an end as it is.
|
|
85
|
+
* Absent is a whole percentage. The words are announced as well as shown.
|
|
86
|
+
* `value-text` still wins.
|
|
87
|
+
*/
|
|
88
|
+
formatOptions?: Intl.NumberFormatOptions;
|
|
74
89
|
/**
|
|
75
90
|
* Bottom of the high band.
|
|
76
91
|
*
|
|
@@ -199,7 +214,11 @@ export declare class HelixHeadlessMeter extends HelixElement {
|
|
|
199
214
|
* keeps an unbanded meter from being painted as good news.
|
|
200
215
|
*/
|
|
201
216
|
private get computedBand();
|
|
202
|
-
/**
|
|
217
|
+
/**
|
|
218
|
+
* What the reading says: the consumer's words, or the reading in
|
|
219
|
+
* `format-options`, a share of the range for a percent and the value for
|
|
220
|
+
* anything else.
|
|
221
|
+
*/
|
|
203
222
|
private get text();
|
|
204
223
|
protected willUpdate(changed: PropertyValues): void;
|
|
205
224
|
/**
|
|
@@ -4,21 +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, HelixElement, hostAria, slottedWords } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, formatNumber, HelixElement, hostAria, slottedWords, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing, svg } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
-
const
|
|
11
|
-
const percent = (share, locale) => {
|
|
12
|
-
let format = percents.get(locale);
|
|
13
|
-
if (!format) {
|
|
14
|
-
format = new Intl.NumberFormat(locale || undefined, {
|
|
15
|
-
maximumFractionDigits: 0,
|
|
16
|
-
style: 'percent',
|
|
17
|
-
});
|
|
18
|
-
percents.set(locale, format);
|
|
19
|
-
}
|
|
20
|
-
return format.format(share);
|
|
21
|
-
};
|
|
10
|
+
const WHOLE_PERCENT = { maximumFractionDigits: 0, style: 'percent' };
|
|
22
11
|
let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
|
|
23
12
|
constructor() {
|
|
24
13
|
super(...arguments);
|
|
@@ -80,7 +69,11 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
|
|
|
80
69
|
return distance === 0 ? 'good' : distance === 1 ? 'fair' : 'poor';
|
|
81
70
|
}
|
|
82
71
|
get text() {
|
|
83
|
-
|
|
72
|
+
const options = this.formatOptions;
|
|
73
|
+
return (this.valueText ||
|
|
74
|
+
(options && options.style !== 'percent'
|
|
75
|
+
? formatNumber(Number.isFinite(this.value) ? this.value : this.span.min, this.locale, options)
|
|
76
|
+
: formatNumber(this.ratio, this.locale, options ?? WHOLE_PERCENT)));
|
|
84
77
|
}
|
|
85
78
|
willUpdate(changed) {
|
|
86
79
|
super.willUpdate(changed);
|
|
@@ -90,7 +83,7 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
|
|
|
90
83
|
this.internals.ariaValueMax = String(max);
|
|
91
84
|
this.internals.ariaValueNow = String(this.reading);
|
|
92
85
|
this.internals.ariaValueText =
|
|
93
|
-
this.valueText ||
|
|
86
|
+
this.valueText || this.formatOptions !== undefined || this.beyond ? this.text : null;
|
|
94
87
|
}
|
|
95
88
|
renderRound() {
|
|
96
89
|
const bounds = this.thresholds;
|
|
@@ -144,6 +137,9 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
|
|
|
144
137
|
__decorate([
|
|
145
138
|
property()
|
|
146
139
|
], HelixHeadlessMeter.prototype, "band", void 0);
|
|
140
|
+
__decorate([
|
|
141
|
+
property({ attribute: 'format-options', type: Object })
|
|
142
|
+
], HelixHeadlessMeter.prototype, "formatOptions", void 0);
|
|
147
143
|
__decorate([
|
|
148
144
|
property({ type: Number })
|
|
149
145
|
], HelixHeadlessMeter.prototype, "high", void 0);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AriaForwardController, HelixElement } from '@fusion.dev/helix-core';
|
|
1
|
+
import { AriaForwardController, HelixElement, KeyboardNavigationController } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/**
|
|
4
4
|
* @summary A set of destinations, with a marker on the current one.
|
|
@@ -22,6 +22,13 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
22
22
|
* Set `orientation="vertical"` to stack the destinations in a column, for a
|
|
23
23
|
* sidebar.
|
|
24
24
|
*
|
|
25
|
+
* Set `arrows` and the arrow keys move focus between the destinations, as
|
|
26
|
+
* Radix's navigation menu does: left and right along a row, up and down a
|
|
27
|
+
* column, Home and End to the ends. A `Megamenu` among them is reached at its
|
|
28
|
+
* trigger. Tab still stops at every link, since a navigation is a list of
|
|
29
|
+
* links and not a single control, and the keys across the other axis are
|
|
30
|
+
* left to the page and to an open panel.
|
|
31
|
+
*
|
|
25
32
|
* @since 0.1.0
|
|
26
33
|
* @status stable
|
|
27
34
|
* @category navigation
|
|
@@ -29,12 +36,20 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
29
36
|
* @documentation https://fusion.dev/helix/components/navigation
|
|
30
37
|
*
|
|
31
38
|
* @slot - The destinations, as your own links.
|
|
39
|
+
* @slot indicator - A marker of your own, drawn inside the `indicator` part, where the current destination's place and size reach it.
|
|
32
40
|
*
|
|
33
|
-
* @csspart indicator - The marker that moves to the current destination.
|
|
41
|
+
* @csspart indicator - The marker that moves to the current destination. It carries the destination's place and size as `--indicator-x`, `--indicator-y`, `--indicator-inline-size` and `--indicator-block-size`, and `data-placed` once it has been placed.
|
|
34
42
|
* @csspart nav - The navigation landmark.
|
|
35
43
|
*/
|
|
36
44
|
export declare class HelixHeadlessNavigation extends HelixElement {
|
|
37
45
|
private readonly indicator;
|
|
46
|
+
/**
|
|
47
|
+
* Whether the arrow keys move focus between the destinations.
|
|
48
|
+
*
|
|
49
|
+
* Off by default, so a page whose readers scroll with the arrow keys while
|
|
50
|
+
* a link has focus keeps doing so.
|
|
51
|
+
*/
|
|
52
|
+
arrows: boolean;
|
|
38
53
|
/**
|
|
39
54
|
* The landmark's name, read by screen readers.
|
|
40
55
|
*
|
|
@@ -43,6 +58,7 @@ export declare class HelixHeadlessNavigation extends HelixElement {
|
|
|
43
58
|
* second "Main".
|
|
44
59
|
*/
|
|
45
60
|
label: string;
|
|
61
|
+
protected readonly keys: KeyboardNavigationController;
|
|
46
62
|
/** Carries a host `aria-label` and `aria-labelledby` to the `<nav>`. */
|
|
47
63
|
protected readonly aria: AriaForwardController;
|
|
48
64
|
/**
|
|
@@ -4,9 +4,24 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { AriaForwardController, customElement, HelixElement, IndicatorController, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, customElement, focusableElements, HelixElement, IndicatorController, KeyboardNavigationController, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
+
const FOCUSABLE = 'a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
11
|
+
const navigable = (item) => {
|
|
12
|
+
const control = () => item.navigationControl ??
|
|
13
|
+
(item.matches(FOCUSABLE) ? item : focusableElements(item)[0]);
|
|
14
|
+
return {
|
|
15
|
+
contains: (node) => {
|
|
16
|
+
const target = control();
|
|
17
|
+
return target !== undefined && node !== null && (node === target || target.contains(node));
|
|
18
|
+
},
|
|
19
|
+
disabled: false,
|
|
20
|
+
focusItem: () => control()?.focus(),
|
|
21
|
+
select: () => { },
|
|
22
|
+
selected: false,
|
|
23
|
+
};
|
|
24
|
+
};
|
|
10
25
|
let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement {
|
|
11
26
|
constructor() {
|
|
12
27
|
super(...arguments);
|
|
@@ -23,14 +38,22 @@ let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement
|
|
|
23
38
|
observe: () => this.items,
|
|
24
39
|
surface: () => this.partNamed('nav'),
|
|
25
40
|
});
|
|
41
|
+
this.arrows = false;
|
|
26
42
|
this.label = 'Main';
|
|
43
|
+
this.keys = new KeyboardNavigationController(this, {
|
|
44
|
+
items: () => (this.arrows ? this.items.map(navigable) : []),
|
|
45
|
+
origin: 'focus',
|
|
46
|
+
reserved: () => this.orientation === 'vertical' ? ['ArrowLeft', 'ArrowRight'] : ['ArrowDown', 'ArrowUp'],
|
|
47
|
+
selects: () => false,
|
|
48
|
+
wrap: false,
|
|
49
|
+
});
|
|
27
50
|
this.aria = new AriaForwardController(this, {
|
|
28
51
|
label: true,
|
|
29
52
|
target: () => this.partNamed('nav'),
|
|
30
53
|
});
|
|
31
54
|
}
|
|
32
55
|
get items() {
|
|
33
|
-
const slot = this.renderRoot.querySelector('slot');
|
|
56
|
+
const slot = this.renderRoot.querySelector('slot:not([name])');
|
|
34
57
|
return (slot?.assignedElements() ?? []);
|
|
35
58
|
}
|
|
36
59
|
watch() {
|
|
@@ -57,11 +80,14 @@ let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement
|
|
|
57
80
|
}
|
|
58
81
|
render() {
|
|
59
82
|
return html `<nav part="nav" aria-label=${this.label}>
|
|
60
|
-
<div part="indicator" aria-hidden="true"></div>
|
|
83
|
+
<div part="indicator" aria-hidden="true"><slot name="indicator"></slot></div>
|
|
61
84
|
<slot @slotchange=${() => this.watch()}></slot>
|
|
62
85
|
</nav>`;
|
|
63
86
|
}
|
|
64
87
|
};
|
|
88
|
+
__decorate([
|
|
89
|
+
property({ type: Boolean })
|
|
90
|
+
], HelixHeadlessNavigation.prototype, "arrows", void 0);
|
|
65
91
|
__decorate([
|
|
66
92
|
property()
|
|
67
93
|
], HelixHeadlessNavigation.prototype, "label", void 0);
|
|
@@ -29,6 +29,12 @@ declare const HelixHeadlessNotifications_base: (new (...args: any[]) => import("
|
|
|
29
29
|
* the feed holds one page of a longer list, and each row says its place in the
|
|
30
30
|
* whole of it.
|
|
31
31
|
*
|
|
32
|
+
* **`load-more` adds a button after the list** that sends `helix-load-more`,
|
|
33
|
+
* for a feed that holds one page of a longer list. Append the next page, set
|
|
34
|
+
* `loading` while it is on its way, and take `load-more` off once there is
|
|
35
|
+
* nothing more. While the feed is loading the button stays, so focus stays on
|
|
36
|
+
* it, and it is `aria-disabled` and sends nothing.
|
|
37
|
+
*
|
|
32
38
|
* @since 0.1.0
|
|
33
39
|
* @status stable
|
|
34
40
|
* @category feedback
|
|
@@ -40,6 +46,7 @@ declare const HelixHeadlessNotifications_base: (new (...args: any[]) => import("
|
|
|
40
46
|
* @slot header - Above the list, for a title and the mark-all control.
|
|
41
47
|
*
|
|
42
48
|
* @event {HelixDismissEvent} helix-dismiss - Fired when the user dismisses a row. The row dispatches it, and you can listen for it on the feed. Cancelable: cancel it to keep the row.
|
|
49
|
+
* @event {HelixLoadMoreEvent} helix-load-more - Fired when a reader presses the `load-more` button, asking for the next page of the feed.
|
|
43
50
|
* @event {HelixReadEvent} helix-read - Fired by an item when it is marked read or unread, and by the feed when everything is marked read. Cancelable.
|
|
44
51
|
*
|
|
45
52
|
* @csspart empty - Shown when there is nothing in the feed.
|
|
@@ -49,6 +56,7 @@ declare const HelixHeadlessNotifications_base: (new (...args: any[]) => import("
|
|
|
49
56
|
* @csspart live - A copy of the empty and loading messages, in a live region that screen readers announce when they change. Visually hidden in the styled tier.
|
|
50
57
|
* @csspart loading - Shown while the feed is loading.
|
|
51
58
|
* @csspart mark-all - The control that marks everything read.
|
|
59
|
+
* @csspart more - The button after the list that asks for more, while `load-more` is set. It is `aria-disabled` while the feed is loading.
|
|
52
60
|
*
|
|
53
61
|
* @cssstate media - While a notification in the list holds something in its media slot, so every row keeps that column.
|
|
54
62
|
*/
|
|
@@ -67,6 +75,15 @@ export declare class HelixHeadlessNotifications extends HelixHeadlessNotificatio
|
|
|
67
75
|
* The feed's name, read by screen readers.
|
|
68
76
|
*/
|
|
69
77
|
label: string;
|
|
78
|
+
/**
|
|
79
|
+
* Whether to draw a button after the list that asks for the next page, by
|
|
80
|
+
* sending `helix-load-more`. Take it off once there is nothing more.
|
|
81
|
+
*/
|
|
82
|
+
loadMore: boolean;
|
|
83
|
+
/**
|
|
84
|
+
* The text of the `load-more` button.
|
|
85
|
+
*/
|
|
86
|
+
loadMoreLabel: string;
|
|
70
87
|
/**
|
|
71
88
|
* Whether to draw a control that marks everything read.
|
|
72
89
|
*/
|
|
@@ -244,6 +261,14 @@ export declare class HelixHeadlessNotifications extends HelixHeadlessNotificatio
|
|
|
244
261
|
private markEmpty;
|
|
245
262
|
protected updated(changed: PropertyValues): void;
|
|
246
263
|
protected render(): TemplateResult;
|
|
264
|
+
/**
|
|
265
|
+
* Asks for the next page, for the `load-more` button, unless a page is
|
|
266
|
+
* already on its way.
|
|
267
|
+
*
|
|
268
|
+
* The button stays while the feed is loading, marked `aria-disabled`, so
|
|
269
|
+
* focus stays on it: removed, it took focus with it to the body.
|
|
270
|
+
*/
|
|
271
|
+
private readonly askForMore;
|
|
247
272
|
/**
|
|
248
273
|
* Marks everything read, and keeps focus in the feed.
|
|
249
274
|
*
|
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, deepContains, focusableElements, HelixElement, HelixReadEvent, hostAria, MixinCollection, markRegion, rovingStop, whenHydrated, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, deepContains, focusableElements, HelixElement, HelixLoadMoreEvent, HelixReadEvent, hostAria, MixinCollection, markRegion, rovingStop, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { feedStep } from '../feed-keys.js';
|
|
@@ -12,6 +12,8 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
|
|
|
12
12
|
constructor() {
|
|
13
13
|
super(...arguments);
|
|
14
14
|
this.label = '';
|
|
15
|
+
this.loadMore = false;
|
|
16
|
+
this.loadMoreLabel = 'Load more';
|
|
15
17
|
this.markAll = false;
|
|
16
18
|
this.markAllLabel = 'Mark all as read';
|
|
17
19
|
this.handleSlotChange = () => {
|
|
@@ -51,6 +53,11 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
|
|
|
51
53
|
rowBox(next)?.focus();
|
|
52
54
|
}
|
|
53
55
|
};
|
|
56
|
+
this.askForMore = () => {
|
|
57
|
+
if (!this.loading) {
|
|
58
|
+
this.dispatchEvent(new HelixLoadMoreEvent());
|
|
59
|
+
}
|
|
60
|
+
};
|
|
54
61
|
this.handleMarkAll = (event) => {
|
|
55
62
|
const button = event.currentTarget;
|
|
56
63
|
const focused = this.shadowRoot?.activeElement === button;
|
|
@@ -146,9 +153,9 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
|
|
|
146
153
|
rove() {
|
|
147
154
|
const rows = this.reachable;
|
|
148
155
|
const stop = rovingStop(rows, this.stopRow);
|
|
149
|
-
const
|
|
150
|
-
for (const row of
|
|
151
|
-
const position =
|
|
156
|
+
const items = this.items;
|
|
157
|
+
for (const row of items) {
|
|
158
|
+
const position = items.indexOf(row) + 1;
|
|
152
159
|
whenHydrated(row, () => {
|
|
153
160
|
row.stop = row === stop;
|
|
154
161
|
row.position = this.total === undefined ? 0 : position;
|
|
@@ -205,17 +212,38 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
|
|
|
205
212
|
</button>`
|
|
206
213
|
: nothing}
|
|
207
214
|
</div>
|
|
208
|
-
<div
|
|
215
|
+
<div
|
|
216
|
+
part="list"
|
|
217
|
+
role="list"
|
|
218
|
+
aria-busy=${this.loading ? 'true' : nothing}
|
|
219
|
+
aria-label=${this.label || nothing}
|
|
220
|
+
>
|
|
209
221
|
<slot name="items" @slotchange=${this.handleSlotChange}></slot>
|
|
210
222
|
${this.renderStatus(hasItems)}
|
|
211
223
|
</div>
|
|
212
224
|
${this.renderLive(hasItems)}
|
|
225
|
+
${this.loadMore
|
|
226
|
+
? html `<button
|
|
227
|
+
part="more"
|
|
228
|
+
type="button"
|
|
229
|
+
aria-disabled=${this.loading ? 'true' : nothing}
|
|
230
|
+
@click=${this.askForMore}
|
|
231
|
+
>
|
|
232
|
+
${this.loadMoreLabel}
|
|
233
|
+
</button>`
|
|
234
|
+
: nothing}
|
|
213
235
|
<div part="footer"><slot name="footer"></slot></div>`;
|
|
214
236
|
}
|
|
215
237
|
};
|
|
216
238
|
__decorate([
|
|
217
239
|
property()
|
|
218
240
|
], HelixHeadlessNotifications.prototype, "label", void 0);
|
|
241
|
+
__decorate([
|
|
242
|
+
property({ attribute: 'load-more', type: Boolean })
|
|
243
|
+
], HelixHeadlessNotifications.prototype, "loadMore", void 0);
|
|
244
|
+
__decorate([
|
|
245
|
+
property({ attribute: 'load-more-label' })
|
|
246
|
+
], HelixHeadlessNotifications.prototype, "loadMoreLabel", void 0);
|
|
219
247
|
__decorate([
|
|
220
248
|
property({ attribute: 'mark-all', type: Boolean })
|
|
221
249
|
], HelixHeadlessNotifications.prototype, "markAll", void 0);
|