@tanstack/table-core 9.0.0-beta.37 → 9.0.0-beta.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/core/headers/buildHeaderGroups.cjs.map +1 -1
- package/dist/core/headers/buildHeaderGroups.d.cts +1 -1
- package/dist/core/headers/buildHeaderGroups.d.ts +1 -1
- package/dist/core/headers/buildHeaderGroups.js.map +1 -1
- package/dist/core/headers/coreHeadersFeature.utils.cjs +7 -7
- package/dist/core/headers/coreHeadersFeature.utils.cjs.map +1 -1
- package/dist/core/headers/coreHeadersFeature.utils.js +7 -7
- package/dist/core/headers/coreHeadersFeature.utils.js.map +1 -1
- package/dist/core/table/coreTablesFeature.utils.cjs +1 -1
- package/dist/core/table/coreTablesFeature.utils.cjs.map +1 -1
- package/dist/core/table/coreTablesFeature.utils.js +1 -1
- package/dist/core/table/coreTablesFeature.utils.js.map +1 -1
- package/dist/features/column-ordering/columnOrderingFeature.types.d.cts +5 -5
- package/dist/features/column-ordering/columnOrderingFeature.types.d.ts +5 -5
- package/dist/features/column-ordering/columnOrderingFeature.utils.cjs +6 -6
- package/dist/features/column-ordering/columnOrderingFeature.utils.cjs.map +1 -1
- package/dist/features/column-ordering/columnOrderingFeature.utils.d.cts +3 -3
- package/dist/features/column-ordering/columnOrderingFeature.utils.d.ts +3 -3
- package/dist/features/column-ordering/columnOrderingFeature.utils.js +6 -6
- package/dist/features/column-ordering/columnOrderingFeature.utils.js.map +1 -1
- package/dist/features/column-pinning/columnPinningFeature.cjs +44 -39
- package/dist/features/column-pinning/columnPinningFeature.cjs.map +1 -1
- package/dist/features/column-pinning/columnPinningFeature.d.cts +6 -1
- package/dist/features/column-pinning/columnPinningFeature.d.ts +6 -1
- package/dist/features/column-pinning/columnPinningFeature.js +45 -40
- package/dist/features/column-pinning/columnPinningFeature.js.map +1 -1
- package/dist/features/column-pinning/columnPinningFeature.types.d.cts +49 -38
- package/dist/features/column-pinning/columnPinningFeature.types.d.ts +49 -38
- package/dist/features/column-pinning/columnPinningFeature.utils.cjs +154 -146
- package/dist/features/column-pinning/columnPinningFeature.utils.cjs.map +1 -1
- package/dist/features/column-pinning/columnPinningFeature.utils.d.cts +81 -73
- package/dist/features/column-pinning/columnPinningFeature.utils.d.ts +81 -73
- package/dist/features/column-pinning/columnPinningFeature.utils.js +141 -133
- package/dist/features/column-pinning/columnPinningFeature.utils.js.map +1 -1
- package/dist/features/column-sizing/columnSizingFeature.cjs +4 -4
- package/dist/features/column-sizing/columnSizingFeature.cjs.map +1 -1
- package/dist/features/column-sizing/columnSizingFeature.js +5 -5
- package/dist/features/column-sizing/columnSizingFeature.js.map +1 -1
- package/dist/features/column-sizing/columnSizingFeature.types.d.cts +18 -12
- package/dist/features/column-sizing/columnSizingFeature.types.d.ts +18 -12
- package/dist/features/column-sizing/columnSizingFeature.utils.cjs +24 -20
- package/dist/features/column-sizing/columnSizingFeature.utils.cjs.map +1 -1
- package/dist/features/column-sizing/columnSizingFeature.utils.d.cts +18 -14
- package/dist/features/column-sizing/columnSizingFeature.utils.d.ts +18 -14
- package/dist/features/column-sizing/columnSizingFeature.utils.js +24 -20
- package/dist/features/column-sizing/columnSizingFeature.utils.js.map +1 -1
- package/dist/features/column-visibility/columnVisibilityFeature.utils.cjs +16 -16
- package/dist/features/column-visibility/columnVisibilityFeature.utils.cjs.map +1 -1
- package/dist/features/column-visibility/columnVisibilityFeature.utils.d.cts +3 -3
- package/dist/features/column-visibility/columnVisibilityFeature.utils.d.ts +3 -3
- package/dist/features/column-visibility/columnVisibilityFeature.utils.js +16 -16
- package/dist/features/column-visibility/columnVisibilityFeature.utils.js.map +1 -1
- package/dist/static-functions.cjs +16 -16
- package/dist/static-functions.d.cts +3 -3
- package/dist/static-functions.d.ts +3 -3
- package/dist/static-functions.js +3 -3
- package/package.json +1 -1
- package/skills/api-not-found/SKILL.md +113 -0
- package/skills/client-vs-server/SKILL.md +164 -0
- package/skills/column-faceting/SKILL.md +91 -0
- package/skills/column-filtering/SKILL.md +82 -0
- package/skills/column-ordering/SKILL.md +75 -0
- package/skills/column-pinning/SKILL.md +89 -0
- package/skills/column-resizing/SKILL.md +91 -0
- package/skills/column-sizing/SKILL.md +72 -0
- package/skills/column-visibility/SKILL.md +75 -0
- package/skills/core/SKILL.md +140 -0
- package/skills/custom-features/SKILL.md +207 -0
- package/skills/expanding/SKILL.md +80 -0
- package/skills/global-filtering/SKILL.md +84 -0
- package/skills/grouping/SKILL.md +50 -394
- package/skills/migrate-v8-to-v9/SKILL.md +230 -390
- package/skills/pagination/SKILL.md +35 -344
- package/skills/row-pinning/SKILL.md +47 -238
- package/skills/row-selection/SKILL.md +39 -351
- package/skills/sorting/SKILL.md +35 -299
- package/skills/table-features/SKILL.md +153 -0
- package/skills/typescript/SKILL.md +126 -0
- package/src/core/headers/buildHeaderGroups.ts +1 -1
- package/src/core/headers/coreHeadersFeature.utils.ts +7 -7
- package/src/core/table/coreTablesFeature.utils.ts +1 -1
- package/src/features/column-ordering/columnOrderingFeature.types.ts +5 -5
- package/src/features/column-ordering/columnOrderingFeature.utils.ts +9 -9
- package/src/features/column-pinning/columnPinningFeature.ts +64 -59
- package/src/features/column-pinning/columnPinningFeature.types.ts +49 -38
- package/src/features/column-pinning/columnPinningFeature.utils.ts +163 -155
- package/src/features/column-sizing/columnSizingFeature.ts +6 -6
- package/src/features/column-sizing/columnSizingFeature.types.ts +18 -12
- package/src/features/column-sizing/columnSizingFeature.utils.ts +31 -27
- package/src/features/column-visibility/columnVisibilityFeature.utils.ts +15 -15
- package/skills/column-definitions/SKILL.md +0 -330
- package/skills/column-layout/SKILL.md +0 -326
- package/skills/column-layout/references/subsystems.md +0 -220
- package/skills/customizing-feature-behavior/SKILL.md +0 -423
- package/skills/filtering/SKILL.md +0 -375
- package/skills/filtering/references/faceting-and-fuzzy.md +0 -218
- package/skills/row-expanding/SKILL.md +0 -356
- package/skills/setup/SKILL.md +0 -390
- package/skills/state-management/SKILL.md +0 -403
|
@@ -14,8 +14,8 @@ import {
|
|
|
14
14
|
header_getStart,
|
|
15
15
|
table_getCenterTotalSize,
|
|
16
16
|
table_getColumnOffsets,
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
table_getEndTotalSize,
|
|
18
|
+
table_getStartTotalSize,
|
|
19
19
|
table_getTotalSize,
|
|
20
20
|
table_resetColumnSizing,
|
|
21
21
|
table_setColumnSizing,
|
|
@@ -119,8 +119,8 @@ export const columnSizingFeature: TableFeature = {
|
|
|
119
119
|
table.getHeaderGroups(),
|
|
120
120
|
],
|
|
121
121
|
},
|
|
122
|
-
|
|
123
|
-
fn: () =>
|
|
122
|
+
table_getStartTotalSize: {
|
|
123
|
+
fn: () => table_getStartTotalSize(table),
|
|
124
124
|
memoDeps: () => [
|
|
125
125
|
table.atoms.columnSizing?.get(),
|
|
126
126
|
table.getHeaderGroups(),
|
|
@@ -133,8 +133,8 @@ export const columnSizingFeature: TableFeature = {
|
|
|
133
133
|
table.getHeaderGroups(),
|
|
134
134
|
],
|
|
135
135
|
},
|
|
136
|
-
|
|
137
|
-
fn: () =>
|
|
136
|
+
table_getEndTotalSize: {
|
|
137
|
+
fn: () => table_getEndTotalSize(table),
|
|
138
138
|
memoDeps: () => [
|
|
139
139
|
table.atoms.columnSizing?.get(),
|
|
140
140
|
table.getHeaderGroups(),
|
|
@@ -30,13 +30,19 @@ export interface ColumnOffsetsByPosition {
|
|
|
30
30
|
*/
|
|
31
31
|
center: ColumnOffsets
|
|
32
32
|
/**
|
|
33
|
-
* Offsets within the
|
|
33
|
+
* Offsets within the logical start pinned region.
|
|
34
|
+
*
|
|
35
|
+
* In LTR languages/layouts, start usually corresponds to left. In RTL
|
|
36
|
+
* languages/layouts, start usually corresponds to right.
|
|
34
37
|
*/
|
|
35
|
-
|
|
38
|
+
start: ColumnOffsets
|
|
36
39
|
/**
|
|
37
|
-
* Offsets within the
|
|
40
|
+
* Offsets within the logical end pinned region.
|
|
41
|
+
*
|
|
42
|
+
* In LTR languages/layouts, end usually corresponds to right. In RTL
|
|
43
|
+
* languages/layouts, end usually corresponds to left.
|
|
38
44
|
*/
|
|
39
|
-
|
|
45
|
+
end: ColumnOffsets
|
|
40
46
|
}
|
|
41
47
|
|
|
42
48
|
export interface TableOptions_ColumnSizing {
|
|
@@ -66,13 +72,13 @@ export interface Table_ColumnSizing {
|
|
|
66
72
|
*/
|
|
67
73
|
getColumnOffsets: () => ColumnOffsetsByPosition
|
|
68
74
|
/**
|
|
69
|
-
* Sums the current sizes of visible
|
|
75
|
+
* Sums the current sizes of visible logical start-pinned leaf columns.
|
|
70
76
|
*/
|
|
71
|
-
|
|
77
|
+
getStartTotalSize: () => number
|
|
72
78
|
/**
|
|
73
|
-
* Sums the current sizes of visible
|
|
79
|
+
* Sums the current sizes of visible logical end-pinned leaf columns.
|
|
74
80
|
*/
|
|
75
|
-
|
|
81
|
+
getEndTotalSize: () => number
|
|
76
82
|
/**
|
|
77
83
|
* Sums the current sizes of all visible leaf columns.
|
|
78
84
|
*/
|
|
@@ -107,8 +113,8 @@ export interface Column_ColumnSizing {
|
|
|
107
113
|
/**
|
|
108
114
|
* Measures the offset from this column's end edge to the end of its region.
|
|
109
115
|
*
|
|
110
|
-
* Pass a pinned region to measure within that region. The value is
|
|
111
|
-
* of visible leaf column sizes after this column.
|
|
116
|
+
* Pass a pinned region to measure within that logical region. The value is
|
|
117
|
+
* the sum of visible leaf column sizes after this column.
|
|
112
118
|
*/
|
|
113
119
|
getAfter: (position?: ColumnPinningPosition | 'center') => number
|
|
114
120
|
/**
|
|
@@ -119,8 +125,8 @@ export interface Column_ColumnSizing {
|
|
|
119
125
|
* Measures the offset from the start of this column's region to its start
|
|
120
126
|
* edge.
|
|
121
127
|
*
|
|
122
|
-
* Pass a pinned region to measure within that region. The value is
|
|
123
|
-
* of visible leaf column sizes before this column.
|
|
128
|
+
* Pass a pinned region to measure within that logical region. The value is
|
|
129
|
+
* the sum of visible leaf column sizes before this column.
|
|
124
130
|
*/
|
|
125
131
|
getStart: (position?: ColumnPinningPosition | 'center') => number
|
|
126
132
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
table_getCenterHeaderGroups,
|
|
3
|
-
|
|
3
|
+
table_getEndHeaderGroups,
|
|
4
4
|
table_getPinnedVisibleLeafColumns,
|
|
5
|
-
|
|
5
|
+
table_getStartHeaderGroups,
|
|
6
6
|
} from '../column-pinning/columnPinningFeature.utils'
|
|
7
7
|
import {
|
|
8
8
|
callMemoOrStaticFn,
|
|
@@ -125,7 +125,7 @@ function buildColumnOffsets<
|
|
|
125
125
|
* @example
|
|
126
126
|
* ```ts
|
|
127
127
|
* const offsets = table_getColumnOffsets(table)
|
|
128
|
-
* const
|
|
128
|
+
* const startOffset = offsets.start.starts[column.id]
|
|
129
129
|
* ```
|
|
130
130
|
*/
|
|
131
131
|
export function table_getColumnOffsets<
|
|
@@ -143,13 +143,13 @@ export function table_getColumnOffsets<
|
|
|
143
143
|
Column_Internal<TFeatures, TData, unknown>
|
|
144
144
|
>,
|
|
145
145
|
),
|
|
146
|
-
|
|
147
|
-
table_getPinnedVisibleLeafColumns(table, '
|
|
146
|
+
start: buildColumnOffsets(
|
|
147
|
+
table_getPinnedVisibleLeafColumns(table, 'start') as Array<
|
|
148
148
|
Column_Internal<TFeatures, TData, unknown>
|
|
149
149
|
>,
|
|
150
150
|
),
|
|
151
|
-
|
|
152
|
-
table_getPinnedVisibleLeafColumns(table, '
|
|
151
|
+
end: buildColumnOffsets(
|
|
152
|
+
table_getPinnedVisibleLeafColumns(table, 'end') as Array<
|
|
153
153
|
Column_Internal<TFeatures, TData, unknown>
|
|
154
154
|
>,
|
|
155
155
|
),
|
|
@@ -159,10 +159,10 @@ export function table_getColumnOffsets<
|
|
|
159
159
|
function toOffsetsKey(
|
|
160
160
|
position: ColumnPinningPosition | 'center' | undefined,
|
|
161
161
|
): keyof ColumnOffsetsByPosition {
|
|
162
|
-
return position === '
|
|
163
|
-
? '
|
|
164
|
-
: position === '
|
|
165
|
-
? '
|
|
162
|
+
return position === 'start'
|
|
163
|
+
? 'start'
|
|
164
|
+
: position === 'end'
|
|
165
|
+
? 'end'
|
|
166
166
|
: position === 'center'
|
|
167
167
|
? 'center'
|
|
168
168
|
: 'all' // undefined | false use the full visible list
|
|
@@ -172,11 +172,15 @@ function toOffsetsKey(
|
|
|
172
172
|
* Computes the offset from the start edge of a pinning region to this column.
|
|
173
173
|
*
|
|
174
174
|
* The value is the sum of all previous visible leaf column sizes in the
|
|
175
|
-
* requested `'
|
|
175
|
+
* requested `'start'`, `'center'`, or `'end'` region.
|
|
176
|
+
*
|
|
177
|
+
* `start` and `end` are logical positions. In LTR languages/layouts, `start`
|
|
178
|
+
* usually corresponds to left and `end` to right. In RTL languages/layouts,
|
|
179
|
+
* `start` usually corresponds to right and `end` to left.
|
|
176
180
|
*
|
|
177
181
|
* @example
|
|
178
182
|
* ```ts
|
|
179
|
-
* const
|
|
183
|
+
* const startOffset = column_getStart(column, 'start')
|
|
180
184
|
* ```
|
|
181
185
|
*/
|
|
182
186
|
export function column_getStart<
|
|
@@ -203,7 +207,7 @@ export function column_getStart<
|
|
|
203
207
|
*
|
|
204
208
|
* @example
|
|
205
209
|
* ```ts
|
|
206
|
-
* const
|
|
210
|
+
* const endOffset = column_getAfter(column, 'end')
|
|
207
211
|
* ```
|
|
208
212
|
*/
|
|
209
213
|
export function column_getAfter<
|
|
@@ -364,7 +368,7 @@ export function table_resetColumnSizing<
|
|
|
364
368
|
/**
|
|
365
369
|
* Sums the rendered size of the full table header row.
|
|
366
370
|
*
|
|
367
|
-
* This includes
|
|
371
|
+
* This includes start, center, and end columns in the main header group.
|
|
368
372
|
*
|
|
369
373
|
* @example
|
|
370
374
|
* ```ts
|
|
@@ -383,24 +387,24 @@ export function table_getTotalSize<
|
|
|
383
387
|
}
|
|
384
388
|
|
|
385
389
|
/**
|
|
386
|
-
* Sums the rendered size of the
|
|
390
|
+
* Sums the rendered size of the logical start pinned header region.
|
|
387
391
|
*
|
|
388
|
-
* An empty
|
|
392
|
+
* An empty start pinning region returns `0`.
|
|
389
393
|
*
|
|
390
394
|
* @example
|
|
391
395
|
* ```ts
|
|
392
|
-
* const width =
|
|
396
|
+
* const width = table_getStartTotalSize(table)
|
|
393
397
|
* ```
|
|
394
398
|
*/
|
|
395
|
-
export function
|
|
399
|
+
export function table_getStartTotalSize<
|
|
396
400
|
TFeatures extends TableFeatures,
|
|
397
401
|
TData extends RowData,
|
|
398
402
|
>(table: Table_Internal<TFeatures, TData>) {
|
|
399
403
|
return (
|
|
400
404
|
callMemoOrStaticFn(
|
|
401
405
|
table,
|
|
402
|
-
'
|
|
403
|
-
|
|
406
|
+
'getStartHeaderGroups',
|
|
407
|
+
table_getStartHeaderGroups,
|
|
404
408
|
)[0]?.headers.reduce((sum: number, header: Header<TFeatures, TData>) => {
|
|
405
409
|
return sum + header_getSize(header)
|
|
406
410
|
}, 0) ?? 0
|
|
@@ -433,24 +437,24 @@ export function table_getCenterTotalSize<
|
|
|
433
437
|
}
|
|
434
438
|
|
|
435
439
|
/**
|
|
436
|
-
* Sums the rendered size of the
|
|
440
|
+
* Sums the rendered size of the logical end pinned header region.
|
|
437
441
|
*
|
|
438
|
-
* An empty
|
|
442
|
+
* An empty end pinning region returns `0`.
|
|
439
443
|
*
|
|
440
444
|
* @example
|
|
441
445
|
* ```ts
|
|
442
|
-
* const width =
|
|
446
|
+
* const width = table_getEndTotalSize(table)
|
|
443
447
|
* ```
|
|
444
448
|
*/
|
|
445
|
-
export function
|
|
449
|
+
export function table_getEndTotalSize<
|
|
446
450
|
TFeatures extends TableFeatures,
|
|
447
451
|
TData extends RowData,
|
|
448
452
|
>(table: Table_Internal<TFeatures, TData>) {
|
|
449
453
|
return (
|
|
450
454
|
callMemoOrStaticFn(
|
|
451
455
|
table,
|
|
452
|
-
'
|
|
453
|
-
|
|
456
|
+
'getEndHeaderGroups',
|
|
457
|
+
table_getEndHeaderGroups,
|
|
454
458
|
)[0]?.headers.reduce((sum: number, header: Header<TFeatures, TData>) => {
|
|
455
459
|
return sum + header_getSize(header)
|
|
456
460
|
}, 0) ?? 0
|
|
@@ -32,7 +32,7 @@ export function getDefaultColumnVisibilityState(): ColumnVisibilityState {
|
|
|
32
32
|
* Updates this column's visibility when hiding is allowed.
|
|
33
33
|
*
|
|
34
34
|
* Passing `visible` stores that value. Omitting it flips the column's current
|
|
35
|
-
* visibility state. Columns that cannot hide are
|
|
35
|
+
* visibility state. Columns that cannot hide are start unchanged.
|
|
36
36
|
*
|
|
37
37
|
* @example
|
|
38
38
|
* ```ts
|
|
@@ -137,8 +137,8 @@ export function column_getToggleVisibilityHandler<
|
|
|
137
137
|
/**
|
|
138
138
|
* Collects the cells from this row whose columns are visible.
|
|
139
139
|
*
|
|
140
|
-
* When column pinning is active, the result is ordered as
|
|
141
|
-
* center cells, then
|
|
140
|
+
* When column pinning is active, the result is ordered as start-pinned cells,
|
|
141
|
+
* center cells, then end-pinned cells.
|
|
142
142
|
*
|
|
143
143
|
* @example
|
|
144
144
|
* ```ts
|
|
@@ -158,9 +158,9 @@ export function row_getVisibleCells<
|
|
|
158
158
|
}
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
const {
|
|
161
|
+
const { start, end } =
|
|
162
162
|
row.table.atoms.columnPinning?.get() ?? getDefaultColumnPinningState()
|
|
163
|
-
if (!
|
|
163
|
+
if (!start.length && !end.length) return visibleCells // no pinning, return early
|
|
164
164
|
|
|
165
165
|
const visibleCellsByColumnId = callMemoOrStaticFn(
|
|
166
166
|
row,
|
|
@@ -168,16 +168,16 @@ export function row_getVisibleCells<
|
|
|
168
168
|
row_getVisibleCellsByColumnId,
|
|
169
169
|
)
|
|
170
170
|
|
|
171
|
-
const
|
|
172
|
-
for (let i = 0; i <
|
|
173
|
-
const cell = visibleCellsByColumnId[
|
|
174
|
-
if (cell)
|
|
171
|
+
const startCells: Array<Cell<TFeatures, TData, unknown>> = []
|
|
172
|
+
for (let i = 0; i < start.length; i++) {
|
|
173
|
+
const cell = visibleCellsByColumnId[start[i]!]
|
|
174
|
+
if (cell) startCells.push(cell)
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
const
|
|
178
|
-
for (let i = 0; i <
|
|
179
|
-
const cell = visibleCellsByColumnId[
|
|
180
|
-
if (cell)
|
|
177
|
+
const endCells: Array<Cell<TFeatures, TData, unknown>> = []
|
|
178
|
+
for (let i = 0; i < end.length; i++) {
|
|
179
|
+
const cell = visibleCellsByColumnId[end[i]!]
|
|
180
|
+
if (cell) endCells.push(cell)
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
// Center cells: visible cells in natural column order, minus pinned ones.
|
|
@@ -185,10 +185,10 @@ export function row_getVisibleCells<
|
|
|
185
185
|
for (let i = 0; i < visibleCells.length; i++) {
|
|
186
186
|
const cell = visibleCells[i]!
|
|
187
187
|
const id = cell.column.id
|
|
188
|
-
if (!
|
|
188
|
+
if (!start.includes(id) && !end.includes(id)) centerCells.push(cell)
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
-
return [...
|
|
191
|
+
return [...startCells, ...centerCells, ...endCells]
|
|
192
192
|
}
|
|
193
193
|
|
|
194
194
|
/**
|
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: column-definitions
|
|
3
|
-
description: >
|
|
4
|
-
Define TanStack Table v9 columns with `createColumnHelper<typeof features, TData>()`.
|
|
5
|
-
Covers `columnHelper.accessor` (key + function forms), `columnHelper.display`,
|
|
6
|
-
`columnHelper.group`, `columnHelper.columns`, the `ColumnDef`/`AccessorKeyColumnDef`/
|
|
7
|
-
`AccessorFnColumnDef`/`DisplayColumnDef`/`GroupColumnDef` types, `accessorKey` with
|
|
8
|
-
`DeepKeys`, `accessorFn`, the `header`/`cell`/`footer`/`aggregatedCell` renderers,
|
|
9
|
-
required `id` rules, and `getRowId` for stable row identity.
|
|
10
|
-
type: core
|
|
11
|
-
library: tanstack-table
|
|
12
|
-
library_version: '9.0.0-alpha.48'
|
|
13
|
-
sources:
|
|
14
|
-
- TanStack/table:docs/guide/column-defs.md
|
|
15
|
-
- TanStack/table:docs/guide/columns.md
|
|
16
|
-
- TanStack/table:packages/table-core/src/helpers/columnHelper.ts
|
|
17
|
-
- TanStack/table:packages/table-core/src/core/columns/constructColumn.ts
|
|
18
|
-
- TanStack/table:examples/react/basic-use-table/src/main.tsx
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
## Setup
|
|
22
|
-
|
|
23
|
-
`createColumnHelper` takes TWO generics in v9: the features type (so accessor keys, sort/filter strings, etc. are typed against your registered features) and the row data type.
|
|
24
|
-
|
|
25
|
-
```ts
|
|
26
|
-
import {
|
|
27
|
-
createColumnHelper,
|
|
28
|
-
tableFeatures,
|
|
29
|
-
rowSortingFeature,
|
|
30
|
-
} from '@tanstack/table-core'
|
|
31
|
-
|
|
32
|
-
type Person = {
|
|
33
|
-
id: string
|
|
34
|
-
firstName: string
|
|
35
|
-
lastName: string
|
|
36
|
-
age: number
|
|
37
|
-
visits: number
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const features = tableFeatures({ rowSortingFeature })
|
|
41
|
-
|
|
42
|
-
// TFeatures FIRST, TData SECOND
|
|
43
|
-
const columnHelper = createColumnHelper<typeof features, Person>()
|
|
44
|
-
|
|
45
|
-
const columns = columnHelper.columns([
|
|
46
|
-
// accessorKey — deep keys via DeepKeys (dot paths) are supported
|
|
47
|
-
columnHelper.accessor('firstName', { header: 'First Name' }),
|
|
48
|
-
columnHelper.accessor('lastName', { header: 'Last Name' }),
|
|
49
|
-
columnHelper.accessor('age', { header: 'Age' }),
|
|
50
|
-
|
|
51
|
-
// accessorFn — needs an explicit `id`
|
|
52
|
-
columnHelper.accessor((row) => `${row.firstName} ${row.lastName}`, {
|
|
53
|
-
id: 'fullName',
|
|
54
|
-
header: 'Full Name',
|
|
55
|
-
cell: (info) => info.getValue(),
|
|
56
|
-
}),
|
|
57
|
-
|
|
58
|
-
// display column — no value extraction, just rendering
|
|
59
|
-
columnHelper.display({
|
|
60
|
-
id: 'actions',
|
|
61
|
-
header: 'Actions',
|
|
62
|
-
cell: ({ row }) => `Edit ${row.original.id}`,
|
|
63
|
-
}),
|
|
64
|
-
|
|
65
|
-
// group column — wraps child columns under a shared header
|
|
66
|
-
columnHelper.group({
|
|
67
|
-
id: 'stats',
|
|
68
|
-
header: 'Stats',
|
|
69
|
-
columns: [columnHelper.accessor('visits', { header: 'Visits' })],
|
|
70
|
-
}),
|
|
71
|
-
])
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Core Patterns
|
|
75
|
-
|
|
76
|
-
### Stable row identity with `getRowId`
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
const table = useTable({
|
|
80
|
-
features,
|
|
81
|
-
columns,
|
|
82
|
-
data,
|
|
83
|
-
getRowId: (row) => row.id, // ← stable from row's own data
|
|
84
|
-
})
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
Without `getRowId`, `row.id` defaults to the row's array index. Row-keyed state (selection, expansion, pinning) then attaches to whatever happens to be at that index after a sort/filter/refetch.
|
|
88
|
-
|
|
89
|
-
### Accessor key with deep path
|
|
90
|
-
|
|
91
|
-
```ts
|
|
92
|
-
type User = { name: { first: string; last: string } }
|
|
93
|
-
|
|
94
|
-
const columnHelper = createColumnHelper<typeof features, User>()
|
|
95
|
-
|
|
96
|
-
columnHelper.accessor('name.first', { header: 'First' })
|
|
97
|
-
columnHelper.accessor('name.last', { header: 'Last' })
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
For nested objects with non-optional intermediate keys, the dotted `accessorKey` form works and infers the right value type. Switch to `accessorFn` when intermediates are optional (see Common Mistakes below).
|
|
101
|
-
|
|
102
|
-
### Header / cell / footer renderers
|
|
103
|
-
|
|
104
|
-
```ts
|
|
105
|
-
columnHelper.accessor('age', {
|
|
106
|
-
header: () => 'Age',
|
|
107
|
-
cell: (info) => info.getValue(),
|
|
108
|
-
footer: (info) => `${info.table.getRowModel().rows.length} rows`,
|
|
109
|
-
})
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Renderers accept string, JSX (in framework adapters), or function forms. Render via `flexRender(def, ctx)` or `<table.FlexRender header={header} />` so all three forms work uniformly.
|
|
113
|
-
|
|
114
|
-
### `columnHelper.columns([...])` for module-scope stability
|
|
115
|
-
|
|
116
|
-
```ts
|
|
117
|
-
// Outside any component / hook — stable reference forever
|
|
118
|
-
const columns = columnHelper.columns([
|
|
119
|
-
columnHelper.accessor('firstName', { header: 'First' }),
|
|
120
|
-
columnHelper.accessor('lastName', { header: 'Last' }),
|
|
121
|
-
])
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
`columnHelper.columns` returns the array as-is but preserves the precise tuple types. Hoist to module scope or wrap in `useMemo` — the table compares `columns` by reference.
|
|
125
|
-
|
|
126
|
-
## Common Mistakes
|
|
127
|
-
|
|
128
|
-
### [CRITICAL] Passing only `TData` to `createColumnHelper`
|
|
129
|
-
|
|
130
|
-
Wrong:
|
|
131
|
-
|
|
132
|
-
```ts
|
|
133
|
-
// v8 signature — TData ends up in the TFeatures slot
|
|
134
|
-
const columnHelper = createColumnHelper<Person>()
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
Correct:
|
|
138
|
-
|
|
139
|
-
```ts
|
|
140
|
-
const features = tableFeatures({ rowSortingFeature })
|
|
141
|
-
const columnHelper = createColumnHelper<typeof features, Person>()
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
v9 changed the generic order: `<TFeatures, TData>`. The compiler error is noisy because `Person` lands in the `TFeatures` slot and breaks every column type that follows.
|
|
145
|
-
|
|
146
|
-
Source: packages/table-core/src/helpers/columnHelper.ts; docs/framework/react/guide/migrating.md
|
|
147
|
-
|
|
148
|
-
### [HIGH] Accessor function returns an object or array
|
|
149
|
-
|
|
150
|
-
Wrong:
|
|
151
|
-
|
|
152
|
-
```ts
|
|
153
|
-
// returns an object — built-in alphanumeric sort and includesString filter break
|
|
154
|
-
columnHelper.accessor((row) => row.name, {
|
|
155
|
-
id: 'name',
|
|
156
|
-
cell: (info) => `${info.getValue().first} ${info.getValue().last}`,
|
|
157
|
-
})
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
Correct:
|
|
161
|
-
|
|
162
|
-
```ts
|
|
163
|
-
// accessor returns a primitive; cell can still format it
|
|
164
|
-
columnHelper.accessor((row) => `${row.name.first} ${row.name.last}`, {
|
|
165
|
-
id: 'fullName',
|
|
166
|
-
cell: (info) => info.getValue(),
|
|
167
|
-
})
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
The accessed value drives sorting, filtering, faceting, and grouping. Built-in `sortFn`/`filterFn`/`aggregationFn` expect a primitive `string` / `number` / `Date`. Return a primitive — or supply a matching custom function.
|
|
171
|
-
|
|
172
|
-
Source: docs/guide/column-defs.md
|
|
173
|
-
|
|
174
|
-
### [CRITICAL] Omitting `id` on an `accessorFn` column
|
|
175
|
-
|
|
176
|
-
Wrong:
|
|
177
|
-
|
|
178
|
-
```tsx
|
|
179
|
-
// accessorFn + JSX header => no id can be derived
|
|
180
|
-
columnHelper.accessor((row) => row.lastName, {
|
|
181
|
-
header: () => <span>Last Name</span>,
|
|
182
|
-
cell: (info) => info.getValue(),
|
|
183
|
-
})
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
Correct:
|
|
187
|
-
|
|
188
|
-
```tsx
|
|
189
|
-
columnHelper.accessor((row) => row.lastName, {
|
|
190
|
-
id: 'lastName', // required when there's no string accessorKey or string header
|
|
191
|
-
header: () => <span>Last Name</span>,
|
|
192
|
-
cell: (info) => info.getValue(),
|
|
193
|
-
})
|
|
194
|
-
```
|
|
195
|
-
|
|
196
|
-
The constructor throws "coreColumnsFeature require an id when using an accessorFn" in development. The same applies to non-string `header` values without a fallback `id`.
|
|
197
|
-
|
|
198
|
-
Source: packages/table-core/src/core/columns/constructColumn.ts
|
|
199
|
-
|
|
200
|
-
### [CRITICAL] Defining `columns` inside the component without `useMemo`
|
|
201
|
-
|
|
202
|
-
Wrong:
|
|
203
|
-
|
|
204
|
-
```tsx
|
|
205
|
-
function MyTable() {
|
|
206
|
-
// new array reference every render → infinite render loop
|
|
207
|
-
const columns = [
|
|
208
|
-
columnHelper.accessor('firstName', { header: 'First' }),
|
|
209
|
-
columnHelper.accessor('lastName', { header: 'Last' }),
|
|
210
|
-
]
|
|
211
|
-
const table = useTable({ features, columns, data })
|
|
212
|
-
}
|
|
213
|
-
```
|
|
214
|
-
|
|
215
|
-
Correct:
|
|
216
|
-
|
|
217
|
-
```tsx
|
|
218
|
-
function MyTable() {
|
|
219
|
-
const columns = React.useMemo(
|
|
220
|
-
() =>
|
|
221
|
-
columnHelper.columns([
|
|
222
|
-
columnHelper.accessor('firstName', { header: 'First' }),
|
|
223
|
-
columnHelper.accessor('lastName', { header: 'Last' }),
|
|
224
|
-
]),
|
|
225
|
-
[],
|
|
226
|
-
)
|
|
227
|
-
const table = useTable({ features, columns, data })
|
|
228
|
-
}
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
TanStack Table compares `columns` and `data` by reference. The #1 FAQ entry across versions.
|
|
232
|
-
|
|
233
|
-
Source: docs/faq.md; examples/react/basic-subscribe/src/main.tsx
|
|
234
|
-
|
|
235
|
-
### [HIGH] Using array-index row IDs with mutating data
|
|
236
|
-
|
|
237
|
-
Wrong:
|
|
238
|
-
|
|
239
|
-
```ts
|
|
240
|
-
// no getRowId — rowSelection survives data updates but maps to wrong rows
|
|
241
|
-
const table = useTable({
|
|
242
|
-
features,
|
|
243
|
-
columns,
|
|
244
|
-
data,
|
|
245
|
-
enableRowSelection: true,
|
|
246
|
-
})
|
|
247
|
-
```
|
|
248
|
-
|
|
249
|
-
Correct:
|
|
250
|
-
|
|
251
|
-
```ts
|
|
252
|
-
const table = useTable({
|
|
253
|
-
features,
|
|
254
|
-
columns,
|
|
255
|
-
data,
|
|
256
|
-
getRowId: (row) => row.id,
|
|
257
|
-
enableRowSelection: true,
|
|
258
|
-
})
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
When `data` reorders, filters, or items are removed/refetched, row-keyed state (selection, expansion, pinning) attaches to the wrong row.
|
|
262
|
-
|
|
263
|
-
Source: docs/guide/rows.md; packages/table-core/src/core/rows/coreRowsFeature.utils.ts
|
|
264
|
-
|
|
265
|
-
### [MEDIUM] `accessorKey` with optional path strips `undefined` from `getValue` type
|
|
266
|
-
|
|
267
|
-
Wrong:
|
|
268
|
-
|
|
269
|
-
```ts
|
|
270
|
-
// amount inferred as `number` even though salary is optional
|
|
271
|
-
columnHelper.accessor('user.salary.amount', {
|
|
272
|
-
cell: (info) => {
|
|
273
|
-
const amount = info.getValue() // type: number (WRONG)
|
|
274
|
-
return amount.toFixed(2) // crashes when salary is undefined
|
|
275
|
-
},
|
|
276
|
-
})
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
Correct:
|
|
280
|
-
|
|
281
|
-
```ts
|
|
282
|
-
columnHelper.accessor((row) => row.user.salary?.amount, {
|
|
283
|
-
id: 'salary',
|
|
284
|
-
cell: (info) => {
|
|
285
|
-
const amount = info.getValue() // type: number | undefined
|
|
286
|
-
return amount?.toFixed(2) ?? '-'
|
|
287
|
-
},
|
|
288
|
-
})
|
|
289
|
-
```
|
|
290
|
-
|
|
291
|
-
The `DeepValue` type doesn't propagate `undefined` through optional intermediates. Use `accessorFn` when any segment is optional — the type follows the expression.
|
|
292
|
-
|
|
293
|
-
Source: https://github.com/TanStack/table/issues/6238
|
|
294
|
-
|
|
295
|
-
### [MEDIUM] `columnHelper.accessor` nested inside `columnHelper.group` loses `getValue` inference
|
|
296
|
-
|
|
297
|
-
Wrong:
|
|
298
|
-
|
|
299
|
-
```ts
|
|
300
|
-
// info.getValue() inferred as unknown
|
|
301
|
-
columnHelper.group({
|
|
302
|
-
id: 'name',
|
|
303
|
-
columns: [
|
|
304
|
-
columnHelper.accessor('firstName', {
|
|
305
|
-
cell: (info) => info.getValue(), // unknown
|
|
306
|
-
}),
|
|
307
|
-
],
|
|
308
|
-
})
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
Correct:
|
|
312
|
-
|
|
313
|
-
```ts
|
|
314
|
-
// Hoist accessor definitions out of the group
|
|
315
|
-
const firstNameCol = columnHelper.accessor('firstName', {
|
|
316
|
-
cell: (info) => info.getValue(), // string
|
|
317
|
-
})
|
|
318
|
-
|
|
319
|
-
columnHelper.group({ id: 'name', columns: [firstNameCol] })
|
|
320
|
-
```
|
|
321
|
-
|
|
322
|
-
The group helper's overloads don't thread `TData` through correctly when accessors are defined inline.
|
|
323
|
-
|
|
324
|
-
Source: https://github.com/TanStack/table/issues/5860
|
|
325
|
-
|
|
326
|
-
## See also
|
|
327
|
-
|
|
328
|
-
- `tanstack-table/setup` — how `features` (with row model factory slots) threads through `useTable`
|
|
329
|
-
- `tanstack-table/customizing-feature-behavior` — per-column `sortFn`/`filterFn`/`aggregationFn`
|
|
330
|
-
- `tanstack-table/row-selection` — why `getRowId` is essentially mandatory
|