Skip to content

Commit e9d89ed

Browse files
committed
feat: support classNames and styles
1 parent c02189e commit e9d89ed

File tree

7 files changed

+160
-16
lines changed

7 files changed

+160
-16
lines changed

docs/examples/className.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,20 @@ const Demo = () => (
5252
expandedRowClassName={(record, i) => `ex-row-${i}`}
5353
data={data}
5454
className="table"
55+
title={() => <span>title</span>}
56+
footer={() => <span>footer</span>}
57+
/>
58+
<h2>scroll</h2>
59+
<Table
60+
columns={columns}
61+
rowClassName={(record, i) => `row-${i}`}
62+
expandedRowRender={record => <p>extra: {record.a}</p>}
63+
expandedRowClassName={(record, i) => `ex-row-${i}`}
64+
data={Array(5).fill(data)}
65+
className="table"
66+
scroll={{ x: 'calc(700px + 50%)', y: 47 * 5 }}
67+
title={() => <span>title</span>}
68+
footer={() => <span>footer</span>}
5569
/>
5670
</div>
5771
);

src/Cell/index.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { useContext } from '@rc-component/context';
2-
import classNames from 'classnames';
2+
import cls from 'classnames';
33
import * as React from 'react';
44
import TableContext from '../context/TableContext';
55
import devRenderTimes from '../hooks/useRenderTimes';
@@ -122,10 +122,8 @@ function Cell<RecordType>(props: CellProps<RecordType>) {
122122
} = props;
123123

124124
const cellPrefixCls = `${prefixCls}-cell`;
125-
const { allColumnsFixedLeft, rowHoverable } = useContext(TableContext, [
126-
'allColumnsFixedLeft',
127-
'rowHoverable',
128-
]);
125+
126+
const { allColumnsFixedLeft, rowHoverable, classNames, styles } = useContext(TableContext);
129127

130128
// ====================== Value =======================
131129
const [childNode, legacyCellProps] = useCellRender(
@@ -212,8 +210,9 @@ function Cell<RecordType>(props: CellProps<RecordType>) {
212210
});
213211

214212
// >>>>> ClassName
215-
const mergedClassName = classNames(
213+
const mergedClassName = cls(
216214
cellPrefixCls,
215+
classNames?.item,
217216
className,
218217
{
219218
// Fixed
@@ -249,6 +248,7 @@ function Cell<RecordType>(props: CellProps<RecordType>) {
249248
...fixedStyle,
250249
...alignStyle,
251250
...additionalProps.style,
251+
...styles?.item,
252252
};
253253

254254
// >>>>> Children Node

src/FixedHolder/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ const FixedHolder = React.forwardRef<HTMLDivElement, FixedHeaderProps<any>>((pro
4646

4747
const {
4848
className,
49+
style,
4950
noData,
5051
columns,
5152
flattenColumns,
@@ -159,6 +160,7 @@ const FixedHolder = React.forwardRef<HTMLDivElement, FixedHeaderProps<any>>((pro
159160
style={{
160161
overflow: 'hidden',
161162
...(isSticky ? { top: stickyTopOffset, bottom: stickyBottomOffset } : {}),
163+
...style,
162164
}}
163165
ref={setScrollRef}
164166
className={classNames(className, {

src/Panel/index.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import * as React from 'react';
33
export interface TitleProps {
44
className: string;
55
children: React.ReactNode;
6+
style: React.CSSProperties;
67
}
78

8-
function Panel({ className, children }: TitleProps) {
9-
return <div className={className}>{children}</div>;
9+
function Panel({ className, style, children }: TitleProps) {
10+
return <div className={className} style={style}>{children}</div>;
1011
}
1112

1213
export default Panel;

src/Table.tsx

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
*/
2626

2727
import type { CompareProps } from '@rc-component/context/lib/Immutable';
28-
import classNames from 'classnames';
28+
import cls from 'classnames';
2929
import ResizeObserver from '@rc-component/resize-observer';
3030
import isVisible from '@rc-component/util/lib/Dom/isVisible';
3131
import { getTargetScrollBarSize } from '@rc-component/util/lib/getScrollBarSize';
@@ -85,11 +85,14 @@ const EMPTY_DATA = [];
8585
// Used for customize scroll
8686
const EMPTY_SCROLL_TARGET = {};
8787

88+
export type SemanticName = 'section'| 'header' | 'title' | 'footer' | 'body' | 'content' | 'item';
8889
export interface TableProps<RecordType = any>
8990
extends Omit<LegacyExpandableProps<RecordType>, 'showExpandColumn'> {
9091
prefixCls?: string;
9192
className?: string;
9293
style?: React.CSSProperties;
94+
classNames?: Partial<Record<SemanticName, string>>;
95+
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
9396
children?: React.ReactNode;
9497
data?: readonly RecordType[];
9598
columns?: ColumnsType<RecordType>;
@@ -190,6 +193,8 @@ function Table<RecordType extends DefaultRecordType>(
190193
className,
191194
rowClassName,
192195
style,
196+
classNames,
197+
styles,
193198
data,
194199
rowKey,
195200
scroll,
@@ -655,10 +660,11 @@ function Table<RecordType extends DefaultRecordType>(
655660
style={{
656661
...scrollXStyle,
657662
...scrollYStyle,
663+
...styles?.body,
658664
}}
659665
onScroll={onBodyScroll}
660666
ref={scrollBodyRef}
661-
className={classNames(`${prefixCls}-body`)}
667+
className={cls(`${prefixCls}-body`, classNames?.body)}
662668
>
663669
<TableComponent
664670
style={{
@@ -698,7 +704,8 @@ function Table<RecordType extends DefaultRecordType>(
698704
<FixedHolder
699705
{...fixedHolderProps}
700706
stickyTopOffset={offsetHeader}
701-
className={`${prefixCls}-header`}
707+
className={cls(`${prefixCls}-header`, classNames?.header)}
708+
style={styles?.header}
702709
ref={scrollHeaderRef}
703710
>
704711
{renderFixedHeaderTable}
@@ -739,8 +746,9 @@ function Table<RecordType extends DefaultRecordType>(
739746
style={{
740747
...scrollXStyle,
741748
...scrollYStyle,
749+
...styles?.content,
742750
}}
743-
className={classNames(`${prefixCls}-content`)}
751+
className={cls(`${prefixCls}-content`, classNames?.content)}
744752
onScroll={onInternalScroll}
745753
ref={scrollBodyRef}
746754
>
@@ -773,7 +781,7 @@ function Table<RecordType extends DefaultRecordType>(
773781

774782
let fullTable = (
775783
<div
776-
className={classNames(prefixCls, className, {
784+
className={cls(prefixCls, className, {
777785
[`${prefixCls}-rtl`]: direction === 'rtl',
778786
[`${prefixCls}-fix-start-shadow`]: horizonScroll,
779787
[`${prefixCls}-fix-end-shadow`]: horizonScroll,
@@ -792,11 +800,11 @@ function Table<RecordType extends DefaultRecordType>(
792800
ref={fullTableRef}
793801
{...dataProps}
794802
>
795-
{title && <Panel className={`${prefixCls}-title`}>{title(mergedData)}</Panel>}
796-
<div ref={scrollBodyContainerRef} className={`${prefixCls}-container`}>
803+
{title && <Panel className={cls(`${prefixCls}-title`, classNames?.title)} style={styles?.title}>{title(mergedData)}</Panel>}
804+
<div ref={scrollBodyContainerRef} className={cls(`${prefixCls}-container`, classNames?.section)} style={styles?.section}>
797805
{groupTableNode}
798806
</div>
799-
{footer && <Panel className={`${prefixCls}-footer`}>{footer(mergedData)}</Panel>}
807+
{footer && <Panel className={cls(`${prefixCls}-footer`, classNames?.footer)} style={styles?.footer}>{footer(mergedData)}</Panel>}
800808
</div>
801809
);
802810

@@ -812,6 +820,9 @@ function Table<RecordType extends DefaultRecordType>(
812820
scrollX: mergedScrollX,
813821
scrollInfo,
814822

823+
classNames,
824+
styles,
825+
815826
// Table
816827
prefixCls,
817828
getComponent,

src/context/TableContext.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import type {
1414
TriggerEventHandler,
1515
} from '../interface';
1616
import type { FixedInfo } from '../utils/fixUtil';
17+
import { SemanticName } from '../Table';
1718

1819
const { makeImmutable, responseImmutable, useImmutableMark } = createImmutable();
1920
export { makeImmutable, responseImmutable, useImmutableMark };
@@ -23,6 +24,9 @@ export type ScrollInfoType = [scrollLeft: number, scrollRange: number];
2324
export interface TableContextProps<RecordType = any> {
2425
// Scroll
2526
scrollX: number | string | true;
27+
style?: React.CSSProperties;
28+
classNames?: Partial<Record<SemanticName, string>>;
29+
styles?: Partial<Record<SemanticName, React.CSSProperties>>;
2630

2731
// Table
2832
prefixCls: string;

tests/semantic.spec.tsx

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { render, fireEvent } from '@testing-library/react';
2+
import React from 'react';
3+
import Table, { TableProps } from '../src';
4+
describe('support classNames and styles', () => {
5+
const columns: TableProps['columns'] = [
6+
{
7+
title: 'title1',
8+
dataIndex: 'a',
9+
className: 'a',
10+
key: 'a',
11+
width: 100,
12+
},
13+
{
14+
title: 'title2',
15+
dataIndex: 'b',
16+
className: 'b',
17+
key: 'b',
18+
width: 100,
19+
},
20+
{
21+
title: 'title3',
22+
dataIndex: 'c',
23+
className: 'c',
24+
key: 'c',
25+
width: 200,
26+
},
27+
{
28+
title: 'Operations',
29+
dataIndex: '',
30+
className: 'd',
31+
key: 'd',
32+
render() {
33+
return <a href="#">Operations</a>;
34+
},
35+
},
36+
];
37+
38+
const data = [
39+
{ a: '123', key: '1' },
40+
{ a: 'cdd', b: 'edd', key: '2' },
41+
{ a: '1333', c: 'eee', d: 2, key: '3' },
42+
];
43+
const commonTableProps = {
44+
columns: columns,
45+
rowClassName: (record, i) => `row-${i}`,
46+
expandedRowRender: (record) => <p>extra: {record.a}</p>,
47+
expandedRowClassName: (record, i) => `ex-row-${i}`,
48+
className: "table",
49+
title: () => <span>title</span>,
50+
footer: () => <span>footer</span>,
51+
};
52+
it('should support className and style', () => {
53+
const testClassNames = {
54+
section: 'test-section',
55+
header: 'test-header',
56+
title: 'test-title',
57+
body: 'test-body',
58+
footer: 'test-footer',
59+
content: 'test-content',
60+
item: 'test-item',
61+
}
62+
const testStyles = {
63+
section: { background: 'red' },
64+
header: { background: 'blue' },
65+
title: { background: 'green' },
66+
body: { background: 'yellow' },
67+
footer: { background: 'pink' },
68+
content: { background: 'purple' },
69+
item: { background: 'orange' },
70+
}
71+
const { container } = render(
72+
<Table
73+
{...commonTableProps}
74+
classNames={testClassNames}
75+
styles={testStyles}
76+
data={data}
77+
/>
78+
)
79+
const section = container.querySelector('.rc-table-container');
80+
const title = container.querySelector('.rc-table-title');
81+
const footer = container.querySelector('.rc-table-footer');
82+
const content = container.querySelector('.rc-table-content');
83+
const item = container.querySelector('.rc-table-cell');
84+
expect(section).toHaveClass(testClassNames.section);
85+
expect(section).toHaveStyle(testStyles.section);
86+
expect(title).toHaveClass(testClassNames.title);
87+
expect(title).toHaveStyle(testStyles.title);
88+
expect(footer).toHaveClass(testClassNames.footer);
89+
expect(footer).toHaveStyle(testStyles.footer);
90+
expect(content).toHaveClass(testClassNames.content);
91+
expect(content).toHaveStyle(testStyles.content);
92+
expect(item).toHaveClass(testClassNames.item);
93+
expect(item).toHaveStyle(testStyles.item);
94+
95+
const { container: scrollContainer } = render(
96+
<Table
97+
{...commonTableProps}
98+
classNames={testClassNames}
99+
styles={testStyles}
100+
data={data}
101+
scroll={{ y: 200 }}
102+
/>
103+
)
104+
const header = scrollContainer.querySelector('.rc-table-header');
105+
const body = scrollContainer.querySelector('.rc-table-body');
106+
expect(header).toHaveClass(testClassNames.header);
107+
expect(header).toHaveStyle(testStyles.header);
108+
expect(body).toHaveClass(testClassNames.body);
109+
expect(body).toHaveStyle(testStyles.body);
110+
})
111+
})
112+

0 commit comments

Comments
 (0)