@fusion.dev/helix-headless 0.145.0 → 0.147.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 +12286 -4281
- package/dist/accordion/item/accordion-item.d.ts +51 -18
- package/dist/accordion/item/accordion-item.js +45 -13
- package/dist/accordion/root/accordion-root.d.ts +16 -7
- package/dist/accordion/root/accordion-root.js +3 -3
- package/dist/announcement/root/announcement-root.d.ts +16 -6
- package/dist/announcement/root/announcement-root.js +37 -7
- package/dist/app-header/root/app-header-root.d.ts +7 -2
- package/dist/app-header/root/app-header-root.js +9 -1
- package/dist/app-header/sectioning.d.ts +3 -1
- package/dist/app-header/sectioning.js +3 -2
- package/dist/area-chart/root/area-chart-root.d.ts +18 -1
- package/dist/area-chart/root/area-chart-root.js +11 -3
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/avatar/root/avatar-root.d.ts +31 -1
- package/dist/avatar/root/avatar-root.js +11 -1
- package/dist/badge/root/badge-root.d.ts +60 -7
- package/dist/badge/root/badge-root.js +89 -6
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +48 -20
- package/dist/bar-chart/stack.d.ts +25 -0
- package/dist/bar-chart/stack.js +27 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.js +51 -4
- package/dist/button/root/button-root.d.ts +50 -38
- package/dist/button/root/button-root.js +42 -53
- package/dist/button/submitter.d.ts +27 -0
- package/dist/button/submitter.js +25 -0
- package/dist/button-group/root/button-group-root.d.ts +2 -1
- package/dist/button-group/root/button-group-root.js +5 -1
- package/dist/canvas/node/canvas-node.d.ts +4 -3
- package/dist/canvas/node/canvas-node.js +3 -2
- package/dist/canvas/root/canvas-root.js +2 -2
- package/dist/card/root/card-root.d.ts +36 -4
- package/dist/card/root/card-root.js +29 -10
- package/dist/carousel/root/carousel-root.d.ts +43 -4
- package/dist/carousel/root/carousel-root.js +40 -12
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/message/chat-message.js +5 -4
- package/dist/chat/naming.d.ts +5 -1
- package/dist/chat/naming.js +4 -2
- package/dist/chat/root/chat-root.d.ts +40 -4
- package/dist/chat/root/chat-root.js +32 -6
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +18 -7
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +14 -11
- package/dist/checkbox-group/select-all.d.ts +21 -0
- package/dist/checkbox-group/select-all.js +7 -0
- package/dist/code-block/highlight.d.ts +15 -0
- package/dist/code-block/highlight.js +4 -0
- package/dist/code-block/root/code-block-root.d.ts +79 -10
- package/dist/code-block/root/code-block-root.js +74 -5
- package/dist/color-input/root/color-input-root.d.ts +14 -0
- package/dist/color-input/root/color-input-root.js +17 -7
- package/dist/color-picker/channels.js +1 -2
- package/dist/color-picker/root/color-picker-root.d.ts +53 -16
- package/dist/color-picker/root/color-picker-root.js +155 -46
- package/dist/color-picker/wheel.d.ts +17 -0
- package/dist/color-picker/wheel.js +6 -0
- package/dist/combobox/root/combobox-root.d.ts +56 -0
- package/dist/combobox/root/combobox-root.js +92 -15
- package/dist/command/root/command-root.d.ts +19 -2
- package/dist/command/root/command-root.js +24 -23
- package/dist/copy-button/root/copy-button-root.d.ts +21 -1
- package/dist/copy-button/root/copy-button-root.js +16 -4
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +6 -0
- package/dist/data-table/keys.js +14 -0
- package/dist/data-table/root/data-table-root.d.ts +27 -18
- package/dist/data-table/root/data-table-root.js +31 -57
- package/dist/data-table/tree.d.ts +16 -1
- package/dist/data-table/tree.js +2 -3
- package/dist/date-input/root/date-input-root.d.ts +11 -2
- package/dist/date-input/root/date-input-root.js +26 -12
- package/dist/date-picker/root/date-picker-root.d.ts +14 -9
- package/dist/date-picker/root/date-picker-root.js +33 -22
- package/dist/description-list/item/description-list-item.d.ts +18 -4
- package/dist/description-list/item/description-list-item.js +8 -4
- package/dist/dialog/description.js +15 -1
- package/dist/dialog/root/dialog-root.d.ts +8 -2
- package/dist/dialog/root/dialog-root.js +16 -1
- package/dist/divider/root/divider-root.d.ts +3 -0
- package/dist/divider/root/divider-root.js +2 -1
- package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
- package/dist/donut-chart/root/donut-chart-root.js +55 -1
- package/dist/donut-chart/slice-label.d.ts +35 -0
- package/dist/donut-chart/slice-label.js +11 -0
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +63 -2
- package/dist/drawer/root/drawer-root.js +75 -4
- package/dist/drilldown/item/drilldown-item.d.ts +21 -1
- package/dist/drilldown/item/drilldown-item.js +40 -5
- package/dist/drilldown/root/drilldown-root.d.ts +21 -3
- package/dist/drilldown/root/drilldown-root.js +22 -3
- package/dist/element-events.generated.js +35 -6
- package/dist/empty/root/empty-root.d.ts +34 -2
- package/dist/empty/root/empty-root.js +26 -4
- package/dist/file-input/root/file-input-root.d.ts +99 -8
- package/dist/file-input/root/file-input-root.js +120 -22
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/file-input/status.d.ts +24 -0
- package/dist/file-input/status.js +10 -0
- package/dist/filter-input/chip/filter-chip.d.ts +23 -0
- package/dist/filter-input/chip/filter-chip.js +11 -2
- package/dist/filter-input/menu/filter-menu.d.ts +2 -0
- package/dist/filter-input/menu/filter-menu.js +12 -4
- package/dist/filter-input/root/filter-input-root.d.ts +38 -6
- package/dist/filter-input/root/filter-input-root.js +18 -28
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/options.d.ts +3 -4
- package/dist/format-date/options.js +2 -2
- package/dist/format-date/root/format-date-root.d.ts +27 -17
- package/dist/format-date/root/format-date-root.js +27 -48
- package/dist/heatmap/root/buckets.d.ts +21 -0
- package/dist/heatmap/root/buckets.js +34 -0
- package/dist/heatmap/root/heatmap-root.d.ts +83 -11
- package/dist/heatmap/root/heatmap-root.js +104 -12
- package/dist/icon/index.d.ts +1 -1
- package/dist/icon/index.js +1 -1
- package/dist/icon/registry.d.ts +26 -1
- package/dist/icon/registry.js +12 -1
- package/dist/icon/root/icon-root.d.ts +25 -1
- package/dist/icon/root/icon-root.js +44 -12
- package/dist/icon/root/index.d.ts +1 -1
- package/dist/icon/root/index.js +1 -1
- package/dist/icon/settle.d.ts +7 -0
- package/dist/icon/settle.js +10 -0
- package/dist/icon-button/root/icon-button-root.d.ts +2 -0
- package/dist/image/root/image-root.d.ts +14 -1
- package/dist/image/root/image-root.js +7 -2
- package/dist/input/root/input-root.d.ts +34 -3
- package/dist/input/root/input-root.js +17 -4
- package/dist/kbd/keys.d.ts +29 -0
- package/dist/kbd/keys.js +52 -0
- package/dist/kbd/root/kbd-root.d.ts +52 -1
- package/dist/kbd/root/kbd-root.js +40 -47
- package/dist/legend/hidden-series.d.ts +10 -2
- package/dist/legend/hidden-series.js +5 -2
- package/dist/legend/root/legend-root.d.ts +77 -12
- package/dist/legend/root/legend-root.js +71 -17
- package/dist/lightbox/root/lightbox-root.d.ts +98 -10
- package/dist/lightbox/root/lightbox-root.js +153 -18
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +24 -0
- package/dist/lightbox/zoom.js +18 -0
- package/dist/line-chart/root/line-chart-root.d.ts +38 -1
- package/dist/line-chart/root/line-chart-root.js +31 -3
- package/dist/list/item/list-item.d.ts +2 -0
- package/dist/list/item/list-item.js +11 -2
- package/dist/list/root/list-root.d.ts +70 -13
- package/dist/list/root/list-root.js +91 -13
- package/dist/list/selection.d.ts +54 -7
- package/dist/list/selection.js +32 -7
- package/dist/listbox/root/listbox-root.d.ts +44 -4
- package/dist/listbox/root/listbox-root.js +72 -34
- package/dist/loader/busy.d.ts +10 -0
- package/dist/loader/busy.js +11 -0
- package/dist/loader/root/loader-root.d.ts +9 -2
- package/dist/loader/root/loader-root.js +23 -3
- package/dist/megamenu/hand-over.d.ts +75 -0
- package/dist/megamenu/hand-over.js +67 -0
- package/dist/megamenu/root/megamenu-root.d.ts +80 -15
- package/dist/megamenu/root/megamenu-root.js +76 -19
- package/dist/menu/item/menu-item.d.ts +51 -2
- package/dist/menu/item/menu-item.js +50 -26
- package/dist/menu/root/menu-root.d.ts +17 -0
- package/dist/menu/root/menu-root.js +2 -2
- package/dist/meter/root/meter-root.d.ts +62 -1
- package/dist/meter/root/meter-root.js +38 -16
- package/dist/navigation/root/navigation-root.d.ts +2 -1
- package/dist/navigation/root/navigation-root.js +2 -2
- package/dist/notifications/root/notifications-root.d.ts +20 -4
- package/dist/notifications/root/notifications-root.js +30 -8
- package/dist/number-input/grain.d.ts +28 -0
- package/dist/number-input/grain.js +14 -0
- package/dist/number-input/root/number-input-root.d.ts +34 -9
- package/dist/number-input/root/number-input-root.js +31 -25
- package/dist/object-inspector/root/object-inspector-root.d.ts +88 -33
- package/dist/object-inspector/root/object-inspector-root.js +134 -92
- package/dist/object-inspector/rows.d.ts +18 -0
- package/dist/object-inspector/rows.js +33 -0
- package/dist/option/index.d.ts +1 -0
- package/dist/option/index.js +1 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/option/separator/option-separator.d.ts +30 -0
- package/dist/option/separator/option-separator.js +21 -0
- package/dist/outline/root/outline-root.d.ts +30 -0
- package/dist/outline/root/outline-root.js +17 -13
- package/dist/pagination/size/pagination-size.d.ts +6 -0
- package/dist/pagination/size/pagination-size.js +5 -3
- package/dist/pin-input/code.d.ts +37 -0
- package/dist/pin-input/code.js +25 -0
- package/dist/pin-input/root/pin-input-root.d.ts +116 -115
- package/dist/pin-input/root/pin-input-root.js +163 -155
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +34 -0
- package/dist/popover/root/popover-root.d.ts +64 -8
- package/dist/popover/root/popover-root.js +67 -4
- package/dist/progress/root/progress-root.d.ts +47 -0
- package/dist/progress/root/progress-root.js +34 -16
- package/dist/qr-code/export.d.ts +45 -1
- package/dist/qr-code/export.js +28 -0
- package/dist/qr-code/name.d.ts +11 -0
- package/dist/qr-code/name.js +7 -0
- package/dist/qr-code/root/qr-code-root.d.ts +36 -11
- package/dist/qr-code/root/qr-code-root.js +58 -11
- package/dist/quote/marks.d.ts +8 -0
- package/dist/quote/marks.js +5 -0
- package/dist/quote/root/quote-root.d.ts +14 -2
- package/dist/quote/root/quote-root.js +23 -1
- package/dist/radio/group/radio-group.d.ts +15 -0
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +7 -2
- package/dist/rating/root/rating-root.d.ts +30 -12
- package/dist/rating/root/rating-root.js +27 -27
- package/dist/scatter-chart/fit.d.ts +15 -0
- package/dist/scatter-chart/fit.js +35 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +51 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +64 -24
- package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
- package/dist/scroll-area/root/scroll-area-root.js +57 -173
- package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
- package/dist/scroll-area/scrollbar-controller.js +172 -0
- package/dist/scroll-area/scrollbar.d.ts +27 -8
- package/dist/scroll-area/scrollbar.js +10 -1
- package/dist/select/align.d.ts +47 -0
- package/dist/select/align.js +7 -0
- package/dist/select/root/select-root.d.ts +71 -0
- package/dist/select/root/select-root.js +78 -6
- package/dist/skeleton/root/skeleton-root.d.ts +3 -0
- package/dist/skeleton/root/skeleton-root.js +4 -2
- package/dist/skip-link/root/skip-link-root.js +2 -2
- package/dist/slider/root/slider-root.d.ts +59 -5
- package/dist/slider/root/slider-root.js +45 -3
- package/dist/sparkline/readings.d.ts +36 -0
- package/dist/sparkline/readings.js +36 -0
- package/dist/sparkline/root/sparkline-root.d.ts +121 -7
- package/dist/sparkline/root/sparkline-root.js +160 -26
- package/dist/speed-dial/item/speed-dial-item.d.ts +1 -1
- package/dist/speed-dial/item/speed-dial-item.js +2 -2
- package/dist/speed-dial/root/speed-dial-root.d.ts +6 -0
- package/dist/speed-dial/root/speed-dial-root.js +11 -3
- package/dist/splitter/root/splitter-root.d.ts +10 -12
- package/dist/splitter/root/splitter-root.js +211 -204
- package/dist/stat/root/stat-root.d.ts +14 -5
- package/dist/stat/root/stat-root.js +21 -5
- package/dist/steps/reach.d.ts +5 -0
- package/dist/steps/reach.js +3 -0
- package/dist/steps/root/steps-root.d.ts +56 -3
- package/dist/steps/root/steps-root.js +50 -6
- package/dist/steps/step/step.d.ts +8 -0
- package/dist/steps/step/step.js +8 -3
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +6 -10
- package/dist/table/column/table-column.js +8 -20
- package/dist/table/root/table-root.d.ts +31 -10
- package/dist/table/root/table-root.js +14 -18
- package/dist/table/row/table-row.d.ts +24 -0
- package/dist/table/row/table-row.js +37 -1
- package/dist/tabs/panel/tab-panel.d.ts +16 -3
- package/dist/tabs/panel/tab-panel.js +34 -5
- package/dist/tabs/root/tabs-root.d.ts +17 -3
- package/dist/tabs/root/tabs-root.js +1 -1
- package/dist/tabs/tab/tab.d.ts +5 -0
- package/dist/tabs/tab/tab.js +5 -2
- package/dist/tag/group/tag-group.d.ts +44 -5
- package/dist/tag/group/tag-group.js +60 -9
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +41 -2
- package/dist/textarea/root/textarea-root.js +39 -1
- package/dist/time-input/root/time-input-root.d.ts +10 -2
- package/dist/time-input/root/time-input-root.js +24 -13
- package/dist/time-picker/root/time-picker-root.d.ts +28 -17
- package/dist/time-picker/root/time-picker-root.js +18 -29
- package/dist/time-picker/wheel-name.d.ts +9 -0
- package/dist/time-picker/wheel-name.js +15 -0
- package/dist/timeline/group/timeline-group.js +2 -2
- package/dist/toast/item/toast-item.d.ts +16 -3
- package/dist/toast/item/toast-item.js +22 -6
- package/dist/toast/root/toast-root.d.ts +34 -4
- package/dist/toast/root/toast-root.js +74 -13
- package/dist/toast/words.d.ts +12 -0
- package/dist/toast/words.js +25 -0
- package/dist/toggle/group/toggle-group.d.ts +52 -7
- package/dist/toggle/group/toggle-group.js +58 -44
- package/dist/toggle/root/toggle-root.js +2 -4
- package/dist/toolbar/root/toolbar-root.d.ts +21 -5
- package/dist/toolbar/root/toolbar-root.js +52 -8
- package/dist/tooltip/root/tooltip-root.d.ts +20 -3
- package/dist/tooltip/root/tooltip-root.js +18 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +45 -2
- package/dist/tour/root/tour-root.js +53 -8
- package/dist/tour/stop/tour-stop.d.ts +3 -0
- package/dist/tour/stop/tour-stop.js +3 -3
- package/dist/tree/item/tree-item.d.ts +7 -3
- package/dist/tree/item/tree-item.js +3 -0
- package/dist/tree/root/tree-root.d.ts +24 -3
- package/dist/tree/root/tree-root.js +32 -13
- package/dist/tree/selection.js +2 -15
- package/dist/trend/figure.d.ts +16 -0
- package/dist/trend/figure.js +8 -0
- package/dist/trend/root/trend-root.d.ts +83 -19
- package/dist/trend/root/trend-root.js +59 -8
- package/dist/video/media-events.d.ts +13 -18
- package/dist/video/media-events.js +1 -5
- package/dist/video/root/extra-controls.d.ts +12 -0
- package/dist/video/root/extra-controls.js +6 -2
- package/dist/video/root/video-root.d.ts +23 -6
- package/dist/video/root/video-root.js +19 -10
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +17 -1
- package/dist/video-playlist/root/video-playlist-root.js +3 -0
- package/dist/virtual-list/fill.d.ts +11 -8
- package/dist/virtual-list/fill.js +10 -17
- package/dist/virtual-list/keys.d.ts +16 -7
- package/dist/virtual-list/keys.js +17 -6
- package/dist/virtual-list/plan.d.ts +65 -0
- package/dist/virtual-list/plan.js +27 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +136 -13
- package/dist/virtual-list/root/virtual-list-root.js +218 -51
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +7441 -1458
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +1501 -326
- package/dist/chat/relative-clock.d.ts +0 -39
- package/dist/chat/relative-clock.js +0 -31
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -27,7 +27,9 @@ declare const HelixHeadlessListbox_base: (new (...args: any[]) => import("@fusio
|
|
|
27
27
|
* highlighted option, Shift with an arrow adds the option it moves to, Shift
|
|
28
28
|
* with Home or End adds every option from the highlight to that end, and
|
|
29
29
|
* Control+A or Command+A chooses every option, or none where all are chosen.
|
|
30
|
-
* In a filter field, Space, Home, End and letters edit the text
|
|
30
|
+
* In a filter field, Space, Home, End and letters edit the text, and with
|
|
31
|
+
* `multiple`, Control with Shift and Home or End adds every option from the
|
|
32
|
+
* highlight to that end.
|
|
31
33
|
*
|
|
32
34
|
* An option with `href` is a link: Enter or a press follows it and selects
|
|
33
35
|
* nothing, and moving onto it with the arrows does not follow it.
|
|
@@ -44,18 +46,22 @@ declare const HelixHeadlessListbox_base: (new (...args: any[]) => import("@fusio
|
|
|
44
46
|
*
|
|
45
47
|
* @slot - The options, and any groups of them.
|
|
46
48
|
* @slot empty - What the list shows when it has no options to show, for content richer than `empty-text`.
|
|
49
|
+
* @slot error - What the list shows while `load-error` is set, for content richer than its text.
|
|
47
50
|
* @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
|
|
48
51
|
* @slot filter-icon - The icon in the filter field. Defaults to a magnifying glass.
|
|
49
52
|
* @slot hint - The hint, for content richer than plain text.
|
|
50
53
|
* @slot label - The label, for content richer than plain text.
|
|
51
54
|
* @slot loading - What the list shows while its options load, for content richer than `loading-text`.
|
|
55
|
+
* @slot no-results - What the list shows when a filter hides every option, for content richer than `no-results-text`.
|
|
52
56
|
*
|
|
53
57
|
* @event {Event} change - Fired after the value changes.
|
|
54
58
|
* @event {HelixBeforeChangeEvent} helix-before-change - Fired when the value is about to change, and cancelable.
|
|
55
59
|
* @event {HelixFilterEvent} helix-filter - Fired before the list is filtered, and cancelable.
|
|
60
|
+
* @event {HelixLoadMoreEvent} helix-load-more - Fired once the list is scrolled within a screen of its end, once for each number of options, and not while `loading` is set. Add the next page of options and set `loading` while you fetch it.
|
|
56
61
|
* @event {Event} input - Fired after the value changes.
|
|
57
62
|
*
|
|
58
|
-
* @csspart empty - The text shown when the filter hides every
|
|
63
|
+
* @csspart empty - The text shown when the list has no options to show, or the filter hides every one. `:state(no-results)` is set for the second.
|
|
64
|
+
* @csspart error - The text shown while `load-error` is set.
|
|
59
65
|
* @csspart feedback - The message that says what is wrong with the value.
|
|
60
66
|
* @csspart filter-icon - The icon beside the filter field.
|
|
61
67
|
* @csspart filter-mark - The default icon beside the filter field, shown when none is slotted.
|
|
@@ -68,8 +74,10 @@ declare const HelixHeadlessListbox_base: (new (...args: any[]) => import("@fusio
|
|
|
68
74
|
* @csspart search-field - The filter field.
|
|
69
75
|
*
|
|
70
76
|
* @cssstate empty - The list has no options to show: none were given, or the filter hid every one.
|
|
77
|
+
* @cssstate error - While `load-error` is set.
|
|
71
78
|
* @cssstate invalid - The control has an error to show, from the browser's validation or from your `feedback`.
|
|
72
79
|
* @cssstate loading - While `loading` is set.
|
|
80
|
+
* @cssstate no-results - A filter hid every option of a list that has some.
|
|
73
81
|
*/
|
|
74
82
|
export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
75
83
|
protected readonly aria: AriaForwardController;
|
|
@@ -130,6 +138,14 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
130
138
|
* Placeholder text for the filter field.
|
|
131
139
|
*/
|
|
132
140
|
filterLabel: string;
|
|
141
|
+
/**
|
|
142
|
+
* What the list says when its options could not be loaded, such as after a
|
|
143
|
+
* request to a server fails. Empty is no error.
|
|
144
|
+
*
|
|
145
|
+
* Set, it shows under any options there are, in place of `empty-text` and
|
|
146
|
+
* `loading-text`, and a screen reader hears it. Clear it when you ask again.
|
|
147
|
+
*/
|
|
148
|
+
loadError: string;
|
|
133
149
|
/**
|
|
134
150
|
* Stops the arrow keys from choosing each option they move to. Enter, Space
|
|
135
151
|
* or a click chooses the highlighted option.
|
|
@@ -143,6 +159,13 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
143
159
|
* Whether more than one option can be chosen.
|
|
144
160
|
*/
|
|
145
161
|
multiple: boolean;
|
|
162
|
+
/**
|
|
163
|
+
* The text shown when a filter hides every option of a list that has some.
|
|
164
|
+
*
|
|
165
|
+
* Absent, the list says `empty-text` in both cases. Set it to tell "nothing
|
|
166
|
+
* matches what you typed" from "there is nothing here".
|
|
167
|
+
*/
|
|
168
|
+
noResultsText?: string;
|
|
146
169
|
/**
|
|
147
170
|
* What a screen reader hears when a filter leaves one option. `{count}` is
|
|
148
171
|
* the count.
|
|
@@ -265,7 +288,8 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
265
288
|
*/
|
|
266
289
|
get options(): HelixHeadlessOption[];
|
|
267
290
|
/**
|
|
268
|
-
*
|
|
291
|
+
* The elements of one kind in the list: its options, its groups or its
|
|
292
|
+
* rules. Walks the tree, and walks *through* a slot when it meets one.
|
|
269
293
|
*
|
|
270
294
|
* Through a slot because that is how this gets composed. `Select` renders a
|
|
271
295
|
* listbox in its own shadow root with a slot inside it, so the options are
|
|
@@ -273,7 +297,7 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
273
297
|
* `querySelectorAll` finds the slot and no options at all, and the whole
|
|
274
298
|
* component comes up empty.
|
|
275
299
|
*/
|
|
276
|
-
private
|
|
300
|
+
private among;
|
|
277
301
|
/** The groups, found the same way and for the same reason. */
|
|
278
302
|
private get groups();
|
|
279
303
|
/** The options a filter has left showing. */
|
|
@@ -430,6 +454,15 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
430
454
|
private takeFilter;
|
|
431
455
|
/** Filters at once on a filter still waiting out `filterDelay`. */
|
|
432
456
|
private flushFilter;
|
|
457
|
+
/** The number of options the list last asked for more at. */
|
|
458
|
+
private askedAt;
|
|
459
|
+
/**
|
|
460
|
+
* Asks for more once the reader is within a screen of the end, React Aria's
|
|
461
|
+
* `onLoadMore`, by core's `endInSight`, the rule Virtual List asks too: once
|
|
462
|
+
* for each number of options, so a scroll that goes on asks again only after
|
|
463
|
+
* the next page arrived, and never while loading.
|
|
464
|
+
*/
|
|
465
|
+
private readonly handleScroll;
|
|
433
466
|
/** Requests a new filter, and returns whether the request went through. */
|
|
434
467
|
requestFilter(next: string): boolean;
|
|
435
468
|
/**
|
|
@@ -485,6 +518,13 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
485
518
|
* the live region still says it.
|
|
486
519
|
*/
|
|
487
520
|
protected renderStatus(hasContent: boolean): TemplateResult | typeof nothing;
|
|
521
|
+
/**
|
|
522
|
+
* Whether a filter hid every option of a list that has some, which is a
|
|
523
|
+
* different thing to say from a list that has none.
|
|
524
|
+
*/
|
|
525
|
+
private get noResults();
|
|
526
|
+
/** The error, or what a filter that hid everything says, before the shared words. */
|
|
527
|
+
protected renderLive(hasContent: boolean): TemplateResult;
|
|
488
528
|
protected render(): TemplateResult;
|
|
489
529
|
}
|
|
490
530
|
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 { AriaForwardController, countLabel, customElement, DelayController, DisabledCascadeController, HelixFilterEvent, HelixFormElement, hostAria, MixinCollection, MixinControllerValue, MixinField, rangeAdd, reportValues, requestChange, scrollItemIntoView, Typeahead, typesCharacter, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, countLabel, customElement, DelayController, DisabledCascadeController, endInSight, HelixFilterEvent, HelixFormElement, HelixLoadMoreEvent, hostAria, MixinCollection, MixinControllerValue, MixinField, rangeAdd, reportValues, requestChange, scrollItemIntoView, selectsAll, Typeahead, typesCharacter, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { magnifyingGlass } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -70,6 +70,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
70
70
|
this.filterable = false;
|
|
71
71
|
this.filterDelay = 0;
|
|
72
72
|
this.filterLabel = 'Filter';
|
|
73
|
+
this.loadError = '';
|
|
73
74
|
this.manual = false;
|
|
74
75
|
this.multiple = false;
|
|
75
76
|
this.resultLabel = '{count} result';
|
|
@@ -118,11 +119,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
118
119
|
}
|
|
119
120
|
return;
|
|
120
121
|
}
|
|
121
|
-
if (this.multiple &&
|
|
122
|
-
!typing &&
|
|
123
|
-
event.key.toLowerCase() === 'a' &&
|
|
124
|
-
(event.ctrlKey || event.metaKey) &&
|
|
125
|
-
!event.altKey) {
|
|
122
|
+
if (this.multiple && !typing && selectsAll(event)) {
|
|
126
123
|
event.preventDefault();
|
|
127
124
|
const reachable = shown.map((option) => option.value);
|
|
128
125
|
const all = reachable.every((value) => this.values.includes(value));
|
|
@@ -138,7 +135,12 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
138
135
|
}
|
|
139
136
|
return;
|
|
140
137
|
}
|
|
141
|
-
|
|
138
|
+
const fieldRange = typing &&
|
|
139
|
+
this.multiple &&
|
|
140
|
+
event.shiftKey &&
|
|
141
|
+
(event.ctrlKey || event.metaKey) &&
|
|
142
|
+
(event.key === 'Home' || event.key === 'End');
|
|
143
|
+
if (!fieldRange && !(typing ? FIELD_MOVES : MOVES).has(event.key)) {
|
|
142
144
|
return;
|
|
143
145
|
}
|
|
144
146
|
event.preventDefault();
|
|
@@ -169,7 +171,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
169
171
|
if (target) {
|
|
170
172
|
this.arrive(target.value);
|
|
171
173
|
const ranged = event.key === 'Home' || event.key === 'End';
|
|
172
|
-
if (this.multiple && !typing && event.shiftKey && ranged) {
|
|
174
|
+
if (this.multiple && (!typing || fieldRange) && event.shiftKey && ranged) {
|
|
173
175
|
const taken = rangeAdd(this.values, shown.map((option) => option.value), at, next);
|
|
174
176
|
if (taken) {
|
|
175
177
|
this.requestValue(taken.join(','));
|
|
@@ -192,6 +194,22 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
192
194
|
this.takeFilter(control);
|
|
193
195
|
};
|
|
194
196
|
this.filtering = new DelayController(this, { renders: false });
|
|
197
|
+
this.askedAt = -1;
|
|
198
|
+
this.handleScroll = (event) => {
|
|
199
|
+
const items = event.currentTarget;
|
|
200
|
+
const count = this.options.length;
|
|
201
|
+
if (this.loading ||
|
|
202
|
+
!endInSight({
|
|
203
|
+
askedAt: this.askedAt,
|
|
204
|
+
count,
|
|
205
|
+
remaining: items.scrollHeight - items.scrollTop - items.clientHeight,
|
|
206
|
+
screen: items.clientHeight,
|
|
207
|
+
})) {
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
this.askedAt = count;
|
|
211
|
+
this.dispatchEvent(new HelixLoadMoreEvent());
|
|
212
|
+
};
|
|
195
213
|
this.handleFilterKeydown = (event) => {
|
|
196
214
|
if (event.key === 'Enter' || FIELD_MOVES.has(event.key)) {
|
|
197
215
|
this.flushFilter();
|
|
@@ -280,40 +298,24 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
280
298
|
return this.multiple ? 'select-multiple' : 'select-one';
|
|
281
299
|
}
|
|
282
300
|
get options() {
|
|
283
|
-
return this.
|
|
301
|
+
return this.among((node) => node instanceof HelixHeadlessOption, this.children);
|
|
284
302
|
}
|
|
285
|
-
|
|
303
|
+
among(is, nodes) {
|
|
286
304
|
const found = [];
|
|
287
305
|
for (const node of nodes) {
|
|
288
|
-
if (node
|
|
306
|
+
if (is(node)) {
|
|
289
307
|
found.push(node);
|
|
290
308
|
}
|
|
291
|
-
else if (node instanceof HTMLSlotElement) {
|
|
292
|
-
found.push(...this.collect(node.assignedElements({ flatten: true })));
|
|
293
|
-
}
|
|
294
309
|
else {
|
|
295
|
-
found.push(...this.
|
|
310
|
+
found.push(...this.among(is, node instanceof HTMLSlotElement
|
|
311
|
+
? node.assignedElements({ flatten: true })
|
|
312
|
+
: node.children));
|
|
296
313
|
}
|
|
297
314
|
}
|
|
298
315
|
return found;
|
|
299
316
|
}
|
|
300
317
|
get groups() {
|
|
301
|
-
|
|
302
|
-
const walk = (nodes) => {
|
|
303
|
-
for (const node of nodes) {
|
|
304
|
-
if (node instanceof HelixHeadlessOptionGroup) {
|
|
305
|
-
found.push(node);
|
|
306
|
-
}
|
|
307
|
-
if (node instanceof HTMLSlotElement) {
|
|
308
|
-
walk(node.assignedElements({ flatten: true }));
|
|
309
|
-
}
|
|
310
|
-
else {
|
|
311
|
-
walk(node.children);
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
};
|
|
315
|
-
walk(this.children);
|
|
316
|
-
return found;
|
|
318
|
+
return this.among((node) => node instanceof HelixHeadlessOptionGroup, this.children);
|
|
317
319
|
}
|
|
318
320
|
get shown() {
|
|
319
321
|
return this.options.filter((option) => !option.hidden);
|
|
@@ -385,9 +387,12 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
385
387
|
option.selected = chosen.has(option.value);
|
|
386
388
|
}
|
|
387
389
|
for (const group of this.groups) {
|
|
388
|
-
const inside = this.
|
|
390
|
+
const inside = this.among((node) => node instanceof HelixHeadlessOption, group.children);
|
|
389
391
|
group.hidden = inside.length > 0 && inside.every((option) => option.hidden);
|
|
390
392
|
}
|
|
393
|
+
for (const rule of this.among((node) => node.localName.endsWith('-option-separator'), this.children)) {
|
|
394
|
+
rule.hidden = needle !== '';
|
|
395
|
+
}
|
|
391
396
|
const shown = this.shown;
|
|
392
397
|
const rescue = !this.parked && (needle !== '' || this.activeValue !== '');
|
|
393
398
|
if (rescue && !shown.some((option) => option.value === this.activeValue)) {
|
|
@@ -471,6 +476,8 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
471
476
|
}
|
|
472
477
|
this.toggleState('empty', !this.showsOptions);
|
|
473
478
|
this.toggleState('loading', this.loading);
|
|
479
|
+
this.toggleState('error', this.loadError !== '');
|
|
480
|
+
this.toggleState('no-results', this.noResults);
|
|
474
481
|
}
|
|
475
482
|
seedDeclared() {
|
|
476
483
|
if (this.owned || this.defaultValue !== '' || this.hasAttribute('default-value')) {
|
|
@@ -545,13 +552,37 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
545
552
|
: true;
|
|
546
553
|
}
|
|
547
554
|
renderStatus(hasContent) {
|
|
555
|
+
if (this.loadError !== '') {
|
|
556
|
+
return html `<p part="error"><slot name="error">${this.loadError}</slot></p>`;
|
|
557
|
+
}
|
|
548
558
|
if (!this.loading && hasContent) {
|
|
549
559
|
return nothing;
|
|
550
560
|
}
|
|
551
|
-
|
|
552
|
-
|
|
561
|
+
if (this.loading) {
|
|
562
|
+
return html `<p part="loading"><slot name="loading">${this.loadingText}</slot></p>`;
|
|
563
|
+
}
|
|
564
|
+
const given = this.noResultsText !== undefined ||
|
|
565
|
+
this.querySelector?.(':scope > [slot="no-results"]') != null;
|
|
566
|
+
return this.noResults && given
|
|
567
|
+
? html `<p part="empty"><slot name="no-results">${this.noResultsText ?? this.emptyText}</slot></p>`
|
|
553
568
|
: html `<p part="empty"><slot name="empty">${this.emptyText}</slot></p>`;
|
|
554
569
|
}
|
|
570
|
+
get noResults() {
|
|
571
|
+
return (this.counted &&
|
|
572
|
+
!this.loading &&
|
|
573
|
+
this.filter !== '' &&
|
|
574
|
+
this.options.length > 0 &&
|
|
575
|
+
!this.hasMatches);
|
|
576
|
+
}
|
|
577
|
+
renderLive(hasContent) {
|
|
578
|
+
if (this.loadError !== '') {
|
|
579
|
+
return html `<span part="live" role="status">${this.loadError}</span>`;
|
|
580
|
+
}
|
|
581
|
+
if (this.noResults && this.noResultsText !== undefined) {
|
|
582
|
+
return html `<span part="live" role="status">${this.noResultsText}</span>`;
|
|
583
|
+
}
|
|
584
|
+
return super.renderLive(hasContent);
|
|
585
|
+
}
|
|
555
586
|
render() {
|
|
556
587
|
const shown = this.showsOptions;
|
|
557
588
|
return html `${this.renderGroupLabel()}
|
|
@@ -588,6 +619,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
588
619
|
aria-required=${this.required ? 'true' : nothing}
|
|
589
620
|
${''}
|
|
590
621
|
tabindex=${this.filterable ? nothing : this.isDisabled ? -1 : 0}
|
|
622
|
+
@scroll=${this.handleScroll}
|
|
591
623
|
>
|
|
592
624
|
<slot @slotchange=${() => this.place()}></slot>
|
|
593
625
|
${this.renderStatus(shown)}
|
|
@@ -616,12 +648,18 @@ __decorate([
|
|
|
616
648
|
__decorate([
|
|
617
649
|
property({ attribute: 'filter-label' })
|
|
618
650
|
], HelixHeadlessListbox.prototype, "filterLabel", void 0);
|
|
651
|
+
__decorate([
|
|
652
|
+
property({ attribute: 'load-error' })
|
|
653
|
+
], HelixHeadlessListbox.prototype, "loadError", void 0);
|
|
619
654
|
__decorate([
|
|
620
655
|
property({ type: Boolean })
|
|
621
656
|
], HelixHeadlessListbox.prototype, "manual", void 0);
|
|
622
657
|
__decorate([
|
|
623
658
|
property({ reflect: true, type: Boolean })
|
|
624
659
|
], HelixHeadlessListbox.prototype, "multiple", void 0);
|
|
660
|
+
__decorate([
|
|
661
|
+
property({ attribute: 'no-results-text' })
|
|
662
|
+
], HelixHeadlessListbox.prototype, "noResultsText", void 0);
|
|
625
663
|
__decorate([
|
|
626
664
|
property({ attribute: 'result-label' })
|
|
627
665
|
], HelixHeadlessListbox.prototype, "resultLabel", void 0);
|
package/dist/loader/busy.d.ts
CHANGED
|
@@ -15,3 +15,13 @@
|
|
|
15
15
|
export declare const claimBusy: (region: Element) => void;
|
|
16
16
|
/** Takes a claim back, and the attribute with the last one. */
|
|
17
17
|
export declare const releaseBusy: (region: Element) => void;
|
|
18
|
+
/**
|
|
19
|
+
* Calls `found` with the region `find` answers once it is in `root`, and
|
|
20
|
+
* returns the call that stops waiting.
|
|
21
|
+
*
|
|
22
|
+
* For a loader whose region is not on the page yet: a framework often draws
|
|
23
|
+
* the loader before the list it stands for, and a region looked up once, a
|
|
24
|
+
* frame after connecting, was never marked. Watches for children and ids being
|
|
25
|
+
* written, and stops at the first answer.
|
|
26
|
+
*/
|
|
27
|
+
export declare const awaitRegion: (root: Node, find: () => Element | null, found: (region: Element) => void) => (() => void);
|
package/dist/loader/busy.js
CHANGED
|
@@ -22,3 +22,14 @@ export const releaseBusy = (region) => {
|
|
|
22
22
|
CLAIMS.set(region, held - 1);
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
|
+
export const awaitRegion = (root, find, found) => {
|
|
26
|
+
const observer = new MutationObserver(() => {
|
|
27
|
+
const region = find();
|
|
28
|
+
if (region) {
|
|
29
|
+
observer.disconnect();
|
|
30
|
+
found(region);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
observer.observe(root, { attributeFilter: ['id'], childList: true, subtree: true });
|
|
34
|
+
return () => observer.disconnect();
|
|
35
|
+
};
|
|
@@ -22,11 +22,12 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
22
22
|
* **`for` names the region being loaded**, and the loader sets
|
|
23
23
|
* `aria-busy="true"` on it for as long as the loader is on the page, so a
|
|
24
24
|
* screen reader waits for the region rather than reading it half filled. Two
|
|
25
|
-
* loaders in one region hold it busy until the last one leaves.
|
|
25
|
+
* loaders in one region hold it busy until the last one leaves. A region drawn
|
|
26
|
+
* after the loader is marked when it arrives.
|
|
26
27
|
*
|
|
27
28
|
* **`delay` keeps a quick load from flashing a loader.** The loader stays
|
|
28
29
|
* hidden, and silent, for that many milliseconds, and appears only if the work
|
|
29
|
-
* is still going.
|
|
30
|
+
* is still going. While it waits it carries `:state(waiting)`.
|
|
30
31
|
*
|
|
31
32
|
* @since 0.1.0
|
|
32
33
|
* @status stable
|
|
@@ -40,6 +41,8 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
40
41
|
* @csspart mark - The region that holds the slotted content at the center.
|
|
41
42
|
* @csspart svg - The rotating circle pair.
|
|
42
43
|
* @csspart track - The full circle behind the indicator.
|
|
44
|
+
*
|
|
45
|
+
* @cssstate waiting - The loader is waiting out its `delay`, hidden and silent.
|
|
43
46
|
*/
|
|
44
47
|
export declare class HelixHeadlessLoader extends HelixElement {
|
|
45
48
|
/**
|
|
@@ -67,6 +70,10 @@ export declare class HelixHeadlessLoader extends HelixElement {
|
|
|
67
70
|
private readonly due;
|
|
68
71
|
/** The region this loader marked busy, so it is the one released. */
|
|
69
72
|
private region;
|
|
73
|
+
/** Stops waiting for a region `for` names that is not on the page yet. */
|
|
74
|
+
private stopAwaiting;
|
|
75
|
+
/** Whether `for` has named an element while the loader was on the page. */
|
|
76
|
+
private found;
|
|
70
77
|
/** Whether the loader is still waiting out its `delay`. */
|
|
71
78
|
private get waiting();
|
|
72
79
|
connectedCallback(): void;
|
|
@@ -4,10 +4,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, DelayController, elementById, HelixElement, hostAria, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, DelayController, elementById, HelixElement, hostAria, reportRuntime, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
|
-
import { claimBusy, releaseBusy } from '../busy.js';
|
|
10
|
+
import { awaitRegion, claimBusy, releaseBusy } from '../busy.js';
|
|
11
11
|
let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
12
12
|
constructor() {
|
|
13
13
|
super(...arguments);
|
|
@@ -16,6 +16,7 @@ let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
|
16
16
|
this.label = 'Loading';
|
|
17
17
|
this.due = new DelayController(this);
|
|
18
18
|
this.region = null;
|
|
19
|
+
this.found = false;
|
|
19
20
|
}
|
|
20
21
|
get waiting() {
|
|
21
22
|
return this.delay > 0 && !this.due.elapsed;
|
|
@@ -29,10 +30,26 @@ let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
|
29
30
|
}
|
|
30
31
|
disconnectedCallback() {
|
|
31
32
|
super.disconnectedCallback();
|
|
33
|
+
if (this.stopAwaiting && !this.found) {
|
|
34
|
+
reportRuntime({
|
|
35
|
+
kind: 'missing-target',
|
|
36
|
+
message: `<${this.localName} for="${this.for}"> named no element in its tree while it was on ` +
|
|
37
|
+
'the page, so no region was marked busy. Give the region that id.',
|
|
38
|
+
tag: this.localName,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
this.stopAwaiting?.();
|
|
42
|
+
this.stopAwaiting = undefined;
|
|
32
43
|
this.release();
|
|
33
44
|
}
|
|
34
45
|
mark() {
|
|
35
|
-
|
|
46
|
+
this.stopAwaiting?.();
|
|
47
|
+
this.stopAwaiting = undefined;
|
|
48
|
+
const named = this.isConnected && this.for !== '';
|
|
49
|
+
const region = named ? elementById(this, this.for) : null;
|
|
50
|
+
if (named && !region) {
|
|
51
|
+
this.stopAwaiting = awaitRegion(this.getRootNode(), () => elementById(this, this.for), () => this.mark());
|
|
52
|
+
}
|
|
36
53
|
if (region === this.region) {
|
|
37
54
|
return;
|
|
38
55
|
}
|
|
@@ -40,6 +57,7 @@ let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
|
40
57
|
if (region) {
|
|
41
58
|
claimBusy(region);
|
|
42
59
|
this.region = region;
|
|
60
|
+
this.found = true;
|
|
43
61
|
}
|
|
44
62
|
}
|
|
45
63
|
release() {
|
|
@@ -51,6 +69,7 @@ let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
|
51
69
|
updated(changed) {
|
|
52
70
|
super.updated(changed);
|
|
53
71
|
if (changed.has('for') && changed.get('for') !== undefined) {
|
|
72
|
+
this.found = false;
|
|
54
73
|
this.mark();
|
|
55
74
|
}
|
|
56
75
|
}
|
|
@@ -59,6 +78,7 @@ let HelixHeadlessLoader = class HelixHeadlessLoader extends HelixElement {
|
|
|
59
78
|
hostAria(this.internals, { label: this.label, role: 'progressbar' });
|
|
60
79
|
this.internals.ariaBusy = 'true';
|
|
61
80
|
this.internals.ariaHidden = this.waiting ? 'true' : null;
|
|
81
|
+
this.toggleState('waiting', this.waiting);
|
|
62
82
|
}
|
|
63
83
|
render() {
|
|
64
84
|
return html `<svg part="svg" viewBox="0 0 24 24" aria-hidden="true" ?hidden=${this.waiting}>
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/** Which way a panel moved when another took its place along the bar. */
|
|
2
|
+
export type Motion = 'from-end' | 'from-start' | 'to-end' | 'to-start';
|
|
3
|
+
/** What a hand-over asks of a megamenu. */
|
|
4
|
+
export interface Handed extends Node {
|
|
5
|
+
/** Asks the panel to open or close, and returns whether it did. */
|
|
6
|
+
requestOpen(open: boolean): boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The bar's one open panel, handed from one megamenu to the next.
|
|
10
|
+
*
|
|
11
|
+
* A page has one panel open at a time: a nav bar whose Products panel is still
|
|
12
|
+
* down while Solutions opens is a nav bar with two panels over the page. Module
|
|
13
|
+
* scope rather than a coordinating parent, because there is nothing to
|
|
14
|
+
* coordinate through: megamenus sit in whatever container the consumer used,
|
|
15
|
+
* which is usually `Navigation` and is not required to be. `Video` holds the
|
|
16
|
+
* media session the same way and for the same reason.
|
|
17
|
+
*
|
|
18
|
+
* When one panel opens in place of another, each is told which way the reader
|
|
19
|
+
* moved, as Radix's `data-motion` does: toward the end of the bar where the
|
|
20
|
+
* one opening comes after the one closing in the document. The one opening
|
|
21
|
+
* enters from the side the reader moved toward, and the one closing leaves
|
|
22
|
+
* toward the side they came from. Only the latest move is ever described.
|
|
23
|
+
*/
|
|
24
|
+
export declare class HandOver<T extends Handed> {
|
|
25
|
+
private readonly motion;
|
|
26
|
+
/**
|
|
27
|
+
* Every megamenu on the page, so a press on another one's trigger counts as
|
|
28
|
+
* moving along the bar. Closing on that press would close this panel before
|
|
29
|
+
* the other opens, and the hand-over would have no direction.
|
|
30
|
+
*/
|
|
31
|
+
readonly connected: Set<T>;
|
|
32
|
+
/** The panel showing now, so opening one closes the last. */
|
|
33
|
+
showing: T | undefined;
|
|
34
|
+
/**
|
|
35
|
+
* The megamenu a pointer is pressing, from the press until the click that
|
|
36
|
+
* ends it. A press moves focus before the click opens anything, and the open
|
|
37
|
+
* panel must not close on that focus move, or the hand-over has no direction.
|
|
38
|
+
*/
|
|
39
|
+
pressed: T | undefined;
|
|
40
|
+
/** The panels closing because another opened in their place. */
|
|
41
|
+
private readonly handed;
|
|
42
|
+
/** @param motion Writes a megamenu's direction, and clears it for `undefined`. */
|
|
43
|
+
constructor(motion: (megamenu: T, to: Motion | undefined) => void);
|
|
44
|
+
/** Counts a megamenu as part of the bar. */
|
|
45
|
+
add(megamenu: T): void;
|
|
46
|
+
/** Stops counting a megamenu that left the page. */
|
|
47
|
+
remove(megamenu: T): void;
|
|
48
|
+
/**
|
|
49
|
+
* Forgets the press a task after it ends, so the click it makes still finds
|
|
50
|
+
* it. One function for every press, so a listener added again is the same
|
|
51
|
+
* listener and never a second one.
|
|
52
|
+
*/
|
|
53
|
+
private readonly release;
|
|
54
|
+
/**
|
|
55
|
+
* The megamenus that share this one's parent, in document order: the bar it
|
|
56
|
+
* is one trigger of.
|
|
57
|
+
*/
|
|
58
|
+
alongside(megamenu: T): T[];
|
|
59
|
+
/** Notes a press on a megamenu, until the press ends. */
|
|
60
|
+
press(megamenu: T): void;
|
|
61
|
+
/**
|
|
62
|
+
* Opens one panel in place of the one showing, and returns that one, if
|
|
63
|
+
* there was one. The other closes through `requestOpen`, so a consumer
|
|
64
|
+
* holding it open is asked rather than overruled, and a refusal clears its
|
|
65
|
+
* direction again.
|
|
66
|
+
*/
|
|
67
|
+
open(opening: T): T | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Notes a panel closing. One that closed on its own moved nowhere, and
|
|
70
|
+
* neither did any other, so every direction clears.
|
|
71
|
+
*/
|
|
72
|
+
close(closing: T): void;
|
|
73
|
+
/** Clears the direction of every megamenu but the ones moving. */
|
|
74
|
+
private settle;
|
|
75
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
export class HandOver {
|
|
2
|
+
constructor(motion) {
|
|
3
|
+
this.motion = motion;
|
|
4
|
+
this.connected = new Set();
|
|
5
|
+
this.handed = new Set();
|
|
6
|
+
this.release = () => {
|
|
7
|
+
setTimeout(() => {
|
|
8
|
+
this.pressed = undefined;
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
add(megamenu) {
|
|
13
|
+
this.connected.add(megamenu);
|
|
14
|
+
}
|
|
15
|
+
remove(megamenu) {
|
|
16
|
+
this.connected.delete(megamenu);
|
|
17
|
+
this.handed.delete(megamenu);
|
|
18
|
+
if (this.showing === megamenu) {
|
|
19
|
+
this.showing = undefined;
|
|
20
|
+
}
|
|
21
|
+
if (this.pressed === megamenu) {
|
|
22
|
+
this.pressed = undefined;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
alongside(megamenu) {
|
|
26
|
+
return [...this.connected]
|
|
27
|
+
.filter((other) => other.parentNode === megamenu.parentNode)
|
|
28
|
+
.sort((a, b) => (a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1));
|
|
29
|
+
}
|
|
30
|
+
press(megamenu) {
|
|
31
|
+
this.pressed = megamenu;
|
|
32
|
+
window.addEventListener('pointerup', this.release, { capture: true, once: true });
|
|
33
|
+
window.addEventListener('pointercancel', this.release, { capture: true, once: true });
|
|
34
|
+
}
|
|
35
|
+
open(opening) {
|
|
36
|
+
const previous = this.showing !== opening ? this.showing : undefined;
|
|
37
|
+
const forward = previous !== undefined &&
|
|
38
|
+
(previous.compareDocumentPosition(opening) & Node.DOCUMENT_POSITION_FOLLOWING) !== 0;
|
|
39
|
+
this.motion(opening, previous ? (forward ? 'from-end' : 'from-start') : undefined);
|
|
40
|
+
this.settle(opening, previous);
|
|
41
|
+
if (previous) {
|
|
42
|
+
this.motion(previous, forward ? 'to-start' : 'to-end');
|
|
43
|
+
this.handed.add(previous);
|
|
44
|
+
if (!previous.requestOpen(false)) {
|
|
45
|
+
this.handed.delete(previous);
|
|
46
|
+
this.motion(previous, undefined);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
this.showing = opening;
|
|
50
|
+
return previous;
|
|
51
|
+
}
|
|
52
|
+
close(closing) {
|
|
53
|
+
if (this.showing === closing) {
|
|
54
|
+
this.showing = undefined;
|
|
55
|
+
}
|
|
56
|
+
if (!this.handed.delete(closing)) {
|
|
57
|
+
this.settle();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
settle(...moving) {
|
|
61
|
+
for (const megamenu of this.connected) {
|
|
62
|
+
if (!moving.includes(megamenu)) {
|
|
63
|
+
this.motion(megamenu, undefined);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|