@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,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { ariaChord, chordParts, customElement, elementById, HelixElement, HelixShortcutEvent, matchesChord, onApple, printableChord, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { ariaChord, chordParts, customElement, elementById, HelixElement, HelixShortcutEvent, keyNames, matchesChord, onApple, printableChord, wordsConverter, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { claimShortcut, releaseShortcut } from '../shortcut.js';
|
|
@@ -29,49 +29,12 @@ const UNTYPED = new Set([
|
|
|
29
29
|
'reset',
|
|
30
30
|
'submit',
|
|
31
31
|
]);
|
|
32
|
-
const APPLE = {
|
|
33
|
-
alt: '⌥',
|
|
34
|
-
backspace: '⌫',
|
|
35
|
-
cmd: '⌘',
|
|
36
|
-
ctrl: '⌃',
|
|
37
|
-
del: '⌦',
|
|
38
|
-
down: '↓',
|
|
39
|
-
enter: '↵',
|
|
40
|
-
esc: 'Esc',
|
|
41
|
-
left: '←',
|
|
42
|
-
meta: '⌘',
|
|
43
|
-
mod: '⌘',
|
|
44
|
-
opt: '⌥',
|
|
45
|
-
right: '→',
|
|
46
|
-
shift: '⇧',
|
|
47
|
-
space: 'Space',
|
|
48
|
-
tab: '⇥',
|
|
49
|
-
up: '↑',
|
|
50
|
-
};
|
|
51
|
-
const ELSEWHERE = {
|
|
52
|
-
alt: 'Alt',
|
|
53
|
-
backspace: 'Backspace',
|
|
54
|
-
cmd: 'Win',
|
|
55
|
-
ctrl: 'Ctrl',
|
|
56
|
-
del: 'Del',
|
|
57
|
-
down: '↓',
|
|
58
|
-
enter: 'Enter',
|
|
59
|
-
esc: 'Esc',
|
|
60
|
-
left: '←',
|
|
61
|
-
meta: 'Win',
|
|
62
|
-
mod: 'Ctrl',
|
|
63
|
-
opt: 'Alt',
|
|
64
|
-
right: '→',
|
|
65
|
-
shift: 'Shift',
|
|
66
|
-
space: 'Space',
|
|
67
|
-
tab: 'Tab',
|
|
68
|
-
up: '↑',
|
|
69
|
-
};
|
|
70
32
|
let HelixHeadlessKbd = class HelixHeadlessKbd extends HelixElement {
|
|
71
33
|
constructor() {
|
|
72
34
|
super(...arguments);
|
|
73
35
|
this.caps = false;
|
|
74
36
|
this.for = '';
|
|
37
|
+
this.keyLabels = {};
|
|
75
38
|
this.keys = '';
|
|
76
39
|
this.handleKeydown = (event) => {
|
|
77
40
|
const press = event;
|
|
@@ -88,9 +51,11 @@ let HelixHeadlessKbd = class HelixHeadlessKbd extends HelixElement {
|
|
|
88
51
|
}
|
|
89
52
|
const shortcut = new HelixShortcutEvent({ keys: this.keys });
|
|
90
53
|
this.dispatchEvent(shortcut);
|
|
91
|
-
if (
|
|
92
|
-
|
|
54
|
+
if (shortcut.defaultPrevented) {
|
|
55
|
+
return;
|
|
93
56
|
}
|
|
57
|
+
press.preventDefault();
|
|
58
|
+
this.act();
|
|
94
59
|
};
|
|
95
60
|
}
|
|
96
61
|
connectedCallback() {
|
|
@@ -133,14 +98,7 @@ let HelixHeadlessKbd = class HelixHeadlessKbd extends HelixElement {
|
|
|
133
98
|
}
|
|
134
99
|
}
|
|
135
100
|
get label() {
|
|
136
|
-
|
|
137
|
-
const names = apple ? APPLE : ELSEWHERE;
|
|
138
|
-
const own = this.keyLabels ?? {};
|
|
139
|
-
const keys = chordParts(this.keys).map((part) => {
|
|
140
|
-
const name = part.toLowerCase();
|
|
141
|
-
return own[name] ?? names[name] ?? (part.length === 1 ? part.toUpperCase() : part);
|
|
142
|
-
});
|
|
143
|
-
return { keys, separator: apple ? '' : '+' };
|
|
101
|
+
return keyNames(chordParts(this.keys), !this.hydrating && onApple(), this.keyLabels ?? {});
|
|
144
102
|
}
|
|
145
103
|
listen() {
|
|
146
104
|
if (!this.within || this.keys === '') {
|
|
@@ -157,6 +115,18 @@ let HelixHeadlessKbd = class HelixHeadlessKbd extends HelixElement {
|
|
|
157
115
|
this.listening?.removeEventListener('keydown', this.handleKeydown);
|
|
158
116
|
this.listening = undefined;
|
|
159
117
|
}
|
|
118
|
+
act() {
|
|
119
|
+
const control = this.activate && this.for !== '' ? elementById(this, this.for) : null;
|
|
120
|
+
if (!(control instanceof HTMLElement)) {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
if (this.activate === 'click') {
|
|
124
|
+
control.click();
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
control.focus();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
160
130
|
firstUpdated(changed) {
|
|
161
131
|
super.firstUpdated(changed);
|
|
162
132
|
this.finishHydration();
|
|
@@ -173,6 +143,9 @@ let HelixHeadlessKbd = class HelixHeadlessKbd extends HelixElement {
|
|
|
173
143
|
return html `${keys.map((key, index) => html `${index > 0 && separator !== '' ? html `<span part="separator">${separator}</span>` : nothing}<span part="key">${key}</span>`)}`;
|
|
174
144
|
}
|
|
175
145
|
};
|
|
146
|
+
__decorate([
|
|
147
|
+
property()
|
|
148
|
+
], HelixHeadlessKbd.prototype, "activate", void 0);
|
|
176
149
|
__decorate([
|
|
177
150
|
property({ reflect: true, type: Boolean })
|
|
178
151
|
], HelixHeadlessKbd.prototype, "caps", void 0);
|
|
@@ -180,7 +153,7 @@ __decorate([
|
|
|
180
153
|
property()
|
|
181
154
|
], HelixHeadlessKbd.prototype, "for", void 0);
|
|
182
155
|
__decorate([
|
|
183
|
-
property({ attribute: 'key-labels',
|
|
156
|
+
property({ attribute: 'key-labels', converter: wordsConverter })
|
|
184
157
|
], HelixHeadlessKbd.prototype, "keyLabels", void 0);
|
|
185
158
|
__decorate([
|
|
186
159
|
property()
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
/** A list as it may be given: names separated by commas, or an array of names. */
|
|
2
|
+
export type NameList = string | readonly string[];
|
|
3
|
+
/**
|
|
4
|
+
* The names in a list, written either way: split on commas from a string,
|
|
5
|
+
* trimmed and without blanks from an array, which is what a framework hands
|
|
6
|
+
* over for `hiddenSeries={['Direct']}`.
|
|
7
|
+
*/
|
|
8
|
+
export declare const namesIn: (list: NameList) => string[];
|
|
1
9
|
/** Whether a name is in the list, matched without regard to case, as a heading is. */
|
|
2
|
-
export declare const isHidden: (list:
|
|
10
|
+
export declare const isHidden: (list: NameList, name: string) => boolean;
|
|
3
11
|
/**
|
|
4
12
|
* The list a press on this name leaves: without it where it was hidden, and
|
|
5
13
|
* with it at the end where it was shown. Written back with a comma and a
|
|
6
14
|
* space, as a person writes a list.
|
|
7
15
|
*/
|
|
8
|
-
export declare const toggledNames: (list:
|
|
16
|
+
export declare const toggledNames: (list: NameList, name: string) => string;
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { commaList, seriesKey } from '@fusion.dev/helix-core';
|
|
2
|
+
export const namesIn = (list) => typeof list === 'string'
|
|
3
|
+
? commaList(list)
|
|
4
|
+
: list.map((name) => String(name).trim()).filter((name) => name !== '');
|
|
2
5
|
export const isHidden = (list, name) => {
|
|
3
6
|
const key = seriesKey(name);
|
|
4
|
-
return
|
|
7
|
+
return namesIn(list).some((one) => seriesKey(one) === key);
|
|
5
8
|
};
|
|
6
9
|
export const toggledNames = (list, name) => {
|
|
7
10
|
const key = seriesKey(name);
|
|
8
|
-
const now =
|
|
11
|
+
const now = namesIn(list);
|
|
9
12
|
const next = isHidden(list, name)
|
|
10
13
|
? now.filter((one) => seriesKey(one) !== key)
|
|
11
14
|
: [...now, name.trim()];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { HelixElement, KeyboardNavigationController, SourceController } from '@fusion.dev/helix-core';
|
|
2
|
-
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
2
|
+
import { nothing, type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
/**
|
|
4
4
|
* @summary A list of the series in a chart, each name beside the color it is drawn in.
|
|
5
5
|
*
|
|
@@ -21,9 +21,10 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
21
21
|
* **`toggles` makes each entry a button that hides its series.** Every chart
|
|
22
22
|
* reading the same table draws without a hidden series and fits its scale to
|
|
23
23
|
* the rest, and the series keeps its color. The button says whether its
|
|
24
|
-
* series is shown with `aria-pressed`. The buttons are
|
|
25
|
-
*
|
|
26
|
-
* and a typed letter goes to the next
|
|
24
|
+
* series is shown with `aria-pressed`. The buttons are a `toolbar`, named
|
|
25
|
+
* as the list is, and one tab stop: the arrow keys move between them, Home
|
|
26
|
+
* and End go to the first and the last, and a typed letter goes to the next
|
|
27
|
+
* name starting with it.
|
|
27
28
|
* `hidden-series` holds the hidden names,
|
|
28
29
|
* so a page can start with some hidden or read which are. Two legends on one
|
|
29
30
|
* table show the same hidden series: the list written last wins, and the
|
|
@@ -42,7 +43,7 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
42
43
|
* `::part(entry)::before` in your stylesheet. The entry holds its series color
|
|
43
44
|
* as `--chart-series`, and this tier ships no CSS.
|
|
44
45
|
* @csspart entry-hidden - An entry whose series is hidden. Set alongside `entry`.
|
|
45
|
-
* @csspart list - The list of entries
|
|
46
|
+
* @csspart list - The list of entries, a `toolbar` under `toggles`.
|
|
46
47
|
* @csspart name - One series name.
|
|
47
48
|
* @csspart toggle - The button around a name under `toggles`, which hides or shows its series.
|
|
48
49
|
*/
|
|
@@ -84,9 +85,11 @@ export declare class HelixHeadlessLegend extends HelixElement {
|
|
|
84
85
|
*
|
|
85
86
|
* Set it to start with series hidden. Every chart reading the same table
|
|
86
87
|
* draws without them. Commas only, because a column's heading may hold a
|
|
87
|
-
* space. For a ring the names are the rows.
|
|
88
|
+
* space. For a ring the names are the rows. An array of names set on the
|
|
89
|
+
* property works too, as React sets `hiddenSeries={['Direct']}`; a toggle
|
|
90
|
+
* writes the list back as a string.
|
|
88
91
|
*/
|
|
89
|
-
hiddenSeries: string;
|
|
92
|
+
hiddenSeries: string | readonly string[];
|
|
90
93
|
/**
|
|
91
94
|
* The name of the list, which a screen reader announces before its entries.
|
|
92
95
|
*
|
|
@@ -176,6 +179,21 @@ export declare class HelixHeadlessLegend extends HelixElement {
|
|
|
176
179
|
*/
|
|
177
180
|
protected names(): string[];
|
|
178
181
|
protected render(): TemplateResult;
|
|
182
|
+
/**
|
|
183
|
+
* What an entry shows before its name, behind a seam a tier can fill.
|
|
184
|
+
*
|
|
185
|
+
* Nothing on this tier, which ships no CSS: the styled tier and a page draw
|
|
186
|
+
* the swatch with `::part(entry)::before`, from the entry's `--chart-series`.
|
|
187
|
+
* A tier that draws its swatch as an element, or a mark per series, returns
|
|
188
|
+
* it here, and `index` says which palette slot the series takes.
|
|
189
|
+
*/
|
|
190
|
+
protected renderSwatch(_name: string, _index: number): TemplateResult | typeof nothing;
|
|
191
|
+
/**
|
|
192
|
+
* An entry's name, behind a seam a tier can move: a value beside the name,
|
|
193
|
+
* or the name in other words. `index` is the series' place among the
|
|
194
|
+
* entries. A toggle holds the same name inside its button.
|
|
195
|
+
*/
|
|
196
|
+
protected renderName(name: string, _index: number): TemplateResult;
|
|
179
197
|
/**
|
|
180
198
|
* The button around a name under `toggles`, behind a seam a tier can move.
|
|
181
199
|
*
|
|
@@ -4,10 +4,10 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import {
|
|
7
|
+
import { customElement, focusItemOf, HelixElement, KeyboardNavigationController, requestValue, SourceController, seriesIndex, seriesKey, typeaheadBy, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
|
-
import { isHidden, toggledNames } from '../hidden-series.js';
|
|
10
|
+
import { isHidden, namesIn, toggledNames } from '../hidden-series.js';
|
|
11
11
|
let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
12
12
|
constructor() {
|
|
13
13
|
super(...arguments);
|
|
@@ -19,14 +19,7 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
|
19
19
|
this.stop = 0;
|
|
20
20
|
this.keys = new KeyboardNavigationController(this, {
|
|
21
21
|
items: () => this.toggles
|
|
22
|
-
? [...this.renderRoot.querySelectorAll('[part="toggle"]')].map((button) => ({
|
|
23
|
-
contains: (node) => button.contains(node),
|
|
24
|
-
disabled: false,
|
|
25
|
-
focusItem: () => button.focus(),
|
|
26
|
-
select: () => { },
|
|
27
|
-
selected: false,
|
|
28
|
-
words: button.textContent?.trim() ?? '',
|
|
29
|
-
}))
|
|
22
|
+
? [...this.renderRoot.querySelectorAll('[part="toggle"]')].map((button) => focusItemOf(button, { words: button.textContent?.trim() ?? '' }))
|
|
30
23
|
: [],
|
|
31
24
|
origin: 'focus',
|
|
32
25
|
selects: () => false,
|
|
@@ -41,15 +34,16 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
|
41
34
|
}
|
|
42
35
|
const table = this.source.element;
|
|
43
36
|
const asked = changed.has('hiddenSeries') &&
|
|
44
|
-
!(changed.get('hiddenSeries') === undefined && this.hiddenSeries ===
|
|
45
|
-
this.writes =
|
|
37
|
+
!(changed.get('hiddenSeries') === undefined && namesIn(this.hiddenSeries).length === 0);
|
|
38
|
+
this.writes =
|
|
39
|
+
asked || (table !== null && table !== this.wroteTo && namesIn(this.hiddenSeries).length > 0);
|
|
46
40
|
if (!this.writes && table !== null) {
|
|
47
41
|
this.follow();
|
|
48
42
|
}
|
|
49
43
|
}
|
|
50
44
|
follow() {
|
|
51
45
|
const hidden = this.source.hidden;
|
|
52
|
-
const now =
|
|
46
|
+
const now = namesIn(this.hiddenSeries);
|
|
53
47
|
const next = this.names().filter((name) => hidden.has(seriesKey(name)));
|
|
54
48
|
const same = next.length === now.length &&
|
|
55
49
|
next.every((name) => now.some((one) => seriesKey(one) === seriesKey(name)));
|
|
@@ -61,7 +55,7 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
|
61
55
|
super.updated(changed);
|
|
62
56
|
if (this.writes) {
|
|
63
57
|
this.writes = false;
|
|
64
|
-
this.wroteTo = this.source.hide(
|
|
58
|
+
this.wroteTo = this.source.hide(namesIn(this.hiddenSeries), this.names()) ?? this.wroteTo;
|
|
65
59
|
}
|
|
66
60
|
}
|
|
67
61
|
disconnectedCallback() {
|
|
@@ -72,14 +66,8 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
|
72
66
|
super.disconnectedCallback();
|
|
73
67
|
}
|
|
74
68
|
toggle(name) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.hiddenSeries = value;
|
|
78
|
-
this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
|
|
79
|
-
},
|
|
80
|
-
event: (value) => new HelixBeforeChangeEvent({ value }),
|
|
81
|
-
host: this,
|
|
82
|
-
next: toggledNames(this.hiddenSeries, name),
|
|
69
|
+
requestValue(this, toggledNames(this.hiddenSeries, name), (value) => {
|
|
70
|
+
this.hiddenSeries = value;
|
|
83
71
|
});
|
|
84
72
|
}
|
|
85
73
|
names() {
|
|
@@ -93,20 +81,31 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
|
93
81
|
const named = this.label || this.source.element?.querySelector('caption')?.textContent?.trim();
|
|
94
82
|
const names = this.names();
|
|
95
83
|
const stop = Math.min(this.stop, names.length - 1);
|
|
96
|
-
|
|
84
|
+
const toolbar = this.toggles;
|
|
85
|
+
return html `<ul
|
|
86
|
+
aria-label=${named || nothing}
|
|
87
|
+
part="list"
|
|
88
|
+
role=${toolbar ? 'toolbar' : 'list'}
|
|
89
|
+
>
|
|
97
90
|
${names.map((name, index) => {
|
|
98
91
|
const off = isHidden(this.hiddenSeries, name);
|
|
99
92
|
return html `<li
|
|
100
93
|
data-series=${seriesIndex(index)}
|
|
101
94
|
part="entry${off ? ' entry-hidden' : ''}"
|
|
102
95
|
style="--chart-series: var(--chart-series-${seriesIndex(index)})"
|
|
103
|
-
role
|
|
96
|
+
role=${toolbar ? 'none' : 'listitem'}
|
|
104
97
|
>
|
|
105
|
-
${this.
|
|
98
|
+
${this.renderSwatch(name, index)}${toolbar ? this.renderToggle(name, off, index, index === stop) : this.renderName(name, index)}
|
|
106
99
|
</li>`;
|
|
107
100
|
})}
|
|
108
101
|
</ul>`;
|
|
109
102
|
}
|
|
103
|
+
renderSwatch(_name, _index) {
|
|
104
|
+
return nothing;
|
|
105
|
+
}
|
|
106
|
+
renderName(name, _index) {
|
|
107
|
+
return html `<span part="name">${name}</span>`;
|
|
108
|
+
}
|
|
110
109
|
renderToggle(name, off, index = 0, holds = true) {
|
|
111
110
|
return html `<button
|
|
112
111
|
aria-pressed=${off ? 'false' : 'true'}
|
|
@@ -118,7 +117,7 @@ let HelixHeadlessLegend = class HelixHeadlessLegend extends HelixElement {
|
|
|
118
117
|
this.stop = index;
|
|
119
118
|
}}
|
|
120
119
|
>
|
|
121
|
-
|
|
120
|
+
${this.renderName(name, index)}
|
|
122
121
|
</button>`;
|
|
123
122
|
}
|
|
124
123
|
};
|
|
@@ -30,7 +30,11 @@ declare const HelixHeadlessLightbox_base: (new (...args: any[]) => import("@fusi
|
|
|
30
30
|
* about. `+` and `-` zoom in and out from the keyboard, and `0` puts it back.
|
|
31
31
|
* The scale and the offset are on the `viewport` part as `--lightbox-zoom`,
|
|
32
32
|
* `--lightbox-pan-x` and `--lightbox-pan-y`, written only while zoomed, and a
|
|
33
|
-
* swipe moves to the next item only while the item is at its own size.
|
|
33
|
+
* swipe moves to the next item only while the item is at its own size. With
|
|
34
|
+
* `controls`, the viewer also draws zoom-out and zoom-in controls, for a
|
|
35
|
+
* pointer with no wheel and no second finger. Once a reader stops zooming, the
|
|
36
|
+
* live region says the new scale in the words of `zoom-status-label`, such as
|
|
37
|
+
* "Zoomed to 150%".
|
|
34
38
|
*
|
|
35
39
|
* Each item is a slide: a `group` with the role description in
|
|
36
40
|
* `slide-role-label`, named by its `label` or by `slide-label`. A touch or a pen
|
|
@@ -55,6 +59,8 @@ declare const HelixHeadlessLightbox_base: (new (...args: any[]) => import("@fusi
|
|
|
55
59
|
* @slot header - Content above the item, such as a title and a close button.
|
|
56
60
|
* @slot next-icon - Replaces the glyph inside the next control.
|
|
57
61
|
* @slot previous-icon - Replaces the glyph inside the previous control.
|
|
62
|
+
* @slot zoom-in-icon - Replaces the glyph inside the zoom-in control.
|
|
63
|
+
* @slot zoom-out-icon - Replaces the glyph inside the zoom-out control.
|
|
58
64
|
*
|
|
59
65
|
* @event {Event} close - Fired when the viewer closes. The component dispatches it again from the host, because the dialog's own event does not leave the shadow root.
|
|
60
66
|
* @event {HelixActivateEvent} helix-activate - Fired after the shown item changes, when the element already holds the new item.
|
|
@@ -67,12 +73,18 @@ declare const HelixHeadlessLightbox_base: (new (...args: any[]) => import("@fusi
|
|
|
67
73
|
* @csspart dialog - The native dialog element.
|
|
68
74
|
* @csspart dismiss - The close control, drawn with `controls`.
|
|
69
75
|
* @csspart dismiss-mark - The glyph on the close control, where none is slotted.
|
|
70
|
-
* @csspart
|
|
76
|
+
* @csspart footer - The slot the footer is in. It draws no box until you give it one.
|
|
77
|
+
* @csspart header - The slot the header is in. It draws no box until you give it one.
|
|
78
|
+
* @csspart live - The live region that announces which item is shown, and the scale once a reader has zoomed.
|
|
71
79
|
* @csspart next - The control that shows the next item, drawn with `controls`.
|
|
72
80
|
* @csspart next-mark - The glyph on the next control, where none is slotted.
|
|
73
81
|
* @csspart previous - The control that shows the previous item, drawn with `controls`.
|
|
74
82
|
* @csspart previous-mark - The glyph on the previous control, where none is slotted.
|
|
75
83
|
* @csspart viewport - The box the current item is shown in.
|
|
84
|
+
* @csspart zoom-in - The control that zooms in by half again, drawn with `controls` where `max-zoom` allows zooming.
|
|
85
|
+
* @csspart zoom-in-mark - The glyph on the zoom-in control, where none is slotted.
|
|
86
|
+
* @csspart zoom-out - The control that zooms back out, drawn with `controls` where `max-zoom` allows zooming.
|
|
87
|
+
* @csspart zoom-out-mark - The glyph on the zoom-out control, where none is slotted.
|
|
76
88
|
*
|
|
77
89
|
* @cssproperty --lightbox-pan-x - How far the zoomed item is moved across from the middle of the viewport, in pixels, toward the right. Written only while zoomed.
|
|
78
90
|
* @cssproperty --lightbox-pan-y - How far the zoomed item is moved down from the middle of the viewport, in pixels. Written only while zoomed.
|
|
@@ -86,12 +98,14 @@ declare const HelixHeadlessLightbox_base: (new (...args: any[]) => import("@fusi
|
|
|
86
98
|
*/
|
|
87
99
|
export declare class HelixHeadlessLightbox extends HelixHeadlessLightbox_base {
|
|
88
100
|
/**
|
|
89
|
-
* Draws the viewer's own previous, next and close controls over the picture
|
|
101
|
+
* Draws the viewer's own previous, next and close controls over the picture,
|
|
102
|
+
* and zoom-out and zoom-in controls where `max-zoom` allows zooming.
|
|
90
103
|
*
|
|
91
104
|
* Off by default, for a viewer whose chrome you compose in the `header` and
|
|
92
105
|
* `footer` slots. The controls hide with the rest of the chrome while the
|
|
93
|
-
* reader is idle,
|
|
94
|
-
* either end of a set that does not `loop
|
|
106
|
+
* reader is idle, the previous and next ones say they are unavailable at
|
|
107
|
+
* either end of a set that does not `loop`, and the zoom ones at either end
|
|
108
|
+
* of the scale.
|
|
95
109
|
*/
|
|
96
110
|
controls: boolean;
|
|
97
111
|
/**
|
|
@@ -156,16 +170,36 @@ export declare class HelixHeadlessLightbox extends HelixHeadlessLightbox_base {
|
|
|
156
170
|
* counter in the chrome can empty this and say it themselves.
|
|
157
171
|
*/
|
|
158
172
|
statusLabel: string;
|
|
173
|
+
/**
|
|
174
|
+
* The zoom-in control's accessible name.
|
|
175
|
+
*/
|
|
176
|
+
zoomInLabel: string;
|
|
177
|
+
/**
|
|
178
|
+
* The zoom-out control's accessible name.
|
|
179
|
+
*/
|
|
180
|
+
zoomOutLabel: string;
|
|
181
|
+
/**
|
|
182
|
+
* What the live region says once a reader has stopped zooming, with the
|
|
183
|
+
* scale as a whole `{percent}` filled in. Empty it to say nothing.
|
|
184
|
+
*/
|
|
185
|
+
zoomStatusLabel: string;
|
|
159
186
|
/** Whether the reader has been still long enough to hide the chrome. */
|
|
160
187
|
private resting;
|
|
161
188
|
/** Whether the viewer is filling the screen. */
|
|
162
189
|
private filled;
|
|
163
190
|
/** What the live region is currently saying. */
|
|
164
191
|
private announcement;
|
|
192
|
+
/** The scale the shown item is drawn at, which the zoom controls read. */
|
|
193
|
+
private zoomScale;
|
|
194
|
+
private readonly zoomSaid;
|
|
195
|
+
/** Whether the zoom is being put back because the item changed, which says nothing. */
|
|
196
|
+
private quietZoom;
|
|
165
197
|
protected readonly swipes: SwipeController;
|
|
166
198
|
private readonly zoomer;
|
|
167
199
|
/** Writes the zoom on the viewport, and nothing at the item's own size. */
|
|
168
200
|
private drawZoom;
|
|
201
|
+
/** Says the new scale in the live region, a moment after the last change. */
|
|
202
|
+
private sayZoom;
|
|
169
203
|
/**
|
|
170
204
|
* Zooms the shown item to `scale`, held between `1` and `max-zoom`, about
|
|
171
205
|
* the middle of the viewport.
|
|
@@ -243,6 +277,10 @@ export declare class HelixHeadlessLightbox extends HelixHeadlessLightbox_base {
|
|
|
243
277
|
private readonly handleKeydown;
|
|
244
278
|
/** `+` and `-` zoom in and out by half again, and `0` puts the item back. Returns whether it was one. */
|
|
245
279
|
private zoomKey;
|
|
280
|
+
/** Zooms in by half again, as `+` and the zoom-in control do. */
|
|
281
|
+
private zoomIn;
|
|
282
|
+
/** Zooms out by as much, as `-` and the zoom-out control do. */
|
|
283
|
+
private zoomOut;
|
|
246
284
|
/** Home and End, which are an index rather than a step. */
|
|
247
285
|
private toEnd;
|
|
248
286
|
/** The item on screen: the one `active` names, or the first where it names none. */
|
|
@@ -288,6 +326,13 @@ export declare class HelixHeadlessLightbox extends HelixHeadlessLightbox_base {
|
|
|
288
326
|
* control that has just shown the last picture keeps focus.
|
|
289
327
|
*/
|
|
290
328
|
protected renderControls(): TemplateResult;
|
|
329
|
+
/**
|
|
330
|
+
* Zoom out and zoom in, for a pointer with no wheel and no second finger.
|
|
331
|
+
*
|
|
332
|
+
* Out before in, so they read as a scale runs. `aria-disabled` at either
|
|
333
|
+
* limit, as the previous and next controls are at the ends.
|
|
334
|
+
*/
|
|
335
|
+
protected renderZoomControls(): TemplateResult;
|
|
291
336
|
}
|
|
292
337
|
declare global {
|
|
293
338
|
interface HTMLElementTagNameMap {
|
|
@@ -4,12 +4,13 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { CommandController, customElement, deepActiveElement, deepContains, drawDismiss, drawDismissGlyph, FullscreenController, fillTemplate, HelixElement, hostAria, IdleController, inlineStep, isRtl, keyClaimed, lockScroll, MixinControllerActive, MixinControllerOpen, resolveActiveItem, SwipeController, swipeStep, unlockScroll, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
|
-
import { caretLeft, caretRight } from '@fusion.dev/helix-icons';
|
|
7
|
+
import { CommandController, customElement, DelayController, deepActiveElement, deepContains, drawDismiss, drawDismissGlyph, FullscreenController, fillTemplate, HelixElement, hostAria, IdleController, inlineStep, isRtl, keyClaimed, lockScroll, MixinControllerActive, MixinControllerOpen, resolveActiveItem, SwipeController, swipeStep, unlockScroll, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { caretLeft, caretRight, minus, plus } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
|
|
12
12
|
import { HelixHeadlessLightboxItem } from '../item/lightbox-item.js';
|
|
13
|
+
import { percentOf } from '../zoom.js';
|
|
13
14
|
import { ZoomController } from '../zoom-controller.js';
|
|
14
15
|
let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerActive(MixinControllerOpen(HelixElement)) {
|
|
15
16
|
constructor() {
|
|
@@ -26,9 +27,15 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
26
27
|
this.slideLabel = '{index} of {count}';
|
|
27
28
|
this.slideRoleLabel = 'slide';
|
|
28
29
|
this.statusLabel = '{index} of {count}';
|
|
30
|
+
this.zoomInLabel = 'Zoom in';
|
|
31
|
+
this.zoomOutLabel = 'Zoom out';
|
|
32
|
+
this.zoomStatusLabel = 'Zoomed to {percent}%';
|
|
29
33
|
this.resting = false;
|
|
30
34
|
this.filled = false;
|
|
31
35
|
this.announcement = '';
|
|
36
|
+
this.zoomScale = 1;
|
|
37
|
+
this.zoomSaid = new DelayController(this, { renders: false });
|
|
38
|
+
this.quietZoom = false;
|
|
32
39
|
this.swipes = new SwipeController(this, {
|
|
33
40
|
axis: () => (this.open && !this.zoomer.engaged ? 'x' : undefined),
|
|
34
41
|
end: (dx, _dy, vx) => {
|
|
@@ -126,13 +133,26 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
126
133
|
viewport?.style.setProperty('--lightbox-pan-y', zoomed ? `${Math.round(pan.y)}px` : '');
|
|
127
134
|
this.toggleState('zoomed', zoomed);
|
|
128
135
|
this.idle.stir();
|
|
136
|
+
if (scale !== this.zoomScale) {
|
|
137
|
+
this.zoomScale = scale;
|
|
138
|
+
this.sayZoom();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
sayZoom() {
|
|
142
|
+
if (this.quietZoom || !this.open || this.zoomStatusLabel === '') {
|
|
143
|
+
this.zoomSaid.cancel();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
this.zoomSaid.start(400, () => {
|
|
147
|
+
this.announcement = fillTemplate(this.zoomStatusLabel, { percent: percentOf(this.zoomScale) });
|
|
148
|
+
});
|
|
129
149
|
}
|
|
130
150
|
zoomTo(scale) {
|
|
131
151
|
this.zoomer.zoomTo(scale);
|
|
132
152
|
}
|
|
133
153
|
chromeHasFocus() {
|
|
134
154
|
const active = deepActiveElement();
|
|
135
|
-
const own = this.shadowRoot?.activeElement?.matches('[part="previous"], [part="next"], [part="dismiss"]');
|
|
155
|
+
const own = this.shadowRoot?.activeElement?.matches('[part="previous"], [part="next"], [part="dismiss"], [part="zoom-in"], [part="zoom-out"]');
|
|
136
156
|
return (own === true ||
|
|
137
157
|
this.knownChildren.some((child) => (child.slot === 'header' || child.slot === 'footer') && deepContains(child, active)));
|
|
138
158
|
}
|
|
@@ -178,12 +198,11 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
178
198
|
if (this.maxZoom <= 1) {
|
|
179
199
|
return false;
|
|
180
200
|
}
|
|
181
|
-
const scale = this.zoomer.scale;
|
|
182
201
|
if (key === '+' || key === '=') {
|
|
183
|
-
this.
|
|
202
|
+
this.zoomIn();
|
|
184
203
|
}
|
|
185
204
|
else if (key === '-') {
|
|
186
|
-
this.
|
|
205
|
+
this.zoomOut();
|
|
187
206
|
}
|
|
188
207
|
else if (key === '0') {
|
|
189
208
|
this.zoomer.reset();
|
|
@@ -193,6 +212,12 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
193
212
|
}
|
|
194
213
|
return true;
|
|
195
214
|
}
|
|
215
|
+
zoomIn() {
|
|
216
|
+
this.zoomer.zoomTo(this.zoomer.scale * 1.5);
|
|
217
|
+
}
|
|
218
|
+
zoomOut() {
|
|
219
|
+
this.zoomer.zoomTo(this.zoomer.scale / 1.5);
|
|
220
|
+
}
|
|
196
221
|
toEnd(at) {
|
|
197
222
|
const target = this.items[at];
|
|
198
223
|
if (target && target !== this.shown) {
|
|
@@ -209,7 +234,9 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
209
234
|
this.toggleState('idle', this.resting);
|
|
210
235
|
this.toggleState('zoomable', this.maxZoom > 1);
|
|
211
236
|
if (changed.has('active') || (changed.has('open') && !this.open)) {
|
|
237
|
+
this.quietZoom = true;
|
|
212
238
|
this.zoomer.reset();
|
|
239
|
+
this.quietZoom = false;
|
|
213
240
|
}
|
|
214
241
|
this.say(changed);
|
|
215
242
|
}
|
|
@@ -305,11 +332,11 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
305
332
|
@pointerleave=${this.idle.leave}
|
|
306
333
|
@pointermove=${this.idle.stir}
|
|
307
334
|
>
|
|
308
|
-
<slot name="header"></slot>
|
|
335
|
+
<slot name="header" part="header"></slot>
|
|
309
336
|
<div part="viewport">
|
|
310
337
|
<slot></slot>
|
|
311
338
|
</div>
|
|
312
|
-
<slot name="footer"></slot>
|
|
339
|
+
<slot name="footer" part="footer"></slot>
|
|
313
340
|
${this.controls ? this.renderControls() : nothing}
|
|
314
341
|
${this.counter ? html `<span part="counter" aria-hidden="true">${this.place()}</span>` : nothing}
|
|
315
342
|
<span part="live" role="status" aria-live="polite">${this.announcement || nothing}</span>
|
|
@@ -342,12 +369,41 @@ let HelixHeadlessLightbox = class HelixHeadlessLightbox extends MixinControllerA
|
|
|
342
369
|
</svg>
|
|
343
370
|
</slot>
|
|
344
371
|
</button>
|
|
372
|
+
${this.maxZoom > 1 ? this.renderZoomControls() : nothing}
|
|
345
373
|
${drawDismiss({
|
|
346
374
|
label: this.dismissLabel,
|
|
347
375
|
mark: html `<slot name="dismiss-icon">${drawDismissGlyph()}</slot>`,
|
|
348
376
|
onDismiss: () => this.close(),
|
|
349
377
|
})}`;
|
|
350
378
|
}
|
|
379
|
+
renderZoomControls() {
|
|
380
|
+
return html `<button
|
|
381
|
+
part="zoom-out"
|
|
382
|
+
type="button"
|
|
383
|
+
aria-label=${this.zoomOutLabel}
|
|
384
|
+
aria-disabled=${this.zoomScale <= 1 ? 'true' : nothing}
|
|
385
|
+
@click=${() => this.zoomOut()}
|
|
386
|
+
>
|
|
387
|
+
<slot name="zoom-out-icon">
|
|
388
|
+
<svg part="zoom-out-mark" fill="currentColor" viewBox=${minus.viewBox} aria-hidden="true">
|
|
389
|
+
${unsafeSVG(minus.content)}
|
|
390
|
+
</svg>
|
|
391
|
+
</slot>
|
|
392
|
+
</button>
|
|
393
|
+
<button
|
|
394
|
+
part="zoom-in"
|
|
395
|
+
type="button"
|
|
396
|
+
aria-label=${this.zoomInLabel}
|
|
397
|
+
aria-disabled=${this.zoomScale >= this.maxZoom ? 'true' : nothing}
|
|
398
|
+
@click=${() => this.zoomIn()}
|
|
399
|
+
>
|
|
400
|
+
<slot name="zoom-in-icon">
|
|
401
|
+
<svg part="zoom-in-mark" fill="currentColor" viewBox=${plus.viewBox} aria-hidden="true">
|
|
402
|
+
${unsafeSVG(plus.content)}
|
|
403
|
+
</svg>
|
|
404
|
+
</slot>
|
|
405
|
+
</button>`;
|
|
406
|
+
}
|
|
351
407
|
};
|
|
352
408
|
__decorate([
|
|
353
409
|
property({ reflect: true, type: Boolean })
|
|
@@ -385,6 +441,15 @@ __decorate([
|
|
|
385
441
|
__decorate([
|
|
386
442
|
property({ attribute: 'status-label' })
|
|
387
443
|
], HelixHeadlessLightbox.prototype, "statusLabel", void 0);
|
|
444
|
+
__decorate([
|
|
445
|
+
property({ attribute: 'zoom-in-label' })
|
|
446
|
+
], HelixHeadlessLightbox.prototype, "zoomInLabel", void 0);
|
|
447
|
+
__decorate([
|
|
448
|
+
property({ attribute: 'zoom-out-label' })
|
|
449
|
+
], HelixHeadlessLightbox.prototype, "zoomOutLabel", void 0);
|
|
450
|
+
__decorate([
|
|
451
|
+
property({ attribute: 'zoom-status-label' })
|
|
452
|
+
], HelixHeadlessLightbox.prototype, "zoomStatusLabel", void 0);
|
|
388
453
|
__decorate([
|
|
389
454
|
state()
|
|
390
455
|
], HelixHeadlessLightbox.prototype, "resting", void 0);
|
|
@@ -394,6 +459,9 @@ __decorate([
|
|
|
394
459
|
__decorate([
|
|
395
460
|
state()
|
|
396
461
|
], HelixHeadlessLightbox.prototype, "announcement", void 0);
|
|
462
|
+
__decorate([
|
|
463
|
+
state()
|
|
464
|
+
], HelixHeadlessLightbox.prototype, "zoomScale", void 0);
|
|
397
465
|
HelixHeadlessLightbox = __decorate([
|
|
398
466
|
customElement('helix-headless-lightbox')
|
|
399
467
|
], HelixHeadlessLightbox);
|
package/dist/lightbox/zoom.d.ts
CHANGED
|
@@ -20,3 +20,5 @@ export declare const zoomAt: (at: Offset, from: number, to: number, pan: Offset)
|
|
|
20
20
|
export declare const spread: (a: Offset, b: Offset) => number;
|
|
21
21
|
/** The point halfway between two fingers. */
|
|
22
22
|
export declare const between: (a: Offset, b: Offset) => Offset;
|
|
23
|
+
/** A scale as a whole percent, which is how a reader hears it: 1.5 is 150. */
|
|
24
|
+
export declare const percentOf: (scale: number) => number;
|