@fusion.dev/helix-core 0.150.0 → 0.151.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.
@@ -1,4 +1,5 @@
1
1
  import type { ReactiveController, ReactiveControllerHost } from 'lit';
2
+ import type { ReadingDetail } from '../../events/details.js';
2
3
  /**
3
4
  * The id every chart puts on its plot, and the boundary a bubble is kept inside.
4
5
  *
@@ -65,7 +66,15 @@ export interface ChartPointerHost extends ReactiveControllerHost, HTMLElement {
65
66
  * the nearest `lang`, then the runtime's own, as `wordsLocale` does.
66
67
  */
67
68
  readonly locale?: string;
69
+ /** The table's rows, whose headings name a reading in `onReading`. */
70
+ readonly sourceRows?: ReadonlyArray<{
71
+ readonly label: string;
72
+ }>;
73
+ /** The heading of the column at this place in a row, which names a series in `onReading`. */
74
+ columnName?(cell: number): string;
68
75
  }
76
+ /** What `onReading` is told: the reading moved, or it was pressed. */
77
+ export type ReadingHeard = 'change' | 'press';
69
78
  /**
70
79
  * Which reading a pointer is nearest, for a chart that draws no markers.
71
80
  *
@@ -84,11 +93,13 @@ export interface ChartPointerHost extends ReactiveControllerHost, HTMLElement {
84
93
  * depending on which line the pointer drifted toward, which is a tooltip that
85
94
  * changes its mind while the reader holds still.
86
95
  *
87
- * **Coarse pointers get nothing.** A touch has no hover, so a tooltip driven by
88
- * one appears where a finger already covers it and stays after the finger
89
- * lifts. The table underneath is the readable version and is what a phone
90
- * should be given, so this listens for `pointermove` and ignores anything whose
91
- * `pointerType` is not fine.
96
+ * **A touch has no hover, so it moves nothing by passing over.** A tooltip
97
+ * driven by a finger dragging across would appear under the finger. So this
98
+ * listens for `pointermove` and ignores anything whose `pointerType` is not
99
+ * fine. **A tap is the touch reader's hover**, for a chart that hears its
100
+ * readings through `onReading`: it shows the reading tapped, as Chart.js does,
101
+ * and keeps it until a tap lands elsewhere, outside the chart or on another
102
+ * reading. A drag that scrolls the page is no tap and shows nothing.
92
103
  *
93
104
  * **The keyboard moves the same reading, which is what makes it the reading
94
105
  * and not the pointer's.** A chart's plot takes focus (`tabindex="0"` on the
@@ -145,6 +156,22 @@ export declare class ChartPointerController implements ReactiveController {
145
156
  * sides. The slices call `set` and this only holds the answer.
146
157
  */
147
158
  axis: 'block' | 'inline' | 'none';
159
+ /**
160
+ * Hears the reading: `change` each time it moves or is put away, and
161
+ * `press` when it is clicked, tapped, or pressed with Enter or Space.
162
+ *
163
+ * Set by a chart that sends `helix-reading-change` and
164
+ * `helix-reading-press`, which it does from here so the event classes are
165
+ * constructed in the chart that declares them. A chart that hears its
166
+ * readings also shows one on a tap.
167
+ */
168
+ onReading: ((heard: ReadingHeard, detail: ReadingDetail) => void) | undefined;
169
+ /** What last moved the reading, which `onReading` is told. */
170
+ private by;
171
+ /** The reading and the series `onReading` was last told of. */
172
+ private said;
173
+ /** Whether a tap shows the reading, which stays until a tap lands elsewhere. */
174
+ private tapped;
148
175
  constructor(host: ChartPointerHost);
149
176
  hostConnected(): void;
150
177
  hostDisconnected(): void;
@@ -207,6 +234,31 @@ export declare class ChartPointerController implements ReactiveController {
207
234
  * position until the render that follows.
208
235
  */
209
236
  hostUpdated(): void;
237
+ /**
238
+ * Tells `onReading` the reading moved, once for each move.
239
+ *
240
+ * After the update, from `hostUpdated`, so a listener reading the chart
241
+ * finds it already showing the reading it was told of.
242
+ */
243
+ private announce;
244
+ /** The reading as `onReading` is told it. */
245
+ private detail;
246
+ /**
247
+ * Shows the reading at `at` for a tap, and keeps it until a tap lands
248
+ * outside the chart. Public for a chart that finds the reading under a
249
+ * finger itself, a scatter's nearest point.
250
+ */
251
+ tapTo(at: number): void;
252
+ /** Stops waiting for a tap elsewhere. */
253
+ private untap;
254
+ /** A press outside the chart puts a tapped reading away. */
255
+ private readonly away;
256
+ private readonly tap;
257
+ /**
258
+ * Tells `onReading` a reading was clicked or tapped, where the press landed
259
+ * on the plot and a reading is shown.
260
+ */
261
+ private readonly press;
210
262
  /**
211
263
  * The box the readings are laid out in, which is the plot and not the host.
212
264
  *
@@ -279,6 +331,11 @@ export declare class ChartPointerController implements ReactiveController {
279
331
  */
280
332
  private readonly arrive;
281
333
  private readonly depart;
334
+ /**
335
+ * The reading a pointer is over, by the slot it is in along `axis`, or
336
+ * `undefined` with nothing to measure.
337
+ */
338
+ private resolve;
282
339
  private readonly move;
283
340
  private readonly leave;
284
341
  }
@@ -10,6 +10,41 @@ export class ChartPointerController {
10
10
  this.keyed = false;
11
11
  this.series = -1;
12
12
  this.axis = 'inline';
13
+ this.by = 'mouse';
14
+ this.said = { at: -1, series: -1 };
15
+ this.tapped = false;
16
+ this.away = (event) => {
17
+ if (!event.composedPath().includes(this.host)) {
18
+ this.clear();
19
+ }
20
+ };
21
+ this.tap = (event) => {
22
+ if (event.pointerType !== 'touch' || !this.onReading || this.axis === 'none') {
23
+ return;
24
+ }
25
+ const at = this.resolve(event);
26
+ if (at !== undefined) {
27
+ this.tapTo(at);
28
+ }
29
+ };
30
+ this.press = (event) => {
31
+ if (!this.onReading || this.at < 0) {
32
+ return;
33
+ }
34
+ const onPlot = event
35
+ .composedPath()
36
+ .some((node) => node instanceof Element &&
37
+ node.id === CHART_PLOT &&
38
+ node.getRootNode() === this.host.renderRoot);
39
+ if (!onPlot) {
40
+ return;
41
+ }
42
+ const type = event.pointerType;
43
+ this.onReading('press', {
44
+ ...this.detail(),
45
+ pointerType: type === 'touch' || type === 'pen' || type === 'mouse' ? type : this.by,
46
+ });
47
+ };
13
48
  this.key = (event) => {
14
49
  if (!this.fromPlot(event) || event.altKey || event.ctrlKey || event.metaKey) {
15
50
  return;
@@ -26,6 +61,13 @@ export class ChartPointerController {
26
61
  }
27
62
  return;
28
63
  }
64
+ if ((event.key === 'Enter' || event.key === ' ') && this.onReading) {
65
+ if (this.at >= 0) {
66
+ event.preventDefault();
67
+ this.onReading('press', { ...this.detail(), pointerType: 'keyboard' });
68
+ }
69
+ return;
70
+ }
29
71
  const paged = (event.key === 'PageDown' || event.key === 'PageUp') && this.at >= 0
30
72
  ? this.host.pageFrom?.(this.at, event.key === 'PageDown')
31
73
  : undefined;
@@ -91,19 +133,12 @@ export class ChartPointerController {
91
133
  if (this.axis === 'none' || !this.accepts(event)) {
92
134
  return;
93
135
  }
94
- const box = this.box();
95
- const count = this.host.readings;
96
- const along = this.axis === 'block' ? box?.height : box?.width;
97
- if (!box || !along || count === 0) {
136
+ const next = this.resolve(event);
137
+ if (next === undefined) {
98
138
  return;
99
139
  }
100
- const from = this.axis === 'block'
101
- ? event.clientY - box.top
102
- : this.mirrored
103
- ? box.right - event.clientX
104
- : event.clientX - box.left;
105
- const slot = Math.floor((from / along) * count);
106
- const next = Math.min(Math.max(slot, 0), count - 1);
140
+ this.untap();
141
+ this.by = event.pointerType === 'pen' ? 'pen' : 'mouse';
107
142
  if (next !== this.at) {
108
143
  this.at = next;
109
144
  this.keyed = false;
@@ -113,7 +148,7 @@ export class ChartPointerController {
113
148
  }
114
149
  };
115
150
  this.leave = () => {
116
- if (this.at !== -1 && !this.keyed) {
151
+ if (this.at !== -1 && !this.keyed && !this.tapped) {
117
152
  this.at = -1;
118
153
  this.host.requestUpdate();
119
154
  }
@@ -127,6 +162,8 @@ export class ChartPointerController {
127
162
  this.host.addEventListener('keydown', this.key);
128
163
  this.host.addEventListener('focusin', this.arrive);
129
164
  this.host.addEventListener('focusout', this.depart);
165
+ this.host.addEventListener('pointerup', this.tap);
166
+ this.host.addEventListener('click', this.press);
130
167
  }
131
168
  hostDisconnected() {
132
169
  this.host.removeEventListener('pointermove', this.move);
@@ -134,9 +171,13 @@ export class ChartPointerController {
134
171
  this.host.removeEventListener('keydown', this.key);
135
172
  this.host.removeEventListener('focusin', this.arrive);
136
173
  this.host.removeEventListener('focusout', this.depart);
174
+ this.host.removeEventListener('pointerup', this.tap);
175
+ this.host.removeEventListener('click', this.press);
176
+ this.untap();
137
177
  this.at = -1;
138
178
  this.series = -1;
139
179
  this.keyed = false;
180
+ this.said = { at: -1, series: -1 };
140
181
  }
141
182
  get column() {
142
183
  return this.series < 0 ? undefined : this.columns()[this.series];
@@ -171,6 +212,7 @@ export class ChartPointerController {
171
212
  : all.filter((at) => host.showsReading?.(at) !== false);
172
213
  }
173
214
  hostUpdated() {
215
+ this.announce();
174
216
  if (!this.moved) {
175
217
  return;
176
218
  }
@@ -179,6 +221,46 @@ export class ChartPointerController {
179
221
  .querySelector('[part="tooltip-anchor"]')
180
222
  ?.reposition?.();
181
223
  }
224
+ announce() {
225
+ if (!this.onReading || (this.at === this.said.at && this.series === this.said.series)) {
226
+ return;
227
+ }
228
+ this.said = { at: this.at, series: this.series };
229
+ this.onReading('change', this.detail());
230
+ }
231
+ detail() {
232
+ const at = this.at;
233
+ const column = this.column;
234
+ return {
235
+ index: at,
236
+ label: at < 0 ? '' : (this.host.sourceRows?.[at]?.label ?? ''),
237
+ pointerType: this.keyed ? 'keyboard' : this.by,
238
+ series: at < 0 || column === undefined ? '' : (this.host.columnName?.(column) ?? ''),
239
+ };
240
+ }
241
+ tapTo(at) {
242
+ if (at < 0) {
243
+ return;
244
+ }
245
+ this.by = 'touch';
246
+ if (!this.tapped) {
247
+ this.tapped = true;
248
+ this.host.ownerDocument.addEventListener('pointerdown', this.away, true);
249
+ }
250
+ if (at !== this.at || this.keyed) {
251
+ this.at = at;
252
+ this.keyed = false;
253
+ this.series = -1;
254
+ this.moved = true;
255
+ this.host.requestUpdate();
256
+ }
257
+ }
258
+ untap() {
259
+ if (this.tapped) {
260
+ this.tapped = false;
261
+ this.host.ownerDocument.removeEventListener('pointerdown', this.away, true);
262
+ }
263
+ }
182
264
  box() {
183
265
  if (!this.plot?.isConnected) {
184
266
  this.plot =
@@ -195,6 +277,8 @@ export class ChartPointerController {
195
277
  return type === 'mouse' || type === 'pen';
196
278
  }
197
279
  set(at) {
280
+ this.untap();
281
+ this.by = 'mouse';
198
282
  if (at !== this.at) {
199
283
  this.at = at;
200
284
  this.keyed = false;
@@ -209,6 +293,7 @@ export class ChartPointerController {
209
293
  target.getRootNode() === this.host.renderRoot);
210
294
  }
211
295
  clear() {
296
+ this.untap();
212
297
  const was = this.at;
213
298
  this.at = -1;
214
299
  this.series = -1;
@@ -217,4 +302,19 @@ export class ChartPointerController {
217
302
  this.host.requestUpdate();
218
303
  }
219
304
  }
305
+ resolve(event) {
306
+ const box = this.box();
307
+ const count = this.host.readings;
308
+ const along = this.axis === 'block' ? box?.height : box?.width;
309
+ if (!box || !along || count === 0) {
310
+ return undefined;
311
+ }
312
+ const from = this.axis === 'block'
313
+ ? event.clientY - box.top
314
+ : this.mirrored
315
+ ? box.right - event.clientX
316
+ : event.clientX - box.left;
317
+ const slot = Math.floor((from / along) * count);
318
+ return Math.min(Math.max(slot, 0), count - 1);
319
+ }
220
320
  }
@@ -382,6 +382,20 @@ export interface PressDetail {
382
382
  /** What the press came from. */
383
383
  pointerType: PressPointerType;
384
384
  }
385
+ /** Detail carried by `helix-reading-change` and `helix-reading-press`. */
386
+ export interface ReadingDetail {
387
+ /** The reading's place among the table's rows, counting from 0, or `-1` once no reading is shown. */
388
+ index: number;
389
+ /** The reading's name, its row's heading, such as `March`. Empty with no reading. */
390
+ label: string;
391
+ /** What moved to the reading or pressed it. */
392
+ pointerType: 'keyboard' | 'mouse' | 'pen' | 'touch';
393
+ /**
394
+ * The heading of the series the up and down keys rest on within the
395
+ * reading, or `''` while the whole reading is read.
396
+ */
397
+ series: string;
398
+ }
385
399
  /** Detail carried by `helix-band`. */
386
400
  export interface BandDetail {
387
401
  /** The band the reading is in now, or `''` where it is in none. */
@@ -94,6 +94,8 @@ import { HelixPreviewEvent } from './preview.js';
94
94
  import { HelixPreviousEvent } from './previous.js';
95
95
  import { HelixRangeChangeEvent } from './range-change.js';
96
96
  import { HelixReadEvent } from './read.js';
97
+ import { HelixReadingChangeEvent } from './reading-change.js';
98
+ import { HelixReadingPressEvent } from './reading-press.js';
97
99
  import { HelixReconnectEvent } from './reconnect.js';
98
100
  import { HelixRejectEvent } from './reject.js';
99
101
  import { HelixRelabelEvent } from './relabel.js';
@@ -116,9 +118,9 @@ import { HelixToggleEvent } from './toggle.js';
116
118
  import { HelixTourAskEvent } from './tour-ask.js';
117
119
  import { HelixTourStatusEvent } from './tour-status.js';
118
120
  import { HelixTypingEvent } from './typing.js';
119
- export type { ActivateDetail, AuraFallbackDetail, BandDetail, CanvasView, CaretDetail, ChangeDetail, CompleteDetail, ConnectDetail, ConsoleDetail, CopyDetail, CreateDetail, DismissDetail, FacetDetail, FilterDetail, GraphFilterDetail, GraphLayoutDetail, GraphPartChangeDetail, GraphSignalDetail, MapClusterDetail, MapPanDetail, MapPartChangeDetail, MapRotateDetail, MapTiltDetail, MapZoomDetail, MoveDetail, NavigateDetail, OpenDetail, PressDetail, PressPointerType, RangeDetail, ReadDetail, ReconnectDetail, Refusal, RefusedFile, RejectDetail, RelabelDetail, RemoveDetail, ReorderDetail, ResizeDetail, ScrolledDetail, SelectDetail, SendDetail, ShortcutDetail, SkipDetail, SortDetail, ToggleDetail, TourAskDetail, TourStatusDetail, TypingDetail, ViewportPanDetail, ViewportZoomDetail, } from './details.js';
121
+ export type { ActivateDetail, AuraFallbackDetail, BandDetail, CanvasView, CaretDetail, ChangeDetail, CompleteDetail, ConnectDetail, ConsoleDetail, CopyDetail, CreateDetail, DismissDetail, FacetDetail, FilterDetail, GraphFilterDetail, GraphLayoutDetail, GraphPartChangeDetail, GraphSignalDetail, MapClusterDetail, MapPanDetail, MapPartChangeDetail, MapRotateDetail, MapTiltDetail, MapZoomDetail, MoveDetail, NavigateDetail, OpenDetail, PressDetail, PressPointerType, RangeDetail, ReadDetail, ReadingDetail, ReconnectDetail, Refusal, RefusedFile, RejectDetail, RelabelDetail, RemoveDetail, ReorderDetail, ResizeDetail, ScrolledDetail, SelectDetail, SendDetail, ShortcutDetail, SkipDetail, SortDetail, ToggleDetail, TourAskDetail, TourStatusDetail, TypingDetail, ViewportPanDetail, ViewportZoomDetail, } from './details.js';
120
122
  export { helixEventNames } from './names.js';
121
- export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, };
123
+ export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, };
122
124
  /**
123
125
  * Every event class, and the one place a new one is registered: a class in a
124
126
  * module of its own, imported above, and named here and in `names.ts`.
@@ -198,6 +200,8 @@ declare const registry: {
198
200
  readonly HelixPreviousEvent: typeof HelixPreviousEvent;
199
201
  readonly HelixRangeChangeEvent: typeof HelixRangeChangeEvent;
200
202
  readonly HelixReadEvent: typeof HelixReadEvent;
203
+ readonly HelixReadingChangeEvent: typeof HelixReadingChangeEvent;
204
+ readonly HelixReadingPressEvent: typeof HelixReadingPressEvent;
201
205
  readonly HelixReconnectEvent: typeof HelixReconnectEvent;
202
206
  readonly HelixRejectEvent: typeof HelixRejectEvent;
203
207
  readonly HelixRelabelEvent: typeof HelixRelabelEvent;
@@ -64,6 +64,8 @@ import { HelixPreviewEvent } from './preview.js';
64
64
  import { HelixPreviousEvent } from './previous.js';
65
65
  import { HelixRangeChangeEvent } from './range-change.js';
66
66
  import { HelixReadEvent } from './read.js';
67
+ import { HelixReadingChangeEvent } from './reading-change.js';
68
+ import { HelixReadingPressEvent } from './reading-press.js';
67
69
  import { HelixReconnectEvent } from './reconnect.js';
68
70
  import { HelixRejectEvent } from './reject.js';
69
71
  import { HelixRelabelEvent } from './relabel.js';
@@ -87,7 +89,7 @@ import { HelixTourAskEvent } from './tour-ask.js';
87
89
  import { HelixTourStatusEvent } from './tour-status.js';
88
90
  import { HelixTypingEvent } from './typing.js';
89
91
  export { helixEventNames } from './names.js';
90
- export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, };
92
+ export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, };
91
93
  const registry = {
92
94
  HelixActionEvent,
93
95
  HelixActivateEvent,
@@ -155,6 +157,8 @@ const registry = {
155
157
  HelixPreviousEvent,
156
158
  HelixRangeChangeEvent,
157
159
  HelixReadEvent,
160
+ HelixReadingChangeEvent,
161
+ HelixReadingPressEvent,
158
162
  HelixReconnectEvent,
159
163
  HelixRejectEvent,
160
164
  HelixRelabelEvent,
@@ -6,7 +6,8 @@ export const helixEventNames = new Set(('action activate aura-fallback band befo
6
6
  'filtered graph-filter graph-layout graph-pan graph-part-change graph-ready ' +
7
7
  'graph-signal graph-zoom history load load-more map-cluster map-pan map-part-change ' +
8
8
  'map-ready map-rotate map-tilt map-zoom move navigate next panel-resize pin press ' +
9
- 'preview previous range-change read reconnect reject relabel remove reorder ' +
9
+ 'preview previous range-change read reading-change reading-press reconnect reject ' +
10
+ 'relabel remove reorder ' +
10
11
  'reordered resize resized sample-end sample-start scrolled select selected send ' +
11
12
  'shortcut sort sorted split toggle tour-ask tour-status typing')
12
13
  .split(' ')
@@ -0,0 +1,14 @@
1
+ import type { ReadingDetail } from './details.js';
2
+ /**
3
+ * A chart moved to a reading, or put its reading away: a pointer crossed into
4
+ * one, a tap or a key landed on one, or the pointer left. Chart.js's
5
+ * `onHover`.
6
+ *
7
+ * Sent once for each change, never for a pointer moving within the reading it
8
+ * is already on. `index` is `-1` once no reading is shown. Not cancelable,
9
+ * since the chart has already moved. Bubbles and is composed.
10
+ */
11
+ export declare class HelixReadingChangeEvent extends CustomEvent<ReadingDetail> {
12
+ static readonly eventName = "helix-reading-change";
13
+ constructor(detail: ReadingDetail);
14
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixReadingChangeEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-reading-change'; }
3
+ constructor(detail) {
4
+ super(HelixReadingChangeEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: false,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -0,0 +1,13 @@
1
+ import type { ReadingDetail } from './details.js';
2
+ /**
3
+ * A reading of a chart was pressed: clicked, tapped, or Enter or Space on the
4
+ * plot while the keys rest on it. Chart.js's `onClick`.
5
+ *
6
+ * For a page that opens what a reading stands for, such as the month behind a
7
+ * column. Not cancelable, since a chart does nothing of its own on a press.
8
+ * Bubbles and is composed.
9
+ */
10
+ export declare class HelixReadingPressEvent extends CustomEvent<ReadingDetail> {
11
+ static readonly eventName = "helix-reading-press";
12
+ constructor(detail: ReadingDetail);
13
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixReadingPressEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-reading-press'; }
3
+ constructor(detail) {
4
+ super(HelixReadingPressEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: false,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -7,9 +7,10 @@ const BOX_SIZING = '*,::before,::after{box-sizing:border-box}';
7
7
  const HIDDEN = ":host([hidden]:not([hidden='until-found'])){display:none}";
8
8
  const SCROLLER = '[data-scroller]{overflow:auto}';
9
9
  const VIRTUAL = '[data-virtual]{overflow-anchor:none}';
10
+ const SPOKEN = '[data-spoken]{position:absolute;inline-size:1px;block-size:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}';
10
11
  const MIRROR = ':host(:dir(rtl)) [data-mirror]{scale:-1 1}';
11
12
  const SETTLED = ':host(:not(:state(settled))),:host(:not(:state(settled))) *{transition:none!important}';
12
- const BASE = unsafeCSS(BOX_SIZING + HIDDEN + SCROLLER + VIRTUAL + MIRROR + SETTLED);
13
+ const BASE = unsafeCSS(BOX_SIZING + HIDDEN + SCROLLER + VIRTUAL + SPOKEN + MIRROR + SETTLED);
13
14
  const LOOK_EVERY = 16;
14
15
  const LOOK_FOR = 96;
15
16
  export class HelixElement extends LitElement {
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  export { auditName } from '@fusion.dev/helix-core/audits/name';
2
2
  export { AriaForwardController, type AriaForwardOptions, } from './controllers/aria-forward-controller/aria-forward-controller.js';
3
3
  export { ArrivalController, type ArrivalOptions, } from './controllers/arrival-controller/arrival-controller.js';
4
- export { ChartPointerController, type ChartPointerHost, } from './controllers/chart-pointer-controller/chart-pointer-controller.js';
4
+ export { ChartPointerController, type ChartPointerHost, type ReadingHeard, } from './controllers/chart-pointer-controller/chart-pointer-controller.js';
5
5
  export { ChildrenController } from './controllers/children-controller/children-controller.js';
6
6
  export { CommandController, type CommandOptions, HelixFallbackCommandEvent, supportsInvokers, } from './controllers/command-controller/command-controller.js';
7
7
  export { CopyController, type CopyOptions, } from './controllers/copy-controller/copy-controller.js';
@@ -33,7 +33,7 @@ export { SwipeController, type SwipeOptions, } from './controllers/swipe-control
33
33
  export { type TokenColor, TokenColorController, } from './controllers/token-color-controller/token-color-controller.js';
34
34
  export { type Rendered, VirtualizeController, type VirtualizeOptions, type Window as VirtualizeWindow, } from './controllers/virtualize-controller/virtualize-controller.js';
35
35
  export { eventsForTag, registerElementEvents } from './events/element-events.js';
36
- export { type ActivateDetail, type AuraFallbackDetail, type BandDetail, type CanvasView, type CaretDetail, type ChangeDetail, type CompleteDetail, type ConnectDetail, type ConsoleDetail, type CopyDetail, type CreateDetail, type DismissDetail, type FacetDetail, type FilterDetail, type GraphFilterDetail, type GraphLayoutDetail, type GraphPartChangeDetail, type GraphSignalDetail, HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, type MapClusterDetail, type MapPanDetail, type MapPartChangeDetail, type MapRotateDetail, type MapTiltDetail, type MapZoomDetail, type MoveDetail, type NavigateDetail, type OpenDetail, type PressDetail, type PressPointerType, type RangeDetail, type ReadDetail, type ReconnectDetail, type Refusal, type RefusedFile, type RejectDetail, type RelabelDetail, type RemoveDetail, type ReorderDetail, type ResizeDetail, type ScrolledDetail, type SelectDetail, type SendDetail, type ShortcutDetail, type SkipDetail, type SortDetail, type ToggleDetail, type TourStatusDetail, type TypingDetail, type ViewportPanDetail, type ViewportZoomDetail, } from './events/events.js';
36
+ export { type ActivateDetail, type AuraFallbackDetail, type BandDetail, type CanvasView, type CaretDetail, type ChangeDetail, type CompleteDetail, type ConnectDetail, type ConsoleDetail, type CopyDetail, type CreateDetail, type DismissDetail, type FacetDetail, type FilterDetail, type GraphFilterDetail, type GraphLayoutDetail, type GraphPartChangeDetail, type GraphSignalDetail, HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, type MapClusterDetail, type MapPanDetail, type MapPartChangeDetail, type MapRotateDetail, type MapTiltDetail, type MapZoomDetail, type MoveDetail, type NavigateDetail, type OpenDetail, type PressDetail, type PressPointerType, type RangeDetail, type ReadDetail, type ReadingDetail, type ReconnectDetail, type Refusal, type RefusedFile, type RejectDetail, type RelabelDetail, type RemoveDetail, type ReorderDetail, type ResizeDetail, type ScrolledDetail, type SelectDetail, type SendDetail, type ShortcutDetail, type SkipDetail, type SortDetail, type ToggleDetail, type TourStatusDetail, type TypingDetail, type ViewportPanDetail, type ViewportZoomDetail, } from './events/events.js';
37
37
  export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
38
38
  export { HelixFormElement } from './helix-form-element/helix-form-element.js';
39
39
  export { MixinChartSource, type MixinChartSourceInterface, PALETTE, PLOT_HEIGHT, PLOT_WIDTH, POSITION_LABEL, seriesIndex, seriesNames, } from './mixins/mixin-chart-source/mixin-chart-source.js';
@@ -74,6 +74,7 @@ export { segmentName } from './utils/date-segments/date-segments.js';
74
74
  export { type DrawDismissOptions, drawDismiss, drawDismissGlyph, } from './utils/draw-dismiss/draw-dismiss.js';
75
75
  export { type DrawIconOptions, drawIcon } from './utils/draw-icon/draw-icon.js';
76
76
  export { CHART_PLOT, drawTooltip, type ReadingCursor } from './utils/draw-tooltip/draw-tooltip.js';
77
+ export { drawValueAxis } from './utils/draw-value-axis/draw-value-axis.js';
77
78
  export { elapsedTime } from './utils/elapsed-time/elapsed-time.js';
78
79
  export { type ElementByIdOptions, elementById, searchableById, } from './utils/element-by-id/element-by-id.js';
79
80
  export { exportParts } from './utils/export-parts/export-parts.js';
@@ -107,7 +108,7 @@ export { plainClick } from './utils/plain-click/plain-click.js';
107
108
  export { appleTouch, onAndroid, onApple, type Platform } from './utils/platform/platform.js';
108
109
  export { pressType, type RecentPress } from './utils/press-type/press-type.js';
109
110
  export { rangeAdd } from './utils/range-add/range-add.js';
110
- export { type ColorBytes, readColor, rgbOf } from './utils/read-color/read-color.js';
111
+ export { type ColorBytes, type ColorBytesAlpha, readColor, readColorAlpha, rgbOf, } from './utils/read-color/read-color.js';
111
112
  export { byRow, type Extremes, extremesOf, type Row, type RowCell, readRows, readSeries, type Series, type SeriesPoint, seriesKey, unbroken, } from './utils/read-series/read-series.js';
112
113
  export { type ElementsProperty, linkDescription, reflectElements, unlinkDescription, } from './utils/reflect-elements/reflect-elements.js';
113
114
  export { type Relative, type RelativeOptions, relativeTime, } from './utils/relative-time/relative-time.js';
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ export { SwipeController, } from './controllers/swipe-controller/swipe-controlle
33
33
  export { TokenColorController, } from './controllers/token-color-controller/token-color-controller.js';
34
34
  export { VirtualizeController, } from './controllers/virtualize-controller/virtualize-controller.js';
35
35
  export { eventsForTag, registerElementEvents } from './events/element-events.js';
36
- export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, } from './events/events.js';
36
+ export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, } from './events/events.js';
37
37
  export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
38
38
  export { HelixFormElement } from './helix-form-element/helix-form-element.js';
39
39
  export { MixinChartSource, PALETTE, PLOT_HEIGHT, PLOT_WIDTH, POSITION_LABEL, seriesIndex, seriesNames, } from './mixins/mixin-chart-source/mixin-chart-source.js';
@@ -74,6 +74,7 @@ export { segmentName } from './utils/date-segments/date-segments.js';
74
74
  export { drawDismiss, drawDismissGlyph, } from './utils/draw-dismiss/draw-dismiss.js';
75
75
  export { drawIcon } from './utils/draw-icon/draw-icon.js';
76
76
  export { CHART_PLOT, drawTooltip } from './utils/draw-tooltip/draw-tooltip.js';
77
+ export { drawValueAxis } from './utils/draw-value-axis/draw-value-axis.js';
77
78
  export { elapsedTime } from './utils/elapsed-time/elapsed-time.js';
78
79
  export { elementById, searchableById, } from './utils/element-by-id/element-by-id.js';
79
80
  export { exportParts } from './utils/export-parts/export-parts.js';
@@ -107,7 +108,7 @@ export { plainClick } from './utils/plain-click/plain-click.js';
107
108
  export { appleTouch, onAndroid, onApple } from './utils/platform/platform.js';
108
109
  export { pressType } from './utils/press-type/press-type.js';
109
110
  export { rangeAdd } from './utils/range-add/range-add.js';
110
- export { readColor, rgbOf } from './utils/read-color/read-color.js';
111
+ export { readColor, readColorAlpha, rgbOf, } from './utils/read-color/read-color.js';
111
112
  export { byRow, extremesOf, readRows, readSeries, seriesKey, unbroken, } from './utils/read-series/read-series.js';
112
113
  export { linkDescription, reflectElements, unlinkDescription, } from './utils/reflect-elements/reflect-elements.js';
113
114
  export { relativeTime, } from './utils/relative-time/relative-time.js';
@@ -29,6 +29,11 @@ export declare class CollectionElement {
29
29
  protected renderLive(hasContent: boolean): TemplateResult;
30
30
  /** News the component has for the live region while there are rows and nothing is loading. */
31
31
  protected announced: string;
32
+ /**
33
+ * Whether the status line is an `empty` or `loading` slot, with the text as
34
+ * its fallback. A family that turns it on documents the two slots.
35
+ */
36
+ protected statusSlots: boolean;
32
37
  /** Binds to a rows slot's `slotchange`, and answers `hasRows` from it. */
33
38
  protected countRows(event: Event): void;
34
39
  /** What the rows slot is given, read from the host so a first render has it. */
@@ -17,6 +17,7 @@ export const MixinCollection = (Base) => {
17
17
  this.slotCounted = false;
18
18
  this.slotRows = 0;
19
19
  this.announced = '';
20
+ this.statusSlots = false;
20
21
  }
21
22
  static { this.words = ''; }
22
23
  countRows(event) {
@@ -49,7 +50,12 @@ export const MixinCollection = (Base) => {
49
50
  return nothing;
50
51
  }
51
52
  const text = this.loading ? this.loadingText : this.emptyText;
52
- const words = cell ? html `<span role=${cell}>${text}</span>` : text;
53
+ const shown = this.statusSlots
54
+ ? this.loading
55
+ ? html `<slot name="loading">${text}</slot>`
56
+ : html `<slot name="empty">${text}</slot>`
57
+ : text;
58
+ const words = cell ? html `<span role=${cell}>${shown}</span>` : shown;
53
59
  const row = cell ? 'row' : nothing;
54
60
  return this.loading
55
61
  ? html `<p part="loading" role=${row}>${words}</p>`
@@ -7,10 +7,16 @@
7
7
  */
8
8
  /** A chord's keys as they are shown, and what is shown between two of them. */
9
9
  export interface KeyNames {
10
- /** Each key's label, in the order the chord names them. */
10
+ /** Each key's label, modifiers first in the platform's order, then the rest as written. */
11
11
  keys: string[];
12
12
  /** What goes between two keys: `+`, a hyphen, or nothing. */
13
13
  separator: string;
14
+ /**
15
+ * The chord in words for a screen reader, such as `Shift Command P`, where a
16
+ * label is a glyph a reader would hear as a symbol. Empty when every label
17
+ * is a word already.
18
+ */
19
+ spoken: string;
14
20
  }
15
21
  /**
16
22
  * The labels of a chord's keys on a platform, with `own` labels in place of
@@ -18,7 +24,9 @@ export interface KeyNames {
18
24
  *
19
25
  * `parts` are the chord's names as `chordParts` splits them. A name `own`
20
26
  * holds takes that label, a name the platform knows takes its glyph or word,
21
- * and any other single character is shown in capitals.
27
+ * and any other single character is shown in capitals. **Modifiers come first,
28
+ * in the platform's order**, so one `keys` value is right on every platform:
29
+ * `mod+shift+p` is `⇧⌘P` on an Apple keyboard and `Ctrl+Shift+P` elsewhere.
22
30
  *
23
31
  * **On an Apple keyboard glyphs run together and words are joined with a
24
32
  * hyphen**, as Apple writes `Command-K`. A label of more than one character
@@ -26,5 +34,9 @@ export interface KeyNames {
26
34
  * nothing between the two ran them into `CommandK`. The platform's own `Esc`
27
35
  * and `Space` keep running on from a glyph, as `⌘Esc` always has. Everywhere
28
36
  * else keys are joined with `+`.
37
+ *
38
+ * `spoken` says the chord in words where a label is one of the platform's
39
+ * glyphs, such as `⌘` or `↑`, which a screen reader reads as a symbol or
40
+ * skips. A label from `own` is taken as words already.
29
41
  */
30
42
  export declare const keyNames: (parts: readonly string[], apple: boolean, own?: Readonly<Record<string, string>>) => KeyNames;