@tanstack/vue-table
Version:
Headless UI for building powerful tables & datagrids for Vue.
179 lines (177 loc) • 4.85 kB
JavaScript
import { FlexRender } from "./FlexRender.js";
import { mergeProxy } from "./merge-proxy.js";
import { useTable } from "./useTable.js";
import { defineComponent, h, inject, provide } from "vue";
import { createColumnHelper } from "@tanstack/table-core";
//#region src/createTableHook.ts
const AppFlexRender = defineComponent({
name: "TableFlexRender",
props: {
cell: {
type: Object,
default: void 0
},
header: {
type: Object,
default: void 0
},
footer: {
type: Object,
default: void 0
}
},
setup(props) {
return () => {
if (props.cell) return h(FlexRender, { cell: props.cell });
if (props.header) return h(FlexRender, { header: props.header });
if (props.footer) return h(FlexRender, { footer: props.footer });
return null;
};
}
});
/**
* Creates app-scoped Vue table helpers with features, row models, and
* renderable component maps pre-bound.
*
* Use this when an app or design system wants typed `useAppTable`, a pre-bound
* column helper, and context helpers for table, cell, and header components.
*
* @example
* ```ts
* const { useAppTable, createAppColumnHelper } = createTableHook({
* features,
* tableComponents: {},
* cellComponents: {},
* headerComponents: {},
* })
* ```
*/
function createTableHook({ tableComponents, cellComponents, headerComponents, ...defaultTableOptions }) {
const TableContext = Symbol("TableContext");
const CellContext = Symbol("CellContext");
const HeaderContext = Symbol("HeaderContext");
function createAppColumnHelper() {
return createColumnHelper();
}
function useTableContext() {
const table = inject(TableContext);
if (!table) throw new Error("`useTableContext` must be used within an `AppTable` component. Make sure your component is wrapped with `<table.AppTable>...</table.AppTable>`.");
return table;
}
function useCellContext() {
const cell = inject(CellContext);
if (!cell) throw new Error("`useCellContext` must be used within an `AppCell` component. Make sure your component is wrapped with `<table.AppCell :cell=\"cell\">...</table.AppCell>`.");
return cell;
}
function useHeaderContext() {
const header = inject(HeaderContext);
if (!header) throw new Error("`useHeaderContext` must be used within an `AppHeader` or `AppFooter` component.");
return header;
}
const CellFlexRender = defineComponent({
name: "AppCellFlexRender",
setup() {
const cell = useCellContext();
return () => h(AppFlexRender, { cell });
}
});
const HeaderFlexRender = defineComponent({
name: "AppHeaderFlexRender",
setup() {
const header = useHeaderContext();
return () => h(AppFlexRender, { header });
}
});
const FooterFlexRender = defineComponent({
name: "AppFooterFlexRender",
setup() {
const header = useHeaderContext();
return () => h(AppFlexRender, { footer: header });
}
});
function useAppTable(tableOptions) {
const mergedOptions = mergeProxy(defaultTableOptions, tableOptions);
const table = useTable(mergedOptions);
const AppTable = defineComponent({
name: "AppTable",
setup(_, { slots }) {
provide(TableContext, table);
return () => {
return slots.default?.();
};
}
});
const AppCell = defineComponent({
name: "AppCell",
props: { cell: {
type: Object,
required: true
} },
setup(props, { slots }) {
const cell = props.cell;
provide(CellContext, cell);
const extendedCell = Object.assign(cell, {
FlexRender: CellFlexRender,
...cellComponents ?? {}
});
return () => {
return slots.default?.({ cell: extendedCell });
};
}
});
const AppHeader = defineComponent({
name: "AppHeader",
props: { header: {
type: Object,
required: true
} },
setup(props, { slots }) {
const header = props.header;
provide(HeaderContext, header);
const extendedHeader = Object.assign(header, {
FlexRender: HeaderFlexRender,
...headerComponents ?? {}
});
return () => {
return slots.default?.({ header: extendedHeader });
};
}
});
const AppFooter = defineComponent({
name: "AppFooter",
props: { header: {
type: Object,
required: true
} },
setup(props, { slots }) {
const header = props.header;
provide(HeaderContext, header);
const extendedHeader = Object.assign(header, {
FlexRender: FooterFlexRender,
...headerComponents ?? {}
});
return () => {
return slots.default?.({ header: extendedHeader });
};
}
});
return Object.assign(table, {
AppTable,
AppCell,
AppHeader,
AppFooter,
FlexRender: AppFlexRender,
...tableComponents ?? {}
});
}
return {
appFeatures: defaultTableOptions.features,
createAppColumnHelper,
useAppTable,
useTableContext,
useCellContext,
useHeaderContext
};
}
//#endregion
export { AppFlexRender, createTableHook };