@fusion.dev/helix-core 0.145.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 +6585 -1920
- package/dist/controllers/aria-forward-controller/aria-forward-controller.d.ts +3 -2
- package/dist/controllers/aria-forward-controller/aria-forward-controller.js +8 -17
- package/dist/controllers/chart-pointer-controller/chart-pointer-controller.d.ts +71 -3
- package/dist/controllers/chart-pointer-controller/chart-pointer-controller.js +50 -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/copy-controller/copy-controller.d.ts +4 -1
- package/dist/controllers/copy-controller/copy-controller.js +2 -1
- package/dist/controllers/countdown-controller/countdown-controller.d.ts +4 -1
- package/dist/controllers/countdown-controller/countdown-controller.js +3 -1
- package/dist/controllers/keyboard-navigation-controller/keyboard-navigation-controller.d.ts +14 -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 +9 -4
- package/dist/controllers/swipe-controller/swipe-controller.d.ts +10 -1
- package/dist/controllers/swipe-controller/swipe-controller.js +1 -1
- package/dist/controllers/virtualize-controller/virtualize-controller.d.ts +48 -1
- package/dist/controllers/virtualize-controller/virtualize-controller.js +52 -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/band.d.ts +13 -0
- package/dist/events/band.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 +459 -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 +113 -1478
- package/dist/events/events.js +93 -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 +18 -0
- package/dist/events/names.js +13 -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/helix-element.js +9 -43
- package/dist/helix-element/react-bridge.d.ts +23 -0
- package/dist/helix-element/react-bridge.js +2 -2
- 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 +30 -9
- package/dist/index.js +30 -9
- package/dist/mixins/mixin-chart-source/mixin-chart-source.d.ts +24 -2
- package/dist/mixins/mixin-chart-source/mixin-chart-source.js +23 -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 +44 -7
- package/dist/mixins/mixin-field/mixin-field.js +2 -2
- package/dist/mixins/mixin-picker-feedback/mixin-picker-feedback.d.ts +42 -0
- package/dist/mixins/mixin-picker-feedback/mixin-picker-feedback.js +46 -0
- package/dist/mixins/mixin-picker-field/mixin-picker-field.d.ts +7 -4
- package/dist/mixins/mixin-picker-field/mixin-picker-field.js +6 -4
- package/dist/mixins/mixin-segmented-field/mixin-segmented-field.js +19 -9
- 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 +26 -8
- package/dist/utils/audit-name/audit-name.js +22 -30
- package/dist/utils/audit-source/audit-source-off.d.ts +10 -0
- package/dist/utils/audit-source/audit-source-off.js +1 -0
- package/dist/utils/audit-source/audit-source.d.ts +19 -0
- package/dist/utils/audit-source/audit-source.js +27 -0
- package/dist/utils/calendar/calendar.js +7 -7
- package/dist/utils/call-listener/call-listener.d.ts +16 -0
- package/dist/utils/call-listener/call-listener.js +17 -0
- package/dist/utils/chord/chord.d.ts +14 -0
- package/dist/utils/chord/chord.js +1 -0
- package/dist/utils/clamp/clamp.d.ts +7 -0
- package/dist/utils/clamp/clamp.js +1 -0
- package/dist/utils/css-color/css-color.js +1 -1
- 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/elapsed-time/elapsed-time.d.ts +1 -1
- package/dist/utils/elapsed-time/elapsed-time.js +2 -5
- package/dist/utils/heading-level/heading-level.d.ts +8 -0
- package/dist/utils/heading-level/heading-level.js +4 -0
- package/dist/utils/host-words/host-words.d.ts +16 -0
- package/dist/utils/host-words/host-words.js +13 -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/load-more/load-more.d.ts +25 -0
- package/dist/utils/load-more/load-more.js +1 -0
- package/dist/utils/locale-of/locale-of.d.ts +18 -0
- package/dist/utils/locale-of/locale-of.js +26 -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/nearest/nearest.d.ts +9 -0
- package/dist/utils/nearest/nearest.js +9 -0
- package/dist/utils/number-format/number-format.d.ts +11 -1
- package/dist/utils/number-format/number-format.js +17 -5
- package/dist/utils/own-rule/own-rule.d.ts +16 -0
- package/dist/utils/own-rule/own-rule.js +7 -0
- package/dist/utils/plain-click/plain-click.d.ts +10 -0
- package/dist/utils/plain-click/plain-click.js +1 -0
- package/dist/utils/platform/platform.d.ts +8 -0
- package/dist/utils/platform/platform.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/read-series/read-series.d.ts +14 -0
- package/dist/utils/read-series/read-series.js +15 -0
- package/dist/utils/relative-time/relative-time.d.ts +8 -0
- package/dist/utils/relative-time/relative-time.js +5 -2
- package/dist/utils/report-render/report-render.js +2 -14
- package/dist/utils/report-runtime/report-runtime.d.ts +11 -4
- package/dist/utils/report-runtime/report-runtime.js +2 -14
- package/dist/utils/report-usage/report-usage.js +2 -14
- 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/scroll-item-into-view/scroll-item-into-view.d.ts +33 -0
- package/dist/utils/scroll-item-into-view/scroll-item-into-view.js +13 -3
- package/dist/utils/slotted-glyph/slotted-glyph.d.ts +33 -0
- package/dist/utils/slotted-glyph/slotted-glyph.js +27 -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 +75 -0
- package/dist/utils/typeahead/typeahead.js +37 -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/verdict-flags/verdict-flags.d.ts +13 -0
- package/dist/utils/verdict-flags/verdict-flags.js +6 -0
- 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 +60 -0
- package/dist/utils/written-list/written-list.js +46 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +29 -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;
|
|
@@ -85,9 +74,11 @@ export class AriaForwardController {
|
|
|
85
74
|
continue;
|
|
86
75
|
}
|
|
87
76
|
const ids = (this.host.getAttribute(attribute) ?? '').split(/\s+/).filter(Boolean);
|
|
88
|
-
const referenced = ids
|
|
89
|
-
|
|
90
|
-
|
|
77
|
+
const referenced = ids.length > 0
|
|
78
|
+
? ids
|
|
79
|
+
.map((id) => elementById(this.host, id))
|
|
80
|
+
.filter((element) => element !== null)
|
|
81
|
+
: [...(this.host[property] ?? [])];
|
|
91
82
|
const elements = referenced.length === 0 && attribute === 'aria-labelledby'
|
|
92
83
|
? this.hostLabels(target)
|
|
93
84
|
: referenced;
|
|
@@ -34,6 +34,37 @@ 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
|
+
* Where PageUp or PageDown goes from the reading at `at`, by place among the
|
|
54
|
+
* readings, for a chart whose page is no fixed count: a calendar's month.
|
|
55
|
+
* Undefined keeps the fixed page.
|
|
56
|
+
*/
|
|
57
|
+
pageFrom?(at: number, forward: boolean): number | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* The words for where a reading stands among them, with `{position}` and
|
|
60
|
+
* `{count}` to fill. Absent or empty, no position is said.
|
|
61
|
+
*/
|
|
62
|
+
readonly positionLabel?: string;
|
|
63
|
+
/**
|
|
64
|
+
* The locale the position's numbers are written in. Absent or empty is the
|
|
65
|
+
* runtime's own.
|
|
66
|
+
*/
|
|
67
|
+
readonly locale?: string;
|
|
37
68
|
}
|
|
38
69
|
/**
|
|
39
70
|
* Which reading a pointer is nearest, for a chart that draws no markers.
|
|
@@ -62,8 +93,9 @@ export interface ChartPointerHost extends ReactiveControllerHost, HTMLElement {
|
|
|
62
93
|
* **The keyboard moves the same reading, which is what makes it the reading
|
|
63
94
|
* and not the pointer's.** A chart's plot takes focus (`tabindex="0"` on the
|
|
64
95
|
* 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
|
-
*
|
|
96
|
+
* readings, Home and End go to the first and the last, PageUp and PageDown
|
|
97
|
+
* move a page of readings, and the other pair of arrows walks the series
|
|
98
|
+
* within a reading. Escape puts the bubble away, as it
|
|
67
99
|
* does a tooltip. The tooltip follows because it already follows `at`, and the
|
|
68
100
|
* chart's readout, a polite live region `drawTooltip` renders, says the
|
|
69
101
|
* reading in words. It speaks only for a key: a pointer crossing a chart is a
|
|
@@ -125,8 +157,41 @@ export declare class ChartPointerController implements ReactiveController {
|
|
|
125
157
|
* from, and the bubble lists every one of them.
|
|
126
158
|
*/
|
|
127
159
|
get column(): number | undefined;
|
|
128
|
-
/**
|
|
160
|
+
/**
|
|
161
|
+
* Whether the series drawn from the cell at this place in a row is shown.
|
|
162
|
+
*
|
|
163
|
+
* The readout asks, so a reading said whole leaves out what a legend hid,
|
|
164
|
+
* as the drawing does.
|
|
165
|
+
*/
|
|
166
|
+
shows(cell: number): boolean;
|
|
167
|
+
/**
|
|
168
|
+
* How far PageUp and PageDown move: four columns of a grid, which is four
|
|
169
|
+
* weeks of a calendar heatmap, a month near enough; and a tenth of the
|
|
170
|
+
* readings otherwise, at least one.
|
|
171
|
+
*/
|
|
172
|
+
private page;
|
|
173
|
+
/**
|
|
174
|
+
* Where the reading stands among the shown readings, in the host's
|
|
175
|
+
* `positionLabel`, such as "2 of 12". Empty with no reading, and where the
|
|
176
|
+
* host gives no words.
|
|
177
|
+
*
|
|
178
|
+
* Counted among the shown readings, so a slice a legend hid is not one of
|
|
179
|
+
* the count.
|
|
180
|
+
*/
|
|
181
|
+
get position(): string;
|
|
182
|
+
/**
|
|
183
|
+
* The cells a series key can rest on: every column a series was drawn
|
|
184
|
+
* from, and is still drawn from.
|
|
185
|
+
*/
|
|
129
186
|
private columns;
|
|
187
|
+
/**
|
|
188
|
+
* The readings the keys walk, by place: every one, less those a legend hid.
|
|
189
|
+
*
|
|
190
|
+
* The keys step through this list, so a hidden
|
|
191
|
+
* slice is passed over as if it were not in the table, which is how the
|
|
192
|
+
* ring draws it.
|
|
193
|
+
*/
|
|
194
|
+
private shown;
|
|
130
195
|
/**
|
|
131
196
|
* Tells the tooltip its anchor moved, which nothing else would.
|
|
132
197
|
*
|
|
@@ -145,6 +210,9 @@ export declare class ChartPointerController implements ReactiveController {
|
|
|
145
210
|
/**
|
|
146
211
|
* The box the readings are laid out in, which is the plot and not the host.
|
|
147
212
|
*
|
|
213
|
+
* Found by its part, or by the id every chart gives its plot, which is how
|
|
214
|
+
* a sparkline's drawing, whose part is `svg`, is found.
|
|
215
|
+
*
|
|
148
216
|
* The host also holds the row of labels, so measuring against it would map
|
|
149
217
|
* the pointer over a box taller than the drawing. That mattered the moment a
|
|
150
218
|
* 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,32 @@ export class ChartPointerController {
|
|
|
24
27
|
}
|
|
25
28
|
return;
|
|
26
29
|
}
|
|
27
|
-
const
|
|
30
|
+
const paged = (event.key === 'PageDown' || event.key === 'PageUp') && this.at >= 0
|
|
31
|
+
? this.host.pageFrom?.(this.at, event.key === 'PageDown')
|
|
32
|
+
: undefined;
|
|
33
|
+
if (paged !== undefined && shown.includes(paged)) {
|
|
34
|
+
event.preventDefault();
|
|
35
|
+
if (paged !== this.at) {
|
|
36
|
+
this.at = paged;
|
|
37
|
+
this.keyed = true;
|
|
38
|
+
this.moved = true;
|
|
39
|
+
this.host.requestUpdate();
|
|
40
|
+
}
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const next = stepReading(event.key, { at: shown.indexOf(this.at), series: this.series }, {
|
|
28
44
|
axis: this.axis,
|
|
29
45
|
count,
|
|
30
46
|
grid: this.grid,
|
|
47
|
+
page: this.page(count),
|
|
31
48
|
rtl: isRtl(this.host),
|
|
32
49
|
series: this.columns().length,
|
|
33
50
|
});
|
|
34
51
|
if (next === undefined) {
|
|
35
52
|
return;
|
|
36
53
|
}
|
|
37
|
-
const
|
|
54
|
+
const at = shown[next.at] ?? -1;
|
|
55
|
+
const { series } = next;
|
|
38
56
|
event.preventDefault();
|
|
39
57
|
if (at === this.at && series === this.series && this.keyed) {
|
|
40
58
|
return;
|
|
@@ -56,10 +74,11 @@ export class ChartPointerController {
|
|
|
56
74
|
}
|
|
57
75
|
catch {
|
|
58
76
|
}
|
|
59
|
-
|
|
77
|
+
const first = this.shown()[0];
|
|
78
|
+
if (!visible || first === undefined) {
|
|
60
79
|
return;
|
|
61
80
|
}
|
|
62
|
-
this.at =
|
|
81
|
+
this.at = first;
|
|
63
82
|
this.keyed = true;
|
|
64
83
|
this.moved = true;
|
|
65
84
|
this.host.requestUpdate();
|
|
@@ -123,12 +142,32 @@ export class ChartPointerController {
|
|
|
123
142
|
get column() {
|
|
124
143
|
return this.series < 0 ? undefined : this.columns()[this.series];
|
|
125
144
|
}
|
|
145
|
+
shows(cell) {
|
|
146
|
+
return this.host.showsColumn?.(cell) !== false;
|
|
147
|
+
}
|
|
148
|
+
page(count) {
|
|
149
|
+
return this.grid > 1 ? this.grid * 4 : Math.max(1, Math.round(count / 10));
|
|
150
|
+
}
|
|
151
|
+
get position() {
|
|
152
|
+
const words = this.host.positionLabel ?? '';
|
|
153
|
+
const shown = this.shown();
|
|
154
|
+
const place = shown.indexOf(this.at);
|
|
155
|
+
if (words === '' || place < 0) {
|
|
156
|
+
return '';
|
|
157
|
+
}
|
|
158
|
+
const format = formatNumbers(this.host.locale ?? '');
|
|
159
|
+
return fillTemplate(words, { count: format(shown.length), position: format(place + 1) });
|
|
160
|
+
}
|
|
126
161
|
columns() {
|
|
127
162
|
const host = this.host;
|
|
128
|
-
|
|
129
|
-
|
|
163
|
+
return (host.plottedColumns ?? []).filter((one) => (host.seriesOf === undefined || host.seriesOf(one) !== undefined) && this.shows(one));
|
|
164
|
+
}
|
|
165
|
+
shown() {
|
|
166
|
+
const host = this.host;
|
|
167
|
+
const all = Array.from({ length: host.readings }, (_, at) => at);
|
|
168
|
+
return host.showsReading === undefined
|
|
130
169
|
? all
|
|
131
|
-
: all.filter((
|
|
170
|
+
: all.filter((at) => host.showsReading?.(at) !== false);
|
|
132
171
|
}
|
|
133
172
|
hostUpdated() {
|
|
134
173
|
if (!this.moved) {
|
|
@@ -141,7 +180,9 @@ export class ChartPointerController {
|
|
|
141
180
|
}
|
|
142
181
|
box() {
|
|
143
182
|
if (!this.plot?.isConnected) {
|
|
144
|
-
this.plot =
|
|
183
|
+
this.plot =
|
|
184
|
+
this.host.renderRoot.querySelector(`[part="plot"], #${CHART_PLOT}`) ??
|
|
185
|
+
undefined;
|
|
145
186
|
}
|
|
146
187
|
return this.plot?.getBoundingClientRect();
|
|
147
188
|
}
|
|
@@ -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);
|
|
@@ -7,8 +7,11 @@ export interface CopyOptions {
|
|
|
7
7
|
* On a timer rather than on the pointer leaving, so it survives a hand that
|
|
8
8
|
* has already moved on: the press and the reading of it are two moments, and
|
|
9
9
|
* a mark that vanishes with the cursor is one a fast reader never sees.
|
|
10
|
+
*
|
|
11
|
+
* A function is read at each copy, for a host whose duration is a property
|
|
12
|
+
* a page can change, as other controllers' options are.
|
|
10
13
|
*/
|
|
11
|
-
after?: number;
|
|
14
|
+
after?: number | (() => number);
|
|
12
15
|
}
|
|
13
16
|
/**
|
|
14
17
|
* Puts text on the clipboard and holds a confirmation for a moment.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { HelixCopyEvent } from '../../events/events.js';
|
|
2
2
|
import { deepActiveElement } from '../../utils/focusable-elements/focusable-elements.js';
|
|
3
|
+
const read = (option) => typeof option === 'function' ? option() : option;
|
|
3
4
|
const write = async (text) => {
|
|
4
5
|
try {
|
|
5
6
|
await navigator.clipboard.writeText(text);
|
|
@@ -53,7 +54,7 @@ export class CopyController {
|
|
|
53
54
|
this.copied = false;
|
|
54
55
|
this.failed = false;
|
|
55
56
|
this.host.requestUpdate();
|
|
56
|
-
}, this.options.after ?? 1200);
|
|
57
|
+
}, read(this.options.after) ?? 1200);
|
|
57
58
|
return wrote;
|
|
58
59
|
}
|
|
59
60
|
hostDisconnected() {
|
|
@@ -46,7 +46,10 @@ export declare class CountdownController implements ReactiveController {
|
|
|
46
46
|
pause(): void;
|
|
47
47
|
/** Runs the clock again from where it stopped. */
|
|
48
48
|
resume(): void;
|
|
49
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* Stops the clock for good, as a dismissal does: nothing is left to resume
|
|
51
|
+
* until the next `start`, so a hold and a release after it run nothing.
|
|
52
|
+
*/
|
|
50
53
|
cancel(): void;
|
|
51
54
|
/** One more reason to hold the clock, such as a pointer arriving. */
|
|
52
55
|
hold(): void;
|
|
@@ -36,13 +36,15 @@ export class CountdownController {
|
|
|
36
36
|
this.startedAt = Date.now();
|
|
37
37
|
this.options.paused?.(false);
|
|
38
38
|
this.timer = setTimeout(() => {
|
|
39
|
-
this.
|
|
39
|
+
this.cancel();
|
|
40
40
|
this.options.done();
|
|
41
41
|
}, this.remaining);
|
|
42
42
|
}
|
|
43
43
|
cancel() {
|
|
44
44
|
clearTimeout(this.timer);
|
|
45
45
|
this.timer = undefined;
|
|
46
|
+
this.remaining = undefined;
|
|
47
|
+
this.startedAt = undefined;
|
|
46
48
|
}
|
|
47
49
|
hold() {
|
|
48
50
|
this.holds += 1;
|
|
@@ -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
|
/**
|
|
@@ -18,6 +19,11 @@ export interface NavigableItem {
|
|
|
18
19
|
select(): void;
|
|
19
20
|
/** Whether the item is the current one, which is where movement starts. */
|
|
20
21
|
selected: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* The words a reader types the start of, for a set that types ahead with
|
|
24
|
+
* `typeaheadByWords`.
|
|
25
|
+
*/
|
|
26
|
+
readonly words?: string;
|
|
21
27
|
}
|
|
22
28
|
/** Where a move starts from: the item that has focus, or the chosen item. */
|
|
23
29
|
export type KeyboardOrigin = 'focus' | 'selection';
|
|
@@ -70,14 +76,15 @@ export interface KeyboardNavigationOptions {
|
|
|
70
76
|
*/
|
|
71
77
|
reserved?: () => string[];
|
|
72
78
|
/**
|
|
73
|
-
* The
|
|
74
|
-
*
|
|
79
|
+
* The search that turns on typeahead, built with `typeaheadBy` from the
|
|
80
|
+
* words of an item: a printable key moves to the next item whose words
|
|
81
|
+
* start with what was typed.
|
|
75
82
|
*
|
|
76
83
|
* Off unless given. A set whose items have no words a reader would type, or
|
|
77
84
|
* that holds a text field of its own, leaves it out. See `Typeahead` for how
|
|
78
85
|
* the letters are matched.
|
|
79
86
|
*/
|
|
80
|
-
typeahead?:
|
|
87
|
+
typeahead?: TypeaheadBy<NavigableItem>;
|
|
81
88
|
/**
|
|
82
89
|
* Whether the ends join up, which they do unless a set says otherwise.
|
|
83
90
|
*
|
|
@@ -98,54 +105,6 @@ export interface KeyboardNavigationOptions {
|
|
|
98
105
|
*/
|
|
99
106
|
wrap?: boolean;
|
|
100
107
|
}
|
|
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
108
|
/**
|
|
150
109
|
* Moves through a set of items with the arrow keys, and chooses as it goes.
|
|
151
110
|
*
|
|
@@ -171,9 +130,10 @@ export declare class Typeahead {
|
|
|
171
130
|
* Disabled items are skipped rather than stopped at, so a set with a gap in it
|
|
172
131
|
* still moves in one press.
|
|
173
132
|
*
|
|
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
|
|
133
|
+
* **Typeahead is opt-in.** Pass `typeahead`, built by `typeaheadBy` from a
|
|
134
|
+
* function that returns an item's words, and a printable key moves to the next
|
|
135
|
+
* item whose words start with the letters typed, choosing it where arriving
|
|
136
|
+
* chooses. A key that a text
|
|
177
137
|
* field inside the set is typing into is left to the field.
|
|
178
138
|
*
|
|
179
139
|
* A set that starts from focus rather than from the selection, or that moves
|
|
@@ -187,7 +147,6 @@ export declare class KeyboardNavigationController implements ReactiveController
|
|
|
187
147
|
private readonly selects;
|
|
188
148
|
private readonly reserved;
|
|
189
149
|
private readonly wrap;
|
|
190
|
-
private readonly words;
|
|
191
150
|
private readonly typeahead;
|
|
192
151
|
constructor(host: ReactiveControllerHost & HTMLElement, { items, origin, reserved, selects, typeahead, wrap, }: KeyboardNavigationOptions);
|
|
193
152
|
/** 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
|
+
}
|