argus-table 0.1.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/README.md +25 -2
  2. package/dist/announce.js +27 -0
  3. package/dist/announce.js.map +1 -0
  4. package/dist/argus-column.js +121 -0
  5. package/dist/argus-column.js.map +1 -0
  6. package/dist/argus-table.js +585 -83
  7. package/dist/argus-table.js.map +1 -1
  8. package/dist/cdn/argus-table.js +79 -4533
  9. package/dist/cdn/argus-table.js.map +1 -1
  10. package/dist/controllers/auto-width.js +89 -0
  11. package/dist/controllers/auto-width.js.map +1 -0
  12. package/dist/controllers/column-children.js +41 -0
  13. package/dist/controllers/column-children.js.map +1 -0
  14. package/dist/controllers/data-controller.js +177 -0
  15. package/dist/controllers/data-controller.js.map +1 -0
  16. package/dist/controllers/reorder-drag.js +160 -0
  17. package/dist/controllers/reorder-drag.js.map +1 -0
  18. package/dist/controllers/resize-drag.js +3 -0
  19. package/dist/controllers/resize-drag.js.map +1 -1
  20. package/dist/controllers/table-controller.js +2 -1
  21. package/dist/controllers/table-controller.js.map +1 -1
  22. package/dist/controllers/virtual-controller.js +149 -10
  23. package/dist/controllers/virtual-controller.js.map +1 -1
  24. package/dist/core/src/columns/column-order.js +50 -0
  25. package/dist/core/src/columns/column-order.js.map +1 -0
  26. package/dist/core/src/columns/resolve-columns.js +5 -1
  27. package/dist/core/src/columns/resolve-columns.js.map +1 -1
  28. package/dist/core/src/data/page-cache.js +143 -0
  29. package/dist/core/src/data/page-cache.js.map +1 -0
  30. package/dist/core/src/grid/row-layout.js +58 -0
  31. package/dist/core/src/grid/row-layout.js.map +1 -0
  32. package/dist/core/src/table/create-table.js +112 -14
  33. package/dist/core/src/table/create-table.js.map +1 -1
  34. package/dist/core/src/table/sorted-row-model.js +86 -0
  35. package/dist/core/src/table/sorted-row-model.js.map +1 -0
  36. package/dist/core/src/virtual/scroll-scale.js +74 -0
  37. package/dist/core/src/virtual/scroll-scale.js.map +1 -0
  38. package/dist/core/src/virtual/steady-window.js +30 -0
  39. package/dist/core/src/virtual/steady-window.js.map +1 -0
  40. package/dist/custom-elements.json +1463 -62
  41. package/dist/events.js +5 -1
  42. package/dist/events.js.map +1 -1
  43. package/dist/index.d.ts +252 -27
  44. package/dist/index.js +3 -2
  45. package/dist/max-height.js +68 -0
  46. package/dist/max-height.js.map +1 -0
  47. package/dist/render/body.js +53 -20
  48. package/dist/render/body.js.map +1 -1
  49. package/dist/render/cells.js +21 -4
  50. package/dist/render/cells.js.map +1 -1
  51. package/dist/render/content.js +12 -5
  52. package/dist/render/content.js.map +1 -1
  53. package/dist/render/header.js +21 -4
  54. package/dist/render/header.js.map +1 -1
  55. package/dist/render/pinned-rows.js +29 -0
  56. package/dist/render/pinned-rows.js.map +1 -0
  57. package/dist/styles/base.js +1 -1
  58. package/dist/styles/base.js.map +1 -1
  59. package/package.json +2 -1
@@ -1,12 +1,20 @@
1
1
  import { controllable } from "./core/src/state/controllable.js";
2
+ import { RowLayout } from "./core/src/grid/row-layout.js";
3
+ import { announce } from "./announce.js";
4
+ import { AutoWidths, measureColumns } from "./controllers/auto-width.js";
5
+ import { ColumnChildrenController } from "./controllers/column-children.js";
6
+ import { DataController } from "./controllers/data-controller.js";
2
7
  import { PinScrollController } from "./controllers/pin-scroll-controller.js";
8
+ import { canStartReorder, dropTarget, startReorderDrag } from "./controllers/reorder-drag.js";
3
9
  import { startResizeDrag } from "./controllers/resize-drag.js";
4
10
  import { TableController } from "./controllers/table-controller.js";
5
11
  import { VirtualController } from "./controllers/virtual-controller.js";
6
- import { CELL_CLICK, COLUMN_RESIZE, RANGE_CHANGE, ROW_CLICK, SORT_CHANGE, fire } from "./events.js";
12
+ import { CELL_CLICK, COLUMN_REORDER, COLUMN_RESIZE, LOAD_ERROR, RANGE_CHANGE, ROW_CLICK, SORT_CHANGE, fire } from "./events.js";
13
+ import { bodyCap, watchMaxElementHeight } from "./max-height.js";
7
14
  import { renderBody } from "./render/body.js";
8
15
  import { renderLightDom } from "./render/cells.js";
9
16
  import { renderHeader } from "./render/header.js";
17
+ import { renderPinnedRows } from "./render/pinned-rows.js";
10
18
  import { baseStyles } from "./styles/base.js";
11
19
  import __decorate from "./_virtual/_@oxc-project_runtime@0.156.0/helpers/esm/decorate.js";
12
20
  import { LitElement, html, nothing } from "lit";
@@ -37,15 +45,24 @@ function sortColumnOf(event) {
37
45
  }
38
46
  }
39
47
  var RESIZE_STEP = 10;
48
+ var HEADER = {
49
+ section: "header",
50
+ index: 0
51
+ };
52
+ /** Where the rows sit in the grid: header, pinned top, body, pinned bottom. */
53
+ function layoutOf(model) {
54
+ return new RowLayout(model.pinnedCount("top"), model.rowCount, model.pinnedCount("bottom"));
55
+ }
40
56
  /** The grid cell or column header an element is, if any. */
41
57
  function gridCell(target) {
42
58
  if (!(target instanceof HTMLElement) || target.dataset.col === void 0) return void 0;
43
59
  const role = target.getAttribute("role");
44
60
  return role === "gridcell" || role === "columnheader" ? target : void 0;
45
61
  }
46
- /** Row index of a rendered row element (`aria-rowindex` minus the header); `-1` for the header. */
47
- function rowIndexOf(row) {
48
- return Number(row?.getAttribute("aria-rowindex") ?? 1) - 2;
62
+ /** The grid row a rendered row element is, from its `aria-rowindex`. */
63
+ function gridRowOf(row, layout) {
64
+ const index = row?.getAttribute("aria-rowindex");
65
+ return index ? layout.fromAriaRowIndex(Number(index)) : void 0;
49
66
  }
50
67
  /**
51
68
  * The pinned edge's shadow, drawn once per side over the scroller rather than
@@ -72,14 +89,27 @@ function track(column) {
72
89
  var ArgusTable = class ArgusTable extends LitElement {
73
90
  constructor(..._args) {
74
91
  super(..._args);
75
- this.columns = [];
76
- this.data = [];
77
92
  this.density = "comfortable";
78
- this.overscan = 6;
93
+ this.#columnsProp = [];
94
+ this.#dataProp = [];
95
+ this.#overscan = 6;
79
96
  this.#sorting = controllable([]);
80
97
  this.#sizing = controllable({});
98
+ this.#order = controllable([]);
99
+ this.#appliedReorders = /* @__PURE__ */ new Map();
100
+ this.#appliedResizes = /* @__PURE__ */ new Map();
101
+ this.#autoWidths = new AutoWidths(() => {
102
+ this.requestUpdate();
103
+ });
104
+ this.#autoWidthsChanged = false;
81
105
  this.#internals = attachGridInternals(this);
82
106
  this.#table = new TableController();
107
+ this.#children = new ColumnChildrenController(this);
108
+ this.#columns = [];
109
+ this.#columnsChanged = false;
110
+ this.#warnedColumns = false;
111
+ this.#data = new DataController(this);
112
+ this.#scrollToTop = false;
83
113
  this.#virtual = new VirtualController(this, () => this.renderRoot.querySelector("[part~=\"table\"]"));
84
114
  this.#pinScroll = new PinScrollController(this, () => this.renderRoot.querySelector("[part~=\"table\"]"));
85
115
  this.#rowPx = 40;
@@ -90,6 +120,11 @@ var ArgusTable = class ArgusTable extends LitElement {
90
120
  };
91
121
  this.#focusPending = false;
92
122
  this.#lastRange = "";
123
+ this.#onRetry = (event) => {
124
+ const button = event.currentTarget;
125
+ if (button.matches(":focus")) button.parentElement?.focus({ preventScroll: true });
126
+ this.#data.retry(Number(button.dataset.row));
127
+ };
93
128
  this.#headerHandlers = {
94
129
  click: (event) => {
95
130
  const id = sortColumnOf(event);
@@ -101,18 +136,28 @@ var ArgusTable = class ArgusTable extends LitElement {
101
136
  if (!(handle instanceof HTMLElement)) return;
102
137
  const id = handle.dataset.resizeCol;
103
138
  const cell = handle.parentElement;
104
- if (id === void 0 || !cell) return;
105
- startResizeDrag(handle, event, cell.getBoundingClientRect().width, this.#direction(), (w) => {
106
- this.#requestResize(id, w);
107
- });
139
+ if (id !== void 0 && cell) {
140
+ startResizeDrag(handle, event, cell.getBoundingClientRect().width, this.#direction(), (w) => {
141
+ this.#requestResize(id, w);
142
+ });
143
+ return;
144
+ }
145
+ this.#startReorder(event);
146
+ },
147
+ /** A double-click on a resize handle fits the column to its rendered content. */
148
+ dblclick: (event) => {
149
+ const handle = event.composedPath()[0];
150
+ const id = handle instanceof HTMLElement ? handle.dataset.resizeCol : void 0;
151
+ if (id === void 0) return;
152
+ this.#requestResizes(measureColumns(this.renderRoot, [id]));
108
153
  }
109
154
  };
110
155
  this.#onKeydown = (event) => {
111
156
  const cell = gridCell(event.composedPath()[0] ?? event.target ?? this);
112
157
  const id = cell?.dataset.col;
113
158
  if (!cell || id === void 0) return;
159
+ const scroller = event.currentTarget;
114
160
  if (event.key === "Tab" && event.shiftKey) {
115
- const scroller = event.currentTarget;
116
161
  scroller.tabIndex = -1;
117
162
  cell.addEventListener("focusout", () => {
118
163
  scroller.removeAttribute("tabindex");
@@ -121,7 +166,14 @@ var ArgusTable = class ArgusTable extends LitElement {
121
166
  }
122
167
  const inHeader = cell.getAttribute("role") === "columnheader";
123
168
  const { key } = event;
124
- if (inHeader && event.altKey && (key === "ArrowLeft" || key === "ArrowRight")) {
169
+ const arrow = key === "ArrowLeft" || key === "ArrowRight";
170
+ if (inHeader && arrow && event.altKey && event.shiftKey) {
171
+ event.preventDefault();
172
+ const towardEnd = key === "ArrowRight" === (this.#direction() === 1);
173
+ this.#moveByKey(id, towardEnd ? 1 : -1);
174
+ return;
175
+ }
176
+ if (inHeader && event.altKey && arrow) {
125
177
  event.preventDefault();
126
178
  const towardEnd = key === "ArrowRight" === (this.#direction() === 1);
127
179
  this.#requestResize(id, this.#currentWidth(id, cell) + (towardEnd ? RESIZE_STEP : -10));
@@ -132,22 +184,41 @@ var ArgusTable = class ArgusTable extends LitElement {
132
184
  this.#requestSort(id);
133
185
  return;
134
186
  }
135
- if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return;
187
+ const corner = event.ctrlKey || event.metaKey;
188
+ if (event.altKey || event.shiftKey || corner && key !== "Home" && key !== "End") return;
189
+ const model = this.#table.model;
190
+ const layout = layoutOf(model);
191
+ const from = inHeader ? HEADER : gridRowOf(cell.parentElement, layout);
192
+ if (!from) return;
136
193
  if (!inHeader && key === "Enter") {
137
194
  event.preventDefault();
138
- this.#activate(event.composedPath());
195
+ if (from.section === "body" && this.#data.stateAt(from.index) === "error") this.#data.retry(from.index);
196
+ else this.#activate(event.composedPath());
139
197
  return;
140
198
  }
141
- const model = this.#table.model;
142
199
  const columns = model.columns;
143
- let row = inHeader ? -1 : rowIndexOf(cell.parentElement);
200
+ let pos = layout.position(from);
201
+ const last = layout.total - 1;
202
+ const bodyFirst = layout.position({
203
+ section: "body",
204
+ index: 0
205
+ });
206
+ const bodyLast = bodyFirst + layout.body - 1;
207
+ const fit = Math.floor(scroller.clientHeight / this.#rowPx + .01);
208
+ const page = Math.max(1, fit - 1 - layout.top - layout.bottom);
144
209
  let col = columns.findIndex((c) => c.id === id);
145
210
  switch (key) {
211
+ case "PageDown":
212
+ if (layout.body > 0 && pos <= bodyLast) pos = Math.min(Math.max(pos, bodyFirst - 1) + page, bodyLast);
213
+ break;
214
+ case "PageUp":
215
+ if (layout.body > 0 && pos > bodyFirst) pos = Math.max(Math.min(pos, bodyLast + 1) - page, bodyFirst);
216
+ break;
146
217
  case "ArrowDown":
147
- row = Math.min(row + 1, model.rowCount - 1);
218
+ pos = Math.min(pos + 1, last);
148
219
  break;
149
220
  case "ArrowUp":
150
- row = Math.max(row - 1, -1);
221
+ pos = Math.max(pos - 1, 0);
151
222
  break;
152
223
  case "ArrowRight":
153
224
  col += this.#direction();
@@ -157,13 +228,21 @@ var ArgusTable = class ArgusTable extends LitElement {
157
228
  break;
158
229
  case "Home":
159
230
  col = 0;
231
+ if (corner) {
232
+ pos = 0;
233
+ scroller.scrollTop = 0;
234
+ }
160
235
  break;
161
236
  case "End":
162
237
  col = columns.length - 1;
238
+ if (corner) pos = last;
163
239
  break;
164
240
  default: return;
165
241
  }
166
242
  event.preventDefault();
243
+ const row = layout.at(pos) ?? HEADER;
244
+ if (key.startsWith("Page") && from.section === "body" && row.section === "body") this.#virtual.scrollBy((row.index - from.index) * this.#rowPx);
245
+ if (corner && key === "End" && row.section === "bottom") scroller.scrollTop = scroller.scrollHeight;
167
246
  const target = columns[Math.min(Math.max(col, 0), columns.length - 1)];
168
247
  if (target) this.#moveTo(row, target.id, model);
169
248
  };
@@ -180,12 +259,14 @@ var ArgusTable = class ArgusTable extends LitElement {
180
259
  for (const target of event.composedPath()) {
181
260
  const cell = gridCell(target);
182
261
  if (cell?.dataset.col !== void 0) {
183
- const index = cell.getAttribute("role") === "columnheader" ? -1 : rowIndexOf(cell.parentElement);
262
+ const model = this.#table.model;
263
+ const row = cell.getAttribute("role") === "columnheader" ? HEADER : gridRowOf(cell.parentElement, layoutOf(model));
184
264
  const { col } = cell.dataset;
185
- if (index !== this.#active?.index || col !== this.#active.col) {
265
+ const prev = this.#active;
266
+ if (row && (row.section !== prev?.section || row.index !== prev.index || col !== prev.col)) {
186
267
  this.#active = {
187
- index,
188
- rowId: this.#table.model.rowAt(index)?.id,
268
+ ...row,
269
+ rowId: this.#gridRowId(model, row),
189
270
  col
190
271
  };
191
272
  this.requestUpdate();
@@ -203,6 +284,34 @@ var ArgusTable = class ArgusTable extends LitElement {
203
284
  this.styles = baseStyles;
204
285
  }
205
286
  /**
287
+ * Column definitions. Property only: functions can't be attributes. While empty,
288
+ * the table reads its `<argus-column>` children instead. `null` or `undefined`
289
+ * means `[]`.
290
+ */
291
+ get columns() {
292
+ return this.#columnsProp;
293
+ }
294
+ set columns(value) {
295
+ this.#columnsProp = value ?? [];
296
+ }
297
+ /**
298
+ * The rows to show. Replace the array to update; changes inside it aren't
299
+ * detected. `null` or `undefined` means `[]`.
300
+ */
301
+ get data() {
302
+ return this.#dataProp;
303
+ }
304
+ set data(value) {
305
+ this.#dataProp = value ?? [];
306
+ }
307
+ /** Rows rendered above and below the visible ones. `null` or `undefined` means the default, 6. */
308
+ get overscan() {
309
+ return this.#overscan;
310
+ }
311
+ set overscan(value) {
312
+ this.#overscan = value ?? 6;
313
+ }
314
+ /**
206
315
  * The sort order, e.g. `[{ id: 'total', desc: true }]`; `[]` when unsorted. Unset,
207
316
  * the table keeps it itself and header clicks change it. Once set, it is
208
317
  * controlled: a click only fires `argus-sort-change` with the proposed order,
@@ -225,14 +334,54 @@ var ArgusTable = class ArgusTable extends LitElement {
225
334
  set columnSizing(value) {
226
335
  this.#sizing.set(value);
227
336
  }
337
+ /**
338
+ * The column order: column ids as the table shows them, e.g.
339
+ * `['id', 'total', 'customer']`. `[]` (the default) keeps the order of `columns`.
340
+ * Each pin group (start-pinned, scrolling, end-pinned) takes its columns in this
341
+ * order; unknown ids are ignored and columns it doesn't list follow the listed
342
+ * ones of their group. After a move it holds every column id. Uncontrolled
343
+ * until set, like `sorting`: once set, a move only fires `argus-column-reorder`
344
+ * with the proposed order. `undefined` hands it back.
345
+ */
346
+ get columnOrder() {
347
+ return this.#order.value;
348
+ }
349
+ set columnOrder(value) {
350
+ this.#order.set(value);
351
+ }
352
+ #columnsProp;
353
+ #dataProp;
354
+ #overscan;
228
355
  #sorting;
229
356
  #sizing;
230
- /** A resize the table applied itself; its event fires once the update is done. */
231
- #appliedResize;
357
+ #order;
358
+ /** Moves the table applied itself, by column; their events fire once the update is done. */
359
+ #appliedReorders;
360
+ /** The header being dragged to a new position, if any. */
361
+ #drag;
362
+ /** A move from the keyboard, announced once it has rendered: the column and its old position. */
363
+ #announceMove;
364
+ /** Resizes the table applied itself, by column; their events fire once the update is done. */
365
+ #appliedResizes;
366
+ /** Measured widths of `width: 'auto'` columns. */
367
+ #autoWidths;
368
+ /** The auto widths last passed to the model; a change re-measures the pinned columns' offsets. */
369
+ #pushedAutoWidths;
370
+ #autoWidthsChanged;
232
371
  /** A sort the table applied itself; its event fires once the update is done. */
233
372
  #appliedSort;
234
373
  #internals;
235
374
  #table;
375
+ #children;
376
+ /** The columns last passed to the model: `columns`, or the `<argus-column>` children. */
377
+ #columns;
378
+ #columnsChanged;
379
+ #warnedColumns;
380
+ /** End of the light-DOM part holding cell content, so later children stay outside it. */
381
+ #contentEnd;
382
+ #data;
383
+ /** Scroll back to the top after the update (a new sort order for a data source). */
384
+ #scrollToTop;
236
385
  #virtual;
237
386
  #pinScroll;
238
387
  #rowPx;
@@ -242,14 +391,69 @@ var ArgusTable = class ArgusTable extends LitElement {
242
391
  /** Move focus to the active cell after the next update (keyboard navigation). */
243
392
  #focusPending;
244
393
  #lastRange;
394
+ #unwatchMaxHeight;
245
395
  connectedCallback() {
246
396
  super.connectedCallback();
247
397
  if (!this.hasAttribute("role")) this.setAttribute("role", "grid");
248
398
  if (this.hasUpdated) this.#observeProbe();
399
+ this.#unwatchMaxHeight = watchMaxElementHeight(() => {
400
+ this.requestUpdate();
401
+ });
249
402
  }
250
403
  disconnectedCallback() {
251
404
  super.disconnectedCallback();
252
405
  this.#probeObserver?.disconnect();
406
+ this.#unwatchMaxHeight?.();
407
+ this.#unwatchMaxHeight = void 0;
408
+ }
409
+ /**
410
+ * `columns` when it has any, otherwise the `<argus-column>` children. Keeps its
411
+ * identity while neither changes, so the model is only rebuilt on a change.
412
+ */
413
+ #effectiveColumns() {
414
+ if (this.columns.length === 0) return this.#children.defs;
415
+ if (!this.#warnedColumns && this.#children.present) {
416
+ this.#warnedColumns = true;
417
+ console.warn("argus-table: the columns property is set, so <argus-column> children are ignored.");
418
+ }
419
+ return this.columns;
420
+ }
421
+ /**
422
+ * The node the light-DOM content is rendered before. Lit's part then ends there,
423
+ * so children appended later (an `<argus-column>`) never land inside it. If the
424
+ * marker was removed (say by `innerHTML`), a new one starts a fresh part.
425
+ */
426
+ #lightDomEnd() {
427
+ if (this.#contentEnd?.parentNode !== this) {
428
+ this.#contentEnd = document.createComment("");
429
+ this.append(this.#contentEnd);
430
+ }
431
+ return this.#contentEnd;
432
+ }
433
+ /**
434
+ * With a `dataSource`, drops every loaded page and loads the rows in view
435
+ * again, keeping the scroll position. With `data`, re-renders the cells (after
436
+ * changing row objects in place). Resolves once the table has re-rendered;
437
+ * reloaded rows arrive as their pages load.
438
+ */
439
+ async refresh() {
440
+ this.#data.refresh();
441
+ this.requestUpdate();
442
+ await this.updateComplete;
443
+ }
444
+ /**
445
+ * Fits columns to their content: the header, the pinned rows and the body rows
446
+ * rendered now (rows out of view aren't measured). It resizes them like a drag
447
+ * would, so `argus-column-resize` fires for each column that changes, and with a
448
+ * controlled `columnSizing` nothing changes until you set it. Without `ids`, fits
449
+ * every resizable column; columns with `resizable: false` keep their width.
450
+ * Resolves once the table has re-rendered.
451
+ */
452
+ async autosizeColumns(ids) {
453
+ await this.updateComplete;
454
+ const targets = this.#table.model.columns.filter((c) => c.resizable && (ids === void 0 || ids.includes(c.id))).map((c) => c.id);
455
+ this.#requestResizes(measureColumns(this.renderRoot, targets));
456
+ await this.updateComplete;
253
457
  }
254
458
  /** Scrolls so that the row at `index` (in the current row order) is at the top. */
255
459
  async scrollToRow(index) {
@@ -258,24 +462,51 @@ var ArgusTable = class ArgusTable extends LitElement {
258
462
  await this.updateComplete;
259
463
  }
260
464
  willUpdate(changed) {
261
- if (changed.has("columns") || changed.has("data") || changed.has("getRowId") || changed.has("sorting") || changed.has("columnSizing")) this.#table.update({
262
- columns: this.columns,
263
- data: this.data,
264
- getRowId: this.getRowId,
265
- sorting: this.#sorting.value,
266
- columnSizing: this.#sizing.value
465
+ const columns = this.#effectiveColumns();
466
+ this.#columnsChanged = columns !== this.#columns;
467
+ this.#columns = columns;
468
+ if (changed.has("dataSource") || changed.has("sorting") || changed.has("getRowId")) {
469
+ this.#data.configure({
470
+ source: this.dataSource,
471
+ sorting: this.#sorting.value,
472
+ getRowId: this.getRowId
473
+ });
474
+ if (this.dataSource && this.hasUpdated && changed.has("sorting")) this.#scrollToTop = !changed.has("dataSource");
475
+ }
476
+ if (this.#columnsChanged || changed.has("data") || changed.has("getRowId") || changed.has("sorting") || changed.has("columnSizing") || changed.has("columnOrder") || changed.has("pinnedRows")) {
477
+ if (this.#columnsChanged) this.#autoWidths.sync(columns.filter((c) => c.width === "auto").map((c) => c.id));
478
+ this.#table.update({
479
+ columns,
480
+ data: this.data,
481
+ getRowId: this.getRowId,
482
+ sorting: this.#sorting.value,
483
+ columnSizing: this.#sizing.value,
484
+ columnOrder: this.#order.value,
485
+ pinnedRows: this.pinnedRows
486
+ });
487
+ }
488
+ const autoWidths = this.#autoWidths.widths;
489
+ this.#autoWidthsChanged = autoWidths !== this.#pushedAutoWidths;
490
+ this.#pushedAutoWidths = autoWidths;
491
+ this.#table.update({
492
+ remote: this.#data.rows,
493
+ autoWidths
267
494
  });
268
495
  const model = this.#table.model;
269
496
  this.#reconcileActive(model);
270
497
  const active = this.#active;
271
- this.#internals.ariaRowCount = String(model.rowCount + 1);
498
+ const unknownTotal = this.#data.rows?.totalKnown === false;
499
+ const layout = layoutOf(model);
500
+ this.#internals.ariaRowCount = unknownTotal ? "-1" : String(layout.total);
272
501
  this.#internals.ariaColCount = String(model.columns.length);
502
+ const extra = (1 + layout.top + layout.bottom) * this.#rowPx;
273
503
  this.#virtual.configure({
274
504
  count: model.rowCount,
275
505
  rowHeight: this.#rowPx,
506
+ cap: bodyCap(model.rowCount * this.#rowPx, extra),
276
507
  overscan: Math.max(0, this.overscan),
277
- rowIdAt: (index) => model.rowAt(index)?.id ?? String(index),
278
- keep: active?.rowId === void 0 ? void 0 : {
508
+ rowIdAt: (index) => this.#rowId(model, index),
509
+ keep: active?.section !== "body" || active.rowId === void 0 ? void 0 : {
279
510
  id: active.rowId,
280
511
  index: active.index
281
512
  }
@@ -287,49 +518,75 @@ var ArgusTable = class ArgusTable extends LitElement {
287
518
  this.#window = this.#virtual.computeWindow();
288
519
  const pinnedWidth = (side) => columns.reduce((sum, c) => c.pin === side ? sum + c.width : sum, 0);
289
520
  const pinned = (side) => `${String(pinnedWidth(side))}px`;
521
+ const layout = layoutOf(model);
290
522
  const style = {
291
523
  "--_cols": columns.map(track).join(" "),
292
524
  "--_width": `${String(model.totalWidth)}px`,
293
525
  "--_pin-start": pinned("start"),
294
- "--_pin-end": pinned("end")
526
+ "--_pin-end": pinned("end"),
527
+ "--_pin-top-rows": String(layout.top),
528
+ "--_pin-bottom-rows": String(layout.bottom)
295
529
  };
296
530
  const active = this.#active;
297
- const bodyActive = active && active.index >= 0 ? {
531
+ const activeIn = (section) => active?.section === section ? {
298
532
  index: active.index,
299
533
  col: active.col
300
534
  } : void 0;
535
+ const firstIndex = (section) => layout.ariaRowIndex({
536
+ section,
537
+ index: 0
538
+ });
301
539
  if (this.rowHeight !== void 0 && this.rowHeight > 0) style["--_row-height"] = `${String(this.rowHeight)}px`;
302
540
  return html`<div
303
541
  part="table"
304
542
  role="presentation"
305
543
  style=${styleMap(style)}
544
+ ?data-dragging=${this.#drag !== void 0}
306
545
  @keydown=${this.#onKeydown}
307
546
  @focusin=${this.#onFocusin}
308
547
  @click=${this.#onClick}
309
548
  >
310
- ${renderHeader(columns, this.#headerHandlers, active?.index === -1 ? active.col : void 0)}
311
- ${model.rowCount === 0 ? html`<div part="empty"><slot name="empty">No rows</slot></div>` : renderBody(this.#window.rows, columns, this.#window.totalSize, bodyActive)}
549
+ ${renderHeader(columns, this.#headerHandlers, activeIn("header")?.col, this.#drag)}
550
+ ${renderPinnedRows("top", layout.top, columns, firstIndex("top"), activeIn("top"))}
551
+ ${model.rowCount === 0 ? html`<div part="empty"><slot name="empty">No rows</slot></div>` : renderBody(this.#window.rows, columns, this.#window.totalSize, activeIn("body"), firstIndex("body"), this.#loading())}
552
+ ${renderPinnedRows("bottom", layout.bottom, columns, firstIndex("bottom"), activeIn("bottom"))}
312
553
  <div class="probe" aria-hidden="true"></div>
313
554
  </div>
314
- ${pinShadow("start", pinnedWidth("start"), model.rowCount, this.#rowPx)}
315
- ${pinShadow("end", pinnedWidth("end"), model.rowCount, this.#rowPx)}`;
555
+ ${pinShadow("start", pinnedWidth("start"), layout.total - 1, this.#rowPx)}
556
+ ${pinShadow("end", pinnedWidth("end"), layout.total - 1, this.#rowPx)}`;
316
557
  }
317
558
  firstUpdated() {
318
559
  this.#observeProbe();
319
560
  this.#measureRowHeight();
320
561
  }
321
562
  updated(changed) {
322
- renderLightDom(this, this.#table.model, this.#window.rows);
323
- if (changed.has("columns") || changed.has("columnSizing")) this.#pinScroll.measure();
563
+ const model = this.#table.model;
564
+ renderLightDom(this, model, this.#window.rows, this.#lightDomEnd());
565
+ this.#measureAutoWidths(model);
566
+ if (this.#scrollToTop) {
567
+ this.#scrollToTop = false;
568
+ const scroller = this.renderRoot.querySelector("[part~=\"table\"]");
569
+ if (scroller) scroller.scrollTop = 0;
570
+ }
571
+ if (this.#columnsChanged || changed.has("columnSizing") || changed.has("columnOrder") || this.#autoWidthsChanged) this.#pinScroll.measure();
324
572
  if (this.#focusPending) {
325
573
  this.#focusPending = false;
326
574
  this.#focusActive();
327
575
  }
328
576
  if (changed.has("density") || changed.has("rowHeight")) this.#measureRowHeight();
329
- if (this.#appliedResize) {
330
- const detail = this.#appliedResize;
331
- this.#appliedResize = void 0;
332
- fire(this, COLUMN_RESIZE, detail);
577
+ if (this.#appliedResizes.size > 0) {
578
+ const details = [...this.#appliedResizes.values()];
579
+ this.#appliedResizes.clear();
580
+ for (const detail of details) fire(this, COLUMN_RESIZE, detail);
581
+ }
582
+ if (this.#announceMove) {
583
+ this.#announceMoved(model, this.#announceMove);
584
+ this.#announceMove = void 0;
585
+ }
586
+ if (this.#appliedReorders.size > 0) {
587
+ const details = [...this.#appliedReorders.values()];
588
+ this.#appliedReorders.clear();
589
+ for (const detail of details) fire(this, COLUMN_REORDER, detail);
333
590
  }
334
591
  if (this.#appliedSort) {
335
592
  const sorting = this.#appliedSort;
@@ -345,11 +602,73 @@ var ArgusTable = class ArgusTable extends LitElement {
345
602
  end: range.end
346
603
  });
347
604
  }
605
+ if (range) {
606
+ const over = Math.max(0, this.overscan);
607
+ this.#data.request(Math.max(0, range.start - over), range.end + 1 + over);
608
+ }
609
+ for (const detail of this.#data.takeErrors()) fire(this, LOAD_ERROR, detail);
610
+ }
611
+ /**
612
+ * Measures the `width: 'auto'` columns once loaded body rows render, or right
613
+ * away when there are no rows (the header and pinned rows only). While a data
614
+ * source's first rows load, they keep the default width. A changed width
615
+ * renders once more.
616
+ */
617
+ #measureAutoWidths(model) {
618
+ const loaded = this.#window.rows.some((r) => model.rowAt(r.index) !== void 0);
619
+ if (!loaded && model.rowCount > 0) return;
620
+ if (this.#autoWidths.measure(this.renderRoot, model.columns, loaded)) this.requestUpdate();
621
+ }
622
+ /**
623
+ * Loading state for the body while a data source is set: the state of each
624
+ * row, and a Retry button on the first visible row of each failed page.
625
+ */
626
+ #loading() {
627
+ const cache = this.#data.rows;
628
+ if (!cache) return void 0;
629
+ const top = this.#window.range?.start ?? 0;
630
+ const firstByPage = /* @__PURE__ */ new Map();
631
+ for (const { index } of this.#window.rows) {
632
+ if (index < top || cache.stateAt(index) !== "error") continue;
633
+ const page = cache.pageOf(index);
634
+ const first = firstByPage.get(page);
635
+ if (first === void 0 || index < first) firstByPage.set(page, index);
636
+ }
637
+ const retry = /* @__PURE__ */ new Map();
638
+ for (const [page, index] of firstByPage) {
639
+ const start = page * cache.pageSize;
640
+ const end = Math.min(start + cache.pageSize, cache.rowCount);
641
+ retry.set(index, `Retry loading rows ${String(start + 1)} to ${String(end)}`);
642
+ }
643
+ return {
644
+ stateAt: (index) => cache.stateAt(index),
645
+ retry,
646
+ onRetry: this.#onRetry
647
+ };
648
+ }
649
+ #onRetry;
650
+ /**
651
+ * A row's id. A data source row that hasn't loaded gets a stand-in: the
652
+ * active cell's row id if it sits there (so its DOM and focus stay put), else
653
+ * the index, which is also its real id when there is no `getRowId`.
654
+ */
655
+ #rowId(model, index) {
656
+ const id = model.rowAt(index)?.id;
657
+ if (id !== void 0) return id;
658
+ const active = this.#active;
659
+ if (active?.index === index && active.rowId !== void 0) return active.rowId;
660
+ return this.#placeholderId(index);
661
+ }
662
+ /** The id of an unloaded row: its index, or a reserved string if `getRowId` makes the ids. */
663
+ #placeholderId(index) {
664
+ return this.getRowId ? `\u0000${String(index)}` : String(index);
348
665
  }
349
666
  #headerHandlers;
350
667
  /**
351
- * Keys on a focused cell or header. Keys from content inside a cell (an input,
352
- * a button) are left to that content.
668
+ * Keys on a focused cell or header: arrows by cell, Home/End along the row,
669
+ * PageUp/PageDown by a page of rows (the view scrolls with it), Ctrl+Home/End
670
+ * (or Cmd) to the first header and the last cell. Keys from content inside a
671
+ * cell (an input, a button) are left to that content.
353
672
  */
354
673
  #onKeydown;
355
674
  /** Focus that lands in a cell (a click, or content inside it) makes that cell active. */
@@ -358,7 +677,8 @@ var ArgusTable = class ArgusTable extends LitElement {
358
677
  #onClick;
359
678
  /**
360
679
  * Fires `argus-cell-click` (when a cell is on the path), then `argus-row-click`,
361
- * for the body row on an event path. Clicks and Enter on a body cell use it.
680
+ * for the body or pinned row on an event path. Clicks and Enter on a cell use
681
+ * it. Rows that haven't loaded and the header fire nothing.
362
682
  */
363
683
  #activate(path) {
364
684
  let columnId;
@@ -368,27 +688,55 @@ var ArgusTable = class ArgusTable extends LitElement {
368
688
  if (role === "gridcell") columnId = target.dataset.col;
369
689
  if (role !== "row") continue;
370
690
  const model = this.#table.model;
371
- const index = rowIndexOf(target);
372
- const row = index >= 0 ? model.rowAt(index) : void 0;
691
+ const at = gridRowOf(target, layoutOf(model));
692
+ if (!at || at.section === "header") return;
693
+ const { index } = at;
694
+ if (at.section === "body") {
695
+ const row = model.rowAt(index);
696
+ if (!row) return;
697
+ if (columnId !== void 0) fire(this, CELL_CLICK, {
698
+ row: row.original,
699
+ columnId,
700
+ value: model.valueAt(index, columnId)
701
+ });
702
+ fire(this, ROW_CLICK, {
703
+ row: row.original,
704
+ rowId: row.id,
705
+ index
706
+ });
707
+ return;
708
+ }
709
+ const pinned = at.section;
710
+ const row = model.pinnedRowAt(pinned, index);
373
711
  if (!row) return;
374
712
  if (columnId !== void 0) fire(this, CELL_CLICK, {
375
713
  row: row.original,
376
714
  columnId,
377
- value: model.valueAt(index, columnId)
715
+ value: model.pinnedValueAt(pinned, index, columnId),
716
+ pinned
378
717
  });
379
718
  fire(this, ROW_CLICK, {
380
719
  row: row.original,
381
720
  rowId: row.id,
382
- index
721
+ index,
722
+ pinned
383
723
  });
384
724
  return;
385
725
  }
386
726
  }
727
+ /** The id of a grid row: a body or pinned row's id; none for the header. */
728
+ #gridRowId(model, row) {
729
+ switch (row.section) {
730
+ case "header": return;
731
+ case "body": return this.#rowId(model, row.index);
732
+ default: return model.pinnedRowAt(row.section, row.index)?.id;
733
+ }
734
+ }
387
735
  /** Makes a cell active and focuses it after the update. The keep-rendered rule renders its row. */
388
- #moveTo(index, col, model) {
736
+ #moveTo(row, col, model) {
389
737
  this.#active = {
390
- index,
391
- rowId: index >= 0 ? model.rowAt(index)?.id : void 0,
738
+ ...row,
739
+ rowId: this.#gridRowId(model, row),
392
740
  col
393
741
  };
394
742
  this.#focusPending = true;
@@ -398,20 +746,30 @@ var ArgusTable = class ArgusTable extends LitElement {
398
746
  const active = this.#active;
399
747
  if (!active) return;
400
748
  const col = CSS.escape(active.col);
401
- const selector = active.index === -1 ? `[part~='header-row'] > [data-col="${col}"]` : `[part~='body'] > [aria-rowindex="${String(active.index + 2)}"] > [data-col="${col}"]`;
402
- const cell = this.renderRoot.querySelector(selector);
749
+ const index = layoutOf(this.#table.model).ariaRowIndex(active);
750
+ const cell = this.renderRoot.querySelector(`[role='row'][aria-rowindex="${String(index)}"] > [data-col="${col}"]`);
403
751
  if (!cell) return;
752
+ cell.focus({ preventScroll: true });
753
+ if (active.section === "body" && this.#virtual.scaled) {
754
+ const layout = layoutOf(this.#table.model);
755
+ const before = (1 + layout.top) * this.#rowPx;
756
+ if (this.#virtual.reveal(active.index, before, layout.bottom * this.#rowPx)) {
757
+ this.#focusPending = true;
758
+ return;
759
+ }
760
+ }
404
761
  cell.scrollIntoView({
405
762
  block: "nearest",
406
763
  inline: "nearest"
407
764
  });
408
- cell.focus({ preventScroll: true });
409
765
  }
410
766
  /**
411
- * Keeps the active cell valid after columns or rows change: on the same row id
412
- * when it still exists (it may have moved), else at the same index, clamped.
413
- * Defaults to the first header. If its row went away while the grid had focus,
414
- * focus follows to the replacement.
767
+ * Keeps the active cell valid after columns or rows change. In the body: on the
768
+ * same row id when it still exists (it may have moved), else at the same
769
+ * index, clamped. A data source row that isn't loaded (yet, or any more) keeps
770
+ * its id. A pinned row stays at its index, clamped to its list. A row whose
771
+ * section has no rows left gives way to the header, the default. If its row
772
+ * went away while the grid had focus, focus follows to the replacement.
415
773
  */
416
774
  #reconcileActive(model) {
417
775
  const columns = model.columns;
@@ -421,21 +779,37 @@ var ArgusTable = class ArgusTable extends LitElement {
421
779
  return;
422
780
  }
423
781
  const prev = this.#active ?? {
424
- index: -1,
782
+ ...HEADER,
425
783
  rowId: void 0,
426
784
  col: first.id
427
785
  };
428
786
  const col = columns.some((c) => c.id === prev.col) ? prev.col : first.id;
429
- let { index, rowId } = prev;
430
- if (rowId !== void 0) {
787
+ let { section, index, rowId } = prev;
788
+ let moved = false;
789
+ if (section === "body" && rowId !== void 0) {
431
790
  const found = model.indexOf(rowId);
432
- if (found === void 0) {
791
+ const unloaded = index < model.rowCount && model.rowAt(index) === void 0;
792
+ if (found !== void 0) index = found;
793
+ else if (!unloaded) {
433
794
  index = Math.min(index, model.rowCount - 1);
434
- rowId = model.rowAt(index)?.id;
435
- if (this.matches(":focus-within")) this.#focusPending = true;
436
- } else index = found;
795
+ rowId = index >= 0 ? model.rowAt(index)?.id ?? this.#placeholderId(index) : void 0;
796
+ moved = true;
797
+ }
798
+ } else if (section === "top" || section === "bottom") {
799
+ const count = model.pinnedCount(section);
800
+ if (index >= count) {
801
+ index = count - 1;
802
+ moved = true;
803
+ }
804
+ rowId = index >= 0 ? model.pinnedRowAt(section, index)?.id : void 0;
805
+ }
806
+ if (index < 0) {
807
+ ({section, index} = HEADER);
808
+ rowId = void 0;
437
809
  }
438
- if (index !== prev.index || rowId !== prev.rowId || col !== prev.col || !this.#active) this.#active = {
810
+ if (moved && this.matches(":focus-within")) this.#focusPending = true;
811
+ if (section !== prev.section || index !== prev.index || rowId !== prev.rowId || col !== prev.col || !this.#active) this.#active = {
812
+ section,
439
813
  index,
440
814
  rowId,
441
815
  col
@@ -457,20 +831,145 @@ var ArgusTable = class ArgusTable extends LitElement {
457
831
  }
458
832
  /** Sets one column's width (clamped by core), through the controlled/uncontrolled rules. */
459
833
  #requestResize(columnId, width) {
460
- const next = this.#table.model.nextSizing(columnId, width);
461
- const target = next?.[columnId];
462
- if (!next || target === void 0 || target === this.#sizing.value[columnId]) return;
834
+ this.#requestResizes(/* @__PURE__ */ new Map([[columnId, width]]));
835
+ }
836
+ /**
837
+ * Sets column widths (clamped by core) in one change, through the
838
+ * controlled/uncontrolled rules. One `argus-column-resize` per column that
839
+ * changes, each with the whole new sizing.
840
+ */
841
+ #requestResizes(widths) {
842
+ const model = this.#table.model;
463
843
  const old = this.#sizing.value;
464
- const { value, applied } = this.#sizing.request(next);
465
- const detail = {
844
+ const targets = [];
845
+ for (const [columnId, width] of widths) {
846
+ const target = model.nextSizing(columnId, width)?.[columnId];
847
+ if (target !== void 0 && target !== old[columnId]) targets.push([columnId, target]);
848
+ }
849
+ if (targets.length === 0) return;
850
+ const { value, applied } = this.#sizing.request({
851
+ ...old,
852
+ ...Object.fromEntries(targets)
853
+ });
854
+ const details = targets.map(([columnId, width]) => ({
466
855
  columnId,
467
- width: target,
856
+ width,
468
857
  sizing: value
469
- };
858
+ }));
470
859
  if (applied) {
471
- this.#appliedResize = detail;
860
+ for (const detail of this.#appliedResizes.values()) detail.sizing = value;
861
+ for (const detail of details) this.#appliedResizes.set(detail.columnId, detail);
472
862
  this.requestUpdate("columnSizing", old);
473
- } else fire(this, COLUMN_RESIZE, detail);
863
+ } else for (const detail of details) fire(this, COLUMN_RESIZE, detail);
864
+ }
865
+ /**
866
+ * Moves a column to position `to` in the whole order (within its pin group),
867
+ * through the controlled/uncontrolled rules. Starts from the latest requested
868
+ * order, so moves can come faster than renders. `false` if it can't move there.
869
+ */
870
+ #requestReorder(columnId, to) {
871
+ const old = this.#order.value;
872
+ const next = this.#table.model.nextOrder(columnId, to, old);
873
+ if (!next) return false;
874
+ const { value, applied } = this.#order.request(next);
875
+ if (applied) {
876
+ for (const detail of this.#appliedReorders.values()) detail.order = value;
877
+ this.#appliedReorders.set(columnId, {
878
+ columnId,
879
+ order: value
880
+ });
881
+ this.requestUpdate("columnOrder", old);
882
+ } else fire(this, COLUMN_REORDER, {
883
+ columnId,
884
+ order: value
885
+ });
886
+ return true;
887
+ }
888
+ /** Alt+Shift+Arrow on a header: one step toward the start (-1) or the end (1). */
889
+ #moveByKey(columnId, step) {
890
+ const model = this.#table.model;
891
+ const from = model.orderOf(this.#order.value).indexOf(columnId);
892
+ const view = model.columns.find((c) => c.id === columnId);
893
+ if (from < 0 || !view) return;
894
+ if (!this.#requestReorder(columnId, from + step)) return;
895
+ this.#focusPending = true;
896
+ this.#announceMove ??= {
897
+ id: columnId,
898
+ from: view.colIndex
899
+ };
900
+ this.requestUpdate();
901
+ }
902
+ /** Tells screen readers where a column moved from the keyboard went. */
903
+ #announceMoved(model, move) {
904
+ const view = model.columns.find((c) => c.id === move.id);
905
+ if (!view || view.colIndex === move.from) return;
906
+ const header = this.renderRoot.querySelector(`[role='columnheader'][data-col="${CSS.escape(move.id)}"] > slot`);
907
+ const name = header instanceof HTMLSlotElement ? header.assignedNodes({ flatten: true }).map((n) => n.textContent).join("").trim() : "";
908
+ announce(this.ownerDocument, `${name || move.id} moved to column ${String(view.colIndex)} of ${String(model.columns.length)}`);
909
+ }
910
+ /** A press on a reorderable header: becomes a drag once the pointer moves. */
911
+ #startReorder(down) {
912
+ const cell = down.composedPath().find((t) => t instanceof HTMLElement && t.getAttribute("role") === "columnheader");
913
+ const columnId = cell?.dataset.moveCol;
914
+ if (!cell || columnId === void 0 || !canStartReorder(down, cell)) return;
915
+ const scroller = this.renderRoot.querySelector("[part~=\"table\"]");
916
+ if (!scroller) return;
917
+ const pin = this.#table.model.columns.find((c) => c.id === columnId)?.pin;
918
+ startReorderDrag(cell, down, {
919
+ scroller,
920
+ targetAt: (x) => dropTarget(this.#dropSlots(pin), columnId, x, this.#direction()),
921
+ scrollArea: () => pin === void 0 ? this.#scrollArea(scroller) : void 0,
922
+ onStart: () => {
923
+ this.#drag = {
924
+ columnId,
925
+ target: void 0
926
+ };
927
+ this.requestUpdate();
928
+ },
929
+ onTarget: (target) => {
930
+ this.#drag = {
931
+ columnId,
932
+ target
933
+ };
934
+ this.requestUpdate();
935
+ },
936
+ onDrop: (target) => {
937
+ this.#drag = void 0;
938
+ if (target && this.#requestReorder(columnId, target.to)) {
939
+ if (this.matches(":focus-within")) this.#focusPending = true;
940
+ }
941
+ this.requestUpdate();
942
+ },
943
+ onCancel: () => {
944
+ this.#drag = void 0;
945
+ this.requestUpdate();
946
+ }
947
+ });
948
+ }
949
+ /** The rendered headers of one pin group, with their positions in the whole order. */
950
+ #dropSlots(pin) {
951
+ const slots = [];
952
+ this.#table.model.columns.forEach((c, index) => {
953
+ if (c.pin !== pin) return;
954
+ const cell = this.renderRoot.querySelector(`[role='columnheader'][data-col="${CSS.escape(c.id)}"]`);
955
+ if (cell) slots.push({
956
+ id: c.id,
957
+ index,
958
+ rect: cell.getBoundingClientRect()
959
+ });
960
+ });
961
+ return slots;
962
+ }
963
+ /** Where the scrolling columns show: the scroller's inside, less the pinned columns. */
964
+ #scrollArea(scroller) {
965
+ const columns = this.#table.model.columns;
966
+ const width = (side) => columns.reduce((sum, c) => c.pin === side ? sum + c.width : sum, 0);
967
+ const ltr = this.#direction() === 1;
968
+ const left = scroller.getBoundingClientRect().left + scroller.clientLeft;
969
+ return {
970
+ left: left + width(ltr ? "start" : "end"),
971
+ right: left + scroller.clientWidth - width(ltr ? "end" : "start")
972
+ };
474
973
  }
475
974
  /** asc → desc → unsorted, through the controlled/uncontrolled rules. */
476
975
  #requestSort(columnId) {
@@ -500,17 +999,20 @@ var ArgusTable = class ArgusTable extends LitElement {
500
999
  }
501
1000
  }
502
1001
  };
503
- __decorate([property({ attribute: false })], ArgusTable.prototype, "columns", void 0);
504
- __decorate([property({ attribute: false })], ArgusTable.prototype, "data", void 0);
1002
+ __decorate([property({ attribute: false })], ArgusTable.prototype, "columns", null);
1003
+ __decorate([property({ attribute: false })], ArgusTable.prototype, "data", null);
1004
+ __decorate([property({ attribute: false })], ArgusTable.prototype, "dataSource", void 0);
1005
+ __decorate([property({ attribute: false })], ArgusTable.prototype, "pinnedRows", void 0);
505
1006
  __decorate([property({ attribute: false })], ArgusTable.prototype, "getRowId", void 0);
506
1007
  __decorate([property({
507
1008
  attribute: "row-height",
508
1009
  type: Number
509
1010
  })], ArgusTable.prototype, "rowHeight", void 0);
510
1011
  __decorate([property({ reflect: true })], ArgusTable.prototype, "density", void 0);
511
- __decorate([property({ type: Number })], ArgusTable.prototype, "overscan", void 0);
1012
+ __decorate([property({ type: Number })], ArgusTable.prototype, "overscan", null);
512
1013
  __decorate([property({ attribute: false })], ArgusTable.prototype, "sorting", null);
513
1014
  __decorate([property({ attribute: false })], ArgusTable.prototype, "columnSizing", null);
1015
+ __decorate([property({ attribute: false })], ArgusTable.prototype, "columnOrder", null);
514
1016
  ArgusTable = __decorate([customElement("argus-table")], ArgusTable);
515
1017
  export { ArgusTable };
516
1018