import * as React from 'react'; import { ColumnDef, flexRender, getCoreRowModel, useReactTable, } from '@tanstack/react-table'; import TableHeader from './table-header/TableHeader'; import styled from '@emotion/styled'; import { FilterConfigType, SearchConfigType, SearchableType, SelectedFilterType, SelectedSortType, SortType, } from './table-header/interface'; declare module 'react' { function forwardRef( render: (props: P, ref: React.Ref) => React.ReactElement | null, ): (props: P & React.RefAttributes) => React.ReactElement | null; } type OwnProps< TData extends { id: string; __typename: 'companies' | 'people' }, SortField, > = { data: Array; columns: Array>; viewName: string; viewIcon?: React.ReactNode; availableSorts?: Array>; availableFilters?: FilterConfigType[]; filterSearchResults?: { results: { render: (value: SearchableType) => string; value: SearchableType; }[]; loading: boolean; }; onSortsUpdate?: (sorts: Array>) => void; onFiltersUpdate?: (sorts: Array>) => void; onFilterSearch?: ( filter: SearchConfigType | null, searchValue: string, ) => void; onRowSelectionChange?: (rowSelection: string[]) => void; }; const StyledTable = styled.table` min-width: 1000px; width: calc(100% - ${(props) => props.theme.spacing(4)}); border-radius: 4px; border-spacing: 0; border-collapse: collapse; margin-left: ${(props) => props.theme.spacing(2)}; margin-right: ${(props) => props.theme.spacing(2)}; th { border-collapse: collapse; color: ${(props) => props.theme.text40}; padding: 0; border: 1px solid ${(props) => props.theme.tertiaryBackground}; text-align: left; :last-child { border-right-color: transparent; } :first-of-type { border-left-color: transparent; } } td { border-collapse: collapse; color: ${(props) => props.theme.text80}; padding: 0; border: 1px solid ${(props) => props.theme.tertiaryBackground}; text-align: left; :last-child { border-right-color: transparent; } :first-of-type { border-left-color: transparent; } } `; const StyledTableWithHeader = styled.div` display: flex; flex-direction: column; flex: 1; width: 100%; `; const StyledTableScrollableContainer = styled.div` overflow: auto; height: 100%; flex: 1; `; const Table = < TData extends { id: string; __typename: 'companies' | 'people' }, SortField, >( { data, columns, viewName, viewIcon, availableSorts, availableFilters, filterSearchResults, onSortsUpdate, onFiltersUpdate, onFilterSearch, onRowSelectionChange, }: OwnProps, ref: React.ForwardedRef<{ resetRowSelection: () => void } | undefined>, ) => { const [internalRowSelection, setInternalRowSelection] = React.useState({}); const table = useReactTable({ data, columns, state: { rowSelection: internalRowSelection, }, getCoreRowModel: getCoreRowModel(), enableRowSelection: true, onRowSelectionChange: setInternalRowSelection, getRowId: (row) => row.id, }); const selectedRows = table.getSelectedRowModel().rows; React.useEffect(() => { const selectedRowIds = selectedRows.map((row) => row.original.id); onRowSelectionChange && onRowSelectionChange(selectedRowIds); }, [onRowSelectionChange, selectedRows]); React.useImperativeHandle(ref, () => { return { resetRowSelection: () => { table.resetRowSelection(); }, }; }); return ( []} filterSearchResults={filterSearchResults} onSortsUpdate={onSortsUpdate} onFiltersUpdate={onFiltersUpdate} onFilterSearch={onFilterSearch} /> {table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => ( {header.isPlaceholder ? null : flexRender( header.column.columnDef.header, header.getContext(), )} ))} ))} {table.getRowModel().rows.map((row, index) => ( {row.getVisibleCells().map((cell) => { return ( {flexRender( cell.column.columnDef.cell, cell.getContext(), )} ); })} ))} ); }; export default React.forwardRef(Table);