Skip to content

Commit

Permalink
feat(Table): attributes customization (#27)
Browse files Browse the repository at this point in the history
Co-authored-by: kseniyakuzina <[email protected]>
  • Loading branch information
kseniya57 and kseniyakuzina authored Aug 13, 2024
1 parent cfd2b7c commit 018dd18
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 27 deletions.
7 changes: 7 additions & 0 deletions src/components/Cell/Cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,31 @@ export interface CellProps<TData>
extends Omit<React.TdHTMLAttributes<HTMLTableCellElement>, 'className'> {
cell?: CellType<TData, unknown>;
className?: string | ((cell?: CellType<TData, unknown>) => string);
attributes?:
| React.TdHTMLAttributes<HTMLTableCellElement>
| ((cell?: CellType<TData, unknown>) => React.TdHTMLAttributes<HTMLTableCellElement>);
}

export const Cell = <TData,>({
cell,
children,
className: classNameProp,
style,
attributes: attributesProp,
...restProps
}: CellProps<TData>) => {
const className = React.useMemo(() => {
return typeof classNameProp === 'function' ? classNameProp(cell) : classNameProp;
}, [cell, classNameProp]);

const attributes = typeof attributesProp === 'function' ? attributesProp(cell) : attributesProp;

return (
<td
className={b('cell', getCellClassModes(cell), className)}
style={getCellStyles(cell, style)}
{...restProps}
{...attributes}
>
{cell ? flexRender(cell.column.columnDef.cell, cell.getContext()) : children}
</td>
Expand Down
41 changes: 26 additions & 15 deletions src/components/DraggableRow/DraggableRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';

import {useSortable} from '@dnd-kit/sortable';
import {useForkRef} from '@gravity-ui/uikit';
import type {Row as RowType} from '@tanstack/react-table';

import {useDraggableRowDepth, useDraggableRowStyle} from '../../hooks';
import type {RowProps} from '../Row';
Expand All @@ -14,7 +15,12 @@ export interface DraggableRowProps<TData, TScrollElement extends Element | Windo

export const DraggableRow = React.forwardRef(
<TData, TScrollElement extends Element | Window = HTMLDivElement>(
{getRowAttributes, row, style, ...restProps}: DraggableRowProps<TData, TScrollElement>,
{
attributes: attributesProp,
row,
style,
...restProps
}: DraggableRowProps<TData, TScrollElement>,
ref: React.Ref<HTMLTableRowElement>,
) => {
const {setNodeRef, transform, transition, isDragging} = useSortable({
Expand Down Expand Up @@ -48,25 +54,30 @@ export const DraggableRow = React.forwardRef(
nestingEnabled: enableNesting,
});

const getDraggableRowDataAttributes = React.useCallback<
NonNullable<RowProps<TData>['getRowAttributes']>
>(
(draggableRow) => ({
...getRowAttributes?.(draggableRow),
'data-key': draggableRow.id,
'data-depth': depth,
'data-draggable': true,
'data-dragging': isDragging,
'data-drag-active': isDragActive,
'data-expanded': isDragActive && isParent,
}),
[getRowAttributes, depth, isDragging, isDragActive, isParent],
const getDraggableRowDataAttributes = React.useCallback(
(draggableRow: RowType<TData>) => {
const attributes =
typeof attributesProp === 'function'
? attributesProp(draggableRow)
: attributesProp;

return {
...attributes,
'data-key': draggableRow.id,
'data-depth': depth,
'data-draggable': true,
'data-dragging': isDragging,
'data-drag-active': isDragActive,
'data-expanded': isDragActive && isParent,
};
},
[attributesProp, depth, isDragging, isDragActive, isParent],
);

return (
<Row
ref={handleRowRef}
getRowAttributes={getDraggableRowDataAttributes}
attributes={getDraggableRowDataAttributes}
row={row}
style={draggableStyle}
{...restProps}
Expand Down
13 changes: 13 additions & 0 deletions src/components/HeaderCell/HeaderCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ export interface HeaderCellProps<TData, TValue> {
renderSortIndicator?: (props: SortIndicatorProps<TData, TValue>) => React.ReactNode;
resizeHandleClassName?: string;
sortIndicatorClassName?: string;
attributes?:
| React.TdHTMLAttributes<HTMLTableCellElement>
| ((
header: Header<TData, TValue>,
parentHeader?: Header<TData, unknown>,
) => React.TdHTMLAttributes<HTMLTableCellElement>);
}

export const HeaderCell = <TData, TValue>({
Expand All @@ -30,6 +36,7 @@ export const HeaderCell = <TData, TValue>({
renderSortIndicator,
resizeHandleClassName,
sortIndicatorClassName,
attributes: attributesProp,
}: HeaderCellProps<TData, TValue>) => {
const className = React.useMemo(() => {
return typeof classNameProp === 'function'
Expand All @@ -53,13 +60,19 @@ export const HeaderCell = <TData, TValue>({

const rowSpan = header.isPlaceholder ? header.getLeafHeaders().length : 1;

const attributes =
typeof attributesProp === 'function'
? attributesProp(header, parentHeader)
: attributesProp;

return (
<th
className={b('header-cell', getHeaderCellClassModes(header), className)}
colSpan={header.colSpan > 1 ? header.colSpan : undefined}
rowSpan={rowSpan > 1 ? rowSpan : undefined}
onClick={header.column.getToggleSortingHandler()}
style={getCellStyles(header)}
{...attributes}
>
{flexRender(header.column.columnDef.header, header.getContext())}{' '}
{header.column.getCanSort() &&
Expand Down
17 changes: 16 additions & 1 deletion src/components/HeaderRow/HeaderRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ export interface HeaderRowProps<TData, TValue> {
renderSortIndicator: HeaderCellProps<TData, TValue>['renderSortIndicator'];
resizeHandleClassName?: HeaderCellProps<TData, TValue>['resizeHandleClassName'];
sortIndicatorClassName: HeaderCellProps<TData, TValue>['sortIndicatorClassName'];
attributes?:
| React.HTMLAttributes<HTMLTableRowElement>
| ((
headerGroup: HeaderGroup<TData>,
parentHeaderGroup?: HeaderGroup<TData>,
) => React.HTMLAttributes<HTMLTableRowElement>);
cellAttributes?: HeaderCellProps<TData, TValue>['attributes'];
}

export const HeaderRow = <TData, TValue>({
Expand All @@ -29,15 +36,22 @@ export const HeaderRow = <TData, TValue>({
renderSortIndicator,
resizeHandleClassName,
sortIndicatorClassName,
attributes: attributesProp,
cellAttributes,
}: HeaderRowProps<TData, TValue>) => {
const className = React.useMemo(() => {
return typeof classNameProp === 'function'
? classNameProp(headerGroup, parentHeaderGroup)
: classNameProp;
}, [classNameProp, headerGroup, parentHeaderGroup]);

const attributes =
typeof attributesProp === 'function'
? attributesProp(headerGroup, parentHeaderGroup)
: attributesProp;

return (
<tr className={b('header-row', className)}>
<tr className={b('header-row', className)} {...attributes}>
{headerGroup.headers.map((header) => (
<HeaderCell
key={header.column.id}
Expand All @@ -50,6 +64,7 @@ export const HeaderRow = <TData, TValue>({
renderSortIndicator={renderSortIndicator}
resizeHandleClassName={resizeHandleClassName}
sortIndicatorClassName={sortIndicatorClassName}
attributes={cellAttributes}
/>
))}
</tr>
Expand Down
30 changes: 23 additions & 7 deletions src/components/Row/Row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ export interface RowProps<TData, TScrollElement extends Element | Window = HTMLD
getGroupTitle?: (row: RowType<TData>) => React.ReactNode;
getIsCustomRow?: (row: RowType<TData>) => boolean;
getIsGroupHeaderRow?: (row: RowType<TData>) => boolean;
getRowAttributes?: (
row: RowType<TData>,
) => React.TdHTMLAttributes<HTMLTableRowElement> | undefined;
groupHeaderClassName?: string;
onClick?: (row: RowType<TData>, event: React.MouseEvent<HTMLTableRowElement>) => void;
renderCustomRowContent?: (props: {
Expand All @@ -37,6 +34,10 @@ export interface RowProps<TData, TScrollElement extends Element | Window = HTMLD
rowVirtualizer?: Virtualizer<TScrollElement, HTMLTableRowElement>;
style?: React.CSSProperties;
virtualItem?: VirtualItem<HTMLTableRowElement>;
attributes?:
| React.HTMLAttributes<HTMLTableRowElement>
| ((row: RowType<TData>) => React.HTMLAttributes<HTMLTableRowElement>);
cellAttributes?: CellProps<TData>['attributes'];
}

export const Row = React.forwardRef(
Expand All @@ -47,7 +48,6 @@ export const Row = React.forwardRef(
getGroupTitle,
getIsCustomRow,
getIsGroupHeaderRow,
getRowAttributes,
groupHeaderClassName,
onClick,
renderCustomRowContent,
Expand All @@ -57,6 +57,8 @@ export const Row = React.forwardRef(
rowVirtualizer,
style,
virtualItem,
attributes: attributesProp,
cellAttributes,
}: RowProps<TData, TScrollElement>,
ref: React.Ref<HTMLTableRowElement>,
) => {
Expand All @@ -83,7 +85,11 @@ export const Row = React.forwardRef(
row,
})
) : (
<Cell className={cellClassName} colSpan={row.getVisibleCells().length}>
<Cell
className={cellClassName}
colSpan={row.getVisibleCells().length}
attributes={cellAttributes}
>
{renderGroupHeader ? (
renderGroupHeader({
className: b('group-header', groupHeaderClassName),
Expand All @@ -107,9 +113,19 @@ export const Row = React.forwardRef(

return row
.getVisibleCells()
.map((cell) => <Cell key={cell.id} cell={cell} className={cellClassName} />);
.map((cell) => (
<Cell
key={cell.id}
cell={cell}
className={cellClassName}
attributes={cellAttributes}
/>
));
};

const attributes =
typeof attributesProp === 'function' ? attributesProp(row) : attributesProp;

return (
<tr
ref={rowRef}
Expand All @@ -127,7 +143,7 @@ export const Row = React.forwardRef(
)}
onClick={handleClick}
data-index={virtualItem?.index}
{...getRowAttributes?.(row)}
{...attributes}
>
{renderRowContent()}
</tr>
Expand Down
28 changes: 24 additions & 4 deletions src/components/Table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ export interface TableProps<TData, TScrollElement extends Element | Window = HTM
getGroupTitle?: RowProps<TData>['getGroupTitle'];
getIsCustomRow?: RowProps<TData>['getIsCustomRow'];
getIsGroupHeaderRow?: RowProps<TData>['getIsGroupHeaderRow'];
getRowAttributes?: RowProps<TData>['getRowAttributes'];
groupHeaderClassName?: RowProps<TData>['groupHeaderClassName'];
headerCellClassName?: HeaderRowProps<TData, unknown>['cellClassName'];
headerClassName?: string;
Expand All @@ -48,6 +47,13 @@ export interface TableProps<TData, TScrollElement extends Element | Window = HTM
table: TableType<TData>;
withFooter?: boolean;
withHeader?: boolean;
attributes?: React.TableHTMLAttributes<HTMLTableElement>;
headerAttributes?: React.HTMLAttributes<HTMLTableSectionElement>;
headerRowAttributes?: HeaderRowProps<TData, unknown>['attributes'];
headerCellAttributes?: HeaderRowProps<TData, unknown>['cellAttributes'];
bodyAttributes?: React.HTMLAttributes<HTMLTableSectionElement>;
rowAttributes?: RowProps<TData>['attributes'];
cellAttributes?: RowProps<TData>['cellAttributes'];
}

export const Table = React.forwardRef(
Expand All @@ -62,7 +68,6 @@ export const Table = React.forwardRef(
footerRowClassName,
getGroupTitle,
getIsGroupHeaderRow,
getRowAttributes,
headerCellClassName,
headerClassName,
headerRowClassName,
Expand All @@ -80,6 +85,13 @@ export const Table = React.forwardRef(
table,
withFooter,
withHeader = true,
attributes,
headerAttributes,
headerRowAttributes,
headerCellAttributes,
bodyAttributes,
rowAttributes,
cellAttributes,
}: TableProps<TData, TScrollElement>,
ref: React.Ref<HTMLTableElement>,
) => {
Expand All @@ -104,9 +116,13 @@ export const Table = React.forwardRef(
ref={ref}
className={b({'with-row-virtualization': Boolean(rowVirtualizer)}, className)}
data-dragging-row-index={draggingRowIndex > -1 ? draggingRowIndex : undefined}
{...attributes}
>
{headerGroups && (
<thead className={b('header', {sticky: stickyHeader}, headerClassName)}>
<thead
className={b('header', {sticky: stickyHeader}, headerClassName)}
{...headerAttributes}
>
{headerGroups.map((headerGroup, index) => (
<HeaderRow
key={headerGroup.id}
Expand All @@ -118,6 +134,8 @@ export const Table = React.forwardRef(
renderSortIndicator={renderSortIndicator}
resizeHandleClassName={resizeHandleClassName}
sortIndicatorClassName={sortIndicatorClassName}
attributes={headerRowAttributes}
cellAttributes={headerCellAttributes}
/>
))}
</thead>
Expand All @@ -127,6 +145,7 @@ export const Table = React.forwardRef(
style={{
height: rowVirtualizer?.getTotalSize(),
}}
{...bodyAttributes}
>
{(rowVirtualizer?.getVirtualItems() || rows).map((virtualItemOrRow) => {
const row = rowVirtualizer
Expand All @@ -138,7 +157,8 @@ export const Table = React.forwardRef(
className: rowClassName,
getGroupTitle,
getIsGroupHeaderRow,
getRowAttributes,
attributes: rowAttributes,
cellAttributes,
onClick: onRowClick,
renderGroupHeader,
renderGroupHeaderRowContent,
Expand Down

0 comments on commit 018dd18

Please sign in to comment.