import { useState } from 'react'; import { Search } from 'lucide-react'; import { useSetRecoilState } from 'recoil'; import { flexRender, useReactTable, getCoreRowModel, getSortedRowModel, getFilteredRowModel, getPaginationRowModel, } from '@tanstack/react-table'; import type { ColumnDef, SortingState, VisibilityState, ColumnFiltersState, } from '@tanstack/react-table'; import { FileContext } from 'librechat-data-provider'; import { Input, Table, Button, Spinner, TableRow, TableBody, TableCell, TableHead, TrashIcon, TableHeader, useMediaQuery, } from '@librechat/client'; import type { TFile } from 'librechat-data-provider'; import { ColumnVisibilityDropdown } from './ColumnVisibilityDropdown'; import { useDeleteFilesFromTable } from '~/hooks/Files'; import { useLocalize, TranslationKeys } from '~/hooks'; import { cn } from '~/utils'; import store from '~/store'; interface DataTableProps { columns: ColumnDef[]; data: TData[]; } const contextMap: Record = { [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 setFiles = useSetRecoilState(store.filesByIndex(0)); const { deleteFiles } = useDeleteFilesFromTable(() => setIsDeleting(false)); const [rowSelection, setRowSelection] = useState({}); const [sorting, setSorting] = useState([]); const isSmallScreen = useMediaQuery('(max-width: 768px)'); const [columnFilters, setColumnFilters] = useState([]); const [columnVisibility, setColumnVisibility] = useState({}); const table = useReactTable({ data, columns, defaultColumn: { minSize: 0, size: Number.MAX_SAFE_INTEGER, maxSize: Number.MAX_SAFE_INTEGER, }, 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="peer w-full pl-10 text-sm focus-visible:ring-2 focus-visible:ring-ring" aria-label={localize('com_files_filter_input')} />
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header, _index) => { const size = header.getSize(); const style: Style = { width: size === Number.MAX_SAFE_INTEGER ? 'auto' : size, }; 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 size = cell.column.getSize(); const style: Style = { width: size === Number.MAX_SAFE_INTEGER ? 'auto' : size, }; 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} / {Math.max(table.getPageCount(), 1)}
); }