import { useState } from 'react'; import { ListFilter } from 'lucide-react'; import { flexRender, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, getSortedRowModel, useReactTable, } from '@tanstack/react-table'; import type { ColumnDef, SortingState, VisibilityState, ColumnFiltersState, } from '@tanstack/react-table'; import { FileContext } from 'librechat-data-provider'; import type { AugmentedColumnDef } from '~/common'; import type { TFile } from 'librechat-data-provider'; import { Button, Input, Table, TableBody, TableCell, TableHead, TableHeader, TableRow, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuTrigger, } from '~/components/ui'; import { useDeleteFilesFromTable } from '~/hooks/Files'; import { TrashIcon, Spinner } from '~/components/svg'; import useLocalize from '~/hooks/useLocalize'; import { useMediaQuery } from '~/hooks'; import { cn } from '~/utils'; interface DataTableProps { columns: ColumnDef[]; data: TData[]; } const contextMap = { [FileContext.filename]: 'com_ui_name', [FileContext.updatedAt]: 'com_ui_date', [FileContext.filterSource]: 'com_ui_storage', [FileContext.context]: 'com_ui_context', [FileContext.bytes]: 'com_ui_size', }; type Style = { width?: number | string; maxWidth?: number | string; minWidth?: number | string; zIndex?: number; }; export default function DataTable({ columns, data }: DataTableProps) { const localize = useLocalize(); const [isDeleting, setIsDeleting] = useState(false); const [rowSelection, setRowSelection] = useState({}); const [sorting, setSorting] = useState([]); const isSmallScreen = useMediaQuery('(max-width: 768px)'); const [columnFilters, setColumnFilters] = useState([]); const [columnVisibility, setColumnVisibility] = useState({}); const { deleteFiles } = useDeleteFilesFromTable(() => setIsDeleting(false)); const table = useReactTable({ data, columns, onSortingChange: setSorting, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), onColumnFiltersChange: setColumnFilters, getFilteredRowModel: getFilteredRowModel(), onColumnVisibilityChange: setColumnVisibility, getPaginationRowModel: getPaginationRowModel(), onRowSelectionChange: setRowSelection, state: { sorting, columnFilters, columnVisibility, rowSelection, }, }); return (
table.getColumn('filename')?.setFilterValue(event.target.value)} className="flex-1 text-sm" /> {table .getAllColumns() .filter((column) => column.getCanHide()) .map((column) => ( column.toggleVisibility(Boolean(value))} > {localize(contextMap[column.id])} ))}
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header, index) => { const style: Style = {}; if (index === 0 && header.id === 'select') { style.width = '35px'; style.minWidth = '35px'; } else if (header.id === 'filename') { style.width = isSmallScreen ? '60%' : '40%'; } else { style.width = isSmallScreen ? '20%' : '15%'; } return ( {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} ); })} ))} {table.getRowModel().rows.length ? ( table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell, index) => { const maxWidth = (cell.column.columnDef as AugmentedColumnDef).meta?.size ?? 'auto'; const style: Style = {}; if (cell.column.id === 'filename') { style.maxWidth = maxWidth; } else if (index === 0) { style.maxWidth = '20px'; } return ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ); })} )) ) : ( {localize('com_files_no_results')} )}
{localize( 'com_files_number_selected', { 0: `${table.getFilteredSelectedRowModel().rows.length}`, 1: `${table.getFilteredRowModel().rows.length}`, }, )} {`${table.getFilteredSelectedRowModel().rows.length}/${ table.getFilteredRowModel().rows.length }`}
{localize('com_ui_page')} {table.getState().pagination.pageIndex + 1} / {table.getPageCount()}
); }