@fusion.dev/helix-headless 0.150.0 → 0.152.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 +1388 -93
- package/dist/app-header/root/app-header-root.d.ts +75 -0
- package/dist/app-header/root/app-header-root.js +140 -5
- package/dist/area-chart/root/area-chart-root.d.ts +36 -0
- package/dist/area-chart/root/area-chart-root.js +17 -2
- package/dist/bar-chart/root/bar-chart-root.d.ts +28 -4
- package/dist/bar-chart/root/bar-chart-root.js +17 -4
- package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +11 -2
- package/dist/breadcrumbs/breadcrumb/breadcrumb.js +11 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +14 -2
- package/dist/breadcrumbs/root/breadcrumbs-root.js +16 -3
- package/dist/callout/root/callout-root.d.ts +20 -0
- package/dist/callout/root/callout-root.js +19 -4
- package/dist/chat/composer/chat-composer.d.ts +30 -0
- package/dist/chat/composer/chat-composer.js +47 -2
- package/dist/chat/root/chat-root.d.ts +10 -0
- package/dist/chat/root/chat-root.js +14 -0
- package/dist/data-table/root/data-table-root.d.ts +34 -2
- package/dist/data-table/root/data-table-root.js +63 -2
- package/dist/dialog/description.d.ts +10 -0
- package/dist/dialog/description.js +22 -8
- package/dist/dialog/root/dialog-root.d.ts +17 -1
- package/dist/dialog/root/dialog-root.js +2 -2
- package/dist/divider/root/divider-root.d.ts +8 -6
- package/dist/divider/root/divider-root.js +10 -2
- package/dist/drawer/root/drawer-root.d.ts +38 -2
- package/dist/drawer/root/drawer-root.js +33 -6
- package/dist/element-events.generated.js +4 -0
- package/dist/kbd/root/kbd-root.d.ts +7 -1
- package/dist/kbd/root/kbd-root.js +8 -4
- package/dist/lightbox/root/lightbox-root.d.ts +44 -6
- package/dist/lightbox/root/lightbox-root.js +59 -11
- package/dist/lightbox/zoom-controller.d.ts +5 -0
- package/dist/lightbox/zoom-controller.js +8 -0
- package/dist/line-chart/root/line-chart-root.d.ts +36 -0
- package/dist/line-chart/root/line-chart-root.js +15 -2
- package/dist/menu/root/menu-root.js +2 -0
- package/dist/navigation/root/navigation-root.d.ts +11 -1
- package/dist/navigation/root/navigation-root.js +10 -5
- package/dist/notifications/root/notifications-root.d.ts +17 -0
- package/dist/notifications/root/notifications-root.js +21 -1
- package/dist/popover/root/popover-root.d.ts +18 -7
- package/dist/popover/root/popover-root.js +8 -1
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +18 -0
- package/dist/scatter-chart/root/scatter-chart-root.js +38 -15
- package/dist/splitter/root/splitter-root.d.ts +41 -0
- package/dist/splitter/root/splitter-root.js +77 -0
- package/dist/table/column/table-column.js +3 -2
- package/dist/table/grid-controller.d.ts +14 -2
- package/dist/table/grid-controller.js +27 -1
- package/dist/table/root/table-root.d.ts +30 -4
- package/dist/table/root/table-root.js +45 -7
- package/dist/table/row/table-row.d.ts +12 -2
- package/dist/table/row/table-row.js +8 -2
- package/dist/tabs/root/tabs-root.d.ts +25 -0
- package/dist/tabs/root/tabs-root.js +28 -1
- package/dist/tour/naming.d.ts +9 -3
- package/dist/tour/naming.js +9 -3
- package/dist/tour/root/tour-root.d.ts +29 -5
- package/dist/tour/root/tour-root.js +13 -1
- package/dist/tour/stop/tour-stop.d.ts +2 -1
- package/dist/tour/stop/tour-stop.js +4 -1
- package/dist/tree/root/tree-root.d.ts +13 -0
- package/dist/tree/root/tree-root.js +42 -2
- package/dist/video/root/video-root.d.ts +6 -0
- package/dist/video/root/video-root.js +5 -1
- package/dist/video-playlist/root/video-playlist-root.d.ts +4 -0
- package/dist/video-playlist/root/video-playlist-root.js +4 -1
- package/dist/virtual-list/root/virtual-list-root.d.ts +23 -1
- package/dist/virtual-list/root/virtual-list-root.js +21 -2
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +1098 -128
- package/types/vue.d.ts +248 -59
- package/types/words.d.ts +12 -2
|
@@ -41,6 +41,11 @@ export declare class ZoomController implements ReactiveController {
|
|
|
41
41
|
hostDisconnected(): void;
|
|
42
42
|
/** Zooms to `scale` about the middle of the box, held to the range. */
|
|
43
43
|
zoomTo(scale: number, at?: Offset): void;
|
|
44
|
+
/**
|
|
45
|
+
* Moves a zoomed item by `by`, in pixels, never so far that an edge comes
|
|
46
|
+
* inside the box. Returns whether it moved.
|
|
47
|
+
*/
|
|
48
|
+
panBy(by: Offset): boolean;
|
|
44
49
|
/** Back to the item at its own size, in the middle. */
|
|
45
50
|
reset(): void;
|
|
46
51
|
private set;
|
|
@@ -79,6 +79,14 @@ export class ZoomController {
|
|
|
79
79
|
const next = clampScale(scale, this.options.max());
|
|
80
80
|
this.set(next, zoomAt(at, this.scale, next, this.pan));
|
|
81
81
|
}
|
|
82
|
+
panBy(by) {
|
|
83
|
+
if (this.scale <= 1) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
const before = this.pan;
|
|
87
|
+
this.set(this.scale, { x: before.x + by.x, y: before.y + by.y });
|
|
88
|
+
return this.pan.x !== before.x || this.pan.y !== before.y;
|
|
89
|
+
}
|
|
82
90
|
reset() {
|
|
83
91
|
if (this.scale !== 1 || this.pan.x !== 0 || this.pan.y !== 0) {
|
|
84
92
|
this.set(1, { x: 0, y: 0 });
|
|
@@ -27,6 +27,9 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
27
27
|
* `<svg>` that fills its box scales with the box, so the same `font-size` can
|
|
28
28
|
* render at 10px in a narrow chart and 43px in a wide one.
|
|
29
29
|
*
|
|
30
|
+
* `value-axis` draws the scale's numbers beside the plot, at the levels
|
|
31
|
+
* `gridlines` rules, written in `locale`.
|
|
32
|
+
*
|
|
30
33
|
* The table is the accessible representation, and the drawing is hidden from
|
|
31
34
|
* screen readers, who get the numbers. The `summary` part names the chart, from
|
|
32
35
|
* `label` or the table's caption, and gives each series' latest reading.
|
|
@@ -37,13 +40,22 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
37
40
|
* a reading. The tooltip follows, the `live` part says the reading in words,
|
|
38
41
|
* and Escape puts the tooltip away.
|
|
39
42
|
*
|
|
43
|
+
* **A tap shows the reading under it**, and keeps it until a tap lands
|
|
44
|
+
* elsewhere. `helix-reading-change` says each move of the reading, by pointer,
|
|
45
|
+
* tap or key, and `helix-reading-press` says a reading was clicked, tapped, or
|
|
46
|
+
* pressed with Enter or Space, for a page that opens what a reading stands for.
|
|
47
|
+
*
|
|
40
48
|
* @since 0.1.0
|
|
41
49
|
* @status stable
|
|
42
50
|
* @category charts
|
|
43
51
|
* @aliases Time Series, Trend Chart, Multi-line Chart
|
|
44
52
|
* @documentation https://fusion.dev/helix/components/line-chart
|
|
45
53
|
*
|
|
54
|
+
* @event {HelixReadingChangeEvent} helix-reading-change - The reading shown moved, or was put away: `index` is the row, or `-1` for none, with its `label`, the `series` the keys rest on, and the `pointerType` that moved it.
|
|
55
|
+
* @event {HelixReadingPressEvent} helix-reading-press - A reading was clicked, tapped, or pressed with Enter or Space, with the same detail as `helix-reading-change`.
|
|
56
|
+
*
|
|
46
57
|
* @csspart area - The wash under one line, where `area` is set.
|
|
58
|
+
* @csspart axis - The numbers of the scale beside the plot, under `value-axis`.
|
|
47
59
|
* @csspart band - The band around the reading under the pointer.
|
|
48
60
|
* @csspart baseline - The rule at zero, where zero is inside the range.
|
|
49
61
|
* @csspart gridline - One rule across the plot, under `gridlines`.
|
|
@@ -60,6 +72,7 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
60
72
|
* @csspart summary - The chart's name and each series' latest reading, written as a sentence for screen readers. Hide it visually.
|
|
61
73
|
* @csspart svg - The drawing surface the lines and areas sit on.
|
|
62
74
|
* @csspart terminus - The mark on one series' last reading.
|
|
75
|
+
* @csspart tick - One number on the axis, placed with `inset-block-start` at its level.
|
|
63
76
|
* @csspart tooltip - The bubble, forwarded from `Tooltip`.
|
|
64
77
|
* @csspart tooltip-anchor - The `Tooltip` element itself.
|
|
65
78
|
* @csspart tooltip-arrow - The bubble's point, forwarded from `Tooltip`.
|
|
@@ -79,6 +92,7 @@ declare const HelixHeadlessLineChart_base: typeof HelixElement & (new (...args:
|
|
|
79
92
|
*
|
|
80
93
|
* @cssproperty --chart-terminus-x - Where a series' last reading sits horizontally, as a percentage. Written by the component.
|
|
81
94
|
* @cssproperty --chart-terminus-y - Where a series' last reading sits vertically, as a percentage. Written by the component.
|
|
95
|
+
* @cssproperty --line-chart-axis - The width of the axis, in `ch`, set from the widest number on it. Written by the component on the axis.
|
|
82
96
|
*/
|
|
83
97
|
export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base {
|
|
84
98
|
/**
|
|
@@ -86,6 +100,13 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
86
100
|
* `registerWords('de', { 'helix-line-chart': { positionLabel: '{position} von {count}' } })`.
|
|
87
101
|
*/
|
|
88
102
|
static words: string;
|
|
103
|
+
/**
|
|
104
|
+
* Sends the reading's moves and presses as `helix-reading-change` and
|
|
105
|
+
* `helix-reading-press`, which the pointer hears. Here and not in a
|
|
106
|
+
* constructor, where the manifest's analyzer reads the assignment as a
|
|
107
|
+
* member of this class.
|
|
108
|
+
*/
|
|
109
|
+
connectedCallback(): void;
|
|
89
110
|
/**
|
|
90
111
|
* Draws a wash under each line, down to the floor of the plot. The washes
|
|
91
112
|
* overlap and do not add up, so for parts that make a total, use
|
|
@@ -202,6 +223,15 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
202
223
|
* layers; a single `mask-image` would only ever cut the last one.
|
|
203
224
|
*/
|
|
204
225
|
terminus?: 'none' | 'ring' | 'square' | 'triangle';
|
|
226
|
+
/**
|
|
227
|
+
* Draws the scale's numbers beside the plot, the `axis` part, at the levels
|
|
228
|
+
* `gridlines` rules, so a reading can be measured off the drawing as well
|
|
229
|
+
* as read from the tooltip.
|
|
230
|
+
*
|
|
231
|
+
* Absent draws none: a line read for its shape needs no numbers beside it,
|
|
232
|
+
* and the tooltip and the table hold every reading.
|
|
233
|
+
*/
|
|
234
|
+
valueAxis: boolean;
|
|
205
235
|
/** The domain every series is drawn against, which the tooltip also needs. */
|
|
206
236
|
private range;
|
|
207
237
|
/**
|
|
@@ -223,6 +253,12 @@ export declare class HelixHeadlessLineChart extends HelixHeadlessLineChart_base
|
|
|
223
253
|
*/
|
|
224
254
|
private ends;
|
|
225
255
|
protected render(): TemplateResult;
|
|
256
|
+
/**
|
|
257
|
+
* The scale's numbers beside the plot, under `value-axis`, written in the
|
|
258
|
+
* chart's locale. A seam, so a subclass can write the numbers its own way,
|
|
259
|
+
* such as a currency.
|
|
260
|
+
*/
|
|
261
|
+
protected renderAxis(y: (value: number) => number, domain: [number, number]): TemplateResult;
|
|
226
262
|
/**
|
|
227
263
|
* What a reader who cannot see the lines is told: the chart's name and the
|
|
228
264
|
* latest reading of each series.
|
|
@@ -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, commaList, customElement, drawTooltip, extent, HelixElement, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesKey, ticks, unbroken, wordsLocale, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { byRow, CHART_PLOT, commaList, customElement, drawTooltip, drawValueAxis, extent, formatNumbers, HelixElement, HelixReadingChangeEvent, HelixReadingPressEvent, linear, linePath, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesKey, ticks, unbroken, wordsLocale, } 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';
|
|
@@ -14,9 +14,16 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
14
14
|
this.area = false;
|
|
15
15
|
this.dashed = '';
|
|
16
16
|
this.markers = false;
|
|
17
|
+
this.valueAxis = false;
|
|
17
18
|
this.zero = false;
|
|
18
19
|
}
|
|
19
20
|
static { this.words = 'helix-line-chart'; }
|
|
21
|
+
connectedCallback() {
|
|
22
|
+
super.connectedCallback();
|
|
23
|
+
this.pointer.onReading = (heard, detail) => this.dispatchEvent(heard === 'press'
|
|
24
|
+
? new HelixReadingPressEvent(detail)
|
|
25
|
+
: new HelixReadingChangeEvent(detail));
|
|
26
|
+
}
|
|
20
27
|
get rulesValue() {
|
|
21
28
|
return this.gridlines !== undefined && this.gridlines !== 'category';
|
|
22
29
|
}
|
|
@@ -58,7 +65,10 @@ let HelixHeadlessLineChart = class HelixHeadlessLineChart extends MixinChartSour
|
|
|
58
65
|
const y = linear(domain, [PLOT_HEIGHT, 0]);
|
|
59
66
|
const slot = PLOT_WIDTH / readings.length;
|
|
60
67
|
const x = linear([0, Math.max(readings.length - 1, 1)], [slot / 2, PLOT_WIDTH - slot / 2]);
|
|
61
|
-
return html `${this.renderPlot(series, x, y, domain)} ${this.renderLabels(readings)}${this.renderSummary(series)}`;
|
|
68
|
+
return html `${this.valueAxis ? this.renderAxis(y, domain) : nothing}${this.renderPlot(series, x, y, domain)} ${this.renderLabels(readings)}${this.renderSummary(series)}`;
|
|
69
|
+
}
|
|
70
|
+
renderAxis(y, domain) {
|
|
71
|
+
return drawValueAxis(domain, (value) => (y(value) / PLOT_HEIGHT) * 100, formatNumbers(wordsLocale(this)), (widest) => `--line-chart-axis: ${widest}ch`);
|
|
62
72
|
}
|
|
63
73
|
renderSummary(series) {
|
|
64
74
|
const rows = this.sourceRows;
|
|
@@ -254,6 +264,9 @@ __decorate([
|
|
|
254
264
|
__decorate([
|
|
255
265
|
property({ reflect: true })
|
|
256
266
|
], HelixHeadlessLineChart.prototype, "terminus", void 0);
|
|
267
|
+
__decorate([
|
|
268
|
+
property({ attribute: 'value-axis', reflect: true, type: Boolean })
|
|
269
|
+
], HelixHeadlessLineChart.prototype, "valueAxis", void 0);
|
|
257
270
|
__decorate([
|
|
258
271
|
property({ reflect: true, type: Boolean })
|
|
259
272
|
], HelixHeadlessLineChart.prototype, "zero", void 0);
|
|
@@ -19,6 +19,13 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
19
19
|
* one page can mark the section in view with `aria-current="location"`. Where
|
|
20
20
|
* several are marked, `page` wins.
|
|
21
21
|
*
|
|
22
|
+
* **The destinations can be a list.** Slot a `<ul>` or an `<ol>` of `<li>`
|
|
23
|
+
* elements, each holding a link, and a screen reader says how many there are
|
|
24
|
+
* and where each one is, as in Radix's `NavigationMenu.List`. The marker and
|
|
25
|
+
* the arrow keys work on the list items as they do on bare links. Give the
|
|
26
|
+
* list `role="list"` as well, since Safari drops the semantics of a list drawn
|
|
27
|
+
* without bullets.
|
|
28
|
+
*
|
|
22
29
|
* Set `orientation="vertical"` to stack the destinations in a column, for a
|
|
23
30
|
* sidebar.
|
|
24
31
|
*
|
|
@@ -73,7 +80,10 @@ export declare class HelixHeadlessNavigation extends HelixElement {
|
|
|
73
80
|
*/
|
|
74
81
|
orientation?: 'vertical';
|
|
75
82
|
private current;
|
|
76
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* The destinations the consumer slotted, and the items of a slotted list in
|
|
85
|
+
* place of the list.
|
|
86
|
+
*/
|
|
77
87
|
private get items();
|
|
78
88
|
/** Re-measures when the links change or hand over the current page. */
|
|
79
89
|
private watch;
|
|
@@ -8,6 +8,10 @@ import { AriaForwardController, customElement, focusableElements, focusItemOf, H
|
|
|
8
8
|
import { html } from 'lit';
|
|
9
9
|
import { property } from 'lit/decorators.js';
|
|
10
10
|
const FOCUSABLE = 'a[href], button, input, select, textarea, [tabindex]:not([tabindex="-1"])';
|
|
11
|
+
const isList = (element) => element.localName === 'ul' ||
|
|
12
|
+
element.localName === 'ol' ||
|
|
13
|
+
element.getAttribute('role') === 'list';
|
|
14
|
+
const markOf = (item) => item.hasAttribute('aria-current') ? item : item.querySelector('[aria-current]');
|
|
11
15
|
const navigable = (item) => {
|
|
12
16
|
const control = () => item.navigationControl ??
|
|
13
17
|
(item.matches(FOCUSABLE) ? item : focusableElements(item)[0]);
|
|
@@ -26,10 +30,11 @@ let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement
|
|
|
26
30
|
active: () => {
|
|
27
31
|
const items = this.items;
|
|
28
32
|
const marked = (item) => {
|
|
29
|
-
const current = item
|
|
30
|
-
return current !== null && current !== 'false';
|
|
33
|
+
const current = markOf(item)?.getAttribute('aria-current');
|
|
34
|
+
return current !== null && current !== undefined && current !== 'false';
|
|
31
35
|
};
|
|
32
|
-
return (items.find((item) => item
|
|
36
|
+
return (items.find((item) => markOf(item)?.getAttribute('aria-current') === 'page') ??
|
|
37
|
+
items.find(marked));
|
|
33
38
|
},
|
|
34
39
|
indicator: () => this.partNamed('indicator'),
|
|
35
40
|
observe: () => this.items,
|
|
@@ -52,14 +57,14 @@ let HelixHeadlessNavigation = class HelixHeadlessNavigation extends HelixElement
|
|
|
52
57
|
static { this.words = 'helix-navigation'; }
|
|
53
58
|
get items() {
|
|
54
59
|
const slot = this.renderRoot.querySelector('slot:not([name])');
|
|
55
|
-
return (slot?.assignedElements() ?? []);
|
|
60
|
+
return (slot?.assignedElements() ?? []).flatMap((one) => isList(one) ? [...one.children] : [one]);
|
|
56
61
|
}
|
|
57
62
|
watch() {
|
|
58
63
|
this.current?.disconnect();
|
|
59
64
|
this.indicator.place();
|
|
60
65
|
this.current = new MutationObserver(() => this.indicator.place());
|
|
61
66
|
for (const item of this.items) {
|
|
62
|
-
this.current.observe(item, { attributeFilter: ['aria-current'] });
|
|
67
|
+
this.current.observe(item, { attributeFilter: ['aria-current'], subtree: true });
|
|
63
68
|
}
|
|
64
69
|
}
|
|
65
70
|
connectedCallback() {
|
|
@@ -29,6 +29,17 @@ declare const HelixHeadlessNotifications_base: (new (...args: any[]) => import("
|
|
|
29
29
|
* the feed holds one page of a longer list, and each row says its place in the
|
|
30
30
|
* whole of it.
|
|
31
31
|
*
|
|
32
|
+
* **Keyboard.**
|
|
33
|
+
*
|
|
34
|
+
* | Key | What it does |
|
|
35
|
+
* |---|---|
|
|
36
|
+
* | Down, Up | On a row, moves to the next or the previous row. |
|
|
37
|
+
* | Home, End | On a row, moves to the first or the last row. |
|
|
38
|
+
* | Page Down, Page Up | From anywhere in a row, moves to the next or the previous row. |
|
|
39
|
+
* | Control+End | From anywhere in the feed, moves to the first control after it on the page. |
|
|
40
|
+
* | Control+Home | From anywhere in the feed, moves to the nearest control before it on the page. |
|
|
41
|
+
* | Tab | Moves through the controls in a row, and on out of the feed. |
|
|
42
|
+
*
|
|
32
43
|
* **`load-more` adds a button after the list** that sends `helix-load-more`,
|
|
33
44
|
* for a feed that holds one page of a longer list. Append the next page, set
|
|
34
45
|
* `loading` while it is on its way, and take `load-more` off once there is
|
|
@@ -246,6 +257,12 @@ export declare class HelixHeadlessNotifications extends HelixHeadlessNotificatio
|
|
|
246
257
|
* is how the APG feed pattern moves on from inside an article.
|
|
247
258
|
*/
|
|
248
259
|
private readonly handleKeydown;
|
|
260
|
+
/**
|
|
261
|
+
* `Control+End` and `Control+Home`, which leave the feed for the first
|
|
262
|
+
* control after it or the nearest one before it, as the APG feed pattern
|
|
263
|
+
* does. A feed of many rows is otherwise a long walk to get past.
|
|
264
|
+
*/
|
|
265
|
+
private leave;
|
|
249
266
|
/**
|
|
250
267
|
* Tells each row whether it is the stop, and where it sits in the feed.
|
|
251
268
|
*
|
|
@@ -34,7 +34,11 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
|
|
|
34
34
|
}
|
|
35
35
|
};
|
|
36
36
|
this.handleKeydown = (event) => {
|
|
37
|
-
if (event.defaultPrevented || event.altKey || event.
|
|
37
|
+
if (event.defaultPrevented || event.altKey || event.metaKey) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (event.ctrlKey) {
|
|
41
|
+
this.leave(event);
|
|
38
42
|
return;
|
|
39
43
|
}
|
|
40
44
|
const rows = this.reachable;
|
|
@@ -151,6 +155,22 @@ let HelixHeadlessNotifications = class HelixHeadlessNotifications extends MixinC
|
|
|
151
155
|
rowFocused(target) {
|
|
152
156
|
return this.reachable.find((row) => rowBox(row) === target);
|
|
153
157
|
}
|
|
158
|
+
leave(event) {
|
|
159
|
+
if (event.key !== 'End' && event.key !== 'Home') {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
const after = event.key === 'End';
|
|
163
|
+
const outside = focusableElements(document.body).filter((one) => one.tabIndex >= 0 &&
|
|
164
|
+
!deepContains(this, one) &&
|
|
165
|
+
(this.compareDocumentPosition(one) &
|
|
166
|
+
(after ? Node.DOCUMENT_POSITION_FOLLOWING : Node.DOCUMENT_POSITION_PRECEDING)) !==
|
|
167
|
+
0);
|
|
168
|
+
const next = after ? outside[0] : outside.at(-1);
|
|
169
|
+
if (next) {
|
|
170
|
+
event.preventDefault();
|
|
171
|
+
next.focus();
|
|
172
|
+
}
|
|
173
|
+
}
|
|
154
174
|
rove() {
|
|
155
175
|
const rows = this.reachable;
|
|
156
176
|
const stop = rovingStop(rows, this.stopRow);
|
|
@@ -11,9 +11,10 @@ declare const HelixHeadlessPopover_base: (new (...args: any[]) => import("@fusio
|
|
|
11
11
|
*
|
|
12
12
|
* The trigger is slotted and stays your own element. A Helix trigger is told
|
|
13
13
|
* whether the popover is open inside its own shadow root. On a plain element,
|
|
14
|
-
* such as a `<button>`, the popover writes `aria-expanded
|
|
15
|
-
*
|
|
16
|
-
* `aria-expanded` yourself
|
|
14
|
+
* such as a `<button>`, the popover writes `aria-expanded`, from a frame after
|
|
15
|
+
* its own first render, or from the first press where that comes sooner. It
|
|
16
|
+
* never writes it where you wrote `aria-expanded` yourself, and writes nothing
|
|
17
|
+
* else onto your markup.
|
|
17
18
|
*
|
|
18
19
|
* The panel is in the top layer through the popover API, so it needs no
|
|
19
20
|
* `z-index`, and an ancestor with `overflow: hidden`, `transform`, `filter`, or
|
|
@@ -36,6 +37,17 @@ declare const HelixHeadlessPopover_base: (new (...args: any[]) => import("@fusio
|
|
|
36
37
|
*
|
|
37
38
|
* The panel's name is `label` when you set it. Otherwise it is the first
|
|
38
39
|
* heading in the panel, or the elements an `aria-labelledby` on the host names.
|
|
40
|
+
* A development build warns when a popover opens with nothing but
|
|
41
|
+
* `fallback-label` to name it.
|
|
42
|
+
*
|
|
43
|
+
* **Keyboard.** Opening moves focus to the first control in the panel, or to
|
|
44
|
+
* the panel where it holds none.
|
|
45
|
+
*
|
|
46
|
+
* | Key | What it does |
|
|
47
|
+
* |---|---|
|
|
48
|
+
* | Enter, Space | On the trigger, opens the panel, or closes it while it is open. |
|
|
49
|
+
* | Escape | Closes the panel and puts focus back on the trigger. |
|
|
50
|
+
* | Tab, Shift+Tab | Moves through the controls in the panel. Leaving the panel and the trigger closes it. With `modal`, moves from the last control round to the first and from the first round to the last. |
|
|
39
51
|
*
|
|
40
52
|
* `arrow` draws a point on the panel's edge facing the trigger. The side the
|
|
41
53
|
* panel landed on is on the host as `:state(placed-top)` and its kin, and the
|
|
@@ -198,7 +210,7 @@ export declare class HelixHeadlessPopover extends HelixHeadlessPopover_base {
|
|
|
198
210
|
private readonly notePress;
|
|
199
211
|
disconnectedCallback(): void;
|
|
200
212
|
private readonly handleTriggerClick;
|
|
201
|
-
/** Whether
|
|
213
|
+
/** Whether the trigger may be told, from a frame after the first render or a reader's press. */
|
|
202
214
|
private pressed;
|
|
203
215
|
/** The plain trigger this popover writes `aria-expanded` on, once it may. */
|
|
204
216
|
private told;
|
|
@@ -207,9 +219,8 @@ export declare class HelixHeadlessPopover extends HelixHeadlessPopover_base {
|
|
|
207
219
|
*
|
|
208
220
|
* A Helix trigger by property, through `tellDisclosure`. A plain element,
|
|
209
221
|
* which has no shadow root to keep the state out of the markup, by
|
|
210
|
-
* `aria-expanded`,
|
|
211
|
-
*
|
|
212
|
-
* be a hydration mismatch. One that already carries `aria-expanded` is the
|
|
222
|
+
* `aria-expanded`, from a frame after the first render or a reader's first
|
|
223
|
+
* press on, so a closed panel is said to be closed before anyone presses. One that already carries `aria-expanded` is the
|
|
213
224
|
* consumer's to keep, and is left alone.
|
|
214
225
|
*/
|
|
215
226
|
private tellTrigger;
|
|
@@ -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, anchorElement, arrowReach, CommandController, customElement, deepActiveElement, FocusScopeController, HelixElement, headingIn, MixinControllerOpen, OpenPhaseController, PopoverController, reflectElements, sideOf, tellDisclosure, words, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, anchorElement, arrowReach, auditName, CommandController, customElement, deepActiveElement, FocusScopeController, HelixElement, headingIn, MixinControllerOpen, OpenPhaseController, PopoverController, reflectElements, sideOf, tellDisclosure, words, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { html, nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { hideOutside } from '../hide-outside.js';
|
|
@@ -144,6 +144,10 @@ let HelixHeadlessPopover = class HelixHeadlessPopover extends MixinControllerOpe
|
|
|
144
144
|
super.connectedCallback();
|
|
145
145
|
this.addEventListener('focusout', this.handleFocusOut);
|
|
146
146
|
this.addEventListener('click', this.notePress, { capture: true });
|
|
147
|
+
void this.whenSettled.then(() => {
|
|
148
|
+
this.pressed = true;
|
|
149
|
+
this.tellTrigger();
|
|
150
|
+
});
|
|
147
151
|
}
|
|
148
152
|
disconnectedCallback() {
|
|
149
153
|
super.disconnectedCallback();
|
|
@@ -180,6 +184,9 @@ let HelixHeadlessPopover = class HelixHeadlessPopover extends MixinControllerOpe
|
|
|
180
184
|
super.updated(changed);
|
|
181
185
|
this.tellTrigger();
|
|
182
186
|
this.nameByHeading();
|
|
187
|
+
if (changed.has('open') && this.open) {
|
|
188
|
+
auditName(this, () => null, 'Give it a `label`, or a heading in the panel.', () => this.label !== '' || this.namedByHeading || headingIn(this.slotted) != null);
|
|
189
|
+
}
|
|
183
190
|
if (this.settled) {
|
|
184
191
|
this.hideAround();
|
|
185
192
|
}
|
|
@@ -66,12 +66,20 @@ declare const HelixHeadlessScatterChart_base: typeof HelixElement & (new (...arg
|
|
|
66
66
|
* reads in its own direction. The summary and the tooltip bubble follow the
|
|
67
67
|
* page's direction.
|
|
68
68
|
*
|
|
69
|
+
* **A tap shows the reading under it**, and keeps it until a tap lands
|
|
70
|
+
* elsewhere. `helix-reading-change` says each move of the reading, by pointer,
|
|
71
|
+
* tap or key, and `helix-reading-press` says a reading was clicked, tapped, or
|
|
72
|
+
* pressed with Enter or Space, for a page that opens what a reading stands for.
|
|
73
|
+
*
|
|
69
74
|
* @since 0.1.0
|
|
70
75
|
* @status stable
|
|
71
76
|
* @category charts
|
|
72
77
|
* @aliases Scatter Plot, XY Chart, Correlation Chart, Dot Plot
|
|
73
78
|
* @documentation https://fusion.dev/helix/components/scatter-chart
|
|
74
79
|
*
|
|
80
|
+
* @event {HelixReadingChangeEvent} helix-reading-change - The reading shown moved, or was put away: `index` is the row, or `-1` for none, with its `label`, the `series` the keys rest on, and the `pointerType` that moved it.
|
|
81
|
+
* @event {HelixReadingPressEvent} helix-reading-press - A reading was clicked, tapped, or pressed with Enter or Space, with the same detail as `helix-reading-change`.
|
|
82
|
+
*
|
|
75
83
|
* @csspart gridline - One line across the plot, drawn when `gridlines` is set.
|
|
76
84
|
* @csspart live - The readout: a polite live region that says the row the keys moved to. Hide it visually.
|
|
77
85
|
* @csspart mark - The invisible point the tooltip is anchored to.
|
|
@@ -238,6 +246,16 @@ export declare class HelixHeadlessScatterChart extends HelixHeadlessScatterChart
|
|
|
238
246
|
* rest on a point with.
|
|
239
247
|
*/
|
|
240
248
|
private readonly handleMove;
|
|
249
|
+
/**
|
|
250
|
+
* The point a tap lands nearest, within twice a pointer's reach, a finger
|
|
251
|
+
* being broader than a cursor. It stays shown until a tap lands elsewhere.
|
|
252
|
+
*/
|
|
253
|
+
private readonly handleTap;
|
|
254
|
+
/**
|
|
255
|
+
* The drawn point nearest a pointer, within `reach` pixels, `undefined` for
|
|
256
|
+
* none in reach, and `null` with no plot to measure.
|
|
257
|
+
*/
|
|
258
|
+
private pointNear;
|
|
241
259
|
private readonly handleLeave;
|
|
242
260
|
}
|
|
243
261
|
declare global {
|
|
@@ -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, formatWords, HelixElement, isRtl, linear, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, ticks, words, wordsLocale, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { CHART_PLOT, customElement, drawTooltip, extent, formatNumbers, formatWords, HelixElement, HelixReadingChangeEvent, HelixReadingPressEvent, isRtl, linear, MixinChartSource, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, ticks, words, wordsLocale, } 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';
|
|
@@ -47,28 +47,27 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
47
47
|
if (event.pointerType !== 'mouse' && event.pointerType !== 'pen') {
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
50
|
+
const found = this.pointNear(event, REACH);
|
|
51
|
+
if (found === null) {
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
-
const across = event.clientX - box.left;
|
|
55
|
-
const up = event.clientY - box.top;
|
|
56
|
-
let found;
|
|
57
|
-
let best = REACH ** 2;
|
|
58
|
-
for (const point of this.drawn) {
|
|
59
|
-
const distance = ((point.x / PLOT_WIDTH) * box.width - across) ** 2 +
|
|
60
|
-
((point.y / PLOT_HEIGHT) * box.height - up) ** 2;
|
|
61
|
-
if (distance <= best) {
|
|
62
|
-
best = distance;
|
|
63
|
-
found = point;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
54
|
if (found !== this.nearest) {
|
|
67
55
|
this.nearest = found;
|
|
68
56
|
this.pointer.set(found?.row ?? -1);
|
|
69
57
|
this.requestUpdate();
|
|
70
58
|
}
|
|
71
59
|
};
|
|
60
|
+
this.handleTap = (event) => {
|
|
61
|
+
if (event.pointerType !== 'touch') {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const found = this.pointNear(event, REACH * 2);
|
|
65
|
+
if (found) {
|
|
66
|
+
this.nearest = found;
|
|
67
|
+
this.pointer.tapTo(found.row);
|
|
68
|
+
this.requestUpdate();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
72
71
|
this.handleLeave = () => {
|
|
73
72
|
this.nearest = undefined;
|
|
74
73
|
};
|
|
@@ -77,13 +76,18 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
77
76
|
connectedCallback() {
|
|
78
77
|
super.connectedCallback();
|
|
79
78
|
this.pointer.axis = 'none';
|
|
79
|
+
this.pointer.onReading = (heard, detail) => this.dispatchEvent(heard === 'press'
|
|
80
|
+
? new HelixReadingPressEvent(detail)
|
|
81
|
+
: new HelixReadingChangeEvent(detail));
|
|
80
82
|
this.addEventListener('pointermove', this.handleMove);
|
|
81
83
|
this.addEventListener('pointerleave', this.handleLeave);
|
|
84
|
+
this.addEventListener('pointerup', this.handleTap);
|
|
82
85
|
}
|
|
83
86
|
disconnectedCallback() {
|
|
84
87
|
super.disconnectedCallback();
|
|
85
88
|
this.removeEventListener('pointermove', this.handleMove);
|
|
86
89
|
this.removeEventListener('pointerleave', this.handleLeave);
|
|
90
|
+
this.removeEventListener('pointerup', this.handleTap);
|
|
87
91
|
}
|
|
88
92
|
seriesOf(cell) {
|
|
89
93
|
const depth = this.measures.ups.indexOf(cell);
|
|
@@ -253,6 +257,25 @@ let HelixHeadlessScatterChart = class HelixHeadlessScatterChart extends MixinCha
|
|
|
253
257
|
y: `${point.y}%`,
|
|
254
258
|
}, (cell) => this.seriesOf(cell), this.pointer);
|
|
255
259
|
}
|
|
260
|
+
pointNear(event, reach) {
|
|
261
|
+
const box = this.partNamed('plot')?.getBoundingClientRect();
|
|
262
|
+
if (!box || box.width === 0 || box.height === 0) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
const across = event.clientX - box.left;
|
|
266
|
+
const up = event.clientY - box.top;
|
|
267
|
+
let found;
|
|
268
|
+
let best = reach ** 2;
|
|
269
|
+
for (const point of this.drawn) {
|
|
270
|
+
const distance = ((point.x / PLOT_WIDTH) * box.width - across) ** 2 +
|
|
271
|
+
((point.y / PLOT_HEIGHT) * box.height - up) ** 2;
|
|
272
|
+
if (distance <= best) {
|
|
273
|
+
best = distance;
|
|
274
|
+
found = point;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return found;
|
|
278
|
+
}
|
|
256
279
|
};
|
|
257
280
|
__decorate([
|
|
258
281
|
words,
|
|
@@ -30,6 +30,21 @@ import { type PropertyValues, type TemplateResult } from 'lit';
|
|
|
30
30
|
* `collapsed-size` keeps a sliver of the pane visible, such as a tab strip.
|
|
31
31
|
* Collapsing overrides `min` and `max`.
|
|
32
32
|
*
|
|
33
|
+
* Set `primary` to the pane that keeps its size when the splitter's own size
|
|
34
|
+
* changes, such as a sidebar beside a window being resized. The other pane
|
|
35
|
+
* takes all of the change, as Web Awesome's split panel does. Without it,
|
|
36
|
+
* both panes keep their share.
|
|
37
|
+
*
|
|
38
|
+
* **Keyboard.** The divider is one tab stop.
|
|
39
|
+
*
|
|
40
|
+
* | Key | What it does |
|
|
41
|
+
* |---|---|
|
|
42
|
+
* | Left, Right | Moves a side-by-side divider by `step`. On a right-to-left page, Left moves it toward the end. |
|
|
43
|
+
* | Up, Down | Moves a stacked divider by `step`. |
|
|
44
|
+
* | Home, End | Moves the divider to its bounds. |
|
|
45
|
+
* | Enter | Collapses the start pane, and opens it again. |
|
|
46
|
+
* | F6 | Moves focus from one pane to the first control in the other, and from the divider to the start pane. |
|
|
47
|
+
*
|
|
33
48
|
* @since 0.1.0
|
|
34
49
|
* @status stable
|
|
35
50
|
* @category layout
|
|
@@ -191,6 +206,32 @@ export declare class HelixHeadlessSplitter extends HelixElement {
|
|
|
191
206
|
*/
|
|
192
207
|
get position(): number;
|
|
193
208
|
set position(next: number);
|
|
209
|
+
/**
|
|
210
|
+
* The pane that keeps its size when the splitter's own size changes. The
|
|
211
|
+
* other pane takes all of the change. Unset, both keep their share.
|
|
212
|
+
*/
|
|
213
|
+
primary?: 'end' | 'start';
|
|
214
|
+
/** Watches this element's length along its axis while `primary` is set. */
|
|
215
|
+
private lengths;
|
|
216
|
+
/** The length along the axis last seen, in pixels. */
|
|
217
|
+
private length;
|
|
218
|
+
/**
|
|
219
|
+
* Starts or stops watching the length, according to `primary`, and holds
|
|
220
|
+
* the primary pane's size in pixels as the length changes.
|
|
221
|
+
*/
|
|
222
|
+
private watchLength;
|
|
223
|
+
/**
|
|
224
|
+
* Moves the divider so the primary pane keeps the pixels it had, as the
|
|
225
|
+
* splitter's length goes from the one last seen to `length`. Not while a
|
|
226
|
+
* pane is shut or a drag holds the divider.
|
|
227
|
+
*/
|
|
228
|
+
private holdPrimary;
|
|
229
|
+
/**
|
|
230
|
+
* F6, which moves focus between the panes, as the window splitter pattern
|
|
231
|
+
* allows: from the start pane to the end pane, and from the end pane or the
|
|
232
|
+
* divider to the start pane. Only a pane that holds a control takes focus.
|
|
233
|
+
*/
|
|
234
|
+
private readonly handlePaneKeys;
|
|
194
235
|
/**
|
|
195
236
|
* Where a dragged divider snaps, comma separated, as Web Awesome's split
|
|
196
237
|
* panel does: a bare number is a percentage and a length such as `240px` is
|