diff --git a/examples/basic/package.json b/examples/basic/package.json index 5c8dc6b..3963e83 100644 --- a/examples/basic/package.json +++ b/examples/basic/package.json @@ -9,6 +9,7 @@ "preview": "vite preview" }, "dependencies": { + "@tanstack/vue-query": "^5.74.0", "@tanstack/vue-table": "^8.21.2", "class-variance-authority": "^0.7.1", "clsx": "^2.1.1", diff --git a/examples/basic/src/App.vue b/examples/basic/src/App.vue index bc7e4e8..6acb790 100644 --- a/examples/basic/src/App.vue +++ b/examples/basic/src/App.vue @@ -2,6 +2,7 @@ import { TSTable } from 'tanstack-table-vue' import { createColumnHelper, FlexRender, getCoreRowModel, getSortedRowModel, type Column } from '@tanstack/vue-table' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from './components/ui/table' +import { useQuery } from '@tanstack/vue-query' interface Person { @@ -40,6 +41,14 @@ const defaultData: Person[] = [ }, ] +const { data, isLoading } = useQuery({ + queryKey: ['people'], + queryFn: async () => { + await new Promise(resolve => setTimeout(resolve, 2000)) + return defaultData + }, +}) + function getSortIcon(column: Column) { if (!column.getCanSort?.()) return null @@ -66,20 +75,19 @@ function getStatusClass(status: string) { const columnHelper = createColumnHelper() +// Create columns with type assertion const columns = [ - columnHelper.group({ - id: 'name', - header: 'Name', - columns: [ - columnHelper.accessor('firstName', {}), - columnHelper.accessor('lastName', {}), - ], + columnHelper.display({ + id: 'avatar', + header: 'Avatar', }), + columnHelper.accessor('firstName', {}), + columnHelper.accessor('lastName', {}), + columnHelper.accessor('age', {}), columnHelper.group({ id: 'info', header: 'Info', columns: [ - columnHelper.accessor('age', {}), columnHelper.group({ id: 'moreInfo', header: 'More Info', @@ -91,6 +99,10 @@ const columns = [ }), ], }), + columnHelper.display({ + id: 'actions', + header: 'Actions', + }) ] const tableOptions = { @@ -136,11 +148,21 @@ const tableOptions = { - - - + + +
+ + + No results. +
diff --git a/examples/basic/src/main.ts b/examples/basic/src/main.ts index 2425c0f..ac18c60 100644 --- a/examples/basic/src/main.ts +++ b/examples/basic/src/main.ts @@ -1,5 +1,7 @@ +import { VueQueryPlugin } from '@tanstack/vue-query' + import { createApp } from 'vue' import './style.css' import App from './App.vue' -createApp(App).mount('#app') +createApp(App).use(VueQueryPlugin).mount('#app') diff --git a/packages/core/src/components/TSTable.vue b/packages/core/src/components/TSTable.vue index 13ab302..c69df8c 100644 --- a/packages/core/src/components/TSTable.vue +++ b/packages/core/src/components/TSTable.vue @@ -3,7 +3,7 @@ import type { ColumnDef, RowData, Table } from '@tanstack/vue-table' import type { CellSlotProps, FooterSlotProps, HeaderSlotProps } from '../shared/types' export interface TSTableProps { - columns: ColumnDef[] + columns: ColumnDef[] data: TData[] tableOptions?: Record } @@ -21,7 +21,7 @@ const columnHelper = createColumnHelper() const processedColumns = computed(() => { const initialTable = useVueTable({ - columns: props.columns as unknown as TStackColumnDef[], + columns: props.columns as TStackColumnDef[], data: props.data, getCoreRowModel: getCoreRowModel(), ...props.tableOptions diff --git a/packages/core/src/shared/types.ts b/packages/core/src/shared/types.ts index d7a0005..a3e4374 100644 --- a/packages/core/src/shared/types.ts +++ b/packages/core/src/shared/types.ts @@ -1,17 +1,17 @@ import type { CellContext, Column, HeaderContext, Row, RowData } from '@tanstack/vue-table' export interface HeaderSlotProps { - column: Column - context: HeaderContext + column: Column + context: HeaderContext } export interface CellSlotProps { row: Row - context: CellContext + context: CellContext value: any } export interface FooterSlotProps { - column: Column - context: HeaderContext + column: Column + context: HeaderContext } diff --git a/packages/core/src/shared/utils.ts b/packages/core/src/shared/utils.ts index 53f712d..4879b17 100644 --- a/packages/core/src/shared/utils.ts +++ b/packages/core/src/shared/utils.ts @@ -11,9 +11,9 @@ import type { Slots } from 'vue' import capitalize from 'lodash.capitalize' const getHeader = ( - col: ColumnDef, + col: ColumnDef, slots: Readonly, - context: HeaderContext, + context: HeaderContext, ) => { const columnId = (col as any).accessorKey || col.id || '' const slotName = `header-${columnId}` @@ -36,9 +36,9 @@ const getHeader = ( } const getFooter = ( - col: ColumnDef, + col: ColumnDef, slots: Readonly, - context: HeaderContext, + context: HeaderContext, ) => { const columnId = (col as any).accessorKey || col.id || '' const slotName = `footer-${columnId}` @@ -60,9 +60,9 @@ const getFooter = ( } const getCell = ( - col: ColumnDef, + col: ColumnDef, slots: Readonly, - context: CellContext, + context: CellContext, ) => { const columnId = (col as any).accessorKey || col.id || '' const slotName = `cell-${columnId}` @@ -86,18 +86,18 @@ const getCell = ( export const processColumns = ( columnHelper: ColumnHelper, - columns: ColumnDef[], + columns: ColumnDef[], slots: Readonly, table: Table, -): TStackColumnDef[] => { - return columns.map((col): TStackColumnDef => { +): TStackColumnDef[] => { + return columns.map((col): TStackColumnDef => { // Handle group columns by checking if columns property exists if ('columns' in col && Array.isArray(col.columns)) { return columnHelper.group({ id: col.id || String(Math.random()), - header: (context: HeaderContext) => getHeader(col, slots, context), - footer: col.footer ? (context: HeaderContext) => getFooter(col, slots, context) : undefined, - columns: processColumns(columnHelper, col.columns, slots, table), + header: (context: HeaderContext) => getHeader(col, slots, context), + footer: col.footer ? (context: HeaderContext) => getFooter(col, slots, context) : undefined, + columns: processColumns(columnHelper, col.columns as ColumnDef[], slots, table), meta: col.meta, }) } @@ -107,9 +107,9 @@ export const processColumns = ( if (accessorCol.accessorKey) { return columnHelper.accessor(accessorCol.accessorKey, { id: accessorCol.id || accessorCol.accessorKey, - header: (context: HeaderContext) => getHeader(col, slots, context), - footer: col.footer ? (context: HeaderContext) => getFooter(col, slots, context) : undefined, - cell: (context: CellContext) => getCell(col, slots, context), + header: (context: HeaderContext) => getHeader(col, slots, context), + footer: col.footer ? (context: HeaderContext) => getFooter(col, slots, context) : undefined, + cell: (context: CellContext) => getCell(col, slots, context), meta: col.meta, }) } @@ -117,9 +117,9 @@ export const processColumns = ( if (accessorCol.accessorFn) { return columnHelper.accessor(accessorCol.accessorFn, { id: accessorCol.id || String(Math.random()), - header: (context: HeaderContext) => getHeader(col, slots, context), - footer: col.footer ? (context: HeaderContext) => getFooter(col, slots, context) : undefined, - cell: (context: CellContext) => getCell(col, slots, context), + header: (context: HeaderContext) => getHeader(col, slots, context), + footer: col.footer ? (context: HeaderContext) => getFooter(col, slots, context) : undefined, + cell: (context: CellContext) => getCell(col, slots, context), meta: col.meta, }) } @@ -127,9 +127,9 @@ export const processColumns = ( // Default case - treat as display column return columnHelper.display({ id: col.id || String(Math.random()), - header: (context: HeaderContext) => getHeader(col, slots, context), - footer: col.footer ? (context: HeaderContext) => getFooter(col, slots, context) : undefined, - cell: (context: CellContext) => getCell(col, slots, context), + header: (context: HeaderContext) => getHeader(col, slots, context), + footer: col.footer ? (context: HeaderContext) => getFooter(col, slots, context) : undefined, + cell: (context: CellContext) => getCell(col, slots, context), meta: col.meta, }) }) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e86e61b..8320e98 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: examples/basic: dependencies: + '@tanstack/vue-query': + specifier: ^5.74.0 + version: 5.74.0(vue@3.5.13(typescript@5.7.3)) '@tanstack/vue-table': specifier: ^8.21.2 version: 8.21.2(vue@3.5.13(typescript@5.7.3)) @@ -495,10 +498,26 @@ packages: peerDependencies: vite: ^5.2.0 || ^6 + '@tanstack/match-sorter-utils@8.19.4': + resolution: {integrity: sha512-Wo1iKt2b9OT7d+YGhvEPD3DXvPv2etTusIMhMUoG7fbhmxcXCtIjJDEygy91Y2JFlwGyjqiBPRozme7UD8hoqg==} + engines: {node: '>=12'} + + '@tanstack/query-core@5.74.0': + resolution: {integrity: sha512-kMqBfXA06INskI06rm+abAY3/Vi/Kq1nRNfLbpwuhuMJ5lMAI5qASretlvjEO5OJoze6w7OB3pNvsbztirIWWQ==} + '@tanstack/table-core@8.21.2': resolution: {integrity: sha512-uvXk/U4cBiFMxt+p9/G7yUWI/UbHYbyghLCjlpWZ3mLeIZiUBSKcUnw9UnKkdRz7Z/N4UBuFLWQdJCjUe7HjvA==} engines: {node: '>=12'} + '@tanstack/vue-query@5.74.0': + resolution: {integrity: sha512-YP6muhx9R9O5jPu3HV1b5fMLf/X+8PJmv1X1iOTdrBr394RVhMxWzTsyTwdrDLs1ydJBfOnop7ZFFCex5LlozA==} + peerDependencies: + '@vue/composition-api': ^1.1.2 + vue: ^2.6.0 || ^3.3.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + '@tanstack/vue-table@8.21.2': resolution: {integrity: sha512-KBgOWxha/x4m1EdhVWxOpqHb661UjqAxzPcmXR3QiA7aShZ547x19Gw0UJX9we+m+tVcPuLRZ61JsYW47QZFfQ==} engines: {node: '>=12'} @@ -551,6 +570,9 @@ packages: '@vue/compiler-vue2@2.7.16': resolution: {integrity: sha512-qYC3Psj9S/mfu9uVi5WvNZIzq+xnXMhOwbTFKKDD7b1lhpnn71jXSFdTQ+WsIEk0ONCd7VV2IMm7ONl6tbQ86A==} + '@vue/devtools-api@6.6.4': + resolution: {integrity: sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==} + '@vue/language-core@2.2.0': resolution: {integrity: sha512-O1ZZFaaBGkKbsRfnVH1ifOK1/1BUkyK+3SQsfnh6PmMmD4qJcTU8godCeA96jjDRTL6zgnK7YzCHfaUlH2r0Mw==} peerDependencies: @@ -979,6 +1001,9 @@ packages: resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} engines: {node: '>= 14.18.0'} + remove-accents@0.5.0: + resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} + require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} @@ -1125,6 +1150,17 @@ packages: vscode-uri@3.1.0: resolution: {integrity: sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==} + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true + vue-tsc@2.2.8: resolution: {integrity: sha512-jBYKBNFADTN+L+MdesNX/TB3XuDSyaWynKMDgR+yCSln0GQ9Tfb7JS2lr46s2LiFUT1WsmfWsSvIElyxzOPqcQ==} hasBin: true @@ -1437,8 +1473,22 @@ snapshots: tailwindcss: 4.1.3 vite: 6.2.5(@types/node@22.14.0)(jiti@2.4.2)(lightningcss@1.29.2)(yaml@2.7.1) + '@tanstack/match-sorter-utils@8.19.4': + dependencies: + remove-accents: 0.5.0 + + '@tanstack/query-core@5.74.0': {} + '@tanstack/table-core@8.21.2': {} + '@tanstack/vue-query@5.74.0(vue@3.5.13(typescript@5.7.3))': + dependencies: + '@tanstack/match-sorter-utils': 8.19.4 + '@tanstack/query-core': 5.74.0 + '@vue/devtools-api': 6.6.4 + vue: 3.5.13(typescript@5.7.3) + vue-demi: 0.14.10(vue@3.5.13(typescript@5.7.3)) + '@tanstack/vue-table@8.21.2(vue@3.5.13(typescript@5.7.3))': dependencies: '@tanstack/table-core': 8.21.2 @@ -1510,6 +1560,8 @@ snapshots: de-indent: 1.0.2 he: 1.2.0 + '@vue/devtools-api@6.6.4': {} + '@vue/language-core@2.2.0(typescript@5.7.3)': dependencies: '@volar/language-core': 2.4.12 @@ -1927,6 +1979,8 @@ snapshots: readdirp@4.1.2: {} + remove-accents@0.5.0: {} + require-from-string@2.0.2: {} resolve@1.22.10: @@ -2045,6 +2099,10 @@ snapshots: vscode-uri@3.1.0: {} + vue-demi@0.14.10(vue@3.5.13(typescript@5.7.3)): + dependencies: + vue: 3.5.13(typescript@5.7.3) + vue-tsc@2.2.8(typescript@5.7.3): dependencies: '@volar/typescript': 2.4.12