@fusion.dev/helix-headless 0.160.0 → 0.161.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 +1729 -50
- package/dist/canvas/root/canvas-root.d.ts +59 -2
- package/dist/canvas/root/canvas-root.js +123 -8
- package/dist/chat/message/chat-message.d.ts +8 -0
- package/dist/chat/message/chat-message.js +11 -0
- package/dist/chat/root/chat-root.d.ts +47 -1
- package/dist/chat/root/chat-root.js +130 -4
- package/dist/code-block/lines.d.ts +12 -0
- package/dist/code-block/lines.js +41 -0
- package/dist/code-block/root/code-block-root.d.ts +88 -5
- package/dist/code-block/root/code-block-root.js +154 -10
- package/dist/element-events.generated.js +4 -0
- package/dist/splitter/root/splitter-root.d.ts +15 -0
- package/dist/splitter/root/splitter-root.js +16 -2
- package/dist/table/grid-controller.d.ts +7 -1
- package/dist/table/grid-controller.js +9 -1
- package/dist/table/root/table-root.d.ts +122 -0
- package/dist/table/root/table-root.js +293 -17
- package/dist/table/row/table-row.d.ts +41 -0
- package/dist/table/row/table-row.js +56 -2
- package/dist/timeline/item/timeline-item.d.ts +47 -10
- package/dist/timeline/item/timeline-item.js +36 -4
- package/dist/video-playlist/item/video-playlist-item.d.ts +11 -0
- package/dist/video-playlist/item/video-playlist-item.js +5 -0
- package/dist/video-playlist/menu/video-playlist-menu.d.ts +6 -0
- package/dist/video-playlist/menu/video-playlist-menu.js +11 -0
- package/dist/video-playlist/root/video-playlist-root.d.ts +59 -5
- package/dist/video-playlist/root/video-playlist-root.js +82 -10
- package/dist/virtual-list/fill.d.ts +6 -1
- package/dist/virtual-list/fill.js +1 -1
- package/dist/virtual-list/keys.d.ts +8 -0
- package/dist/virtual-list/keys.js +20 -0
- package/dist/virtual-list/root/virtual-list-root.d.ts +98 -13
- package/dist/virtual-list/root/virtual-list-root.js +195 -20
- package/lint.json +1 -1
- package/package.json +5 -5
- package/types/jsx.d.ts +936 -68
- package/types/vue.d.ts +226 -12
- 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.
|
|
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.
|
|
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.
|
|
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.
|
|
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 {
|