@fusion.dev/helix-headless 0.142.1 → 0.144.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 +25381 -1202
- package/dist/accordion/item/accordion-item.d.ts +38 -2
- package/dist/accordion/item/accordion-item.js +38 -6
- package/dist/accordion/root/accordion-root.d.ts +23 -1
- package/dist/accordion/root/accordion-root.js +39 -3
- package/dist/announcement/root/announcement-root.d.ts +11 -7
- package/dist/announcement/root/announcement-root.js +1 -1
- package/dist/app-header/root/app-header-root.d.ts +21 -0
- package/dist/app-header/root/app-header-root.js +31 -5
- package/dist/area-chart/root/area-chart-root.d.ts +12 -4
- package/dist/area-chart/root/area-chart-root.js +39 -11
- package/dist/avatar/group/avatar-group.d.ts +24 -3
- package/dist/avatar/group/avatar-group.js +34 -2
- package/dist/avatar/root/avatar-root.d.ts +17 -1
- package/dist/avatar/root/avatar-root.js +31 -10
- package/dist/badge/root/badge-root.d.ts +12 -0
- package/dist/badge/root/badge-root.js +1 -1
- package/dist/bar-chart/root/bar-chart-root.d.ts +30 -5
- package/dist/bar-chart/root/bar-chart-root.js +58 -21
- package/dist/blockquote/root/blockquote-root.d.ts +12 -7
- package/dist/blockquote/root/blockquote-root.js +6 -4
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -3
- package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -1
- package/dist/button/root/button-root.d.ts +84 -1
- package/dist/button/root/button-root.js +81 -3
- package/dist/callout/root/callout-root.d.ts +32 -6
- package/dist/callout/root/callout-root.js +26 -7
- package/dist/canvas/root/canvas-root.d.ts +1 -0
- package/dist/canvas/root/canvas-root.js +10 -1
- package/dist/card/root/card-root.d.ts +30 -1
- package/dist/card/root/card-root.js +38 -5
- package/dist/carousel/root/carousel-root.d.ts +47 -5
- package/dist/carousel/root/carousel-root.js +53 -21
- package/dist/chat/composer/chat-composer.d.ts +13 -11
- package/dist/chat/composer/chat-composer.js +6 -12
- package/dist/chat/message/chat-message.js +8 -1
- package/dist/chat/root/chat-root.d.ts +1 -0
- package/dist/chat/root/chat-root.js +2 -1
- package/dist/checkbox/root/checkbox-root.d.ts +7 -0
- package/dist/checkbox/root/checkbox-root.js +9 -3
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +116 -33
- package/dist/checkbox-group/root/checkbox-group-root.js +141 -44
- package/dist/code/root/code-root.d.ts +1 -1
- package/dist/code-block/lines.d.ts +13 -0
- package/dist/code-block/lines.js +2 -0
- package/dist/code-block/root/code-block-root.d.ts +49 -0
- package/dist/code-block/root/code-block-root.js +44 -3
- package/dist/color-input/root/color-input-root.d.ts +60 -2
- package/dist/color-input/root/color-input-root.js +55 -7
- package/dist/color-picker/channels.d.ts +26 -0
- package/dist/color-picker/channels.js +84 -0
- package/dist/color-picker/root/color-picker-root.d.ts +118 -12
- package/dist/color-picker/root/color-picker-root.js +183 -13
- package/dist/combobox/root/combobox-root.d.ts +126 -3
- package/dist/combobox/root/combobox-root.js +224 -21
- package/dist/command/root/command-root.d.ts +47 -10
- package/dist/command/root/command-root.js +45 -4
- package/dist/copy-button/from.d.ts +22 -0
- package/dist/copy-button/from.js +28 -0
- package/dist/copy-button/root/copy-button-root.d.ts +48 -7
- package/dist/copy-button/root/copy-button-root.js +54 -8
- package/dist/data-table/root/data-table-root.d.ts +164 -10
- package/dist/data-table/root/data-table-root.js +488 -57
- package/dist/date-input/root/date-input-root.d.ts +123 -9
- package/dist/date-input/root/date-input-root.js +147 -45
- package/dist/date-picker/root/date-picker-root.d.ts +229 -18
- package/dist/date-picker/root/date-picker-root.js +342 -46
- package/dist/dialog/description.d.ts +9 -0
- package/dist/dialog/description.js +14 -0
- package/dist/dialog/root/dialog-root.d.ts +101 -10
- package/dist/dialog/root/dialog-root.js +83 -4
- package/dist/donut-chart/root/donut-chart-root.d.ts +61 -16
- package/dist/donut-chart/root/donut-chart-root.js +48 -13
- package/dist/drawer/root/drawer-root.d.ts +93 -7
- package/dist/drawer/root/drawer-root.js +126 -5
- package/dist/drawer/swipe-start.d.ts +9 -0
- package/dist/drawer/swipe-start.js +12 -0
- package/dist/drilldown/item/drilldown-item.d.ts +16 -13
- package/dist/drilldown/item/drilldown-item.js +6 -2
- package/dist/drilldown/root/drilldown-root.d.ts +21 -5
- package/dist/drilldown/root/drilldown-root.js +26 -10
- package/dist/element-events.generated.js +42 -13
- package/dist/empty/root/empty-root.d.ts +1 -1
- package/dist/file-input/root/file-input-root.d.ts +65 -1
- package/dist/file-input/root/file-input-root.js +76 -12
- package/dist/file-input/screen.d.ts +35 -0
- package/dist/file-input/screen.js +49 -0
- package/dist/filter-input/menu/filter-menu.d.ts +9 -0
- package/dist/filter-input/menu/filter-menu.js +8 -0
- package/dist/filter-input/root/filter-input-root.d.ts +43 -6
- package/dist/filter-input/root/filter-input-root.js +89 -10
- package/dist/filter-input/suggest.d.ts +17 -0
- package/dist/filter-input/suggest.js +23 -0
- package/dist/format-date/options.d.ts +33 -0
- package/dist/format-date/options.js +42 -0
- package/dist/format-date/root/format-date-root.d.ts +62 -3
- package/dist/format-date/root/format-date-root.js +78 -37
- package/dist/graph/root/graph-root.d.ts +24 -3
- package/dist/graph/root/graph-root.js +66 -12
- package/dist/heatmap/root/buckets.d.ts +2 -1
- package/dist/heatmap/root/buckets.js +5 -1
- package/dist/heatmap/root/heatmap-root.d.ts +47 -9
- package/dist/heatmap/root/heatmap-root.js +46 -18
- package/dist/icon/index.d.ts +2 -0
- package/dist/icon/index.js +2 -0
- package/dist/icon/registry.d.ts +37 -0
- package/dist/icon/registry.js +83 -0
- package/dist/icon/root/icon-root.d.ts +53 -6
- package/dist/icon/root/icon-root.js +72 -4
- package/dist/icon/root/index.d.ts +2 -0
- package/dist/icon/root/index.js +2 -0
- package/dist/icon/set.d.ts +1 -0
- package/dist/icon/set.js +3 -0
- package/dist/icon-button/root/icon-button-root.d.ts +1 -1
- package/dist/image/root/image-root.d.ts +23 -2
- package/dist/image/root/image-root.js +23 -4
- package/dist/input/root/input-root.d.ts +62 -9
- package/dist/input/root/input-root.js +61 -5
- package/dist/kbd/root/kbd-root.d.ts +26 -11
- package/dist/kbd/root/kbd-root.js +35 -38
- package/dist/kbd/shortcut.d.ts +18 -0
- package/dist/kbd/shortcut.js +35 -0
- package/dist/legend/hidden-series.d.ts +8 -0
- package/dist/legend/hidden-series.js +13 -0
- package/dist/legend/root/legend-root.d.ts +63 -0
- package/dist/legend/root/legend-root.js +61 -7
- package/dist/lightbox/item/lightbox-item.d.ts +17 -1
- package/dist/lightbox/item/lightbox-item.js +10 -1
- package/dist/lightbox/root/lightbox-root.d.ts +77 -6
- package/dist/lightbox/root/lightbox-root.js +116 -5
- package/dist/line-chart/root/line-chart-root.d.ts +29 -4
- package/dist/line-chart/root/line-chart-root.js +58 -17
- package/dist/list/item/list-item.d.ts +11 -5
- package/dist/list/item/list-item.js +5 -6
- package/dist/listbox/range.d.ts +17 -0
- package/dist/listbox/range.js +5 -0
- package/dist/listbox/root/listbox-root.d.ts +184 -4
- package/dist/listbox/root/listbox-root.js +229 -23
- package/dist/loader/busy.d.ts +17 -0
- package/dist/loader/busy.js +24 -0
- package/dist/loader/root/loader-root.d.ts +37 -0
- package/dist/loader/root/loader-root.js +52 -3
- package/dist/map/root/map-root.d.ts +19 -4
- package/dist/map/root/map-root.js +36 -7
- package/dist/megamenu/root/megamenu-root.d.ts +10 -1
- package/dist/megamenu/root/megamenu-root.js +10 -1
- package/dist/menu/item/menu-item.d.ts +41 -12
- package/dist/menu/item/menu-item.js +46 -3
- package/dist/menu/root/menu-root.d.ts +32 -2
- package/dist/menu/root/menu-root.js +48 -8
- package/dist/meter/root/meter-root.d.ts +13 -0
- package/dist/meter/root/meter-root.js +24 -5
- package/dist/navigation/root/navigation-root.d.ts +10 -2
- package/dist/navigation/root/navigation-root.js +13 -2
- package/dist/notifications/feed-keys.d.ts +10 -0
- package/dist/notifications/feed-keys.js +14 -0
- package/dist/notifications/group/notification-group.d.ts +1 -0
- package/dist/notifications/notification/notification.d.ts +29 -0
- package/dist/notifications/notification/notification.js +51 -3
- package/dist/notifications/root/notifications-root.d.ts +49 -0
- package/dist/notifications/root/notifications-root.js +76 -2
- package/dist/number-input/root/number-input-root.d.ts +109 -7
- package/dist/number-input/root/number-input-root.js +109 -21
- package/dist/object-inspector/root/object-inspector-root.d.ts +49 -5
- package/dist/object-inspector/root/object-inspector-root.js +92 -12
- package/dist/option/root/option-root.d.ts +58 -6
- package/dist/option/root/option-root.js +35 -5
- package/dist/outline/root/outline-root.d.ts +13 -2
- package/dist/outline/root/outline-root.js +4 -2
- package/dist/pagination/root/pagination-root.d.ts +19 -1
- package/dist/pagination/root/pagination-root.js +49 -9
- package/dist/pagination/size/pagination-size.d.ts +13 -3
- package/dist/pagination/size/pagination-size.js +7 -0
- package/dist/pin-input/format.d.ts +7 -0
- package/dist/pin-input/format.js +16 -0
- package/dist/pin-input/root/pin-input-root.d.ts +37 -0
- package/dist/pin-input/root/pin-input-root.js +48 -7
- package/dist/popover/root/popover-root.d.ts +78 -3
- package/dist/popover/root/popover-root.js +74 -5
- package/dist/progress/root/progress-root.d.ts +23 -1
- package/dist/progress/root/progress-root.js +40 -10
- package/dist/qr-code/export.d.ts +31 -0
- package/dist/qr-code/export.js +10 -0
- package/dist/qr-code/root/qr-code-root.d.ts +45 -0
- package/dist/qr-code/root/qr-code-root.js +78 -3
- package/dist/radio/group/radio-group.d.ts +64 -0
- package/dist/radio/group/radio-group.js +66 -12
- package/dist/radio/root/radio-root.d.ts +8 -5
- package/dist/radio/root/radio-root.js +1 -2
- package/dist/rating/root/rating-root.d.ts +49 -1
- package/dist/rating/root/rating-root.js +69 -10
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +17 -3
- package/dist/scatter-chart/root/scatter-chart-root.js +40 -14
- package/dist/select/root/select-root.d.ts +93 -3
- package/dist/select/root/select-root.js +111 -13
- package/dist/skeleton/root/skeleton-root.d.ts +39 -3
- package/dist/skeleton/root/skeleton-root.js +33 -4
- package/dist/skip-link/root/skip-link-root.d.ts +10 -0
- package/dist/skip-link/root/skip-link-root.js +15 -1
- package/dist/slider/root/slider-root.d.ts +59 -2
- package/dist/slider/root/slider-root.js +82 -8
- package/dist/sparkline/root/sparkline-root.d.ts +9 -10
- package/dist/speed-dial/item/speed-dial-item.d.ts +11 -5
- package/dist/speed-dial/item/speed-dial-item.js +7 -2
- package/dist/speed-dial/root/speed-dial-root.d.ts +15 -4
- package/dist/speed-dial/root/speed-dial-root.js +19 -5
- package/dist/splitter/root/splitter-root.d.ts +28 -6
- package/dist/splitter/root/splitter-root.js +35 -1
- package/dist/stat/root/stat-root.d.ts +9 -1
- package/dist/stat/root/stat-root.js +15 -2
- package/dist/steps/root/steps-root.js +1 -1
- package/dist/steps/step/step.d.ts +1 -0
- package/dist/steps/step/step.js +1 -1
- package/dist/switch/root/switch-root.d.ts +14 -2
- package/dist/switch/root/switch-root.js +7 -1
- package/dist/table/cell/table-cell.d.ts +24 -4
- package/dist/table/cell/table-cell.js +21 -1
- package/dist/table/column/table-column.d.ts +32 -6
- package/dist/table/column/table-column.js +36 -6
- package/dist/table/root/table-root.d.ts +94 -3
- package/dist/table/root/table-root.js +128 -5
- package/dist/table/row/table-row.d.ts +7 -0
- package/dist/table/row/table-row.js +9 -1
- package/dist/tabs/root/tabs-root.d.ts +6 -1
- package/dist/tabs/root/tabs-root.js +6 -2
- package/dist/tag/group/tag-group.d.ts +107 -0
- package/dist/tag/group/tag-group.js +157 -0
- package/dist/tag/index.d.ts +1 -0
- package/dist/tag/index.js +1 -0
- package/dist/tag/root/tag-root.d.ts +83 -1
- package/dist/tag/root/tag-root.js +87 -17
- package/dist/tag/selection.d.ts +10 -0
- package/dist/tag/selection.js +12 -0
- package/dist/textarea/grow.d.ts +22 -0
- package/dist/textarea/grow.js +20 -0
- package/dist/textarea/root/textarea-root.d.ts +13 -0
- package/dist/textarea/root/textarea-root.js +10 -2
- package/dist/time-input/root/time-input-root.d.ts +71 -6
- package/dist/time-input/root/time-input-root.js +110 -44
- package/dist/time-picker/root/time-picker-root.d.ts +155 -26
- package/dist/time-picker/root/time-picker-root.js +192 -63
- package/dist/toast/hotkey.d.ts +22 -0
- package/dist/toast/hotkey.js +23 -0
- package/dist/toast/item/toast-item.d.ts +16 -1
- package/dist/toast/item/toast-item.js +41 -13
- package/dist/toast/root/toast-root.d.ts +105 -8
- package/dist/toast/root/toast-root.js +209 -4
- package/dist/toggle/group/toggle-group.d.ts +95 -16
- package/dist/toggle/group/toggle-group.js +99 -13
- package/dist/toggle/root/toggle-root.d.ts +26 -11
- package/dist/toggle/root/toggle-root.js +14 -6
- package/dist/toolbar/root/toolbar-root.d.ts +55 -15
- package/dist/toolbar/root/toolbar-root.js +99 -16
- package/dist/tooltip/focus-target.d.ts +6 -0
- package/dist/tooltip/focus-target.js +9 -0
- package/dist/tooltip/root/tooltip-root.d.ts +73 -15
- package/dist/tooltip/root/tooltip-root.js +96 -7
- package/dist/tour/naming.d.ts +30 -0
- package/dist/tour/naming.js +10 -0
- package/dist/tour/root/tour-root.d.ts +67 -3
- package/dist/tour/root/tour-root.js +105 -17
- package/dist/tour/stop/tour-stop.d.ts +65 -3
- package/dist/tour/stop/tour-stop.js +61 -11
- package/dist/tour/wait.d.ts +11 -0
- package/dist/tour/wait.js +19 -0
- package/dist/tree/item/tree-item.d.ts +21 -5
- package/dist/tree/item/tree-item.js +14 -4
- package/dist/tree/root/tree-root.d.ts +29 -5
- package/dist/tree/root/tree-root.js +64 -8
- package/dist/trend/root/trend-root.d.ts +36 -1
- package/dist/trend/root/trend-root.js +41 -15
- package/dist/video/root/keys.d.ts +5 -0
- package/dist/video/root/keys.js +13 -1
- package/dist/video/root/video-root.d.ts +19 -0
- package/dist/video/root/video-root.js +48 -4
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +20 -2
- package/dist/video-playlist/menu/video-playlist-menu.js +27 -5
- package/dist/video-playlist/root/video-playlist-root.js +6 -3
- package/dist/virtual-list/root/virtual-list-root.d.ts +52 -4
- package/dist/virtual-list/root/virtual-list-root.js +103 -21
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +9140 -1149
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +2089 -267
|
@@ -4,10 +4,11 @@ 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, fillTemplate, formatNumbers, HelixActivateEvent, HelixElement, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, hostAria, KeyboardNavigationController, MixinViewport, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, fillTemplate, formatNumbers, HelixActivateEvent, HelixBeforeChangeEvent, HelixBeforeToggleEvent, HelixElement, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, hostAria, KeyboardNavigationController, MixinViewport, requestChange, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { buildings, cloudRain, dotsNine, leaf, mountains, path, polygon, stack, target, } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
|
+
import { live } from 'lit/directives/live.js';
|
|
11
12
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
13
|
const MAP_TYPES = ['standard', 'hybrid', 'satellite'];
|
|
13
14
|
const iconOf = (layer) => {
|
|
@@ -205,10 +206,37 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
|
|
|
205
206
|
: this.standardLabel;
|
|
206
207
|
}
|
|
207
208
|
showLayers(layers, shown) {
|
|
208
|
-
|
|
209
|
-
|
|
209
|
+
const first = layers[0];
|
|
210
|
+
if (!first) {
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
requestChange({
|
|
214
|
+
apply: () => {
|
|
215
|
+
for (const layer of layers) {
|
|
216
|
+
layer.hidden = !shown;
|
|
217
|
+
}
|
|
218
|
+
this.requestUpdate();
|
|
219
|
+
},
|
|
220
|
+
event: (checked) => new HelixBeforeToggleEvent({ checked }),
|
|
221
|
+
host: first,
|
|
222
|
+
next: shown,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
chooseMapType(type) {
|
|
226
|
+
const applied = requestChange({
|
|
227
|
+
apply: (value) => {
|
|
228
|
+
this.mapType = value === 'standard' ? undefined : value;
|
|
229
|
+
},
|
|
230
|
+
event: (value) => new HelixBeforeChangeEvent({ value }),
|
|
231
|
+
host: this,
|
|
232
|
+
next: type,
|
|
233
|
+
});
|
|
234
|
+
if (applied) {
|
|
235
|
+
this.dispatchEvent(new Event('change', { bubbles: true }));
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
this.requestUpdate();
|
|
210
239
|
}
|
|
211
|
-
this.requestUpdate();
|
|
212
240
|
}
|
|
213
241
|
get layerEntries() {
|
|
214
242
|
const entries = [];
|
|
@@ -382,9 +410,10 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
|
|
|
382
410
|
<input
|
|
383
411
|
type="radio"
|
|
384
412
|
name="map-type"
|
|
385
|
-
.checked=${chosen === type}
|
|
386
|
-
@change=${() => {
|
|
387
|
-
|
|
413
|
+
.checked=${live(chosen === type)}
|
|
414
|
+
@change=${(event) => {
|
|
415
|
+
event.stopPropagation();
|
|
416
|
+
this.chooseMapType(type);
|
|
388
417
|
}}
|
|
389
418
|
/>
|
|
390
419
|
${preview
|
|
@@ -31,7 +31,7 @@ declare const HelixHeadlessMegamenu_base: (new (...args: any[]) => import("@fusi
|
|
|
31
31
|
*
|
|
32
32
|
* @event {HelixBeforeCloseEvent} helix-before-close - The panel is about to close. Cancelable.
|
|
33
33
|
* @event {HelixBeforeOpenEvent} helix-before-open - The panel is about to open. Cancelable.
|
|
34
|
-
* @event {
|
|
34
|
+
* @event {ToggleEvent} toggle - The panel opened or closed. Carries `newState` and `oldState`.
|
|
35
35
|
*
|
|
36
36
|
* @csspart surface - The floating panel that opens.
|
|
37
37
|
* @csspart trigger - The default trigger button, shown when the `trigger` slot is empty.
|
|
@@ -194,6 +194,15 @@ export declare class HelixHeadlessMegamenu extends HelixHeadlessMegamenu_base {
|
|
|
194
194
|
private readonly handlePointerDown;
|
|
195
195
|
private readonly handlePointerEnter;
|
|
196
196
|
private readonly handlePointerLeave;
|
|
197
|
+
/**
|
|
198
|
+
* Closes the panel when keyboard focus leaves it for the page.
|
|
199
|
+
*
|
|
200
|
+
* Only when focus went somewhere: a `relatedTarget` of null is focus leaving
|
|
201
|
+
* the document, such as a switch to another window, and a reader who comes
|
|
202
|
+
* back expects the panel as they left it. `requestOpen` rather than `close`,
|
|
203
|
+
* because focus has already gone where the reader sent it.
|
|
204
|
+
*/
|
|
205
|
+
private readonly handleFocusOut;
|
|
197
206
|
private readonly handleTriggerClick;
|
|
198
207
|
/**
|
|
199
208
|
* Shuts the panel when a reader takes one of the destinations in it.
|
|
@@ -5,7 +5,7 @@ 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, HelixElement, MixinControllerOpen, PopoverController, tellDisclosure, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { anchorElement, customElement, deepContains, 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;
|
|
@@ -57,6 +57,13 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
57
57
|
this.requestOpen(false);
|
|
58
58
|
});
|
|
59
59
|
};
|
|
60
|
+
this.handleFocusOut = (event) => {
|
|
61
|
+
const next = event.relatedTarget;
|
|
62
|
+
if (!this.open || next === null || deepContains(this, next)) {
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
this.requestOpen(false);
|
|
66
|
+
};
|
|
60
67
|
this.handleTriggerClick = (event) => {
|
|
61
68
|
this.stop();
|
|
62
69
|
if (this.openOn !== 'hover') {
|
|
@@ -154,6 +161,7 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
154
161
|
this.addEventListener('click', this.handleContentClick);
|
|
155
162
|
this.addEventListener('pointerenter', this.handlePointerEnter);
|
|
156
163
|
this.addEventListener('pointerleave', this.handlePointerLeave);
|
|
164
|
+
this.addEventListener('focusout', this.handleFocusOut);
|
|
157
165
|
}
|
|
158
166
|
disconnectedCallback() {
|
|
159
167
|
super.disconnectedCallback();
|
|
@@ -164,6 +172,7 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
164
172
|
this.removeEventListener('click', this.handleContentClick);
|
|
165
173
|
this.removeEventListener('pointerenter', this.handlePointerEnter);
|
|
166
174
|
this.removeEventListener('pointerleave', this.handlePointerLeave);
|
|
175
|
+
this.removeEventListener('focusout', this.handleFocusOut);
|
|
167
176
|
this.stop();
|
|
168
177
|
if (showing === this) {
|
|
169
178
|
showing = undefined;
|
|
@@ -14,6 +14,11 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
14
14
|
* only one can be on. A row that opens a page keeps `menuitem` and sets
|
|
15
15
|
* `aria-haspopup`.
|
|
16
16
|
*
|
|
17
|
+
* Choosing a choice row checks or unchecks it before `helix-select` is sent,
|
|
18
|
+
* so a listener reads the new `checked`. An `exclusive` row turns on and turns
|
|
19
|
+
* off the `exclusive` rows next to it. Cancel `helix-before-toggle` to keep a
|
|
20
|
+
* row as it is and set `checked` yourself.
|
|
21
|
+
*
|
|
17
22
|
* The menu sets whether the row's page is showing as a property, never as an
|
|
18
23
|
* attribute. An attribute written onto your element after it upgrades causes a
|
|
19
24
|
* hydration mismatch.
|
|
@@ -27,12 +32,15 @@ import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
|
27
32
|
* @slot start - Content before the label, such as an icon.
|
|
28
33
|
* @slot submenu - The rows of a submenu that this row opens.
|
|
29
34
|
*
|
|
35
|
+
* @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.
|
|
30
36
|
* @event {HelixSelectEvent} helix-select - The row was chosen. Cancelable: cancel it to keep the menu open.
|
|
31
37
|
*
|
|
32
38
|
* @csspart item - The row, which is an `<a>` where `href` is set.
|
|
33
39
|
* @csspart mark - The trailing mark: a check mark when the row is checked, or a caret
|
|
34
40
|
* when it opens a submenu. A row never shows both, so they share one column.
|
|
35
41
|
* @csspart start - The leading column that holds the `start` slot. It is always rendered.
|
|
42
|
+
*
|
|
43
|
+
* @cssstate checked - The row is checked.
|
|
36
44
|
*/
|
|
37
45
|
export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
38
46
|
/**
|
|
@@ -45,10 +53,16 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
45
53
|
* thing they are not.
|
|
46
54
|
*
|
|
47
55
|
* `checked` implies it, so a row that is on never has to say both.
|
|
56
|
+
*
|
|
57
|
+
* Choosing the row checks or unchecks it, after a `helix-before-toggle` that
|
|
58
|
+
* you can cancel.
|
|
48
59
|
*/
|
|
49
60
|
checkable: boolean;
|
|
50
61
|
/**
|
|
51
62
|
* Whether the row is checked.
|
|
63
|
+
*
|
|
64
|
+
* The row changes it when it is chosen. Not reflected: the attribute is the
|
|
65
|
+
* state you start the row in, and `:state(checked)` carries the current one.
|
|
52
66
|
*/
|
|
53
67
|
checked: boolean;
|
|
54
68
|
/**
|
|
@@ -66,11 +80,11 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
66
80
|
/**
|
|
67
81
|
* Whether only one row in its set can be checked at a time.
|
|
68
82
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
83
|
+
* The set is the run of `exclusive` rows next to this one, up to the first
|
|
84
|
+
* element that is not one, such as a divider. Choosing a row in it checks
|
|
85
|
+
* that row and unchecks the others. Choosing the row that is checked leaves
|
|
86
|
+
* it checked. `menuitemradio` tells a reader which kind of set they are in,
|
|
87
|
+
* where `menuitemcheckbox` says every row is independent.
|
|
74
88
|
*
|
|
75
89
|
* Meaningless without `checkable`, since a row that cannot be ticked is not
|
|
76
90
|
* one of a set of anything.
|
|
@@ -225,16 +239,31 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
225
239
|
/** Chooses the row, the same as pressing it. */
|
|
226
240
|
select(): void;
|
|
227
241
|
/**
|
|
228
|
-
* Whether the row has focus, which
|
|
242
|
+
* Whether the row has focus, which makes it the row the keyboard is on.
|
|
243
|
+
*
|
|
244
|
+
* `Option` calls the same thing `active`. A menu holds no answer the way a
|
|
245
|
+
* radio group does, only a row the reader has walked to, so focus is the
|
|
246
|
+
* whole of what "the current one" can mean here. Read from the shadow root
|
|
247
|
+
* rather than kept as state, because focus moves for reasons this element is
|
|
248
|
+
* not told about: a press, a Tab, the drilldown putting the reader on the
|
|
249
|
+
* first row of a page it has just opened.
|
|
250
|
+
*/
|
|
251
|
+
get active(): boolean;
|
|
252
|
+
/**
|
|
253
|
+
* Whether the row has focus, the same as `active`.
|
|
229
254
|
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
* one" can mean here. Read from the shadow root rather than kept as state,
|
|
233
|
-
* because focus moves for reasons this element is not told about: a press, a
|
|
234
|
-
* Tab, the drilldown putting the reader on the first row of a page it has
|
|
235
|
-
* just opened.
|
|
255
|
+
* @deprecated Read `active`. Everywhere else in the library `selected` means
|
|
256
|
+
* chosen out of a set, and a menu row is never chosen that way.
|
|
236
257
|
*/
|
|
237
258
|
get selected(): boolean;
|
|
259
|
+
/**
|
|
260
|
+
* Checks or unchecks a choice row.
|
|
261
|
+
*
|
|
262
|
+
* An `exclusive` row only turns on, and turning on turns its set off.
|
|
263
|
+
*/
|
|
264
|
+
private tick;
|
|
265
|
+
/** The other `exclusive` rows in this row's run of siblings. */
|
|
266
|
+
private exclusivePeers;
|
|
238
267
|
private choose;
|
|
239
268
|
private readonly handleClick;
|
|
240
269
|
/**
|
|
@@ -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, HelixElement, HelixSelectEvent } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, deepActiveElement, HelixBeforeToggleEvent, HelixElement, HelixSelectEvent, 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';
|
|
@@ -58,6 +58,7 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
58
58
|
}
|
|
59
59
|
willUpdate(changed) {
|
|
60
60
|
super.willUpdate(changed);
|
|
61
|
+
this.toggleState('checked', this.checked);
|
|
61
62
|
if (!this.childrenKnown) {
|
|
62
63
|
return;
|
|
63
64
|
}
|
|
@@ -78,13 +79,55 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
78
79
|
select() {
|
|
79
80
|
this.choose();
|
|
80
81
|
}
|
|
82
|
+
get active() {
|
|
83
|
+
const active = deepActiveElement();
|
|
84
|
+
return active !== null && active.getRootNode() === this.renderRoot;
|
|
85
|
+
}
|
|
81
86
|
get selected() {
|
|
82
|
-
return this.
|
|
87
|
+
return this.active;
|
|
88
|
+
}
|
|
89
|
+
tick() {
|
|
90
|
+
if (!(this.checkable || this.checked) || this.hasSubmenu) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const next = this.exclusive ? true : !this.checked;
|
|
94
|
+
if (next === this.checked) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const applied = requestChange({
|
|
98
|
+
apply: (checked) => {
|
|
99
|
+
this.checked = checked;
|
|
100
|
+
},
|
|
101
|
+
event: (checked) => new HelixBeforeToggleEvent({ checked }),
|
|
102
|
+
host: this,
|
|
103
|
+
next,
|
|
104
|
+
});
|
|
105
|
+
if (applied && this.exclusive) {
|
|
106
|
+
for (const peer of this.exclusivePeers()) {
|
|
107
|
+
peer.checked = false;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exclusivePeers() {
|
|
112
|
+
const peers = [];
|
|
113
|
+
const inSet = (node) => node !== null &&
|
|
114
|
+
node.isMenuItem === true &&
|
|
115
|
+
node.exclusive &&
|
|
116
|
+
node.slot === this.slot;
|
|
117
|
+
for (const step of ['previousElementSibling', 'nextElementSibling']) {
|
|
118
|
+
let node = this[step];
|
|
119
|
+
while (inSet(node)) {
|
|
120
|
+
peers.push(node);
|
|
121
|
+
node = node[step];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return peers;
|
|
83
125
|
}
|
|
84
126
|
choose() {
|
|
85
127
|
if (this.disabled) {
|
|
86
128
|
return;
|
|
87
129
|
}
|
|
130
|
+
this.tick();
|
|
88
131
|
this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
|
|
89
132
|
}
|
|
90
133
|
render() {
|
|
@@ -155,7 +198,7 @@ __decorate([
|
|
|
155
198
|
property({ reflect: true, type: Boolean })
|
|
156
199
|
], HelixHeadlessMenuItem.prototype, "checkable", void 0);
|
|
157
200
|
__decorate([
|
|
158
|
-
property({
|
|
201
|
+
property({ type: Boolean })
|
|
159
202
|
], HelixHeadlessMenuItem.prototype, "checked", void 0);
|
|
160
203
|
__decorate([
|
|
161
204
|
property({ reflect: true, type: Boolean })
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HelixElement, KeyboardNavigationController, type Placement } from '@fusion.dev/helix-core';
|
|
1
|
+
import { AriaForwardController, HelixElement, KeyboardNavigationController, type Placement } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
declare const HelixHeadlessMenu_base: (new (...args: any[]) => import("@fusion.dev/helix-core").CollectionElement) & (new (...args: any[]) => import("@fusion.dev/helix-core").MixinControllerOpenInterface) & typeof HelixElement;
|
|
4
4
|
/**
|
|
@@ -9,6 +9,12 @@ declare const HelixHeadlessMenu_base: (new (...args: any[]) => import("@fusion.d
|
|
|
9
9
|
* menu renders its surface in the top layer with the popover API, so an
|
|
10
10
|
* ancestor with `overflow: hidden` does not clip it and it needs no `z-index`.
|
|
11
11
|
*
|
|
12
|
+
* Slot a `helix-button` or `helix-icon-button` as the trigger, and the menu
|
|
13
|
+
* tells it that it opens a menu and whether the menu is open. A plain
|
|
14
|
+
* `<button>` can only be told by writing attributes onto your markup, which
|
|
15
|
+
* the menu does not do, so give it `aria-haspopup="menu"` and set its
|
|
16
|
+
* `aria-expanded` from the `toggle` event.
|
|
17
|
+
*
|
|
12
18
|
* Submenus drill down. A submenu replaces the panel's content, and a back row
|
|
13
19
|
* returns to the previous page. One panel avoids the diagonal pointer path that
|
|
14
20
|
* side-by-side panels need, stays inside a narrow window, and works on touch
|
|
@@ -30,7 +36,7 @@ declare const HelixHeadlessMenu_base: (new (...args: any[]) => import("@fusion.d
|
|
|
30
36
|
* @event {HelixBeforeCloseEvent} helix-before-close - The menu is about to close. Cancelable: cancel it to keep it open.
|
|
31
37
|
* @event {HelixBeforeOpenEvent} helix-before-open - The menu is about to open. Cancelable: cancel it to keep it closed.
|
|
32
38
|
* @event {HelixSelectEvent} helix-select - An item was chosen. Cancelable: cancel it to keep the menu open.
|
|
33
|
-
* @event {
|
|
39
|
+
* @event {ToggleEvent} toggle - The menu opened or closed. The event carries `newState` and `oldState`.
|
|
34
40
|
*
|
|
35
41
|
* @csspart back - The control that returns from a submenu.
|
|
36
42
|
* @csspart back-mark - The glyph on the back control of a submenu.
|
|
@@ -53,6 +59,10 @@ export declare class HelixHeadlessMenu extends HelixHeadlessMenu_base {
|
|
|
53
59
|
backLabel: string;
|
|
54
60
|
/**
|
|
55
61
|
* Accessible name for the surface.
|
|
62
|
+
*
|
|
63
|
+
* Empty by default, which names the surface by its trigger, so a menu opened
|
|
64
|
+
* from "Actions" is announced as "Actions". An `aria-label` or
|
|
65
|
+
* `aria-labelledby` on the host names it too, and wins over both.
|
|
56
66
|
*/
|
|
57
67
|
label: string;
|
|
58
68
|
/**
|
|
@@ -92,6 +102,8 @@ export declare class HelixHeadlessMenu extends HelixHeadlessMenu_base {
|
|
|
92
102
|
* menu that drills, so those keys are spoken for here rather than unhandled.
|
|
93
103
|
*/
|
|
94
104
|
protected readonly keys: KeyboardNavigationController;
|
|
105
|
+
/** Carries a host `aria-label` and `aria-labelledby` to the surface. */
|
|
106
|
+
protected readonly aria: AriaForwardController;
|
|
95
107
|
private readonly panel;
|
|
96
108
|
/**
|
|
97
109
|
* Tells a slotted trigger the disclosure state, by property.
|
|
@@ -108,6 +120,8 @@ export declare class HelixHeadlessMenu extends HelixHeadlessMenu_base {
|
|
|
108
120
|
private get items();
|
|
109
121
|
/** Opens the menu. */
|
|
110
122
|
show(): void;
|
|
123
|
+
/** Opens the menu with focus on its first or its last row. */
|
|
124
|
+
private openAt;
|
|
111
125
|
/** Closes the menu and returns it to its first page. */
|
|
112
126
|
hide(): void;
|
|
113
127
|
/** Shows an item's submenu in place of the current page. */
|
|
@@ -124,10 +138,26 @@ export declare class HelixHeadlessMenu extends HelixHeadlessMenu_base {
|
|
|
124
138
|
*/
|
|
125
139
|
private readonly handleFocusIn;
|
|
126
140
|
private readonly handleKeydown;
|
|
141
|
+
/**
|
|
142
|
+
* Down and Up on the trigger open the menu on its first and its last row.
|
|
143
|
+
*
|
|
144
|
+
* Everything else passes through. Escape in particular is not this element's
|
|
145
|
+
* while the menu is closed, so a dialog around the menu still closes on it.
|
|
146
|
+
*/
|
|
147
|
+
private handleClosedKeydown;
|
|
127
148
|
private readonly handleTriggerClick;
|
|
128
149
|
connectedCallback(): void;
|
|
129
150
|
disconnectedCallback(): void;
|
|
130
151
|
protected updated(changed: PropertyValues): void;
|
|
152
|
+
/**
|
|
153
|
+
* Names the surface by its trigger, where nothing else names it.
|
|
154
|
+
*
|
|
155
|
+
* By element reference, which is the one direction that crosses: the surface
|
|
156
|
+
* is in this shadow root and the trigger is in the tree around it. A host
|
|
157
|
+
* `aria-labelledby` is carried down by `aria`, and a host `aria-label` or
|
|
158
|
+
* `label` is a name of its own, so each of them clears this reference.
|
|
159
|
+
*/
|
|
160
|
+
private nameSurface;
|
|
131
161
|
/**
|
|
132
162
|
* Says whether the page showing reserves a column either side of its labels.
|
|
133
163
|
*
|
|
@@ -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 { anchorElement, customElement, DrilldownController, HelixElement, inlineStep, KeyboardNavigationController, MixinCollection, MixinControllerOpen, PopoverController, scrollItemIntoView, tellDisclosure, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, anchorElement, customElement, DrilldownController, deepActiveElement, deepContains, HelixElement, inlineStep, KeyboardNavigationController, MixinCollection, MixinControllerOpen, PopoverController, scrollItemIntoView, slottedWords, tellDisclosure, } 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';
|
|
@@ -13,7 +13,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
13
13
|
constructor() {
|
|
14
14
|
super(...arguments);
|
|
15
15
|
this.backLabel = 'Back';
|
|
16
|
-
this.label = '
|
|
16
|
+
this.label = '';
|
|
17
17
|
this.offset = 4;
|
|
18
18
|
this.placement = 'bottom-start';
|
|
19
19
|
this.drilldown = new DrilldownController(this, {
|
|
@@ -22,9 +22,14 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
22
22
|
slot: 'submenu',
|
|
23
23
|
});
|
|
24
24
|
this.keys = new KeyboardNavigationController(this, {
|
|
25
|
-
items: () => this.items,
|
|
25
|
+
items: () => (this.open ? this.items : []),
|
|
26
26
|
reserved: () => ['ArrowLeft', 'ArrowRight'],
|
|
27
27
|
selects: () => false,
|
|
28
|
+
typeahead: (item) => slottedWords(item, ['']),
|
|
29
|
+
});
|
|
30
|
+
this.aria = new AriaForwardController(this, {
|
|
31
|
+
label: true,
|
|
32
|
+
target: () => this.partNamed('surface'),
|
|
28
33
|
});
|
|
29
34
|
this.panel = new PopoverController(this, {
|
|
30
35
|
anchor: () => this.trigger,
|
|
@@ -61,8 +66,12 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
61
66
|
scrollItemIntoView(item, { padding: 4, ...(surface ? { scroller: surface } : {}) });
|
|
62
67
|
};
|
|
63
68
|
this.handleKeydown = (event) => {
|
|
69
|
+
if (!this.open) {
|
|
70
|
+
this.handleClosedKeydown(event);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
64
73
|
const items = this.items;
|
|
65
|
-
const at = items.
|
|
74
|
+
const at = items.findIndex((item) => item.active);
|
|
66
75
|
const along = inlineStep(this, event.key);
|
|
67
76
|
if (event.key === 'Escape') {
|
|
68
77
|
event.stopPropagation();
|
|
@@ -94,7 +103,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
94
103
|
}
|
|
95
104
|
tellTrigger() {
|
|
96
105
|
const slot = this.renderRoot?.querySelector('slot[name="trigger"]');
|
|
97
|
-
tellDisclosure(slot?.assignedElements({ flatten:
|
|
106
|
+
tellDisclosure(slot?.assignedElements({ flatten: true })[0], this.open, 'menu');
|
|
98
107
|
}
|
|
99
108
|
get trigger() {
|
|
100
109
|
return anchorElement(this.renderRoot?.querySelector('slot[name="trigger"]'), this);
|
|
@@ -103,11 +112,15 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
103
112
|
return this.drilldown.rows.filter((row) => !row.disabled);
|
|
104
113
|
}
|
|
105
114
|
show() {
|
|
115
|
+
this.openAt('first');
|
|
116
|
+
}
|
|
117
|
+
openAt(end) {
|
|
106
118
|
if (this.open || !this.requestOpen(true)) {
|
|
107
119
|
return;
|
|
108
120
|
}
|
|
109
121
|
this.updateComplete.then(() => {
|
|
110
|
-
this.items
|
|
122
|
+
const items = this.items;
|
|
123
|
+
(end === 'first' ? items[0] : items[items.length - 1])?.focus();
|
|
111
124
|
});
|
|
112
125
|
}
|
|
113
126
|
hide() {
|
|
@@ -116,7 +129,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
116
129
|
}
|
|
117
130
|
this.panel.hide();
|
|
118
131
|
this.drilldown.reset();
|
|
119
|
-
if (this
|
|
132
|
+
if (deepContains(this, deepActiveElement())) {
|
|
120
133
|
this.trigger.focus();
|
|
121
134
|
}
|
|
122
135
|
}
|
|
@@ -135,6 +148,18 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
135
148
|
this.drilldown.back();
|
|
136
149
|
this.updateComplete.then(() => leaving?.focus());
|
|
137
150
|
}
|
|
151
|
+
handleClosedKeydown(event) {
|
|
152
|
+
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
const slot = this.renderRoot?.querySelector('slot[name="trigger"]');
|
|
156
|
+
const triggers = slot?.assignedElements({ flatten: true }) ?? [];
|
|
157
|
+
if (!event.composedPath().some((node) => triggers.includes(node))) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
event.preventDefault();
|
|
161
|
+
this.openAt(event.key === 'ArrowDown' ? 'first' : 'last');
|
|
162
|
+
}
|
|
138
163
|
connectedCallback() {
|
|
139
164
|
super.connectedCallback();
|
|
140
165
|
this.addEventListener('helix-select', this.handleSelect, true);
|
|
@@ -159,6 +184,21 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
159
184
|
}
|
|
160
185
|
this.toggleState('drilled', !this.drilldown.atRoot);
|
|
161
186
|
this.markColumns();
|
|
187
|
+
this.nameSurface();
|
|
188
|
+
}
|
|
189
|
+
nameSurface() {
|
|
190
|
+
const surface = this.partNamed('surface');
|
|
191
|
+
if (!surface || !('ariaLabelledByElements' in surface)) {
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
if (this.hasAttribute('aria-labelledby')) {
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
const trigger = this.renderRoot
|
|
198
|
+
?.querySelector('slot[name="trigger"]')
|
|
199
|
+
?.assignedElements({ flatten: true })[0];
|
|
200
|
+
const named = this.label !== '' || this.hasAttribute('aria-label');
|
|
201
|
+
surface.ariaLabelledByElements = trigger && !named ? [trigger] : null;
|
|
162
202
|
}
|
|
163
203
|
markColumns() {
|
|
164
204
|
const rows = this.drilldown.rows;
|
|
@@ -183,7 +223,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
183
223
|
popover="manual"
|
|
184
224
|
role="menu"
|
|
185
225
|
aria-busy=${this.loading ? 'true' : nothing}
|
|
186
|
-
aria-label=${this.label}
|
|
226
|
+
aria-label=${this.label || nothing}
|
|
187
227
|
data-drilled=${this.drilldown.atRoot ? nothing : ''}
|
|
188
228
|
?hidden=${!this.open}
|
|
189
229
|
>
|
|
@@ -22,6 +22,8 @@ export type MeterBand = 'fair' | 'good' | 'poor';
|
|
|
22
22
|
* @aliases Gauge, Level, Capacity
|
|
23
23
|
* @documentation https://fusion.dev/helix/components/meter
|
|
24
24
|
*
|
|
25
|
+
* @slot label - A visible label. Its words name the meter in place of `label`.
|
|
26
|
+
*
|
|
25
27
|
* @csspart groove - The unfilled circle, in `ring` and `arc`.
|
|
26
28
|
* @csspart indicator - The part of the track the value fills.
|
|
27
29
|
* @csspart indicator-fair - The fill while the reading is in a band next to the good band. Set alongside `indicator`.
|
|
@@ -77,8 +79,17 @@ export declare class HelixHeadlessMeter extends HelixElement {
|
|
|
77
79
|
high?: number;
|
|
78
80
|
/**
|
|
79
81
|
* Accessible name for the reading.
|
|
82
|
+
*
|
|
83
|
+
* A visible label in the `label` slot names it instead, with the words it
|
|
84
|
+
* shows, so the name and the label cannot disagree.
|
|
80
85
|
*/
|
|
81
86
|
label: string;
|
|
87
|
+
/**
|
|
88
|
+
* The locale the percentage is written in, such as `fr` for `72 %`.
|
|
89
|
+
*
|
|
90
|
+
* Absent uses the runtime's own.
|
|
91
|
+
*/
|
|
92
|
+
locale: string;
|
|
82
93
|
/**
|
|
83
94
|
* Top of the low band.
|
|
84
95
|
*
|
|
@@ -212,6 +223,8 @@ export declare class HelixHeadlessMeter extends HelixElement {
|
|
|
212
223
|
* where the arc starts.
|
|
213
224
|
*/
|
|
214
225
|
private renderRound;
|
|
226
|
+
/** A label's words changed, so the name is written again. */
|
|
227
|
+
private readonly renamed;
|
|
215
228
|
protected render(): TemplateResult;
|
|
216
229
|
}
|
|
217
230
|
declare global {
|
|
@@ -4,18 +4,34 @@ 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 } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, 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 percents = new Map();
|
|
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
22
|
let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
|
|
11
23
|
constructor() {
|
|
12
24
|
super(...arguments);
|
|
13
25
|
this.label = 'Meter';
|
|
26
|
+
this.locale = '';
|
|
14
27
|
this.max = 100;
|
|
15
28
|
this.min = 0;
|
|
16
29
|
this.showValue = false;
|
|
17
30
|
this.value = 0;
|
|
18
31
|
this.valueText = '';
|
|
32
|
+
this.renamed = () => {
|
|
33
|
+
this.requestUpdate();
|
|
34
|
+
};
|
|
19
35
|
}
|
|
20
36
|
get span() {
|
|
21
37
|
const min = Number.isFinite(this.min) ? this.min : 0;
|
|
@@ -64,17 +80,17 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
|
|
|
64
80
|
return distance === 0 ? 'good' : distance === 1 ? 'fair' : 'poor';
|
|
65
81
|
}
|
|
66
82
|
get text() {
|
|
67
|
-
return this.valueText ||
|
|
83
|
+
return this.valueText || percent(this.ratio, this.locale);
|
|
68
84
|
}
|
|
69
85
|
willUpdate(changed) {
|
|
70
86
|
super.willUpdate(changed);
|
|
71
87
|
const { max, min } = this.span;
|
|
72
|
-
hostAria(this.internals, { label: this.label, role: 'meter' });
|
|
88
|
+
hostAria(this.internals, { label: slottedWords(this, ['label']) || this.label, role: 'meter' });
|
|
73
89
|
this.internals.ariaValueMin = String(min);
|
|
74
90
|
this.internals.ariaValueMax = String(max);
|
|
75
91
|
this.internals.ariaValueNow = String(this.reading);
|
|
76
92
|
this.internals.ariaValueText =
|
|
77
|
-
this.valueText || (this.beyond ?
|
|
93
|
+
this.valueText || (this.beyond ? percent(this.ratio, this.locale) : null);
|
|
78
94
|
}
|
|
79
95
|
renderRound() {
|
|
80
96
|
const bounds = this.thresholds;
|
|
@@ -108,7 +124,7 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
|
|
|
108
124
|
const beyond = this.beyond;
|
|
109
125
|
const { max, min } = this.span;
|
|
110
126
|
const at = (value) => `${((value - min) / (max - min)) * 100}%`;
|
|
111
|
-
return html
|
|
127
|
+
return html `<slot name="label" @slotchange=${this.renamed}></slot>${this.shape
|
|
112
128
|
? this.renderRound()
|
|
113
129
|
: html `<div part="track">
|
|
114
130
|
${bounds
|
|
@@ -134,6 +150,9 @@ __decorate([
|
|
|
134
150
|
__decorate([
|
|
135
151
|
property()
|
|
136
152
|
], HelixHeadlessMeter.prototype, "label", void 0);
|
|
153
|
+
__decorate([
|
|
154
|
+
property()
|
|
155
|
+
], HelixHeadlessMeter.prototype, "locale", void 0);
|
|
137
156
|
__decorate([
|
|
138
157
|
property({ type: Number })
|
|
139
158
|
], HelixHeadlessMeter.prototype, "low", void 0);
|