Files
jh-monitor/src/components/data-table.tsx

94 lines
3.0 KiB
TypeScript

'use client'
import * as React from 'react'
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from './ui/table'
import { ReactNode, useState } from 'react'
import { ArrowUpDownIcon, ArrowUpIcon, ArrowDownIcon } from 'lucide-react'
import { ColumnDef, flexRender, getCoreRowModel, getSortedRowModel, useReactTable } from '@tanstack/react-table'
import { cn } from '@/lib/utils'
type Data = Record<string, unknown>
type Column = {
label: string
props?: string
render?: (val: Data) => ReactNode
sortable?: boolean
}
export function DataTable<T extends Data>(props: {
data: T[]
columns: Column[]
pinFirst?: boolean
}) {
const table = useReactTable({
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
data: props.data,
columns: props.columns.map(col => ({
meta: col,
header: col.label,
accessorKey: col.props,
cell: info => col.render?.(info.row.original) || String(info.getValue()),
enableSorting: col.sortable,
})) as ColumnDef<T>[],
})
return (
<Table>
<TableHeader>
{/* 表头行 */}
{table.getHeaderGroups().map(group => (
<TableRow key={group.id}>
{/* 表头 */}
{group.headers.map((header, index) => (
<TableHead
key={header.id}
className={cn(
header.column.columnDef.enableSorting && 'hover:bg-gray-200 transition-colors duration-150 ease-in-out cursor-pointer',
header.column.getIsSorted() && 'text-primary',
props.pinFirst && index === 0 && 'sticky left-0 bg-gray-50 border-r',
)}
onClick={header.column.getToggleSortingHandler()}>
<div className="flex flex-row items-center justify-between">
{flexRender(header.column.columnDef.header, header.getContext())}
{header.column.columnDef.enableSorting && (
header.column.getIsSorted() == 'asc' ? (
<ArrowUpIcon className="size-4" />
) : header.column.getIsSorted() == 'desc' ? (
<ArrowDownIcon className="size-4" />
) : (
<ArrowUpDownIcon className="size-4" />
)
)}
</div>
</TableHead>
))}
</TableRow>
))}
</TableHeader>
<TableBody>
{/* 表格行 */}
{table.getRowModel().rows.map(row => (
<TableRow key={row.id}>
{/* 表格 */}
{row.getVisibleCells().map((cell, index) => (
<TableCell
key={cell.id}
className={cn(
props.pinFirst && index === 0 && 'sticky left-0 bg-white border-r',
)}>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
))}
</TableBody>
</Table>
)
}