@fusion.dev/helix-headless 0.146.0 → 0.147.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +5266 -785
- package/dist/accordion/item/accordion-item.d.ts +38 -19
- package/dist/accordion/item/accordion-item.js +31 -9
- package/dist/accordion/root/accordion-root.d.ts +8 -2
- package/dist/accordion/root/accordion-root.js +3 -3
- package/dist/announcement/root/announcement-root.d.ts +13 -4
- package/dist/announcement/root/announcement-root.js +34 -6
- package/dist/area-chart/root/area-chart-root.d.ts +18 -1
- package/dist/area-chart/root/area-chart-root.js +11 -3
- package/dist/avatar/root/avatar-root.d.ts +31 -1
- package/dist/avatar/root/avatar-root.js +11 -1
- package/dist/badge/root/badge-root.d.ts +57 -6
- package/dist/badge/root/badge-root.js +88 -5
- 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/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/card/root/card-root.d.ts +12 -1
- package/dist/card/root/card-root.js +11 -4
- package/dist/chat/root/chat-root.d.ts +15 -1
- package/dist/chat/root/chat-root.js +11 -2
- package/dist/checkbox/root/checkbox-root.js +5 -7
- package/dist/checkbox-group/root/checkbox-group-root.js +4 -3
- package/dist/checkbox-group/select-all.d.ts +0 -6
- package/dist/checkbox-group/select-all.js +0 -5
- package/dist/code-block/root/code-block-root.d.ts +35 -14
- package/dist/code-block/root/code-block-root.js +17 -3
- 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 +101 -51
- package/dist/color-picker/wheel.d.ts +17 -0
- package/dist/color-picker/wheel.js +6 -0
- package/dist/combobox/root/combobox-root.d.ts +13 -0
- package/dist/combobox/root/combobox-root.js +14 -1
- package/dist/command/root/command-root.d.ts +3 -1
- 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 +13 -7
- 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 +18 -4
- package/dist/description-list/item/description-list-item.js +8 -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 +39 -4
- package/dist/drilldown/root/drilldown-root.js +3 -2
- package/dist/element-events.generated.js +4 -1
- package/dist/empty/root/empty-root.d.ts +31 -1
- package/dist/empty/root/empty-root.js +26 -5
- package/dist/file-input/root/file-input-root.d.ts +34 -6
- package/dist/file-input/root/file-input-root.js +54 -19
- package/dist/file-input/status.d.ts +24 -0
- package/dist/file-input/status.js +10 -0
- package/dist/filter-input/chip/filter-chip.d.ts +23 -0
- package/dist/filter-input/chip/filter-chip.js +11 -2
- package/dist/filter-input/root/filter-input-root.d.ts +8 -0
- package/dist/filter-input/root/filter-input-root.js +17 -27
- package/dist/format-date/options.d.ts +3 -4
- package/dist/format-date/options.js +2 -2
- package/dist/format-date/root/format-date-root.d.ts +18 -1
- package/dist/format-date/root/format-date-root.js +19 -23
- 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 +64 -3
- package/dist/heatmap/root/heatmap-root.js +89 -19
- 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 +9 -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/keys.d.ts +29 -0
- package/dist/kbd/keys.js +52 -0
- package/dist/kbd/root/kbd-root.d.ts +20 -3
- package/dist/kbd/root/kbd-root.js +24 -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 +22 -10
- 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 +26 -5
- package/dist/list/selection.d.ts +17 -0
- package/dist/list/selection.js +16 -0
- package/dist/listbox/root/listbox-root.d.ts +9 -5
- package/dist/listbox/root/listbox-root.js +29 -37
- 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 +36 -50
- package/dist/menu/item/menu-item.js +4 -4
- package/dist/menu/root/menu-root.d.ts +3 -0
- package/dist/meter/root/meter-root.d.ts +42 -0
- package/dist/meter/root/meter-root.js +33 -7
- package/dist/notifications/root/notifications-root.d.ts +10 -1
- package/dist/notifications/root/notifications-root.js +11 -1
- 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 +13 -6
- package/dist/object-inspector/root/object-inspector-root.js +18 -17
- 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 +5 -0
- package/dist/pagination/size/pagination-size.js +4 -2
- package/dist/pin-input/code.d.ts +28 -1
- package/dist/pin-input/code.js +12 -0
- package/dist/pin-input/root/pin-input-root.d.ts +98 -121
- package/dist/pin-input/root/pin-input-root.js +157 -148
- 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 +17 -6
- package/dist/qr-code/root/qr-code-root.js +10 -12
- 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/root/scatter-chart-root.d.ts +30 -0
- package/dist/scatter-chart/root/scatter-chart-root.js +34 -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 +59 -3
- package/dist/select/root/select-root.js +72 -12
- 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/item/speed-dial-item.d.ts +1 -1
- package/dist/speed-dial/item/speed-dial-item.js +2 -2
- package/dist/speed-dial/root/speed-dial-root.d.ts +6 -0
- package/dist/speed-dial/root/speed-dial-root.js +9 -1
- package/dist/splitter/root/splitter-root.d.ts +3 -0
- package/dist/splitter/root/splitter-root.js +2 -0
- 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/column/table-column.d.ts +6 -0
- package/dist/table/column/table-column.js +5 -1
- package/dist/table/root/table-root.js +13 -6
- package/dist/table/row/table-row.d.ts +24 -0
- package/dist/table/row/table-row.js +37 -1
- 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 +19 -7
- 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 +11 -14
- package/dist/time-picker/root/time-picker-root.js +15 -23
- package/dist/toast/item/toast-item.d.ts +3 -3
- package/dist/toast/item/toast-item.js +0 -1
- package/dist/toast/root/toast-root.d.ts +28 -4
- package/dist/toast/root/toast-root.js +58 -12
- 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 -41
- package/dist/toggle/root/toggle-root.js +2 -4
- package/dist/toolbar/root/toolbar-root.d.ts +21 -5
- package/dist/toolbar/root/toolbar-root.js +52 -8
- package/dist/tooltip/root/tooltip-root.d.ts +7 -1
- package/dist/tooltip/root/tooltip-root.js +10 -1
- 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 +5 -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 +48 -24
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +2979 -738
- package/types/svelte.d.ts +1 -0
- package/types/vue.d.ts +619 -202
- 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
|
@@ -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;
|
package/dist/lightbox/zoom.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { clamp } from '@fusion.dev/helix-core';
|
|
2
|
+
const held = (value, low, high) => clamp(value, low, high) || 0;
|
|
3
|
+
export const clampScale = (scale, max) => held(scale, 1, Math.max(max, 1));
|
|
3
4
|
export const clampPan = (pan, scale, width, height) => {
|
|
4
5
|
const x = ((scale - 1) * width) / 2;
|
|
5
6
|
const y = ((scale - 1) * height) / 2;
|
|
6
|
-
return { x:
|
|
7
|
+
return { x: held(pan.x, -x, x), y: held(pan.y, -y, y) };
|
|
7
8
|
};
|
|
8
9
|
export const zoomAt = (at, from, to, pan) => ({
|
|
9
10
|
x: at.x - ((at.x - pan.x) * to) / from,
|
|
@@ -14,3 +15,4 @@ export const between = (a, b) => ({
|
|
|
14
15
|
x: (a.x + b.x) / 2,
|
|
15
16
|
y: (a.y + b.y) / 2,
|
|
16
17
|
});
|
|
18
|
+
export const percentOf = (scale) => Math.round(scale * 100);
|
|
@@ -15,6 +15,10 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
15
15
|
*
|
|
16
16
|
* Every series shares one scale, as in the bar chart.
|
|
17
17
|
*
|
|
18
|
+
* `dashed` names the series drawn as a dashed line, such as a forecast or a
|
|
19
|
+
* target beside the readings: `dashed="Forecast"`. Each takes a
|
|
20
|
+
* `line-dashed` part beside `line`.
|
|
21
|
+
*
|
|
18
22
|
* `area` fills each series down to the floor on its own, so the fills overlap.
|
|
19
23
|
* For a total made of parts, use `Area Chart`, which stacks the series so the
|
|
20
24
|
* top edge is the total and each band is a share.
|
|
@@ -47,6 +51,7 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
47
51
|
* @csspart label - One reading's name.
|
|
48
52
|
* @csspart labels - The row of reading names.
|
|
49
53
|
* @csspart line - The line for one series.
|
|
54
|
+
* @csspart line-dashed - A `line` whose series `dashed` names. Set alongside `line`.
|
|
50
55
|
* @csspart live - The readout: a polite live region that says the reading the keys moved to. Hide it visually.
|
|
51
56
|
* @csspart mark - The invisible point the tooltip is anchored to.
|
|
52
57
|
* @csspart marker - The mark on one reading, under `markers`, and on a reading with a blank on either side. Placed with `inset-inline-start` and `inset-block-start`, and carries its series color as `--chart-series`.
|
|
@@ -112,6 +117,15 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
112
117
|
* here, which is what lets a line take the reading aid.
|
|
113
118
|
*/
|
|
114
119
|
curve?: Curve;
|
|
120
|
+
/**
|
|
121
|
+
* The series drawn as a dashed line, by their headings, separated by
|
|
122
|
+
* commas: `dashed="Forecast, Target"`.
|
|
123
|
+
*
|
|
124
|
+
* For a series that is not a reading, such as a forecast or a goal, drawn
|
|
125
|
+
* beside the ones that are. Each takes a `line-dashed` part beside `line`,
|
|
126
|
+
* which a stylesheet draws dashed. Absent, every line is solid.
|
|
127
|
+
*/
|
|
128
|
+
dashed: string;
|
|
115
129
|
/**
|
|
116
130
|
* Which rules are drawn across the plot, if any.
|
|
117
131
|
*
|
|
@@ -276,6 +290,8 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
276
290
|
* start, as the drawing is mirrored.
|
|
277
291
|
*/
|
|
278
292
|
protected renderMarkers(series: Series[], x: (value: number) => number, y: (value: number) => number): TemplateResult | typeof nothing;
|
|
293
|
+
/** Whether `dashed` names this series, matched as a heading is. */
|
|
294
|
+
private dashes;
|
|
279
295
|
/**
|
|
280
296
|
* One series, its wash first so the line is drawn over its own fill.
|
|
281
297
|
*
|
|
@@ -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 { byRow, CHART_PLOT, customElement, drawTooltip, extent, HelixElement, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, ticks, unbroken, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { byRow, CHART_PLOT, commaList, customElement, drawTooltip, extent, HelixElement, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesKey, ticks, unbroken, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing, svg } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import '../../tooltip/index.js';
|
|
@@ -12,6 +12,7 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
12
12
|
constructor() {
|
|
13
13
|
super(...arguments);
|
|
14
14
|
this.area = false;
|
|
15
|
+
this.dashed = '';
|
|
15
16
|
this.markers = false;
|
|
16
17
|
this.zero = false;
|
|
17
18
|
}
|
|
@@ -166,6 +167,10 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
166
167
|
style=${`--chart-series: var(--chart-series-${seriesIndex(depth)}); inset-inline-start: ${(x(point.at) / PLOT_WIDTH) * 100}%; inset-block-start: ${(y(point.value) / PLOT_HEIGHT) * 100}%`}
|
|
167
168
|
></span>`)}`;
|
|
168
169
|
}
|
|
170
|
+
dashes(name) {
|
|
171
|
+
const key = seriesKey(name);
|
|
172
|
+
return this.dashed !== '' && commaList(this.dashed).some((one) => seriesKey(one) === key);
|
|
173
|
+
}
|
|
169
174
|
renderSeries(one, depth, x, y) {
|
|
170
175
|
if (!this.showsSeries(one.name)) {
|
|
171
176
|
return html `${nothing}`;
|
|
@@ -199,7 +204,7 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
199
204
|
d=${path}
|
|
200
205
|
data-series=${index}
|
|
201
206
|
fill="none"
|
|
202
|
-
part="line"
|
|
207
|
+
part="line${this.dashes(one.name) ? ' line-dashed' : ''}"
|
|
203
208
|
style="--chart-series: var(--chart-series-${index})"
|
|
204
209
|
/>`;
|
|
205
210
|
}
|
|
@@ -235,6 +240,9 @@ __decorate([
|
|
|
235
240
|
__decorate([
|
|
236
241
|
property({ reflect: true })
|
|
237
242
|
], HelixHeadlessLineChart.prototype, "curve", void 0);
|
|
243
|
+
__decorate([
|
|
244
|
+
property()
|
|
245
|
+
], HelixHeadlessLineChart.prototype, "dashed", void 0);
|
|
238
246
|
__decorate([
|
|
239
247
|
property()
|
|
240
248
|
], HelixHeadlessLineChart.prototype, "gridlines", void 0);
|
|
@@ -27,12 +27,14 @@ import { type ListSelectionBehavior, type ListSelectionMode } from '../selection
|
|
|
27
27
|
* |---|---|
|
|
28
28
|
* | Down, Up | Moves to the next or the previous row. Under `replace`, selects it. |
|
|
29
29
|
* | Home, End | Moves to the first or the last row. Under `replace`, selects it. |
|
|
30
|
+
* | Page Down, Page Up | Moves a box's height of rows, so the row at one edge lands at the other. Under `replace`, selects the row it lands on. |
|
|
30
31
|
* | A letter or a word | Moves to the next row whose words start with what you typed. |
|
|
31
32
|
* | Left, Right | Moves between the row and the controls in its `end` slot. |
|
|
32
33
|
* | Space | Selects the row, or lets it go. |
|
|
33
|
-
* | Shift with Down, Up, Home, End or Space | Selects every row from the last one pressed, in `multiple`. |
|
|
34
|
-
* | Control or Command with Down, Up, Home or
|
|
34
|
+
* | Shift with Down, Up, Home, End, Page Down, Page Up or Space | Selects every row from the last one pressed, in `multiple`. |
|
|
35
|
+
* | Control or Command with Down, Up, Home, End, Page Down or Page Up | Moves without selecting, under `replace`. |
|
|
35
36
|
* | Control or Command with A | Selects every row, in `multiple`. |
|
|
37
|
+
* | Escape | Lets go of every selected row, asking first, and keeps the key from the dialog or menu around the list. With nothing selected, the key goes on to them. |
|
|
36
38
|
* | Enter | Acts on the row: follows its link, or sends `helix-action` from it. |
|
|
37
39
|
*
|
|
38
40
|
* A press with Shift selects every row from the last one pressed, and a press
|
|
@@ -185,6 +187,12 @@ export declare class HelixHeadlessList extends HelixElement {
|
|
|
185
187
|
* nothing was pressed yet.
|
|
186
188
|
*/
|
|
187
189
|
private arrive;
|
|
190
|
+
/**
|
|
191
|
+
* Page Down or Page Up from the row: focus moves a box's height of rows, the
|
|
192
|
+
* list's own where it scrolls and the window's where it does not, and lands
|
|
193
|
+
* the way an arrow does, so `replace` and Shift choose as they do there.
|
|
194
|
+
*/
|
|
195
|
+
private page;
|
|
188
196
|
/** Acts on the row: follows its link, or says it was acted on. */
|
|
189
197
|
protected act(row: HelixHeadlessListItem): void;
|
|
190
198
|
/** Left and Right inside a row: the cell, then each control in `end`, and back. */
|
|
@@ -4,12 +4,12 @@ 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 { commaList, customElement, HelixActionEvent, HelixBeforeChangeEvent, HelixElement, hostAria, inlineStep, KeyboardNavigationController, requestChange, rovingStop,
|
|
7
|
+
import { commaList, customElement, HelixActionEvent, HelixBeforeChangeEvent, HelixElement, hostAria, inlineStep, KeyboardNavigationController, requestChange, rovingStop, selectsAll, typeaheadByWords, whenHydrated, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { HelixHeadlessListItem } from '../item/list-item.js';
|
|
11
11
|
import { numbering } from '../numbering.js';
|
|
12
|
-
import { choiceValue, rowStop, } from '../selection.js';
|
|
12
|
+
import { choiceValue, pageReach, rowStop, } from '../selection.js';
|
|
13
13
|
const PRESSABLE = 'a[href], button, input, label, select, textarea, [tabindex]';
|
|
14
14
|
let HelixHeadlessList = class HelixHeadlessList extends HelixElement {
|
|
15
15
|
constructor() {
|
|
@@ -23,15 +23,19 @@ let HelixHeadlessList = class HelixHeadlessList extends HelixElement {
|
|
|
23
23
|
origin: 'focus',
|
|
24
24
|
reserved: () => ['ArrowLeft', 'ArrowRight'],
|
|
25
25
|
selects: () => false,
|
|
26
|
-
typeahead:
|
|
26
|
+
typeahead: typeaheadByWords(),
|
|
27
27
|
wrap: false,
|
|
28
28
|
});
|
|
29
29
|
this.handleKeyCapture = (event) => {
|
|
30
30
|
this.moving = { extend: event.shiftKey, toggle: event.ctrlKey || event.metaKey };
|
|
31
31
|
};
|
|
32
32
|
this.handleKeydown = (event) => {
|
|
33
|
-
this.moving = undefined;
|
|
34
33
|
const row = this.interactive ? this.rowOf(event) : undefined;
|
|
34
|
+
if (row && !row.disabled && !event.altKey && /^Page(Down|Up)$/.test(event.key)) {
|
|
35
|
+
event.preventDefault();
|
|
36
|
+
this.page(row, event.key === 'PageDown' ? 1 : -1);
|
|
37
|
+
}
|
|
38
|
+
this.moving = undefined;
|
|
35
39
|
if (!row || row.disabled || event.altKey) {
|
|
36
40
|
return;
|
|
37
41
|
}
|
|
@@ -43,11 +47,16 @@ let HelixHeadlessList = class HelixHeadlessList extends HelixElement {
|
|
|
43
47
|
if (event.composedPath()[0] !== row.cell) {
|
|
44
48
|
return;
|
|
45
49
|
}
|
|
46
|
-
if (
|
|
50
|
+
if (selectsAll(event) && this.selectionMode === 'multiple') {
|
|
47
51
|
event.preventDefault();
|
|
48
52
|
const every = this.reachable.map((one) => this.valueFor(one)).join(', ');
|
|
49
53
|
this.choose(every === this.value ? null : every);
|
|
50
54
|
}
|
|
55
|
+
else if (event.key === 'Escape' && this.value !== '' && this.selectionMode !== 'none') {
|
|
56
|
+
event.preventDefault();
|
|
57
|
+
event.stopPropagation();
|
|
58
|
+
this.choose('');
|
|
59
|
+
}
|
|
51
60
|
else if (event.key === 'Enter' && !toggle) {
|
|
52
61
|
event.preventDefault();
|
|
53
62
|
this.act(row);
|
|
@@ -188,6 +197,18 @@ let HelixHeadlessList = class HelixHeadlessList extends HelixElement {
|
|
|
188
197
|
}
|
|
189
198
|
this.choose(next);
|
|
190
199
|
}
|
|
200
|
+
page(row, step) {
|
|
201
|
+
const rows = this.reachable;
|
|
202
|
+
const edges = rows.map((one) => {
|
|
203
|
+
const box = one.getBoundingClientRect();
|
|
204
|
+
return { bottom: box.bottom, top: box.top };
|
|
205
|
+
});
|
|
206
|
+
const room = this.scrollHeight > this.clientHeight + 1 ? this.clientHeight : window.innerHeight;
|
|
207
|
+
const target = rows[pageReach(edges, rows.indexOf(row), room, step)];
|
|
208
|
+
if (target && target !== row) {
|
|
209
|
+
target.focusItem();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
191
212
|
act(row) {
|
|
192
213
|
if (row.disabled) {
|
|
193
214
|
return;
|
package/dist/list/selection.d.ts
CHANGED
|
@@ -47,3 +47,20 @@ export declare const choiceValue: ({ anchor, arrived, behavior, extend, mode, pr
|
|
|
47
47
|
* and from the cell going back reaches the last control.
|
|
48
48
|
*/
|
|
49
49
|
export declare const rowStop: (count: number, at: number, step: -1 | 1) => number;
|
|
50
|
+
/** Where a row sits along the list, in pixels, as the page keys measure it. */
|
|
51
|
+
export interface RowEdges {
|
|
52
|
+
/** The row's top edge. */
|
|
53
|
+
top: number;
|
|
54
|
+
/** The row's bottom edge. */
|
|
55
|
+
bottom: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Where Page Down (`step` 1) or Page Up (`step` -1) goes from row `at`: the
|
|
59
|
+
* farthest row that fits whole in `room` pixels together with row `at`, so the
|
|
60
|
+
* row at one edge of the box lands at the other, and at least the next row.
|
|
61
|
+
*
|
|
62
|
+
* Measured rather than counted, because a list's rows differ in height. Rows of
|
|
63
|
+
* one height `h` move `floor(room / h) - 1` rows, which is what Data Table and
|
|
64
|
+
* Virtual List move. At either end it stays on row `at`.
|
|
65
|
+
*/
|
|
66
|
+
export declare const pageReach: (rows: readonly RowEdges[], at: number, room: number, step: -1 | 1) => number;
|
package/dist/list/selection.js
CHANGED
|
@@ -28,3 +28,19 @@ export const rowStop = (count, at, step) => {
|
|
|
28
28
|
}
|
|
29
29
|
return next < 0 ? count - 1 : next;
|
|
30
30
|
};
|
|
31
|
+
export const pageReach = (rows, at, room, step) => {
|
|
32
|
+
const from = rows[at];
|
|
33
|
+
if (!from) {
|
|
34
|
+
return at;
|
|
35
|
+
}
|
|
36
|
+
let reach = at;
|
|
37
|
+
for (let next = at + step; next >= 0 && next < rows.length; next += step) {
|
|
38
|
+
const row = rows[next];
|
|
39
|
+
const span = step === 1 ? row.bottom - from.top : from.bottom - row.top;
|
|
40
|
+
if (span > room && next !== at + step) {
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
reach = next;
|
|
44
|
+
}
|
|
45
|
+
return reach;
|
|
46
|
+
};
|
|
@@ -27,7 +27,9 @@ declare const HelixHeadlessListbox_base: (new (...args: any[]) => import("@fusio
|
|
|
27
27
|
* highlighted option, Shift with an arrow adds the option it moves to, Shift
|
|
28
28
|
* with Home or End adds every option from the highlight to that end, and
|
|
29
29
|
* Control+A or Command+A chooses every option, or none where all are chosen.
|
|
30
|
-
* In a filter field, Space, Home, End and letters edit the text
|
|
30
|
+
* In a filter field, Space, Home, End and letters edit the text, and with
|
|
31
|
+
* `multiple`, Control with Shift and Home or End adds every option from the
|
|
32
|
+
* highlight to that end.
|
|
31
33
|
*
|
|
32
34
|
* An option with `href` is a link: Enter or a press follows it and selects
|
|
33
35
|
* nothing, and moving onto it with the arrows does not follow it.
|
|
@@ -286,7 +288,8 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
286
288
|
*/
|
|
287
289
|
get options(): HelixHeadlessOption[];
|
|
288
290
|
/**
|
|
289
|
-
*
|
|
291
|
+
* The elements of one kind in the list: its options, its groups or its
|
|
292
|
+
* rules. Walks the tree, and walks *through* a slot when it meets one.
|
|
290
293
|
*
|
|
291
294
|
* Through a slot because that is how this gets composed. `Select` renders a
|
|
292
295
|
* listbox in its own shadow root with a slot inside it, so the options are
|
|
@@ -294,7 +297,7 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
294
297
|
* `querySelectorAll` finds the slot and no options at all, and the whole
|
|
295
298
|
* component comes up empty.
|
|
296
299
|
*/
|
|
297
|
-
private
|
|
300
|
+
private among;
|
|
298
301
|
/** The groups, found the same way and for the same reason. */
|
|
299
302
|
private get groups();
|
|
300
303
|
/** The options a filter has left showing. */
|
|
@@ -455,8 +458,9 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
455
458
|
private askedAt;
|
|
456
459
|
/**
|
|
457
460
|
* Asks for more once the reader is within a screen of the end, React Aria's
|
|
458
|
-
* `onLoadMore
|
|
459
|
-
*
|
|
461
|
+
* `onLoadMore`, by core's `endInSight`, the rule Virtual List asks too: once
|
|
462
|
+
* for each number of options, so a scroll that goes on asks again only after
|
|
463
|
+
* the next page arrived, and never while loading.
|
|
460
464
|
*/
|
|
461
465
|
private readonly handleScroll;
|
|
462
466
|
/** Requests a new filter, and returns whether the request went through. */
|
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { AriaForwardController, countLabel, customElement, DelayController, DisabledCascadeController, HelixFilterEvent, HelixFormElement, HelixLoadMoreEvent, hostAria, MixinCollection, MixinControllerValue, MixinField, rangeAdd, reportValues, requestChange, scrollItemIntoView, Typeahead, typesCharacter, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, countLabel, customElement, DelayController, DisabledCascadeController, endInSight, HelixFilterEvent, HelixFormElement, HelixLoadMoreEvent, hostAria, MixinCollection, MixinControllerValue, MixinField, rangeAdd, reportValues, requestChange, scrollItemIntoView, selectsAll, Typeahead, typesCharacter, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { magnifyingGlass } from '@fusion.dev/helix-icons';
|
|
9
9
|
import { html, nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
@@ -119,11 +119,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
119
119
|
}
|
|
120
120
|
return;
|
|
121
121
|
}
|
|
122
|
-
if (this.multiple &&
|
|
123
|
-
!typing &&
|
|
124
|
-
event.key.toLowerCase() === 'a' &&
|
|
125
|
-
(event.ctrlKey || event.metaKey) &&
|
|
126
|
-
!event.altKey) {
|
|
122
|
+
if (this.multiple && !typing && selectsAll(event)) {
|
|
127
123
|
event.preventDefault();
|
|
128
124
|
const reachable = shown.map((option) => option.value);
|
|
129
125
|
const all = reachable.every((value) => this.values.includes(value));
|
|
@@ -139,7 +135,12 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
139
135
|
}
|
|
140
136
|
return;
|
|
141
137
|
}
|
|
142
|
-
|
|
138
|
+
const fieldRange = typing &&
|
|
139
|
+
this.multiple &&
|
|
140
|
+
event.shiftKey &&
|
|
141
|
+
(event.ctrlKey || event.metaKey) &&
|
|
142
|
+
(event.key === 'Home' || event.key === 'End');
|
|
143
|
+
if (!fieldRange && !(typing ? FIELD_MOVES : MOVES).has(event.key)) {
|
|
143
144
|
return;
|
|
144
145
|
}
|
|
145
146
|
event.preventDefault();
|
|
@@ -170,7 +171,7 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
170
171
|
if (target) {
|
|
171
172
|
this.arrive(target.value);
|
|
172
173
|
const ranged = event.key === 'Home' || event.key === 'End';
|
|
173
|
-
if (this.multiple && !typing && event.shiftKey && ranged) {
|
|
174
|
+
if (this.multiple && (!typing || fieldRange) && event.shiftKey && ranged) {
|
|
174
175
|
const taken = rangeAdd(this.values, shown.map((option) => option.value), at, next);
|
|
175
176
|
if (taken) {
|
|
176
177
|
this.requestValue(taken.join(','));
|
|
@@ -197,13 +198,17 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
197
198
|
this.handleScroll = (event) => {
|
|
198
199
|
const items = event.currentTarget;
|
|
199
200
|
const count = this.options.length;
|
|
200
|
-
if (this.loading ||
|
|
201
|
+
if (this.loading ||
|
|
202
|
+
!endInSight({
|
|
203
|
+
askedAt: this.askedAt,
|
|
204
|
+
count,
|
|
205
|
+
remaining: items.scrollHeight - items.scrollTop - items.clientHeight,
|
|
206
|
+
screen: items.clientHeight,
|
|
207
|
+
})) {
|
|
201
208
|
return;
|
|
202
209
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
this.dispatchEvent(new HelixLoadMoreEvent());
|
|
206
|
-
}
|
|
210
|
+
this.askedAt = count;
|
|
211
|
+
this.dispatchEvent(new HelixLoadMoreEvent());
|
|
207
212
|
};
|
|
208
213
|
this.handleFilterKeydown = (event) => {
|
|
209
214
|
if (event.key === 'Enter' || FIELD_MOVES.has(event.key)) {
|
|
@@ -293,40 +298,24 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
293
298
|
return this.multiple ? 'select-multiple' : 'select-one';
|
|
294
299
|
}
|
|
295
300
|
get options() {
|
|
296
|
-
return this.
|
|
301
|
+
return this.among((node) => node instanceof HelixHeadlessOption, this.children);
|
|
297
302
|
}
|
|
298
|
-
|
|
303
|
+
among(is, nodes) {
|
|
299
304
|
const found = [];
|
|
300
305
|
for (const node of nodes) {
|
|
301
|
-
if (node
|
|
306
|
+
if (is(node)) {
|
|
302
307
|
found.push(node);
|
|
303
308
|
}
|
|
304
|
-
else if (node instanceof HTMLSlotElement) {
|
|
305
|
-
found.push(...this.collect(node.assignedElements({ flatten: true })));
|
|
306
|
-
}
|
|
307
309
|
else {
|
|
308
|
-
found.push(...this.
|
|
310
|
+
found.push(...this.among(is, node instanceof HTMLSlotElement
|
|
311
|
+
? node.assignedElements({ flatten: true })
|
|
312
|
+
: node.children));
|
|
309
313
|
}
|
|
310
314
|
}
|
|
311
315
|
return found;
|
|
312
316
|
}
|
|
313
317
|
get groups() {
|
|
314
|
-
|
|
315
|
-
const walk = (nodes) => {
|
|
316
|
-
for (const node of nodes) {
|
|
317
|
-
if (node instanceof HelixHeadlessOptionGroup) {
|
|
318
|
-
found.push(node);
|
|
319
|
-
}
|
|
320
|
-
if (node instanceof HTMLSlotElement) {
|
|
321
|
-
walk(node.assignedElements({ flatten: true }));
|
|
322
|
-
}
|
|
323
|
-
else {
|
|
324
|
-
walk(node.children);
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
};
|
|
328
|
-
walk(this.children);
|
|
329
|
-
return found;
|
|
318
|
+
return this.among((node) => node instanceof HelixHeadlessOptionGroup, this.children);
|
|
330
319
|
}
|
|
331
320
|
get shown() {
|
|
332
321
|
return this.options.filter((option) => !option.hidden);
|
|
@@ -398,9 +387,12 @@ let HelixHeadlessListbox = class HelixHeadlessListbox extends MixinCollection(Mi
|
|
|
398
387
|
option.selected = chosen.has(option.value);
|
|
399
388
|
}
|
|
400
389
|
for (const group of this.groups) {
|
|
401
|
-
const inside = this.
|
|
390
|
+
const inside = this.among((node) => node instanceof HelixHeadlessOption, group.children);
|
|
402
391
|
group.hidden = inside.length > 0 && inside.every((option) => option.hidden);
|
|
403
392
|
}
|
|
393
|
+
for (const rule of this.among((node) => node.localName.endsWith('-option-separator'), this.children)) {
|
|
394
|
+
rule.hidden = needle !== '';
|
|
395
|
+
}
|
|
404
396
|
const shown = this.shown;
|
|
405
397
|
const rescue = !this.parked && (needle !== '' || this.activeValue !== '');
|
|
406
398
|
if (rescue && !shown.some((option) => option.value === this.activeValue)) {
|