Skip to content

Commit 9d743a2

Browse files
authored
refactor: Support all type of shadow (#1238)
* chore: tmp check for fixed * chore: add zIndex placeholder * docs: update demo * chore: add scrollInfo context * chore: add comment * chore: fixed it * chore: clean up * chore: clean up * chore: fix ci * test: update snapshot * test: fix test case * chore: opt code * test: fix test case * test: fix test case * chore: clean up * test: fix test case * test: fix test case * test: clean up
1 parent 15658cc commit 9d743a2

24 files changed

+470
-12340
lines changed

assets/index.less

Lines changed: 22 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -56,76 +56,37 @@
5656
}
5757

5858
// ================== Cell ==================
59-
&-fixed-column-gapped {
60-
.@{tablePrefixCls}-cell-fix-left-last::after,
61-
.@{tablePrefixCls}-cell-fix-right-first::after {
62-
display: none !important;
63-
}
64-
}
65-
6659
&-cell {
6760
background: #f4f4f4;
6861

69-
&-fix-left,
70-
&-fix-right {
71-
z-index: 2;
62+
&-fix {
63+
position: sticky !important;
64+
z-index: calc(2 + var(--z-offset));
7265
}
7366

74-
&-fix-right:last-child:not(&-fix-sticky) {
75-
border-right-color: transparent;
76-
}
77-
78-
.@{tablePrefixCls}-rtl & {
79-
&-fix-right:last-child {
80-
border-right-color: @border-color;
81-
}
82-
&-fix-left:last-child {
83-
border-left-color: transparent;
67+
&-fix-start-shadow,
68+
&-fix-end-shadow {
69+
&::after {
70+
position: absolute;
71+
top: 0;
72+
bottom: 0;
73+
width: 5px;
74+
background: rgba(0, 0, 0, 0.5);
75+
opacity: 0;
76+
content: '';
77+
transition: opacity 0.3s;
8478
}
85-
}
8679

87-
&-fix-left-first {
88-
.@{tablePrefixCls}-rtl & {
89-
box-shadow: 1px 0 0 @border-color;
80+
&-show::after {
81+
opacity: 1;
9082
}
9183
}
9284

93-
&-fix-left-first::after,
94-
&-fix-left-last::after {
95-
position: absolute;
96-
top: 0;
97-
right: -1px;
98-
bottom: -1px;
99-
width: 20px;
100-
transform: translateX(100%);
101-
transition: box-shadow 0.3s;
102-
content: '';
103-
pointer-events: none;
104-
}
105-
106-
&-fix-left-all::after {
107-
display: none;
85+
&-fix-start-shadow::after {
86+
inset-inline-start: 100%;
10887
}
109-
110-
&-fix-right-first,
111-
&-fix-right-last {
112-
box-shadow: -1px 0 0 @border-color;
113-
114-
.@{tablePrefixCls}-rtl & {
115-
box-shadow: none;
116-
}
117-
118-
&::after {
119-
position: absolute;
120-
top: 0;
121-
bottom: -1px;
122-
left: -1px;
123-
width: 20px;
124-
transform: translateX(-100%);
125-
transition: box-shadow 0.3s;
126-
content: '';
127-
pointer-events: none;
128-
}
88+
&-fix-end-shadow::after {
89+
inset-inline-end: 100%;
12990
}
13091

13192
&&-ellipsis {
@@ -134,9 +95,8 @@
13495
text-overflow: ellipsis;
13596

13697
// Fixed first or last should special process
137-
&.@{tablePrefixCls}-cell-fix-left-first,
138-
&.@{tablePrefixCls}-cell-fix-left-last,
139-
&.@{tablePrefixCls}-cell-fix-right-first &.@{tablePrefixCls}-cell-fix-right-last {
98+
&.@{tablePrefixCls}-cell-fix-start-shadow,
99+
&.@{tablePrefixCls}-cell-fix-end-shadow {
140100
overflow: visible;
141101

142102
.@{tablePrefixCls}-cell-content {

docs/examples/fixedColumns.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ const columns: ColumnType<RecordType>[] = [
3434
{ title: 'title8', dataIndex: 'b', key: 'h' },
3535
{ title: 'title9', dataIndex: 'b', key: 'i' },
3636
{ title: 'title10', dataIndex: 'b', key: 'j' },
37-
{ title: 'title11', dataIndex: 'b', key: 'k', width: 50 },
37+
{ title: 'title11', dataIndex: 'b', key: 'k', width: 50, fixed: 'right' },
3838
{ title: 'title12', dataIndex: 'b', key: 'l', width: 100, fixed: 'right' },
3939
];
4040

docs/examples/scrollXY.tsx

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,18 @@ import Table from 'rc-table';
44
import '../../assets/index.less';
55

66
const columns: TableProps['columns'] = [
7-
{ title: 'title1', dataIndex: 'a', key: 'a', width: 100 },
7+
{ title: 'title1', dataIndex: 'a', key: 'a', width: 100, fixed: 'start' },
88
{ title: 'title2', dataIndex: 'b', key: 'b', width: 100 },
9-
{ title: 'title3', dataIndex: 'c', key: 'c', width: 100 },
9+
{ title: 'title3', dataIndex: 'c', key: 'c', width: 100, fixed: 'start' },
1010
{ title: 'title4', dataIndex: 'b', key: 'd', width: 100 },
1111
{ title: 'title5', dataIndex: 'b', key: 'e', width: 100 },
1212
{ title: 'title6', dataIndex: 'b', key: 'f', width: 100 },
1313
{ title: 'title7', dataIndex: 'b', key: 'g', width: 100 },
1414
{ title: 'title8', dataIndex: 'b', key: 'h', width: 100 },
1515
{ title: 'title9', dataIndex: 'b', key: 'i', width: 100 },
16-
{ title: 'title10', dataIndex: 'b', key: 'j', width: 100 },
16+
{ title: 'title10', dataIndex: 'b', key: 'j', width: 100, fixed: 'end' },
1717
{ title: 'title11', dataIndex: 'b', key: 'k', width: 100 },
18-
{ title: 'title12', dataIndex: 'b', key: 'l', width: 100 },
18+
{ title: 'title12', dataIndex: 'b', key: 'l', width: 100, fixed: 'end' },
1919
];
2020

2121
const data = [
@@ -32,6 +32,8 @@ const data = [
3232

3333
const Demo = () => {
3434
const [visible, setVisible] = React.useState(true);
35+
const [rtl, setRtl] = React.useState(true);
36+
3537
return (
3638
<div>
3739
<h2>Scroll X/Y</h2>
@@ -43,8 +45,23 @@ const Demo = () => {
4345
>
4446
Trigger Visible
4547
</button>
48+
<button
49+
type="button"
50+
onClick={() => {
51+
setRtl(!rtl);
52+
}}
53+
>
54+
{rtl ? 'RTL' : 'LTR'}
55+
</button>
56+
4657
<div style={{ display: visible ? undefined : 'none' }}>
47-
<Table style={{ width: 800 }} scroll={{ x: 1500, y: 300 }} columns={columns} data={data} />
58+
<Table
59+
direction={rtl ? 'rtl' : 'ltr'}
60+
style={{ width: 800 }}
61+
scroll={{ x: 1500, y: 300 }}
62+
columns={columns}
63+
data={data}
64+
/>
4865
</div>
4966
</div>
5067
);

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,6 @@
7171
"@types/styled-components": "^5.1.32",
7272
"@umijs/fabric": "^4.0.1",
7373
"@vitest/coverage-v8": "^2.0.5",
74-
"cheerio": "1.0.0-rc.12",
7574
"cross-env": "^7.0.0",
7675
"dumi": "^2.1.3",
7776
"eslint": "^8.54.0",

src/Cell/index.tsx

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,11 @@ export interface CellProps<RecordType extends DefaultRecordType> {
3737
shouldCellUpdate?: (record: RecordType, prevRecord: RecordType) => boolean;
3838

3939
// Fixed
40-
fixLeft?: number | false;
41-
fixRight?: number | false;
42-
firstFixLeft?: boolean;
43-
lastFixLeft?: boolean;
44-
firstFixRight?: boolean;
45-
lastFixRight?: boolean;
40+
fixStart?: number | false;
41+
fixEnd?: number | false;
42+
fixedStartShadow?: boolean;
43+
fixedEndShadow?: boolean;
44+
zIndex?: number;
4645
allColsFixedLeft?: boolean;
4746

4847
// ====================== Private Props ======================
@@ -104,12 +103,11 @@ function Cell<RecordType>(props: CellProps<RecordType>) {
104103
rowSpan,
105104

106105
// Fixed
107-
fixLeft,
108-
fixRight,
109-
firstFixLeft,
110-
lastFixLeft,
111-
firstFixRight,
112-
lastFixRight,
106+
fixStart,
107+
fixEnd,
108+
fixedStartShadow,
109+
fixedEndShadow,
110+
zIndex,
113111

114112
// Private
115113
appendNode,
@@ -118,8 +116,7 @@ function Cell<RecordType>(props: CellProps<RecordType>) {
118116
} = props;
119117

120118
const cellPrefixCls = `${prefixCls}-cell`;
121-
const { supportSticky, allColumnsFixedLeft, rowHoverable } = useContext(TableContext, [
122-
'supportSticky',
119+
const { allColumnsFixedLeft, rowHoverable } = useContext(TableContext, [
123120
'allColumnsFixedLeft',
124121
'rowHoverable',
125122
]);
@@ -136,16 +133,31 @@ function Cell<RecordType>(props: CellProps<RecordType>) {
136133

137134
// ====================== Fixed =======================
138135
const fixedStyle: React.CSSProperties = {};
139-
const isFixLeft = typeof fixLeft === 'number' && supportSticky;
140-
const isFixRight = typeof fixRight === 'number' && supportSticky;
136+
const isFixStart = typeof fixStart === 'number' && !allColumnsFixedLeft;
137+
const isFixEnd = typeof fixEnd === 'number' && !allColumnsFixedLeft;
141138

142-
if (isFixLeft) {
143-
fixedStyle.position = 'sticky';
144-
fixedStyle.left = fixLeft as number;
139+
const [showFixStartShadow, showFixEndShadow] = useContext(TableContext, ({ scrollInfo }) => {
140+
if (!isFixStart && !isFixEnd) {
141+
return [false, false];
142+
}
143+
144+
const [scroll, scrollWidth] = scrollInfo;
145+
146+
const absScroll = Math.abs(scroll);
147+
148+
const showStartShadow = isFixStart && fixedStartShadow && absScroll > fixStart;
149+
const showEndShadow = isFixEnd && fixedEndShadow && scrollWidth - absScroll > fixEnd;
150+
151+
return [showStartShadow, showEndShadow];
152+
});
153+
154+
if (isFixStart) {
155+
fixedStyle.insetInlineStart = fixStart as number;
156+
fixedStyle['--z-offset'] = zIndex;
145157
}
146-
if (isFixRight) {
147-
fixedStyle.position = 'sticky';
148-
fixedStyle.right = fixRight as number;
158+
if (isFixEnd) {
159+
fixedStyle.insetInlineEnd = fixEnd as number;
160+
fixedStyle['--z-offset'] = zIndex;
149161
}
150162

151163
// ================ RowSpan & ColSpan =================
@@ -190,16 +202,20 @@ function Cell<RecordType>(props: CellProps<RecordType>) {
190202
cellPrefixCls,
191203
className,
192204
{
193-
[`${cellPrefixCls}-fix-left`]: isFixLeft && supportSticky,
194-
[`${cellPrefixCls}-fix-left-first`]: firstFixLeft && supportSticky,
195-
[`${cellPrefixCls}-fix-left-last`]: lastFixLeft && supportSticky,
196-
[`${cellPrefixCls}-fix-left-all`]: lastFixLeft && allColumnsFixedLeft && supportSticky,
197-
[`${cellPrefixCls}-fix-right`]: isFixRight && supportSticky,
198-
[`${cellPrefixCls}-fix-right-first`]: firstFixRight && supportSticky,
199-
[`${cellPrefixCls}-fix-right-last`]: lastFixRight && supportSticky,
205+
// Fixed
206+
[`${cellPrefixCls}-fix`]: isFixStart || isFixEnd,
207+
[`${cellPrefixCls}-fix-start`]: isFixStart,
208+
[`${cellPrefixCls}-fix-end`]: isFixEnd,
209+
210+
// Fixed shadow
211+
[`${cellPrefixCls}-fix-start-shadow`]: fixedStartShadow,
212+
[`${cellPrefixCls}-fix-start-shadow-show`]: fixedStartShadow && showFixStartShadow,
213+
[`${cellPrefixCls}-fix-end-shadow`]: fixedEndShadow,
214+
[`${cellPrefixCls}-fix-end-shadow-show`]: fixedEndShadow && showFixEndShadow,
215+
200216
[`${cellPrefixCls}-ellipsis`]: ellipsis,
201217
[`${cellPrefixCls}-with-append`]: appendNode,
202-
[`${cellPrefixCls}-fix-sticky`]: (isFixLeft || isFixRight) && isSticky && supportSticky,
218+
[`${cellPrefixCls}-fix-sticky`]: (isFixStart || isFixEnd) && isSticky,
203219
[`${cellPrefixCls}-row-hover`]: !legacyCellProps && hovering,
204220
},
205221
additionalProps.className,
@@ -233,7 +249,7 @@ function Cell<RecordType>(props: CellProps<RecordType>) {
233249
mergedChildNode = null;
234250
}
235251

236-
if (ellipsis && (lastFixLeft || firstFixRight)) {
252+
if (ellipsis && (fixedStartShadow || fixedEndShadow)) {
237253
mergedChildNode = <span className={`${cellPrefixCls}-content`}>{mergedChildNode}</span>;
238254
}
239255

src/FixedHolder/index.tsx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,22 @@ const FixedHolder = React.forwardRef<HTMLDivElement, FixedHeaderProps<any>>((pro
8585
function onWheel(e: WheelEvent) {
8686
const { currentTarget, deltaX } = e as unknown as React.WheelEvent<HTMLDivElement>;
8787
if (deltaX) {
88-
onScroll({ currentTarget, scrollLeft: currentTarget.scrollLeft + deltaX });
88+
const { scrollLeft, scrollWidth, clientWidth } = currentTarget;
89+
const maxScrollWidth = scrollWidth - clientWidth;
90+
let nextScroll = scrollLeft + deltaX;
91+
92+
if (direction === 'rtl') {
93+
nextScroll = Math.max(-maxScrollWidth, nextScroll);
94+
nextScroll = Math.min(0, nextScroll);
95+
} else {
96+
nextScroll = Math.min(maxScrollWidth, nextScroll);
97+
nextScroll = Math.max(0, nextScroll);
98+
}
99+
100+
onScroll({
101+
currentTarget,
102+
scrollLeft: nextScroll,
103+
});
89104
e.preventDefault();
90105
}
91106
}
@@ -124,13 +139,15 @@ const FixedHolder = React.forwardRef<HTMLDivElement, FixedHeaderProps<any>>((pro
124139

125140
// Calculate the sticky offsets
126141
const headerStickyOffsets = useMemo(() => {
127-
const { right, left } = stickyOffsets;
142+
const { start, end } = stickyOffsets;
128143
return {
129144
...stickyOffsets,
130-
left:
131-
direction === 'rtl' ? [...left.map(width => width + combinationScrollBarSize), 0] : left,
132-
right:
133-
direction === 'rtl' ? right : [...right.map(width => width + combinationScrollBarSize), 0],
145+
// left:
146+
// direction === 'rtl' ? [...left.map(width => width + combinationScrollBarSize), 0] : left,
147+
// right:
148+
// direction === 'rtl' ? right : [...right.map(width => width + combinationScrollBarSize), 0],
149+
start: start,
150+
end: [...end.map(width => width + combinationScrollBarSize), 0],
134151
isSticky,
135152
};
136153
}, [combinationScrollBarSize, stickyOffsets, isSticky]);

src/Footer/Cell.tsx

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,14 @@ export default function SummaryCell({
2323
rowSpan,
2424
align,
2525
}: SummaryCellProps) {
26-
const { prefixCls, direction } = useContext(TableContext, ['prefixCls', 'direction']);
26+
const { prefixCls } = useContext(TableContext, ['prefixCls']);
2727
const { scrollColumnIndex, stickyOffsets, flattenColumns } = React.useContext(SummaryContext);
2828
const lastIndex = index + colSpan - 1;
2929
const mergedColSpan = lastIndex + 1 === scrollColumnIndex ? colSpan + 1 : colSpan;
3030

31-
const fixedInfo = getCellFixedInfo(
32-
index,
33-
index + mergedColSpan - 1,
34-
flattenColumns,
35-
stickyOffsets,
36-
direction,
31+
const fixedInfo = React.useMemo(
32+
() => getCellFixedInfo(index, index + mergedColSpan - 1, flattenColumns, stickyOffsets),
33+
[index, mergedColSpan, flattenColumns, stickyOffsets],
3734
);
3835

3936
return (

src/Header/HeaderRow.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const HeaderRow = <RecordType extends any>(props: RowProps<RecordType>) => {
3232
onHeaderRow,
3333
index,
3434
} = props;
35-
const { prefixCls, direction } = useContext(TableContext, ['prefixCls', 'direction']);
35+
const { prefixCls } = useContext(TableContext, ['prefixCls']);
3636
let rowProps: React.HTMLAttributes<HTMLElement>;
3737
if (onHeaderRow) {
3838
rowProps = onHeaderRow(
@@ -52,7 +52,6 @@ const HeaderRow = <RecordType extends any>(props: RowProps<RecordType>) => {
5252
cell.colEnd,
5353
flattenColumns,
5454
stickyOffsets,
55-
direction,
5655
);
5756

5857
let additionalProps: React.HTMLAttributes<HTMLElement>;

0 commit comments

Comments
 (0)