mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
chore: add new props (withPagination, getRowCanExpand, renderSubComponent, expanded, and getSubRows)
This commit is contained in:
+116
-55
@@ -1,11 +1,12 @@
|
||||
'use client';
|
||||
|
||||
import { ReactNode, useCallback, useEffect, useState } from 'react';
|
||||
import { Fragment, ReactNode, useCallback, useEffect, useState } from 'react';
|
||||
import {
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getPaginationRowModel,
|
||||
getExpandedRowModel,
|
||||
getSortedRowModel,
|
||||
TableOptions,
|
||||
useReactTable,
|
||||
@@ -15,6 +16,7 @@ import {
|
||||
OnChangeFn,
|
||||
Row,
|
||||
HeaderContext,
|
||||
ExpandedState,
|
||||
} from '@tanstack/react-table';
|
||||
import { rankItem } from '@tanstack/match-sorter-utils';
|
||||
import { Icon } from '@iconify/react';
|
||||
@@ -33,6 +35,9 @@ interface TableClassNames {
|
||||
bodyRowClassName?: string;
|
||||
selectedBodyRowClassName?: string;
|
||||
bodyColumnClassName?: string;
|
||||
bodySubRowClassName?: (depth: number) => string;
|
||||
selectedBodySubRowClassName?: (depth: number) => string;
|
||||
bodySubRowColumnClassName?: (depth: number) => string;
|
||||
tableFooterClassName?: string;
|
||||
footerRowClassName?: string;
|
||||
footerColumnClassName?: string;
|
||||
@@ -60,6 +65,7 @@ export interface TableProps<TData extends object> {
|
||||
enableRowSelection?: boolean | ((row: Row<TData>) => boolean);
|
||||
renderFooter?: boolean;
|
||||
withCheckbox?: boolean;
|
||||
withPagination?: boolean;
|
||||
rowOptions?: number[];
|
||||
/**
|
||||
* Custom row renderer. Should return a complete <tr> element or null.
|
||||
@@ -67,6 +73,10 @@ export interface TableProps<TData extends object> {
|
||||
* Return null to render the default row.
|
||||
*/
|
||||
renderCustomRow?: (row: Row<TData>) => ReactNode | null;
|
||||
getRowCanExpand?: (row: Row<TData>) => boolean;
|
||||
renderSubComponent?: (props: { row: Row<TData> }) => React.ReactElement;
|
||||
expanded?: ExpandedState;
|
||||
getSubRows?: (originalRow: TData, index: number) => TData[] | undefined;
|
||||
}
|
||||
|
||||
const DUMMY_SKELETON_DATA = [{}, {}, {}, {}, {}];
|
||||
@@ -92,7 +102,12 @@ export const TABLE_DEFAULT_STYLING = {
|
||||
bodyRowClassName:
|
||||
'transition-all duration-200 border-t border-base-content/10 bg-transparent',
|
||||
selectedBodyRowClassName: 'bg-primary/5',
|
||||
bodyColumnClassName: 'px-4 py-3 text-base-content',
|
||||
bodyColumnClassName: 'px-4 py-3 text-base-content font-medium',
|
||||
bodySubRowClassName: (depth: number) =>
|
||||
'transition-all duration-200 border-t border-base-content/10 bg-transparent',
|
||||
selectedBodySubRowClassName: (depth: number) => 'bg-primary/5',
|
||||
bodySubRowColumnClassName: (depth: number) =>
|
||||
'px-4 py-3 text-base-content font-medium',
|
||||
paginationClassName: 'px-3',
|
||||
tableFooterClassName: 'font-semibold border-base-content/10',
|
||||
footerRowClassName: 'bg-base-200 border-t-2 border-base-content/10',
|
||||
@@ -120,8 +135,13 @@ const Table = <TData extends object>({
|
||||
enableRowSelection,
|
||||
renderFooter = false,
|
||||
withCheckbox = false,
|
||||
withPagination = true,
|
||||
rowOptions = [10, 20, 50, 100],
|
||||
renderCustomRow,
|
||||
getRowCanExpand,
|
||||
renderSubComponent,
|
||||
expanded = {},
|
||||
getSubRows,
|
||||
}: TableProps<TData>) => {
|
||||
const isServerSideTable =
|
||||
totalItems !== undefined &&
|
||||
@@ -154,10 +174,14 @@ const Table = <TData extends object>({
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getPaginationRowModel: getPaginationRowModel(),
|
||||
onPaginationChange: setPagination,
|
||||
getExpandedRowModel: getExpandedRowModel(),
|
||||
getRowCanExpand: getRowCanExpand ?? (getSubRows ? undefined : () => false),
|
||||
getSubRows,
|
||||
manualSorting,
|
||||
state: {
|
||||
pagination,
|
||||
globalFilter: fuzzySearchValue,
|
||||
expanded,
|
||||
},
|
||||
filterFns: {
|
||||
fuzzy: fuzzyFilter,
|
||||
@@ -228,7 +252,10 @@ const Table = <TData extends object>({
|
||||
<div
|
||||
className={cn(
|
||||
TABLE_DEFAULT_STYLING.containerClassName,
|
||||
tableClassNames.containerClassName
|
||||
tableClassNames.containerClassName,
|
||||
{
|
||||
'mb-0': !withPagination,
|
||||
}
|
||||
)}
|
||||
>
|
||||
<div
|
||||
@@ -352,36 +379,67 @@ const Table = <TData extends object>({
|
||||
}
|
||||
|
||||
return (
|
||||
<tr
|
||||
key={row.id}
|
||||
className={cn(
|
||||
TABLE_DEFAULT_STYLING.bodyRowClassName,
|
||||
tableClassNames.bodyRowClassName,
|
||||
{
|
||||
[tableClassNames.selectedBodyRowClassName]:
|
||||
row.getIsSelected(),
|
||||
}
|
||||
)}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<td
|
||||
key={cell.id}
|
||||
className={cn(
|
||||
{ 'first:w-9 first:pr-0': withCheckbox },
|
||||
TABLE_DEFAULT_STYLING.bodyColumnClassName,
|
||||
tableClassNames.bodyColumnClassName
|
||||
)}
|
||||
>
|
||||
{!isLoading &&
|
||||
flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext()
|
||||
<Fragment key={row.id}>
|
||||
<tr
|
||||
data-depth={row.depth}
|
||||
className={cn(
|
||||
row.depth > 0
|
||||
? tableClassNames.bodySubRowClassName(row.depth)
|
||||
: tableClassNames.bodyRowClassName,
|
||||
{
|
||||
[tableClassNames.selectedBodyRowClassName!]:
|
||||
row.getIsSelected() && row.depth === 0,
|
||||
[tableClassNames.selectedBodySubRowClassName(
|
||||
row.depth
|
||||
)!]: row.getIsSelected() && row.depth > 0,
|
||||
}
|
||||
)}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<td
|
||||
key={cell.id}
|
||||
className={cn(
|
||||
{ 'first:w-9 first:pr-0': withCheckbox },
|
||||
TABLE_DEFAULT_STYLING.bodyColumnClassName,
|
||||
row.depth > 0
|
||||
? tableClassNames.bodySubRowColumnClassName(
|
||||
row.depth
|
||||
)
|
||||
: tableClassNames.bodyColumnClassName
|
||||
)}
|
||||
>
|
||||
{!isLoading &&
|
||||
flexRender(
|
||||
cell.column.columnDef.cell,
|
||||
cell.getContext()
|
||||
)}
|
||||
|
||||
{isLoading && <div className='skeleton w-full h-4' />}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
{isLoading && <div className='skeleton w-full h-4' />}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
|
||||
{row.getIsExpanded() && (
|
||||
<>
|
||||
{renderSubComponent && (
|
||||
<tr
|
||||
className={cn(
|
||||
TABLE_DEFAULT_STYLING.bodySubRowClassName(1),
|
||||
tableClassNames.bodySubRowClassName(1),
|
||||
{
|
||||
[tableClassNames.selectedBodySubRowClassName(1)]:
|
||||
row.getIsSelected(),
|
||||
}
|
||||
)}
|
||||
>
|
||||
<td colSpan={row.getVisibleCells().length}>
|
||||
{renderSubComponent({ row })}
|
||||
</td>
|
||||
</tr>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
@@ -425,30 +483,33 @@ const Table = <TData extends object>({
|
||||
!isLoading &&
|
||||
emptyContent}
|
||||
|
||||
{data.length > 0 && table.getRowModel().rows.length > 0 && !isLoading && (
|
||||
<div
|
||||
className={cn(
|
||||
'mt-5',
|
||||
TABLE_DEFAULT_STYLING.paginationClassName,
|
||||
tableClassNames.paginationClassName
|
||||
)}
|
||||
>
|
||||
<Pagination
|
||||
totalItems={isServerSideTable ? totalItems : table.getRowCount()}
|
||||
itemsPerPage={table.getState().pagination.pageSize}
|
||||
currentPage={
|
||||
isServerSideTable
|
||||
? page
|
||||
: table.getState().pagination.pageIndex + 1
|
||||
}
|
||||
onPrevPage={prevPageClickHandler}
|
||||
onNextPage={nextPageClickHandler}
|
||||
onPageChange={pageChangeHandler}
|
||||
rowOptions={rowOptions}
|
||||
onRowChange={onPageSizeChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{data.length > 0 &&
|
||||
table.getRowModel().rows.length > 0 &&
|
||||
!isLoading &&
|
||||
withPagination && (
|
||||
<div
|
||||
className={cn(
|
||||
'mt-5',
|
||||
TABLE_DEFAULT_STYLING.paginationClassName,
|
||||
tableClassNames.paginationClassName
|
||||
)}
|
||||
>
|
||||
<Pagination
|
||||
totalItems={isServerSideTable ? totalItems : table.getRowCount()}
|
||||
itemsPerPage={table.getState().pagination.pageSize}
|
||||
currentPage={
|
||||
isServerSideTable
|
||||
? page
|
||||
: table.getState().pagination.pageIndex + 1
|
||||
}
|
||||
onPrevPage={prevPageClickHandler}
|
||||
onNextPage={nextPageClickHandler}
|
||||
onPageChange={pageChangeHandler}
|
||||
rowOptions={rowOptions}
|
||||
onRowChange={onPageSizeChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user