@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,387 +1,78 @@
1
1
  ---
2
2
  name: pagination
3
3
  description: >
4
- Paginate rows in TanStack Table v9 with the `paginatedRowModel` stage. Covers
5
- `rowPaginationFeature` + `createPaginatedRowModel()`, `state.pagination`
6
- ({ pageIndex, pageSize }), `onPaginationChange`, `manualPagination`,
7
- `rowCount` and `pageCount` for server-side, `autoResetPageIndex`,
8
- `paginateExpandedRows`, navigation APIs (`nextPage`/`previousPage`/`firstPage`/
9
- `lastPage`/`setPageIndex`/`setPageSize`), `getCanNextPage` / `getCanPreviousPage`,
10
- `getPageCount` / `getRowCount` / `getPageOptions`, and `getPrePaginatedRowModel`
11
- for "total filtered" counts.
12
- type: core
13
- library: tanstack-table
14
- library_version: '9.0.0-alpha.48'
15
- requires:
16
- - state-management
4
+ Paginate with rowPaginationFeature and paginatedRowModel or manualPagination. Load for pageIndex/pageSize state, rowCount/pageCount, unknown next-page limits, already-paginated server data, or autoResetPageIndex surprises.
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']
17
12
  sources:
18
- - TanStack/table:docs/guide/pagination.md
19
- - TanStack/table:packages/table-core/src/features/row-pagination/rowPaginationFeature.utils.ts
20
- - TanStack/table:packages/table-core/src/features/row-pagination/createPaginatedRowModel.ts
21
- - TanStack/table:examples/react/pagination/src/main.tsx
13
+ - 'TanStack/table:docs/framework/react/guide/pagination.md'
14
+ - 'TanStack/table:packages/table-core/src/features/row-pagination'
15
+ - 'TanStack/table:examples/react/pagination'
22
16
  ---
23
17
 
24
- This skill builds on `tanstack-table/state-management`. Read it first for the atom model and `manual*` mode.
18
+ This skill builds on `core`, `table-features`, and `client-vs-server`. Choose client slicing or server pages, never both accidentally.
25
19
 
26
20
  ## Setup
27
21
 
28
22
  ```ts
29
23
  import {
30
- tableFeatures,
31
- rowPaginationFeature,
32
24
  createPaginatedRowModel,
33
- constructTable,
25
+ rowPaginationFeature,
26
+ tableFeatures,
34
27
  } from '@tanstack/table-core'
35
- import type { PaginationState } from '@tanstack/table-core'
36
28
 
37
- const features = tableFeatures({
29
+ export const features = tableFeatures({
38
30
  rowPaginationFeature,
39
31
  paginatedRowModel: createPaginatedRowModel(),
40
32
  })
41
-
42
- const table = constructTable({
43
- features,
44
- columns,
45
- data,
46
- initialState: {
47
- pagination: { pageIndex: 0, pageSize: 10 } satisfies PaginationState,
48
- },
49
- })
50
-
51
- table.nextPage()
52
- table.setPageIndex(5)
53
- table.setPageSize(25)
54
- table.getCanNextPage()
55
- table.getPageCount()
56
- table.getRowCount()
33
+ export const initialState = { pagination: { pageIndex: 0, pageSize: 25 } }
57
34
  ```
58
35
 
59
36
  ## Core Patterns
60
37
 
61
- ### Pagination toolbar
62
-
63
- ```tsx
64
- // From examples/react/pagination/src/main.tsx
65
- <div>
66
- <button
67
- onClick={() => table.firstPage()}
68
- disabled={!table.getCanPreviousPage()}
69
- >
70
- {'<<'}
71
- </button>
72
- <button
73
- onClick={() => table.previousPage()}
74
- disabled={!table.getCanPreviousPage()}
75
- >
76
- {'<'}
77
- </button>
78
- <button onClick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
79
- {'>'}
80
- </button>
81
- <button onClick={() => table.lastPage()} disabled={!table.getCanNextPage()}>
82
- {'>>'}
83
- </button>
84
-
85
- <span>
86
- Page {table.store.state.pagination.pageIndex + 1} of{' '}
87
- {table.getPageCount().toLocaleString()}
88
- </span>
89
-
90
- <span>
91
- | Go to page:
92
- <input
93
- type="number"
94
- defaultValue={table.store.state.pagination.pageIndex + 1}
95
- onChange={(e) => {
96
- const page = e.target.value ? Number(e.target.value) - 1 : 0
97
- table.setPageIndex(page)
98
- }}
99
- />
100
- </span>
101
-
102
- <select
103
- value={table.store.state.pagination.pageSize}
104
- onChange={(e) => table.setPageSize(Number(e.target.value))}
105
- >
106
- {[10, 20, 30, 40, 50].map((size) => (
107
- <option key={size} value={size}>
108
- Show {size}
109
- </option>
110
- ))}
111
- </select>
112
- </div>
113
- ```
114
-
115
- ### Server-side pagination
116
-
117
- ```tsx
118
- const [pagination, setPagination] = useState<PaginationState>({
119
- pageIndex: 0,
120
- pageSize: 10,
121
- })
122
- const { data: dataQuery } = useQuery({
123
- queryKey: ['rows', pagination],
124
- queryFn: () => fetchPage(pagination.pageIndex, pagination.pageSize),
125
- })
126
-
127
- const table = useTable({
128
- features: tableFeatures({ rowPaginationFeature }),
129
- // no paginatedRowModel registered — server paginates
130
- data: dataQuery?.rows ?? EMPTY,
131
- columns,
132
- manualPagination: true,
133
- rowCount: dataQuery?.rowCount, // server-provided total
134
- // OR: pageCount: dataQuery.pageCount
135
- // OR: pageCount: -1 if unknown (next button stays enabled)
136
- state: { pagination },
137
- onPaginationChange: setPagination,
138
- })
139
- ```
140
-
141
- ### Disable auto page reset when filters change
142
-
143
- ```ts
144
- const features = tableFeatures({
145
- rowPaginationFeature,
146
- columnFilteringFeature,
147
- paginatedRowModel: createPaginatedRowModel(),
148
- filteredRowModel: createFilteredRowModel(),
149
- filterFns,
150
- })
151
- const table = constructTable({
152
- features,
153
- columns,
154
- data,
155
- autoResetPageIndex: false, // keep current page while user types in a filter
156
- })
157
- ```
158
-
159
- `autoResetPageIndex` defaults to `!manualPagination` — true client-side, false manual.
160
-
161
- ### "Total filtered rows" display while paginated
162
-
163
38
  ```ts
164
- const totalFiltered = table.getPrePaginatedRowModel().rows.length
165
- const onCurrentPage = table.getRowModel().rows.length
39
+ const serverOptions = { manualPagination: true, rowCount: response.total }
166
40
  ```
167
41
 
168
- `getPrePaginatedRowModel` is the row model AFTER filtering/sorting/grouping/expansion but BEFORE the page slice.
42
+ Pass one already-processed page and either `rowCount` or `pageCount`.
169
43
 
170
44
  ## Common Mistakes
171
45
 
172
- ### [HIGH] Setting `manualPagination: true` without supplying `rowCount` or `pageCount`
173
-
174
- Wrong:
175
-
176
- ```tsx
177
- // getPageCount() returns 1, next/prev buttons are disabled
178
- const table = useTable({
179
- features: tableFeatures({ rowPaginationFeature }),
180
- data, // only 10 rows for the current page
181
- columns,
182
- manualPagination: true,
183
- state: { pagination },
184
- onPaginationChange: setPagination,
185
- // missing: rowCount or pageCount
186
- })
187
- ```
188
-
189
- Correct:
46
+ ### [CRITICAL] Expecting manual mode to slice
190
47
 
191
- ```tsx
192
- const table = useTable({
193
- features: tableFeatures({ rowPaginationFeature }),
194
- data: dataQuery.rows,
195
- columns,
196
- manualPagination: true,
197
- rowCount: dataQuery.rowCount, // server tells the table the total
198
- // OR: pageCount: dataQuery.pageCount
199
- // OR: pageCount: -1 if unknown
200
- state: { pagination },
201
- onPaginationChange: setPagination,
202
- })
203
- ```
204
-
205
- `getRowCount()` defaults to `getPrePaginatedRowModel().rows.length` — which in manual mode is only the current page. Without `rowCount`/`pageCount`, the table thinks there's one page total.
48
+ Wrong: `const options = { data: allRows, manualPagination: true }`
206
49
 
207
- Source: packages/table-core/src/features/row-pagination/rowPaginationFeature.utils.ts
50
+ Correct: `const options = { data: requestedPageRows, manualPagination: true, rowCount: totalRows }`
208
51
 
209
- ### [MEDIUM] Putting `pagination` in BOTH `state` and `initialState`
210
-
211
- Wrong:
212
-
213
- ```tsx
214
- const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 10 })
215
- const table = useTable({
216
- initialState: { pagination: { pageSize: 25 } }, // IGNORED
217
- state: { pagination }, // wins (pageSize 10)
218
- onPaginationChange: setPagination,
219
- })
220
- ```
52
+ Manual pagination trusts the provided data as the current page.
221
53
 
222
- Correct:
54
+ Source: `https://github.com/TanStack/table/issues/4917`
223
55
 
224
- ```tsx
225
- const [pagination, setPagination] = useState({ pageIndex: 0, pageSize: 25 })
226
- const table = useTable({
227
- features: tableFeatures({
228
- rowPaginationFeature,
229
- paginatedRowModel: createPaginatedRowModel(),
230
- }),
231
- columns,
232
- data,
233
- state: { pagination },
234
- onPaginationChange: setPagination,
235
- })
236
- ```
56
+ ### [HIGH] Omitting the server total
237
57
 
238
- `state` always overrides `initialState`. Seed the controlled state in `useState` or use `initialState` alone — never both.
58
+ Wrong: `const options = { data: pageRows, manualPagination: true }`
239
59
 
240
- Source: docs/guide/pagination.md
60
+ Correct: `const options = { data: pageRows, manualPagination: true, rowCount: 1234 }`
241
61
 
242
- ### [MEDIUM] `autoResetPageIndex: false` without manual clamping leaves empty pages
62
+ Without a count, last-page and next-page availability cannot reflect the server dataset.
243
63
 
244
- Wrong:
64
+ Source: `packages/table-core/src/features/row-pagination/rowPaginationFeature.types.ts`
245
65
 
246
- ```ts
247
- // features already has paginatedRowModel + filteredRowModel registered
248
- const table = useTable({
249
- features,
250
- columns,
251
- data,
252
- autoResetPageIndex: false, // user on page 5, then filters down to 2 pages
253
- // → page 5 is empty. No automatic clamp.
254
- })
255
- ```
66
+ ### [HIGH] Fighting automatic page resets
256
67
 
257
- Correct:
68
+ Wrong: `onPaginationChange: setPagination`
258
69
 
259
- ```ts
260
- // Either leave autoResetPageIndex default (true) for client-side,
261
- // or clamp manually after a data-altering effect:
262
- useEffect(() => {
263
- const lastPage = Math.max(0, table.getPageCount() - 1)
264
- if (table.atoms.pagination.get().pageIndex > lastPage) {
265
- table.setPageIndex(lastPage)
266
- }
267
- }, [data, columnFilters])
268
- ```
269
-
270
- `setPageIndex` only clamps against `options.pageCount` (max safe int when unset). It doesn't clamp against the current row model.
271
-
272
- Source: packages/table-core/src/features/row-pagination/rowPaginationFeature.utils.ts
273
-
274
- ### [LOW] Expecting `getRowCount()` to equal `data.length` under filtering/grouping/expansion
275
-
276
- Wrong:
277
-
278
- ```ts
279
- console.log(table.getRowCount()) // count after all transforms
280
- console.log(data.length) // raw input count
281
- // These diverge under filtering, grouping, or tree vs flat input.
282
- ```
283
-
284
- Correct:
285
-
286
- ```ts
287
- table.getCoreRowModel().rows.length // raw row count (flat)
288
- table.getPreFilteredRowModel().rows.length // before filtering
289
- table.getFilteredRowModel().rows.length // after filtering
290
- table.getRowCount() // pre-paginated count (or `rowCount` option in manual mode)
291
- table.getRowModel().rows.length // current page only
292
- ```
293
-
294
- `getRowCount` returns `options.rowCount ?? getPrePaginatedRowModel().rows.length`. Pick the model that matches the question.
295
-
296
- Source: docs/guide/row-models.md
297
-
298
- ### [HIGH] `getToggleAllRowsSelectedHandler` only selects current page under server pagination
299
-
300
- Wrong:
301
-
302
- ```tsx
303
- // Header checkbox only affects current page in manualPagination mode
304
- <input
305
- checked={table.getIsAllRowsSelected()}
306
- onChange={table.getToggleAllRowsSelectedHandler()}
307
- />
308
- ```
309
-
310
- Correct:
311
-
312
- ```tsx
313
- // Use page-aware APIs with server pagination
314
- <input
315
- checked={table.getIsAllPageRowsSelected()}
316
- onChange={table.getToggleAllPageRowsSelectedHandler()}
317
- />
318
- // For "select all server-side rows", track a separate "all rows mode"
319
- // boolean alongside the row map.
320
- ```
321
-
322
- The table only knows about the current page's rows under `manualPagination`. "Select all" can never mean "every row on the server" without an explicit out-of-band selection mode.
323
-
324
- Source: https://github.com/TanStack/table/issues/4781
325
-
326
- ### [MEDIUM] `autoResetPageIndex` resets to `initialState.pageIndex` (not 0)
327
-
328
- Wrong:
329
-
330
- ```ts
331
- // Filtering data resets to the deep-linked pageIndex, not 0
332
- const table = useTable({
333
- data,
334
- columns,
335
- initialState: { pagination: { pageIndex: 5, pageSize: 10 } },
336
- autoResetPageIndex: true,
337
- })
338
- ```
339
-
340
- Correct:
341
-
342
- ```ts
343
- useEffect(() => {
344
- table.setPageIndex(0)
345
- }, [columnFilters, globalFilter])
346
- // Or: don't rely on autoResetPageIndex when deep-linking pageIndex
347
- ```
348
-
349
- `_autoResetPageIndex` calls `resetPageIndex()` without `true`, which restores to `initialState.pagination.pageIndex` — typically a URL deep-link page that's now invalid.
350
-
351
- Source: https://github.com/TanStack/table/issues/6207
352
-
353
- ### [CRITICAL] Reimplementing pagination math manually
354
-
355
- Wrong:
356
-
357
- ```ts
358
- // Hand-rolled page slicing instead of using the API
359
- const paginatedRows = useMemo(
360
- () => allRows.slice(pageIndex * pageSize, (pageIndex + 1) * pageSize),
361
- [allRows, pageIndex, pageSize],
362
- )
363
- ```
364
-
365
- Correct:
366
-
367
- ```ts
368
- const table = useTable({
369
- features: tableFeatures({
370
- rowPaginationFeature,
371
- paginatedRowModel: createPaginatedRowModel(),
372
- }),
373
- columns,
374
- data,
375
- })
376
- // table.nextPage(), table.setPageIndex(...), table.getRowModel().rows
377
- ```
70
+ Correct: `const options = { onPaginationChange: setPagination, autoResetPageIndex: false }`
378
71
 
379
- The built-in APIs honor `autoResetPageIndex`, `paginateExpandedRows`, and reset interactions across other features.
72
+ Client data and processing changes may reset page index; configure the policy when product state must retain it.
380
73
 
381
- Source: maintainer interview (Phase 4, 2026-05-17)
74
+ Source: `docs/framework/react/guide/pagination.md#auto-reset-page-index`
382
75
 
383
- ## See also
76
+ ## API Discovery
384
77
 
385
- - `tanstack-table/state-management` `manualPagination` + `autoResetAll`
386
- - `tanstack-table/row-expanding` — `paginateExpandedRows` interaction
387
- - `tanstack-table/row-selection` — "select all" pitfalls under server pagination
78
+ Inspect `node_modules/@tanstack/table-core/src/features/row-pagination/` for reset rules, count calculation, and navigation APIs.