Skip to content

Commit

Permalink
[DataGridPro] Fix pinned columns in RTL mode (#14586)
Browse files Browse the repository at this point in the history
  • Loading branch information
KenanYusuf authored Sep 16, 2024
1 parent dd4447c commit 2777772
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 38 deletions.
19 changes: 13 additions & 6 deletions packages/x-data-grid/src/components/cell/GridCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
unstable_capitalize as capitalize,
} from '@mui/utils';
import { fastMemo } from '@mui/x-internals/fastMemo';
import { useRtl } from '@mui/system/RtlProvider';
import { doesSupportPreventScroll } from '../../utils/doesSupportPreventScroll';
import { getDataGridUtilityClass, gridClasses } from '../../constants/gridClasses';
import {
Expand Down Expand Up @@ -175,6 +176,7 @@ const GridCell = React.forwardRef<HTMLDivElement, GridCellProps>(function GridCe

const apiRef = useGridApiContext();
const rootProps = useGridRootProps();
const isRtl = useRtl();

const field = column.field;

Expand Down Expand Up @@ -334,16 +336,21 @@ const GridCell = React.forwardRef<HTMLDivElement, GridCellProps>(function GridCe
...styleProp,
};

if (pinnedPosition === PinnedPosition.LEFT) {
cellStyle.left = pinnedOffset;
}
const isLeftPinned = pinnedPosition === PinnedPosition.LEFT;
const isRightPinned = pinnedPosition === PinnedPosition.RIGHT;

if (isLeftPinned || isRightPinned) {
let side: 'left' | 'right' = isLeftPinned ? 'left' : 'right';

if (isRtl) {
side = isLeftPinned ? 'right' : 'left';
}

if (pinnedPosition === PinnedPosition.RIGHT) {
cellStyle.right = pinnedOffset;
cellStyle[side] = pinnedOffset;
}

return cellStyle;
}, [width, isNotVisible, styleProp, pinnedOffset, pinnedPosition]);
}, [width, isNotVisible, styleProp, pinnedOffset, pinnedPosition, isRtl]);

React.useEffect(() => {
if (!hasFocus || cellMode === GridCellModes.Edit) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
const renderContext = useGridSelector(apiRef, gridRenderContextColumnsSelector);
const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector);
const columnsLookup = useGridSelector(apiRef, gridColumnLookupSelector);
const offsetLeft = computeOffsetLeft(
columnPositions,
renderContext,
isRtl,
pinnedColumns.left.length,
);
const offsetLeft = computeOffsetLeft(columnPositions, renderContext, pinnedColumns.left.length);
const gridHasFiller = dimensions.columnsTotalWidth < dimensions.viewportOuterSize.width;

React.useEffect(() => {
Expand Down Expand Up @@ -230,20 +225,30 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
computedWidth: number;
}) => {
let style: React.CSSProperties | undefined;
if (pinnedPosition === 'left' || pinnedPosition === 'right') {

const isLeftPinned = pinnedPosition === GridPinnedColumnPosition.LEFT;
const isRightPinned = pinnedPosition === GridPinnedColumnPosition.RIGHT;

if (isLeftPinned || isRightPinned) {
const pinnedOffset = getPinnedCellOffset(
pinnedPosition,
computedWidth,
columnIndex,
columnPositions,
dimensions,
);
let side = isLeftPinned ? 'left' : 'right';

if (isRtl) {
side = isLeftPinned ? 'right' : 'left';
}

if (pinnedPosition === 'left') {
style = { left: pinnedOffset };
style = { [side]: pinnedOffset };
}

if (pinnedPosition === 'right') {
style = { right: pinnedOffset };
style = { [side]: pinnedOffset };
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,14 @@ export const useGridColumnResize = (

refs.cellElements = findGridCellElementsFromCol(refs.columnHeaderElement, apiRef.current);

refs.fillerLeft = findGridElement(apiRef.current, 'filler--pinnedLeft');
refs.fillerRight = findGridElement(apiRef.current, 'filler--pinnedRight');
refs.fillerLeft = findGridElement(
apiRef.current,
isRtl ? 'filler--pinnedRight' : 'filler--pinnedLeft',
);
refs.fillerRight = findGridElement(
apiRef.current,
isRtl ? 'filler--pinnedLeft' : 'filler--pinnedRight',
);

const pinnedPosition = apiRef.current.unstable_applyPipeProcessors(
'isColumnPinned',
Expand All @@ -468,20 +474,20 @@ export const useGridColumnResize = (
refs.leftPinnedCellsAfter =
pinnedPosition !== GridPinnedColumnPosition.LEFT
? []
: findLeftPinnedCellsAfterCol(apiRef.current, refs.columnHeaderElement);
: findLeftPinnedCellsAfterCol(apiRef.current, refs.columnHeaderElement, isRtl);
refs.rightPinnedCellsBefore =
pinnedPosition !== GridPinnedColumnPosition.RIGHT
? []
: findRightPinnedCellsBeforeCol(apiRef.current, refs.columnHeaderElement);
: findRightPinnedCellsBeforeCol(apiRef.current, refs.columnHeaderElement, isRtl);

refs.leftPinnedHeadersAfter =
pinnedPosition !== GridPinnedColumnPosition.LEFT
? []
: findLeftPinnedHeadersAfterCol(apiRef.current, refs.columnHeaderElement);
: findLeftPinnedHeadersAfterCol(apiRef.current, refs.columnHeaderElement, isRtl);
refs.rightPinnedHeadersBefore =
pinnedPosition !== GridPinnedColumnPosition.RIGHT
? []
: findRightPinnedHeadersBeforeCol(apiRef.current, refs.columnHeaderElement);
: findRightPinnedHeadersBeforeCol(apiRef.current, refs.columnHeaderElement, isRtl);

resizeDirection.current = getResizeDirection(separator, isRtl);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,6 @@ export const useGridVirtualScroller = () => {
const offsetLeft = computeOffsetLeft(
columnPositions,
currentRenderContext,
isRtl,
pinnedColumns.left.length,
);
const showBottomBorder = isLastVisibleInSection && params.position === 'top';
Expand Down Expand Up @@ -939,14 +938,11 @@ export function areRenderContextsEqual(context1: GridRenderContext, context2: Gr
export function computeOffsetLeft(
columnPositions: number[],
renderContext: GridColumnsRenderContext,
isRtl: boolean,
pinnedLeftLength: number,
) {
const factor = isRtl ? -1 : 1;
const left =
factor * (columnPositions[renderContext.firstColumnIndex] ?? 0) -
(columnPositions[renderContext.firstColumnIndex] ?? 0) -
(columnPositions[pinnedLeftLength] ?? 0);

return Math.abs(left);
}

Expand Down
40 changes: 28 additions & 12 deletions packages/x-data-grid/src/utils/domUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,23 +166,31 @@ const findPinnedCells = ({
return cells;
};

export function findLeftPinnedCellsAfterCol(api: GridPrivateApiCommunity, col: HTMLElement) {
export function findLeftPinnedCellsAfterCol(
api: GridPrivateApiCommunity,
col: HTMLElement,
isRtl: boolean,
) {
const colIndex = parseCellColIndex(col);
return findPinnedCells({
api,
colIndex,
position: 'left',
filterFn: (index) => index > colIndex!,
position: isRtl ? 'right' : 'left',
filterFn: (index) => (isRtl ? index < colIndex! : index > colIndex!),
});
}

export function findRightPinnedCellsBeforeCol(api: GridPrivateApiCommunity, col: HTMLElement) {
export function findRightPinnedCellsBeforeCol(
api: GridPrivateApiCommunity,
col: HTMLElement,
isRtl: boolean,
) {
const colIndex = parseCellColIndex(col);
return findPinnedCells({
api,
colIndex,
position: 'right',
filterFn: (index) => index < colIndex!,
position: isRtl ? 'left' : 'right',
filterFn: (index) => (isRtl ? index > colIndex! : index < colIndex!),
});
}

Expand Down Expand Up @@ -218,23 +226,31 @@ const findPinnedHeaders = ({
return elements;
};

export function findLeftPinnedHeadersAfterCol(api: GridPrivateApiCommunity, col: HTMLElement) {
export function findLeftPinnedHeadersAfterCol(
api: GridPrivateApiCommunity,
col: HTMLElement,
isRtl: boolean,
) {
const colIndex = parseCellColIndex(col);
return findPinnedHeaders({
api,
position: 'left',
position: isRtl ? 'right' : 'left',
colIndex,
filterFn: (index) => index > colIndex!,
filterFn: (index) => (isRtl ? index < colIndex! : index > colIndex!),
});
}

export function findRightPinnedHeadersBeforeCol(api: GridPrivateApiCommunity, col: HTMLElement) {
export function findRightPinnedHeadersBeforeCol(
api: GridPrivateApiCommunity,
col: HTMLElement,
isRtl: boolean,
) {
const colIndex = parseCellColIndex(col);
return findPinnedHeaders({
api,
position: 'right',
position: isRtl ? 'left' : 'right',
colIndex,
filterFn: (index) => index < colIndex!,
filterFn: (index) => (isRtl ? index > colIndex! : index < colIndex!),
});
}

Expand Down
83 changes: 83 additions & 0 deletions test/regressions/data-grid/DataGridRTLPinnedColumns.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import * as React from 'react';
import { prefixer } from 'stylis';
import rtlPlugin from 'stylis-plugin-rtl';
import { useGridApiRef, DataGridPro } from '@mui/x-data-grid-pro';
import { arSD } from '@mui/x-data-grid/locales';
import createCache from '@emotion/cache';
import { CacheProvider } from '@emotion/react';
import { createTheme, ThemeProvider, useTheme } from '@mui/material/styles';

// Create rtl cache
const cacheRtl = createCache({
key: 'data-grid-rtl-demo',
stylisPlugins: [prefixer, rtlPlugin],
});

const columns = [
{
field: 'id',
headerName: 'تعريف',
width: 150,
},
{
field: 'name',
headerName: 'اسم',
width: 150,
},
{
field: 'age',
headerName: 'عمر',
valueGetter: (value) => `${value} سنوات`,
width: 150,
},
{
field: 'occupation',
headerName: 'المهنة',
width: 150,
},
{
field: 'gender',
headerName: 'جنس',
width: 150,
},
];

const rows = [
{ id: 1, name: 'سارہ', age: 35, occupation: 'معلم', gender: 'أنثى' },
{ id: 2, name: 'زید', age: 42, occupation: 'مهندس', gender: 'ذكر' },
{ id: 3, name: 'علی', age: 33, occupation: 'محاسب', gender: 'ذكر' },
{ id: 4, name: 'فاطمہ', age: 25, occupation: 'معلم', gender: 'أنثى' },
{ id: 5, name: 'ایندریو', age: 65, occupation: 'مهندس', gender: 'ذكر' },
];

export default function DataGridRTLPinnedColumns() {
const apiRef = useGridApiRef();
const existingTheme = useTheme();
const theme = React.useMemo(
() =>
createTheme({}, arSD, existingTheme, {
direction: 'rtl',
}),
[existingTheme],
);

return (
<CacheProvider value={cacheRtl}>
<ThemeProvider theme={theme}>
<div dir="rtl" style={{ height: 500, width: '100%' }}>
<DataGridPro
apiRef={apiRef}
rows={rows}
columns={columns}
initialState={{
pinnedColumns: {
left: ['id', 'name'],
right: ['occupation'],
},
}}
/>
</div>
</ThemeProvider>
</CacheProvider>
);
}

0 comments on commit 2777772

Please sign in to comment.