"use client" import { ScrollArea } from "@/components/ui/scroll-area" import { TableCell, TableHead, TableRow } from "@/components/ui/table" import { useMediaQuery } from "@/hooks/useMediaQuery" import { cn } from "@/lib/utils" import { ColumnDef, Row, SortDirection, SortingState, flexRender, getCoreRowModel, getSortedRowModel, useReactTable, } from "@tanstack/react-table" import { HTMLAttributes, forwardRef, useEffect, useRef, useState } from "react" import { TableVirtuoso } from "react-virtuoso" // Original Table is wrapped with a
(see https://ui.shadcn.com/docs/components/table#radix-:r24:-content-manual), // but here we don't want it, so let's use a new component with only tag const TableComponent = forwardRef>( ({ className, ...props }, ref) => (
), ) TableComponent.displayName = "TableComponent" const TableRowComponent = (rows: Row[]) => function getTableRow(props: HTMLAttributes) { // @ts-expect-error data-index is a valid attribute const index = props["data-index"] const row = rows[index] if (!row) return null return ( {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} ) } function SortingIndicator({ isSorted }: { isSorted: SortDirection | false }) { if (!isSorted) return null return (
{ { asc: "↑", desc: "↓", }[isSorted] }
) } interface DataTableProps { columns: ColumnDef[] data: TData[] rowComponent?: ( rows: Row[], ) => (props: HTMLAttributes) => JSX.Element | null } export function DataTable({ columns, data, rowComponent, }: DataTableProps) { const [sorting, setSorting] = useState([ { id: "type", desc: true, }, ]) const table = useReactTable({ data, columns, state: { sorting, }, onSortingChange: setSorting, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), }) const { rows } = table.getRowModel() const [heightState, setHeight] = useState(0) const ref = useRef(null) const isDesktop = useMediaQuery("(min-width: 640px)") useEffect(() => { const calculateHeight = () => { if (ref.current) { const virtuosoElement = ref.current let topOffset = 0 let currentElement = virtuosoElement as any // Calculate the total offset from the top of the document while (currentElement) { topOffset += currentElement.offsetTop || 0 currentElement = currentElement.offsetParent as HTMLElement } const totalHeight = window.innerHeight const calculatedHeight = totalHeight - topOffset setHeight(calculatedHeight) } } calculateHeight() // Initial calculation if (isDesktop) { window.addEventListener("resize", calculateHeight) } return () => { if (isDesktop) window.removeEventListener("resize", calculateHeight) } }, [isDesktop]) return (
table.getHeaderGroups().map((headerGroup) => ( // Change header background color to non-transparent {headerGroup.headers.map((header) => { return ( {header.isPlaceholder ? null : (
{flexRender( header.column.columnDef.header, header.getContext(), )}
)}
) })}
)) } />
) }