Portal/rsconcept/frontend/src/components/ui/DataTable/TableBody.tsx

108 lines
3.6 KiB
TypeScript
Raw Normal View History

'use no memo';
2024-06-07 20:17:03 +03:00
import { Cell, flexRender, Row, Table } from '@tanstack/react-table';
import clsx from 'clsx';
import { CProps } from '@/components/props';
import { IConditionalStyle } from '.';
import SelectRow from './SelectRow';
interface TableBodyProps<TData> {
table: Table<TData>;
dense?: boolean;
noHeader?: boolean;
enableRowSelection?: boolean;
conditionalRowStyles?: IConditionalStyle<TData>[];
lastSelected: string | undefined;
onChangeLastSelected: (newValue: string | undefined) => void;
2024-06-07 20:17:03 +03:00
onRowClicked?: (rowData: TData, event: CProps.EventMouse) => void;
onRowDoubleClicked?: (rowData: TData, event: CProps.EventMouse) => void;
}
function TableBody<TData>({
table,
dense,
noHeader,
enableRowSelection,
conditionalRowStyles,
lastSelected,
onChangeLastSelected,
2024-06-07 20:17:03 +03:00
onRowClicked,
onRowDoubleClicked
}: TableBodyProps<TData>) {
function handleRowClicked(target: Row<TData>, event: CProps.EventMouse) {
2024-12-04 22:52:45 +03:00
onRowClicked?.(target.original, event);
2024-06-07 20:17:03 +03:00
if (enableRowSelection && target.getCanSelect()) {
if (event.shiftKey && !!lastSelected && lastSelected !== target.id) {
const { rows, rowsById } = table.getRowModel();
const lastIndex = rowsById[lastSelected].index;
const currentIndex = target.index;
const toggleRows = rows.slice(
lastIndex > currentIndex ? currentIndex : lastIndex + 1,
lastIndex > currentIndex ? lastIndex : currentIndex + 1
);
2024-08-06 14:38:10 +03:00
const newSelection: Record<string, boolean> = {};
2024-06-07 20:17:03 +03:00
toggleRows.forEach(row => {
newSelection[row.id] = !target.getIsSelected();
});
table.setRowSelection(prev => ({ ...prev, ...newSelection }));
onChangeLastSelected(undefined);
2024-06-07 20:17:03 +03:00
} else {
onChangeLastSelected(target.id);
2024-06-07 20:17:03 +03:00
target.toggleSelected(!target.getIsSelected());
}
}
}
function getRowStyles(row: Row<TData>) {
return {
...conditionalRowStyles!
.filter(item => item.when(row.original))
.reduce((prev, item) => ({ ...prev, ...item.style }), {})
};
}
return (
<tbody>
{table.getRowModel().rows.map((row: Row<TData>, index) => (
<tr
key={row.id}
className={clsx(
'cc-scroll-row clr-hover',
2024-06-07 20:17:03 +03:00
!noHeader && 'scroll-mt-[calc(2px+2rem)]',
row.getIsSelected() ? 'clr-selected' : index % 2 === 0 ? 'clr-controls' : 'bg-app-100'
2024-06-07 20:17:03 +03:00
)}
style={{ ...(conditionalRowStyles ? getRowStyles(row) : []) }}
>
{enableRowSelection ? (
<td key={`select-${row.id}`} className='pl-3 pr-1 align-middle border-y'>
<SelectRow row={row} onChangeLastSelected={onChangeLastSelected} />
2024-06-07 20:17:03 +03:00
</td>
) : null}
{row.getVisibleCells().map((cell: Cell<TData, unknown>) => (
<td
key={cell.id}
className='px-2 align-middle border-y'
style={{
cursor: onRowClicked || onRowDoubleClicked ? 'pointer' : 'auto',
paddingBottom: dense ? '0.25rem' : '0.5rem',
paddingTop: dense ? '0.25rem' : '0.5rem',
width: noHeader && index === 0 ? `calc(var(--col-${cell.column.id}-size) * 1px)` : 'auto'
2024-06-07 20:17:03 +03:00
}}
onClick={event => handleRowClicked(row, event)}
onDoubleClick={event => (onRowDoubleClicked ? onRowDoubleClicked(row.original, event) : undefined)}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</td>
))}
</tr>
))}
</tbody>
);
}
export default TableBody;