@tanstack/table-core 9.0.0-beta.69 → 9.0.0-beta.70

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 (89) hide show
  1. package/dist/core/cells/constructCell.d.ts +1 -1
  2. package/dist/core/cells/coreCellsFeature.types.d.ts +1 -1
  3. package/dist/core/cells/coreCellsFeature.utils.d.ts +1 -1
  4. package/dist/core/columns/constructColumn.d.ts +1 -1
  5. package/dist/core/columns/coreColumnsFeature.types.d.ts +1 -1
  6. package/dist/core/columns/coreColumnsFeature.utils.d.ts +1 -1
  7. package/dist/core/headers/buildHeaderGroups.d.ts +1 -1
  8. package/dist/core/headers/constructHeader.d.ts +1 -1
  9. package/dist/core/headers/coreHeadersFeature.types.d.ts +1 -1
  10. package/dist/core/headers/coreHeadersFeature.utils.d.ts +1 -1
  11. package/dist/core/row-models/coreRowModelsFeature.types.d.ts +4 -4
  12. package/dist/core/row-models/coreRowModelsFeature.utils.d.ts +1 -1
  13. package/dist/core/row-models/createCoreRowModel.d.ts +1 -1
  14. package/dist/core/rows/constructRow.d.ts +1 -1
  15. package/dist/core/rows/coreRowsFeature.types.d.ts +1 -1
  16. package/dist/core/rows/coreRowsFeature.utils.d.ts +1 -1
  17. package/dist/features/cell-selection/cellSelectionFeature.js +13 -2
  18. package/dist/features/cell-selection/cellSelectionFeature.types.d.ts +9 -0
  19. package/dist/features/cell-selection/cellSelectionFeature.utils.d.ts +20 -1
  20. package/dist/features/cell-selection/cellSelectionFeature.utils.js +139 -11
  21. package/dist/features/cell-selection/cellSelectionGeometry.js +32 -1
  22. package/dist/features/cell-spanning/cellSpanningFeature.d.ts +13 -0
  23. package/dist/features/cell-spanning/cellSpanningFeature.js +47 -0
  24. package/dist/features/cell-spanning/cellSpanningFeature.types.d.ts +150 -0
  25. package/dist/features/cell-spanning/cellSpanningFeature.utils.d.ts +74 -0
  26. package/dist/features/cell-spanning/cellSpanningFeature.utils.js +262 -0
  27. package/dist/features/column-faceting/columnFacetingFeature.utils.d.ts +1 -1
  28. package/dist/features/column-faceting/createFacetedRowModel.d.ts +1 -1
  29. package/dist/features/column-filtering/columnFilteringFeature.utils.d.ts +1 -1
  30. package/dist/features/column-filtering/createFilteredRowModel.d.ts +1 -1
  31. package/dist/features/column-grouping/columnGroupingFeature.utils.d.ts +2 -2
  32. package/dist/features/column-grouping/createGroupedRowModel.d.ts +1 -1
  33. package/dist/features/column-ordering/columnOrderingFeature.utils.d.ts +1 -1
  34. package/dist/features/column-pinning/columnPinningFeature.utils.d.ts +2 -2
  35. package/dist/features/column-resizing/columnResizingFeature.utils.d.ts +1 -1
  36. package/dist/features/column-sizing/columnSizingFeature.utils.d.ts +2 -2
  37. package/dist/features/column-visibility/columnVisibilityFeature.utils.d.ts +1 -1
  38. package/dist/features/global-filtering/globalFilteringFeature.utils.d.ts +1 -1
  39. package/dist/features/row-aggregation/rowAggregationFeature.types.d.ts +1 -1
  40. package/dist/features/row-expanding/createExpandedRowModel.d.ts +1 -1
  41. package/dist/features/row-expanding/rowExpandingFeature.utils.d.ts +1 -1
  42. package/dist/features/row-pagination/createPaginatedRowModel.d.ts +1 -1
  43. package/dist/features/row-pinning/rowPinningFeature.utils.d.ts +1 -1
  44. package/dist/features/row-selection/rowSelectionFeature.utils.d.ts +1 -1
  45. package/dist/features/row-sorting/createSortedRowModel.d.ts +1 -1
  46. package/dist/features/row-sorting/rowSortingFeature.utils.d.ts +1 -1
  47. package/dist/features/stockFeatures.d.ts +2 -0
  48. package/dist/features/stockFeatures.js +2 -0
  49. package/dist/index.d.ts +24 -22
  50. package/dist/index.js +2 -1
  51. package/dist/static-functions.d.ts +3 -2
  52. package/dist/static-functions.js +3 -2
  53. package/dist/types/Cell.d.ts +3 -1
  54. package/dist/types/Column.d.ts +7 -7
  55. package/dist/types/ColumnDef.d.ts +8 -6
  56. package/dist/types/Header.d.ts +1 -1
  57. package/dist/types/Row.d.ts +4 -4
  58. package/dist/types/RowModel.d.ts +4 -4
  59. package/dist/types/Table.d.ts +15 -13
  60. package/dist/types/TableFeatures.d.ts +4 -4
  61. package/dist/types/TableOptions.d.ts +16 -14
  62. package/dist/types/TableState.d.ts +8 -8
  63. package/dist/worker/createWorkerRowModel.d.ts +1 -1
  64. package/dist/worker/rebuildRowModel.d.ts +1 -1
  65. package/package.json +1 -1
  66. package/skills/aggregation/SKILL.md +1 -1
  67. package/skills/api-not-found/SKILL.md +1 -1
  68. package/skills/cell-selection/SKILL.md +1 -1
  69. package/skills/cell-spanning/SKILL.md +162 -0
  70. package/skills/client-vs-server/SKILL.md +1 -1
  71. package/skills/column-faceting/SKILL.md +1 -1
  72. package/skills/column-filtering/SKILL.md +1 -1
  73. package/skills/column-ordering/SKILL.md +1 -1
  74. package/skills/column-pinning/SKILL.md +1 -1
  75. package/skills/column-resizing/SKILL.md +1 -1
  76. package/skills/column-sizing/SKILL.md +1 -1
  77. package/skills/column-visibility/SKILL.md +1 -1
  78. package/skills/core/SKILL.md +1 -1
  79. package/skills/custom-features/SKILL.md +1 -1
  80. package/skills/expanding/SKILL.md +1 -1
  81. package/skills/global-filtering/SKILL.md +1 -1
  82. package/skills/grouping/SKILL.md +1 -1
  83. package/skills/migrate-v8-to-v9/SKILL.md +1 -1
  84. package/skills/pagination/SKILL.md +1 -1
  85. package/skills/row-pinning/SKILL.md +1 -1
  86. package/skills/row-selection/SKILL.md +1 -1
  87. package/skills/sorting/SKILL.md +1 -1
  88. package/skills/table-features/SKILL.md +1 -1
  89. package/skills/typescript/SKILL.md +1 -1
@@ -0,0 +1,150 @@
1
+ import { CellData, RowData } from "../../types/type-utils.js";
2
+ import { Column } from "../../types/Column.js";
3
+ import { Row } from "../../types/Row.js";
4
+ import { Table } from "../../types/Table.js";
5
+ import { TableFeatures } from "../../types/TableFeatures.js";
6
+ //#region src/features/cell-spanning/cellSpanningFeature.types.d.ts
7
+ /**
8
+ * The table's cell span index for the rows that are currently rendered.
9
+ *
10
+ * Cell APIs read this; it is exposed for devtools and for virtualizers that
11
+ * need to know where a run's anchor sits relative to the rendered window.
12
+ */
13
+ interface CellSpanIndex<in out TFeatures extends TableFeatures, in out TData extends RowData> {
14
+ /**
15
+ * Column spans per render-order row position, indexed by render-order column
16
+ * position. Holes are the common case: only rows that declared a column span
17
+ * get an array. In a stored array, the spanning cell holds its span and the
18
+ * cells it covers hold `0`; every other cell holds `1`.
19
+ */
20
+ colSpans: Array<Int32Array | undefined>;
21
+ /**
22
+ * Render-order index for every visible column id. Hidden columns are absent.
23
+ */
24
+ columnIndexes: Record<string, number>;
25
+ /**
26
+ * Row spans per column id, indexed by render-order row position. Only columns
27
+ * that produced at least one run longer than one row appear here; a missing
28
+ * column means every cell in it spans exactly one row. In a stored array, the
29
+ * run's anchor row holds the run length and the rows it covers hold `0`.
30
+ */
31
+ rowSpans: Record<string, Int32Array>;
32
+ /**
33
+ * The exact ordered rows this index was built from, in render order:
34
+ * top-pinned rows, then the (paginated) center rows, then bottom-pinned
35
+ * rows. Cell reads compare against this to reject stale row positions.
36
+ */
37
+ rows: ReadonlyArray<Row<TFeatures, TData>>;
38
+ }
39
+ /**
40
+ * Context passed to a `spanRows` predicate for each candidate row.
41
+ *
42
+ * The run is anchored: `anchorRow` is the row whose cell will render the
43
+ * merged content, and every later row in the run is tested against it, which
44
+ * keeps runs transitive by construction. `previousRow` is provided for
45
+ * predicates that want a step-wise comparison instead.
46
+ */
47
+ interface RowSpanContext<in out TFeatures extends TableFeatures, in out TData extends RowData, TValue extends CellData = CellData> {
48
+ anchorRow: Row<TFeatures, TData>;
49
+ anchorValue: TValue;
50
+ column: Column<TFeatures, TData, TValue>;
51
+ previousRow: Row<TFeatures, TData>;
52
+ row: Row<TFeatures, TData>;
53
+ table: Table<TFeatures, TData>;
54
+ value: TValue;
55
+ }
56
+ /**
57
+ * Context passed to a `spanColumns` resolver for each rendered row.
58
+ */
59
+ interface ColSpanContext<in out TFeatures extends TableFeatures, in out TData extends RowData, TValue extends CellData = CellData> {
60
+ column: Column<TFeatures, TData, TValue>;
61
+ row: Row<TFeatures, TData>;
62
+ table: Table<TFeatures, TData>;
63
+ }
64
+ interface ColumnDef_CellSpanning<in out TFeatures extends TableFeatures, in out TData extends RowData, TValue extends CellData = CellData> {
65
+ /**
66
+ * Turns this column off for cell spanning even when the table allows it.
67
+ * Defaults to `true`.
68
+ */
69
+ enableCellSpanning?: boolean;
70
+ /**
71
+ * Makes this column's cell span the given number of columns per row,
72
+ * starting at itself and counted in the order columns actually render.
73
+ *
74
+ * Return `1` or less for no span. Larger values are clamped to the end of
75
+ * the cell's pinned region, so a span can never cross the start-pinned,
76
+ * center, or end-pinned boundary; pass `Infinity` for "the rest of my
77
+ * region". Hidden columns are not counted.
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * { accessorKey: 'label', spanColumns: ({ row }) => row.original.isSummary ? Infinity : 1 }
82
+ * ```
83
+ */
84
+ spanColumns?: number | ((context: ColSpanContext<TFeatures, TData, TValue>) => number);
85
+ /**
86
+ * Merges adjacent rows in this column into a single vertically spanning
87
+ * cell.
88
+ *
89
+ * `true` merges rows whose values for this column are the same value
90
+ * (`Object.is`). Nullish values never merge under the default comparison.
91
+ *
92
+ * A predicate replaces the comparison entirely and decides whether `row`
93
+ * joins the run anchored at `anchorRow`; it may merge nullish values. It is
94
+ * called once per candidate row each time the span index rebuilds, and each
95
+ * call allocates one context object, so keep it cheap.
96
+ *
97
+ * Spans are always recomputed from the rows that are actually rendered, so
98
+ * sorting, filtering, and paging only change which rows are adjacent. Runs
99
+ * never cross a page boundary, a pinned-row section boundary, a change of
100
+ * position in the row tree, or a grouped row. Ignored while this column is
101
+ * grouped.
102
+ *
103
+ * @example
104
+ * ```ts
105
+ * { accessorKey: 'department', spanRows: true }
106
+ * ```
107
+ */
108
+ spanRows?: boolean | ((context: RowSpanContext<TFeatures, TData, TValue>) => boolean);
109
+ }
110
+ interface TableOptions_CellSpanning {
111
+ /**
112
+ * Allows cells to span rows or columns. When `false` every cell reports a
113
+ * span of `1` and the span index is never built. Defaults to `true`.
114
+ */
115
+ enableCellSpanning?: boolean;
116
+ }
117
+ interface Cell_CellSpanning {
118
+ /**
119
+ * Number of columns this cell spans when rendered. `1` when it does not
120
+ * span, and `0` when another cell's column span covers it.
121
+ *
122
+ * Never render a `0` as a `colSpan` attribute; skip the cell instead. See
123
+ * `getIsCovered`.
124
+ */
125
+ getColSpan: () => number;
126
+ /**
127
+ * Whether another cell's span covers this cell. Skip rendering covered
128
+ * cells; the cell that covers them carries the content and the span
129
+ * attributes.
130
+ */
131
+ getIsCovered: () => boolean;
132
+ /**
133
+ * Number of rows this cell spans when rendered. `1` when it does not span,
134
+ * and `0` when a spanning cell above it covers it, matching the
135
+ * `header.rowSpan` convention.
136
+ *
137
+ * Never render a `0` as a `rowSpan` attribute: in HTML, `rowspan="0"` means
138
+ * "span to the end of the row group", which merges the cell down the entire
139
+ * table section. Skip the cell instead. See `getIsCovered`.
140
+ */
141
+ getRowSpan: () => number;
142
+ }
143
+ interface Table_CellSpanning<in out TFeatures extends TableFeatures, in out TData extends RowData> {
144
+ /**
145
+ * The memoized span index for the rows that are currently rendered.
146
+ */
147
+ getCellSpanIndex: () => CellSpanIndex<TFeatures, TData>;
148
+ }
149
+ //#endregion
150
+ export { CellSpanIndex, Cell_CellSpanning, ColSpanContext, ColumnDef_CellSpanning, RowSpanContext, TableOptions_CellSpanning, Table_CellSpanning };
@@ -0,0 +1,74 @@
1
+ import { CellData, RowData } from "../../types/type-utils.js";
2
+ import { Column } from "../../types/Column.js";
3
+ import { Table } from "../../types/Table.js";
4
+ import { CellSpanIndex } from "./cellSpanningFeature.types.js";
5
+ import { Cell } from "../../types/Cell.js";
6
+ import { TableFeatures } from "../../types/TableFeatures.js";
7
+ //#region src/features/cell-spanning/cellSpanningFeature.utils.d.ts
8
+ /**
9
+ * Checks whether this column takes part in cell spanning.
10
+ *
11
+ * A column def opting out with `enableCellSpanning: false` wins over the table
12
+ * option, matching how the other per-column enable flags resolve.
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * const canSpan = column_getCanSpan(column)
17
+ * ```
18
+ */
19
+ declare function column_getCanSpan<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData = CellData>(column: Column<TFeatures, TData, TValue>): boolean;
20
+ /**
21
+ * Builds the table's cell span index for the rows that are currently rendered.
22
+ *
23
+ * Spans are always derived from scratch from the final row model, so sorting,
24
+ * filtering, pagination, expansion, and row pinning only change adjacency and
25
+ * the index follows. Nothing is persisted and there is nothing to configure.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * const spanIndex = table_getCellSpanIndex(table)
30
+ * ```
31
+ */
32
+ declare function table_getCellSpanIndex<TFeatures extends TableFeatures, TData extends RowData>(table: Table<TFeatures, TData>): CellSpanIndex<TFeatures, TData>;
33
+ /**
34
+ * Returns how many rows this cell spans.
35
+ *
36
+ * `1` when it does not span, and `0` when a spanning cell above it covers it,
37
+ * matching the `header.rowSpan` convention where `0` means "skip this cell".
38
+ *
39
+ * Deliberately not memoized: a per-cell memo would allocate a closure and a
40
+ * dependency array for every cell, costing more than the two lookups this
41
+ * performs against the table-level span index.
42
+ *
43
+ * @example
44
+ * ```ts
45
+ * const rowSpan = cell_getRowSpan(cell)
46
+ * ```
47
+ */
48
+ declare function cell_getRowSpan<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData = CellData>(cell: Cell<TFeatures, TData, TValue>): number;
49
+ /**
50
+ * Returns how many columns this cell spans.
51
+ *
52
+ * `1` when it does not span, and `0` when another cell's column span covers
53
+ * it.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * const colSpan = cell_getColSpan(cell)
58
+ * ```
59
+ */
60
+ declare function cell_getColSpan<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData = CellData>(cell: Cell<TFeatures, TData, TValue>): number;
61
+ /**
62
+ * Checks whether another cell's span covers this cell.
63
+ *
64
+ * Covered cells must not be rendered; the cell that covers them carries the
65
+ * content and the span attributes.
66
+ *
67
+ * @example
68
+ * ```ts
69
+ * const isCovered = cell_getIsCovered(cell)
70
+ * ```
71
+ */
72
+ declare function cell_getIsCovered<TFeatures extends TableFeatures, TData extends RowData, TValue extends CellData = CellData>(cell: Cell<TFeatures, TData, TValue>): boolean;
73
+ //#endregion
74
+ export { cell_getColSpan, cell_getIsCovered, cell_getRowSpan, column_getCanSpan, table_getCellSpanIndex };
@@ -0,0 +1,262 @@
1
+ import { callMemoOrStaticFn, isFunction, makeObjectMap } from "../../utils.js";
2
+
3
+ //#region src/features/cell-spanning/cellSpanningFeature.utils.ts
4
+ const EMPTY_ROW_SPANS = makeObjectMap();
5
+ const EMPTY_COLUMN_INDEXES = makeObjectMap();
6
+ const EMPTY_COL_SPANS = [];
7
+ const NO_SECTION_STARTS = [];
8
+ /**
9
+ * Resolves the rows in the order a renderer actually draws them, plus the
10
+ * positions at which a new visual section begins.
11
+ *
12
+ * Without row pinning this is the final row model itself, returned by
13
+ * reference so the common path allocates nothing. With row pinning it is the
14
+ * concatenation the three-list renderer walks: `getTopRows()`,
15
+ * `getCenterRows()`, `getBottomRows()`. `getCenterRows()` filters the row
16
+ * model by the pinned ids, so no row appears in two sections and every row
17
+ * gets exactly one position; with `keepPinnedRows` a pinned row that filtering
18
+ * removed from the row model still appears exactly once, in its pinned
19
+ * section.
20
+ *
21
+ * The pinning reads are optional-chained so the feature stays correct when
22
+ * `rowPinningFeature` is not registered.
23
+ */
24
+ function getRenderedRows(table) {
25
+ const rows = table.getRowModel().rows;
26
+ const rowPinning = table.atoms.rowPinning?.get();
27
+ if (!rowPinning || !rowPinning.top.length && !rowPinning.bottom.length) return {
28
+ rows,
29
+ sectionStarts: NO_SECTION_STARTS
30
+ };
31
+ const pinnedTable = table;
32
+ const top = pinnedTable.getTopRows?.() ?? [];
33
+ const center = pinnedTable.getCenterRows?.() ?? rows;
34
+ const bottom = pinnedTable.getBottomRows?.() ?? [];
35
+ return {
36
+ rows: [
37
+ ...top,
38
+ ...center,
39
+ ...bottom
40
+ ],
41
+ sectionStarts: [top.length, top.length + center.length]
42
+ };
43
+ }
44
+ /**
45
+ * Resolves the visible columns in the order cells render, plus the two
46
+ * boundaries between the start-pinned, center, and end-pinned regions.
47
+ *
48
+ * Read off a rendered row's visible cells rather than re-derived, so the
49
+ * ordering is the renderer's own by construction. `getVisibleCells` only
50
+ * exists when `columnVisibilityFeature` is registered; without it renderers
51
+ * walk `row.getAllCells()`, whose order is `table.getAllLeafColumns()`.
52
+ */
53
+ function getRenderedColumns(table, firstRow) {
54
+ const cells = firstRow.getVisibleCells?.() ?? firstRow.getAllCells();
55
+ const columns = new Array(cells.length);
56
+ for (let i = 0; i < cells.length; i++) columns[i] = cells[i].column;
57
+ const pinning = table.atoms.columnPinning?.get();
58
+ let centerStart = 0;
59
+ let centerEnd = columns.length;
60
+ if (pinning) {
61
+ while (centerStart < centerEnd && pinning.start.includes(columns[centerStart].id)) centerStart++;
62
+ while (centerEnd > centerStart && pinning.end.includes(columns[centerEnd - 1].id)) centerEnd--;
63
+ }
64
+ return {
65
+ columns,
66
+ centerStart,
67
+ centerEnd
68
+ };
69
+ }
70
+ /**
71
+ * Checks whether this column takes part in cell spanning.
72
+ *
73
+ * A column def opting out with `enableCellSpanning: false` wins over the table
74
+ * option, matching how the other per-column enable flags resolve.
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * const canSpan = column_getCanSpan(column)
79
+ * ```
80
+ */
81
+ function column_getCanSpan(column) {
82
+ if (column.columnDef.enableCellSpanning === false) return false;
83
+ return column.table.options.enableCellSpanning ?? true;
84
+ }
85
+ /**
86
+ * Builds the table's cell span index for the rows that are currently rendered.
87
+ *
88
+ * Spans are always derived from scratch from the final row model, so sorting,
89
+ * filtering, pagination, expansion, and row pinning only change adjacency and
90
+ * the index follows. Nothing is persisted and there is nothing to configure.
91
+ *
92
+ * @example
93
+ * ```ts
94
+ * const spanIndex = table_getCellSpanIndex(table)
95
+ * ```
96
+ */
97
+ function table_getCellSpanIndex(table) {
98
+ const { rows, sectionStarts } = getRenderedRows(table);
99
+ const rowCount = rows.length;
100
+ const empty = {
101
+ colSpans: EMPTY_COL_SPANS,
102
+ columnIndexes: EMPTY_COLUMN_INDEXES,
103
+ rowSpans: EMPTY_ROW_SPANS,
104
+ rows
105
+ };
106
+ if (!rowCount || table.options.enableCellSpanning === false) return empty;
107
+ const { columns, centerStart, centerEnd } = getRenderedColumns(table, rows[0]);
108
+ const columnCount = columns.length;
109
+ if (!columnCount) return empty;
110
+ const columnIndexes = makeObjectMap();
111
+ for (let c = 0; c < columnCount; c++) columnIndexes[columns[c].id] = c;
112
+ const breaks = new Uint8Array(rowCount);
113
+ for (let s = 0; s < sectionStarts.length; s++) {
114
+ const start = sectionStarts[s];
115
+ if (start < rowCount) breaks[start] = 1;
116
+ }
117
+ for (let r = 0; r < rowCount; r++) {
118
+ const row = rows[r];
119
+ row._cellSpanRowIndex = r;
120
+ const prev = r > 0 ? rows[r - 1] : void 0;
121
+ if (prev && (row.depth !== prev.depth || row.parentId !== prev.parentId) || row.getIsGrouped?.() === true) breaks[r] = 1;
122
+ }
123
+ const colSpans = [];
124
+ let anyColSpan = false;
125
+ for (let c = 0; c < columnCount; c++) {
126
+ const column = columns[c];
127
+ const spanColumns = column.columnDef.spanColumns;
128
+ if (spanColumns === void 0 || !column_getCanSpan(column)) continue;
129
+ const regionEnd = c < centerStart ? centerStart : c < centerEnd ? centerEnd : columnCount;
130
+ for (let r = 0; r < rowCount; r++) {
131
+ const existing = colSpans[r];
132
+ if (existing && existing[c] === 0) continue;
133
+ const requested = isFunction(spanColumns) ? spanColumns({
134
+ column,
135
+ row: rows[r],
136
+ table
137
+ }) : spanColumns;
138
+ if (!(requested > 1)) continue;
139
+ const span = Math.min(requested, regionEnd - c);
140
+ if (span < 2) continue;
141
+ const target = existing ?? (colSpans[r] = new Int32Array(columnCount).fill(1));
142
+ target[c] = span;
143
+ for (let k = c + 1; k < c + span; k++) target[k] = 0;
144
+ anyColSpan = true;
145
+ }
146
+ }
147
+ const rowSpans = makeObjectMap();
148
+ for (let c = 0; c < columnCount; c++) {
149
+ const column = columns[c];
150
+ const spanRows = column.columnDef.spanRows;
151
+ if (!spanRows || !column_getCanSpan(column)) continue;
152
+ if (column.getIsGrouped?.() === true) continue;
153
+ const columnId = column.id;
154
+ const predicate = isFunction(spanRows) ? spanRows : void 0;
155
+ const spans = new Int32Array(rowCount).fill(1);
156
+ let anyRun = false;
157
+ let anchorIndex = -1;
158
+ let anchorValue;
159
+ let anchorColSpan = 1;
160
+ for (let r = 0; r < rowCount; r++) {
161
+ const row = rows[r];
162
+ const rowColSpans = anyColSpan ? colSpans[r] : void 0;
163
+ const cellColSpan = rowColSpans ? rowColSpans[c] : 1;
164
+ if (cellColSpan === 0) {
165
+ anchorIndex = -1;
166
+ continue;
167
+ }
168
+ const value = row.getValue(columnId);
169
+ if (anchorIndex !== -1 && !breaks[r] && cellColSpan === anchorColSpan && (predicate ? predicate({
170
+ anchorRow: rows[anchorIndex],
171
+ anchorValue,
172
+ column,
173
+ previousRow: rows[r - 1],
174
+ row,
175
+ table,
176
+ value
177
+ }) : value != null && Object.is(value, anchorValue))) {
178
+ spans[r] = 0;
179
+ spans[anchorIndex] = spans[anchorIndex] + 1;
180
+ anyRun = true;
181
+ continue;
182
+ }
183
+ anchorIndex = r;
184
+ anchorValue = value;
185
+ anchorColSpan = cellColSpan;
186
+ }
187
+ if (anyRun) rowSpans[columnId] = spans;
188
+ }
189
+ return {
190
+ colSpans,
191
+ columnIndexes,
192
+ rowSpans,
193
+ rows
194
+ };
195
+ }
196
+ function resolveRowIndex(index, cell) {
197
+ const rowIndex = cell.row._cellSpanRowIndex;
198
+ if (rowIndex === void 0 || index.rows[rowIndex] !== cell.row) return -1;
199
+ return rowIndex;
200
+ }
201
+ /**
202
+ * Returns how many rows this cell spans.
203
+ *
204
+ * `1` when it does not span, and `0` when a spanning cell above it covers it,
205
+ * matching the `header.rowSpan` convention where `0` means "skip this cell".
206
+ *
207
+ * Deliberately not memoized: a per-cell memo would allocate a closure and a
208
+ * dependency array for every cell, costing more than the two lookups this
209
+ * performs against the table-level span index.
210
+ *
211
+ * @example
212
+ * ```ts
213
+ * const rowSpan = cell_getRowSpan(cell)
214
+ * ```
215
+ */
216
+ function cell_getRowSpan(cell) {
217
+ const table = cell.row.table;
218
+ const index = callMemoOrStaticFn(table, "getCellSpanIndex", table_getCellSpanIndex);
219
+ const spans = index.rowSpans[cell.column.id];
220
+ if (!spans) return 1;
221
+ const rowIndex = resolveRowIndex(index, cell);
222
+ if (rowIndex === -1) return 1;
223
+ return spans[rowIndex];
224
+ }
225
+ /**
226
+ * Returns how many columns this cell spans.
227
+ *
228
+ * `1` when it does not span, and `0` when another cell's column span covers
229
+ * it.
230
+ *
231
+ * @example
232
+ * ```ts
233
+ * const colSpan = cell_getColSpan(cell)
234
+ * ```
235
+ */
236
+ function cell_getColSpan(cell) {
237
+ const table = cell.row.table;
238
+ const index = callMemoOrStaticFn(table, "getCellSpanIndex", table_getCellSpanIndex);
239
+ const rowIndex = resolveRowIndex(index, cell);
240
+ if (rowIndex === -1) return 1;
241
+ const spans = index.colSpans[rowIndex];
242
+ if (!spans) return 1;
243
+ const columnIndex = index.columnIndexes[cell.column.id];
244
+ return columnIndex === void 0 ? 1 : spans[columnIndex];
245
+ }
246
+ /**
247
+ * Checks whether another cell's span covers this cell.
248
+ *
249
+ * Covered cells must not be rendered; the cell that covers them carries the
250
+ * content and the span attributes.
251
+ *
252
+ * @example
253
+ * ```ts
254
+ * const isCovered = cell_getIsCovered(cell)
255
+ * ```
256
+ */
257
+ function cell_getIsCovered(cell) {
258
+ return cell_getRowSpan(cell) === 0 || cell_getColSpan(cell) === 0;
259
+ }
260
+
261
+ //#endregion
262
+ export { cell_getColSpan, cell_getIsCovered, cell_getRowSpan, column_getCanSpan, table_getCellSpanIndex };
@@ -1,7 +1,7 @@
1
1
  import { CellData, RowData } from "../../types/type-utils.js";
2
- import { Table } from "../../types/Table.js";
3
2
  import { Column } from "../../types/Column.js";
4
3
  import { RowModel } from "../../core/row-models/coreRowModelsFeature.types.js";
4
+ import { Table } from "../../types/Table.js";
5
5
  import { TableFeatures } from "../../types/TableFeatures.js";
6
6
  //#region src/features/column-faceting/columnFacetingFeature.utils.d.ts
7
7
  /**
@@ -1,6 +1,6 @@
1
1
  import { RowData } from "../../types/type-utils.js";
2
- import { Table } from "../../types/Table.js";
3
2
  import { RowModel } from "../../core/row-models/coreRowModelsFeature.types.js";
3
+ import { Table } from "../../types/Table.js";
4
4
  import { TableFeatures } from "../../types/TableFeatures.js";
5
5
  //#region src/features/column-faceting/createFacetedRowModel.d.ts
6
6
  /**
@@ -1,7 +1,7 @@
1
1
  import { CellData, RowData, Updater } from "../../types/type-utils.js";
2
- import { Table } from "../../types/Table.js";
3
2
  import { Column } from "../../types/Column.js";
4
3
  import { ColumnFiltersState, FilterFn } from "./columnFilteringFeature.types.js";
4
+ import { Table } from "../../types/Table.js";
5
5
  import { TableFeatures } from "../../types/TableFeatures.js";
6
6
  //#region src/features/column-filtering/columnFilteringFeature.utils.d.ts
7
7
  /**
@@ -1,6 +1,6 @@
1
1
  import { RowData } from "../../types/type-utils.js";
2
- import { Table } from "../../types/Table.js";
3
2
  import { RowModel } from "../../core/row-models/coreRowModelsFeature.types.js";
3
+ import { Table } from "../../types/Table.js";
4
4
  import { TableFeatures } from "../../types/TableFeatures.js";
5
5
  //#region src/features/column-filtering/createFilteredRowModel.d.ts
6
6
  /**
@@ -1,8 +1,8 @@
1
1
  import { CellData, RowData, Updater } from "../../types/type-utils.js";
2
- import { Table } from "../../types/Table.js";
2
+ import { GroupingState, Row_ColumnGrouping } from "./columnGroupingFeature.types.js";
3
3
  import { Column } from "../../types/Column.js";
4
4
  import { Row } from "../../types/Row.js";
5
- import { GroupingState, Row_ColumnGrouping } from "./columnGroupingFeature.types.js";
5
+ import { Table } from "../../types/Table.js";
6
6
  import { Cell } from "../../types/Cell.js";
7
7
  import { TableFeatures } from "../../types/TableFeatures.js";
8
8
  //#region src/features/column-grouping/columnGroupingFeature.utils.d.ts
@@ -1,6 +1,6 @@
1
1
  import { RowData } from "../../types/type-utils.js";
2
- import { Table } from "../../types/Table.js";
3
2
  import { RowModel } from "../../core/row-models/coreRowModelsFeature.types.js";
3
+ import { Table } from "../../types/Table.js";
4
4
  import { TableFeatures } from "../../types/TableFeatures.js";
5
5
  //#region src/features/column-grouping/createGroupedRowModel.d.ts
6
6
  /**
@@ -1,8 +1,8 @@
1
1
  import { CellData, RowData, Updater } from "../../types/type-utils.js";
2
2
  import { ColumnPinningPosition } from "../column-pinning/columnPinningFeature.types.js";
3
3
  import { ColumnIndexes, ColumnOrderState } from "./columnOrderingFeature.types.js";
4
- import { Table } from "../../types/Table.js";
5
4
  import { Column } from "../../types/Column.js";
5
+ import { Table } from "../../types/Table.js";
6
6
  import { TableFeatures } from "../../types/TableFeatures.js";
7
7
  //#region src/features/column-ordering/columnOrderingFeature.utils.d.ts
8
8
  /**
@@ -1,10 +1,10 @@
1
1
  import { CellData, RowData, Updater } from "../../types/type-utils.js";
2
2
  import { HeaderGroup } from "../../types/HeaderGroup.js";
3
- import { Header } from "../../types/Header.js";
4
3
  import { ColumnPinningPosition, ColumnPinningState } from "./columnPinningFeature.types.js";
5
- import { Table } from "../../types/Table.js";
4
+ import { Header } from "../../types/Header.js";
6
5
  import { Column } from "../../types/Column.js";
7
6
  import { Row } from "../../types/Row.js";
7
+ import { Table } from "../../types/Table.js";
8
8
  import { Cell } from "../../types/Cell.js";
9
9
  import { TableFeatures } from "../../types/TableFeatures.js";
10
10
  //#region src/features/column-pinning/columnPinningFeature.utils.d.ts
@@ -1,8 +1,8 @@
1
1
  import { CellData, RowData, Updater } from "../../types/type-utils.js";
2
2
  import { columnResizingState } from "./columnResizingFeature.types.js";
3
3
  import { Header } from "../../types/Header.js";
4
- import { Table } from "../../types/Table.js";
5
4
  import { Column } from "../../types/Column.js";
5
+ import { Table } from "../../types/Table.js";
6
6
  import { TableFeatures } from "../../types/TableFeatures.js";
7
7
  //#region src/features/column-resizing/columnResizingFeature.utils.d.ts
8
8
  /**
@@ -1,9 +1,9 @@
1
1
  import { CellData, RowData, Updater } from "../../types/type-utils.js";
2
+ import { ColumnPinningPosition } from "../column-pinning/columnPinningFeature.types.js";
2
3
  import { ColumnOffsetsByPosition, ColumnSizingState } from "./columnSizingFeature.types.js";
3
4
  import { Header } from "../../types/Header.js";
4
- import { ColumnPinningPosition } from "../column-pinning/columnPinningFeature.types.js";
5
- import { Table } from "../../types/Table.js";
6
5
  import { Column } from "../../types/Column.js";
6
+ import { Table } from "../../types/Table.js";
7
7
  import { TableFeatures } from "../../types/TableFeatures.js";
8
8
  //#region src/features/column-sizing/columnSizingFeature.utils.d.ts
9
9
  /**
@@ -1,8 +1,8 @@
1
1
  import { CellData, RowData, Updater } from "../../types/type-utils.js";
2
- import { Table } from "../../types/Table.js";
3
2
  import { Column } from "../../types/Column.js";
4
3
  import { ColumnVisibilityState } from "./columnVisibilityFeature.types.js";
5
4
  import { Row } from "../../types/Row.js";
5
+ import { Table } from "../../types/Table.js";
6
6
  import { Cell } from "../../types/Cell.js";
7
7
  import { TableFeatures } from "../../types/TableFeatures.js";
8
8
  import "../../index.js";
@@ -1,7 +1,7 @@
1
1
  import { CellData, RowData } from "../../types/type-utils.js";
2
- import { Table } from "../../types/Table.js";
3
2
  import { Column } from "../../types/Column.js";
4
3
  import { CreatedFilterFn, FilterFn } from "../column-filtering/columnFilteringFeature.types.js";
4
+ import { Table } from "../../types/Table.js";
5
5
  import { TableFeatures } from "../../types/TableFeatures.js";
6
6
  import "../../index.js";
7
7
  //#region src/features/global-filtering/globalFilteringFeature.utils.d.ts
@@ -1,9 +1,9 @@
1
1
  import { CellData, RowData } from "../../types/type-utils.js";
2
2
  import { BuiltInAggregationFn } from "./aggregationFns.js";
3
3
  import { ColumnDefTemplate } from "../../types/ColumnDef.js";
4
- import { Table } from "../../types/Table.js";
5
4
  import { Column } from "../../types/Column.js";
6
5
  import { Row } from "../../types/Row.js";
6
+ import { Table } from "../../types/Table.js";
7
7
  import { Cell } from "../../types/Cell.js";
8
8
  import { IsAny, TableFeatures } from "../../types/TableFeatures.js";
9
9
  //#region src/features/row-aggregation/rowAggregationFeature.types.d.ts
@@ -1,6 +1,6 @@
1
1
  import { RowData } from "../../types/type-utils.js";
2
- import { Table } from "../../types/Table.js";
3
2
  import { RowModel } from "../../core/row-models/coreRowModelsFeature.types.js";
3
+ import { Table } from "../../types/Table.js";
4
4
  import { TableFeatures } from "../../types/TableFeatures.js";
5
5
  //#region src/features/row-expanding/createExpandedRowModel.d.ts
6
6
  /**
@@ -1,7 +1,7 @@
1
1
  import { RowData, Updater } from "../../types/type-utils.js";
2
2
  import { ExpandedState } from "./rowExpandingFeature.types.js";
3
- import { Table } from "../../types/Table.js";
4
3
  import { Row } from "../../types/Row.js";
4
+ import { Table } from "../../types/Table.js";
5
5
  import { TableFeatures } from "../../types/TableFeatures.js";
6
6
  //#region src/features/row-expanding/rowExpandingFeature.utils.d.ts
7
7
  /**
@@ -1,6 +1,6 @@
1
1
  import { RowData } from "../../types/type-utils.js";
2
- import { Table } from "../../types/Table.js";
3
2
  import { RowModel } from "../../core/row-models/coreRowModelsFeature.types.js";
3
+ import { Table } from "../../types/Table.js";
4
4
  import { TableFeatures } from "../../types/TableFeatures.js";
5
5
  //#region src/features/row-pagination/createPaginatedRowModel.d.ts
6
6
  /**
@@ -1,7 +1,7 @@
1
1
  import { RowData, Updater } from "../../types/type-utils.js";
2
2
  import { RowPinningPosition, RowPinningState } from "./rowPinningFeature.types.js";
3
- import { Table } from "../../types/Table.js";
4
3
  import { Row } from "../../types/Row.js";
4
+ import { Table } from "../../types/Table.js";
5
5
  import { TableFeatures } from "../../types/TableFeatures.js";
6
6
  //#region src/features/row-pinning/rowPinningFeature.utils.d.ts
7
7
  /**