@tanstack/svelte-table 9.0.0-alpha.47 → 9.0.0-alpha.49

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.
@@ -0,0 +1,340 @@
1
+ ---
2
+ name: svelte/getting-started
3
+ description: >
4
+ End-to-end first-table journey for `@tanstack/svelte-table@9` on Svelte 5. Install the adapter,
5
+ declare `_features` with `tableFeatures()`, register `_rowModels` factories with their `*Fns`
6
+ parameters, build a typed column helper with both `TFeatures` and `TData` generics, instantiate
7
+ the table with `createTable(options)` using `$state` data and `get data()` reactive option getters,
8
+ and render with `FlexRender`. Svelte 5+ only — Svelte 3/4 must use v8.
9
+ type: lifecycle
10
+ library: tanstack-table
11
+ framework: svelte
12
+ library_version: '9.0.0-alpha.48'
13
+ requires:
14
+ - setup
15
+ - column-definitions
16
+ - state-management
17
+ - svelte/table-state
18
+ sources:
19
+ - TanStack/table:docs/installation.md
20
+ - TanStack/table:docs/framework/svelte/svelte-table.md
21
+ - TanStack/table:examples/svelte/basic-create-table/
22
+ - TanStack/table:examples/svelte/basic-app-table/
23
+ - TanStack/table:examples/svelte/basic-snippets/
24
+ - TanStack/table:packages/svelte-table/src/index.ts
25
+ ---
26
+
27
+ # Getting Started — Svelte
28
+
29
+ A first working `@tanstack/svelte-table` v9 table from a blank Svelte 5 project. Read this
30
+ end-to-end before searching the docs — the v9 shape diverges enough from v8 (and from your
31
+ muscle memory) that skimming will produce broken code.
32
+
33
+ ## CRITICAL: Svelte version
34
+
35
+ **`@tanstack/svelte-table@9` requires Svelte 5 or newer.** The adapter is built on runes
36
+ (`$state`, `$derived.by`, `$effect.pre`). If your project is on Svelte 3 or 4, do **one** of:
37
+
38
+ - Upgrade the project to Svelte 5, then install v9.
39
+ - Stay on `@tanstack/svelte-table@8` for that project.
40
+
41
+ There is no shim, no `/legacy` export, and no support path that runs v9 on Svelte 4.
42
+
43
+ ## 1. Install
44
+
45
+ ```bash
46
+ pnpm add @tanstack/svelte-table
47
+ # optional: external atoms / fine-grained selectors
48
+ pnpm add @tanstack/svelte-store
49
+ ```
50
+
51
+ You do **not** install `@tanstack/table-core` separately — the Svelte adapter re-exports
52
+ everything you need (column helpers, feature objects, row-model factories, types).
53
+
54
+ ## 2. Define `_features` and `_rowModels`
55
+
56
+ v9 is explicit. You opt in to every feature and every row model. The core row model is
57
+ included by default, so the minimum viable table is:
58
+
59
+ ```ts
60
+ const _features = tableFeatures({})
61
+ const _rowModels = {}
62
+ ```
63
+
64
+ For anything beyond a flat table, register the features you'll use **and** the matching
65
+ row-model factories. Row-model factories take `*Fns` registries as parameters:
66
+
67
+ ```ts
68
+ import {
69
+ columnFilteringFeature,
70
+ createFilteredRowModel,
71
+ createPaginatedRowModel,
72
+ createSortedRowModel,
73
+ filterFns,
74
+ rowPaginationFeature,
75
+ rowSortingFeature,
76
+ sortFns,
77
+ tableFeatures,
78
+ } from '@tanstack/svelte-table'
79
+
80
+ const _features = tableFeatures({
81
+ rowPaginationFeature,
82
+ rowSortingFeature,
83
+ columnFilteringFeature,
84
+ })
85
+
86
+ const _rowModels = {
87
+ paginatedRowModel: createPaginatedRowModel(),
88
+ sortedRowModel: createSortedRowModel(sortFns),
89
+ filteredRowModel: createFilteredRowModel(filterFns),
90
+ }
91
+ ```
92
+
93
+ **Skipping a feature** in `_features` means its state slice does not exist on `table.atoms`,
94
+ its options on `createTable` do nothing, and its derived APIs (`table.setSorting`,
95
+ `column.getCanSort`) are not on the instance.
96
+
97
+ ## 3. Type your data and define columns
98
+
99
+ ```ts
100
+ type Person = {
101
+ firstName: string
102
+ lastName: string
103
+ age: number
104
+ visits: number
105
+ status: 'relationship' | 'complicated' | 'single'
106
+ progress: number
107
+ }
108
+ ```
109
+
110
+ Both `ColumnDef` and the column helper take the two generics `<typeof _features, TData>`:
111
+
112
+ ```ts
113
+ import { createColumnHelper, type ColumnDef } from '@tanstack/svelte-table'
114
+
115
+ const columnHelper = createColumnHelper<typeof _features, Person>()
116
+
117
+ const columns = columnHelper.columns([
118
+ columnHelper.accessor('firstName', {
119
+ header: 'First Name',
120
+ cell: (info) => info.getValue(),
121
+ }),
122
+ columnHelper.accessor((row) => row.lastName, {
123
+ id: 'lastName',
124
+ header: () => 'Last Name',
125
+ cell: (info) => info.getValue(),
126
+ }),
127
+ columnHelper.accessor('age', { header: 'Age' }),
128
+ columnHelper.accessor('visits', { header: 'Visits' }),
129
+ columnHelper.accessor('status', { header: 'Status' }),
130
+ columnHelper.accessor('progress', { header: 'Profile Progress' }),
131
+ ])
132
+ ```
133
+
134
+ Or use raw `ColumnDef` arrays if you don't want the helper:
135
+
136
+ ```ts
137
+ const columns: Array<ColumnDef<typeof _features, Person>> = [
138
+ {
139
+ accessorKey: 'firstName',
140
+ header: 'First Name',
141
+ cell: (info) => info.getValue(),
142
+ },
143
+ ]
144
+ ```
145
+
146
+ ## 4. Create the table
147
+
148
+ Use Svelte 5 `$state` for the data and pass it through a **reactive getter** so the table
149
+ re-evaluates `data` when the rune changes. The same pattern applies for any other reactive
150
+ option (`columns`, `rowCount`, `state.*`).
151
+
152
+ ```svelte
153
+ <script lang="ts">
154
+ import { createTable, tableFeatures } from '@tanstack/svelte-table'
155
+ import { makeData, type Person } from './makeData'
156
+
157
+ const _features = tableFeatures({})
158
+
159
+ // ... columns from step 3 ...
160
+
161
+ let data = $state<Person[]>(makeData(20))
162
+
163
+ const refreshData = () => {
164
+ data = makeData(20)
165
+ }
166
+
167
+ const table = createTable({
168
+ _features,
169
+ _rowModels: {},
170
+ columns,
171
+ get data() {
172
+ return data
173
+ },
174
+ })
175
+ </script>
176
+ ```
177
+
178
+ `createTable` syncs options inside `$effect.pre`, so external `$state` updates flow into the
179
+ table **before** the DOM reads `getRowModel()` — no stale-frame bugs.
180
+
181
+ ## 5. Render with `FlexRender`
182
+
183
+ `FlexRender` handles plain strings, function renderers, component renderers
184
+ (`renderComponent`), and snippet renderers (`renderSnippet`).
185
+
186
+ ```svelte
187
+ <script lang="ts">
188
+ import { FlexRender } from '@tanstack/svelte-table'
189
+ </script>
190
+
191
+ <button onclick={refreshData}>Regenerate</button>
192
+
193
+ <table>
194
+ <thead>
195
+ {#each table.getHeaderGroups() as headerGroup (headerGroup.id)}
196
+ <tr>
197
+ {#each headerGroup.headers as header (header.id)}
198
+ <th>
199
+ {#if !header.isPlaceholder}
200
+ <FlexRender {header} />
201
+ {/if}
202
+ </th>
203
+ {/each}
204
+ </tr>
205
+ {/each}
206
+ </thead>
207
+ <tbody>
208
+ {#each table.getRowModel().rows as row (row.id)}
209
+ <tr>
210
+ {#each row.getAllCells() as cell (cell.id)}
211
+ <td><FlexRender {cell} /></td>
212
+ {/each}
213
+ </tr>
214
+ {/each}
215
+ </tbody>
216
+ </table>
217
+ ```
218
+
219
+ **Key the `{#each}` blocks on stable ids.** Without keys, Svelte recreates nodes and loses
220
+ focus, scroll, and any per-row component state.
221
+
222
+ ## 6. Adding a feature — pagination
223
+
224
+ ```svelte
225
+ <script lang="ts">
226
+ import {
227
+ createPaginatedRowModel,
228
+ createTable,
229
+ rowPaginationFeature,
230
+ tableFeatures,
231
+ } from '@tanstack/svelte-table'
232
+
233
+ const _features = tableFeatures({ rowPaginationFeature })
234
+
235
+ const table = createTable({
236
+ _features,
237
+ _rowModels: {
238
+ paginatedRowModel: createPaginatedRowModel(),
239
+ },
240
+ columns,
241
+ get data() {
242
+ return data
243
+ },
244
+ initialState: {
245
+ pagination: { pageIndex: 0, pageSize: 10 },
246
+ },
247
+ })
248
+ </script>
249
+
250
+ <div>
251
+ <button
252
+ onclick={() => table.previousPage()}
253
+ disabled={!table.getCanPreviousPage()}>Prev</button
254
+ >
255
+ <span
256
+ >Page {table.atoms.pagination.get().pageIndex + 1} of {table.getPageCount()}</span
257
+ >
258
+ <button onclick={() => table.nextPage()} disabled={!table.getCanNextPage()}
259
+ >Next</button
260
+ >
261
+ </div>
262
+ ```
263
+
264
+ To make pagination reactive in the controls, either pass a selector to `createTable` or use
265
+ `subscribeTable`:
266
+
267
+ ```ts
268
+ import { subscribeTable } from '@tanstack/svelte-table'
269
+
270
+ const pagination = subscribeTable(table.atoms.pagination)
271
+ // pagination.current.pageIndex is reactive
272
+ ```
273
+
274
+ ## 7. `createTableHook` (when you have more than one table)
275
+
276
+ For apps with multiple tables, define the `_features`, `_rowModels`, and shared components
277
+ once:
278
+
279
+ ```ts
280
+ // hooks/table.ts
281
+ import {
282
+ createPaginatedRowModel,
283
+ createSortedRowModel,
284
+ createTableHook,
285
+ rowPaginationFeature,
286
+ rowSortingFeature,
287
+ sortFns,
288
+ tableFeatures,
289
+ } from '@tanstack/svelte-table'
290
+
291
+ export const { createAppTable, createAppColumnHelper } = createTableHook({
292
+ _features: tableFeatures({ rowPaginationFeature, rowSortingFeature }),
293
+ _rowModels: {
294
+ paginatedRowModel: createPaginatedRowModel(),
295
+ sortedRowModel: createSortedRowModel(sortFns),
296
+ },
297
+ })
298
+ ```
299
+
300
+ ```svelte
301
+ <script lang="ts">
302
+ import { createAppColumnHelper, createAppTable } from './hooks/table'
303
+
304
+ const columnHelper = createAppColumnHelper<Person>()
305
+ const columns = columnHelper.columns([
306
+ columnHelper.accessor('firstName', { header: 'First' }),
307
+ ])
308
+
309
+ const table = createAppTable({
310
+ columns,
311
+ get data() {
312
+ return data
313
+ },
314
+ })
315
+ </script>
316
+ ```
317
+
318
+ ## Common failure modes
319
+
320
+ - **Svelte 3/4.** Adapter will not work. See top of file.
321
+ - **`createSvelteTable` / `useSvelteTable` / `getCoreRowModel`** — all v8 names. v9 uses
322
+ `createTable` and `_rowModels: { paginatedRowModel: createPaginatedRowModel(), ... }`.
323
+ - **Plain `data` instead of `get data()` getter.** Table will not see data updates. Always
324
+ pass a reactive getter for state that lives in `$state`.
325
+ - **Missing feature in `_features`.** `table.setSorting` / `column.getCanSort` won't exist.
326
+ TypeScript will tell you; if it doesn't, you're missing the `<typeof _features, TData>`
327
+ generics on the column helper or `ColumnDef`.
328
+ - **Plain object instead of `tableFeatures({...})`.** Loses typed atom keys; you'll get
329
+ `unknown` state shapes everywhere.
330
+ - **Unkeyed `{#each}` blocks.** Reuse bugs (focus jumps, wrong row selected).
331
+ - **Reimplementing built-ins.** If you write a manual sort comparator across rows, you're
332
+ re-doing `rowSortingFeature`. Register it instead.
333
+
334
+ ## Next steps
335
+
336
+ - `tanstack-table/svelte/table-state` — reactivity model, selectors, subscribeTable, ownership.
337
+ - `tanstack-table/core/filtering` / `pagination` / `sorting` / `row-selection` — feature-by-feature.
338
+ - `tanstack-table/svelte/compose-with-tanstack-query` — server-side data.
339
+ - `tanstack-table/svelte/compose-with-tanstack-virtual` — large datasets.
340
+ - `tanstack-table/svelte/production-readiness` — selector tuning, bundle size.
@@ -0,0 +1,256 @@
1
+ ---
2
+ name: svelte/migrate-v8-to-v9
3
+ description: >
4
+ Mechanical migration from `@tanstack/svelte-table@8` to `@tanstack/svelte-table@9`. v9 in Svelte
5
+ is a full rewrite — Svelte 5 runes only (no Svelte 3/4), no `/legacy` adapter (unlike React),
6
+ `createSvelteTable` → `createTable`, `getCoreRowModel` / `getSortedRowModel` factories → required
7
+ `_features` + `_rowModels` registration, `flexRender` helper → `<FlexRender>` component,
8
+ writable-store `state` → rune-based getters / external atoms, `onStateChange` → per-slice
9
+ `on[State]Change` or `atoms`. Plan a feature-by-feature audit, not a search-and-replace.
10
+ type: lifecycle
11
+ library: tanstack-table
12
+ framework: svelte
13
+ library_version: '9.0.0-alpha.48'
14
+ requires:
15
+ - setup
16
+ - state-management
17
+ - column-definitions
18
+ sources:
19
+ - TanStack/table:docs/framework/svelte/svelte-table.md
20
+ - TanStack/table:docs/framework/svelte/guide/table-state.md
21
+ - TanStack/table:packages/svelte-table/src/
22
+ - TanStack/table:examples/svelte/basic-create-table/
23
+ - TanStack/table:examples/svelte/basic-external-atoms/
24
+ - TanStack/table:examples/svelte/basic-external-state/
25
+ ---
26
+
27
+ # Migrate v8 → v9 (Svelte)
28
+
29
+ ## CRITICAL: v9 = Svelte 5
30
+
31
+ **v9 of the Svelte adapter only supports Svelte 5+.** No backport. No shim. No `/legacy` import.
32
+ The v9 adapter is built on Svelte 5 runes (`$state`, `$derived.by`, `$effect.pre`). If your app
33
+ is still on Svelte 3/4, you have two real options:
34
+
35
+ 1. Stay on `@tanstack/svelte-table@8`. v8 keeps working with the Svelte 3/4 writable-store API.
36
+ 2. Migrate the app to Svelte 5 first, then migrate the table.
37
+
38
+ There is no third option. Trying to install v9 on a Svelte 4 codebase will error at compile.
39
+
40
+ > This makes the Svelte migration heavier than React's. React has a `/legacy` re-export that
41
+ > mirrors the v8 surface; Svelte does not. Plan for a real rewrite of every table screen.
42
+
43
+ ## What changed at the type / API level
44
+
45
+ | v8 | v9 |
46
+ | -------------------------------------------------- | ------------------------------------------------------------------------------------- |
47
+ | `createSvelteTable(options)` | `createTable(options, selector?)` |
48
+ | `getCoreRowModel()` | included by default; no factory |
49
+ | `getPaginationRowModel()` | `_rowModels.paginatedRowModel: createPaginatedRowModel()` |
50
+ | `getSortedRowModel()` | `_rowModels.sortedRowModel: createSortedRowModel(sortFns)` |
51
+ | `getFilteredRowModel()` | `_rowModels.filteredRowModel: createFilteredRowModel(filterFns)` |
52
+ | `getExpandedRowModel()` | `_rowModels.expandedRowModel: createExpandedRowModel()` |
53
+ | `getGroupedRowModel()` | `_rowModels.groupedRowModel: createGroupedRowModel(aggregationFns)` |
54
+ | `getFacetedRowModel()` / `MinMax` / `UniqueValues` | facet APIs auto-derived when `*Facet*Feature` registered |
55
+ | `flexRender(template, ctx)` helper | `<FlexRender header={h} />` / `<FlexRender cell={c} />` / `<FlexRender footer={h} />` |
56
+ | `ColumnDef<TData>` | `ColumnDef<TFeatures, TData>` (extra generic) |
57
+ | `createColumnHelper<TData>()` | `createColumnHelper<TFeatures, TData>()` |
58
+ | writable store on the table instance | `table.atoms.<slice>` + `table.store` + `table.state` |
59
+ | `onStateChange` (monolithic) | per-slice `on[State]Change`, or external `atoms` |
60
+ | `useSvelteTable` (rare) | gone |
61
+
62
+ ## What did NOT change
63
+
64
+ - The data array is still the source of truth; columns are still defined the same way
65
+ shape-wise (`accessorKey` / `accessorFn` / `header` / `cell` / `footer`).
66
+ - Filter, sort, aggregation function registries are still `filterFns`, `sortFns`,
67
+ `aggregationFns` — but now passed into row-model factories instead of being auto-resolved.
68
+ - Feature APIs (`table.nextPage()`, `column.getCanSort()`, `row.toggleSelected()`) keep the
69
+ same names.
70
+
71
+ ## Migration checklist (per file)
72
+
73
+ For each Svelte component that uses the table:
74
+
75
+ 1. **Upgrade Svelte.** Ensure the app is on Svelte 5 and the component compiles in runes mode.
76
+ 2. **Replace store with rune.** `let data = writable([])` → `let data = $state([])`. Reads
77
+ inside markup are no longer `$data` — just `data`.
78
+ 3. **Import surface.** `import { createSvelteTable, getCoreRowModel, flexRender }` →
79
+ `import { createTable, FlexRender, tableFeatures, ... }`.
80
+ 4. **Add `_features`.** Create `const _features = tableFeatures({ ... only the features this
81
+ table uses ... })`.
82
+ 5. **Move row-model factories.** Every `get*RowModel: get*RowModel()` becomes a `_rowModels`
83
+ entry with the matching `create*RowModel(*Fns)` factory.
84
+ 6. **Generic columns.** Add `<typeof _features, TData>` to `ColumnDef<>` and
85
+ `createColumnHelper<>()`. TypeScript will tell you when you missed one.
86
+ 7. **`data` as a getter.** `data: data` → `get data() { return data }`. Same for any other
87
+ reactive option (`state.*`, `columns`, `rowCount`).
88
+ 8. **State.** Pick the new ownership model — see below.
89
+ 9. **Rendering.** `{flexRender(header.column.columnDef.header, header.getContext())}` →
90
+ `<FlexRender header={header} />`. Same for cells and footers.
91
+ 10. **Components / snippets in cells.** v8: pass a Svelte component constructor. v9: wrap with
92
+ `renderComponent(MyCell, props)` or `renderSnippet(snippet, args)`.
93
+
94
+ ## State ownership — choose one per slice
95
+
96
+ ### Was: `writable` store + `onStateChange`
97
+
98
+ ```svelte
99
+ <script lang="ts">
100
+ // v8
101
+ import { writable } from 'svelte/store'
102
+ const options = writable({ ... })
103
+ $: $options.state = $state
104
+ </script>
105
+ ```
106
+
107
+ ### Now: pick one of three
108
+
109
+ **Internal (default).** Pass only `initialState` and let the table own it.
110
+
111
+ ```ts
112
+ const table = createTable({
113
+ _features,
114
+ _rowModels: { paginatedRowModel: createPaginatedRowModel() },
115
+ columns,
116
+ get data() {
117
+ return data
118
+ },
119
+ initialState: {
120
+ pagination: { pageIndex: 0, pageSize: 25 },
121
+ },
122
+ })
123
+ ```
124
+
125
+ **External `state` + per-slice `on[State]Change`.** Closest to a literal v8 port.
126
+
127
+ ```svelte
128
+ <script lang="ts">
129
+ let sorting: SortingState = $state([])
130
+ let pagination: PaginationState = $state({ pageIndex: 0, pageSize: 10 })
131
+
132
+ const table = createTable({
133
+ _features,
134
+ _rowModels: { ... },
135
+ columns,
136
+ get data() { return data },
137
+ state: {
138
+ get sorting() { return sorting },
139
+ get pagination() { return pagination },
140
+ },
141
+ onSortingChange: (updater) => {
142
+ sorting = updater instanceof Function ? updater(sorting) : updater
143
+ },
144
+ onPaginationChange: (updater) => {
145
+ pagination = updater instanceof Function ? updater(pagination) : updater
146
+ },
147
+ })
148
+ </script>
149
+ ```
150
+
151
+ **External atoms (preferred for shared state).** Atomic, subscribable from anywhere.
152
+
153
+ ```ts
154
+ import { createAtom, useSelector } from '@tanstack/svelte-store'
155
+
156
+ const sortingAtom = createAtom<SortingState>([])
157
+ const paginationAtom = createAtom<PaginationState>({ pageIndex: 0, pageSize: 10 })
158
+
159
+ const sorting = useSelector(sortingAtom)
160
+ const pagination = useSelector(paginationAtom)
161
+
162
+ const table = createTable({
163
+ _features,
164
+ _rowModels: { ... },
165
+ columns,
166
+ get data() { return data },
167
+ atoms: {
168
+ sorting: sortingAtom,
169
+ pagination: paginationAtom,
170
+ },
171
+ })
172
+ ```
173
+
174
+ **Do not combine** `state.pagination` with `atoms.pagination` — atoms always win, `state` is
175
+ discarded silently, you'll think your callbacks aren't firing.
176
+
177
+ ## Rendering migration cheat sheet
178
+
179
+ ```svelte
180
+ <!-- v8 -->
181
+ <th>
182
+ {#if !header.isPlaceholder}
183
+ <svelte:component
184
+ this={flexRender(header.column.columnDef.header, header.getContext())}
185
+ />
186
+ {/if}
187
+ </th>
188
+
189
+ <!-- v9 -->
190
+ <th>
191
+ {#if !header.isPlaceholder}
192
+ <FlexRender {header} />
193
+ {/if}
194
+ </th>
195
+ ```
196
+
197
+ For cells that render a custom Svelte component:
198
+
199
+ ```svelte
200
+ <!-- v8: column def -->
201
+ { cell: () => MyCellComponent }
202
+
203
+ <!-- v9: column def -->
204
+ import { renderComponent } from '@tanstack/svelte-table'
205
+ { cell: ({ row }) => renderComponent(MyCellComponent, { row }) }
206
+ ```
207
+
208
+ For inline snippets:
209
+
210
+ ```svelte
211
+ <!-- v9 -->
212
+ import { renderSnippet } from '@tanstack/svelte-table'
213
+
214
+ {#snippet myCell(row)}
215
+ <strong>{row.original.firstName}</strong>
216
+ {/snippet}
217
+
218
+ { cell: ({ row }) => renderSnippet(myCell, row) }
219
+ ```
220
+
221
+ ## After the rewrite — verify
222
+
223
+ - `pnpm test:types` (or `svelte-check`) catches missing `<typeof _features, TData>` generics,
224
+ missing `_features` / `_rowModels`, and feature APIs called on tables that didn't register
225
+ them.
226
+ - `pnpm build` should pass with the new `_features` set. Bundle should shrink — only the
227
+ features you register are included.
228
+ - Click through every table screen. Reset buttons, multi-sort, pagination reset on filter,
229
+ expanded-row count under pagination — these are all the spots where v8 muscle memory
230
+ reaches for an option (`autoResetPageIndex` etc.) that's still named the same in v9 but
231
+ only takes effect if the matching feature is registered.
232
+
233
+ ## Common failure modes during migration
234
+
235
+ - **Trying to skip the Svelte 5 upgrade.** Will not work.
236
+ - **Reaching for `useLegacyTable`.** Doesn't exist in `@tanstack/svelte-table`. That's a
237
+ React-only escape hatch.
238
+ - **Importing from `@tanstack/table-core` directly.** Re-exported by the adapter — go through
239
+ the adapter.
240
+ - **Plain `data` instead of `get data()` getter.** Largest single source of "but my data
241
+ changed" bugs during migration.
242
+ - **Plain `_features: { rowPaginationFeature }` instead of `tableFeatures({...})`.** Loses
243
+ inference; you'll get `any` everywhere.
244
+ - **Forgetting feature registration after copying the row-model factory.** Adding
245
+ `paginatedRowModel: createPaginatedRowModel()` without `rowPaginationFeature` in
246
+ `_features` does nothing.
247
+ - **Reimplementing v8 helpers** (`flexRender`-style functions, manual store subscriptions,
248
+ hand-rolled selectors) instead of using `FlexRender` / `subscribeTable` / atom selectors.
249
+ That's the #1 AI tell on this migration.
250
+
251
+ ## Related skills
252
+
253
+ - `tanstack-table/svelte/getting-started` — clean-slate setup.
254
+ - `tanstack-table/svelte/table-state` — the v9 state model in depth.
255
+ - `tanstack-table/core/state-management` — atom precedence rules.
256
+ - `tanstack-table/svelte/production-readiness` — post-migration tuning.