@fusion.dev/helix-headless 0.144.0 → 0.145.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 +8312 -881
- package/dist/accordion/item/accordion-item.d.ts +48 -12
- package/dist/accordion/item/accordion-item.js +26 -5
- package/dist/accordion/root/accordion-root.d.ts +6 -0
- package/dist/accordion/root/accordion-root.js +7 -1
- package/dist/announcement/root/announcement-root.d.ts +21 -1
- package/dist/announcement/root/announcement-root.js +36 -1
- package/dist/app-header/root/app-header-root.d.ts +7 -0
- package/dist/app-header/root/app-header-root.js +5 -1
- package/dist/app-header/sectioning.d.ts +7 -0
- package/dist/app-header/sectioning.js +26 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +32 -1
- package/dist/breadcrumbs/root/breadcrumbs-root.js +25 -2
- package/dist/canvas/root/canvas-root.d.ts +38 -3
- package/dist/canvas/root/canvas-root.js +121 -40
- package/dist/carousel/root/carousel-root.d.ts +90 -0
- package/dist/carousel/root/carousel-root.js +134 -12
- 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 +25 -9
- package/dist/chat/naming.d.ts +22 -0
- package/dist/chat/naming.js +12 -0
- package/dist/chat/relative-clock.d.ts +39 -0
- package/dist/chat/relative-clock.js +31 -0
- package/dist/chat/root/chat-root.d.ts +36 -0
- package/dist/chat/root/chat-root.js +24 -1
- package/dist/code-block/root/code-block-root.d.ts +8 -1
- package/dist/code-block/root/code-block-root.js +5 -5
- package/dist/copy-button/root/copy-button-root.d.ts +21 -1
- package/dist/copy-button/root/copy-button-root.js +2 -2
- package/dist/data-table/root/data-table-root.d.ts +150 -2
- package/dist/data-table/root/data-table-root.js +303 -29
- package/dist/data-table/tree.d.ts +40 -0
- package/dist/data-table/tree.js +55 -0
- 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/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 +11 -0
- package/dist/drilldown/root/drilldown-root.js +8 -3
- package/dist/element-events.generated.js +53 -8
- package/dist/filter-input/menu/filter-menu.d.ts +3 -0
- package/dist/filter-input/menu/filter-menu.js +8 -4
- package/dist/image/root/image-root.js +9 -1
- package/dist/input/root/input-root.d.ts +1 -1
- package/dist/input/root/input-root.js +2 -2
- package/dist/list/item/list-item.d.ts +68 -1
- package/dist/list/item/list-item.js +66 -4
- package/dist/list/numbering.d.ts +14 -0
- package/dist/list/numbering.js +8 -0
- package/dist/list/root/list-root.d.ts +106 -9
- package/dist/list/root/list-root.js +189 -4
- package/dist/list/selection.d.ts +19 -0
- package/dist/list/selection.js +21 -0
- package/dist/listbox/root/listbox-root.js +1 -2
- 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 +21 -0
- package/dist/megamenu/root/megamenu-root.js +16 -2
- package/dist/menu/index.d.ts +1 -0
- package/dist/menu/index.js +1 -0
- package/dist/menu/item/menu-item.d.ts +38 -11
- package/dist/menu/item/menu-item.js +33 -1
- package/dist/menu/root/menu-root.d.ts +25 -1
- package/dist/menu/root/menu-root.js +63 -6
- package/dist/menu/section/menu-section.d.ts +55 -0
- package/dist/menu/section/menu-section.js +60 -0
- package/dist/navigation/root/navigation-root.d.ts +16 -1
- package/dist/navigation/root/navigation-root.js +27 -1
- package/dist/notifications/root/notifications-root.d.ts +18 -0
- package/dist/notifications/root/notifications-root.js +17 -1
- package/dist/object-inspector/root/object-inspector-root.d.ts +97 -16
- package/dist/object-inspector/root/object-inspector-root.js +179 -79
- package/dist/object-inspector/rows.d.ts +57 -0
- package/dist/object-inspector/rows.js +86 -0
- package/dist/outline/levels.d.ts +31 -0
- package/dist/outline/levels.js +23 -0
- package/dist/outline/root/outline-root.d.ts +68 -3
- package/dist/outline/root/outline-root.js +73 -8
- package/dist/pagination/size/pagination-size.d.ts +11 -2
- package/dist/pagination/size/pagination-size.js +19 -4
- package/dist/radio/group/radio-group.d.ts +4 -10
- package/dist/radio/group/radio-group.js +5 -10
- package/dist/rating/root/rating-root.d.ts +1 -1
- package/dist/rating/root/rating-root.js +2 -2
- package/dist/scroll-area/root/scroll-area-root.d.ts +113 -0
- package/dist/scroll-area/root/scroll-area-root.js +218 -3
- package/dist/scroll-area/scrollbar.d.ts +65 -0
- package/dist/scroll-area/scrollbar.js +24 -0
- package/dist/select/root/select-root.js +1 -1
- package/dist/splitter/root/splitter-root.d.ts +13 -0
- package/dist/splitter/root/splitter-root.js +20 -2
- package/dist/splitter/snap.d.ts +9 -0
- package/dist/splitter/snap.js +12 -0
- package/dist/steps/reach.d.ts +15 -0
- package/dist/steps/reach.js +12 -0
- package/dist/steps/root/steps-root.d.ts +30 -0
- package/dist/steps/root/steps-root.js +53 -0
- package/dist/steps/step/step.d.ts +38 -2
- package/dist/steps/step/step.js +28 -6
- package/dist/table/column/table-column.d.ts +11 -0
- package/dist/table/column/table-column.js +6 -1
- package/dist/table/root/table-root.d.ts +101 -0
- package/dist/table/root/table-root.js +166 -5
- 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 +9 -5
- package/dist/tabs/panel/tab-panel.js +3 -4
- package/dist/tabs/root/tabs-root.d.ts +25 -1
- package/dist/tabs/root/tabs-root.js +21 -3
- package/dist/tabs/tab/tab.d.ts +36 -4
- package/dist/tabs/tab/tab.js +46 -3
- 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 +10 -17
- package/dist/toast/item/toast-item.js +15 -36
- package/dist/toolbar/root/toolbar-root.d.ts +13 -0
- package/dist/toolbar/root/toolbar-root.js +15 -5
- package/dist/tree/item/tree-item.d.ts +54 -1
- package/dist/tree/item/tree-item.js +89 -20
- package/dist/tree/root/tree-root.d.ts +37 -0
- package/dist/tree/root/tree-root.js +51 -6
- package/dist/tree/selection.d.ts +24 -0
- package/dist/tree/selection.js +26 -0
- package/dist/video/media-events.d.ts +49 -0
- package/dist/video/media-events.js +39 -0
- package/dist/video/root/video-root.d.ts +99 -13
- package/dist/video/root/video-root.js +84 -47
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +3 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +2 -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 +70 -2
- 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 +30 -0
- package/dist/virtual-list/fill.js +39 -0
- package/dist/virtual-list/keys.d.ts +15 -0
- package/dist/virtual-list/keys.js +24 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +155 -23
- package/dist/virtual-list/root/virtual-list-root.js +175 -34
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +3778 -801
- package/types/svelte.d.ts +2 -0
- package/types/vue.d.ts +782 -215
- package/dist/listbox/range.d.ts +0 -17
- package/dist/listbox/range.js +0 -5
|
@@ -45,7 +45,8 @@ declare const HelixHeadlessMap_base: (new (...args: any[]) => import("@fusion.de
|
|
|
45
45
|
* for each layer, which sets the layer's `hidden` attribute. Layers with the
|
|
46
46
|
* same `group`, such as a route and its dotted legs, share one tile. A tile
|
|
47
47
|
* sends `helix-before-toggle` from the layer first, so you can store the
|
|
48
|
-
* choice or refuse it
|
|
48
|
+
* choice or refuse it, and `helix-toggle` from it once `hidden` holds the
|
|
49
|
+
* choice.
|
|
49
50
|
*
|
|
50
51
|
* Imagery, a `helix-map-raster` with `ground`, is a map type and not a tile.
|
|
51
52
|
* The menu opens with a card for each type, Standard, Hybrid, and Satellite,
|
|
@@ -80,6 +81,7 @@ declare const HelixHeadlessMap_base: (new (...args: any[]) => import("@fusion.de
|
|
|
80
81
|
* @event {HelixMapRotateEvent} helix-map-rotate - A rotate or Face north button, or Shift with Left or Right, was pressed. Turn your map in response.
|
|
81
82
|
* @event {HelixMapTiltEvent} helix-map-tilt - The 3D button, or Shift with Up or Down, was pressed. Tilt your map in response.
|
|
82
83
|
* @event {HelixMapZoomEvent} helix-map-zoom - A zoom button or key was pressed, with a direction. Zoom your map in response.
|
|
84
|
+
* @event {HelixToggleEvent} helix-toggle - A layer's tile in the layers menu showed or hid it. Sent from the layer once its `hidden` attribute holds the choice, with `checked` true when it is shown.
|
|
83
85
|
*
|
|
84
86
|
* @csspart attribution - The strip under the map that holds the credit.
|
|
85
87
|
* @csspart compass - The compass and the pan and rotate buttons around it.
|
|
@@ -291,7 +293,9 @@ export declare class HelixHeadlessMap extends HelixHeadlessMap_base {
|
|
|
291
293
|
* **Asked first, from the layer.** The tile wrote `hidden` onto the
|
|
292
294
|
* consumer's element and said nothing, so a page could neither keep the
|
|
293
295
|
* choice nor keep its own state in step. The request comes from the first
|
|
294
|
-
* layer of the tile, which is the element the page wrote.
|
|
296
|
+
* layer of the tile, which is the element the page wrote. Once `hidden`
|
|
297
|
+
* holds the answer, the same layer sends `helix-toggle`, the request's verb
|
|
298
|
+
* without `before`, since the platform has no word for a layer shown.
|
|
295
299
|
*/
|
|
296
300
|
private showLayers;
|
|
297
301
|
/** Asks for a map type, and sends `change` once it holds. */
|
|
@@ -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, fillTemplate, formatNumbers, HelixActivateEvent, HelixBeforeChangeEvent, HelixBeforeToggleEvent, HelixElement, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, hostAria, KeyboardNavigationController, MixinViewport, requestChange, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, fillTemplate, formatNumbers, HelixActivateEvent, HelixBeforeChangeEvent, HelixBeforeToggleEvent, HelixElement, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixToggleEvent, 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';
|
|
@@ -210,7 +210,7 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
|
|
|
210
210
|
if (!first) {
|
|
211
211
|
return;
|
|
212
212
|
}
|
|
213
|
-
requestChange({
|
|
213
|
+
const applied = requestChange({
|
|
214
214
|
apply: () => {
|
|
215
215
|
for (const layer of layers) {
|
|
216
216
|
layer.hidden = !shown;
|
|
@@ -221,6 +221,9 @@ let HelixHeadlessMap = class HelixHeadlessMap extends MixinViewport(HelixElement
|
|
|
221
221
|
host: first,
|
|
222
222
|
next: shown,
|
|
223
223
|
});
|
|
224
|
+
if (applied) {
|
|
225
|
+
first.dispatchEvent(new HelixToggleEvent({ checked: shown }));
|
|
226
|
+
}
|
|
224
227
|
}
|
|
225
228
|
chooseMapType(type) {
|
|
226
229
|
const applied = requestChange({
|
|
@@ -20,6 +20,13 @@ declare const HelixHeadlessMegamenu_base: (new (...args: any[]) => import("@fusi
|
|
|
20
20
|
* which. Hover is the default because in a navigation bar people expect to move
|
|
21
21
|
* along the row and see each section.
|
|
22
22
|
*
|
|
23
|
+
* When one panel opens in place of another, each says which way the reader
|
|
24
|
+
* moved, as Radix's `data-motion` does: the one opening is
|
|
25
|
+
* `:state(from-start)` or `:state(from-end)`, by where the one closing sits in
|
|
26
|
+
* the bar, and the one closing is `:state(to-start)` or `:state(to-end)`. A
|
|
27
|
+
* stylesheet slides them on that. Put megamenus in a `Navigation` with
|
|
28
|
+
* `arrows` and the arrow keys move between their triggers.
|
|
29
|
+
*
|
|
23
30
|
* @since 0.1.0
|
|
24
31
|
* @status stable
|
|
25
32
|
* @category navigation
|
|
@@ -38,8 +45,12 @@ declare const HelixHeadlessMegamenu_base: (new (...args: any[]) => import("@fusi
|
|
|
38
45
|
*
|
|
39
46
|
* @cssproperty --megamenu-top - Where the panel starts, measured from the bar above it.
|
|
40
47
|
*
|
|
48
|
+
* @cssstate from-end - The panel opened in place of one later in the bar, so it can enter from that side.
|
|
49
|
+
* @cssstate from-start - The panel opened in place of one earlier in the bar.
|
|
41
50
|
* @cssstate narrow - The page is narrower than `band-below`, so the panel is shown as a band whatever its variant.
|
|
42
51
|
* @cssstate open - The panel is open, and the trigger is shown as current.
|
|
52
|
+
* @cssstate to-end - The panel closed because one later in the bar opened, so it can leave toward it.
|
|
53
|
+
* @cssstate to-start - The panel closed because one earlier in the bar opened.
|
|
43
54
|
*/
|
|
44
55
|
export declare class HelixHeadlessMegamenu extends HelixHeadlessMegamenu_base {
|
|
45
56
|
/**
|
|
@@ -119,6 +130,11 @@ export declare class HelixHeadlessMegamenu extends HelixHeadlessMegamenu_base {
|
|
|
119
130
|
private get slotted();
|
|
120
131
|
/** Whatever the consumer slotted, or the button rendered in its place. */
|
|
121
132
|
private get trigger();
|
|
133
|
+
/**
|
|
134
|
+
* @internal The control a `Navigation`'s arrow keys move to: the trigger
|
|
135
|
+
* the consumer slotted, or the button drawn in its place.
|
|
136
|
+
*/
|
|
137
|
+
get navigationControl(): HTMLElement;
|
|
122
138
|
/** Shuts it and puts the reader back where they were. */
|
|
123
139
|
private close;
|
|
124
140
|
/**
|
|
@@ -241,6 +257,11 @@ export declare class HelixHeadlessMegamenu extends HelixHeadlessMegamenu_base {
|
|
|
241
257
|
* overruled.
|
|
242
258
|
*/
|
|
243
259
|
protected willUpdate(changed: PropertyValues): void;
|
|
260
|
+
/**
|
|
261
|
+
* Says which way the reader moved when one panel took over from another.
|
|
262
|
+
* Nothing clears all four, for a panel opened on its own.
|
|
263
|
+
*/
|
|
264
|
+
private motion;
|
|
244
265
|
protected updated(changed: PropertyValues): void;
|
|
245
266
|
/**
|
|
246
267
|
* The control that opens it, behind a seam the styled tier can move.
|
|
@@ -117,6 +117,9 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
117
117
|
get trigger() {
|
|
118
118
|
return anchorElement(this.renderRoot?.querySelector('slot[name="trigger"]'), this.partNamed('trigger') ?? this);
|
|
119
119
|
}
|
|
120
|
+
get navigationControl() {
|
|
121
|
+
return this.trigger;
|
|
122
|
+
}
|
|
120
123
|
close() {
|
|
121
124
|
if (!this.requestOpen(false)) {
|
|
122
125
|
return;
|
|
@@ -184,8 +187,13 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
184
187
|
return;
|
|
185
188
|
}
|
|
186
189
|
if (this.open) {
|
|
187
|
-
|
|
188
|
-
|
|
190
|
+
const previous = showing && showing !== this ? showing : undefined;
|
|
191
|
+
const forward = previous !== undefined &&
|
|
192
|
+
(previous.compareDocumentPosition(this) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
|
|
193
|
+
this.motion(previous ? (forward ? 'from-end' : 'from-start') : undefined);
|
|
194
|
+
if (previous) {
|
|
195
|
+
previous.motion(forward ? 'to-end' : 'to-start');
|
|
196
|
+
previous.requestOpen(false);
|
|
189
197
|
}
|
|
190
198
|
showing = this;
|
|
191
199
|
}
|
|
@@ -193,6 +201,12 @@ let HelixHeadlessMegamenu = class HelixHeadlessMegamenu extends MixinControllerO
|
|
|
193
201
|
showing = undefined;
|
|
194
202
|
}
|
|
195
203
|
}
|
|
204
|
+
motion(to) {
|
|
205
|
+
this.toggleState('from-end', to === 'from-end');
|
|
206
|
+
this.toggleState('from-start', to === 'from-start');
|
|
207
|
+
this.toggleState('to-end', to === 'to-end');
|
|
208
|
+
this.toggleState('to-start', to === 'to-start');
|
|
209
|
+
}
|
|
196
210
|
updated(changed) {
|
|
197
211
|
super.updated?.(changed);
|
|
198
212
|
if (changed.has('bandBelow')) {
|
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,30 @@ 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
|
+
*
|
|
26
32
|
* @since 0.1.0
|
|
27
33
|
* @status stable
|
|
28
34
|
* @aliases Menu option, Menu row
|
|
29
35
|
* @documentation https://fusion.dev/helix/components/menu
|
|
30
36
|
*
|
|
31
37
|
* @slot - The label.
|
|
38
|
+
* @slot end - Words after the label, such as a count or a detail, beside any `shortcut`.
|
|
32
39
|
* @slot start - Content before the label, such as an icon.
|
|
33
40
|
* @slot submenu - The rows of a submenu that this row opens.
|
|
34
41
|
*
|
|
35
42
|
* @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
43
|
* @event {HelixSelectEvent} helix-select - The row was chosen. Cancelable: cancel it to keep the menu open.
|
|
37
44
|
*
|
|
45
|
+
* @csspart end - The trailing column that holds the shortcut and the `end` slot. It is always rendered.
|
|
38
46
|
* @csspart item - The row, which is an `<a>` where `href` is set.
|
|
39
47
|
* @csspart mark - The trailing mark: a check mark when the row is checked, or a caret
|
|
40
48
|
* when it opens a submenu. A row never shows both, so they share one column.
|
|
49
|
+
* @csspart shortcut - The key drawn for `shortcut`.
|
|
50
|
+
* @csspart shortcut-kbd - The key inside it.
|
|
41
51
|
* @csspart start - The leading column that holds the `start` slot. It is always rendered.
|
|
42
52
|
*
|
|
43
53
|
* @cssstate checked - The row is checked.
|
|
@@ -100,19 +110,16 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
100
110
|
* roves, which is the same maneuver `Tree.Item` makes and the reason `href`
|
|
101
111
|
* changes the markup rather than only adding an attribute.
|
|
102
112
|
*
|
|
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.
|
|
113
|
+
* **`Option` takes an `href` too, and keeps its role a different way.** A
|
|
114
|
+
* listbox keeps focus somewhere else, in the text field for a combobox, and
|
|
115
|
+
* names the current option with `aria-activedescendant`, which can only point
|
|
116
|
+
* at the option's host. So an option stays `role="option"` on its host, draws
|
|
117
|
+
* no anchor, and follows its link through an anchor made for the moment. A
|
|
118
|
+
* menu has no such constraint, because focus really moves to the row.
|
|
112
119
|
*/
|
|
113
120
|
href: string;
|
|
114
121
|
/**
|
|
115
|
-
* Whether the row is on the menu page that is showing.
|
|
122
|
+
* @internal Whether the row is on the menu page that is showing.
|
|
116
123
|
*
|
|
117
124
|
* Set by the menu, and a property rather than an attribute for that reason.
|
|
118
125
|
* Public because the menu has to reach it, and not something a consumer
|
|
@@ -124,7 +131,14 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
124
131
|
*/
|
|
125
132
|
rel: string;
|
|
126
133
|
/**
|
|
127
|
-
*
|
|
134
|
+
* The row's keyboard shortcut as a chord, such as `mod+s`, shown after the
|
|
135
|
+
* label in the platform's glyphs and given to the row as
|
|
136
|
+
* `aria-keyshortcuts`. `mod` is Command on an Apple keyboard and Control
|
|
137
|
+
* elsewhere. Showing a shortcut does not bind it.
|
|
138
|
+
*/
|
|
139
|
+
shortcut: string;
|
|
140
|
+
/**
|
|
141
|
+
* @internal Whether the page showing is this row's submenu, or one below it.
|
|
128
142
|
*
|
|
129
143
|
* Separate from `onPage`, and it has to be. A row that opened a page is not
|
|
130
144
|
* itself on that page, so both are false for it, and rendering nothing on
|
|
@@ -185,6 +199,8 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
185
199
|
* exactly the thing that is.
|
|
186
200
|
*/
|
|
187
201
|
private start;
|
|
202
|
+
/** Whether anything is slotted after the label, read the way `start` is. */
|
|
203
|
+
private end;
|
|
188
204
|
/**
|
|
189
205
|
* Both answers, from the children, before each render.
|
|
190
206
|
*
|
|
@@ -205,6 +221,17 @@ export declare class HelixHeadlessMenuItem extends HelixElement {
|
|
|
205
221
|
* is never rebuilt and never fires on its way out.
|
|
206
222
|
*/
|
|
207
223
|
private readonly readStart;
|
|
224
|
+
/** Re-reads whether anything is after the label, as `readStart` does before it. */
|
|
225
|
+
private readonly readEnd;
|
|
226
|
+
/**
|
|
227
|
+
* The trailing column: the shortcut's key, then whatever is slotted in `end`.
|
|
228
|
+
* Drawn by `Kbd`, interpolated so each tier draws its own.
|
|
229
|
+
*
|
|
230
|
+
* The key is hidden from the accessibility tree, since the row's
|
|
231
|
+
* `aria-keyshortcuts` says it in words a screen reader reads as keys: inside
|
|
232
|
+
* the row its glyphs became part of the row's name.
|
|
233
|
+
*/
|
|
234
|
+
protected renderEnd(): TemplateResult;
|
|
208
235
|
/**
|
|
209
236
|
* Re-reads whether anything is in the submenu, from whichever slot is current.
|
|
210
237
|
*
|
|
@@ -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,22 @@ 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;
|
|
29
33
|
this.readStart = () => {
|
|
30
34
|
const slot = this.renderRoot.querySelector('slot[name="start"]');
|
|
31
35
|
this.start = (slot?.assignedNodes().length ?? 0) > 0;
|
|
32
36
|
};
|
|
37
|
+
this.readEnd = () => {
|
|
38
|
+
const slot = this.renderRoot.querySelector('slot[name="end"]');
|
|
39
|
+
this.end = (slot?.assignedNodes().length ?? 0) > 0;
|
|
40
|
+
};
|
|
33
41
|
this.readSubmenu = () => {
|
|
34
42
|
const slot = this.renderRoot.querySelector('slot[name="submenu"]');
|
|
35
43
|
this.submenu = (slot?.assignedElements().length ?? 0) > 0;
|
|
@@ -65,11 +73,25 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
65
73
|
const named = (name) => this.knownChildren.some((child) => child.slot === name);
|
|
66
74
|
this.submenu = named('submenu');
|
|
67
75
|
this.start = named('start');
|
|
76
|
+
this.end = named('end');
|
|
68
77
|
}
|
|
69
78
|
firstUpdated(changed) {
|
|
70
79
|
super.firstUpdated(changed);
|
|
71
80
|
this.finishHydration();
|
|
72
81
|
}
|
|
82
|
+
renderEnd() {
|
|
83
|
+
const kbd = this.tag('kbd');
|
|
84
|
+
return html `<span part="end" ?data-empty=${!this.end && this.shortcut === ''}
|
|
85
|
+
>${this.shortcut === ''
|
|
86
|
+
? nothing
|
|
87
|
+
: staticHtml `<${kbd}
|
|
88
|
+
part="shortcut"
|
|
89
|
+
exportparts="kbd: shortcut-kbd"
|
|
90
|
+
aria-hidden="true"
|
|
91
|
+
keys=${this.shortcut}
|
|
92
|
+
></${kbd}>`}<slot name="end" @slotchange=${this.readEnd}></slot
|
|
93
|
+
></span>`;
|
|
94
|
+
}
|
|
73
95
|
focus() {
|
|
74
96
|
this.partNamed('item')?.focus();
|
|
75
97
|
}
|
|
@@ -142,10 +164,12 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
142
164
|
const ticks = this.checkable || this.checked;
|
|
143
165
|
const role = ticks ? (this.exclusive ? 'menuitemradio' : 'menuitemcheckbox') : 'menuitem';
|
|
144
166
|
const checkedState = ticks ? (this.checked ? 'true' : 'false') : nothing;
|
|
167
|
+
const keys = this.shortcut === '' ? nothing : ariaChord(this.shortcut, !this.hydrating && onApple());
|
|
145
168
|
const inside = html `<span part="start" ?data-empty=${!this.start}
|
|
146
169
|
><slot name="start" @slotchange=${this.readStart}></slot
|
|
147
170
|
></span>
|
|
148
171
|
<slot></slot>
|
|
172
|
+
${this.renderEnd()}
|
|
149
173
|
${submenu
|
|
150
174
|
? html `<svg
|
|
151
175
|
part="mark"
|
|
@@ -177,6 +201,7 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
177
201
|
role=${role}
|
|
178
202
|
aria-checked=${checkedState}
|
|
179
203
|
aria-haspopup=${submenu ? 'menu' : nothing}
|
|
204
|
+
aria-keyshortcuts=${keys}
|
|
180
205
|
tabindex="-1"
|
|
181
206
|
@click=${this.handleClick}
|
|
182
207
|
@keydown=${this.handleKeydown}
|
|
@@ -187,6 +212,7 @@ let HelixHeadlessMenuItem = class HelixHeadlessMenuItem extends HelixElement {
|
|
|
187
212
|
aria-checked=${checkedState}
|
|
188
213
|
aria-disabled=${this.disabled ? 'true' : nothing}
|
|
189
214
|
aria-haspopup=${submenu ? 'menu' : nothing}
|
|
215
|
+
aria-keyshortcuts=${keys}
|
|
190
216
|
tabindex=${this.disabled ? nothing : '-1'}
|
|
191
217
|
@click=${this.handleClick}
|
|
192
218
|
@keydown=${this.handleKeydown}
|
|
@@ -218,6 +244,9 @@ __decorate([
|
|
|
218
244
|
__decorate([
|
|
219
245
|
property()
|
|
220
246
|
], HelixHeadlessMenuItem.prototype, "rel", void 0);
|
|
247
|
+
__decorate([
|
|
248
|
+
property()
|
|
249
|
+
], HelixHeadlessMenuItem.prototype, "shortcut", void 0);
|
|
221
250
|
__decorate([
|
|
222
251
|
property({ attribute: false })
|
|
223
252
|
], HelixHeadlessMenuItem.prototype, "showingSubmenu", void 0);
|
|
@@ -233,6 +262,9 @@ __decorate([
|
|
|
233
262
|
__decorate([
|
|
234
263
|
state()
|
|
235
264
|
], HelixHeadlessMenuItem.prototype, "start", void 0);
|
|
265
|
+
__decorate([
|
|
266
|
+
state()
|
|
267
|
+
], HelixHeadlessMenuItem.prototype, "end", void 0);
|
|
236
268
|
HelixHeadlessMenuItem = __decorate([
|
|
237
269
|
customElement('helix-headless-menu-item')
|
|
238
270
|
], HelixHeadlessMenuItem);
|
|
@@ -24,6 +24,16 @@ 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
|
+
* With `context`, the trigger is an area and the menu is its context menu: a
|
|
32
|
+
* right-click, a long press, Shift+F10 or the menu key over the area opens it
|
|
33
|
+
* at the pointer, or at the area's corner from the keyboard, as Radix's context
|
|
34
|
+
* menu does. A press on the area does not open it, and closing it returns focus
|
|
35
|
+
* to where it was.
|
|
36
|
+
*
|
|
27
37
|
* @since 0.1.0
|
|
28
38
|
* @status stable
|
|
29
39
|
* @category overlays
|
|
@@ -31,7 +41,7 @@ declare const HelixHeadlessMenu_base: (new (...args: any[]) => import("@fusion.d
|
|
|
31
41
|
* @documentation https://fusion.dev/helix/components/menu
|
|
32
42
|
*
|
|
33
43
|
* @slot - The items.
|
|
34
|
-
* @slot trigger - The control that opens the menu.
|
|
44
|
+
* @slot trigger - The control that opens the menu, or with `context` the area a context menu opens over.
|
|
35
45
|
*
|
|
36
46
|
* @event {HelixBeforeCloseEvent} helix-before-close - The menu is about to close. Cancelable: cancel it to keep it open.
|
|
37
47
|
* @event {HelixBeforeOpenEvent} helix-before-open - The menu is about to open. Cancelable: cancel it to keep it closed.
|
|
@@ -57,6 +67,11 @@ export declare class HelixHeadlessMenu extends HelixHeadlessMenu_base {
|
|
|
57
67
|
* The text of the row that returns from a submenu.
|
|
58
68
|
*/
|
|
59
69
|
backLabel: string;
|
|
70
|
+
/**
|
|
71
|
+
* Whether the menu is the trigger's context menu: it opens where the reader
|
|
72
|
+
* asks for one, with a right-click, a long press, Shift+F10 or the menu key.
|
|
73
|
+
*/
|
|
74
|
+
context: boolean;
|
|
60
75
|
/**
|
|
61
76
|
* Accessible name for the surface.
|
|
62
77
|
*
|
|
@@ -104,6 +119,10 @@ export declare class HelixHeadlessMenu extends HelixHeadlessMenu_base {
|
|
|
104
119
|
protected readonly keys: KeyboardNavigationController;
|
|
105
120
|
/** Carries a host `aria-label` and `aria-labelledby` to the surface. */
|
|
106
121
|
protected readonly aria: AriaForwardController;
|
|
122
|
+
/** Where a context menu was asked for, in the viewport, while it is open. */
|
|
123
|
+
private point;
|
|
124
|
+
/** Where focus was when a context menu opened, so closing it returns there. */
|
|
125
|
+
private returnTo;
|
|
107
126
|
private readonly panel;
|
|
108
127
|
/**
|
|
109
128
|
* Tells a slotted trigger the disclosure state, by property.
|
|
@@ -124,6 +143,11 @@ export declare class HelixHeadlessMenu extends HelixHeadlessMenu_base {
|
|
|
124
143
|
private openAt;
|
|
125
144
|
/** Closes the menu and returns it to its first page. */
|
|
126
145
|
hide(): void;
|
|
146
|
+
/**
|
|
147
|
+
* Opens a context menu where the reader asked for it: at the pointer, or at
|
|
148
|
+
* the area's corner where the keyboard asked and the event has no position.
|
|
149
|
+
*/
|
|
150
|
+
private readonly handleContextMenu;
|
|
127
151
|
/** Shows an item's submenu in place of the current page. */
|
|
128
152
|
private enter;
|
|
129
153
|
/** Returns to the page above, or closes when there is none. */
|
|
@@ -9,16 +9,20 @@ import { caretLeft } from '@fusion.dev/helix-icons';
|
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
|
+
const isSection = (element) => 'isMenuSection' in element && element.isMenuSection === true;
|
|
12
13
|
let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinControllerOpen(HelixElement)) {
|
|
13
14
|
constructor() {
|
|
14
15
|
super(...arguments);
|
|
15
16
|
this.backLabel = 'Back';
|
|
17
|
+
this.context = false;
|
|
16
18
|
this.label = '';
|
|
17
19
|
this.offset = 4;
|
|
18
20
|
this.placement = 'bottom-start';
|
|
19
21
|
this.drilldown = new DrilldownController(this, {
|
|
20
22
|
isRow: (element) => 'isMenuItem' in element && element.isMenuItem === true,
|
|
21
|
-
root: () => [...this.children]
|
|
23
|
+
root: () => [...this.children]
|
|
24
|
+
.filter((child) => child.slot !== 'trigger')
|
|
25
|
+
.flatMap((child) => (isSection(child) ? [...child.children] : [child])),
|
|
22
26
|
slot: 'submenu',
|
|
23
27
|
});
|
|
24
28
|
this.keys = new KeyboardNavigationController(this, {
|
|
@@ -32,7 +36,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
32
36
|
target: () => this.partNamed('surface'),
|
|
33
37
|
});
|
|
34
38
|
this.panel = new PopoverController(this, {
|
|
35
|
-
anchor: () => this.
|
|
39
|
+
anchor: () => this.context && this.point
|
|
40
|
+
? this.renderRoot?.querySelector('#point')
|
|
41
|
+
: this.trigger,
|
|
36
42
|
boundary: () => this,
|
|
37
43
|
offset: () => this.offset,
|
|
38
44
|
onDismiss: () => this.hide(),
|
|
@@ -40,6 +46,28 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
40
46
|
placement: () => this.placement,
|
|
41
47
|
surface: () => this.partNamed('surface'),
|
|
42
48
|
});
|
|
49
|
+
this.handleContextMenu = (event) => {
|
|
50
|
+
if (!this.context) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const slot = this.renderRoot?.querySelector('slot[name="trigger"]');
|
|
54
|
+
const areas = slot?.assignedElements({ flatten: true }) ?? [];
|
|
55
|
+
if (!event.composedPath().some((node) => areas.includes(node))) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
event.preventDefault();
|
|
59
|
+
const box = this.trigger.getBoundingClientRect();
|
|
60
|
+
const keyed = event.clientX === 0 && event.clientY === 0;
|
|
61
|
+
this.point = keyed ? { x: box.left, y: box.top } : { x: event.clientX, y: event.clientY };
|
|
62
|
+
if (this.open) {
|
|
63
|
+
this.requestUpdate();
|
|
64
|
+
this.updateComplete.then(() => this.panel.reposition());
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const active = deepActiveElement();
|
|
68
|
+
this.returnTo = active instanceof HTMLElement ? active : undefined;
|
|
69
|
+
this.show();
|
|
70
|
+
};
|
|
43
71
|
this.handleSelect = (event) => {
|
|
44
72
|
const item = event.target;
|
|
45
73
|
if (!this.items.includes(item)) {
|
|
@@ -93,6 +121,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
93
121
|
event.preventDefault();
|
|
94
122
|
};
|
|
95
123
|
this.handleTriggerClick = () => {
|
|
124
|
+
if (this.context) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
96
127
|
if (this.open) {
|
|
97
128
|
this.hide();
|
|
98
129
|
}
|
|
@@ -130,8 +161,11 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
130
161
|
this.panel.hide();
|
|
131
162
|
this.drilldown.reset();
|
|
132
163
|
if (deepContains(this, deepActiveElement())) {
|
|
133
|
-
|
|
164
|
+
;
|
|
165
|
+
(this.context ? (this.returnTo ?? this.trigger) : this.trigger).focus();
|
|
134
166
|
}
|
|
167
|
+
this.point = undefined;
|
|
168
|
+
this.returnTo = undefined;
|
|
135
169
|
}
|
|
136
170
|
enter(item) {
|
|
137
171
|
if (!this.drilldown.enter(item)) {
|
|
@@ -149,7 +183,7 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
149
183
|
this.updateComplete.then(() => leaving?.focus());
|
|
150
184
|
}
|
|
151
185
|
handleClosedKeydown(event) {
|
|
152
|
-
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
|
|
186
|
+
if (this.context || (event.key !== 'ArrowDown' && event.key !== 'ArrowUp')) {
|
|
153
187
|
return;
|
|
154
188
|
}
|
|
155
189
|
const slot = this.renderRoot?.querySelector('slot[name="trigger"]');
|
|
@@ -165,17 +199,30 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
165
199
|
this.addEventListener('helix-select', this.handleSelect, true);
|
|
166
200
|
this.addEventListener('keydown', this.handleKeydown);
|
|
167
201
|
this.addEventListener('focusin', this.handleFocusIn);
|
|
202
|
+
this.addEventListener('contextmenu', this.handleContextMenu);
|
|
168
203
|
}
|
|
169
204
|
disconnectedCallback() {
|
|
170
205
|
super.disconnectedCallback();
|
|
171
206
|
this.removeEventListener('helix-select', this.handleSelect, true);
|
|
172
207
|
this.removeEventListener('keydown', this.handleKeydown);
|
|
173
208
|
this.removeEventListener('focusin', this.handleFocusIn);
|
|
209
|
+
this.removeEventListener('contextmenu', this.handleContextMenu);
|
|
174
210
|
}
|
|
175
211
|
updated(changed) {
|
|
176
212
|
super.updated(changed);
|
|
177
|
-
this.
|
|
213
|
+
if (!this.context) {
|
|
214
|
+
this.tellTrigger();
|
|
215
|
+
}
|
|
178
216
|
for (const child of this.children) {
|
|
217
|
+
if (isSection(child)) {
|
|
218
|
+
child.onPage = this.drilldown.atRoot;
|
|
219
|
+
for (const row of child.children) {
|
|
220
|
+
if (row.isMenuItem === true) {
|
|
221
|
+
this.mark(row, this.drilldown.atRoot);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
179
226
|
const item = child;
|
|
180
227
|
if (item.isMenuItem !== true) {
|
|
181
228
|
continue;
|
|
@@ -217,7 +264,14 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
217
264
|
}
|
|
218
265
|
}
|
|
219
266
|
render() {
|
|
220
|
-
|
|
267
|
+
const point = this.context && this.point;
|
|
268
|
+
return html `<slot name="trigger" @click=${this.handleTriggerClick}></slot>${point
|
|
269
|
+
? html `<span
|
|
270
|
+
id="point"
|
|
271
|
+
aria-hidden="true"
|
|
272
|
+
style="position: fixed; left: 0; top: 0; translate: ${point.x}px ${point.y}px"
|
|
273
|
+
></span>`
|
|
274
|
+
: nothing}
|
|
221
275
|
<div
|
|
222
276
|
part="surface"
|
|
223
277
|
popover="manual"
|
|
@@ -250,6 +304,9 @@ let HelixHeadlessMenu = class HelixHeadlessMenu extends MixinCollection(MixinCon
|
|
|
250
304
|
__decorate([
|
|
251
305
|
property({ attribute: 'back-label' })
|
|
252
306
|
], HelixHeadlessMenu.prototype, "backLabel", void 0);
|
|
307
|
+
__decorate([
|
|
308
|
+
property({ reflect: true, type: Boolean })
|
|
309
|
+
], HelixHeadlessMenu.prototype, "context", void 0);
|
|
253
310
|
__decorate([
|
|
254
311
|
property()
|
|
255
312
|
], HelixHeadlessMenu.prototype, "label", void 0);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
+
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
|
+
/**
|
|
4
|
+
* @summary A group of rows in a menu, under a heading.
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
* The rows inside it are the menu's rows: the arrow keys and typed letters move
|
|
8
|
+
* through them with the rest, and a set of `exclusive` rows is still the run
|
|
9
|
+
* of them next to each other. The section is a `group` named by its heading,
|
|
10
|
+
* as React Aria's menu section is, so a screen reader says which group a row
|
|
11
|
+
* is in as it arrives.
|
|
12
|
+
*
|
|
13
|
+
* A section goes on the menu's first page. A submenu's page takes rows and
|
|
14
|
+
* dividers.
|
|
15
|
+
*
|
|
16
|
+
* @since 0.1.0
|
|
17
|
+
* @status stable
|
|
18
|
+
* @aliases Menu group, Menu heading
|
|
19
|
+
* @documentation https://fusion.dev/helix/components/menu
|
|
20
|
+
*
|
|
21
|
+
* @slot - The rows.
|
|
22
|
+
* @slot heading - The heading, for content richer than `label`.
|
|
23
|
+
*
|
|
24
|
+
* @csspart heading - The words that name the section.
|
|
25
|
+
* @csspart section - The group that holds the heading and the rows.
|
|
26
|
+
*/
|
|
27
|
+
export declare class HelixHeadlessMenuSection extends HelixElement {
|
|
28
|
+
/**
|
|
29
|
+
* The heading's words, when they are plain text. Content in the `heading`
|
|
30
|
+
* slot replaces it.
|
|
31
|
+
*/
|
|
32
|
+
label: string;
|
|
33
|
+
/**
|
|
34
|
+
* @internal Set by the menu: whether the section is on the page showing. A
|
|
35
|
+
* property, because the menu writes it after the section upgrades.
|
|
36
|
+
*/
|
|
37
|
+
onPage: boolean;
|
|
38
|
+
/** @internal What a menu reads to tell a section from a row. */
|
|
39
|
+
readonly isMenuSection = true;
|
|
40
|
+
/**
|
|
41
|
+
* Whether anything is slotted as the heading, read from the children before
|
|
42
|
+
* each render and from the slot after. A section with neither this nor a
|
|
43
|
+
* `label` draws no heading.
|
|
44
|
+
*/
|
|
45
|
+
private heading;
|
|
46
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
47
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
48
|
+
private readonly readHeading;
|
|
49
|
+
protected render(): TemplateResult | typeof nothing;
|
|
50
|
+
}
|
|
51
|
+
declare global {
|
|
52
|
+
interface HTMLElementTagNameMap {
|
|
53
|
+
'helix-headless-menu-section': HelixHeadlessMenuSection;
|
|
54
|
+
}
|
|
55
|
+
}
|