@fusion.dev/helix-core 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 +5203 -1777
- package/dist/controllers/aria-forward-controller/aria-forward-controller.d.ts +3 -2
- package/dist/controllers/aria-forward-controller/aria-forward-controller.js +3 -14
- package/dist/controllers/chart-pointer-controller/chart-pointer-controller.d.ts +65 -3
- package/dist/controllers/chart-pointer-controller/chart-pointer-controller.js +37 -9
- package/dist/controllers/chart-pointer-controller/reading-step.d.ts +7 -1
- package/dist/controllers/chart-pointer-controller/reading-step.js +5 -0
- package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.d.ts +9 -55
- package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.js +7 -39
- package/dist/controllers/relative-clock-controller/relative-clock-controller.d.ts +44 -0
- package/dist/controllers/relative-clock-controller/relative-clock-controller.js +31 -0
- package/dist/controllers/source-controller/source-controller.d.ts +10 -3
- package/dist/controllers/source-controller/source-controller.js +7 -4
- package/dist/controllers/virtualize-controller/virtualize-controller.d.ts +48 -1
- package/dist/controllers/virtualize-controller/virtualize-controller.js +50 -7
- package/dist/events/action.d.ts +12 -0
- package/dist/events/action.js +6 -0
- package/dist/events/activate.d.ts +22 -0
- package/dist/events/activate.js +11 -0
- package/dist/events/aura-fallback.d.ts +12 -0
- package/dist/events/aura-fallback.js +11 -0
- package/dist/events/before-activate.d.ts +24 -0
- package/dist/events/before-activate.js +11 -0
- package/dist/events/before-change.d.ts +26 -0
- package/dist/events/before-change.js +11 -0
- package/dist/events/before-close.d.ts +6 -0
- package/dist/events/before-close.js +11 -0
- package/dist/events/before-collapse.d.ts +6 -0
- package/dist/events/before-collapse.js +11 -0
- package/dist/events/before-edit.d.ts +6 -0
- package/dist/events/before-edit.js +11 -0
- package/dist/events/before-move.d.ts +17 -0
- package/dist/events/before-move.js +11 -0
- package/dist/events/before-open.d.ts +17 -0
- package/dist/events/before-open.js +11 -0
- package/dist/events/before-panel-resize.d.ts +13 -0
- package/dist/events/before-panel-resize.js +11 -0
- package/dist/events/before-pin.d.ts +6 -0
- package/dist/events/before-pin.js +11 -0
- package/dist/events/before-reconnect.d.ts +14 -0
- package/dist/events/before-reconnect.js +11 -0
- package/dist/events/before-relabel.d.ts +15 -0
- package/dist/events/before-relabel.js +11 -0
- package/dist/events/before-resize.d.ts +6 -0
- package/dist/events/before-resize.js +11 -0
- package/dist/events/before-split.d.ts +12 -0
- package/dist/events/before-split.js +11 -0
- package/dist/events/before-toggle.d.ts +23 -0
- package/dist/events/before-toggle.js +11 -0
- package/dist/events/canvas-edit.d.ts +16 -0
- package/dist/events/canvas-edit.js +11 -0
- package/dist/events/canvas-pan.d.ts +13 -0
- package/dist/events/canvas-pan.js +11 -0
- package/dist/events/canvas-view.d.ts +14 -0
- package/dist/events/canvas-view.js +11 -0
- package/dist/events/canvas-zoom.d.ts +6 -0
- package/dist/events/canvas-zoom.js +11 -0
- package/dist/events/caret.d.ts +17 -0
- package/dist/events/caret.js +11 -0
- package/dist/events/clear.d.ts +11 -0
- package/dist/events/clear.js +6 -0
- package/dist/events/collapse.d.ts +12 -0
- package/dist/events/collapse.js +11 -0
- package/dist/events/complete.d.ts +26 -0
- package/dist/events/complete.js +11 -0
- package/dist/events/connect.d.ts +14 -0
- package/dist/events/connect.js +11 -0
- package/dist/events/console.d.ts +13 -0
- package/dist/events/console.js +11 -0
- package/dist/events/copy-error.d.ts +9 -0
- package/dist/events/copy-error.js +6 -0
- package/dist/events/copy.d.ts +12 -0
- package/dist/events/copy.js +10 -0
- package/dist/events/create.d.ts +18 -0
- package/dist/events/create.js +11 -0
- package/dist/events/details.d.ts +454 -0
- package/dist/events/details.js +1 -0
- package/dist/events/dismiss.d.ts +16 -0
- package/dist/events/dismiss.js +11 -0
- package/dist/events/edit.d.ts +12 -0
- package/dist/events/edit.js +11 -0
- package/dist/events/end.d.ts +9 -0
- package/dist/events/end.js +6 -0
- package/dist/events/events.d.ts +111 -1478
- package/dist/events/events.js +91 -863
- package/dist/events/expand.d.ts +10 -0
- package/dist/events/expand.js +11 -0
- package/dist/events/facet.d.ts +17 -0
- package/dist/events/facet.js +11 -0
- package/dist/events/filter.d.ts +12 -0
- package/dist/events/filter.js +11 -0
- package/dist/events/filtered.d.ts +12 -0
- package/dist/events/filtered.js +11 -0
- package/dist/events/graph-filter.d.ts +10 -0
- package/dist/events/graph-filter.js +11 -0
- package/dist/events/graph-layout.d.ts +10 -0
- package/dist/events/graph-layout.js +11 -0
- package/dist/events/graph-pan.d.ts +9 -0
- package/dist/events/graph-pan.js +11 -0
- package/dist/events/graph-part-change.d.ts +10 -0
- package/dist/events/graph-part-change.js +11 -0
- package/dist/events/graph-ready.d.ts +8 -0
- package/dist/events/graph-ready.js +6 -0
- package/dist/events/graph-signal.d.ts +11 -0
- package/dist/events/graph-signal.js +11 -0
- package/dist/events/graph-zoom.d.ts +6 -0
- package/dist/events/graph-zoom.js +11 -0
- package/dist/events/history.d.ts +16 -0
- package/dist/events/history.js +11 -0
- package/dist/events/load-more.d.ts +12 -0
- package/dist/events/load-more.js +6 -0
- package/dist/events/load.d.ts +12 -0
- package/dist/events/load.js +6 -0
- package/dist/events/map-cluster.d.ts +15 -0
- package/dist/events/map-cluster.js +11 -0
- package/dist/events/map-pan.d.ts +18 -0
- package/dist/events/map-pan.js +11 -0
- package/dist/events/map-part-change.d.ts +16 -0
- package/dist/events/map-part-change.js +11 -0
- package/dist/events/map-ready.d.ts +15 -0
- package/dist/events/map-ready.js +6 -0
- package/dist/events/map-rotate.d.ts +9 -0
- package/dist/events/map-rotate.js +11 -0
- package/dist/events/map-tilt.d.ts +9 -0
- package/dist/events/map-tilt.js +11 -0
- package/dist/events/map-zoom.d.ts +13 -0
- package/dist/events/map-zoom.js +11 -0
- package/dist/events/move.d.ts +11 -0
- package/dist/events/move.js +11 -0
- package/dist/events/names.d.ts +15 -0
- package/dist/events/names.js +88 -0
- package/dist/events/navigate.d.ts +13 -0
- package/dist/events/navigate.js +11 -0
- package/dist/events/next.d.ts +23 -0
- package/dist/events/next.js +11 -0
- package/dist/events/panel-resize.d.ts +12 -0
- package/dist/events/panel-resize.js +11 -0
- package/dist/events/pin.d.ts +12 -0
- package/dist/events/pin.js +11 -0
- package/dist/events/press.d.ts +19 -0
- package/dist/events/press.js +11 -0
- package/dist/events/preview.d.ts +14 -0
- package/dist/events/preview.js +11 -0
- package/dist/events/previous.d.ts +6 -0
- package/dist/events/previous.js +11 -0
- package/dist/events/range-change.d.ts +10 -0
- package/dist/events/range-change.js +11 -0
- package/dist/events/read.d.ts +19 -0
- package/dist/events/read.js +11 -0
- package/dist/events/reconnect.d.ts +6 -0
- package/dist/events/reconnect.js +11 -0
- package/dist/events/reject.d.ts +13 -0
- package/dist/events/reject.js +11 -0
- package/dist/events/relabel.d.ts +6 -0
- package/dist/events/relabel.js +11 -0
- package/dist/events/remove.d.ts +12 -0
- package/dist/events/remove.js +11 -0
- package/dist/events/reorder.d.ts +18 -0
- package/dist/events/reorder.js +11 -0
- package/dist/events/reordered.d.ts +12 -0
- package/dist/events/reordered.js +11 -0
- package/dist/events/resize.d.ts +19 -0
- package/dist/events/resize.js +11 -0
- package/dist/events/resized.d.ts +16 -0
- package/dist/events/resized.js +11 -0
- package/dist/events/sample-end.d.ts +5 -0
- package/dist/events/sample-end.js +6 -0
- package/dist/events/sample-start.d.ts +18 -0
- package/dist/events/sample-start.js +6 -0
- package/dist/events/scrolled.d.ts +32 -0
- package/dist/events/scrolled.js +11 -0
- package/dist/events/select.d.ts +12 -0
- package/dist/events/select.js +11 -0
- package/dist/events/selected.d.ts +12 -0
- package/dist/events/selected.js +11 -0
- package/dist/events/send.d.ts +18 -0
- package/dist/events/send.js +11 -0
- package/dist/events/shortcut.d.ts +13 -0
- package/dist/events/shortcut.js +11 -0
- package/dist/events/sort.d.ts +17 -0
- package/dist/events/sort.js +11 -0
- package/dist/events/sorted.d.ts +15 -0
- package/dist/events/sorted.js +11 -0
- package/dist/events/split.d.ts +12 -0
- package/dist/events/split.js +11 -0
- package/dist/events/toggle.d.ts +15 -0
- package/dist/events/toggle.js +11 -0
- package/dist/events/tour-ask.d.ts +16 -0
- package/dist/events/tour-ask.js +11 -0
- package/dist/events/tour-status.d.ts +14 -0
- package/dist/events/tour-status.js +11 -0
- package/dist/events/typing.d.ts +10 -0
- package/dist/events/typing.js +11 -0
- package/dist/helix-element/react-bridge.d.ts +10 -0
- package/dist/helix-element/react-bridge.js +1 -1
- package/dist/helix-form-element/helix-form-element.d.ts +5 -20
- package/dist/helix-form-element/helix-form-element.js +4 -56
- package/dist/index.d.ts +15 -3
- package/dist/index.js +15 -3
- package/dist/mixins/mixin-chart-source/mixin-chart-source.d.ts +17 -2
- package/dist/mixins/mixin-chart-source/mixin-chart-source.js +22 -1
- package/dist/mixins/mixin-controller-active/mixin-controller-active.js +4 -3
- package/dist/mixins/mixin-controller-checked/mixin-controller-checked.d.ts +5 -2
- package/dist/mixins/mixin-controller-checked/mixin-controller-checked.js +2 -1
- package/dist/mixins/mixin-controller-value/mixin-controller-value.d.ts +4 -2
- package/dist/mixins/mixin-controller-value/mixin-controller-value.js +7 -2
- package/dist/mixins/mixin-dismissible/mixin-dismissible.js +20 -4
- package/dist/mixins/mixin-field/mixin-field.js +2 -2
- package/dist/mixins/mixin-picker-field/mixin-picker-field.d.ts +15 -3
- package/dist/mixins/mixin-picker-field/mixin-picker-field.js +11 -4
- package/dist/mixins/mixin-segmented-field/mixin-segmented-field.d.ts +1 -1
- package/dist/mixins/mixin-segmented-field/mixin-segmented-field.js +10 -4
- package/dist/utils/audit-name/audit-name-off.d.ts +10 -0
- package/dist/utils/audit-name/audit-name-off.js +1 -0
- package/dist/utils/audit-name/audit-name.d.ts +19 -6
- package/dist/utils/audit-name/audit-name.js +10 -27
- package/dist/utils/calendar/calendar.js +7 -7
- package/dist/utils/draw-tooltip/draw-tooltip.d.ts +1 -1
- package/dist/utils/draw-tooltip/draw-tooltip.js +3 -1
- package/dist/utils/draw-tooltip/spoken-reading.d.ts +6 -2
- package/dist/utils/draw-tooltip/spoken-reading.js +5 -4
- package/dist/utils/heading-level/heading-level.d.ts +8 -0
- package/dist/utils/heading-level/heading-level.js +4 -0
- package/dist/utils/implicit-submit/implicit-submit.d.ts +25 -0
- package/dist/utils/implicit-submit/implicit-submit.js +52 -0
- package/dist/utils/name-text/name-text.d.ts +12 -0
- package/dist/utils/name-text/name-text.js +25 -0
- package/dist/utils/number-format/number-format.d.ts +2 -1
- package/dist/utils/number-format/number-format.js +13 -5
- package/dist/utils/plain-click/plain-click.d.ts +10 -0
- package/dist/utils/plain-click/plain-click.js +1 -0
- package/dist/utils/press-type/press-type.d.ts +20 -0
- package/dist/utils/press-type/press-type.js +15 -0
- package/dist/utils/report-runtime/report-runtime.d.ts +6 -3
- package/dist/utils/row-data/row-data.d.ts +15 -0
- package/dist/utils/row-data/row-data.js +17 -0
- package/dist/utils/row-order/row-order.d.ts +141 -0
- package/dist/utils/row-order/row-order.js +76 -0
- package/dist/utils/tell-disclosure/tell-disclosure.d.ts +4 -0
- package/dist/utils/tree-arrow/tree-arrow.d.ts +23 -0
- package/dist/utils/tree-arrow/tree-arrow.js +9 -0
- package/dist/utils/typeahead/typeahead.d.ts +67 -0
- package/dist/utils/typeahead/typeahead.js +36 -0
- package/dist/utils/value-as/value-as.d.ts +9 -0
- package/dist/utils/value-as/value-as.js +9 -1
- package/dist/utils/watch-labels/watch-labels.d.ts +16 -0
- package/dist/utils/watch-labels/watch-labels.js +34 -0
- package/dist/utils/words-converter/words-converter.d.ts +14 -0
- package/dist/utils/words-converter/words-converter.js +15 -0
- package/dist/utils/written-list/written-list.d.ts +29 -0
- package/dist/utils/written-list/written-list.js +30 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +18 -5
|
@@ -84,7 +84,8 @@ export interface AriaForwardOptions {
|
|
|
84
84
|
* and the host is a generic the reader never lands on, so a `<label for>` or a
|
|
85
85
|
* wrapping `<label>` left the textbox unnamed. The labels travel the same way a
|
|
86
86
|
* forwarded `aria-labelledby` does, as element references, and are read again
|
|
87
|
-
*
|
|
87
|
+
* on every update, which a form control asks for whenever a label in its tree
|
|
88
|
+
* changes (`watchLabels`), and as focus arrives.
|
|
88
89
|
*/
|
|
89
90
|
export declare class AriaForwardController implements ReactiveController {
|
|
90
91
|
private readonly host;
|
|
@@ -128,7 +129,7 @@ export declare class AriaForwardController implements ReactiveController {
|
|
|
128
129
|
forward(): void;
|
|
129
130
|
hostConnected(): void;
|
|
130
131
|
hostDisconnected(): void;
|
|
131
|
-
/** Forwards again as focus arrives
|
|
132
|
+
/** Forwards again as focus arrives. */
|
|
132
133
|
private readonly refresh;
|
|
133
134
|
hostUpdated(): void;
|
|
134
135
|
}
|
|
@@ -1,17 +1,6 @@
|
|
|
1
|
-
import { auditName } from '
|
|
1
|
+
import { auditName } from '#audit-name';
|
|
2
2
|
import { elementById } from '../../utils/element-by-id/element-by-id.js';
|
|
3
|
-
|
|
4
|
-
if (node instanceof HTMLSlotElement) {
|
|
5
|
-
return node.assignedNodes({ flatten: true }).map(shownText).join('');
|
|
6
|
-
}
|
|
7
|
-
if (node.nodeType === Node.TEXT_NODE) {
|
|
8
|
-
return node.textContent ?? '';
|
|
9
|
-
}
|
|
10
|
-
if (node instanceof HTMLElement && node.hidden) {
|
|
11
|
-
return '';
|
|
12
|
-
}
|
|
13
|
-
return [...node.childNodes].map(shownText).join('');
|
|
14
|
-
};
|
|
3
|
+
import { nameText } from '../../utils/name-text/name-text.js';
|
|
15
4
|
const RELATIONSHIPS = [
|
|
16
5
|
['aria-describedby', 'ariaDescribedByElements'],
|
|
17
6
|
['aria-labelledby', 'ariaLabelledByElements'],
|
|
@@ -49,7 +38,7 @@ export class AriaForwardController {
|
|
|
49
38
|
return true;
|
|
50
39
|
}
|
|
51
40
|
const own = target.labels;
|
|
52
|
-
return [...(own ?? [])].some((label) =>
|
|
41
|
+
return [...(own ?? [])].some((label) => nameText(label).trim() !== '');
|
|
53
42
|
}
|
|
54
43
|
hostLabels(target) {
|
|
55
44
|
const labels = this.host.labels;
|
|
@@ -34,6 +34,31 @@ export interface ChartPointerHost extends ReactiveControllerHost, HTMLElement {
|
|
|
34
34
|
* drawn from, such as a scatter's measure across.
|
|
35
35
|
*/
|
|
36
36
|
seriesOf?(cell: number): number | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Whether the series drawn from the cell at this place in a row is shown,
|
|
39
|
+
* which it is unless a legend hid it. Absent, every series is shown.
|
|
40
|
+
*
|
|
41
|
+
* The series keys pass over a hidden one, and the readout leaves it out.
|
|
42
|
+
*/
|
|
43
|
+
showsColumn?(cell: number): boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Whether the reading at this place is shown, for a chart whose readings
|
|
46
|
+
* a legend can hide: a ring's slices are its rows. Absent, every reading is
|
|
47
|
+
* shown.
|
|
48
|
+
*
|
|
49
|
+
* The keys pass over a hidden reading, as they pass over a hidden series.
|
|
50
|
+
*/
|
|
51
|
+
showsReading?(at: number): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* The words for where a reading stands among them, with `{position}` and
|
|
54
|
+
* `{count}` to fill. Absent or empty, no position is said.
|
|
55
|
+
*/
|
|
56
|
+
readonly positionLabel?: string;
|
|
57
|
+
/**
|
|
58
|
+
* The locale the position's numbers are written in. Absent or empty is the
|
|
59
|
+
* runtime's own.
|
|
60
|
+
*/
|
|
61
|
+
readonly locale?: string;
|
|
37
62
|
}
|
|
38
63
|
/**
|
|
39
64
|
* Which reading a pointer is nearest, for a chart that draws no markers.
|
|
@@ -62,8 +87,9 @@ export interface ChartPointerHost extends ReactiveControllerHost, HTMLElement {
|
|
|
62
87
|
* **The keyboard moves the same reading, which is what makes it the reading
|
|
63
88
|
* and not the pointer's.** A chart's plot takes focus (`tabindex="0"` on the
|
|
64
89
|
* element carrying `CHART_PLOT`), and while it has it the arrow keys walk the
|
|
65
|
-
* readings, Home and End go to the first and the last, and
|
|
66
|
-
*
|
|
90
|
+
* readings, Home and End go to the first and the last, PageUp and PageDown
|
|
91
|
+
* move a page of readings, and the other pair of arrows walks the series
|
|
92
|
+
* within a reading. Escape puts the bubble away, as it
|
|
67
93
|
* does a tooltip. The tooltip follows because it already follows `at`, and the
|
|
68
94
|
* chart's readout, a polite live region `drawTooltip` renders, says the
|
|
69
95
|
* reading in words. It speaks only for a key: a pointer crossing a chart is a
|
|
@@ -125,8 +151,41 @@ export declare class ChartPointerController implements ReactiveController {
|
|
|
125
151
|
* from, and the bubble lists every one of them.
|
|
126
152
|
*/
|
|
127
153
|
get column(): number | undefined;
|
|
128
|
-
/**
|
|
154
|
+
/**
|
|
155
|
+
* Whether the series drawn from the cell at this place in a row is shown.
|
|
156
|
+
*
|
|
157
|
+
* The readout asks, so a reading said whole leaves out what a legend hid,
|
|
158
|
+
* as the drawing does.
|
|
159
|
+
*/
|
|
160
|
+
shows(cell: number): boolean;
|
|
161
|
+
/**
|
|
162
|
+
* How far PageUp and PageDown move: four columns of a grid, which is four
|
|
163
|
+
* weeks of a calendar heatmap, a month near enough; and a tenth of the
|
|
164
|
+
* readings otherwise, at least one.
|
|
165
|
+
*/
|
|
166
|
+
private page;
|
|
167
|
+
/**
|
|
168
|
+
* Where the reading stands among the shown readings, in the host's
|
|
169
|
+
* `positionLabel`, such as "2 of 12". Empty with no reading, and where the
|
|
170
|
+
* host gives no words.
|
|
171
|
+
*
|
|
172
|
+
* Counted among the shown readings, so a slice a legend hid is not one of
|
|
173
|
+
* the count.
|
|
174
|
+
*/
|
|
175
|
+
get position(): string;
|
|
176
|
+
/**
|
|
177
|
+
* The cells a series key can rest on: every column a series was drawn
|
|
178
|
+
* from, and is still drawn from.
|
|
179
|
+
*/
|
|
129
180
|
private columns;
|
|
181
|
+
/**
|
|
182
|
+
* The readings the keys walk, by place: every one, less those a legend hid.
|
|
183
|
+
*
|
|
184
|
+
* The keys step through this list, so a hidden
|
|
185
|
+
* slice is passed over as if it were not in the table, which is how the
|
|
186
|
+
* ring draws it.
|
|
187
|
+
*/
|
|
188
|
+
private shown;
|
|
130
189
|
/**
|
|
131
190
|
* Tells the tooltip its anchor moved, which nothing else would.
|
|
132
191
|
*
|
|
@@ -145,6 +204,9 @@ export declare class ChartPointerController implements ReactiveController {
|
|
|
145
204
|
/**
|
|
146
205
|
* The box the readings are laid out in, which is the plot and not the host.
|
|
147
206
|
*
|
|
207
|
+
* Found by its part, or by the id every chart gives its plot, which is how
|
|
208
|
+
* a sparkline's drawing, whose part is `svg`, is found.
|
|
209
|
+
*
|
|
148
210
|
* The host also holds the row of labels, so measuring against it would map
|
|
149
211
|
* the pointer over a box taller than the drawing. That mattered the moment a
|
|
150
212
|
* chart started measuring down the box rather than across it, which is what
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { fillTemplate } from '../../utils/fill-template/fill-template.js';
|
|
2
|
+
import { formatNumbers } from '../../utils/format-numbers/format-numbers.js';
|
|
1
3
|
import { isRtl } from '../../utils/is-rtl/is-rtl.js';
|
|
2
4
|
import { stepReading } from './reading-step.js';
|
|
3
5
|
export const CHART_PLOT = 'helix-chart-plot';
|
|
@@ -13,7 +15,8 @@ export class ChartPointerController {
|
|
|
13
15
|
if (!this.fromPlot(event) || event.altKey || event.ctrlKey || event.metaKey) {
|
|
14
16
|
return;
|
|
15
17
|
}
|
|
16
|
-
const
|
|
18
|
+
const shown = this.shown();
|
|
19
|
+
const count = shown.length;
|
|
17
20
|
if (count === 0) {
|
|
18
21
|
return;
|
|
19
22
|
}
|
|
@@ -24,17 +27,19 @@ export class ChartPointerController {
|
|
|
24
27
|
}
|
|
25
28
|
return;
|
|
26
29
|
}
|
|
27
|
-
const next = stepReading(event.key, { at: this.at, series: this.series }, {
|
|
30
|
+
const next = stepReading(event.key, { at: shown.indexOf(this.at), series: this.series }, {
|
|
28
31
|
axis: this.axis,
|
|
29
32
|
count,
|
|
30
33
|
grid: this.grid,
|
|
34
|
+
page: this.page(count),
|
|
31
35
|
rtl: isRtl(this.host),
|
|
32
36
|
series: this.columns().length,
|
|
33
37
|
});
|
|
34
38
|
if (next === undefined) {
|
|
35
39
|
return;
|
|
36
40
|
}
|
|
37
|
-
const
|
|
41
|
+
const at = shown[next.at] ?? -1;
|
|
42
|
+
const { series } = next;
|
|
38
43
|
event.preventDefault();
|
|
39
44
|
if (at === this.at && series === this.series && this.keyed) {
|
|
40
45
|
return;
|
|
@@ -56,10 +61,11 @@ export class ChartPointerController {
|
|
|
56
61
|
}
|
|
57
62
|
catch {
|
|
58
63
|
}
|
|
59
|
-
|
|
64
|
+
const first = this.shown()[0];
|
|
65
|
+
if (!visible || first === undefined) {
|
|
60
66
|
return;
|
|
61
67
|
}
|
|
62
|
-
this.at =
|
|
68
|
+
this.at = first;
|
|
63
69
|
this.keyed = true;
|
|
64
70
|
this.moved = true;
|
|
65
71
|
this.host.requestUpdate();
|
|
@@ -123,12 +129,32 @@ export class ChartPointerController {
|
|
|
123
129
|
get column() {
|
|
124
130
|
return this.series < 0 ? undefined : this.columns()[this.series];
|
|
125
131
|
}
|
|
132
|
+
shows(cell) {
|
|
133
|
+
return this.host.showsColumn?.(cell) !== false;
|
|
134
|
+
}
|
|
135
|
+
page(count) {
|
|
136
|
+
return this.grid > 1 ? this.grid * 4 : Math.max(1, Math.round(count / 10));
|
|
137
|
+
}
|
|
138
|
+
get position() {
|
|
139
|
+
const words = this.host.positionLabel ?? '';
|
|
140
|
+
const shown = this.shown();
|
|
141
|
+
const place = shown.indexOf(this.at);
|
|
142
|
+
if (words === '' || place < 0) {
|
|
143
|
+
return '';
|
|
144
|
+
}
|
|
145
|
+
const format = formatNumbers(this.host.locale ?? '');
|
|
146
|
+
return fillTemplate(words, { count: format(shown.length), position: format(place + 1) });
|
|
147
|
+
}
|
|
126
148
|
columns() {
|
|
127
149
|
const host = this.host;
|
|
128
|
-
|
|
129
|
-
|
|
150
|
+
return (host.plottedColumns ?? []).filter((one) => (host.seriesOf === undefined || host.seriesOf(one) !== undefined) && this.shows(one));
|
|
151
|
+
}
|
|
152
|
+
shown() {
|
|
153
|
+
const host = this.host;
|
|
154
|
+
const all = Array.from({ length: host.readings }, (_, at) => at);
|
|
155
|
+
return host.showsReading === undefined
|
|
130
156
|
? all
|
|
131
|
-
: all.filter((
|
|
157
|
+
: all.filter((at) => host.showsReading?.(at) !== false);
|
|
132
158
|
}
|
|
133
159
|
hostUpdated() {
|
|
134
160
|
if (!this.moved) {
|
|
@@ -141,7 +167,9 @@ export class ChartPointerController {
|
|
|
141
167
|
}
|
|
142
168
|
box() {
|
|
143
169
|
if (!this.plot?.isConnected) {
|
|
144
|
-
this.plot =
|
|
170
|
+
this.plot =
|
|
171
|
+
this.host.renderRoot.querySelector(`[part="plot"], #${CHART_PLOT}`) ??
|
|
172
|
+
undefined;
|
|
145
173
|
}
|
|
146
174
|
return this.plot?.getBoundingClientRect();
|
|
147
175
|
}
|
|
@@ -18,6 +18,11 @@ export interface ReadingLayout {
|
|
|
18
18
|
count: number;
|
|
19
19
|
/** How many readings stand in one column, for a grid. `1` is a row of them. */
|
|
20
20
|
grid: number;
|
|
21
|
+
/**
|
|
22
|
+
* How far PageUp and PageDown move, in readings. Absent, they move nothing
|
|
23
|
+
* and the page keeps them.
|
|
24
|
+
*/
|
|
25
|
+
page?: number;
|
|
21
26
|
/** Whether the line of text runs right to left, which turns the inline arrows. */
|
|
22
27
|
rtl: boolean;
|
|
23
28
|
/** How many series a reading holds, which the cross pair of arrows walks. */
|
|
@@ -49,7 +54,8 @@ export declare const amongSeries: (key: string, layout: ReadingLayout) => number
|
|
|
49
54
|
* Where a key moves the reading, or `undefined` for a key that moves nothing,
|
|
50
55
|
* which the page keeps.
|
|
51
56
|
*
|
|
52
|
-
* Home and End go to the first and the last
|
|
57
|
+
* Home and End go to the first and the last, and PageUp and PageDown move a
|
|
58
|
+
* `page` of readings where the layout gives one. From no reading, an arrow moving
|
|
53
59
|
* on starts at the first and one moving back at the last, so either arrow
|
|
54
60
|
* starts somewhere a reader expects. A series key on no reading starts on the
|
|
55
61
|
* first. Nothing walks off either end.
|
|
@@ -29,6 +29,11 @@ export const stepReading = (key, from, layout) => {
|
|
|
29
29
|
if (key === 'End') {
|
|
30
30
|
return { at: last, series: from.series };
|
|
31
31
|
}
|
|
32
|
+
if ((key === 'PageDown' || key === 'PageUp') && layout.page !== undefined) {
|
|
33
|
+
const step = Math.max(1, layout.page) * (key === 'PageDown' ? 1 : -1);
|
|
34
|
+
const at = from.at < 0 ? (step > 0 ? 0 : last) : Math.min(Math.max(from.at + step, 0), last);
|
|
35
|
+
return { at, series: from.series };
|
|
36
|
+
}
|
|
32
37
|
const along = alongReadings(key, layout);
|
|
33
38
|
if (along !== 0) {
|
|
34
39
|
const at = from.at < 0 ? (along > 0 ? 0 : last) : Math.min(Math.max(from.at + along, 0), last);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
import { type TypeaheadBy } from '../../utils/typeahead/typeahead.js';
|
|
2
3
|
/** What a controller needs of an item to move to it and choose it. */
|
|
3
4
|
export interface NavigableItem {
|
|
4
5
|
/**
|
|
@@ -70,14 +71,15 @@ export interface KeyboardNavigationOptions {
|
|
|
70
71
|
*/
|
|
71
72
|
reserved?: () => string[];
|
|
72
73
|
/**
|
|
73
|
-
* The
|
|
74
|
-
*
|
|
74
|
+
* The search that turns on typeahead, built with `typeaheadBy` from the
|
|
75
|
+
* words of an item: a printable key moves to the next item whose words
|
|
76
|
+
* start with what was typed.
|
|
75
77
|
*
|
|
76
78
|
* Off unless given. A set whose items have no words a reader would type, or
|
|
77
79
|
* that holds a text field of its own, leaves it out. See `Typeahead` for how
|
|
78
80
|
* the letters are matched.
|
|
79
81
|
*/
|
|
80
|
-
typeahead?:
|
|
82
|
+
typeahead?: TypeaheadBy<NavigableItem>;
|
|
81
83
|
/**
|
|
82
84
|
* Whether the ends join up, which they do unless a set says otherwise.
|
|
83
85
|
*
|
|
@@ -98,54 +100,6 @@ export interface KeyboardNavigationOptions {
|
|
|
98
100
|
*/
|
|
99
101
|
wrap?: boolean;
|
|
100
102
|
}
|
|
101
|
-
/**
|
|
102
|
-
* Whether a press types a character, which is what typeahead reads.
|
|
103
|
-
*
|
|
104
|
-
* One character with no Control, Command or Alt held, so a shortcut such as
|
|
105
|
-
* Control+A is never taken for the letter A. Shift is allowed, because a
|
|
106
|
-
* capital is still a letter.
|
|
107
|
-
*/
|
|
108
|
-
export declare const typesCharacter: (event: KeyboardEvent) => boolean;
|
|
109
|
-
/**
|
|
110
|
-
* Finds an item by the letters a reader types at a set, the way a native
|
|
111
|
-
* `<select>` does.
|
|
112
|
-
*
|
|
113
|
-
* Letters typed within `timeout` milliseconds of each other build one search,
|
|
114
|
-
* so typing "ca" moves to "Canada" past "Cambodia". The same letter typed again
|
|
115
|
-
* moves to the next item that starts with it, so pressing "c" three times visits
|
|
116
|
-
* the first three. A pause starts a new search.
|
|
117
|
-
*
|
|
118
|
-
* Matching ignores case and leading spaces, and searches from the reader's
|
|
119
|
-
* position, wrapping at the end. A search that matches nothing moves nothing.
|
|
120
|
-
*
|
|
121
|
-
* Holds only the letters, so one instance serves any set: the caller passes the
|
|
122
|
-
* words of the items and where the reader is on every key.
|
|
123
|
-
*/
|
|
124
|
-
export declare class Typeahead {
|
|
125
|
-
private letters;
|
|
126
|
-
private last;
|
|
127
|
-
private readonly timeout;
|
|
128
|
-
constructor({ timeout }?: {
|
|
129
|
-
timeout?: number;
|
|
130
|
-
});
|
|
131
|
-
/**
|
|
132
|
-
* Whether a search is under way.
|
|
133
|
-
*
|
|
134
|
-
* A set that chooses on Space asks this first, because a Space typed in the
|
|
135
|
-
* middle of a search is part of the words, as in "New York".
|
|
136
|
-
*/
|
|
137
|
-
typing(now?: number): boolean;
|
|
138
|
-
/**
|
|
139
|
-
* Adds a character to the search, and returns the index of the item it
|
|
140
|
-
* matches, or `-1` where none does.
|
|
141
|
-
*
|
|
142
|
-
* `texts` are the words of the items a reader can reach, in order, and
|
|
143
|
-
* `from` is the index of the item the reader is on, or `-1`.
|
|
144
|
-
*/
|
|
145
|
-
match(key: string, texts: readonly string[], from: number, now?: number): number;
|
|
146
|
-
/** Ends the search, so the next letter starts a new one. */
|
|
147
|
-
reset(): void;
|
|
148
|
-
}
|
|
149
103
|
/**
|
|
150
104
|
* Moves through a set of items with the arrow keys, and chooses as it goes.
|
|
151
105
|
*
|
|
@@ -171,9 +125,10 @@ export declare class Typeahead {
|
|
|
171
125
|
* Disabled items are skipped rather than stopped at, so a set with a gap in it
|
|
172
126
|
* still moves in one press.
|
|
173
127
|
*
|
|
174
|
-
* **Typeahead is opt-in.** Pass `typeahead
|
|
175
|
-
* item's words, and a printable key moves to the next
|
|
176
|
-
* with the letters typed, choosing it where arriving
|
|
128
|
+
* **Typeahead is opt-in.** Pass `typeahead`, built by `typeaheadBy` from a
|
|
129
|
+
* function that returns an item's words, and a printable key moves to the next
|
|
130
|
+
* item whose words start with the letters typed, choosing it where arriving
|
|
131
|
+
* chooses. A key that a text
|
|
177
132
|
* field inside the set is typing into is left to the field.
|
|
178
133
|
*
|
|
179
134
|
* A set that starts from focus rather than from the selection, or that moves
|
|
@@ -187,7 +142,6 @@ export declare class KeyboardNavigationController implements ReactiveController
|
|
|
187
142
|
private readonly selects;
|
|
188
143
|
private readonly reserved;
|
|
189
144
|
private readonly wrap;
|
|
190
|
-
private readonly words;
|
|
191
145
|
private readonly typeahead;
|
|
192
146
|
constructor(host: ReactiveControllerHost & HTMLElement, { items, origin, reserved, selects, typeahead, wrap, }: KeyboardNavigationOptions);
|
|
193
147
|
/** Where this press starts from, read again on every press. */
|
|
@@ -1,41 +1,9 @@
|
|
|
1
1
|
import { inlineStep } from '../../utils/inline-step/inline-step.js';
|
|
2
2
|
import { keyClaimed } from '../../utils/key-claimed/key-claimed.js';
|
|
3
|
+
import { typesCharacter } from '../../utils/typeahead/typeahead.js';
|
|
3
4
|
const KEYS = new Set(['ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'End', 'Home']);
|
|
4
|
-
export const typesCharacter = (event) => event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey;
|
|
5
|
-
export class Typeahead {
|
|
6
|
-
constructor({ timeout = 500 } = {}) {
|
|
7
|
-
this.letters = '';
|
|
8
|
-
this.last = 0;
|
|
9
|
-
this.timeout = timeout;
|
|
10
|
-
}
|
|
11
|
-
typing(now = Date.now()) {
|
|
12
|
-
return this.letters !== '' && now - this.last <= this.timeout;
|
|
13
|
-
}
|
|
14
|
-
match(key, texts, from, now = Date.now()) {
|
|
15
|
-
if (!this.typing(now)) {
|
|
16
|
-
this.letters = '';
|
|
17
|
-
}
|
|
18
|
-
this.last = now;
|
|
19
|
-
this.letters += key.toLowerCase();
|
|
20
|
-
const words = texts.map((text) => text.trim().toLowerCase());
|
|
21
|
-
const repeated = [...this.letters].every((letter) => letter === this.letters[0]);
|
|
22
|
-
const needle = repeated ? (this.letters[0] ?? '') : this.letters;
|
|
23
|
-
const start = repeated ? from + 1 : Math.max(from, 0);
|
|
24
|
-
for (let step = 0; step < words.length; step += 1) {
|
|
25
|
-
const at = (start + step) % words.length;
|
|
26
|
-
if (words[at]?.startsWith(needle)) {
|
|
27
|
-
return at;
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
return -1;
|
|
31
|
-
}
|
|
32
|
-
reset() {
|
|
33
|
-
this.letters = '';
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
5
|
export class KeyboardNavigationController {
|
|
37
6
|
constructor(host, { items, origin = 'selection', reserved = () => [], selects = () => true, typeahead, wrap = true, }) {
|
|
38
|
-
this.typeahead = new Typeahead();
|
|
39
7
|
this.handleKeydown = (event) => {
|
|
40
8
|
if (!KEYS.has(event.key)) {
|
|
41
9
|
this.handleTypeahead(event);
|
|
@@ -76,7 +44,7 @@ export class KeyboardNavigationController {
|
|
|
76
44
|
next = last;
|
|
77
45
|
}
|
|
78
46
|
event.preventDefault();
|
|
79
|
-
this.typeahead.reset();
|
|
47
|
+
this.typeahead?.search.reset();
|
|
80
48
|
this.arrive(items[next]);
|
|
81
49
|
};
|
|
82
50
|
this.host = host;
|
|
@@ -84,7 +52,7 @@ export class KeyboardNavigationController {
|
|
|
84
52
|
this.originOf = typeof origin === 'function' ? origin : () => origin;
|
|
85
53
|
this.reserved = reserved;
|
|
86
54
|
this.selects = selects;
|
|
87
|
-
this.
|
|
55
|
+
this.typeahead = typeahead;
|
|
88
56
|
this.wrap = wrap;
|
|
89
57
|
host.addController(this);
|
|
90
58
|
}
|
|
@@ -107,11 +75,11 @@ export class KeyboardNavigationController {
|
|
|
107
75
|
return selected < 0 ? focused : selected;
|
|
108
76
|
}
|
|
109
77
|
handleTypeahead(event) {
|
|
110
|
-
const
|
|
111
|
-
if (!
|
|
78
|
+
const typeahead = this.typeahead;
|
|
79
|
+
if (!typeahead || !typesCharacter(event) || keyClaimed(event)) {
|
|
112
80
|
return;
|
|
113
81
|
}
|
|
114
|
-
if (event.key === ' ' && !
|
|
82
|
+
if (event.key === ' ' && !typeahead.search.typing()) {
|
|
115
83
|
return;
|
|
116
84
|
}
|
|
117
85
|
const items = this.items().filter((item) => !item.disabled);
|
|
@@ -122,7 +90,7 @@ export class KeyboardNavigationController {
|
|
|
122
90
|
if (this.origin === 'focus' && from === -1) {
|
|
123
91
|
return;
|
|
124
92
|
}
|
|
125
|
-
const at =
|
|
93
|
+
const at = typeahead.search.match(event.key, items.map(typeahead.words), from);
|
|
126
94
|
event.preventDefault();
|
|
127
95
|
if (at >= 0 && at !== from) {
|
|
128
96
|
this.arrive(items[at]);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ReactiveController, ReactiveControllerHost } from 'lit';
|
|
2
|
+
/** What the clock reads from its host. */
|
|
3
|
+
export interface RelativeClockOptions {
|
|
4
|
+
/**
|
|
5
|
+
* When the reading drawn at `now` stops being true, as `relativeTime` and
|
|
6
|
+
* `elapsedTime` say in `next`, in milliseconds from `now`; or `undefined`
|
|
7
|
+
* where the host shows no reading, which reads nothing and schedules
|
|
8
|
+
* nothing.
|
|
9
|
+
*/
|
|
10
|
+
expires: (now: Date) => number | undefined;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The time a relative reading is drawn against, moved on when the reading
|
|
14
|
+
* would change: "3 minutes ago" becoming "4 minutes ago".
|
|
15
|
+
*
|
|
16
|
+
* **One wakeup when the words go stale, and none in between.** The reading
|
|
17
|
+
* says how long it holds, so the clock asks core's shared ticker for exactly
|
|
18
|
+
* that moment: a reading a minute old wakes once a minute, an hour old once an
|
|
19
|
+
* hour, and a date never. Every reading on the page shares the ticker's one
|
|
20
|
+
* timer. Chat Message and Format Date draw against it.
|
|
21
|
+
*
|
|
22
|
+
* **Only on a page.** A server has nobody to update a reading for, and a
|
|
23
|
+
* subscription there holds the element after its markup is sent, so off the
|
|
24
|
+
* page `tick()` reads the time and schedules nothing.
|
|
25
|
+
*/
|
|
26
|
+
export declare class RelativeClockController implements ReactiveController {
|
|
27
|
+
private readonly host;
|
|
28
|
+
private readonly options;
|
|
29
|
+
/** The time the host last drew against, in milliseconds. */
|
|
30
|
+
now: number;
|
|
31
|
+
private stop;
|
|
32
|
+
constructor(host: ReactiveControllerHost & HTMLElement, options: RelativeClockOptions);
|
|
33
|
+
hostConnected(): void;
|
|
34
|
+
hostDisconnected(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Reads the clock again, asks the host to draw against it, and schedules
|
|
37
|
+
* the next reading.
|
|
38
|
+
*
|
|
39
|
+
* The host calls it when what it reads changes, the instant or the locale,
|
|
40
|
+
* and the ticker calls it when the words go stale. A host with no reading
|
|
41
|
+
* is left as it is.
|
|
42
|
+
*/
|
|
43
|
+
tick(): void;
|
|
44
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { subscribe } from '../../utils/ticker/ticker.js';
|
|
2
|
+
export class RelativeClockController {
|
|
3
|
+
constructor(host, options) {
|
|
4
|
+
this.host = host;
|
|
5
|
+
this.options = options;
|
|
6
|
+
this.now = Date.now();
|
|
7
|
+
this.stop = undefined;
|
|
8
|
+
host.addController(this);
|
|
9
|
+
}
|
|
10
|
+
hostConnected() {
|
|
11
|
+
this.tick();
|
|
12
|
+
}
|
|
13
|
+
hostDisconnected() {
|
|
14
|
+
this.stop?.();
|
|
15
|
+
this.stop = undefined;
|
|
16
|
+
}
|
|
17
|
+
tick() {
|
|
18
|
+
this.stop?.();
|
|
19
|
+
this.stop = undefined;
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
const next = this.options.expires(new Date(now));
|
|
22
|
+
if (next === undefined) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
this.now = now;
|
|
26
|
+
this.host.requestUpdate();
|
|
27
|
+
if (Number.isFinite(next) && this.host.isConnected) {
|
|
28
|
+
this.stop = subscribe(next, () => this.tick());
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -107,13 +107,20 @@ export declare class SourceController implements ReactiveController {
|
|
|
107
107
|
get hidden(): ReadonlySet<string>;
|
|
108
108
|
/**
|
|
109
109
|
* Hides these series on the table and shows every other, for every chart
|
|
110
|
-
* and legend reading it, which then redraw.
|
|
110
|
+
* and legend reading it, which then redraw. Answers the table it wrote to,
|
|
111
|
+
* or null where `for` names none.
|
|
112
|
+
*
|
|
113
|
+
* Given `among`, only those names are shown or hidden, and a series hidden
|
|
114
|
+
* outside them stays hidden. A legend passes its own entries, so a legend
|
|
115
|
+
* of the rows and a legend of the columns on one table each keep what the
|
|
116
|
+
* other hid.
|
|
111
117
|
*
|
|
112
118
|
* Names are matched without regard to case or surrounding space, as a
|
|
113
119
|
* column's heading is everywhere else. Nothing happens where `for` names no
|
|
114
|
-
* table, or the set is already this one
|
|
120
|
+
* table, or the set is already this one, so two writers that agree stop
|
|
121
|
+
* asking each other to redraw.
|
|
115
122
|
*/
|
|
116
|
-
hide(names: Iterable<string>):
|
|
123
|
+
hide(names: Iterable<string>, among?: Iterable<string>): Element | null;
|
|
117
124
|
/** Counts this controller among the readers of the table it watches, or of none. */
|
|
118
125
|
private enlist;
|
|
119
126
|
hostConnected(): void;
|
|
@@ -54,15 +54,17 @@ export class SourceController {
|
|
|
54
54
|
const element = this.element;
|
|
55
55
|
return element ? (HIDDEN.get(element) ?? NONE) : NONE;
|
|
56
56
|
}
|
|
57
|
-
hide(names) {
|
|
57
|
+
hide(names, among) {
|
|
58
58
|
const element = this.resolve();
|
|
59
59
|
if (!element) {
|
|
60
|
-
return;
|
|
60
|
+
return null;
|
|
61
61
|
}
|
|
62
|
-
const next = new Set([...names].map(seriesKey).filter(Boolean));
|
|
63
62
|
const now = HIDDEN.get(element) ?? NONE;
|
|
63
|
+
const mine = among === undefined ? undefined : new Set([...among].map(seriesKey));
|
|
64
|
+
const kept = mine === undefined ? [] : [...now].filter((one) => !mine.has(one));
|
|
65
|
+
const next = new Set([...kept, ...[...names].map(seriesKey)].filter(Boolean));
|
|
64
66
|
if (next.size === now.size && [...next].every((one) => now.has(one))) {
|
|
65
|
-
return;
|
|
67
|
+
return element;
|
|
66
68
|
}
|
|
67
69
|
if (next.size === 0) {
|
|
68
70
|
HIDDEN.delete(element);
|
|
@@ -73,6 +75,7 @@ export class SourceController {
|
|
|
73
75
|
for (const reader of READERS.get(element) ?? []) {
|
|
74
76
|
reader.host.requestUpdate();
|
|
75
77
|
}
|
|
78
|
+
return element;
|
|
76
79
|
}
|
|
77
80
|
enlist(element) {
|
|
78
81
|
if (this.watched) {
|