@fusion.dev/helix-headless 0.160.0 → 0.162.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.
Files changed (39) hide show
  1. package/custom-elements.json +1729 -50
  2. package/dist/canvas/root/canvas-root.d.ts +59 -2
  3. package/dist/canvas/root/canvas-root.js +123 -8
  4. package/dist/chat/message/chat-message.d.ts +8 -0
  5. package/dist/chat/message/chat-message.js +11 -0
  6. package/dist/chat/root/chat-root.d.ts +47 -1
  7. package/dist/chat/root/chat-root.js +130 -4
  8. package/dist/code-block/lines.d.ts +12 -0
  9. package/dist/code-block/lines.js +41 -0
  10. package/dist/code-block/root/code-block-root.d.ts +88 -5
  11. package/dist/code-block/root/code-block-root.js +154 -10
  12. package/dist/element-events.generated.js +4 -0
  13. package/dist/splitter/root/splitter-root.d.ts +15 -0
  14. package/dist/splitter/root/splitter-root.js +16 -2
  15. package/dist/table/grid-controller.d.ts +7 -1
  16. package/dist/table/grid-controller.js +9 -1
  17. package/dist/table/root/table-root.d.ts +122 -0
  18. package/dist/table/root/table-root.js +293 -17
  19. package/dist/table/row/table-row.d.ts +41 -0
  20. package/dist/table/row/table-row.js +56 -2
  21. package/dist/timeline/item/timeline-item.d.ts +47 -10
  22. package/dist/timeline/item/timeline-item.js +36 -4
  23. package/dist/video-playlist/item/video-playlist-item.d.ts +11 -0
  24. package/dist/video-playlist/item/video-playlist-item.js +5 -0
  25. package/dist/video-playlist/menu/video-playlist-menu.d.ts +6 -0
  26. package/dist/video-playlist/menu/video-playlist-menu.js +11 -0
  27. package/dist/video-playlist/root/video-playlist-root.d.ts +59 -5
  28. package/dist/video-playlist/root/video-playlist-root.js +82 -10
  29. package/dist/virtual-list/fill.d.ts +6 -1
  30. package/dist/virtual-list/fill.js +1 -1
  31. package/dist/virtual-list/keys.d.ts +8 -0
  32. package/dist/virtual-list/keys.js +20 -0
  33. package/dist/virtual-list/root/virtual-list-root.d.ts +98 -13
  34. package/dist/virtual-list/root/virtual-list-root.js +195 -20
  35. package/lint.json +1 -1
  36. package/package.json +5 -5
  37. package/types/jsx.d.ts +936 -68
  38. package/types/vue.d.ts +226 -12
  39. package/types/words.d.ts +79 -0
@@ -58,6 +58,16 @@ declare const HelixHeadlessCanvas_base: (new (...args: any[]) => import("@fusion
58
58
  * - What a key changes that a reader cannot see is said: where a card moved
59
59
  * to, its new size, how many cards are selected, and the zoom. A selected
60
60
  * card or connection says so when a reader arrives on it.
61
+ * - Control or Command with C copies the selected cards, and the connections
62
+ * between them, as a JSON Canvas document in text, which another board or
63
+ * an app that reads the format takes. A paste is your page's: listen for
64
+ * `paste` on the board, read the text with `fromJsonCanvas`, and add the
65
+ * cards it holds.
66
+ * - Control or Command with Z undoes the last move or resize the board made,
67
+ * and with Shift, or Control with Y, makes it again. `undo()` and `redo()`
68
+ * do the same from a script. Each asks with `helix-before-move` and tells
69
+ * with `helix-move`, as a move does, so a board that holds its positions in
70
+ * your state is undone through your state.
61
71
  *
62
72
  * Every drag also works with clicks, as WCAG 2.5.7 requires for a pointer that
63
73
  * cannot hold a button down. Click a selected card's move handle, a corner, a
@@ -198,6 +208,8 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
198
208
  * what the controls drive rather than the mechanism.
199
209
  */
200
210
  controlsLabel: string;
211
+ /** What screen readers hear after a copy, with `{count}` for the cards copied. */
212
+ copiedLabel: string;
201
213
  /** The board's name where `label` is empty. */
202
214
  fallbackLabel: string;
203
215
  /**
@@ -271,6 +283,8 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
271
283
  * `{to}`.
272
284
  */
273
285
  reconnectingLabel: string;
286
+ /** What screen readers hear after a move or a resize is made again. */
287
+ redoneLabel: string;
274
288
  /**
275
289
  * What screen readers hear after a key resizes a card, with `{name}` for the
276
290
  * card and `{width}` and `{height}` for its new size, in the document's
@@ -336,12 +350,12 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
336
350
  * keeps its place in it. Absent, cards land where they are let go.
337
351
  */
338
352
  snap?: number;
353
+ /** The text announced when a connection is stopped before it is requested. */
354
+ stoppedLabel: string;
339
355
  /**
340
356
  * A label being edited in place: whose, and what it said before.
341
357
  */
342
358
  private editing;
343
- /** The text announced when a connection is stopped before it is requested. */
344
- stoppedLabel: string;
345
359
  /**
346
360
  * What each tone means on this board, in words read out with the cards and
347
361
  * connections in it, such as `{"danger": "Blocked", "success": "Done"}`.
@@ -355,6 +369,8 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
355
369
  toneLabels: Partial<Record<CanvasTone, string>>;
356
370
  /** The hint shown when one finger swipes over the board with `gestures="cooperative"`. */
357
371
  twoFingerHintLabel: string;
372
+ /** What screen readers hear after a move or a resize is undone. */
373
+ undoneLabel: string;
358
374
  /** The line shown while the board, with `gestures="activate"`, has the gestures. */
359
375
  usingLabel: string;
360
376
  /**
@@ -770,6 +786,47 @@ export declare class HelixHeadlessCanvas extends HelixHeadlessCanvas_base {
770
786
  * Returns whether it applied, so a caller knows whether to report a finish.
771
787
  */
772
788
  private requestMove;
789
+ /**
790
+ * The moves and resizes the board made, oldest first, each as where its
791
+ * cards stood before and after, for `undo` to take back. At most 100.
792
+ */
793
+ private undoable;
794
+ /** The moves undone, most recent last, for `redo` to make again. */
795
+ private redoable;
796
+ /** Where the cards of the gesture in progress stood before its first step. */
797
+ private moving;
798
+ /** Whether a move is an undo or a redo, which history does not record again. */
799
+ private replaying;
800
+ /**
801
+ * Says a move is finished, and keeps it for `undo`: where its cards stood
802
+ * before the gesture, and where they stand now.
803
+ */
804
+ private finishMove;
805
+ /**
806
+ * Puts the cards of the last move or resize back where they stood, asking
807
+ * with `helix-before-move` first. Returns whether anything moved: false
808
+ * with nothing to undo, or when the request was refused.
809
+ */
810
+ undo(): boolean;
811
+ /**
812
+ * Makes the last move or resize `undo` took back again, asking with
813
+ * `helix-before-move` first. Returns whether anything moved.
814
+ */
815
+ redo(): boolean;
816
+ /** Moves the cards of the last entry of `from` to its `side`, and files it in `to`. */
817
+ private replay;
818
+ /**
819
+ * A copy on the board with cards selected writes them, and the connections
820
+ * between them, as a JSON Canvas document in text. Not from a field a card
821
+ * holds, nor over text a reader selected, which are the platform's to copy.
822
+ */
823
+ private readonly handleCopy;
824
+ /**
825
+ * Control or Command with Z undoes, and with Shift, or Control with Y,
826
+ * redoes, from anywhere on the board but a field a card holds, where the
827
+ * keys are the field's.
828
+ */
829
+ private readonly handleHistoryKey;
773
830
  /**
774
831
  * Moves the view while a pointer carries something near its edge, and
775
832
  * carries it along: a card, a corner, a connection being drawn, the box that
@@ -48,6 +48,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
48
48
  this.connectingLabel = 'Connecting from {from}. Move to another card and press Enter, or Escape to stop.';
49
49
  this.connectionLabel = 'From {from} to {to}';
50
50
  this.controlsLabel = 'Board controls';
51
+ this.copiedLabel = '{count, plural, one {# card copied} other {# cards copied}}';
51
52
  this.fallbackLabel = 'Canvas';
52
53
  this.label = '';
53
54
  this.labelEditorLabel = 'Label for {name}';
@@ -56,6 +57,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
56
57
  this.movedLabel = '{name} moved to {x}, {y}';
57
58
  this.readOnly = false;
58
59
  this.reconnectingLabel = 'Moving the end of the connection from {from} to {to}. Move to a card and press Enter, or Escape to stop.';
60
+ this.redoneLabel = 'Move made again';
59
61
  this.resizedLabel = '{name} resized to {width} by {height}';
60
62
  this.roleLabel = 'canvas';
61
63
  this.selected = '';
@@ -64,6 +66,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
64
66
  this.stoppedLabel = 'Stopped connecting.';
65
67
  this.toneLabels = {};
66
68
  this.twoFingerHintLabel = 'Use two fingers to move the board';
69
+ this.undoneLabel = 'Move undone';
67
70
  this.usingLabel = 'Using the board. Press Escape to scroll the page again.';
68
71
  this.wheelHintLabel = 'Use {key} and scroll to zoom the board';
69
72
  this.zoomedLabel = 'Zoom {zoom}';
@@ -81,6 +84,45 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
81
84
  this.fingers = new Map();
82
85
  this.keying = undefined;
83
86
  this.edgeKeys = new WeakMap();
87
+ this.undoable = [];
88
+ this.redoable = [];
89
+ this.replaying = false;
90
+ this.handleCopy = (event) => {
91
+ const origin = event.composedPath()[0];
92
+ const text = globalThis.getSelection?.()?.toString() ?? '';
93
+ if (this.picked.length === 0 || !event.clipboardData || text !== '') {
94
+ return;
95
+ }
96
+ if (origin?.closest?.(INTERACTIVE)) {
97
+ return;
98
+ }
99
+ const picked = new Set(this.picked);
100
+ const whole = this.toJsonCanvas();
101
+ const copy = {
102
+ edges: (whole.edges ?? []).filter((edge) => picked.has(edge.fromNode) && picked.has(edge.toNode)),
103
+ nodes: (whole.nodes ?? []).filter((node) => picked.has(node.id)),
104
+ };
105
+ event.clipboardData.setData('text/plain', JSON.stringify(copy));
106
+ event.preventDefault();
107
+ this.say(formatWords(this, 'copiedLabel', { count: copy.nodes?.length ?? 0 }));
108
+ };
109
+ this.handleHistoryKey = (event) => {
110
+ if (event.defaultPrevented || event.altKey || !(event.ctrlKey || event.metaKey)) {
111
+ return;
112
+ }
113
+ const key = event.key.toLowerCase();
114
+ const again = (key === 'z' && event.shiftKey) || (key === 'y' && !event.shiftKey);
115
+ if (key !== 'z' && !again) {
116
+ return;
117
+ }
118
+ const origin = event.composedPath()[0];
119
+ if (origin?.closest?.(INTERACTIVE)) {
120
+ return;
121
+ }
122
+ if (again ? this.redo() : this.undo()) {
123
+ event.preventDefault();
124
+ }
125
+ };
84
126
  this.edgePan = new EdgePan(() => this.partNamed('viewport')?.getBoundingClientRect(), (by) => this.panCarrying(by), () => {
85
127
  if (!this.dragging) {
86
128
  this.direct = false;
@@ -348,7 +390,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
348
390
  }
349
391
  this.sizing = undefined;
350
392
  if (sizing.moved) {
351
- this.dispatchEvent(new HelixMoveEvent(sizing.moved));
393
+ this.finishMove(sizing.moved);
352
394
  }
353
395
  return;
354
396
  }
@@ -393,7 +435,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
393
435
  this.clicked(carry.pressed, event);
394
436
  }
395
437
  if (carry.moved) {
396
- this.dispatchEvent(new HelixMoveEvent(carry.moved));
438
+ this.finishMove(carry.moved);
397
439
  }
398
440
  return;
399
441
  }
@@ -478,7 +520,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
478
520
  })),
479
521
  };
480
522
  if (this.requestMove(detail)) {
481
- this.dispatchEvent(new HelixMoveEvent(detail));
523
+ this.finishMove(detail);
482
524
  this.say(formatWords(this, 'movedLabel', {
483
525
  name: this.nameOf(card.name),
484
526
  x: card.x,
@@ -498,7 +540,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
498
540
  const box = this.resized({ height: card.height, width: card.width, x: card.x, y: card.y }, 'bottom-right', step ? stepTo(edge.x, along, step) - edge.x : along * NUDGE, step ? stepTo(edge.y, down, step) - edge.y : down * NUDGE);
499
541
  const detail = { nodes: [{ name: card.name, ...box }] };
500
542
  if (this.requestMove(detail)) {
501
- this.dispatchEvent(new HelixMoveEvent(detail));
543
+ this.finishMove(detail);
502
544
  this.say(formatWords(this, 'resizedLabel', {
503
545
  height: box.height,
504
546
  name: this.nameOf(card.name),
@@ -1209,6 +1251,12 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
1209
1251
  for (const { height, name, width, x, y } of detail.nodes) {
1210
1252
  const card = this.byName.get(name);
1211
1253
  if (card) {
1254
+ if (!this.replaying) {
1255
+ this.moving ??= new Map();
1256
+ if (!this.moving.has(name)) {
1257
+ this.moving.set(name, { height: card.height, width: card.width, x: card.x, y: card.y });
1258
+ }
1259
+ }
1212
1260
  card.x = x;
1213
1261
  card.y = y;
1214
1262
  if (width !== undefined && height !== undefined) {
@@ -1220,6 +1268,52 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
1220
1268
  this.requestUpdate();
1221
1269
  return true;
1222
1270
  }
1271
+ finishMove(detail) {
1272
+ const moving = this.moving;
1273
+ this.moving = undefined;
1274
+ if (moving && moving.size > 0) {
1275
+ const place = (name) => {
1276
+ const card = this.byName.get(name);
1277
+ return card
1278
+ ? { height: card.height, name, width: card.width, x: card.x, y: card.y }
1279
+ : undefined;
1280
+ };
1281
+ this.undoable.push({
1282
+ after: {
1283
+ nodes: [...moving.keys()]
1284
+ .map(place)
1285
+ .filter((one) => one !== undefined),
1286
+ },
1287
+ before: { nodes: [...moving].map(([name, at]) => ({ name, ...at })) },
1288
+ });
1289
+ this.undoable = this.undoable.slice(-100);
1290
+ this.redoable = [];
1291
+ }
1292
+ this.dispatchEvent(new HelixMoveEvent(detail));
1293
+ }
1294
+ undo() {
1295
+ return this.replay(this.undoable, this.redoable, 'before', this.undoneLabel);
1296
+ }
1297
+ redo() {
1298
+ return this.replay(this.redoable, this.undoable, 'after', this.redoneLabel);
1299
+ }
1300
+ replay(from, to, side, words) {
1301
+ const entry = from.pop();
1302
+ if (!entry) {
1303
+ return false;
1304
+ }
1305
+ this.replaying = true;
1306
+ const applied = this.requestMove(entry[side]);
1307
+ this.replaying = false;
1308
+ if (!applied) {
1309
+ from.push(entry);
1310
+ return false;
1311
+ }
1312
+ to.push(entry);
1313
+ this.dispatchEvent(new HelixMoveEvent(entry[side]));
1314
+ this.say(words);
1315
+ return true;
1316
+ }
1223
1317
  panCarrying(by) {
1224
1318
  const last = this.carryPointer;
1225
1319
  if (!last) {
@@ -1299,6 +1393,7 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
1299
1393
  this.linking = undefined;
1300
1394
  this.said = this.stoppedLabel;
1301
1395
  }
1396
+ this.moving = undefined;
1302
1397
  this.letGo();
1303
1398
  }
1304
1399
  letGo() {
@@ -1703,8 +1798,9 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
1703
1798
  }
1704
1799
  this.handOn();
1705
1800
  this.walked = this.walk;
1801
+ const watching = this.watched !== undefined;
1706
1802
  this.watchBox();
1707
- if (!this.touched) {
1803
+ if (watching && !this.touched) {
1708
1804
  this.fitInto(true);
1709
1805
  }
1710
1806
  }
@@ -1782,6 +1878,8 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
1782
1878
  this.addEventListener('focusin', this.handleFocusIn);
1783
1879
  this.addEventListener('focusout', this.handleFocusOut);
1784
1880
  this.addEventListener('keydown', this.handleStopKeydown);
1881
+ this.addEventListener('keydown', this.handleHistoryKey);
1882
+ this.addEventListener('copy', this.handleCopy);
1785
1883
  this.addEventListener('pointercancel', this.handlePointerUp);
1786
1884
  this.addEventListener('pointerdown', this.handlePointerDown);
1787
1885
  this.addEventListener('pointermove', this.handlePointerMove);
@@ -1802,6 +1900,8 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
1802
1900
  this.removeEventListener('focusin', this.handleFocusIn);
1803
1901
  this.removeEventListener('focusout', this.handleFocusOut);
1804
1902
  this.removeEventListener('keydown', this.handleStopKeydown);
1903
+ this.removeEventListener('keydown', this.handleHistoryKey);
1904
+ this.removeEventListener('copy', this.handleCopy);
1805
1905
  this.removeEventListener('pointercancel', this.handlePointerUp);
1806
1906
  this.removeEventListener('pointerdown', this.handlePointerDown);
1807
1907
  this.removeEventListener('pointermove', this.handlePointerMove);
@@ -1826,6 +1926,9 @@ let HelixHeadlessCanvas = class HelixHeadlessCanvas extends MixinViewport(HelixE
1826
1926
  };
1827
1927
  }
1828
1928
  this.origin = origin;
1929
+ if (this.watched && !this.touched) {
1930
+ this.fitInto(true);
1931
+ }
1829
1932
  hostAria(this.internals, { label: this.label });
1830
1933
  this.toggleState('connecting', this.drawing);
1831
1934
  this.toggleState('direct', this.direct);
@@ -2148,6 +2251,10 @@ __decorate([
2148
2251
  words,
2149
2252
  property({ attribute: 'controls-label' })
2150
2253
  ], HelixHeadlessCanvas.prototype, "controlsLabel", void 0);
2254
+ __decorate([
2255
+ words,
2256
+ property({ attribute: 'copied-label' })
2257
+ ], HelixHeadlessCanvas.prototype, "copiedLabel", void 0);
2151
2258
  __decorate([
2152
2259
  words,
2153
2260
  property({ attribute: 'fallback-label' })
@@ -2184,6 +2291,10 @@ __decorate([
2184
2291
  words,
2185
2292
  property({ attribute: 'reconnecting-label' })
2186
2293
  ], HelixHeadlessCanvas.prototype, "reconnectingLabel", void 0);
2294
+ __decorate([
2295
+ words,
2296
+ property({ attribute: 'redone-label' })
2297
+ ], HelixHeadlessCanvas.prototype, "redoneLabel", void 0);
2187
2298
  __decorate([
2188
2299
  words,
2189
2300
  property({ attribute: 'resized-label' })
@@ -2206,13 +2317,13 @@ __decorate([
2206
2317
  __decorate([
2207
2318
  property({ type: Number })
2208
2319
  ], HelixHeadlessCanvas.prototype, "snap", void 0);
2209
- __decorate([
2210
- state()
2211
- ], HelixHeadlessCanvas.prototype, "editing", void 0);
2212
2320
  __decorate([
2213
2321
  words,
2214
2322
  property({ attribute: 'stopped-label' })
2215
2323
  ], HelixHeadlessCanvas.prototype, "stoppedLabel", void 0);
2324
+ __decorate([
2325
+ state()
2326
+ ], HelixHeadlessCanvas.prototype, "editing", void 0);
2216
2327
  __decorate([
2217
2328
  property({ attribute: 'tone-labels', converter: wordsConverter })
2218
2329
  ], HelixHeadlessCanvas.prototype, "toneLabels", void 0);
@@ -2220,6 +2331,10 @@ __decorate([
2220
2331
  words,
2221
2332
  property({ attribute: 'two-finger-hint-label' })
2222
2333
  ], HelixHeadlessCanvas.prototype, "twoFingerHintLabel", void 0);
2334
+ __decorate([
2335
+ words,
2336
+ property({ attribute: 'undone-label' })
2337
+ ], HelixHeadlessCanvas.prototype, "undoneLabel", void 0);
2223
2338
  __decorate([
2224
2339
  words,
2225
2340
  property({ attribute: 'using-label' })
@@ -112,6 +112,14 @@ export declare class HelixHeadlessChatMessage extends HelixElement {
112
112
  * holds the reason. Everything else that moves it is the consumer's.
113
113
  */
114
114
  state?: 'failed' | 'sending' | 'sent' | 'streaming';
115
+ /** @internal Set by the chat with `turnPosition`: how many turns there are. */
116
+ turnCount: number;
117
+ /**
118
+ * @internal Set by the chat: where the turn stands in the conversation,
119
+ * from 1, and how many turns there are, which a screen reader says as
120
+ * "3 of 40". Zero where no chat has said.
121
+ */
122
+ turnPosition: number;
115
123
  /**
116
124
  * @internal Set by the chat: the word for `me` and the sentence that names a
117
125
  * turn with both an author and a time, in the chat's language.
@@ -19,6 +19,8 @@ let HelixHeadlessChatMessage = class HelixHeadlessChatMessage extends HelixEleme
19
19
  this.locale = '';
20
20
  this.retryLabel = 'Try again';
21
21
  this.sendingLabel = 'Sending';
22
+ this.turnCount = 0;
23
+ this.turnPosition = 0;
22
24
  this.turnWords = TURN_WORDS;
23
25
  this.isChatMessage = true;
24
26
  this.clock = new RelativeClockController(this, {
@@ -64,6 +66,9 @@ let HelixHeadlessChatMessage = class HelixHeadlessChatMessage extends HelixEleme
64
66
  }
65
67
  hostAria(this.internals, { label: this.name, role: 'article' });
66
68
  this.internals.ariaBusy = this.state === 'streaming' ? 'true' : null;
69
+ const placed = this.turnPosition > 0 && this.turnCount > 0;
70
+ this.internals.ariaPosInSet = placed ? String(this.turnPosition) : null;
71
+ this.internals.ariaSetSize = placed ? String(this.turnCount) : null;
67
72
  }
68
73
  get reading() {
69
74
  const moment = this.moment;
@@ -160,6 +165,12 @@ __decorate([
160
165
  __decorate([
161
166
  property({ reflect: true })
162
167
  ], HelixHeadlessChatMessage.prototype, "state", void 0);
168
+ __decorate([
169
+ property({ attribute: false })
170
+ ], HelixHeadlessChatMessage.prototype, "turnCount", void 0);
171
+ __decorate([
172
+ property({ attribute: false })
173
+ ], HelixHeadlessChatMessage.prototype, "turnPosition", void 0);
163
174
  __decorate([
164
175
  property({ attribute: false })
165
176
  ], HelixHeadlessChatMessage.prototype, "turnWords", void 0);
@@ -59,6 +59,19 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
59
59
  * "Ada is typing" (`typing-label`), which a screen reader hears, and clearing
60
60
  * it takes them away. Anything slotted into `status` is drawn first.
61
61
  *
62
+ * **Keyboard.** The transcript moves between turns the way a feed does. Each
63
+ * turn says its place, such as "3 of 40", windowed or not.
64
+ *
65
+ * | Key | What it does |
66
+ * |---|---|
67
+ * | Page Down, Page Up | On a turn or inside one, moves focus to the next or the previous turn. On the transcript itself, moves focus to the turn at the top of the view. |
68
+ * | Control with End | Moves focus to the composer. |
69
+ * | Control with Home | Moves focus to the first control above the transcript, or to the transcript. |
70
+ *
71
+ * While you are scrolled away from the newest turn, the `resume` region shows
72
+ * a button that takes you back, named by `resume-label`, "Jump to latest".
73
+ * Slot your own control into `resume` to replace it.
74
+ *
62
75
  * A screen reader names each turn by its author and its time, such as "You, 2
63
76
  * minutes ago". Set `me-label` and `message-label` to say it in your language,
64
77
  * and give each turn by `them` an `author-label`. A turn with neither an author
@@ -84,7 +97,7 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
84
97
  * @slot actions - Controls for the whole conversation, beside the header.
85
98
  * @slot composer - The composer, below the transcript.
86
99
  * @slot header - Content above the transcript that names the conversation.
87
- * @slot resume - The control that returns to the bottom, shown while the user has scrolled away.
100
+ * @slot resume - The control that returns to the bottom, shown while the user has scrolled away. Defaults to a button named by `resume-label`.
88
101
  * @slot status - Status beside the composer, such as someone typing or a lost connection.
89
102
  *
90
103
  * @event {HelixBeforePinEvent} helix-before-pin - Fired when the user pins or unpins the transcript by scrolling. Cancelable.
@@ -124,6 +137,8 @@ declare const HelixHeadlessChat_base: (new (...args: any[]) => import("@fusion.d
124
137
  * @csspart message-state - The state text of a turn from `turns`, when there is one to show.
125
138
  * @csspart message-time - The time of a turn from `turns`.
126
139
  * @csspart resume - The control shown while the user is scrolled away from the bottom.
140
+ * @csspart resume-button - The button the `resume` region shows when nothing is slotted into it.
141
+ * @csspart resume-mark - The arrow on the default `resume-button`.
127
142
  * @csspart status - The status region, outside the log.
128
143
  * @csspart turn - The wrapper around the message drawn for one turn from `turns`.
129
144
  * @csspart typing - The words that say who is typing, in the status band, while `typing` names someone.
@@ -232,6 +247,8 @@ export declare class HelixHeadlessChat extends HelixHeadlessChat_base {
232
247
  */
233
248
  get pinned(): boolean;
234
249
  set pinned(next: boolean);
250
+ /** The words on the button that returns to the newest turn, where `resume` is empty. */
251
+ resumeLabel: string;
235
252
  /**
236
253
  * How near the bottom still counts as being at it, in pixels.
237
254
  *
@@ -484,6 +501,30 @@ export declare class HelixHeadlessChat extends HelixHeadlessChat_base {
484
501
  * has hydrated, so its first render is the server's.
485
502
  */
486
503
  private tellTurns;
504
+ /**
505
+ * Which turn an event came from, by its place, `-1` for the transcript
506
+ * itself, or `undefined` for anywhere else.
507
+ */
508
+ private turnFrom;
509
+ /** The place of the turn at the top of the view, or the first turn. */
510
+ private topTurn;
511
+ /**
512
+ * Moves focus to turn `at`, drawing it first where the transcript is
513
+ * windowed and it is not drawn.
514
+ *
515
+ * **A turn takes focus only once a reader moves to it**, so the
516
+ * `tabindex="-1"` a turn written as a child needs is written then, long
517
+ * after any server's markup has hydrated, and never on a turn nobody moved
518
+ * to.
519
+ */
520
+ private focusTurn;
521
+ /** The first control in the regions `names` holds, in their order. */
522
+ private firstControlIn;
523
+ /**
524
+ * Page Down and Page Up move between turns, and Control with End or Home
525
+ * leaves the transcript, the keys the APG's feed answers.
526
+ */
527
+ private readonly handleKeydown;
487
528
  private readonly handleSlotChange;
488
529
  private readonly handleSettle;
489
530
  /**
@@ -513,6 +554,11 @@ export declare class HelixHeadlessChat extends HelixHeadlessChat_base {
513
554
  private readonly handleScroll;
514
555
  /** The turns fed as data, a window of them, between the room the rest would take. */
515
556
  private renderTurns;
557
+ /**
558
+ * The `resume` slot, with the way back drawn where nothing is slotted, behind a seam:
559
+ * the slot answers a page, and this answers the tier above.
560
+ */
561
+ protected renderResume(): TemplateResult;
516
562
  protected render(): TemplateResult;
517
563
  }
518
564
  declare global {