Skip to content

Commit d2eed49

Browse files
feat: add measureRowRender prop (#1347)
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
1 parent 8c37e7f commit d2eed49

File tree

5 files changed

+128
-1
lines changed

5 files changed

+128
-1
lines changed

docs/examples/measureRowRender.tsx

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React from 'react';
2+
import Table from 'rc-table';
3+
4+
// 示例:使用 measureRowRender 来隐藏 MeasureRow 中的弹层
5+
const MeasureRowRenderExample = () => {
6+
const columns = [
7+
{
8+
title: (
9+
<div>
10+
Name
11+
<div className="filter-dropdown" style={{ display: 'none' }}>
12+
Filter Content
13+
</div>
14+
</div>
15+
),
16+
dataIndex: 'name',
17+
key: 'name',
18+
width: 100,
19+
},
20+
{
21+
title: 'Age',
22+
dataIndex: 'age',
23+
key: 'age',
24+
width: 80,
25+
},
26+
];
27+
28+
const data = [
29+
{ key: 1, name: 'John', age: 25 },
30+
{ key: 2, name: 'Jane', age: 30 },
31+
];
32+
33+
// 自定义 MeasureRow 渲染,隐藏弹层内容
34+
const measureRowRender = measureRow => <div style={{ display: 'none' }}>{measureRow}</div>;
35+
36+
return (
37+
<Table
38+
columns={columns}
39+
data={data}
40+
sticky
41+
scroll={{ x: true }}
42+
measureRowRender={measureRowRender}
43+
/>
44+
);
45+
};
46+
47+
export default MeasureRowRenderExample;

src/Body/MeasureRow.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import * as React from 'react';
22
import ResizeObserver from 'rc-resize-observer';
33
import MeasureCell from './MeasureCell';
44
import isVisible from 'rc-util/lib/Dom/isVisible';
5+
import { useContext } from '@rc-component/context';
6+
import TableContext from '../context/TableContext';
57
import type { ColumnType } from '../interface';
68

79
export interface MeasureRowProps {
@@ -18,8 +20,9 @@ export default function MeasureRow({
1820
columns,
1921
}: MeasureRowProps) {
2022
const ref = React.useRef<HTMLTableRowElement>(null);
23+
const { measureRowRender } = useContext(TableContext, ['measureRowRender']);
2124

22-
return (
25+
const measureRow = (
2326
<tr aria-hidden="true" className={`${prefixCls}-measure-row`} style={{ height: 0 }} ref={ref}>
2427
<ResizeObserver.Collection
2528
onBatchResize={infoList => {
@@ -44,4 +47,6 @@ export default function MeasureRow({
4447
</ResizeObserver.Collection>
4548
</tr>
4649
);
50+
51+
return measureRowRender ? measureRowRender(measureRow) : measureRow;
4752
}

src/Table.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,12 @@ export interface TableProps<RecordType = any>
168168
internalRefs?: {
169169
body: React.MutableRefObject<HTMLDivElement>;
170170
};
171+
/**
172+
* @private Internal usage, may remove by refactor.
173+
*
174+
* !!! DO NOT USE IN PRODUCTION ENVIRONMENT !!!
175+
*/
176+
measureRowRender?: (measureRow: React.ReactNode) => React.ReactNode;
171177
}
172178

173179
function defaultEmpty() {
@@ -210,6 +216,9 @@ function Table<RecordType extends DefaultRecordType>(
210216
onRow,
211217
onHeaderRow,
212218

219+
// Measure Row
220+
measureRowRender,
221+
213222
// Events
214223
onScroll,
215224

@@ -850,6 +859,9 @@ function Table<RecordType extends DefaultRecordType>(
850859
childrenColumnName: mergedChildrenColumnName,
851860

852861
rowHoverable,
862+
863+
// Measure Row
864+
measureRowRender,
853865
}),
854866
[
855867
// Scroll
@@ -901,6 +913,8 @@ function Table<RecordType extends DefaultRecordType>(
901913
mergedChildrenColumnName,
902914

903915
rowHoverable,
916+
917+
measureRowRender,
904918
],
905919
);
906920

src/context/TableContext.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ export interface TableContextProps<RecordType = any> {
7272
rowHoverable?: boolean;
7373

7474
expandedRowOffset: ExpandableConfig<RecordType>['expandedRowOffset'];
75+
76+
// Measure Row
77+
measureRowRender?: (measureRow: React.ReactNode) => React.ReactNode;
7578
}
7679

7780
const TableContext = createContext<TableContextProps>();

tests/FixedHeader.spec.jsx

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,4 +265,62 @@ describe('Table.FixedHeader', () => {
265265
'rc-table-cell-fix-left-last',
266266
);
267267
});
268+
269+
it('should support measureRowRender to wrap MeasureRow with custom provider', async () => {
270+
const FilterDropdown = ({ visible, onVisibleChange }) => (
271+
<div className="test-filter-dropdown" style={{ display: visible ? 'block' : 'none' }}>
272+
Filter Content
273+
<button onClick={() => onVisibleChange && onVisibleChange(!visible)}>Toggle</button>
274+
</div>
275+
);
276+
277+
const columns = [
278+
{
279+
title: (
280+
<div>
281+
Name
282+
<FilterDropdown visible={true} onVisibleChange={() => {}} />
283+
</div>
284+
),
285+
dataIndex: 'name',
286+
key: 'name',
287+
width: 100,
288+
},
289+
];
290+
291+
const data = [
292+
{
293+
key: 1,
294+
name: 'Jack',
295+
},
296+
];
297+
298+
// Mock ConfigProvider-like wrapper
299+
const measureRowRender = measureRow => (
300+
<div data-testid="measure-row-wrapper" style={{ display: 'none' }}>
301+
{measureRow}
302+
</div>
303+
);
304+
305+
const wrapper = mount(
306+
<Table
307+
columns={columns}
308+
data={data}
309+
sticky
310+
scroll={{ x: true }}
311+
measureRowRender={measureRowRender}
312+
/>,
313+
);
314+
315+
await safeAct(wrapper);
316+
317+
// Check that measureRowRender wrapper is applied
318+
const measureRowWrapper = wrapper.find('[data-testid="measure-row-wrapper"]');
319+
expect(measureRowWrapper).toHaveLength(1);
320+
expect(measureRowWrapper.prop('style').display).toBe('none');
321+
322+
// Check that MeasureRow is inside the wrapper
323+
const measureRowInWrapper = measureRowWrapper.find('.rc-table-measure-row');
324+
expect(measureRowInWrapper).toHaveLength(1);
325+
});
268326
});

0 commit comments

Comments
 (0)