@fusion.dev/helix-headless 0.145.0 → 0.146.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 +7373 -3849
- package/dist/accordion/item/accordion-item.d.ts +14 -0
- package/dist/accordion/item/accordion-item.js +16 -6
- package/dist/accordion/root/accordion-root.d.ts +8 -5
- package/dist/announcement/root/announcement-root.d.ts +3 -2
- package/dist/announcement/root/announcement-root.js +3 -1
- package/dist/app-header/root/app-header-root.d.ts +7 -2
- package/dist/app-header/root/app-header-root.js +9 -1
- package/dist/app-header/sectioning.d.ts +3 -1
- package/dist/app-header/sectioning.js +3 -2
- package/dist/avatar/group/avatar-group.d.ts +20 -14
- package/dist/avatar/group/avatar-group.js +17 -19
- package/dist/badge/root/badge-root.d.ts +3 -1
- package/dist/badge/root/badge-root.js +2 -2
- package/dist/bar-chart/root/bar-chart-root.d.ts +18 -1
- package/dist/bar-chart/root/bar-chart-root.js +52 -15
- package/dist/bar-chart/stack.d.ts +15 -0
- package/dist/bar-chart/stack.js +19 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +25 -0
- package/dist/breadcrumbs/root/breadcrumbs-root.js +50 -3
- package/dist/button/root/button-root.d.ts +26 -0
- package/dist/button/root/button-root.js +38 -18
- package/dist/button-group/root/button-group-root.d.ts +2 -1
- package/dist/button-group/root/button-group-root.js +5 -1
- package/dist/canvas/node/canvas-node.d.ts +4 -3
- package/dist/canvas/node/canvas-node.js +3 -2
- package/dist/canvas/root/canvas-root.js +2 -2
- package/dist/card/root/card-root.d.ts +24 -3
- package/dist/card/root/card-root.js +20 -8
- package/dist/carousel/root/carousel-root.d.ts +43 -4
- package/dist/carousel/root/carousel-root.js +40 -12
- package/dist/carousel/stops.d.ts +20 -0
- package/dist/carousel/stops.js +30 -0
- package/dist/chat/message/chat-message.js +5 -4
- package/dist/chat/naming.d.ts +5 -1
- package/dist/chat/naming.js +4 -2
- package/dist/chat/root/chat-root.d.ts +25 -3
- package/dist/chat/root/chat-root.js +22 -5
- package/dist/checkbox/root/checkbox-root.d.ts +20 -0
- package/dist/checkbox/root/checkbox-root.js +14 -1
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +8 -2
- package/dist/checkbox-group/root/checkbox-group-root.js +12 -10
- package/dist/checkbox-group/select-all.d.ts +27 -0
- package/dist/checkbox-group/select-all.js +12 -0
- package/dist/code-block/highlight.d.ts +15 -0
- package/dist/code-block/highlight.js +4 -0
- package/dist/code-block/root/code-block-root.d.ts +49 -1
- package/dist/code-block/root/code-block-root.js +58 -3
- package/dist/color-input/root/color-input-root.d.ts +3 -0
- package/dist/color-input/root/color-input-root.js +6 -3
- package/dist/color-picker/root/color-picker-root.d.ts +33 -4
- package/dist/color-picker/root/color-picker-root.js +80 -21
- package/dist/color-picker/swatches.d.ts +12 -0
- package/dist/color-picker/swatches.js +26 -0
- package/dist/combobox/root/combobox-root.d.ts +43 -0
- package/dist/combobox/root/combobox-root.js +79 -15
- package/dist/command/root/command-root.d.ts +16 -1
- package/dist/command/root/command-root.js +22 -4
- package/dist/copy-button/root/copy-button-root.d.ts +5 -0
- package/dist/copy-button/root/copy-button-root.js +10 -3
- package/dist/data-table/index.d.ts +1 -1
- package/dist/data-table/index.js +1 -1
- package/dist/data-table/keys.d.ts +24 -0
- package/dist/data-table/keys.js +24 -0
- package/dist/data-table/root/data-table-root.d.ts +27 -18
- package/dist/data-table/root/data-table-root.js +20 -52
- package/dist/data-table/tree.d.ts +16 -1
- package/dist/data-table/tree.js +2 -3
- package/dist/date-input/root/date-input-root.d.ts +3 -1
- package/dist/date-input/root/date-input-root.js +18 -7
- package/dist/date-picker/root/date-picker-root.js +12 -6
- package/dist/dialog/description.js +15 -1
- package/dist/dialog/root/dialog-root.d.ts +8 -2
- package/dist/dialog/root/dialog-root.js +16 -1
- package/dist/divider/root/divider-root.d.ts +3 -0
- package/dist/divider/root/divider-root.js +2 -1
- package/dist/donut-chart/root/donut-chart-root.d.ts +31 -0
- package/dist/donut-chart/root/donut-chart-root.js +48 -1
- package/dist/drawer/reveal.d.ts +8 -0
- package/dist/drawer/reveal.js +1 -0
- package/dist/drawer/root/drawer-root.d.ts +59 -0
- package/dist/drawer/root/drawer-root.js +63 -4
- package/dist/drilldown/item/drilldown-item.js +1 -1
- package/dist/drilldown/root/drilldown-root.d.ts +21 -3
- package/dist/drilldown/root/drilldown-root.js +21 -3
- package/dist/element-events.generated.js +31 -5
- package/dist/empty/root/empty-root.d.ts +3 -1
- package/dist/empty/root/empty-root.js +3 -2
- package/dist/file-input/root/file-input-root.d.ts +69 -6
- package/dist/file-input/root/file-input-root.js +82 -19
- package/dist/file-input/screen.d.ts +2 -1
- package/dist/filter-input/menu/filter-menu.d.ts +2 -0
- package/dist/filter-input/menu/filter-menu.js +12 -4
- package/dist/filter-input/root/filter-input-root.d.ts +30 -6
- package/dist/filter-input/root/filter-input-root.js +1 -1
- package/dist/filter-input/suggest.d.ts +28 -3
- package/dist/filter-input/suggest.js +18 -8
- package/dist/format-date/root/format-date-root.d.ts +9 -16
- package/dist/format-date/root/format-date-root.js +10 -27
- package/dist/heatmap/root/heatmap-root.d.ts +24 -13
- package/dist/heatmap/root/heatmap-root.js +34 -12
- package/dist/icon/root/icon-root.d.ts +12 -1
- package/dist/icon/root/icon-root.js +21 -10
- package/dist/icon/settle.d.ts +7 -0
- package/dist/icon/settle.js +10 -0
- package/dist/icon-button/root/icon-button-root.d.ts +2 -0
- package/dist/image/root/image-root.d.ts +5 -1
- package/dist/image/root/image-root.js +1 -1
- package/dist/input/root/input-root.d.ts +12 -2
- package/dist/input/root/input-root.js +11 -2
- package/dist/kbd/root/kbd-root.d.ts +35 -1
- package/dist/kbd/root/kbd-root.js +23 -4
- package/dist/legend/root/legend-root.d.ts +55 -8
- package/dist/legend/root/legend-root.js +55 -13
- package/dist/lightbox/root/lightbox-root.d.ts +49 -6
- package/dist/lightbox/root/lightbox-root.js +86 -19
- package/dist/lightbox/zoom-controller.d.ts +59 -0
- package/dist/lightbox/zoom-controller.js +128 -0
- package/dist/lightbox/zoom.d.ts +22 -0
- package/dist/lightbox/zoom.js +16 -0
- package/dist/line-chart/root/line-chart-root.d.ts +22 -1
- package/dist/line-chart/root/line-chart-root.js +21 -1
- package/dist/list/item/list-item.d.ts +2 -0
- package/dist/list/item/list-item.js +11 -2
- package/dist/list/root/list-root.d.ts +62 -13
- package/dist/list/root/list-root.js +70 -13
- package/dist/list/selection.d.ts +37 -7
- package/dist/list/selection.js +16 -7
- package/dist/listbox/root/listbox-root.d.ts +37 -1
- package/dist/listbox/root/listbox-root.js +49 -3
- package/dist/loader/busy.d.ts +10 -0
- package/dist/loader/busy.js +11 -0
- package/dist/loader/root/loader-root.d.ts +9 -2
- package/dist/loader/root/loader-root.js +23 -3
- package/dist/megamenu/root/megamenu-root.d.ts +51 -10
- package/dist/megamenu/root/megamenu-root.js +76 -5
- package/dist/menu/item/menu-item.d.ts +51 -2
- package/dist/menu/item/menu-item.js +47 -23
- package/dist/menu/root/menu-root.d.ts +14 -0
- package/dist/menu/root/menu-root.js +2 -2
- package/dist/meter/root/meter-root.d.ts +20 -1
- package/dist/meter/root/meter-root.js +11 -15
- package/dist/navigation/root/navigation-root.d.ts +2 -1
- package/dist/navigation/root/navigation-root.js +2 -2
- package/dist/notifications/root/notifications-root.d.ts +10 -3
- package/dist/notifications/root/notifications-root.js +19 -7
- package/dist/number-input/root/number-input-root.d.ts +17 -8
- package/dist/number-input/root/number-input-root.js +2 -7
- package/dist/object-inspector/root/object-inspector-root.d.ts +75 -27
- package/dist/object-inspector/root/object-inspector-root.js +117 -76
- package/dist/object-inspector/rows.d.ts +18 -0
- package/dist/object-inspector/rows.js +33 -0
- package/dist/option/root/option-root.d.ts +5 -3
- package/dist/outline/root/outline-root.d.ts +18 -0
- package/dist/outline/root/outline-root.js +23 -5
- package/dist/pagination/size/pagination-size.d.ts +1 -0
- package/dist/pagination/size/pagination-size.js +1 -1
- package/dist/pin-input/code.d.ts +10 -0
- package/dist/pin-input/code.js +13 -0
- package/dist/pin-input/root/pin-input-root.d.ts +25 -1
- package/dist/pin-input/root/pin-input-root.js +10 -11
- package/dist/popover/hide-outside.d.ts +14 -0
- package/dist/popover/hide-outside.js +41 -0
- package/dist/popover/root/popover-root.d.ts +57 -7
- package/dist/popover/root/popover-root.js +58 -3
- package/dist/progress/root/progress-root.d.ts +20 -0
- package/dist/progress/root/progress-root.js +15 -15
- package/dist/qr-code/export.d.ts +26 -1
- package/dist/qr-code/export.js +14 -0
- package/dist/qr-code/root/qr-code-root.d.ts +19 -5
- package/dist/qr-code/root/qr-code-root.js +58 -9
- package/dist/quote/marks.d.ts +8 -0
- package/dist/quote/marks.js +5 -0
- package/dist/quote/root/quote-root.d.ts +14 -2
- package/dist/quote/root/quote-root.js +23 -1
- package/dist/radio/root/radio-root.d.ts +6 -2
- package/dist/radio/root/radio-root.js +6 -1
- package/dist/rating/root/rating-root.d.ts +9 -4
- package/dist/rating/root/rating-root.js +31 -7
- package/dist/rating/steps.d.ts +7 -0
- package/dist/rating/steps.js +9 -0
- package/dist/scatter-chart/fit.d.ts +15 -0
- package/dist/scatter-chart/fit.js +35 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +21 -1
- package/dist/scatter-chart/root/scatter-chart-root.js +30 -17
- package/dist/scroll-area/root/scroll-area-root.d.ts +22 -51
- package/dist/scroll-area/root/scroll-area-root.js +57 -173
- package/dist/scroll-area/scrollbar-controller.d.ts +111 -0
- package/dist/scroll-area/scrollbar-controller.js +172 -0
- package/dist/scroll-area/scrollbar.d.ts +27 -0
- package/dist/scroll-area/scrollbar.js +9 -0
- package/dist/select/root/select-root.d.ts +15 -0
- package/dist/select/root/select-root.js +18 -6
- package/dist/skeleton/root/skeleton-root.d.ts +3 -0
- package/dist/skeleton/root/skeleton-root.js +4 -2
- package/dist/skip-link/root/skip-link-root.js +2 -2
- package/dist/slider/root/slider-root.d.ts +41 -4
- package/dist/slider/root/slider-root.js +23 -3
- package/dist/sparkline/readings.d.ts +18 -0
- package/dist/sparkline/readings.js +19 -0
- package/dist/sparkline/root/sparkline-root.d.ts +78 -7
- package/dist/sparkline/root/sparkline-root.js +118 -23
- package/dist/speed-dial/root/speed-dial-root.js +2 -2
- package/dist/splitter/root/splitter-root.d.ts +7 -12
- package/dist/splitter/root/splitter-root.js +209 -204
- package/dist/stat/root/stat-root.d.ts +14 -5
- package/dist/stat/root/stat-root.js +21 -5
- package/dist/steps/reach.d.ts +5 -0
- package/dist/steps/reach.js +3 -0
- package/dist/steps/root/steps-root.d.ts +49 -3
- package/dist/steps/root/steps-root.js +44 -5
- package/dist/steps/step/step.d.ts +7 -0
- package/dist/steps/step/step.js +7 -2
- package/dist/switch/root/switch-root.d.ts +10 -0
- package/dist/table/column/table-column.d.ts +0 -10
- package/dist/table/column/table-column.js +3 -19
- package/dist/table/root/table-root.d.ts +31 -10
- package/dist/table/root/table-root.js +2 -13
- package/dist/tabs/panel/tab-panel.d.ts +16 -3
- package/dist/tabs/panel/tab-panel.js +34 -5
- package/dist/tabs/root/tabs-root.d.ts +12 -0
- package/dist/tabs/root/tabs-root.js +1 -1
- package/dist/tabs/tab/tab.d.ts +5 -0
- package/dist/tabs/tab/tab.js +5 -2
- package/dist/tag/group/tag-group.d.ts +31 -4
- package/dist/tag/group/tag-group.js +46 -7
- package/dist/tag/root/tag-root.js +9 -2
- package/dist/textarea/root/textarea-root.d.ts +28 -1
- package/dist/textarea/root/textarea-root.js +40 -1
- package/dist/time-input/root/time-input-root.d.ts +5 -1
- package/dist/time-input/root/time-input-root.js +16 -8
- package/dist/time-picker/root/time-picker-root.d.ts +18 -4
- package/dist/time-picker/root/time-picker-root.js +7 -10
- package/dist/time-picker/wheel-name.d.ts +9 -0
- package/dist/time-picker/wheel-name.js +15 -0
- package/dist/timeline/group/timeline-group.js +2 -2
- package/dist/toast/item/toast-item.d.ts +14 -1
- package/dist/toast/item/toast-item.js +22 -5
- package/dist/toast/root/toast-root.d.ts +6 -0
- package/dist/toast/root/toast-root.js +16 -1
- package/dist/toggle/group/toggle-group.d.ts +24 -3
- package/dist/toggle/group/toggle-group.js +34 -5
- package/dist/tooltip/root/tooltip-root.d.ts +13 -2
- package/dist/tooltip/root/tooltip-root.js +9 -1
- package/dist/tour/back.d.ts +10 -0
- package/dist/tour/back.js +8 -0
- package/dist/tour/root/tour-root.d.ts +30 -2
- package/dist/tour/root/tour-root.js +34 -8
- package/dist/tree/item/tree-item.d.ts +7 -3
- package/dist/tree/item/tree-item.js +3 -0
- package/dist/tree/root/tree-root.d.ts +24 -3
- package/dist/tree/root/tree-root.js +32 -13
- package/dist/tree/selection.js +2 -15
- package/dist/trend/root/trend-root.d.ts +43 -18
- package/dist/trend/root/trend-root.js +31 -6
- package/dist/video/media-events.d.ts +13 -18
- package/dist/video/media-events.js +1 -5
- package/dist/video/root/video-root.d.ts +18 -5
- package/dist/video/root/video-root.js +19 -10
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +2 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +2 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +7 -1
- package/dist/virtual-list/fill.d.ts +0 -8
- package/dist/virtual-list/fill.js +1 -17
- package/dist/virtual-list/plan.d.ts +49 -0
- package/dist/virtual-list/plan.js +16 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +114 -13
- package/dist/virtual-list/root/virtual-list-root.js +183 -40
- package/lint.json +1 -1
- package/package.json +8 -8
- package/types/jsx.d.ts +4577 -835
- package/types/vue.d.ts +926 -168
- package/dist/chat/relative-clock.d.ts +0 -39
- package/dist/chat/relative-clock.js +0 -31
- package/dist/data-table/root/order.d.ts +0 -141
- package/dist/data-table/root/order.js +0 -76
- package/dist/tag/selection.d.ts +0 -10
- package/dist/tag/selection.js +0 -12
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const clamp = (value, low, high) => Math.min(Math.max(value, low), high) || 0;
|
|
2
|
+
export const clampScale = (scale, max) => clamp(scale, 1, Math.max(max, 1));
|
|
3
|
+
export const clampPan = (pan, scale, width, height) => {
|
|
4
|
+
const x = ((scale - 1) * width) / 2;
|
|
5
|
+
const y = ((scale - 1) * height) / 2;
|
|
6
|
+
return { x: clamp(pan.x, -x, x), y: clamp(pan.y, -y, y) };
|
|
7
|
+
};
|
|
8
|
+
export const zoomAt = (at, from, to, pan) => ({
|
|
9
|
+
x: at.x - ((at.x - pan.x) * to) / from,
|
|
10
|
+
y: at.y - ((at.y - pan.y) * to) / from,
|
|
11
|
+
});
|
|
12
|
+
export const spread = (a, b) => Math.hypot(a.x - b.x, a.y - b.y);
|
|
13
|
+
export const between = (a, b) => ({
|
|
14
|
+
x: (a.x + b.x) / 2,
|
|
15
|
+
y: (a.y + b.y) / 2,
|
|
16
|
+
});
|
|
@@ -49,6 +49,8 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
49
49
|
* @csspart line - The line for one series.
|
|
50
50
|
* @csspart live - The readout: a polite live region that says the reading the keys moved to. Hide it visually.
|
|
51
51
|
* @csspart mark - The invisible point the tooltip is anchored to.
|
|
52
|
+
* @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`.
|
|
53
|
+
* @csspart marker-lone - A `marker` on a reading with a blank on either side, which no line reaches. Set alongside `marker`.
|
|
52
54
|
* @csspart plot - The drawing, which takes focus to be read by key.
|
|
53
55
|
* @csspart summary - The chart's name and each series' latest reading, written as a sentence for screen readers. Hide it visually.
|
|
54
56
|
* @csspart svg - The drawing surface the lines and areas sit on.
|
|
@@ -138,6 +140,15 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
138
140
|
protected get rulesValue(): boolean;
|
|
139
141
|
/** Whether each reading is ruled, which only two values ask for. */
|
|
140
142
|
protected get rulesCategory(): boolean;
|
|
143
|
+
/**
|
|
144
|
+
* Draws a mark on every reading, the `marker` part, so a reader sees where
|
|
145
|
+
* the readings are, as well as the line between them.
|
|
146
|
+
*
|
|
147
|
+
* Absent draws none, except on a reading with a blank on either side: it
|
|
148
|
+
* has no line to be part of, so it takes a mark, the `marker` part with
|
|
149
|
+
* `marker-lone` beside it, or it would not be drawn at all.
|
|
150
|
+
*/
|
|
151
|
+
markers: boolean;
|
|
141
152
|
/**
|
|
142
153
|
* The shape of the mark on each series' last reading.
|
|
143
154
|
*
|
|
@@ -200,7 +211,8 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
200
211
|
* The latest, because where a series ended is the question a line over time
|
|
201
212
|
* is asked first, which is what `AreaChart` gives too. Each series' own last
|
|
202
213
|
* reading, so a series with a blank in the last row still says where it was.
|
|
203
|
-
* Written the way the table writes it, such as `$128k` for `128000`.
|
|
214
|
+
* Written the way the table writes it, such as `$128k` for `128000`. A
|
|
215
|
+
* series a legend hid is not drawn and is not said.
|
|
204
216
|
*/
|
|
205
217
|
protected renderSummary(series: Series[]): TemplateResult;
|
|
206
218
|
/**
|
|
@@ -255,6 +267,15 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
255
267
|
x: number;
|
|
256
268
|
y: number;
|
|
257
269
|
}>): TemplateResult | typeof nothing;
|
|
270
|
+
/**
|
|
271
|
+
* The marks on the readings: every one under `markers`, and otherwise only
|
|
272
|
+
* a reading no line reaches, which has a blank on either side.
|
|
273
|
+
*
|
|
274
|
+
* Elements beside the drawing, as the termini are, so a mark is round in a
|
|
275
|
+
* drawing `preserveAspectRatio="none"` stretches. Placed from the inline
|
|
276
|
+
* start, as the drawing is mirrored.
|
|
277
|
+
*/
|
|
278
|
+
protected renderMarkers(series: Series[], x: (value: number) => number, y: (value: number) => number): TemplateResult | typeof nothing;
|
|
258
279
|
/**
|
|
259
280
|
* One series, its wash first so the line is drawn over its own fill.
|
|
260
281
|
*
|
|
@@ -12,6 +12,7 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
12
12
|
constructor() {
|
|
13
13
|
super(...arguments);
|
|
14
14
|
this.area = false;
|
|
15
|
+
this.markers = false;
|
|
15
16
|
this.zero = false;
|
|
16
17
|
}
|
|
17
18
|
get rulesValue() {
|
|
@@ -62,7 +63,7 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
62
63
|
const columns = this.plottedColumns;
|
|
63
64
|
const latest = series.flatMap((one, depth) => {
|
|
64
65
|
const last = one.points.at(-1);
|
|
65
|
-
if (last === undefined) {
|
|
66
|
+
if (last === undefined || !this.showsSeries(one.name)) {
|
|
66
67
|
return [];
|
|
67
68
|
}
|
|
68
69
|
const text = rows[last.at]?.cells[columns[depth] ?? -1]?.text ?? String(last.value);
|
|
@@ -109,6 +110,7 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
109
110
|
${series.map((one, depth) => this.renderSeries(one, depth, x, y))}
|
|
110
111
|
</svg>
|
|
111
112
|
${this.renderTermini(ends)}
|
|
113
|
+
${this.renderMarkers(series, x, y)}
|
|
112
114
|
${this.renderTooltip()}
|
|
113
115
|
</div>`;
|
|
114
116
|
}
|
|
@@ -149,6 +151,21 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
149
151
|
style=${`--chart-series: var(--chart-series-${end.index}); --chart-terminus-x: ${end.x}%; --chart-terminus-y: ${end.y}%`}
|
|
150
152
|
></span>`)}`;
|
|
151
153
|
}
|
|
154
|
+
renderMarkers(series, x, y) {
|
|
155
|
+
const marks = series.flatMap((one, depth) => this.showsSeries(one.name)
|
|
156
|
+
? unbroken(one).flatMap((run) => run.length > 1 && !this.markers
|
|
157
|
+
? []
|
|
158
|
+
: run.map((point) => ({ depth, lone: run.length === 1, point })))
|
|
159
|
+
: []);
|
|
160
|
+
if (marks.length === 0) {
|
|
161
|
+
return nothing;
|
|
162
|
+
}
|
|
163
|
+
return html `${marks.map(({ depth, lone, point }) => html `<span
|
|
164
|
+
aria-hidden="true"
|
|
165
|
+
part="marker${lone ? ' marker-lone' : ''}"
|
|
166
|
+
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
|
+
></span>`)}`;
|
|
168
|
+
}
|
|
152
169
|
renderSeries(one, depth, x, y) {
|
|
153
170
|
if (!this.showsSeries(one.name)) {
|
|
154
171
|
return html `${nothing}`;
|
|
@@ -221,6 +238,9 @@ __decorate([
|
|
|
221
238
|
__decorate([
|
|
222
239
|
property()
|
|
223
240
|
], HelixHeadlessLineChart.prototype, "gridlines", void 0);
|
|
241
|
+
__decorate([
|
|
242
|
+
property({ reflect: true, type: Boolean })
|
|
243
|
+
], HelixHeadlessLineChart.prototype, "markers", void 0);
|
|
224
244
|
__decorate([
|
|
225
245
|
property({ reflect: true })
|
|
226
246
|
], HelixHeadlessLineChart.prototype, "terminus", void 0);
|
|
@@ -109,6 +109,8 @@ export declare class HelixHeadlessListItem extends HelixElement {
|
|
|
109
109
|
value: string;
|
|
110
110
|
/** The row's words, or none where the children are not known yet. */
|
|
111
111
|
get words(): string;
|
|
112
|
+
/** Whether something is slotted into `description`, or false where the children are not known yet. */
|
|
113
|
+
private get described();
|
|
112
114
|
/** Whether a list with `selection-mode` holds this row, which makes it a row of a grid. */
|
|
113
115
|
private get grouped();
|
|
114
116
|
/** @internal The cell a list with `selection-mode` moves focus to. */
|
|
@@ -20,6 +20,9 @@ let HelixHeadlessListItem = class HelixHeadlessListItem extends HelixElement {
|
|
|
20
20
|
get words() {
|
|
21
21
|
return this.childrenKnown ? slottedWords(this, ['']) : '';
|
|
22
22
|
}
|
|
23
|
+
get described() {
|
|
24
|
+
return this.childrenKnown && this.knownChildren.some((child) => child.slot === 'description');
|
|
25
|
+
}
|
|
23
26
|
get grouped() {
|
|
24
27
|
return this.focusable !== undefined;
|
|
25
28
|
}
|
|
@@ -54,20 +57,26 @@ let HelixHeadlessListItem = class HelixHeadlessListItem extends HelixElement {
|
|
|
54
57
|
}
|
|
55
58
|
render() {
|
|
56
59
|
const content = html `${this.renderRail()}<slot name="start"></slot>
|
|
57
|
-
<slot></slot>
|
|
58
|
-
<slot name="description"></slot>`;
|
|
60
|
+
<slot id="label"></slot>
|
|
61
|
+
<slot name="description" id="description"></slot>`;
|
|
59
62
|
const role = this.grouped ? 'gridcell' : nothing;
|
|
60
63
|
const tabindex = this.grouped ? (this.focusable ? '0' : '-1') : nothing;
|
|
64
|
+
const labelledby = this.grouped && this.words !== '' ? 'label' : nothing;
|
|
65
|
+
const describedby = this.grouped && this.described ? 'description' : nothing;
|
|
61
66
|
return this.href === ''
|
|
62
67
|
? html `<div
|
|
63
68
|
part="row${this.current === undefined ? '' : ' row-current'}"
|
|
64
69
|
role=${role}
|
|
65
70
|
tabindex=${tabindex}
|
|
71
|
+
aria-labelledby=${labelledby}
|
|
72
|
+
aria-describedby=${describedby}
|
|
66
73
|
>${content}<slot name="end"></slot></div>`
|
|
67
74
|
: html `<div
|
|
68
75
|
part="row${this.current === undefined ? '' : ' row-current'}"
|
|
69
76
|
role=${role}
|
|
70
77
|
tabindex=${tabindex}
|
|
78
|
+
aria-labelledby=${labelledby}
|
|
79
|
+
aria-describedby=${describedby}
|
|
71
80
|
><a
|
|
72
81
|
part="link"
|
|
73
82
|
href=${this.href}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { HelixElement, KeyboardNavigationController } from '@fusion.dev/helix-core';
|
|
2
2
|
import { type PropertyValues, type TemplateResult } from 'lit';
|
|
3
3
|
import { HelixHeadlessListItem } from '../item/list-item.js';
|
|
4
|
-
import { type ListSelectionMode } from '../selection.js';
|
|
4
|
+
import { type ListSelectionBehavior, type ListSelectionMode } from '../selection.js';
|
|
5
5
|
/**
|
|
6
6
|
* @summary A set of rows, announced as a list.
|
|
7
7
|
*
|
|
@@ -10,15 +10,33 @@ import { type ListSelectionMode } from '../selection.js';
|
|
|
10
10
|
* announces each one's position, such as "1 of 7".
|
|
11
11
|
*
|
|
12
12
|
* **`selection-mode` makes the list interactive**, in the way of a grid list:
|
|
13
|
-
* a grid of rows that is one tab stop.
|
|
14
|
-
*
|
|
15
|
-
* row starting with it. Left and Right move between the row and the controls
|
|
16
|
-
* in its `end` slot. `single` selects one row at a time and `multiple` any
|
|
17
|
-
* number, with Space or a press, and `value` holds the selected rows' values,
|
|
13
|
+
* a grid of rows that is one tab stop. `single` selects one row at a time and
|
|
14
|
+
* `multiple` any number, and `value` holds the selected rows' values,
|
|
18
15
|
* separated by commas. A change asks with `helix-before-change` and tells
|
|
19
|
-
* with `change`.
|
|
20
|
-
* `
|
|
21
|
-
* `
|
|
16
|
+
* with `change`. `none` selects nothing, so a press acts on the row. A
|
|
17
|
+
* `disabled` row is passed over. Each row is named by its label and described
|
|
18
|
+
* by its description, so the words of the controls in `end` are not read as
|
|
19
|
+
* part of its name.
|
|
20
|
+
*
|
|
21
|
+
* `selection-behavior` says what a press does to the rows already selected.
|
|
22
|
+
* `toggle`, the default, adds or takes out the row. `replace` selects the row
|
|
23
|
+
* alone, as a file list does, and the arrow keys carry the selection with
|
|
24
|
+
* them. Control or Command with a press then adds or takes out one row.
|
|
25
|
+
*
|
|
26
|
+
* | Key | What it does |
|
|
27
|
+
* |---|---|
|
|
28
|
+
* | Down, Up | Moves to the next or the previous row. Under `replace`, selects it. |
|
|
29
|
+
* | Home, End | Moves to the first or the last row. Under `replace`, selects it. |
|
|
30
|
+
* | A letter or a word | Moves to the next row whose words start with what you typed. |
|
|
31
|
+
* | Left, Right | Moves between the row and the controls in its `end` slot. |
|
|
32
|
+
* | 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 End | Moves without selecting, under `replace`. |
|
|
35
|
+
* | Control or Command with A | Selects every row, in `multiple`. |
|
|
36
|
+
* | Enter | Acts on the row: follows its link, or sends `helix-action` from it. |
|
|
37
|
+
*
|
|
38
|
+
* A press with Shift selects every row from the last one pressed, and a press
|
|
39
|
+
* with Control or Command adds or takes out one row under `replace`.
|
|
22
40
|
*
|
|
23
41
|
* **Leave `selection-mode` unset for a list a reader reads**, and set it for
|
|
24
42
|
* one a reader chooses from or acts on. The rows of an interactive list are
|
|
@@ -80,6 +98,12 @@ export declare class HelixHeadlessList extends HelixElement {
|
|
|
80
98
|
* its last row, as `<ol reversed>` does.
|
|
81
99
|
*/
|
|
82
100
|
reversed: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* What a press does to the rows already selected, in a list that selects:
|
|
103
|
+
* `toggle` adds or takes out the row, and `replace` selects it alone and
|
|
104
|
+
* lets the arrow keys carry the selection.
|
|
105
|
+
*/
|
|
106
|
+
selectionBehavior: ListSelectionBehavior;
|
|
83
107
|
/**
|
|
84
108
|
* Makes the list interactive: `single` selects one row, `multiple` any
|
|
85
109
|
* number, and `none` moves and acts without selecting. Unset is a list a
|
|
@@ -112,6 +136,13 @@ export declare class HelixHeadlessList extends HelixElement {
|
|
|
112
136
|
value: string;
|
|
113
137
|
/** The row the reader was last on, which keeps the tab stop. */
|
|
114
138
|
private last;
|
|
139
|
+
/** The value of the row a Shift range runs from: the last row pressed. */
|
|
140
|
+
private anchor;
|
|
141
|
+
/**
|
|
142
|
+
* Shift and Control or Command on the key that is moving focus, read when
|
|
143
|
+
* focus arrives on a row and cleared once the key has been answered.
|
|
144
|
+
*/
|
|
145
|
+
private moving;
|
|
115
146
|
/**
|
|
116
147
|
* Up, Down, Home, End and typed letters, moving focus and choosing nothing,
|
|
117
148
|
* from the focused row and without wrapping. Left and Right are the row's.
|
|
@@ -136,15 +167,33 @@ export declare class HelixHeadlessList extends HelixElement {
|
|
|
136
167
|
/** The row a press or a key came from, read off the event's path. */
|
|
137
168
|
private rowOf;
|
|
138
169
|
/**
|
|
139
|
-
* Selects
|
|
140
|
-
* carries the `value`
|
|
141
|
-
* has moved.
|
|
170
|
+
* Selects what a press or a key leaves, asking first. `helix-before-change`
|
|
171
|
+
* carries the `value` it would leave, and `change` follows once it has moved.
|
|
142
172
|
*/
|
|
143
|
-
|
|
173
|
+
private choose;
|
|
174
|
+
/** What `choiceValue` needs of this list for a row. */
|
|
175
|
+
private choice;
|
|
176
|
+
/**
|
|
177
|
+
* Selects the row, or lets it go, by `selection-behavior`: Shift takes in
|
|
178
|
+
* the rows from the last one pressed, and Control or Command toggles one row
|
|
179
|
+
* under `replace`. The row is where the next range runs from.
|
|
180
|
+
*/
|
|
181
|
+
protected press(row: HelixHeadlessListItem, extend?: boolean, toggle?: boolean): void;
|
|
182
|
+
/**
|
|
183
|
+
* A key moved focus onto the row: under `replace` it is selected alone, and
|
|
184
|
+
* with Shift the rows from the anchor are taken in, from `from` where
|
|
185
|
+
* nothing was pressed yet.
|
|
186
|
+
*/
|
|
187
|
+
private arrive;
|
|
144
188
|
/** Acts on the row: follows its link, or says it was acted on. */
|
|
145
189
|
protected act(row: HelixHeadlessListItem): void;
|
|
146
190
|
/** Left and Right inside a row: the cell, then each control in `end`, and back. */
|
|
147
191
|
private moveInRow;
|
|
192
|
+
/**
|
|
193
|
+
* Notes the modifiers of a key before the keyboard controller moves focus
|
|
194
|
+
* with it, which happens first, in the same dispatch.
|
|
195
|
+
*/
|
|
196
|
+
private readonly handleKeyCapture;
|
|
148
197
|
private readonly handleKeydown;
|
|
149
198
|
private readonly handleClick;
|
|
150
199
|
private readonly handleFocusin;
|
|
@@ -4,46 +4,57 @@ 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, whenHydrated, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { commaList, customElement, HelixActionEvent, HelixBeforeChangeEvent, HelixElement, hostAria, inlineStep, KeyboardNavigationController, requestChange, rovingStop, typeaheadBy, 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 {
|
|
12
|
+
import { choiceValue, 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() {
|
|
16
16
|
super(...arguments);
|
|
17
17
|
this.label = '';
|
|
18
18
|
this.reversed = false;
|
|
19
|
+
this.selectionBehavior = 'toggle';
|
|
19
20
|
this.value = '';
|
|
20
21
|
this.keys = new KeyboardNavigationController(this, {
|
|
21
22
|
items: () => this.reachable.map((row) => this.navigable(row)),
|
|
22
23
|
origin: 'focus',
|
|
23
24
|
reserved: () => ['ArrowLeft', 'ArrowRight'],
|
|
24
25
|
selects: () => false,
|
|
25
|
-
typeahead: (item) => item.words,
|
|
26
|
+
typeahead: typeaheadBy((item) => item.words),
|
|
26
27
|
wrap: false,
|
|
27
28
|
});
|
|
29
|
+
this.handleKeyCapture = (event) => {
|
|
30
|
+
this.moving = { extend: event.shiftKey, toggle: event.ctrlKey || event.metaKey };
|
|
31
|
+
};
|
|
28
32
|
this.handleKeydown = (event) => {
|
|
33
|
+
this.moving = undefined;
|
|
29
34
|
const row = this.interactive ? this.rowOf(event) : undefined;
|
|
30
|
-
if (!row || row.disabled || event.altKey
|
|
35
|
+
if (!row || row.disabled || event.altKey) {
|
|
31
36
|
return;
|
|
32
37
|
}
|
|
33
|
-
|
|
38
|
+
const toggle = event.ctrlKey || event.metaKey;
|
|
39
|
+
if (!toggle && (event.key === 'ArrowLeft' || event.key === 'ArrowRight')) {
|
|
34
40
|
this.moveInRow(row, event);
|
|
35
41
|
return;
|
|
36
42
|
}
|
|
37
43
|
if (event.composedPath()[0] !== row.cell) {
|
|
38
44
|
return;
|
|
39
45
|
}
|
|
40
|
-
if (event.key === '
|
|
46
|
+
if (toggle && event.key.toLowerCase() === 'a' && this.selectionMode === 'multiple') {
|
|
47
|
+
event.preventDefault();
|
|
48
|
+
const every = this.reachable.map((one) => this.valueFor(one)).join(', ');
|
|
49
|
+
this.choose(every === this.value ? null : every);
|
|
50
|
+
}
|
|
51
|
+
else if (event.key === 'Enter' && !toggle) {
|
|
41
52
|
event.preventDefault();
|
|
42
53
|
this.act(row);
|
|
43
54
|
}
|
|
44
|
-
else if (event.key === ' ') {
|
|
55
|
+
else if (event.key === ' ' && !event.defaultPrevented) {
|
|
45
56
|
event.preventDefault();
|
|
46
|
-
this.press(row);
|
|
57
|
+
this.press(row, event.shiftKey, toggle);
|
|
47
58
|
}
|
|
48
59
|
};
|
|
49
60
|
this.handleClick = (event) => {
|
|
@@ -62,13 +73,17 @@ let HelixHeadlessList = class HelixHeadlessList extends HelixElement {
|
|
|
62
73
|
this.act(row);
|
|
63
74
|
}
|
|
64
75
|
else {
|
|
65
|
-
this.press(row);
|
|
76
|
+
this.press(row, event.shiftKey, event.ctrlKey || event.metaKey);
|
|
66
77
|
}
|
|
67
78
|
};
|
|
68
79
|
this.handleFocusin = (event) => {
|
|
69
80
|
const row = this.interactive ? this.rowOf(event) : undefined;
|
|
70
81
|
if (row && row !== this.last) {
|
|
82
|
+
const from = this.last;
|
|
71
83
|
this.last = row;
|
|
84
|
+
if (event.composedPath()[0] === row.cell) {
|
|
85
|
+
this.arrive(row, from);
|
|
86
|
+
}
|
|
72
87
|
this.sync();
|
|
73
88
|
}
|
|
74
89
|
};
|
|
@@ -121,9 +136,8 @@ let HelixHeadlessList = class HelixHeadlessList extends HelixElement {
|
|
|
121
136
|
.composedPath()
|
|
122
137
|
.find((node) => node instanceof HelixHeadlessListItem && node.parentElement === this);
|
|
123
138
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if (mode === undefined || mode === 'none' || row.disabled) {
|
|
139
|
+
choose(next) {
|
|
140
|
+
if (next === null) {
|
|
127
141
|
return;
|
|
128
142
|
}
|
|
129
143
|
requestChange({
|
|
@@ -133,9 +147,47 @@ let HelixHeadlessList = class HelixHeadlessList extends HelixElement {
|
|
|
133
147
|
},
|
|
134
148
|
event: (value) => new HelixBeforeChangeEvent({ value }),
|
|
135
149
|
host: this,
|
|
136
|
-
next
|
|
150
|
+
next,
|
|
137
151
|
});
|
|
138
152
|
}
|
|
153
|
+
choice(row, extend, toggle, arrived) {
|
|
154
|
+
return {
|
|
155
|
+
anchor: this.anchor,
|
|
156
|
+
arrived,
|
|
157
|
+
behavior: this.selectionBehavior,
|
|
158
|
+
extend,
|
|
159
|
+
mode: this.selectionMode ?? 'none',
|
|
160
|
+
pressed: this.valueFor(row),
|
|
161
|
+
shown: this.reachable.map((one) => this.valueFor(one)),
|
|
162
|
+
toggle,
|
|
163
|
+
value: this.value,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
press(row, extend = false, toggle = false) {
|
|
167
|
+
const mode = this.selectionMode;
|
|
168
|
+
if (mode === undefined || mode === 'none' || row.disabled) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const next = choiceValue(this.choice(row, extend, toggle, false));
|
|
172
|
+
if (!extend) {
|
|
173
|
+
this.anchor = this.valueFor(row);
|
|
174
|
+
}
|
|
175
|
+
this.choose(next);
|
|
176
|
+
}
|
|
177
|
+
arrive(row, from) {
|
|
178
|
+
const moving = this.moving;
|
|
179
|
+
if (!moving || this.selectionMode === undefined || this.selectionMode === 'none') {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (moving.extend && this.anchor === undefined && from) {
|
|
183
|
+
this.anchor = this.valueFor(from);
|
|
184
|
+
}
|
|
185
|
+
const next = choiceValue(this.choice(row, moving.extend, moving.toggle, true));
|
|
186
|
+
if (!moving.extend && next !== null) {
|
|
187
|
+
this.anchor = this.valueFor(row);
|
|
188
|
+
}
|
|
189
|
+
this.choose(next);
|
|
190
|
+
}
|
|
139
191
|
act(row) {
|
|
140
192
|
if (row.disabled) {
|
|
141
193
|
return;
|
|
@@ -160,12 +212,14 @@ let HelixHeadlessList = class HelixHeadlessList extends HelixElement {
|
|
|
160
212
|
}
|
|
161
213
|
connectedCallback() {
|
|
162
214
|
super.connectedCallback();
|
|
215
|
+
this.addEventListener('keydown', this.handleKeyCapture, true);
|
|
163
216
|
this.addEventListener('keydown', this.handleKeydown);
|
|
164
217
|
this.addEventListener('click', this.handleClick);
|
|
165
218
|
this.addEventListener('focusin', this.handleFocusin);
|
|
166
219
|
}
|
|
167
220
|
disconnectedCallback() {
|
|
168
221
|
super.disconnectedCallback();
|
|
222
|
+
this.removeEventListener('keydown', this.handleKeyCapture, true);
|
|
169
223
|
this.removeEventListener('keydown', this.handleKeydown);
|
|
170
224
|
this.removeEventListener('click', this.handleClick);
|
|
171
225
|
this.removeEventListener('focusin', this.handleFocusin);
|
|
@@ -202,6 +256,9 @@ __decorate([
|
|
|
202
256
|
__decorate([
|
|
203
257
|
property({ type: Boolean })
|
|
204
258
|
], HelixHeadlessList.prototype, "reversed", void 0);
|
|
259
|
+
__decorate([
|
|
260
|
+
property({ attribute: 'selection-behavior' })
|
|
261
|
+
], HelixHeadlessList.prototype, "selectionBehavior", void 0);
|
|
205
262
|
__decorate([
|
|
206
263
|
property({ attribute: 'selection-mode' })
|
|
207
264
|
], HelixHeadlessList.prototype, "selectionMode", void 0);
|
package/dist/list/selection.d.ts
CHANGED
|
@@ -1,13 +1,43 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { type SelectionMode } from '@fusion.dev/helix-core';
|
|
2
|
+
/** How many rows a reader can select in an interactive list: core's `SelectionMode`. */
|
|
3
|
+
export type ListSelectionMode = SelectionMode;
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
+
* What a press does to the rows already selected: `toggle` adds or takes out
|
|
6
|
+
* the row, and `replace` selects it alone, as a file list does.
|
|
7
|
+
*/
|
|
8
|
+
export type ListSelectionBehavior = 'replace' | 'toggle';
|
|
9
|
+
/** A press on a row, or a key arriving on one, and what the list held then. */
|
|
10
|
+
export interface ListChoice {
|
|
11
|
+
/** The list's `selection-mode`. */
|
|
12
|
+
mode: ListSelectionMode;
|
|
13
|
+
/** The list's `selection-behavior`. */
|
|
14
|
+
behavior: ListSelectionBehavior;
|
|
15
|
+
/** The list's `value`, before the press. */
|
|
16
|
+
value: string;
|
|
17
|
+
/** The value of the row pressed or arrived on. */
|
|
18
|
+
pressed: string;
|
|
19
|
+
/** The values of the rows a reader can reach, in order. */
|
|
20
|
+
shown: readonly string[];
|
|
21
|
+
/** The value of the row a range runs from, where there is one. */
|
|
22
|
+
anchor?: string | undefined;
|
|
23
|
+
/** Whether Shift was held, which takes in the rows from the anchor. */
|
|
24
|
+
extend?: boolean;
|
|
25
|
+
/** Whether Control or Command was held, which toggles under `replace` and moves without choosing. */
|
|
26
|
+
toggle?: boolean;
|
|
27
|
+
/** Whether a key moved focus onto the row, where a press is false. */
|
|
28
|
+
arrived?: boolean;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The `value` a press or an arrival leaves, or `null` where it changes nothing.
|
|
5
32
|
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
33
|
+
* - With Shift, in a list that selects many, every row from the anchor to this
|
|
34
|
+
* one is added, as Data Table and Listbox add a range.
|
|
35
|
+
* - Under `replace`, the row is selected alone, by a press or by a key moving
|
|
36
|
+
* onto it. Control or Command toggles it under a press, and moves without
|
|
37
|
+
* choosing under a key.
|
|
38
|
+
* - Under `toggle`, a press adds or takes out the row, and a key only moves.
|
|
9
39
|
*/
|
|
10
|
-
export declare const
|
|
40
|
+
export declare const choiceValue: ({ anchor, arrived, behavior, extend, mode, pressed, shown, toggle, value, }: ListChoice) => string | null;
|
|
11
41
|
/**
|
|
12
42
|
* Where Left or Right goes inside a row: `at` is the row's place among its
|
|
13
43
|
* `count` stops, the cell first and its controls after it, and `step` is the
|
package/dist/list/selection.js
CHANGED
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
import { commaList,
|
|
2
|
-
export const
|
|
1
|
+
import { commaList, pressedValue, rangeAdd } from '@fusion.dev/helix-core';
|
|
2
|
+
export const choiceValue = ({ anchor, arrived = false, behavior, extend = false, mode, pressed, shown, toggle = false, value, }) => {
|
|
3
|
+
if (mode === 'none') {
|
|
4
|
+
return null;
|
|
5
|
+
}
|
|
3
6
|
const now = commaList(value);
|
|
4
|
-
if (mode === '
|
|
5
|
-
|
|
7
|
+
if (extend && mode === 'multiple') {
|
|
8
|
+
const from = anchor === undefined ? -1 : shown.indexOf(anchor);
|
|
9
|
+
const range = rangeAdd(now, shown, from, shown.indexOf(pressed));
|
|
10
|
+
return range ? range.join(', ') : null;
|
|
11
|
+
}
|
|
12
|
+
if (behavior === 'replace' && !toggle) {
|
|
13
|
+
return now.length === 1 && now[0] === pressed ? null : pressed;
|
|
6
14
|
}
|
|
7
|
-
if (
|
|
8
|
-
return
|
|
15
|
+
if (arrived) {
|
|
16
|
+
return null;
|
|
9
17
|
}
|
|
10
|
-
|
|
18
|
+
const next = pressedValue(mode, value, pressed);
|
|
19
|
+
return next === value ? null : next;
|
|
11
20
|
};
|
|
12
21
|
export const rowStop = (count, at, step) => {
|
|
13
22
|
if (count <= 1) {
|
|
@@ -44,18 +44,22 @@ declare const HelixHeadlessListbox_base: (new (...args: any[]) => import("@fusio
|
|
|
44
44
|
*
|
|
45
45
|
* @slot - The options, and any groups of them.
|
|
46
46
|
* @slot empty - What the list shows when it has no options to show, for content richer than `empty-text`.
|
|
47
|
+
* @slot error - What the list shows while `load-error` is set, for content richer than its text.
|
|
47
48
|
* @slot feedback - The message that says what is wrong, for content richer than a string. It shows while there is a message.
|
|
48
49
|
* @slot filter-icon - The icon in the filter field. Defaults to a magnifying glass.
|
|
49
50
|
* @slot hint - The hint, for content richer than plain text.
|
|
50
51
|
* @slot label - The label, for content richer than plain text.
|
|
51
52
|
* @slot loading - What the list shows while its options load, for content richer than `loading-text`.
|
|
53
|
+
* @slot no-results - What the list shows when a filter hides every option, for content richer than `no-results-text`.
|
|
52
54
|
*
|
|
53
55
|
* @event {Event} change - Fired after the value changes.
|
|
54
56
|
* @event {HelixBeforeChangeEvent} helix-before-change - Fired when the value is about to change, and cancelable.
|
|
55
57
|
* @event {HelixFilterEvent} helix-filter - Fired before the list is filtered, and cancelable.
|
|
58
|
+
* @event {HelixLoadMoreEvent} helix-load-more - Fired once the list is scrolled within a screen of its end, once for each number of options, and not while `loading` is set. Add the next page of options and set `loading` while you fetch it.
|
|
56
59
|
* @event {Event} input - Fired after the value changes.
|
|
57
60
|
*
|
|
58
|
-
* @csspart empty - The text shown when the filter hides every
|
|
61
|
+
* @csspart empty - The text shown when the list has no options to show, or the filter hides every one. `:state(no-results)` is set for the second.
|
|
62
|
+
* @csspart error - The text shown while `load-error` is set.
|
|
59
63
|
* @csspart feedback - The message that says what is wrong with the value.
|
|
60
64
|
* @csspart filter-icon - The icon beside the filter field.
|
|
61
65
|
* @csspart filter-mark - The default icon beside the filter field, shown when none is slotted.
|
|
@@ -68,8 +72,10 @@ declare const HelixHeadlessListbox_base: (new (...args: any[]) => import("@fusio
|
|
|
68
72
|
* @csspart search-field - The filter field.
|
|
69
73
|
*
|
|
70
74
|
* @cssstate empty - The list has no options to show: none were given, or the filter hid every one.
|
|
75
|
+
* @cssstate error - While `load-error` is set.
|
|
71
76
|
* @cssstate invalid - The control has an error to show, from the browser's validation or from your `feedback`.
|
|
72
77
|
* @cssstate loading - While `loading` is set.
|
|
78
|
+
* @cssstate no-results - A filter hid every option of a list that has some.
|
|
73
79
|
*/
|
|
74
80
|
export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
75
81
|
protected readonly aria: AriaForwardController;
|
|
@@ -130,6 +136,14 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
130
136
|
* Placeholder text for the filter field.
|
|
131
137
|
*/
|
|
132
138
|
filterLabel: string;
|
|
139
|
+
/**
|
|
140
|
+
* What the list says when its options could not be loaded, such as after a
|
|
141
|
+
* request to a server fails. Empty is no error.
|
|
142
|
+
*
|
|
143
|
+
* Set, it shows under any options there are, in place of `empty-text` and
|
|
144
|
+
* `loading-text`, and a screen reader hears it. Clear it when you ask again.
|
|
145
|
+
*/
|
|
146
|
+
loadError: string;
|
|
133
147
|
/**
|
|
134
148
|
* Stops the arrow keys from choosing each option they move to. Enter, Space
|
|
135
149
|
* or a click chooses the highlighted option.
|
|
@@ -143,6 +157,13 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
143
157
|
* Whether more than one option can be chosen.
|
|
144
158
|
*/
|
|
145
159
|
multiple: boolean;
|
|
160
|
+
/**
|
|
161
|
+
* The text shown when a filter hides every option of a list that has some.
|
|
162
|
+
*
|
|
163
|
+
* Absent, the list says `empty-text` in both cases. Set it to tell "nothing
|
|
164
|
+
* matches what you typed" from "there is nothing here".
|
|
165
|
+
*/
|
|
166
|
+
noResultsText?: string;
|
|
146
167
|
/**
|
|
147
168
|
* What a screen reader hears when a filter leaves one option. `{count}` is
|
|
148
169
|
* the count.
|
|
@@ -430,6 +451,14 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
430
451
|
private takeFilter;
|
|
431
452
|
/** Filters at once on a filter still waiting out `filterDelay`. */
|
|
432
453
|
private flushFilter;
|
|
454
|
+
/** The number of options the list last asked for more at. */
|
|
455
|
+
private askedAt;
|
|
456
|
+
/**
|
|
457
|
+
* Asks for more once the reader is within a screen of the end, React Aria's
|
|
458
|
+
* `onLoadMore`: once for each number of options, so a scroll that goes on
|
|
459
|
+
* asks again only after the next page arrived, and never while loading.
|
|
460
|
+
*/
|
|
461
|
+
private readonly handleScroll;
|
|
433
462
|
/** Requests a new filter, and returns whether the request went through. */
|
|
434
463
|
requestFilter(next: string): boolean;
|
|
435
464
|
/**
|
|
@@ -485,6 +514,13 @@ export declare class HelixHeadlessListbox extends HelixHeadlessListbox_base {
|
|
|
485
514
|
* the live region still says it.
|
|
486
515
|
*/
|
|
487
516
|
protected renderStatus(hasContent: boolean): TemplateResult | typeof nothing;
|
|
517
|
+
/**
|
|
518
|
+
* Whether a filter hid every option of a list that has some, which is a
|
|
519
|
+
* different thing to say from a list that has none.
|
|
520
|
+
*/
|
|
521
|
+
private get noResults();
|
|
522
|
+
/** The error, or what a filter that hid everything says, before the shared words. */
|
|
523
|
+
protected renderLive(hasContent: boolean): TemplateResult;
|
|
488
524
|
protected render(): TemplateResult;
|
|
489
525
|
}
|
|
490
526
|
declare global {
|