Skip to content

Commit 6986eb9

Browse files
authored
Add rtl direction (#426)
* add rtl direction * auto change fixed left to right * remove redundant code * add some tests * some changes to useColumns.tsx * fix test coverage issue
1 parent c098e7a commit 6986eb9

File tree

15 files changed

+963
-31
lines changed

15 files changed

+963
-31
lines changed

assets/index.less

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
box-sizing: border-box;
2626
position: relative;
2727

28+
&-rtl {
29+
direction: rtl;
30+
}
2831
// ================= Global =================
2932
table {
3033
border-spacing: 0px;
@@ -45,6 +48,10 @@
4548
box-sizing: border-box;
4649
white-space: normal;
4750
word-break: break-word;
51+
.@{tablePrefixCls}-rtl& {
52+
border-left: @border;
53+
border-right: 0;
54+
}
4855
}
4956

5057
// ================== Cell ==================
@@ -58,6 +65,22 @@
5865
border-right-color: transparent;
5966
}
6067

68+
.@{tablePrefixCls}-rtl & {
69+
&-fix-right:last-child {
70+
border-right-color: @border-color;
71+
}
72+
&-fix-left:last-child {
73+
border-left-color: transparent;
74+
}
75+
}
76+
77+
&-fix-left-first {
78+
.@{tablePrefixCls}-rtl & {
79+
box-shadow: 1px 0 0 @border-color;
80+
}
81+
}
82+
83+
&-fix-left-first::after,
6184
&-fix-left-last::after {
6285
pointer-events: none;
6386
content: '';
@@ -70,9 +93,14 @@
7093
transform: translateX(100%);
7194
}
7295

73-
&-fix-right-first {
96+
&-fix-right-first,
97+
&-fix-right-last {
7498
box-shadow: -1px 0 0 @border-color;
7599

100+
.@{tablePrefixCls}-rtl & {
101+
box-shadow: none;
102+
}
103+
76104
&::after {
77105
pointer-events: none;
78106
content: '';
@@ -92,8 +120,9 @@
92120
text-overflow: ellipsis;
93121

94122
// Fixed first or last should special process
123+
&.@{tablePrefixCls}-cell-fix-left-first,
95124
&.@{tablePrefixCls}-cell-fix-left-last,
96-
&.@{tablePrefixCls}-cell-fix-right-first {
125+
&.@{tablePrefixCls}-cell-fix-right-first &.@{tablePrefixCls}-cell-fix-right-last {
97126
overflow: visible;
98127

99128
.@{tablePrefixCls}-cell-content {
@@ -106,13 +135,15 @@
106135
}
107136

108137
&-ping-left {
138+
.@{tablePrefixCls}-cell-fix-left-first::after,
109139
.@{tablePrefixCls}-cell-fix-left-last::after {
110140
box-shadow: inset 10px 0 8px -8px green;
111141
}
112142
}
113143

114144
&-ping-right {
115-
.@{tablePrefixCls}-cell-fix-right-first::after {
145+
.@{tablePrefixCls}-cell-fix-right-first::after,
146+
.@{tablePrefixCls}-cell-fix-right-last::after {
116147
box-shadow: inset -10px 0 8px -8px green;
117148
}
118149
}
@@ -142,6 +173,11 @@
142173
left: -1px;
143174
width: 1px;
144175
background: @table-head-background-color;
176+
177+
.@{tablePrefixCls}-rtl& {
178+
right: -1px;
179+
left: auto;
180+
}
145181
}
146182
}
147183

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import React from 'react';
2+
import Table from '../src';
3+
import '../assets/index.less';
4+
import { ColumnsType } from '../src/interface';
5+
import { useCheckbox } from './utils/useInput';
6+
7+
interface RecordType {
8+
a: string;
9+
b?: string;
10+
c: string;
11+
d: number;
12+
key: string;
13+
}
14+
15+
const originData: RecordType[] = [
16+
{ a: 'aaa', b: 'bbb', c: '内容内容内容内容内容', d: 3, key: '1' },
17+
{ a: 'aaa', b: 'bbb', c: '内容内容内容内容内容', d: 3, key: '2' },
18+
{ a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '3' },
19+
{ a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '4' },
20+
{ a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '5' },
21+
{ a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '6' },
22+
{ a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '7' },
23+
{ a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '8' },
24+
{ a: 'aaa', c: '内容内容内容内容内容', d: 2, key: '9' },
25+
];
26+
27+
const longTextData: RecordType[] = [...originData];
28+
longTextData[0] = {
29+
...longTextData[0],
30+
a: 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa',
31+
};
32+
33+
const useColumn = (
34+
fixLeft: boolean,
35+
fixTitle: boolean,
36+
fixRight: boolean,
37+
ellipsis: boolean,
38+
percentage: boolean,
39+
) => {
40+
const columns: ColumnsType<RecordType> = React.useMemo(
41+
() => [
42+
{
43+
title: 'title1',
44+
dataIndex: 'a',
45+
key: 'a',
46+
width: percentage ? '10%' : 80,
47+
fixed: fixLeft ? 'left' : null,
48+
ellipsis,
49+
},
50+
{ title: 'title2', dataIndex: 'b', key: 'b', width: 80, fixed: fixLeft ? 'left' : null },
51+
{
52+
title: 'title3',
53+
fixed: fixLeft && fixTitle ? 'left' : null,
54+
children: [
55+
{ title: 'title4', dataIndex: 'c', key: 'd', width: 100 },
56+
{ title: 'title5', dataIndex: 'c', key: 'e', width: 100 },
57+
],
58+
},
59+
{ title: 'title6', dataIndex: 'c', key: 'f' },
60+
{ title: 'title7', dataIndex: 'c', key: 'g' },
61+
{ title: 'title8', dataIndex: 'c', key: 'h' },
62+
{ title: 'title9', dataIndex: 'b', key: 'i' },
63+
{ title: 'title10', dataIndex: 'b', key: 'j' },
64+
{ title: 'title11', dataIndex: 'b', key: 'k', width: 100, fixed: fixRight ? 'right' : null },
65+
{ title: 'title12', dataIndex: 'b', key: 'l', width: 80, fixed: fixRight ? 'right' : null },
66+
],
67+
[fixLeft, fixTitle, fixRight, ellipsis, percentage],
68+
);
69+
70+
return columns;
71+
};
72+
73+
const Demo = () => {
74+
const [autoWidth, autoWidthProps] = useCheckbox(false);
75+
const [isRtl, isRtlProps] = useCheckbox(true);
76+
const [longText, longTextProps] = useCheckbox(false);
77+
const [fixHeader, fixHeaderProps] = useCheckbox(true);
78+
const [fixLeft, fixLeftProps] = useCheckbox(true);
79+
const [fixRight, fixRightProps] = useCheckbox(true);
80+
const [fixTitle3, fixTitle3Props] = useCheckbox(false);
81+
const [ellipsis, ellipsisProps] = useCheckbox(false);
82+
const [percentage, percentageProps] = useCheckbox(false);
83+
const [empty, emptyProps] = useCheckbox(false);
84+
const columns = useColumn(fixLeft, fixTitle3, fixRight, ellipsis, percentage);
85+
86+
let mergedData: RecordType[];
87+
if (empty) {
88+
mergedData = null;
89+
} else if (longText) {
90+
mergedData = longTextData;
91+
} else {
92+
mergedData = originData;
93+
}
94+
95+
return (
96+
<React.StrictMode>
97+
<div>
98+
<h2>Fixed columns and header in RTL direction</h2>
99+
100+
<label>
101+
<input {...isRtlProps} />
102+
IsRtl
103+
</label>
104+
<label>
105+
<input {...autoWidthProps} />
106+
Auto Width
107+
</label>
108+
<label>
109+
<input {...longTextProps} />
110+
Long Text
111+
</label>
112+
<label>
113+
<input {...fixHeaderProps} />
114+
Fix Header
115+
</label>
116+
<label>
117+
<input {...fixLeftProps} />
118+
Fix Left
119+
</label>
120+
<label>
121+
<input {...fixTitle3Props} />
122+
Fix title3
123+
</label>
124+
<label>
125+
<input {...fixRightProps} />
126+
Fix Right
127+
</label>
128+
<label>
129+
<input {...ellipsisProps} />
130+
Ellipsis First Column
131+
</label>
132+
<label>
133+
<input {...percentageProps} />
134+
Percentage Width
135+
</label>
136+
<label>
137+
<input {...emptyProps} />
138+
Empty
139+
</label>
140+
141+
<Table<RecordType>
142+
columns={columns}
143+
scroll={{ x: 1650, y: fixHeader ? 300 : null }}
144+
data={mergedData}
145+
style={{ width: autoWidth ? null : 800 }}
146+
direction={isRtl ? 'rtl' : 'ltr'}
147+
/>
148+
</div>
149+
</React.StrictMode>
150+
);
151+
};
152+
153+
export default Demo;

src/Body/BodyRow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ function BodyRow<RecordType extends { children?: RecordType[] }>(props: BodyRowP
4949
cellComponent,
5050
childrenColumnName,
5151
} = props;
52-
const { prefixCls } = React.useContext(TableContext);
52+
const { prefixCls, direction } = React.useContext(TableContext);
5353
const {
5454
fixHeader,
5555
fixColumn,
@@ -77,7 +77,7 @@ function BodyRow<RecordType extends { children?: RecordType[] }>(props: BodyRowP
7777

7878
// Move to Body to enhance performance
7979
const fixedInfoList = flattenColumns.map((column, colIndex) =>
80-
getCellFixedInfo(colIndex, colIndex, flattenColumns, stickyOffsets),
80+
getCellFixedInfo(colIndex, colIndex, flattenColumns, stickyOffsets, direction),
8181
);
8282

8383
const rowSupportExpand = expandableType === 'row' && (!rowExpandable || rowExpandable(record));

src/Cell/index.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,10 @@ export interface CellProps<RecordType extends DefaultRecordType> {
4444
// Fixed
4545
fixLeft?: number | false;
4646
fixRight?: number | false;
47+
firstFixLeft?: boolean;
4748
lastFixLeft?: boolean;
4849
firstFixRight?: boolean;
50+
lastFixRight?: boolean;
4951

5052
// Additional
5153
/** @private Used for `expandable` with nest tree */
@@ -67,8 +69,10 @@ function Cell<RecordType extends DefaultRecordType>(
6769
rowSpan,
6870
fixLeft,
6971
fixRight,
72+
firstFixLeft,
7073
lastFixLeft,
7174
firstFixRight,
75+
lastFixRight,
7276
appendNode,
7377
additionalProps = {},
7478
ellipsis,
@@ -134,6 +138,7 @@ function Cell<RecordType extends DefaultRecordType>(
134138
}
135139
if (isFixRight) {
136140
fixedStyle.position = 'sticky';
141+
137142
fixedStyle.right = fixRight as number;
138143
}
139144

@@ -163,9 +168,11 @@ function Cell<RecordType extends DefaultRecordType>(
163168
className,
164169
{
165170
[`${cellPrefixCls}-fix-left`]: isFixLeft,
171+
[`${cellPrefixCls}-fix-left-first`]: firstFixLeft,
166172
[`${cellPrefixCls}-fix-left-last`]: lastFixLeft,
167173
[`${cellPrefixCls}-fix-right`]: isFixRight,
168174
[`${cellPrefixCls}-fix-right-first`]: firstFixRight,
175+
[`${cellPrefixCls}-fix-right-last`]: lastFixRight,
169176
[`${cellPrefixCls}-ellipsis`]: ellipsis,
170177
[`${cellPrefixCls}-with-append`]: appendNode,
171178
},

src/Header/FixedHeader.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import TableContext from '../context/TableContext';
77
export interface FixedHeaderProps<RecordType> extends HeaderProps<RecordType> {
88
colWidths: number[];
99
columCount: number;
10+
direction: 'ltr' | 'rtl';
1011
}
1112

1213
function FixedHeader<RecordType>({
@@ -15,6 +16,7 @@ function FixedHeader<RecordType>({
1516
colWidths,
1617
columCount,
1718
stickyOffsets,
19+
direction,
1820
...props
1921
}: FixedHeaderProps<RecordType>) {
2022
const { prefixCls, scrollbarSize } = React.useContext(TableContext);
@@ -40,11 +42,11 @@ function FixedHeader<RecordType>({
4042

4143
// Calculate the sticky offsets
4244
const headerStickyOffsets = React.useMemo(() => {
43-
const { right } = stickyOffsets;
44-
45+
const { right, left } = stickyOffsets;
4546
return {
4647
...stickyOffsets,
47-
right: [...right.map(width => width + scrollbarSize), 0],
48+
left: direction === 'rtl' ? [...left.map(width => width + scrollbarSize), 0] : left,
49+
right: direction === 'rtl' ? right : [...right.map(width => width + scrollbarSize), 0],
4850
};
4951
}, [scrollbarSize, stickyOffsets]);
5052

src/Header/HeaderRow.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function HeaderRow<RecordType>({
3030
onHeaderRow,
3131
index,
3232
}: RowProps<RecordType>) {
33-
const { prefixCls } = React.useContext(TableContext);
33+
const { prefixCls, direction } = React.useContext(TableContext);
3434

3535
let rowProps: React.HTMLAttributes<HTMLElement>;
3636
if (onHeaderRow) {
@@ -48,6 +48,7 @@ function HeaderRow<RecordType>({
4848
cell.colEnd,
4949
flattenColumns,
5050
stickyOffsets,
51+
direction,
5152
);
5253

5354
let additionalProps: React.HTMLAttributes<HTMLElement>;

0 commit comments

Comments
 (0)