@tanstack/svelte-table 9.0.0-beta.5 → 9.0.0-beta.51

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 (30) hide show
  1. package/README.md +2 -0
  2. package/dist/createTable.svelte.d.ts +0 -1
  3. package/dist/createTable.svelte.js +1 -2
  4. package/dist/createTableHook.svelte.d.ts +47 -13
  5. package/dist/createTableHook.svelte.js +16 -8
  6. package/dist/experimental-worker-plugin.d.ts +1 -0
  7. package/dist/experimental-worker-plugin.js +1 -0
  8. package/dist/index.d.ts +1 -1
  9. package/dist/render-component.js +4 -0
  10. package/package.json +10 -5
  11. package/skills/create-table-hook/SKILL.md +168 -0
  12. package/skills/getting-started/SKILL.md +172 -0
  13. package/skills/migrate-v8-to-v9/SKILL.md +195 -0
  14. package/skills/table-state/SKILL.md +205 -0
  15. package/skills/with-tanstack-query/SKILL.md +147 -0
  16. package/skills/with-tanstack-virtual/SKILL.md +150 -0
  17. package/src/createTable.svelte.ts +1 -2
  18. package/src/createTableHook.svelte.ts +127 -21
  19. package/src/experimental-worker-plugin.ts +1 -0
  20. package/src/index.ts +1 -0
  21. package/skills/svelte/client-to-server/SKILL.md +0 -238
  22. package/skills/svelte/compose-with-tanstack-form/SKILL.md +0 -295
  23. package/skills/svelte/compose-with-tanstack-pacer/SKILL.md +0 -176
  24. package/skills/svelte/compose-with-tanstack-query/SKILL.md +0 -299
  25. package/skills/svelte/compose-with-tanstack-store/SKILL.md +0 -277
  26. package/skills/svelte/compose-with-tanstack-virtual/SKILL.md +0 -286
  27. package/skills/svelte/getting-started/SKILL.md +0 -340
  28. package/skills/svelte/migrate-v8-to-v9/SKILL.md +0 -256
  29. package/skills/svelte/production-readiness/SKILL.md +0 -256
  30. package/skills/svelte/table-state/SKILL.md +0 -441
@@ -0,0 +1,195 @@
1
+ ---
2
+ name: migrate-v8-to-v9
3
+ description: >
4
+ Complete Svelte v8-to-v9 migration reference: Svelte 5, createTable, explicit features and row-model slots, atom/rune state, rendering helpers, prototype methods, type generics, sorting, sizing, selection, and logical pinning.
5
+ metadata:
6
+ type: lifecycle
7
+ library: '@tanstack/svelte-table'
8
+ framework: svelte
9
+ library_version: '9.0.0-beta.51'
10
+ requires:
11
+ - '@tanstack/table-core#migrate-v8-to-v9'
12
+ - getting-started
13
+ - table-state
14
+ sources:
15
+ - 'TanStack/table:docs/framework/svelte/guide/migrating.md'
16
+ - 'TanStack/table:packages/svelte-table/src/index.ts'
17
+ - 'TanStack/table:examples/svelte/basic-create-table'
18
+ ---
19
+
20
+ Use this as the complete breaking-change checklist, not merely a quick start. V9 is treated as the current API. Migrate the app to Svelte 5 before migrating Table; the v9 adapter has no Svelte 3/4 compatibility layer.
21
+
22
+ Framework prerequisite: Svelte 5 (`svelte ^5.0.0`).
23
+
24
+ ## Recommended Migration Order
25
+
26
+ 1. Upgrade to Svelte 5 and replace v8 stores with runes/getters.
27
+ 2. Rename `createSvelteTable` to `createTable`.
28
+ 3. Define explicit `tableFeatures`, then move row models and registries into it.
29
+ 4. Update state reads/ownership and rendering.
30
+ 5. Apply every shared API and type rename below.
31
+ 6. Use `stockFeatures` only as a temporary audit bridge; explicit features are the production target.
32
+
33
+ ```ts
34
+ const features = tableFeatures({
35
+ rowSortingFeature,
36
+ sortedRowModel: createSortedRowModel(),
37
+ sortFns: { alphanumeric: sortFn_alphanumeric },
38
+ })
39
+
40
+ const table = createTable({
41
+ features,
42
+ columns,
43
+ get data() {
44
+ return data
45
+ },
46
+ })
47
+ ```
48
+
49
+ ## Construction and Feature Registration
50
+
51
+ | v8 | v9 |
52
+ | -------------------------------------------- | ---------------------------------------------------------- |
53
+ | `createSvelteTable(options)` | `createTable(options, selector?)` |
54
+ | All features bundled | Required `features: tableFeatures({...})` |
55
+ | `getCoreRowModel()` option | Remove; the core row model is automatic |
56
+ | `get*RowModel()` table options | `create*RowModel()` slots in `tableFeatures` |
57
+ | `sortingFns` table option | `sortFns` feature slot |
58
+ | `filterFns` / `aggregationFns` table options | Same-named feature slots |
59
+ | Top-level `onStateChange` | Per-slice callbacks, external atoms, or store subscription |
60
+
61
+ Available feature imports are `columnFilteringFeature`, `globalFilteringFeature`, `rowSortingFeature`, `rowPaginationFeature`, `rowSelectionFeature`, `rowExpandingFeature`, `rowPinningFeature`, `columnPinningFeature`, `columnVisibilityFeature`, `columnOrderingFeature`, `columnSizingFeature`, `columnResizingFeature`, `rowAggregationFeature`, `columnGroupingFeature`, and `columnFacetingFeature`. An API does not exist unless its feature is registered. Put a feature before its dependent slot in the same `tableFeatures` call. Aggregation is independent from grouping: register `rowAggregationFeature` for aggregation APIs and add `columnGroupingFeature` only for grouped rows.
62
+
63
+ ### Row-model mapping
64
+
65
+ | v8 option | v9 slot and factory |
66
+ | -------------------------- | ------------------------------------------------------------------- |
67
+ | `getFilteredRowModel()` | `filteredRowModel: createFilteredRowModel()` after column filtering |
68
+ | `getSortedRowModel()` | `sortedRowModel: createSortedRowModel()` after row sorting |
69
+ | `getPaginationRowModel()` | `paginatedRowModel: createPaginatedRowModel()` after pagination |
70
+ | `getExpandedRowModel()` | `expandedRowModel: createExpandedRowModel()` after expanding |
71
+ | `getGroupedRowModel()` | `groupedRowModel: createGroupedRowModel()` after grouping |
72
+ | `getFacetedRowModel()` | `facetedRowModel: createFacetedRowModel()` after faceting |
73
+ | `getFacetedMinMaxValues()` | `facetedMinMaxValues: createFacetedMinMaxValues()` |
74
+ | `getFacetedUniqueValues()` | `facetedUniqueValues: createFacetedUniqueValues()` |
75
+
76
+ Factories take no arguments. Register `filterFns`, `sortFns`, and `aggregationFns` as sibling feature slots holding individually imported built-ins (`filterFn_includesString`, `sortFn_alphanumeric`, `aggregationFn_sum`) under their conventional keys. The full registry objects still work but bundle every built-in.
77
+
78
+ ## Svelte State Migration
79
+
80
+ - Reactive option inputs must remain live: use getters for rune values such as `data` and controlled state slices.
81
+ - `table.getState().sorting` becomes `table.state.sorting`, `table.store.state.sorting`, or the narrow `table.atoms.sorting.get()`.
82
+ - `table.state` contains all registered state by default. Pass a second-argument selector to `createTable` only to narrow its reactive surface.
83
+ - `subscribeTable(table.atoms.pagination, selector?)` exposes `.current` for fine-grained template subscriptions.
84
+ - For Svelte-owned controlled slices, use `createTableState` and matching `onSortingChange`, `onPaginationChange`, and other per-slice callbacks.
85
+ - For shared ownership, provide atoms created by `@tanstack/svelte-store` through `atoms`. Never provide both `atoms.pagination` and `state.pagination`.
86
+ - Subscribe to `table.store` to observe every state change. Do not port the removed top-level `onStateChange`.
87
+ - Treat `table.baseAtoms` as internal writable state; prefer feature APIs or external atoms.
88
+
89
+ ## Rendering and Composition
90
+
91
+ | v8 | v9 |
92
+ | ---------------------------------------- | -------------------------------------------------------------------------------- |
93
+ | `flexRender(...)` / `<svelte:component>` | `<FlexRender {cell} />`, `<FlexRender {header} />`, or `<FlexRender {footer} />` |
94
+ | Component returned directly | `renderComponent(Component, props)` |
95
+ | Svelte snippet content | `renderSnippet(snippet, props)` |
96
+ | Repeated raw options | `tableOptions(...)` composition |
97
+ | Repeated table conventions | `createTableHook({ features, ... })` and its pre-bound helpers |
98
+
99
+ `createTableHook` returns a feature-bound table creator and column helper; use it for application-wide conventions, not as a required migration step.
100
+
101
+ ## Complete Shared Breaking-Change Map
102
+
103
+ ### Instance methods
104
+
105
+ Row, cell, column, header, and related object methods now live on shared prototypes and use `this`. Call `row.getValue(...)`, `cell.getContext()`, `column.getCanSort()`, and `header.getContext()` on their instances. Do not destructure them or pass them as bare callbacks. They are not own enumerable properties, so object spread, `Object.keys`, and JSON serialization do not preserve them. Table methods are not affected.
106
+
107
+ ### Logical column pinning
108
+
109
+ There are no `left`/`right` aliases in beta.38.
110
+
111
+ | old | new |
112
+ | -------------------------------------------------------------- | ------------------------------------------------------------- |
113
+ | `columnPinning.left` / `.right` | `.start` / `.end` |
114
+ | `column.pin('left' \| 'right')` | `column.pin('start' \| 'end')` |
115
+ | `getIsPinned() === 'left' \| 'right'` | `'start' \| 'end'` |
116
+ | `row.getLeftVisibleCells()` / `getRightVisibleCells()` | `getStartVisibleCells()` / `getEndVisibleCells()` |
117
+ | `getLeftHeaderGroups()` / `getRightHeaderGroups()` | `getStartHeaderGroups()` / `getEndHeaderGroups()` |
118
+ | `getLeftFooterGroups()` / `getRightFooterGroups()` | `getStartFooterGroups()` / `getEndFooterGroups()` |
119
+ | `getLeftFlatHeaders()` / `getRightFlatHeaders()` | `getStartFlatHeaders()` / `getEndFlatHeaders()` |
120
+ | `getLeftLeafHeaders()` / `getRightLeafHeaders()` | `getStartLeafHeaders()` / `getEndLeafHeaders()` |
121
+ | `getLeftLeafColumns()` / `getRightLeafColumns()` | `getStartLeafColumns()` / `getEndLeafColumns()` |
122
+ | `getLeftVisibleLeafColumns()` / `getRightVisibleLeafColumns()` | `getStartVisibleLeafColumns()` / `getEndVisibleLeafColumns()` |
123
+ | `getLeftTotalSize()` / `getRightTotalSize()` | `getStartTotalSize()` / `getEndTotalSize()` |
124
+ | `column.getStart('left')` | `column.getStart('start')` |
125
+ | `column.getAfter('right')` | `column.getAfter('end')` |
126
+ | `column.getIndex('left' \| 'right')` | `column.getIndex('start' \| 'end')` |
127
+
128
+ This is logical region naming, not automatic DOM direction handling. Prefer CSS `inset-inline-start`/`inset-inline-end`. `columnResizeDirection` is unchanged.
129
+
130
+ ### Feature and state splits
131
+
132
+ - `enablePinning` splits into `enableColumnPinning` and `enableRowPinning`.
133
+ - Interactive resizing requires both `columnSizingFeature` and `columnResizingFeature`; fixed widths need only sizing.
134
+ - `columnSizingInfo` becomes `columnResizing`.
135
+ - `setColumnSizingInfo()` becomes `setColumnResizing()`.
136
+ - `onColumnSizingInfoChange` becomes `onColumnResizingChange`.
137
+
138
+ ### Sorting, rows, and selection
139
+
140
+ | v8 | v9 |
141
+ | ------------------------------ | ----------------------------- |
142
+ | `sortingFn` | `sortFn` |
143
+ | `sortingFns` | `sortFns` |
144
+ | `getSortingFn()` | `getSortFn()` |
145
+ | `getAutoSortingFn()` | `getAutoSortFn()` |
146
+ | `SortingFn` / `SortingFns` | `SortFn` / `SortFns` |
147
+ | `row._getAllCellsByColumnId()` | `row.getAllCellsByColumnId()` |
148
+
149
+ All other `_`-prefixed internal APIs are removed, including `_getPinnedRows`, `_getFacetedRowModel`, `_getFacetedMinMaxValues`, and `_getFacetedUniqueValues`; do not seek replacements unless a public API is documented.
150
+
151
+ `getIsSomeRowsSelected()` and `getIsSomePageRowsSelected()` now mean at least one, including all. For an indeterminate checkbox, combine “some” with `!getIsAllRowsSelected()` or `!getIsAllPageRowsSelected()`.
152
+
153
+ ## TypeScript Migration
154
+
155
+ - Core types now take `TFeatures` first: `ColumnDef<typeof features, Person>`, `Column<typeof features, Person>`, `Row<typeof features, Person>`, `Table<typeof features, Person>`.
156
+ - Replace `createColumnHelper<Person>()` with `createColumnHelper<typeof features, Person>()`; wrap arrays in `columnHelper.columns([...])` for inference.
157
+ - With `stockFeatures`, use `StockFeatures` as the feature type.
158
+ - `TableMeta` and `ColumnMeta` declaration merging still works only after adding `TFeatures` first. Prefer per-table `tableMeta`/`columnMeta: metaHelper<...>()` slots.
159
+ - Replace global `FilterFns`, `SortFns`, `AggregationFns`, and `FilterMeta` augmentation with `filterFns`, `sortFns`, `aggregationFns`, and `filterMeta: metaHelper<...>()` slots. Registered keys become valid string references.
160
+ - Prefer explicit object row types; `RowData` is restricted to records or arrays.
161
+
162
+ ## Common Migration Failures
163
+
164
+ ### CRITICAL: Running v9 on Svelte 3/4
165
+
166
+ Upgrade to Svelte 5 first. Writable-store-era table setup is not a supported v9 adapter contract.
167
+
168
+ ### HIGH: Moving the feature but not its row model
169
+
170
+ Register both the feature and its `create*RowModel()` slot. Leaving `get*RowModel` on table options silently leaves the v9 processing pipeline incomplete.
171
+
172
+ ### HIGH: Snapshotting a rune value
173
+
174
+ Use `get data() { return data }`; a one-time `data` snapshot does not remain reactive.
175
+
176
+ ### HIGH: Destructuring instance methods
177
+
178
+ Keep calls bound to row/cell/column/header instances; shallow copies do not contain prototype methods.
179
+
180
+ ## Final Checklist
181
+
182
+ - [ ] Svelte is version 5+; old writable-store patterns are removed.
183
+ - [ ] `createSvelteTable` is replaced by `createTable`.
184
+ - [ ] Explicit features, row models, and function registries are in `tableFeatures`.
185
+ - [ ] `getCoreRowModel` and the separate `rowModels` shape are removed.
186
+ - [ ] Reactive inputs and controlled slices use getters/runes; state reads use v9 surfaces.
187
+ - [ ] `onStateChange` is replaced; atom/state ownership does not overlap.
188
+ - [ ] Rendering uses `FlexRender`, `renderComponent`, or `renderSnippet`.
189
+ - [ ] Prototype method calls, pinning, sizing/resizing, sorting, row, and selection semantics are audited.
190
+ - [ ] Helpers, types, meta, registries, and `RowData` use the v9 generic/slot shapes.
191
+ - [ ] Temporary `stockFeatures` usage has an explicit removal plan.
192
+
193
+ ## API Discovery
194
+
195
+ Verify the installed target in `node_modules/@tanstack/svelte-table/src/index.ts` and its adapter sources. Verify feature slots and exact beta APIs in `node_modules/@tanstack/table-core/src`; do not reconstruct v9 APIs from v8 memory.
@@ -0,0 +1,205 @@
1
+ ---
2
+ name: table-state
3
+ description: >
4
+ Use Svelte 5 rune-backed table.atoms/store and selected table.state, reactive option getters, controlled $state slices, value-or-updater callbacks, external atoms, and auto-reset behavior without snapshot mismatches.
5
+ metadata:
6
+ type: framework
7
+ library: '@tanstack/svelte-table'
8
+ framework: svelte
9
+ library_version: '9.0.0-beta.51'
10
+ requires:
11
+ - '@tanstack/table-core#core'
12
+ - getting-started
13
+ sources:
14
+ - 'TanStack/table:docs/framework/svelte/guide/table-state.md'
15
+ - 'TanStack/table:docs/framework/svelte/guide/pagination.md'
16
+ - 'TanStack/table:examples/svelte/basic-external-state'
17
+ - 'TanStack/table:packages/svelte-table/src/createTable.svelte.ts'
18
+ ---
19
+
20
+ This skill builds on `@tanstack/table-core#core` and `getting-started`. Read them first for table ownership and Svelte construction.
21
+
22
+ ## State Mental Model
23
+
24
+ TanStack Table is primarily a state coordinator. Keep state internal unless another system must read, persist, or drive it. Without `initialState`, `atoms`, `state`, or `on[State]Change`, the table owns all registered slices.
25
+
26
+ - `table.baseAtoms` are internal writable atoms initialized from resolved initial state.
27
+ - `table.atoms` are readonly derived atoms for the active owner of each registered slice.
28
+ - `table.store` is the readonly flat store assembled from those atoms.
29
+ - `table.state` is only the result selected by the second `createTable` argument.
30
+
31
+ Svelte 5 backs these surfaces with runes and synchronizes reactive options before DOM updates. Only registered features create state and types. If pagination is missing, register `rowPaginationFeature`; do not add a cast or an ad hoc state field. Keep `features` and `columns` stable and pass changing `data` through a getter.
32
+
33
+ ## Setup
34
+
35
+ Keep state internal unless another subsystem needs to own it. Select only render state that the component needs.
36
+
37
+ ```svelte
38
+ <script lang="ts">
39
+ import {
40
+ createTable,
41
+ rowPaginationFeature,
42
+ tableFeatures,
43
+ } from '@tanstack/svelte-table'
44
+
45
+ const features = tableFeatures({ rowPaginationFeature })
46
+ const columns = [{ accessorKey: 'name' }]
47
+ let data = $state([{ name: 'Ada' }])
48
+ const table = createTable(
49
+ {
50
+ features,
51
+ columns,
52
+ get data() {
53
+ return data
54
+ },
55
+ },
56
+ (state) => ({ pagination: state.pagination }),
57
+ )
58
+ </script>
59
+
60
+ <button onclick={() => table.nextPage()} disabled={!table.getCanNextPage()}>
61
+ Page {table.state.pagination.pageIndex + 1}
62
+ </button>
63
+ ```
64
+
65
+ ## Core Patterns
66
+
67
+ ### Control a slice with value-or-updater semantics
68
+
69
+ ```ts
70
+ import type { PaginationState, Updater } from '@tanstack/svelte-table'
71
+
72
+ let pagination = $state<PaginationState>({ pageIndex: 0, pageSize: 20 })
73
+ const updatePagination = (next: Updater<PaginationState>) => {
74
+ pagination = typeof next === 'function' ? next(pagination) : next
75
+ }
76
+ ```
77
+
78
+ Pass `get state() { return { pagination } }` and `onPaginationChange: updatePagination` to `createTable`.
79
+
80
+ ### Subscribe narrowly outside selected table.state
81
+
82
+ ```ts
83
+ import { subscribeTable } from '@tanstack/svelte-table'
84
+
85
+ const pageIndex = subscribeTable(
86
+ table.atoms.pagination,
87
+ (value) => value.pageIndex,
88
+ )
89
+ ```
90
+
91
+ Read `pageIndex.current` in rune-tracked Svelte code. Use feature APIs for writes; `baseAtoms` is a low-level escape hatch.
92
+
93
+ ## Choose State Ownership
94
+
95
+ Use one owner per slice:
96
+
97
+ - Prefer internal state plus feature APIs for table-local interaction.
98
+ - Use `initialState` for starting/reset values; changing it later does not reset state.
99
+ - Prefer a stable external atom in `atoms` for state shared with Query, routing, or another component. Do not also add its change callback.
100
+ - Use a `$state` value exposed through a `state` getter plus the matching callback for simple controlled state. Always resolve value-or-updater semantics.
101
+
102
+ External atoms win over controlled `state`, which syncs into the internal base atom. Avoid multiple owners. The global v8 `onStateChange` option is gone; subscribe to `table.store` if all state changes must be observed.
103
+
104
+ ## Initialize, Update, and Reset
105
+
106
+ Prefer `setSorting`, `nextPage`, `toggleVisibility`, `toggleSelected`, and other feature APIs over direct state writes. Write a base atom only for rare internal-state needs; write the external atom when `atoms.<slice>` owns it.
107
+
108
+ ```ts
109
+ table.resetSorting()
110
+ table.resetPagination()
111
+ table.resetPagination(true)
112
+ ```
113
+
114
+ Feature resets use `table.initialState` unless `true` requests the feature default and can flow to external owners. Core `table.reset()` resets internal base atoms only. Use feature types such as `PaginationState` for a slice and `TableState<typeof features>` for the complete registered state.
115
+
116
+ ## Common Mistakes
117
+
118
+ ### HIGH Controlling without writing back
119
+
120
+ Wrong:
121
+
122
+ ```ts
123
+ const options = { state: { pagination }, onPaginationChange: console.log }
124
+ ```
125
+
126
+ Correct:
127
+
128
+ ```ts
129
+ const options = {
130
+ get state() {
131
+ return { pagination }
132
+ },
133
+ onPaginationChange: updatePagination,
134
+ }
135
+ ```
136
+
137
+ A controlled slice is frozen unless every updater is resolved into the owning rune.
138
+
139
+ Source: `docs/framework/svelte/guide/table-state.md`
140
+
141
+ ### HIGH Reading snapshots outside tracking
142
+
143
+ Wrong:
144
+
145
+ ```ts
146
+ const pageIndex = table.store.state.pagination.pageIndex
147
+ ```
148
+
149
+ Correct:
150
+
151
+ ```ts
152
+ const pageIndex = subscribeTable(
153
+ table.atoms.pagination,
154
+ (value) => value.pageIndex,
155
+ )
156
+ ```
157
+
158
+ `store.state` is a current snapshot; it does not create a future Svelte update outside a tracked scope.
159
+
160
+ Source: `packages/svelte-table/src/createTable.svelte.ts`
161
+
162
+ ### MEDIUM Declaring one slice in two owners
163
+
164
+ Wrong:
165
+
166
+ ```ts
167
+ const options = { initialState: { pagination: start }, state: { pagination } }
168
+ ```
169
+
170
+ Correct:
171
+
172
+ ```ts
173
+ const options = {
174
+ get state() {
175
+ return { pagination }
176
+ },
177
+ }
178
+ ```
179
+
180
+ Controlled `atoms` or `state` wins over `initialState`; choose one owner per slice.
181
+
182
+ Source: `docs/framework/svelte/guide/table-state.md`
183
+
184
+ ### MEDIUM Fighting automatic page reset
185
+
186
+ Wrong:
187
+
188
+ ```ts
189
+ table.setPageIndex(4)
190
+ data = filteredData
191
+ ```
192
+
193
+ Correct:
194
+
195
+ ```ts
196
+ const options = { autoResetPageIndex: false }
197
+ ```
198
+
199
+ Client row-model changes reset the page by default; disable it only when the application handles invalid empty pages.
200
+
201
+ Source: `docs/framework/svelte/guide/pagination.md`
202
+
203
+ ## API Discovery
204
+
205
+ Inspect `node_modules/@tanstack/svelte-table/src/createTable.svelte.ts`, `createTableState.svelte.ts`, and `subscribe.ts`; inspect registered state slices in the matching core feature source.
@@ -0,0 +1,147 @@
1
+ ---
2
+ name: with-tanstack-query
3
+ description: >
4
+ Compose Svelte Query with Svelte Table manual filtering, sorting, and pagination using reactive query inputs, query-result data getters, server counts, and a single source of server-data truth.
5
+ metadata:
6
+ type: composition
7
+ library: '@tanstack/svelte-table'
8
+ framework: svelte
9
+ library_version: '9.0.0-beta.51'
10
+ requires:
11
+ - '@tanstack/table-core#client-vs-server'
12
+ - getting-started
13
+ - table-state
14
+ sources:
15
+ - 'TanStack/table:examples/svelte/with-tanstack-query'
16
+ - 'TanStack/table:docs/framework/svelte/guide/pagination.md'
17
+ ---
18
+
19
+ This skill builds on `@tanstack/table-core#client-vs-server`, `getting-started`, and `table-state`. Decide which row-processing stages the server owns before composing Query.
20
+
21
+ ## Setup
22
+
23
+ ```ts
24
+ import { createQuery, keepPreviousData } from '@tanstack/svelte-query'
25
+ import {
26
+ createTable,
27
+ rowPaginationFeature,
28
+ tableFeatures,
29
+ } from '@tanstack/svelte-table'
30
+
31
+ const features = tableFeatures({ rowPaginationFeature })
32
+ let pagination = $state({ pageIndex: 0, pageSize: 20 })
33
+ const defaultData: Array<{ name: string }> = []
34
+ const dataQuery = createQuery<{
35
+ rows: Array<{ name: string }>
36
+ rowCount: number
37
+ }>(() => ({
38
+ queryKey: ['people', pagination.pageIndex, pagination.pageSize],
39
+ queryFn: () =>
40
+ fetch(
41
+ `/api/people?page=${pagination.pageIndex}&size=${pagination.pageSize}`,
42
+ ).then((r) => r.json()),
43
+ placeholderData: keepPreviousData,
44
+ }))
45
+ const table = createTable({
46
+ features,
47
+ columns,
48
+ get data() {
49
+ return dataQuery.data?.rows ?? defaultData
50
+ },
51
+ get rowCount() {
52
+ return dataQuery.data?.rowCount ?? 0
53
+ },
54
+ manualPagination: true,
55
+ get state() {
56
+ return { pagination }
57
+ },
58
+ onPaginationChange: (next) => {
59
+ pagination = typeof next === 'function' ? next(pagination) : next
60
+ },
61
+ })
62
+ ```
63
+
64
+ ## Core Patterns
65
+
66
+ ### Put every server-owned stage in the query key
67
+
68
+ If sorting or filtering is manual too, control those slices and include their serializable values in `queryKey`. Return data already processed in that same order.
69
+
70
+ ### Keep Query as server-data owner
71
+
72
+ Expose `dataQuery.data` through Table getters. Copy it into `$state` only when the application explicitly owns an editable draft and defines cache synchronization.
73
+
74
+ ## Common Mistakes
75
+
76
+ ### HIGH Building a non-reactive query
77
+
78
+ Wrong:
79
+
80
+ ```ts
81
+ const query = createQuery({
82
+ queryKey: ['people', pagination.pageIndex],
83
+ queryFn,
84
+ })
85
+ ```
86
+
87
+ Correct:
88
+
89
+ ```ts
90
+ const query = createQuery(() => ({
91
+ queryKey: ['people', pagination.pageIndex],
92
+ queryFn,
93
+ }))
94
+ ```
95
+
96
+ The options function lets Svelte Query track the rune read and refetch on page changes.
97
+
98
+ Source: `examples/svelte/with-tanstack-query/src/App.svelte`
99
+
100
+ ### HIGH Expecting manual mode to fetch
101
+
102
+ Wrong:
103
+
104
+ ```ts
105
+ const options = { manualPagination: true }
106
+ ```
107
+
108
+ Correct:
109
+
110
+ ```ts
111
+ const options = {
112
+ manualPagination: true,
113
+ get data() {
114
+ return dataQuery.data?.rows ?? defaultData
115
+ },
116
+ }
117
+ ```
118
+
119
+ Manual mode only bypasses Table pagination; Query or application code performs the request. Hoist `defaultData` instead of creating a new `[]` from a repeatedly evaluated getter.
120
+
121
+ Source: `docs/framework/svelte/guide/pagination.md`
122
+
123
+ ### HIGH Omitting total counts
124
+
125
+ Wrong:
126
+
127
+ ```ts
128
+ const options = { manualPagination: true, data: pageRows }
129
+ ```
130
+
131
+ Correct:
132
+
133
+ ```ts
134
+ const options = {
135
+ manualPagination: true,
136
+ data: pageRows,
137
+ rowCount: response.rowCount,
138
+ }
139
+ ```
140
+
141
+ Table cannot derive navigation limits from one server page; provide `rowCount` or `pageCount`.
142
+
143
+ Source: `docs/framework/svelte/guide/pagination.md`
144
+
145
+ ## API Discovery
146
+
147
+ Inspect `node_modules/@tanstack/svelte-table/src/index.ts` for adapter APIs and installed `@tanstack/svelte-query/src` for the exact Query version. Table manual-stage options live in the matching core feature source.