@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,492 +1,332 @@
1
1
  ---
2
2
  name: migrate-v8-to-v9
3
3
  description: >
4
- Mechanical breaking-change migration from TanStack Table v8 to v9 at the
5
- `@tanstack/table-core` level. Covers hook/entry rename
6
- (`useReactTable`/`createSolidTable`/… → `useTable`/`injectTable`/`createTable`/
7
- `constructTable`), the new required `features` option (which now carries row
8
- model factories and fn registries — `rowModels` option is removed),
9
- `createColumnHelper<TData>()` `createColumnHelper<typeof features, TData>()`,
10
- row-model factory rename (`getCoreRowModel()` → automatic; `getSortedRowModel()`
11
- → `createSortedRowModel()` as a slot on `tableFeatures({...})` with `sortFns` also
12
- a slot; same for filtered/paginated/grouped/expanded/faceted), `table.getState()` → `table.store.state` / `table.atoms.<slice>.get()`,
13
- sorting renames (`sortingFn` → `sortFn`, etc.), `enablePinning` split, column
14
- sizing/resizing split, underscore-prefixed APIs becoming public, `RowData`
15
- type tightening, TFeatures-first generics, the `useLegacyTable` React escape
16
- hatch (deprecated, removed in v10), and the `stockFeatures` v8-style "everything
17
- on" registry.
18
- type: lifecycle
19
- library: tanstack-table
20
- library_version: '9.0.0-alpha.48'
21
- requires:
22
- - setup
23
- - state-management
24
- - column-definitions
4
+ Perform a complete TanStack Table v8-to-v9 migration audit: feature registration, row-model and function-registry slots, state/store changes, prototype methods, column pinning and resizing renames, sorting and selection semantics, removed internals, helpers, meta typing, and generic changes. Load this shared inventory before the installed framework adapter's migration skill.
5
+ metadata:
6
+ type: lifecycle
7
+ library: '@tanstack/table-core'
8
+ library_version: '9.0.0-beta.42'
9
+ requires: ['core', 'table-features', 'typescript']
25
10
  sources:
26
- - TanStack/table:docs/framework/table-core/guide/migrating.md
27
- - TanStack/table:docs/framework/react/guide/use-legacy-table.md
28
- - TanStack/table:packages/react-table/src/legacy.ts
11
+ - 'TanStack/table:docs/framework/react/guide/migrating.md'
12
+ - 'TanStack/table:docs/framework/preact/guide/migrating.md'
13
+ - 'TanStack/table:docs/framework/solid/guide/migrating.md'
14
+ - 'TanStack/table:docs/framework/svelte/guide/migrating.md'
15
+ - 'TanStack/table:docs/framework/vue/guide/migrating.md'
16
+ - 'TanStack/table:docs/framework/angular/guide/migrating.md'
17
+ - 'TanStack/table:docs/framework/lit/guide/migrating.md'
18
+ - 'TanStack/table:packages/table-core/src/index.ts'
19
+ - 'TanStack/table:packages/table-core/src/types/TableFeatures.ts'
20
+ - 'TanStack/table:packages/table-core/src/features/column-pinning/columnPinningFeature.types.ts'
21
+ - 'TanStack/table:packages/table-core/src/features/column-resizing/columnResizingFeature.types.ts'
22
+ - 'TanStack/table:packages/react-table/src/legacy.ts'
29
23
  ---
30
24
 
31
- ## Setup
25
+ Apply this complete shared inventory before loading the installed adapter's `migrate-v8-to-v9` skill. The adapter skill owns hook/controller construction, reactive inputs, rendering helpers, and framework subscription APIs.
32
26
 
33
- v9 is a substantial reshape, not a tweak. The breaking changes group into:
27
+ ## Migration strategy
34
28
 
35
- 1. **Hook/entry rename** per adapter.
36
- 2. **`features` is required** — features are tree-shaken. Row model factories and fn registries (`sortFns`, `filterFns`, `aggregationFns`) now live as slots on the `features` object; the `rowModels` option is gone.
37
- 3. **Column helper generic order** `<TFeatures, TData>` not `<TData>`.
38
- 4. **Row-model factories** moved out of root options and into `tableFeatures({...})` as named slots; factory args for `*Fns` are replaced by dedicated fn-registry slots on `features`.
39
- 5. **State surface renamed** — `table.getState()` → `table.store.state` / `table.atoms.<slice>.get()` / `table.state` (selector).
40
- 6. **Sorting names**: `sortingFn` `sortFn`, `sortingFns` `sortFns`, `getSortingFn()` → `getSortFn()`, type `SortingFn` → `SortFn`.
41
- 7. **`enablePinning` split** into `enableColumnPinning` + `enableRowPinning` (table-level); per-column `enablePinning` stays.
42
- 8. **Column resizing split out** of column sizing. `columnSizingInfo` state → `columnResizing`. `onColumnSizingInfoChange` → `onColumnResizingChange`.
43
- 9. **Underscore-prefixed APIs are public now** — drop the `_` prefix (`row._getAllCellsByColumnId()` → `row.getAllCellsByColumnId()`, `table._getFacetedRowModel()` → public, etc.).
44
- 10. **Generics now lead with `TFeatures`** — `Column<TFeatures, TData, TValue>`, `Row<TFeatures, TData>`, `ColumnMeta<TFeatures, TData, TValue>`.
45
- 11. **`RowData` tightened** from `unknown | object | any[]` to `Record<string, any> | Array<any>`.
46
- 12. **`data` and `columns` are readonly** in v9 — flow changes through state, don't mutate.
29
+ 1. Make the v8 table pass its existing tests before changing it.
30
+ 2. Migrate construction and features while preserving behavior.
31
+ 3. Let TypeScript expose missing features and stale names.
32
+ 4. Migrate state ownership and rendering through the adapter skill.
33
+ 5. Test every enabled client/server row-model stage and interaction.
34
+ 6. Replace temporary `stockFeatures` usage with explicit features when practical.
47
35
 
48
- For React projects that cannot migrate every table at once, `useLegacyTable` from `@tanstack/react-table/legacy` accepts the v8 shape on top of the v9 engine. Deprecated, ships every feature, no `table.Subscribe`. Removed in v10.
36
+ Treat `useLegacyTable` as a deprecated, React-only emergency bridge. It bundles every feature, can exceed the v8 bundle, and must not become the target architecture. Import it only from `@tanstack/react-table/legacy` when an existing incremental migration requires it.
49
37
 
50
- ## Core Patterns
51
-
52
- ### Full v9 equivalent for the most common v8 shape
38
+ ## Minimal v9 shape
53
39
 
54
40
  ```ts
55
- // === v9 (correct) ===
56
41
  import {
57
- useTable,
58
- tableFeatures,
59
- rowSortingFeature,
60
- rowPaginationFeature,
61
- columnFilteringFeature,
62
- columnSizingFeature,
63
- columnResizingFeature,
64
- createColumnHelper,
65
- createSortedRowModel,
66
42
  createFilteredRowModel,
67
- createPaginatedRowModel,
68
- sortFns,
69
- filterFns,
70
- } from '@tanstack/react-table'
71
- import type { ColumnDef } from '@tanstack/react-table'
72
-
73
- const features = tableFeatures({
74
- rowSortingFeature,
75
- rowPaginationFeature,
43
+ createSortedRowModel,
76
44
  columnFilteringFeature,
77
- columnSizingFeature,
78
- columnResizingFeature, // explicit — formerly part of ColumnSizing
79
- // Row model factories and fn registries are slots on features, not rowModels.
80
- sortedRowModel: createSortedRowModel(),
81
- filteredRowModel: createFilteredRowModel(),
82
- paginatedRowModel: createPaginatedRowModel(),
83
- sortFns,
84
45
  filterFns,
85
- })
86
-
87
- const columnHelper = createColumnHelper<typeof features, Person>()
88
-
89
- const columns: ColumnDef<typeof features, Person>[] = columnHelper.columns([
90
- columnHelper.accessor('name', {
91
- header: 'Name',
92
- sortFn: 'alphanumeric', // renamed from sortingFn
93
- }),
94
- ])
95
-
96
- const table = useTable({
97
- features,
98
- columns,
99
- data,
100
- enableColumnPinning: true, // split from enablePinning
101
- enableRowPinning: true,
102
- })
103
-
104
- // State reads
105
- const allState = table.store.state // full snapshot
106
- const sorting = table.atoms.sorting.get() // per-slice atom
107
- const cells = row.getAllCellsByColumnId() // no underscore
108
-
109
- // Rendering
110
- // <table.FlexRender header={header} />
111
- // <table.FlexRender cell={cell} />
112
- ```
113
-
114
- ### v8 muscle-memory anti-shape
115
-
116
- ```ts
117
- // === v8 muscle memory — every line is broken in v9. ===
118
- import {
119
- useReactTable, // (1) renamed → useTable
120
- getCoreRowModel, // (2) no longer a root option
121
- getFilteredRowModel, // move to rowModels as factories
122
- getSortedRowModel, // createSortedRowModel(sortFns) etc.
123
- getPaginationRowModel,
124
- createColumnHelper, // (3) needs <TFeatures, TData> now
125
- sortingFns, // (4) renamed → sortFns
126
- filterFns,
127
- flexRender, // still exists, prefer table.FlexRender
128
- } from '@tanstack/react-table'
129
- import type { ColumnDef, Row } from '@tanstack/react-table'
130
-
131
- const columnHelper = createColumnHelper<Person>() // wrong arity
132
-
133
- const columns: ColumnDef<Person>[] = [
134
- // (5) ColumnDef<TFeatures, TData, TValue> now
135
- { accessorKey: 'name', header: 'Name', sortingFn: 'alphanumeric' }, // (6) renamed → sortFn
136
- ]
137
-
138
- const table = useReactTable({
139
- columns,
140
- data,
141
- getCoreRowModel: getCoreRowModel(), // (2) move into rowModels
142
- getFilteredRowModel: getFilteredRowModel(),
143
- getSortedRowModel: getSortedRowModel(),
144
- getPaginationRowModel: getPaginationRowModel(),
145
- filterFns, // (7) no longer a root option
146
- sortingFns, // (4)+(7)
147
- enablePinning: true, // (8) split → enableColumnPinning / enableRowPinning
148
- onColumnSizingInfoChange: setInfo, // (9) renamed → onColumnResizingChange
149
- })
150
-
151
- const all = table.getState() // (10) → table.store.state
152
- const cells = row._getAllCellsByColumnId() // underscore removed
153
- ```
154
-
155
- ### Transitional `useLegacyTable` (React only)
156
-
157
- ```ts
158
- import {
159
- useLegacyTable,
160
- getCoreRowModel,
161
- legacyCreateColumnHelper,
162
- } from '@tanstack/react-table/legacy'
163
-
164
- const legacyHelper = legacyCreateColumnHelper<Person>()
165
- const legacyTable = useLegacyTable({
166
- columns,
167
- data,
168
- getCoreRowModel: getCoreRowModel(),
169
- })
170
- ```
171
-
172
- This accepts the v8 shape on top of the v9 engine. Deprecated, ships every feature, no `table.Subscribe`, no atoms. Removed in v10. Use to unblock incremental migration only — not as a long-term API. Angular has no `useLegacyTable` equivalent; Angular projects must migrate directly.
173
-
174
- ## Common Mistakes
175
-
176
- ### [CRITICAL] Hallucinating react-table v7 / pre-v9 API names
177
-
178
- Wrong:
179
-
180
- ```ts
181
- // v7
182
- import { useTable, useSortBy } from 'react-table'
183
- const table = useTable({ columns, data }, useSortBy)
184
-
185
- // v8
186
- import { useReactTable, getCoreRowModel } from '@tanstack/react-table'
187
- const table = useReactTable({
188
- columns,
189
- data,
190
- getCoreRowModel: getCoreRowModel(),
191
- })
192
- ```
193
-
194
- Correct:
195
-
196
- ```ts
197
- import {
198
- useTable,
199
- tableFeatures,
200
46
  rowSortingFeature,
201
- createSortedRowModel,
202
47
  sortFns,
203
- } from '@tanstack/react-table'
48
+ tableFeatures,
49
+ } from '@tanstack/table-core'
204
50
 
205
- const features = tableFeatures({
51
+ export const features = tableFeatures({
52
+ columnFilteringFeature,
206
53
  rowSortingFeature,
54
+ filteredRowModel: createFilteredRowModel(),
207
55
  sortedRowModel: createSortedRowModel(),
56
+ filterFns,
208
57
  sortFns,
209
58
  })
210
- const table = useTable({ features, columns, data })
211
59
  ```
212
60
 
213
- Every major release of TanStack Table has been a substantial upgrade. Agents trained on v7 or v8 will confidently emit shapes that no longer exist. This is the #2 AI failure (after reimplementing built-ins).
61
+ Pass `features` to the adapter's v9 table constructor. Define it statically outside render/setup work when possible.
214
62
 
215
- Source: maintainer interview (Phase 4, 2026-05-17)
63
+ ## Complete shared breaking-change inventory
216
64
 
217
- ### [CRITICAL] Importing pre-bundled `getCoreRowModel` / `getSortedRowModel` etc.
65
+ ### 1. Register every non-core feature explicitly
218
66
 
219
- Wrong:
67
+ V8 bundled all stock features. V9 exposes an API only when its feature is present in `tableFeatures({...})`.
220
68
 
221
- ```ts
222
- // v8 pattern won't drive v9 row models
223
- const table = useTable({
224
- features,
225
- data,
226
- columns,
227
- getCoreRowModel: getCoreRowModel(),
228
- getSortedRowModel: getSortedRowModel(),
229
- })
230
- ```
69
+ | Capability | V9 feature |
70
+ | --------------------------- | ------------------------- |
71
+ | Column faceting | `columnFacetingFeature` |
72
+ | Column filtering | `columnFilteringFeature` |
73
+ | Grouping and aggregation | `columnGroupingFeature` |
74
+ | Column ordering | `columnOrderingFeature` |
75
+ | Column pinning | `columnPinningFeature` |
76
+ | Interactive column resizing | `columnResizingFeature` |
77
+ | Column sizes and offsets | `columnSizingFeature` |
78
+ | Column visibility | `columnVisibilityFeature` |
79
+ | Global filtering | `globalFilteringFeature` |
80
+ | Row expansion | `rowExpandingFeature` |
81
+ | Pagination | `rowPaginationFeature` |
82
+ | Row pinning | `rowPinningFeature` |
83
+ | Row selection | `rowSelectionFeature` |
84
+ | Sorting | `rowSortingFeature` |
231
85
 
232
- Correct:
86
+ The core row model and core table/row/column/header/cell behavior are automatic. `stockFeatures` restores a v8-like all-features surface, but use it as an audit shortcut rather than the default production recommendation.
233
87
 
234
- ```ts
235
- import {
236
- useTable,
237
- tableFeatures,
238
- rowSortingFeature,
239
- createSortedRowModel,
240
- sortFns,
241
- } from '@tanstack/react-table'
88
+ Honor feature prerequisites in the same `tableFeatures` call:
242
89
 
243
- const features = tableFeatures({
244
- rowSortingFeature,
245
- sortedRowModel: createSortedRowModel(),
246
- sortFns,
247
- })
248
- const table = useTable({ features, columns, data })
249
- ```
90
+ - `columnResizingFeature` requires `columnSizingFeature`.
91
+ - `globalFilteringFeature` requires `columnFilteringFeature`.
92
+ - Every row-model or function-registry slot requires its associated feature.
93
+ - Put prerequisite feature properties before dependent slots so inference and diagnostics remain clear.
250
94
 
251
- In v9, row model factories are slots on `features`: `filteredRowModel: createFilteredRowModel()`, `sortedRowModel: createSortedRowModel()`, `groupedRowModel: createGroupedRowModel()`. The fn registries move too: `filterFns`, `sortFns`, `aggregationFns` are named slots on `features`. Core is automatic.
95
+ ### 2. Move row models into feature slots and rename factories
252
96
 
253
- Source: PR #6234 (atoms refactor); packages/table-core/src/index.ts
97
+ V8 `get*RowModel()` table options and the earlier-v9-beta `rowModels` object are gone. V9 `create*RowModel()` factories take no registry arguments and are registered as named feature slots.
254
98
 
255
- ### [CRITICAL] `createColumnHelper<TData>()` (v8 arity)
99
+ | V8 table option | V9 `tableFeatures` slot | V9 factory |
100
+ | -------------------------------------------------- | -------------------------------------- | ---------------------------------------------- |
101
+ | `getCoreRowModel: getCoreRowModel()` | automatic; omit for the built-in model | built-in `createCoreRowModel()` is the default |
102
+ | `getFilteredRowModel: getFilteredRowModel()` | `filteredRowModel` | `createFilteredRowModel()` |
103
+ | `getSortedRowModel: getSortedRowModel()` | `sortedRowModel` | `createSortedRowModel()` |
104
+ | `getPaginationRowModel: getPaginationRowModel()` | `paginatedRowModel` | `createPaginatedRowModel()` |
105
+ | `getExpandedRowModel: getExpandedRowModel()` | `expandedRowModel` | `createExpandedRowModel()` |
106
+ | `getGroupedRowModel: getGroupedRowModel()` | `groupedRowModel` | `createGroupedRowModel()` |
107
+ | `getFacetedRowModel: getFacetedRowModel()` | `facetedRowModel` | `createFacetedRowModel()` |
108
+ | `getFacetedMinMaxValues: getFacetedMinMaxValues()` | `facetedMinMaxValues` | `createFacetedMinMaxValues()` |
109
+ | `getFacetedUniqueValues: getFacetedUniqueValues()` | `facetedUniqueValues` | `createFacetedUniqueValues()` |
256
110
 
257
- Wrong:
111
+ For a custom core model, use the `coreRowModel` slot rather than restoring the v8 table option.
258
112
 
259
- ```ts
260
- const columnHelper = createColumnHelper<Person>()
261
- ```
113
+ Move registries from table options or factory arguments into these feature slots:
262
114
 
263
- Correct:
115
+ | V8 | V9 |
116
+ | ---------------- | ---------------- |
117
+ | `sortingFns` | `sortFns` |
118
+ | `filterFns` | `filterFns` |
119
+ | `aggregationFns` | `aggregationFns` |
264
120
 
265
- ```ts
266
- const features = tableFeatures({ rowSortingFeature })
267
- const columnHelper = createColumnHelper<typeof features, Person>()
268
- ```
121
+ Register built-ins only when needed, or spread them with custom functions. A slot's keys become the valid string names in column definitions.
269
122
 
270
- v9 requires `<TFeatures, TData>`. `typeof features` is the standard idiom — declare features once at module scope and reuse the type.
123
+ ### 3. Migrate state reads and whole-state observation
271
124
 
272
- Source: packages/table-core/src/helpers/columnHelper.ts; docs/framework/react/guide/migrating.md
125
+ `table.getState()` and the top-level `onStateChange` option are removed. Individual `on[Slice]Change` callbacks remain.
273
126
 
274
- ### [HIGH] Reading state via `table.getState()`
127
+ | V8 need | V9 shared surface |
128
+ | ------------------------------- | --------------------------------------------------- |
129
+ | Full current snapshot | `table.store.state` |
130
+ | One current slice | `table.atoms.<slice>.get()` |
131
+ | Adapter-selected reactive state | `table.state` where the adapter exposes it |
132
+ | Observe all changes | `table.store.subscribe(...)` |
133
+ | Control one slice | `state.<slice>` plus `on<Slice>Change` |
134
+ | Externally own one slice | `atoms.<slice>` with a writable TanStack Store atom |
135
+ | Internal state | omit both `state.<slice>` and `atoms.<slice>` |
275
136
 
276
- Wrong:
137
+ Load the adapter `table-state` skill before choosing reactive reads; adapters intentionally differ. When both an external atom and `state` provide a slice, the atom wins. Table writes go directly to that atom, and `table.reset()` does not reset externally owned atoms.
277
138
 
278
- ```ts
279
- const all = table.getState()
280
- ```
139
+ ### 4. Keep instance methods bound
281
140
 
282
- Correct:
141
+ Row, cell, column, header, and related object methods moved to shared prototypes. Destructuring, passing a bare callback, spreading, `Object.keys`, and `JSON.stringify` no longer preserve or reveal those methods.
283
142
 
284
143
  ```ts
285
- const all = table.store.state // flat snapshot, no subscription
286
- const sorting = table.atoms.sorting.get() // per-slice
287
- const selected = table.state // typed selector output (framework adapters)
288
- ```
289
-
290
- `table.getState()` was removed. There are three reads now, picked by what you need.
144
+ // v8 code that breaks
145
+ const { getValue } = row
146
+ rows.map(row.getVisibleCells)
291
147
 
292
- Source: docs/framework/table-core/guide/migrating.md
293
-
294
- ### [HIGH] Sorting renames missed
295
-
296
- Wrong:
297
-
298
- ```ts
299
- { accessorKey: 'age', sortingFn: 'alphanumeric' } // v8 name
300
- useTable({ sortingFns: { ... } }) // v8 option
301
- column.getSortingFn() // v8 method
148
+ // v9
149
+ const value = row.getValue('name')
150
+ rows.map((row) => row.getVisibleCells())
302
151
  ```
303
152
 
304
- Correct:
153
+ Audit all methods extracted from rows, cells, columns, headers, and header groups. Table-instance methods are not subject to this specific migration rule.
305
154
 
306
- ```ts
307
- columnHelper.accessor('age', { sortFn: 'alphanumeric' })
308
- // sortFns is a slot on features: tableFeatures({ rowSortingFeature, sortedRowModel: createSortedRowModel(), sortFns })
309
- column.getSortFn()
310
- ```
155
+ ### 5. Replace physical column pinning with logical pinning
311
156
 
312
- v9 renamed every sorting API: `sortingFn` `sortFn`, `sortingFns` `sortFns` (now a features slot, not a factory arg), type `SortingFn` → `SortFn`, `getSortingFn()` → `getSortFn()`. TypeScript surfaces these but agents try v8 names first.
157
+ V9 beta.38 has no `left`/`right` aliases. Replace all state keys, return-value comparisons, arguments, and API families:
313
158
 
314
- Source: packages/table-core/src/features/row-sorting/rowSortingFeature.types.ts
159
+ | V8 | V9 |
160
+ | ------------------------------------------------------------------------------------------ | ------------------------------------------------------------- |
161
+ | `columnPinning.left` / `.right` | `.start` / `.end` |
162
+ | `column.pin('left' \| 'right')` | `column.pin('start' \| 'end')` |
163
+ | `column.getIsPinned() === 'left' \| 'right'` | compare with `'start' \| 'end'` |
164
+ | `row.getLeftVisibleCells()` / `getRightVisibleCells()` | `getStartVisibleCells()` / `getEndVisibleCells()` |
165
+ | `table.getLeftHeaderGroups()` / `getRightHeaderGroups()` | `getStartHeaderGroups()` / `getEndHeaderGroups()` |
166
+ | `table.getLeftFooterGroups()` / `getRightFooterGroups()` | `getStartFooterGroups()` / `getEndFooterGroups()` |
167
+ | `table.getLeftFlatHeaders()` / `getRightFlatHeaders()` | `getStartFlatHeaders()` / `getEndFlatHeaders()` |
168
+ | `table.getLeftLeafHeaders()` / `getRightLeafHeaders()` | `getStartLeafHeaders()` / `getEndLeafHeaders()` |
169
+ | `table.getLeftLeafColumns()` / `getRightLeafColumns()` | `getStartLeafColumns()` / `getEndLeafColumns()` |
170
+ | `table.getLeftVisibleLeafColumns()` / `getRightVisibleLeafColumns()` | `getStartVisibleLeafColumns()` / `getEndVisibleLeafColumns()` |
171
+ | `table.getLeftTotalSize()` / `getRightTotalSize()` | `getStartTotalSize()` / `getEndTotalSize()` |
172
+ | `'left' \| 'right'` passed to `getStart`, `getAfter`, `getIndex`, or pinned-region helpers | `'start' \| 'end'` |
315
173
 
316
- ### [HIGH] Using `enablePinning` at the table level
174
+ This names logical regions; it does not automatically apply DOM direction or sticky CSS. Use logical CSS such as `inset-inline-start`/`insetInlineStart` and `inset-inline-end`/`insetInlineEnd`. `columnResizeDirection` remains `'ltr' | 'rtl'`.
317
175
 
318
- Wrong:
176
+ ### 6. Split column sizing from resizing
319
177
 
320
- ```ts
321
- const table = useTable({
322
- features: tableFeatures({ columnPinningFeature, rowPinningFeature }),
323
- enablePinning: true, // ignored at table level in v9
324
- })
325
- ```
178
+ V8's combined sizing feature became two tree-shakeable features:
326
179
 
327
- Correct:
180
+ - Register `columnSizingFeature` for sizes, offsets, and total-size APIs.
181
+ - Also register `columnResizingFeature` for drag handles and transient interaction state.
182
+ - `columnResizingFeature` cannot stand alone.
328
183
 
329
- ```ts
330
- const table = useTable({
331
- features: tableFeatures({ columnPinningFeature, rowPinningFeature }),
332
- enableColumnPinning: true,
333
- enableRowPinning: true,
334
- })
184
+ | V8 | V9 |
185
+ | -------------------------- | ------------------------ |
186
+ | `columnSizingInfo` state | `columnResizing` state |
187
+ | `setColumnSizingInfo(...)` | `setColumnResizing(...)` |
188
+ | `onColumnSizingInfoChange` | `onColumnResizingChange` |
335
189
 
336
- // Per-column opt-out is still `enablePinning`:
337
- columnHelper.accessor('id', { enablePinning: false })
338
- ```
190
+ The current source spelling is `setColumnResizing` with an uppercase `C`.
339
191
 
340
- v9 split `enablePinning` (table-level) into `enableColumnPinning` + `enableRowPinning`. The bare name now refers ONLY to per-column opt-out.
192
+ ### 7. Rename sorting APIs
341
193
 
342
- Source: packages/table-core/src/features/column-pinning/columnPinningFeature.types.ts
194
+ | V8 | V9 |
195
+ | --------------------------- | ------------------------ |
196
+ | column-def `sortingFn` | `sortFn` |
197
+ | `column.getSortingFn()` | `column.getSortFn()` |
198
+ | `column.getAutoSortingFn()` | `column.getAutoSortFn()` |
199
+ | `SortingFn` | `SortFn` |
200
+ | `SortingFns` | `SortFns` |
201
+ | built-in `sortingFns` | `sortFns` |
343
202
 
344
- ### [HIGH] Treating column resizing as part of column sizing
203
+ Also move the registry to `tableFeatures`, as described above.
345
204
 
346
- Wrong:
205
+ ### 8. Split the table-level pinning switch
347
206
 
348
- ```ts
349
- // v8 — ColumnSizing implied resizing too
350
- const table = useTable({
351
- features: tableFeatures({ columnSizingFeature }),
352
- onColumnSizingInfoChange: setInfo, // v8 name
353
- })
354
- ```
207
+ Replace the v8 table option `enablePinning` with `enableColumnPinning` and/or `enableRowPinning`. Do not mechanically rename a column definition's `enablePinning`: that column-level option still exists.
355
208
 
356
- Correct:
209
+ ### 9. Remove internal APIs and use public surfaces
357
210
 
358
- ```ts
359
- const table = useTable({
360
- features: tableFeatures({
361
- columnSizingFeature,
362
- columnResizingFeature, // explicit in v9
363
- }),
364
- onColumnResizingChange: setResizing, // renamed
365
- // state key columnSizingInfo → columnResizing
366
- })
367
- ```
211
+ All underscore-prefixed internals are unsupported and removed. Known migration points include:
368
212
 
369
- v9 split them: `columnSizingFeature` for fixed widths, `columnResizingFeature` for drag-to-resize. State key `columnSizingInfo` → `columnResizing`; option `onColumnSizingInfoChange` → `onColumnResizingChange`.
213
+ | Removed v8 internal | V9 public direction |
214
+ | --------------------------------- | ------------------------------------------------------------- |
215
+ | `row._getAllCellsByColumnId()` | `row.getAllCellsByColumnId()` |
216
+ | `table._getPinnedRows()` | `table.getTopRows()`, `getCenterRows()`, or `getBottomRows()` |
217
+ | `table._getFacetedRowModel()` | public faceting APIs on the relevant column/table |
218
+ | `table._getFacetedMinMaxValues()` | `getFacetedMinMaxValues()` |
219
+ | `table._getFacetedUniqueValues()` | `getFacetedUniqueValues()` |
370
220
 
371
- Source: docs/framework/table-core/guide/migrating.md
221
+ For any other `_` API, do not guess. Inspect the installed v9 package source for the public replacement or redesign the integration.
372
222
 
373
- ### [MEDIUM] Calling underscore-prefixed APIs
223
+ ### 10. Update row-selection predicates
374
224
 
375
- Wrong:
225
+ `getIsSomeRowsSelected()` and `getIsSomePageRowsSelected()` now mean **at least one**, including the all-selected case. They no longer mean “some but not all.” Build an indeterminate checkbox with both predicates:
376
226
 
377
227
  ```ts
378
- row._getAllCellsByColumnId()
379
- table._getFacetedRowModel()
380
- table._getFacetedMinMaxValues()
381
- table._getFacetedUniqueValues()
382
- table._getPinnedRows()
228
+ const indeterminate =
229
+ table.getIsSomeRowsSelected() && !table.getIsAllRowsSelected()
383
230
  ```
384
231
 
385
- Correct:
232
+ For a page checkbox, use `table.getIsSomePageRowsSelected() && !table.getIsAllPageRowsSelected()`.
386
233
 
387
- ```ts
388
- row.getAllCellsByColumnId()
389
- table.getFacetedRowModel()
390
- table.getFacetedMinMaxValues()
391
- table.getFacetedUniqueValues()
392
- table.getPinnedRows()
393
- ```
234
+ ### 11. Update TypeScript feature generics and helpers
235
+
236
+ Most core types add `TFeatures` before their data/value parameters:
394
237
 
395
- All became public — drop the underscore.
238
+ | V8 | V9 |
239
+ | ----------------------------- | ---------------------------------------- |
240
+ | `Column<TData>` | `Column<TFeatures, TData, TValue>` |
241
+ | `ColumnDef<TData>` | `ColumnDef<TFeatures, TData, TValue>` |
242
+ | `Table<TData>` | `Table<TFeatures, TData>` |
243
+ | `Row<TData>` | `Row<TFeatures, TData>` |
244
+ | `Cell<TData, TValue>` | `Cell<TFeatures, TData, TValue>` |
245
+ | `createColumnHelper<TData>()` | `createColumnHelper<TFeatures, TData>()` |
396
246
 
397
- Source: docs/framework/table-core/guide/migrating.md
247
+ Prefer inference. Use `typeof features` only where an explicit type boundary is necessary; use `StockFeatures` when that is genuinely the selected feature set. Wrap column arrays with `columnHelper.columns([...])` to preserve individual and nested `TValue` inference.
398
248
 
399
- ### [MEDIUM] Module augmentation with v8 generic arity
249
+ `RowData` is now `Record<string, any> | Array<any>`, not `unknown`. Wrap primitive records in an object or array shape.
400
250
 
401
- Wrong:
251
+ Global `TableMeta`/`ColumnMeta` declaration merging can remain, but add `TFeatures` as the first generic. Prefer per-table type-only slots where isolation helps:
402
252
 
403
253
  ```ts
404
- declare module '@tanstack/react-table' {
405
- interface ColumnMeta<TData, TValue> {
406
- customProp: string
407
- }
408
- }
254
+ const features = tableFeatures({
255
+ columnFilteringFeature,
256
+ tableMeta: metaHelper<MyTableMeta>(),
257
+ columnMeta: metaHelper<MyColumnMeta>(),
258
+ filterMeta: metaHelper<MyFilterMeta>(),
259
+ })
409
260
  ```
410
261
 
411
- Correct:
262
+ Replace global `FilterFns`, `SortFns`, and `AggregationFns` augmentation with the matching registry slots; their object keys supply the string-literal names. Replace `FilterMeta` augmentation with the `filterMeta` slot unless global behavior is intentional.
412
263
 
413
- ```ts
414
- declare module '@tanstack/react-table' {
415
- interface ColumnMeta<TFeatures, TData, TValue> {
416
- customProp: string
417
- }
418
- }
419
- ```
264
+ ### 12. Migrate adapter construction and rendering separately
420
265
 
421
- v9 added `TFeatures` as the first generic. Module augmentation silently widens types if arity is wrong.
266
+ The following are breaking but not shared core mappings: adapter hook/factory/controller names, Svelte 5 requirements, reactive getter rules, state-selection components/helpers, and `FlexRender` syntax. Load the installed adapter's migration skill and follow its exact source. Do not apply React names to Preact, Solid, Svelte, Vue, Angular, or Lit.
422
267
 
423
- Source: docs/framework/table-core/guide/migrating.md
268
+ ## Optional v9 adoption after parity
424
269
 
425
- ### [MEDIUM] Mutating `data` or `columns` in place
270
+ Do not confuse new capabilities with required breakages. After the table works, consider `tableOptions()` for reusable partial configuration, `createTableHook()` for app-level table conventions, per-slice atoms/subscriptions for narrower rendering, per-table meta slots, and explicit features for smaller bundles.
426
271
 
427
- Wrong:
272
+ ## Complete audit checklist
428
273
 
429
- ```ts
430
- // v8 pattern, breaks at TS layer in v9
431
- const data: Person[] = []
432
- function addRow(row: Person) {
433
- data.push(row)
434
- rerender()
435
- }
436
- ```
274
+ - [ ] Load the installed framework adapter's migration and table-state skills.
275
+ - [ ] Replace the v8 adapter constructor/hook/controller with its v9 entrypoint.
276
+ - [ ] Add a stable `features` object to every table.
277
+ - [ ] Inventory every feature API used by table, row, column, cell, and header code; register all 14 required stock features.
278
+ - [ ] Use `stockFeatures` only as a temporary parity aid and record an explicit-feature follow-up.
279
+ - [ ] Remove `getCoreRowModel()` unless supplying a deliberate custom `coreRowModel` slot.
280
+ - [ ] Move all remaining `get*RowModel()` options or earlier-beta `rowModels` entries to `create*RowModel()` feature slots.
281
+ - [ ] Register each dependent feature before its row-model slot.
282
+ - [ ] Move `filterFns`, `sortingFns`/`sortFns`, and `aggregationFns` into feature slots; pass no registries to factories.
283
+ - [ ] Register `columnFilteringFeature` before global filtering and filter/facet dependencies.
284
+ - [ ] Register `columnSizingFeature` before `columnResizingFeature`.
285
+ - [ ] Replace `table.getState()` and top-level `onStateChange` according to the adapter state guide.
286
+ - [ ] Verify every controlled slice has an update path; verify externally owned atoms are reset by their owner.
287
+ - [ ] Audit destructured, spread, serialized, or bare-callback instance methods.
288
+ - [ ] Replace every column-pinning `left`/`right` key, argument, comparison, method family, and sticky CSS declaration with logical start/end equivalents.
289
+ - [ ] Split table-level `enablePinning`; preserve column-def `enablePinning` where intended.
290
+ - [ ] Split sizing/resizing features and rename the resizing state, setter, and callback.
291
+ - [ ] Replace every `sortingFn`/`SortingFn`/`sortingFns` spelling with its v9 `sort*` spelling.
292
+ - [ ] Remove every consumed underscore-prefixed internal API.
293
+ - [ ] Recheck indeterminate selection logic against the new “at least one” semantics.
294
+ - [ ] Add `TFeatures` to unavoidable explicit core types, helpers, and retained meta augmentation; otherwise restore inference.
295
+ - [ ] Replace function-registry and filter-meta declaration merging with per-table slots where appropriate.
296
+ - [ ] Ensure every row is a record or array under the stricter `RowData` constraint.
297
+ - [ ] Migrate adapter-specific rendering, reactive data inputs, and subscription primitives.
298
+ - [ ] Type-check without `any`/casts added merely to suppress migration failures.
299
+ - [ ] Test sorting, filtering, faceting, grouping, expansion, pagination, selection, ordering, pinning, sizing, and resizing—only where enabled.
300
+ - [ ] Test client/server ownership for every row-model pipeline stage and ensure manual modes receive already-processed data.
301
+ - [ ] Test LTR and RTL layouts when column pinning or resizing is enabled.
302
+ - [ ] Remove `useLegacyTable` after the incremental migration step that required it.
437
303
 
438
- Correct:
304
+ ## Common migration failures
439
305
 
440
- ```ts
441
- const [data, setData] = useState<Person[]>([])
442
- function addRow(row: Person) {
443
- setData((prev) => [...prev, row])
444
- }
445
- ```
306
+ ### [CRITICAL] Silencing a missing API instead of registering its feature
446
307
 
447
- PR #6183 makes `data` and `columns` readonly to force changes through state.
308
+ If `table.nextPage`, `column.toggleSorting`, or a state slice disappears, add the associated feature. Do not cast the table to a broader type.
448
309
 
449
- Source: PR #6183
310
+ ### [CRITICAL] Mixing v8, early-v9-beta, and beta.38 configuration
450
311
 
451
- ### [MEDIUM] Reaching for `useLegacyTable` in new code
312
+ Do not combine v8 `get*RowModel` options, an earlier beta's `rowModels` object, or physical pinning names with the current `tableFeatures` slots.
452
313
 
453
- Wrong:
314
+ ### [HIGH] Treating `stockFeatures` or `useLegacyTable` as the finished migration
454
315
 
455
- ```ts
456
- // Long-term use of the legacy shim
457
- import { useLegacyTable, getCoreRowModel } from '@tanstack/react-table/legacy'
458
- const table = useLegacyTable({
459
- columns,
460
- data,
461
- getCoreRowModel: getCoreRowModel(),
462
- })
463
- ```
316
+ Both obscure missing feature decisions; `useLegacyTable` is deprecated and React-only. Reach behavior parity, then complete the explicit v9 setup.
464
317
 
465
- Correct:
318
+ ### [HIGH] Copying one adapter's state or rendering API into another
466
319
 
467
- ```ts
468
- // Migrate to native v9 shape
469
- import {
470
- useTable,
471
- tableFeatures,
472
- rowSortingFeature,
473
- createSortedRowModel,
474
- sortFns,
475
- } from '@tanstack/react-table'
476
- const features = tableFeatures({
477
- rowSortingFeature,
478
- sortedRowModel: createSortedRowModel(),
479
- sortFns,
480
- })
481
- const table = useTable({ features, columns, data })
482
- ```
320
+ Core concepts are shared, but reactive reads, constructors, and rendering helpers are not. Load the package-local adapter skills.
483
321
 
484
- `useLegacyTable` is React-only, deprecated, bundles every feature, doesn't support `table.Subscribe`, and is removed in v10. It exists to unblock incremental migration — not as a long-term API.
322
+ ## Installed-source API discovery
485
323
 
486
- Source: packages/react-table/src/legacy.ts; docs/framework/react/guide/use-legacy-table.md
324
+ Use the installed version, not main-branch memory:
487
325
 
488
- ## See also
326
+ 1. Inspect `node_modules/@tanstack/table-core/src/index.ts` for exports.
327
+ 2. Inspect `src/types/TableFeatures.ts` for valid slots and prerequisites.
328
+ 3. Inspect `src/features/<feature>/*.types.ts` for current options, state, and APIs.
329
+ 4. Inspect the installed adapter's `src/index.ts` and its migration skill for entrypoints and rendering.
330
+ 5. Inspect `src/legacy.ts` only to remove an existing bridge, never to design new v9 code.
489
331
 
490
- - `tanstack-table/setup` what the v9-native shape looks like
491
- - `tanstack-table/state-management` — `table.store.state` / `table.atoms` / `table.state` ownership
492
- - `tanstack-table/column-definitions` — `createColumnHelper<typeof features, TData>()` generic order
332
+ If package-manager layout prevents that exact path, resolve the installed package root first. Do not substitute APIs from a different v9 beta.