@tanstack/vue-table 9.0.0-beta.3 → 9.0.0-beta.5

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.
@@ -1,59 +1,29 @@
1
- import { NoInfer, RowData, Table, TableFeatures, TableOptions, TableState } from "@tanstack/table-core";
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, TSelected = TableState<TFeatures>> = Omit<Table<TFeatures, TData>, 'store'> & {
6
+ type VueTable<TFeatures extends TableFeatures, TData extends RowData> = Omit<Table<TFeatures, TData>, 'store'> & {
9
7
  /**
10
- * @deprecated Prefer `table.state` for render reads,
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.
8
+ * @deprecated Prefer `table.atoms.<slice>.get()` for slice snapshots, or
9
+ * `table.Subscribe` for explicit subscriptions. `table.store.state` is a
10
+ * current-value snapshot and is easy to misuse in render code.
15
11
  */
16
12
  readonly store: Table<TFeatures, TData>['store'];
17
- /**
18
- * Store mode: `selector` required. Source mode: pass `source` (atom or store); omit
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)
13
+ /** Creates a reactive render boundary. The child function reads the table
14
+ * atoms it needs, so Vue only tracks those atom reads.
47
15
  */
48
- readonly state: Readonly<TSelected>;
16
+ Subscribe: (props: {
17
+ children: (atoms: Table<TFeatures, TData>['atoms']) => VNode | Array<VNode>;
18
+ }) => VNode | Array<VNode>;
49
19
  };
50
20
  /**
51
21
  * Creates a Vue table instance backed by Vue-aware TanStack Store atoms.
52
22
  *
53
23
  * Table options may contain Vue refs or computed values. The adapter unwraps
54
24
  * those reactive inputs, watches them with synchronous flushing, and keeps the
55
- * table options in sync. The optional selector projects from `table.store` and
56
- * exposes the selected value on `table.state`.
25
+ * table options in sync. Use `table.Subscribe` or native Vue computed values
26
+ * around `table.atoms.<slice>.get()` for selected reactive reads.
57
27
  *
58
28
  * @example
59
29
  * ```ts
@@ -64,13 +34,10 @@ type VueTable<TFeatures extends TableFeatures, TData extends RowData, TSelected
64
34
  * columns,
65
35
  * data,
66
36
  * },
67
- * (state) => ({ pagination: state.pagination }),
68
37
  * )
69
- *
70
- * table.state.pagination
71
38
  * ```
72
39
  */
73
- declare function useTable<TFeatures extends TableFeatures, TData extends RowData, TSelected = TableState<TFeatures>>(tableOptions: TableOptions<TFeatures, TData> | TableOptionsWithReactiveData<TFeatures, TData>, selector?: (state: TableState<TFeatures>) => TSelected): VueTable<TFeatures, TData, TSelected>;
40
+ declare function useTable<TFeatures extends TableFeatures, TData extends RowData>(tableOptions: TableOptions<TFeatures, TData> | TableOptionsWithReactiveData<TFeatures, TData>): VueTable<TFeatures, TData>;
74
41
  //#endregion
75
- export { SubscribeSource, TableOptionsWithReactiveData, VueTable, useTable };
42
+ export { TableOptionsWithReactiveData, VueTable, useTable };
76
43
  //# sourceMappingURL=useTable.d.cts.map
@@ -1,59 +1,29 @@
1
1
  import { MaybeRef, VNode } from "vue";
2
- import { NoInfer, RowData, Table, TableFeatures, TableOptions, TableState } from "@tanstack/table-core";
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, TSelected = TableState<TFeatures>> = Omit<Table<TFeatures, TData>, 'store'> & {
6
+ type VueTable<TFeatures extends TableFeatures, TData extends RowData> = Omit<Table<TFeatures, TData>, 'store'> & {
9
7
  /**
10
- * @deprecated Prefer `table.state` for render reads,
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.
8
+ * @deprecated Prefer `table.atoms.<slice>.get()` for slice snapshots, or
9
+ * `table.Subscribe` for explicit subscriptions. `table.store.state` is a
10
+ * current-value snapshot and is easy to misuse in render code.
15
11
  */
16
12
  readonly store: Table<TFeatures, TData>['store'];
17
- /**
18
- * Store mode: `selector` required. Source mode: pass `source` (atom or store); omit
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)
13
+ /** Creates a reactive render boundary. The child function reads the table
14
+ * atoms it needs, so Vue only tracks those atom reads.
47
15
  */
48
- readonly state: Readonly<TSelected>;
16
+ Subscribe: (props: {
17
+ children: (atoms: Table<TFeatures, TData>['atoms']) => VNode | Array<VNode>;
18
+ }) => VNode | Array<VNode>;
49
19
  };
50
20
  /**
51
21
  * Creates a Vue table instance backed by Vue-aware TanStack Store atoms.
52
22
  *
53
23
  * Table options may contain Vue refs or computed values. The adapter unwraps
54
24
  * those reactive inputs, watches them with synchronous flushing, and keeps the
55
- * table options in sync. The optional selector projects from `table.store` and
56
- * exposes the selected value on `table.state`.
25
+ * table options in sync. Use `table.Subscribe` or native Vue computed values
26
+ * around `table.atoms.<slice>.get()` for selected reactive reads.
57
27
  *
58
28
  * @example
59
29
  * ```ts
@@ -64,13 +34,10 @@ type VueTable<TFeatures extends TableFeatures, TData extends RowData, TSelected
64
34
  * columns,
65
35
  * data,
66
36
  * },
67
- * (state) => ({ pagination: state.pagination }),
68
37
  * )
69
- *
70
- * table.state.pagination
71
38
  * ```
72
39
  */
73
- declare function useTable<TFeatures extends TableFeatures, TData extends RowData, TSelected = TableState<TFeatures>>(tableOptions: TableOptions<TFeatures, TData> | TableOptionsWithReactiveData<TFeatures, TData>, selector?: (state: TableState<TFeatures>) => TSelected): VueTable<TFeatures, TData, TSelected>;
40
+ declare function useTable<TFeatures extends TableFeatures, TData extends RowData>(tableOptions: TableOptions<TFeatures, TData> | TableOptionsWithReactiveData<TFeatures, TData>): VueTable<TFeatures, TData>;
74
41
  //#endregion
75
- export { SubscribeSource, TableOptionsWithReactiveData, VueTable, useTable };
42
+ export { TableOptionsWithReactiveData, VueTable, useTable };
76
43
  //# 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,8 +17,8 @@ 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. The optional selector projects from `table.store` and
22
- * exposes the selected value on `table.state`.
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
@@ -30,24 +29,26 @@ function getReactiveOptionDeps(options) {
30
29
  * columns,
31
30
  * data,
32
31
  * },
33
- * (state) => ({ pagination: state.pagination }),
34
32
  * )
35
- *
36
- * table.state.pagination
37
33
  * ```
38
34
  */
39
- function useTable(tableOptions, selector) {
35
+ function useTable(tableOptions) {
40
36
  const syncTableOptions = (table, options) => {
41
37
  table.setOptions((prev) => flatMerge(prev, getOptionsWithReactiveValues(options)));
42
38
  };
39
+ const reactivity = vueReactivity();
43
40
  const mergedOptions = mergeProxy(tableOptions, { features: {
44
- coreReativityFeature: vueReactivity(),
41
+ coreReativityFeature: reactivity,
45
42
  ...unref(tableOptions.features) ?? {}
46
43
  } });
47
44
  const coreTable = constructTable(mergeProxy(getOptionsWithReactiveValues(mergedOptions), { mergeOptions: (defaultOptions, newOptions) => {
48
45
  return flatMerge(defaultOptions, newOptions);
49
46
  } }));
50
47
  const table = coreTable;
48
+ if (getCurrentScope()) onScopeDispose(() => {
49
+ var _reactivity$unmount;
50
+ return (_reactivity$unmount = reactivity.unmount) === null || _reactivity$unmount === void 0 ? void 0 : _reactivity$unmount.call(reactivity);
51
+ });
51
52
  watch(() => getReactiveOptionDeps(mergedOptions), () => {
52
53
  syncTableOptions(coreTable, mergedOptions);
53
54
  }, { immediate: true });
@@ -64,18 +65,10 @@ function useTable(tableOptions, selector) {
64
65
  }, (controlledValues) => {
65
66
  if (controlledValues.length > 0) syncTableOptions(coreTable, mergedOptions);
66
67
  }, { immediate: true });
67
- table.Subscribe = ((props) => {
68
- const selected = useSelector(props.source ?? table.store, props.selector, { compare: shallow });
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
- }
68
+ table.Subscribe = (props) => {
69
+ return props.children(table.atoms);
78
70
  };
71
+ return table;
79
72
  }
80
73
 
81
74
  //#endregion
@@ -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 { shallow, useSelector } from '@tanstack/vue-store'\nimport { flatMerge, mergeProxy } from './merge-proxy'\nimport { vueReactivity } from './reactivity'\nimport type {\n Atom,\n ReadonlyAtom,\n ReadonlyStore,\n Store,\n} from '@tanstack/vue-store'\nimport type {\n NoInfer,\n RowData,\n Table,\n TableFeatures,\n TableOptions,\n TableState,\n} from '@tanstack/table-core'\nimport type { MaybeRef, VNode } from 'vue'\n\nexport type SubscribeSource<TValue> =\n | Atom<TValue>\n | ReadonlyAtom<TValue>\n | Store<TValue>\n | ReadonlyStore<TValue>\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 TSelected = TableState<TFeatures>,\n> = Omit<Table<TFeatures, TData>, 'store'> & {\n /**\n * @deprecated Prefer `table.state` for render reads,\n * `table.atoms.<slice>.get()` for slice snapshots, or\n * `table.Subscribe` / `useSelector(table.store, selector)` for explicit\n * subscriptions. `table.store.state` is a current-value snapshot and is easy\n * to misuse in render code.\n */\n readonly store: Table<TFeatures, TData>['store']\n /**\n * Store mode: `selector` required. Source mode: pass `source` (atom or store); omit\n * `selector` for the whole value (identity), or pass `selector` to project. Split\n * overloads so source-only infers `TSourceValue` for `children` (see React `Subscribe`).\n */\n Subscribe: {\n <TSourceValue>(props: {\n source: SubscribeSource<TSourceValue>\n selector?: undefined\n children:\n | ((state: Readonly<TSourceValue>) => VNode | Array<VNode>)\n | VNode\n | Array<VNode>\n }): VNode | Array<VNode>\n <TSourceValue, TSubSelected>(props: {\n source: SubscribeSource<TSourceValue>\n selector: (state: TSourceValue) => TSubSelected\n children:\n | ((state: Readonly<TSubSelected>) => VNode | Array<VNode>)\n | VNode\n | Array<VNode>\n }): VNode | Array<VNode>\n <TSubSelected>(props: {\n selector: (state: NoInfer<TableState<TFeatures>>) => TSubSelected\n children:\n | ((state: Readonly<TSubSelected>) => VNode | Array<VNode>)\n | VNode\n | Array<VNode>\n }): VNode | Array<VNode>\n }\n /**\n * The selected state of the table. This state may not match the structure of\n * the full table state because it is selected by the selector function that\n * you pass as the 2nd argument to `useTable`.\n *\n * @example\n * const table = useTable(options, (state) => ({ globalFilter: state.globalFilter })) // only globalFilter is part of the selected state\n *\n * console.log(table.state.globalFilter)\n */\n readonly state: Readonly<TSelected>\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. The optional selector projects from `table.store` and\n * exposes the selected value on `table.state`.\n *\n * @example\n * ```ts\n * const table = useTable(\n * {\n * features,\n * rowModels: {},\n * columns,\n * data,\n * },\n * (state) => ({ pagination: state.pagination }),\n * )\n *\n * table.state.pagination\n * ```\n */\nexport function useTable<\n TFeatures extends TableFeatures,\n TData extends RowData,\n TSelected = TableState<TFeatures>,\n>(\n tableOptions:\n | TableOptions<TFeatures, TData>\n | TableOptionsWithReactiveData<TFeatures, TData>,\n selector?: (state: TableState<TFeatures>) => TSelected,\n): VueTable<TFeatures, TData, TSelected> {\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 mergedOptions = mergeProxy(tableOptions, {\n features: {\n coreReativityFeature: vueReactivity(),\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, TSelected>\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 source?: SubscribeSource<unknown>\n selector?: ((state: unknown) => unknown) | undefined\n children:\n | ((state: Readonly<unknown>) => VNode | Array<VNode>)\n | VNode\n | Array<VNode>\n }) => {\n const source = props.source ?? table.store\n const selected = useSelector(source as never, props.selector as never, {\n compare: shallow,\n })\n if (typeof props.children === 'function') {\n return props.children(selected.value as Readonly<unknown>)\n }\n return props.children\n }) as VueTable<TFeatures, TData, TSelected>['Subscribe']\n\n const stateStore = useSelector(table.store, selector)\n\n return {\n ...table,\n get state() {\n return stateStore.value\n },\n }\n}\n"],"mappings":";;;;;;;AAoCA,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;;;;;;;;;;;;;;;;;;;;;;;;AAiFA,SAAgB,SAKd,cAGA,UACuC;CACvC,MAAM,oBACJ,OACA,YACG;EACH,MAAM,YAAY,SAChB,UAAU,MAAM,6BAA6B,OAAO,CAAC,CACvD;CACF;CAEA,MAAM,gBAAgB,WAAW,cAAc,EAC7C,UAAU;EACR,sBAAsB,cAAc;EACpC,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,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,cAAc,UAOd;EAEJ,MAAM,WAAW,YADF,MAAM,UAAU,MAAM,OACS,MAAM,UAAmB,EACrE,SAAS,QACX,CAAC;EACD,IAAI,OAAO,MAAM,aAAa,YAC5B,OAAO,MAAM,SAAS,SAAS,KAA0B;EAE3D,OAAO,MAAM;CACf;CAEA,MAAM,aAAa,YAAY,MAAM,OAAO,QAAQ;CAEpD,OAAO;EACL,GAAG;EACH,IAAI,QAAQ;GACV,OAAO,WAAW;EACpB;CACF;AACF"}
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 TableState,\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> = Omit<Table<TFeatures, TData>, 'store'> & {\n /**\n * @deprecated Prefer `table.atoms.<slice>.get()` for slice snapshots, or\n * `table.Subscribe` for explicit subscriptions. `table.store.state` is a\n * current-value snapshot and is easy to misuse in render code.\n */\n readonly store: Table<TFeatures, TData>['store']\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 * rowModels: {},\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 coreReativityFeature: 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)\n }\n\n return table\n}\n"],"mappings":";;;;;;AAsBA,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;;;;;;;;;;;;;;;;;;;;;AAwCA,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,sBAAsB;EACtB,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,KAAK;CACnC;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",
3
+ "version": "9.0.0-beta.5",
4
4
  "description": "Headless UI for building powerful tables & datagrids for Vue.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -50,8 +50,8 @@
50
50
  "skills"
51
51
  ],
52
52
  "dependencies": {
53
- "@tanstack/table-core": "^9.0.0-beta.2",
54
- "@tanstack/vue-store": "^0.11.0"
53
+ "@tanstack/store": "^0.11.0",
54
+ "@tanstack/table-core": "^9.0.0-beta.2"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@vitejs/plugin-vue": "^6.0.7",
package/src/FlexRender.ts CHANGED
@@ -1,12 +1,27 @@
1
1
  import { defineComponent, h, isVNode } from 'vue'
2
2
  import type { PropType } from 'vue'
3
- import type {
4
- Cell,
5
- CellData,
6
- Header,
7
- RowData,
8
- TableFeatures,
9
- } from '@tanstack/table-core'
3
+
4
+ export interface FlexRenderCell {
5
+ column: {
6
+ columnDef: {
7
+ aggregatedCell?: any
8
+ cell?: any
9
+ }
10
+ }
11
+ getContext: () => any
12
+ getIsAggregated?: () => boolean
13
+ getIsPlaceholder?: () => boolean
14
+ }
15
+
16
+ export interface FlexRenderHeader {
17
+ column: {
18
+ columnDef: {
19
+ footer?: any
20
+ header?: any
21
+ }
22
+ }
23
+ getContext: () => any
24
+ }
10
25
 
11
26
  /**
12
27
  * If rendering headers, cells, or footers with custom markup, use flexRender instead of `cell.getValue()` or `cell.renderValue()`.
@@ -60,24 +75,24 @@ export const FlexRender = defineComponent({
60
75
  default: undefined,
61
76
  },
62
77
  cell: {
63
- type: Object as PropType<Cell<any, any, any>>,
78
+ type: Object as PropType<FlexRenderCell>,
64
79
  default: undefined,
65
80
  },
66
81
  header: {
67
- type: Object as PropType<Header<any, any, any>>,
82
+ type: Object as PropType<FlexRenderHeader>,
68
83
  default: undefined,
69
84
  },
70
85
  footer: {
71
- type: Object as PropType<Header<any, any, any>>,
86
+ type: Object as PropType<FlexRenderHeader>,
72
87
  default: undefined,
73
88
  },
74
89
  },
75
90
  setup: (props: {
76
91
  render?: any
77
92
  props?: any
78
- cell?: Cell<any, any, any>
79
- header?: Header<any, any, any>
80
- footer?: Header<any, any, any>
93
+ cell?: FlexRenderCell
94
+ header?: FlexRenderHeader
95
+ footer?: FlexRenderHeader
81
96
  }) => {
82
97
  return () => {
83
98
  // New shorthand pattern: extract render and props from cell/header/footer
@@ -1,10 +1,10 @@
1
1
  import { createColumnHelper as coreCreateColumnHelper } from '@tanstack/table-core'
2
- import { useSelector } from '@tanstack/vue-store'
3
2
  import { defineComponent, h, inject, provide } from 'vue'
4
3
  import { FlexRender } from './FlexRender'
5
4
  import { mergeProxy } from './merge-proxy'
6
5
  import { useTable } from './useTable'
7
6
  import type { TableOptionsWithReactiveData, VueTable } from './useTable'
7
+ import type { FlexRenderCell, FlexRenderHeader } from './FlexRender'
8
8
  import type { Component, InjectionKey, PropType, VNodeChild } from 'vue'
9
9
  import type {
10
10
  AccessorFn,
@@ -192,31 +192,22 @@ export type CreateTableHookOptions<
192
192
  headerComponents?: THeaderComponents
193
193
  }
194
194
 
195
- export interface AppTableProps<
196
- TFeatures extends TableFeatures,
197
- TSelected = unknown,
198
- > {
199
- selector?: (state: TableState<TFeatures>) => TSelected
200
- }
195
+ export interface AppTableProps {}
201
196
 
202
197
  export interface AppCellProps<
203
198
  TFeatures extends TableFeatures,
204
199
  TData extends RowData,
205
200
  TValue extends CellData = CellData,
206
- TSelected = unknown,
207
201
  > {
208
202
  cell: Cell<TFeatures, TData, TValue>
209
- selector?: (state: TableState<TFeatures>) => TSelected
210
203
  }
211
204
 
212
205
  export interface AppHeaderProps<
213
206
  TFeatures extends TableFeatures,
214
207
  TData extends RowData,
215
208
  TValue extends CellData = CellData,
216
- TSelected = unknown,
217
209
  > {
218
210
  header: Header<TFeatures, TData, TValue>
219
- selector?: (state: TableState<TFeatures>) => TSelected
220
211
  }
221
212
 
222
213
  export type AppVueTable<
@@ -226,9 +217,9 @@ export type AppVueTable<
226
217
  TTableComponents extends Record<string, ComponentType<any>>,
227
218
  TCellComponents extends Record<string, ComponentType<any>>,
228
219
  THeaderComponents extends Record<string, ComponentType<any>>,
229
- > = VueTable<TFeatures, TData, TSelected> &
220
+ > = VueTable<TFeatures, TData> &
230
221
  NoInfer<TTableComponents> & {
231
- AppTable: Component<AppTableProps<TFeatures>>
222
+ AppTable: Component<AppTableProps>
232
223
  AppCell: Component<AppCellProps<TFeatures, TData>>
233
224
  AppHeader: Component<AppHeaderProps<TFeatures, TData>>
234
225
  AppFooter: Component<AppHeaderProps<TFeatures, TData>>
@@ -239,15 +230,15 @@ export const AppFlexRender = defineComponent({
239
230
  name: 'TableFlexRender',
240
231
  props: {
241
232
  cell: {
242
- type: Object as PropType<Cell<any, any, any>>,
233
+ type: Object as PropType<FlexRenderCell>,
243
234
  default: undefined,
244
235
  },
245
236
  header: {
246
- type: Object as PropType<Header<any, any, any>>,
237
+ type: Object as PropType<FlexRenderHeader>,
247
238
  default: undefined,
248
239
  },
249
240
  footer: {
250
- type: Object as PropType<Header<any, any, any>>,
241
+ type: Object as PropType<FlexRenderHeader>,
251
242
  default: undefined,
252
243
  },
253
244
  },
@@ -314,7 +305,7 @@ export function createTableHook<
314
305
  THeaderComponents
315
306
  >) {
316
307
  const TableContext = Symbol('TableContext') as InjectionKey<
317
- VueTable<TFeatures, any, any>
308
+ VueTable<TFeatures, any>
318
309
  >
319
310
  const CellContext = Symbol('CellContext') as InjectionKey<
320
311
  Cell<TFeatures, any, any>
@@ -410,19 +401,15 @@ export function createTableHook<
410
401
  },
411
402
  })
412
403
 
413
- function useAppTable<
414
- TData extends RowData,
415
- TSelected = TableState<TFeatures>,
416
- >(
404
+ function useAppTable<TData extends RowData>(
417
405
  tableOptions: Omit<
418
406
  TableOptionsWithReactiveData<TFeatures, TData>,
419
407
  'features' | 'rowModels'
420
408
  >,
421
- selector?: (state: TableState<TFeatures>) => TSelected,
422
409
  ): AppVueTable<
423
410
  TFeatures,
424
411
  TData,
425
- TSelected,
412
+ TableState<TFeatures>,
426
413
  TTableComponents,
427
414
  TCellComponents,
428
415
  THeaderComponents
@@ -432,28 +419,14 @@ export function createTableHook<
432
419
  tableOptions,
433
420
  ) as TableOptionsWithReactiveData<TFeatures, TData>
434
421
 
435
- const table = useTable<TFeatures, TData, TSelected>(mergedOptions, selector)
422
+ const table = useTable<TFeatures, TData>(mergedOptions)
436
423
 
437
424
  const AppTable = defineComponent({
438
425
  name: 'AppTable',
439
- props: {
440
- selector: {
441
- type: Function as PropType<(state: TableState<TFeatures>) => unknown>,
442
- default: undefined,
443
- },
444
- },
445
- setup(props, { slots }) {
426
+ setup(_, { slots }) {
446
427
  provide(TableContext, table)
447
- const selected = props.selector
448
- ? useSelector(table.store, props.selector)
449
- : undefined
450
-
451
428
  return () => {
452
- if (!props.selector) {
453
- return slots.default?.()
454
- }
455
-
456
- return slots.default?.({ state: selected?.value })
429
+ return slots.default?.()
457
430
  }
458
431
  },
459
432
  })
@@ -465,20 +438,12 @@ export function createTableHook<
465
438
  type: Object as PropType<object>,
466
439
  required: true,
467
440
  },
468
- selector: {
469
- type: Function as PropType<(state: TableState<TFeatures>) => unknown>,
470
- default: undefined,
471
- },
472
441
  },
473
442
  setup(props, { slots }) {
474
443
  const cell = props.cell as Cell<TFeatures, TData, any>
475
444
 
476
445
  provide(CellContext, cell)
477
446
 
478
- const selected = props.selector
479
- ? useSelector(table.store, props.selector)
480
- : undefined
481
-
482
447
  const extendedCell = Object.assign(cell, {
483
448
  FlexRender: CellFlexRender,
484
449
  ...(cellComponents ?? {}),
@@ -486,11 +451,7 @@ export function createTableHook<
486
451
  TCellComponents & { FlexRender: Component }
487
452
 
488
453
  return () => {
489
- return slots.default?.(
490
- props.selector
491
- ? { cell: extendedCell, state: selected?.value }
492
- : { cell: extendedCell },
493
- )
454
+ return slots.default?.({ cell: extendedCell })
494
455
  }
495
456
  },
496
457
  })
@@ -502,20 +463,12 @@ export function createTableHook<
502
463
  type: Object as PropType<object>,
503
464
  required: true,
504
465
  },
505
- selector: {
506
- type: Function as PropType<(state: TableState<TFeatures>) => unknown>,
507
- default: undefined,
508
- },
509
466
  },
510
467
  setup(props, { slots }) {
511
468
  const header = props.header as Header<TFeatures, TData, any>
512
469
 
513
470
  provide(HeaderContext, header)
514
471
 
515
- const selected = props.selector
516
- ? useSelector(table.store, props.selector)
517
- : undefined
518
-
519
472
  const extendedHeader = Object.assign(header, {
520
473
  FlexRender: HeaderFlexRender,
521
474
  ...(headerComponents ?? {}),
@@ -523,11 +476,7 @@ export function createTableHook<
523
476
  THeaderComponents & { FlexRender: Component }
524
477
 
525
478
  return () => {
526
- return slots.default?.(
527
- props.selector
528
- ? { header: extendedHeader, state: selected?.value }
529
- : { header: extendedHeader },
530
- )
479
+ return slots.default?.({ header: extendedHeader })
531
480
  }
532
481
  },
533
482
  })
@@ -539,20 +488,12 @@ export function createTableHook<
539
488
  type: Object as PropType<object>,
540
489
  required: true,
541
490
  },
542
- selector: {
543
- type: Function as PropType<(state: TableState<TFeatures>) => unknown>,
544
- default: undefined,
545
- },
546
491
  },
547
492
  setup(props, { slots }) {
548
493
  const header = props.header as Header<TFeatures, TData, any>
549
494
 
550
495
  provide(HeaderContext, header)
551
496
 
552
- const selected = props.selector
553
- ? useSelector(table.store, props.selector)
554
- : undefined
555
-
556
497
  const extendedHeader = Object.assign(header, {
557
498
  FlexRender: FooterFlexRender,
558
499
  ...(headerComponents ?? {}),
@@ -560,11 +501,7 @@ export function createTableHook<
560
501
  THeaderComponents & { FlexRender: Component }
561
502
 
562
503
  return () => {
563
- return slots.default?.(
564
- props.selector
565
- ? { header: extendedHeader, state: selected?.value }
566
- : { header: extendedHeader },
567
- )
504
+ return slots.default?.({ header: extendedHeader })
568
505
  }
569
506
  },
570
507
  })
@@ -579,7 +516,7 @@ export function createTableHook<
579
516
  }) as AppVueTable<
580
517
  TFeatures,
581
518
  TData,
582
- TSelected,
519
+ TableState<TFeatures>,
583
520
  TTableComponents,
584
521
  TCellComponents,
585
522
  THeaderComponents