Skip to content

Commit

Permalink
feat: rowSpan & colSpan
Browse files Browse the repository at this point in the history
  • Loading branch information
zombieJ committed Aug 18, 2023
1 parent c281263 commit 68fe6ba
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 55 deletions.
2 changes: 1 addition & 1 deletion assets/virtual.less
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
}

.@{tablePrefixCls}-cell {
flex: 1 0 auto;
flex: 0 0 var(--virtual-width);
width: var(--virtual-width);
padding: 8px 16px;
border-right: @border;
Expand Down
65 changes: 60 additions & 5 deletions docs/examples/virtual.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,19 @@ const columns: ColumnsType = [
dataIndex: 'c',
key: 'c',
onCell: (_, index) => {
if (index % 3 === 0) {
if (index % 4 === 0) {
return {
rowSpan: 3,
};
}

if (index % 4 === 3) {
return {
rowSpan: 1,
colSpan: 3,
};
}

return {
rowSpan: 0,
};
Expand All @@ -37,11 +44,59 @@ const columns: ColumnsType = [
key: 'd',
children: [
// Children columns
{ title: 'title4-1', dataIndex: 'b' },
{ title: 'title4-2', dataIndex: 'b' },
{
title: 'title4-1',
dataIndex: 'b',
onCell: (_, index) => {
if (index % 4 === 0) {
return {
colSpan: 3,
};
}

if (index % 4 === 3) {
return {
colSpan: 0,
};
}
},
},
{
title: 'title4-2',
dataIndex: 'b',
onCell: (_, index) => {
if (index % 4 === 0 || index % 4 === 3) {
return {
colSpan: 0,
};
}
},
},
],
},
{ title: 'title6', dataIndex: 'b', key: 'f' },
{
title: 'title6',
dataIndex: 'b',
key: 'f',
onCell: (_, index) => {
if (index % 4 === 0) {
return {
rowSpan: 0,
colSpan: 0,
};
}

if (index % 4 === 1) {
return {
rowSpan: 3,
};
}

return {
rowSpan: 0,
};
},
},
{
title: (
<div>
Expand All @@ -62,7 +117,7 @@ const columns: ColumnsType = [
{ title: 'title12', dataIndex: 'b', key: 'l', width: 100, fixed: 'right' },
];

const data: RecordType[] = new Array(3 * 10000).fill(null).map((_, index) => ({
const data: RecordType[] = new Array(4 * 10000).fill(null).map((_, index) => ({
a: `a${index}`,
b: `b${index}`,
c: `c${index}`,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
"classnames": "^2.2.5",
"rc-resize-observer": "^1.1.0",
"rc-util": "^5.27.1",
"rc-virtual-list": "^3.10.1"
"rc-virtual-list": "^3.10.2"
},
"devDependencies": {
"@rc-component/father-plugin": "^1.0.2",
Expand Down
4 changes: 2 additions & 2 deletions src/Body/BodyRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ export function getCellProps<RecordType>(
);
}

let additionalCellProps: React.TdHTMLAttributes<HTMLElement> = {};
let additionalCellProps: React.TdHTMLAttributes<HTMLElement>;
if (column.onCell) {
additionalCellProps = column.onCell(record, index);
}
Expand All @@ -146,7 +146,7 @@ export function getCellProps<RecordType>(
key,
fixedInfo,
appendCellNode,
additionalCellProps,
additionalCellProps: additionalCellProps || {},
};
}

Expand Down
69 changes: 40 additions & 29 deletions src/StaticTable/BodyGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import TableContext from '../context/TableContext';
import useFlattenRecords, { type FlattenData } from '../hooks/useFlattenRecords';
import type { ColumnType, OnCustomizeScroll } from '../interface';
import BodyLine from './BodyLine';
import StaticContext from './StaticContext';
import { GridContext, StaticContext } from './context';
import { RowSpanVirtualCell } from './VirtualCell';

export interface GridProps<RecordType = any> {
Expand All @@ -32,9 +32,6 @@ const Grid = React.forwardRef<GridRef, GridProps>((props, ref) => {
]);
const { scrollY, scrollX } = useContext(StaticContext);

// const context = useContext(TableContext);
// console.log('=>', context, scrollX, scrollY);

// =========================== Ref ============================
const listRef = React.useRef<ListRef>();

Expand All @@ -50,6 +47,11 @@ const Grid = React.forwardRef<GridRef, GridProps>((props, ref) => {
});
}, [flattenColumns]);

const columnsOffset = React.useMemo<number[]>(
() => columnsWidth.map(colWidth => colWidth[2]),
[columnsWidth],
);

React.useEffect(() => {
columnsWidth.forEach(([key, width]) => {
onColumnResize(key, width);
Expand Down Expand Up @@ -123,6 +125,10 @@ const Grid = React.forwardRef<GridRef, GridProps>((props, ref) => {

for (let i = startIndex; i <= endIndex; i += 1) {
const item = flattenData[i];
if (!item) {
continue;
}

const rowKey = getRowKey(item.record, i);

flattenColumns.forEach((column, colIndex) => {
Expand All @@ -134,9 +140,9 @@ const Grid = React.forwardRef<GridRef, GridProps>((props, ref) => {
const endKey = getRowKey(endItem.record, endItemIndex);

const sizeInfo = getSize(rowKey, endKey);
const right = columnsWidth[colIndex][2];
const left = columnsWidth[colIndex - 1][2] || 0;
console.log('!!!', i, rowSpan, endItem, sizeInfo, right);
const right = columnsOffset[colIndex];
const left = columnsOffset[colIndex - 1] || 0;
console.log('!!!', i, -offsetY + sizeInfo.top, left);

nodes.push(
<RowSpanVirtualCell
Expand All @@ -163,32 +169,37 @@ const Grid = React.forwardRef<GridRef, GridProps>((props, ref) => {
return nodes;
};

// ========================= Context ==========================
const gridContext = React.useMemo(() => ({ columnsOffset }), [columnsOffset]);

// ========================== Render ==========================
const tblPrefixCls = `${prefixCls}-tbody`;

return (
<div>
<VirtualList<FlattenData<any>>
ref={listRef}
className={classNames(tblPrefixCls, `${tblPrefixCls}-virtual`)}
height={scrollY}
itemHeight={24}
data={flattenData}
itemKey={item => getRowKey(item.record)}
scrollWidth={scrollX}
onVirtualScroll={({ x }) => {
onScroll({
scrollLeft: x,
});
}}
extraRender={extraRender}
>
{(item, index, itemProps) => {
const rowKey = getRowKey(item.record, index);
return <BodyLine data={item} rowKey={rowKey} index={index} {...itemProps} />;
}}
</VirtualList>
</div>
<GridContext.Provider value={gridContext}>
<div>
<VirtualList<FlattenData<any>>
ref={listRef}
className={classNames(tblPrefixCls, `${tblPrefixCls}-virtual`)}
height={scrollY}
itemHeight={24}
data={flattenData}
itemKey={item => getRowKey(item.record)}
scrollWidth={scrollX}
onVirtualScroll={({ x }) => {
onScroll({
scrollLeft: x,
});
}}
extraRender={extraRender}
>
{(item, index, itemProps) => {
const rowKey = getRowKey(item.record, index);
return <BodyLine data={item} rowKey={rowKey} index={index} {...itemProps} />;
}}
</VirtualList>
</div>
</GridContext.Provider>
);
});

Expand Down
2 changes: 1 addition & 1 deletion src/StaticTable/BodyLine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as React from 'react';
import { useRowInfo } from '../Body/BodyRow';
import TableContext from '../context/TableContext';
import type { FlattenData } from '../hooks/useFlattenRecords';
import StaticContext from './StaticContext';
import { StaticContext } from './context';
import VirtualCell from './VirtualCell';

export interface BodyLineProps<RecordType = any> {
Expand Down
10 changes: 0 additions & 10 deletions src/StaticTable/StaticContext.ts

This file was deleted.

32 changes: 27 additions & 5 deletions src/StaticTable/VirtualCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { getCellProps, useRowInfo } from '../Body/BodyRow';
import Cell from '../Cell';
import type { ColumnType } from '../interface';
import classNames from 'classnames';
import { useContext } from '@rc-component/context';
import { GridContext } from './context';

export interface VirtualCellProps<RecordType extends { index: number }> {
rowInfo: ReturnType<typeof useRowInfo>;
Expand All @@ -25,6 +27,8 @@ function VirtualCell<RecordType extends { index: number } = any>(

const { render, dataIndex, className: columnClassName, width: colWidth } = column;

const { columnsOffset } = useContext(GridContext, ['columnsOffset']);

const { key, fixedInfo, appendCellNode, additionalCellProps } = getCellProps(
rowInfo,
column,
Expand All @@ -33,19 +37,37 @@ function VirtualCell<RecordType extends { index: number } = any>(
index,
);

const { style: cellStyle, colSpan, rowSpan } = additionalCellProps;
const { style: cellStyle, colSpan = 1, rowSpan = 1 } = additionalCellProps;

// ========================= ColWidth =========================
// column width
const startColIndex = colIndex - 1;
const concatColWidth =
colSpan > 1
? columnsOffset[startColIndex + colSpan] - (columnsOffset[startColIndex] || 0)
: (colWidth as number);

// margin offset
const marginOffset = colSpan > 1 ? (colWidth as number) - concatColWidth : 0;

// ========================== Style ===========================
const mergedStyle = {
...cellStyle,
...style,
'--virtual-width': `${colWidth}px`,
'--virtual-width': `${concatColWidth}px`,
marginRight: marginOffset,
};

// 0 rowSpan or colSpan should not render
if (colSpan === 0) {
mergedStyle.visibility = 'hidden';
}

// When `colSpan` or `rowSpan` is `0`, should skip render.
const mergedRender =
!forceRender && (colSpan === 0 || rowSpan === 0 || colSpan > 1 || rowSpan > 1)
? () => null
: render;
!forceRender && (colSpan === 0 || rowSpan === 0 || rowSpan > 1) ? () => null : render;

// ========================== Render ==========================
return (
<Cell
className={classNames(columnClassName, className)}
Expand Down
14 changes: 14 additions & 0 deletions src/StaticTable/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { createContext } from '@rc-component/context';

export interface StaticContextProps {
scrollX: number;
scrollY: number;
}

export const StaticContext = createContext<StaticContextProps>(null);

export interface GridContextProps {
columnsOffset: number[];
}

export const GridContext = createContext<GridContextProps>(null);
2 changes: 1 addition & 1 deletion src/StaticTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { INTERNAL_HOOKS } from '..';
import type { CustomizeScrollBody } from '../interface';
import Table, { type TableProps } from '../Table';
import Grid from './BodyGrid';
import StaticContext from './StaticContext';
import { StaticContext } from './context';
import useWidthColumns from './useWidthColumns';

const renderBody: CustomizeScrollBody<any> = (rawData, props) => {
Expand Down

0 comments on commit 68fe6ba

Please sign in to comment.