import { createColumnHelper, FilterFn, flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, } from "@tanstack/react-table"; import { ArrowDownIcon, ArrowUpIcon, ChevronDoubleLeftIcon, ChevronDoubleRightIcon, ChevronLeftIcon, ChevronRightIcon, } from "@heroicons/react/24/solid"; import React, { useEffect, useMemo, useState } from "react"; import parseCsv from "../lib/parseCsv"; import DebouncedInput from "./DebouncedInput"; import loadUrlProxied from "../lib/loadUrlProxied"; const Table = ({ data: ogData = [], cols: ogCols = [], csv = "", url = "", fullWidth = false, }) => { if (csv) { const out = parseCsv(csv); ogData = out.rows; ogCols = out.fields; } const [data, setData] = React.useState(ogData); const [cols, setCols] = React.useState(ogCols); const [error, setError] = React.useState(""); // TODO: add error handling const tableCols = useMemo(() => { const columnHelper = createColumnHelper(); return cols.map((c) => columnHelper.accessor(c.key, { header: () => c.name, cell: (info) => info.getValue(), }) ); }, [data, cols]); const [globalFilter, setGlobalFilter] = useState(""); const table = useReactTable({ data, columns: tableCols, getCoreRowModel: getCoreRowModel(), state: { globalFilter, }, globalFilterFn: globalFilterFn, onGlobalFilterChange: setGlobalFilter, getFilteredRowModel: getFilteredRowModel(), getPaginationRowModel: getPaginationRowModel(), getSortedRowModel: getSortedRowModel(), }); useEffect(() => { if (url) { loadUrlProxied(url).then((data) => { const { rows, fields } = parseCsv(data); setData(rows); setCols(fields); }); } }, [url]); return (
setGlobalFilter(String(value))} className="p-2 text-sm shadow border border-block" placeholder="Search all columns..." /> {table.getHeaderGroups().map((hg) => ( {hg.headers.map((h) => ( ))} ))} {table.getRowModel().rows.map((r) => ( {r.getVisibleCells().map((c) => ( ))} ))}
{flexRender(h.column.columnDef.header, h.getContext())} {{ asc: ( ), desc: ( ), }[h.column.getIsSorted() as string] ?? (
)}
{flexRender(c.column.columnDef.cell, c.getContext())}
Page
{table.getState().pagination.pageIndex + 1} of{" "} {table.getPageCount()}
); }; const globalFilterFn: FilterFn = (row, columnId, filterValue: string) => { const search = filterValue.toLowerCase(); let value = row.getValue(columnId) as string; if (typeof value === "number") value = String(value); return value?.toLowerCase().includes(search); }; export default Table;