argus-table 0.3.0 → 0.4.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/dist/argus-column-group.js +66 -0
- package/dist/argus-column-group.js.map +1 -0
- package/dist/argus-column.js +4 -25
- package/dist/argus-column.js.map +1 -1
- package/dist/argus-table.js +553 -200
- package/dist/argus-table.js.map +1 -1
- package/dist/attributes.js +21 -0
- package/dist/attributes.js.map +1 -0
- package/dist/cdn/argus-table.js +92 -57
- package/dist/cdn/argus-table.js.map +1 -1
- package/dist/column-registry.js +23 -0
- package/dist/column-registry.js.map +1 -0
- package/dist/controllers/auto-width.js +6 -5
- package/dist/controllers/auto-width.js.map +1 -1
- package/dist/controllers/column-children.js +32 -9
- package/dist/controllers/column-children.js.map +1 -1
- package/dist/controllers/column-window.js +0 -4
- package/dist/controllers/column-window.js.map +1 -1
- package/dist/controllers/plugins.js +25 -6
- package/dist/controllers/plugins.js.map +1 -1
- package/dist/controllers/reorder-drag.js +12 -9
- package/dist/controllers/reorder-drag.js.map +1 -1
- package/dist/controllers/row-measure.js +2 -1
- package/dist/controllers/row-measure.js.map +1 -1
- package/dist/controllers/virtual-controller.js +25 -32
- package/dist/controllers/virtual-controller.js.map +1 -1
- package/dist/core/src/columns/column-groups.js +129 -0
- package/dist/core/src/columns/column-groups.js.map +1 -0
- package/dist/core/src/columns/column-order.js +125 -31
- package/dist/core/src/columns/column-order.js.map +1 -1
- package/dist/core/src/columns/resolve-columns.js +0 -1
- package/dist/core/src/columns/resolve-columns.js.map +1 -1
- package/dist/core/src/columns/spread-width.js +43 -0
- package/dist/core/src/columns/spread-width.js.map +1 -0
- package/dist/core/src/filters/filter.js +6 -8
- package/dist/core/src/filters/filter.js.map +1 -1
- package/dist/core/src/grid/row-layout.js +19 -11
- package/dist/core/src/grid/row-layout.js.map +1 -1
- package/dist/core/src/state/selection.js +2 -1
- package/dist/core/src/state/selection.js.map +1 -1
- package/dist/core/src/table/create-table.js +57 -22
- package/dist/core/src/table/create-table.js.map +1 -1
- package/dist/core/src/table/sorted-row-model.js.map +1 -1
- package/dist/core/src/virtual/row-sizes.js +0 -4
- package/dist/core/src/virtual/row-sizes.js.map +1 -1
- package/dist/custom-elements.json +489 -245
- package/dist/events.js +16 -16
- package/dist/events.js.map +1 -1
- package/dist/index.d.ts +273 -127
- package/dist/index.js +3 -2
- package/dist/render/body.js +2 -2
- package/dist/render/body.js.map +1 -1
- package/dist/render/cells.js +11 -3
- package/dist/render/cells.js.map +1 -1
- package/dist/render/content-directive.js +1 -1
- package/dist/render/content-directive.js.map +1 -1
- package/dist/render/content.js +15 -3
- package/dist/render/content.js.map +1 -1
- package/dist/render/header.js +82 -19
- package/dist/render/header.js.map +1 -1
- package/dist/styles/base.js +1 -1
- package/dist/styles/base.js.map +1 -1
- package/package.json +1 -1
package/dist/argus-table.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { clickSelection, sameSelection, selectAll, selectRange, toggleRow } from "./core/src/state/selection.js";
|
|
2
2
|
import { controllable } from "./core/src/state/controllable.js";
|
|
3
|
+
import { groupKey } from "./core/src/columns/column-groups.js";
|
|
3
4
|
import { RowLayout } from "./core/src/grid/row-layout.js";
|
|
5
|
+
import { sameUnit } from "./core/src/columns/column-order.js";
|
|
6
|
+
import { spreadWidth } from "./core/src/columns/spread-width.js";
|
|
4
7
|
import "./core/src/table/create-table.js";
|
|
5
8
|
import { announce } from "./announce.js";
|
|
6
9
|
import { AutoWidths, measureColumns } from "./controllers/auto-width.js";
|
|
@@ -14,15 +17,16 @@ import { canStartReorder, dropTarget, startReorderDrag } from "./controllers/reo
|
|
|
14
17
|
import { startResizeDrag } from "./controllers/resize-drag.js";
|
|
15
18
|
import { TableController } from "./controllers/table-controller.js";
|
|
16
19
|
import { VirtualController } from "./controllers/virtual-controller.js";
|
|
17
|
-
import { CELL_CLICK,
|
|
20
|
+
import { CELL_CLICK, COLUMN_FILTERS_CHANGE, COLUMN_ORDER_CHANGE, COLUMN_PINNING_CHANGE, COLUMN_SIZING_CHANGE, COLUMN_VISIBILITY_CHANGE, LOAD_ERROR, RANGE_CHANGE, ROW_CLICK, SELECTION_CHANGE, SORTING_CHANGE, fire } from "./events.js";
|
|
18
21
|
import { fromInteractive } from "./interactive.js";
|
|
19
22
|
import { bodyCap, watchMaxElementHeight } from "./max-height.js";
|
|
20
23
|
import { renderBody } from "./render/body.js";
|
|
21
24
|
import { renderLightDom } from "./render/cells.js";
|
|
22
25
|
import { content, flushContent } from "./render/content-directive.js";
|
|
23
|
-
import { renderHeader } from "./render/header.js";
|
|
26
|
+
import { columnKey, renderHeader } from "./render/header.js";
|
|
24
27
|
import { renderPinnedRows } from "./render/pinned-rows.js";
|
|
25
28
|
import { baseStyles } from "./styles/base.js";
|
|
29
|
+
import { switchConverter } from "./attributes.js";
|
|
26
30
|
import __decorate from "./_virtual/_@oxc-project_runtime@0.156.0/helpers/esm/decorate.js";
|
|
27
31
|
import { LitElement, html, nothing } from "lit";
|
|
28
32
|
import { customElement, property } from "lit/decorators.js";
|
|
@@ -50,7 +54,7 @@ function sortColumnOf(event) {
|
|
|
50
54
|
if (target.dataset.resizeCol !== void 0) return void 0;
|
|
51
55
|
if (target.matches("button,input,select,textarea,a[href],label,[contenteditable],[popover],dialog")) return void 0;
|
|
52
56
|
if (target.dataset.sortCol !== void 0) return target.dataset.sortCol;
|
|
53
|
-
if (target.getAttribute("
|
|
57
|
+
if (target.getAttribute("role") === "row") return void 0;
|
|
54
58
|
}
|
|
55
59
|
}
|
|
56
60
|
var RESIZE_STEP = 10;
|
|
@@ -62,13 +66,13 @@ var rowHeightConverter = { fromAttribute(value) {
|
|
|
62
66
|
const px = Number(text.replace(/px$/, ""));
|
|
63
67
|
return text !== "" && px > 0 ? px : void 0;
|
|
64
68
|
} };
|
|
65
|
-
|
|
66
|
-
section: "header",
|
|
67
|
-
index: 0
|
|
68
|
-
};
|
|
69
|
-
/** Where the rows sit in the grid: header, pinned top, body, pinned bottom. */
|
|
69
|
+
/** Where the rows sit in the grid: header rows, pinned top, body, pinned bottom. */
|
|
70
70
|
function layoutOf(model) {
|
|
71
|
-
return new RowLayout(model.pinnedCount("top"), model.rowCount, model.pinnedCount("bottom"));
|
|
71
|
+
return new RowLayout(model.pinnedCount("top"), model.rowCount, model.pinnedCount("bottom"), model.headerRows);
|
|
72
|
+
}
|
|
73
|
+
/** The drop slot and applied-move key of a column or group (`HeaderDrag.key`). */
|
|
74
|
+
function unitKey(unit) {
|
|
75
|
+
return unit.kind === "column" ? columnKey(unit.id) : groupKey(unit.id, unit.pin);
|
|
72
76
|
}
|
|
73
77
|
/** The grid cell or column header an element is, if any. */
|
|
74
78
|
function gridCell(target) {
|
|
@@ -76,11 +80,19 @@ function gridCell(target) {
|
|
|
76
80
|
const role = target.getAttribute("role");
|
|
77
81
|
return role === "gridcell" || role === "columnheader" ? target : void 0;
|
|
78
82
|
}
|
|
83
|
+
/** The column group header an element is, if any. */
|
|
84
|
+
function groupCell(target) {
|
|
85
|
+
return target instanceof HTMLElement && target.dataset.groupKey !== void 0 ? target : void 0;
|
|
86
|
+
}
|
|
79
87
|
/** The grid row a rendered row element is, from its `aria-rowindex`. */
|
|
80
88
|
function gridRowOf(row, layout) {
|
|
81
89
|
const index = row?.getAttribute("aria-rowindex");
|
|
82
90
|
return index ? layout.fromAriaRowIndex(Number(index)) : void 0;
|
|
83
91
|
}
|
|
92
|
+
/** The grid row a cell or column header is in. */
|
|
93
|
+
function gridRowOfCell(cell, layout) {
|
|
94
|
+
return gridRowOf(cell.parentElement, layout);
|
|
95
|
+
}
|
|
84
96
|
/**
|
|
85
97
|
* The pinned edge's shadow, drawn once per side over the scroller rather than
|
|
86
98
|
* per row: a shadow on every pinned cell repaints on every scroll frame. It
|
|
@@ -103,6 +115,10 @@ function pinShadow(side, width, contentPx) {
|
|
|
103
115
|
function track(column) {
|
|
104
116
|
return column.flex === void 0 ? `${String(column.width)}px` : `minmax(${String(column.minWidth)}px, ${String(column.flex)}fr)`;
|
|
105
117
|
}
|
|
118
|
+
/** Total width of the columns pinned to one side. */
|
|
119
|
+
function pinnedWidth(columns, side) {
|
|
120
|
+
return columns.reduce((sum, c) => c.pin === side ? sum + c.width : sum, 0);
|
|
121
|
+
}
|
|
106
122
|
var ArgusTable = class ArgusTable extends LitElement {
|
|
107
123
|
static {
|
|
108
124
|
this.styles = baseStyles;
|
|
@@ -119,6 +135,21 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
119
135
|
this.#columnsProp = value ?? [];
|
|
120
136
|
}
|
|
121
137
|
/**
|
|
138
|
+
* Headers over several columns: `{ id, header, columns }`, where `columns` lists
|
|
139
|
+
* column ids and nested groups. Each level of nesting adds a header row. A group's
|
|
140
|
+
* columns stay next to each other: they move within the group, and the group
|
|
141
|
+
* moves as a whole (drag its header, or Alt+Shift+Arrow). A group whose columns
|
|
142
|
+
* are pinned to different sides shows on each side. Property only. While empty
|
|
143
|
+
* and `columns` is too, the table reads its `<argus-column-group>` children.
|
|
144
|
+
* `null` or `undefined` means `[]`.
|
|
145
|
+
*/
|
|
146
|
+
get columnGroups() {
|
|
147
|
+
return this.#columnGroupsProp;
|
|
148
|
+
}
|
|
149
|
+
set columnGroups(value) {
|
|
150
|
+
this.#columnGroupsProp = value ?? [];
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
122
153
|
* The rows to show. Replace the array to update; changes inside it aren't
|
|
123
154
|
* detected. `null` or `undefined` means `[]`.
|
|
124
155
|
*/
|
|
@@ -138,7 +169,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
138
169
|
/**
|
|
139
170
|
* The sort order, e.g. `[{ id: 'total', desc: true }]`; `[]` when unsorted. Unset,
|
|
140
171
|
* the table keeps it itself and header clicks change it. Once set, it is
|
|
141
|
-
* controlled: a click only fires `argus-
|
|
172
|
+
* controlled: a click only fires `argus-sorting-change` with the proposed order,
|
|
142
173
|
* and nothing changes until you set the property. Set `undefined` to hand it back.
|
|
143
174
|
*/
|
|
144
175
|
get sorting() {
|
|
@@ -150,7 +181,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
150
181
|
/**
|
|
151
182
|
* Resized widths in px by column id, e.g. `{ name: 240 }`. A resized flex column
|
|
152
183
|
* becomes fixed. Uncontrolled until set, like `sorting`: once set, a resize only
|
|
153
|
-
* fires `argus-column-
|
|
184
|
+
* fires `argus-column-sizing-change` with the proposed widths. `undefined` hands it back.
|
|
154
185
|
*/
|
|
155
186
|
get columnSizing() {
|
|
156
187
|
return this.#sizing.value;
|
|
@@ -164,7 +195,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
164
195
|
* Each pin group (start-pinned, scrolling, end-pinned) takes its columns in this
|
|
165
196
|
* order; unknown ids are ignored and columns it doesn't list follow the listed
|
|
166
197
|
* ones of their group. After a move it holds every column id. Uncontrolled
|
|
167
|
-
* until set, like `sorting`: once set, a move only fires `argus-column-
|
|
198
|
+
* until set, like `sorting`: once set, a move only fires `argus-column-order-change`
|
|
168
199
|
* with the proposed order. `undefined` hands it back.
|
|
169
200
|
*/
|
|
170
201
|
get columnOrder() {
|
|
@@ -179,7 +210,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
179
210
|
* `{ total: 'end', id: false }`. Columns it doesn't list keep their `pin`. A pinned
|
|
180
211
|
* column joins the edge of its group nearest its place in `columnOrder`, and stops
|
|
181
212
|
* flexing. Uncontrolled until set, like `sorting`: once set, pinning from a plugin
|
|
182
|
-
* only fires `argus-column-
|
|
213
|
+
* only fires `argus-column-pinning-change` with the proposed pins. `undefined` hands it back.
|
|
183
214
|
*/
|
|
184
215
|
get columnPinning() {
|
|
185
216
|
return this.#pinning.value;
|
|
@@ -193,7 +224,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
193
224
|
* doesn't list keep their `hidden`. A hidden column isn't rendered, but sorting by
|
|
194
225
|
* it still works and it keeps its place in `columnOrder`. Uncontrolled until set,
|
|
195
226
|
* like `sorting`: once set, hiding or showing from a plugin only fires
|
|
196
|
-
* `argus-column-
|
|
227
|
+
* `argus-column-visibility-change` with the proposed visibility. `undefined` hands it back.
|
|
197
228
|
*/
|
|
198
229
|
get columnVisibility() {
|
|
199
230
|
return this.#visibility.value;
|
|
@@ -209,7 +240,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
209
240
|
* `dataSource`, the filters go to `getRows()` and the server filters. Users set
|
|
210
241
|
* filters through plugins (the column menu) on columns with a `filter` kind.
|
|
211
242
|
* Uncontrolled until set, like `sorting`: once set, a change from a plugin only
|
|
212
|
-
* fires `argus-column-
|
|
243
|
+
* fires `argus-column-filters-change` with the proposed filters. `undefined` hands it back.
|
|
213
244
|
*/
|
|
214
245
|
get columnFilters() {
|
|
215
246
|
return this.#filters.value;
|
|
@@ -232,7 +263,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
232
263
|
/**
|
|
233
264
|
* The selected rows, as row ids (from `getRowId`, or the row's index as a
|
|
234
265
|
* string), e.g. `['p4', 'p7']`. Uncontrolled until set, like `sorting`: once
|
|
235
|
-
* set, a click only fires `argus-
|
|
266
|
+
* set, a click only fires `argus-selection-change` with the proposed ids.
|
|
236
267
|
* `undefined` hands it back. The table never drops ids on its own: they stay
|
|
237
268
|
* through sorting, a new `data` or reloaded pages. With a `dataSource`,
|
|
238
269
|
* Ctrl/Cmd+A selects the loaded rows only.
|
|
@@ -258,6 +289,10 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
258
289
|
if (!sameItems(next, this.#pluginsProp)) this.#pluginsProp = next;
|
|
259
290
|
}
|
|
260
291
|
#columnsProp;
|
|
292
|
+
#columnGroupsProp;
|
|
293
|
+
/** The groups last passed to the model: `columnGroups`, or the `<argus-column-group>` children. */
|
|
294
|
+
#groups;
|
|
295
|
+
#groupsChanged;
|
|
261
296
|
#pluginsProp;
|
|
262
297
|
#dataProp;
|
|
263
298
|
#overscan;
|
|
@@ -286,13 +321,13 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
286
321
|
/** Whether the checkbox column was last shown; a change re-measures the pinned columns. */
|
|
287
322
|
#selectionColumn;
|
|
288
323
|
#selectionColumnChanged;
|
|
289
|
-
/** The select-all checkbox's state, kept until
|
|
324
|
+
/** The select-all checkbox's state, kept until the selection or the shown rows change. */
|
|
290
325
|
#checkAll;
|
|
291
|
-
/** Moves the table applied itself, by column; their events fire once the update is done. */
|
|
326
|
+
/** Moves the table applied itself, by column or group; their events fire once the update is done. */
|
|
292
327
|
#appliedReorders;
|
|
293
328
|
/** The header being dragged to a new position, if any. */
|
|
294
329
|
#drag;
|
|
295
|
-
/** A move from the keyboard, announced once it has rendered:
|
|
330
|
+
/** A move from the keyboard, announced once it has rendered: what moved and its old position. */
|
|
296
331
|
#announceMove;
|
|
297
332
|
/** Resizes the table applied itself, by column; their events fire once the update is done. */
|
|
298
333
|
#appliedResizes;
|
|
@@ -316,6 +351,8 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
316
351
|
#columns;
|
|
317
352
|
#columnsChanged;
|
|
318
353
|
#warnedColumns;
|
|
354
|
+
/** The header row of column headers at the last reconcile (`#reconcileActive`). */
|
|
355
|
+
#leafLevel;
|
|
319
356
|
/** End of the light-DOM part holding cell content, so later children stay outside it. */
|
|
320
357
|
#contentEnd;
|
|
321
358
|
/** The light-DOM part: disconnected with the table, so foreign content is released. */
|
|
@@ -346,6 +383,10 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
346
383
|
* aren't counted yet. Scrolled to again whenever the row count changes.
|
|
347
384
|
*/
|
|
348
385
|
#scrollTarget;
|
|
386
|
+
/** The scroll container (`part="table"`); `null` before the first render. */
|
|
387
|
+
#scroller() {
|
|
388
|
+
return this.renderRoot.querySelector("[part~=\"table\"]");
|
|
389
|
+
}
|
|
349
390
|
constructor() {
|
|
350
391
|
super();
|
|
351
392
|
this.density = "comfortable";
|
|
@@ -353,6 +394,9 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
353
394
|
this.selectionMode = "none";
|
|
354
395
|
this.selectionCheckboxes = false;
|
|
355
396
|
this.#columnsProp = [];
|
|
397
|
+
this.#columnGroupsProp = [];
|
|
398
|
+
this.#groups = [];
|
|
399
|
+
this.#groupsChanged = false;
|
|
356
400
|
this.#pluginsProp = [];
|
|
357
401
|
this.#dataProp = [];
|
|
358
402
|
this.#overscan = 6;
|
|
@@ -397,12 +441,14 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
397
441
|
this.#requestFilter(columnId, filter);
|
|
398
442
|
},
|
|
399
443
|
filterValues: (columnId, limit) => this.#table.model.filterValues(columnId, limit),
|
|
444
|
+
filteredIndexes: (except) => this.#table.model.indexesPassing(except),
|
|
400
445
|
cellOf: (event) => this.#cellTarget(event),
|
|
401
446
|
setSort: (columnId, direction) => {
|
|
402
447
|
this.#setSort(columnId, direction);
|
|
403
448
|
},
|
|
404
449
|
focusHeader: (columnId) => {
|
|
405
|
-
|
|
450
|
+
const model = this.#table.model;
|
|
451
|
+
this.#moveTo(layoutOf(model).leafHeader, columnId, model);
|
|
406
452
|
},
|
|
407
453
|
announce: (message) => {
|
|
408
454
|
announce(this.ownerDocument, message);
|
|
@@ -421,12 +467,13 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
421
467
|
this.#columns = [];
|
|
422
468
|
this.#columnsChanged = false;
|
|
423
469
|
this.#warnedColumns = false;
|
|
470
|
+
this.#leafLevel = 0;
|
|
424
471
|
this.#lightConnected = true;
|
|
425
472
|
this.#data = new DataController(this);
|
|
426
473
|
this.#scrollToTop = false;
|
|
427
|
-
this.#virtual = new VirtualController(this, () => this
|
|
428
|
-
this.#pinScroll = new PinScrollController(this, () => this
|
|
429
|
-
this.#columnWindow = new ColumnWindowController(this, () => this
|
|
474
|
+
this.#virtual = new VirtualController(this, () => this.#scroller());
|
|
475
|
+
this.#pinScroll = new PinScrollController(this, () => this.#scroller());
|
|
476
|
+
this.#columnWindow = new ColumnWindowController(this, () => this.#scroller());
|
|
430
477
|
this.#rendered = [];
|
|
431
478
|
this.#rowPx = 40;
|
|
432
479
|
this.#rowsKey = "";
|
|
@@ -462,6 +509,15 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
462
509
|
if (event.button !== 0) return;
|
|
463
510
|
const handle = event.composedPath()[0];
|
|
464
511
|
if (!(handle instanceof HTMLElement)) return;
|
|
512
|
+
const group = this.#groupCellOf(handle.dataset.resizeGroup);
|
|
513
|
+
if (group) {
|
|
514
|
+
const starts = this.#groupWidths(group.columns);
|
|
515
|
+
const total = [...starts.values()].reduce((sum, w) => sum + w, 0);
|
|
516
|
+
startResizeDrag(handle, event, total, this.#direction(), (w) => {
|
|
517
|
+
this.#requestGroupResize(group.columns, starts, w);
|
|
518
|
+
});
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
465
521
|
const id = handle.dataset.resizeCol;
|
|
466
522
|
const cell = handle.parentElement;
|
|
467
523
|
if (id !== void 0 && cell) {
|
|
@@ -475,15 +531,23 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
475
531
|
/** A double-click on a resize handle fits the column to its rendered content. */
|
|
476
532
|
dblclick: (event) => {
|
|
477
533
|
const handle = event.composedPath()[0];
|
|
478
|
-
|
|
534
|
+
if (!(handle instanceof HTMLElement)) return;
|
|
535
|
+
const group = this.#groupCellOf(handle.dataset.resizeGroup);
|
|
536
|
+
if (group) {
|
|
537
|
+
this.autosizeColumns([...group.columns]);
|
|
538
|
+
return;
|
|
539
|
+
}
|
|
540
|
+
const id = handle.dataset.resizeCol;
|
|
479
541
|
if (id === void 0) return;
|
|
480
542
|
this.#requestResizes(measureColumns(this.renderRoot, [id]));
|
|
481
543
|
}
|
|
482
544
|
};
|
|
483
545
|
this.#onKeydown = (event) => {
|
|
484
|
-
const
|
|
546
|
+
const origin = event.composedPath()[0] ?? event.target ?? this;
|
|
547
|
+
const group = groupCell(origin);
|
|
548
|
+
const cell = gridCell(origin) ?? group;
|
|
485
549
|
const id = cell?.dataset.col;
|
|
486
|
-
if (!cell || id === void 0) return;
|
|
550
|
+
if (!cell || id === void 0 && !group) return;
|
|
487
551
|
const scroller = event.currentTarget;
|
|
488
552
|
if (event.key === "Tab" && event.shiftKey) {
|
|
489
553
|
scroller.tabIndex = -1;
|
|
@@ -492,21 +556,22 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
492
556
|
}, { once: true });
|
|
493
557
|
return;
|
|
494
558
|
}
|
|
559
|
+
if (group || id === void 0) {
|
|
560
|
+
this.#groupKey(event, cell, scroller);
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
495
563
|
const pluginTarget = id === "--argus-selection" ? void 0 : this.#cellTarget(event);
|
|
496
564
|
if (pluginTarget && this.#plugins.keydown(event, pluginTarget)) return;
|
|
497
565
|
const inHeader = cell.getAttribute("role") === "columnheader";
|
|
498
566
|
const { key } = event;
|
|
499
|
-
|
|
500
|
-
if (inHeader && arrow && event.altKey && event.shiftKey) {
|
|
501
|
-
event.preventDefault();
|
|
502
|
-
const towardEnd = key === "ArrowRight" === (this.#direction() === 1);
|
|
503
|
-
this.#moveByKey(id, towardEnd ? 1 : -1);
|
|
504
|
-
return;
|
|
505
|
-
}
|
|
506
|
-
if (inHeader && event.altKey && arrow) {
|
|
567
|
+
if (inHeader && (key === "ArrowLeft" || key === "ArrowRight") && event.altKey) {
|
|
507
568
|
event.preventDefault();
|
|
508
569
|
const towardEnd = key === "ArrowRight" === (this.#direction() === 1);
|
|
509
|
-
|
|
570
|
+
if (event.shiftKey) this.#moveByKey({
|
|
571
|
+
kind: "column",
|
|
572
|
+
id
|
|
573
|
+
}, towardEnd ? 1 : -1);
|
|
574
|
+
else this.#requestResize(id, this.#currentWidth(id, cell) + (towardEnd ? RESIZE_STEP : -10));
|
|
510
575
|
return;
|
|
511
576
|
}
|
|
512
577
|
if (inHeader && (key === "Enter" || key === " ") && cell.dataset.sortCol !== void 0) {
|
|
@@ -519,7 +584,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
519
584
|
if (event.altKey || event.shiftKey || corner && key !== "Home" && key !== "End") return;
|
|
520
585
|
const model = this.#table.model;
|
|
521
586
|
const layout = layoutOf(model);
|
|
522
|
-
const from =
|
|
587
|
+
const from = gridRowOfCell(cell, layout);
|
|
523
588
|
if (!from) return;
|
|
524
589
|
if (!inHeader && key === "Enter") {
|
|
525
590
|
event.preventDefault();
|
|
@@ -547,7 +612,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
547
612
|
case "Home":
|
|
548
613
|
col = 0;
|
|
549
614
|
if (corner) {
|
|
550
|
-
pos = 0;
|
|
615
|
+
pos = this.#headerLevelDown(model, 0, columns[0]?.id ?? id);
|
|
551
616
|
this.#virtual.scrollToEdge("start");
|
|
552
617
|
}
|
|
553
618
|
break;
|
|
@@ -558,11 +623,20 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
558
623
|
default: return;
|
|
559
624
|
}
|
|
560
625
|
event.preventDefault();
|
|
561
|
-
|
|
626
|
+
let row = layout.at(pos) ?? layout.leafHeader;
|
|
627
|
+
const target = columns[Math.min(Math.max(col, 0), columns.length - 1)];
|
|
628
|
+
if (!target) return;
|
|
629
|
+
if (row.section === "header" && row.index < layout.header - 1 && key === "ArrowUp") {
|
|
630
|
+
const level = this.#headerLevelUp(model, row.index, target.id);
|
|
631
|
+
if (level === void 0) return;
|
|
632
|
+
row = {
|
|
633
|
+
section: "header",
|
|
634
|
+
index: level
|
|
635
|
+
};
|
|
636
|
+
}
|
|
562
637
|
if (key.startsWith("Page") && from.section === "body" && row.section === "body") this.#virtual.scrollBy(this.#virtual.startOf(row.index) - this.#virtual.startOf(from.index));
|
|
563
638
|
if (corner && key === "End" && row.section === "bottom") this.#virtual.scrollToEdge("end");
|
|
564
|
-
|
|
565
|
-
if (target) this.#moveTo(row, target.id, model);
|
|
639
|
+
this.#moveTo(row, target.id, model);
|
|
566
640
|
};
|
|
567
641
|
this.#onFocusin = (event) => {
|
|
568
642
|
const scroller = event.currentTarget;
|
|
@@ -575,10 +649,15 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
575
649
|
return;
|
|
576
650
|
}
|
|
577
651
|
for (const target of event.composedPath()) {
|
|
652
|
+
const group = groupCell(target);
|
|
653
|
+
if (group) {
|
|
654
|
+
this.#focusGroup(group);
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
578
657
|
const cell = gridCell(target);
|
|
579
658
|
if (cell?.dataset.col !== void 0) {
|
|
580
659
|
const model = this.#table.model;
|
|
581
|
-
const row =
|
|
660
|
+
const row = gridRowOfCell(cell, layoutOf(model));
|
|
582
661
|
const { col } = cell.dataset;
|
|
583
662
|
const prev = this.#active;
|
|
584
663
|
if (row && (row.section !== prev?.section || row.index !== prev.index || col !== prev.col)) {
|
|
@@ -646,24 +725,23 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
646
725
|
super.connectedCallback();
|
|
647
726
|
if (!this.hasAttribute("role")) this.setAttribute("role", "grid");
|
|
648
727
|
if (this.hasUpdated) this.#observeProbe();
|
|
649
|
-
|
|
650
|
-
this.#lightConnected = true;
|
|
651
|
-
this.#lightPart.setConnected(true);
|
|
652
|
-
flushContent(this);
|
|
653
|
-
}
|
|
728
|
+
this.#setLightConnected(true);
|
|
654
729
|
this.#unwatchMaxHeight = watchMaxElementHeight(() => {
|
|
655
730
|
this.requestUpdate();
|
|
656
731
|
});
|
|
657
732
|
}
|
|
733
|
+
/** Connects or disconnects the cell content (framework content mounts and unmounts with it). */
|
|
734
|
+
#setLightConnected(connected) {
|
|
735
|
+
if (!this.#lightPart || this.#lightConnected === connected) return;
|
|
736
|
+
this.#lightConnected = connected;
|
|
737
|
+
this.#lightPart.setConnected(connected);
|
|
738
|
+
flushContent(this);
|
|
739
|
+
}
|
|
658
740
|
disconnectedCallback() {
|
|
659
741
|
super.disconnectedCallback();
|
|
660
742
|
this.#probeObserver?.disconnect();
|
|
661
743
|
this.#rowMeasure.stop();
|
|
662
|
-
|
|
663
|
-
this.#lightConnected = false;
|
|
664
|
-
this.#lightPart.setConnected(false);
|
|
665
|
-
flushContent(this);
|
|
666
|
-
}
|
|
744
|
+
this.#setLightConnected(false);
|
|
667
745
|
this.#unwatchMaxHeight?.();
|
|
668
746
|
this.#unwatchMaxHeight = void 0;
|
|
669
747
|
}
|
|
@@ -680,6 +758,14 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
680
758
|
return this.columns;
|
|
681
759
|
}
|
|
682
760
|
/**
|
|
761
|
+
* `columnGroups` when it has any or `columns` is set (which turns off all
|
|
762
|
+
* children), otherwise the `<argus-column-group>` children.
|
|
763
|
+
*/
|
|
764
|
+
#effectiveGroups() {
|
|
765
|
+
if (this.columnGroups.length > 0 || this.columns.length > 0) return this.columnGroups;
|
|
766
|
+
return this.#children.groups;
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
683
769
|
* The node the light-DOM content is rendered before. Lit's part then ends there,
|
|
684
770
|
* so children appended later (an `<argus-column>`) never land inside it. If the
|
|
685
771
|
* marker was removed (say by `innerHTML`), a new one starts a fresh part.
|
|
@@ -705,7 +791,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
705
791
|
/**
|
|
706
792
|
* Fits columns to their content: the header, the pinned rows and the body rows
|
|
707
793
|
* rendered now (rows out of view aren't measured). It resizes them like a drag
|
|
708
|
-
* would, so `argus-column-
|
|
794
|
+
* would, so `argus-column-sizing-change` fires for each column that changes, and with a
|
|
709
795
|
* controlled `columnSizing` nothing changes until you set it. Without `ids`, fits
|
|
710
796
|
* every resizable column; columns with `resizable: false` keep their width.
|
|
711
797
|
* With `virtualizeColumns`, columns out of view render for the measurement.
|
|
@@ -745,13 +831,14 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
745
831
|
* The state users change, as one object of plain JSON for saving a user's
|
|
746
832
|
* layout: `sorting`, `columnSizing`, `columnOrder`, `columnPinning`,
|
|
747
833
|
* `columnVisibility`, `columnFilters`, `selection`, `quickFilter`, and `scroll`
|
|
748
|
-
* (the row at the top and the
|
|
834
|
+
* (the row at the top and the inline offset), with `version: 1`. Controlled properties are
|
|
749
835
|
* included with the values you set. The object is a copy: changing it changes
|
|
750
836
|
* nothing in the table.
|
|
751
837
|
*/
|
|
752
838
|
getState() {
|
|
753
|
-
const scroller = this
|
|
839
|
+
const scroller = this.#scroller();
|
|
754
840
|
return structuredClone({
|
|
841
|
+
version: 1,
|
|
755
842
|
sorting: this.#sorting.value,
|
|
756
843
|
columnSizing: this.#sizing.value,
|
|
757
844
|
columnOrder: this.#order.value,
|
|
@@ -762,14 +849,14 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
762
849
|
quickFilter: this.#quickFilter,
|
|
763
850
|
scroll: {
|
|
764
851
|
row: this.#virtual.topRow,
|
|
765
|
-
|
|
852
|
+
inline: Math.abs(scroller?.scrollLeft ?? 0)
|
|
766
853
|
}
|
|
767
854
|
});
|
|
768
855
|
}
|
|
769
856
|
/**
|
|
770
857
|
* Restores state from `getState()`, for example a layout saved in
|
|
771
858
|
* `localStorage`. Only the keys given change; ids of columns that no longer
|
|
772
|
-
* exist are ignored. Properties you control are left alone (set them
|
|
859
|
+
* exist are ignored. State of another `version` is ignored as a whole. Properties you control are left alone (set them
|
|
773
860
|
* yourself), and the others stay uncontrolled. No change events fire.
|
|
774
861
|
* `quickFilter` is set like the property: a search box of yours shows it only
|
|
775
862
|
* if you read it back. `scroll` is applied after the rest, so with a
|
|
@@ -777,6 +864,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
777
864
|
* has re-rendered there.
|
|
778
865
|
*/
|
|
779
866
|
async setState(state) {
|
|
867
|
+
if ((state.version ?? 1) !== 1) return;
|
|
780
868
|
this.#restore("sorting", this.#sorting, state.sorting);
|
|
781
869
|
this.#restore("columnSizing", this.#sizing, state.columnSizing);
|
|
782
870
|
this.#restore("columnOrder", this.#order, state.columnOrder);
|
|
@@ -795,8 +883,8 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
795
883
|
row: scroll.row,
|
|
796
884
|
count
|
|
797
885
|
};
|
|
798
|
-
const scroller = this
|
|
799
|
-
if (scroller) scroller.scrollLeft = scroll.
|
|
886
|
+
const scroller = this.#scroller();
|
|
887
|
+
if (scroller && scroll.inline >= 0) scroller.scrollLeft = scroll.inline * this.#direction();
|
|
800
888
|
await new Promise(requestAnimationFrame);
|
|
801
889
|
await this.#settled();
|
|
802
890
|
}
|
|
@@ -822,9 +910,13 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
822
910
|
}
|
|
823
911
|
willUpdate(changed) {
|
|
824
912
|
if (changed.has("plugins")) this.#plugins.set(this.plugins);
|
|
913
|
+
this.#plugins.willUpdate(new Set(changed.keys()));
|
|
825
914
|
const columns = this.#plugins.transform(this.#effectiveColumns());
|
|
826
915
|
this.#columnsChanged = columns !== this.#columns;
|
|
827
916
|
this.#columns = columns;
|
|
917
|
+
const groups = this.#plugins.transformGroups(this.#effectiveGroups());
|
|
918
|
+
this.#groupsChanged = groups !== this.#groups;
|
|
919
|
+
this.#groups = groups;
|
|
828
920
|
const filtersChanged = changed.has("columnFilters") || changed.has("quickFilter");
|
|
829
921
|
if (changed.has("dataSource") || changed.has("sorting") || changed.has("getRowId") || filtersChanged) {
|
|
830
922
|
this.#data.configure({
|
|
@@ -838,10 +930,11 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
838
930
|
this.#scrollTarget = void 0;
|
|
839
931
|
}
|
|
840
932
|
if (filtersChanged && this.hasUpdated) this.#announceRows = true;
|
|
841
|
-
if (this.#columnsChanged || changed.has("data") || changed.has("getRowId") || changed.has("sorting") || changed.has("columnSizing") || changed.has("columnOrder") || changed.has("columnPinning") || changed.has("columnVisibility") || changed.has("columnFilters") || changed.has("quickFilter") || changed.has("pinnedRows")) {
|
|
933
|
+
if (this.#columnsChanged || this.#groupsChanged || changed.has("data") || changed.has("getRowId") || changed.has("sorting") || changed.has("columnSizing") || changed.has("columnOrder") || changed.has("columnPinning") || changed.has("columnVisibility") || changed.has("columnFilters") || changed.has("quickFilter") || changed.has("pinnedRows")) {
|
|
842
934
|
if (this.#columnsChanged) this.#autoWidths.sync(columns.filter((c) => c.width === "auto").map((c) => c.id));
|
|
843
935
|
this.#table.update({
|
|
844
936
|
columns,
|
|
937
|
+
columnGroups: groups,
|
|
845
938
|
data: this.data,
|
|
846
939
|
getRowId: this.getRowId,
|
|
847
940
|
sorting: this.#sorting.value,
|
|
@@ -873,7 +966,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
873
966
|
this.#internals.ariaRowCount = unknownTotal ? "-1" : String(layout.total);
|
|
874
967
|
this.#internals.ariaColCount = String(model.columns.length);
|
|
875
968
|
this.#internals.ariaMultiSelectable = this.#mode() === "multi" ? "true" : null;
|
|
876
|
-
const extra = this.#
|
|
969
|
+
const extra = this.#headerAndPinnedPx(layout);
|
|
877
970
|
const auto = this.rowHeight === "auto";
|
|
878
971
|
if (!auto) this.#rowMeasure.stop();
|
|
879
972
|
else if (changed.size > 0 || this.#columnsChanged) this.#rowMeasure.invalidate();
|
|
@@ -899,20 +992,22 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
899
992
|
this.#window = this.#virtual.computeWindow();
|
|
900
993
|
const rendered = this.#columnWindow.compute(columns, this.virtualizeColumns, this.virtualizeColumns ? this.#keptColumns(model) : []);
|
|
901
994
|
this.#rendered = rendered;
|
|
902
|
-
const
|
|
903
|
-
const
|
|
995
|
+
const pinStart = pinnedWidth(columns, "start");
|
|
996
|
+
const pinEnd = pinnedWidth(columns, "end");
|
|
997
|
+
const cols = columns.map(track).join(" ");
|
|
904
998
|
const layout = layoutOf(model);
|
|
905
999
|
const style = {
|
|
906
|
-
"--_cols":
|
|
1000
|
+
"--_cols": cols,
|
|
907
1001
|
"--_width": `${String(model.totalWidth)}px`,
|
|
908
|
-
"--_pin-start":
|
|
909
|
-
"--_pin-end":
|
|
1002
|
+
"--_pin-start": `${String(pinStart)}px`,
|
|
1003
|
+
"--_pin-end": `${String(pinEnd)}px`,
|
|
1004
|
+
"--_header-rows": String(layout.header),
|
|
910
1005
|
"--_pin-top-rows": String(layout.top),
|
|
911
1006
|
"--_pin-bottom-rows": String(layout.bottom)
|
|
912
1007
|
};
|
|
913
1008
|
const auto = this.rowHeight === "auto";
|
|
914
1009
|
if (auto) {
|
|
915
|
-
const key = `${
|
|
1010
|
+
const key = `${cols}|${String(this.#rowPx)}`;
|
|
916
1011
|
if (key !== this.#rowsKey) {
|
|
917
1012
|
this.#rowsKey = key;
|
|
918
1013
|
this.#rowMeasure.invalidate();
|
|
@@ -930,7 +1025,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
930
1025
|
index: 0
|
|
931
1026
|
});
|
|
932
1027
|
if (typeof this.rowHeight === "number" && this.rowHeight > 0) style["--_row-height"] = `${String(this.rowHeight)}px`;
|
|
933
|
-
const contentPx = this.#
|
|
1028
|
+
const contentPx = this.#headerAndPinnedPx(layout) + (model.rowCount === 0 ? 0 : this.#window.totalSize);
|
|
934
1029
|
return html`<div
|
|
935
1030
|
part="table"
|
|
936
1031
|
role="presentation"
|
|
@@ -942,14 +1037,20 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
942
1037
|
@mousedown=${this.#onMousedown}
|
|
943
1038
|
@click=${this.#onClick}
|
|
944
1039
|
>
|
|
945
|
-
${renderHeader(
|
|
1040
|
+
${renderHeader({
|
|
1041
|
+
columns: rendered,
|
|
1042
|
+
groups: model.headerGroups,
|
|
1043
|
+
handlers: this.#headerHandlers,
|
|
1044
|
+
active: activeIn("header"),
|
|
1045
|
+
drag: this.#drag,
|
|
1046
|
+
checkAll: this.#checkAllOf(model)
|
|
1047
|
+
})}
|
|
946
1048
|
${renderPinnedRows("top", layout.top, rendered, firstIndex("top"), activeIn("top"))}
|
|
947
1049
|
${model.rowCount === 0 ? html`<div part="empty"><slot name="empty">No rows</slot></div>` : renderBody(this.#window.rows, rendered, this.#window.totalSize, activeIn("body"), firstIndex("body"), this.#loading(), this.#selectedAt(model), this.#selectionColumn ? this.#checkboxHandlers : void 0, auto)}
|
|
948
1050
|
${renderPinnedRows("bottom", layout.bottom, rendered, firstIndex("bottom"), activeIn("bottom"))}
|
|
949
1051
|
<div class="probe" aria-hidden="true"></div>
|
|
950
1052
|
</div>
|
|
951
|
-
${pinShadow("start",
|
|
952
|
-
${pinShadow("end", pinnedWidth("end"), contentPx)}`;
|
|
1053
|
+
${pinShadow("start", pinStart, contentPx)} ${pinShadow("end", pinEnd, contentPx)}`;
|
|
953
1054
|
}
|
|
954
1055
|
firstUpdated() {
|
|
955
1056
|
this.#observeProbe();
|
|
@@ -957,7 +1058,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
957
1058
|
}
|
|
958
1059
|
updated(changed) {
|
|
959
1060
|
const model = this.#table.model;
|
|
960
|
-
const part = renderLightDom(this, model, this.#window.rows, this.#rendered, this.#lightDomEnd());
|
|
1061
|
+
const part = renderLightDom(this, model, this.#window.rows, this.#rendered, model.headerGroups, this.#lightDomEnd());
|
|
961
1062
|
if (this.#lightPart && this.#lightPart !== part) this.#lightPart.setConnected(false);
|
|
962
1063
|
this.#lightPart = part;
|
|
963
1064
|
flushContent(this);
|
|
@@ -965,45 +1066,25 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
965
1066
|
const resized = this.rowHeight === "auto" && this.#measureRows();
|
|
966
1067
|
if (this.#scrollToTop) {
|
|
967
1068
|
this.#scrollToTop = false;
|
|
968
|
-
const scroller = this
|
|
1069
|
+
const scroller = this.#scroller();
|
|
969
1070
|
if (scroller) scroller.scrollTop = 0;
|
|
970
1071
|
}
|
|
971
1072
|
this.#chaseScrollTarget(model.rowCount);
|
|
972
|
-
if (this.#columnsChanged || changed.has("columnSizing") || changed.has("columnOrder") || changed.has("columnPinning") || changed.has("columnVisibility") || this.#autoWidthsChanged || this.#selectionColumnChanged) this.#pinScroll.measure();
|
|
1073
|
+
if (this.#columnsChanged || this.#groupsChanged || changed.has("columnSizing") || changed.has("columnOrder") || changed.has("columnPinning") || changed.has("columnVisibility") || this.#autoWidthsChanged || this.#selectionColumnChanged) this.#pinScroll.measure();
|
|
973
1074
|
if (this.#focusPending && !resized) {
|
|
974
1075
|
this.#focusPending = false;
|
|
975
1076
|
this.#focusActive();
|
|
976
1077
|
}
|
|
977
1078
|
if (changed.has("density") || changed.has("rowHeight")) this.#measureRowHeight();
|
|
978
|
-
|
|
979
|
-
const details = [...this.#appliedResizes.values()];
|
|
980
|
-
this.#appliedResizes.clear();
|
|
981
|
-
for (const detail of details) fire(this, COLUMN_RESIZE, detail);
|
|
982
|
-
}
|
|
1079
|
+
this.#fireApplied(this.#appliedResizes, COLUMN_SIZING_CHANGE);
|
|
983
1080
|
if (this.#announceMove) {
|
|
984
1081
|
this.#announceMoved(model, this.#announceMove);
|
|
985
1082
|
this.#announceMove = void 0;
|
|
986
1083
|
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
}
|
|
992
|
-
if (this.#appliedPins.size > 0) {
|
|
993
|
-
const details = [...this.#appliedPins.values()];
|
|
994
|
-
this.#appliedPins.clear();
|
|
995
|
-
for (const detail of details) fire(this, COLUMN_PIN, detail);
|
|
996
|
-
}
|
|
997
|
-
if (this.#appliedHides.size > 0) {
|
|
998
|
-
const details = [...this.#appliedHides.values()];
|
|
999
|
-
this.#appliedHides.clear();
|
|
1000
|
-
for (const detail of details) fire(this, COLUMN_HIDE, detail);
|
|
1001
|
-
}
|
|
1002
|
-
if (this.#appliedFilters.size > 0) {
|
|
1003
|
-
const details = [...this.#appliedFilters.values()];
|
|
1004
|
-
this.#appliedFilters.clear();
|
|
1005
|
-
for (const detail of details) fire(this, COLUMN_FILTER, detail);
|
|
1006
|
-
}
|
|
1084
|
+
this.#fireApplied(this.#appliedReorders, COLUMN_ORDER_CHANGE);
|
|
1085
|
+
this.#fireApplied(this.#appliedPins, COLUMN_PINNING_CHANGE);
|
|
1086
|
+
this.#fireApplied(this.#appliedHides, COLUMN_VISIBILITY_CHANGE);
|
|
1087
|
+
this.#fireApplied(this.#appliedFilters, COLUMN_FILTERS_CHANGE);
|
|
1007
1088
|
if (this.#announceRows) {
|
|
1008
1089
|
this.#announceRows = false;
|
|
1009
1090
|
this.#announceRowCount(model);
|
|
@@ -1011,20 +1092,20 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1011
1092
|
if (this.#appliedSort) {
|
|
1012
1093
|
const sorting = this.#appliedSort;
|
|
1013
1094
|
this.#appliedSort = void 0;
|
|
1014
|
-
fire(this,
|
|
1095
|
+
fire(this, SORTING_CHANGE, { sorting });
|
|
1015
1096
|
}
|
|
1016
1097
|
if (this.#appliedSelection) {
|
|
1017
1098
|
const selection = this.#appliedSelection;
|
|
1018
1099
|
this.#appliedSelection = void 0;
|
|
1019
|
-
fire(this,
|
|
1100
|
+
fire(this, SELECTION_CHANGE, { selection });
|
|
1020
1101
|
}
|
|
1021
1102
|
const { range } = this.#window;
|
|
1022
1103
|
const key = range ? `${String(range.start)}:${String(range.end)}` : "";
|
|
1023
1104
|
if (range && key !== this.#lastRange) {
|
|
1024
1105
|
this.#lastRange = key;
|
|
1025
1106
|
fire(this, RANGE_CHANGE, {
|
|
1026
|
-
|
|
1027
|
-
|
|
1107
|
+
first: range.start,
|
|
1108
|
+
last: range.end
|
|
1028
1109
|
});
|
|
1029
1110
|
}
|
|
1030
1111
|
if (range) {
|
|
@@ -1043,12 +1124,19 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1043
1124
|
#keptColumns(model) {
|
|
1044
1125
|
return [
|
|
1045
1126
|
this.#active?.col,
|
|
1046
|
-
this.#drag?.
|
|
1127
|
+
...this.#drag?.key.startsWith("c:") ? this.#drag.columns : [],
|
|
1047
1128
|
this.dataSource ? model.columns.find((c) => c.kind === "data")?.id : void 0,
|
|
1048
1129
|
...this.#autoWidths.pending(model.columns),
|
|
1049
1130
|
...this.#measureKeep
|
|
1050
1131
|
];
|
|
1051
1132
|
}
|
|
1133
|
+
/** Fires the events of changes the table applied itself, once the update is done. */
|
|
1134
|
+
#fireApplied(applied, name) {
|
|
1135
|
+
if (applied.size === 0) return;
|
|
1136
|
+
const details = [...applied.values()];
|
|
1137
|
+
applied.clear();
|
|
1138
|
+
for (const detail of details) fire(this, name, detail);
|
|
1139
|
+
}
|
|
1052
1140
|
/**
|
|
1053
1141
|
* Measures the `width: 'auto'` columns once loaded body rows render, or right
|
|
1054
1142
|
* away when there are no rows (the header and pinned rows only). While a data
|
|
@@ -1113,6 +1201,129 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1113
1201
|
*/
|
|
1114
1202
|
#onKeydown;
|
|
1115
1203
|
/**
|
|
1204
|
+
* The header row to go to from header row `level` down, over a column: the first
|
|
1205
|
+
* group row from `level` with a group over it, else the column headers.
|
|
1206
|
+
*/
|
|
1207
|
+
#headerLevelDown(model, level, columnId) {
|
|
1208
|
+
const leaf = model.headerGroups.length;
|
|
1209
|
+
for (let l = level; l < leaf; l++) if (model.headerCell(l, columnId)?.kind === "group") return l;
|
|
1210
|
+
return leaf;
|
|
1211
|
+
}
|
|
1212
|
+
/** The first group row from `level` up with a group over a column, or `undefined`. */
|
|
1213
|
+
#headerLevelUp(model, level, columnId) {
|
|
1214
|
+
for (let l = Math.min(level, model.headerGroups.length - 1); l >= 0; l--) if (model.headerCell(l, columnId)?.kind === "group") return l;
|
|
1215
|
+
}
|
|
1216
|
+
/**
|
|
1217
|
+
* Keys on a focused group header. Arrows move between group headers in its row
|
|
1218
|
+
* (fillers are skipped) and to the headers above and below it; ArrowDown ends on
|
|
1219
|
+
* the column headers. Home and End go to the row's first and last group,
|
|
1220
|
+
* PageDown into the body, Ctrl+Home and Ctrl+End to the corners, and
|
|
1221
|
+
* Alt+Shift+Arrow moves the group. Groups don't sort or resize.
|
|
1222
|
+
*/
|
|
1223
|
+
#groupKey(event, cell, scroller) {
|
|
1224
|
+
const model = this.#table.model;
|
|
1225
|
+
const layout = layoutOf(model);
|
|
1226
|
+
const at = gridRowOf(cell.parentElement, layout);
|
|
1227
|
+
const row = at?.section === "header" ? model.headerGroups[at.index] : void 0;
|
|
1228
|
+
const here = row?.find((c) => c.key === cell.dataset.groupKey);
|
|
1229
|
+
if (!at || !row || here?.groupId === void 0) return;
|
|
1230
|
+
const level = at.index;
|
|
1231
|
+
const active = this.#active;
|
|
1232
|
+
const anchor = active?.section === "header" && active.index === level && here.columns.includes(active.col) ? active.col : here.columns[0];
|
|
1233
|
+
if (anchor === void 0) return;
|
|
1234
|
+
const { key } = event;
|
|
1235
|
+
const arrow = key === "ArrowLeft" || key === "ArrowRight";
|
|
1236
|
+
const towardEnd = key === "ArrowRight" === (this.#direction() === 1);
|
|
1237
|
+
if (arrow && event.altKey) {
|
|
1238
|
+
event.preventDefault();
|
|
1239
|
+
if (event.shiftKey) this.#moveByKey({
|
|
1240
|
+
kind: "group",
|
|
1241
|
+
id: here.groupId,
|
|
1242
|
+
pin: here.pin
|
|
1243
|
+
}, towardEnd ? 1 : -1);
|
|
1244
|
+
else if (here.resizable) {
|
|
1245
|
+
const starts = this.#groupWidths(here.columns);
|
|
1246
|
+
const total = [...starts.values()].reduce((sum, w) => sum + w, 0);
|
|
1247
|
+
this.#requestGroupResize(here.columns, starts, total + (towardEnd ? RESIZE_STEP : -10));
|
|
1248
|
+
}
|
|
1249
|
+
return;
|
|
1250
|
+
}
|
|
1251
|
+
if (key === "Enter" || key === " ") {
|
|
1252
|
+
event.preventDefault();
|
|
1253
|
+
return;
|
|
1254
|
+
}
|
|
1255
|
+
if (this.#selectionKey(event, cell, anchor, true, scroller)) return;
|
|
1256
|
+
const corner = event.ctrlKey || event.metaKey;
|
|
1257
|
+
if (event.altKey || event.shiftKey || corner && key !== "Home" && key !== "End") return;
|
|
1258
|
+
const groups = row.filter((c) => c.kind === "group");
|
|
1259
|
+
const columns = model.columns;
|
|
1260
|
+
let to;
|
|
1261
|
+
switch (key) {
|
|
1262
|
+
case "ArrowLeft":
|
|
1263
|
+
case "ArrowRight": {
|
|
1264
|
+
const col = groups[groups.indexOf(here) + (towardEnd ? 1 : -1)]?.columns[0];
|
|
1265
|
+
if (col !== void 0) to = {
|
|
1266
|
+
row: at,
|
|
1267
|
+
col
|
|
1268
|
+
};
|
|
1269
|
+
break;
|
|
1270
|
+
}
|
|
1271
|
+
case "Home":
|
|
1272
|
+
case "End":
|
|
1273
|
+
if (corner) {
|
|
1274
|
+
const first = key === "Home";
|
|
1275
|
+
const col = (first ? columns[0] : columns.at(-1))?.id;
|
|
1276
|
+
if (col === void 0) break;
|
|
1277
|
+
if (first) this.#virtual.scrollToEdge("start");
|
|
1278
|
+
else if (layout.bottom > 0) this.#virtual.scrollToEdge("end");
|
|
1279
|
+
const pos = first ? this.#headerLevelDown(model, 0, col) : layout.total - 1;
|
|
1280
|
+
to = {
|
|
1281
|
+
row: layout.at(pos) ?? layout.leafHeader,
|
|
1282
|
+
col
|
|
1283
|
+
};
|
|
1284
|
+
} else {
|
|
1285
|
+
const col = (key === "Home" ? groups[0] : groups.at(-1))?.columns[0];
|
|
1286
|
+
if (col !== void 0) to = {
|
|
1287
|
+
row: at,
|
|
1288
|
+
col
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
break;
|
|
1292
|
+
case "ArrowDown":
|
|
1293
|
+
to = {
|
|
1294
|
+
row: {
|
|
1295
|
+
section: "header",
|
|
1296
|
+
index: this.#headerLevelDown(model, level + 1, anchor)
|
|
1297
|
+
},
|
|
1298
|
+
col: anchor
|
|
1299
|
+
};
|
|
1300
|
+
break;
|
|
1301
|
+
case "ArrowUp": {
|
|
1302
|
+
const up = this.#headerLevelUp(model, level - 1, anchor);
|
|
1303
|
+
if (up !== void 0) to = {
|
|
1304
|
+
row: {
|
|
1305
|
+
section: "header",
|
|
1306
|
+
index: up
|
|
1307
|
+
},
|
|
1308
|
+
col: anchor
|
|
1309
|
+
};
|
|
1310
|
+
break;
|
|
1311
|
+
}
|
|
1312
|
+
case "PageDown": {
|
|
1313
|
+
const pos = this.#verticalStep(key, layout.position(at), layout, scroller);
|
|
1314
|
+
to = {
|
|
1315
|
+
row: layout.at(pos) ?? at,
|
|
1316
|
+
col: anchor
|
|
1317
|
+
};
|
|
1318
|
+
break;
|
|
1319
|
+
}
|
|
1320
|
+
case "PageUp": break;
|
|
1321
|
+
default: return;
|
|
1322
|
+
}
|
|
1323
|
+
event.preventDefault();
|
|
1324
|
+
if (to) this.#moveTo(to.row, to.col, model);
|
|
1325
|
+
}
|
|
1326
|
+
/**
|
|
1116
1327
|
* The grid position ArrowUp/ArrowDown (one row) or PageUp/PageDown (a page of
|
|
1117
1328
|
* the body) moves to from `pos`. PageDown from above the body lands a page
|
|
1118
1329
|
* into it and stops at its last row; PageUp stays in the body.
|
|
@@ -1135,9 +1346,9 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1135
1346
|
#pageRows(key, pos, layout, scroller) {
|
|
1136
1347
|
if (this.rowHeight !== "auto") {
|
|
1137
1348
|
const fit = Math.floor(scroller.clientHeight / this.#rowPx + .01);
|
|
1138
|
-
return Math.max(1, fit -
|
|
1349
|
+
return Math.max(1, fit - layout.header - layout.top - layout.bottom);
|
|
1139
1350
|
}
|
|
1140
|
-
const view = scroller.clientHeight - this.#
|
|
1351
|
+
const view = scroller.clientHeight - this.#headerAndPinnedPx(layout);
|
|
1141
1352
|
const bodyFirst = layout.position({
|
|
1142
1353
|
section: "body",
|
|
1143
1354
|
index: 0
|
|
@@ -1207,6 +1418,22 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1207
1418
|
}
|
|
1208
1419
|
/** Focus that lands in a cell (a click, or content inside it) makes that cell active. */
|
|
1209
1420
|
#onFocusin;
|
|
1421
|
+
/** Focus on a group header makes it active, on the column it was active on, else its first. */
|
|
1422
|
+
#focusGroup(cell) {
|
|
1423
|
+
const model = this.#table.model;
|
|
1424
|
+
const row = gridRowOf(cell.parentElement, layoutOf(model));
|
|
1425
|
+
const group = row && model.headerGroups[row.index]?.find((c) => c.key === cell.dataset.groupKey);
|
|
1426
|
+
const first = group?.columns[0];
|
|
1427
|
+
if (!row || !group || first === void 0) return;
|
|
1428
|
+
const prev = this.#active;
|
|
1429
|
+
if (prev?.section === "header" && prev.index === row.index && group.columns.includes(prev.col)) return;
|
|
1430
|
+
this.#active = {
|
|
1431
|
+
...row,
|
|
1432
|
+
rowId: void 0,
|
|
1433
|
+
col: first
|
|
1434
|
+
};
|
|
1435
|
+
this.requestUpdate();
|
|
1436
|
+
}
|
|
1210
1437
|
/**
|
|
1211
1438
|
* `argus-cell-click`, then `argus-row-click`, for clicks in the body; then,
|
|
1212
1439
|
* with a `selectionMode`, the click selects its row.
|
|
@@ -1255,7 +1482,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1255
1482
|
}
|
|
1256
1483
|
/**
|
|
1257
1484
|
* Whether all, some or none of the selectable rows are selected. With `data`
|
|
1258
|
-
* it's worked out once per
|
|
1485
|
+
* it's worked out once per selection and rows shown, not on scroll;
|
|
1259
1486
|
* with a `dataSource` every time, over the loaded rows, which eviction keeps few.
|
|
1260
1487
|
*/
|
|
1261
1488
|
#checkAllState(model) {
|
|
@@ -1277,11 +1504,13 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1277
1504
|
this.#visibility.value
|
|
1278
1505
|
];
|
|
1279
1506
|
const cached = this.#checkAll;
|
|
1280
|
-
if (cached?.key.length
|
|
1507
|
+
if (cached?.key.length === key.length && key.every((k, i) => k === cached.key[i])) return cached.state;
|
|
1508
|
+
const state = count();
|
|
1509
|
+
this.#checkAll = {
|
|
1281
1510
|
key,
|
|
1282
|
-
state
|
|
1511
|
+
state
|
|
1283
1512
|
};
|
|
1284
|
-
return
|
|
1513
|
+
return state;
|
|
1285
1514
|
}
|
|
1286
1515
|
/**
|
|
1287
1516
|
* A Shift+press on a row in `multi` mode selects a range of rows, not the
|
|
@@ -1332,8 +1561,9 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1332
1561
|
/** The anchor row and where it is now; `undefined` if it isn't in the rows (or not loaded). */
|
|
1333
1562
|
#anchorAt(model) {
|
|
1334
1563
|
const id = this.#anchor;
|
|
1335
|
-
|
|
1336
|
-
|
|
1564
|
+
if (id === void 0) return void 0;
|
|
1565
|
+
const index = model.indexOf(id);
|
|
1566
|
+
return index === void 0 ? void 0 : {
|
|
1337
1567
|
id,
|
|
1338
1568
|
index
|
|
1339
1569
|
};
|
|
@@ -1351,7 +1581,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1351
1581
|
if (applied) {
|
|
1352
1582
|
this.#appliedSelection = value;
|
|
1353
1583
|
this.requestUpdate("selection", old);
|
|
1354
|
-
} else fire(this,
|
|
1584
|
+
} else fire(this, SELECTION_CHANGE, { selection: value });
|
|
1355
1585
|
}
|
|
1356
1586
|
/**
|
|
1357
1587
|
* Fires `argus-cell-click` (when a cell is on the path), then `argus-row-click`,
|
|
@@ -1375,6 +1605,8 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1375
1605
|
if (!row) return;
|
|
1376
1606
|
if (columnId !== void 0) fire(this, CELL_CLICK, {
|
|
1377
1607
|
row: row.original,
|
|
1608
|
+
rowId: row.id,
|
|
1609
|
+
index,
|
|
1378
1610
|
columnId,
|
|
1379
1611
|
value: model.valueAt(index, columnId)
|
|
1380
1612
|
});
|
|
@@ -1390,6 +1622,8 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1390
1622
|
if (!row) return;
|
|
1391
1623
|
if (columnId !== void 0) fire(this, CELL_CLICK, {
|
|
1392
1624
|
row: row.original,
|
|
1625
|
+
rowId: row.id,
|
|
1626
|
+
index,
|
|
1393
1627
|
columnId,
|
|
1394
1628
|
value: model.pinnedValueAt(pinned, index, columnId),
|
|
1395
1629
|
pinned
|
|
@@ -1425,13 +1659,27 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1425
1659
|
const active = this.#active;
|
|
1426
1660
|
if (!active) return;
|
|
1427
1661
|
const col = CSS.escape(active.col);
|
|
1428
|
-
const
|
|
1429
|
-
const
|
|
1662
|
+
const model = this.#table.model;
|
|
1663
|
+
const layout = layoutOf(model);
|
|
1664
|
+
const index = layout.ariaRowIndex(active);
|
|
1665
|
+
const row = `[role='row'][aria-rowindex="${String(index)}"]`;
|
|
1666
|
+
if (active.section === "header" && active.index < layout.header - 1) {
|
|
1667
|
+
const key = model.headerCell(active.index, active.col)?.key ?? "";
|
|
1668
|
+
const group = this.renderRoot.querySelector(`${row} > [data-group-key="${CSS.escape(key)}"]`);
|
|
1669
|
+
if (!group) return;
|
|
1670
|
+
group.focus({ preventScroll: true });
|
|
1671
|
+
const leaf = `[role='row'][aria-rowindex="${String(layout.header)}"] > [data-col="${col}"]`;
|
|
1672
|
+
this.renderRoot.querySelector(leaf)?.scrollIntoView({
|
|
1673
|
+
block: "nearest",
|
|
1674
|
+
inline: "nearest"
|
|
1675
|
+
});
|
|
1676
|
+
return;
|
|
1677
|
+
}
|
|
1678
|
+
const cell = this.renderRoot.querySelector(`${row} > [data-col="${col}"]`);
|
|
1430
1679
|
if (!cell) return;
|
|
1431
1680
|
cell.focus({ preventScroll: true });
|
|
1432
1681
|
if (active.section === "body" && (this.#virtual.scaled || this.rowHeight === "auto")) {
|
|
1433
|
-
const
|
|
1434
|
-
const before = this.#rowPx + this.#pinnedPx("top", layout);
|
|
1682
|
+
const before = layout.header * this.#rowPx + this.#pinnedPx("top", layout);
|
|
1435
1683
|
if (this.#virtual.reveal(active.index, before, this.#pinnedPx("bottom", layout))) {
|
|
1436
1684
|
this.#focusPending = true;
|
|
1437
1685
|
return;
|
|
@@ -1457,14 +1705,24 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1457
1705
|
this.#active = void 0;
|
|
1458
1706
|
return;
|
|
1459
1707
|
}
|
|
1708
|
+
const layout = layoutOf(model);
|
|
1709
|
+
const leaf = layout.header - 1;
|
|
1460
1710
|
const prev = this.#active ?? {
|
|
1461
|
-
...
|
|
1711
|
+
...layout.leafHeader,
|
|
1462
1712
|
rowId: void 0,
|
|
1463
1713
|
col: first.id
|
|
1464
1714
|
};
|
|
1465
1715
|
const col = columns.some((c) => c.id === prev.col) ? prev.col : this.#columnInPlaceOf(model, prev.col, first.id);
|
|
1466
1716
|
let { section, index, rowId } = prev;
|
|
1467
1717
|
let moved = col !== prev.col && this.#active !== void 0;
|
|
1718
|
+
if (section === "header") {
|
|
1719
|
+
if (!this.#active || index === this.#leafLevel) index = leaf;
|
|
1720
|
+
else if (index >= leaf || model.headerCell(index, col)?.kind !== "group") {
|
|
1721
|
+
index = leaf;
|
|
1722
|
+
moved = true;
|
|
1723
|
+
}
|
|
1724
|
+
}
|
|
1725
|
+
this.#leafLevel = leaf;
|
|
1468
1726
|
if (section === "body" && rowId !== void 0) {
|
|
1469
1727
|
const found = model.indexOf(rowId);
|
|
1470
1728
|
const unloaded = index < model.rowCount && model.rowAt(index) === void 0;
|
|
@@ -1483,7 +1741,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1483
1741
|
rowId = index >= 0 ? model.pinnedRowAt(section, index)?.id : void 0;
|
|
1484
1742
|
}
|
|
1485
1743
|
if (index < 0) {
|
|
1486
|
-
({section, index} =
|
|
1744
|
+
({section, index} = layout.leafHeader);
|
|
1487
1745
|
rowId = void 0;
|
|
1488
1746
|
}
|
|
1489
1747
|
if (moved && this.matches(":focus-within")) this.#focusPending = true;
|
|
@@ -1517,6 +1775,49 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1517
1775
|
const view = this.#table.model.columns.find((c) => c.id === columnId);
|
|
1518
1776
|
return view && view.flex === void 0 ? view.width : cell.getBoundingClientRect().width;
|
|
1519
1777
|
}
|
|
1778
|
+
/** The group header cell with a key, from the model. */
|
|
1779
|
+
#groupCellOf(key) {
|
|
1780
|
+
if (key === void 0) return void 0;
|
|
1781
|
+
return this.#table.model.headerGroups.flat().find((c) => c.key === key);
|
|
1782
|
+
}
|
|
1783
|
+
/**
|
|
1784
|
+
* The widths a group resize starts from, by column: the latest requested ones
|
|
1785
|
+
* (key presses can come faster than renders), else the model's, else the
|
|
1786
|
+
* rendered width of a flex column.
|
|
1787
|
+
*/
|
|
1788
|
+
#groupWidths(columnIds) {
|
|
1789
|
+
const widths = /* @__PURE__ */ new Map();
|
|
1790
|
+
for (const id of columnIds) {
|
|
1791
|
+
const header = this.renderRoot.querySelector(`[part~='header-cell'][data-col="${CSS.escape(id)}"]`);
|
|
1792
|
+
const view = this.#table.model.columns.find((c) => c.id === id);
|
|
1793
|
+
const sized = this.#sizing.value[id];
|
|
1794
|
+
widths.set(id, sized ?? (header ? this.#currentWidth(id, header) : view?.width ?? 0));
|
|
1795
|
+
}
|
|
1796
|
+
return widths;
|
|
1797
|
+
}
|
|
1798
|
+
/**
|
|
1799
|
+
* Resizes a group to `total` px: the change is spread over its resizable columns
|
|
1800
|
+
* in proportion to their widths, within their bounds (one `argus-column-sizing-change`
|
|
1801
|
+
* per column that changes). The other columns keep their width.
|
|
1802
|
+
*/
|
|
1803
|
+
#requestGroupResize(columnIds, starts, total) {
|
|
1804
|
+
const views = new Map(this.#table.model.columns.map((c) => [c.id, c]));
|
|
1805
|
+
let fixed = 0;
|
|
1806
|
+
const spread = [];
|
|
1807
|
+
for (const id of columnIds) {
|
|
1808
|
+
const view = views.get(id);
|
|
1809
|
+
const width = starts.get(id) ?? view?.width ?? 0;
|
|
1810
|
+
if (view?.resizable) spread.push({
|
|
1811
|
+
id,
|
|
1812
|
+
width,
|
|
1813
|
+
minWidth: view.minWidth,
|
|
1814
|
+
maxWidth: view.maxWidth
|
|
1815
|
+
});
|
|
1816
|
+
else fixed += width;
|
|
1817
|
+
}
|
|
1818
|
+
if (spread.length === 0) return;
|
|
1819
|
+
this.#requestResizes(spreadWidth(spread, total - fixed));
|
|
1820
|
+
}
|
|
1520
1821
|
#direction() {
|
|
1521
1822
|
return getComputedStyle(this).direction === "rtl" ? -1 : 1;
|
|
1522
1823
|
}
|
|
@@ -1526,8 +1827,8 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1526
1827
|
}
|
|
1527
1828
|
/**
|
|
1528
1829
|
* Sets column widths (clamped by core) in one change, through the
|
|
1529
|
-
* controlled/uncontrolled rules. One `argus-column-
|
|
1530
|
-
* changes, each with the whole new sizing.
|
|
1830
|
+
* controlled/uncontrolled rules. One `argus-column-sizing-change` per column
|
|
1831
|
+
* that changes, each with the whole new sizing.
|
|
1531
1832
|
*/
|
|
1532
1833
|
#requestResizes(widths) {
|
|
1533
1834
|
const model = this.#table.model;
|
|
@@ -1543,15 +1844,15 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1543
1844
|
...Object.fromEntries(targets)
|
|
1544
1845
|
});
|
|
1545
1846
|
const details = targets.map(([columnId, width]) => ({
|
|
1847
|
+
columnSizing: value,
|
|
1546
1848
|
columnId,
|
|
1547
|
-
width
|
|
1548
|
-
sizing: value
|
|
1849
|
+
width
|
|
1549
1850
|
}));
|
|
1550
1851
|
if (applied) {
|
|
1551
|
-
for (const detail of this.#appliedResizes.values()) detail.
|
|
1852
|
+
for (const detail of this.#appliedResizes.values()) detail.columnSizing = value;
|
|
1552
1853
|
for (const detail of details) this.#appliedResizes.set(detail.columnId, detail);
|
|
1553
1854
|
this.requestUpdate("columnSizing", old);
|
|
1554
|
-
} else for (const detail of details) fire(this,
|
|
1855
|
+
} else for (const detail of details) fire(this, COLUMN_SIZING_CHANGE, detail);
|
|
1555
1856
|
}
|
|
1556
1857
|
/**
|
|
1557
1858
|
* Pins or unpins a column through the controlled/uncontrolled rules. Starts
|
|
@@ -1563,17 +1864,17 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1563
1864
|
if (!next) return;
|
|
1564
1865
|
const { value, applied } = this.#pinning.request(next);
|
|
1565
1866
|
if (applied) {
|
|
1566
|
-
for (const detail of this.#appliedPins.values()) detail.
|
|
1867
|
+
for (const detail of this.#appliedPins.values()) detail.columnPinning = value;
|
|
1567
1868
|
this.#appliedPins.set(columnId, {
|
|
1869
|
+
columnPinning: value,
|
|
1568
1870
|
columnId,
|
|
1569
|
-
pin
|
|
1570
|
-
pinning: value
|
|
1871
|
+
pin
|
|
1571
1872
|
});
|
|
1572
1873
|
this.requestUpdate("columnPinning", old);
|
|
1573
|
-
} else fire(this,
|
|
1874
|
+
} else fire(this, COLUMN_PINNING_CHANGE, {
|
|
1875
|
+
columnPinning: value,
|
|
1574
1876
|
columnId,
|
|
1575
|
-
pin
|
|
1576
|
-
pinning: value
|
|
1877
|
+
pin
|
|
1577
1878
|
});
|
|
1578
1879
|
}
|
|
1579
1880
|
/** Hides or shows a column through the controlled/uncontrolled rules. */
|
|
@@ -1583,17 +1884,17 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1583
1884
|
if (!next) return;
|
|
1584
1885
|
const { value, applied } = this.#visibility.request(next);
|
|
1585
1886
|
if (applied) {
|
|
1586
|
-
for (const detail of this.#appliedHides.values()) detail.
|
|
1887
|
+
for (const detail of this.#appliedHides.values()) detail.columnVisibility = value;
|
|
1587
1888
|
this.#appliedHides.set(columnId, {
|
|
1889
|
+
columnVisibility: value,
|
|
1588
1890
|
columnId,
|
|
1589
|
-
hidden
|
|
1590
|
-
visibility: value
|
|
1891
|
+
visible: !hidden
|
|
1591
1892
|
});
|
|
1592
1893
|
this.requestUpdate("columnVisibility", old);
|
|
1593
|
-
} else fire(this,
|
|
1894
|
+
} else fire(this, COLUMN_VISIBILITY_CHANGE, {
|
|
1895
|
+
columnVisibility: value,
|
|
1594
1896
|
columnId,
|
|
1595
|
-
hidden
|
|
1596
|
-
visibility: value
|
|
1897
|
+
visible: !hidden
|
|
1597
1898
|
});
|
|
1598
1899
|
}
|
|
1599
1900
|
/** Sets or clears a column's filter through the controlled/uncontrolled rules. */
|
|
@@ -1603,17 +1904,17 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1603
1904
|
if (!next) return;
|
|
1604
1905
|
const { value, applied } = this.#filters.request(next);
|
|
1605
1906
|
if (applied) {
|
|
1606
|
-
for (const detail of this.#appliedFilters.values()) detail.
|
|
1907
|
+
for (const detail of this.#appliedFilters.values()) detail.columnFilters = value;
|
|
1607
1908
|
this.#appliedFilters.set(columnId, {
|
|
1909
|
+
columnFilters: value,
|
|
1608
1910
|
columnId,
|
|
1609
|
-
filter
|
|
1610
|
-
filters: value
|
|
1911
|
+
columnFilter: filter
|
|
1611
1912
|
});
|
|
1612
1913
|
this.requestUpdate("columnFilters", old);
|
|
1613
|
-
} else fire(this,
|
|
1914
|
+
} else fire(this, COLUMN_FILTERS_CHANGE, {
|
|
1915
|
+
columnFilters: value,
|
|
1614
1916
|
columnId,
|
|
1615
|
-
filter
|
|
1616
|
-
filters: value
|
|
1917
|
+
columnFilter: filter
|
|
1617
1918
|
});
|
|
1618
1919
|
}
|
|
1619
1920
|
/**
|
|
@@ -1626,80 +1927,127 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1626
1927
|
announce(this.ownerDocument, n === 1 ? "1 row" : `${String(n)} rows`);
|
|
1627
1928
|
}
|
|
1628
1929
|
/**
|
|
1629
|
-
* Moves a column to position `to` among
|
|
1630
|
-
*
|
|
1631
|
-
* order, so moves can come faster than
|
|
1930
|
+
* Moves a column or group to position `to` among its siblings (the columns and
|
|
1931
|
+
* groups of its parent group on its pin side), through the controlled/uncontrolled
|
|
1932
|
+
* rules. Starts from the latest requested order, so moves can come faster than
|
|
1933
|
+
* renders. `false` if it can't move there.
|
|
1632
1934
|
*/
|
|
1633
|
-
#requestReorder(
|
|
1935
|
+
#requestReorder(unit, to) {
|
|
1634
1936
|
const old = this.#order.value;
|
|
1635
|
-
const
|
|
1636
|
-
|
|
1937
|
+
const model = this.#table.model;
|
|
1938
|
+
const moving = model.siblingUnits(unit, old).find((s) => sameUnit(s.unit, unit));
|
|
1939
|
+
const next = model.nextMove(unit, to, old);
|
|
1940
|
+
const columnId = moving?.columns[0];
|
|
1941
|
+
if (!next || columnId === void 0) return false;
|
|
1942
|
+
const detail = (columnOrder) => unit.kind === "group" ? {
|
|
1943
|
+
columnOrder,
|
|
1944
|
+
columnId,
|
|
1945
|
+
groupId: unit.id
|
|
1946
|
+
} : {
|
|
1947
|
+
columnOrder,
|
|
1948
|
+
columnId
|
|
1949
|
+
};
|
|
1637
1950
|
const { value, applied } = this.#order.request(next);
|
|
1638
1951
|
if (applied) {
|
|
1639
|
-
for (const
|
|
1640
|
-
this.#appliedReorders.set(
|
|
1641
|
-
columnId,
|
|
1642
|
-
order: value
|
|
1643
|
-
});
|
|
1952
|
+
for (const pending of this.#appliedReorders.values()) pending.columnOrder = value;
|
|
1953
|
+
this.#appliedReorders.set(unitKey(unit), detail(value));
|
|
1644
1954
|
this.requestUpdate("columnOrder", old);
|
|
1645
|
-
} else fire(this,
|
|
1646
|
-
columnId,
|
|
1647
|
-
order: value
|
|
1648
|
-
});
|
|
1955
|
+
} else fire(this, COLUMN_ORDER_CHANGE, detail(value));
|
|
1649
1956
|
return true;
|
|
1650
1957
|
}
|
|
1651
|
-
/** Alt+Shift+Arrow on a header: one step toward the start (-1) or the end (1). */
|
|
1652
|
-
#moveByKey(
|
|
1958
|
+
/** Alt+Shift+Arrow on a column or group header: one step toward the start (-1) or the end (1). */
|
|
1959
|
+
#moveByKey(unit, step) {
|
|
1653
1960
|
const model = this.#table.model;
|
|
1654
|
-
const
|
|
1655
|
-
const
|
|
1656
|
-
|
|
1657
|
-
if (from
|
|
1658
|
-
if (!this.#requestReorder(columnId, from + step)) return;
|
|
1961
|
+
const from = model.siblingUnits(unit, this.#order.value).findIndex((s) => sameUnit(s.unit, unit));
|
|
1962
|
+
const at = this.#colIndexOf(model, unit);
|
|
1963
|
+
if (from < 0 || at === void 0) return;
|
|
1964
|
+
if (!this.#requestReorder(unit, from + step)) return;
|
|
1659
1965
|
this.#focusPending = true;
|
|
1660
1966
|
this.#announceMove ??= {
|
|
1661
|
-
|
|
1662
|
-
from:
|
|
1967
|
+
unit,
|
|
1968
|
+
from: at
|
|
1663
1969
|
};
|
|
1664
1970
|
this.requestUpdate();
|
|
1665
1971
|
}
|
|
1666
|
-
/**
|
|
1667
|
-
#
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
const name = header instanceof HTMLSlotElement ? header.assignedNodes({ flatten: true }).map((n) => n.textContent).join("").trim() : "";
|
|
1672
|
-
announce(this.ownerDocument, `${name || move.id} moved to column ${String(view.colIndex)} of ${String(model.columns.length)}`);
|
|
1972
|
+
/** `aria-colindex` of a column's header, or of a group's first column on its side. */
|
|
1973
|
+
#colIndexOf(model, unit) {
|
|
1974
|
+
if (unit.kind === "column") return model.columns.find((c) => c.id === unit.id)?.colIndex;
|
|
1975
|
+
const key = unitKey(unit);
|
|
1976
|
+
return model.headerGroups.flat().find((c) => c.key === key)?.colIndex;
|
|
1673
1977
|
}
|
|
1674
|
-
/**
|
|
1978
|
+
/** Tells screen readers where a column or group moved from the keyboard went. */
|
|
1979
|
+
#announceMoved(model, move) {
|
|
1980
|
+
const { unit } = move;
|
|
1981
|
+
const total = String(model.columns.length);
|
|
1982
|
+
if (unit.kind === "column") {
|
|
1983
|
+
const view = model.columns.find((c) => c.id === unit.id);
|
|
1984
|
+
if (!view || view.colIndex === move.from) return;
|
|
1985
|
+
const name = this.#slotText(`[role='columnheader'][data-col="${CSS.escape(unit.id)}"] > slot`);
|
|
1986
|
+
announce(this.ownerDocument, `${name || unit.id} moved to column ${String(view.colIndex)} of ${total}`);
|
|
1987
|
+
return;
|
|
1988
|
+
}
|
|
1989
|
+
const key = unitKey(unit);
|
|
1990
|
+
const cell = model.headerGroups.flat().find((c) => c.key === key);
|
|
1991
|
+
if (!cell || cell.colIndex === move.from) return;
|
|
1992
|
+
const name = this.#slotText(`[data-group-key="${CSS.escape(key)}"] slot`);
|
|
1993
|
+
const last = cell.colIndex + cell.span - 1;
|
|
1994
|
+
const where = cell.span === 1 ? `column ${String(cell.colIndex)}` : `columns ${String(cell.colIndex)} to ${String(last)}`;
|
|
1995
|
+
announce(this.ownerDocument, `${name || unit.id} moved to ${where} of ${total}`);
|
|
1996
|
+
}
|
|
1997
|
+
/** The text slotted into a header, read through the slot's assigned nodes. */
|
|
1998
|
+
#slotText(selector) {
|
|
1999
|
+
const slot = this.renderRoot.querySelector(selector);
|
|
2000
|
+
return slot instanceof HTMLSlotElement ? slot.assignedNodes({ flatten: true }).map((n) => n.textContent).join("").trim() : "";
|
|
2001
|
+
}
|
|
2002
|
+
/** A press on a reorderable column or group header: becomes a drag once the pointer moves. */
|
|
1675
2003
|
#startReorder(down) {
|
|
1676
2004
|
const cell = down.composedPath().find((t) => t instanceof HTMLElement && t.getAttribute("role") === "columnheader");
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
if (
|
|
1681
|
-
|
|
2005
|
+
if (!cell || !canStartReorder(down, cell)) return;
|
|
2006
|
+
const model = this.#table.model;
|
|
2007
|
+
let unit;
|
|
2008
|
+
if (cell.dataset.moveCol !== void 0) unit = {
|
|
2009
|
+
kind: "column",
|
|
2010
|
+
id: cell.dataset.moveCol
|
|
2011
|
+
};
|
|
2012
|
+
else {
|
|
2013
|
+
const key = cell.dataset.moveGroup;
|
|
2014
|
+
const group = model.headerGroups.flat().find((c) => c.key === key);
|
|
2015
|
+
if (group?.groupId === void 0) return;
|
|
2016
|
+
unit = {
|
|
2017
|
+
kind: "group",
|
|
2018
|
+
id: group.groupId,
|
|
2019
|
+
pin: group.pin
|
|
2020
|
+
};
|
|
2021
|
+
}
|
|
2022
|
+
const scroller = this.#scroller();
|
|
2023
|
+
const moving = model.siblingUnits(unit).find((s) => sameUnit(s.unit, unit));
|
|
2024
|
+
if (!scroller || !moving) return;
|
|
2025
|
+
const key = unitKey(unit);
|
|
2026
|
+
const columns = new Set(moving.columns);
|
|
2027
|
+
const pin = unit.kind === "group" ? unit.pin : model.columns.find((c) => c.id === unit.id)?.pin;
|
|
1682
2028
|
startReorderDrag(cell, down, {
|
|
1683
2029
|
scroller,
|
|
1684
|
-
targetAt: (x) => dropTarget(this.#dropSlots(
|
|
2030
|
+
targetAt: (x) => dropTarget(this.#dropSlots(unit), key, x, this.#direction()),
|
|
1685
2031
|
scrollArea: () => pin === void 0 ? this.#scrollArea(scroller) : void 0,
|
|
1686
2032
|
onStart: () => {
|
|
1687
2033
|
this.#drag = {
|
|
1688
|
-
|
|
2034
|
+
key,
|
|
2035
|
+
columns,
|
|
1689
2036
|
target: void 0
|
|
1690
2037
|
};
|
|
1691
2038
|
this.requestUpdate();
|
|
1692
2039
|
},
|
|
1693
2040
|
onTarget: (target) => {
|
|
1694
2041
|
this.#drag = {
|
|
1695
|
-
|
|
2042
|
+
key,
|
|
2043
|
+
columns,
|
|
1696
2044
|
target
|
|
1697
2045
|
};
|
|
1698
2046
|
this.requestUpdate();
|
|
1699
2047
|
},
|
|
1700
2048
|
onDrop: (target) => {
|
|
1701
2049
|
this.#drag = void 0;
|
|
1702
|
-
if (target && this.#requestReorder(
|
|
2050
|
+
if (target && this.#requestReorder(unit, target.to)) {
|
|
1703
2051
|
if (this.matches(":focus-within")) this.#focusPending = true;
|
|
1704
2052
|
}
|
|
1705
2053
|
this.requestUpdate();
|
|
@@ -1711,16 +2059,17 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1711
2059
|
});
|
|
1712
2060
|
}
|
|
1713
2061
|
/**
|
|
1714
|
-
* The rendered headers of
|
|
1715
|
-
*
|
|
2062
|
+
* The rendered headers of what a column or group moves among (see
|
|
2063
|
+
* `siblingUnits`), with their positions there. With `virtualizeColumns`, columns
|
|
2064
|
+
* out of view have no header and no slot.
|
|
1716
2065
|
*/
|
|
1717
|
-
#dropSlots(
|
|
2066
|
+
#dropSlots(unit) {
|
|
1718
2067
|
const slots = [];
|
|
1719
|
-
this.#table.model.
|
|
1720
|
-
|
|
1721
|
-
const cell = this.renderRoot.querySelector(`[role='columnheader'][data-col="${CSS.escape(
|
|
2068
|
+
this.#table.model.siblingUnits(unit).forEach((sibling, index) => {
|
|
2069
|
+
const id = unitKey(sibling.unit);
|
|
2070
|
+
const cell = this.renderRoot.querySelector(sibling.unit.kind === "column" ? `[role='columnheader'][data-col="${CSS.escape(sibling.unit.id)}"]` : `[data-group-key="${CSS.escape(id)}"]`);
|
|
1722
2071
|
if (cell) slots.push({
|
|
1723
|
-
id
|
|
2072
|
+
id,
|
|
1724
2073
|
index,
|
|
1725
2074
|
rect: cell.getBoundingClientRect()
|
|
1726
2075
|
});
|
|
@@ -1729,8 +2078,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1729
2078
|
}
|
|
1730
2079
|
/** Where the scrolling columns show: the scroller's inside, less the pinned columns. */
|
|
1731
2080
|
#scrollArea(scroller) {
|
|
1732
|
-
const
|
|
1733
|
-
const width = (side) => columns.reduce((sum, c) => c.pin === side ? sum + c.width : sum, 0);
|
|
2081
|
+
const width = (side) => pinnedWidth(this.#table.model.columns, side);
|
|
1734
2082
|
const ltr = this.#direction() === 1;
|
|
1735
2083
|
const left = scroller.getBoundingClientRect().left + scroller.clientLeft;
|
|
1736
2084
|
return {
|
|
@@ -1750,8 +2098,8 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1750
2098
|
#setSort(columnId, direction) {
|
|
1751
2099
|
const view = this.#table.model.columns.find((c) => c.id === columnId);
|
|
1752
2100
|
if (view?.kind !== "data" || !view.sortable) return;
|
|
1753
|
-
if (direction === (view.sorted === false ?
|
|
1754
|
-
if (direction ===
|
|
2101
|
+
if (direction === (view.sorted === false ? void 0 : view.sorted)) return;
|
|
2102
|
+
if (direction === void 0) this.#applySorting([]);
|
|
1755
2103
|
else this.#applySorting([{
|
|
1756
2104
|
id: columnId,
|
|
1757
2105
|
desc: direction === "desc"
|
|
@@ -1764,7 +2112,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1764
2112
|
if (applied) {
|
|
1765
2113
|
this.#appliedSort = value;
|
|
1766
2114
|
this.requestUpdate("sorting", old);
|
|
1767
|
-
} else fire(this,
|
|
2115
|
+
} else fire(this, SORTING_CHANGE, { sorting: value });
|
|
1768
2116
|
}
|
|
1769
2117
|
/**
|
|
1770
2118
|
* A data column as plugins see it. Header functions call this on every
|
|
@@ -1789,7 +2137,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1789
2137
|
width: view.width,
|
|
1790
2138
|
sorted: view.sorted === false ? void 0 : view.sorted,
|
|
1791
2139
|
filter: view.filter,
|
|
1792
|
-
|
|
2140
|
+
columnFilter: this.#filters.value[id]
|
|
1793
2141
|
};
|
|
1794
2142
|
}
|
|
1795
2143
|
/** The header or cell an event happened in, for plugins. */
|
|
@@ -1799,12 +2147,12 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1799
2147
|
const columnId = cell?.dataset.col;
|
|
1800
2148
|
if (!cell || columnId === void 0) continue;
|
|
1801
2149
|
const model = this.#table.model;
|
|
1802
|
-
const row =
|
|
2150
|
+
const row = gridRowOfCell(cell, layoutOf(model));
|
|
1803
2151
|
if (!row) return void 0;
|
|
1804
2152
|
return {
|
|
1805
2153
|
section: row.section,
|
|
1806
2154
|
columnId,
|
|
1807
|
-
rowIndex: row.index,
|
|
2155
|
+
rowIndex: row.section === "header" ? 0 : row.index,
|
|
1808
2156
|
rowId: this.#gridRowId(model, row)
|
|
1809
2157
|
};
|
|
1810
2158
|
}
|
|
@@ -1823,6 +2171,10 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1823
2171
|
if (this.rowHeight !== "auto" || count === 0) return count * this.#rowPx;
|
|
1824
2172
|
return Math.max(this.#rowMeasure.pinned[side], count * this.#rowPx);
|
|
1825
2173
|
}
|
|
2174
|
+
/** The header rows and the pinned rows: the rows in the scroller besides the body. */
|
|
2175
|
+
#headerAndPinnedPx(layout) {
|
|
2176
|
+
return layout.header * this.#rowPx + this.#pinnedPx("top", layout) + this.#pinnedPx("bottom", layout);
|
|
2177
|
+
}
|
|
1826
2178
|
/**
|
|
1827
2179
|
* `rowHeight: 'auto'`: reads the heights of the rendered rows, after their
|
|
1828
2180
|
* content has rendered. Returns whether any changed (an update is requested).
|
|
@@ -1843,6 +2195,7 @@ var ArgusTable = class ArgusTable extends LitElement {
|
|
|
1843
2195
|
}
|
|
1844
2196
|
};
|
|
1845
2197
|
__decorate([property({ attribute: false })], ArgusTable.prototype, "columns", null);
|
|
2198
|
+
__decorate([property({ attribute: false })], ArgusTable.prototype, "columnGroups", null);
|
|
1846
2199
|
__decorate([property({ attribute: false })], ArgusTable.prototype, "data", null);
|
|
1847
2200
|
__decorate([property({ attribute: false })], ArgusTable.prototype, "dataSource", void 0);
|
|
1848
2201
|
__decorate([property({ attribute: false })], ArgusTable.prototype, "pinnedRows", void 0);
|
|
@@ -1855,7 +2208,7 @@ __decorate([property({ reflect: true })], ArgusTable.prototype, "density", void
|
|
|
1855
2208
|
__decorate([property({ type: Number })], ArgusTable.prototype, "overscan", null);
|
|
1856
2209
|
__decorate([property({
|
|
1857
2210
|
attribute: "virtualize-columns",
|
|
1858
|
-
|
|
2211
|
+
converter: switchConverter
|
|
1859
2212
|
})], ArgusTable.prototype, "virtualizeColumns", void 0);
|
|
1860
2213
|
__decorate([property({ attribute: false })], ArgusTable.prototype, "sorting", null);
|
|
1861
2214
|
__decorate([property({ attribute: false })], ArgusTable.prototype, "columnSizing", null);
|
|
@@ -1867,7 +2220,7 @@ __decorate([property({ attribute: "quick-filter" })], ArgusTable.prototype, "qui
|
|
|
1867
2220
|
__decorate([property({ attribute: "selection-mode" })], ArgusTable.prototype, "selectionMode", void 0);
|
|
1868
2221
|
__decorate([property({
|
|
1869
2222
|
attribute: "selection-checkboxes",
|
|
1870
|
-
|
|
2223
|
+
converter: switchConverter
|
|
1871
2224
|
})], ArgusTable.prototype, "selectionCheckboxes", void 0);
|
|
1872
2225
|
__decorate([property({ attribute: false })], ArgusTable.prototype, "selection", null);
|
|
1873
2226
|
__decorate([property({ attribute: false })], ArgusTable.prototype, "contentRenderer", void 0);
|