UNPKG

@tanstack/vue-table

Version:

Headless UI for building powerful tables & datagrids for Vue.

179 lines (177 loc) 4.85 kB
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 };