diff --git a/packages/x-data-grid-pro/src/tests/columns.DataGridPro.test.tsx b/packages/x-data-grid-pro/src/tests/columns.DataGridPro.test.tsx index 4bd7bece7b4d4..f85124d4cb7a3 100644 --- a/packages/x-data-grid-pro/src/tests/columns.DataGridPro.test.tsx +++ b/packages/x-data-grid-pro/src/tests/columns.DataGridPro.test.tsx @@ -13,7 +13,7 @@ import { GridAutosizeOptions, } from '@mui/x-data-grid-pro'; import { useGridPrivateApiContext } from '@mui/x-data-grid-pro/internals'; -import { getColumnHeaderCell, getCell, microtasks } from 'test/utils/helperFn'; +import { getColumnHeaderCell, getCell, microtasks, getRow } from 'test/utils/helperFn'; const isJSDOM = /jsdom/.test(window.navigator.userAgent); @@ -228,6 +228,79 @@ describe(' - Columns', () => { expect(bottomPinnedRowCell?.getBoundingClientRect().width).to.equal(150); }); + // https://github.com/mui/mui-x/issues/12852 + it('should work with right pinned column', () => { + render( + , + ); + + const pinnedHeaderCell = getColumnHeaderCell(1); + const pinnedCell = getCell(1, 1); + const pinnedSeparator = pinnedHeaderCell.querySelector( + `.${gridClasses['columnSeparator--resizable']}`, + )!; + const pinnedRightPosition = pinnedHeaderCell.getBoundingClientRect().right; + + // resize right pinned column to the right + fireEvent.mouseDown(pinnedSeparator, { clientX: 100 }); + fireEvent.mouseMove(pinnedSeparator, { clientX: 150, buttons: 1 }); + + // check that the right pinned column has shrunk and is in the same position + expect(pinnedHeaderCell.getBoundingClientRect().width).to.equal(50); + expect(pinnedCell.getBoundingClientRect().width).to.equal(50); + expect(pinnedHeaderCell.getBoundingClientRect().right).to.equal(pinnedRightPosition); + + // release the mouse and check that the right pinned column is still in the same position + fireEvent.mouseUp(pinnedSeparator); + expect(pinnedHeaderCell.getBoundingClientRect().width).to.equal(50); + expect(pinnedCell.getBoundingClientRect().width).to.equal(50); + expect(pinnedHeaderCell.getBoundingClientRect().right).to.equal(pinnedRightPosition); + + // resize the right pinned column to the left + fireEvent.mouseDown(pinnedSeparator, { clientX: 150 }); + fireEvent.mouseMove(pinnedSeparator, { clientX: 50, buttons: 1 }); + + // check that the right pinned column has grown and is in the same position + expect(pinnedHeaderCell.getBoundingClientRect().width).to.equal(150); + expect(pinnedCell.getBoundingClientRect().width).to.equal(150); + expect(pinnedHeaderCell.getBoundingClientRect().right).to.equal(pinnedRightPosition); + + // release the mouse and check that the right pinned column is still in the same position + fireEvent.mouseUp(pinnedSeparator); + expect(pinnedHeaderCell.getBoundingClientRect().width).to.equal(150); + expect(pinnedCell.getBoundingClientRect().width).to.equal(150); + expect(pinnedHeaderCell.getBoundingClientRect().right).to.equal(pinnedRightPosition); + }); + + // https://github.com/mui/mui-x/issues/13548 + it('should fill remaining horizontal space in a row with an empty cell', () => { + render(); + + const row = getRow(0); + const rowWidth = row.getBoundingClientRect().width; + const headerCell = getColumnHeaderCell(0); + const separator = headerCell.querySelector(`.${gridClasses['columnSeparator--resizable']}`)!; + const emptyCell = row.querySelector(`.${gridClasses.cellEmpty}`)!; + + // check that empty cell takes up the remaining width in a row + expect(emptyCell.getBoundingClientRect().width).to.equal(rowWidth - 100); + + // check that empty cell takes up the remaining width when the column is resized + fireEvent.mouseDown(separator, { clientX: 100 }); + fireEvent.mouseMove(separator, { clientX: 50, buttons: 1 }); + expect(emptyCell.getBoundingClientRect().width).to.equal(rowWidth - 50); + + // release the mouse and check that the empty cell still takes up the remaining width + fireEvent.mouseUp(separator); + expect(emptyCell.getBoundingClientRect().width).to.equal(rowWidth - 50); + }); + describe('flex resizing', () => { before(function beforeHook() { if (isJSDOM) { diff --git a/packages/x-data-grid/src/components/GridRow.tsx b/packages/x-data-grid/src/components/GridRow.tsx index 0dd0ca01af0b0..94b77710c472d 100644 --- a/packages/x-data-grid/src/components/GridRow.tsx +++ b/packages/x-data-grid/src/components/GridRow.tsx @@ -69,28 +69,6 @@ export interface GridRowProps extends React.HTMLAttributes { [x: `data-${string}`]: string; } -function EmptyCell({ width }: { width: number }) { - if (!width) { - return null; - } - - return ( -
- ); -} - -EmptyCell.propTypes = { - // ----------------------------- Warning -------------------------------- - // | These PropTypes are generated from the TypeScript type definitions | - // | To update them edit the TypeScript types and run "pnpm proptypes" | - // ---------------------------------------------------------------------- - width: PropTypes.number.isRequired, -} as any; - const GridRow = forwardRef(function GridRow(props, refProp) { const { selected, @@ -464,10 +442,6 @@ const GridRow = forwardRef(function GridRow(props, } : null; - const expandedWidth = - dimensions.viewportOuterSize.width - dimensions.columnsTotalWidth - scrollbarWidth; - const emptyCellWidth = Math.max(0, expandedWidth); - return (
(function GridRow(props, style={{ width: offsetLeft }} /> {cells} - {emptyCellWidth > 0 && } - {rightCells.length > 0 &&
} +
{rightCells} {scrollbarWidth !== 0 && 0} />}
diff --git a/packages/x-data-grid/src/components/containers/GridRootStyles.ts b/packages/x-data-grid/src/components/containers/GridRootStyles.ts index 84cb0ec975ebf..3e52d28189683 100644 --- a/packages/x-data-grid/src/components/containers/GridRootStyles.ts +++ b/packages/x-data-grid/src/components/containers/GridRootStyles.ts @@ -567,6 +567,7 @@ export const GridRootStyles = styled('div', { lineHeight: 'inherit', }, [`& .${c.cellEmpty}`]: { + flex: 1, padding: 0, height: 'unset', }, diff --git a/packages/x-data-grid/src/hooks/features/columnResize/useGridColumnResize.tsx b/packages/x-data-grid/src/hooks/features/columnResize/useGridColumnResize.tsx index ae4c318dc523f..8874cdc6f84f4 100644 --- a/packages/x-data-grid/src/hooks/features/columnResize/useGridColumnResize.tsx +++ b/packages/x-data-grid/src/hooks/features/columnResize/useGridColumnResize.tsx @@ -301,12 +301,14 @@ export const useGridColumnResize = ( const prevWidth = refs.columnHeaderElement!.offsetWidth; const widthDiff = newWidth - prevWidth; const columnWidthDiff = newWidth - refs.initialColWidth; - const newTotalWidth = refs.initialTotalWidth + columnWidthDiff; - apiRef.current.rootElementRef?.current?.style.setProperty( - '--DataGrid-rowWidth', - `${newTotalWidth}px`, - ); + if (columnWidthDiff > 0) { + const newTotalWidth = refs.initialTotalWidth + columnWidthDiff; + apiRef.current.rootElementRef?.current?.style.setProperty( + '--DataGrid-rowWidth', + `${newTotalWidth}px`, + ); + } refs.colDef!.computedWidth = newWidth; refs.colDef!.width = newWidth; diff --git a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx index bf430095a3ffd..04780799c377e 100644 --- a/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx +++ b/packages/x-data-grid/src/tests/rows.DataGrid.test.tsx @@ -22,6 +22,7 @@ import { GridRenderCellParams, useGridApiRef, GridApi, + gridClasses, } from '@mui/x-data-grid'; import { getBasicGridData } from '@mui/x-data-grid-generator'; import { @@ -32,6 +33,7 @@ import { getActiveCell, getCell, microtasks, + $$, } from 'test/utils/helperFn'; import { fireUserEvent } from 'test/utils/fireUserEvent'; import Dialog from '@mui/material/Dialog'; @@ -756,7 +758,7 @@ describe(' - Rows', () => { width={100} />, ); - expect(document.querySelectorAll('.MuiDataGrid-cell')).to.have.length(2); + expect($$(`.${gridClasses.cell}:not(.${gridClasses.cellEmpty})`)).to.have.length(2); }); it('should measure rows while scrolling', async () => { diff --git a/test/regressions/data-grid/DataGridBordered.js b/test/regressions/data-grid/DataGridBordered.js new file mode 100644 index 0000000000000..b790417a5fc01 --- /dev/null +++ b/test/regressions/data-grid/DataGridBordered.js @@ -0,0 +1,26 @@ +import * as React from 'react'; +import { DataGridPro } from '@mui/x-data-grid-pro'; +import { randomTraderName, randomEmail } from '@mui/x-data-grid-generator'; + +const columns = [ + { field: 'name', headerName: 'Name', width: 160 }, + { field: 'email', headerName: 'Email', width: 200 }, + { field: 'age', headerName: 'Age', type: 'number' }, +]; + +const rows = [ + { + id: 1, + name: randomTraderName(), + email: randomEmail(), + age: 25, + }, +]; + +export default function DataGridBordered() { + return ( +
+ +
+ ); +} diff --git a/test/regressions/data-grid/DataGridPinnedColumnsBordered.js b/test/regressions/data-grid/DataGridPinnedColumnsBordered.js new file mode 100644 index 0000000000000..6fec3acd27857 --- /dev/null +++ b/test/regressions/data-grid/DataGridPinnedColumnsBordered.js @@ -0,0 +1,32 @@ +import * as React from 'react'; +import { DataGridPro } from '@mui/x-data-grid-pro'; +import { randomTraderName, randomEmail } from '@mui/x-data-grid-generator'; + +const columns = [ + { field: 'name', headerName: 'Name', width: 160 }, + { field: 'email', headerName: 'Email', width: 200 }, + { field: 'age', headerName: 'Age', type: 'number' }, +]; + +const rows = [ + { + id: 1, + name: randomTraderName(), + email: randomEmail(), + age: 25, + }, +]; + +export default function DataGridPinnedColumnsBordered() { + return ( +
+ +
+ ); +} diff --git a/test/regressions/data-grid/DataGridPinnedColumnsScrollbars.js b/test/regressions/data-grid/DataGridPinnedColumnsScrollbars.js new file mode 100644 index 0000000000000..7108528695f7a --- /dev/null +++ b/test/regressions/data-grid/DataGridPinnedColumnsScrollbars.js @@ -0,0 +1,134 @@ +import * as React from 'react'; +import DeleteIcon from '@mui/icons-material/Delete'; +import EditIcon from '@mui/icons-material/Edit'; +import { DataGridPro, GridActionsCellItem } from '@mui/x-data-grid-pro'; +import { + randomCreatedDate, + randomTraderName, + randomEmail, + randomUpdatedDate, +} from '@mui/x-data-grid-generator'; + +const columns = [ + { field: 'name', headerName: 'Name', width: 160, editable: true }, + { field: 'email', headerName: 'Email', width: 200, editable: true }, + { field: 'age', headerName: 'Age', type: 'number', editable: true }, + { + field: 'dateCreated', + headerName: 'Date Created', + type: 'date', + width: 180, + editable: true, + }, + { + field: 'lastLogin', + headerName: 'Last Login', + type: 'dateTime', + width: 220, + editable: true, + }, + { + field: 'actions', + type: 'actions', + width: 100, + getActions: () => [ + } label="Edit" />, + } label="Delete" />, + ], + }, +]; + +const rows = [ + { + id: 1, + name: randomTraderName(), + email: randomEmail(), + age: 25, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 2, + name: randomTraderName(), + email: randomEmail(), + age: 32, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 3, + name: randomTraderName(), + email: randomEmail(), + age: 45, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 4, + name: randomTraderName(), + email: randomEmail(), + age: 28, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 5, + name: randomTraderName(), + email: randomEmail(), + age: 39, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 6, + name: randomTraderName(), + email: randomEmail(), + age: 52, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 7, + name: randomTraderName(), + email: randomEmail(), + age: 33, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 8, + name: randomTraderName(), + email: randomEmail(), + age: 41, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 9, + name: randomTraderName(), + email: randomEmail(), + age: 36, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, + { + id: 10, + name: randomTraderName(), + email: randomEmail(), + age: 29, + dateCreated: randomCreatedDate(), + lastLogin: randomUpdatedDate(), + }, +]; + +export default function DataGridPinnedColumnsScrollbars() { + return ( +
+ +
+ ); +} diff --git a/test/regressions/data-grid/DataGridPinnedColumnsWithGap.js b/test/regressions/data-grid/DataGridPinnedColumnsWithGap.js new file mode 100644 index 0000000000000..492e054a6e243 --- /dev/null +++ b/test/regressions/data-grid/DataGridPinnedColumnsWithGap.js @@ -0,0 +1,30 @@ +import * as React from 'react'; +import { DataGridPro } from '@mui/x-data-grid-pro'; +import { randomTraderName, randomEmail } from '@mui/x-data-grid-generator'; + +const columns = [ + { field: 'name', headerName: 'Name', width: 160 }, + { field: 'email', headerName: 'Email', width: 200 }, + { field: 'age', headerName: 'Age', type: 'number' }, +]; + +const rows = [ + { + id: 1, + name: randomTraderName(), + email: randomEmail(), + age: 25, + }, +]; + +export default function DataGridPinnedColumnsWithGap() { + return ( +
+ +
+ ); +} diff --git a/test/regressions/index.test.ts b/test/regressions/index.test.ts index 849ee53754d6c..3bd8357b5c684 100644 --- a/test/regressions/index.test.ts +++ b/test/regressions/index.test.ts @@ -14,7 +14,13 @@ function sleep(timeoutMS: number | undefined) { const isMaterialUIv6 = materialPackageJson.version.startsWith('6.'); // Tests that need a longer timeout. -const timeSensitiveSuites = ['ColumnAutosizingAsync']; +const timeSensitiveSuites = [ + 'ColumnAutosizingAsync', + 'DensitySelectorGrid', + 'DataGridOverlays', + 'PopularFeaturesDemo', + 'ServerSideRowGroupingGroupExpansion', +]; const isConsoleWarningIgnored = (msg?: string) => { if (