Files
kandev/apps/web/components/ui/data-table.tsx
T
2026-02-19 22:18:01 +00:00

110 lines
3.3 KiB
TypeScript

"use client";
import {
type ColumnDef,
type PaginationState,
flexRender,
getCoreRowModel,
useReactTable,
} from "@tanstack/react-table";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@kandev/ui/table";
import { DataTablePagination } from "./data-table-pagination";
interface DataTableProps<TData, TValue> {
columns: ColumnDef<TData, TValue>[];
data: TData[];
pageCount?: number;
pagination?: PaginationState;
onPaginationChange?: (pagination: PaginationState) => void;
isLoading?: boolean;
onRowClick?: (row: TData) => void;
}
export function DataTable<TData, TValue>({
columns,
data,
pageCount = -1,
pagination,
onPaginationChange,
isLoading = false,
onRowClick,
}: DataTableProps<TData, TValue>) {
// eslint-disable-next-line react-hooks/incompatible-library -- TanStack Table's API is designed this way
const table = useReactTable({
data,
columns,
pageCount,
state: {
pagination,
},
onPaginationChange: onPaginationChange
? (updater) => {
const newPagination = typeof updater === "function" ? updater(pagination!) : updater;
onPaginationChange(newPagination);
}
: undefined,
getCoreRowModel: getCoreRowModel(),
manualPagination: true,
});
return (
<div className="space-y-4">
<div className="rounded-md border">
<Table>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableHead key={header.id}>
{header.isPlaceholder
? null
: flexRender(header.column.columnDef.header, header.getContext())}
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{(() => {
if (isLoading) {
return (
<TableRow>
<TableCell colSpan={columns.length} className="h-24 text-center">
Loading...
</TableCell>
</TableRow>
);
}
if (table.getRowModel().rows?.length) {
return table.getRowModel().rows.map((row) => (
<TableRow
key={row.id}
data-state={row.getIsSelected() && "selected"}
className={onRowClick ? "cursor-pointer hover:bg-muted/50" : undefined}
onClick={() => onRowClick?.(row.original)}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
));
}
return (
<TableRow>
<TableCell colSpan={columns.length} className="h-24 text-center">
No results.
</TableCell>
</TableRow>
);
})()}
</TableBody>
</Table>
</div>
{pagination && onPaginationChange && <DataTablePagination table={table} />}
</div>
);
}