From 50559caf52a0af86bbb9fd3545b4282b5f7e71a5 Mon Sep 17 00:00:00 2001 From: rstubryan Date: Wed, 3 Dec 2025 22:28:18 +0700 Subject: [PATCH] feat(FE-326): Support custom header rows and cell render hook --- src/components/Table.tsx | 155 +++++++++++++++++++++++++++------------ 1 file changed, 110 insertions(+), 45 deletions(-) diff --git a/src/components/Table.tsx b/src/components/Table.tsx index b02dd3b5..eafd3e7a 100644 --- a/src/components/Table.tsx +++ b/src/components/Table.tsx @@ -14,6 +14,8 @@ import { SortingState, OnChangeFn, Row, + HeaderGroup, + Column, } from '@tanstack/react-table'; import { rankItem } from '@tanstack/match-sorter-utils'; import { Icon } from '@iconify/react'; @@ -32,6 +34,20 @@ interface TableClassNames { bodyRowClassName?: string; bodyColumnClassName?: string; paginationClassName?: string; + customHeaderRowClassName?: string; + customHeaderCellClassName?: string; +} + +export interface CustomHeaderRow { + id: string; + cells: Array<{ + id: string; + content: ReactNode; + colSpan?: number; + rowSpan?: number; + className?: string; + }>; + className?: string; } export interface TableProps { @@ -52,6 +68,13 @@ export interface TableProps { rowSelection?: Record; setRowSelection?: OnChangeFn>; enableRowSelection?: boolean | ((row: Row) => boolean); + customHeaderRows?: CustomHeaderRow[]; + renderCustomHeaders?: boolean; + onCustomHeaderCellRender?: ( + cell: ReactNode, + column: Column, + headerGroup: HeaderGroup + ) => ReactNode; } const DUMMY_SKELETON_DATA = [{}, {}, {}, {}, {}]; @@ -85,6 +108,8 @@ const Table = ({ bodyRowClassName: '', bodyColumnClassName: '', paginationClassName: '', + customHeaderRowClassName: '', + customHeaderCellClassName: '', }, emptyContent = emptyContentDefaultValue, sorting, @@ -93,6 +118,9 @@ const Table = ({ rowSelection, setRowSelection, enableRowSelection, + customHeaderRows = [], + renderCustomHeaders = false, + onCustomHeaderCellRender, }: TableProps) => { const isServerSideTable = totalItems !== undefined && @@ -195,55 +223,92 @@ const Table = ({
+ {renderCustomHeaders && + customHeaderRows.length > 0 && + customHeaderRows.map((headerRow) => ( + + {headerRow.cells.map((cell) => ( + + ))} + + ))} + {table.getHeaderGroups().map((headerGroup) => ( - {headerGroup.headers.map((header) => ( - - ))} + > +
+ {cellContent} + + {header.column.getCanSort() && ( +
+ + +
+ )} +
+ + ); + })} ))}
+ {cell.content} +
-
- {flexRender( - header.column.columnDef.header, - header.getContext() - )} + {headerGroup.headers.map((header) => { + let cellContent = flexRender( + header.column.columnDef.header, + header.getContext() + ); - {header.column.getCanSort() && ( -
- - -
+ if (onCustomHeaderCellRender) { + cellContent = onCustomHeaderCellRender( + cellContent, + header.column, + headerGroup + ); + } + + return ( +
-