@fusion.dev/helix-headless 0.22.0 → 0.24.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 +48397 -26631
- package/dist/announcement/root/announcement-root.d.ts +19 -5
- package/dist/area-chart/index.d.ts +1 -0
- package/dist/area-chart/index.js +1 -0
- package/dist/area-chart/root/area-chart-root.d.ts +182 -0
- package/dist/area-chart/root/area-chart-root.js +205 -0
- package/dist/carousel/root/carousel-root.d.ts +1 -0
- package/dist/carousel/root/carousel-root.js +18 -2
- package/dist/chat/index.d.ts +1 -1
- package/dist/chat/message/chat-message.d.ts +7 -0
- package/dist/chat/message/chat-message.js +2 -1
- package/dist/chat/root/chat-root.d.ts +195 -4
- package/dist/chat/root/chat-root.js +316 -23
- package/dist/checkbox-group/root/checkbox-group-root.d.ts +2 -0
- package/dist/checkbox-group/root/checkbox-group-root.js +12 -2
- package/dist/code-block/index.d.ts +1 -0
- package/dist/code-block/index.js +1 -0
- package/dist/code-block/patch.d.ts +62 -0
- package/dist/code-block/patch.js +93 -0
- package/dist/code-block/root/code-block-root.d.ts +82 -17
- package/dist/code-block/root/code-block-root.js +83 -6
- package/dist/color-picker/root/color-picker-root.d.ts +4 -3
- package/dist/color-picker/root/color-picker-root.js +4 -1
- package/dist/data-table/root/data-table-root.d.ts +195 -23
- package/dist/data-table/root/data-table-root.js +308 -27
- package/dist/description-list/index.d.ts +2 -0
- package/dist/description-list/index.js +2 -0
- package/dist/description-list/item/description-list-item.d.ts +39 -0
- package/dist/description-list/item/description-list-item.js +26 -0
- package/dist/description-list/root/description-list-root.d.ts +56 -0
- package/dist/description-list/root/description-list-root.js +21 -0
- package/dist/element-events.generated.js +27 -6
- package/dist/filter-input/chip/filter-chip.d.ts +114 -0
- package/dist/filter-input/chip/filter-chip.js +61 -0
- package/dist/filter-input/field/filter-field.d.ts +128 -0
- package/dist/filter-input/field/filter-field.js +70 -0
- package/dist/filter-input/grammar.d.ts +96 -0
- package/dist/filter-input/grammar.js +133 -0
- package/dist/filter-input/index.d.ts +5 -0
- package/dist/filter-input/index.js +5 -0
- package/dist/filter-input/menu/filter-menu.d.ts +153 -0
- package/dist/filter-input/menu/filter-menu.js +164 -0
- package/dist/filter-input/operator/filter-operator.d.ts +105 -0
- package/dist/filter-input/operator/filter-operator.js +39 -0
- package/dist/filter-input/root/filter-input-root.d.ts +118 -9
- package/dist/filter-input/root/filter-input-root.js +96 -2
- package/dist/format-date/root/format-date-root.js +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/line-chart/root/line-chart-root.d.ts +9 -2
- package/dist/listbox/root/listbox-root.d.ts +8 -7
- package/dist/listbox/root/listbox-root.js +7 -2
- package/dist/menu/item/menu-item.d.ts +54 -6
- package/dist/menu/item/menu-item.js +31 -6
- package/dist/menu/root/menu-root.d.ts +23 -0
- package/dist/menu/root/menu-root.js +13 -2
- package/dist/notifications/group/notification-group.d.ts +129 -0
- package/dist/notifications/group/notification-group.js +106 -0
- package/dist/notifications/index.d.ts +1 -0
- package/dist/notifications/index.js +1 -0
- package/dist/notifications/notification/notification.d.ts +39 -13
- package/dist/notifications/notification/notification.js +11 -8
- package/dist/notifications/root/notifications-root.d.ts +57 -1
- package/dist/notifications/root/notifications-root.js +35 -4
- package/dist/number-input/root/number-input-root.d.ts +21 -1
- package/dist/number-input/root/number-input-root.js +18 -5
- package/dist/object-inspector/index.d.ts +1 -0
- package/dist/object-inspector/index.js +1 -0
- package/dist/object-inspector/root/object-inspector-root.d.ts +183 -0
- package/dist/object-inspector/root/object-inspector-root.js +348 -0
- package/dist/outline/root/outline-root.d.ts +16 -1
- package/dist/outline/root/outline-root.js +27 -9
- package/dist/radio/group/radio-group.d.ts +1 -0
- package/dist/scatter-chart/index.d.ts +1 -0
- package/dist/scatter-chart/index.js +1 -0
- package/dist/scatter-chart/root/scatter-chart-root.d.ts +144 -0
- package/dist/scatter-chart/root/scatter-chart-root.js +205 -0
- package/dist/skip-link/index.d.ts +1 -0
- package/dist/skip-link/index.js +1 -0
- package/dist/skip-link/root/skip-link-root.d.ts +81 -0
- package/dist/skip-link/root/skip-link-root.js +58 -0
- package/dist/speed-dial/root/speed-dial-root.d.ts +1 -0
- package/dist/speed-dial/root/speed-dial-root.js +6 -2
- package/dist/steps/root/steps-root.d.ts +1 -0
- package/dist/table/column/table-column.d.ts +79 -0
- package/dist/table/column/table-column.js +125 -5
- package/dist/table/root/table-root.d.ts +2 -0
- package/dist/table/root/table-root.js +12 -3
- package/dist/time-picker/root/time-picker-root.d.ts +9 -0
- package/dist/time-picker/root/time-picker-root.js +5 -0
- package/dist/toast/root/toast-root.d.ts +2 -0
- package/dist/tooltip/root/tooltip-root.js +1 -1
- package/dist/tour/root/tour-root.d.ts +1 -0
- package/dist/tree/item/tree-item.d.ts +7 -4
- package/dist/tree/item/tree-item.js +4 -1
- package/dist/video/root/video-root.d.ts +23 -1
- package/dist/video/root/video-root.js +42 -22
- package/dist/virtual-list/root/virtual-list-root.d.ts +10 -6
- package/dist/virtual-list/root/virtual-list-root.js +10 -4
- package/package.json +5 -5
- package/types/jsx.d.ts +4535 -346
- package/types/svelte.d.ts +11 -0
- package/types/vue.d.ts +737 -39
|
@@ -5,25 +5,31 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
7
|
var HelixHeadlessDataTable_1;
|
|
8
|
-
import { customElement, HelixElement, HelixFilterEvent, HelixNavigateEvent, HelixSortEvent, hostAria, MixinCollection, requestChange, slotFilled, VirtualizeController, } from '@fusion.dev/helix-core';
|
|
8
|
+
import { customElement, HelixElement, HelixFilterEvent, HelixNavigateEvent, HelixReorderEvent, HelixSelectEvent, HelixSortEvent, hostAria, MixinCollection, requestChange, slotFilled, VirtualizeController, } from '@fusion.dev/helix-core';
|
|
9
9
|
import { nothing } from 'lit';
|
|
10
10
|
import { property, state } from 'lit/decorators.js';
|
|
11
11
|
import { repeat } from 'lit/directives/repeat.js';
|
|
12
12
|
import { html } from 'lit/static-html.js';
|
|
13
|
+
import { at } from '../../table/column/table-column.js';
|
|
14
|
+
import '../../checkbox/index.js';
|
|
13
15
|
import '../../pagination/index.js';
|
|
14
16
|
import { arranged, cycle, format, ordered, parse, window_, } from './order.js';
|
|
15
17
|
let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollection(HelixElement) {
|
|
16
18
|
constructor() {
|
|
17
19
|
super(...arguments);
|
|
18
20
|
this.defaultFilter = '';
|
|
21
|
+
this.defaultOrder = '';
|
|
19
22
|
this.defaultPage = 1;
|
|
20
23
|
this.defaultPageSize = 0;
|
|
24
|
+
this.defaultSelected = '';
|
|
21
25
|
this.defaultSort = '';
|
|
22
26
|
this.estimate = 32;
|
|
23
|
-
this.key = '';
|
|
24
27
|
this.label = '';
|
|
25
28
|
this.mode = 'client';
|
|
29
|
+
this.reorderable = false;
|
|
30
|
+
this.rowKey = '';
|
|
26
31
|
this.rows = [];
|
|
32
|
+
this.selectable = false;
|
|
27
33
|
this.total = 0;
|
|
28
34
|
this.windowed = false;
|
|
29
35
|
this.sortState = undefined;
|
|
@@ -31,6 +37,10 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
31
37
|
this.pageState = undefined;
|
|
32
38
|
this.pageSizeState = undefined;
|
|
33
39
|
this.paginatedState = undefined;
|
|
40
|
+
this.orderState = undefined;
|
|
41
|
+
this.selectedState = undefined;
|
|
42
|
+
this.dragOrder = undefined;
|
|
43
|
+
this.warnedAboutKey = false;
|
|
34
44
|
this.virtualize = new VirtualizeController(this, {
|
|
35
45
|
container: () => this.windowed ? this.renderRoot.querySelector('[part="table"]') : null,
|
|
36
46
|
count: () => this.available,
|
|
@@ -39,6 +49,33 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
39
49
|
rows: () => (this.windowed ? this.drawn() : []),
|
|
40
50
|
});
|
|
41
51
|
this.warnedAboutSize = false;
|
|
52
|
+
this.toggleRow = (key, event) => {
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
const keys = this.chosen;
|
|
55
|
+
if (event.detail.checked) {
|
|
56
|
+
keys.add(key);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
keys.delete(key);
|
|
60
|
+
}
|
|
61
|
+
this.requestSelected(keys);
|
|
62
|
+
};
|
|
63
|
+
this.toggleAll = (event) => {
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
const every = this.everyKey;
|
|
66
|
+
const keys = this.chosen;
|
|
67
|
+
if (every.length > 0 && every.every((key) => keys.has(key))) {
|
|
68
|
+
for (const key of every) {
|
|
69
|
+
keys.delete(key);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
for (const key of every) {
|
|
74
|
+
keys.add(key);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
this.requestSelected(keys);
|
|
78
|
+
};
|
|
42
79
|
this.handleSlotChange = () => {
|
|
43
80
|
this.requestUpdate();
|
|
44
81
|
};
|
|
@@ -49,21 +86,74 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
49
86
|
}
|
|
50
87
|
};
|
|
51
88
|
this.handleHeadClick = (event) => {
|
|
89
|
+
if (this.partIn(event, 'grip') || this.partIn(event, 'resizer')) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
52
92
|
const column = this.columnFrom(event);
|
|
53
93
|
if (column?.canSort) {
|
|
54
94
|
this.toggleSort(column.field);
|
|
55
95
|
}
|
|
56
96
|
};
|
|
57
|
-
this.
|
|
58
|
-
if (
|
|
97
|
+
this.handleGripKey = (event) => {
|
|
98
|
+
if (!this.partIn(event, 'grip')) {
|
|
59
99
|
return;
|
|
60
100
|
}
|
|
61
101
|
const column = this.columnFrom(event);
|
|
62
|
-
|
|
102
|
+
const forward = getComputedStyle(this).direction === 'rtl' ? -1 : 1;
|
|
103
|
+
const by = event.key === 'ArrowRight' ? forward : event.key === 'ArrowLeft' ? -forward : 0;
|
|
104
|
+
if (column && by !== 0) {
|
|
63
105
|
event.preventDefault();
|
|
64
|
-
this.
|
|
106
|
+
this.moveColumn(column.field, by);
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
this.handleGripDown = (event) => {
|
|
110
|
+
if (event.button !== 0 || !this.partIn(event, 'grip')) {
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const column = this.columnFrom(event);
|
|
114
|
+
if (!column?.field) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this.dragging = { field: column.field, pointer: event.pointerId };
|
|
118
|
+
this.dragOrder = this.fields;
|
|
119
|
+
window.addEventListener('pointermove', this.handleGripMove);
|
|
120
|
+
window.addEventListener('pointerup', this.handleGripUp);
|
|
121
|
+
window.addEventListener('pointercancel', this.handleGripCancel);
|
|
122
|
+
};
|
|
123
|
+
this.handleGripMove = (event) => {
|
|
124
|
+
const dragging = this.dragging;
|
|
125
|
+
if (!dragging || event.pointerId !== dragging.pointer || !this.dragOrder) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const rtl = getComputedStyle(this).direction === 'rtl';
|
|
129
|
+
const others = this.orderedColumns.filter((column) => column.field !== '' && column.field !== dragging.field);
|
|
130
|
+
const place = others.filter((column) => {
|
|
131
|
+
const box = column.shadowRoot?.querySelector('[part="column"]')?.getBoundingClientRect();
|
|
132
|
+
if (!box) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const middle = box.left + box.width / 2;
|
|
136
|
+
return rtl ? event.clientX < middle : event.clientX > middle;
|
|
137
|
+
}).length;
|
|
138
|
+
const next = others.map((column) => column.field);
|
|
139
|
+
next.splice(place, 0, dragging.field);
|
|
140
|
+
if (next.join(' ') !== this.dragOrder.join(' ')) {
|
|
141
|
+
this.dragOrder = next;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
this.handleGripUp = () => {
|
|
145
|
+
const wanted = this.dragOrder;
|
|
146
|
+
this.stopDrag();
|
|
147
|
+
if (wanted && wanted.join(' ') !== this.fields.join(' ')) {
|
|
148
|
+
this.requestOrder(wanted);
|
|
65
149
|
}
|
|
66
150
|
};
|
|
151
|
+
this.handleGripCancel = () => {
|
|
152
|
+
this.stopDrag();
|
|
153
|
+
};
|
|
154
|
+
this.handleResize = () => {
|
|
155
|
+
queueMicrotask(() => this.requestUpdate());
|
|
156
|
+
};
|
|
67
157
|
this.handleNavigate = (event) => {
|
|
68
158
|
event.stopPropagation();
|
|
69
159
|
const wanted = Number(event.detail.value);
|
|
@@ -102,6 +192,22 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
102
192
|
this.pageState = next;
|
|
103
193
|
this.requestUpdate('page', previous);
|
|
104
194
|
}
|
|
195
|
+
get order() {
|
|
196
|
+
return this.orderState ?? this.defaultOrder;
|
|
197
|
+
}
|
|
198
|
+
set order(next) {
|
|
199
|
+
const previous = this.order;
|
|
200
|
+
this.orderState = next;
|
|
201
|
+
this.requestUpdate('order', previous);
|
|
202
|
+
}
|
|
203
|
+
get selected() {
|
|
204
|
+
return this.selectedState ?? this.defaultSelected;
|
|
205
|
+
}
|
|
206
|
+
set selected(next) {
|
|
207
|
+
const previous = this.selected;
|
|
208
|
+
this.selectedState = next;
|
|
209
|
+
this.requestUpdate('selected', previous);
|
|
210
|
+
}
|
|
105
211
|
get pageSize() {
|
|
106
212
|
return Math.max(0, Math.floor(this.pageSizeState ?? this.defaultPageSize) || 0);
|
|
107
213
|
}
|
|
@@ -150,7 +256,24 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
150
256
|
return rows.slice(first, last);
|
|
151
257
|
}
|
|
152
258
|
get tableColumns() {
|
|
153
|
-
return
|
|
259
|
+
return this.knownChildren.filter((child) => 'isTableColumn' in child && child.isTableColumn === true);
|
|
260
|
+
}
|
|
261
|
+
get orderedColumns() {
|
|
262
|
+
const columns = this.tableColumns;
|
|
263
|
+
const wanted = this.dragOrder ?? this.order.split(/[\s,]+/).filter(Boolean);
|
|
264
|
+
if (wanted.length === 0) {
|
|
265
|
+
return columns;
|
|
266
|
+
}
|
|
267
|
+
const rank = new Map(wanted.map((field, place) => [field, place]));
|
|
268
|
+
const moving = columns
|
|
269
|
+
.filter((column) => column.field !== '')
|
|
270
|
+
.sort((a, b) => (rank.get(a.field) ?? Number.POSITIVE_INFINITY) -
|
|
271
|
+
(rank.get(b.field) ?? Number.POSITIVE_INFINITY));
|
|
272
|
+
let next = 0;
|
|
273
|
+
return columns.map((column) => (column.field === '' ? column : (moving[next++] ?? column)));
|
|
274
|
+
}
|
|
275
|
+
get fields() {
|
|
276
|
+
return this.orderedColumns.filter((column) => column.field !== '').map((column) => column.field);
|
|
154
277
|
}
|
|
155
278
|
get axes() {
|
|
156
279
|
return this.tableColumns
|
|
@@ -158,8 +281,12 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
158
281
|
.map((column) => ({ field: column.field, order: (row) => column.order(row) }));
|
|
159
282
|
}
|
|
160
283
|
get template() {
|
|
161
|
-
const declared = this.
|
|
162
|
-
|
|
284
|
+
const declared = this.orderedColumns;
|
|
285
|
+
if (declared.length === 0) {
|
|
286
|
+
return '';
|
|
287
|
+
}
|
|
288
|
+
const tracks = declared.map((column) => column.track).join(' ');
|
|
289
|
+
return this.selectable ? `max-content ${tracks}` : tracks;
|
|
163
290
|
}
|
|
164
291
|
static { this.COMFORTABLE = 2_000; }
|
|
165
292
|
warnIfCrowded(drawn) {
|
|
@@ -235,6 +362,78 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
235
362
|
next,
|
|
236
363
|
});
|
|
237
364
|
}
|
|
365
|
+
requestOrder(fields) {
|
|
366
|
+
return requestChange({
|
|
367
|
+
apply: (value) => {
|
|
368
|
+
const previous = this.order;
|
|
369
|
+
this.orderState = value;
|
|
370
|
+
this.requestUpdate('order', previous);
|
|
371
|
+
},
|
|
372
|
+
event: (value) => new HelixReorderEvent({ value }),
|
|
373
|
+
host: this,
|
|
374
|
+
next: fields.join(' '),
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
requestSelected(keys) {
|
|
378
|
+
return requestChange({
|
|
379
|
+
apply: (value) => {
|
|
380
|
+
const previous = this.selected;
|
|
381
|
+
this.selectedState = value;
|
|
382
|
+
this.requestUpdate('selected', previous);
|
|
383
|
+
},
|
|
384
|
+
event: (value) => new HelixSelectEvent({ value }),
|
|
385
|
+
host: this,
|
|
386
|
+
next: [...keys].join(','),
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
get chosen() {
|
|
390
|
+
return new Set(this.selected
|
|
391
|
+
.split(',')
|
|
392
|
+
.map((key) => key.trim())
|
|
393
|
+
.filter(Boolean));
|
|
394
|
+
}
|
|
395
|
+
keyOf(row, place) {
|
|
396
|
+
if (this.rowKey) {
|
|
397
|
+
const value = at(row, this.rowKey);
|
|
398
|
+
return value === undefined || value === null ? String(place) : String(value);
|
|
399
|
+
}
|
|
400
|
+
if (this.selectable && !this.warnedAboutKey && typeof window !== 'undefined') {
|
|
401
|
+
this.warnedAboutKey = true;
|
|
402
|
+
console.warn(`<${this.localName} selectable> has no \`row-key\`, so it knows each row by its place in the result, and a sort, a filter or new data selects a different row than the one that was chosen. Set \`row-key\` to the field that identifies a row.`);
|
|
403
|
+
}
|
|
404
|
+
return String(place);
|
|
405
|
+
}
|
|
406
|
+
get everyKey() {
|
|
407
|
+
const rows = this.mode === 'server' ? this.rows : this.arrange().rows;
|
|
408
|
+
return rows.map((row, place) => this.keyOf(row, place));
|
|
409
|
+
}
|
|
410
|
+
moveColumn(field, by) {
|
|
411
|
+
const fields = this.fields;
|
|
412
|
+
const from = fields.indexOf(field);
|
|
413
|
+
const to = from + by;
|
|
414
|
+
if (from < 0 || to < 0 || to >= fields.length) {
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
fields.splice(to, 0, ...fields.splice(from, 1));
|
|
418
|
+
return this.requestOrder(fields);
|
|
419
|
+
}
|
|
420
|
+
csv() {
|
|
421
|
+
const columns = this.orderedColumns.filter((column) => column.field !== '');
|
|
422
|
+
const rows = this.mode === 'server' ? this.rows : this.arrange().rows;
|
|
423
|
+
const quote = (value) => {
|
|
424
|
+
if (value === undefined || value === null) {
|
|
425
|
+
return '';
|
|
426
|
+
}
|
|
427
|
+
let text = String(value);
|
|
428
|
+
if (typeof value === 'string' && /^[=+\-@\t\r]/.test(text)) {
|
|
429
|
+
text = `'${text}`;
|
|
430
|
+
}
|
|
431
|
+
return /[",\r\n]/.test(text) ? `"${text.replaceAll('"', '""')}"` : text;
|
|
432
|
+
};
|
|
433
|
+
const head = columns.map((column) => quote(column.textContent?.trim() || column.field));
|
|
434
|
+
const body = rows.map((row) => columns.map((column) => quote(at(row, column.field))));
|
|
435
|
+
return [head, ...body].map((line) => line.join(',')).join('\r\n');
|
|
436
|
+
}
|
|
238
437
|
requestFilter(next) {
|
|
239
438
|
return requestChange({
|
|
240
439
|
apply: (value) => {
|
|
@@ -273,11 +472,18 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
273
472
|
if (!root?.querySelector) {
|
|
274
473
|
return;
|
|
275
474
|
}
|
|
475
|
+
if (this.assignsByName) {
|
|
476
|
+
const single = root.querySelector('slot[name="columns"]') !== null;
|
|
477
|
+
this.orderedColumns.forEach((column, index) => {
|
|
478
|
+
this.route(column, single ? 'columns' : `column-${index + 1}`);
|
|
479
|
+
});
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
276
482
|
const head = root.querySelector('slot[name="columns"]');
|
|
277
483
|
if (!head?.assign) {
|
|
278
484
|
return;
|
|
279
485
|
}
|
|
280
|
-
const columns = this.
|
|
486
|
+
const columns = this.orderedColumns;
|
|
281
487
|
head.assign(...columns);
|
|
282
488
|
const rest = [...this.children].filter((child) => !columns.includes(child));
|
|
283
489
|
for (const [name, wanted] of [
|
|
@@ -293,6 +499,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
293
499
|
willUpdate(changed) {
|
|
294
500
|
super.willUpdate(changed);
|
|
295
501
|
hostAria(this.internals, { label: this.label || 'Table', role: 'grid' });
|
|
502
|
+
this.internals.ariaMultiSelectable = this.selectable ? 'true' : null;
|
|
296
503
|
const placement = this.placement;
|
|
297
504
|
if (changed.has('rows') || placement !== this.measuredAgainst) {
|
|
298
505
|
this.measuredAgainst = placement;
|
|
@@ -321,6 +528,7 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
321
528
|
announceSort() {
|
|
322
529
|
const current = parse(this.sort);
|
|
323
530
|
for (const column of this.tableColumns) {
|
|
531
|
+
column.movable = this.reorderable && column.field !== '';
|
|
324
532
|
column.sorted =
|
|
325
533
|
current && column.canSort && column.field === current.field
|
|
326
534
|
? current.direction === 'asc'
|
|
@@ -337,18 +545,39 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
337
545
|
>${column.read(row)}</span
|
|
338
546
|
>`;
|
|
339
547
|
}
|
|
548
|
+
renderCheckbox(name, checked, indeterminate, toggle) {
|
|
549
|
+
const checkbox = this.tag('checkbox');
|
|
550
|
+
return html `<${checkbox}
|
|
551
|
+
part="checkbox"
|
|
552
|
+
exportparts="box: checkbox-box, control: checkbox-control, feedback: checkbox-feedback,
|
|
553
|
+
field: checkbox-field, hint: checkbox-hint, label: checkbox-label, mark: checkbox-mark"
|
|
554
|
+
aria-label=${name}
|
|
555
|
+
.checked=${checked}
|
|
556
|
+
.indeterminate=${indeterminate}
|
|
557
|
+
@helix-before-toggle=${toggle}
|
|
558
|
+
></${checkbox}>`;
|
|
559
|
+
}
|
|
340
560
|
renderRows(rows) {
|
|
341
|
-
const columns = this.
|
|
342
|
-
const field = this.
|
|
561
|
+
const columns = this.orderedColumns;
|
|
562
|
+
const field = this.rowKey;
|
|
343
563
|
const start = this.windowStart;
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
564
|
+
const chosen = this.selectable ? this.chosen : undefined;
|
|
565
|
+
const named = columns.find((column) => column.field !== '');
|
|
566
|
+
return html `${repeat(rows, (row, index) => (field ? String(row[field] ?? start + index) : start + index), (row, index) => {
|
|
567
|
+
const key = chosen ? this.keyOf(row, this.rowIndex(index) - 2) : '';
|
|
568
|
+
const picked = chosen?.has(key) ?? false;
|
|
569
|
+
return html `<div
|
|
570
|
+
part="row"
|
|
571
|
+
role="row"
|
|
572
|
+
aria-rowindex=${this.rowIndex(index)}
|
|
573
|
+
aria-selected=${chosen ? String(picked) : nothing}
|
|
574
|
+
data-index=${this.windowed ? start + index : nothing}
|
|
575
|
+
>
|
|
576
|
+
${chosen
|
|
577
|
+
? html `<span part="select" role="gridcell">${this.renderCheckbox(`Select ${named ? String(named.order(row) ?? key) : key}`, picked, false, (event) => this.toggleRow(key, event))}</span>`
|
|
578
|
+
: nothing}${columns.map((column) => this.renderCell(column, row))}
|
|
579
|
+
</div>`;
|
|
580
|
+
})}`;
|
|
352
581
|
}
|
|
353
582
|
rowIndex(within) {
|
|
354
583
|
const size = this.pageSize;
|
|
@@ -370,6 +599,12 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
370
599
|
? html `<div part="before" role="presentation" style="block-size: ${before}px"></div>`
|
|
371
600
|
: html `<div part="after" role="presentation" style="block-size: ${after}px"></div>`;
|
|
372
601
|
}
|
|
602
|
+
renderSelectAll() {
|
|
603
|
+
const every = this.everyKey;
|
|
604
|
+
const keys = this.chosen;
|
|
605
|
+
const count = every.filter((key) => keys.has(key)).length;
|
|
606
|
+
return html `<span part="select-all" role="columnheader">${this.renderCheckbox('Select every row', every.length > 0 && count === every.length, count > 0 && count < every.length, this.toggleAll)}</span>`;
|
|
607
|
+
}
|
|
373
608
|
render() {
|
|
374
609
|
const { available, matched, rows } = this.view;
|
|
375
610
|
const template = this.template;
|
|
@@ -381,12 +616,14 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
381
616
|
role="rowgroup"
|
|
382
617
|
aria-busy=${this.loading ? 'true' : nothing}
|
|
383
618
|
aria-rowcount=${this.mode === 'server' ? Math.max(this.total, available) + 1 : matched + 1}
|
|
384
|
-
aria-colcount=${columns.length
|
|
619
|
+
aria-colcount=${columns.length ? columns.length + (this.selectable ? 1 : 0) : nothing}
|
|
385
620
|
style=${template ? `--data-table-template: ${template}` : nothing}
|
|
386
621
|
@scroll=${this.handleScroll}
|
|
387
622
|
>
|
|
388
623
|
<div part="head" role="row">
|
|
389
|
-
|
|
624
|
+
${this.selectable ? this.renderSelectAll() : nothing}${this.assignsByName && !this.hydrating
|
|
625
|
+
? this.orderedColumns.map((_, index) => html `<slot name=${`column-${index + 1}`} @slotchange=${this.handleSlotChange}></slot>`)
|
|
626
|
+
: html `<slot name="columns" @slotchange=${this.handleSlotChange}></slot>`}
|
|
390
627
|
</div>
|
|
391
628
|
${this.renderSpacer('before')}${this.renderRows(rows)}${this.renderSpacer('after')}
|
|
392
629
|
${this.renderStatus(available > 0)}
|
|
@@ -407,12 +644,29 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
407
644
|
connectedCallback() {
|
|
408
645
|
super.connectedCallback();
|
|
409
646
|
this.addEventListener('click', this.handleHeadClick);
|
|
410
|
-
this.addEventListener('keydown', this.
|
|
647
|
+
this.addEventListener('keydown', this.handleGripKey);
|
|
648
|
+
this.addEventListener('pointerdown', this.handleGripDown);
|
|
649
|
+
this.addEventListener('helix-before-resize', this.handleResize);
|
|
411
650
|
}
|
|
412
651
|
disconnectedCallback() {
|
|
413
652
|
super.disconnectedCallback();
|
|
414
653
|
this.removeEventListener('click', this.handleHeadClick);
|
|
415
|
-
this.removeEventListener('keydown', this.
|
|
654
|
+
this.removeEventListener('keydown', this.handleGripKey);
|
|
655
|
+
this.removeEventListener('pointerdown', this.handleGripDown);
|
|
656
|
+
this.removeEventListener('helix-before-resize', this.handleResize);
|
|
657
|
+
this.stopDrag();
|
|
658
|
+
}
|
|
659
|
+
partIn(event, name) {
|
|
660
|
+
return event
|
|
661
|
+
.composedPath()
|
|
662
|
+
.some((node) => node instanceof Element && node.getAttribute('part') === name);
|
|
663
|
+
}
|
|
664
|
+
stopDrag() {
|
|
665
|
+
this.dragging = undefined;
|
|
666
|
+
this.dragOrder = undefined;
|
|
667
|
+
window.removeEventListener('pointermove', this.handleGripMove);
|
|
668
|
+
window.removeEventListener('pointerup', this.handleGripUp);
|
|
669
|
+
window.removeEventListener('pointercancel', this.handleGripCancel);
|
|
416
670
|
}
|
|
417
671
|
columnFrom(event) {
|
|
418
672
|
const columns = this.tableColumns;
|
|
@@ -427,12 +681,18 @@ let HelixHeadlessDataTable = class HelixHeadlessDataTable extends MixinCollectio
|
|
|
427
681
|
__decorate([
|
|
428
682
|
property({ attribute: 'default-filter' })
|
|
429
683
|
], HelixHeadlessDataTable.prototype, "defaultFilter", void 0);
|
|
684
|
+
__decorate([
|
|
685
|
+
property({ attribute: 'default-order' })
|
|
686
|
+
], HelixHeadlessDataTable.prototype, "defaultOrder", void 0);
|
|
430
687
|
__decorate([
|
|
431
688
|
property({ attribute: 'default-page', type: Number })
|
|
432
689
|
], HelixHeadlessDataTable.prototype, "defaultPage", void 0);
|
|
433
690
|
__decorate([
|
|
434
691
|
property({ attribute: 'default-page-size', type: Number })
|
|
435
692
|
], HelixHeadlessDataTable.prototype, "defaultPageSize", void 0);
|
|
693
|
+
__decorate([
|
|
694
|
+
property({ attribute: 'default-selected' })
|
|
695
|
+
], HelixHeadlessDataTable.prototype, "defaultSelected", void 0);
|
|
436
696
|
__decorate([
|
|
437
697
|
property({ attribute: 'default-sort' })
|
|
438
698
|
], HelixHeadlessDataTable.prototype, "defaultSort", void 0);
|
|
@@ -444,22 +704,34 @@ __decorate([
|
|
|
444
704
|
], HelixHeadlessDataTable.prototype, "sort", null);
|
|
445
705
|
__decorate([
|
|
446
706
|
property()
|
|
447
|
-
], HelixHeadlessDataTable.prototype, "
|
|
707
|
+
], HelixHeadlessDataTable.prototype, "label", void 0);
|
|
448
708
|
__decorate([
|
|
449
709
|
property()
|
|
450
710
|
], HelixHeadlessDataTable.prototype, "filter", null);
|
|
451
711
|
__decorate([
|
|
452
712
|
property()
|
|
453
|
-
], HelixHeadlessDataTable.prototype, "
|
|
713
|
+
], HelixHeadlessDataTable.prototype, "mode", void 0);
|
|
454
714
|
__decorate([
|
|
455
715
|
property({ type: Number })
|
|
456
716
|
], HelixHeadlessDataTable.prototype, "page", null);
|
|
717
|
+
__decorate([
|
|
718
|
+
property({ type: Boolean })
|
|
719
|
+
], HelixHeadlessDataTable.prototype, "reorderable", void 0);
|
|
457
720
|
__decorate([
|
|
458
721
|
property()
|
|
459
|
-
], HelixHeadlessDataTable.prototype, "
|
|
722
|
+
], HelixHeadlessDataTable.prototype, "order", null);
|
|
723
|
+
__decorate([
|
|
724
|
+
property({ attribute: 'row-key' })
|
|
725
|
+
], HelixHeadlessDataTable.prototype, "rowKey", void 0);
|
|
460
726
|
__decorate([
|
|
461
727
|
property({ attribute: false })
|
|
462
728
|
], HelixHeadlessDataTable.prototype, "rows", void 0);
|
|
729
|
+
__decorate([
|
|
730
|
+
property({ type: Boolean })
|
|
731
|
+
], HelixHeadlessDataTable.prototype, "selectable", void 0);
|
|
732
|
+
__decorate([
|
|
733
|
+
property()
|
|
734
|
+
], HelixHeadlessDataTable.prototype, "selected", null);
|
|
463
735
|
__decorate([
|
|
464
736
|
property({ attribute: 'page-size', type: Number })
|
|
465
737
|
], HelixHeadlessDataTable.prototype, "pageSize", null);
|
|
@@ -487,6 +759,15 @@ __decorate([
|
|
|
487
759
|
__decorate([
|
|
488
760
|
state()
|
|
489
761
|
], HelixHeadlessDataTable.prototype, "paginatedState", void 0);
|
|
762
|
+
__decorate([
|
|
763
|
+
state()
|
|
764
|
+
], HelixHeadlessDataTable.prototype, "orderState", void 0);
|
|
765
|
+
__decorate([
|
|
766
|
+
state()
|
|
767
|
+
], HelixHeadlessDataTable.prototype, "selectedState", void 0);
|
|
768
|
+
__decorate([
|
|
769
|
+
state()
|
|
770
|
+
], HelixHeadlessDataTable.prototype, "dragOrder", void 0);
|
|
490
771
|
HelixHeadlessDataTable = HelixHeadlessDataTable_1 = __decorate([
|
|
491
772
|
customElement('helix-headless-data-table')
|
|
492
773
|
], HelixHeadlessDataTable);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
+
import { type TemplateResult } from 'lit';
|
|
3
|
+
/**
|
|
4
|
+
* @summary One label and its value.
|
|
5
|
+
*
|
|
6
|
+
* @description
|
|
7
|
+
* An element rather than a pair of slots on the list, because a pair is the
|
|
8
|
+
* unit a reader hears: the label is the `<dt>` and the value its `<dd>`, and the
|
|
9
|
+
* two stay together however the list lays them out.
|
|
10
|
+
*
|
|
11
|
+
* The value is the default slot, since it is what varies and is often more
|
|
12
|
+
* than text: a tag, an avatar, a link. The label is text almost every time, so
|
|
13
|
+
* it is also a property.
|
|
14
|
+
*
|
|
15
|
+
* @since 0.1.0
|
|
16
|
+
* @status experimental
|
|
17
|
+
* @documentation https://helix.fusion.dev/components/description-list
|
|
18
|
+
*
|
|
19
|
+
* @slot - The value.
|
|
20
|
+
* @slot label - The label, when it is more than text. Falls back to `label`.
|
|
21
|
+
*
|
|
22
|
+
* @csspart label - The `<dt>`, holding the label.
|
|
23
|
+
* @csspart value - The `<dd>`, holding the value.
|
|
24
|
+
*/
|
|
25
|
+
export declare class HelixHeadlessDescriptionListItem extends HelixElement {
|
|
26
|
+
/**
|
|
27
|
+
* What the value is, for the common case of plain text.
|
|
28
|
+
*
|
|
29
|
+
* The fallback of the `label` slot, so slotted content replaces it rather than
|
|
30
|
+
* appearing beside it.
|
|
31
|
+
*/
|
|
32
|
+
label: string;
|
|
33
|
+
protected render(): TemplateResult;
|
|
34
|
+
}
|
|
35
|
+
declare global {
|
|
36
|
+
interface HTMLElementTagNameMap {
|
|
37
|
+
'helix-headless-description-list-item': HelixHeadlessDescriptionListItem;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
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
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { customElement, HelixElement } from '@fusion.dev/helix-core';
|
|
8
|
+
import { html } from 'lit';
|
|
9
|
+
import { property } from 'lit/decorators.js';
|
|
10
|
+
let HelixHeadlessDescriptionListItem = class HelixHeadlessDescriptionListItem extends HelixElement {
|
|
11
|
+
constructor() {
|
|
12
|
+
super(...arguments);
|
|
13
|
+
this.label = '';
|
|
14
|
+
}
|
|
15
|
+
render() {
|
|
16
|
+
return html `<dt part="label"><slot name="label">${this.label}</slot></dt>
|
|
17
|
+
<dd part="value"><slot></slot></dd>`;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
__decorate([
|
|
21
|
+
property()
|
|
22
|
+
], HelixHeadlessDescriptionListItem.prototype, "label", void 0);
|
|
23
|
+
HelixHeadlessDescriptionListItem = __decorate([
|
|
24
|
+
customElement('helix-headless-description-list-item')
|
|
25
|
+
], HelixHeadlessDescriptionListItem);
|
|
26
|
+
export { HelixHeadlessDescriptionListItem };
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { HelixElement } from '@fusion.dev/helix-core';
|
|
2
|
+
import { type TemplateResult } from 'lit';
|
|
3
|
+
/**
|
|
4
|
+
* @summary Labels and their values, read as pairs: the details panel every
|
|
5
|
+
* product has.
|
|
6
|
+
*
|
|
7
|
+
* @description
|
|
8
|
+
* "Owner: Ada, Region: us-east, Created: 3 days ago" is the commonest panel in
|
|
9
|
+
* any console, and built from layout primitives it is a run of adjacent text:
|
|
10
|
+
* nothing tells a screen reader that a label and a value belong together, or
|
|
11
|
+
* how many pairs there are. This renders the element the platform has for it,
|
|
12
|
+
* a `<dl>`, with each item's label a `<dt>` and its value a `<dd>`.
|
|
13
|
+
*
|
|
14
|
+
* **The items render their own term and description**, and the list takes them
|
|
15
|
+
* through its slot. The accessibility tree is built from the flattened tree, so
|
|
16
|
+
* the pairs reach it inside the list rather than beside it. Measured in
|
|
17
|
+
* Chromium's tree rather than assumed, because a list whose semantics stopped
|
|
18
|
+
* at a shadow boundary would look identical on screen: one description list
|
|
19
|
+
* holding term and definition pairs, node for node what a plain `<dl>` with the
|
|
20
|
+
* same content produces, with a slotted label and with an item drawn as
|
|
21
|
+
* `display: contents` alike.
|
|
22
|
+
*
|
|
23
|
+
* @since 0.1.0
|
|
24
|
+
* @status experimental
|
|
25
|
+
* @category data
|
|
26
|
+
* @aliases Data list, Key-value list, Details, Properties
|
|
27
|
+
* @documentation https://helix.fusion.dev/components/description-list
|
|
28
|
+
*
|
|
29
|
+
* @slot - The items.
|
|
30
|
+
*
|
|
31
|
+
* @csspart list - The `<dl>` holding the items.
|
|
32
|
+
*/
|
|
33
|
+
export declare class HelixHeadlessDescriptionList extends HelixElement {
|
|
34
|
+
/**
|
|
35
|
+
* Whether each label sits over its value or beside it.
|
|
36
|
+
*
|
|
37
|
+
* Absent is a column, the label over the value, which fits any width and is
|
|
38
|
+
* how a narrow panel reads. `row` puts every label in one column and every
|
|
39
|
+
* value in the next, which is how a wide panel is scanned: down the labels to
|
|
40
|
+
* the one wanted, then across.
|
|
41
|
+
*
|
|
42
|
+
* On the list rather than on each item, because beside only reads when the
|
|
43
|
+
* labels line up, and lining up is a fact about all of them.
|
|
44
|
+
*
|
|
45
|
+
* **Optional rather than defaulted to `column`**, for the reason `Stat` gives:
|
|
46
|
+
* a reflecting default writes an attribute onto markup the consumer rendered,
|
|
47
|
+
* and React reports that as a hydration mismatch.
|
|
48
|
+
*/
|
|
49
|
+
direction?: 'row';
|
|
50
|
+
protected render(): TemplateResult;
|
|
51
|
+
}
|
|
52
|
+
declare global {
|
|
53
|
+
interface HTMLElementTagNameMap {
|
|
54
|
+
'helix-headless-description-list': HelixHeadlessDescriptionList;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
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
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { customElement, HelixElement } from '@fusion.dev/helix-core';
|
|
8
|
+
import { html } from 'lit';
|
|
9
|
+
import { property } from 'lit/decorators.js';
|
|
10
|
+
let HelixHeadlessDescriptionList = class HelixHeadlessDescriptionList extends HelixElement {
|
|
11
|
+
render() {
|
|
12
|
+
return html `<dl part="list"><slot></slot></dl>`;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
__decorate([
|
|
16
|
+
property({ reflect: true })
|
|
17
|
+
], HelixHeadlessDescriptionList.prototype, "direction", void 0);
|
|
18
|
+
HelixHeadlessDescriptionList = __decorate([
|
|
19
|
+
customElement('helix-headless-description-list')
|
|
20
|
+
], HelixHeadlessDescriptionList);
|
|
21
|
+
export { HelixHeadlessDescriptionList };
|