@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
package/dist/qr-code/export.js
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
export const boxIn = (rect, area, box) => {
|
|
2
|
+
const scale = box / area.width;
|
|
3
|
+
return [
|
|
4
|
+
(rect.left - area.left) * scale,
|
|
5
|
+
(rect.top - area.top) * scale,
|
|
6
|
+
rect.width * scale,
|
|
7
|
+
rect.height * scale,
|
|
8
|
+
];
|
|
9
|
+
};
|
|
10
|
+
export const logoBox = (rect, area, box) => {
|
|
11
|
+
const frame = boxIn(rect, area, box);
|
|
12
|
+
const [x, y, width, height] = frame;
|
|
13
|
+
return x < 0 || y < 0 || x + width > box || y + height > box ? undefined : frame;
|
|
14
|
+
};
|
|
1
15
|
const attribute = (value) => value.replace(/&/g, '&').replace(/"/g, '"').replace(/</g, '<');
|
|
2
16
|
const unit = (value) => String(Math.round(value * 100) / 100);
|
|
3
17
|
const placed = ([x, y, width, height]) => `x="${unit(x)}" y="${unit(y)}" width="${unit(width)}" height="${unit(height)}"`;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The name a code is read by: its `label`, or with none, the word for a code,
|
|
3
|
+
* followed by the value where the value is a web address.
|
|
4
|
+
*
|
|
5
|
+
* **A value that is no web address is never read out.** A code that sets up
|
|
6
|
+
* an authenticator (`otpauth://…?secret=…`) or joins a network
|
|
7
|
+
* (`WIFI:…;P:…;;`) carries a secret in its value, and the value as the name
|
|
8
|
+
* read that secret aloud to anyone in earshot. A web address is what a
|
|
9
|
+
* sighted reader gets by scanning, so it is said after the word.
|
|
10
|
+
*/
|
|
11
|
+
export declare const qrName: (label: string, value: string, word: string) => string;
|
|
@@ -13,9 +13,12 @@ export type QrStyle = 'dots' | 'rounded' | 'square';
|
|
|
13
13
|
* thousand modules, and an element for each would be a thousand nodes for one
|
|
14
14
|
* image.
|
|
15
15
|
*
|
|
16
|
-
* The element has `role="img"` and an accessible name. Set
|
|
17
|
-
* code is for
|
|
18
|
-
*
|
|
16
|
+
* The element has `role="img"` and an accessible name. Set `label` to what
|
|
17
|
+
* the code is for, such as "Open the menu". With no `label`, a code is named
|
|
18
|
+
* by `code-label`, "QR code", followed by its value where the value is a web
|
|
19
|
+
* address, which a URL read aloud makes a destination. Any other value is
|
|
20
|
+
* never read out: a code that sets up an authenticator or joins a network
|
|
21
|
+
* carries a secret in it.
|
|
19
22
|
*
|
|
20
23
|
* The quiet zone of four modules is required by the specification, and a
|
|
21
24
|
* scanner rejects a code cropped to its edge. It is drawn inside the `viewBox`,
|
|
@@ -56,6 +59,11 @@ export type QrStyle = 'dots' | 'rounded' | 'square';
|
|
|
56
59
|
* @cssstate overflow - The value is too long for a code at the correction level, so the fallback shows.
|
|
57
60
|
*/
|
|
58
61
|
export declare class HelixHeadlessQrCode extends HelixElement {
|
|
62
|
+
/**
|
|
63
|
+
* The words a code with no `label` is named by, followed by its value where
|
|
64
|
+
* the value is a web address.
|
|
65
|
+
*/
|
|
66
|
+
codeLabel: string;
|
|
59
67
|
/**
|
|
60
68
|
* The error correction level, which sets how much of the code can be lost
|
|
61
69
|
* and still scan.
|
|
@@ -68,10 +76,13 @@ export declare class HelixHeadlessQrCode extends HelixElement {
|
|
|
68
76
|
*/
|
|
69
77
|
correction?: QrCorrection;
|
|
70
78
|
/**
|
|
71
|
-
* The image's accessible name
|
|
79
|
+
* The image's accessible name: what the code is for, such as "Open the
|
|
80
|
+
* menu".
|
|
72
81
|
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
82
|
+
* Absent names it by `code-label` and, for a web address, the address,
|
|
83
|
+
* which is what a reader who cannot scan it needs. Any other value is left
|
|
84
|
+
* out of the name, since it may hold a secret, such as an authenticator's
|
|
85
|
+
* key or a network's password.
|
|
75
86
|
*/
|
|
76
87
|
label: string;
|
|
77
88
|
/**
|
|
@@ -8,7 +8,8 @@ import { customElement, HelixElement, rgbOf } from '@fusion.dev/helix-core';
|
|
|
8
8
|
import { html, nothing, svg, } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
import { encode } from 'uqr';
|
|
11
|
-
import { qrSvg } from '../export.js';
|
|
11
|
+
import { boxIn, logoBox, qrSvg } from '../export.js';
|
|
12
|
+
import { qrName } from '../name.js';
|
|
12
13
|
const QUIET = 4;
|
|
13
14
|
const pixelsOf = (image) => {
|
|
14
15
|
try {
|
|
@@ -76,6 +77,7 @@ const pathFor = (matrix, style, only = 'all') => {
|
|
|
76
77
|
let HelixHeadlessQrCode = class HelixHeadlessQrCode extends HelixElement {
|
|
77
78
|
constructor() {
|
|
78
79
|
super(...arguments);
|
|
80
|
+
this.codeLabel = 'QR code';
|
|
79
81
|
this.label = '';
|
|
80
82
|
this.value = '';
|
|
81
83
|
this.logo = false;
|
|
@@ -150,15 +152,8 @@ let HelixHeadlessQrCode = class HelixHeadlessQrCode extends HelixElement {
|
|
|
150
152
|
if (!holder || holder.hidden || !mark || area.width === 0) {
|
|
151
153
|
return undefined;
|
|
152
154
|
}
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
(rect.left - area.left) * scale,
|
|
156
|
-
(rect.top - area.top) * scale,
|
|
157
|
-
rect.width * scale,
|
|
158
|
-
rect.height * scale,
|
|
159
|
-
];
|
|
160
|
-
const frame = at(holder.getBoundingClientRect());
|
|
161
|
-
if (frame[0] < 0 || frame[1] < 0 || frame[0] + frame[2] > box || frame[1] + frame[3] > box) {
|
|
155
|
+
const frame = logoBox(holder.getBoundingClientRect(), area, box);
|
|
156
|
+
if (!frame) {
|
|
162
157
|
return undefined;
|
|
163
158
|
}
|
|
164
159
|
const fill = getComputedStyle(holder).backgroundColor;
|
|
@@ -166,7 +161,7 @@ let HelixHeadlessQrCode = class HelixHeadlessQrCode extends HelixElement {
|
|
|
166
161
|
const logo = {
|
|
167
162
|
frame,
|
|
168
163
|
ground: ground ? background : rgbOf(fill),
|
|
169
|
-
mark:
|
|
164
|
+
mark: boxIn(mark.getBoundingClientRect(), area, box),
|
|
170
165
|
};
|
|
171
166
|
if (mark instanceof HTMLImageElement) {
|
|
172
167
|
return { ...logo, href: pixelsOf(mark) };
|
|
@@ -215,7 +210,7 @@ let HelixHeadlessQrCode = class HelixHeadlessQrCode extends HelixElement {
|
|
|
215
210
|
viewBox="0 0 ${box} ${box}"
|
|
216
211
|
xmlns="http://www.w3.org/2000/svg"
|
|
217
212
|
role="img"
|
|
218
|
-
aria-label=${this.label
|
|
213
|
+
aria-label=${qrName(this.label, this.value, this.codeLabel)}
|
|
219
214
|
shape-rendering="crispEdges"
|
|
220
215
|
>
|
|
221
216
|
<path
|
|
@@ -250,6 +245,9 @@ let HelixHeadlessQrCode = class HelixHeadlessQrCode extends HelixElement {
|
|
|
250
245
|
</span>`;
|
|
251
246
|
}
|
|
252
247
|
};
|
|
248
|
+
__decorate([
|
|
249
|
+
property({ attribute: 'code-label' })
|
|
250
|
+
], HelixHeadlessQrCode.prototype, "codeLabel", void 0);
|
|
253
251
|
__decorate([
|
|
254
252
|
property({ attribute: 'correction' })
|
|
255
253
|
], HelixHeadlessQrCode.prototype, "correction", void 0);
|
|
@@ -30,6 +30,21 @@ declare const HelixHeadlessRadioGroup_base: (new (...args: any[]) => import("@fu
|
|
|
30
30
|
* `helix-select`. A native radio sends `input` and `change` in the same task as
|
|
31
31
|
* the click.
|
|
32
32
|
*
|
|
33
|
+
* **Keyboard.** The group is one tab stop: the chosen radio, or the first that
|
|
34
|
+
* can be chosen.
|
|
35
|
+
*
|
|
36
|
+
* | Key | What it does |
|
|
37
|
+
* |---|---|
|
|
38
|
+
* | Right, Down | Chooses the next radio, from the last back to the first. |
|
|
39
|
+
* | Left, Up | Chooses the radio before, from the first round to the last. |
|
|
40
|
+
* | Home, End | Chooses the first or the last radio. |
|
|
41
|
+
* | Space, Enter | Chooses the focused radio. |
|
|
42
|
+
*
|
|
43
|
+
* Left and Right swap on a right-to-left page, and a disabled radio is passed
|
|
44
|
+
* over. Under `readonly` the arrows move focus and choose nothing. The group
|
|
45
|
+
* is a `radiogroup` named by `label`, and each radio is a `role="radio"`
|
|
46
|
+
* button with `aria-checked`.
|
|
47
|
+
*
|
|
33
48
|
* @since 0.1.0
|
|
34
49
|
* @status stable
|
|
35
50
|
* @aliases RadioButtons, Choice group
|
|
@@ -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 { customElement, HelixElement, HostClickController, MixinSelectableItem, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { customElement, HelixElement, HostClickController, MixinSelectableItem, slotFilled, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
let HelixHeadlessRadio = class HelixHeadlessRadio extends MixinSelectableItem(HelixElement) {
|
|
@@ -35,7 +35,7 @@ let HelixHeadlessRadio = class HelixHeadlessRadio extends MixinSelectableItem(He
|
|
|
35
35
|
<span part="box" aria-hidden="true"
|
|
36
36
|
><slot
|
|
37
37
|
name="indicator"
|
|
38
|
-
@slotchange=${(event) => this.toggleState('has-indicator', event.target
|
|
38
|
+
@slotchange=${(event) => this.toggleState('has-indicator', slotFilled(event.target))}
|
|
39
39
|
></slot
|
|
40
40
|
></span>
|
|
41
41
|
<slot name="icon"></slot>
|
|
@@ -18,6 +18,20 @@ declare const HelixHeadlessRating_base: (new (...args: any[]) => import("@fusion
|
|
|
18
18
|
* With `clearable`, pressing the chosen score again, or Backspace or Delete on
|
|
19
19
|
* the marks, takes the rating back to unrated and sends `helix-clear`.
|
|
20
20
|
*
|
|
21
|
+
* **Keyboard.** The marks are one tab stop, on the chosen score or the first.
|
|
22
|
+
*
|
|
23
|
+
* | Key | What it does |
|
|
24
|
+
* |---|---|
|
|
25
|
+
* | Right, Down | Chooses the next score up, and stops at the highest. |
|
|
26
|
+
* | Left, Up | Chooses the next score down, and stops at the lowest. |
|
|
27
|
+
* | Home, End | Chooses the lowest or the highest score. |
|
|
28
|
+
* | Space, Enter | Chooses the focused score, or clears it under `clearable` when it is already chosen. |
|
|
29
|
+
* | Backspace, Delete | Clears the rating, under `clearable`. |
|
|
30
|
+
*
|
|
31
|
+
* Left and Right swap on a right-to-left page. The marks are a `radiogroup`
|
|
32
|
+
* named by `label`, and each score is a `radio` named by `option-label`, such
|
|
33
|
+
* as "3 out of 5". A read-only rating is one `img` named by its score.
|
|
34
|
+
*
|
|
21
35
|
* @since 0.1.0
|
|
22
36
|
* @status stable
|
|
23
37
|
* @category forms
|
|
@@ -172,8 +186,8 @@ export declare class HelixHeadlessRating extends HelixHeadlessRating_base {
|
|
|
172
186
|
* each of its own options. Anything past the first slotted element is
|
|
173
187
|
* ignored.
|
|
174
188
|
*/
|
|
175
|
-
private
|
|
176
|
-
/** Whether `
|
|
189
|
+
private readonly mark;
|
|
190
|
+
/** Whether `mark` has had its first answer from the children. */
|
|
177
191
|
private markRead;
|
|
178
192
|
/**
|
|
179
193
|
* What the pointer is over, which is shown instead of the score while it is.
|
|
@@ -215,18 +229,17 @@ export declare class HelixHeadlessRating extends HelixHeadlessRating_base {
|
|
|
215
229
|
/** The pointer drawing a score, while one is. */
|
|
216
230
|
private dragging;
|
|
217
231
|
/**
|
|
218
|
-
*
|
|
232
|
+
* The shape for one place, or nothing when the stylesheet is drawing it.
|
|
219
233
|
*
|
|
220
|
-
*
|
|
221
|
-
*
|
|
222
|
-
*
|
|
234
|
+
* One copy per place, kept so a render does not remake them: a drag renders
|
|
235
|
+
* on every pointer move, and handing Lit a fresh node each time would swap
|
|
236
|
+
* every mark in the row on every frame of a gesture whose whole point is
|
|
237
|
+
* that only the fill moves.
|
|
223
238
|
*/
|
|
224
|
-
private readonly clones;
|
|
225
|
-
/** The shape for one place, or nothing when the stylesheet is drawing it. */
|
|
226
239
|
private markFor;
|
|
227
240
|
private readonly handleMarkSlot;
|
|
228
241
|
/** The element slotted into `empty-mark`, which the track copies. */
|
|
229
|
-
private
|
|
242
|
+
private readonly empty;
|
|
230
243
|
/**
|
|
231
244
|
* The step under a point on the row, or the nearest one to it.
|
|
232
245
|
*
|
|
@@ -4,10 +4,9 @@ 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, valueAsNumber as asNumber, customElement, fillTemplate, numberAsValue as fromNumber, HelixClearEvent, HelixFormElement, HelixPreviewEvent, KeyboardNavigationController, MixinControllerValue, MixinField, reportRuntime, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, valueAsNumber as asNumber, customElement, fillTemplate, numberAsValue as fromNumber, HelixClearEvent, HelixFormElement, HelixPreviewEvent, KeyboardNavigationController, MixinControllerValue, MixinField, nearest, reportRuntime, SlottedGlyph, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
|
-
import { nearestStep } from '../steps.js';
|
|
11
10
|
let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue(MixinField(HelixFormElement)) {
|
|
12
11
|
constructor() {
|
|
13
12
|
super(...arguments);
|
|
@@ -23,7 +22,7 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
23
22
|
this.aria = new AriaForwardController(this, {
|
|
24
23
|
target: () => this.partNamed('marks'),
|
|
25
24
|
});
|
|
26
|
-
this.
|
|
25
|
+
this.mark = new SlottedGlyph();
|
|
27
26
|
this.markRead = false;
|
|
28
27
|
this.previewing = undefined;
|
|
29
28
|
this.keys = new KeyboardNavigationController(this, {
|
|
@@ -32,19 +31,12 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
32
31
|
wrap: false,
|
|
33
32
|
});
|
|
34
33
|
this.dragging = undefined;
|
|
35
|
-
this.clones = new Map();
|
|
36
34
|
this.handleMarkSlot = (event) => {
|
|
37
35
|
const slot = event.target;
|
|
38
|
-
|
|
39
|
-
this.
|
|
40
|
-
if (slot.name === 'empty-mark') {
|
|
41
|
-
this.emptySource = source;
|
|
42
|
-
}
|
|
43
|
-
else {
|
|
44
|
-
this.markSource = source;
|
|
45
|
-
}
|
|
36
|
+
(slot.name === 'empty-mark' ? this.empty : this.mark).read(slot);
|
|
37
|
+
this.requestUpdate();
|
|
46
38
|
};
|
|
47
|
-
this.
|
|
39
|
+
this.empty = new SlottedGlyph();
|
|
48
40
|
this.handleDragStart = (event) => {
|
|
49
41
|
if (this.isDisabled || this.readOnly || event.button !== 0) {
|
|
50
42
|
return;
|
|
@@ -167,21 +159,11 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
167
159
|
}));
|
|
168
160
|
}
|
|
169
161
|
markFor(layer, index) {
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
return undefined;
|
|
173
|
-
}
|
|
174
|
-
const key = `${layer}:${index}`;
|
|
175
|
-
const held = this.clones.get(key);
|
|
176
|
-
if (held) {
|
|
177
|
-
return held;
|
|
178
|
-
}
|
|
179
|
-
const clone = source.cloneNode(true);
|
|
180
|
-
this.clones.set(key, clone);
|
|
181
|
-
return clone;
|
|
162
|
+
const glyph = layer === 'track' && this.empty.slotted ? this.empty : this.mark;
|
|
163
|
+
return glyph.copyFor(`${layer}:${index}`);
|
|
182
164
|
}
|
|
183
165
|
scoreAt(clientX) {
|
|
184
|
-
let
|
|
166
|
+
let closest;
|
|
185
167
|
let best = Number.POSITIVE_INFINITY;
|
|
186
168
|
for (const option of this.renderRoot?.querySelectorAll('[part="option"]') ?? []) {
|
|
187
169
|
const box = option.getBoundingClientRect();
|
|
@@ -191,10 +173,10 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
191
173
|
const away = clientX < box.left ? box.left - clientX : clientX - box.right;
|
|
192
174
|
if (away < best) {
|
|
193
175
|
best = away;
|
|
194
|
-
|
|
176
|
+
closest = option.dataset.score;
|
|
195
177
|
}
|
|
196
178
|
}
|
|
197
|
-
return
|
|
179
|
+
return closest;
|
|
198
180
|
}
|
|
199
181
|
clearsAt(score) {
|
|
200
182
|
return this.clearable && this.value !== '' && Number(score) === Number(this.value);
|
|
@@ -239,8 +221,8 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
239
221
|
super.willUpdate(changed);
|
|
240
222
|
if (!this.markRead && this.childrenKnown) {
|
|
241
223
|
this.markRead = true;
|
|
242
|
-
this.
|
|
243
|
-
this.
|
|
224
|
+
this.mark.take(this.knownChildren.find((child) => child.slot === 'mark'));
|
|
225
|
+
this.empty.take(this.knownChildren.find((child) => child.slot === 'empty-mark'));
|
|
244
226
|
}
|
|
245
227
|
}
|
|
246
228
|
firstUpdated(changed) {
|
|
@@ -255,7 +237,7 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
255
237
|
if (!answered) {
|
|
256
238
|
return first;
|
|
257
239
|
}
|
|
258
|
-
return
|
|
240
|
+
return nearest(this.steps, this.score) ?? first;
|
|
259
241
|
}
|
|
260
242
|
render() {
|
|
261
243
|
const showing = this.previewing ?? this.score;
|
|
@@ -276,7 +258,7 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
276
258
|
aria-describedby=${this.describedBy ?? nothing}
|
|
277
259
|
aria-invalid=${this.invalidity ?? nothing}
|
|
278
260
|
aria-required=${this.required && !this.readOnly ? 'true' : nothing}
|
|
279
|
-
data-slotted=${this.
|
|
261
|
+
data-slotted=${this.mark.slotted ? '' : nothing}
|
|
280
262
|
style=${`--rating-full: ${Math.floor(showing)}; --rating-part: ${showing - Math.floor(showing)}; --rating-steps: ${this.positions.length}`}
|
|
281
263
|
@pointercancel=${this.handleDragCancel}
|
|
282
264
|
@keydown=${this.handleClearKey}
|
|
@@ -299,7 +281,7 @@ let HelixHeadlessRating = class HelixHeadlessRating extends MixinControllerValue
|
|
|
299
281
|
<span
|
|
300
282
|
part="track"
|
|
301
283
|
aria-hidden="true"
|
|
302
|
-
data-slotted=${this.
|
|
284
|
+
data-slotted=${this.empty.slotted ? '' : nothing}
|
|
303
285
|
>${marksIn('track')}</span
|
|
304
286
|
>
|
|
305
287
|
<span
|
|
@@ -367,15 +349,9 @@ __decorate([
|
|
|
367
349
|
__decorate([
|
|
368
350
|
property({ attribute: 'value-text' })
|
|
369
351
|
], HelixHeadlessRating.prototype, "valueText", void 0);
|
|
370
|
-
__decorate([
|
|
371
|
-
state()
|
|
372
|
-
], HelixHeadlessRating.prototype, "markSource", void 0);
|
|
373
352
|
__decorate([
|
|
374
353
|
state()
|
|
375
354
|
], HelixHeadlessRating.prototype, "previewing", void 0);
|
|
376
|
-
__decorate([
|
|
377
|
-
state()
|
|
378
|
-
], HelixHeadlessRating.prototype, "emptySource", void 0);
|
|
379
355
|
HelixHeadlessRating = __decorate([
|
|
380
356
|
customElement('helix-headless-rating')
|
|
381
357
|
], HelixHeadlessRating);
|
|
@@ -5,6 +5,11 @@ import '../../tooltip/index.js';
|
|
|
5
5
|
export interface ScatterPoint {
|
|
6
6
|
depth: number;
|
|
7
7
|
row: number;
|
|
8
|
+
/**
|
|
9
|
+
* How large the point is drawn under `size-by`, from 0 to 1: the square root
|
|
10
|
+
* of its share of the largest size, so its area follows the measure.
|
|
11
|
+
*/
|
|
12
|
+
weight?: number | undefined;
|
|
8
13
|
x: number;
|
|
9
14
|
y: number;
|
|
10
15
|
}
|
|
@@ -35,6 +40,11 @@ declare const HelixHeadlessScatterChart_base: typeof HelixElement & (new (...arg
|
|
|
35
40
|
* `trend` draws each series' line of best fit, by least squares, across the
|
|
36
41
|
* plot in the series' color.
|
|
37
42
|
*
|
|
43
|
+
* **`size-by` names a third measure, drawn as each point's size**, as a bubble
|
|
44
|
+
* chart does: `size-by="Population"` takes that column out of the series and
|
|
45
|
+
* gives each point an area in proportion to its row's number there. The
|
|
46
|
+
* tooltip and the table still say the number.
|
|
47
|
+
*
|
|
38
48
|
* The summary gives each series' correlation coefficient and its number of
|
|
39
49
|
* points. The table has every number, and the drawing is hidden from screen
|
|
40
50
|
* readers.
|
|
@@ -94,6 +104,7 @@ declare const HelixHeadlessScatterChart_base: typeof HelixElement & (new (...arg
|
|
|
94
104
|
* @csspart y-name - The name of the vertical measure.
|
|
95
105
|
* @csspart y-tick - One labeled value on the vertical axis.
|
|
96
106
|
*
|
|
107
|
+
* @cssproperty --chart-point-weight - How large a point is drawn under `size-by`, from 0 to 1, by area. The component writes it, and the stylesheet that sizes the point reads it.
|
|
97
108
|
* @cssproperty --chart-point-x - A point's horizontal position, as a percentage. The component writes it.
|
|
98
109
|
* @cssproperty --chart-point-y - A point's vertical position, as a percentage from the top. The component writes it.
|
|
99
110
|
* @cssproperty --chart-tick - A tick's position along its axis, as a percentage. The component writes it.
|
|
@@ -116,6 +127,15 @@ export declare class HelixHeadlessScatterChart extends HelixHeadlessScatterChart
|
|
|
116
127
|
* The word the summary uses for a row when it counts them.
|
|
117
128
|
*/
|
|
118
129
|
pointsLabel: string;
|
|
130
|
+
/**
|
|
131
|
+
* The heading of a column whose numbers size the points, such as
|
|
132
|
+
* `Population`, which makes the chart a bubble chart.
|
|
133
|
+
*
|
|
134
|
+
* That column is then a measure and no series: it draws no points of its
|
|
135
|
+
* own, and each point's area follows its row's number in it. Absent, every
|
|
136
|
+
* point is one size.
|
|
137
|
+
*/
|
|
138
|
+
sizeBy: string;
|
|
119
139
|
/**
|
|
120
140
|
* Draws each series' line of best fit across the plot, by least squares, in
|
|
121
141
|
* the series' color: the regression line a reader would otherwise draw by
|
|
@@ -148,6 +168,16 @@ export declare class HelixHeadlessScatterChart extends HelixHeadlessScatterChart
|
|
|
148
168
|
* which is where a reader is told what it is.
|
|
149
169
|
*/
|
|
150
170
|
seriesOf(cell: number): number | undefined;
|
|
171
|
+
/**
|
|
172
|
+
* The numeric columns by what they measure: the first across, the column
|
|
173
|
+
* `size-by` names as the size, and every other one up, as a series.
|
|
174
|
+
*/
|
|
175
|
+
protected get measures(): {
|
|
176
|
+
across: number | undefined;
|
|
177
|
+
size: number | undefined;
|
|
178
|
+
ups: number[];
|
|
179
|
+
};
|
|
180
|
+
showsColumn(cell: number): boolean;
|
|
151
181
|
/** Whether the levels across are ruled. */
|
|
152
182
|
protected get rulesX(): boolean;
|
|
153
183
|
/** Whether the levels up are ruled. */
|
|
@@ -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 { CHART_PLOT, customElement, drawTooltip, extent, formatNumbers, HelixElement, isRtl, linear, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, ticks, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { CHART_PLOT, customElement, drawTooltip, extent, formatNumbers, HelixElement, isRtl, linear, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesKey, ticks, } 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';
|
|
@@ -37,6 +37,7 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
37
37
|
super(...arguments);
|
|
38
38
|
this.correlationLabel = 'correlation';
|
|
39
39
|
this.pointsLabel = 'points';
|
|
40
|
+
this.sizeBy = '';
|
|
40
41
|
this.trend = false;
|
|
41
42
|
this.drawn = [];
|
|
42
43
|
this.nearest = undefined;
|
|
@@ -82,8 +83,20 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
82
83
|
this.removeEventListener('pointerleave', this.handleLeave);
|
|
83
84
|
}
|
|
84
85
|
seriesOf(cell) {
|
|
85
|
-
const depth = this.
|
|
86
|
-
return depth <
|
|
86
|
+
const depth = this.measures.ups.indexOf(cell);
|
|
87
|
+
return depth < 0 ? undefined : seriesIndex(depth);
|
|
88
|
+
}
|
|
89
|
+
get measures() {
|
|
90
|
+
const rows = this.sourceRows;
|
|
91
|
+
const key = seriesKey(this.sizeBy);
|
|
92
|
+
const size = key === ''
|
|
93
|
+
? undefined
|
|
94
|
+
: this.plottedColumns.find((column) => seriesKey(rows.find((row) => row.cells[column])?.cells[column]?.name ?? '') === key);
|
|
95
|
+
const [across, ...ups] = this.plottedColumns.filter((column) => column !== size);
|
|
96
|
+
return { across, size, ups };
|
|
97
|
+
}
|
|
98
|
+
showsColumn(cell) {
|
|
99
|
+
return cell !== this.measures.size && super.showsColumn(cell);
|
|
87
100
|
}
|
|
88
101
|
get rulesX() {
|
|
89
102
|
return this.gridlines !== undefined && this.gridlines !== 'y';
|
|
@@ -93,8 +106,7 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
93
106
|
}
|
|
94
107
|
get field() {
|
|
95
108
|
const rows = this.sourceRows;
|
|
96
|
-
const
|
|
97
|
-
const [across, ...ups] = columns;
|
|
109
|
+
const { across, size, ups } = this.measures;
|
|
98
110
|
const name = (column) => column === undefined ? '' : (rows.find((row) => row.cells[column])?.cells[column]?.name ?? '');
|
|
99
111
|
const pairs = ups.map((column) => rows.flatMap((row, index) => {
|
|
100
112
|
const x = across === undefined ? undefined : row.cells[across]?.value;
|
|
@@ -107,10 +119,22 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
107
119
|
const y = nice(extent(all.length > 0 ? all.map(([, one]) => one) : [0]));
|
|
108
120
|
const along = linear(x, [0, PLOT_WIDTH]);
|
|
109
121
|
const up = linear(y, [PLOT_HEIGHT, 0]);
|
|
122
|
+
const sizes = rows.map((row) => (size === undefined ? undefined : row.cells[size]?.value));
|
|
123
|
+
const largest = Math.max(0, ...sizes.map((one) => one ?? 0));
|
|
124
|
+
const weight = (row) => {
|
|
125
|
+
const one = sizes[row];
|
|
126
|
+
return one === undefined || largest <= 0 ? undefined : Math.sqrt(Math.max(0, one) / largest);
|
|
127
|
+
};
|
|
110
128
|
return {
|
|
111
129
|
pairs: pairs.map((series) => series.map(([one, two]) => [one, two])),
|
|
112
130
|
points: pairs.flatMap((series, depth) => shown[depth]
|
|
113
|
-
? series.map(([one, two, row]) => ({
|
|
131
|
+
? series.map(([one, two, row]) => ({
|
|
132
|
+
depth,
|
|
133
|
+
row,
|
|
134
|
+
weight: weight(row),
|
|
135
|
+
x: along(one),
|
|
136
|
+
y: up(two),
|
|
137
|
+
}))
|
|
114
138
|
: []),
|
|
115
139
|
x,
|
|
116
140
|
xName: name(across),
|
|
@@ -174,7 +198,7 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
174
198
|
data-series=${index}
|
|
175
199
|
?data-active=${point.row === at}
|
|
176
200
|
part="point${point.row === at ? ' point-active' : ''}"
|
|
177
|
-
style=${`--chart-series: var(--chart-series-${index}); --chart-point-x: ${point.x}%; --chart-point-y: ${point.y}
|
|
201
|
+
style=${`--chart-series: var(--chart-series-${index}); --chart-point-x: ${point.x}%; --chart-point-y: ${point.y}%${point.weight === undefined ? '' : `; --chart-point-weight: ${point.weight}`}`}
|
|
178
202
|
></span>`;
|
|
179
203
|
})}
|
|
180
204
|
${this.renderTooltip()}
|
|
@@ -243,6 +267,9 @@ __decorate([
|
|
|
243
267
|
__decorate([
|
|
244
268
|
property({ attribute: 'points-label' })
|
|
245
269
|
], HelixHeadlessScatterChart.prototype, "pointsLabel", void 0);
|
|
270
|
+
__decorate([
|
|
271
|
+
property({ attribute: 'size-by' })
|
|
272
|
+
], HelixHeadlessScatterChart.prototype, "sizeBy", void 0);
|
|
246
273
|
__decorate([
|
|
247
274
|
property({ reflect: true, type: Boolean })
|
|
248
275
|
], HelixHeadlessScatterChart.prototype, "trend", void 0);
|
|
@@ -1,11 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The arithmetic behind the scrollbars a scroll area draws under `scrollbars`.
|
|
3
|
-
*
|
|
4
|
-
* Every length here is along one axis and counted from that axis' start, which
|
|
5
|
-
* is the right-hand edge on a right-to-left page for the horizontal one. The
|
|
6
|
-
* component turns a pointer and a `scrollLeft` into those counts, so nothing
|
|
7
|
-
* below has to know which way the line runs.
|
|
8
|
-
*/
|
|
9
1
|
/** Which scrollbars are drawn, and when. Absent keeps the browser's own. */
|
|
10
2
|
export type Scrollbars = 'always' | 'auto' | 'hover' | 'scroll';
|
|
11
3
|
/** The two axes a scrollbar runs along. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { clamp } from '@fusion.dev/helix-core';
|
|
2
2
|
export const thumbFraction = ({ client, scroll }) => scroll <= 0 ? 1 : clamp(client / scroll, 0, 1);
|
|
3
3
|
export const scrollFraction = ({ client, offset, scroll }) => {
|
|
4
4
|
const room = scroll - client;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/** A box on the screen, in viewport pixels. */
|
|
2
|
+
export interface Box {
|
|
3
|
+
height: number;
|
|
4
|
+
left: number;
|
|
5
|
+
top: number;
|
|
6
|
+
width: number;
|
|
7
|
+
}
|
|
8
|
+
/** What places a list over its trigger. */
|
|
9
|
+
export interface Over {
|
|
10
|
+
/** How far inside the screen's edges the list stays, in pixels. */
|
|
11
|
+
margin: number;
|
|
12
|
+
/** The option to sit on the trigger: its top within the list, and its height. */
|
|
13
|
+
option: {
|
|
14
|
+
height: number;
|
|
15
|
+
top: number;
|
|
16
|
+
};
|
|
17
|
+
/** The list's own size. */
|
|
18
|
+
panel: {
|
|
19
|
+
height: number;
|
|
20
|
+
width: number;
|
|
21
|
+
};
|
|
22
|
+
/** Whether the line of text runs right to left, which aligns the end edges. */
|
|
23
|
+
rtl: boolean;
|
|
24
|
+
/** The trigger. */
|
|
25
|
+
trigger: Box;
|
|
26
|
+
/** The screen. */
|
|
27
|
+
viewport: {
|
|
28
|
+
height: number;
|
|
29
|
+
width: number;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Where a list opened over its trigger goes, so the option it opens on sits
|
|
34
|
+
* where the trigger is: the native select's place on macOS, and Radix's
|
|
35
|
+
* `item-aligned`.
|
|
36
|
+
*
|
|
37
|
+
* The option's middle on the trigger's middle, then kept on the screen: a
|
|
38
|
+
* list that would run off the bottom moves up, and one that would run off the
|
|
39
|
+
* top moves down, so near an edge the option is beside the trigger rather than
|
|
40
|
+
* on it. A list taller than the screen starts at its top edge. The start edges
|
|
41
|
+
* line up, the left in English and the right in Arabic, kept on the screen the
|
|
42
|
+
* same way.
|
|
43
|
+
*/
|
|
44
|
+
export declare const over: ({ margin, option, panel, rtl, trigger, viewport, }: Over) => {
|
|
45
|
+
left: number;
|
|
46
|
+
top: number;
|
|
47
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export const over = ({ margin, option, panel, rtl, trigger, viewport, }) => {
|
|
2
|
+
const centered = trigger.top + trigger.height / 2 - (option.top + option.height / 2);
|
|
3
|
+
const top = Math.max(margin, Math.min(centered, viewport.height - margin - panel.height));
|
|
4
|
+
const start = rtl ? trigger.left + trigger.width - panel.width : trigger.left;
|
|
5
|
+
const left = Math.max(margin, Math.min(start, viewport.width - margin - panel.width));
|
|
6
|
+
return { left: Math.round(left), top: Math.round(top) };
|
|
7
|
+
};
|