@tanstack/svelte-table 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.
@@ -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.42'
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.42'
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.
@@ -0,0 +1,150 @@
1
+ ---
2
+ name: with-tanstack-virtual
3
+ description: >
4
+ Virtualize Svelte Table final row or column models with reactive counts and scroll targets, stable keys, dynamic measurement, absolute transforms, sticky regions, grid/flex sizing, and infinite data.
5
+ metadata:
6
+ type: composition
7
+ library: '@tanstack/svelte-table'
8
+ framework: svelte
9
+ library_version: '9.0.0-beta.42'
10
+ requires:
11
+ - '@tanstack/table-core#core'
12
+ - getting-started
13
+ - table-state
14
+ sources:
15
+ - 'TanStack/table:docs/framework/svelte/guide/virtualization.md'
16
+ - 'TanStack/table:examples/svelte/virtualized-rows'
17
+ - 'TanStack/table:examples/svelte/virtualized-columns'
18
+ - 'TanStack/table:examples/svelte/virtualized-infinite-scrolling'
19
+ ---
20
+
21
+ This skill builds on `@tanstack/table-core#core`, `getting-started`, and `table-state`. Virtual is a rendering layer over Table’s final model, never a `tableFeatures` plugin.
22
+
23
+ ## Setup
24
+
25
+ ```svelte
26
+ <script lang="ts">
27
+ import { get } from 'svelte/store'
28
+ import { createVirtualizer } from '@tanstack/svelte-virtual'
29
+
30
+ let scrollElement = $state<HTMLDivElement>()
31
+ const rows = $derived(table.getRowModel().rows)
32
+ const rowVirtualizer = createVirtualizer({
33
+ count: rows.length,
34
+ getScrollElement: () => scrollElement ?? null,
35
+ estimateSize: () => 34,
36
+ getItemKey: (index) => rows[index]!.id,
37
+ overscan: 5,
38
+ })
39
+
40
+ // The store adapter does not track getter options. Push reactive inputs.
41
+ $effect(() => {
42
+ get(rowVirtualizer).setOptions({
43
+ count: rows.length,
44
+ getScrollElement: () => scrollElement ?? null,
45
+ })
46
+ })
47
+ </script>
48
+
49
+ <div
50
+ bind:this={scrollElement}
51
+ style="height: 500px; overflow: auto; position: relative"
52
+ >
53
+ <div style:height={`${$rowVirtualizer.getTotalSize()}px`}>
54
+ {#each $rowVirtualizer.getVirtualItems() as item (item.key)}
55
+ <div style={`position:absolute;transform:translateY(${item.start}px)`}>
56
+ {rows[item.index].id}
57
+ </div>
58
+ {/each}
59
+ </div>
60
+ </div>
61
+ ```
62
+
63
+ ## Core Patterns
64
+
65
+ ### Virtualize visible models
66
+
67
+ Use `table.getRowModel().rows` for rows and `table.getVisibleLeafColumns()` for columns. Recompute counts when filtering, sorting, expansion, or visibility changes.
68
+
69
+ ### Make CSS geometry agree with measurement
70
+
71
+ Use one scroll container, a total-size spacer, positioned items, and either fixed estimates or `measureElement`. For semantic tables with dynamic rows, follow the maintained grid/flex examples rather than assuming native table layout will honor transforms.
72
+
73
+ ### Fetch before the virtual end
74
+
75
+ In infinite scrolling, compare the last virtual item with fetched row count, then request the next Query page only when more server rows exist and no fetch is active.
76
+
77
+ ## Common Mistakes
78
+
79
+ ### HIGH Virtualizing raw data
80
+
81
+ Wrong:
82
+
83
+ ```ts
84
+ const rows = data
85
+ ```
86
+
87
+ Correct:
88
+
89
+ ```ts
90
+ const rows = $derived(table.getRowModel().rows)
91
+ ```
92
+
93
+ Raw data ignores Table filtering, sorting, grouping, expansion, and pagination decisions.
94
+
95
+ Source: `examples/svelte/virtualized-rows/src/App.svelte`
96
+
97
+ ### HIGH Expecting getter options to stay reactive
98
+
99
+ Wrong:
100
+
101
+ ```ts
102
+ const virtualizer = createVirtualizer({
103
+ get count() {
104
+ return rows.length
105
+ },
106
+ getScrollElement,
107
+ })
108
+ ```
109
+
110
+ Correct:
111
+
112
+ ```ts
113
+ const virtualizer = createVirtualizer({ count: rows.length, getScrollElement })
114
+ $effect(() => {
115
+ get(virtualizer).setOptions({
116
+ count: rows.length,
117
+ getScrollElement,
118
+ })
119
+ })
120
+ ```
121
+
122
+ `createVirtualizer` returns a Svelte store, and its adapter does not track getter options. Push rune-derived counts and the bound scroll element with `$effect` and `get(store).setOptions(...)`.
123
+
124
+ Source: `examples/svelte/virtualized-rows/src/App.svelte`
125
+
126
+ ### HIGH Omitting the geometry contract
127
+
128
+ Wrong:
129
+
130
+ ```svelte
131
+ {#each rowVirtualizer.getVirtualItems() as item}<div>
132
+ {rows[item.index].id}
133
+ </div>{/each}
134
+ ```
135
+
136
+ Correct:
137
+
138
+ ```svelte
139
+ <div style:height={`${$rowVirtualizer.getTotalSize()}px`}>
140
+ <div style="position:absolute"></div>
141
+ </div>
142
+ ```
143
+
144
+ Virtual supplies ranges and measurements, not spacer height, transforms, sticky regions, or column widths. In markup, call virtualizer methods through the store auto-subscription (`$rowVirtualizer`); use `get(rowVirtualizer)` in script code.
145
+
146
+ Source: `docs/framework/svelte/guide/virtualization.md`
147
+
148
+ ## API Discovery
149
+
150
+ Inspect installed `@tanstack/svelte-table/src` for Table APIs and `@tanstack/svelte-virtual/src` for the exact virtualizer options. Use the maintained Svelte examples for layout combinations.