Skip to content

Commit

Permalink
[DataGrid] Keep focused cell in the DOM (#7357)
Browse files Browse the repository at this point in the history
Signed-off-by: yared tsegaye <[email protected]>
Signed-off-by: Rom Grk <[email protected]>
Co-authored-by: Yared Tsegaye <[email protected]>
Co-authored-by: yaredtsyg <[email protected]>
Co-authored-by: Rom Grk <[email protected]>
Co-authored-by: Andrew Cherniavskii <[email protected]>
  • Loading branch information
5 people authored Jul 21, 2023
1 parent a22d608 commit 51b77fb
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { gridEditRowsStateSelector } from '@mui/x-data-grid/internals';
import { GridRowOrderChangeParams } from '../../../models/gridRowOrderChangeParams';
import { GridPrivateApiPro } from '../../../models/gridApiPro';
import { DataGridProProcessedProps } from '../../../models/dataGridProProps';
import { GRID_REORDER_COL_DEF } from './gridRowReorderColDef';

type OwnerState = { classes: DataGridProProcessedProps['classes'] };

Expand Down Expand Up @@ -98,6 +99,7 @@ export const useGridRowReorder = (
});

originRowIndex.current = apiRef.current.getRowIndexRelativeToVisibleRows(params.id);
apiRef.current.setCellFocus(params.id, GRID_REORDER_COL_DEF.field);
},
[isRowReorderDisabled, classes.rowDragging, logger, apiRef],
);
Expand Down
75 changes: 56 additions & 19 deletions packages/grid/x-data-grid/src/components/GridRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ export interface GridRowProps extends React.HTMLAttributes<HTMLDivElement> {
tabbableCell: string | null;
row?: GridRowModel;
isLastVisible?: boolean;
focusedCellColumnIndexNotInRange?: number;
isNotVisible?: boolean;
onClick?: React.MouseEventHandler<HTMLDivElement>;
onDoubleClick?: React.MouseEventHandler<HTMLDivElement>;
onMouseEnter?: React.MouseEventHandler<HTMLDivElement>;
Expand Down Expand Up @@ -114,6 +116,8 @@ const GridRow = React.forwardRef<HTMLDivElement, GridRowProps>(function GridRow(
firstColumnToRender,
lastColumnToRender,
isLastVisible = false,
focusedCellColumnIndexNotInRange,
isNotVisible,
focusedCell,
tabbableCell,
onClick,
Expand Down Expand Up @@ -277,6 +281,14 @@ const GridRow = React.forwardRef<HTMLDivElement, GridRowProps>(function GridRow(
Object.keys(editRowsState).length > 0);

const editCellState = editRowsState[rowId]?.[column.field] ?? null;
let cellIsNotVisible = false;

if (
focusedCellColumnIndexNotInRange !== undefined &&
visibleColumns[focusedCellColumnIndexNotInRange].field === column.field
) {
cellIsNotVisible = true;
}

return (
<CellComponent
Expand All @@ -291,6 +303,7 @@ const GridRow = React.forwardRef<HTMLDivElement, GridRowProps>(function GridRow(
colSpan={cellProps.colSpan}
disableDragEvents={disableDragEvents}
editCellState={editCellState}
isNotVisible={cellIsNotVisible}
{...slotProps?.cell}
/>
);
Expand Down Expand Up @@ -322,27 +335,39 @@ const GridRow = React.forwardRef<HTMLDivElement, GridRowProps>(function GridRow(
}
}

const style = {
...styleProp,
maxHeight: rowHeight === 'auto' ? 'none' : rowHeight, // max-height doesn't support "auto"
minHeight,
};
const style = React.useMemo(() => {
if (isNotVisible) {
return {
opacity: 0,
width: 0,
height: 0,
};
}

if (sizes?.spacingTop) {
const property = rootProps.rowSpacingType === 'border' ? 'borderTopWidth' : 'marginTop';
style[property] = sizes.spacingTop;
}
const rowStyle = {
...styleProp,
maxHeight: rowHeight === 'auto' ? 'none' : rowHeight, // max-height doesn't support "auto"
minHeight,
};

if (sizes?.spacingBottom) {
const property = rootProps.rowSpacingType === 'border' ? 'borderBottomWidth' : 'marginBottom';
let propertyValue = style[property];
// avoid overriding existing value
if (typeof propertyValue !== 'number') {
propertyValue = parseInt(propertyValue || '0', 10);
if (sizes?.spacingTop) {
const property = rootProps.rowSpacingType === 'border' ? 'borderTopWidth' : 'marginTop';
rowStyle[property] = sizes.spacingTop;
}
propertyValue += sizes.spacingBottom;
style[property] = propertyValue;
}

if (sizes?.spacingBottom) {
const property = rootProps.rowSpacingType === 'border' ? 'borderBottomWidth' : 'marginBottom';
let propertyValue = rowStyle[property];
// avoid overriding existing value
if (typeof propertyValue !== 'number') {
propertyValue = parseInt(propertyValue || '0', 10);
}
propertyValue += sizes.spacingBottom;
rowStyle[property] = propertyValue;
}

return rowStyle;
}, [isNotVisible, rowHeight, styleProp, minHeight, sizes, rootProps.rowSpacingType]);

const rowClassNames = apiRef.current.unstable_applyPipeProcessors('rowClassName', [], rowId);

Expand Down Expand Up @@ -370,7 +395,16 @@ const GridRow = React.forwardRef<HTMLDivElement, GridRowProps>(function GridRow(

for (let i = 0; i < renderedColumns.length; i += 1) {
const column = renderedColumns[i];
const indexRelativeToAllColumns = firstColumnToRender + i;

let indexRelativeToAllColumns = firstColumnToRender + i;

if (focusedCellColumnIndexNotInRange !== undefined && focusedCell) {
if (visibleColumns[focusedCellColumnIndexNotInRange].field === column.field) {
indexRelativeToAllColumns = focusedCellColumnIndexNotInRange;
} else {
indexRelativeToAllColumns -= 1;
}
}

const cellColSpanInfo = apiRef.current.unstable_getCellColSpanInfo(
rowId,
Expand All @@ -386,6 +420,7 @@ const GridRow = React.forwardRef<HTMLDivElement, GridRowProps>(function GridRow(
showRightBorder: rootProps.showCellVerticalBorder,
indexRelativeToAllColumns,
};

cells.push(getCell(column, cellProps));
} else {
const { width } = cellColSpanInfo.cellProps;
Expand Down Expand Up @@ -446,12 +481,14 @@ GridRow.propTypes = {
* If `null`, no cell in this row has focus.
*/
focusedCell: PropTypes.string,
focusedCellColumnIndexNotInRange: PropTypes.number,
/**
* Index of the row in the whole sorted and filtered dataset.
* If some rows above have expanded children, this index also take those children into account.
*/
index: PropTypes.number.isRequired,
isLastVisible: PropTypes.bool,
isNotVisible: PropTypes.bool,
lastColumnToRender: PropTypes.number.isRequired,
onClick: PropTypes.func,
onDoubleClick: PropTypes.func,
Expand Down
52 changes: 39 additions & 13 deletions packages/grid/x-data-grid/src/components/cell/GridCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
GridCellModes,
GridRowId,
GridCellMode,
GridEditCellProps,
} from '../../models';
import {
GridRenderEditCellParams,
Expand All @@ -26,7 +27,6 @@ import {
} from '../../models/params/gridCellParams';
import { GridColDef, GridAlignment } from '../../models/colDef/gridColDef';
import { GridTreeNodeWithRender } from '../../models/gridRows';
import { GridEditCellProps } from '../../models/gridEditRowModel';
import { useGridSelector, objectShallowCompare } from '../../hooks/utils/useGridSelector';
import { useGridApiContext } from '../../hooks/utils/useGridApiContext';
import { useGridRootProps } from '../../hooks/utils/useGridRootProps';
Expand All @@ -45,6 +45,7 @@ type GridCellV7Props = {
width: number;
colSpan?: number;
disableDragEvents?: boolean;
isNotVisible?: boolean;
editCellState: GridEditCellProps<any> | null;
onClick?: React.MouseEventHandler<HTMLDivElement>;
onDoubleClick?: React.MouseEventHandler<HTMLDivElement>;
Expand Down Expand Up @@ -267,6 +268,7 @@ const GridCell = React.forwardRef<HTMLDivElement, GridCellProps>((props, ref) =>
row,
colSpan,
disableDragEvents,
isNotVisible,
onClick,
onDoubleClick,
onMouseDown,
Expand Down Expand Up @@ -330,12 +332,22 @@ const GridCell = React.forwardRef<HTMLDivElement, GridCellProps>((props, ref) =>
[apiRef, field, rowId],
);

const style = {
minWidth: width,
maxWidth: width,
minHeight: height,
maxHeight: height === 'auto' ? 'none' : height, // max-height doesn't support "auto"
};
const style = React.useMemo(() => {
if (isNotVisible) {
return {
padding: 0,
opacity: 0,
width: 0,
};
}
const cellStyle = {
minWidth: width,
maxWidth: width,
minHeight: height,
maxHeight: height === 'auto' ? 'none' : height, // max-height doesn't support "auto"
};
return cellStyle;
}, [width, height, isNotVisible]);

React.useEffect(() => {
if (!hasFocus || cellMode === GridCellModes.Edit) {
Expand Down Expand Up @@ -393,6 +405,7 @@ const GridCell = React.forwardRef<HTMLDivElement, GridCellProps>((props, ref) =>
let children: React.ReactNode = childrenProp;
if (children === undefined) {
const valueString = valueToRender?.toString();

children = (
<div className={classes.content} title={valueString}>
{valueString}
Expand Down Expand Up @@ -483,6 +496,7 @@ GridCell.propTypes = {
isValidating: PropTypes.bool,
value: PropTypes.any,
}),
isNotVisible: PropTypes.bool,
height: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number]),
onClick: PropTypes.func,
onDoubleClick: PropTypes.func,
Expand Down Expand Up @@ -514,6 +528,7 @@ const GridCellV7 = React.forwardRef<HTMLDivElement, GridCellV7Props>((props, ref
row,
colSpan,
disableDragEvents,
isNotVisible,
onClick,
onDoubleClick,
onMouseDown,
Expand Down Expand Up @@ -637,12 +652,22 @@ const GridCellV7 = React.forwardRef<HTMLDivElement, GridCellV7Props>((props, ref
[apiRef, field, rowId],
);

const style = {
minWidth: width,
maxWidth: width,
minHeight: height,
maxHeight: height === 'auto' ? 'none' : height, // max-height doesn't support "auto"
};
const style = React.useMemo(() => {
if (isNotVisible) {
return {
padding: 0,
opacity: 0,
width: 0,
};
}
const cellStyle = {
minWidth: width,
maxWidth: width,
minHeight: height,
maxHeight: height === 'auto' ? 'none' : height, // max-height doesn't support "auto"
};
return cellStyle;
}, [width, height, isNotVisible]);

React.useEffect(() => {
if (!hasFocus || cellMode === GridCellModes.Edit) {
Expand Down Expand Up @@ -788,6 +813,7 @@ GridCellV7.propTypes = {
value: PropTypes.any,
}),
height: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number]).isRequired,
isNotVisible: PropTypes.bool,
onClick: PropTypes.func,
onDoubleClick: PropTypes.func,
onDragEnter: PropTypes.func,
Expand Down
Loading

0 comments on commit 51b77fb

Please sign in to comment.