@fusion.dev/helix-headless 0.143.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 +16990 -1383
- 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/area-chart/root/area-chart-root.d.ts +12 -4
- package/dist/area-chart/root/area-chart-root.js +24 -7
- package/dist/avatar/root/avatar-root.d.ts +14 -0
- package/dist/avatar/root/avatar-root.js +23 -9
- package/dist/badge/root/badge-root.d.ts +11 -7
- package/dist/badge/root/badge-root.js +1 -1
- package/dist/bar-chart/root/bar-chart-root.d.ts +12 -3
- package/dist/bar-chart/root/bar-chart-root.js +17 -10
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +32 -1
- package/dist/breadcrumbs/root/breadcrumbs-root.js +25 -2
- package/dist/button/root/button-root.d.ts +47 -1
- package/dist/button/root/button-root.js +38 -4
- package/dist/callout/root/callout-root.d.ts +18 -1
- package/dist/callout/root/callout-root.js +15 -4
- package/dist/canvas/root/canvas-root.d.ts +38 -3
- package/dist/canvas/root/canvas-root.js +121 -40
- 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 +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/checkbox/root/checkbox-root.js +2 -0
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +53 -3
- package/dist/checkbox-group/root/checkbox-group-root.js +71 -22
- 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 +38 -1
- package/dist/code-block/root/code-block-root.js +28 -7
- package/dist/color-input/root/color-input-root.d.ts +34 -1
- package/dist/color-input/root/color-input-root.js +23 -4
- 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 +81 -5
- package/dist/color-picker/root/color-picker-root.js +103 -10
- package/dist/combobox/root/combobox-root.d.ts +38 -3
- package/dist/combobox/root/combobox-root.js +64 -2
- package/dist/command/root/command-root.d.ts +30 -4
- package/dist/command/root/command-root.js +33 -3
- 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 +47 -1
- package/dist/copy-button/root/copy-button-root.js +44 -8
- 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/date-input/root/date-input-root.d.ts +73 -4
- package/dist/date-input/root/date-input-root.js +93 -43
- package/dist/date-picker/root/date-picker-root.d.ts +145 -1
- package/dist/date-picker/root/date-picker-root.js +239 -48
- 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.d.ts +9 -0
- package/dist/dialog/description.js +14 -0
- package/dist/dialog/root/dialog-root.d.ts +64 -1
- package/dist/dialog/root/dialog-root.js +49 -23
- package/dist/donut-chart/root/donut-chart-root.d.ts +25 -4
- package/dist/donut-chart/root/donut-chart-root.js +21 -6
- package/dist/drawer/root/drawer-root.d.ts +63 -2
- package/dist/drawer/root/drawer-root.js +95 -19
- 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 +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 +61 -13
- package/dist/empty/root/empty-root.d.ts +1 -1
- package/dist/file-input/root/file-input-root.d.ts +47 -0
- package/dist/file-input/root/file-input-root.js +60 -22
- 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 +3 -0
- package/dist/filter-input/menu/filter-menu.js +8 -4
- package/dist/filter-input/root/filter-input-root.d.ts +38 -4
- package/dist/filter-input/root/filter-input-root.js +67 -3
- 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 +51 -0
- package/dist/format-date/root/format-date-root.js +58 -38
- package/dist/heatmap/root/heatmap-root.d.ts +23 -6
- package/dist/heatmap/root/heatmap-root.js +24 -13
- 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 +30 -4
- package/dist/icon/root/icon-root.js +41 -6
- 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/image/root/image-root.d.ts +14 -0
- package/dist/image/root/image-root.js +23 -2
- package/dist/input/root/input-root.d.ts +11 -0
- package/dist/input/root/input-root.js +16 -1
- package/dist/kbd/root/kbd-root.d.ts +20 -13
- package/dist/kbd/root/kbd-root.js +35 -37
- 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 +56 -0
- package/dist/legend/root/legend-root.js +54 -5
- package/dist/lightbox/item/lightbox-item.d.ts +15 -0
- package/dist/lightbox/item/lightbox-item.js +10 -1
- package/dist/lightbox/root/lightbox-root.d.ts +61 -1
- package/dist/lightbox/root/lightbox-root.js +94 -4
- package/dist/line-chart/root/line-chart-root.d.ts +11 -3
- package/dist/line-chart/root/line-chart-root.js +19 -5
- 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.d.ts +74 -3
- package/dist/listbox/root/listbox-root.js +86 -9
- 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 +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/meter/root/meter-root.d.ts +7 -0
- package/dist/meter/root/meter-root.js +6 -3
- package/dist/navigation/root/navigation-root.d.ts +16 -1
- package/dist/navigation/root/navigation-root.js +27 -1
- package/dist/notifications/feed-keys.d.ts +10 -0
- package/dist/notifications/feed-keys.js +14 -0
- package/dist/notifications/notification/notification.d.ts +17 -0
- package/dist/notifications/notification/notification.js +21 -2
- package/dist/notifications/root/notifications-root.d.ts +60 -0
- package/dist/notifications/root/notifications-root.js +76 -1
- package/dist/number-input/root/number-input-root.d.ts +47 -0
- package/dist/number-input/root/number-input-root.js +58 -22
- package/dist/object-inspector/root/object-inspector-root.d.ts +98 -16
- package/dist/object-inspector/root/object-inspector-root.js +180 -80
- package/dist/object-inspector/rows.d.ts +57 -0
- package/dist/object-inspector/rows.js +86 -0
- package/dist/option/root/option-root.d.ts +54 -5
- package/dist/option/root/option-root.js +34 -5
- 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/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 +21 -0
- package/dist/pin-input/root/pin-input-root.js +29 -2
- package/dist/popover/root/popover-root.d.ts +62 -4
- package/dist/popover/root/popover-root.js +53 -5
- package/dist/progress/root/progress-root.d.ts +7 -0
- package/dist/progress/root/progress-root.js +9 -3
- 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 +26 -0
- package/dist/qr-code/root/qr-code-root.js +49 -2
- package/dist/radio/group/radio-group.d.ts +17 -0
- package/dist/radio/group/radio-group.js +14 -1
- package/dist/rating/root/rating-root.d.ts +25 -0
- package/dist/rating/root/rating-root.js +46 -4
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +17 -3
- package/dist/scatter-chart/root/scatter-chart-root.js +25 -7
- 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.d.ts +24 -0
- package/dist/select/root/select-root.js +21 -7
- package/dist/skeleton/root/skeleton-root.d.ts +25 -0
- package/dist/skeleton/root/skeleton-root.js +17 -2
- package/dist/slider/root/slider-root.d.ts +39 -0
- package/dist/slider/root/slider-root.js +45 -9
- 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/stat/root/stat-root.d.ts +2 -0
- package/dist/stat/root/stat-root.js +1 -1
- 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 +39 -2
- package/dist/steps/step/step.js +29 -7
- package/dist/switch/root/switch-root.d.ts +12 -2
- package/dist/switch/root/switch-root.js +6 -1
- 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/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 +60 -0
- package/dist/tag/root/tag-root.js +74 -18
- 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 +9 -0
- package/dist/textarea/root/textarea-root.js +9 -1
- package/dist/time-input/root/time-input-root.d.ts +44 -5
- package/dist/time-input/root/time-input-root.js +69 -39
- package/dist/time-picker/root/time-picker-root.d.ts +54 -8
- package/dist/time-picker/root/time-picker-root.js +121 -91
- 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/hotkey.d.ts +22 -0
- package/dist/toast/hotkey.js +23 -0
- package/dist/toast/item/toast-item.d.ts +26 -18
- package/dist/toast/item/toast-item.js +55 -48
- package/dist/toast/root/toast-root.d.ts +42 -8
- package/dist/toast/root/toast-root.js +64 -4
- package/dist/toggle/group/toggle-group.d.ts +57 -15
- package/dist/toggle/group/toggle-group.js +69 -9
- package/dist/toggle/root/toggle-root.d.ts +12 -1
- package/dist/toggle/root/toggle-root.js +11 -3
- package/dist/toolbar/root/toolbar-root.d.ts +13 -0
- package/dist/toolbar/root/toolbar-root.js +15 -5
- 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 +42 -17
- package/dist/tooltip/root/tooltip-root.js +50 -9
- package/dist/tour/naming.d.ts +30 -0
- package/dist/tour/naming.js +10 -0
- package/dist/tour/root/tour-root.d.ts +35 -0
- package/dist/tour/root/tour-root.js +56 -5
- package/dist/tour/stop/tour-stop.d.ts +53 -8
- package/dist/tour/stop/tour-stop.js +45 -15
- package/dist/tour/wait.d.ts +11 -0
- package/dist/tour/wait.js +19 -0
- 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/trend/root/trend-root.d.ts +13 -0
- package/dist/trend/root/trend-root.js +14 -9
- 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 +8871 -1286
- package/types/svelte.d.ts +3 -0
- package/types/vue.d.ts +1918 -269
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
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { customElement, HelixElement } from '@fusion.dev/helix-core';
|
|
8
|
+
import { html, nothing } from 'lit';
|
|
9
|
+
import { property, state } from 'lit/decorators.js';
|
|
10
|
+
let HelixHeadlessMenuSection = class HelixHeadlessMenuSection extends HelixElement {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.label = '';
|
|
14
|
+
this.onPage = true;
|
|
15
|
+
this.isMenuSection = true;
|
|
16
|
+
this.heading = false;
|
|
17
|
+
this.readHeading = (event) => {
|
|
18
|
+
this.heading = event.target.assignedNodes().length > 0;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
willUpdate(changed) {
|
|
22
|
+
super.willUpdate(changed);
|
|
23
|
+
if (this.childrenKnown) {
|
|
24
|
+
this.heading = this.knownChildren.some((child) => child.slot === 'heading');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
firstUpdated(changed) {
|
|
28
|
+
super.firstUpdated(changed);
|
|
29
|
+
this.finishHydration();
|
|
30
|
+
}
|
|
31
|
+
render() {
|
|
32
|
+
if (!this.onPage) {
|
|
33
|
+
return nothing;
|
|
34
|
+
}
|
|
35
|
+
return html `<div part="section" role="group" aria-labelledby="heading">
|
|
36
|
+
<div
|
|
37
|
+
id="heading"
|
|
38
|
+
part="heading"
|
|
39
|
+
role="presentation"
|
|
40
|
+
?hidden=${this.label === '' && !this.heading}
|
|
41
|
+
>
|
|
42
|
+
<slot name="heading" @slotchange=${this.readHeading}>${this.label}</slot>
|
|
43
|
+
</div>
|
|
44
|
+
<slot></slot>
|
|
45
|
+
</div>`;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
__decorate([
|
|
49
|
+
property()
|
|
50
|
+
], HelixHeadlessMenuSection.prototype, "label", void 0);
|
|
51
|
+
__decorate([
|
|
52
|
+
property({ attribute: false })
|
|
53
|
+
], HelixHeadlessMenuSection.prototype, "onPage", void 0);
|
|
54
|
+
__decorate([
|
|
55
|
+
state()
|
|
56
|
+
], HelixHeadlessMenuSection.prototype, "heading", void 0);
|
|
57
|
+
HelixHeadlessMenuSection = __decorate([
|
|
58
|
+
customElement('helix-headless-menu-section')
|
|
59
|
+
], HelixHeadlessMenuSection);
|
|
60
|
+
export { HelixHeadlessMenuSection };
|
|
@@ -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,6 +79,9 @@ 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;
|
|
82
87
|
/**
|
|
@@ -218,6 +223,8 @@ export declare class HelixHeadlessMeter extends HelixElement {
|
|
|
218
223
|
* where the arc starts.
|
|
219
224
|
*/
|
|
220
225
|
private renderRound;
|
|
226
|
+
/** A label's words changed, so the name is written again. */
|
|
227
|
+
private readonly renamed;
|
|
221
228
|
protected render(): TemplateResult;
|
|
222
229
|
}
|
|
223
230
|
declare global {
|
|
@@ -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, 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
10
|
const percents = new Map();
|
|
@@ -29,6 +29,9 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
|
|
|
29
29
|
this.showValue = false;
|
|
30
30
|
this.value = 0;
|
|
31
31
|
this.valueText = '';
|
|
32
|
+
this.renamed = () => {
|
|
33
|
+
this.requestUpdate();
|
|
34
|
+
};
|
|
32
35
|
}
|
|
33
36
|
get span() {
|
|
34
37
|
const min = Number.isFinite(this.min) ? this.min : 0;
|
|
@@ -82,7 +85,7 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
|
|
|
82
85
|
willUpdate(changed) {
|
|
83
86
|
super.willUpdate(changed);
|
|
84
87
|
const { max, min } = this.span;
|
|
85
|
-
hostAria(this.internals, { label: this.label, role: 'meter' });
|
|
88
|
+
hostAria(this.internals, { label: slottedWords(this, ['label']) || this.label, role: 'meter' });
|
|
86
89
|
this.internals.ariaValueMin = String(min);
|
|
87
90
|
this.internals.ariaValueMax = String(max);
|
|
88
91
|
this.internals.ariaValueNow = String(this.reading);
|
|
@@ -121,7 +124,7 @@ let HelixHeadlessMeter = class HelixHeadlessMeter extends HelixElement {
|
|
|
121
124
|
const beyond = this.beyond;
|
|
122
125
|
const { max, min } = this.span;
|
|
123
126
|
const at = (value) => `${((value - min) / (max - min)) * 100}%`;
|
|
124
|
-
return html
|
|
127
|
+
return html `<slot name="label" @slotchange=${this.renamed}></slot>${this.shape
|
|
125
128
|
? this.renderRound()
|
|
126
129
|
: html `<div part="track">
|
|
127
130
|
${bounds
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AriaForwardController, HelixElement } from '@fusion.dev/helix-core';
|
|
1
|
+
import { AriaForwardController, HelixElement, KeyboardNavigationController } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/**
|
|
4
4
|
* @summary A set of destinations, with a marker on the current one.
|
|
@@ -22,6 +22,13 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
22
22
|
* Set `orientation="vertical"` to stack the destinations in a column, for a
|
|
23
23
|
* sidebar.
|
|
24
24
|
*
|
|
25
|
+
* Set `arrows` and the arrow keys move focus between the destinations, as
|
|
26
|
+
* Radix's navigation menu does: left and right along a row, up and down a
|
|
27
|
+
* column, Home and End to the ends. A `Megamenu` among them is reached at its
|
|
28
|
+
* trigger. Tab still stops at every link, since a navigation is a list of
|
|
29
|
+
* links and not a single control, and the keys across the other axis are
|
|
30
|
+
* left to the page and to an open panel.
|
|
31
|
+
*
|
|
25
32
|
* @since 0.1.0
|
|
26
33
|
* @status stable
|
|
27
34
|
* @category navigation
|
|
@@ -35,6 +42,13 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
35
42
|
*/
|
|
36
43
|
export declare class HelixHeadlessNavigation extends HelixElement {
|
|
37
44
|
private readonly indicator;
|
|
45
|
+
/**
|
|
46
|
+
* Whether the arrow keys move focus between the destinations.
|
|
47
|
+
*
|
|
48
|
+
* Off by default, so a page whose readers scroll with the arrow keys while
|
|
49
|
+
* a link has focus keeps doing so.
|
|
50
|
+
*/
|
|
51
|
+
arrows: boolean;
|
|
38
52
|
/**
|
|
39
53
|
* The landmark's name, read by screen readers.
|
|
40
54
|
*
|
|
@@ -43,6 +57,7 @@ export declare class HelixHeadlessNavigation extends HelixElement {
|
|
|
43
57
|
* second "Main".
|
|
44
58
|
*/
|
|
45
59
|
label: string;
|
|
60
|
+
protected readonly keys: KeyboardNavigationController;
|
|
46
61
|
/** Carries a host `aria-label` and `aria-labelledby` to the `<nav>`. */
|
|
47
62
|
protected readonly aria: AriaForwardController;
|
|
48
63
|
/**
|