@tanstack/vue-table 9.0.0-beta.3 → 9.0.0-beta.30
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.
- package/README.md +1 -0
- package/dist/FlexRender.cjs.map +1 -1
- package/dist/FlexRender.d.cts +30 -12
- package/dist/FlexRender.d.ts +30 -12
- package/dist/FlexRender.js.map +1 -1
- package/dist/createTableHook.cjs +23 -64
- package/dist/createTableHook.cjs.map +1 -1
- package/dist/createTableHook.d.cts +52 -28
- package/dist/createTableHook.d.ts +52 -28
- package/dist/createTableHook.js +23 -64
- package/dist/createTableHook.js.map +1 -1
- package/dist/flex-render.d.cts +2 -2
- package/dist/flex-render.d.ts +2 -2
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/reactivity.cjs +10 -19
- package/dist/reactivity.cjs.map +1 -1
- package/dist/reactivity.js +10 -19
- package/dist/reactivity.js.map +1 -1
- package/dist/useTable.cjs +12 -20
- package/dist/useTable.cjs.map +1 -1
- package/dist/useTable.d.cts +11 -51
- package/dist/useTable.d.ts +11 -51
- package/dist/useTable.js +13 -21
- package/dist/useTable.js.map +1 -1
- package/package.json +4 -4
- package/skills/vue/client-to-server/SKILL.md +21 -26
- package/skills/vue/compose-with-tanstack-form/SKILL.md +4 -4
- package/skills/vue/compose-with-tanstack-pacer/SKILL.md +6 -3
- package/skills/vue/compose-with-tanstack-query/SKILL.md +18 -20
- package/skills/vue/compose-with-tanstack-store/SKILL.md +7 -6
- package/skills/vue/compose-with-tanstack-virtual/SKILL.md +8 -4
- package/skills/vue/getting-started/SKILL.md +55 -49
- package/skills/vue/migrate-v8-to-v9/SKILL.md +50 -32
- package/skills/vue/production-readiness/SKILL.md +28 -21
- package/skills/vue/table-state/SKILL.md +22 -26
- package/src/FlexRender.ts +28 -13
- package/src/createTableHook.ts +126 -90
- package/src/reactivity.ts +17 -43
- package/src/useTable.ts +23 -101
package/dist/useTable.cjs
CHANGED
|
@@ -2,7 +2,6 @@ const require_merge_proxy = require('./merge-proxy.cjs');
|
|
|
2
2
|
const require_reactivity = require('./reactivity.cjs');
|
|
3
3
|
let vue = require("vue");
|
|
4
4
|
let _tanstack_table_core = require("@tanstack/table-core");
|
|
5
|
-
let _tanstack_vue_store = require("@tanstack/vue-store");
|
|
6
5
|
|
|
7
6
|
//#region src/useTable.ts
|
|
8
7
|
function getOptionsWithReactiveValues(options) {
|
|
@@ -18,36 +17,37 @@ function getReactiveOptionDeps(options) {
|
|
|
18
17
|
*
|
|
19
18
|
* Table options may contain Vue refs or computed values. The adapter unwraps
|
|
20
19
|
* those reactive inputs, watches them with synchronous flushing, and keeps the
|
|
21
|
-
* table options in sync.
|
|
22
|
-
*
|
|
20
|
+
* table options in sync. Use `table.Subscribe` or native Vue computed values
|
|
21
|
+
* around `table.atoms.<slice>.get()` for selected reactive reads.
|
|
23
22
|
*
|
|
24
23
|
* @example
|
|
25
24
|
* ```ts
|
|
26
25
|
* const table = useTable(
|
|
27
26
|
* {
|
|
28
27
|
* features,
|
|
29
|
-
* rowModels: {},
|
|
30
28
|
* columns,
|
|
31
29
|
* data,
|
|
32
30
|
* },
|
|
33
|
-
* (state) => ({ pagination: state.pagination }),
|
|
34
31
|
* )
|
|
35
|
-
*
|
|
36
|
-
* table.state.pagination
|
|
37
32
|
* ```
|
|
38
33
|
*/
|
|
39
|
-
function useTable(tableOptions
|
|
34
|
+
function useTable(tableOptions) {
|
|
40
35
|
const syncTableOptions = (table, options) => {
|
|
41
36
|
table.setOptions((prev) => require_merge_proxy.flatMerge(prev, getOptionsWithReactiveValues(options)));
|
|
42
37
|
};
|
|
38
|
+
const reactivity = require_reactivity.vueReactivity();
|
|
43
39
|
const mergedOptions = require_merge_proxy.mergeProxy(tableOptions, { features: {
|
|
44
|
-
|
|
40
|
+
coreReactivityFeature: reactivity,
|
|
45
41
|
...(0, vue.unref)(tableOptions.features) ?? {}
|
|
46
42
|
} });
|
|
47
43
|
const coreTable = (0, _tanstack_table_core.constructTable)(require_merge_proxy.mergeProxy(getOptionsWithReactiveValues(mergedOptions), { mergeOptions: (defaultOptions, newOptions) => {
|
|
48
44
|
return require_merge_proxy.flatMerge(defaultOptions, newOptions);
|
|
49
45
|
} }));
|
|
50
46
|
const table = coreTable;
|
|
47
|
+
if ((0, vue.getCurrentScope)()) (0, vue.onScopeDispose)(() => {
|
|
48
|
+
var _reactivity$unmount;
|
|
49
|
+
return (_reactivity$unmount = reactivity.unmount) === null || _reactivity$unmount === void 0 ? void 0 : _reactivity$unmount.call(reactivity);
|
|
50
|
+
});
|
|
51
51
|
(0, vue.watch)(() => getReactiveOptionDeps(mergedOptions), () => {
|
|
52
52
|
syncTableOptions(coreTable, mergedOptions);
|
|
53
53
|
}, { immediate: true });
|
|
@@ -64,18 +64,10 @@ function useTable(tableOptions, selector) {
|
|
|
64
64
|
}, (controlledValues) => {
|
|
65
65
|
if (controlledValues.length > 0) syncTableOptions(coreTable, mergedOptions);
|
|
66
66
|
}, { immediate: true });
|
|
67
|
-
table.Subscribe = (
|
|
68
|
-
|
|
69
|
-
if (typeof props.children === "function") return props.children(selected.value);
|
|
70
|
-
return props.children;
|
|
71
|
-
});
|
|
72
|
-
const stateStore = (0, _tanstack_vue_store.useSelector)(table.store, selector);
|
|
73
|
-
return {
|
|
74
|
-
...table,
|
|
75
|
-
get state() {
|
|
76
|
-
return stateStore.value;
|
|
77
|
-
}
|
|
67
|
+
table.Subscribe = (props) => {
|
|
68
|
+
return props.children(table.atoms);
|
|
78
69
|
};
|
|
70
|
+
return table;
|
|
79
71
|
}
|
|
80
72
|
|
|
81
73
|
//#endregion
|
package/dist/useTable.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTable.cjs","names":["mergeProxy","flatMerge","vueReactivity"
|
|
1
|
+
{"version":3,"file":"useTable.cjs","names":["mergeProxy","flatMerge","vueReactivity"],"sources":["../src/useTable.ts"],"sourcesContent":["import { getCurrentScope, onScopeDispose, unref, watch } from 'vue'\nimport { constructTable } from '@tanstack/table-core'\nimport { flatMerge, mergeProxy } from './merge-proxy'\nimport { vueReactivity } from './reactivity'\nimport type {\n RowData,\n Table,\n TableFeatures,\n TableOptions,\n} from '@tanstack/table-core'\nimport type { MaybeRef, VNode } from 'vue'\n\nexport type TableOptionsWithReactiveData<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = {\n [K in keyof TableOptions<TFeatures, TData>]: K extends 'data'\n ? MaybeRef<ReadonlyArray<TData>>\n : MaybeRef<TableOptions<TFeatures, TData>[K]>\n}\n\nfunction getOptionsWithReactiveValues<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(options: TableOptionsWithReactiveData<TFeatures, TData>) {\n const resolvedOptions: Record<string, unknown> = {}\n\n for (const key of Object.keys(options)) {\n resolvedOptions[key] = unref(\n options[key as keyof TableOptionsWithReactiveData<TFeatures, TData>],\n )\n }\n\n return mergeProxy(options, resolvedOptions)\n}\n\nfunction getReactiveOptionDeps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(options: TableOptionsWithReactiveData<TFeatures, TData>) {\n return Object.keys(options).map((key) =>\n unref(options[key as keyof TableOptionsWithReactiveData<TFeatures, TData>]),\n )\n}\n\nexport type VueTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = Table<TFeatures, TData> & {\n /** Creates a reactive render boundary. The child function reads the table\n * atoms it needs, so Vue only tracks those atom reads.\n */\n Subscribe: (props: {\n children: (atoms: Table<TFeatures, TData>['atoms']) => VNode | Array<VNode>\n }) => VNode | Array<VNode>\n}\n\n/**\n * Creates a Vue table instance backed by Vue-aware TanStack Store atoms.\n *\n * Table options may contain Vue refs or computed values. The adapter unwraps\n * those reactive inputs, watches them with synchronous flushing, and keeps the\n * table options in sync. Use `table.Subscribe` or native Vue computed values\n * around `table.atoms.<slice>.get()` for selected reactive reads.\n *\n * @example\n * ```ts\n * const table = useTable(\n * {\n * features,\n * columns,\n * data,\n * },\n * )\n * ```\n */\nexport function useTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n tableOptions:\n | TableOptions<TFeatures, TData>\n | TableOptionsWithReactiveData<TFeatures, TData>,\n): VueTable<TFeatures, TData> {\n const syncTableOptions = (\n table: Table<TFeatures, TData>,\n options: TableOptionsWithReactiveData<TFeatures, TData>,\n ) => {\n table.setOptions((prev) =>\n flatMerge(prev, getOptionsWithReactiveValues(options)),\n )\n }\n\n const reactivity = vueReactivity()\n\n const mergedOptions = mergeProxy(tableOptions, {\n features: {\n coreReactivityFeature: reactivity,\n ...(unref(tableOptions.features) ?? {}),\n },\n }) as TableOptionsWithReactiveData<TFeatures, TData>\n\n const resolvedOptions = mergeProxy(\n getOptionsWithReactiveValues(mergedOptions),\n {\n // Remove state and onStateChange - store handles it internally\n mergeOptions: (\n defaultOptions: TableOptions<TFeatures, TData>,\n newOptions: Partial<TableOptions<TFeatures, TData>>,\n ) => {\n return flatMerge(defaultOptions, newOptions)\n },\n },\n ) as TableOptions<TFeatures, TData>\n\n const coreTable = constructTable(resolvedOptions)\n const table = coreTable as unknown as VueTable<TFeatures, TData>\n\n if (getCurrentScope()) {\n onScopeDispose(() => reactivity.unmount?.())\n }\n\n watch(\n () => getReactiveOptionDeps(mergedOptions),\n () => {\n syncTableOptions(coreTable, mergedOptions)\n },\n { immediate: true },\n )\n\n watch(\n () => {\n const controlledState = unref(tableOptions.state) as\n | Record<string, unknown>\n | undefined\n const controlledAtoms = unref(tableOptions.atoms) as\n | Record<string, unknown>\n | undefined\n\n if (!controlledState) {\n return []\n }\n\n const controlledValues: Array<unknown> = []\n\n for (const key of Object.keys(table.initialState)) {\n if (!(key in controlledState) || controlledAtoms?.[key] !== undefined) {\n continue\n }\n\n // Reading only controlled state slices here lets Vue subscribe to\n // getters/computed values that are passed through `options.state`.\n controlledValues.push(controlledState[key])\n }\n\n return controlledValues\n },\n (controlledValues) => {\n if (controlledValues.length > 0) {\n syncTableOptions(coreTable, mergedOptions)\n }\n },\n { immediate: true },\n )\n\n table.Subscribe = (props: {\n children: (atoms: Table<TFeatures, TData>['atoms']) => VNode | Array<VNode>\n }) => {\n return props.children(table.atoms as Table<TFeatures, TData>['atoms'])\n }\n\n return table\n}\n"],"mappings":";;;;;;AAqBA,SAAS,6BAGP,SAAyD;CACzD,MAAM,kBAA2C,CAAC;CAElD,KAAK,MAAM,OAAO,OAAO,KAAK,OAAO,GACnC,gBAAgB,sBACd,QAAQ,IACV;CAGF,OAAOA,+BAAW,SAAS,eAAe;AAC5C;AAEA,SAAS,sBAGP,SAAyD;CACzD,OAAO,OAAO,KAAK,OAAO,CAAC,CAAC,KAAK,uBACzB,QAAQ,IAA4D,CAC5E;AACF;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,SAId,cAG4B;CAC5B,MAAM,oBACJ,OACA,YACG;EACH,MAAM,YAAY,SAChBC,8BAAU,MAAM,6BAA6B,OAAO,CAAC,CACvD;CACF;CAEA,MAAM,aAAaC,iCAAc;CAEjC,MAAM,gBAAgBF,+BAAW,cAAc,EAC7C,UAAU;EACR,uBAAuB;EACvB,kBAAU,aAAa,QAAQ,KAAK,CAAC;CACvC,EACF,CAAC;CAeD,MAAM,qDAbkBA,+BACtB,6BAA6B,aAAa,GAC1C,EAEE,eACE,gBACA,eACG;EACH,OAAOC,8BAAU,gBAAgB,UAAU;CAC7C,EACF,CAG6C,CAAC;CAChD,MAAM,QAAQ;CAEd,6BAAoB,GAClB,8BAAqB;;2CAAW,kGAAU;EAAC;CAG7C,qBACQ,sBAAsB,aAAa,SACnC;EACJ,iBAAiB,WAAW,aAAa;CAC3C,GACA,EAAE,WAAW,KAAK,CACpB;CAEA,qBACQ;EACJ,MAAM,iCAAwB,aAAa,KAAK;EAGhD,MAAM,iCAAwB,aAAa,KAAK;EAIhD,IAAI,CAAC,iBACH,OAAO,CAAC;EAGV,MAAM,mBAAmC,CAAC;EAE1C,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM,YAAY,GAAG;GACjD,IAAI,EAAE,OAAO,uFAAoB,gBAAkB,UAAS,QAC1D;GAKF,iBAAiB,KAAK,gBAAgB,IAAI;EAC5C;EAEA,OAAO;CACT,IACC,qBAAqB;EACpB,IAAI,iBAAiB,SAAS,GAC5B,iBAAiB,WAAW,aAAa;CAE7C,GACA,EAAE,WAAW,KAAK,CACpB;CAEA,MAAM,aAAa,UAEb;EACJ,OAAO,MAAM,SAAS,MAAM,KAAyC;CACvE;CAEA,OAAO;AACT"}
|
package/dist/useTable.d.cts
CHANGED
|
@@ -1,76 +1,36 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Atom, ReadonlyAtom, ReadonlyStore, Store } from "@tanstack/vue-store";
|
|
1
|
+
import { RowData, Table, TableFeatures, TableOptions } from "@tanstack/table-core";
|
|
3
2
|
import { MaybeRef, VNode } from "vue";
|
|
4
3
|
|
|
5
4
|
//#region src/useTable.d.ts
|
|
6
|
-
type SubscribeSource<TValue> = Atom<TValue> | ReadonlyAtom<TValue> | Store<TValue> | ReadonlyStore<TValue>;
|
|
7
5
|
type TableOptionsWithReactiveData<TFeatures extends TableFeatures, TData extends RowData> = { [K in keyof TableOptions<TFeatures, TData>]: K extends 'data' ? MaybeRef<ReadonlyArray<TData>> : MaybeRef<TableOptions<TFeatures, TData>[K]> };
|
|
8
|
-
type VueTable<TFeatures extends TableFeatures, TData extends RowData
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
* `table.atoms.<slice>.get()` for slice snapshots, or
|
|
12
|
-
* `table.Subscribe` / `useSelector(table.store, selector)` for explicit
|
|
13
|
-
* subscriptions. `table.store.state` is a current-value snapshot and is easy
|
|
14
|
-
* to misuse in render code.
|
|
6
|
+
type VueTable<TFeatures extends TableFeatures, TData extends RowData> = Table<TFeatures, TData> & {
|
|
7
|
+
/** Creates a reactive render boundary. The child function reads the table
|
|
8
|
+
* atoms it needs, so Vue only tracks those atom reads.
|
|
15
9
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* `selector` for the whole value (identity), or pass `selector` to project. Split
|
|
20
|
-
* overloads so source-only infers `TSourceValue` for `children` (see React `Subscribe`).
|
|
21
|
-
*/
|
|
22
|
-
Subscribe: {
|
|
23
|
-
<TSourceValue>(props: {
|
|
24
|
-
source: SubscribeSource<TSourceValue>;
|
|
25
|
-
selector?: undefined;
|
|
26
|
-
children: ((state: Readonly<TSourceValue>) => VNode | Array<VNode>) | VNode | Array<VNode>;
|
|
27
|
-
}): VNode | Array<VNode>;
|
|
28
|
-
<TSourceValue, TSubSelected>(props: {
|
|
29
|
-
source: SubscribeSource<TSourceValue>;
|
|
30
|
-
selector: (state: TSourceValue) => TSubSelected;
|
|
31
|
-
children: ((state: Readonly<TSubSelected>) => VNode | Array<VNode>) | VNode | Array<VNode>;
|
|
32
|
-
}): VNode | Array<VNode>;
|
|
33
|
-
<TSubSelected>(props: {
|
|
34
|
-
selector: (state: NoInfer<TableState<TFeatures>>) => TSubSelected;
|
|
35
|
-
children: ((state: Readonly<TSubSelected>) => VNode | Array<VNode>) | VNode | Array<VNode>;
|
|
36
|
-
}): VNode | Array<VNode>;
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* The selected state of the table. This state may not match the structure of
|
|
40
|
-
* the full table state because it is selected by the selector function that
|
|
41
|
-
* you pass as the 2nd argument to `useTable`.
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* const table = useTable(options, (state) => ({ globalFilter: state.globalFilter })) // only globalFilter is part of the selected state
|
|
45
|
-
*
|
|
46
|
-
* console.log(table.state.globalFilter)
|
|
47
|
-
*/
|
|
48
|
-
readonly state: Readonly<TSelected>;
|
|
10
|
+
Subscribe: (props: {
|
|
11
|
+
children: (atoms: Table<TFeatures, TData>['atoms']) => VNode | Array<VNode>;
|
|
12
|
+
}) => VNode | Array<VNode>;
|
|
49
13
|
};
|
|
50
14
|
/**
|
|
51
15
|
* Creates a Vue table instance backed by Vue-aware TanStack Store atoms.
|
|
52
16
|
*
|
|
53
17
|
* Table options may contain Vue refs or computed values. The adapter unwraps
|
|
54
18
|
* those reactive inputs, watches them with synchronous flushing, and keeps the
|
|
55
|
-
* table options in sync.
|
|
56
|
-
*
|
|
19
|
+
* table options in sync. Use `table.Subscribe` or native Vue computed values
|
|
20
|
+
* around `table.atoms.<slice>.get()` for selected reactive reads.
|
|
57
21
|
*
|
|
58
22
|
* @example
|
|
59
23
|
* ```ts
|
|
60
24
|
* const table = useTable(
|
|
61
25
|
* {
|
|
62
26
|
* features,
|
|
63
|
-
* rowModels: {},
|
|
64
27
|
* columns,
|
|
65
28
|
* data,
|
|
66
29
|
* },
|
|
67
|
-
* (state) => ({ pagination: state.pagination }),
|
|
68
30
|
* )
|
|
69
|
-
*
|
|
70
|
-
* table.state.pagination
|
|
71
31
|
* ```
|
|
72
32
|
*/
|
|
73
|
-
declare function useTable<TFeatures extends TableFeatures, TData extends RowData
|
|
33
|
+
declare function useTable<TFeatures extends TableFeatures, TData extends RowData>(tableOptions: TableOptions<TFeatures, TData> | TableOptionsWithReactiveData<TFeatures, TData>): VueTable<TFeatures, TData>;
|
|
74
34
|
//#endregion
|
|
75
|
-
export {
|
|
35
|
+
export { TableOptionsWithReactiveData, VueTable, useTable };
|
|
76
36
|
//# sourceMappingURL=useTable.d.cts.map
|
package/dist/useTable.d.ts
CHANGED
|
@@ -1,76 +1,36 @@
|
|
|
1
1
|
import { MaybeRef, VNode } from "vue";
|
|
2
|
-
import {
|
|
3
|
-
import { Atom, ReadonlyAtom, ReadonlyStore, Store } from "@tanstack/vue-store";
|
|
2
|
+
import { RowData, Table, TableFeatures, TableOptions } from "@tanstack/table-core";
|
|
4
3
|
|
|
5
4
|
//#region src/useTable.d.ts
|
|
6
|
-
type SubscribeSource<TValue> = Atom<TValue> | ReadonlyAtom<TValue> | Store<TValue> | ReadonlyStore<TValue>;
|
|
7
5
|
type TableOptionsWithReactiveData<TFeatures extends TableFeatures, TData extends RowData> = { [K in keyof TableOptions<TFeatures, TData>]: K extends 'data' ? MaybeRef<ReadonlyArray<TData>> : MaybeRef<TableOptions<TFeatures, TData>[K]> };
|
|
8
|
-
type VueTable<TFeatures extends TableFeatures, TData extends RowData
|
|
9
|
-
/**
|
|
10
|
-
*
|
|
11
|
-
* `table.atoms.<slice>.get()` for slice snapshots, or
|
|
12
|
-
* `table.Subscribe` / `useSelector(table.store, selector)` for explicit
|
|
13
|
-
* subscriptions. `table.store.state` is a current-value snapshot and is easy
|
|
14
|
-
* to misuse in render code.
|
|
6
|
+
type VueTable<TFeatures extends TableFeatures, TData extends RowData> = Table<TFeatures, TData> & {
|
|
7
|
+
/** Creates a reactive render boundary. The child function reads the table
|
|
8
|
+
* atoms it needs, so Vue only tracks those atom reads.
|
|
15
9
|
*/
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
* `selector` for the whole value (identity), or pass `selector` to project. Split
|
|
20
|
-
* overloads so source-only infers `TSourceValue` for `children` (see React `Subscribe`).
|
|
21
|
-
*/
|
|
22
|
-
Subscribe: {
|
|
23
|
-
<TSourceValue>(props: {
|
|
24
|
-
source: SubscribeSource<TSourceValue>;
|
|
25
|
-
selector?: undefined;
|
|
26
|
-
children: ((state: Readonly<TSourceValue>) => VNode | Array<VNode>) | VNode | Array<VNode>;
|
|
27
|
-
}): VNode | Array<VNode>;
|
|
28
|
-
<TSourceValue, TSubSelected>(props: {
|
|
29
|
-
source: SubscribeSource<TSourceValue>;
|
|
30
|
-
selector: (state: TSourceValue) => TSubSelected;
|
|
31
|
-
children: ((state: Readonly<TSubSelected>) => VNode | Array<VNode>) | VNode | Array<VNode>;
|
|
32
|
-
}): VNode | Array<VNode>;
|
|
33
|
-
<TSubSelected>(props: {
|
|
34
|
-
selector: (state: NoInfer<TableState<TFeatures>>) => TSubSelected;
|
|
35
|
-
children: ((state: Readonly<TSubSelected>) => VNode | Array<VNode>) | VNode | Array<VNode>;
|
|
36
|
-
}): VNode | Array<VNode>;
|
|
37
|
-
};
|
|
38
|
-
/**
|
|
39
|
-
* The selected state of the table. This state may not match the structure of
|
|
40
|
-
* the full table state because it is selected by the selector function that
|
|
41
|
-
* you pass as the 2nd argument to `useTable`.
|
|
42
|
-
*
|
|
43
|
-
* @example
|
|
44
|
-
* const table = useTable(options, (state) => ({ globalFilter: state.globalFilter })) // only globalFilter is part of the selected state
|
|
45
|
-
*
|
|
46
|
-
* console.log(table.state.globalFilter)
|
|
47
|
-
*/
|
|
48
|
-
readonly state: Readonly<TSelected>;
|
|
10
|
+
Subscribe: (props: {
|
|
11
|
+
children: (atoms: Table<TFeatures, TData>['atoms']) => VNode | Array<VNode>;
|
|
12
|
+
}) => VNode | Array<VNode>;
|
|
49
13
|
};
|
|
50
14
|
/**
|
|
51
15
|
* Creates a Vue table instance backed by Vue-aware TanStack Store atoms.
|
|
52
16
|
*
|
|
53
17
|
* Table options may contain Vue refs or computed values. The adapter unwraps
|
|
54
18
|
* those reactive inputs, watches them with synchronous flushing, and keeps the
|
|
55
|
-
* table options in sync.
|
|
56
|
-
*
|
|
19
|
+
* table options in sync. Use `table.Subscribe` or native Vue computed values
|
|
20
|
+
* around `table.atoms.<slice>.get()` for selected reactive reads.
|
|
57
21
|
*
|
|
58
22
|
* @example
|
|
59
23
|
* ```ts
|
|
60
24
|
* const table = useTable(
|
|
61
25
|
* {
|
|
62
26
|
* features,
|
|
63
|
-
* rowModels: {},
|
|
64
27
|
* columns,
|
|
65
28
|
* data,
|
|
66
29
|
* },
|
|
67
|
-
* (state) => ({ pagination: state.pagination }),
|
|
68
30
|
* )
|
|
69
|
-
*
|
|
70
|
-
* table.state.pagination
|
|
71
31
|
* ```
|
|
72
32
|
*/
|
|
73
|
-
declare function useTable<TFeatures extends TableFeatures, TData extends RowData
|
|
33
|
+
declare function useTable<TFeatures extends TableFeatures, TData extends RowData>(tableOptions: TableOptions<TFeatures, TData> | TableOptionsWithReactiveData<TFeatures, TData>): VueTable<TFeatures, TData>;
|
|
74
34
|
//#endregion
|
|
75
|
-
export {
|
|
35
|
+
export { TableOptionsWithReactiveData, VueTable, useTable };
|
|
76
36
|
//# sourceMappingURL=useTable.d.ts.map
|
package/dist/useTable.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { flatMerge, mergeProxy } from "./merge-proxy.js";
|
|
2
2
|
import { vueReactivity } from "./reactivity.js";
|
|
3
|
-
import { unref, watch } from "vue";
|
|
3
|
+
import { getCurrentScope, onScopeDispose, unref, watch } from "vue";
|
|
4
4
|
import { constructTable } from "@tanstack/table-core";
|
|
5
|
-
import { shallow, useSelector } from "@tanstack/vue-store";
|
|
6
5
|
|
|
7
6
|
//#region src/useTable.ts
|
|
8
7
|
function getOptionsWithReactiveValues(options) {
|
|
@@ -18,36 +17,37 @@ function getReactiveOptionDeps(options) {
|
|
|
18
17
|
*
|
|
19
18
|
* Table options may contain Vue refs or computed values. The adapter unwraps
|
|
20
19
|
* those reactive inputs, watches them with synchronous flushing, and keeps the
|
|
21
|
-
* table options in sync.
|
|
22
|
-
*
|
|
20
|
+
* table options in sync. Use `table.Subscribe` or native Vue computed values
|
|
21
|
+
* around `table.atoms.<slice>.get()` for selected reactive reads.
|
|
23
22
|
*
|
|
24
23
|
* @example
|
|
25
24
|
* ```ts
|
|
26
25
|
* const table = useTable(
|
|
27
26
|
* {
|
|
28
27
|
* features,
|
|
29
|
-
* rowModels: {},
|
|
30
28
|
* columns,
|
|
31
29
|
* data,
|
|
32
30
|
* },
|
|
33
|
-
* (state) => ({ pagination: state.pagination }),
|
|
34
31
|
* )
|
|
35
|
-
*
|
|
36
|
-
* table.state.pagination
|
|
37
32
|
* ```
|
|
38
33
|
*/
|
|
39
|
-
function useTable(tableOptions
|
|
34
|
+
function useTable(tableOptions) {
|
|
40
35
|
const syncTableOptions = (table, options) => {
|
|
41
36
|
table.setOptions((prev) => flatMerge(prev, getOptionsWithReactiveValues(options)));
|
|
42
37
|
};
|
|
38
|
+
const reactivity = vueReactivity();
|
|
43
39
|
const mergedOptions = mergeProxy(tableOptions, { features: {
|
|
44
|
-
|
|
40
|
+
coreReactivityFeature: reactivity,
|
|
45
41
|
...unref(tableOptions.features) ?? {}
|
|
46
42
|
} });
|
|
47
43
|
const coreTable = constructTable(mergeProxy(getOptionsWithReactiveValues(mergedOptions), { mergeOptions: (defaultOptions, newOptions) => {
|
|
48
44
|
return flatMerge(defaultOptions, newOptions);
|
|
49
45
|
} }));
|
|
50
46
|
const table = coreTable;
|
|
47
|
+
if (getCurrentScope()) onScopeDispose(() => {
|
|
48
|
+
var _reactivity$unmount;
|
|
49
|
+
return (_reactivity$unmount = reactivity.unmount) === null || _reactivity$unmount === void 0 ? void 0 : _reactivity$unmount.call(reactivity);
|
|
50
|
+
});
|
|
51
51
|
watch(() => getReactiveOptionDeps(mergedOptions), () => {
|
|
52
52
|
syncTableOptions(coreTable, mergedOptions);
|
|
53
53
|
}, { immediate: true });
|
|
@@ -64,18 +64,10 @@ function useTable(tableOptions, selector) {
|
|
|
64
64
|
}, (controlledValues) => {
|
|
65
65
|
if (controlledValues.length > 0) syncTableOptions(coreTable, mergedOptions);
|
|
66
66
|
}, { immediate: true });
|
|
67
|
-
table.Subscribe = (
|
|
68
|
-
|
|
69
|
-
if (typeof props.children === "function") return props.children(selected.value);
|
|
70
|
-
return props.children;
|
|
71
|
-
});
|
|
72
|
-
const stateStore = useSelector(table.store, selector);
|
|
73
|
-
return {
|
|
74
|
-
...table,
|
|
75
|
-
get state() {
|
|
76
|
-
return stateStore.value;
|
|
77
|
-
}
|
|
67
|
+
table.Subscribe = (props) => {
|
|
68
|
+
return props.children(table.atoms);
|
|
78
69
|
};
|
|
70
|
+
return table;
|
|
79
71
|
}
|
|
80
72
|
|
|
81
73
|
//#endregion
|
package/dist/useTable.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useTable.js","names":[],"sources":["../src/useTable.ts"],"sourcesContent":["import { unref, watch } from 'vue'\nimport { constructTable } from '@tanstack/table-core'\nimport {
|
|
1
|
+
{"version":3,"file":"useTable.js","names":[],"sources":["../src/useTable.ts"],"sourcesContent":["import { getCurrentScope, onScopeDispose, unref, watch } from 'vue'\nimport { constructTable } from '@tanstack/table-core'\nimport { flatMerge, mergeProxy } from './merge-proxy'\nimport { vueReactivity } from './reactivity'\nimport type {\n RowData,\n Table,\n TableFeatures,\n TableOptions,\n} from '@tanstack/table-core'\nimport type { MaybeRef, VNode } from 'vue'\n\nexport type TableOptionsWithReactiveData<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = {\n [K in keyof TableOptions<TFeatures, TData>]: K extends 'data'\n ? MaybeRef<ReadonlyArray<TData>>\n : MaybeRef<TableOptions<TFeatures, TData>[K]>\n}\n\nfunction getOptionsWithReactiveValues<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(options: TableOptionsWithReactiveData<TFeatures, TData>) {\n const resolvedOptions: Record<string, unknown> = {}\n\n for (const key of Object.keys(options)) {\n resolvedOptions[key] = unref(\n options[key as keyof TableOptionsWithReactiveData<TFeatures, TData>],\n )\n }\n\n return mergeProxy(options, resolvedOptions)\n}\n\nfunction getReactiveOptionDeps<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(options: TableOptionsWithReactiveData<TFeatures, TData>) {\n return Object.keys(options).map((key) =>\n unref(options[key as keyof TableOptionsWithReactiveData<TFeatures, TData>]),\n )\n}\n\nexport type VueTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n> = Table<TFeatures, TData> & {\n /** Creates a reactive render boundary. The child function reads the table\n * atoms it needs, so Vue only tracks those atom reads.\n */\n Subscribe: (props: {\n children: (atoms: Table<TFeatures, TData>['atoms']) => VNode | Array<VNode>\n }) => VNode | Array<VNode>\n}\n\n/**\n * Creates a Vue table instance backed by Vue-aware TanStack Store atoms.\n *\n * Table options may contain Vue refs or computed values. The adapter unwraps\n * those reactive inputs, watches them with synchronous flushing, and keeps the\n * table options in sync. Use `table.Subscribe` or native Vue computed values\n * around `table.atoms.<slice>.get()` for selected reactive reads.\n *\n * @example\n * ```ts\n * const table = useTable(\n * {\n * features,\n * columns,\n * data,\n * },\n * )\n * ```\n */\nexport function useTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n>(\n tableOptions:\n | TableOptions<TFeatures, TData>\n | TableOptionsWithReactiveData<TFeatures, TData>,\n): VueTable<TFeatures, TData> {\n const syncTableOptions = (\n table: Table<TFeatures, TData>,\n options: TableOptionsWithReactiveData<TFeatures, TData>,\n ) => {\n table.setOptions((prev) =>\n flatMerge(prev, getOptionsWithReactiveValues(options)),\n )\n }\n\n const reactivity = vueReactivity()\n\n const mergedOptions = mergeProxy(tableOptions, {\n features: {\n coreReactivityFeature: reactivity,\n ...(unref(tableOptions.features) ?? {}),\n },\n }) as TableOptionsWithReactiveData<TFeatures, TData>\n\n const resolvedOptions = mergeProxy(\n getOptionsWithReactiveValues(mergedOptions),\n {\n // Remove state and onStateChange - store handles it internally\n mergeOptions: (\n defaultOptions: TableOptions<TFeatures, TData>,\n newOptions: Partial<TableOptions<TFeatures, TData>>,\n ) => {\n return flatMerge(defaultOptions, newOptions)\n },\n },\n ) as TableOptions<TFeatures, TData>\n\n const coreTable = constructTable(resolvedOptions)\n const table = coreTable as unknown as VueTable<TFeatures, TData>\n\n if (getCurrentScope()) {\n onScopeDispose(() => reactivity.unmount?.())\n }\n\n watch(\n () => getReactiveOptionDeps(mergedOptions),\n () => {\n syncTableOptions(coreTable, mergedOptions)\n },\n { immediate: true },\n )\n\n watch(\n () => {\n const controlledState = unref(tableOptions.state) as\n | Record<string, unknown>\n | undefined\n const controlledAtoms = unref(tableOptions.atoms) as\n | Record<string, unknown>\n | undefined\n\n if (!controlledState) {\n return []\n }\n\n const controlledValues: Array<unknown> = []\n\n for (const key of Object.keys(table.initialState)) {\n if (!(key in controlledState) || controlledAtoms?.[key] !== undefined) {\n continue\n }\n\n // Reading only controlled state slices here lets Vue subscribe to\n // getters/computed values that are passed through `options.state`.\n controlledValues.push(controlledState[key])\n }\n\n return controlledValues\n },\n (controlledValues) => {\n if (controlledValues.length > 0) {\n syncTableOptions(coreTable, mergedOptions)\n }\n },\n { immediate: true },\n )\n\n table.Subscribe = (props: {\n children: (atoms: Table<TFeatures, TData>['atoms']) => VNode | Array<VNode>\n }) => {\n return props.children(table.atoms as Table<TFeatures, TData>['atoms'])\n }\n\n return table\n}\n"],"mappings":";;;;;;AAqBA,SAAS,6BAGP,SAAyD;CACzD,MAAM,kBAA2C,CAAC;CAElD,KAAK,MAAM,OAAO,OAAO,KAAK,OAAO,GACnC,gBAAgB,OAAO,MACrB,QAAQ,IACV;CAGF,OAAO,WAAW,SAAS,eAAe;AAC5C;AAEA,SAAS,sBAGP,SAAyD;CACzD,OAAO,OAAO,KAAK,OAAO,CAAC,CAAC,KAAK,QAC/B,MAAM,QAAQ,IAA4D,CAC5E;AACF;;;;;;;;;;;;;;;;;;;;AAiCA,SAAgB,SAId,cAG4B;CAC5B,MAAM,oBACJ,OACA,YACG;EACH,MAAM,YAAY,SAChB,UAAU,MAAM,6BAA6B,OAAO,CAAC,CACvD;CACF;CAEA,MAAM,aAAa,cAAc;CAEjC,MAAM,gBAAgB,WAAW,cAAc,EAC7C,UAAU;EACR,uBAAuB;EACvB,GAAI,MAAM,aAAa,QAAQ,KAAK,CAAC;CACvC,EACF,CAAC;CAeD,MAAM,YAAY,eAbM,WACtB,6BAA6B,aAAa,GAC1C,EAEE,eACE,gBACA,eACG;EACH,OAAO,UAAU,gBAAgB,UAAU;CAC7C,EACF,CAG6C,CAAC;CAChD,MAAM,QAAQ;CAEd,IAAI,gBAAgB,GAClB,qBAAqB;;2CAAW,kGAAU;EAAC;CAG7C,YACQ,sBAAsB,aAAa,SACnC;EACJ,iBAAiB,WAAW,aAAa;CAC3C,GACA,EAAE,WAAW,KAAK,CACpB;CAEA,YACQ;EACJ,MAAM,kBAAkB,MAAM,aAAa,KAAK;EAGhD,MAAM,kBAAkB,MAAM,aAAa,KAAK;EAIhD,IAAI,CAAC,iBACH,OAAO,CAAC;EAGV,MAAM,mBAAmC,CAAC;EAE1C,KAAK,MAAM,OAAO,OAAO,KAAK,MAAM,YAAY,GAAG;GACjD,IAAI,EAAE,OAAO,uFAAoB,gBAAkB,UAAS,QAC1D;GAKF,iBAAiB,KAAK,gBAAgB,IAAI;EAC5C;EAEA,OAAO;CACT,IACC,qBAAqB;EACpB,IAAI,iBAAiB,SAAS,GAC5B,iBAAiB,WAAW,aAAa;CAE7C,GACA,EAAE,WAAW,KAAK,CACpB;CAEA,MAAM,aAAa,UAEb;EACJ,OAAO,MAAM,SAAS,MAAM,KAAyC;CACvE;CAEA,OAAO;AACT"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/vue-table",
|
|
3
|
-
"version": "9.0.0-beta.
|
|
3
|
+
"version": "9.0.0-beta.30",
|
|
4
4
|
"description": "Headless UI for building powerful tables & datagrids for Vue.",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -50,13 +50,13 @@
|
|
|
50
50
|
"skills"
|
|
51
51
|
],
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@tanstack/
|
|
54
|
-
"@tanstack/
|
|
53
|
+
"@tanstack/store": "^0.11.0",
|
|
54
|
+
"@tanstack/table-core": "9.0.0-beta.30"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@vitejs/plugin-vue": "^6.0.7",
|
|
58
58
|
"eslint-plugin-vue": "^10.9.2",
|
|
59
|
-
"vue": "^3.5.
|
|
59
|
+
"vue": "^3.5.38"
|
|
60
60
|
},
|
|
61
61
|
"peerDependencies": {
|
|
62
62
|
"vue": ">=3.2"
|
|
@@ -3,7 +3,7 @@ name: vue/client-to-server
|
|
|
3
3
|
description: >
|
|
4
4
|
Convert a client-side `@tanstack/vue-table` to server-side. Set `manualPagination` /
|
|
5
5
|
`manualSorting` / `manualFiltering` / `manualGrouping` / `manualExpanding` for whichever
|
|
6
|
-
slices the server owns;
|
|
6
|
+
slices the server owns; omit the matching row model factory from `tableFeatures` (don't ship
|
|
7
7
|
`paginatedRowModel` when the server paginates); supply `rowCount` so `table.getPageCount()`
|
|
8
8
|
works; own the relevant state slices via either external atoms (`@tanstack/vue-store`
|
|
9
9
|
`createAtom` + `options.atoms`) or `state` + `on[State]Change` with getter wrappers. Key any
|
|
@@ -87,10 +87,9 @@ watchEffect(() => {
|
|
|
87
87
|
if (next != null) rowCount.value = next // keep last known total for pager UI
|
|
88
88
|
})
|
|
89
89
|
|
|
90
|
-
// 3) Manual pagination + `rowCount`.
|
|
90
|
+
// 3) Manual pagination + `rowCount`. No paginatedRowModel in features — server paginates.
|
|
91
91
|
const table = useTable({
|
|
92
92
|
features,
|
|
93
|
-
rowModels: {},
|
|
94
93
|
columns,
|
|
95
94
|
data: tableData,
|
|
96
95
|
rowCount,
|
|
@@ -104,18 +103,19 @@ Source: `examples/vue/with-tanstack-query/src/App.tsx`, `examples/vue/basic-exte
|
|
|
104
103
|
|
|
105
104
|
## Core Patterns
|
|
106
105
|
|
|
107
|
-
### 1. The `manual*` flag +
|
|
106
|
+
### 1. The `manual*` flag + factory omission pair
|
|
108
107
|
|
|
109
|
-
Pick which slices live server-side and flip the matching `manual*` flag. **Also
|
|
110
|
-
matching
|
|
108
|
+
Pick which slices live server-side and flip the matching `manual*` flag. **Also omit the
|
|
109
|
+
matching row model factory from `tableFeatures`** — otherwise the table re-processes
|
|
110
|
+
server-processed rows.
|
|
111
111
|
|
|
112
|
-
| Server owns | Set |
|
|
113
|
-
| ----------- | ------------------------ |
|
|
114
|
-
| Pagination | `manualPagination: true` | `paginatedRowModel`
|
|
115
|
-
| Sorting | `manualSorting: true` | `sortedRowModel`
|
|
116
|
-
| Filtering | `manualFiltering: true` | `filteredRowModel`
|
|
117
|
-
| Grouping | `manualGrouping: true` | `groupedRowModel`
|
|
118
|
-
| Expanding | `manualExpanding: true` | `expandedRowModel`
|
|
112
|
+
| Server owns | Set | Omit from `tableFeatures` |
|
|
113
|
+
| ----------- | ------------------------ | ------------------------- |
|
|
114
|
+
| Pagination | `manualPagination: true` | `paginatedRowModel` |
|
|
115
|
+
| Sorting | `manualSorting: true` | `sortedRowModel` |
|
|
116
|
+
| Filtering | `manualFiltering: true` | `filteredRowModel` |
|
|
117
|
+
| Grouping | `manualGrouping: true` | `groupedRowModel` |
|
|
118
|
+
| Expanding | `manualExpanding: true` | `expandedRowModel` |
|
|
119
119
|
|
|
120
120
|
Column visibility / ordering / pinning / row selection are client-side state and stay as-is.
|
|
121
121
|
|
|
@@ -127,7 +127,6 @@ Without `rowCount`, `getPageCount()` falls back to `Math.ceil(data.length / page
|
|
|
127
127
|
```ts
|
|
128
128
|
useTable({
|
|
129
129
|
features,
|
|
130
|
-
rowModels: {},
|
|
131
130
|
columns,
|
|
132
131
|
data: tableData,
|
|
133
132
|
rowCount: dataQuery.data.value?.rowCount, // or a stable ref/computed
|
|
@@ -151,7 +150,6 @@ const paginationAtom = createAtom<PaginationState>({
|
|
|
151
150
|
})
|
|
152
151
|
useTable({
|
|
153
152
|
features,
|
|
154
|
-
rowModels: {},
|
|
155
153
|
columns,
|
|
156
154
|
data,
|
|
157
155
|
rowCount,
|
|
@@ -169,7 +167,6 @@ const pagination = ref<PaginationState>({ pageIndex: 0, pageSize: 10 })
|
|
|
169
167
|
|
|
170
168
|
useTable({
|
|
171
169
|
features,
|
|
172
|
-
rowModels: {},
|
|
173
170
|
columns,
|
|
174
171
|
data,
|
|
175
172
|
rowCount,
|
|
@@ -230,7 +227,6 @@ the table will paginate that 10-row slice again and show "Page 1 of 1".
|
|
|
230
227
|
// ❌
|
|
231
228
|
useTable({
|
|
232
229
|
features,
|
|
233
|
-
rowModels: {},
|
|
234
230
|
columns,
|
|
235
231
|
data: serverPage.rows,
|
|
236
232
|
rowCount,
|
|
@@ -243,13 +239,13 @@ useTable({
|
|
|
243
239
|
|
|
244
240
|
```ts
|
|
245
241
|
// ❌ Factory ships for nothing AND the table re-paginates server-sliced data.
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
242
|
+
const features = tableFeatures({
|
|
243
|
+
rowPaginationFeature,
|
|
244
|
+
paginatedRowModel: createPaginatedRowModel(),
|
|
245
|
+
})
|
|
249
246
|
|
|
250
|
-
// ✅
|
|
251
|
-
|
|
252
|
-
}
|
|
247
|
+
// ✅ Omit the factory when the server paginates; keep the feature for its API.
|
|
248
|
+
const features = tableFeatures({ rowPaginationFeature })
|
|
253
249
|
```
|
|
254
250
|
|
|
255
251
|
Same applies to `sortedRowModel`, `filteredRowModel`, `groupedRowModel`, `expandedRowModel`
|
|
@@ -267,7 +263,6 @@ when the server owns the slice.
|
|
|
267
263
|
const pagination = ref({ pageIndex: 0, pageSize: 10 })
|
|
268
264
|
useTable({
|
|
269
265
|
features,
|
|
270
|
-
rowModels: {},
|
|
271
266
|
columns,
|
|
272
267
|
data,
|
|
273
268
|
rowCount,
|
|
@@ -350,8 +345,8 @@ table.setColumnFilters(/* ... */)
|
|
|
350
345
|
### "API missing" because the feature isn't in `features` (CRITICAL — v9-specific)
|
|
351
346
|
|
|
352
347
|
Server-side pagination still needs `rowPaginationFeature` in `tableFeatures({...})` — that's
|
|
353
|
-
what surfaces `table.setPageIndex`, `table.nextPage`, `table.getPageCount`. The
|
|
354
|
-
`
|
|
348
|
+
what surfaces `table.setPageIndex`, `table.nextPage`, `table.getPageCount`. The row model
|
|
349
|
+
factory (`paginatedRowModel`) is what you omit; the feature stays.
|
|
355
350
|
|
|
356
351
|
```ts
|
|
357
352
|
const features = tableFeatures({ rowPaginationFeature }) // ✅ even with manualPagination
|
|
@@ -60,7 +60,10 @@ type Person = {
|
|
|
60
60
|
}
|
|
61
61
|
type FormRow = Omit<Person, 'subRows'> // <-- avoid TS2589 in form DeepKeys
|
|
62
62
|
|
|
63
|
-
const features = tableFeatures({
|
|
63
|
+
const features = tableFeatures({
|
|
64
|
+
rowPaginationFeature,
|
|
65
|
+
paginatedRowModel: createPaginatedRowModel(),
|
|
66
|
+
})
|
|
64
67
|
const columnHelper = createColumnHelper<typeof features, FormRow>()
|
|
65
68
|
|
|
66
69
|
// 2) Form owns the data array. The table reads it.
|
|
@@ -99,7 +102,6 @@ const columns = computed(() =>
|
|
|
99
102
|
|
|
100
103
|
const table = useTable({
|
|
101
104
|
features,
|
|
102
|
-
rowModels: { paginatedRowModel: createPaginatedRowModel() },
|
|
103
105
|
get columns() {
|
|
104
106
|
return columns.value
|
|
105
107
|
},
|
|
@@ -191,7 +193,6 @@ const form = useForm({ defaultValues: { data: makeData(100) } })
|
|
|
191
193
|
|
|
192
194
|
const table = useTable({
|
|
193
195
|
features,
|
|
194
|
-
rowModels: { paginatedRowModel: createPaginatedRowModel() },
|
|
195
196
|
columns,
|
|
196
197
|
get data() {
|
|
197
198
|
return form.state.values.data
|
|
@@ -324,7 +325,6 @@ const columns = computed(() =>
|
|
|
324
325
|
)
|
|
325
326
|
const table = useTable({
|
|
326
327
|
features,
|
|
327
|
-
rowModels: {},
|
|
328
328
|
get columns() {
|
|
329
329
|
return columns.value
|
|
330
330
|
},
|
|
@@ -150,7 +150,6 @@ const throttler = new Throttler(
|
|
|
150
150
|
|
|
151
151
|
useTable({
|
|
152
152
|
features,
|
|
153
|
-
rowModels: {},
|
|
154
153
|
columns,
|
|
155
154
|
data,
|
|
156
155
|
state: {
|
|
@@ -301,8 +300,12 @@ useTable({ ..., data: filtered })
|
|
|
301
300
|
```ts
|
|
302
301
|
// ✅ Use the table's filter feature; debounce the writer.
|
|
303
302
|
useTable({
|
|
304
|
-
features: tableFeatures({
|
|
305
|
-
|
|
303
|
+
features: tableFeatures({
|
|
304
|
+
columnFilteringFeature,
|
|
305
|
+
globalFilteringFeature,
|
|
306
|
+
filteredRowModel: createFilteredRowModel(),
|
|
307
|
+
filterFns,
|
|
308
|
+
}),
|
|
306
309
|
columns,
|
|
307
310
|
data,
|
|
308
311
|
})
|