argus-table 0.2.1 → 0.3.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.
Files changed (69) hide show
  1. package/README.md +1 -1
  2. package/dist/argus-column.js +24 -1
  3. package/dist/argus-column.js.map +1 -1
  4. package/dist/argus-table.js +1026 -167
  5. package/dist/argus-table.js.map +1 -1
  6. package/dist/cdn/argus-table.js +74 -50
  7. package/dist/cdn/argus-table.js.map +1 -1
  8. package/dist/controllers/auto-width.js +11 -0
  9. package/dist/controllers/auto-width.js.map +1 -1
  10. package/dist/controllers/column-window.js +139 -0
  11. package/dist/controllers/column-window.js.map +1 -0
  12. package/dist/controllers/data-controller.js +9 -4
  13. package/dist/controllers/data-controller.js.map +1 -1
  14. package/dist/controllers/plugins.js +102 -0
  15. package/dist/controllers/plugins.js.map +1 -0
  16. package/dist/controllers/reorder-drag.js +9 -10
  17. package/dist/controllers/reorder-drag.js.map +1 -1
  18. package/dist/controllers/row-measure.js +121 -0
  19. package/dist/controllers/row-measure.js.map +1 -0
  20. package/dist/controllers/virtual-controller.js +316 -10
  21. package/dist/controllers/virtual-controller.js.map +1 -1
  22. package/dist/core/src/columns/column-order.js +14 -10
  23. package/dist/core/src/columns/column-order.js.map +1 -1
  24. package/dist/core/src/columns/resolve-columns.js +18 -4
  25. package/dist/core/src/columns/resolve-columns.js.map +1 -1
  26. package/dist/core/src/data/page-cache.js +4 -0
  27. package/dist/core/src/data/page-cache.js.map +1 -1
  28. package/dist/core/src/filters/filter.js +185 -0
  29. package/dist/core/src/filters/filter.js.map +1 -0
  30. package/dist/core/src/state/selection.js +70 -0
  31. package/dist/core/src/state/selection.js.map +1 -0
  32. package/dist/core/src/table/create-table.js +239 -64
  33. package/dist/core/src/table/create-table.js.map +1 -1
  34. package/dist/core/src/table/filtered-row-model.js +48 -0
  35. package/dist/core/src/table/filtered-row-model.js.map +1 -0
  36. package/dist/core/src/table/sorted-row-model.js +13 -2
  37. package/dist/core/src/table/sorted-row-model.js.map +1 -1
  38. package/dist/core/src/virtual/column-window.js +72 -0
  39. package/dist/core/src/virtual/column-window.js.map +1 -0
  40. package/dist/core/src/virtual/row-pool.js +2 -1
  41. package/dist/core/src/virtual/row-pool.js.map +1 -1
  42. package/dist/core/src/virtual/row-sizes.js +156 -0
  43. package/dist/core/src/virtual/row-sizes.js.map +1 -0
  44. package/dist/core/src/virtual/scroll-scale.js +41 -3
  45. package/dist/core/src/virtual/scroll-scale.js.map +1 -1
  46. package/dist/custom-elements.json +1320 -74
  47. package/dist/events.js +9 -1
  48. package/dist/events.js.map +1 -1
  49. package/dist/index.d.ts +609 -74
  50. package/dist/index.js +3 -2
  51. package/dist/interactive.js +22 -0
  52. package/dist/interactive.js.map +1 -0
  53. package/dist/max-height.js +22 -8
  54. package/dist/max-height.js.map +1 -1
  55. package/dist/render/body.js +47 -7
  56. package/dist/render/body.js.map +1 -1
  57. package/dist/render/cells.js +14 -11
  58. package/dist/render/cells.js.map +1 -1
  59. package/dist/render/content-directive.js +115 -0
  60. package/dist/render/content-directive.js.map +1 -0
  61. package/dist/render/content.js +20 -9
  62. package/dist/render/content.js.map +1 -1
  63. package/dist/render/header.js +24 -5
  64. package/dist/render/header.js.map +1 -1
  65. package/dist/render/pinned-rows.js +1 -1
  66. package/dist/render/pinned-rows.js.map +1 -1
  67. package/dist/styles/base.js +1 -1
  68. package/dist/styles/base.js.map +1 -1
  69. package/package.json +1 -1
@@ -0,0 +1,70 @@
1
+ // ../core/src/state/selection.ts
2
+ /** Whether two selections hold the same ids, in any order. */
3
+ function sameSelection(a, b) {
4
+ if (a.length !== b.length) return false;
5
+ const ids = new Set(a);
6
+ return b.every((id) => ids.has(id));
7
+ }
8
+ /**
9
+ * Selects or deselects one row and makes it the anchor. In `'single'` mode,
10
+ * selecting a row replaces the selection.
11
+ */
12
+ function toggleRow(current, mode, id) {
13
+ if (mode === "none") return void 0;
14
+ if (current.includes(id)) return {
15
+ selection: current.filter((s) => s !== id),
16
+ anchor: id
17
+ };
18
+ return {
19
+ selection: mode === "single" ? [id] : [...current, id],
20
+ anchor: id
21
+ };
22
+ }
23
+ /**
24
+ * The rows from index `from` to `to` (either order, both inclusive), in row
25
+ * order. With `add`, they join the current selection instead of replacing it.
26
+ * The anchor stays where it was.
27
+ */
28
+ function selectRange(current, from, to, idAt, add) {
29
+ const ids = add ? [...current] : [];
30
+ const have = new Set(ids);
31
+ const [first, last] = (to >= from ? 1 : -1) === 1 ? [from, to] : [to, from];
32
+ for (let index = first; index <= last; index++) {
33
+ const id = idAt(index);
34
+ if (id === void 0 || have.has(id)) continue;
35
+ have.add(id);
36
+ ids.push(id);
37
+ }
38
+ return ids;
39
+ }
40
+ /**
41
+ * Every row of `ids` selected, keeping the rows already selected (with a
42
+ * `dataSource`, `ids` are only the loaded rows: selected rows elsewhere stay).
43
+ */
44
+ function selectAll(current, ids) {
45
+ const have = new Set(current);
46
+ return [...current, ...ids.filter((id) => !have.has(id))];
47
+ }
48
+ /**
49
+ * A click on a row, desktop style. A plain click selects only that row; Ctrl or
50
+ * Cmd toggles it. In `'multi'` mode, Shift selects the range from the anchor
51
+ * (at `anchorIndex`) to the row, and Ctrl+Shift adds that range. Without an
52
+ * anchor in the current rows, Shift acts like a plain click. `undefined` in
53
+ * `'none'` mode. The selection may come back unchanged (a click on the one
54
+ * selected row): check with `sameSelection` before reporting a change.
55
+ */
56
+ function clickSelection(current, mode, target, anchor, modifiers, idAt) {
57
+ if (mode === "none") return void 0;
58
+ if (mode === "multi" && modifiers.range && anchor) return {
59
+ selection: selectRange(current, anchor.index, target.index, idAt, modifiers.toggle),
60
+ anchor: anchor.id
61
+ };
62
+ if (modifiers.toggle) return toggleRow(current, mode, target.id);
63
+ return {
64
+ selection: [target.id],
65
+ anchor: target.id
66
+ };
67
+ }
68
+ export { clickSelection, sameSelection, selectAll, selectRange, toggleRow };
69
+
70
+ //# sourceMappingURL=selection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selection.js","names":[],"sources":["../../../../../core/src/state/selection.ts"],"sourcesContent":["import type { SelectionMode, SelectionState } from '../types.js';\n\n/**\n * Row selection rules, DOM-free. The element owns the state (through\n * `controllable`) and the anchor; these functions only compute the next ones.\n *\n * The anchor is the row a range starts from: the last row clicked or toggled\n * without Shift. Ranges are by index in the current row order, so they follow\n * sorting; `idAt` returns `undefined` for a row that can't be selected (a\n * `dataSource` row not loaded), and such rows are left out.\n */\n\n/** The selection after a step, and the row later ranges start from. */\nexport interface SelectionStep {\n selection: SelectionState;\n anchor: string | undefined;\n}\n\n/** The row a click or key acts on: its id and its index in the current row order. */\nexport interface SelectionTarget {\n id: string;\n index: number;\n}\n\n/** Modifier keys of a click: Ctrl or Cmd toggles, Shift selects a range. */\nexport interface SelectionModifiers {\n toggle: boolean;\n range: boolean;\n}\n\n/** Whether two selections hold the same ids, in any order. */\nexport function sameSelection(a: readonly string[], b: readonly string[]): boolean {\n if (a.length !== b.length) return false;\n const ids = new Set(a);\n return b.every((id) => ids.has(id));\n}\n\n/**\n * Selects or deselects one row and makes it the anchor. In `'single'` mode,\n * selecting a row replaces the selection.\n */\nexport function toggleRow(\n current: readonly string[],\n mode: SelectionMode,\n id: string,\n): SelectionStep | undefined {\n if (mode === 'none') return undefined;\n if (current.includes(id)) return { selection: current.filter((s) => s !== id), anchor: id };\n return { selection: mode === 'single' ? [id] : [...current, id], anchor: id };\n}\n\n/**\n * The rows from index `from` to `to` (either order, both inclusive), in row\n * order. With `add`, they join the current selection instead of replacing it.\n * The anchor stays where it was.\n */\nexport function selectRange(\n current: readonly string[],\n from: number,\n to: number,\n idAt: (index: number) => string | undefined,\n add: boolean,\n): SelectionState {\n const ids: string[] = add ? [...current] : [];\n const have = new Set(ids);\n const step = to >= from ? 1 : -1;\n const [first, last] = step === 1 ? [from, to] : [to, from];\n for (let index = first; index <= last; index++) {\n const id = idAt(index);\n if (id === undefined || have.has(id)) continue;\n have.add(id);\n ids.push(id);\n }\n return ids;\n}\n\n/**\n * Every row of `ids` selected, keeping the rows already selected (with a\n * `dataSource`, `ids` are only the loaded rows: selected rows elsewhere stay).\n */\nexport function selectAll(current: readonly string[], ids: readonly string[]): SelectionState {\n const have = new Set(current);\n return [...current, ...ids.filter((id) => !have.has(id))];\n}\n\n/**\n * A click on a row, desktop style. A plain click selects only that row; Ctrl or\n * Cmd toggles it. In `'multi'` mode, Shift selects the range from the anchor\n * (at `anchorIndex`) to the row, and Ctrl+Shift adds that range. Without an\n * anchor in the current rows, Shift acts like a plain click. `undefined` in\n * `'none'` mode. The selection may come back unchanged (a click on the one\n * selected row): check with `sameSelection` before reporting a change.\n */\nexport function clickSelection(\n current: readonly string[],\n mode: SelectionMode,\n target: SelectionTarget,\n anchor: { id: string; index: number } | undefined,\n modifiers: SelectionModifiers,\n idAt: (index: number) => string | undefined,\n): SelectionStep | undefined {\n if (mode === 'none') return undefined;\n if (mode === 'multi' && modifiers.range && anchor) {\n return {\n selection: selectRange(current, anchor.index, target.index, idAt, modifiers.toggle),\n anchor: anchor.id,\n };\n }\n if (modifiers.toggle) return toggleRow(current, mode, target.id);\n return { selection: [target.id], anchor: target.id };\n}\n"],"mappings":";;AA+BA,SAAgB,cAAc,GAAsB,GAA+B;CACjF,IAAI,EAAE,WAAW,EAAE,QAAQ,OAAO;CAClC,MAAM,MAAM,IAAI,IAAI,CAAC;CACrB,OAAO,EAAE,OAAO,OAAO,IAAI,IAAI,EAAE,CAAC;AACpC;;;;;AAMA,SAAgB,UACd,SACA,MACA,IAC2B;CAC3B,IAAI,SAAS,QAAQ,OAAO,KAAA;CAC5B,IAAI,QAAQ,SAAS,EAAE,GAAG,OAAO;EAAE,WAAW,QAAQ,QAAQ,MAAM,MAAM,EAAE;EAAG,QAAQ;CAAG;CAC1F,OAAO;EAAE,WAAW,SAAS,WAAW,CAAC,EAAE,IAAI,CAAC,GAAG,SAAS,EAAE;EAAG,QAAQ;CAAG;AAC9E;;;;;;AAOA,SAAgB,YACd,SACA,MACA,IACA,MACA,KACgB;CAChB,MAAM,MAAgB,MAAM,CAAC,GAAG,OAAO,IAAI,CAAC;CAC5C,MAAM,OAAO,IAAI,IAAI,GAAG;CAExB,MAAM,CAAC,OAAO,SADD,MAAM,OAAO,IAAI,QACC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI;CACzD,KAAK,IAAI,QAAQ,OAAO,SAAS,MAAM,SAAS;EAC9C,MAAM,KAAK,KAAK,KAAK;EACrB,IAAI,OAAO,KAAA,KAAa,KAAK,IAAI,EAAE,GAAG;EACtC,KAAK,IAAI,EAAE;EACX,IAAI,KAAK,EAAE;CACb;CACA,OAAO;AACT;;;;;AAMA,SAAgB,UAAU,SAA4B,KAAwC;CAC5F,MAAM,OAAO,IAAI,IAAI,OAAO;CAC5B,OAAO,CAAC,GAAG,SAAS,GAAG,IAAI,QAAQ,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;AAC1D;;;;;;;;;AAUA,SAAgB,eACd,SACA,MACA,QACA,QACA,WACA,MAC2B;CAC3B,IAAI,SAAS,QAAQ,OAAO,KAAA;CAC5B,IAAI,SAAS,WAAW,UAAU,SAAS,QACzC,OAAO;EACL,WAAW,YAAY,SAAS,OAAO,OAAO,OAAO,OAAO,MAAM,UAAU,MAAM;EAClF,QAAQ,OAAO;CACjB;CAEF,IAAI,UAAU,QAAQ,OAAO,UAAU,SAAS,MAAM,OAAO,EAAE;CAC/D,OAAO;EAAE,WAAW,CAAC,OAAO,EAAE;EAAG,QAAQ,OAAO;CAAG;AACrD"}
@@ -1,14 +1,16 @@
1
1
  import { moveColumn, normalizeOrder } from "../columns/column-order.js";
2
2
  import { resolveColumns } from "../columns/resolve-columns.js";
3
- import { sortedRowModel } from "./sorted-row-model.js";
4
- import { columnPinningFeature, columnSizingFeature, constructTable, rowSortingFeature, sortFn_alphanumeric, sortFn_basic, sortFn_datetime, sortFn_text, tableFeatures } from "@tanstack/table-core";
3
+ import { distinctValues, rowPredicate } from "../filters/filter.js";
4
+ import { filteredRowModel, setRowPredicate } from "./filtered-row-model.js";
5
+ import { sortedRowModel, valuesChanged } from "./sorted-row-model.js";
6
+ import { columnSizingFeature, constructTable, rowSortingFeature, sortFn_alphanumeric, sortFn_basic, sortFn_datetime, sortFn_text, tableFeatures } from "@tanstack/table-core";
5
7
  import { storeReactivityBindings } from "@tanstack/table-core/store-reactivity-bindings";
6
8
  // ../core/src/table/create-table.ts
7
9
  var features = tableFeatures({
8
10
  coreReactivityFeature: storeReactivityBindings(),
9
- columnPinningFeature,
10
11
  columnSizingFeature,
11
12
  rowSortingFeature,
13
+ filteredRowModel: filteredRowModel(),
12
14
  sortedRowModel: sortedRowModel(),
13
15
  sortFns: {
14
16
  alphanumeric: sortFn_alphanumeric,
@@ -17,7 +19,51 @@ var features = tableFeatures({
17
19
  text: sortFn_text
18
20
  }
19
21
  });
22
+ /**
23
+ * Id of the selection column, the checkbox column the model adds first when
24
+ * `selectionColumn` is set. Not a column of `columns`: it never appears in the
25
+ * column order, sizing or events.
26
+ */
27
+ var SELECTION_COLUMN_ID = "--argus-selection";
20
28
  var defaultRowId = (_row, index) => String(index);
29
+ /**
30
+ * Ids of the columns kept from `before` whose accessor changed: a new function,
31
+ * or a different path. A new column has nothing cached and isn't listed.
32
+ */
33
+ function changedAccessors(before, after) {
34
+ const old = new Map(before.map((c) => [c.id, c.accessor]));
35
+ return after.filter((c) => old.has(c.id) && old.get(c.id) !== c.accessor).map((c) => c.id);
36
+ }
37
+ /** The selection column's view: first, pinned to the start, fixed, and inert to sorting, sizing and moves. */
38
+ function selectionView(pinEdge) {
39
+ return {
40
+ id: SELECTION_COLUMN_ID,
41
+ kind: "selection",
42
+ colIndex: 1,
43
+ pin: "start",
44
+ offset: 0,
45
+ pinEdge,
46
+ hidden: false,
47
+ width: 40,
48
+ flex: void 0,
49
+ auto: false,
50
+ minWidth: 40,
51
+ maxWidth: 40,
52
+ sortable: false,
53
+ resizable: false,
54
+ reorderable: false,
55
+ pinnable: false,
56
+ hideable: false,
57
+ filter: void 0,
58
+ filtered: false,
59
+ align: "center",
60
+ wrap: false,
61
+ sorted: false,
62
+ header: void 0,
63
+ cell: void 0,
64
+ hasAccessor: false
65
+ };
66
+ }
21
67
  function toTanStack(column) {
22
68
  return {
23
69
  id: column.id,
@@ -30,9 +76,12 @@ function toTanStack(column) {
30
76
  };
31
77
  }
32
78
  /**
33
- * Creates the table model over TanStack Table. It owns no state: sorting, sizing and order
34
- * come in through `update()`, and `nextSorting()`, `nextSizing()` and `nextOrder()` only propose
79
+ * Creates the table model over TanStack Table. It owns no state: sorting, sizing, order,
80
+ * pinning and visibility come in through `update()`, and the `next*()` methods only propose
35
81
  * changes, so the caller decides (controlled or uncontrolled) whether to apply them.
82
+ *
83
+ * Hidden columns stay in TanStack, so their values still sort and read; only the
84
+ * views leave them out. Pin groups, sticky offsets and the order are the model's own.
36
85
  */
37
86
  function createTableModel(initial) {
38
87
  let options = initial;
@@ -40,40 +89,56 @@ function createTableModel(initial) {
40
89
  let byId = new Map(resolved.map((c) => [c.id, c]));
41
90
  let tanStackById = new Map(resolved.map((c) => [c.id, toTanStack(c)]));
42
91
  let views;
92
+ const pinOf = (column, pinning = options.columnPinning) => {
93
+ const state = pinning?.[column.id];
94
+ if (state === "start" || state === "end") return state;
95
+ return state === false ? void 0 : column.pin;
96
+ };
97
+ const hiddenOf = (column, visibility = options.columnVisibility) => {
98
+ const state = visibility?.[column.id];
99
+ return typeof state === "boolean" ? !state : column.hidden;
100
+ };
101
+ const shown = (id) => {
102
+ const column = byId.get(id);
103
+ return column !== void 0 && !hiddenOf(column);
104
+ };
43
105
  let sizing;
44
106
  const sizingState = () => {
45
107
  if (sizing) return sizing;
46
108
  const auto = options.autoWidths;
47
- if (!auto) return sizing = options.columnSizing;
48
109
  const merged = {};
110
+ let any = false;
49
111
  for (const column of resolved) {
50
- const px = auto[column.id];
112
+ if (column.flex !== void 0 && pinOf(column) !== void 0) {
113
+ merged[column.id] = column.pinnedWidth;
114
+ any = true;
115
+ }
116
+ const px = auto?.[column.id];
51
117
  if (!column.auto || px === void 0 || !Number.isFinite(px)) continue;
52
118
  merged[column.id] = Math.min(column.maxWidth, Math.max(column.minWidth, px));
119
+ any = true;
53
120
  }
54
- return sizing = {
121
+ return sizing = any ? {
55
122
  ...merged,
56
123
  ...options.columnSizing
57
- };
124
+ } : options.columnSizing;
58
125
  };
126
+ const orderable = () => resolved.map((c) => ({
127
+ id: c.id,
128
+ pin: pinOf(c),
129
+ reorderable: c.reorderable
130
+ }));
59
131
  let order;
60
- const orderState = () => order ??= normalizeOrder(options.columnOrder ?? [], resolved);
132
+ const orderState = () => order ??= normalizeOrder(options.columnOrder ?? [], orderable());
61
133
  const rowViews = /* @__PURE__ */ new WeakMap();
62
134
  let indexById;
63
135
  let ordered;
64
136
  const orderedColumns = () => {
65
137
  const current = orderState();
66
- if (ordered?.order !== current) {
67
- const pinOf = (id) => byId.get(id)?.pin;
68
- ordered = {
69
- order: current,
70
- columns: current.flatMap((id) => tanStackById.get(id) ?? []),
71
- pinning: {
72
- start: current.filter((id) => pinOf(id) === "start"),
73
- end: current.filter((id) => pinOf(id) === "end")
74
- }
75
- };
76
- }
138
+ if (ordered?.order !== current) ordered = {
139
+ order: current,
140
+ columns: current.flatMap((id) => tanStackById.get(id) ?? [])
141
+ };
77
142
  return ordered;
78
143
  };
79
144
  const tableOptions = () => ({
@@ -83,51 +148,95 @@ function createTableModel(initial) {
83
148
  getRowId: options.getRowId ?? defaultRowId,
84
149
  state: {
85
150
  sorting: options.sorting,
86
- columnSizing: sizingState(),
87
- columnPinning: orderedColumns().pinning
151
+ columnSizing: sizingState()
88
152
  },
89
153
  onSortingChange: () => void 0,
90
- onColumnSizingChange: () => void 0,
91
- onColumnPinningChange: () => void 0
154
+ onColumnSizingChange: () => void 0
92
155
  });
93
156
  const table = constructTable(tableOptions());
157
+ const predicateFor = (except) => options.remote ? void 0 : rowPredicate(byId, options.columnFilters, options.quickFilter, resolved.filter((c) => c.hasAccessor && !hiddenOf(c)), except);
158
+ setRowPredicate(table, predicateFor());
94
159
  const rows = () => table.getRowModel().rows;
95
160
  const pinned = (side) => options.pinnedRows?.[side] ?? [];
161
+ const widthOf = (id) => table.getColumn(id)?.getSize() ?? 0;
162
+ const view = (def, colIndex, offset, pinEdge, width) => {
163
+ const sort = options.sorting.find((s) => s.id === def.id);
164
+ const pin = pinOf(def);
165
+ const resized = options.columnSizing[def.id] !== void 0;
166
+ return {
167
+ id: def.id,
168
+ kind: "data",
169
+ colIndex,
170
+ pin,
171
+ offset,
172
+ pinEdge,
173
+ hidden: colIndex === 0,
174
+ width,
175
+ flex: pin === void 0 && !resized ? def.flex : void 0,
176
+ auto: def.auto && !resized,
177
+ minWidth: def.minWidth,
178
+ maxWidth: def.maxWidth,
179
+ sortable: def.sortable,
180
+ resizable: def.resizable,
181
+ reorderable: def.reorderable,
182
+ pinnable: def.pinnable,
183
+ hideable: def.hideable,
184
+ filter: def.filter,
185
+ filtered: options.columnFilters?.[def.id] !== void 0,
186
+ align: def.align,
187
+ wrap: def.wrap,
188
+ sorted: sort ? sort.desc ? "desc" : "asc" : false,
189
+ header: def.header,
190
+ cell: def.cell,
191
+ hasAccessor: def.hasAccessor
192
+ };
193
+ };
96
194
  const buildViews = () => {
97
- const start = table.getStartLeafColumns();
98
- const center = table.getCenterLeafColumns();
99
- const end = table.getEndLeafColumns();
100
- const sorting = options.sorting;
101
- const view = (column, colIndex, offset, pinEdge) => {
102
- const def = byId.get(column.id);
103
- if (!def) throw new Error(`argus-table: unknown column '${column.id}'.`);
104
- const sort = sorting.find((s) => s.id === column.id);
105
- return {
106
- id: def.id,
107
- colIndex,
108
- pin: def.pin,
109
- offset,
110
- pinEdge,
111
- width: column.getSize(),
112
- flex: options.columnSizing[def.id] === void 0 ? def.flex : void 0,
113
- auto: def.auto && options.columnSizing[def.id] === void 0,
114
- minWidth: def.minWidth,
115
- maxWidth: def.maxWidth,
116
- sortable: def.sortable,
117
- resizable: def.resizable,
118
- reorderable: def.reorderable,
119
- align: def.align,
120
- sorted: sort ? sort.desc ? "desc" : "asc" : false,
121
- header: def.header,
122
- cell: def.cell,
123
- hasAccessor: def.hasAccessor
124
- };
195
+ const groups = {
196
+ start: [],
197
+ center: [],
198
+ end: []
125
199
  };
126
- return [
127
- ...start.map((c, i) => view(c, i + 1, c.getStart("start"), i === start.length - 1)),
128
- ...center.map((c, i) => view(c, start.length + i + 1, c.getStart("center"), false)),
129
- ...end.map((c, i) => view(c, start.length + center.length + i + 1, c.getAfter("end"), i === 0))
130
- ];
200
+ for (const id of orderState()) {
201
+ const def = byId.get(id);
202
+ if (def && !hiddenOf(def)) groups[pinOf(def) ?? "center"].push(def);
203
+ }
204
+ const { start, center, end } = groups;
205
+ const lead = options.selectionColumn ? 1 : 0;
206
+ if (lead && byId.has("--argus-selection")) throw new Error(`argus-table: the column id '${SELECTION_COLUMN_ID}' is reserved.`);
207
+ let x = lead * 40;
208
+ const list = start.map((def, i) => {
209
+ const width = widthOf(def.id);
210
+ const v = view(def, lead + i + 1, x, i === start.length - 1, width);
211
+ x += width;
212
+ return v;
213
+ });
214
+ x = 0;
215
+ for (const [i, def] of center.entries()) {
216
+ const width = widthOf(def.id);
217
+ list.push(view(def, lead + start.length + i + 1, x, false, width));
218
+ x += width;
219
+ }
220
+ const ends = [];
221
+ x = 0;
222
+ for (const [i, def] of [...end.entries()].reverse()) {
223
+ const width = widthOf(def.id);
224
+ ends.unshift(view(def, lead + start.length + center.length + i + 1, x, i === 0, width));
225
+ x += width;
226
+ }
227
+ list.push(...ends);
228
+ if (lead) list.unshift(selectionView(start.length === 0));
229
+ return list;
230
+ };
231
+ let allViews;
232
+ const buildAllViews = (shownViews) => {
233
+ const byShownId = new Map(shownViews.map((v) => [v.id, v]));
234
+ return orderState().flatMap((id) => {
235
+ const shownView = byShownId.get(id);
236
+ if (shownView) return [shownView];
237
+ const def = byId.get(id);
238
+ return def ? [view(def, 0, 0, false, widthOf(id))] : [];
239
+ });
131
240
  };
132
241
  return {
133
242
  update(next) {
@@ -136,28 +245,44 @@ function createTableModel(initial) {
136
245
  ...next
137
246
  };
138
247
  if (!Object.keys(next).some((key) => next[key] !== options[key])) return;
248
+ let reread = [];
139
249
  if (next.columns && next.columns !== options.columns) {
250
+ reread = changedAccessors(options.columns, next.columns);
140
251
  resolved = resolveColumns(next.columns);
141
252
  byId = new Map(resolved.map((c) => [c.id, c]));
142
253
  tanStackById = new Map(resolved.map((c) => [c.id, toTanStack(c)]));
143
254
  }
144
- if (merged.columns !== options.columns || merged.columnSizing !== options.columnSizing || merged.autoWidths !== options.autoWidths) sizing = void 0;
145
- if (merged.columns !== options.columns || merged.columnOrder !== options.columnOrder) order = void 0;
255
+ const pinningChanged = merged.columnPinning !== options.columnPinning;
256
+ if (merged.columns !== options.columns || merged.columnSizing !== options.columnSizing || merged.autoWidths !== options.autoWidths || pinningChanged) sizing = void 0;
257
+ if (merged.columns !== options.columns || merged.columnOrder !== options.columnOrder || pinningChanged) order = void 0;
258
+ const refilter = merged.columns !== options.columns || merged.columnFilters !== options.columnFilters || merged.quickFilter !== options.quickFilter || merged.columnVisibility !== options.columnVisibility || merged.remote !== options.remote;
146
259
  options = merged;
147
260
  views = void 0;
261
+ allViews = void 0;
262
+ if (refilter) setRowPredicate(table, predicateFor());
148
263
  table.setOptions((prev) => ({
149
264
  ...prev,
150
265
  ...tableOptions()
151
266
  }));
267
+ if (reread.length && !options.remote) {
268
+ for (const row of table.getCoreRowModel().rows) for (const id of reread) Reflect.deleteProperty(row._valuesCache, id);
269
+ valuesChanged(table);
270
+ }
152
271
  },
153
272
  get columns() {
154
273
  return views ??= buildViews();
155
274
  },
275
+ get allColumns() {
276
+ return allViews ??= buildAllViews(this.columns);
277
+ },
156
278
  get rowCount() {
157
279
  return options.remote?.rowCount ?? rows().length;
158
280
  },
281
+ get rowOrder() {
282
+ return options.remote ?? rows();
283
+ },
159
284
  get totalWidth() {
160
- return table.getTotalSize();
285
+ return this.columns.reduce((sum, column) => sum + column.width, 0);
161
286
  },
162
287
  rowAt(index) {
163
288
  if (options.remote) {
@@ -190,6 +315,10 @@ function createTableModel(initial) {
190
315
  };
191
316
  return indexById.map.get(rowId);
192
317
  },
318
+ selectableIds() {
319
+ if (options.remote) return options.remote.loadedIds();
320
+ return rows().map((r) => r.id);
321
+ },
193
322
  valueAt(index, columnId) {
194
323
  if (options.remote) {
195
324
  const entry = options.remote.entryAt(index);
@@ -242,10 +371,56 @@ function createTableModel(initial) {
242
371
  };
243
372
  },
244
373
  orderOf(base) {
245
- return base === void 0 ? orderState() : normalizeOrder(base, resolved);
374
+ return base === void 0 ? orderState() : normalizeOrder(base, orderable());
246
375
  },
247
376
  nextOrder(columnId, to, base) {
248
- return moveColumn(base ?? orderState(), resolved, columnId, to);
377
+ return moveColumn(base ?? orderState(), orderable(), columnId, to, shown);
378
+ },
379
+ nextPinning(columnId, pin, base = options.columnPinning) {
380
+ const column = byId.get(columnId);
381
+ if (!column?.pinnable || (pinOf(column, base) ?? false) === pin) return void 0;
382
+ return {
383
+ ...base,
384
+ [columnId]: pin
385
+ };
386
+ },
387
+ nextVisibility(columnId, hidden, base = options.columnVisibility) {
388
+ const column = byId.get(columnId);
389
+ if (!column || hiddenOf(column, base) === hidden) return void 0;
390
+ const othersShown = resolved.some((c) => c !== column && !hiddenOf(c, base));
391
+ if (hidden && (!column.hideable || !othersShown)) return void 0;
392
+ return {
393
+ ...base,
394
+ [columnId]: !hidden
395
+ };
396
+ },
397
+ nextFilters(columnId, filter, base = options.columnFilters ?? {}) {
398
+ const column = byId.get(columnId);
399
+ if (!column) return void 0;
400
+ const current = base[columnId];
401
+ if (filter === void 0) {
402
+ if (current === void 0) return void 0;
403
+ const next = { ...base };
404
+ Reflect.deleteProperty(next, columnId);
405
+ return next;
406
+ }
407
+ if (column.filter === void 0) return void 0;
408
+ if (current && JSON.stringify(current) === JSON.stringify(filter)) return void 0;
409
+ return {
410
+ ...base,
411
+ [columnId]: filter
412
+ };
413
+ },
414
+ filterValues(columnId, limit = 1e3) {
415
+ const column = byId.get(columnId);
416
+ if (!column) return void 0;
417
+ if (column.filterOptions) return {
418
+ values: [...column.filterOptions],
419
+ truncated: false
420
+ };
421
+ if (options.remote) return void 0;
422
+ const rows = table.getCoreRowModel().rows;
423
+ return distinctValues(rows, column, predicateFor(columnId), limit);
249
424
  },
250
425
  pinnedCount(side) {
251
426
  return pinned(side).length;
@@ -278,6 +453,6 @@ function createTableModel(initial) {
278
453
  }
279
454
  };
280
455
  }
281
- export { createTableModel };
456
+ export { SELECTION_COLUMN_ID, createTableModel };
282
457
 
283
458
  //# sourceMappingURL=create-table.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"create-table.js","names":[],"sources":["../../../../../core/src/table/create-table.ts"],"sourcesContent":["import {\n columnPinningFeature,\n columnSizingFeature,\n constructTable,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_basic,\n sortFn_datetime,\n sortFn_text,\n tableFeatures,\n type Column,\n type ColumnDef as TanStackColumnDef,\n type Row,\n type Table,\n type TableOptions,\n} from '@tanstack/table-core';\nimport { storeReactivityBindings } from '@tanstack/table-core/store-reactivity-bindings';\nimport { moveColumn, normalizeOrder } from '../columns/column-order.js';\nimport { resolveColumns, type ResolvedColumn } from '../columns/resolve-columns.js';\nimport { sortedRowModel } from './sorted-row-model.js';\nimport type {\n CellContext,\n ColumnAlign,\n ColumnDef,\n ColumnOrderState,\n ColumnPin,\n ColumnSizingState,\n PinnedRows,\n RowPin,\n SortState,\n} from '../types.js';\n\n// The TanStack adapter. Everything TanStack stays in this module: callers only see\n// the view types below, so TanStack can be upgraded or replaced without touching\n// `argus-table`'s public API.\n\nconst features = tableFeatures({\n // Vanilla (framework-free) reactivity; required by `constructTable`.\n coreReactivityFeature: storeReactivityBindings(),\n columnPinningFeature,\n columnSizingFeature,\n rowSortingFeature,\n // Our own: TanStack's is very slow in Firefox at scale (see sorted-row-model.ts).\n sortedRowModel: sortedRowModel(),\n // Registered by name so `sortFn: 'auto'` can pick one by value type.\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n basic: sortFn_basic,\n datetime: sortFn_datetime,\n text: sortFn_text,\n },\n});\ntype Features = typeof features;\ntype AnyRow = Record<string, unknown>;\n\n/** Sort direction of a column, or `false` when it isn't sorted. */\nexport type SortDirection = 'asc' | 'desc' | false;\n\n/** A column as the renderer sees it, in visual order: start-pinned, scrolling, end-pinned. */\nexport interface ColumnView<TData, TContent> {\n id: string;\n /** 1-based position in visual order, for `aria-colindex`. */\n colIndex: number;\n pin: ColumnPin | undefined;\n /**\n * Sticky inset in px: from the start edge for `'start'` columns, from the end edge\n * for `'end'` columns. For scrolling columns, the start within the scrolling area.\n */\n offset: number;\n /** `true` on the pinned column next to the scrolling area (one per pinned side). */\n pinEdge: boolean;\n /** Current width in px (a resized width wins over the column's own). */\n width: number;\n /** Share of free space, or `undefined` for a fixed width. A resized column stops flexing. */\n flex: number | undefined;\n /**\n * `true` for a `width: 'auto'` column that hasn't been resized: the table measures\n * its content and passes the width in as `autoWidths`.\n */\n auto: boolean;\n minWidth: number;\n maxWidth: number;\n sortable: boolean;\n resizable: boolean;\n reorderable: boolean;\n align: ColumnAlign;\n sorted: SortDirection;\n header: ColumnDef<TData, TContent>['header'];\n cell: ColumnDef<TData, TContent>['cell'];\n hasAccessor: boolean;\n}\n\n/** A row of the current (sorted) row model. */\nexport interface RowView<TData> {\n id: string;\n /** Index in the current row model, 0-based. */\n index: number;\n original: TData;\n}\n\n/**\n * Rows that live outside the model, loaded page by page (`dataSource`). The\n * source sorts them, so the model reads them as they are. `PageCache` implements it.\n */\nexport interface RemoteRows<TData> {\n readonly rowCount: number;\n /** The loaded row at an index, with its id; `undefined` while it isn't loaded. */\n entryAt(index: number): { id: string; row: TData } | undefined;\n /** The index of a loaded row's id, or `undefined`. */\n indexOf(rowId: string): number | undefined;\n}\n\nexport interface TableModelOptions<TData, TContent> {\n columns: readonly ColumnDef<TData, TContent>[];\n data: readonly TData[];\n /**\n * Remote rows. When set, rows come from here instead of `data`, and the model\n * doesn't sort them (the source does).\n */\n remote?: RemoteRows<TData> | undefined;\n /** Row id function. Default: the row's index in `data`, as a string. */\n getRowId: ((row: TData, index: number) => string) | undefined;\n /** Current sort state; its owner is the caller (see `controllable`). */\n sorting: SortState;\n /** Current resized widths; its owner is the caller. */\n columnSizing: ColumnSizingState;\n /**\n * Current column order; its owner is the caller. Each pin group follows it; an\n * empty array (the default) keeps the order of `columns`.\n */\n columnOrder?: ColumnOrderState | undefined;\n /**\n * Measured widths of `width: 'auto'` columns, in px by id. Clamped to the column's\n * bounds; a resized width wins. Ids of other columns are ignored.\n */\n autoWidths?: ColumnSizingState | undefined;\n /** Rows fixed above or below the body. They stay out of the row model: never sorted, not counted. */\n pinnedRows?: PinnedRows<TData> | undefined;\n}\n\nexport interface TableModel<TData, TContent> {\n /** Updates any subset of the options. Unchanged references are ignored. */\n update(options: Partial<TableModelOptions<TData, TContent>>): void;\n /** Columns in visual order. */\n readonly columns: readonly ColumnView<TData, TContent>[];\n /** Number of rows in the current row model. */\n readonly rowCount: number;\n /** Sum of all column widths in px (flex columns count their minimum). */\n readonly totalWidth: number;\n /** The row at an index of the current row model; `undefined` for a remote row not loaded yet. */\n rowAt(index: number): RowView<TData> | undefined;\n /** The index of a row id in the current row model (after sorting), or `undefined`. */\n indexOf(rowId: string): number | undefined;\n /** The value a column reads from the row at `index`. */\n valueAt(index: number, columnId: string): unknown;\n /** What a column's `cell` function receives for the row at `index`. */\n cellContext(index: number, columnId: string): CellContext<TData> | undefined;\n /**\n * The sort state that clicking this column's header would produce:\n * asc → desc → unsorted, one column at a time. `undefined` if it can't sort.\n */\n nextSorting(columnId: string): SortState | undefined;\n /**\n * The sizing state after setting a column to `width` px, clamped to its bounds.\n * `undefined` if the column can't be resized.\n */\n nextSizing(columnId: string, width: number): ColumnSizingState | undefined;\n /**\n * The full column order as the table shows it: start-pinned, scrolling and\n * end-pinned ids. `base` defaults to the current `columnOrder`.\n */\n orderOf(base?: readonly string[]): ColumnOrderState;\n /**\n * The order after moving a column to position `to` (0-based, in the whole order,\n * counted after the move), starting from `base` (default: the current order).\n * `undefined` if the column can't move, `to` is outside its pin group, or nothing changes.\n */\n nextOrder(columnId: string, to: number, base?: readonly string[]): ColumnOrderState | undefined;\n /** Number of rows pinned to a side. */\n pinnedCount(side: RowPin): number;\n /**\n * A pinned row, `index` counted within its side. Its id comes from `getRowId`,\n * else it is `'top-{index}'` or `'bottom-{index}'`, apart from the data rows' index ids.\n */\n pinnedRowAt(side: RowPin, index: number): RowView<TData> | undefined;\n /** The value a column reads from a pinned row. */\n pinnedValueAt(side: RowPin, index: number, columnId: string): unknown;\n /** What a column's `cell` function receives for a pinned row (with `pinned` set). */\n pinnedCellContext(side: RowPin, index: number, columnId: string): CellContext<TData> | undefined;\n}\n\nconst defaultRowId = (_row: unknown, index: number) => String(index);\n\nfunction toTanStack<TData, TContent>(\n column: ResolvedColumn<TData, TContent>,\n): TanStackColumnDef<Features, AnyRow> {\n return {\n id: column.id,\n accessorFn: column.getValue as (row: AnyRow, index: number) => unknown,\n size: column.width,\n minSize: column.minWidth,\n maxSize: column.maxWidth,\n enableSorting: column.sortable,\n sortUndefined: 'last',\n };\n}\n\n/**\n * Creates the table model over TanStack Table. It owns no state: sorting, sizing and order\n * come in through `update()`, and `nextSorting()`, `nextSizing()` and `nextOrder()` only propose\n * changes, so the caller decides (controlled or uncontrolled) whether to apply them.\n */\nexport function createTableModel<TData, TContent>(\n initial: TableModelOptions<TData, TContent>,\n): TableModel<TData, TContent> {\n let options = initial;\n let resolved = resolveColumns(options.columns);\n let byId = new Map(resolved.map((c) => [c.id, c]));\n // TanStack column defs by id, kept between updates that don't change `columns`.\n let tanStackById = new Map(resolved.map((c) => [c.id, toTanStack(c)]));\n let views: ColumnView<TData, TContent>[] | undefined;\n // TanStack's sizing state: measured auto widths under the resized ones. Kept stable\n // between updates that don't touch either.\n let sizing: ColumnSizingState | undefined;\n const sizingState = (): ColumnSizingState => {\n if (sizing) return sizing;\n const auto = options.autoWidths;\n if (!auto) return (sizing = options.columnSizing);\n const merged: ColumnSizingState = {};\n for (const column of resolved) {\n const px = auto[column.id];\n if (!column.auto || px === undefined || !Number.isFinite(px)) continue;\n merged[column.id] = Math.min(column.maxWidth, Math.max(column.minWidth, px));\n }\n return (sizing = { ...merged, ...options.columnSizing });\n };\n // The normalized order, kept stable between updates that touch neither columns nor order.\n let order: ColumnOrderState | undefined;\n const orderState = (): ColumnOrderState =>\n (order ??= normalizeOrder(options.columnOrder ?? [], resolved));\n const rowViews = new WeakMap<Row<Features, AnyRow>, RowView<TData>>();\n // Built lazily per row model (sorting or new data gives a new array).\n let indexById: { rows: readonly Row<Features, AnyRow>[]; map: Map<string, number> } | undefined;\n\n // The order reaches TanStack as the order of its column defs (the scrolling\n // columns follow it) and of the pinning arrays (the pinned ones do). Rebuilt only\n // when the order changes: a new columns array makes TanStack rebuild its columns,\n // though not its row models, which depend on data and sorting alone.\n let ordered:\n | {\n order: ColumnOrderState;\n columns: TanStackColumnDef<Features, AnyRow>[];\n pinning: { start: string[]; end: string[] };\n }\n | undefined;\n const orderedColumns = () => {\n const current = orderState();\n if (ordered?.order !== current) {\n const pinOf = (id: string) => byId.get(id)?.pin;\n ordered = {\n order: current,\n columns: current.flatMap((id) => tanStackById.get(id) ?? []),\n pinning: {\n start: current.filter((id) => pinOf(id) === 'start'),\n end: current.filter((id) => pinOf(id) === 'end'),\n },\n };\n }\n return ordered;\n };\n\n const tableOptions = (): TableOptions<Features, AnyRow> => ({\n features,\n columns: orderedColumns().columns,\n // Remote rows bypass TanStack's row models; it still handles columns and state.\n data: (options.remote ? [] : options.data) as AnyRow[],\n getRowId: (options.getRowId ?? defaultRowId) as (row: AnyRow, index: number) => string,\n state: {\n sorting: options.sorting,\n columnSizing: sizingState(),\n columnPinning: orderedColumns().pinning,\n },\n // State is owned by the caller; TanStack's own setters must not change it.\n onSortingChange: () => undefined,\n onColumnSizingChange: () => undefined,\n onColumnPinningChange: () => undefined,\n });\n\n const table: Table<Features, AnyRow> = constructTable(tableOptions());\n\n const rows = () => table.getRowModel().rows;\n const pinned = (side: RowPin): readonly TData[] => options.pinnedRows?.[side] ?? [];\n\n const buildViews = (): ColumnView<TData, TContent>[] => {\n const start = table.getStartLeafColumns();\n const center = table.getCenterLeafColumns();\n const end = table.getEndLeafColumns();\n const sorting = options.sorting;\n const view = (\n column: Column<Features, AnyRow>,\n colIndex: number,\n offset: number,\n pinEdge: boolean,\n ): ColumnView<TData, TContent> => {\n const def = byId.get(column.id);\n if (!def) throw new Error(`argus-table: unknown column '${column.id}'.`);\n const sort = sorting.find((s) => s.id === column.id);\n return {\n id: def.id,\n colIndex,\n pin: def.pin,\n offset,\n pinEdge,\n width: column.getSize(),\n flex: options.columnSizing[def.id] === undefined ? def.flex : undefined,\n auto: def.auto && options.columnSizing[def.id] === undefined,\n minWidth: def.minWidth,\n maxWidth: def.maxWidth,\n sortable: def.sortable,\n resizable: def.resizable,\n reorderable: def.reorderable,\n align: def.align,\n sorted: sort ? (sort.desc ? 'desc' : 'asc') : false,\n header: def.header,\n cell: def.cell,\n hasAccessor: def.hasAccessor,\n };\n };\n return [\n ...start.map((c, i) => view(c, i + 1, c.getStart('start'), i === start.length - 1)),\n ...center.map((c, i) => view(c, start.length + i + 1, c.getStart('center'), false)),\n ...end.map((c, i) =>\n view(c, start.length + center.length + i + 1, c.getAfter('end'), i === 0),\n ),\n ];\n };\n\n return {\n update(next) {\n const merged = { ...options, ...next };\n const changed = (Object.keys(next) as (keyof typeof next)[]).some(\n (key) => next[key] !== options[key],\n );\n if (!changed) return;\n if (next.columns && next.columns !== options.columns) {\n resolved = resolveColumns(next.columns);\n byId = new Map(resolved.map((c) => [c.id, c]));\n tanStackById = new Map(resolved.map((c) => [c.id, toTanStack(c)]));\n }\n if (\n merged.columns !== options.columns ||\n merged.columnSizing !== options.columnSizing ||\n merged.autoWidths !== options.autoWidths\n ) {\n sizing = undefined;\n }\n if (merged.columns !== options.columns || merged.columnOrder !== options.columnOrder) {\n order = undefined;\n }\n options = merged;\n views = undefined;\n table.setOptions((prev) => ({ ...prev, ...tableOptions() }));\n },\n\n get columns() {\n return (views ??= buildViews());\n },\n\n get rowCount() {\n return options.remote?.rowCount ?? rows().length;\n },\n\n get totalWidth() {\n return table.getTotalSize();\n },\n\n rowAt(index) {\n if (options.remote) {\n const entry = options.remote.entryAt(index);\n return entry && { id: entry.id, index, original: entry.row };\n }\n const row = rows()[index];\n if (!row) return undefined;\n let view = rowViews.get(row);\n if (view?.index !== index) {\n view = { id: row.id, index, original: row.original as TData };\n rowViews.set(row, view);\n }\n return view;\n },\n\n indexOf(rowId) {\n if (options.remote) return options.remote.indexOf(rowId);\n const current = rows();\n if (indexById?.rows !== current) {\n indexById = { rows: current, map: new Map(current.map((r, i) => [r.id, i])) };\n }\n return indexById.map.get(rowId);\n },\n\n valueAt(index, columnId) {\n if (options.remote) {\n const entry = options.remote.entryAt(index);\n return entry && byId.get(columnId)?.getValue(entry.row, index);\n }\n return rows()[index]?.getValue(columnId);\n },\n\n cellContext(index, columnId) {\n if (options.remote) {\n const entry = options.remote.entryAt(index);\n const column = byId.get(columnId);\n if (!entry || !column) return undefined;\n return {\n row: entry.row,\n rowId: entry.id,\n index,\n columnId,\n value: column.getValue(entry.row, index),\n };\n }\n const row = rows()[index];\n if (!row || !byId.has(columnId)) return undefined;\n return {\n row: row.original as TData,\n rowId: row.id,\n index,\n columnId,\n value: row.getValue(columnId),\n };\n },\n\n nextSorting(columnId) {\n if (byId.get(columnId)?.sortable !== true) return undefined;\n const current = options.sorting.find((s) => s.id === columnId);\n if (!current) return [{ id: columnId, desc: false }];\n return current.desc ? [] : [{ id: columnId, desc: true }];\n },\n\n nextSizing(columnId, width) {\n const column = byId.get(columnId);\n if (!column?.resizable || !Number.isFinite(width)) return undefined;\n const clamped = Math.round(Math.min(column.maxWidth, Math.max(column.minWidth, width)));\n return { ...options.columnSizing, [columnId]: clamped };\n },\n\n orderOf(base) {\n return base === undefined ? orderState() : normalizeOrder(base, resolved);\n },\n\n nextOrder(columnId, to, base) {\n return moveColumn(base ?? orderState(), resolved, columnId, to);\n },\n\n pinnedCount(side) {\n return pinned(side).length;\n },\n\n pinnedRowAt(side, index) {\n if (index < 0 || index >= pinned(side).length) return undefined;\n const row = pinned(side)[index] as TData;\n const id = options.getRowId ? options.getRowId(row, index) : `${side}-${String(index)}`;\n return { id, index, original: row };\n },\n\n pinnedValueAt(side, index, columnId) {\n if (index < 0 || index >= pinned(side).length) return undefined;\n return byId.get(columnId)?.getValue(pinned(side)[index] as TData, index);\n },\n\n pinnedCellContext(side, index, columnId) {\n const row = this.pinnedRowAt(side, index);\n const column = byId.get(columnId);\n if (!row || !column) return undefined;\n return {\n row: row.original,\n rowId: row.id,\n index,\n columnId,\n value: column.getValue(row.original, index),\n pinned: side,\n };\n },\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"create-table.js","names":[],"sources":["../../../../../core/src/table/create-table.ts"],"sourcesContent":["import {\n columnSizingFeature,\n constructTable,\n rowSortingFeature,\n sortFn_alphanumeric,\n sortFn_basic,\n sortFn_datetime,\n sortFn_text,\n tableFeatures,\n type ColumnDef as TanStackColumnDef,\n type Row,\n type Table,\n type TableOptions,\n} from '@tanstack/table-core';\nimport { storeReactivityBindings } from '@tanstack/table-core/store-reactivity-bindings';\nimport { moveColumn, normalizeOrder } from '../columns/column-order.js';\nimport { resolveColumns, type ResolvedColumn } from '../columns/resolve-columns.js';\nimport { distinctValues, rowPredicate } from '../filters/filter.js';\nimport { filteredRowModel, setRowPredicate } from './filtered-row-model.js';\nimport { sortedRowModel, valuesChanged } from './sorted-row-model.js';\nimport type {\n CellContext,\n ColumnAlign,\n ColumnDef,\n ColumnFilter,\n ColumnFilterState,\n ColumnOrderState,\n ColumnPin,\n ColumnPinningState,\n ColumnSizingState,\n ColumnVisibilityState,\n FilterKind,\n FilterValue,\n PinnedRows,\n RowPin,\n SortState,\n} from '../types.js';\n\n// The TanStack adapter. Everything TanStack stays in this module: callers only see\n// the view types below, so TanStack can be upgraded or replaced without touching\n// `argus-table`'s public API.\n\nconst features = tableFeatures({\n // Vanilla (framework-free) reactivity; required by `constructTable`.\n coreReactivityFeature: storeReactivityBindings(),\n // No pinning, ordering or visibility feature: the model groups, orders and hides\n // columns itself (see `buildViews`), so they cost no bundle size.\n columnSizingFeature,\n rowSortingFeature,\n // Our own filtering, without TanStack's filtering feature (see filtered-row-model.ts).\n // TanStack's types tie this slot to that feature; at runtime the core row models read it.\n ...({ filteredRowModel: filteredRowModel() } as object),\n // Our own: TanStack's is very slow in Firefox at scale (see sorted-row-model.ts).\n sortedRowModel: sortedRowModel(),\n // Registered by name so `sortFn: 'auto'` can pick one by value type.\n sortFns: {\n alphanumeric: sortFn_alphanumeric,\n basic: sortFn_basic,\n datetime: sortFn_datetime,\n text: sortFn_text,\n },\n});\ntype Features = typeof features;\ntype AnyRow = Record<string, unknown>;\n\n/** Sort direction of a column, or `false` when it isn't sorted. */\nexport type SortDirection = 'asc' | 'desc' | false;\n\n/**\n * Id of the selection column, the checkbox column the model adds first when\n * `selectionColumn` is set. Not a column of `columns`: it never appears in the\n * column order, sizing or events.\n */\nexport const SELECTION_COLUMN_ID = '--argus-selection';\n\n/** Width of the selection column in px. */\nexport const SELECTION_COLUMN_WIDTH = 40;\n\n/** A column as the renderer sees it, in visual order: start-pinned, scrolling, end-pinned. */\nexport interface ColumnView<TData, TContent> {\n id: string;\n /** `'data'` for a column of `columns`; `'selection'` for the checkbox column. */\n kind: 'data' | 'selection';\n /** 1-based position in visual order, for `aria-colindex`. `0` for a hidden column. */\n colIndex: number;\n /** The pin in effect: `columnPinning`'s, else the column's own. */\n pin: ColumnPin | undefined;\n /**\n * Sticky inset in px: from the start edge for `'start'` columns, from the end edge\n * for `'end'` columns. For scrolling columns, the start within the scrolling area.\n */\n offset: number;\n /** `true` on the pinned column next to the scrolling area (one per pinned side). */\n pinEdge: boolean;\n /**\n * `true` for a hidden column. Only `allColumns` lists hidden columns; `columns`\n * holds the ones the table shows.\n */\n hidden: boolean;\n /** Current width in px (a resized width wins over the column's own). */\n width: number;\n /** Share of free space, or `undefined` for a fixed width. A resized column stops flexing. */\n flex: number | undefined;\n /**\n * `true` for a `width: 'auto'` column that hasn't been resized: the table measures\n * its content and passes the width in as `autoWidths`.\n */\n auto: boolean;\n minWidth: number;\n maxWidth: number;\n sortable: boolean;\n resizable: boolean;\n reorderable: boolean;\n pinnable: boolean;\n hideable: boolean;\n /** The kind of filter users can set, or `undefined` when they can't filter the column. */\n filter: FilterKind | undefined;\n /** `true` when `columnFilters` has a filter for the column. */\n filtered: boolean;\n align: ColumnAlign;\n /** Whether the cell text wraps (`ColumnDef.wrap`). */\n wrap: boolean;\n sorted: SortDirection;\n header: ColumnDef<TData, TContent>['header'];\n cell: ColumnDef<TData, TContent>['cell'];\n hasAccessor: boolean;\n}\n\n/** A row of the current (filtered and sorted) row model. */\nexport interface RowView<TData> {\n id: string;\n /** Index in the current row model, 0-based. */\n index: number;\n original: TData;\n}\n\n/**\n * Rows that live outside the model, loaded page by page (`dataSource`). The\n * source sorts them, so the model reads them as they are. `PageCache` implements it.\n */\nexport interface RemoteRows<TData> {\n readonly rowCount: number;\n /** The loaded row at an index, with its id; `undefined` while it isn't loaded. */\n entryAt(index: number): { id: string; row: TData } | undefined;\n /** The index of a loaded row's id, or `undefined`. */\n indexOf(rowId: string): number | undefined;\n /** The ids of every loaded row, in row order. */\n loadedIds(): string[];\n}\n\nexport interface TableModelOptions<TData, TContent> {\n columns: readonly ColumnDef<TData, TContent>[];\n data: readonly TData[];\n /**\n * Remote rows. When set, rows come from here instead of `data`, and the model\n * doesn't sort them (the source does).\n */\n remote?: RemoteRows<TData> | undefined;\n /** Row id function. Default: the row's index in `data`, as a string. */\n getRowId: ((row: TData, index: number) => string) | undefined;\n /** Current sort state; its owner is the caller (see `controllable`). */\n sorting: SortState;\n /** Current resized widths; its owner is the caller. */\n columnSizing: ColumnSizingState;\n /**\n * Current column order; its owner is the caller. Each pin group follows it; an\n * empty array (the default) keeps the order of `columns`.\n */\n columnOrder?: ColumnOrderState | undefined;\n /** Pins set at runtime, over the columns' own `pin`; its owner is the caller. */\n columnPinning?: ColumnPinningState | undefined;\n /** Visibility set at runtime, over the columns' own `hidden`; its owner is the caller. */\n columnVisibility?: ColumnVisibilityState | undefined;\n /**\n * Column filters; its owner is the caller. Rows that fail one leave the row model.\n * Remote rows aren't filtered: the source does it.\n */\n columnFilters?: ColumnFilterState | undefined;\n /**\n * Words to find in the shown columns' values as text, ignoring case: a row stays\n * when each word is in one of its values. Remote rows aren't filtered.\n */\n quickFilter?: string | undefined;\n /**\n * Measured widths of `width: 'auto'` columns, in px by id. Clamped to the column's\n * bounds; a resized width wins. Ids of other columns are ignored.\n */\n autoWidths?: ColumnSizingState | undefined;\n /** Rows fixed above or below the body. They stay out of the row model: never sorted, not counted. */\n pinnedRows?: PinnedRows<TData> | undefined;\n /**\n * Adds the selection (checkbox) column first among the start-pinned columns. It\n * has the id `SELECTION_COLUMN_ID`, a fixed width, and no part in sorting,\n * sizing or the column order.\n */\n selectionColumn?: boolean | undefined;\n}\n\nexport interface TableModel<TData, TContent> {\n /** Updates any subset of the options. Unchanged references are ignored. */\n update(options: Partial<TableModelOptions<TData, TContent>>): void;\n /** The columns the table shows, in visual order. */\n readonly columns: readonly ColumnView<TData, TContent>[];\n /**\n * Every column of `columns`, hidden ones included (with `hidden: true` and\n * `colIndex: 0`), in the order of `orderOf()`. Not the selection column.\n */\n readonly allColumns: readonly ColumnView<TData, TContent>[];\n /** Number of rows in the current row model. */\n readonly rowCount: number;\n /**\n * Changes identity whenever the row at an index may have changed: new data, a\n * sort, a filter, a new remote source. Compare it by identity only.\n */\n readonly rowOrder: object;\n /** Sum of the shown columns' widths in px (flex columns count their minimum). */\n readonly totalWidth: number;\n /** The row at an index of the current row model; `undefined` for a remote row not loaded yet. */\n rowAt(index: number): RowView<TData> | undefined;\n /** The index of a row id in the current row model (after filtering and sorting), or `undefined`. */\n indexOf(rowId: string): number | undefined;\n /**\n * The ids of the rows that can be selected, in row order: every row of the row\n * model, or only the loaded ones for remote rows.\n */\n selectableIds(): string[];\n /** The value a column reads from the row at `index`. */\n valueAt(index: number, columnId: string): unknown;\n /** What a column's `cell` function receives for the row at `index`. */\n cellContext(index: number, columnId: string): CellContext<TData> | undefined;\n /**\n * The sort state that clicking this column's header would produce:\n * asc → desc → unsorted, one column at a time. `undefined` if it can't sort.\n */\n nextSorting(columnId: string): SortState | undefined;\n /**\n * The sizing state after setting a column to `width` px, clamped to its bounds.\n * `undefined` if the column can't be resized.\n */\n nextSizing(columnId: string, width: number): ColumnSizingState | undefined;\n /**\n * The full column order as the table shows it: start-pinned, scrolling and\n * end-pinned ids. `base` defaults to the current `columnOrder`.\n */\n orderOf(base?: readonly string[]): ColumnOrderState;\n /**\n * The order after moving a column to position `to` (0-based among the shown data\n * columns, in visual order, counted after the move; hidden columns keep their place),\n * starting from `base` (default: the current order). `undefined` if the column can't\n * move or is hidden, `to` is outside its pin group, or nothing changes.\n */\n nextOrder(columnId: string, to: number, base?: readonly string[]): ColumnOrderState | undefined;\n /**\n * The pinning state after pinning a column to a side, or unpinning it with `false`,\n * starting from `base` (default: the current `columnPinning`). `undefined` for an\n * unknown column, one with `pinnable: false`, or no change.\n */\n nextPinning(\n columnId: string,\n pin: ColumnPin | false,\n base?: ColumnPinningState,\n ): ColumnPinningState | undefined;\n /**\n * The visibility state after hiding or showing a column, starting from `base`\n * (default: the current `columnVisibility`). `undefined` for an unknown column,\n * hiding one with `hideable: false` or the last one shown, or no change.\n */\n nextVisibility(\n columnId: string,\n hidden: boolean,\n base?: ColumnVisibilityState,\n ): ColumnVisibilityState | undefined;\n /**\n * The filter state after setting a column's filter, or clearing it with `undefined`,\n * starting from `base` (default: the current `columnFilters`). `undefined` for an\n * unknown column, setting a filter on a column without `filter`, or no change.\n */\n nextFilters(\n columnId: string,\n filter: ColumnFilter | undefined,\n base?: ColumnFilterState,\n ): ColumnFilterState | undefined;\n /**\n * The values a `'set'` filter on the column offers: its `filterOptions`, else (not for\n * remote rows) the distinct values of the rows the other filters keep, sorted, at most\n * `limit` of them (`truncated` when there are more). `undefined` for an unknown column,\n * or remote rows without `filterOptions`.\n */\n filterValues(\n columnId: string,\n limit?: number,\n ): { values: FilterValue[]; truncated: boolean } | undefined;\n /** Number of rows pinned to a side. */\n pinnedCount(side: RowPin): number;\n /**\n * A pinned row, `index` counted within its side. Its id comes from `getRowId`,\n * else it is `'top-{index}'` or `'bottom-{index}'`, apart from the data rows' index ids.\n */\n pinnedRowAt(side: RowPin, index: number): RowView<TData> | undefined;\n /** The value a column reads from a pinned row. */\n pinnedValueAt(side: RowPin, index: number, columnId: string): unknown;\n /** What a column's `cell` function receives for a pinned row (with `pinned` set). */\n pinnedCellContext(side: RowPin, index: number, columnId: string): CellContext<TData> | undefined;\n}\n\nconst defaultRowId = (_row: unknown, index: number) => String(index);\n\n/**\n * Ids of the columns kept from `before` whose accessor changed: a new function,\n * or a different path. A new column has nothing cached and isn't listed.\n */\nfunction changedAccessors<TData, TContent>(\n before: readonly ColumnDef<TData, TContent>[],\n after: readonly ColumnDef<TData, TContent>[],\n): string[] {\n const old = new Map(before.map((c) => [c.id, c.accessor]));\n return after.filter((c) => old.has(c.id) && old.get(c.id) !== c.accessor).map((c) => c.id);\n}\n\n/** The selection column's view: first, pinned to the start, fixed, and inert to sorting, sizing and moves. */\nfunction selectionView<TData, TContent>(pinEdge: boolean): ColumnView<TData, TContent> {\n return {\n id: SELECTION_COLUMN_ID,\n kind: 'selection',\n colIndex: 1,\n pin: 'start',\n offset: 0,\n pinEdge,\n hidden: false,\n width: SELECTION_COLUMN_WIDTH,\n flex: undefined,\n auto: false,\n minWidth: SELECTION_COLUMN_WIDTH,\n maxWidth: SELECTION_COLUMN_WIDTH,\n sortable: false,\n resizable: false,\n reorderable: false,\n pinnable: false,\n hideable: false,\n filter: undefined,\n filtered: false,\n align: 'center',\n wrap: false,\n sorted: false,\n header: undefined,\n cell: undefined,\n hasAccessor: false,\n };\n}\n\nfunction toTanStack<TData, TContent>(\n column: ResolvedColumn<TData, TContent>,\n): TanStackColumnDef<Features, AnyRow> {\n return {\n id: column.id,\n accessorFn: column.getValue as (row: AnyRow, index: number) => unknown,\n size: column.width,\n minSize: column.minWidth,\n maxSize: column.maxWidth,\n enableSorting: column.sortable,\n sortUndefined: 'last',\n };\n}\n\n/**\n * Creates the table model over TanStack Table. It owns no state: sorting, sizing, order,\n * pinning and visibility come in through `update()`, and the `next*()` methods only propose\n * changes, so the caller decides (controlled or uncontrolled) whether to apply them.\n *\n * Hidden columns stay in TanStack, so their values still sort and read; only the\n * views leave them out. Pin groups, sticky offsets and the order are the model's own.\n */\nexport function createTableModel<TData, TContent>(\n initial: TableModelOptions<TData, TContent>,\n): TableModel<TData, TContent> {\n let options = initial;\n let resolved = resolveColumns(options.columns);\n let byId = new Map(resolved.map((c) => [c.id, c]));\n // TanStack column defs by id, kept between updates that don't change `columns`.\n let tanStackById = new Map(resolved.map((c) => [c.id, toTanStack(c)]));\n let views: ColumnView<TData, TContent>[] | undefined;\n // The pin and visibility in effect: the state's, else the column's own.\n const pinOf = (\n column: ResolvedColumn<TData, TContent>,\n pinning = options.columnPinning,\n ): ColumnPin | undefined => {\n const state = pinning?.[column.id];\n if (state === 'start' || state === 'end') return state;\n return state === false ? undefined : column.pin;\n };\n const hiddenOf = (\n column: ResolvedColumn<TData, TContent>,\n visibility = options.columnVisibility,\n ): boolean => {\n const state = visibility?.[column.id];\n return typeof state === 'boolean' ? !state : column.hidden;\n };\n const shown = (id: string) => {\n const column = byId.get(id);\n return column !== undefined && !hiddenOf(column);\n };\n // TanStack's sizing state: measured auto widths and the widths of pinned flex columns\n // under the resized ones. Kept stable between updates that don't touch them.\n let sizing: ColumnSizingState | undefined;\n const sizingState = (): ColumnSizingState => {\n if (sizing) return sizing;\n const auto = options.autoWidths;\n const merged: ColumnSizingState = {};\n let any = false;\n for (const column of resolved) {\n // A pinned column can't flex: it takes a fixed width for its sticky offsets.\n if (column.flex !== undefined && pinOf(column) !== undefined) {\n merged[column.id] = column.pinnedWidth;\n any = true;\n }\n const px = auto?.[column.id];\n if (!column.auto || px === undefined || !Number.isFinite(px)) continue;\n merged[column.id] = Math.min(column.maxWidth, Math.max(column.minWidth, px));\n any = true;\n }\n return (sizing = any ? { ...merged, ...options.columnSizing } : options.columnSizing);\n };\n // What ordering needs, with the pin in effect.\n const orderable = () =>\n resolved.map((c) => ({ id: c.id, pin: pinOf(c), reorderable: c.reorderable }));\n // The normalized order, kept stable between updates that touch neither columns,\n // order nor pinning.\n let order: ColumnOrderState | undefined;\n const orderState = (): ColumnOrderState =>\n (order ??= normalizeOrder(options.columnOrder ?? [], orderable()));\n const rowViews = new WeakMap<Row<Features, AnyRow>, RowView<TData>>();\n // Built lazily per row model (sorting or new data gives a new array).\n let indexById: { rows: readonly Row<Features, AnyRow>[]; map: Map<string, number> } | undefined;\n\n // TanStack gets its column defs in the order, hidden ones included. Rebuilt only when\n // the order changes: a new columns array makes TanStack rebuild its columns, though\n // not its row models, which depend on data and sorting alone.\n let ordered:\n { order: ColumnOrderState; columns: TanStackColumnDef<Features, AnyRow>[] } | undefined;\n const orderedColumns = () => {\n const current = orderState();\n if (ordered?.order !== current) {\n ordered = { order: current, columns: current.flatMap((id) => tanStackById.get(id) ?? []) };\n }\n return ordered;\n };\n\n const tableOptions = (): TableOptions<Features, AnyRow> => ({\n features,\n columns: orderedColumns().columns,\n // Remote rows bypass TanStack's row models; it still handles columns and state.\n data: (options.remote ? [] : options.data) as AnyRow[],\n getRowId: (options.getRowId ?? defaultRowId) as (row: AnyRow, index: number) => string,\n state: {\n sorting: options.sorting,\n columnSizing: sizingState(),\n },\n // State is owned by the caller; TanStack's own setters must not change it.\n onSortingChange: () => undefined,\n onColumnSizingChange: () => undefined,\n });\n\n const table: Table<Features, AnyRow> = constructTable(tableOptions());\n\n // The row test of the filters, the quick filter and the shown columns (which the quick\n // filter reads). Remote rows are filtered by their source.\n const predicateFor = (except?: string) =>\n options.remote\n ? undefined\n : rowPredicate(\n byId,\n options.columnFilters,\n options.quickFilter,\n resolved.filter((c) => c.hasAccessor && !hiddenOf(c)),\n except,\n );\n setRowPredicate(table, predicateFor());\n\n const rows = () => table.getRowModel().rows;\n const pinned = (side: RowPin): readonly TData[] => options.pinnedRows?.[side] ?? [];\n\n const widthOf = (id: string) => table.getColumn(id)?.getSize() ?? 0;\n const view = (\n def: ResolvedColumn<TData, TContent>,\n colIndex: number,\n offset: number,\n pinEdge: boolean,\n width: number,\n ): ColumnView<TData, TContent> => {\n const sort = options.sorting.find((s) => s.id === def.id);\n const pin = pinOf(def);\n const resized = options.columnSizing[def.id] !== undefined;\n return {\n id: def.id,\n kind: 'data',\n colIndex,\n pin,\n offset,\n pinEdge,\n hidden: colIndex === 0,\n width,\n flex: pin === undefined && !resized ? def.flex : undefined,\n auto: def.auto && !resized,\n minWidth: def.minWidth,\n maxWidth: def.maxWidth,\n sortable: def.sortable,\n resizable: def.resizable,\n reorderable: def.reorderable,\n pinnable: def.pinnable,\n hideable: def.hideable,\n filter: def.filter,\n filtered: options.columnFilters?.[def.id] !== undefined,\n align: def.align,\n wrap: def.wrap,\n sorted: sort ? (sort.desc ? 'desc' : 'asc') : false,\n header: def.header,\n cell: def.cell,\n hasAccessor: def.hasAccessor,\n };\n };\n\n const buildViews = (): ColumnView<TData, TContent>[] => {\n const groups: Record<ColumnPin | 'center', ResolvedColumn<TData, TContent>[]> = {\n start: [],\n center: [],\n end: [],\n };\n for (const id of orderState()) {\n const def = byId.get(id);\n if (def && !hiddenOf(def)) groups[pinOf(def) ?? 'center'].push(def);\n }\n const { start, center, end } = groups;\n // The selection column comes first: it shifts every column one place on, and\n // the other start-pinned columns its width further from the start edge.\n const lead = options.selectionColumn ? 1 : 0;\n if (lead && byId.has(SELECTION_COLUMN_ID)) {\n throw new Error(`argus-table: the column id '${SELECTION_COLUMN_ID}' is reserved.`);\n }\n // Offsets: start columns from the start edge (after the selection column), the\n // scrolling ones within the scrolling area, end columns from the end edge.\n let x = lead * SELECTION_COLUMN_WIDTH;\n const list = start.map((def, i) => {\n const width = widthOf(def.id);\n const v = view(def, lead + i + 1, x, i === start.length - 1, width);\n x += width;\n return v;\n });\n x = 0;\n for (const [i, def] of center.entries()) {\n const width = widthOf(def.id);\n list.push(view(def, lead + start.length + i + 1, x, false, width));\n x += width;\n }\n const ends: ColumnView<TData, TContent>[] = [];\n x = 0;\n for (const [i, def] of [...end.entries()].reverse()) {\n const width = widthOf(def.id);\n ends.unshift(view(def, lead + start.length + center.length + i + 1, x, i === 0, width));\n x += width;\n }\n list.push(...ends);\n if (lead) list.unshift(selectionView(start.length === 0));\n return list;\n };\n\n let allViews: ColumnView<TData, TContent>[] | undefined;\n const buildAllViews = (shownViews: readonly ColumnView<TData, TContent>[]) => {\n const byShownId = new Map(shownViews.map((v) => [v.id, v]));\n return orderState().flatMap((id) => {\n const shownView = byShownId.get(id);\n if (shownView) return [shownView];\n const def = byId.get(id);\n return def ? [view(def, 0, 0, false, widthOf(id))] : [];\n });\n };\n\n return {\n update(next) {\n const merged = { ...options, ...next };\n const changed = (Object.keys(next) as (keyof typeof next)[]).some(\n (key) => next[key] !== options[key],\n );\n if (!changed) return;\n let reread: string[] = [];\n if (next.columns && next.columns !== options.columns) {\n reread = changedAccessors(options.columns, next.columns);\n resolved = resolveColumns(next.columns);\n byId = new Map(resolved.map((c) => [c.id, c]));\n tanStackById = new Map(resolved.map((c) => [c.id, toTanStack(c)]));\n }\n const pinningChanged = merged.columnPinning !== options.columnPinning;\n if (\n merged.columns !== options.columns ||\n merged.columnSizing !== options.columnSizing ||\n merged.autoWidths !== options.autoWidths ||\n pinningChanged\n ) {\n sizing = undefined;\n }\n if (\n merged.columns !== options.columns ||\n merged.columnOrder !== options.columnOrder ||\n pinningChanged\n ) {\n order = undefined;\n }\n const refilter =\n merged.columns !== options.columns ||\n merged.columnFilters !== options.columnFilters ||\n merged.quickFilter !== options.quickFilter ||\n merged.columnVisibility !== options.columnVisibility ||\n merged.remote !== options.remote;\n options = merged;\n views = undefined;\n allViews = undefined;\n if (refilter) setRowPredicate(table, predicateFor());\n table.setOptions((prev) => ({ ...prev, ...tableOptions() }));\n if (reread.length && !options.remote) {\n // TanStack caches each value on its row by column id, and keeps rows\n // while the data is the same: drop the values of the columns that now\n // read differently, and sort again.\n for (const row of table.getCoreRowModel().rows) {\n for (const id of reread) Reflect.deleteProperty(row._valuesCache, id);\n }\n valuesChanged(table);\n }\n },\n\n get columns() {\n return (views ??= buildViews());\n },\n\n get allColumns() {\n return (allViews ??= buildAllViews(this.columns));\n },\n\n get rowCount() {\n return options.remote?.rowCount ?? rows().length;\n },\n get rowOrder() {\n return options.remote ?? rows();\n },\n\n get totalWidth() {\n return this.columns.reduce((sum, column) => sum + column.width, 0);\n },\n\n rowAt(index) {\n if (options.remote) {\n const entry = options.remote.entryAt(index);\n return entry && { id: entry.id, index, original: entry.row };\n }\n const row = rows()[index];\n if (!row) return undefined;\n let view = rowViews.get(row);\n if (view?.index !== index) {\n view = { id: row.id, index, original: row.original as TData };\n rowViews.set(row, view);\n }\n return view;\n },\n\n indexOf(rowId) {\n if (options.remote) return options.remote.indexOf(rowId);\n const current = rows();\n if (indexById?.rows !== current) {\n indexById = { rows: current, map: new Map(current.map((r, i) => [r.id, i])) };\n }\n return indexById.map.get(rowId);\n },\n\n selectableIds() {\n if (options.remote) return options.remote.loadedIds();\n return rows().map((r) => r.id);\n },\n\n valueAt(index, columnId) {\n if (options.remote) {\n const entry = options.remote.entryAt(index);\n return entry && byId.get(columnId)?.getValue(entry.row, index);\n }\n return rows()[index]?.getValue(columnId);\n },\n\n cellContext(index, columnId) {\n if (options.remote) {\n const entry = options.remote.entryAt(index);\n const column = byId.get(columnId);\n if (!entry || !column) return undefined;\n return {\n row: entry.row,\n rowId: entry.id,\n index,\n columnId,\n value: column.getValue(entry.row, index),\n };\n }\n const row = rows()[index];\n if (!row || !byId.has(columnId)) return undefined;\n return {\n row: row.original as TData,\n rowId: row.id,\n index,\n columnId,\n value: row.getValue(columnId),\n };\n },\n\n nextSorting(columnId) {\n if (byId.get(columnId)?.sortable !== true) return undefined;\n const current = options.sorting.find((s) => s.id === columnId);\n if (!current) return [{ id: columnId, desc: false }];\n return current.desc ? [] : [{ id: columnId, desc: true }];\n },\n\n nextSizing(columnId, width) {\n const column = byId.get(columnId);\n if (!column?.resizable || !Number.isFinite(width)) return undefined;\n const clamped = Math.round(Math.min(column.maxWidth, Math.max(column.minWidth, width)));\n return { ...options.columnSizing, [columnId]: clamped };\n },\n\n orderOf(base) {\n return base === undefined ? orderState() : normalizeOrder(base, orderable());\n },\n\n nextOrder(columnId, to, base) {\n return moveColumn(base ?? orderState(), orderable(), columnId, to, shown);\n },\n\n nextPinning(columnId, pin, base = options.columnPinning) {\n const column = byId.get(columnId);\n if (!column?.pinnable || (pinOf(column, base) ?? false) === pin) return undefined;\n return { ...base, [columnId]: pin };\n },\n\n nextVisibility(columnId, hidden, base = options.columnVisibility) {\n const column = byId.get(columnId);\n if (!column || hiddenOf(column, base) === hidden) return undefined;\n const othersShown = resolved.some((c) => c !== column && !hiddenOf(c, base));\n if (hidden && (!column.hideable || !othersShown)) return undefined;\n return { ...base, [columnId]: !hidden };\n },\n\n nextFilters(columnId, filter, base = options.columnFilters ?? {}) {\n const column = byId.get(columnId);\n if (!column) return undefined;\n const current = base[columnId];\n if (filter === undefined) {\n if (current === undefined) return undefined;\n const next = { ...base };\n Reflect.deleteProperty(next, columnId);\n return next;\n }\n if (column.filter === undefined) return undefined;\n if (current && JSON.stringify(current) === JSON.stringify(filter)) return undefined;\n return { ...base, [columnId]: filter };\n },\n\n filterValues(columnId, limit = 1000) {\n const column = byId.get(columnId);\n if (!column) return undefined;\n if (column.filterOptions) return { values: [...column.filterOptions], truncated: false };\n if (options.remote) return undefined;\n const rows = table.getCoreRowModel().rows as unknown as Iterable<{\n original: TData;\n index: number;\n }>;\n return distinctValues(rows, column, predicateFor(columnId), limit);\n },\n\n pinnedCount(side) {\n return pinned(side).length;\n },\n\n pinnedRowAt(side, index) {\n if (index < 0 || index >= pinned(side).length) return undefined;\n const row = pinned(side)[index] as TData;\n const id = options.getRowId ? options.getRowId(row, index) : `${side}-${String(index)}`;\n return { id, index, original: row };\n },\n\n pinnedValueAt(side, index, columnId) {\n if (index < 0 || index >= pinned(side).length) return undefined;\n return byId.get(columnId)?.getValue(pinned(side)[index] as TData, index);\n },\n\n pinnedCellContext(side, index, columnId) {\n const row = this.pinnedRowAt(side, index);\n const column = byId.get(columnId);\n if (!row || !column) return undefined;\n return {\n row: row.original,\n rowId: row.id,\n index,\n columnId,\n value: column.getValue(row.original, index),\n pinned: side,\n };\n },\n };\n}\n"],"mappings":"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"}