@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.
- 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
|
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { AriaForwardController, anchorAt, assignSlots, commaList, customElement, cycle, everyState, followLink, format, formatWords, HelixElement, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, inRowOrder, MixinCollection, onAndroid, parse, ReorderController, rangeAdd, reflectElements, requestChange, sort, splitValues, toggleEvery, whenHydrated, words, } from '@fusion.dev/helix-core';
|
|
7
|
+
import { AriaForwardController, anchorAt, assignSlots, commaList, customElement, cycle, everyState, followLink, format, formatWords, HelixBeforeToggleEvent, HelixElement, HelixLoadMoreEvent, HelixSelectEvent, HelixSelectedEvent, HelixSortEvent, HelixSortedEvent, HelixToggleEvent, inRowOrder, MixinCollection, onAndroid, parse, ReorderController, rangeAdd, reflectElements, requestChange, scrollingAncestor, sort, splitValues, toggleEvery, whenHydrated, words, } from '@fusion.dev/helix-core';
|
|
8
8
|
import { nothing } from 'lit';
|
|
9
9
|
import { property, state } from 'lit/decorators.js';
|
|
10
10
|
import { html } from 'lit/static-html.js';
|
|
@@ -53,14 +53,18 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
53
53
|
this.ascendingLabel = 'ascending';
|
|
54
54
|
this.canceledLabel = 'Canceled';
|
|
55
55
|
this.columns = '';
|
|
56
|
+
this.defaultExpanded = '';
|
|
56
57
|
this.defaultSelected = '';
|
|
57
58
|
this.defaultSort = '';
|
|
58
59
|
this.descendingLabel = 'descending';
|
|
59
60
|
this.droppedLabel = 'Dropped';
|
|
60
61
|
this.errorText = '';
|
|
62
|
+
this.expandColumnLabel = 'Expand';
|
|
63
|
+
this.expandRowLabel = 'Expand {row}';
|
|
61
64
|
this.fallbackLabel = 'Table';
|
|
62
65
|
this.grid = false;
|
|
63
66
|
this.label = '';
|
|
67
|
+
this.loadMore = false;
|
|
64
68
|
this.movedLabel = '{name} moved to position {position} of {count}';
|
|
65
69
|
this.moveRowLabel = 'Move {row}';
|
|
66
70
|
this.pickedUpLabel = 'Picked up {name}';
|
|
@@ -68,12 +72,15 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
68
72
|
this.rowGripsLabel = 'Move rows';
|
|
69
73
|
this.selectable = false;
|
|
70
74
|
this.selectAllLabel = 'Select every row';
|
|
75
|
+
this.selectColumnLabel = 'Select';
|
|
71
76
|
this.selectedLabel = '{count} selected';
|
|
77
|
+
this.selectionBehavior = 'toggle';
|
|
72
78
|
this.selectRowLabel = 'Select {row}';
|
|
73
79
|
this.sortedLabel = '{direction, select, ascending {Sorted by {column}, ascending} descending {Sorted by {column}, descending} other {Sorted by {column}}}';
|
|
74
80
|
this.unsortedLabel = 'Not sorted';
|
|
75
81
|
this.sortState = undefined;
|
|
76
82
|
this.selectedState = undefined;
|
|
83
|
+
this.expandedState = undefined;
|
|
77
84
|
this.headed = false;
|
|
78
85
|
this.aria = new AriaForwardController(this, {
|
|
79
86
|
label: true,
|
|
@@ -81,13 +88,20 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
81
88
|
});
|
|
82
89
|
this.gridKeys = new TableGridController(this, {
|
|
83
90
|
activate: (place, event) => this.activate(place, event),
|
|
91
|
+
arrive: (to, control) => {
|
|
92
|
+
if (this.replaces && !control) {
|
|
93
|
+
this.chooseOnly(to);
|
|
94
|
+
}
|
|
95
|
+
},
|
|
84
96
|
columns: () => this.tableColumns.filter((column) => column.shown),
|
|
85
97
|
lead: () => this.lead,
|
|
86
98
|
on: () => this.grid,
|
|
87
99
|
part: (name) => this.partNamed(name),
|
|
88
100
|
rows: () => (this.childrenKnown ? this.arrangedRows : []),
|
|
89
101
|
rowWords: () => this.arrangedRows.map((row) => textOf(row.children[0])),
|
|
90
|
-
selectAll: () => this.selectable &&
|
|
102
|
+
selectAll: () => this.selectable &&
|
|
103
|
+
!this.single &&
|
|
104
|
+
this.requestSelected(new Set([...this.chosen, ...this.enabledKeys])),
|
|
91
105
|
selectRange: (to, from) => this.selectRange(to, from),
|
|
92
106
|
});
|
|
93
107
|
this.reorder = new ReorderController(this, {
|
|
@@ -131,6 +145,33 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
131
145
|
event.preventDefault();
|
|
132
146
|
this.chooseRow(found.key, event.detail.checked);
|
|
133
147
|
};
|
|
148
|
+
this.handleRowClick = (event) => {
|
|
149
|
+
if (!this.replaces || event.defaultPrevented) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const path = event.composedPath();
|
|
153
|
+
const at = this.arrangedRows.findIndex((row) => path.includes(row));
|
|
154
|
+
const row = this.arrangedRows[at];
|
|
155
|
+
if (!row) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const control = path.find((node) => node instanceof Element &&
|
|
159
|
+
(node.matches('a[href], button, input, select, textarea, label, [contenteditable]') ||
|
|
160
|
+
(node.getRootNode() === row.shadowRoot && node.localName !== 'slot')));
|
|
161
|
+
if (control) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
if (event.shiftKey && !this.single) {
|
|
165
|
+
this.selectRange(at, at);
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
const found = this.keyed.find((one) => one.row === row);
|
|
169
|
+
if (found && (event.ctrlKey || event.metaKey)) {
|
|
170
|
+
this.chooseRow(found.key, !this.chosen.has(found.key));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
this.chooseOnly(at);
|
|
174
|
+
};
|
|
134
175
|
this.anchorKey = undefined;
|
|
135
176
|
this.handleHeadClick = (event) => {
|
|
136
177
|
const path = event.composedPath();
|
|
@@ -149,8 +190,17 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
149
190
|
this.watcher = undefined;
|
|
150
191
|
this.alignment = undefined;
|
|
151
192
|
this.aligned = '';
|
|
193
|
+
this.endInView = false;
|
|
152
194
|
}
|
|
153
195
|
static { this.words = 'helix-table'; }
|
|
196
|
+
get expanded() {
|
|
197
|
+
return this.expandedState ?? this.defaultExpanded;
|
|
198
|
+
}
|
|
199
|
+
set expanded(next) {
|
|
200
|
+
const previous = this.expanded;
|
|
201
|
+
this.expandedState = next;
|
|
202
|
+
this.requestUpdate('expanded', previous);
|
|
203
|
+
}
|
|
154
204
|
get selected() {
|
|
155
205
|
return this.selectedState ?? this.defaultSelected;
|
|
156
206
|
}
|
|
@@ -167,10 +217,44 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
167
217
|
this.sortState = next;
|
|
168
218
|
this.requestUpdate('sort', previous);
|
|
169
219
|
}
|
|
220
|
+
get nests() {
|
|
221
|
+
return this.childrenKnown && this.keyed.some(({ row }) => (row.parent ?? '') !== '');
|
|
222
|
+
}
|
|
223
|
+
get open() {
|
|
224
|
+
return new Set(commaList(this.expanded));
|
|
225
|
+
}
|
|
226
|
+
toggleRow(key) {
|
|
227
|
+
const row = this.rowFor(key);
|
|
228
|
+
if (!row) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
const next = !this.open.has(key);
|
|
232
|
+
const applied = requestChange({
|
|
233
|
+
apply: (checked) => {
|
|
234
|
+
const keys = this.open;
|
|
235
|
+
if (checked) {
|
|
236
|
+
keys.add(key);
|
|
237
|
+
}
|
|
238
|
+
else {
|
|
239
|
+
keys.delete(key);
|
|
240
|
+
}
|
|
241
|
+
const previous = this.expanded;
|
|
242
|
+
this.expandedState = inRowOrder(keys, this.everyKey).join(',');
|
|
243
|
+
this.requestUpdate('expanded', previous);
|
|
244
|
+
},
|
|
245
|
+
event: (checked) => new HelixBeforeToggleEvent({ checked }),
|
|
246
|
+
host: row,
|
|
247
|
+
next,
|
|
248
|
+
});
|
|
249
|
+
if (applied) {
|
|
250
|
+
row.dispatchEvent(new HelixToggleEvent({ checked: next }));
|
|
251
|
+
}
|
|
252
|
+
}
|
|
170
253
|
get lead() {
|
|
171
254
|
return [
|
|
172
255
|
...(this.reorderable ? ['grip'] : []),
|
|
173
256
|
...(this.selectable ? ['select'] : []),
|
|
257
|
+
...(this.nests ? ['expand'] : []),
|
|
174
258
|
];
|
|
175
259
|
}
|
|
176
260
|
rowFor(key) {
|
|
@@ -203,16 +287,69 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
203
287
|
const index = spec
|
|
204
288
|
? declared.findIndex((column) => column.canSort && column.field === spec.field)
|
|
205
289
|
: -1;
|
|
206
|
-
|
|
207
|
-
|
|
290
|
+
let ordered = rows;
|
|
291
|
+
if (spec && index >= 0) {
|
|
292
|
+
const records = rows.map((element) => ({ element, value: textOf(element.children[index]) }));
|
|
293
|
+
const numeric = records.every(({ value }) => value === '' || Number.isFinite(numberOf(value)));
|
|
294
|
+
const order = numeric
|
|
295
|
+
? (row) => (row.value === '' ? '' : numberOf(row.value))
|
|
296
|
+
: (row) => row.value;
|
|
297
|
+
const sorted = sort(records, spec, [
|
|
298
|
+
{ field: spec.field, order },
|
|
299
|
+
]);
|
|
300
|
+
ordered = sorted.map((record) => record.element);
|
|
208
301
|
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
const
|
|
215
|
-
|
|
302
|
+
return this.nests ? this.nested(ordered) : ordered;
|
|
303
|
+
}
|
|
304
|
+
nested(rows) {
|
|
305
|
+
const keys = new Map(this.keyed.map(({ key, row }) => [row, key]));
|
|
306
|
+
const present = new Set(keys.values());
|
|
307
|
+
const under = new Map();
|
|
308
|
+
for (const row of rows) {
|
|
309
|
+
const parent = row.parent ?? '';
|
|
310
|
+
const at = parent !== '' && present.has(parent) ? parent : '';
|
|
311
|
+
under.set(at, [...(under.get(at) ?? []), row]);
|
|
312
|
+
}
|
|
313
|
+
const open = this.open;
|
|
314
|
+
const drawn = [];
|
|
315
|
+
const seen = new Set();
|
|
316
|
+
const walk = (parent) => {
|
|
317
|
+
for (const row of under.get(parent) ?? []) {
|
|
318
|
+
if (seen.has(row)) {
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
seen.add(row);
|
|
322
|
+
drawn.push(row);
|
|
323
|
+
const key = keys.get(row) ?? '';
|
|
324
|
+
if (open.has(key)) {
|
|
325
|
+
walk(key);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
};
|
|
329
|
+
walk('');
|
|
330
|
+
return drawn;
|
|
331
|
+
}
|
|
332
|
+
shape() {
|
|
333
|
+
const parents = new Map(this.keyed.map(({ key, row }) => [key, row.parent ?? '']));
|
|
334
|
+
const shapes = new Map();
|
|
335
|
+
for (const key of parents.keys()) {
|
|
336
|
+
let level = 1;
|
|
337
|
+
let at = parents.get(key) ?? '';
|
|
338
|
+
const passed = new Set([key]);
|
|
339
|
+
while (at !== '' && parents.has(at) && !passed.has(at)) {
|
|
340
|
+
passed.add(at);
|
|
341
|
+
level += 1;
|
|
342
|
+
at = parents.get(at) ?? '';
|
|
343
|
+
}
|
|
344
|
+
shapes.set(key, { branch: false, level });
|
|
345
|
+
}
|
|
346
|
+
for (const parent of parents.values()) {
|
|
347
|
+
const shape = shapes.get(parent);
|
|
348
|
+
if (shape) {
|
|
349
|
+
shape.branch = true;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return shapes;
|
|
216
353
|
}
|
|
217
354
|
news() {
|
|
218
355
|
const current = this.sort;
|
|
@@ -274,12 +411,38 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
274
411
|
return this.keyed.find((one) => one.key === key)?.row.disabled === true;
|
|
275
412
|
}
|
|
276
413
|
chooseAll() {
|
|
414
|
+
if (this.single) {
|
|
415
|
+
return;
|
|
416
|
+
}
|
|
277
417
|
this.requestSelected(new Set(toggleEvery(this.chosen, this.enabledKeys)));
|
|
278
418
|
}
|
|
419
|
+
get single() {
|
|
420
|
+
return this.selectionMode === 'single';
|
|
421
|
+
}
|
|
422
|
+
get replaces() {
|
|
423
|
+
return this.selectable && this.selectionBehavior === 'replace';
|
|
424
|
+
}
|
|
425
|
+
chooseOnly(at) {
|
|
426
|
+
const row = this.arrangedRows[at];
|
|
427
|
+
const found = this.keyed.find((one) => one.row === row);
|
|
428
|
+
if (!found || found.row.disabled) {
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
this.anchorKey = found.key;
|
|
432
|
+
const now = this.chosen;
|
|
433
|
+
if (now.size === 1 && now.has(found.key)) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
this.requestSelected(new Set([found.key]));
|
|
437
|
+
}
|
|
279
438
|
selectRange(to, from) {
|
|
280
439
|
if (!this.selectable) {
|
|
281
440
|
return false;
|
|
282
441
|
}
|
|
442
|
+
if (this.single) {
|
|
443
|
+
this.chooseOnly(to);
|
|
444
|
+
return true;
|
|
445
|
+
}
|
|
283
446
|
const keyOf = new Map(this.keyed.map(({ key, row }) => [row, key]));
|
|
284
447
|
const keys = this.arrangedRows.map((row) => keyOf.get(row) ?? '');
|
|
285
448
|
const { anchor, anchorKey } = anchorAt(keys, this.anchorKey, from);
|
|
@@ -296,8 +459,11 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
296
459
|
return;
|
|
297
460
|
}
|
|
298
461
|
this.anchorKey = key;
|
|
299
|
-
const keys = this.chosen;
|
|
462
|
+
const keys = this.single ? new Set(this.chosen.has(key) ? [key] : []) : this.chosen;
|
|
300
463
|
if (on) {
|
|
464
|
+
if (this.single) {
|
|
465
|
+
keys.clear();
|
|
466
|
+
}
|
|
301
467
|
keys.add(key);
|
|
302
468
|
}
|
|
303
469
|
else {
|
|
@@ -311,6 +477,15 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
311
477
|
if (event.key === 'F2') {
|
|
312
478
|
return false;
|
|
313
479
|
}
|
|
480
|
+
if (place.row >= 0 && leads[place.column] === 'expand') {
|
|
481
|
+
const row = this.arrangedRows[place.row];
|
|
482
|
+
const found = this.keyed.find((one) => one.row === row);
|
|
483
|
+
if (found && row?.branch) {
|
|
484
|
+
this.toggleRow(found.key);
|
|
485
|
+
return true;
|
|
486
|
+
}
|
|
487
|
+
return false;
|
|
488
|
+
}
|
|
314
489
|
if (place.row === -1) {
|
|
315
490
|
if (lead) {
|
|
316
491
|
this.chooseAll();
|
|
@@ -327,7 +502,12 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
327
502
|
const row = this.arrangedRows[place.row];
|
|
328
503
|
const found = this.keyed.find((one) => one.row === row);
|
|
329
504
|
if (this.selectable && found && (event.key === ' ' || lead)) {
|
|
330
|
-
this.
|
|
505
|
+
if (this.replaces && !lead && !(event.ctrlKey || event.metaKey)) {
|
|
506
|
+
this.chooseOnly(place.row);
|
|
507
|
+
}
|
|
508
|
+
else {
|
|
509
|
+
this.chooseRow(found.key, !this.chosen.has(found.key));
|
|
510
|
+
}
|
|
331
511
|
return true;
|
|
332
512
|
}
|
|
333
513
|
if (event.key === 'Enter' && row?.href && !row.disabled) {
|
|
@@ -339,6 +519,9 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
339
519
|
markSelected() {
|
|
340
520
|
const keys = this.chosen;
|
|
341
521
|
const still = Boolean(parse(this.sort));
|
|
522
|
+
const tree = this.nests;
|
|
523
|
+
const shapes = tree ? this.shape() : undefined;
|
|
524
|
+
const open = this.open;
|
|
342
525
|
for (const { key, row } of this.keyed) {
|
|
343
526
|
if (!row.isTableRow) {
|
|
344
527
|
continue;
|
|
@@ -347,6 +530,8 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
347
530
|
const label = formatWords(this, 'selectRowLabel', { row: name });
|
|
348
531
|
const grip = this.reorderable ? formatWords(this, 'moveRowLabel', { row: name }) : '';
|
|
349
532
|
const move = this.reorder.moveOf(key);
|
|
533
|
+
const shape = shapes?.get(key);
|
|
534
|
+
const expand = tree ? formatWords(this, 'expandRowLabel', { row: name }) : '';
|
|
350
535
|
whenHydrated(row, () => {
|
|
351
536
|
row.selectable = this.selectable;
|
|
352
537
|
row.selected = keys.has(key);
|
|
@@ -354,6 +539,11 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
354
539
|
row.gripLabel = grip;
|
|
355
540
|
row.gripStill = still;
|
|
356
541
|
row.move = move;
|
|
542
|
+
row.level = shape?.level ?? 0;
|
|
543
|
+
row.branch = shape?.branch ?? false;
|
|
544
|
+
row.open = open.has(key);
|
|
545
|
+
row.expandLabel = expand;
|
|
546
|
+
row.expandWith = tree ? () => this.toggleRow(key) : undefined;
|
|
357
547
|
});
|
|
358
548
|
}
|
|
359
549
|
}
|
|
@@ -434,14 +624,22 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
434
624
|
super.connectedCallback();
|
|
435
625
|
this.watcher = new MutationObserver(() => this.requestUpdate());
|
|
436
626
|
this.watcher.observe(this, { characterData: true, childList: true, subtree: true });
|
|
627
|
+
if (this.hasUpdated) {
|
|
628
|
+
this.watchEnd();
|
|
629
|
+
}
|
|
437
630
|
this.addEventListener('click', this.handleHeadClick);
|
|
631
|
+
this.addEventListener('click', this.handleRowClick);
|
|
438
632
|
this.addEventListener('helix-before-toggle', this.handleToggle);
|
|
439
633
|
}
|
|
440
634
|
disconnectedCallback() {
|
|
441
635
|
super.disconnectedCallback();
|
|
636
|
+
this.endWatcher?.disconnect();
|
|
637
|
+
this.endWatcher = undefined;
|
|
638
|
+
this.watchedEnd = undefined;
|
|
442
639
|
this.watcher?.disconnect();
|
|
443
640
|
this.watcher = undefined;
|
|
444
641
|
this.removeEventListener('click', this.handleHeadClick);
|
|
642
|
+
this.removeEventListener('click', this.handleRowClick);
|
|
445
643
|
this.removeEventListener('helix-before-toggle', this.handleToggle);
|
|
446
644
|
}
|
|
447
645
|
static { this.shadowRootOptions = {
|
|
@@ -508,6 +706,38 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
508
706
|
this.gridKeys.mark();
|
|
509
707
|
this.gridKeys.place();
|
|
510
708
|
}
|
|
709
|
+
this.watchEnd();
|
|
710
|
+
}
|
|
711
|
+
watchEnd() {
|
|
712
|
+
const end = this.loadMore ? this.renderRoot.querySelector('[data-end]') : null;
|
|
713
|
+
if (end === this.watchedEnd) {
|
|
714
|
+
if (this.endInView) {
|
|
715
|
+
this.askForMore();
|
|
716
|
+
}
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
this.endWatcher?.disconnect();
|
|
720
|
+
this.endWatcher = undefined;
|
|
721
|
+
this.endInView = false;
|
|
722
|
+
this.watchedEnd = end ?? undefined;
|
|
723
|
+
if (!end || typeof IntersectionObserver === 'undefined') {
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
this.endWatcher = new IntersectionObserver((entries) => {
|
|
727
|
+
this.endInView = entries.some((entry) => entry.isIntersecting);
|
|
728
|
+
if (this.endInView) {
|
|
729
|
+
this.askForMore();
|
|
730
|
+
}
|
|
731
|
+
}, { root: scrollingAncestor(this, { axis: 'y' }), rootMargin: '0px 0px 100% 0px' });
|
|
732
|
+
this.endWatcher.observe(end);
|
|
733
|
+
}
|
|
734
|
+
askForMore() {
|
|
735
|
+
const count = this.slotted.length;
|
|
736
|
+
if (!this.loadMore || this.loading || this.askedAt === count) {
|
|
737
|
+
return;
|
|
738
|
+
}
|
|
739
|
+
this.askedAt = count;
|
|
740
|
+
this.dispatchEvent(new HelixLoadMoreEvent());
|
|
511
741
|
}
|
|
512
742
|
renderGripHead() {
|
|
513
743
|
if (!this.reorderable) {
|
|
@@ -520,10 +750,26 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
520
750
|
tabindex=${this.grid ? (this.gridKeys.isStop({ column: 0, row: -1 }) ? '0' : '-1') : nothing}
|
|
521
751
|
></span>`;
|
|
522
752
|
}
|
|
753
|
+
renderExpandHead() {
|
|
754
|
+
if (!this.nests) {
|
|
755
|
+
return nothing;
|
|
756
|
+
}
|
|
757
|
+
return html `<span
|
|
758
|
+
part="expand-head"
|
|
759
|
+
role="columnheader"
|
|
760
|
+
aria-label=${this.expandColumnLabel}
|
|
761
|
+
tabindex=${this.grid ? (this.gridKeys.isStop({ column: this.lead.indexOf('expand'), row: -1 }) ? '0' : '-1') : nothing}
|
|
762
|
+
></span>`;
|
|
763
|
+
}
|
|
523
764
|
renderSelectAll() {
|
|
524
765
|
if (!this.selectable) {
|
|
525
766
|
return nothing;
|
|
526
767
|
}
|
|
768
|
+
if (this.single) {
|
|
769
|
+
return html `<span part="select-all" role="columnheader" aria-label=${this.selectColumnLabel}
|
|
770
|
+
tabindex=${this.grid ? (this.gridKeys.isStop({ column: this.lead.indexOf('select'), row: -1 }) ? '0' : '-1') : nothing}
|
|
771
|
+
></span>`;
|
|
772
|
+
}
|
|
527
773
|
const every = this.childrenKnown ? this.enabledKeys : [];
|
|
528
774
|
const { checked, indeterminate } = everyState(this.chosen, every);
|
|
529
775
|
const checkbox = this.tag('checkbox');
|
|
@@ -551,13 +797,13 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
551
797
|
const end = grid ? html `<span part="grid-end" tabindex="-1"></span>` : nothing;
|
|
552
798
|
return html `<slot name="heading"></slot>${start}<div
|
|
553
799
|
part="table"
|
|
554
|
-
role=${grid ? 'grid' : 'table'}
|
|
555
|
-
aria-multiselectable=${grid && this.selectable ? 'true' : nothing}
|
|
800
|
+
role=${grid ? (this.nests ? 'treegrid' : 'grid') : 'table'}
|
|
801
|
+
aria-multiselectable=${grid && this.selectable ? (this.single ? 'false' : 'true') : nothing}
|
|
556
802
|
aria-busy=${this.loading ? 'true' : nothing}
|
|
557
803
|
aria-label=${this.label || this.fallbackLabel}
|
|
558
804
|
style=${template ? `--table-template: ${template}` : ''}
|
|
559
805
|
>
|
|
560
|
-
<div part="head" role="row">${this.renderGripHead()}${this.renderSelectAll()}<slot name="columns"></slot></div>
|
|
806
|
+
<div part="head" role="row">${this.renderGripHead()}${this.renderSelectAll()}${this.renderExpandHead()}<slot name="columns"></slot></div>
|
|
561
807
|
<slot
|
|
562
808
|
@slotchange=${(event) => {
|
|
563
809
|
this.countRows(event);
|
|
@@ -567,7 +813,7 @@ let HelixHeadlessTable = class HelixHeadlessTable extends MixinCollection(HelixE
|
|
|
567
813
|
${this.errorText === ''
|
|
568
814
|
? this.renderStatus(this.hasRows, grid ? 'gridcell' : 'cell')
|
|
569
815
|
: html `<p part="error" role="row"><span role=${grid ? 'gridcell' : 'cell'}><slot name="error">${this.errorText}</slot></span></p>`}
|
|
570
|
-
</div>${end}${this.errorText === ''
|
|
816
|
+
</div>${end}${this.loadMore ? html `<span data-end aria-hidden="true"></span>` : nothing}${this.errorText === ''
|
|
571
817
|
? this.renderLive(this.hasRows)
|
|
572
818
|
: html `<span part="live" role="status">${this.errorText}</span>`}${this.reorder.drawDragPreview()}`;
|
|
573
819
|
}
|
|
@@ -583,6 +829,9 @@ __decorate([
|
|
|
583
829
|
__decorate([
|
|
584
830
|
property()
|
|
585
831
|
], HelixHeadlessTable.prototype, "columns", void 0);
|
|
832
|
+
__decorate([
|
|
833
|
+
property({ attribute: 'default-expanded' })
|
|
834
|
+
], HelixHeadlessTable.prototype, "defaultExpanded", void 0);
|
|
586
835
|
__decorate([
|
|
587
836
|
property({ attribute: 'default-selected' })
|
|
588
837
|
], HelixHeadlessTable.prototype, "defaultSelected", void 0);
|
|
@@ -600,6 +849,17 @@ __decorate([
|
|
|
600
849
|
__decorate([
|
|
601
850
|
property({ attribute: 'error-text' })
|
|
602
851
|
], HelixHeadlessTable.prototype, "errorText", void 0);
|
|
852
|
+
__decorate([
|
|
853
|
+
words,
|
|
854
|
+
property({ attribute: 'expand-column-label' })
|
|
855
|
+
], HelixHeadlessTable.prototype, "expandColumnLabel", void 0);
|
|
856
|
+
__decorate([
|
|
857
|
+
property()
|
|
858
|
+
], HelixHeadlessTable.prototype, "expanded", null);
|
|
859
|
+
__decorate([
|
|
860
|
+
words,
|
|
861
|
+
property({ attribute: 'expand-row-label' })
|
|
862
|
+
], HelixHeadlessTable.prototype, "expandRowLabel", void 0);
|
|
603
863
|
__decorate([
|
|
604
864
|
words,
|
|
605
865
|
property({ attribute: 'fallback-label' })
|
|
@@ -610,6 +870,9 @@ __decorate([
|
|
|
610
870
|
__decorate([
|
|
611
871
|
property()
|
|
612
872
|
], HelixHeadlessTable.prototype, "label", void 0);
|
|
873
|
+
__decorate([
|
|
874
|
+
property({ attribute: 'load-more', type: Boolean })
|
|
875
|
+
], HelixHeadlessTable.prototype, "loadMore", void 0);
|
|
613
876
|
__decorate([
|
|
614
877
|
words,
|
|
615
878
|
property({ attribute: 'moved-label' })
|
|
@@ -636,6 +899,10 @@ __decorate([
|
|
|
636
899
|
words,
|
|
637
900
|
property({ attribute: 'select-all-label' })
|
|
638
901
|
], HelixHeadlessTable.prototype, "selectAllLabel", void 0);
|
|
902
|
+
__decorate([
|
|
903
|
+
words,
|
|
904
|
+
property({ attribute: 'select-column-label' })
|
|
905
|
+
], HelixHeadlessTable.prototype, "selectColumnLabel", void 0);
|
|
639
906
|
__decorate([
|
|
640
907
|
property()
|
|
641
908
|
], HelixHeadlessTable.prototype, "selected", null);
|
|
@@ -643,6 +910,12 @@ __decorate([
|
|
|
643
910
|
words,
|
|
644
911
|
property({ attribute: 'selected-label' })
|
|
645
912
|
], HelixHeadlessTable.prototype, "selectedLabel", void 0);
|
|
913
|
+
__decorate([
|
|
914
|
+
property({ attribute: 'selection-behavior' })
|
|
915
|
+
], HelixHeadlessTable.prototype, "selectionBehavior", void 0);
|
|
916
|
+
__decorate([
|
|
917
|
+
property({ attribute: 'selection-mode' })
|
|
918
|
+
], HelixHeadlessTable.prototype, "selectionMode", void 0);
|
|
646
919
|
__decorate([
|
|
647
920
|
words,
|
|
648
921
|
property({ attribute: 'select-row-label' })
|
|
@@ -664,6 +937,9 @@ __decorate([
|
|
|
664
937
|
__decorate([
|
|
665
938
|
state()
|
|
666
939
|
], HelixHeadlessTable.prototype, "selectedState", void 0);
|
|
940
|
+
__decorate([
|
|
941
|
+
state()
|
|
942
|
+
], HelixHeadlessTable.prototype, "expandedState", void 0);
|
|
667
943
|
HelixHeadlessTable = __decorate([
|
|
668
944
|
customElement('helix-headless-table')
|
|
669
945
|
], HelixHeadlessTable);
|
|
@@ -22,6 +22,12 @@ export type TableRowMove = 'dragging' | 'drop-after' | 'drop-before';
|
|
|
22
22
|
* the drop indicator is, with the `dragging`, `drop-before`, and `drop-after`
|
|
23
23
|
* states.
|
|
24
24
|
*
|
|
25
|
+
* **`parent` nests the row under another**, by that row's key. The table
|
|
26
|
+
* then draws a column of disclosure buttons: a row with rows under it has one,
|
|
27
|
+
* named by the table's `expand-row-label` and saying whether it is open with
|
|
28
|
+
* `aria-expanded`, and its rows are drawn only while it is open. The cell is
|
|
29
|
+
* indented by the row's depth through `--table-row-level`.
|
|
30
|
+
*
|
|
25
31
|
* **`href` makes the whole row a link**, as a row action does in React Aria's
|
|
26
32
|
* table: a press anywhere on the row follows it, except on a link or a control
|
|
27
33
|
* of the row's own, and Control, Command or Shift open it the way they open a
|
|
@@ -48,15 +54,21 @@ export type TableRowMove = 'dragging' | 'drop-after' | 'drop-before';
|
|
|
48
54
|
* @csspart checkbox-mark-checked - Added to `checkbox-mark` while its box is checked.
|
|
49
55
|
* @csspart checkbox-mark-dash - Added to `checkbox-mark` while it draws the dash, which it keeps until its box is checked.
|
|
50
56
|
* @csspart checkbox-mark-indeterminate - Added to `checkbox-mark` while only some rows are selected.
|
|
57
|
+
* @csspart expand - The cell that holds the row's disclosure button, in a table whose rows nest. It carries `--table-row-level`, the row's depth from 1.
|
|
58
|
+
* @csspart expand-button - The button that shows and hides the rows under this one.
|
|
59
|
+
* @csspart expand-mark - The caret on the disclosure button, which points along the line, turned down by the styled tier while the row is open.
|
|
51
60
|
* @csspart grip - The cell that holds the row's grip, in a `reorderable` table.
|
|
52
61
|
* @csspart grip-button - The button that moves the row.
|
|
53
62
|
* @csspart grip-mark - The icon on the grip.
|
|
54
63
|
* @csspart select - The cell that holds the row's checkbox, in a `selectable` table.
|
|
55
64
|
* @csspart select-selected - Added to `select` while the row is selected.
|
|
56
65
|
*
|
|
66
|
+
* @cssproperty --table-row-level - Written by the row on its `expand` cell: how deep the row sits, from 1. Do not set it.
|
|
67
|
+
*
|
|
57
68
|
* @cssstate dragging - The row is being moved, in a `reorderable` table.
|
|
58
69
|
* @cssstate drop-after - The row being moved goes after this one when it is dropped.
|
|
59
70
|
* @cssstate drop-before - The row being moved goes before this one when it is dropped.
|
|
71
|
+
* @cssstate expanded - While the rows under this one are shown.
|
|
60
72
|
* @cssstate link - While the row has `href` and is not `disabled`, so a press on it follows the link.
|
|
61
73
|
* @cssstate selected - While the row is selected, in a `selectable` table.
|
|
62
74
|
*/
|
|
@@ -80,6 +92,12 @@ export declare class HelixHeadlessTableRow extends HelixElement {
|
|
|
80
92
|
* Empty, the default, leaves presses to the row's cells.
|
|
81
93
|
*/
|
|
82
94
|
href: string;
|
|
95
|
+
/**
|
|
96
|
+
* The key of the row this one sits under, in a table whose rows nest: that
|
|
97
|
+
* row's `value`, or its place among the rows where it has none. Empty, the
|
|
98
|
+
* default, is a row at the top.
|
|
99
|
+
*/
|
|
100
|
+
parent: string;
|
|
83
101
|
/** The `rel` of the row's link. You set it yourself, as on an anchor. */
|
|
84
102
|
rel: string;
|
|
85
103
|
/** Where the row's link opens, such as `_blank`. */
|
|
@@ -133,6 +151,22 @@ export declare class HelixHeadlessTableRow extends HelixElement {
|
|
|
133
151
|
* by the table that sets `gridCell`. Not a consumer's to set.
|
|
134
152
|
*/
|
|
135
153
|
selectStop: boolean;
|
|
154
|
+
/**
|
|
155
|
+
* @internal How deep the row sits, from 1, in a table whose rows nest, and
|
|
156
|
+
* 0 in one whose rows do not, which draws no disclosure cell. Written by the
|
|
157
|
+
* table. Not a consumer's to set.
|
|
158
|
+
*/
|
|
159
|
+
level: number;
|
|
160
|
+
/** @internal Whether rows sit under this one. Written by the table. */
|
|
161
|
+
branch: boolean;
|
|
162
|
+
/** @internal Whether the rows under this one are shown. Written by the table. */
|
|
163
|
+
open: boolean;
|
|
164
|
+
/** @internal The name of the disclosure button. Written by the table. */
|
|
165
|
+
expandLabel: string;
|
|
166
|
+
/** @internal Whether the disclosure cell holds the grid's one tab stop. Written by the table. */
|
|
167
|
+
expandStop: boolean;
|
|
168
|
+
/** @internal What a press on the disclosure button asks of the table. Written by the table. */
|
|
169
|
+
expandWith: (() => void) | undefined;
|
|
136
170
|
/** The table's rules this row holds, so the next ones replace them rather than pile up. */
|
|
137
171
|
private columnRules;
|
|
138
172
|
/**
|
|
@@ -173,6 +207,13 @@ export declare class HelixHeadlessTableRow extends HelixElement {
|
|
|
173
207
|
* leaves the tab order. `aria-disabled` while a sort decides the order.
|
|
174
208
|
*/
|
|
175
209
|
protected renderGrip(): TemplateResult | typeof nothing;
|
|
210
|
+
/**
|
|
211
|
+
* The disclosure cell, in a table whose rows nest: a button where rows sit
|
|
212
|
+
* under this one, and an empty cell where none do, so the columns stay in
|
|
213
|
+
* line. In a grid the cell takes focus and Space or Enter on it presses the
|
|
214
|
+
* button, which leaves the tab order.
|
|
215
|
+
*/
|
|
216
|
+
protected renderExpand(): TemplateResult | typeof nothing;
|
|
176
217
|
protected render(): TemplateResult;
|
|
177
218
|
}
|
|
178
219
|
declare global {
|