@fusion.dev/helix-headless 0.146.0 → 0.148.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 +9287 -1084
- package/dist/accordion/item/accordion-item.d.ts +43 -21
- package/dist/accordion/item/accordion-item.js +37 -11
- package/dist/accordion/root/accordion-root.d.ts +8 -2
- package/dist/accordion/root/accordion-root.js +6 -8
- package/dist/announcement/root/announcement-root.d.ts +66 -6
- package/dist/announcement/root/announcement-root.js +144 -13
- package/dist/area-chart/root/area-chart-root.d.ts +18 -1
- package/dist/area-chart/root/area-chart-root.js +14 -7
- package/dist/avatar/root/avatar-root.d.ts +31 -1
- package/dist/avatar/root/avatar-root.js +11 -1
- package/dist/badge/count.d.ts +14 -0
- package/dist/badge/count.js +20 -0
- package/dist/badge/root/badge-root.d.ts +57 -6
- package/dist/badge/root/badge-root.js +77 -8
- package/dist/bar-chart/root/bar-chart-root.js +11 -20
- package/dist/bar-chart/stack.d.ts +10 -0
- package/dist/bar-chart/stack.js +8 -0
- package/dist/blockquote/root/blockquote-root.d.ts +66 -8
- package/dist/blockquote/root/blockquote-root.js +85 -8
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +14 -0
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +12 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.js +2 -2
- package/dist/button/root/button-root.d.ts +24 -38
- package/dist/button/root/button-root.js +6 -37
- package/dist/button/submitter.d.ts +27 -0
- package/dist/button/submitter.js +25 -0
- package/dist/button-group/arrows.d.ts +14 -0
- package/dist/button-group/arrows.js +10 -0
- package/dist/button-group/root/button-group-root.d.ts +141 -3
- package/dist/button-group/root/button-group-root.js +142 -2
- package/dist/canvas/edge-pan.d.ts +61 -0
- package/dist/canvas/edge-pan.js +63 -0
- package/dist/canvas/node/canvas-node.d.ts +12 -2
- package/dist/canvas/node/canvas-node.js +6 -2
- package/dist/canvas/root/canvas-document.d.ts +10 -0
- package/dist/canvas/root/canvas-document.js +1 -0
- package/dist/canvas/root/canvas-root.d.ts +107 -5
- package/dist/canvas/root/canvas-root.js +140 -36
- package/dist/canvas/snap.d.ts +42 -0
- package/dist/canvas/snap.js +32 -0
- package/dist/card/root/card-root.d.ts +12 -1
- package/dist/card/root/card-root.js +11 -4
- package/dist/carousel/root/carousel-root.d.ts +4 -3
- package/dist/carousel/root/carousel-root.js +2 -6
- package/dist/chat/root/chat-root.d.ts +28 -4
- package/dist/chat/root/chat-root.js +12 -7
- package/dist/checkbox/root/checkbox-root.js +5 -7
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +13 -0
- package/dist/checkbox-group/root/checkbox-group-root.js +16 -7
- package/dist/checkbox-group/select-all.d.ts +9 -4
- package/dist/checkbox-group/select-all.js +1 -1
- package/dist/code-block/root/code-block-root.d.ts +41 -18
- package/dist/code-block/root/code-block-root.js +21 -6
- package/dist/color-input/root/color-input-root.d.ts +11 -0
- package/dist/color-input/root/color-input-root.js +12 -5
- package/dist/color-picker/channels.js +1 -2
- package/dist/color-picker/root/color-picker-root.d.ts +32 -24
- package/dist/color-picker/root/color-picker-root.js +99 -55
- package/dist/color-picker/wheel.d.ts +28 -0
- package/dist/color-picker/wheel.js +15 -0
- package/dist/combobox/root/combobox-root.d.ts +83 -11
- package/dist/combobox/root/combobox-root.js +81 -18
- package/dist/command/root/command-root.d.ts +7 -4
- package/dist/command/root/command-root.js +2 -19
- package/dist/copy-button/root/copy-button-root.d.ts +16 -1
- package/dist/copy-button/root/copy-button-root.js +7 -2
- package/dist/data-table/keys.d.ts +0 -18
- package/dist/data-table/keys.js +1 -11
- package/dist/data-table/root/data-table-root.js +29 -50
- package/dist/date-input/root/date-input-root.d.ts +8 -1
- package/dist/date-input/root/date-input-root.js +8 -5
- package/dist/date-picker/root/date-picker-root.d.ts +14 -9
- package/dist/date-picker/root/date-picker-root.js +21 -16
- package/dist/description-list/item/description-list-item.d.ts +22 -4
- package/dist/description-list/item/description-list-item.js +14 -4
- package/dist/divider/root/divider-root.d.ts +45 -16
- package/dist/divider/root/divider-root.js +28 -4
- package/dist/donut-chart/root/donut-chart-root.js +13 -6
- package/dist/donut-chart/slice-label.d.ts +35 -0
- package/dist/donut-chart/slice-label.js +11 -0
- package/dist/drawer/root/drawer-root.d.ts +4 -2
- package/dist/drawer/root/drawer-root.js +15 -3
- package/dist/drilldown/item/drilldown-item.d.ts +21 -1
- package/dist/drilldown/item/drilldown-item.js +38 -4
- package/dist/drilldown/root/drilldown-root.js +3 -2
- package/dist/element-events.generated.js +5 -1
- package/dist/empty/root/empty-root.d.ts +46 -2
- package/dist/empty/root/empty-root.js +50 -5
- package/dist/file-input/root/file-input-root.d.ts +34 -6
- package/dist/file-input/root/file-input-root.js +55 -21
- package/dist/file-input/status.d.ts +24 -0
- package/dist/file-input/status.js +11 -0
- package/dist/filter-input/chip/filter-chip.d.ts +23 -0
- package/dist/filter-input/chip/filter-chip.js +10 -2
- package/dist/filter-input/root/filter-input-root.d.ts +8 -0
- package/dist/filter-input/root/filter-input-root.js +17 -27
- package/dist/format-date/fields.d.ts +20 -0
- package/dist/format-date/fields.js +14 -0
- package/dist/format-date/options.d.ts +5 -5
- package/dist/format-date/options.js +10 -39
- package/dist/format-date/root/format-date-root.d.ts +53 -4
- package/dist/format-date/root/format-date-root.js +38 -50
- package/dist/graph/root/graph-root.d.ts +23 -5
- package/dist/graph/root/graph-root.js +17 -20
- 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 +76 -3
- package/dist/heatmap/root/heatmap-root.js +105 -20
- 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 +13 -0
- package/dist/icon/root/icon-root.js +23 -2
- package/dist/icon/root/index.d.ts +1 -1
- package/dist/icon/root/index.js +1 -1
- package/dist/image/root/image-root.d.ts +20 -0
- package/dist/image/root/image-root.js +6 -1
- package/dist/input/root/input-root.d.ts +23 -2
- package/dist/input/root/input-root.js +12 -8
- package/dist/kbd/root/kbd-root.d.ts +20 -3
- package/dist/kbd/root/kbd-root.js +23 -50
- 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 +25 -7
- package/dist/legend/root/legend-root.js +25 -26
- package/dist/lightbox/root/lightbox-root.d.ts +50 -5
- package/dist/lightbox/root/lightbox-root.js +76 -8
- package/dist/lightbox/zoom.d.ts +2 -0
- package/dist/lightbox/zoom.js +5 -3
- package/dist/line-chart/root/line-chart-root.d.ts +16 -0
- package/dist/line-chart/root/line-chart-root.js +10 -2
- package/dist/list/root/list-root.d.ts +10 -2
- package/dist/list/root/list-root.js +31 -24
- package/dist/list/selection.d.ts +17 -0
- package/dist/list/selection.js +16 -0
- package/dist/listbox/root/listbox-root.d.ts +125 -26
- package/dist/listbox/root/listbox-root.js +156 -166
- package/dist/map/marker/map-marker.d.ts +2 -1
- package/dist/map/root/map-root.d.ts +40 -2
- package/dist/map/root/map-root.js +64 -23
- 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 +38 -14
- package/dist/megamenu/root/megamenu-root.js +29 -50
- package/dist/menu/item/menu-item.js +4 -4
- package/dist/menu/root/menu-root.d.ts +5 -2
- package/dist/meter/root/meter-root.d.ts +42 -0
- package/dist/meter/root/meter-root.js +33 -7
- package/dist/navigation/root/navigation-root.js +5 -8
- package/dist/notifications/group/notification-group.d.ts +8 -1
- package/dist/notifications/group/notification-group.js +12 -6
- package/dist/notifications/notification/notification.d.ts +12 -1
- package/dist/notifications/notification/notification.js +3 -1
- package/dist/notifications/root/notifications-root.d.ts +48 -3
- package/dist/notifications/root/notifications-root.js +36 -6
- 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 +17 -1
- package/dist/number-input/root/number-input-root.js +29 -18
- package/dist/object-inspector/root/object-inspector-root.d.ts +17 -6
- package/dist/object-inspector/root/object-inspector-root.js +31 -20
- package/dist/option/index.d.ts +1 -0
- package/dist/option/index.js +1 -0
- 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 +12 -0
- package/dist/outline/root/outline-root.js +5 -19
- 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 +51 -1
- package/dist/pin-input/code.js +37 -0
- package/dist/pin-input/root/pin-input-root.d.ts +98 -121
- package/dist/pin-input/root/pin-input-root.js +151 -156
- package/dist/popover/hide-outside.js +2 -9
- package/dist/popover/root/popover-root.d.ts +7 -1
- package/dist/popover/root/popover-root.js +9 -1
- package/dist/progress/root/progress-root.d.ts +27 -0
- package/dist/progress/root/progress-root.js +25 -7
- package/dist/qr-code/export.d.ts +19 -0
- package/dist/qr-code/export.js +14 -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 +31 -9
- package/dist/qr-code/root/qr-code-root.js +29 -17
- package/dist/radio/group/radio-group.d.ts +15 -0
- package/dist/radio/root/radio-root.js +2 -2
- package/dist/rating/root/rating-root.d.ts +22 -9
- package/dist/rating/root/rating-root.js +15 -39
- package/dist/scatter-chart/measures.d.ts +22 -0
- package/dist/scatter-chart/measures.js +11 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +26 -0
- package/dist/scatter-chart/root/scatter-chart-root.js +21 -7
- package/dist/scroll-area/scrollbar.d.ts +0 -8
- package/dist/scroll-area/scrollbar.js +1 -1
- package/dist/select/align.d.ts +47 -0
- package/dist/select/align.js +7 -0
- package/dist/select/root/select-root.d.ts +115 -11
- package/dist/select/root/select-root.js +104 -20
- package/dist/slider/root/slider-root.d.ts +18 -1
- package/dist/slider/root/slider-root.js +22 -0
- package/dist/sparkline/readings.d.ts +30 -12
- package/dist/sparkline/readings.js +32 -15
- package/dist/sparkline/root/sparkline-root.d.ts +46 -3
- package/dist/sparkline/root/sparkline-root.js +60 -21
- package/dist/speed-dial/group/speed-dial-group.d.ts +48 -0
- package/dist/speed-dial/group/speed-dial-group.js +43 -0
- package/dist/speed-dial/index.d.ts +1 -0
- package/dist/speed-dial/index.js +1 -0
- package/dist/speed-dial/item/speed-dial-item.d.ts +27 -2
- package/dist/speed-dial/item/speed-dial-item.js +43 -5
- package/dist/speed-dial/long-press.d.ts +50 -0
- package/dist/speed-dial/long-press.js +48 -0
- package/dist/speed-dial/root/speed-dial-root.d.ts +86 -1
- package/dist/speed-dial/root/speed-dial-root.js +123 -6
- package/dist/splitter/root/splitter-root.d.ts +9 -2
- package/dist/splitter/root/splitter-root.js +18 -3
- package/dist/steps/root/steps-root.d.ts +8 -1
- package/dist/steps/root/steps-root.js +6 -1
- package/dist/steps/step/step.d.ts +1 -0
- package/dist/steps/step/step.js +1 -1
- package/dist/table/cell/table-cell.d.ts +8 -1
- package/dist/table/cell/table-cell.js +6 -2
- package/dist/table/column/table-column.d.ts +6 -0
- package/dist/table/column/table-column.js +5 -1
- package/dist/table/grid-controller.d.ts +117 -0
- package/dist/table/grid-controller.js +293 -0
- package/dist/table/root/table-root.d.ts +47 -3
- package/dist/table/root/table-root.js +93 -29
- package/dist/table/row/table-row.d.ts +36 -0
- package/dist/table/row/table-row.js +52 -2
- package/dist/tabs/root/tabs-root.d.ts +5 -3
- package/dist/tag/group/tag-group.d.ts +16 -4
- package/dist/tag/group/tag-group.js +23 -20
- package/dist/textarea/root/textarea-root.d.ts +14 -2
- package/dist/textarea/root/textarea-root.js +6 -7
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +10 -7
- package/dist/time-picker/root/time-picker-root.d.ts +12 -14
- package/dist/time-picker/root/time-picker-root.js +18 -23
- package/dist/toast/item/toast-item.d.ts +9 -6
- package/dist/toast/item/toast-item.js +1 -1
- package/dist/toast/root/toast-root.d.ts +40 -4
- package/dist/toast/root/toast-root.js +68 -16
- package/dist/toast/words.d.ts +12 -0
- package/dist/toast/words.js +25 -0
- package/dist/toggle/group/toggle-group.d.ts +29 -5
- package/dist/toggle/group/toggle-group.js +26 -43
- package/dist/toggle/root/toggle-root.js +2 -4
- package/dist/toolbar/root/toolbar-root.d.ts +52 -5
- package/dist/toolbar/root/toolbar-root.js +88 -13
- package/dist/tooltip/root/tooltip-root.d.ts +7 -1
- package/dist/tooltip/root/tooltip-root.js +10 -2
- package/dist/tour/root/tour-root.d.ts +15 -0
- package/dist/tour/root/tour-root.js +20 -1
- package/dist/tour/stop/tour-stop.d.ts +3 -0
- package/dist/tour/stop/tour-stop.js +3 -3
- package/dist/tree/root/tree-root.js +2 -2
- package/dist/trend/figure.d.ts +16 -0
- package/dist/trend/figure.js +8 -0
- package/dist/trend/root/trend-root.d.ts +41 -2
- package/dist/trend/root/trend-root.js +29 -3
- 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 +16 -1
- package/dist/video/root/video-root.js +15 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +11 -1
- package/dist/video-playlist/root/video-playlist-root.js +3 -0
- package/dist/virtual-list/fill.d.ts +11 -0
- package/dist/virtual-list/fill.js +9 -0
- package/dist/virtual-list/keys.d.ts +16 -7
- package/dist/virtual-list/keys.js +17 -6
- package/dist/virtual-list/plan.d.ts +17 -1
- package/dist/virtual-list/plan.js +13 -2
- package/dist/virtual-list/root/virtual-list-root.d.ts +25 -3
- package/dist/virtual-list/root/virtual-list-root.js +53 -41
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +4934 -954
- package/types/svelte.d.ts +2 -0
- package/types/vue.d.ts +946 -253
- package/dist/color-picker/swatches.d.ts +0 -12
- package/dist/color-picker/swatches.js +0 -26
- package/dist/rating/steps.d.ts +0 -7
- package/dist/rating/steps.js +0 -9
- package/dist/tooltip/focus-target.d.ts +0 -6
- package/dist/tooltip/focus-target.js +0 -9
|
@@ -4,21 +4,27 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { customElement, deepActiveElement, HelixElement, HelixSelectEvent, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { ariaChord, chordParts, customElement, deepActiveElement, HelixElement, HelixSelectEvent, keyNames, onApple, reportRuntime, slotFilled, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
|
-
import { property } from 'lit/decorators.js';
|
|
9
|
+
import { property, state } from 'lit/decorators.js';
|
|
10
|
+
let toldSelected = false;
|
|
10
11
|
let HelixHeadlessSpeedDialItem = class HelixHeadlessSpeedDialItem extends HelixElement {
|
|
11
12
|
constructor() {
|
|
12
13
|
super(...arguments);
|
|
13
14
|
this.disabled = false;
|
|
15
|
+
this.shortcut = '';
|
|
14
16
|
this.value = '';
|
|
15
17
|
this.isSpeedDialItem = true;
|
|
18
|
+
this.hasShortcut = false;
|
|
19
|
+
this.readShortcut = () => {
|
|
20
|
+
this.hasShortcut = slotFilled(this.renderRoot.querySelector('slot[name="shortcut"]'));
|
|
21
|
+
};
|
|
16
22
|
this.handleClick = () => {
|
|
17
23
|
this.choose();
|
|
18
24
|
};
|
|
19
25
|
}
|
|
20
|
-
focus() {
|
|
21
|
-
this.partNamed('item')?.focus();
|
|
26
|
+
focus(options) {
|
|
27
|
+
this.partNamed('item')?.focus(options);
|
|
22
28
|
}
|
|
23
29
|
focusItem() {
|
|
24
30
|
this.focus();
|
|
@@ -31,6 +37,14 @@ let HelixHeadlessSpeedDialItem = class HelixHeadlessSpeedDialItem extends HelixE
|
|
|
31
37
|
return active !== null && active.getRootNode() === this.renderRoot;
|
|
32
38
|
}
|
|
33
39
|
get selected() {
|
|
40
|
+
if (!toldSelected) {
|
|
41
|
+
toldSelected = true;
|
|
42
|
+
reportRuntime({
|
|
43
|
+
kind: 'deprecated',
|
|
44
|
+
message: `<${this.localName}>.selected is deprecated: read \`active\`, which says the same.`,
|
|
45
|
+
tag: this.localName,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
34
48
|
return this.active;
|
|
35
49
|
}
|
|
36
50
|
choose() {
|
|
@@ -40,26 +54,50 @@ let HelixHeadlessSpeedDialItem = class HelixHeadlessSpeedDialItem extends HelixE
|
|
|
40
54
|
this.dispatchEvent(new HelixSelectEvent({ value: this.value }));
|
|
41
55
|
}
|
|
42
56
|
render() {
|
|
57
|
+
const keys = this.shortcut === '' ? nothing : ariaChord(this.shortcut, !this.hydrating && onApple());
|
|
43
58
|
return html `<button
|
|
44
59
|
part="item"
|
|
45
60
|
role="menuitem"
|
|
46
61
|
type="button"
|
|
47
62
|
aria-disabled=${this.disabled ? 'true' : nothing}
|
|
63
|
+
aria-keyshortcuts=${keys}
|
|
48
64
|
?disabled=${this.disabled}
|
|
49
65
|
tabindex="-1"
|
|
50
66
|
@click=${this.handleClick}
|
|
51
67
|
>
|
|
52
68
|
<span part="icon"><slot name="icon"></slot></span>
|
|
53
|
-
<span part="label"><slot></slot
|
|
69
|
+
<span part="label"><slot></slot><span
|
|
70
|
+
part="shortcut"
|
|
71
|
+
aria-hidden="true"
|
|
72
|
+
?hidden=${!this.hasShortcut && this.shortcut === ''}
|
|
73
|
+
>${this.renderShortcut()}</span
|
|
74
|
+
></span>
|
|
54
75
|
</button>`;
|
|
55
76
|
}
|
|
77
|
+
renderShortcut() {
|
|
78
|
+
const drawn = keyNames(chordParts(this.shortcut), !this.hydrating && onApple());
|
|
79
|
+
return html `<slot name="shortcut" @slotchange=${this.readShortcut}>${drawn.keys.join(drawn.separator)}</slot>`;
|
|
80
|
+
}
|
|
81
|
+
firstUpdated(changed) {
|
|
82
|
+
super.firstUpdated(changed);
|
|
83
|
+
this.readShortcut();
|
|
84
|
+
if (this.shortcut !== '') {
|
|
85
|
+
this.finishHydration();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
56
88
|
};
|
|
57
89
|
__decorate([
|
|
58
90
|
property({ reflect: true, type: Boolean })
|
|
59
91
|
], HelixHeadlessSpeedDialItem.prototype, "disabled", void 0);
|
|
92
|
+
__decorate([
|
|
93
|
+
property()
|
|
94
|
+
], HelixHeadlessSpeedDialItem.prototype, "shortcut", void 0);
|
|
60
95
|
__decorate([
|
|
61
96
|
property()
|
|
62
97
|
], HelixHeadlessSpeedDialItem.prototype, "value", void 0);
|
|
98
|
+
__decorate([
|
|
99
|
+
state()
|
|
100
|
+
], HelixHeadlessSpeedDialItem.prototype, "hasShortcut", void 0);
|
|
63
101
|
HelixHeadlessSpeedDialItem = __decorate([
|
|
64
102
|
customElement('helix-headless-speed-dial-item')
|
|
65
103
|
], HelixHeadlessSpeedDialItem);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { ReactiveControllerHost } from 'lit';
|
|
2
|
+
/** How long a press is held before it counts, in milliseconds, as React Aria waits. */
|
|
3
|
+
export declare const LONG_PRESS_DELAY = 500;
|
|
4
|
+
/**
|
|
5
|
+
* How far a held pointer may drift and still be the same press, in pixels. A
|
|
6
|
+
* finger is never still, and one that moves further is scrolling or dragging.
|
|
7
|
+
*/
|
|
8
|
+
export declare const LONG_PRESS_SLOP = 10;
|
|
9
|
+
/** What a long press reads and calls. */
|
|
10
|
+
export interface LongPressOptions {
|
|
11
|
+
/** Called once a press has been held for the delay without drifting. */
|
|
12
|
+
onLongPress: () => void;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Watches one control's presses for a held one.
|
|
16
|
+
*
|
|
17
|
+
* The control's own handlers call `down`, `move` and `up`, so a press counts
|
|
18
|
+
* only where it started on the control, and `cancel` drops it. The click a
|
|
19
|
+
* held press ends in is the long press's, and `takeClick` says so once, so the
|
|
20
|
+
* control's own action does not run as well.
|
|
21
|
+
*/
|
|
22
|
+
export declare class LongPress {
|
|
23
|
+
private readonly options;
|
|
24
|
+
private readonly wait;
|
|
25
|
+
/** Where the press began, while one is held and still counts. */
|
|
26
|
+
private from;
|
|
27
|
+
/** Whether the press that just ended was a long one, until its click is taken. */
|
|
28
|
+
private held;
|
|
29
|
+
constructor(host: ReactiveControllerHost, options: LongPressOptions);
|
|
30
|
+
/** Starts the wait for a press of the primary button. */
|
|
31
|
+
down(event: PointerEvent): void;
|
|
32
|
+
/** Drops the press once the pointer drifts past the slop. */
|
|
33
|
+
move(event: PointerEvent): void;
|
|
34
|
+
/**
|
|
35
|
+
* Ends the press. A press released before the delay is an ordinary one.
|
|
36
|
+
*
|
|
37
|
+
* A held one keeps its claim on a click only until the task ends: the click
|
|
38
|
+
* a release makes comes in the same task, and a release that makes none, off
|
|
39
|
+
* the control or after a touch's own menu, must not leave the next Enter on
|
|
40
|
+
* the control swallowed.
|
|
41
|
+
*/
|
|
42
|
+
up(): void;
|
|
43
|
+
/** Drops the press, which then neither opens anything nor swallows a click. */
|
|
44
|
+
cancel(): void;
|
|
45
|
+
/**
|
|
46
|
+
* Whether a click belongs to the long press that just ended, and so is not
|
|
47
|
+
* the control's. True once.
|
|
48
|
+
*/
|
|
49
|
+
takeClick(): boolean;
|
|
50
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { DelayController } from '@fusion.dev/helix-core';
|
|
2
|
+
export const LONG_PRESS_DELAY = 500;
|
|
3
|
+
export const LONG_PRESS_SLOP = 10;
|
|
4
|
+
export class LongPress {
|
|
5
|
+
constructor(host, options) {
|
|
6
|
+
this.options = options;
|
|
7
|
+
this.from = undefined;
|
|
8
|
+
this.held = false;
|
|
9
|
+
this.wait = new DelayController(host);
|
|
10
|
+
}
|
|
11
|
+
down(event) {
|
|
12
|
+
this.held = false;
|
|
13
|
+
if (event.button !== 0) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
this.from = { x: event.clientX, y: event.clientY };
|
|
17
|
+
this.wait.start(LONG_PRESS_DELAY, () => {
|
|
18
|
+
this.from = undefined;
|
|
19
|
+
this.held = true;
|
|
20
|
+
this.options.onLongPress();
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
move(event) {
|
|
24
|
+
const from = this.from;
|
|
25
|
+
if (from && Math.hypot(event.clientX - from.x, event.clientY - from.y) > LONG_PRESS_SLOP) {
|
|
26
|
+
this.cancel();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
up() {
|
|
30
|
+
this.from = undefined;
|
|
31
|
+
this.wait.cancel();
|
|
32
|
+
if (this.held) {
|
|
33
|
+
setTimeout(() => {
|
|
34
|
+
this.held = false;
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
cancel() {
|
|
39
|
+
this.from = undefined;
|
|
40
|
+
this.held = false;
|
|
41
|
+
this.wait.cancel();
|
|
42
|
+
}
|
|
43
|
+
takeClick() {
|
|
44
|
+
const held = this.held;
|
|
45
|
+
this.held = false;
|
|
46
|
+
return held;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -25,6 +25,31 @@ declare const HelixHeadlessSpeedDial_base: (new (...args: any[]) => import("@fus
|
|
|
25
25
|
* action whose name starts with it. The actions are one tab stop, and Tab
|
|
26
26
|
* closes the dial and moves on.
|
|
27
27
|
*
|
|
28
|
+
* **Keyboard.** On the trigger, Enter, Space or a press opens the dial on its
|
|
29
|
+
* first action. With the dial open:
|
|
30
|
+
*
|
|
31
|
+
* | Key | What it does |
|
|
32
|
+
* |---|---|
|
|
33
|
+
* | Down, Right | Moves to the next action, from the last back to the first. |
|
|
34
|
+
* | Up, Left | Moves to the action before, from the first round to the last. |
|
|
35
|
+
* | Home, End | Moves to the first or the last action. |
|
|
36
|
+
* | A letter | Moves to the next action whose name starts with it. |
|
|
37
|
+
* | Enter, Space | Chooses the action, and the dial closes. |
|
|
38
|
+
* | Escape | Closes the dial and puts focus back on the trigger. |
|
|
39
|
+
* | Tab | Closes the dial and moves on. |
|
|
40
|
+
*
|
|
41
|
+
* **Groups.** Put actions in `Speed Dial.Group`, named by its `label`, to set
|
|
42
|
+
* them apart as Menu's sections do: each is a `group` of the menu, and the
|
|
43
|
+
* arrow keys walk through every group's actions in order.
|
|
44
|
+
*
|
|
45
|
+
* **A trigger with its own action.** With `open-on="long-press"`, a press on
|
|
46
|
+
* the trigger is the trigger's own, such as composing a message, and holding it
|
|
47
|
+
* for half a second opens the dial, as React Aria's menu trigger does with
|
|
48
|
+
* `trigger="longPress"`. Alt+Down or Alt+Up opens it from the keyboard, and
|
|
49
|
+
* the trigger says so in its description, `long-press-label`, the drawn one
|
|
50
|
+
* and a slotted one alike. A press that has opened the dial does not also do
|
|
51
|
+
* the trigger's action.
|
|
52
|
+
*
|
|
28
53
|
* @since 0.1.0
|
|
29
54
|
* @status stable
|
|
30
55
|
* @category actions
|
|
@@ -49,10 +74,26 @@ export declare class HelixHeadlessSpeedDial extends HelixHeadlessSpeedDial_base
|
|
|
49
74
|
* Accessible name for the trigger and the set of actions it opens.
|
|
50
75
|
*/
|
|
51
76
|
label: string;
|
|
77
|
+
/**
|
|
78
|
+
* The description the trigger gives under `open-on="long-press"`, saying how
|
|
79
|
+
* its actions are reached.
|
|
80
|
+
*
|
|
81
|
+
* A slotted trigger is described by the dial, which carries the words as
|
|
82
|
+
* its own label for that: a Helix button's inner control at once, and a
|
|
83
|
+
* plain element of yours once a reader reaches it, after hydration, unless
|
|
84
|
+
* you described or labeled it yourself.
|
|
85
|
+
*/
|
|
86
|
+
longPressLabel: string;
|
|
52
87
|
/**
|
|
53
88
|
* Space between the trigger and the actions, in pixels.
|
|
54
89
|
*/
|
|
55
90
|
offset: number;
|
|
91
|
+
/**
|
|
92
|
+
* What opens the dial. `click` opens it on a press of the trigger. Under
|
|
93
|
+
* `long-press`, a press is the trigger's own action, and the dial opens on a
|
|
94
|
+
* press held for half a second, or on Alt+Down or Alt+Up.
|
|
95
|
+
*/
|
|
96
|
+
openOn: 'click' | 'long-press';
|
|
56
97
|
/**
|
|
57
98
|
* The direction the actions open in. They move to another side if that side
|
|
58
99
|
* does not fit.
|
|
@@ -74,11 +115,34 @@ export declare class HelixHeadlessSpeedDial extends HelixHeadlessSpeedDial_base
|
|
|
74
115
|
protected readonly panel: PopoverController;
|
|
75
116
|
/** Whatever the consumer slotted, or the button rendered in its place. */
|
|
76
117
|
private get trigger();
|
|
77
|
-
/**
|
|
118
|
+
/**
|
|
119
|
+
* The actions, in order: this element's own rows, and the rows of each group
|
|
120
|
+
* slotted beside them, and nothing else slotted.
|
|
121
|
+
*/
|
|
78
122
|
private get items();
|
|
123
|
+
/** Watches the trigger for a held press, under `open-on="long-press"`. */
|
|
124
|
+
private readonly longPress;
|
|
125
|
+
private get pressHeld();
|
|
126
|
+
/**
|
|
127
|
+
* Puts focus on the trigger, the slotted one or the button drawn in its
|
|
128
|
+
* place, as a `focus()` on a native control would. The host itself takes no
|
|
129
|
+
* focus, so a page focusing it after a dialog closes landed nowhere.
|
|
130
|
+
*/
|
|
131
|
+
focus(options?: FocusOptions): void;
|
|
79
132
|
/** Shuts it and puts the reader back on the trigger. */
|
|
80
133
|
private close;
|
|
81
134
|
private readonly handleTriggerClick;
|
|
135
|
+
/**
|
|
136
|
+
* Takes the click a held press ends in, ahead of the trigger's own
|
|
137
|
+
* listeners, so a press that opened the dial does not also do the trigger's
|
|
138
|
+
* action. In capture, on the host, which is above a slotted trigger.
|
|
139
|
+
*/
|
|
140
|
+
private readonly handleHeldClick;
|
|
141
|
+
private readonly handleTriggerPointerDown;
|
|
142
|
+
private readonly handleTriggerPointerMove;
|
|
143
|
+
private readonly handleTriggerPointerUp;
|
|
144
|
+
private readonly handleTriggerPointerCancel;
|
|
145
|
+
private readonly handleTriggerContextMenu;
|
|
82
146
|
private readonly handleSelect;
|
|
83
147
|
private readonly handleKeydown;
|
|
84
148
|
connectedCallback(): void;
|
|
@@ -107,6 +171,27 @@ export declare class HelixHeadlessSpeedDial extends HelixHeadlessSpeedDial_base
|
|
|
107
171
|
* is expanded is already saying it has something to expand.
|
|
108
172
|
*/
|
|
109
173
|
private announce;
|
|
174
|
+
/** The control the dial has described, so the description can be taken back. */
|
|
175
|
+
private described;
|
|
176
|
+
/**
|
|
177
|
+
* Describes a slotted trigger by `long-press-label` under
|
|
178
|
+
* `open-on="long-press"`, as the drawn one is, or takes it back.
|
|
179
|
+
*
|
|
180
|
+
* **By the host, which carries the words as its label.** The drawn
|
|
181
|
+
* trigger's description is in this shadow root, and a reference from the
|
|
182
|
+
* consumer's trigger, or from the button inside a Helix one, cannot point
|
|
183
|
+
* in; it can point out, to the host. Core's `linkDescription` says where
|
|
184
|
+
* that is safe: inside a component's shadow root always, and on the
|
|
185
|
+
* consumer's own element only once `light` says a reader has acted, which
|
|
186
|
+
* is after hydration. React Aria's long press describes whatever trigger it
|
|
187
|
+
* is given.
|
|
188
|
+
*
|
|
189
|
+
* @param light A reader has just reached the trigger.
|
|
190
|
+
*/
|
|
191
|
+
private describeTrigger;
|
|
192
|
+
/** A reader reaching a slotted trigger, which is late enough to describe a plain one. */
|
|
193
|
+
private readonly handleTriggerFocusIn;
|
|
194
|
+
protected firstUpdated(changed: PropertyValues): void;
|
|
110
195
|
protected updated(changed: PropertyValues): void;
|
|
111
196
|
/**
|
|
112
197
|
* The control that opens it, behind a seam the styled tier can move.
|
|
@@ -4,20 +4,31 @@ 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, drawIcon, HelixElement, KeyboardNavigationController, MixinControllerOpen, PopoverController, slottedWords, tellDisclosure,
|
|
7
|
+
import { anchorElement, customElement, drawIcon, focusTarget, HelixElement, KeyboardNavigationController, linkDescription, MixinControllerOpen, PopoverController, slottedWords, tellDisclosure, typeaheadByWords, unlinkDescription, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { plus } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property } from 'lit/decorators.js';
|
|
11
|
+
import { LongPress } from '../long-press.js';
|
|
12
|
+
const navigable = (item) => ({
|
|
13
|
+
contains: (node) => item.contains(node),
|
|
14
|
+
disabled: item.disabled,
|
|
15
|
+
focusItem: () => item.focusItem(),
|
|
16
|
+
select: () => item.select(),
|
|
17
|
+
selected: item.active,
|
|
18
|
+
words: slottedWords(item, ['']),
|
|
19
|
+
});
|
|
11
20
|
let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControllerOpen(HelixElement) {
|
|
12
21
|
constructor() {
|
|
13
22
|
super(...arguments);
|
|
14
23
|
this.label = 'Actions';
|
|
24
|
+
this.longPressLabel = 'Long press or press Alt+Down to show the actions';
|
|
15
25
|
this.offset = 12;
|
|
26
|
+
this.openOn = 'click';
|
|
16
27
|
this.placement = 'top-end';
|
|
17
28
|
this.keys = new KeyboardNavigationController(this, {
|
|
18
|
-
items: () => (this.open ? this.items : []),
|
|
29
|
+
items: () => (this.open ? this.items.map(navigable) : []),
|
|
19
30
|
selects: () => false,
|
|
20
|
-
typeahead:
|
|
31
|
+
typeahead: typeaheadByWords(),
|
|
21
32
|
});
|
|
22
33
|
this.focusOnOpen = false;
|
|
23
34
|
this.panel = new PopoverController(this, {
|
|
@@ -29,13 +40,48 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
|
|
|
29
40
|
placement: () => this.placement,
|
|
30
41
|
surface: () => this.partNamed('actions'),
|
|
31
42
|
});
|
|
43
|
+
this.longPress = new LongPress(this, {
|
|
44
|
+
onLongPress: () => {
|
|
45
|
+
if (!this.open) {
|
|
46
|
+
this.focusOnOpen = this.requestOpen(true);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
});
|
|
32
50
|
this.handleTriggerClick = () => {
|
|
33
51
|
if (this.open) {
|
|
34
52
|
this.requestOpen(false);
|
|
35
53
|
return;
|
|
36
54
|
}
|
|
55
|
+
if (this.pressHeld) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
37
58
|
this.focusOnOpen = this.requestOpen(true);
|
|
38
59
|
};
|
|
60
|
+
this.handleHeldClick = (event) => {
|
|
61
|
+
if (this.pressHeld && this.longPress.takeClick()) {
|
|
62
|
+
event.stopImmediatePropagation();
|
|
63
|
+
event.preventDefault();
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
this.handleTriggerPointerDown = (event) => {
|
|
67
|
+
if (this.pressHeld && !this.open) {
|
|
68
|
+
this.longPress.down(event);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
this.handleTriggerPointerMove = (event) => {
|
|
72
|
+
this.longPress.move(event);
|
|
73
|
+
};
|
|
74
|
+
this.handleTriggerPointerUp = () => {
|
|
75
|
+
this.longPress.up();
|
|
76
|
+
};
|
|
77
|
+
this.handleTriggerPointerCancel = () => {
|
|
78
|
+
this.longPress.cancel();
|
|
79
|
+
};
|
|
80
|
+
this.handleTriggerContextMenu = (event) => {
|
|
81
|
+
if (this.pressHeld) {
|
|
82
|
+
event.preventDefault();
|
|
83
|
+
}
|
|
84
|
+
};
|
|
39
85
|
this.handleSelect = (event) => {
|
|
40
86
|
queueMicrotask(() => {
|
|
41
87
|
if (!event.defaultPrevented) {
|
|
@@ -45,6 +91,12 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
|
|
|
45
91
|
};
|
|
46
92
|
this.handleKeydown = (event) => {
|
|
47
93
|
if (!this.open) {
|
|
94
|
+
if (this.pressHeld &&
|
|
95
|
+
event.altKey &&
|
|
96
|
+
(event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
|
|
97
|
+
event.preventDefault();
|
|
98
|
+
this.focusOnOpen = this.requestOpen(true);
|
|
99
|
+
}
|
|
48
100
|
return;
|
|
49
101
|
}
|
|
50
102
|
if (event.key === 'Tab') {
|
|
@@ -58,29 +110,57 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
|
|
|
58
110
|
this.close();
|
|
59
111
|
event.preventDefault();
|
|
60
112
|
};
|
|
113
|
+
this.handleTriggerFocusIn = () => {
|
|
114
|
+
if (this.pressHeld) {
|
|
115
|
+
this.describeTrigger(true);
|
|
116
|
+
}
|
|
117
|
+
};
|
|
61
118
|
}
|
|
62
119
|
get trigger() {
|
|
63
120
|
return anchorElement(this.renderRoot?.querySelector('slot[name="trigger"]'), this.partNamed('trigger') ?? this);
|
|
64
121
|
}
|
|
65
122
|
get items() {
|
|
66
123
|
const slot = this.renderRoot?.querySelector('slot:not([name])');
|
|
67
|
-
|
|
124
|
+
const isItem = (one) => one.isSpeedDialItem === true;
|
|
125
|
+
return (slot?.assignedElements?.() ?? []).flatMap((one) => isItem(one)
|
|
126
|
+
? [one]
|
|
127
|
+
: one.isSpeedDialGroup === true
|
|
128
|
+
? [...one.children].filter(isItem)
|
|
129
|
+
: []);
|
|
130
|
+
}
|
|
131
|
+
get pressHeld() {
|
|
132
|
+
return this.openOn === 'long-press';
|
|
133
|
+
}
|
|
134
|
+
focus(options) {
|
|
135
|
+
const trigger = this.trigger;
|
|
136
|
+
if (trigger === this) {
|
|
137
|
+
super.focus(options);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
trigger.focus(options);
|
|
68
141
|
}
|
|
69
142
|
close() {
|
|
70
143
|
if (!this.requestOpen(false)) {
|
|
71
144
|
return;
|
|
72
145
|
}
|
|
73
|
-
this.
|
|
146
|
+
this.focus();
|
|
74
147
|
}
|
|
75
148
|
connectedCallback() {
|
|
76
149
|
super.connectedCallback();
|
|
77
150
|
this.addEventListener('helix-select', this.handleSelect);
|
|
78
151
|
this.addEventListener('keydown', this.handleKeydown);
|
|
152
|
+
this.addEventListener('click', this.handleHeldClick, true);
|
|
79
153
|
}
|
|
80
154
|
disconnectedCallback() {
|
|
81
155
|
super.disconnectedCallback();
|
|
156
|
+
if (this.described) {
|
|
157
|
+
unlinkDescription(this.described, this);
|
|
158
|
+
this.described = undefined;
|
|
159
|
+
this.internals.ariaLabel = null;
|
|
160
|
+
}
|
|
82
161
|
this.removeEventListener('helix-select', this.handleSelect);
|
|
83
162
|
this.removeEventListener('keydown', this.handleKeydown);
|
|
163
|
+
this.removeEventListener('click', this.handleHeldClick, true);
|
|
84
164
|
}
|
|
85
165
|
announce() {
|
|
86
166
|
const trigger = this.trigger;
|
|
@@ -89,9 +169,27 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
|
|
|
89
169
|
}
|
|
90
170
|
tellDisclosure(trigger, this.open, 'menu');
|
|
91
171
|
}
|
|
172
|
+
describeTrigger(light = false) {
|
|
173
|
+
const trigger = this.trigger;
|
|
174
|
+
const slotted = this.pressHeld && trigger !== this && trigger !== this.partNamed('trigger');
|
|
175
|
+
const control = slotted ? focusTarget(trigger) : undefined;
|
|
176
|
+
if (this.described && this.described !== control) {
|
|
177
|
+
unlinkDescription(this.described, this);
|
|
178
|
+
this.described = undefined;
|
|
179
|
+
}
|
|
180
|
+
if (control && control !== this.described && linkDescription(control, this, light)) {
|
|
181
|
+
this.described = control;
|
|
182
|
+
}
|
|
183
|
+
this.internals.ariaLabel = this.described ? this.longPressLabel : null;
|
|
184
|
+
}
|
|
185
|
+
firstUpdated(changed) {
|
|
186
|
+
super.firstUpdated(changed);
|
|
187
|
+
requestAnimationFrame(() => this.describeTrigger());
|
|
188
|
+
}
|
|
92
189
|
updated(changed) {
|
|
93
190
|
super.updated?.(changed);
|
|
94
191
|
this.announce();
|
|
192
|
+
this.describeTrigger();
|
|
95
193
|
if (this.open && this.focusOnOpen) {
|
|
96
194
|
this.focusOnOpen = false;
|
|
97
195
|
this.updateComplete.then(() => {
|
|
@@ -102,10 +200,22 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
|
|
|
102
200
|
}
|
|
103
201
|
}
|
|
104
202
|
renderTrigger() {
|
|
105
|
-
|
|
203
|
+
const held = this.pressHeld;
|
|
204
|
+
return html `<slot
|
|
205
|
+
name="trigger"
|
|
206
|
+
@click=${this.handleTriggerClick}
|
|
207
|
+
@contextmenu=${this.handleTriggerContextMenu}
|
|
208
|
+
@focusin=${this.handleTriggerFocusIn}
|
|
209
|
+
@pointercancel=${this.handleTriggerPointerCancel}
|
|
210
|
+
@pointerdown=${this.handleTriggerPointerDown}
|
|
211
|
+
@pointermove=${this.handleTriggerPointerMove}
|
|
212
|
+
@pointerup=${this.handleTriggerPointerUp}
|
|
213
|
+
@slotchange=${() => this.describeTrigger()}
|
|
214
|
+
>
|
|
106
215
|
<button
|
|
107
216
|
part="trigger"
|
|
108
217
|
type="button"
|
|
218
|
+
aria-describedby=${held ? 'long-press' : nothing}
|
|
109
219
|
aria-expanded=${this.open ? 'true' : 'false'}
|
|
110
220
|
aria-haspopup="menu"
|
|
111
221
|
aria-label=${this.label}
|
|
@@ -113,6 +223,7 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
|
|
|
113
223
|
${''}
|
|
114
224
|
${drawIcon(plus)}
|
|
115
225
|
</button>
|
|
226
|
+
${held ? html `<span id="long-press" hidden>${this.longPressLabel}</span>` : nothing}
|
|
116
227
|
</slot>`;
|
|
117
228
|
}
|
|
118
229
|
render() {
|
|
@@ -131,9 +242,15 @@ let HelixHeadlessSpeedDial = class HelixHeadlessSpeedDial extends MixinControlle
|
|
|
131
242
|
__decorate([
|
|
132
243
|
property()
|
|
133
244
|
], HelixHeadlessSpeedDial.prototype, "label", void 0);
|
|
245
|
+
__decorate([
|
|
246
|
+
property({ attribute: 'long-press-label' })
|
|
247
|
+
], HelixHeadlessSpeedDial.prototype, "longPressLabel", void 0);
|
|
134
248
|
__decorate([
|
|
135
249
|
property({ type: Number })
|
|
136
250
|
], HelixHeadlessSpeedDial.prototype, "offset", void 0);
|
|
251
|
+
__decorate([
|
|
252
|
+
property({ attribute: 'open-on' })
|
|
253
|
+
], HelixHeadlessSpeedDial.prototype, "openOn", void 0);
|
|
137
254
|
__decorate([
|
|
138
255
|
property()
|
|
139
256
|
], HelixHeadlessSpeedDial.prototype, "placement", void 0);
|
|
@@ -13,8 +13,9 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
13
13
|
* added at `firstUpdated` and is not in the server markup. Before it appears,
|
|
14
14
|
* both dividers work on their own.
|
|
15
15
|
*
|
|
16
|
-
* The divider has `role="separator"` and `aria-valuenow`,
|
|
17
|
-
*
|
|
16
|
+
* The divider has `role="separator"` and `aria-valuenow`, with
|
|
17
|
+
* `aria-valuetext` saying the start pane's share as a percentage in the
|
|
18
|
+
* reader's locale, and `aria-controls` names the start pane. Drag it with a pointer or move it with the arrow keys,
|
|
18
19
|
* press `Home` or `End` to move it to its bounds, and press `Enter` to collapse
|
|
19
20
|
* the start pane and open it again. A drag in progress is tracked as a state, so both dividers a
|
|
20
21
|
* corner moves stay lit for as long as they move.
|
|
@@ -36,12 +37,14 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
36
37
|
* @documentation https://fusion.dev/helix/components/splitter
|
|
37
38
|
*
|
|
38
39
|
* @slot end - The pane after the divider.
|
|
40
|
+
* @slot handle - A mark drawn at the middle of the divider, such as a grip icon. It takes no focus and no pointer of its own: a press on it is a press on the divider.
|
|
39
41
|
* @slot start - The pane before the divider.
|
|
40
42
|
*
|
|
41
43
|
* @event {HelixBeforeCollapseEvent} helix-before-collapse - Fired before a pane shuts or reopens, whether or not the resize that caused it was allowed. It carries its own position, because a shut pane sits at `collapsed-size`. Cancelable: canceling it leaves the pane as it was and the divider where the gesture put it.
|
|
42
44
|
* @event {HelixBeforeResizeEvent} helix-before-resize - Fired before the divider settles, and only when the gesture moved it. A press that moved nothing, a drag that came back, an arrow key with no room left, and a corner that moved only the other divider do not fire it. Cancelable: canceling it leaves the position to you and keeps the rest of the gesture, so a collapse the gesture reached still fires `helix-before-collapse`, which you can also cancel. A dragged divider stays where it was dropped until you set your own `position`.
|
|
43
45
|
* @event {HelixCollapseEvent} helix-collapse - Fired after a pane shuts or reopens, with the side that is shut, or empty where both are open.
|
|
44
46
|
* @event {HelixResizedEvent} helix-resized - Fired after the divider settles somewhere new, with the new position.
|
|
47
|
+
* @event {Event} input - Fired each time the divider moves, as a range input does: on each step of a drag, and before `helix-resized` for a key, a double click or a corner. Read `position` for where it is now.
|
|
45
48
|
*
|
|
46
49
|
* @csspart corner - The handle where two dividers cross, added on the client.
|
|
47
50
|
* @csspart end - The box that holds the second pane.
|
|
@@ -50,6 +53,10 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
50
53
|
*
|
|
51
54
|
* @cssproperty --splitter-corner-at - Where a nested splitter crosses this one, as a percentage.
|
|
52
55
|
* @cssproperty --splitter-position - Where the divider sits, as a percentage of the box.
|
|
56
|
+
*
|
|
57
|
+
* @cssstate collapsed - While a pane is shut. `data-collapsed` on the host says which.
|
|
58
|
+
* @cssstate dragging - While the pointer or a corner holds the divider.
|
|
59
|
+
* @cssstate vertical - While the panes are one above the other, whether `orientation` says so or `auto` turned them.
|
|
53
60
|
*/
|
|
54
61
|
export declare class HelixHeadlessSplitter extends HelixElement {
|
|
55
62
|
/**
|
|
@@ -5,7 +5,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
var HelixHeadlessSplitter_1;
|
|
8
|
-
import { AriaForwardController, capturePointer, closestInstance, commaList, customElement, HelixBeforeCollapseEvent, HelixBeforeResizeEvent, HelixCollapseEvent, HelixElement, HelixResizedEvent, inlineStep, isRtl, requestChange, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { AriaForwardController, capturePointer, closestInstance, commaList, customElement, formatPercent, HelixBeforeCollapseEvent, HelixBeforeResizeEvent, HelixCollapseEvent, HelixElement, HelixResizedEvent, inlineStep, isRtl, requestChange, } from '@fusion.dev/helix-core';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { snapTo } from '../snap.js';
|
|
@@ -127,6 +127,7 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
|
|
|
127
127
|
this.positionState = wanted;
|
|
128
128
|
this.collapsedState = 'none';
|
|
129
129
|
this.requestUpdate('position', previous);
|
|
130
|
+
this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
|
|
130
131
|
}
|
|
131
132
|
settle(next) {
|
|
132
133
|
const wanted = this.clamp(next);
|
|
@@ -143,6 +144,9 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
|
|
|
143
144
|
const previous = this.position;
|
|
144
145
|
this.positionState = value;
|
|
145
146
|
this.requestUpdate('position', previous);
|
|
147
|
+
if (value !== previous) {
|
|
148
|
+
this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
|
|
149
|
+
}
|
|
146
150
|
this.dispatchEvent(new HelixResizedEvent({ value: String(value) }));
|
|
147
151
|
},
|
|
148
152
|
event: (value) => new HelixBeforeResizeEvent({ value: String(value) }),
|
|
@@ -446,6 +450,7 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
|
|
|
446
450
|
super.firstUpdated(changed);
|
|
447
451
|
this.watchWidth();
|
|
448
452
|
this.findOuter();
|
|
453
|
+
this.finishHydration();
|
|
449
454
|
}
|
|
450
455
|
updated(changed) {
|
|
451
456
|
super.updated(changed);
|
|
@@ -471,6 +476,9 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
|
|
|
471
476
|
}
|
|
472
477
|
willUpdate(changed) {
|
|
473
478
|
super.willUpdate(changed);
|
|
479
|
+
this.toggleState('dragging', this.dragging);
|
|
480
|
+
this.toggleState('collapsed', this.collapsed !== undefined);
|
|
481
|
+
this.toggleState('vertical', this.vertical);
|
|
474
482
|
}
|
|
475
483
|
render() {
|
|
476
484
|
const position = this.showing;
|
|
@@ -492,7 +500,11 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
|
|
|
492
500
|
aria-valuemax=${this.collapsed ? 100 : this.clamp(this.maxPercent)}
|
|
493
501
|
aria-valuemin=${this.collapsed ? 0 : this.clamp(this.minPercent)}
|
|
494
502
|
aria-valuenow=${Math.round(position)}
|
|
495
|
-
aria-valuetext=${this.collapsed
|
|
503
|
+
aria-valuetext=${this.collapsed
|
|
504
|
+
? this.collapsedLabel
|
|
505
|
+
: this.hydrating
|
|
506
|
+
? nothing
|
|
507
|
+
: formatPercent(Math.round(position) / 100)}
|
|
496
508
|
?data-dragging=${this.dragging}
|
|
497
509
|
?data-flush=${this.flush}
|
|
498
510
|
@dblclick=${this.handleDoubleClick}
|
|
@@ -501,7 +513,9 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
|
|
|
501
513
|
@pointerdown=${this.handlePointerDown}
|
|
502
514
|
@pointermove=${this.handlePointerMove}
|
|
503
515
|
@pointerup=${this.handlePointerUp}
|
|
504
|
-
|
|
516
|
+
>
|
|
517
|
+
<slot name="handle"></slot>
|
|
518
|
+
</div>
|
|
505
519
|
<div part="end" ?data-dragging=${this.dragging}>
|
|
506
520
|
<slot name="end"></slot>
|
|
507
521
|
</div>
|
|
@@ -514,6 +528,7 @@ let HelixHeadlessSplitter = HelixHeadlessSplitter_1 = class HelixHeadlessSplitte
|
|
|
514
528
|
aria-valuemax="100"
|
|
515
529
|
aria-valuemin="0"
|
|
516
530
|
aria-valuenow=${Math.round(crossing.at)}
|
|
531
|
+
aria-valuetext=${formatPercent(Math.round(crossing.at) / 100)}
|
|
517
532
|
data-cross=${index}
|
|
518
533
|
style="--splitter-corner-at: ${crossing.at}%; --splitter-position: ${position}%"
|
|
519
534
|
@dblclick=${this.handleCornerDoubleClick}
|