Skip to content

Commit

Permalink
Merge branch 'master' into column-spanning
Browse files Browse the repository at this point in the history
  • Loading branch information
cherniavskii committed Apr 11, 2022
2 parents b5e50d1 + df9f7dd commit 919cffb
Show file tree
Hide file tree
Showing 17 changed files with 103 additions and 58 deletions.
2 changes: 1 addition & 1 deletion docs/data/data-grid/events/events.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@
"name": "rowsScroll",
"description": "Fired during the scroll of the grid viewport.",
"params": "GridScrollParams",
"event": "MuiEvent<{}>"
"event": "MuiEvent<React.UIEvent | MuiBaseEvent>"
},
{
"name": "rowsScrollEnd",
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/components/data-grid/events/events.json
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@
"name": "rowsScroll",
"description": "Fired during the scroll of the grid viewport.",
"params": "GridScrollParams",
"event": "MuiEvent<{}>"
"event": "MuiEvent<React.UIEvent | MuiBaseEvent>"
},
{
"name": "rowsScrollEnd",
Expand Down
2 changes: 1 addition & 1 deletion packages/grid/x-data-grid-generator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"peerDependencies": {
"@mui/icons-material": "^5.2.5",
"@mui/material": "^5.2.8",
"react": "^17.0.2"
"react": "^17.0.2 || ^18.0.0"
},
"setupFiles": [
"<rootDir>/src/setupTests.js"
Expand Down
2 changes: 1 addition & 1 deletion packages/grid/x-data-grid-pro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"peerDependencies": {
"@mui/material": "^5.2.8",
"@mui/system": "^5.2.8",
"react": "^17.0.2"
"react": "^17.0.2 || ^18.0.0"
},
"setupFiles": [
"<rootDir>/src/setupTests.js"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,27 +122,15 @@ export const DataGridProColumnHeaders = React.forwardRef<
const pinnedColumns = useGridSelector(apiRef, gridPinnedColumnsSelector);
const [leftPinnedColumns, rightPinnedColumns] = filterColumns(pinnedColumns, visibleColumnFields);

const {
isDragging,
renderContext,
updateInnerPosition,
getRootProps,
getInnerProps,
getColumns,
} = useGridColumnHeaders({
innerRef,
minColumnIndex: leftPinnedColumns.length,
});
const { isDragging, renderContext, getRootProps, getInnerProps, getColumns } =
useGridColumnHeaders({
innerRef,
minColumnIndex: leftPinnedColumns.length,
});

const ownerState = { leftPinnedColumns, rightPinnedColumns, classes: rootProps.classes };
const classes = useUtilityClasses(ownerState);

React.useEffect(() => {
if (renderContext) {
updateInnerPosition(renderContext);
}
}, [renderContext, updateInnerPosition]);

const leftRenderContext =
renderContext && leftPinnedColumns.length
? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -210,10 +210,6 @@ const DataGridProVirtualScroller = React.forwardRef<
useGridApiEventHandler(apiRef, GridEvents.columnWidthChange, refreshRenderZonePosition);
useGridApiEventHandler(apiRef, GridEvents.columnOrderChange, refreshRenderZonePosition);

React.useEffect(() => {
refreshRenderZonePosition();
}, [refreshRenderZonePosition]);

const leftRenderContext =
renderContext && leftPinnedColumns.length > 0
? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,26 @@ describe('<DataGridPro /> - Column Headers', () => {
],
};

it('should not scroll the column headers when a column is focused', function test() {
if (isJSDOM) {
this.skip(); // JSDOM version of .focus() doesn't scroll
}
render(
<div style={{ width: 102, height: 500 }}>
<DataGridPro
{...baselineProps}
columns={[{ field: 'brand' }, { field: 'foundationYear' }]}
/>
</div>,
);
const columnHeaders = document.querySelector('.MuiDataGrid-columnHeaders')!;
expect(columnHeaders.scrollLeft).to.equal(0);
const columnCell = getColumnHeaderCell(0);
columnCell.focus();
fireEvent.keyDown(columnCell, { key: 'End' });
expect(columnHeaders.scrollLeft).to.equal(0);
});

describe('GridColumnHeaderMenu', () => {
it('should close the menu when the window is scrolled', () => {
render(
Expand Down
2 changes: 1 addition & 1 deletion packages/grid/x-data-grid/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"peerDependencies": {
"@mui/material": "^5.2.8",
"@mui/system": "^5.2.8",
"react": "^17.0.2"
"react": "^17.0.2 || ^18.0.0"
},
"setupFiles": [
"<rootDir>/src/setupTests.js"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,13 +207,11 @@ function GridColumnHeaderItem(props: GridColumnHeaderItemProps) {
const columnMenuState = apiRef.current.state.columnMenu;
if (hasFocus && !columnMenuState.open) {
const focusableElement = headerCellRef.current!.querySelector<HTMLElement>('[tabindex="0"]');
if (focusableElement) {
focusableElement!.focus();
} else {
headerCellRef.current!.focus();
}
const elementToFocus = focusableElement || headerCellRef.current;
elementToFocus?.focus();
apiRef.current.columnHeadersContainerElementRef!.current!.scrollLeft = 0;
}
});
}, [apiRef, hasFocus]);

const headerClassName =
typeof column.headerClassName === 'function'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,11 @@ const GridColumnHeadersRoot = styled('div', {
};
});

interface GridColumnHeadersProps extends React.HTMLAttributes<HTMLDivElement> {
innerRef?: React.Ref<HTMLDivElement>;
}
interface GridColumnHeadersProps extends React.HTMLAttributes<HTMLDivElement> {}

export const GridColumnHeaders = React.forwardRef<HTMLDivElement, GridColumnHeadersProps>(
function GridColumnHeaders(props, ref) {
const { innerRef, className, ...other } = props;
const { className, ...other } = props;
const rootProps = useGridRootProps();

const ownerState = { classes: rootProps.classes };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import { unstable_composeClasses as composeClasses } from '@mui/material';
import { useForkRef } from '@mui/material/utils';
import { GridEvents } from '../../models/events';
import { GridCellParams } from '../../models/params/gridCellParams';
import { GridRenderCellParams } from '../../models/params/gridCellParams';
import { isNavigationKey, isSpaceKey } from '../../utils/keyboardUtils';
import { useGridApiContext } from '../../hooks/utils/useGridApiContext';
import { useGridRootProps } from '../../hooks/utils/useGridRootProps';
Expand All @@ -27,7 +27,7 @@ interface TouchRippleActions {
stop: (event: any, callback?: () => void) => void;
}

const GridCellCheckboxForwardRef = React.forwardRef<HTMLInputElement, GridCellParams>(
const GridCellCheckboxForwardRef = React.forwardRef<HTMLInputElement, GridRenderCellParams>(
function GridCellCheckboxRenderer(props, ref) {
const {
field,
Expand All @@ -42,6 +42,7 @@ const GridCellCheckboxForwardRef = React.forwardRef<HTMLInputElement, GridCellPa
hasFocus,
tabIndex,
getValue,
api,
...other
} = props;
const apiRef = useGridApiContext();
Expand Down Expand Up @@ -118,6 +119,11 @@ GridCellCheckboxForwardRef.propTypes = {
// | These PropTypes are generated from the TypeScript type definitions |
// | To update them edit the TypeScript types and run "yarn proptypes" |
// ----------------------------------------------------------------------
/**
* GridApi that let you manipulate the grid.
* @deprecated Use the `apiRef` returned by `useGridApiContext` or `useGridApiRef` (only available in `@mui/x-data-grid-pro`)
*/
api: PropTypes.any.isRequired,
/**
* The mode of the cell.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { useForkRef } from '@mui/material/utils';
import { defaultMemoize } from 'reselect';
import { useGridApiContext } from '../../utils/useGridApiContext';
Expand Down Expand Up @@ -30,6 +31,10 @@ interface UseGridColumnHeadersProps {
minColumnIndex?: number;
}

function isUIEvent(event: any): event is React.UIEvent {
return !!event.target;
}

export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
const { innerRef: innerRefProp, minColumnIndex = 0 } = props;

Expand Down Expand Up @@ -103,8 +108,14 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
],
);

React.useLayoutEffect(() => {
if (renderContext) {
updateInnerPosition(renderContext);
}
}, [renderContext, updateInnerPosition]);

const handleScroll = React.useCallback<GridEventListener<GridEvents.rowsScroll>>(
({ left, renderContext: nextRenderContext = null }) => {
({ left, renderContext: nextRenderContext = null }, event) => {
if (!innerRef.current) {
return;
}
Expand All @@ -120,13 +131,30 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
}
prevScrollLeft.current = left;

// We can only update the position when we guarantee that the render context has been
// rendered. This is achieved using ReactDOM.flushSync or when the context doesn't change.
let canUpdateInnerPosition = false;

if (nextRenderContext !== prevRenderContext.current || !prevRenderContext.current) {
setRenderContext(nextRenderContext);
// ReactDOM.flushSync cannot be called on `scroll` events fired inside effects
if (isUIEvent(event)) {
// To prevent flickering, the inner position can only be updated after the new context has
// been rendered. ReactDOM.flushSync ensures that the state changes will happen before
// updating the position.
ReactDOM.flushSync(() => {
setRenderContext(nextRenderContext);
});
canUpdateInnerPosition = true;
} else {
setRenderContext(nextRenderContext);
}
prevRenderContext.current = nextRenderContext;
} else {
canUpdateInnerPosition = true;
}

// Pass directly the render context to avoid waiting for the next render
if (nextRenderContext) {
if (nextRenderContext && canUpdateInnerPosition) {
updateInnerPosition(nextRenderContext);
}
},
Expand Down Expand Up @@ -217,7 +245,7 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {

columns.push(
<GridColumnHeaderItem
key={i}
key={column.field}
{...sortColumnLookup[column.field]}
columnMenuOpen={open}
filterItemsCounter={
Expand Down Expand Up @@ -250,7 +278,6 @@ export const useGridColumnHeaders = (props: UseGridColumnHeadersProps) => {
renderContext,
getColumns,
isDragging: !!dragCol,
updateInnerPosition,
getRootProps: (other = {}) => ({ style: rootStyle, ...other }),
getInnerProps: () => ({ ref: handleInnerRef, 'aria-rowindex': 1, role: 'row' }),
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { useForkRef } from '@mui/material/utils';
import { useGridApiContext } from '../../utils/useGridApiContext';
import { useGridRootProps } from '../../utils/useGridRootProps';
Expand Down Expand Up @@ -206,13 +207,18 @@ export const useGridVirtualScroller = (props: UseGridVirtualScrollerProps) => {
],
);

React.useLayoutEffect(() => {
if (renderContext) {
updateRenderZonePosition(renderContext);
}
}, [renderContext, updateRenderZonePosition]);

const updateRenderContext = React.useCallback(
(nextRenderContext) => {
setRenderContext(nextRenderContext);
updateRenderZonePosition(nextRenderContext);
prevRenderContext.current = nextRenderContext;
},
[setRenderContext, prevRenderContext, updateRenderZonePosition],
[setRenderContext, prevRenderContext],
);

React.useEffect(() => {
Expand All @@ -221,7 +227,6 @@ export const useGridVirtualScroller = (props: UseGridVirtualScrollerProps) => {
}

const initialRenderContext = computeRenderContext();
prevRenderContext.current = initialRenderContext;
updateRenderContext(initialRenderContext);

const { top, left } = scrollPosition.current!;
Expand Down Expand Up @@ -266,14 +271,21 @@ export const useGridVirtualScroller = (props: UseGridVirtualScrollerProps) => {
prevTotalWidth.current !== columnsTotalWidth;

// TODO v6: rename event to a wider name, it's not only fired for row scrolling
apiRef.current.publishEvent(GridEvents.rowsScroll, {
top: scrollTop,
left: scrollLeft,
renderContext: shouldSetState ? nextRenderContext : prevRenderContext.current,
});
apiRef.current.publishEvent(
GridEvents.rowsScroll,
{
top: scrollTop,
left: scrollLeft,
renderContext: shouldSetState ? nextRenderContext : prevRenderContext.current,
},
event,
);

if (shouldSetState) {
updateRenderContext(nextRenderContext);
// Prevents batching render context changes
ReactDOM.flushSync(() => {
updateRenderContext(nextRenderContext);
});
prevTotalWidth.current = columnsTotalWidth;
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ export interface GridEventLookup
};

// Scroll
rowsScroll: { params: GridScrollParams };
rowsScroll: { params: GridScrollParams; event: React.UIEvent | MuiBaseEvent };
virtualScrollerContentSizeChange: {};

// Selection
Expand Down
4 changes: 2 additions & 2 deletions packages/x-date-pickers-pro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@
"dayjs": "^1.10.7",
"luxon": "^1.28.0 || ^2.0.0",
"moment": "^2.29.1",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react": "^17.0.2 || ^18.0.0",
"react-dom": "^17.0.2 || ^18.0.0"
},
"peerDependenciesMeta": {
"date-fns": {
Expand Down
4 changes: 2 additions & 2 deletions packages/x-date-pickers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@
"dayjs": "^1.10.7",
"luxon": "^1.28.0 || ^2.0.0",
"moment": "^2.29.1",
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react": "^17.0.2 || ^18.0.0",
"react-dom": "^17.0.2 || ^18.0.0"
},
"peerDependenciesMeta": {
"date-fns": {
Expand Down
2 changes: 1 addition & 1 deletion packages/x-license-pro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"yargs": "^17.4.1"
},
"peerDependencies": {
"react": "^17.0.2"
"react": "^17.0.2 || ^18.0.0"
},
"setupFiles": [
"<rootDir>/src/setupTests.js"
Expand Down

0 comments on commit 919cffb

Please sign in to comment.