Skip to content

Commit 8f94f6f

Browse files
Added feature to right side freeze columnj
1 parent 565107e commit 8f94f6f

14 files changed

+341
-111
lines changed

packages/core/src/data-editor/data-editor.tsx

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,9 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
884884
const maxColumnWidth = Math.max(maxColumnWidthIn, minColumnWidth);
885885
const maxColumnAutoWidth = Math.max(maxColumnAutoWidthIn ?? maxColumnWidth, minColumnWidth);
886886

887+
const freezeLeftColumns = typeof freezeColumns === "number" ? freezeColumns: freezeColumns[0];
888+
const freezeRightColumns = typeof freezeColumns === "number" ? 0 : freezeColumns[1];
889+
887890
const docStyle = React.useMemo(() => {
888891
if (typeof window === "undefined") return { fontSize: "16px" };
889892
return window.getComputedStyle(document.documentElement);
@@ -1533,9 +1536,13 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
15331536
height: targetRect.height + 2 * paddingY,
15341537
};
15351538

1536-
let frozenWidth = 0;
1537-
for (let i = 0; i < freezeColumns; i++) {
1538-
frozenWidth += columns[i].width;
1539+
let frozenLeftWidth = 0;
1540+
for (let i = 0; i < freezeLeftColumns; i++) {
1541+
frozenLeftWidth += columns[i].width;
1542+
}
1543+
let frozenRightWidth = 0;
1544+
for (let i = mangledCols.length - 1; i >= mangledCols.length - freezeRightColumns; i--) {
1545+
frozenRightWidth += columns[i].width;
15391546
}
15401547
let trailingRowHeight = 0;
15411548
const freezeTrailingRowsEffective = freezeTrailingRows + (lastRowSticky ? 1 : 0);
@@ -1548,8 +1555,8 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
15481555
}
15491556

15501557
// scrollBounds is already scaled
1551-
let sLeft = frozenWidth * scale + scrollBounds.left + rowMarkerOffset * rowMarkerWidth * scale;
1552-
let sRight = scrollBounds.right;
1558+
let sLeft = frozenLeftWidth * scale + scrollBounds.left + rowMarkerOffset * rowMarkerWidth * scale;
1559+
let sRight = scrollBounds.right - frozenRightWidth * scale;
15531560
let sTop = scrollBounds.top + totalHeaderHeight * scale;
15541561
let sBottom = scrollBounds.bottom - trailingRowHeight * scale;
15551562

@@ -1593,7 +1600,11 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
15931600
scrollY = bounds.y + bounds.height - sBottom;
15941601
}
15951602

1596-
if (dir === "vertical" || (typeof col === "number" && col < freezeColumns)) {
1603+
if (
1604+
dir === "vertical" ||
1605+
(typeof col === "number" &&
1606+
(col < freezeLeftColumns || col >= mangledCols.length - freezeRightColumns))
1607+
) {
15971608
scrollX = 0;
15981609
} else if (
15991610
dir === "horizontal" ||
@@ -1623,7 +1634,9 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
16231634
rowMarkerWidth,
16241635
scrollRef,
16251636
totalHeaderHeight,
1626-
freezeColumns,
1637+
freezeLeftColumns,
1638+
freezeRightColumns,
1639+
mangledCols.length,
16271640
columns,
16281641
mangledRows,
16291642
lastRowSticky,
@@ -2468,18 +2481,29 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
24682481
selected = [selected[0] - rowMarkerOffset, selected[1]];
24692482
}
24702483

2471-
const freezeRegion =
2472-
freezeColumns === 0
2484+
const freezeLeftRegion =
2485+
freezeLeftColumns === 0
24732486
? undefined
24742487
: {
24752488
x: 0,
24762489
y: region.y,
2477-
width: freezeColumns,
2490+
width: freezeLeftColumns,
2491+
height: region.height,
2492+
};
2493+
2494+
const freezeRightRegion =
2495+
freezeRightColumns === 0
2496+
? undefined
2497+
: {
2498+
x: columns.length - freezeRightColumns,
2499+
y: region.y,
2500+
width: freezeRightColumns,
24782501
height: region.height,
24792502
};
24802503

24812504
const freezeRegions: Rectangle[] = [];
2482-
if (freezeRegion !== undefined) freezeRegions.push(freezeRegion);
2505+
if (freezeLeftRegion !== undefined) freezeRegions.push(freezeLeftRegion);
2506+
if (freezeRightRegion !== undefined) freezeRegions.push(freezeRightRegion);
24832507
if (freezeTrailingRows > 0) {
24842508
freezeRegions.push({
24852509
x: region.x - rowMarkerOffset,
@@ -2488,11 +2512,20 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
24882512
height: freezeTrailingRows,
24892513
});
24902514

2491-
if (freezeColumns > 0) {
2515+
if (freezeLeftColumns > 0) {
24922516
freezeRegions.push({
24932517
x: 0,
24942518
y: rows - freezeTrailingRows,
2495-
width: freezeColumns,
2519+
width: freezeLeftColumns,
2520+
height: freezeTrailingRows,
2521+
});
2522+
}
2523+
2524+
if (freezeRightColumns > 0) {
2525+
freezeRegions.push({
2526+
x: columns.length - freezeRightColumns,
2527+
y: rows - freezeTrailingRows,
2528+
width: freezeRightColumns,
24962529
height: freezeTrailingRows,
24972530
});
24982531
}
@@ -2507,7 +2540,7 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
25072540
ty,
25082541
extras: {
25092542
selected,
2510-
freezeRegion,
2543+
freezeRegion: freezeLeftRegion,
25112544
freezeRegions,
25122545
},
25132546
};
@@ -2521,7 +2554,9 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
25212554
rowMarkerOffset,
25222555
showTrailingBlankRow,
25232556
rows,
2524-
freezeColumns,
2557+
freezeLeftColumns,
2558+
freezeRightColumns,
2559+
columns.length,
25252560
freezeTrailingRows,
25262561
setVisibleRegion,
25272562
onVisibleRegionChanged,
@@ -3817,7 +3852,7 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
38173852
);
38183853
}, [onGroupHeaderRenamed, renameGroup]);
38193854

3820-
const mangledFreezeColumns = Math.min(mangledCols.length, freezeColumns + (hasRowMarkers ? 1 : 0));
3855+
const mangledFreezeColumns = Math.min(mangledCols.length, freezeLeftColumns + (hasRowMarkers ? 1 : 0));
38213856

38223857
React.useImperativeHandle(
38233858
forwardedRef,
@@ -4055,7 +4090,7 @@ const DataEditorImpl: React.ForwardRefRenderFunction<DataEditorRef, DataEditorPr
40554090
onColumnProposeMove={onColumnProposeMove}
40564091
drawCell={drawCell}
40574092
disabledRows={disabledRows}
4058-
freezeColumns={mangledFreezeColumns}
4093+
freezeColumns={[mangledFreezeColumns, freezeRightColumns]}
40594094
lockColumns={rowMarkerOffset}
40604095
firstColAccessible={rowMarkerOffset === 0}
40614096
getCellContent={getMangledCellContent}

packages/core/src/docs/examples/freeze-columns.stories.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ export default {
3030
],
3131
};
3232

33-
export const FreezeColumns: React.VFC<any> = (p: { freezeColumns: number }) => {
33+
export const FreezeColumns: React.VFC<any> = (p: { freezeLeftColumns: number, freezeRightColumns: number }) => {
3434
const { cols, getCellContent } = useMockDataGenerator(100);
3535

3636
return (
3737
<DataEditor
3838
{...defaultProps}
3939
rowMarkers="both"
40-
freezeColumns={p.freezeColumns}
40+
freezeColumns={[p.freezeLeftColumns, p.freezeRightColumns]}
4141
getCellContent={getCellContent}
4242
columns={cols}
4343
verticalBorder={false}
@@ -46,7 +46,14 @@ export const FreezeColumns: React.VFC<any> = (p: { freezeColumns: number }) => {
4646
);
4747
};
4848
(FreezeColumns as any).argTypes = {
49-
freezeColumns: {
49+
freezeLeftColumns: {
50+
control: {
51+
type: "range",
52+
min: 0,
53+
max: 10,
54+
},
55+
},
56+
freezeRightColumns: {
5057
control: {
5158
type: "range",
5259
min: 0,
@@ -55,5 +62,6 @@ export const FreezeColumns: React.VFC<any> = (p: { freezeColumns: number }) => {
5562
},
5663
};
5764
(FreezeColumns as any).args = {
58-
freezeColumns: 1,
65+
freezeLeftColumns: 1,
66+
freezeRightColumns: 1,
5967
};

packages/core/src/internal/data-grid/data-grid.tsx

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ export interface DataGridProps {
7070

7171
readonly accessibilityHeight: number;
7272

73-
readonly freezeColumns: number;
73+
readonly freezeColumns: number | [left: number, right: number];
7474
readonly freezeTrailingRows: number;
7575
readonly hasAppendRow: boolean;
7676
readonly firstColAccessible: boolean;
@@ -393,7 +393,9 @@ const DataGrid: React.ForwardRefRenderFunction<DataGridRef, DataGridProps> = (p,
393393
} = p;
394394
const translateX = p.translateX ?? 0;
395395
const translateY = p.translateY ?? 0;
396-
const cellXOffset = Math.max(freezeColumns, Math.min(columns.length - 1, cellXOffsetReal));
396+
const freezeLeftColumns = typeof freezeColumns === "number" ? freezeColumns : freezeColumns[0];
397+
const freezeRightColumns = typeof freezeColumns === "number" ? 0 : freezeColumns[1];
398+
const cellXOffset = Math.max(freezeLeftColumns, Math.min(columns.length - 1, cellXOffsetReal));
397399

398400
const ref = React.useRef<HTMLCanvasElement | null>(null);
399401
const windowEventTargetRef = React.useRef<Document | Window>(window);
@@ -440,7 +442,10 @@ const DataGrid: React.ForwardRefRenderFunction<DataGridRef, DataGridProps> = (p,
440442
}, [cellYOffset, cellXOffset, translateX, translateY, enableFirefoxRescaling, enableSafariRescaling]);
441443

442444
const mappedColumns = useMappedColumns(columns, freezeColumns);
443-
const stickyX = fixedShadowX ? getStickyWidth(mappedColumns, dragAndDropState) : 0;
445+
const stickyX = React.useMemo(
446+
() => (fixedShadowX ? getStickyWidth(mappedColumns, dragAndDropState) : [0, 0]),
447+
[fixedShadowX, mappedColumns, dragAndDropState]
448+
);
444449

445450
// row: -1 === columnHeader, -2 === groupHeader
446451
const getBoundsForItem = React.useCallback(
@@ -465,7 +470,7 @@ const DataGrid: React.ForwardRefRenderFunction<DataGridRef, DataGridProps> = (p,
465470
translateX,
466471
translateY,
467472
rows,
468-
freezeColumns,
473+
freezeLeftColumns,
469474
freezeTrailingRows,
470475
mappedColumns,
471476
rowHeight
@@ -493,7 +498,7 @@ const DataGrid: React.ForwardRefRenderFunction<DataGridRef, DataGridProps> = (p,
493498
translateX,
494499
translateY,
495500
rows,
496-
freezeColumns,
501+
freezeLeftColumns,
497502
freezeTrailingRows,
498503
mappedColumns,
499504
rowHeight,
@@ -508,7 +513,14 @@ const DataGrid: React.ForwardRefRenderFunction<DataGridRef, DataGridProps> = (p,
508513
const y = (posY - rect.top) / scale;
509514
const edgeDetectionBuffer = 5;
510515

511-
const effectiveCols = getEffectiveColumns(mappedColumns, cellXOffset, width, undefined, translateX);
516+
const effectiveCols = getEffectiveColumns(
517+
mappedColumns,
518+
cellXOffset,
519+
width,
520+
freezeColumns,
521+
undefined,
522+
translateX
523+
);
512524

513525
let button = 0;
514526
let buttons = 0;
@@ -518,7 +530,7 @@ const DataGrid: React.ForwardRefRenderFunction<DataGridRef, DataGridProps> = (p,
518530
}
519531

520532
// -1 === off right edge
521-
const col = getColumnIndexForX(x, effectiveCols, translateX);
533+
const col = getColumnIndexForX(x, effectiveCols, freezeColumns, width, translateX);
522534

523535
// -1: header or above
524536
// undefined: offbottom
@@ -686,6 +698,7 @@ const DataGrid: React.ForwardRefRenderFunction<DataGridRef, DataGridProps> = (p,
686698
fillHandle,
687699
selection,
688700
totalHeaderHeight,
701+
freezeColumns,
689702
]
690703
);
691704

@@ -1717,7 +1730,14 @@ const DataGrid: React.ForwardRefRenderFunction<DataGridRef, DataGridProps> = (p,
17171730
const accessibilityTree = useDebouncedMemo(
17181731
() => {
17191732
if (width < 50 || experimental?.disableAccessibilityTree === true) return null;
1720-
let effectiveCols = getEffectiveColumns(mappedColumns, cellXOffset, width, dragAndDropState, translateX);
1733+
let effectiveCols = getEffectiveColumns(
1734+
mappedColumns,
1735+
cellXOffset,
1736+
width,
1737+
freezeColumns,
1738+
dragAndDropState,
1739+
translateX
1740+
);
17211741
const colOffset = firstColAccessible ? 0 : -1;
17221742
if (!firstColAccessible && effectiveCols[0]?.sourceIndex === 0) {
17231743
effectiveCols = effectiveCols.slice(1);
@@ -1851,33 +1871,59 @@ const DataGrid: React.ForwardRefRenderFunction<DataGridRef, DataGridProps> = (p,
18511871
onKeyDown,
18521872
getBoundsForItem,
18531873
onCellFocused,
1874+
freezeColumns,
18541875
],
18551876
200
18561877
);
18571878

1858-
const opacityX =
1859-
freezeColumns === 0 || !fixedShadowX ? 0 : cellXOffset > freezeColumns ? 1 : clamp(-translateX / 100, 0, 1);
1879+
const opacityXLeft =
1880+
freezeLeftColumns === 0 || !fixedShadowX
1881+
? 0
1882+
: cellXOffset > freezeLeftColumns
1883+
? 1
1884+
: clamp(-translateX / 100, 0, 1);
1885+
1886+
const opacityXRight =
1887+
freezeRightColumns === 0 || !fixedShadowX
1888+
? 0
1889+
: cellXOffset + width < columns.length - freezeRightColumns
1890+
? 1
1891+
: clamp((translateX - (columns.length - freezeRightColumns - width) * 32) / 100, 0, 1);
18601892

18611893
const absoluteOffsetY = -cellYOffset * 32 + translateY;
18621894
const opacityY = !fixedShadowY ? 0 : clamp(-absoluteOffsetY / 100, 0, 1);
18631895

18641896
const stickyShadow = React.useMemo(() => {
1865-
if (!opacityX && !opacityY) {
1897+
if (!opacityXLeft && !opacityY && !opacityXRight) {
18661898
return null;
18671899
}
18681900

1869-
const styleX: React.CSSProperties = {
1901+
const transition = "opacity 0.2s";
1902+
1903+
const styleXLeft: React.CSSProperties = {
18701904
position: "absolute",
18711905
top: 0,
1872-
left: stickyX,
1873-
width: width - stickyX,
1906+
left: stickyX[0],
1907+
width: width - stickyX[0],
18741908
height: height,
1875-
opacity: opacityX,
1909+
opacity: opacityXLeft,
18761910
pointerEvents: "none",
1877-
transition: !smoothScrollX ? "opacity 0.2s" : undefined,
1911+
transition: !smoothScrollX ? transition : undefined,
18781912
boxShadow: "inset 13px 0 10px -13px rgba(0, 0, 0, 0.2)",
18791913
};
18801914

1915+
const styleXRight: React.CSSProperties = {
1916+
position: "absolute",
1917+
top: 0,
1918+
right: stickyX[1],
1919+
width: width - stickyX[1],
1920+
height: height,
1921+
opacity: opacityXRight,
1922+
pointerEvents: "none",
1923+
transition: !smoothScrollX ? transition : undefined,
1924+
boxShadow: "inset -13px 0 10px -13px rgba(0, 0, 0, 0.2)",
1925+
};
1926+
18811927
const styleY: React.CSSProperties = {
18821928
position: "absolute",
18831929
top: totalHeaderHeight,
@@ -1886,17 +1932,28 @@ const DataGrid: React.ForwardRefRenderFunction<DataGridRef, DataGridProps> = (p,
18861932
height: height,
18871933
opacity: opacityY,
18881934
pointerEvents: "none",
1889-
transition: !smoothScrollY ? "opacity 0.2s" : undefined,
1935+
transition: !smoothScrollY ? transition : undefined,
18901936
boxShadow: "inset 0 13px 10px -13px rgba(0, 0, 0, 0.2)",
18911937
};
18921938

18931939
return (
18941940
<>
1895-
{opacityX > 0 && <div id="shadow-x" style={styleX} />}
1941+
{opacityXLeft > 0 && <div id="shadow-x" style={styleXLeft} />}
1942+
{opacityXRight > 0 && <div id="shadow-x" style={styleXRight} />}
18961943
{opacityY > 0 && <div id="shadow-y" style={styleY} />}
18971944
</>
18981945
);
1899-
}, [opacityX, opacityY, stickyX, width, smoothScrollX, totalHeaderHeight, height, smoothScrollY]);
1946+
}, [
1947+
opacityXLeft,
1948+
opacityY,
1949+
stickyX,
1950+
width,
1951+
smoothScrollX,
1952+
totalHeaderHeight,
1953+
height,
1954+
smoothScrollY,
1955+
opacityXRight,
1956+
]);
19001957

19011958
const overlayStyle = React.useMemo<React.CSSProperties>(
19021959
() => ({

0 commit comments

Comments
 (0)