@tanstack/svelte-table 9.0.0-beta.2 → 9.0.0-beta.21

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.
@@ -34,7 +34,6 @@ export type SvelteTable<TFeatures extends TableFeatures, TData extends RowData,
34
34
  * const table = createTable(
35
35
  * {
36
36
  * features,
37
- * rowModels: {},
38
37
  * columns,
39
38
  * data,
40
39
  * },
@@ -17,7 +17,6 @@ import { svelteReactivity } from './reactivity.svelte';
17
17
  * const table = createTable(
18
18
  * {
19
19
  * features,
20
- * rowModels: {},
21
20
  * columns,
22
21
  * data,
23
22
  * },
@@ -32,7 +31,7 @@ export function createTable(tableOptions, selector) {
32
31
  // 1. Merge reactivity into options using mergeObjects (preserves getters)
33
32
  const mergedOptions = mergeObjects(tableOptions, {
34
33
  features: {
35
- coreReativityFeature: svelteReactivity(),
34
+ coreReactivityFeature: svelteReactivity(),
36
35
  ...tableOptions.features,
37
36
  },
38
37
  });
@@ -213,12 +213,12 @@ export type AppSvelteTable<TFeatures extends TableFeatures, TData extends RowDat
213
213
  * rowPaginationFeature,
214
214
  * rowSortingFeature,
215
215
  * columnFilteringFeature,
216
- * }),
217
- * rowModels: {
218
216
  * paginatedRowModel: createPaginatedRowModel(),
219
- * sortedRowModel: createSortedRowModel(sortFns),
220
- * filteredRowModel: createFilteredRowModel(filterFns),
221
- * },
217
+ * sortedRowModel: createSortedRowModel(),
218
+ * filteredRowModel: createFilteredRowModel(),
219
+ * sortFns,
220
+ * filterFns,
221
+ * }),
222
222
  * tableComponents: { PaginationControls, RowCount },
223
223
  * cellComponents: { TextCell, NumberCell },
224
224
  * headerComponents: { SortIndicator, ColumnFilter },
@@ -228,7 +228,7 @@ export type AppSvelteTable<TFeatures extends TableFeatures, TData extends RowDat
228
228
  export declare function createTableHook<TFeatures extends TableFeatures, const TTableComponents extends Record<string, ComponentType<any>>, const TCellComponents extends Record<string, ComponentType<any>>, const THeaderComponents extends Record<string, ComponentType<any>>>({ tableComponents, cellComponents, headerComponents, ...defaultTableOptions }: CreateTableHookOptions<TFeatures, TTableComponents, TCellComponents, THeaderComponents>): {
229
229
  appFeatures: TFeatures;
230
230
  createAppColumnHelper: <TData extends RowData>() => AppColumnHelper<TFeatures, TData, TCellComponents, THeaderComponents>;
231
- createAppTable: <TData extends RowData, TSelected = TableState<TFeatures>>(tableOptions: Omit<TableOptions<TFeatures, TData>, "features" | "rowModels">, selector?: (state: TableState<TFeatures>) => TSelected) => AppSvelteTable<TFeatures, TData, TSelected, TTableComponents, TCellComponents, THeaderComponents>;
231
+ createAppTable: <TData extends RowData, TSelected = TableState<TFeatures>>(tableOptions: Omit<TableOptions<TFeatures, TData>, "features">, selector?: (state: TableState<TFeatures>) => TSelected) => AppSvelteTable<TFeatures, TData, TSelected, TTableComponents, TCellComponents, THeaderComponents>;
232
232
  useTableContext: <TData extends RowData = RowData>() => SvelteTable<TFeatures, TData>;
233
233
  useCellContext: <TValue extends CellData = unknown>() => Cell<TFeatures, any, TValue>;
234
234
  useHeaderContext: <TValue extends CellData = unknown>() => Header<TFeatures, any, TValue>;
@@ -34,12 +34,12 @@ import FlexRenderSvelte from './FlexRender.svelte';
34
34
  * rowPaginationFeature,
35
35
  * rowSortingFeature,
36
36
  * columnFilteringFeature,
37
- * }),
38
- * rowModels: {
39
37
  * paginatedRowModel: createPaginatedRowModel(),
40
- * sortedRowModel: createSortedRowModel(sortFns),
41
- * filteredRowModel: createFilteredRowModel(filterFns),
42
- * },
38
+ * sortedRowModel: createSortedRowModel(),
39
+ * filteredRowModel: createFilteredRowModel(),
40
+ * sortFns,
41
+ * filterFns,
42
+ * }),
43
43
  * tableComponents: { PaginationControls, RowCount },
44
44
  * cellComponents: { TextCell, NumberCell },
45
45
  * headerComponents: { SortIndicator, ColumnFilter },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/svelte-table",
3
- "version": "9.0.0-beta.2",
3
+ "version": "9.0.0-beta.21",
4
4
  "description": "Headless UI for building powerful tables & datagrids for Svelte.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -53,14 +53,14 @@
53
53
  ],
54
54
  "dependencies": {
55
55
  "@tanstack/svelte-store": "^0.12.0",
56
- "@tanstack/table-core": "9.0.0-beta.1"
56
+ "@tanstack/table-core": "9.0.0-beta.21"
57
57
  },
58
58
  "devDependencies": {
59
59
  "@sveltejs/package": "^2.5.8",
60
60
  "@sveltejs/vite-plugin-svelte": "^7.1.2",
61
61
  "eslint-plugin-svelte": "^3.19.0",
62
- "svelte": "^5.56.1",
63
- "svelte-check": "^4.5.0"
62
+ "svelte": "^5.56.2",
63
+ "svelte-check": "^4.6.0"
64
64
  },
65
65
  "peerDependencies": {
66
66
  "svelte": "^5.0.0"
@@ -3,9 +3,9 @@ name: svelte/client-to-server
3
3
  description: >
4
4
  Convert a client-side Svelte table to server-side (manual) modes. Toggle `manualPagination`,
5
5
  `manualSorting`, `manualFiltering`, `manualGrouping`, `manualExpanding` for whatever the server
6
- owns, drop the matching `rowModels` factories and `features` you no longer need, supply
7
- `rowCount` for the pager, then drive the request from `table.atoms.pagination` /
8
- `table.atoms.sorting` / etc. (or external atoms you own) using rune-aware getters
6
+ owns, drop the matching row-model factory slots from `tableFeatures` and any `features` you no
7
+ longer need, supply `rowCount` for the pager, then drive the request from `table.atoms.pagination`
8
+ / `table.atoms.sorting` / etc. (or external atoms you own) using rune-aware getters
9
9
  (`get data()`, `get rowCount()`) so the table re-syncs in `$effect.pre`. Svelte 5+ only.
10
10
  type: lifecycle
11
11
  library: tanstack-table
@@ -44,8 +44,7 @@ already-paged window is perfectly valid for medium datasets.
44
44
  | `manualGrouping` | Server returns already-grouped rows | Pre-shaped data |
45
45
  | `manualExpanding` | Server resolves sub-rows | Server-provided sub-row tree |
46
46
 
47
- When a stage is manual, you can drop its row-model factory. `manualPagination: true` does not
48
- need `paginatedRowModel: createPaginatedRowModel()`.
47
+ When a stage is manual, you can drop its row-model factory slot from `tableFeatures`. `manualPagination: true` does not need `paginatedRowModel: createPaginatedRowModel()` in the features object.
49
48
 
50
49
  ## Step 1 — Identify what's moving server-side
51
50
 
@@ -111,7 +110,6 @@ const filters = useSelector(filtersAtom)
111
110
  // No row-model factories for these — server owns them.
112
111
  const table = createTable({
113
112
  features,
114
- rowModels: {},
115
113
  columns,
116
114
  get data() {
117
115
  return query.data?.rows ?? []
@@ -196,11 +194,11 @@ const table = createTable({
196
194
  columnFilteringFeature,
197
195
  rowPaginationFeature,
198
196
  rowSortingFeature,
197
+ filteredRowModel: createFilteredRowModel(), // client filters the page
198
+ sortedRowModel: createSortedRowModel(), // client sorts the page
199
+ filterFns,
200
+ sortFns,
199
201
  }),
200
- rowModels: {
201
- filteredRowModel: createFilteredRowModel(filterFns), // client filters the page
202
- sortedRowModel: createSortedRowModel(sortFns), // client sorts the page
203
- },
204
202
  columns,
205
203
  get data() {
206
204
  return query.data?.rows ?? []
@@ -116,6 +116,9 @@ Each cell type is a small Svelte component that knows which row + field it edits
116
116
  const features = tableFeatures({
117
117
  rowPaginationFeature,
118
118
  columnFilteringFeature,
119
+ filteredRowModel: createFilteredRowModel(),
120
+ paginatedRowModel: createPaginatedRowModel(),
121
+ filterFns,
119
122
  })
120
123
 
121
124
  const columnHelper = createColumnHelper<typeof features, Person>()
@@ -170,10 +173,6 @@ Each cell type is a small Svelte component that knows which row + field it edits
170
173
 
171
174
  const table = createTable({
172
175
  features,
173
- rowModels: {
174
- filteredRowModel: createFilteredRowModel(filterFns),
175
- paginatedRowModel: createPaginatedRowModel(),
176
- },
177
176
  columns,
178
177
  get data() {
179
178
  // The form is the source of truth.
@@ -95,7 +95,7 @@ Same shape, calling `table.setGlobalFilter`:
95
95
 
96
96
  ## Throttle column resizing
97
97
 
98
- `columnResizingFeature` writes to `columnSizing` continuously. v9 supports `columnResizeMode:
98
+ `columnResizingFeature` (which requires `columnSizingFeature` to also be registered in `tableFeatures`) writes to `columnSizing` continuously. v9 supports `columnResizeMode:
99
99
  'onChange' | 'onEnd'` — the default is `'onChange'` (commit per-frame). For very heavy tables,
100
100
  either:
101
101
 
@@ -58,7 +58,6 @@ the affected pipeline stages, pipe the result back through reactive getters.
58
58
 
59
59
  const table = createTable({
60
60
  features,
61
- rowModels: {},
62
61
  columns,
63
62
  get data() {
64
63
  return dataQuery.data?.rows ?? []
@@ -115,7 +114,6 @@ const dataQuery = createQuery(() => ({
115
114
 
116
115
  const table = createTable({
117
116
  features,
118
- rowModels: {},
119
117
  columns,
120
118
  get data() {
121
119
  return dataQuery.data?.rows ?? []
@@ -152,7 +150,6 @@ const table = createTable({
152
150
  rowSortingFeature,
153
151
  columnFilteringFeature,
154
152
  }),
155
- rowModels: {},
156
153
  columns,
157
154
  get data() {
158
155
  return dataQuery.data?.rows ?? []
@@ -46,7 +46,7 @@ If a slice is supplied externally via `atoms`, `table.atoms.<slice>` reads from
46
46
 
47
47
  ## The Svelte bindings (what `svelteReactivity()` actually does)
48
48
 
49
- The Svelte adapter ships `svelteReactivity()` and installs it as `coreReativityFeature`. It
49
+ The Svelte adapter ships `svelteReactivity()` and installs it as `coreReactivityFeature`. It
50
50
  maps Store primitives to runes:
51
51
 
52
52
  - Readonly atoms → `$derived.by(fn)`
@@ -83,7 +83,6 @@ The second argument to `createTable` is a TanStack Store selector. The result is
83
83
  const table = createTable(
84
84
  {
85
85
  features,
86
- rowModels: { paginatedRowModel: createPaginatedRowModel() },
87
86
  columns,
88
87
  get data() {
89
88
  return data
@@ -161,9 +160,6 @@ const pagination = useSelector(paginationAtom)
161
160
 
162
161
  const table = createTable({
163
162
  features,
164
- rowModels: {
165
- /* ... */
166
- },
167
163
  columns,
168
164
  get data() {
169
165
  return data
@@ -215,9 +211,6 @@ export const rowSelectionAtom = createAtom<RowSelectionState>({})
215
211
 
216
212
  const table = createTable({
217
213
  features,
218
- rowModels: {
219
- /* ... */
220
- },
221
214
  columns,
222
215
  get data() {
223
216
  return data
@@ -59,13 +59,17 @@ pnpm add @tanstack/svelte-virtual
59
59
  import { createVirtualizer } from '@tanstack/svelte-virtual'
60
60
  import { get } from 'svelte/store'
61
61
 
62
- const features = tableFeatures({ columnSizingFeature, rowSortingFeature })
62
+ const features = tableFeatures({
63
+ columnSizingFeature,
64
+ rowSortingFeature,
65
+ sortedRowModel: createSortedRowModel(),
66
+ sortFns,
67
+ })
63
68
 
64
69
  let data = $state<Person[]>(makeData(200_000))
65
70
 
66
71
  const table = createTable({
67
72
  features,
68
- rowModels: { sortedRowModel: createSortedRowModel(sortFns) },
69
73
  columns,
70
74
  get data() {
71
75
  return data
@@ -218,7 +222,6 @@ const flatData = $derived(
218
222
 
219
223
  const table = createTable({
220
224
  features: tableFeatures({}),
221
- rowModels: {},
222
225
  columns,
223
226
  get data() {
224
227
  return flatData
@@ -2,8 +2,8 @@
2
2
  name: svelte/getting-started
3
3
  description: >
4
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
5
+ declare `features` with `tableFeatures()` (including row-model factories and `*Fns` registries as
6
+ feature slots), build a typed column helper with both `TFeatures` and `TData` generics, instantiate
7
7
  the table with `createTable(options)` using `$state` data and `get data()` reactive option getters,
8
8
  and render with `FlexRender`. Svelte 5+ only — Svelte 3/4 must use v8.
9
9
  type: lifecycle
@@ -51,18 +51,17 @@ pnpm add @tanstack/svelte-store
51
51
  You do **not** install `@tanstack/table-core` separately — the Svelte adapter re-exports
52
52
  everything you need (column helpers, feature objects, row-model factories, types).
53
53
 
54
- ## 2. Define `features` and `rowModels`
54
+ ## 2. Define `features`
55
55
 
56
56
  v9 is explicit. You opt in to every feature and every row model. The core row model is
57
57
  included by default, so the minimum viable table is:
58
58
 
59
59
  ```ts
60
60
  const features = tableFeatures({})
61
- const rowModels = {}
62
61
  ```
63
62
 
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:
63
+ For anything beyond a flat table, register the features you'll use along with the matching
64
+ row-model factories and `*Fns` registries — all as slots inside `tableFeatures`:
66
65
 
67
66
  ```ts
68
67
  import {
@@ -81,13 +80,12 @@ const features = tableFeatures({
81
80
  rowPaginationFeature,
82
81
  rowSortingFeature,
83
82
  columnFilteringFeature,
84
- })
85
-
86
- const rowModels = {
87
83
  paginatedRowModel: createPaginatedRowModel(),
88
- sortedRowModel: createSortedRowModel(sortFns),
89
- filteredRowModel: createFilteredRowModel(filterFns),
90
- }
84
+ sortedRowModel: createSortedRowModel(),
85
+ filteredRowModel: createFilteredRowModel(),
86
+ sortFns,
87
+ filterFns,
88
+ })
91
89
  ```
92
90
 
93
91
  **Skipping a feature** in `features` means its state slice does not exist on `table.atoms`,
@@ -166,7 +164,6 @@ option (`columns`, `rowCount`, `state.*`).
166
164
 
167
165
  const table = createTable({
168
166
  features,
169
- rowModels: {},
170
167
  columns,
171
168
  get data() {
172
169
  return data
@@ -230,13 +227,13 @@ focus, scroll, and any per-row component state.
230
227
  tableFeatures,
231
228
  } from '@tanstack/svelte-table'
232
229
 
233
- const features = tableFeatures({ rowPaginationFeature })
230
+ const features = tableFeatures({
231
+ rowPaginationFeature,
232
+ paginatedRowModel: createPaginatedRowModel(),
233
+ })
234
234
 
235
235
  const table = createTable({
236
236
  features,
237
- rowModels: {
238
- paginatedRowModel: createPaginatedRowModel(),
239
- },
240
237
  columns,
241
238
  get data() {
242
239
  return data
@@ -273,8 +270,7 @@ const pagination = subscribeTable(table.atoms.pagination)
273
270
 
274
271
  ## 7. `createTableHook` (when you have more than one table)
275
272
 
276
- For apps with multiple tables, define the `features`, `rowModels`, and shared components
277
- once:
273
+ For apps with multiple tables, define `features` (including row-model factories) and shared components once:
278
274
 
279
275
  ```ts
280
276
  // hooks/table.ts
@@ -289,11 +285,13 @@ import {
289
285
  } from '@tanstack/svelte-table'
290
286
 
291
287
  export const { createAppTable, createAppColumnHelper } = createTableHook({
292
- features: tableFeatures({ rowPaginationFeature, rowSortingFeature }),
293
- rowModels: {
288
+ features: tableFeatures({
289
+ rowPaginationFeature,
290
+ rowSortingFeature,
294
291
  paginatedRowModel: createPaginatedRowModel(),
295
- sortedRowModel: createSortedRowModel(sortFns),
296
- },
292
+ sortedRowModel: createSortedRowModel(),
293
+ sortFns,
294
+ }),
297
295
  })
298
296
  ```
299
297
 
@@ -319,7 +317,7 @@ export const { createAppTable, createAppColumnHelper } = createTableHook({
319
317
 
320
318
  - **Svelte 3/4.** Adapter will not work. See top of file.
321
319
  - **`createSvelteTable` / `useSvelteTable` / `getCoreRowModel`** — all v8 names. v9 uses
322
- `createTable` and `rowModels: { paginatedRowModel: createPaginatedRowModel(), ... }`.
320
+ `createTable` with row-model factories registered as slots in `tableFeatures({ paginatedRowModel: createPaginatedRowModel(), ... })`.
323
321
  - **Plain `data` instead of `get data()` getter.** Table will not see data updates. Always
324
322
  pass a reactive getter for state that lives in `$state`.
325
323
  - **Missing feature in `features`.** `table.setSorting` / `column.getCanSort` won't exist.
@@ -3,10 +3,11 @@ name: svelte/migrate-v8-to-v9
3
3
  description: >
4
4
  Mechanical migration from `@tanstack/svelte-table@8` to `@tanstack/svelte-table@9`. v9 in Svelte
5
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.
6
+ `createSvelteTable` → `createTable`, `getCoreRowModel` / `getSortedRowModel` factories →
7
+ row-model factories registered as slots inside `tableFeatures({...})`, `flexRender` helper →
8
+ `<FlexRender>` component, writable-store `state` → rune-based getters / external atoms,
9
+ `onStateChange` → per-slice `on[State]Change` or `atoms`. Plan a feature-by-feature audit, not a
10
+ search-and-replace.
10
11
  type: lifecycle
11
12
  library: tanstack-table
12
13
  framework: svelte
@@ -46,11 +47,11 @@ There is no third option. Trying to install v9 on a Svelte 4 codebase will error
46
47
  | -------------------------------------------------- | ------------------------------------------------------------------------------------- |
47
48
  | `createSvelteTable(options)` | `createTable(options, selector?)` |
48
49
  | `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)` |
50
+ | `getPaginationRowModel()` | `tableFeatures({ paginatedRowModel: createPaginatedRowModel() })` |
51
+ | `getSortedRowModel()` | `tableFeatures({ sortedRowModel: createSortedRowModel(), sortFns })` |
52
+ | `getFilteredRowModel()` | `tableFeatures({ filteredRowModel: createFilteredRowModel(), filterFns })` |
53
+ | `getExpandedRowModel()` | `tableFeatures({ expandedRowModel: createExpandedRowModel() })` |
54
+ | `getGroupedRowModel()` | `tableFeatures({ groupedRowModel: createGroupedRowModel(), aggregationFns })` |
54
55
  | `getFacetedRowModel()` / `MinMax` / `UniqueValues` | facet APIs auto-derived when `*Facet*Feature` registered |
55
56
  | `flexRender(template, ctx)` helper | `<FlexRender header={h} />` / `<FlexRender cell={c} />` / `<FlexRender footer={h} />` |
56
57
  | `ColumnDef<TData>` | `ColumnDef<TFeatures, TData>` (extra generic) |
@@ -79,8 +80,7 @@ For each Svelte component that uses the table:
79
80
  `import { createTable, FlexRender, tableFeatures, ... }`.
80
81
  4. **Add `features`.** Create `const features = tableFeatures({ ... only the features this
81
82
  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.
83
+ 5. **Move row-model factories into `tableFeatures`.** Every `get*RowModel: get*RowModel()` becomes a slot inside `tableFeatures({ ..., create*RowModel() })`. Any `*Fns` registry that was passed as a factory argument is now also a named slot in the same `tableFeatures` call.
84
84
  6. **Generic columns.** Add `<typeof features, TData>` to `ColumnDef<>` and
85
85
  `createColumnHelper<>()`. TypeScript will tell you when you missed one.
86
86
  7. **`data` as a getter.** `data: data` → `get data() { return data }`. Same for any other
@@ -99,7 +99,7 @@ table uses ... })`.
99
99
  <script lang="ts">
100
100
  // v8
101
101
  import { writable } from 'svelte/store'
102
- const options = writable({ ... })
102
+ const options = writable({ data, columns })
103
103
  $: $options.state = $state
104
104
  </script>
105
105
  ```
@@ -111,7 +111,6 @@ table uses ... })`.
111
111
  ```ts
112
112
  const table = createTable({
113
113
  features,
114
- rowModels: { paginatedRowModel: createPaginatedRowModel() },
115
114
  columns,
116
115
  get data() {
117
116
  return data
@@ -131,12 +130,17 @@ const table = createTable({
131
130
 
132
131
  const table = createTable({
133
132
  features,
134
- rowModels: { ... },
135
133
  columns,
136
- get data() { return data },
134
+ get data() {
135
+ return data
136
+ },
137
137
  state: {
138
- get sorting() { return sorting },
139
- get pagination() { return pagination },
138
+ get sorting() {
139
+ return sorting
140
+ },
141
+ get pagination() {
142
+ return pagination
143
+ },
140
144
  },
141
145
  onSortingChange: (updater) => {
142
146
  sorting = updater instanceof Function ? updater(sorting) : updater
@@ -154,16 +158,20 @@ const table = createTable({
154
158
  import { createAtom, useSelector } from '@tanstack/svelte-store'
155
159
 
156
160
  const sortingAtom = createAtom<SortingState>([])
157
- const paginationAtom = createAtom<PaginationState>({ pageIndex: 0, pageSize: 10 })
161
+ const paginationAtom = createAtom<PaginationState>({
162
+ pageIndex: 0,
163
+ pageSize: 10,
164
+ })
158
165
 
159
166
  const sorting = useSelector(sortingAtom)
160
167
  const pagination = useSelector(paginationAtom)
161
168
 
162
169
  const table = createTable({
163
170
  features,
164
- rowModels: { ... },
165
171
  columns,
166
- get data() { return data },
172
+ get data() {
173
+ return data
174
+ },
167
175
  atoms: {
168
176
  sorting: sortingAtom,
169
177
  pagination: paginationAtom,
@@ -221,8 +229,8 @@ import { renderSnippet } from '@tanstack/svelte-table'
221
229
  ## After the rewrite — verify
222
230
 
223
231
  - `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.
232
+ missing `features` or row-model factory slots, and feature APIs called on tables that didn't
233
+ register them.
226
234
  - `pnpm build` should pass with the new `features` set. Bundle should shrink — only the
227
235
  features you register are included.
228
236
  - Click through every table screen. Reset buttons, multi-sort, pagination reset on filter,
@@ -241,9 +249,9 @@ import { renderSnippet } from '@tanstack/svelte-table'
241
249
  changed" bugs during migration.
242
250
  - **Plain `features: { rowPaginationFeature }` instead of `tableFeatures({...})`.** Loses
243
251
  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.
252
+ - **Forgetting feature registration after adding the row-model factory slot.** Adding
253
+ `paginatedRowModel: createPaginatedRowModel()` to `tableFeatures` without also including
254
+ `rowPaginationFeature` does nothing.
247
255
  - **Reimplementing v8 helpers** (`flexRender`-style functions, manual store subscriptions,
248
256
  hand-rolled selectors) instead of using `FlexRender` / `subscribeTable` / atom selectors.
249
257
  That's the #1 AI tell on this migration.
@@ -69,8 +69,9 @@ If you find yourself running a table without a feature's UI ever showing, drop t
69
69
  `createTable` syncs options in `$effect.pre`. If any of these identities flip every component
70
70
  run, the table re-syncs more than it needs to.
71
71
 
72
- - **`features` and `rowModels`**: declare at module scope, not inside the component
73
- function, and never inside `$derived` / `$effect`.
72
+ - **`features`**: declare at module scope, not inside the component function, and never
73
+ inside `$derived` / `$effect`. The `features` object now also carries row-model factories
74
+ and `*Fns` registries, so keeping it stable prevents unnecessary re-sync.
74
75
  - **`columns`**: same — module scope or `$state.frozen` / a non-reactive `const` in the
75
76
  component. Reactive recompute of columns is rare and almost always a bug.
76
77
  - **`data`**: pass with a getter (`get data()`) so the reference is stable when the data
@@ -80,8 +81,10 @@ run, the table re-syncs more than it needs to.
80
81
  ```svelte
81
82
  <script lang="ts">
82
83
  // module scope is fine in .svelte too, when truly static
83
- const features = tableFeatures({ rowPaginationFeature })
84
- const rowModels = { paginatedRowModel: createPaginatedRowModel() }
84
+ const features = tableFeatures({
85
+ rowPaginationFeature,
86
+ paginatedRowModel: createPaginatedRowModel(),
87
+ })
85
88
  const columns = columnHelper.columns([
86
89
  /* ... */
87
90
  ])
@@ -91,7 +94,6 @@ run, the table re-syncs more than it needs to.
91
94
 
92
95
  const table = createTable({
93
96
  features,
94
- rowModels,
95
97
  columns,
96
98
  get data() {
97
99
  return data
@@ -48,7 +48,7 @@ A table instance has three (and a half) state surfaces:
48
48
  - `table.state` — the value returned by the optional selector passed as the second argument to
49
49
  `createTable`. **Svelte-only surface.**
50
50
 
51
- The Svelte adapter installs `svelteReactivity()` as the `coreReativityFeature`:
51
+ The Svelte adapter installs `svelteReactivity()` as the `coreReactivityFeature`:
52
52
 
53
53
  | Core concept | Svelte binding |
54
54
  | ------------- | --------------- |
@@ -81,14 +81,13 @@ import {
81
81
  const features = tableFeatures({
82
82
  rowPaginationFeature,
83
83
  rowSortingFeature,
84
+ paginatedRowModel: createPaginatedRowModel(),
85
+ sortedRowModel: createSortedRowModel(),
86
+ sortFns,
84
87
  })
85
88
 
86
89
  const table = createTable({
87
90
  features,
88
- rowModels: {
89
- paginatedRowModel: createPaginatedRowModel(),
90
- sortedRowModel: createSortedRowModel(sortFns),
91
- },
92
91
  columns,
93
92
  get data() {
94
93
  return data
@@ -122,7 +121,6 @@ exposed as `table.state`. The default selector returns the full registered state
122
121
  const table = createTable(
123
122
  {
124
123
  features,
125
- rowModels: { paginatedRowModel: createPaginatedRowModel() },
126
124
  columns,
127
125
  get data() {
128
126
  return data
@@ -186,7 +184,6 @@ The default: set starting values, let the table own the rest. `initialState` als
186
184
  ```ts
187
185
  const table = createTable({
188
186
  features,
189
- rowModels: {},
190
187
  columns,
191
188
  get data() {
192
189
  return data
@@ -231,7 +228,6 @@ const pagination = useSelector(paginationAtom)
231
228
 
232
229
  const table = createTable({
233
230
  features,
234
- rowModels: {},
235
231
  columns,
236
232
  get data() {
237
233
  return data
@@ -266,7 +262,6 @@ updates.
266
262
 
267
263
  const table = createTable({
268
264
  features,
269
- rowModels: {},
270
265
  columns,
271
266
  get data() {
272
267
  return data
@@ -340,8 +335,7 @@ Always key `{#each}` blocks on stable ids (`headerGroup.id`, `header.id`, `row.i
340
335
 
341
336
  ## `createTableHook` — app-wide composition
342
337
 
343
- Create one configured hook per app: shared `features`, `rowModels`, defaults, and pre-bound
344
- component registries.
338
+ Create one configured hook per app: shared `features` (including row-model factories), defaults, and pre-bound component registries.
345
339
 
346
340
  ```ts
347
341
  import {
@@ -363,11 +357,13 @@ export const {
363
357
  useCellContext,
364
358
  useHeaderContext,
365
359
  } = createTableHook({
366
- features: tableFeatures({ rowPaginationFeature, rowSortingFeature }),
367
- rowModels: {
360
+ features: tableFeatures({
361
+ rowPaginationFeature,
362
+ rowSortingFeature,
368
363
  paginatedRowModel: createPaginatedRowModel(),
369
- sortedRowModel: createSortedRowModel(sortFns),
370
- },
364
+ sortedRowModel: createSortedRowModel(),
365
+ sortFns,
366
+ }),
371
367
  cellComponents: { TextCell },
372
368
  headerComponents: { SortIndicator },
373
369
  })
@@ -51,7 +51,6 @@ export type SvelteTable<
51
51
  * const table = createTable(
52
52
  * {
53
53
  * features,
54
- * rowModels: {},
55
54
  * columns,
56
55
  * data,
57
56
  * },
@@ -73,7 +72,7 @@ export function createTable<
73
72
  // 1. Merge reactivity into options using mergeObjects (preserves getters)
74
73
  const mergedOptions = mergeObjects(tableOptions, {
75
74
  features: {
76
- coreReativityFeature: svelteReactivity(),
75
+ coreReactivityFeature: svelteReactivity(),
77
76
  ...tableOptions.features,
78
77
  },
79
78
  }) as TableOptions<TFeatures, TData>
@@ -404,12 +404,12 @@ export type AppSvelteTable<
404
404
  * rowPaginationFeature,
405
405
  * rowSortingFeature,
406
406
  * columnFilteringFeature,
407
- * }),
408
- * rowModels: {
409
407
  * paginatedRowModel: createPaginatedRowModel(),
410
- * sortedRowModel: createSortedRowModel(sortFns),
411
- * filteredRowModel: createFilteredRowModel(filterFns),
412
- * },
408
+ * sortedRowModel: createSortedRowModel(),
409
+ * filteredRowModel: createFilteredRowModel(),
410
+ * sortFns,
411
+ * filterFns,
412
+ * }),
413
413
  * tableComponents: { PaginationControls, RowCount },
414
414
  * cellComponents: { TextCell, NumberCell },
415
415
  * headerComponents: { SortIndicator, ColumnFilter },
@@ -527,10 +527,7 @@ export function createTableHook<
527
527
  TData extends RowData,
528
528
  TSelected = TableState<TFeatures>,
529
529
  >(
530
- tableOptions: Omit<
531
- TableOptions<TFeatures, TData>,
532
- 'features' | 'rowModels'
533
- >,
530
+ tableOptions: Omit<TableOptions<TFeatures, TData>, 'features'>,
534
531
  selector?: (state: TableState<TFeatures>) => TSelected,
535
532
  ): AppSvelteTable<
536
533
  TFeatures,