@tanstack/vue-table
Version:
Headless UI for building powerful tables & datagrids for Vue.
72 lines (70 loc) • 2.55 kB
JavaScript
import { flatMerge, mergeProxy } from "./merge-proxy.js";
import { vueReactivity } from "./reactivity.js";
import { getCurrentScope, onScopeDispose, unref, watch } from "vue";
import { constructTable } from "@tanstack/table-core";
//#region src/useTable.ts
function getOptionsWithReactiveValues(options) {
const resolvedOptions = {};
for (const key of Object.keys(options)) resolvedOptions[key] = unref(options[key]);
return mergeProxy(options, resolvedOptions);
}
function getReactiveOptionDeps(options) {
return Object.keys(options).map((key) => unref(options[key]));
}
/**
* Creates a Vue table instance backed by Vue-aware TanStack Store atoms.
*
* Table options may contain Vue refs or computed values. The adapter unwraps
* those reactive inputs, watches them with synchronous flushing, and keeps the
* table options in sync. Use `table.Subscribe` or native Vue computed values
* around `table.atoms.<slice>.get()` for selected reactive reads.
*
* @example
* ```ts
* const table = useTable(
* {
* features,
* columns,
* data,
* },
* )
* ```
*/
function useTable(tableOptions) {
const syncTableOptions = (table, options) => {
table.setOptions((prev) => flatMerge(prev, getOptionsWithReactiveValues(options)));
};
const reactivity = vueReactivity();
const mergedOptions = mergeProxy(tableOptions, { features: {
coreReactivityFeature: reactivity,
...unref(tableOptions.features) ?? {}
} });
const resolvedOptions = mergeProxy(getOptionsWithReactiveValues(mergedOptions), { mergeOptions: (defaultOptions, newOptions) => {
return flatMerge(defaultOptions, newOptions);
} });
const coreTable = constructTable(resolvedOptions);
const table = coreTable;
if (getCurrentScope()) onScopeDispose(() => reactivity.unmount?.());
watch(() => getReactiveOptionDeps(mergedOptions), () => {
syncTableOptions(coreTable, mergedOptions);
}, { immediate: true });
watch(() => {
const controlledState = unref(tableOptions.state);
const controlledAtoms = unref(tableOptions.atoms);
if (!controlledState) return [];
const controlledValues = [];
for (const key of Object.keys(table.initialState)) {
if (!(key in controlledState) || controlledAtoms?.[key] !== void 0) continue;
controlledValues.push(controlledState[key]);
}
return controlledValues;
}, (controlledValues) => {
if (controlledValues.length > 0) syncTableOptions(coreTable, mergedOptions);
}, { immediate: true });
table.Subscribe = (props) => {
return props.children(table.atoms);
};
return table;
}
//#endregion
export { useTable };