@tanstack/vue-table 9.0.0-beta.4 → 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 (53) hide show
  1. package/README.md +2 -0
  2. package/dist/FlexRender.cjs +2 -3
  3. package/dist/FlexRender.cjs.map +1 -1
  4. package/dist/FlexRender.d.cts +30 -12
  5. package/dist/FlexRender.d.ts +30 -12
  6. package/dist/FlexRender.js +2 -3
  7. package/dist/FlexRender.js.map +1 -1
  8. package/dist/createTableHook.cjs +4 -9
  9. package/dist/createTableHook.cjs.map +1 -1
  10. package/dist/createTableHook.d.cts +49 -21
  11. package/dist/createTableHook.d.ts +49 -21
  12. package/dist/createTableHook.js +4 -9
  13. package/dist/createTableHook.js.map +1 -1
  14. package/dist/experimental-worker-plugin.cjs +9 -0
  15. package/dist/experimental-worker-plugin.d.cts +1 -0
  16. package/dist/experimental-worker-plugin.d.ts +1 -0
  17. package/dist/experimental-worker-plugin.js +3 -0
  18. package/dist/flex-render.d.cts +2 -2
  19. package/dist/flex-render.d.ts +2 -2
  20. package/dist/index.d.cts +3 -3
  21. package/dist/index.d.ts +3 -3
  22. package/dist/reactivity.cjs +2 -6
  23. package/dist/reactivity.cjs.map +1 -1
  24. package/dist/reactivity.js +2 -6
  25. package/dist/reactivity.js.map +1 -1
  26. package/dist/useTable.cjs +3 -7
  27. package/dist/useTable.cjs.map +1 -1
  28. package/dist/useTable.d.cts +1 -8
  29. package/dist/useTable.d.ts +1 -8
  30. package/dist/useTable.js +3 -7
  31. package/dist/useTable.js.map +1 -1
  32. package/package.json +8 -4
  33. package/skills/create-table-hook/SKILL.md +146 -0
  34. package/skills/getting-started/SKILL.md +144 -0
  35. package/skills/migrate-v8-to-v9/SKILL.md +185 -0
  36. package/skills/table-state/SKILL.md +191 -0
  37. package/skills/with-tanstack-query/SKILL.md +127 -0
  38. package/skills/with-tanstack-virtual/SKILL.md +116 -0
  39. package/src/FlexRender.ts +28 -13
  40. package/src/createTableHook.ts +112 -20
  41. package/src/experimental-worker-plugin.ts +1 -0
  42. package/src/reactivity.ts +1 -2
  43. package/src/useTable.ts +3 -11
  44. package/skills/vue/client-to-server/SKILL.md +0 -365
  45. package/skills/vue/compose-with-tanstack-form/SKILL.md +0 -369
  46. package/skills/vue/compose-with-tanstack-pacer/SKILL.md +0 -318
  47. package/skills/vue/compose-with-tanstack-query/SKILL.md +0 -385
  48. package/skills/vue/compose-with-tanstack-store/SKILL.md +0 -301
  49. package/skills/vue/compose-with-tanstack-virtual/SKILL.md +0 -340
  50. package/skills/vue/getting-started/SKILL.md +0 -409
  51. package/skills/vue/migrate-v8-to-v9/SKILL.md +0 -375
  52. package/skills/vue/production-readiness/SKILL.md +0 -271
  53. package/skills/vue/table-state/SKILL.md +0 -403
@@ -1,403 +0,0 @@
1
- ---
2
- name: vue/table-state
3
- description: >
4
- Vue reactivity for `@tanstack/vue-table` v9. Covers `useTable(options, selector?)`, reactive
5
- `data`/`columns` via `ref`/`computed` getters, the `vueReactivity()` binding (readonly atoms →
6
- `computed`, writable → `shallowRef`, subscriptions via `watch({flush:'sync'})`), the three state
7
- surfaces `table.atoms.<slice>` / `table.store` / `table.state`, selected state via the second
8
- `useTable` argument, the `<FlexRender>` component, `table.Subscribe` for atom/source subscriptions,
9
- and composition with `createAtom` / `useSelector` from `@tanstack/vue-store`.
10
- type: framework
11
- library: tanstack-table
12
- framework: vue
13
- library_version: '9.0.0-alpha.48'
14
- requires:
15
- - state-management
16
- - setup
17
- sources:
18
- - docs/framework/vue/guide/table-state.md
19
- - docs/framework/vue/vue-table.md
20
- - packages/vue-table/src/useTable.ts
21
- - packages/vue-table/src/reactivity.ts
22
- - packages/vue-table/src/FlexRender.ts
23
- - examples/vue/basic-use-table/
24
- - examples/vue/basic-external-atoms/
25
- - examples/vue/basic-external-state/
26
- ---
27
-
28
- # Vue Table State, Subscribe & createTableHook
29
-
30
- ## Dependencies
31
-
32
- ```bash
33
- pnpm add @tanstack/vue-table @tanstack/vue-store
34
- ```
35
-
36
- `@tanstack/vue-store` is a peer for `createAtom` / `useSelector`. It is only required when you
37
- opt into external atoms — basic tables that use `initialState` or built-in state work without it.
38
-
39
- This skill is v9-specific (`9.0.0-alpha.48`). The hook is `useTable` for every framework now; the
40
- v8 name `useVueTable` no longer exists.
41
-
42
- ## Setup
43
-
44
- Every Vue table call requires `features` (built from `tableFeatures({...})`) and `rowModels`.
45
- Core row model is automatic; only register `paginatedRowModel`, `sortedRowModel`, etc. when you
46
- use the matching feature.
47
-
48
- ```vue
49
- <script setup lang="ts">
50
- import { ref } from 'vue'
51
- import {
52
- FlexRender,
53
- createColumnHelper,
54
- createSortedRowModel,
55
- rowSortingFeature,
56
- sortFns,
57
- tableFeatures,
58
- useTable,
59
- } from '@tanstack/vue-table'
60
-
61
- type Person = { firstName: string; lastName: string; age: number }
62
-
63
- // Stable identity — declare outside the component or at module scope.
64
- const features = tableFeatures({ rowSortingFeature })
65
- const columnHelper = createColumnHelper<typeof features, Person>()
66
- const columns = columnHelper.columns([
67
- columnHelper.accessor('firstName', { header: 'First' }),
68
- columnHelper.accessor('lastName', { header: 'Last' }),
69
- columnHelper.accessor('age', { header: 'Age' }),
70
- ])
71
-
72
- const data = ref<Person[]>([])
73
-
74
- const table = useTable({
75
- features,
76
- rowModels: { sortedRowModel: createSortedRowModel(sortFns) },
77
- columns,
78
- // Reactive data: pass the ref directly OR a getter — the adapter unwraps.
79
- data,
80
- })
81
- </script>
82
-
83
- <template>
84
- <table>
85
- <thead>
86
- <tr v-for="hg in table.getHeaderGroups()" :key="hg.id">
87
- <th v-for="h in hg.headers" :key="h.id">
88
- <FlexRender v-if="!h.isPlaceholder" :header="h" />
89
- </th>
90
- </tr>
91
- </thead>
92
- <tbody>
93
- <tr v-for="row in table.getRowModel().rows" :key="row.id">
94
- <td v-for="cell in row.getAllCells()" :key="cell.id">
95
- <FlexRender :cell="cell" />
96
- </td>
97
- </tr>
98
- </tbody>
99
- </table>
100
- </template>
101
- ```
102
-
103
- ### Why this works
104
-
105
- The Vue adapter calls `vueReactivity()` and installs it as `coreReativityFeature` automatically
106
- (see `packages/vue-table/src/useTable.ts`):
107
-
108
- - Readonly atoms back onto `computed()` refs.
109
- - Writable atoms back onto `shallowRef()`.
110
- - Subscriptions use `watch(source, cb, { flush: 'sync' })`, so table updates are visible to Vue
111
- render and computed work immediately.
112
-
113
- `useTable` also runs a `watch(() => getReactiveOptionDeps(...))` on every option, so passing a
114
- `ref` or `computed` for `data`, `columns`, `rowCount`, etc. is supported — the table calls
115
- `setOptions` whenever any reactive option changes.
116
-
117
- > **Vue note.** `table.Subscribe` exists for parity with React, but you usually do not need it.
118
- > Vue's reactivity re-evaluates template reads automatically — wrap reads in `computed(...)` if
119
- > you need them outside a template. Do not import React-Compiler workarounds.
120
-
121
- ## Core Patterns
122
-
123
- ### 1. The three read surfaces
124
-
125
- ```ts
126
- // (a) Per-slice atom — narrowest, no full state snapshot built
127
- const sorting = table.atoms.sorting.get()
128
-
129
- // (b) Flat readonly store — every registered slice as one object
130
- const snapshot = table.state
131
-
132
- // (c) Vue selected state — the value returned from useTable's 2nd arg
133
- const table = useTable(
134
- {
135
- features,
136
- rowModels: { sortedRowModel: createSortedRowModel(sortFns) },
137
- columns,
138
- data,
139
- },
140
- (state) => ({ sorting: state.sorting }),
141
- )
142
- table.state.sorting // typed, reactive
143
- ```
144
-
145
- `table.atoms.<slice>` only contains slices for features registered in `features`. If
146
- `rowSortingFeature` is not registered, `table.atoms.sorting` is `undefined` (and TypeScript
147
- flags it). This is the v9-specific "missing API" gotcha — register the feature first.
148
-
149
- Source: `docs/framework/vue/guide/table-state.md` (Feature-based State, Accessing Table State).
150
-
151
- ### 2. Reactive data with a getter or computed
152
-
153
- The adapter accepts a `ref`/`computed` for any option. The idiomatic shapes are:
154
-
155
- ```ts
156
- // (a) Pass the ref directly — adapter unwraps via `unref()`
157
- const data = ref(makeData(100))
158
- const table = useTable({ features, rowModels: {}, columns, data })
159
-
160
- // (b) Use a getter when `data` is owned by a parent object
161
- const table = useTable({
162
- features,
163
- rowModels: {},
164
- columns,
165
- get data() {
166
- return data.value
167
- },
168
- })
169
-
170
- // (c) Computed when filtering/derivation lives on the client
171
- const filtered = computed(() => data.value.filter(/* … */))
172
- const table = useTable({
173
- features,
174
- rowModels: {},
175
- columns,
176
- get data() {
177
- return filtered.value
178
- },
179
- })
180
- ```
181
-
182
- When `data.value` changes, `useTable` calls `setOptions` synchronously and the table re-derives.
183
- Source: `examples/vue/basic-use-table/src/App.tsx`, `examples/vue/virtualized-rows/src/App.vue`.
184
-
185
- ### 3. External atoms (recommended for shared state)
186
-
187
- Use `createAtom` from `@tanstack/vue-store`; pass through `options.atoms`. Atoms take
188
- precedence over `options.state` — pick one mechanism per slice.
189
-
190
- ```vue
191
- <script setup lang="ts">
192
- import { ref } from 'vue'
193
- import { createAtom, useSelector } from '@tanstack/vue-store'
194
- import {
195
- createPaginatedRowModel,
196
- rowPaginationFeature,
197
- tableFeatures,
198
- useTable,
199
- type PaginationState,
200
- } from '@tanstack/vue-table'
201
-
202
- const features = tableFeatures({ rowPaginationFeature })
203
-
204
- const paginationAtom = createAtom<PaginationState>({
205
- pageIndex: 0,
206
- pageSize: 10,
207
- })
208
- const pagination = useSelector(paginationAtom) // reactive ref-like
209
-
210
- const data = ref([] as Person[])
211
- const table = useTable({
212
- features,
213
- rowModels: { paginatedRowModel: createPaginatedRowModel() },
214
- columns,
215
- data,
216
- atoms: { pagination: paginationAtom },
217
- // NOTE: no `onPaginationChange` — `table.setPageIndex()` writes through to the atom.
218
- })
219
- </script>
220
-
221
- <template>
222
- <button @click="table.nextPage()" :disabled="!table.getCanNextPage()">
223
- Next
224
- </button>
225
- <span>Page {{ pagination.value.pageIndex + 1 }}</span>
226
- </template>
227
- ```
228
-
229
- Source: `examples/vue/basic-external-atoms/src/App.tsx`.
230
-
231
- ### 4. External `state` + `on[State]Change` with getters
232
-
233
- Still supported and convenient for migration paths. The critical rule: pass each slice as a
234
- **getter** so Vue can track `.value` changes. A raw ref captured in the state object is read
235
- once and never re-tracked.
236
-
237
- ```ts
238
- const sorting = ref<SortingState>([])
239
- const pagination = ref<PaginationState>({ pageIndex: 0, pageSize: 10 })
240
-
241
- const table = useTable({
242
- features,
243
- rowModels: {
244
- sortedRowModel: createSortedRowModel(sortFns),
245
- paginatedRowModel: createPaginatedRowModel(),
246
- },
247
- columns,
248
- data,
249
- state: {
250
- get sorting() {
251
- return sorting.value
252
- }, // <- getter
253
- get pagination() {
254
- return pagination.value
255
- }, // <- getter
256
- },
257
- onSortingChange: (u) => {
258
- sorting.value = typeof u === 'function' ? u(sorting.value) : u
259
- },
260
- onPaginationChange: (u) => {
261
- pagination.value = typeof u === 'function' ? u(pagination.value) : u
262
- },
263
- })
264
- ```
265
-
266
- Source: `examples/vue/basic-external-state/src/App.tsx`,
267
- `docs/framework/vue/guide/table-state.md` (External State).
268
-
269
- ### 5. `<FlexRender>` and `table.Subscribe`
270
-
271
- `<FlexRender>` accepts a `cell`, `header`, or `footer` prop (preferred). The legacy
272
- `:render` / `:props` pattern still works.
273
-
274
- ```vue
275
- <FlexRender :cell="cell" />
276
- <FlexRender :header="header" />
277
- <FlexRender :footer="header" />
278
-
279
- <!-- Legacy form -->
280
- <FlexRender :render="cell.column.columnDef.cell" :props="cell.getContext()" />
281
- ```
282
-
283
- `table.Subscribe` mostly mirrors React. It is rarely the right tool in Vue — prefer
284
- `computed(() => table.atoms.<slice>.get())` or the `useTable` selector. If you do need it
285
- (for cross-store source subscription), it accepts a `source` prop:
286
-
287
- ```ts
288
- // In a render function or JSX file
289
- return () => (
290
- <table.Subscribe source={someAtom} selector={(v) => v.someField}>
291
- {(value) => <span>{value}</span>}
292
- </table.Subscribe>
293
- )
294
- ```
295
-
296
- ## Common Mistakes
297
-
298
- ### Passing a `ref` to `state.pagination` without a getter (CRITICAL)
299
-
300
- ```ts
301
- // ❌ Captures the ref object; later `pagination.value = …` writes are invisible.
302
- const pagination = ref<PaginationState>({ pageIndex: 0, pageSize: 10 })
303
- const table = useTable({
304
- features,
305
- rowModels: {},
306
- columns,
307
- data,
308
- state: { pagination },
309
- })
310
-
311
- // ✅ Use a getter so Vue tracks `.value`.
312
- const table = useTable({
313
- features,
314
- rowModels: {},
315
- columns,
316
- data,
317
- state: {
318
- get pagination() {
319
- return pagination.value
320
- },
321
- },
322
- onPaginationChange: (u) => {
323
- pagination.value = typeof u === 'function' ? u(pagination.value) : u
324
- },
325
- })
326
- ```
327
-
328
- Source: `docs/framework/vue/guide/table-state.md` (External State).
329
-
330
- ### Reading `table.atoms.<slice>.get()` outside a reactive context (HIGH)
331
-
332
- ```ts
333
- // ❌ One-shot read at component setup — never updates.
334
- const pagination = table.atoms.pagination.get()
335
-
336
- // ✅ Wrap in `computed` so Vue tracks the atom.
337
- const pagination = computed(() => table.atoms.pagination.get())
338
- // or
339
- const table = useTable(opts, (s) => ({ pagination: s.pagination }))
340
- // then read `table.state.pagination`
341
- ```
342
-
343
- ### Using the v8 `useVueTable` name (HIGH)
344
-
345
- ```ts
346
- // ❌ Removed in v9.
347
- import { useVueTable } from '@tanstack/vue-table'
348
-
349
- // ✅
350
- import { useTable } from '@tanstack/vue-table'
351
- ```
352
-
353
- ### "API missing" because the feature is not in `features` (CRITICAL, v9-specific)
354
-
355
- ```ts
356
- // ❌ `rowSortingFeature` not registered → `table.setSorting` and `table.atoms.sorting` do not exist.
357
- const features = tableFeatures({})
358
- const table = useTable({ features, rowModels: {}, columns, data })
359
- table.setSorting([{ id: 'age', desc: true }]) // TS error / runtime no-op
360
-
361
- // ✅ Register the feature; add the matching row model factory if it's a row-model feature.
362
- const features = tableFeatures({ rowSortingFeature })
363
- const table = useTable({
364
- features,
365
- rowModels: { sortedRowModel: createSortedRowModel(sortFns) },
366
- columns,
367
- data,
368
- })
369
- ```
370
-
371
- ### Reimplementing built-in state transitions (CRITICAL — #1 AI tell)
372
-
373
- ```ts
374
- // ❌ Hand-rolled sort — bypasses the table's invariants and reset APIs.
375
- const sorting = ref<SortingState>([])
376
- const sorted = computed(() => [...data.value].sort(/* … */))
377
-
378
- // ✅ Let the table own it. Use `table.setSorting`, `column.toggleSorting`,
379
- // `header.column.getToggleSortingHandler()`.
380
- ```
381
-
382
- The library exposes `setSorting`, `setColumnFilters`, `toggleSelected`, `nextPage`, etc. for
383
- nearly every state transition.
384
-
385
- ### Hallucinating pre-v9 API names
386
-
387
- `useVueTable`, `getCoreRowModel()` as an option, `createColumnHelper<TData>()` (single generic),
388
- `sortingFn` instead of `sortFn` — all v8 shapes that will not compile. See
389
- `migrate-v8-to-v9` for the full rename list.
390
-
391
- ### Unstable `features` / `columns` / `data` identity
392
-
393
- Declare `features`, `columnHelper`, and `columns` **outside** `<script setup>` (at module
394
- scope) or use `computed`. Recreating them every render churns the table's option diff watcher
395
- and triggers a `setOptions` on every render — slow, and external atom slices can flicker.
396
-
397
- ## See Also
398
-
399
- - `tanstack-table/vue/getting-started` — the end-to-end first-table walkthrough
400
- - `tanstack-table/vue/production-readiness` — selectors, tree-shaking, identity
401
- - `tanstack-table/vue/compose-with-tanstack-store` — external atoms in depth
402
- - `tanstack-table/table-core/state-management` (core) — the atom model that drives this skill
403
- - `tanstack-table/vue/migrate-v8-to-v9` — `useVueTable` → `useTable`