Skip to content

Commit

Permalink
feat: support virtual components.body (#1069)
Browse files Browse the repository at this point in the history
* feat: support virtual components.body

* test: add test case

* demo: restore

* perf: perf context

* fix: remove unused code
  • Loading branch information
linxianxi authored Jan 22, 2024
1 parent 5926b1c commit 2c075f1
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 17 deletions.
14 changes: 10 additions & 4 deletions src/VirtualTable/BodyGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const Grid = React.forwardRef<GridRef, GridProps>((props, ref) => {
'emptyNode',
'scrollX',
]);
const { sticky, scrollY, listItemHeight } = useContext(StaticContext);
const { sticky, scrollY, listItemHeight, getComponent } = useContext(StaticContext);

// =========================== Ref ============================
const listRef = React.useRef<ListRef>();
Expand Down Expand Up @@ -198,6 +198,11 @@ const Grid = React.forwardRef<GridRef, GridProps>((props, ref) => {
// ========================== Render ==========================
const tblPrefixCls = `${prefixCls}-tbody`;

// default 'div' in rc-virtual-list
const wrapperComponent = getComponent(['body', 'wrapper']);
const RowComponent = getComponent(['body', 'row'], 'div');
const cellComponent = getComponent(['body', 'cell'], 'div');

let bodyContent: React.ReactNode;
if (flattenData.length) {
// ========================== Sticky Scroll Bar ==========================
Expand All @@ -220,6 +225,7 @@ const Grid = React.forwardRef<GridRef, GridProps>((props, ref) => {
itemHeight={listItemHeight || 24}
data={flattenData}
itemKey={item => getRowKey(item.record)}
component={wrapperComponent}
scrollWidth={scrollX as number}
onVirtualScroll={({ x }) => {
onScroll({
Expand All @@ -236,11 +242,11 @@ const Grid = React.forwardRef<GridRef, GridProps>((props, ref) => {
);
} else {
bodyContent = (
<div className={classNames(`${prefixCls}-placeholder`)}>
<Cell component="div" prefixCls={prefixCls}>
<RowComponent className={classNames(`${prefixCls}-placeholder`)}>
<Cell component={cellComponent} prefixCls={prefixCls}>
{emptyNode}
</Cell>
</div>
</RowComponent>
);
}

Expand Down
17 changes: 11 additions & 6 deletions src/VirtualTable/BodyLine.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import TableContext, { responseImmutable } from '../context/TableContext';
import type { FlattenData } from '../hooks/useFlattenRecords';
import useRowInfo from '../hooks/useRowInfo';
import VirtualCell from './VirtualCell';
import { StaticContext } from './context';

export interface BodyLineProps<RecordType = any> {
data: FlattenData<RecordType>;
Expand All @@ -27,9 +28,13 @@ const BodyLine = React.forwardRef<HTMLDivElement, BodyLineProps>((props, ref) =>
TableContext,
['prefixCls', 'flattenColumns', 'fixColumn', 'componentWidth', 'scrollX'],
);
const { getComponent } = useContext(StaticContext, ['getComponent']);

const rowInfo = useRowInfo(record, rowKey, index, indent);

const RowComponent = getComponent(['body', 'row'], 'div');
const cellComponent = getComponent(['body', 'cell'], 'div');

// ========================== Expand ==========================
const { rowSupportExpand, expanded, rowProps, expandedRowRender, expandedRowClassName } = rowInfo;

Expand All @@ -50,15 +55,15 @@ const BodyLine = React.forwardRef<HTMLDivElement, BodyLineProps>((props, ref) =>
const rowCellCls = `${prefixCls}-expanded-row-cell`;

expandRowNode = (
<div
<RowComponent
className={classNames(
`${prefixCls}-expanded-row`,
`${prefixCls}-expanded-row-level-${indent + 1}`,
computedExpandedRowClassName,
)}
>
<Cell
component="div"
component={cellComponent}
prefixCls={prefixCls}
className={classNames(rowCellCls, {
[`${rowCellCls}-fixed`]: fixColumn,
Expand All @@ -67,12 +72,11 @@ const BodyLine = React.forwardRef<HTMLDivElement, BodyLineProps>((props, ref) =>
>
{expandContent}
</Cell>
</div>
</RowComponent>
);
}

// ========================== Render ==========================

const rowStyle: React.CSSProperties = {
...style,
width: scrollX as number,
Expand All @@ -84,7 +88,7 @@ const BodyLine = React.forwardRef<HTMLDivElement, BodyLineProps>((props, ref) =>
}

const rowNode = (
<div
<RowComponent
{...rowProps}
{...restProps}
ref={rowSupportExpand ? null : ref}
Expand All @@ -97,6 +101,7 @@ const BodyLine = React.forwardRef<HTMLDivElement, BodyLineProps>((props, ref) =>
return (
<VirtualCell
key={colIndex}
component={cellComponent}
rowInfo={rowInfo}
column={column}
colIndex={colIndex}
Expand All @@ -109,7 +114,7 @@ const BodyLine = React.forwardRef<HTMLDivElement, BodyLineProps>((props, ref) =>
/>
);
})}
</div>
</RowComponent>
);

if (rowSupportExpand) {
Expand Down
6 changes: 4 additions & 2 deletions src/VirtualTable/VirtualCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as React from 'react';
import { getCellProps } from '../Body/BodyRow';
import Cell from '../Cell';
import type useRowInfo from '../hooks/useRowInfo';
import type { ColumnType } from '../interface';
import type { ColumnType, CustomizeComponent } from '../interface';
import { GridContext } from './context';

export interface VirtualCellProps<RecordType> {
Expand All @@ -13,6 +13,7 @@ export interface VirtualCellProps<RecordType> {
colIndex: number;
indent: number;
index: number;
component?: CustomizeComponent;
/** Used for `column.render` */
renderIndex: number;
record: RecordType;
Expand Down Expand Up @@ -42,6 +43,7 @@ function VirtualCell<RecordType = any>(props: VirtualCellProps<RecordType>) {
colIndex,
indent,
index,
component,
renderIndex,
record,
style,
Expand Down Expand Up @@ -114,7 +116,7 @@ function VirtualCell<RecordType = any>(props: VirtualCellProps<RecordType>) {
ellipsis={column.ellipsis}
align={column.align}
scope={column.rowScope}
component="div"
component={component}
prefixCls={rowInfo.prefixCls}
key={key}
record={record}
Expand Down
3 changes: 2 additions & 1 deletion src/VirtualTable/context.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { createContext } from '@rc-component/context';
import type { TableSticky } from '../interface';
import type { GetComponent, TableSticky } from '../interface';

export interface StaticContextProps {
scrollY: number;
listItemHeight: number;
sticky: boolean | TableSticky;
getComponent: GetComponent;
}

export const StaticContext = createContext<StaticContextProps>(null);
Expand Down
13 changes: 9 additions & 4 deletions src/VirtualTable/index.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import type { CompareProps } from '@rc-component/context/lib/Immutable';
import classNames from 'classnames';
import { warning } from 'rc-util';
import { useEvent, warning } from 'rc-util';
import * as React from 'react';
import { INTERNAL_HOOKS } from '../constant';
import { makeImmutable } from '../context/TableContext';
import type { CustomizeScrollBody, Reference } from '../interface';
import type { CustomizeScrollBody, GetComponent, Reference } from '../interface';
import Table, { DEFAULT_PREFIX, type TableProps } from '../Table';
import Grid from './BodyGrid';
import { StaticContext } from './context';
import getValue from 'rc-util/lib/utils/get';

const renderBody: CustomizeScrollBody<any> = (rawData, props) => {
const { ref, onScroll } = props;
Expand Down Expand Up @@ -54,10 +55,14 @@ function VirtualTable<RecordType>(props: VirtualTableProps<RecordType>, ref: Rea
}
}

const getComponent = useEvent<GetComponent>(
(path, defaultComponent) => getValue(components, path) || defaultComponent,
);

// ========================= Context ==========================
const context = React.useMemo(
() => ({ sticky, scrollY, listItemHeight }),
[sticky, scrollY, listItemHeight],
() => ({ sticky, scrollY, listItemHeight, getComponent }),
[sticky, scrollY, listItemHeight, getComponent],
);

// ========================== Render ==========================
Expand Down
18 changes: 18 additions & 0 deletions tests/Virtual.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -398,18 +398,36 @@ describe('Table.Virtual', () => {
});

it('components', async () => {
const Wrapper = React.forwardRef((props, ref: React.Ref<HTMLDivElement>) => (
<div {...props} ref={ref} data-mark="my-wrapper" />
));

const { container } = getTable({
components: {
header: {
cell: function MyTh(props: any) {
return <th {...props} data-mark="my-th" />;
},
},
body: {
wrapper: Wrapper,
row: (props: any) => <div {...props} data-mark="my-row" />,
cell: (props: any) => <div {...props} data-mark="my-cell" />,
},
},
});

await waitFakeTimer();

expect(container.querySelector('thead th')).toHaveAttribute('data-mark', 'my-th');
expect(container.querySelector('.rc-virtual-list-holder')).toHaveAttribute(
'data-mark',
'my-wrapper',
);
expect(container.querySelector('.rc-table-row')).toHaveAttribute('data-mark', 'my-row');
expect(container.querySelector('.rc-table-row .rc-table-cell')).toHaveAttribute(
'data-mark',
'my-cell',
);
});
});

1 comment on commit 2c075f1

@vercel
Copy link

@vercel vercel bot commented on 2c075f1 Jan 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

table – ./

table-git-master-react-component.vercel.app
table-react-component.vercel.app

Please sign in to comment.