@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
|
@@ -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() {
|
|
@@ -117,6 +149,9 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
117
149
|
get trigger() {
|
|
118
150
|
return anchorElement(this.renderRoot?.querySelector('slot[name="trigger"]'), this.partNamed('trigger') ?? this);
|
|
119
151
|
}
|
|
152
|
+
get navigationControl() {
|
|
153
|
+
return this.trigger;
|
|
154
|
+
}
|
|
120
155
|
close() {
|
|
121
156
|
if (!this.requestOpen(false)) {
|
|
122
157
|
return;
|
|
@@ -156,12 +191,14 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
156
191
|
connectedCallback() {
|
|
157
192
|
super.connectedCallback();
|
|
158
193
|
this.watchWidth();
|
|
194
|
+
connected.add(this);
|
|
159
195
|
window.addEventListener('scroll', this.handleScroll, { capture: true, passive: true });
|
|
160
196
|
this.addEventListener('pointerdown', this.handlePointerDown);
|
|
161
197
|
this.addEventListener('click', this.handleContentClick);
|
|
162
198
|
this.addEventListener('pointerenter', this.handlePointerEnter);
|
|
163
199
|
this.addEventListener('pointerleave', this.handlePointerLeave);
|
|
164
200
|
this.addEventListener('focusout', this.handleFocusOut);
|
|
201
|
+
this.addEventListener('keydown', this.handleKeyDown);
|
|
165
202
|
}
|
|
166
203
|
disconnectedCallback() {
|
|
167
204
|
super.disconnectedCallback();
|
|
@@ -173,6 +210,8 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
173
210
|
this.removeEventListener('pointerenter', this.handlePointerEnter);
|
|
174
211
|
this.removeEventListener('pointerleave', this.handlePointerLeave);
|
|
175
212
|
this.removeEventListener('focusout', this.handleFocusOut);
|
|
213
|
+
this.removeEventListener('keydown', this.handleKeyDown);
|
|
214
|
+
connected.delete(this);
|
|
176
215
|
this.stop();
|
|
177
216
|
if (showing === this) {
|
|
178
217
|
showing = undefined;
|
|
@@ -184,14 +223,59 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
184
223
|
return;
|
|
185
224
|
}
|
|
186
225
|
if (this.open) {
|
|
187
|
-
|
|
188
|
-
|
|
226
|
+
const previous = showing && showing !== this ? showing : undefined;
|
|
227
|
+
const forward = previous !== undefined &&
|
|
228
|
+
(previous.compareDocumentPosition(this) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
|
|
229
|
+
this.motion(previous ? (forward ? 'from-end' : 'from-start') : undefined);
|
|
230
|
+
this.from = previous?.size;
|
|
231
|
+
HelixHeadlessMegamenu_1.settle(this, previous);
|
|
232
|
+
if (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
|
+
}
|
|
189
239
|
}
|
|
190
240
|
showing = this;
|
|
241
|
+
return;
|
|
191
242
|
}
|
|
192
|
-
|
|
243
|
+
if (showing === this) {
|
|
193
244
|
showing = undefined;
|
|
194
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
|
+
}
|
|
273
|
+
}
|
|
274
|
+
motion(to) {
|
|
275
|
+
this.toggleState('from-end', to === 'from-end');
|
|
276
|
+
this.toggleState('from-start', to === 'from-start');
|
|
277
|
+
this.toggleState('to-end', to === 'to-end');
|
|
278
|
+
this.toggleState('to-start', to === 'to-start');
|
|
195
279
|
}
|
|
196
280
|
updated(changed) {
|
|
197
281
|
super.updated?.(changed);
|
|
@@ -202,6 +286,7 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
202
286
|
this.tellTrigger();
|
|
203
287
|
if (this.open) {
|
|
204
288
|
this.band();
|
|
289
|
+
this.measure();
|
|
205
290
|
}
|
|
206
291
|
}
|
|
207
292
|
renderTrigger() {
|
package/dist/menu/index.d.ts
CHANGED
package/dist/menu/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
import '../../kbd/index.js';
|
|
3
4
|
/**
|
|
4
5
|
* @summary One row in a menu: a command, a choice, or a way into a submenu.
|
|
5
6
|
*
|
|
@@ -23,21 +24,44 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
23
24
|
* attribute. An attribute written onto your element after it upgrades causes a
|
|
24
25
|
* hydration mismatch.
|
|
25
26
|
*
|
|
27
|
+
* `shortcut` shows a row's keyboard shortcut after its label, drawn by `Kbd`
|
|
28
|
+
* in the platform's glyphs, and gives the row `aria-keyshortcuts`. It binds
|
|
29
|
+
* nothing: the shortcut is the page's to bind. Other trailing words, such as a
|
|
30
|
+
* count, go in the `end` slot.
|
|
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
|
+
*
|
|
26
41
|
* @since 0.1.0
|
|
27
42
|
* @status stable
|
|
28
43
|
* @aliases Menu option, Menu row
|
|
29
44
|
* @documentation https://fusion.dev/helix/components/menu
|
|
30
45
|
*
|
|
31
46
|
* @slot - The label.
|
|
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.
|
|
32
51
|
* @slot start - Content before the label, such as an icon.
|
|
33
52
|
* @slot submenu - The rows of a submenu that this row opens.
|
|
34
53
|
*
|
|
35
54
|
* @event {HelixBeforeToggleEvent} helix-before-toggle - A choice row is about to be checked or unchecked, carrying the state asked for. Cancelable: cancel it to keep the row as it is.
|
|
36
55
|
* @event {HelixSelectEvent} helix-select - The row was chosen. Cancelable: cancel it to keep the menu open.
|
|
37
56
|
*
|
|
57
|
+
* @csspart end - The trailing column that holds the shortcut and the `end` slot. It is always rendered.
|
|
38
58
|
* @csspart item - The row, which is an `<a>` where `href` is set.
|
|
39
59
|
* @csspart mark - The trailing mark: a check mark when the row is checked, or a caret
|
|
40
60
|
* when it opens a submenu. A row never shows both, so they share one column.
|
|
61
|
+
* @csspart shortcut - The key drawn for `shortcut`.
|
|
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.
|
|
41
65
|
* @csspart start - The leading column that holds the `start` slot. It is always rendered.
|
|
42
66
|
*
|
|
43
67
|
* @cssstate checked - The row is checked.
|
|
@@ -100,19 +124,16 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
100
124
|
* roves, which is the same maneuver `Tree.Item` makes and the reason `href`
|
|
101
125
|
* changes the markup rather than only adding an attribute.
|
|
102
126
|
*
|
|
103
|
-
* **`Option`
|
|
104
|
-
*
|
|
105
|
-
*
|
|
106
|
-
* option
|
|
107
|
-
*
|
|
108
|
-
*
|
|
109
|
-
* back `null`. So `role="option"` is pinned to the host, and an anchor under
|
|
110
|
-
* it hits the naming failure above. A menu has no such constraint because
|
|
111
|
-
* focus really moves to the row.
|
|
127
|
+
* **`Option` takes an `href` too, and keeps its role a different way.** A
|
|
128
|
+
* listbox keeps focus somewhere else, in the text field for a combobox, and
|
|
129
|
+
* names the current option with `aria-activedescendant`, which can only point
|
|
130
|
+
* at the option's host. So an option stays `role="option"` on its host, draws
|
|
131
|
+
* no anchor, and follows its link through an anchor made for the moment. A
|
|
132
|
+
* menu has no such constraint, because focus really moves to the row.
|
|
112
133
|
*/
|
|
113
134
|
href: string;
|
|
114
135
|
/**
|
|
115
|
-
* Whether the row is on the menu page that is showing.
|
|
136
|
+
* @internal Whether the row is on the menu page that is showing.
|
|
116
137
|
*
|
|
117
138
|
* Set by the menu, and a property rather than an attribute for that reason.
|
|
118
139
|
* Public because the menu has to reach it, and not something a consumer
|
|
@@ -124,7 +145,14 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
124
145
|
*/
|
|
125
146
|
rel: string;
|
|
126
147
|
/**
|
|
127
|
-
*
|
|
148
|
+
* The row's keyboard shortcut as a chord, such as `mod+s`, shown after the
|
|
149
|
+
* label in the platform's glyphs and given to the row as
|
|
150
|
+
* `aria-keyshortcuts`. `mod` is Command on an Apple keyboard and Control
|
|
151
|
+
* elsewhere. Showing a shortcut does not bind it.
|
|
152
|
+
*/
|
|
153
|
+
shortcut: string;
|
|
154
|
+
/**
|
|
155
|
+
* @internal Whether the page showing is this row's submenu, or one below it.
|
|
128
156
|
*
|
|
129
157
|
* Separate from `onPage`, and it has to be. A row that opened a page is not
|
|
130
158
|
* itself on that page, so both are false for it, and rendering nothing on
|
|
@@ -185,6 +213,10 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
185
213
|
* exactly the thing that is.
|
|
186
214
|
*/
|
|
187
215
|
private start;
|
|
216
|
+
/** Whether anything is slotted after the label, read the way `start` is. */
|
|
217
|
+
private end;
|
|
218
|
+
/** Whether anything is slotted under the label, read the way `start` is. */
|
|
219
|
+
private description;
|
|
188
220
|
/**
|
|
189
221
|
* Both answers, from the children, before each render.
|
|
190
222
|
*
|
|
@@ -205,6 +237,29 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
205
237
|
* is never rebuilt and never fires on its way out.
|
|
206
238
|
*/
|
|
207
239
|
private readonly readStart;
|
|
240
|
+
/** Re-reads whether anything is after the label, as `readStart` does before it. */
|
|
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();
|
|
253
|
+
/**
|
|
254
|
+
* The trailing column: the shortcut's key, then whatever is slotted in `end`.
|
|
255
|
+
* Drawn by `Kbd`, interpolated so each tier draws its own.
|
|
256
|
+
*
|
|
257
|
+
* The key is hidden from the accessibility tree, since the row's
|
|
258
|
+
* `aria-keyshortcuts` says it in words a screen reader reads as keys: inside
|
|
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.
|
|
261
|
+
*/
|
|
262
|
+
protected renderEnd(): TemplateResult;
|
|
208
263
|
/**
|
|
209
264
|
* Re-reads whether anything is in the submenu, from whichever slot is current.
|
|
210
265
|
*
|
|
@@ -284,6 +339,27 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
284
339
|
* both announces and navigates.
|
|
285
340
|
*/
|
|
286
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;
|
|
287
363
|
protected render(): TemplateResult | typeof nothing;
|
|
288
364
|
}
|
|
289
365
|
declare global {
|
|
@@ -4,11 +4,13 @@ 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, deepActiveElement, HelixBeforeToggleEvent, HelixElement, HelixSelectEvent, requestChange, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { ariaChord, customElement, deepActiveElement, HelixBeforeToggleEvent, HelixElement, HelixSelectEvent, onApple, requestChange, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { caretRight, check } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
|
+
import { html as staticHtml } from 'lit/static-html.js';
|
|
13
|
+
import '../../kbd/index.js';
|
|
12
14
|
let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
13
15
|
constructor() {
|
|
14
16
|
super(...arguments);
|
|
@@ -20,16 +22,27 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
20
22
|
this.href = '';
|
|
21
23
|
this.onPage = true;
|
|
22
24
|
this.rel = '';
|
|
25
|
+
this.shortcut = '';
|
|
23
26
|
this.showingSubmenu = false;
|
|
24
27
|
this.target = '';
|
|
25
28
|
this.value = '';
|
|
26
29
|
this.isMenuItem = true;
|
|
27
30
|
this.submenu = false;
|
|
28
31
|
this.start = false;
|
|
32
|
+
this.end = false;
|
|
33
|
+
this.description = false;
|
|
29
34
|
this.readStart = () => {
|
|
30
35
|
const slot = this.renderRoot.querySelector('slot[name="start"]');
|
|
31
36
|
this.start = (slot?.assignedNodes().length ?? 0) > 0;
|
|
32
37
|
};
|
|
38
|
+
this.readEnd = () => {
|
|
39
|
+
const slot = this.renderRoot.querySelector('slot[name="end"]');
|
|
40
|
+
this.end = (slot?.assignedNodes().length ?? 0) > 0;
|
|
41
|
+
};
|
|
42
|
+
this.readDescription = () => {
|
|
43
|
+
const slot = this.renderRoot.querySelector('slot[name="description"]');
|
|
44
|
+
this.description = (slot?.assignedNodes().length ?? 0) > 0;
|
|
45
|
+
};
|
|
33
46
|
this.readSubmenu = () => {
|
|
34
47
|
const slot = this.renderRoot.querySelector('slot[name="submenu"]');
|
|
35
48
|
this.submenu = (slot?.assignedElements().length ?? 0) > 0;
|
|
@@ -65,11 +78,41 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
65
78
|
const named = (name) => this.knownChildren.some((child) => child.slot === name);
|
|
66
79
|
this.submenu = named('submenu');
|
|
67
80
|
this.start = named('start');
|
|
81
|
+
this.end = named('end');
|
|
82
|
+
this.description = named('description');
|
|
68
83
|
}
|
|
69
84
|
firstUpdated(changed) {
|
|
70
85
|
super.firstUpdated(changed);
|
|
71
86
|
this.finishHydration();
|
|
72
87
|
}
|
|
88
|
+
renderDescription() {
|
|
89
|
+
return html `<slot
|
|
90
|
+
id="description"
|
|
91
|
+
name="description"
|
|
92
|
+
aria-hidden="true"
|
|
93
|
+
?data-empty=${!this.description}
|
|
94
|
+
@slotchange=${this.readDescription}
|
|
95
|
+
></slot>`;
|
|
96
|
+
}
|
|
97
|
+
get describedBy() {
|
|
98
|
+
const ids = [this.description ? 'description' : '', this.end ? 'end-words' : '']
|
|
99
|
+
.filter((id) => id !== '')
|
|
100
|
+
.join(' ');
|
|
101
|
+
return ids === '' ? nothing : ids;
|
|
102
|
+
}
|
|
103
|
+
renderEnd() {
|
|
104
|
+
const kbd = this.tag('kbd');
|
|
105
|
+
return html `<span part="end" ?data-empty=${!this.end && this.shortcut === ''}
|
|
106
|
+
>${this.shortcut === ''
|
|
107
|
+
? nothing
|
|
108
|
+
: staticHtml `<${kbd}
|
|
109
|
+
part="shortcut"
|
|
110
|
+
exportparts="kbd: shortcut-kbd, key: shortcut-key, separator: shortcut-separator"
|
|
111
|
+
aria-hidden="true"
|
|
112
|
+
keys=${this.shortcut}
|
|
113
|
+
></${kbd}>`}<slot id="end-words" name="end" aria-hidden="true" @slotchange=${this.readEnd}></slot
|
|
114
|
+
></span>`;
|
|
115
|
+
}
|
|
73
116
|
focus() {
|
|
74
117
|
this.partNamed('item')?.focus();
|
|
75
118
|
}
|
|
@@ -130,6 +173,23 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
130
173
|
this.tick();
|
|
131
174
|
this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
|
|
132
175
|
}
|
|
176
|
+
renderMark(submenu) {
|
|
177
|
+
if (submenu) {
|
|
178
|
+
return html `<slot name="chevron" aria-hidden="true"
|
|
179
|
+
><svg part="mark" data-mirror fill="currentColor" viewBox=${caretRight.viewBox} aria-hidden="true">
|
|
180
|
+
${unsafeSVG(caretRight.content)}
|
|
181
|
+
</svg></slot
|
|
182
|
+
>`;
|
|
183
|
+
}
|
|
184
|
+
if (this.checked) {
|
|
185
|
+
return html `<slot name="check" aria-hidden="true"
|
|
186
|
+
><svg part="mark" fill="currentColor" viewBox=${check.viewBox} aria-hidden="true">
|
|
187
|
+
${unsafeSVG(check.content)}
|
|
188
|
+
</svg></slot
|
|
189
|
+
>`;
|
|
190
|
+
}
|
|
191
|
+
return nothing;
|
|
192
|
+
}
|
|
133
193
|
render() {
|
|
134
194
|
if (this.showingSubmenu) {
|
|
135
195
|
return html `<slot name="submenu" @slotchange=${this.readSubmenu}></slot>`;
|
|
@@ -142,31 +202,14 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
142
202
|
const ticks = this.checkable || this.checked;
|
|
143
203
|
const role = ticks ? (this.exclusive ? 'menuitemradio' : 'menuitemcheckbox') : 'menuitem';
|
|
144
204
|
const checkedState = ticks ? (this.checked ? 'true' : 'false') : nothing;
|
|
205
|
+
const keys = this.shortcut === '' ? nothing : ariaChord(this.shortcut, !this.hydrating && onApple());
|
|
145
206
|
const inside = html `<span part="start" ?data-empty=${!this.start}
|
|
146
207
|
><slot name="start" @slotchange=${this.readStart}></slot
|
|
147
208
|
></span>
|
|
148
209
|
<slot></slot>
|
|
149
|
-
${
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
data-mirror
|
|
153
|
-
fill="currentColor"
|
|
154
|
-
viewBox=${caretRight.viewBox}
|
|
155
|
-
aria-hidden="true"
|
|
156
|
-
>
|
|
157
|
-
${unsafeSVG(caretRight.content)}
|
|
158
|
-
</svg>`
|
|
159
|
-
: this.checked
|
|
160
|
-
? html `<svg
|
|
161
|
-
part="mark"
|
|
162
|
-
fill="currentColor"
|
|
163
|
-
viewBox=${check.viewBox}
|
|
164
|
-
aria-hidden="true"
|
|
165
|
-
>
|
|
166
|
-
${unsafeSVG(check.content)}
|
|
167
|
-
</svg>`
|
|
168
|
-
:
|
|
169
|
-
nothing}`;
|
|
210
|
+
${this.renderDescription()}
|
|
211
|
+
${this.renderEnd()}
|
|
212
|
+
${this.renderMark(submenu)}`;
|
|
170
213
|
return html `${linked
|
|
171
214
|
? html `<a
|
|
172
215
|
part="item"
|
|
@@ -176,7 +219,9 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
176
219
|
?download=${this.download}
|
|
177
220
|
role=${role}
|
|
178
221
|
aria-checked=${checkedState}
|
|
222
|
+
aria-describedby=${this.describedBy}
|
|
179
223
|
aria-haspopup=${submenu ? 'menu' : nothing}
|
|
224
|
+
aria-keyshortcuts=${keys}
|
|
180
225
|
tabindex="-1"
|
|
181
226
|
@click=${this.handleClick}
|
|
182
227
|
@keydown=${this.handleKeydown}
|
|
@@ -185,8 +230,10 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
185
230
|
part="item"
|
|
186
231
|
role=${role}
|
|
187
232
|
aria-checked=${checkedState}
|
|
233
|
+
aria-describedby=${this.describedBy}
|
|
188
234
|
aria-disabled=${this.disabled ? 'true' : nothing}
|
|
189
235
|
aria-haspopup=${submenu ? 'menu' : nothing}
|
|
236
|
+
aria-keyshortcuts=${keys}
|
|
190
237
|
tabindex=${this.disabled ? nothing : '-1'}
|
|
191
238
|
@click=${this.handleClick}
|
|
192
239
|
@keydown=${this.handleKeydown}
|
|
@@ -218,6 +265,9 @@ __decorate([
|
|
|
218
265
|
__decorate([
|
|
219
266
|
property()
|
|
220
267
|
], HelixHeadlessMenuItem.prototype, "rel", void 0);
|
|
268
|
+
__decorate([
|
|
269
|
+
property()
|
|
270
|
+
], HelixHeadlessMenuItem.prototype, "shortcut", void 0);
|
|
221
271
|
__decorate([
|
|
222
272
|
property({ attribute: false })
|
|
223
273
|
], HelixHeadlessMenuItem.prototype, "showingSubmenu", void 0);
|
|
@@ -233,6 +283,12 @@ __decorate([
|
|
|
233
283
|
__decorate([
|
|
234
284
|
state()
|
|
235
285
|
], HelixHeadlessMenuItem.prototype, "start", void 0);
|
|
286
|
+
__decorate([
|
|
287
|
+
state()
|
|
288
|
+
], HelixHeadlessMenuItem.prototype, "end", void 0);
|
|
289
|
+
__decorate([
|
|
290
|
+
state()
|
|
291
|
+
], HelixHeadlessMenuItem.prototype, "description", void 0);
|
|
236
292
|
HelixHeadlessMenuItem = __decorate([
|
|
237
293
|
customElement('helix-headless-menu-item')
|
|
238
294
|
], HelixHeadlessMenuItem);
|
|
@@ -24,6 +24,30 @@ declare const HelixHeadlessMenu_base: (new (...args: any[]) => import("@fusion.d
|
|
|
24
24
|
* sets this on items as a property, never as an attribute. An attribute written
|
|
25
25
|
* onto your element after it upgrades causes a hydration mismatch.
|
|
26
26
|
*
|
|
27
|
+
* Group rows under a heading with `Menu.Section`, which is a `group` named by
|
|
28
|
+
* its heading. Between runs of rows, a `<helix-divider announced>` is a
|
|
29
|
+
* separator a screen reader announces.
|
|
30
|
+
*
|
|
31
|
+
* Keys: Enter, Space or Down Arrow on the trigger opens the menu on its first
|
|
32
|
+
* row, and Up Arrow on its last. In the menu, Up and Down Arrow move between
|
|
33
|
+
* rows, Home and End go to the first and the last, a typed letter moves to
|
|
34
|
+
* the next row whose name starts with it, Enter and Space choose, Right Arrow
|
|
35
|
+
* opens a row's submenu and Left Arrow goes back, the two swapping on a
|
|
36
|
+
* right-to-left page, and Escape closes the menu and returns focus to the
|
|
37
|
+
* trigger. Tab closes it and moves on.
|
|
38
|
+
*
|
|
39
|
+
* While it is open, the surface carries the trigger's width as
|
|
40
|
+
* `--floating-anchor-inline-size` and the room left below it as
|
|
41
|
+
* `--floating-available-block-size`, as Radix's dropdown menu publishes its
|
|
42
|
+
* trigger's width, for a menu as wide as its trigger:
|
|
43
|
+
* `helix-menu::part(surface) { min-inline-size: var(--floating-anchor-inline-size) }`.
|
|
44
|
+
*
|
|
45
|
+
* With `context`, the trigger is an area and the menu is its context menu: a
|
|
46
|
+
* right-click, a long press, Shift+F10 or the menu key over the area opens it
|
|
47
|
+
* at the pointer, or at the area's corner from the keyboard, as Radix's context
|
|
48
|
+
* menu does. A press on the area does not open it, and closing it returns focus
|
|
49
|
+
* to where it was.
|
|
50
|
+
*
|
|
27
51
|
* @since 0.1.0
|
|
28
52
|
* @status stable
|
|
29
53
|
* @category overlays
|
|
@@ -31,7 +55,7 @@ declare const HelixHeadlessMenu_base: (new (...args: any[]) => import("@fusion.d
|
|
|
31
55
|
* @documentation https://fusion.dev/helix/components/menu
|
|
32
56
|
*
|
|
33
57
|
* @slot - The items.
|
|
34
|
-
* @slot trigger - The control that opens the menu.
|
|
58
|
+
* @slot trigger - The control that opens the menu, or with `context` the area a context menu opens over.
|
|
35
59
|
*
|
|
36
60
|
* @event {HelixBeforeCloseEvent} helix-before-close - The menu is about to close. Cancelable: cancel it to keep it open.
|
|
37
61
|
* @event {HelixBeforeOpenEvent} helix-before-open - The menu is about to open. Cancelable: cancel it to keep it closed.
|
|
@@ -57,6 +81,11 @@ export declare class HelixHeadlessMenu extends HelixHeadlessMenu_base {
|
|
|
57
81
|
* The text of the row that returns from a submenu.
|
|
58
82
|
*/
|
|
59
83
|
backLabel: string;
|
|
84
|
+
/**
|
|
85
|
+
* Whether the menu is the trigger's context menu: it opens where the reader
|
|
86
|
+
* asks for one, with a right-click, a long press, Shift+F10 or the menu key.
|
|
87
|
+
*/
|
|
88
|
+
context: boolean;
|
|
60
89
|
/**
|
|
61
90
|
* Accessible name for the surface.
|
|
62
91
|
*
|
|
@@ -104,6 +133,10 @@ export declare class HelixHeadlessMenu extends HelixHeadlessMenu_base {
|
|
|
104
133
|
protected readonly keys: KeyboardNavigationController;
|
|
105
134
|
/** Carries a host `aria-label` and `aria-labelledby` to the surface. */
|
|
106
135
|
protected readonly aria: AriaForwardController;
|
|
136
|
+
/** Where a context menu was asked for, in the viewport, while it is open. */
|
|
137
|
+
private point;
|
|
138
|
+
/** Where focus was when a context menu opened, so closing it returns there. */
|
|
139
|
+
private returnTo;
|
|
107
140
|
private readonly panel;
|
|
108
141
|
/**
|
|
109
142
|
* Tells a slotted trigger the disclosure state, by property.
|
|
@@ -124,6 +157,11 @@ export declare class HelixHeadlessMenu extends HelixHeadlessMenu_base {
|
|
|
124
157
|
private openAt;
|
|
125
158
|
/** Closes the menu and returns it to its first page. */
|
|
126
159
|
hide(): void;
|
|
160
|
+
/**
|
|
161
|
+
* Opens a context menu where the reader asked for it: at the pointer, or at
|
|
162
|
+
* the area's corner where the keyboard asked and the event has no position.
|
|
163
|
+
*/
|
|
164
|
+
private readonly handleContextMenu;
|
|
127
165
|
/** Shows an item's submenu in place of the current page. */
|
|
128
166
|
private enter;
|
|
129
167
|
/** Returns to the page above, or closes when there is none. */
|