Skip to content

Commit

Permalink
feat(Cell): make Cell generic
Browse files Browse the repository at this point in the history
  • Loading branch information
b1rdex committed Sep 13, 2023
1 parent ddf4a89 commit b2287af
Showing 1 changed file with 143 additions and 139 deletions.
282 changes: 143 additions & 139 deletions src/Cell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,154 +69,158 @@ const groupKeys = [
'renderSortIcon'
];

const Cell = React.forwardRef(<RowData = any>(props: InnerCellProps<RowData>, ref: React.Ref<HTMLDivElement>) => {
const {
classPrefix = 'cell',
width = 0,
left = 0,
headerHeight = ROW_HEADER_HEIGHT,
depth = 0,
height = ROW_HEIGHT,
style,
className,
fullText,
firstColumn,
lastColumn,
isHeaderCell,
align,
children,
rowData,
dataKey,
rowIndex,
removed,
rowKey,
rowSpan,
wordWrap,
verticalAlign,
expanded,
treeCol,
hasChildren,
predefinedStyle,
renderCell,
renderTreeToggle,
onClick,
onTreeToggle,
...rest
} = props;

const { rtl, hasCustomTreeCol, isTree } = React.useContext(TableContext);

const isTreeCol = treeCol || (!hasCustomTreeCol && firstColumn && isTree);
const cellHeight = typeof height === 'function' ? height(rowData!) : height;

if (isTreeCol && !isHeaderCell && !rowData) {
throw new Error('[Table.Cell]: `rowData` is required for tree column');
}
const Cell = React.forwardRef(
<RowData = any,>(props: InnerCellProps<RowData>, ref: React.Ref<HTMLDivElement>) => {
const {
classPrefix = 'cell',
width = 0,
left = 0,
headerHeight = ROW_HEADER_HEIGHT,
depth = 0,
height = ROW_HEIGHT,
style,
className,
fullText,
firstColumn,
lastColumn,
isHeaderCell,
align,
children,
rowData,
dataKey,
rowIndex,
removed,
rowKey,
rowSpan,
wordWrap,
verticalAlign,
expanded,
treeCol,
hasChildren,
predefinedStyle,
renderCell,
renderTreeToggle,
onClick,
onTreeToggle,
...rest
} = props;

const handleTreeToggle = useCallback(
(event: React.MouseEvent) => {
onTreeToggle?.(rowKey, rowIndex, rowData, event);
},
[onTreeToggle, rowData, rowIndex, rowKey]
);

const { withClassPrefix, merge, prefix } = useClassNames(classPrefix);
const classes = merge(
className,
withClassPrefix({
expanded: expanded && isTreeCol,
first: firstColumn,
last: lastColumn,
rowspan: rowSpan && !isHeaderCell,
'full-text': fullText
})
);

const nextHeight = isHeaderCell ? headerHeight : cellHeight;
const styles = {
...predefinedStyle,
[fullText ? 'minWidth' : 'width']: width,
height: nextHeight,
zIndex: depth,
[rtl ? 'right' : 'left']: left
};

const paddingKey = rtl ? 'paddingRight' : 'paddingLeft';
const contentStyles: React.CSSProperties = {
...style,
width: fullText ? width - 1 : width,
height: nextHeight,
textAlign: align,
[paddingKey]: isTreeCol ? depth * LAYER_WIDTH + 10 : style?.[paddingKey] || style?.padding
};

if (verticalAlign) {
contentStyles.display = 'table-cell';
contentStyles.verticalAlign = verticalAlign;
}
const { rtl, hasCustomTreeCol, isTree } = React.useContext(TableContext);

if (wordWrap) {
contentStyles.wordBreak = typeof wordWrap === 'boolean' ? 'break-all' : wordWrap;
contentStyles.overflowWrap = wordWrap === 'break-word' ? wordWrap : undefined;
}
const isTreeCol = treeCol || (!hasCustomTreeCol && firstColumn && isTree);
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const cellHeight = typeof height === 'function' ? height(rowData!) : height;

let cellContent = isNil(children) && rowData && dataKey ? get(rowData, dataKey) : children;
if (isTreeCol && !isHeaderCell && !rowData) {
throw new Error('[Table.Cell]: `rowData` is required for tree column');
}

if (typeof children === 'function') {
cellContent = children(rowData!, rowIndex);
}
const handleTreeToggle = useCallback(
(event: React.MouseEvent) => {
onTreeToggle?.(rowKey, rowIndex, rowData, event);
},
[onTreeToggle, rowData, rowIndex, rowKey]
);

const { withClassPrefix, merge, prefix } = useClassNames(classPrefix);
const classes = merge(
className,
withClassPrefix({
expanded: expanded && isTreeCol,
first: firstColumn,
last: lastColumn,
rowspan: rowSpan && !isHeaderCell,
'full-text': fullText
})
);

const renderTreeNodeExpandIcon = () => {
const ExpandIconComponent = expanded ? ArrowDown : ArrowRight;
const expandButton = <ExpandIconComponent className={prefix('expand-icon')} />;

if (isTreeCol && hasChildren) {
return (
<span
role="button"
tabIndex={-1}
className={prefix('expand-wrapper')}
onClick={handleTreeToggle}
>
{renderTreeToggle ? renderTreeToggle(expandButton, rowData, expanded) : expandButton}
</span>
);
const nextHeight = isHeaderCell ? headerHeight : cellHeight;
const styles = {
...predefinedStyle,
[fullText ? 'minWidth' : 'width']: width,
height: nextHeight,
zIndex: depth,
[rtl ? 'right' : 'left']: left
};

const paddingKey = rtl ? 'paddingRight' : 'paddingLeft';
const contentStyles: React.CSSProperties = {
...style,
width: fullText ? width - 1 : width,
height: nextHeight,
textAlign: align,
[paddingKey]: isTreeCol ? depth * LAYER_WIDTH + 10 : style?.[paddingKey] || style?.padding
};

if (verticalAlign) {
contentStyles.display = 'table-cell';
contentStyles.verticalAlign = verticalAlign;
}

return null;
};

const content = wordWrap ? (
<div className={prefix('wrap')}>
{renderTreeNodeExpandIcon()}
{renderCell ? renderCell(cellContent) : cellContent}
</div>
) : (
<>
{renderTreeNodeExpandIcon()}
{renderCell ? renderCell(cellContent) : cellContent}
</>
);

if (removed) {
return null;
}
if (wordWrap) {
contentStyles.wordBreak = typeof wordWrap === 'boolean' ? 'break-all' : wordWrap;
contentStyles.overflowWrap = wordWrap === 'break-word' ? wordWrap : undefined;
}

let cellContent = isNil(children) && rowData && dataKey ? get(rowData, dataKey) : children;

return (
<div
ref={ref}
role={isHeaderCell ? 'columnheader' : 'gridcell'}
{...omit(rest, [...groupKeys, ...columnHandledProps])}
onClick={onClick}
className={classes}
style={styles}
>
<div className={prefix('content')} style={contentStyles}>
{content}
if (typeof children === 'function') {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
cellContent = children(rowData!, rowIndex);
}

const renderTreeNodeExpandIcon = () => {
const ExpandIconComponent = expanded ? ArrowDown : ArrowRight;
const expandButton = <ExpandIconComponent className={prefix('expand-icon')} />;

if (isTreeCol && hasChildren) {
return (
<span
role="button"
tabIndex={-1}
className={prefix('expand-wrapper')}
onClick={handleTreeToggle}
>
{renderTreeToggle ? renderTreeToggle(expandButton, rowData, expanded) : expandButton}
</span>
);
}

return null;
};

const content = wordWrap ? (
<div className={prefix('wrap')}>
{renderTreeNodeExpandIcon()}
{renderCell ? renderCell(cellContent) : cellContent}
</div>
</div>
);
});
) : (
<>
{renderTreeNodeExpandIcon()}
{renderCell ? renderCell(cellContent) : cellContent}
</>
);

if (removed) {
return null;
}

return (
<div
ref={ref}
role={isHeaderCell ? 'columnheader' : 'gridcell'}
{...omit(rest, [...groupKeys, ...columnHandledProps])}
onClick={onClick}
className={classes}
style={styles}
>
<div className={prefix('content')} style={contentStyles}>
{content}
</div>
</div>
);
}
);

Cell.displayName = 'Table.Cell';
Cell.propTypes = {
Expand Down

0 comments on commit b2287af

Please sign in to comment.