@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.
Files changed (100) hide show
  1. package/README.md +1 -0
  2. package/dist/core/headers/buildHeaderGroups.cjs.map +1 -1
  3. package/dist/core/headers/buildHeaderGroups.d.cts +1 -1
  4. package/dist/core/headers/buildHeaderGroups.d.ts +1 -1
  5. package/dist/core/headers/buildHeaderGroups.js.map +1 -1
  6. package/dist/core/headers/coreHeadersFeature.utils.cjs +7 -7
  7. package/dist/core/headers/coreHeadersFeature.utils.cjs.map +1 -1
  8. package/dist/core/headers/coreHeadersFeature.utils.js +7 -7
  9. package/dist/core/headers/coreHeadersFeature.utils.js.map +1 -1
  10. package/dist/core/table/coreTablesFeature.utils.cjs +1 -1
  11. package/dist/core/table/coreTablesFeature.utils.cjs.map +1 -1
  12. package/dist/core/table/coreTablesFeature.utils.js +1 -1
  13. package/dist/core/table/coreTablesFeature.utils.js.map +1 -1
  14. package/dist/features/column-ordering/columnOrderingFeature.types.d.cts +5 -5
  15. package/dist/features/column-ordering/columnOrderingFeature.types.d.ts +5 -5
  16. package/dist/features/column-ordering/columnOrderingFeature.utils.cjs +6 -6
  17. package/dist/features/column-ordering/columnOrderingFeature.utils.cjs.map +1 -1
  18. package/dist/features/column-ordering/columnOrderingFeature.utils.d.cts +3 -3
  19. package/dist/features/column-ordering/columnOrderingFeature.utils.d.ts +3 -3
  20. package/dist/features/column-ordering/columnOrderingFeature.utils.js +6 -6
  21. package/dist/features/column-ordering/columnOrderingFeature.utils.js.map +1 -1
  22. package/dist/features/column-pinning/columnPinningFeature.cjs +44 -39
  23. package/dist/features/column-pinning/columnPinningFeature.cjs.map +1 -1
  24. package/dist/features/column-pinning/columnPinningFeature.d.cts +6 -1
  25. package/dist/features/column-pinning/columnPinningFeature.d.ts +6 -1
  26. package/dist/features/column-pinning/columnPinningFeature.js +45 -40
  27. package/dist/features/column-pinning/columnPinningFeature.js.map +1 -1
  28. package/dist/features/column-pinning/columnPinningFeature.types.d.cts +49 -38
  29. package/dist/features/column-pinning/columnPinningFeature.types.d.ts +49 -38
  30. package/dist/features/column-pinning/columnPinningFeature.utils.cjs +154 -146
  31. package/dist/features/column-pinning/columnPinningFeature.utils.cjs.map +1 -1
  32. package/dist/features/column-pinning/columnPinningFeature.utils.d.cts +81 -73
  33. package/dist/features/column-pinning/columnPinningFeature.utils.d.ts +81 -73
  34. package/dist/features/column-pinning/columnPinningFeature.utils.js +141 -133
  35. package/dist/features/column-pinning/columnPinningFeature.utils.js.map +1 -1
  36. package/dist/features/column-sizing/columnSizingFeature.cjs +4 -4
  37. package/dist/features/column-sizing/columnSizingFeature.cjs.map +1 -1
  38. package/dist/features/column-sizing/columnSizingFeature.js +5 -5
  39. package/dist/features/column-sizing/columnSizingFeature.js.map +1 -1
  40. package/dist/features/column-sizing/columnSizingFeature.types.d.cts +18 -12
  41. package/dist/features/column-sizing/columnSizingFeature.types.d.ts +18 -12
  42. package/dist/features/column-sizing/columnSizingFeature.utils.cjs +24 -20
  43. package/dist/features/column-sizing/columnSizingFeature.utils.cjs.map +1 -1
  44. package/dist/features/column-sizing/columnSizingFeature.utils.d.cts +18 -14
  45. package/dist/features/column-sizing/columnSizingFeature.utils.d.ts +18 -14
  46. package/dist/features/column-sizing/columnSizingFeature.utils.js +24 -20
  47. package/dist/features/column-sizing/columnSizingFeature.utils.js.map +1 -1
  48. package/dist/features/column-visibility/columnVisibilityFeature.utils.cjs +16 -16
  49. package/dist/features/column-visibility/columnVisibilityFeature.utils.cjs.map +1 -1
  50. package/dist/features/column-visibility/columnVisibilityFeature.utils.d.cts +3 -3
  51. package/dist/features/column-visibility/columnVisibilityFeature.utils.d.ts +3 -3
  52. package/dist/features/column-visibility/columnVisibilityFeature.utils.js +16 -16
  53. package/dist/features/column-visibility/columnVisibilityFeature.utils.js.map +1 -1
  54. package/dist/static-functions.cjs +16 -16
  55. package/dist/static-functions.d.cts +3 -3
  56. package/dist/static-functions.d.ts +3 -3
  57. package/dist/static-functions.js +3 -3
  58. package/package.json +1 -1
  59. package/skills/api-not-found/SKILL.md +113 -0
  60. package/skills/client-vs-server/SKILL.md +164 -0
  61. package/skills/column-faceting/SKILL.md +91 -0
  62. package/skills/column-filtering/SKILL.md +82 -0
  63. package/skills/column-ordering/SKILL.md +75 -0
  64. package/skills/column-pinning/SKILL.md +89 -0
  65. package/skills/column-resizing/SKILL.md +91 -0
  66. package/skills/column-sizing/SKILL.md +72 -0
  67. package/skills/column-visibility/SKILL.md +75 -0
  68. package/skills/core/SKILL.md +140 -0
  69. package/skills/custom-features/SKILL.md +207 -0
  70. package/skills/expanding/SKILL.md +80 -0
  71. package/skills/global-filtering/SKILL.md +84 -0
  72. package/skills/grouping/SKILL.md +50 -394
  73. package/skills/migrate-v8-to-v9/SKILL.md +230 -390
  74. package/skills/pagination/SKILL.md +35 -344
  75. package/skills/row-pinning/SKILL.md +47 -238
  76. package/skills/row-selection/SKILL.md +39 -351
  77. package/skills/sorting/SKILL.md +35 -299
  78. package/skills/table-features/SKILL.md +153 -0
  79. package/skills/typescript/SKILL.md +126 -0
  80. package/src/core/headers/buildHeaderGroups.ts +1 -1
  81. package/src/core/headers/coreHeadersFeature.utils.ts +7 -7
  82. package/src/core/table/coreTablesFeature.utils.ts +1 -1
  83. package/src/features/column-ordering/columnOrderingFeature.types.ts +5 -5
  84. package/src/features/column-ordering/columnOrderingFeature.utils.ts +9 -9
  85. package/src/features/column-pinning/columnPinningFeature.ts +64 -59
  86. package/src/features/column-pinning/columnPinningFeature.types.ts +49 -38
  87. package/src/features/column-pinning/columnPinningFeature.utils.ts +163 -155
  88. package/src/features/column-sizing/columnSizingFeature.ts +6 -6
  89. package/src/features/column-sizing/columnSizingFeature.types.ts +18 -12
  90. package/src/features/column-sizing/columnSizingFeature.utils.ts +31 -27
  91. package/src/features/column-visibility/columnVisibilityFeature.utils.ts +15 -15
  92. package/skills/column-definitions/SKILL.md +0 -330
  93. package/skills/column-layout/SKILL.md +0 -326
  94. package/skills/column-layout/references/subsystems.md +0 -220
  95. package/skills/customizing-feature-behavior/SKILL.md +0 -423
  96. package/skills/filtering/SKILL.md +0 -375
  97. package/skills/filtering/references/faceting-and-fuzzy.md +0 -218
  98. package/skills/row-expanding/SKILL.md +0 -356
  99. package/skills/setup/SKILL.md +0 -390
  100. package/skills/state-management/SKILL.md +0 -403
@@ -1,344 +1,80 @@
1
1
  ---
2
2
  name: sorting
3
3
  description: >
4
- Sort rows in TanStack Table v9 with the `sortedRowModel` stage. Covers
5
- `rowSortingFeature` + `createSortedRowModel()` (registered on `features`), the built-in `sortFns`
6
- registry (renamed from v8 `sortingFns`), `state.sorting` (SortingState =
7
- Array<{ id, desc }>), `onSortingChange`, `columnDef.sortFn`
8
- (string | function | 'auto'), `sortDescFirst`, `sortUndefined`
9
- ('first'|'last'|-1|1|false), `invertSorting`, `enableMultiSort`,
10
- `maxMultiSortColCount`, `isMultiSortEvent`, `table.setSorting` /
11
- `resetSorting`, `column.getToggleSortingHandler` /
12
- `getNextSortingOrder` / `clearSorting` / `getCanSort` / `getCanMultiSort`,
13
- `manualSorting` for server-side, and fuzzy `compareItems` pairing.
14
- type: core
15
- library: tanstack-table
16
- library_version: '9.0.0-alpha.48'
17
- requires:
18
- - state-management
19
- - customizing-feature-behavior
4
+ Sort with rowSortingFeature, sortedRowModel, sortFns, multi-sort and removal options, sortUndefined, and manualSorting. Load for comparator direction, incoming server order, or product-specific sorting cycles.
5
+ metadata:
6
+ {
7
+ type: sub-skill,
8
+ library: '@tanstack/table-core',
9
+ library_version: '9.0.0-beta.42',
10
+ }
11
+ requires: ['core', 'table-features', 'client-vs-server']
20
12
  sources:
21
- - TanStack/table:docs/guide/sorting.md
22
- - TanStack/table:packages/table-core/src/fns/sortFns.ts
23
- - TanStack/table:packages/table-core/src/features/row-sorting/createSortedRowModel.ts
24
- - TanStack/table:packages/table-core/src/features/row-sorting/rowSortingFeature.utils.ts
25
- - TanStack/table:examples/react/sorting/src/main.tsx
13
+ - 'TanStack/table:docs/framework/react/guide/sorting.md'
14
+ - 'TanStack/table:packages/table-core/src/features/row-sorting'
15
+ - 'TanStack/table:examples/react/sorting'
26
16
  ---
27
17
 
28
- This skill builds on `tanstack-table/state-management` and `tanstack-table/customizing-feature-behavior`. Read those first for the atom model and `sortFn` overrides.
18
+ This skill builds on `core`, `table-features`, and `client-vs-server`. Sorting state describes order; client processing requires a sorted model and server processing requires sorted input.
29
19
 
30
20
  ## Setup
31
21
 
32
22
  ```ts
33
23
  import {
34
- tableFeatures,
35
- rowSortingFeature,
36
24
  createSortedRowModel,
25
+ rowSortingFeature,
37
26
  sortFns,
38
- createColumnHelper,
39
- constructTable,
27
+ tableFeatures,
40
28
  } from '@tanstack/table-core'
41
- import type { SortingState } from '@tanstack/table-core'
42
-
43
- type Person = {
44
- firstName: string
45
- lastName: string
46
- age: number
47
- status: 'single' | 'complicated' | 'relationship'
48
- }
49
29
 
50
- const features = tableFeatures({
30
+ export const features = tableFeatures({
51
31
  rowSortingFeature,
52
32
  sortedRowModel: createSortedRowModel(),
53
33
  sortFns,
54
34
  })
55
- const columnHelper = createColumnHelper<typeof features, Person>()
56
-
57
- const columns = columnHelper.columns([
58
- columnHelper.accessor('firstName', { sortFn: 'alphanumeric' }),
59
- columnHelper.accessor('lastName', {
60
- sortUndefined: 'last',
61
- sortDescFirst: false,
62
- }),
63
- columnHelper.accessor('age', { sortFn: 'basic' }),
64
- ])
65
-
66
- const table = constructTable({
67
- features,
68
- columns,
69
- data,
70
- initialState: { sorting: [] satisfies SortingState },
71
- })
72
-
73
- table.setSorting([{ id: 'age', desc: true }])
74
35
  ```
75
36
 
76
37
  ## Core Patterns
77
38
 
78
- ### Clickable header sorting with multi-sort on Shift+click
79
-
80
- ```tsx
81
- // From examples/react/sorting/src/main.tsx
82
- {
83
- headerGroup.headers.map((header) => (
84
- <th
85
- key={header.id}
86
- onClick={header.column.getToggleSortingHandler()}
87
- style={{ cursor: header.column.getCanSort() ? 'pointer' : 'default' }}
88
- >
89
- <table.FlexRender header={header} />
90
- {{ asc: ' 🔼', desc: ' 🔽' }[header.column.getIsSorted() as string] ??
91
- null}
92
- </th>
93
- ))
94
- }
95
- ```
96
-
97
- `getToggleSortingHandler` already handles multi-sort when the user holds Shift (configurable via `isMultiSortEvent`).
98
-
99
- ### Custom `sortFn` for an enum
100
-
101
39
  ```ts
102
- // From examples/react/sorting/src/main.tsx
103
- const sortStatusFn: SortFn<typeof features, Person> = (
104
- rowA,
105
- rowB,
106
- _columnId,
107
- ) => {
108
- const statusOrder = ['single', 'complicated', 'relationship']
109
- return (
110
- statusOrder.indexOf(rowA.original.status) -
111
- statusOrder.indexOf(rowB.original.status)
112
- )
113
- }
114
-
115
- columnHelper.accessor('status', { sortFn: sortStatusFn })
116
- ```
117
-
118
- Always return an ascending-order comparison. The row model multiplies by `-1` for descending and again for `invertSorting`.
119
-
120
- ### Direction control with `sortUndefined` and `invertSorting`
121
-
122
- ```ts
123
- columnHelper.accessor('rank', {
124
- invertSorting: true, // rank 1 above rank 2 even when "descending"
125
- })
126
-
127
- columnHelper.accessor('lastName', {
128
- sortUndefined: 'last', // ABSOLUTE: end regardless of asc/desc
129
- sortDescFirst: false,
130
- })
40
+ const options = { enableSortingRemoval: false, enableMultiSort: true }
41
+ const numericColumn = { sortUndefined: 'last' as const }
131
42
  ```
132
43
 
133
- `sortUndefined` literals (`'first'`, `'last'`) are absolute. Numeric (`-1`, `1`) flips with `desc`.
134
-
135
- ### Server-side sorting
136
-
137
- ```tsx
138
- const [sorting, setSorting] = useState<SortingState>([])
139
- const { data } = useQuery({
140
- queryKey: ['rows', sorting],
141
- queryFn: () =>
142
- fetch('/api/rows?sort=' + serialize(sorting)).then((r) => r.json()),
143
- })
144
-
145
- const table = useTable({
146
- features: tableFeatures({ rowSortingFeature }),
147
- // omit sortedRowModel from features — server sorts
148
- columns,
149
- data,
150
- manualSorting: true,
151
- state: { sorting },
152
- onSortingChange: setSorting,
153
- })
154
- ```
44
+ Configure sort cycles and undefined placement to match the product rather than relying on implicit defaults.
155
45
 
156
46
  ## Common Mistakes
157
47
 
158
- ### [HIGH] Using v8 `sortingFn` / `sortingFns` names
159
-
160
- Wrong:
161
-
162
- ```tsx
163
- {
164
- accessorKey: 'fullName',
165
- sortingFn: 'alphanumeric', // v8 name — falls through to sortFn_basic
166
- }
167
- // useTable({ sortingFns: { ...sortingFns, myFn } }) // v8 option name
168
- ```
169
-
170
- Correct:
171
-
172
- ```tsx
173
- import { sortFns, createSortedRowModel } from '@tanstack/react-table'
174
-
175
- columnHelper.accessor('firstName', {
176
- sortFn: 'alphanumeric',
177
- })
178
-
179
- const features = tableFeatures({
180
- rowSortingFeature,
181
- sortedRowModel: createSortedRowModel(),
182
- sortFns: {
183
- ...sortFns,
184
- myCustom: (a, b, id) => a.original[id] - b.original[id],
185
- },
186
- })
187
-
188
- const table = useTable({ features, columns, data })
189
- ```
190
-
191
- v9 renamed `columnDef.sortingFn → sortFn`, the fn registry slot `sortingFns → sortFns` (now registered on `features`), exported registry `sortingFns → sortFns`. The new column option defaults to `'auto'` and falls back to `sortFn_basic` when lookup misses — wrong names sort wrong, silently.
192
-
193
- Source: packages/table-core/src/features/row-sorting/rowSortingFeature.utils.ts
194
-
195
- ### [MEDIUM] Expecting `sortUndefined: 'first' | 'last'` to work in v8
48
+ ### [CRITICAL] Expecting manual mode to reorder
196
49
 
197
- Wrong:
50
+ Wrong: `const options = { data: unsortedRows, manualSorting: true }`
198
51
 
199
- ```tsx
200
- // agent assumes numeric and literal forms are interchangeable
201
- { accessorKey: 'lastName', sortUndefined: -1 } // ascending-first, descending-LAST
202
- ```
203
-
204
- Correct:
205
-
206
- ```tsx
207
- // From examples/react/sorting/src/main.tsx
208
- columnHelper.accessor((row) => row.lastName, {
209
- id: 'lastName',
210
- sortUndefined: 'last', // ABSOLUTE: always at end regardless of asc/desc
211
- sortDescFirst: false,
212
- })
213
- ```
214
-
215
- v8 only had `false | -1 | 1`. v9 added `'first'` / `'last'`. Numeric flips with `desc`; literals are absolute.
216
-
217
- Source: packages/table-core/src/features/row-sorting/createSortedRowModel.ts
218
-
219
- ### [MEDIUM] Custom `sortFn` factors `desc` in itself
220
-
221
- Wrong:
222
-
223
- ```tsx
224
- // takes sort direction into account, breaks the toggle
225
- const customSort: SortFn<any, any> = (a, b, id, desc) => {
226
- // desc isn't even a parameter — agents try to detect via state
227
- const cmp = a.original[id] - b.original[id]
228
- return desc ? -cmp : cmp
229
- }
230
- ```
231
-
232
- Correct:
233
-
234
- ```tsx
235
- // From examples/react/sorting/src/main.tsx
236
- // Always return ascending; the row model handles desc & invertSorting.
237
- const sortStatusFn: SortFn<any, any> = (rowA, rowB, _columnId) => {
238
- const statusOrder = ['single', 'complicated', 'relationship']
239
- return (
240
- statusOrder.indexOf(rowA.original.status) -
241
- statusOrder.indexOf(rowB.original.status)
242
- )
243
- }
244
- ```
245
-
246
- From the docs guide: "The comparison function does not need to take whether or not the column is in descending or ascending order into account. The row models will take care of that logic." Doubly-flipping yields broken toggles.
247
-
248
- Source: packages/table-core/src/features/row-sorting/createSortedRowModel.ts
249
-
250
- ### [MEDIUM] Fuzzy filter without a fuzzy-aware `sortFn`
251
-
252
- Wrong:
253
-
254
- ```ts
255
- columnHelper.accessor('fullName', {
256
- filterFn: 'fuzzy',
257
- // BUG: rows sort alphabetically, not by match rank
258
- })
259
- ```
260
-
261
- Correct:
52
+ Correct: `const options = { data: serverSortedRows, manualSorting: true }`
262
53
 
263
- ```ts
264
- import { compareItems } from '@tanstack/match-sorter-utils'
265
-
266
- const fuzzySort: SortFn<typeof features, Person> = (rowA, rowB, columnId) => {
267
- let dir = 0
268
- if (rowA.columnFiltersMeta[columnId]) {
269
- dir = compareItems(
270
- rowA.columnFiltersMeta[columnId].itemRank!,
271
- rowB.columnFiltersMeta[columnId].itemRank!,
272
- )
273
- }
274
- return dir === 0 ? sortFns.alphanumeric(rowA, rowB, columnId) : dir
275
- }
276
-
277
- columnHelper.accessor('fullName', { filterFn: 'fuzzy', sortFn: fuzzySort })
278
- ```
279
-
280
- The fuzzy filter writes `{ itemRank }` into `row.columnFiltersMeta[columnId]` via `addMeta`. Without a sortFn that reads it, results sort alphabetically and defeat the fuzzy ranking.
54
+ Manual sorting bypasses `sortedRowModel` and trusts incoming order.
281
55
 
282
- Source: examples/react/filters-fuzzy/src/main.tsx
56
+ Source: `packages/table-core/src/features/row-sorting/rowSortingFeature.types.ts`
283
57
 
284
- ### [MEDIUM] `getCanSort` returns false for display columns under `manualSorting`
58
+ ### [HIGH] Reversing inside the comparator
285
59
 
286
- Wrong:
60
+ Wrong: `const newest: SortFn<any, any> = (a, b, id) => b.getValue<number>(id) - a.getValue<number>(id)`
287
61
 
288
- ```ts
289
- // getCanSort() returns false even though manualSorting is true
290
- const table = useTable({
291
- manualSorting: true,
292
- columns: [
293
- { id: 'computed', header: 'Computed', cell: (info) => row.x + row.y },
294
- ],
295
- })
296
- ```
62
+ Correct: `const numeric: SortFn<any, any> = (a, b, id) => a.getValue<number>(id) - b.getValue<number>(id)`
297
63
 
298
- Correct:
64
+ Return ascending comparison only; Table reverses it when sorting is descending.
299
65
 
300
- ```ts
301
- columnHelper.display({
302
- id: 'computed',
303
- header: 'Computed',
304
- enableSorting: true, // force-enable for manualSorting
305
- cell: (info) => info.row.original.x + info.row.original.y,
306
- })
307
- ```
66
+ Source: `docs/framework/react/guide/sorting.md#custom-sorting-functions`
308
67
 
309
- `getCanSort` checks for `accessorKey`/`accessorFn` even under `manualSorting`. Force it on display columns via `enableSorting: true` (and let the server sort).
68
+ ### [MEDIUM] Leaving ambiguous sort policy
310
69
 
311
- Source: https://github.com/TanStack/table/issues/4136
70
+ Wrong: `const options = { enableSortingRemoval: true }`
312
71
 
313
- ### [CRITICAL] Reimplementing what built-in APIs provide
72
+ Correct: `const options = { enableSortingRemoval: false }; const rankColumn = { sortUndefined: 'last' as const }`
314
73
 
315
- Wrong:
316
-
317
- ```ts
318
- const [sorting, setSorting] = useState([])
319
- const sortedData = useMemo(
320
- () => [...data].sort(/* …custom… */),
321
- [data, sorting],
322
- )
323
- // then uses sortedData directly, bypassing the table
324
- ```
325
-
326
- Correct:
327
-
328
- ```ts
329
- const features = tableFeatures({
330
- rowSortingFeature,
331
- sortedRowModel: createSortedRowModel(),
332
- sortFns,
333
- })
334
- const table = useTable({ features, columns, data })
335
- // table.setSorting(...), column.toggleSorting(), header.getToggleSortingHandler()
336
- ```
74
+ Undefined placement and removal cycles can differ from expected product behavior unless configured.
337
75
 
338
- Source: maintainer interview (Phase 4, 2026-05-17)
76
+ Source: `packages/table-core/src/features/row-sorting/rowSortingFeature.types.ts`
339
77
 
340
- ## See also
78
+ ## API Discovery
341
79
 
342
- - `tanstack-table/customizing-feature-behavior` `sortFn` authoring + `addMeta` chain
343
- - `tanstack-table/filtering` — fuzzy filter pattern that pairs with `fuzzySort`
344
- - `tanstack-table/state-management` — `manualSorting` + server-side state ownership
80
+ Inspect `node_modules/@tanstack/table-core/src/features/row-sorting/` and `src/fns/sortFns.ts` for current names and comparator contracts.
@@ -0,0 +1,153 @@
1
+ ---
2
+ name: table-features
3
+ description: >
4
+ Register TanStack Table v9 tableFeatures, feature plugins, create*RowModel factories, and function registries in prerequisite order. Load when an option, state slice, or instance API is missing, or when choosing explicit features versus stockFeatures.
5
+ metadata:
6
+ type: sub-skill
7
+ library: '@tanstack/table-core'
8
+ library_version: '9.0.0-beta.42'
9
+ requires: ['core']
10
+ sources:
11
+ - 'TanStack/table:docs/guide/row-models.md'
12
+ - 'TanStack/table:packages/table-core/src/types/TableFeatures.ts'
13
+ - 'TanStack/table:packages/table-core/src/features/stockFeatures.ts'
14
+ - 'TanStack/table:packages/table-core/src/core/table/constructTable.ts'
15
+ ---
16
+
17
+ This skill builds on `core`. Read it first for the headless model and stable inputs.
18
+
19
+ ## Setup
20
+
21
+ <!-- skill-snippet:check -->
22
+
23
+ ```ts
24
+ import {
25
+ aggregationFns,
26
+ columnGroupingFeature,
27
+ createFilteredRowModel,
28
+ createSortedRowModel,
29
+ columnFilteringFeature,
30
+ filterFns,
31
+ rowSortingFeature,
32
+ sortFns,
33
+ tableFeatures,
34
+ } from '@tanstack/table-core'
35
+
36
+ export const features = tableFeatures({
37
+ columnFilteringFeature,
38
+ filteredRowModel: createFilteredRowModel(),
39
+ filterFns,
40
+ columnGroupingFeature,
41
+ aggregationFns,
42
+ rowSortingFeature,
43
+ sortedRowModel: createSortedRowModel(),
44
+ sortFns,
45
+ })
46
+ ```
47
+
48
+ ## Core Patterns
49
+
50
+ ### Register feature before its dependent slot
51
+
52
+ ```ts
53
+ const features = tableFeatures({
54
+ rowSortingFeature,
55
+ sortedRowModel: createSortedRowModel(),
56
+ })
57
+ ```
58
+
59
+ `tableFeatures` checks slot prerequisites and its inferred type gates APIs throughout the table.
60
+
61
+ ### Register named function slots with their features
62
+
63
+ ```ts
64
+ const features = tableFeatures({
65
+ columnFilteringFeature,
66
+ filterFns,
67
+ rowSortingFeature,
68
+ sortFns,
69
+ columnGroupingFeature,
70
+ aggregationFns,
71
+ })
72
+ ```
73
+
74
+ `filterFns`, `sortFns`, and `aggregationFns` are feature slots, not table
75
+ options. They respectively require `columnFilteringFeature`,
76
+ `rowSortingFeature`, and `columnGroupingFeature`. A registered key can be used
77
+ as a typed string name; pass a function directly when no registry name is
78
+ needed.
79
+
80
+ ### Prefer explicit features
81
+
82
+ ```ts
83
+ const features = tableFeatures({ columnFilteringFeature })
84
+ ```
85
+
86
+ Use `stockFeatures` only for deliberate kitchen-sink or temporary migration behavior.
87
+
88
+ ## Common Mistakes
89
+
90
+ ### [CRITICAL] Calling an unregistered feature API
91
+
92
+ Wrong:
93
+
94
+ ```ts
95
+ const features = tableFeatures({})
96
+ table.setSorting([{ id: 'name', desc: false }])
97
+ ```
98
+
99
+ Correct:
100
+
101
+ ```ts
102
+ const features = tableFeatures({ rowSortingFeature })
103
+ ```
104
+
105
+ Optional feature state and APIs are installed only when their feature is registered.
106
+
107
+ Source: `packages/table-core/src/core/table/constructTable.ts`
108
+
109
+ ### [HIGH] Omitting a slot prerequisite
110
+
111
+ Wrong:
112
+
113
+ ```ts
114
+ const features = tableFeatures({ sortedRowModel: createSortedRowModel() })
115
+ ```
116
+
117
+ Correct:
118
+
119
+ ```ts
120
+ const features = tableFeatures({
121
+ rowSortingFeature,
122
+ sortedRowModel: createSortedRowModel(),
123
+ })
124
+ ```
125
+
126
+ The sorted model slot requires `rowSortingFeature`; the same rule applies to every mapped slot.
127
+
128
+ Source: `packages/table-core/src/types/TableFeatures.ts#FeatureSlotPrereqs`
129
+
130
+ ### [MEDIUM] Shipping all features by default
131
+
132
+ Wrong:
133
+
134
+ ```ts
135
+ const features = stockFeatures
136
+ ```
137
+
138
+ Correct:
139
+
140
+ ```ts
141
+ const features = tableFeatures({
142
+ rowSortingFeature,
143
+ sortedRowModel: createSortedRowModel(),
144
+ })
145
+ ```
146
+
147
+ `stockFeatures` registers every stock plugin and processing slot, defeating v9's normal tree-shaking strategy.
148
+
149
+ Source: `packages/table-core/src/features/stockFeatures.ts`
150
+
151
+ ## API Discovery
152
+
153
+ Inspect `node_modules/@tanstack/table-core/src/types/TableFeatures.ts` for current slots and `FeatureSlotPrereqs`, and `src/features/stockFeatures.ts` for the stock inventory.
@@ -0,0 +1,126 @@
1
+ ---
2
+ name: typescript
3
+ description: >
4
+ Preserve TanStack Table v9 inference with createColumnHelper, columns(), tableOptions, tableFeatures, and metaHelper. Load for ColumnDef errors, reusable tables, typed meta, named registries, or unnecessary manual feature generics.
5
+ metadata:
6
+ type: sub-skill
7
+ library: '@tanstack/table-core'
8
+ library_version: '9.0.0-beta.42'
9
+ requires: ['core', 'table-features']
10
+ sources:
11
+ - 'TanStack/table:docs/guide/helpers.md'
12
+ - 'TanStack/table:docs/guide/column-defs.md'
13
+ - 'TanStack/table:docs/guide/table-and-column-meta.md'
14
+ - 'TanStack/table:packages/table-core/src/helpers'
15
+ ---
16
+
17
+ This skill builds on `core` and `table-features`. Let the feature object and helpers carry types through userland.
18
+
19
+ ## Setup
20
+
21
+ ```ts
22
+ import {
23
+ createColumnHelper,
24
+ metaHelper,
25
+ tableFeatures,
26
+ } from '@tanstack/table-core'
27
+
28
+ type Person = { id: string; age: number }
29
+ type ColumnMeta = { align?: 'start' | 'end' }
30
+ const features = tableFeatures({ columnMeta: metaHelper<ColumnMeta>() })
31
+ const helper = createColumnHelper<typeof features, Person>()
32
+ export const columns = helper.columns([
33
+ helper.accessor('age', { meta: { align: 'end' } }),
34
+ ])
35
+ ```
36
+
37
+ ## Core Patterns
38
+
39
+ ### Preserve heterogeneous accessor values
40
+
41
+ ```ts
42
+ const columns = helper.columns([
43
+ helper.accessor('id', { header: 'ID' }),
44
+ helper.accessor('age', { header: 'Age' }),
45
+ ])
46
+ ```
47
+
48
+ `columns()` preserves each accessor's `TValue` instead of widening the array.
49
+
50
+ ### Compose options through the helper
51
+
52
+ ```ts
53
+ const defaults = tableOptions<typeof features, Person>({
54
+ defaultColumn: { meta: { align: 'start' } },
55
+ })
56
+ ```
57
+
58
+ Use `tableOptions` for reusable fragments; direct adapter options are enough for one-offs.
59
+
60
+ ## Common Mistakes
61
+
62
+ ### [HIGH] Erasing accessor value inference
63
+
64
+ Wrong:
65
+
66
+ ```ts
67
+ const columns: ColumnDef<typeof features, Person, unknown>[] = [
68
+ helper.accessor('age', {}),
69
+ ]
70
+ ```
71
+
72
+ Correct:
73
+
74
+ ```ts
75
+ const columns = helper.columns([helper.accessor('age', {})])
76
+ ```
77
+
78
+ The broad annotation discards the accessor-specific `number` value type.
79
+
80
+ Source: `docs/guide/helpers.md#createcolumnhelper`
81
+
82
+ ### [MEDIUM] Threading internal feature generics manually
83
+
84
+ Wrong:
85
+
86
+ ```ts
87
+ type Features = TableFeatures
88
+ ```
89
+
90
+ Correct:
91
+
92
+ ```ts
93
+ type Features = typeof features
94
+ ```
95
+
96
+ The concrete registry is the source of feature-gated APIs and registry keys.
97
+
98
+ Source: `packages/table-core/src/types/TableFeatures.ts`
99
+
100
+ ### [MEDIUM] Globally merging per-table meta
101
+
102
+ Wrong:
103
+
104
+ ```ts
105
+ declare module '@tanstack/table-core' {
106
+ interface ColumnMeta<TData, TValue> {
107
+ align?: string
108
+ }
109
+ }
110
+ ```
111
+
112
+ Correct:
113
+
114
+ ```ts
115
+ const features = tableFeatures({
116
+ columnMeta: metaHelper<{ align?: 'start' | 'end' }>(),
117
+ })
118
+ ```
119
+
120
+ V9 type-only feature slots keep meta types scoped to the table factory.
121
+
122
+ Source: `docs/guide/table-and-column-meta.md`
123
+
124
+ ## API Discovery
125
+
126
+ Inspect `node_modules/@tanstack/table-core/src/helpers/` and the signatures re-exported by `src/index.ts`; avoid copying deep internal generic signatures into application code.
@@ -21,7 +21,7 @@ export function buildHeaderGroups<
21
21
  allColumns: Array<Column<TFeatures, TData, TValue>>,
22
22
  columnsToGroup: Array<Column<TFeatures, TData, TValue>>,
23
23
  table: Table_Internal<TFeatures, TData>,
24
- headerFamily?: 'center' | 'left' | 'right',
24
+ headerFamily?: 'center' | 'start' | 'end',
25
25
  ) {
26
26
  // Find the max depth of the columns:
27
27
  // build the leaf column row