@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
|
@@ -4,21 +4,32 @@ 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, DisabledCascadeController, HelixFormElement, hostAria, IndicatorController, KeyboardNavigationController, MixinControllerValue, MixinField, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { commaList, customElement, DisabledCascadeController, HelixFormElement, hostAria, IndicatorController, KeyboardNavigationController, MixinControllerValue, MixinField, rovingStop, toggleValue, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { HelixHeadlessToggle } from '../root/toggle-root.js';
|
|
11
11
|
let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinControllerValue(MixinField(HelixFormElement)) {
|
|
12
12
|
constructor() {
|
|
13
13
|
super(...arguments);
|
|
14
|
+
this.lastFocused = undefined;
|
|
15
|
+
this.noteFocus = (event) => {
|
|
16
|
+
const item = this.items.find((one) => one === event.target);
|
|
17
|
+
if (this.multiple && item && item !== this.lastFocused) {
|
|
18
|
+
this.lastFocused = item;
|
|
19
|
+
this.sync();
|
|
20
|
+
}
|
|
21
|
+
};
|
|
14
22
|
this.focusable = true;
|
|
15
23
|
this.indicator = new IndicatorController(this, {
|
|
16
|
-
active: () => this.items.find((item) => item.value === this.value),
|
|
24
|
+
active: () => this.multiple ? undefined : this.items.find((item) => item.value === this.value),
|
|
17
25
|
indicator: () => this.partNamed('indicator'),
|
|
18
26
|
observe: () => this.items,
|
|
19
27
|
surface: () => this.partNamed('track'),
|
|
20
28
|
});
|
|
21
|
-
this.keys = new KeyboardNavigationController(this, {
|
|
29
|
+
this.keys = new KeyboardNavigationController(this, {
|
|
30
|
+
items: () => this.items,
|
|
31
|
+
selects: () => !this.multiple,
|
|
32
|
+
});
|
|
22
33
|
this.cascade = new DisabledCascadeController(this, {
|
|
23
34
|
items: () => this.items,
|
|
24
35
|
});
|
|
@@ -27,7 +38,10 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
27
38
|
if (event.defaultPrevented) {
|
|
28
39
|
return;
|
|
29
40
|
}
|
|
30
|
-
|
|
41
|
+
const value = event.detail.value;
|
|
42
|
+
this.requestValue(this.multiple
|
|
43
|
+
? toggleValue(this.values, value, this.items.map((item) => item.value)).join(',')
|
|
44
|
+
: value);
|
|
31
45
|
});
|
|
32
46
|
};
|
|
33
47
|
}
|
|
@@ -41,16 +55,28 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
41
55
|
}
|
|
42
56
|
}
|
|
43
57
|
sync() {
|
|
44
|
-
const active = this.items.find((item) => item.value === this.value);
|
|
58
|
+
const active = this.multiple ? undefined : this.items.find((item) => item.value === this.value);
|
|
59
|
+
const pressed = new Set(this.values);
|
|
45
60
|
const entry = this.focusable ? this.entry() : undefined;
|
|
46
61
|
for (const item of this.items) {
|
|
47
62
|
item.selected = item === active;
|
|
63
|
+
item.pressed = this.multiple ? pressed.has(item.value) : undefined;
|
|
48
64
|
item.focusable = item === entry;
|
|
49
65
|
}
|
|
50
66
|
}
|
|
51
67
|
entry() {
|
|
52
|
-
const
|
|
53
|
-
|
|
68
|
+
const items = this.items;
|
|
69
|
+
if (this.multiple) {
|
|
70
|
+
return rovingStop(items, this.lastFocused, {
|
|
71
|
+
disabled: (item) => item.disabled,
|
|
72
|
+
selected: (item) => item.pressed === true,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
const active = items.find((item) => item.value === this.value);
|
|
76
|
+
return active && !active.disabled ? active : items.find((item) => !item.disabled);
|
|
77
|
+
}
|
|
78
|
+
get multiple() {
|
|
79
|
+
return this.selectionMode === 'multiple';
|
|
54
80
|
}
|
|
55
81
|
get focusTarget() {
|
|
56
82
|
return (super.focusTarget ??
|
|
@@ -64,6 +90,9 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
64
90
|
if (this.value === '') {
|
|
65
91
|
return false;
|
|
66
92
|
}
|
|
93
|
+
if (this.multiple) {
|
|
94
|
+
return this.children === undefined || this.values.length > 0;
|
|
95
|
+
}
|
|
67
96
|
if (this.children === undefined) {
|
|
68
97
|
return true;
|
|
69
98
|
}
|
|
@@ -73,10 +102,12 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
73
102
|
connectedCallback() {
|
|
74
103
|
super.connectedCallback();
|
|
75
104
|
this.addEventListener('helix-select', this.handleSelection);
|
|
105
|
+
this.addEventListener('focusin', this.noteFocus);
|
|
76
106
|
}
|
|
77
107
|
disconnectedCallback() {
|
|
78
108
|
super.disconnectedCallback();
|
|
79
109
|
this.removeEventListener('helix-select', this.handleSelection);
|
|
110
|
+
this.removeEventListener('focusin', this.noteFocus);
|
|
80
111
|
}
|
|
81
112
|
firstUpdated(changed) {
|
|
82
113
|
super.firstUpdated(changed);
|
|
@@ -92,12 +123,32 @@ let HelixHeadlessToggleGroup = class HelixHeadlessToggleGroup extends MixinContr
|
|
|
92
123
|
willUpdate(changed) {
|
|
93
124
|
super.willUpdate(changed);
|
|
94
125
|
this.adopt();
|
|
95
|
-
hostAria(this.internals, { label: this.label, role: 'radiogroup' });
|
|
96
|
-
this.internals.
|
|
126
|
+
hostAria(this.internals, { label: this.label, role: this.multiple ? 'toolbar' : 'radiogroup' });
|
|
127
|
+
this.internals.ariaOrientation = this.orientation ?? null;
|
|
128
|
+
this.internals.setFormValue(this.formValue());
|
|
129
|
+
}
|
|
130
|
+
formValue() {
|
|
131
|
+
if (!this.answered) {
|
|
132
|
+
return null;
|
|
133
|
+
}
|
|
134
|
+
if (!this.multiple || this.name === '') {
|
|
135
|
+
return this.value;
|
|
136
|
+
}
|
|
137
|
+
const data = new FormData();
|
|
138
|
+
for (const value of this.values) {
|
|
139
|
+
data.append(this.name, value);
|
|
140
|
+
}
|
|
141
|
+
return data;
|
|
97
142
|
}
|
|
98
143
|
validate() {
|
|
99
144
|
this.reportRequired(!this.answered, 'Choose one to continue.', 'track');
|
|
100
145
|
}
|
|
146
|
+
get values() {
|
|
147
|
+
return this.multiple ? commaList(this.value) : this.value === '' ? [] : [this.value];
|
|
148
|
+
}
|
|
149
|
+
set values(next) {
|
|
150
|
+
this.value = next.join(',');
|
|
151
|
+
}
|
|
101
152
|
render() {
|
|
102
153
|
const inside = this.labelPlacement === 'start';
|
|
103
154
|
const label = this.renderGroupLabel();
|
|
@@ -127,6 +178,15 @@ __decorate([
|
|
|
127
178
|
__decorate([
|
|
128
179
|
property({ attribute: 'label-placement', reflect: true })
|
|
129
180
|
], HelixHeadlessToggleGroup.prototype, "labelPlacement", void 0);
|
|
181
|
+
__decorate([
|
|
182
|
+
property({ reflect: true })
|
|
183
|
+
], HelixHeadlessToggleGroup.prototype, "orientation", void 0);
|
|
184
|
+
__decorate([
|
|
185
|
+
property({ attribute: 'selection-mode', reflect: true })
|
|
186
|
+
], HelixHeadlessToggleGroup.prototype, "selectionMode", void 0);
|
|
187
|
+
__decorate([
|
|
188
|
+
property({ attribute: false })
|
|
189
|
+
], HelixHeadlessToggleGroup.prototype, "values", null);
|
|
130
190
|
HelixHeadlessToggleGroup = __decorate([
|
|
131
191
|
customElement('helix-headless-toggle-group')
|
|
132
192
|
], HelixHeadlessToggleGroup);
|
|
@@ -5,7 +5,9 @@ declare const HelixHeadlessToggle_base: (new (...args: any[]) => import("@fusion
|
|
|
5
5
|
* @summary One option in a toggle group.
|
|
6
6
|
*
|
|
7
7
|
* @description
|
|
8
|
-
* Renders a `<button role="radio">` for use as a form control.
|
|
8
|
+
* Renders a `<button role="radio">` for use as a form control. In a group with
|
|
9
|
+
* `selection-mode="multiple"` it is a `<button>` that says whether it is
|
|
10
|
+
* pressed with `aria-pressed`.
|
|
9
11
|
*
|
|
10
12
|
* Do not use it for navigation. For navigation, use links marked with
|
|
11
13
|
* `aria-current` and styled by the `data-navigation-item` recipe in the base
|
|
@@ -23,6 +25,7 @@ declare const HelixHeadlessToggle_base: (new (...args: any[]) => import("@fusion
|
|
|
23
25
|
*
|
|
24
26
|
* @csspart item - The radio button.
|
|
25
27
|
*
|
|
28
|
+
* @cssstate pressed - The item is pressed, in a group where several can be.
|
|
26
29
|
* @cssstate selected - The item is chosen.
|
|
27
30
|
*/
|
|
28
31
|
export declare class HelixHeadlessToggle extends HelixHeadlessToggle_base {
|
|
@@ -69,6 +72,14 @@ export declare class HelixHeadlessToggle extends HelixHeadlessToggle_base {
|
|
|
69
72
|
* React consumer's hydration reports and does not patch up.
|
|
70
73
|
*/
|
|
71
74
|
focusable?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Whether the item is pressed, in a group where several can be, and
|
|
77
|
+
* `undefined` in a group where one is chosen.
|
|
78
|
+
*
|
|
79
|
+
* Written by the group, like `selected`, so no attribute.
|
|
80
|
+
*/
|
|
81
|
+
pressed?: boolean | undefined;
|
|
82
|
+
protected willUpdate(changed: PropertyValues): void;
|
|
72
83
|
/**
|
|
73
84
|
* Asks for the render that follows a hydration, so the stop stops being every
|
|
74
85
|
* choice's.
|
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
import { customElement, HelixElement, HostClickController, MixinSelectableItem, } from '@fusion.dev/helix-core';
|
|
8
|
-
import { html } from 'lit';
|
|
8
|
+
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessToggle = class HelixHeadlessToggle extends MixinSelectableItem(HelixElement) {
|
|
11
11
|
constructor() {
|
|
@@ -18,6 +18,10 @@ let HelixHeadlessToggle = class HelixHeadlessToggle extends MixinSelectableItem(
|
|
|
18
18
|
set defaultSelected(next) {
|
|
19
19
|
this.toggleAttribute('selected', next);
|
|
20
20
|
}
|
|
21
|
+
willUpdate(changed) {
|
|
22
|
+
super.willUpdate(changed);
|
|
23
|
+
this.toggleState('pressed', this.pressed === true);
|
|
24
|
+
}
|
|
21
25
|
firstUpdated(changed) {
|
|
22
26
|
super.firstUpdated(changed);
|
|
23
27
|
this.finishHydration();
|
|
@@ -26,8 +30,9 @@ let HelixHeadlessToggle = class HelixHeadlessToggle extends MixinSelectableItem(
|
|
|
26
30
|
return html `<button
|
|
27
31
|
part="item"
|
|
28
32
|
type="button"
|
|
29
|
-
role
|
|
30
|
-
aria-checked=${this.selected ? 'true' : 'false'}
|
|
33
|
+
role=${this.pressed === undefined ? 'radio' : nothing}
|
|
34
|
+
aria-checked=${this.pressed === undefined ? (this.selected ? 'true' : 'false') : nothing}
|
|
35
|
+
aria-pressed=${this.pressed === undefined ? nothing : String(this.pressed)}
|
|
31
36
|
?disabled=${this.disabled}
|
|
32
37
|
tabindex=${(this.focusable ?? this.selected) || !this.childrenKnown ? '0' : '-1'}
|
|
33
38
|
@click=${() => this.select()}
|
|
@@ -39,6 +44,9 @@ let HelixHeadlessToggle = class HelixHeadlessToggle extends MixinSelectableItem(
|
|
|
39
44
|
__decorate([
|
|
40
45
|
property({ attribute: false })
|
|
41
46
|
], HelixHeadlessToggle.prototype, "focusable", void 0);
|
|
47
|
+
__decorate([
|
|
48
|
+
property({ attribute: false })
|
|
49
|
+
], HelixHeadlessToggle.prototype, "pressed", void 0);
|
|
42
50
|
HelixHeadlessToggle = __decorate([
|
|
43
51
|
customElement('helix-headless-toggle')
|
|
44
52
|
], HelixHeadlessToggle);
|
|
@@ -12,6 +12,14 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
12
12
|
* focus counts as a control, including your own elements. A child that takes no
|
|
13
13
|
* focus, such as a divider, is skipped. A menu is reached at its trigger.
|
|
14
14
|
*
|
|
15
|
+
* Controls inside a plain wrapper, such as a `Button Group`, are each a stop
|
|
16
|
+
* of the toolbar's own, as React Aria's toolbar flattens a group: the arrows
|
|
17
|
+
* walk through the group's buttons and on past it, and the group takes no tab
|
|
18
|
+
* stop of its own.
|
|
19
|
+
*
|
|
20
|
+
* The arrows wrap from the last control to the first. Set `stop-at-ends` to
|
|
21
|
+
* keep them at the ends, as Radix's `loop` set to false does.
|
|
22
|
+
*
|
|
15
23
|
* A nested composite, such as a toggle group, is one stop on the toolbar's
|
|
16
24
|
* axis: the toolbar's arrows move past it, and the arrows across the toolbar
|
|
17
25
|
* move inside it. A composite with a `focusable` property, as Toggle Group
|
|
@@ -49,6 +57,11 @@ export declare class HelixHeadlessToolbar extends HelixElement {
|
|
|
49
57
|
* The direction the arrow keys move focus in.
|
|
50
58
|
*/
|
|
51
59
|
orientation?: 'horizontal' | 'vertical';
|
|
60
|
+
/**
|
|
61
|
+
* Whether the arrow keys stop at the first and the last control. Unset, they
|
|
62
|
+
* wrap around from one end to the other.
|
|
63
|
+
*/
|
|
64
|
+
stopAtEnds: boolean;
|
|
52
65
|
private watcher;
|
|
53
66
|
/**
|
|
54
67
|
* The children that take part in the toolbar, in document order, each with
|
|
@@ -31,6 +31,7 @@ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
|
|
|
31
31
|
target: () => this.partNamed('toolbar'),
|
|
32
32
|
});
|
|
33
33
|
this.wroteForeign = false;
|
|
34
|
+
this.stopAtEnds = false;
|
|
34
35
|
this.handleFocusIn = (event) => {
|
|
35
36
|
const control = this.origin(event);
|
|
36
37
|
if (control) {
|
|
@@ -75,11 +76,14 @@ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
|
|
|
75
76
|
return;
|
|
76
77
|
}
|
|
77
78
|
let next = current;
|
|
79
|
+
const last = controls.length - 1;
|
|
78
80
|
if (forward) {
|
|
79
|
-
next = (current + 1) % controls.length;
|
|
81
|
+
next = this.stopAtEnds ? Math.min(current + 1, last) : (current + 1) % controls.length;
|
|
80
82
|
}
|
|
81
83
|
else if (back) {
|
|
82
|
-
next =
|
|
84
|
+
next = this.stopAtEnds
|
|
85
|
+
? Math.max(current - 1, 0)
|
|
86
|
+
: (current - 1 + controls.length) % controls.length;
|
|
83
87
|
}
|
|
84
88
|
else if (event.key === 'Home') {
|
|
85
89
|
next = 0;
|
|
@@ -110,9 +114,12 @@ let HelixHeadlessToolbar = class HelixHeadlessToolbar extends HelixElement {
|
|
|
110
114
|
child.getAttribute('aria-hidden') === 'true') {
|
|
111
115
|
continue;
|
|
112
116
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
if (takesFocus(child)) {
|
|
118
|
+
controls.push({ child, stops: this.inside(child) });
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
for (const stop of this.within(child)) {
|
|
122
|
+
controls.push({ child: stop, stops: [stop] });
|
|
116
123
|
}
|
|
117
124
|
}
|
|
118
125
|
return controls;
|
|
@@ -204,6 +211,9 @@ __decorate([
|
|
|
204
211
|
__decorate([
|
|
205
212
|
property({ reflect: true })
|
|
206
213
|
], HelixHeadlessToolbar.prototype, "orientation", void 0);
|
|
214
|
+
__decorate([
|
|
215
|
+
property({ attribute: 'stop-at-ends', type: Boolean })
|
|
216
|
+
], HelixHeadlessToolbar.prototype, "stopAtEnds", void 0);
|
|
207
217
|
HelixHeadlessToolbar = __decorate([
|
|
208
218
|
customElement('helix-headless-toolbar')
|
|
209
219
|
], HelixHeadlessToolbar);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The element focus lands on when a trigger is focused: the trigger itself,
|
|
3
|
+
* or, for a component that delegates focus, the control inside its shadow root,
|
|
4
|
+
* followed down through any component nested there.
|
|
5
|
+
*/
|
|
6
|
+
export declare const focusTarget: (trigger: Element) => Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const CONTROL = 'a[href], button, input, select, textarea, [contenteditable], [tabindex]:not([tabindex="-1"])';
|
|
2
|
+
export const focusTarget = (trigger) => {
|
|
3
|
+
const root = trigger.shadowRoot;
|
|
4
|
+
if (!root?.delegatesFocus) {
|
|
5
|
+
return trigger;
|
|
6
|
+
}
|
|
7
|
+
const inner = root.querySelector(CONTROL);
|
|
8
|
+
return inner ? focusTarget(inner) : trigger;
|
|
9
|
+
};
|
|
@@ -10,29 +10,32 @@ declare const HelixHeadlessTooltip_base: (new (...args: any[]) => import("@fusio
|
|
|
10
10
|
* does not clip it and no `z-index` is needed. `FloatingController` positions
|
|
11
11
|
* it and flips it to another side when the preferred side does not fit.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* trigger: an IDREF cannot cross a shadow boundary.
|
|
16
|
-
*
|
|
17
|
-
* To add a description, place the tooltip beside the trigger and name the
|
|
18
|
-
* trigger with `for`:
|
|
13
|
+
* **The tooltip describes its trigger itself, in both forms.** Wrap the
|
|
14
|
+
* trigger, or place the tooltip beside it and name the trigger with `for`:
|
|
19
15
|
*
|
|
20
16
|
* ```html
|
|
21
|
-
* <helix-headless-button id="save"
|
|
22
|
-
* <helix-headless-tooltip
|
|
17
|
+
* <helix-headless-button id="save">Save</helix-headless-button>
|
|
18
|
+
* <helix-headless-tooltip for="save" content="Save your work"></helix-headless-tooltip>
|
|
23
19
|
* ```
|
|
24
20
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
21
|
+
* The link is an element reference on the control that takes focus, and it is
|
|
22
|
+
* never written into your markup before a reader has acted. A trigger that is a
|
|
23
|
+
* Helix component is described at once, inside its own shadow root. A plain
|
|
24
|
+
* element in your markup is described when a reader first points at it or
|
|
25
|
+
* focuses it, which is after any hydration, and only where you have written no
|
|
26
|
+
* `aria-describedby` or `aria-labelledby` of your own. Write
|
|
27
|
+
* `aria-describedby` pointing at the tooltip yourself to have the link in the
|
|
28
|
+
* server's markup. Where the browser has no element references, write it
|
|
29
|
+
* yourself; the tooltip warns once on first open if nothing links the two.
|
|
28
30
|
*
|
|
29
31
|
* The tooltip shows on hover and on focus. It hides on pointer leave, on blur,
|
|
30
32
|
* on Escape, and when the trigger is activated. The pointer can move from the
|
|
31
33
|
* trigger onto the bubble and the bubble stays.
|
|
32
34
|
*
|
|
33
35
|
* Once one tooltip is showing, moving to another trigger shows its tooltip
|
|
34
|
-
* with no `delay`, and the first one hides. The same holds for
|
|
35
|
-
* milliseconds after a tooltip hides.
|
|
36
|
+
* with no `delay`, and the first one hides. The same holds for `skip-delay`
|
|
37
|
+
* milliseconds after a tooltip hides, 300 unless you set it. `show-on="focus"`
|
|
38
|
+
* shows the tooltip on keyboard focus only, for a hint a pointer does not need.
|
|
36
39
|
*
|
|
37
40
|
* @since 0.1.0
|
|
38
41
|
* @status stable
|
|
@@ -40,9 +43,8 @@ declare const HelixHeadlessTooltip_base: (new (...args: any[]) => import("@fusio
|
|
|
40
43
|
* @aliases Hint, Popup label
|
|
41
44
|
* @documentation https://fusion.dev/helix/components/tooltip
|
|
42
45
|
*
|
|
43
|
-
* @slot - The trigger, in the wrapping form.
|
|
44
|
-
*
|
|
45
|
-
* says, and use `for` otherwise.
|
|
46
|
+
* @slot - The trigger, in the wrapping form. The tooltip describes it, as it
|
|
47
|
+
* describes the element `for` names.
|
|
46
48
|
* @slot content - Rich content for the bubble. It replaces the `content`
|
|
47
49
|
* property.
|
|
48
50
|
*
|
|
@@ -149,6 +151,18 @@ export declare class HelixHeadlessTooltip extends HelixHeadlessTooltip_base {
|
|
|
149
151
|
* It moves if that side does not fit.
|
|
150
152
|
*/
|
|
151
153
|
placement: Placement;
|
|
154
|
+
/**
|
|
155
|
+
* What shows the bubble. Unset, it is a pointer resting on the trigger and
|
|
156
|
+
* keyboard focus. `focus` is keyboard focus alone, for a hint a pointer does
|
|
157
|
+
* not need, such as a shortcut a mouse reader has no use for.
|
|
158
|
+
*/
|
|
159
|
+
showOn?: 'focus';
|
|
160
|
+
/**
|
|
161
|
+
* How long after a tooltip hides the next one still shows at once, with no
|
|
162
|
+
* `delay`, in milliseconds. The same skip delay Radix uses. Zero makes every
|
|
163
|
+
* tooltip wait.
|
|
164
|
+
*/
|
|
165
|
+
skipDelay: number;
|
|
152
166
|
/**
|
|
153
167
|
* The id of a box to keep the bubble inside. Defaults to the viewport.
|
|
154
168
|
*
|
|
@@ -260,7 +274,7 @@ export declare class HelixHeadlessTooltip extends HelixHeadlessTooltip_base {
|
|
|
260
274
|
* Shows after the pointer has rested for `delay`, or at once while the
|
|
261
275
|
* tooltips are warm.
|
|
262
276
|
*
|
|
263
|
-
* **Warm is another tooltip showing, or one that hid within `
|
|
277
|
+
* **Warm is another tooltip showing, or one that hid within `skipDelay`.**
|
|
264
278
|
* A reader scanning a toolbar has already waited once, and waiting again on
|
|
265
279
|
* every control turns the scan into a series of pauses.
|
|
266
280
|
*/
|
|
@@ -344,6 +358,17 @@ export declare class HelixHeadlessTooltip extends HelixHeadlessTooltip_base {
|
|
|
344
358
|
* have upgraded, or existed, when this one connected.
|
|
345
359
|
*/
|
|
346
360
|
private bind;
|
|
361
|
+
/** The control this tooltip has described, so the link can be taken back. */
|
|
362
|
+
private linked;
|
|
363
|
+
/**
|
|
364
|
+
* Describes the control that takes the trigger's focus by this tooltip.
|
|
365
|
+
*
|
|
366
|
+
* `light` says a reader has just acted, which is what allows a write onto a
|
|
367
|
+
* plain element in the consumer's markup. See `linkDescription`.
|
|
368
|
+
*/
|
|
369
|
+
private link;
|
|
370
|
+
/** A reader arriving on the trigger, which is late enough to write the link. */
|
|
371
|
+
private readonly linkOnArrival;
|
|
347
372
|
private unbind;
|
|
348
373
|
/** Said once per element, however many times it opens. */
|
|
349
374
|
private audited;
|
|
@@ -4,11 +4,11 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { anchorElement, customElement, elementById, HelixElement, hostAria, MixinControllerOpen, PopoverController, reportRuntime, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { anchorElement, arrowReach, customElement, elementById, HelixElement, hostAria, linkDescription, MixinControllerOpen, PopoverController, reportRuntime, sideOf, unlinkDescription, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
|
+
import { focusTarget } from '../focus-target.js';
|
|
10
11
|
const GENERIC = new Set(['div', 'p', 'section', 'span']);
|
|
11
|
-
const SKIP_DELAY = 300;
|
|
12
12
|
const WARMTH = Symbol.for('fusion.helix.tooltip.warmth');
|
|
13
13
|
const warmth = () => {
|
|
14
14
|
const globals = globalThis;
|
|
@@ -26,22 +26,20 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
|
|
|
26
26
|
this.offset = 8;
|
|
27
27
|
this.persist = false;
|
|
28
28
|
this.placement = 'top';
|
|
29
|
+
this.skipDelay = 300;
|
|
29
30
|
this.within = '';
|
|
30
31
|
this.holds = new Set();
|
|
31
32
|
this.bubbleLayer = new PopoverController(this, {
|
|
32
33
|
anchor: () => this.trigger,
|
|
33
34
|
arrow: () => this.partNamed('arrow'),
|
|
34
35
|
boundary: () => [this, this.named],
|
|
35
|
-
offset: () =>
|
|
36
|
-
const point = this.partNamed('arrow');
|
|
37
|
-
return this.offset + (point?.offsetWidth ?? 0) / Math.SQRT2;
|
|
38
|
-
},
|
|
36
|
+
offset: () => this.offset + arrowReach(this.partNamed('arrow')),
|
|
39
37
|
onDismiss: () => {
|
|
40
38
|
this.holds.clear();
|
|
41
39
|
this.hide();
|
|
42
40
|
},
|
|
43
41
|
onPlace: (placement) => {
|
|
44
|
-
const side = placement
|
|
42
|
+
const side = sideOf(placement);
|
|
45
43
|
this.toggleState('placed-bottom', side === 'bottom');
|
|
46
44
|
this.toggleState('placed-left', side === 'left');
|
|
47
45
|
this.toggleState('placed-right', side === 'right');
|
|
@@ -56,11 +54,14 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
|
|
|
56
54
|
this.requestUpdate();
|
|
57
55
|
};
|
|
58
56
|
this.showLater = () => {
|
|
57
|
+
if (this.showOn === 'focus') {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
59
60
|
this.holds.add('pointer');
|
|
60
61
|
clearTimeout(this.timer);
|
|
61
62
|
const warm = warmth();
|
|
62
63
|
const others = [...warm.showing].some((one) => one !== this);
|
|
63
|
-
if (others || performance.now() - warm.hidAt <
|
|
64
|
+
if (others || performance.now() - warm.hidAt < this.skipDelay) {
|
|
64
65
|
this.show();
|
|
65
66
|
return;
|
|
66
67
|
}
|
|
@@ -102,6 +103,10 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
|
|
|
102
103
|
this.holds.clear();
|
|
103
104
|
this.hide();
|
|
104
105
|
};
|
|
106
|
+
this.linkOnArrival = (event) => {
|
|
107
|
+
const first = event.composedPath()[0];
|
|
108
|
+
this.link(true, event.type === 'focusin' && first instanceof Element ? first : undefined);
|
|
109
|
+
};
|
|
105
110
|
this.audited = false;
|
|
106
111
|
}
|
|
107
112
|
get trigger() {
|
|
@@ -179,14 +184,41 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
|
|
|
179
184
|
return;
|
|
180
185
|
}
|
|
181
186
|
this.unbind();
|
|
187
|
+
target.addEventListener('pointerenter', this.linkOnArrival);
|
|
188
|
+
target.addEventListener('focusin', this.linkOnArrival);
|
|
182
189
|
target.addEventListener('pointerenter', this.showLater);
|
|
183
190
|
target.addEventListener('pointerleave', this.hideLater);
|
|
184
191
|
target.addEventListener('focusin', this.showNow);
|
|
185
192
|
target.addEventListener('focusout', this.releaseFocus);
|
|
186
193
|
target.addEventListener('click', this.handleActivate);
|
|
187
194
|
this.bound = target;
|
|
195
|
+
this.link(false);
|
|
196
|
+
const drawn = this.trigger.updateComplete;
|
|
197
|
+
void drawn?.then(() => {
|
|
198
|
+
if (this.bound === target) {
|
|
199
|
+
this.link(false);
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
link(light, target = focusTarget(this.trigger)) {
|
|
204
|
+
if (this.linked === target) {
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (this.linked) {
|
|
208
|
+
unlinkDescription(this.linked, this);
|
|
209
|
+
this.linked = undefined;
|
|
210
|
+
}
|
|
211
|
+
if (linkDescription(target, this, light)) {
|
|
212
|
+
this.linked = target;
|
|
213
|
+
}
|
|
188
214
|
}
|
|
189
215
|
unbind() {
|
|
216
|
+
if (this.linked) {
|
|
217
|
+
unlinkDescription(this.linked, this);
|
|
218
|
+
this.linked = undefined;
|
|
219
|
+
}
|
|
220
|
+
this.bound?.removeEventListener('pointerenter', this.linkOnArrival);
|
|
221
|
+
this.bound?.removeEventListener('focusin', this.linkOnArrival);
|
|
190
222
|
this.bound?.removeEventListener('pointerenter', this.showLater);
|
|
191
223
|
this.bound?.removeEventListener('pointerleave', this.hideLater);
|
|
192
224
|
this.bound?.removeEventListener('click', this.handleActivate);
|
|
@@ -199,6 +231,9 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
|
|
|
199
231
|
return;
|
|
200
232
|
}
|
|
201
233
|
this.audited = true;
|
|
234
|
+
if (this.linked) {
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
202
237
|
if (this.for === '') {
|
|
203
238
|
if (this.triggerSays(this.describedText)) {
|
|
204
239
|
return;
|
|
@@ -293,7 +328,7 @@ let HelixHeadlessTooltip = class HelixHeadlessTooltip extends MixinControllerOpe
|
|
|
293
328
|
}
|
|
294
329
|
hostAria(this.internals, {
|
|
295
330
|
describedBy: this.hasContent ? [bubble] : [],
|
|
296
|
-
label: this.
|
|
331
|
+
label: this.describedText,
|
|
297
332
|
});
|
|
298
333
|
}
|
|
299
334
|
render() {
|
|
@@ -339,6 +374,12 @@ __decorate([
|
|
|
339
374
|
__decorate([
|
|
340
375
|
property()
|
|
341
376
|
], HelixHeadlessTooltip.prototype, "placement", void 0);
|
|
377
|
+
__decorate([
|
|
378
|
+
property({ attribute: 'show-on' })
|
|
379
|
+
], HelixHeadlessTooltip.prototype, "showOn", void 0);
|
|
380
|
+
__decorate([
|
|
381
|
+
property({ attribute: 'skip-delay', type: Number })
|
|
382
|
+
], HelixHeadlessTooltip.prototype, "skipDelay", void 0);
|
|
342
383
|
__decorate([
|
|
343
384
|
property()
|
|
344
385
|
], HelixHeadlessTooltip.prototype, "within", void 0);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** What names and describes a stop's panel. */
|
|
2
|
+
export interface StopNaming {
|
|
3
|
+
/** The elements that describe the panel, in reading order. */
|
|
4
|
+
describedBy: Element[];
|
|
5
|
+
/** The elements that name the panel, or none where a label names it. */
|
|
6
|
+
labelledBy: Element[];
|
|
7
|
+
}
|
|
8
|
+
/** Where a stop's words are. */
|
|
9
|
+
export interface StopWords {
|
|
10
|
+
/** The elements in the stop's default slot. */
|
|
11
|
+
content: readonly Element[];
|
|
12
|
+
/** The elements in its `description` slot. */
|
|
13
|
+
description: readonly Element[];
|
|
14
|
+
/** The elements in its `heading` slot. */
|
|
15
|
+
heading: readonly Element[];
|
|
16
|
+
/** Whether the stop has a `label` of its own. */
|
|
17
|
+
labeled: boolean;
|
|
18
|
+
/** The element that says the stop's place in the tour, such as "2 of 5". */
|
|
19
|
+
progress: Element | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* What names a tour stop's panel and what describes it.
|
|
23
|
+
*
|
|
24
|
+
* Named by the `heading` slot, then by the first heading in the content, then
|
|
25
|
+
* by the stop's own `label`, and where there is none of those, by its place in
|
|
26
|
+
* the tour, so no stop is an unnamed group. Described by the `description`
|
|
27
|
+
* slot and by its place, which is how a screen reader hears where it is as
|
|
28
|
+
* focus moves from one stop to the next.
|
|
29
|
+
*/
|
|
30
|
+
export declare const stopNaming: ({ content, description, heading, labeled, progress, }: StopWords) => StopNaming;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { headingIn } from '@fusion.dev/helix-core';
|
|
2
|
+
export const stopNaming = ({ content, description, heading, labeled, progress, }) => {
|
|
3
|
+
const first = heading.length > 0 ? null : headingIn(content);
|
|
4
|
+
const found = heading.length > 0 ? [...heading] : first ? [first] : [];
|
|
5
|
+
const place = progress ? [progress] : [];
|
|
6
|
+
if (found.length === 0 && !labeled) {
|
|
7
|
+
return { describedBy: [...description], labelledBy: place };
|
|
8
|
+
}
|
|
9
|
+
return { describedBy: [...description, ...place], labelledBy: found };
|
|
10
|
+
};
|