diff --git a/packages/grid/_modules_/grid/components/cell/GridCell.tsx b/packages/grid/_modules_/grid/components/cell/GridCell.tsx index e7f6af3cf11a4..75aae6df4cd7f 100644 --- a/packages/grid/_modules_/grid/components/cell/GridCell.tsx +++ b/packages/grid/_modules_/grid/components/cell/GridCell.tsx @@ -130,12 +130,7 @@ function GridCell(props: GridCellProps) { (eventName: keyof GridCellEventLookup, propHandler: any) => (event: React.SyntheticEvent) => { // Ignore portal - // The target is not an element when triggered by a Select inside the cell - // See https://github.com/mui-org/material-ui/issues/10534 - if ( - (event.target as any).nodeType === 1 && - !event.currentTarget.contains(event.target as Element) - ) { + if (!event.currentTarget.contains(event.target as Element)) { return; } diff --git a/packages/grid/_modules_/grid/components/cell/GridEditSingleSelectCell.tsx b/packages/grid/_modules_/grid/components/cell/GridEditSingleSelectCell.tsx index d44020ce62568..36664a496e142 100644 --- a/packages/grid/_modules_/grid/components/cell/GridEditSingleSelectCell.tsx +++ b/packages/grid/_modules_/grid/components/cell/GridEditSingleSelectCell.tsx @@ -10,6 +10,7 @@ import { import { isEscapeKey } from '../../utils/keyboardUtils'; import { useGridRootProps } from '../../hooks/utils/useGridRootProps'; import { GridEditModes } from '../../models/gridEditRowModel'; +import { GridEvents } from '../../models/events/gridEvents'; const renderSingleSelectOptions = (option) => typeof option === 'object' ? ( @@ -71,10 +72,19 @@ function GridEditSingleSelectCell(props: GridRenderEditCellParams & SelectProps) const handleChange = async (event) => { setOpen(false); api.setEditCellValue({ id, field, value: event.target.value }, event); - if (!event.key && rootProps.editMode === 'cell') { - const isValid = await Promise.resolve(api.commitCellChange({ id, field }, event)); - if (isValid) { - api.setCellMode(id, field, 'view'); + + if (rootProps.editMode === GridEditModes.Row) { + return; + } + + const isValid = await Promise.resolve(api.commitCellChange({ id, field }, event)); + if (isValid) { + api.setCellMode(id, field, 'view'); + + if (event.key) { + // TODO v6: remove once we stop ignoring events fired from portals + const params = api.getCellParams(id, field); + api.publishEvent(GridEvents.cellNavigationKeyDown, params, event); } } }; diff --git a/packages/grid/_modules_/grid/hooks/features/keyboard/useGridKeyboard.ts b/packages/grid/_modules_/grid/hooks/features/keyboard/useGridKeyboard.ts index ba007d4f7c191..d851d62587453 100644 --- a/packages/grid/_modules_/grid/hooks/features/keyboard/useGridKeyboard.ts +++ b/packages/grid/_modules_/grid/hooks/features/keyboard/useGridKeyboard.ts @@ -53,9 +53,10 @@ export const useGridKeyboard = (apiRef: GridApiRef): void => { const handleCellKeyDown = React.useCallback>( (params, event) => { - // The target is not an element when triggered by a Select inside the cell - // See https://github.com/mui-org/material-ui/issues/10534 - if ((event.target as any).nodeType === 1 && !isGridCellRoot(event.target as Element)) { + // Ignore portal + // Do not apply shortcuts if the focus is not on the cell root component + // TODO replace with !event.currentTarget.contains(event.target as Element) + if (!isGridCellRoot(event.target as Element)) { return; } diff --git a/packages/grid/x-data-grid-generator/src/renderer/renderEditContractType.tsx b/packages/grid/x-data-grid-generator/src/renderer/renderEditContractType.tsx index 4771ca3280754..c8ad8baeaac8c 100644 --- a/packages/grid/x-data-grid-generator/src/renderer/renderEditContractType.tsx +++ b/packages/grid/x-data-grid-generator/src/renderer/renderEditContractType.tsx @@ -6,6 +6,7 @@ import MenuItem from '@mui/material/MenuItem'; import { createStyles, makeStyles } from '@mui/styles'; import { createTheme } from '@mui/material/styles'; import { CONTRACT_TYPE_OPTIONS } from '../services/static-data'; +import { GridEvents } from '../../../_modules_/grid/models/events/gridEvents'; const defaultTheme = createTheme(); const useStyles = makeStyles( @@ -32,9 +33,13 @@ function EditContractType(props: GridRenderCellParams) { const handleChange: SelectProps['onChange'] = (event) => { api.setEditCellValue({ id, field, value: event.target.value }, event); - if (!(event as any).key) { - api.commitCellChange({ id, field }); - api.setCellMode(id, field, 'view'); + api.commitCellChange({ id, field }); + api.setCellMode(id, field, 'view'); + + if ((event as any).key) { + // TODO v6: remove once we stop ignoring events fired from portals + const params = api.getCellParams(id, field); + api.publishEvent(GridEvents.cellNavigationKeyDown, params, event); } }; diff --git a/packages/grid/x-data-grid-generator/src/renderer/renderEditIncoterm.tsx b/packages/grid/x-data-grid-generator/src/renderer/renderEditIncoterm.tsx index d3ff39ca82245..2fe2ba1586172 100644 --- a/packages/grid/x-data-grid-generator/src/renderer/renderEditIncoterm.tsx +++ b/packages/grid/x-data-grid-generator/src/renderer/renderEditIncoterm.tsx @@ -8,6 +8,7 @@ import ListItemText from '@mui/material/ListItemText'; import { createStyles, makeStyles } from '@mui/styles'; import { createTheme } from '@mui/material/styles'; import { INCOTERM_OPTIONS } from '../services/static-data'; +import { GridEvents } from '../../../_modules_/grid/models/events/gridEvents'; const defaultTheme = createTheme(); const useStyles = makeStyles( @@ -34,9 +35,13 @@ function EditIncoterm(props: GridRenderEditCellParams) { const handleChange: SelectProps['onChange'] = (event) => { api.setEditCellValue({ id, field, value: event.target.value }, event); - if (!(event as any).key) { - api.commitCellChange({ id, field }); - api.setCellMode(id, field, 'view'); + api.commitCellChange({ id, field }); + api.setCellMode(id, field, 'view'); + + if ((event as any).key) { + // TODO v6: remove once we stop ignoring events fired from portals + const params = api.getCellParams(id, field); + api.publishEvent(GridEvents.cellNavigationKeyDown, params, event); } }; diff --git a/packages/grid/x-data-grid-generator/src/renderer/renderEditRateType.tsx b/packages/grid/x-data-grid-generator/src/renderer/renderEditRateType.tsx index ad6c2a44ba66c..e3487ce07a268 100644 --- a/packages/grid/x-data-grid-generator/src/renderer/renderEditRateType.tsx +++ b/packages/grid/x-data-grid-generator/src/renderer/renderEditRateType.tsx @@ -6,6 +6,7 @@ import MenuItem from '@mui/material/MenuItem'; import { createStyles, makeStyles } from '@mui/styles'; import { createTheme } from '@mui/material/styles'; import { RATE_TYPE_OPTIONS } from '../services/static-data'; +import { GridEvents } from '../../../_modules_/grid/models/events/gridEvents'; const defaultTheme = createTheme(); const useStyles = makeStyles( @@ -32,9 +33,13 @@ function EditRateType(props: GridRenderCellParams) { const handleChange: SelectProps['onChange'] = (event) => { api.setEditCellValue({ id, field, value: event.target.value }, event); - if (!(event as any).key) { - api.commitCellChange({ id, field }); - api.setCellMode(id, field, 'view'); + api.commitCellChange({ id, field }); + api.setCellMode(id, field, 'view'); + + if ((event as any).key) { + // TODO v6: remove once we stop ignoring events fired from portals + const params = api.getCellParams(id, field); + api.publishEvent(GridEvents.cellNavigationKeyDown, params, event); } }; diff --git a/packages/grid/x-data-grid-generator/src/renderer/renderEditStatus.tsx b/packages/grid/x-data-grid-generator/src/renderer/renderEditStatus.tsx index cefe5b5574b4b..2a809652c00ed 100644 --- a/packages/grid/x-data-grid-generator/src/renderer/renderEditStatus.tsx +++ b/packages/grid/x-data-grid-generator/src/renderer/renderEditStatus.tsx @@ -12,6 +12,7 @@ import DoneIcon from '@mui/icons-material/Done'; import { createStyles, makeStyles } from '@mui/styles'; import { createTheme } from '@mui/material/styles'; import { STATUS_OPTIONS } from '../services/static-data'; +import { GridEvents } from '../../../_modules_/grid/models/events/gridEvents'; const defaultTheme = createTheme(); const useStyles = makeStyles( @@ -38,9 +39,13 @@ function EditStatus(props: GridRenderEditCellParams) { const handleChange: SelectProps['onChange'] = (event) => { api.setEditCellValue({ id, field, value: event.target.value }, event); - if (!(event as any).key) { - api.commitCellChange({ id, field }); - api.setCellMode(id, field, 'view'); + api.commitCellChange({ id, field }); + api.setCellMode(id, field, 'view'); + + if ((event as any).key) { + // TODO v6: remove once we stop ignoring events fired from portals + const params = api.getCellParams(id, field); + api.publishEvent(GridEvents.cellNavigationKeyDown, params, event); } }; diff --git a/packages/grid/x-data-grid-generator/src/renderer/renderEditTaxCode.tsx b/packages/grid/x-data-grid-generator/src/renderer/renderEditTaxCode.tsx index 4dc0af0a0300e..72691b3198f44 100644 --- a/packages/grid/x-data-grid-generator/src/renderer/renderEditTaxCode.tsx +++ b/packages/grid/x-data-grid-generator/src/renderer/renderEditTaxCode.tsx @@ -6,6 +6,7 @@ import MenuItem from '@mui/material/MenuItem'; import { createStyles, makeStyles } from '@mui/styles'; import { createTheme } from '@mui/material/styles'; import { TAXCODE_OPTIONS } from '../services/static-data'; +import { GridEvents } from '../../../_modules_/grid/models/events/gridEvents'; const defaultTheme = createTheme(); const useStyles = makeStyles( @@ -32,9 +33,13 @@ function EditTaxCode(props: GridRenderCellParams) { const handleChange: SelectProps['onChange'] = (event) => { api.setEditCellValue({ id, field, value: event.target.value }, event); - if (!(event as any).key) { - api.commitCellChange({ id, field }); - api.setCellMode(id, field, 'view'); + api.commitCellChange({ id, field }); + api.setCellMode(id, field, 'view'); + + if ((event as any).key) { + // TODO v6: remove once we stop ignoring events fired from portals + const params = api.getCellParams(id, field); + api.publishEvent(GridEvents.cellNavigationKeyDown, params, event); } }; diff --git a/packages/grid/x-data-grid-pro/src/tests/editRows.DataGridPro.test.tsx b/packages/grid/x-data-grid-pro/src/tests/editRows.DataGridPro.test.tsx index b33b41ed45a21..b7e6269483598 100644 --- a/packages/grid/x-data-grid-pro/src/tests/editRows.DataGridPro.test.tsx +++ b/packages/grid/x-data-grid-pro/src/tests/editRows.DataGridPro.test.tsx @@ -754,7 +754,7 @@ describe(' - Edit Rows', () => { expect(secondOption).to.have.text('Admin'); }); - it('should set the focus correctly', () => { + it('should set the focus correctly when entering the edit mode with a double click', () => { render( - Edit Rows', () => { expect(screen.getByRole('button', { name: 'Nike' })).toHaveFocus(); }); + it('should move the focus to the cell below when selecting a value with Enter', async () => { + render( + , + ); + const cell = getCell(0, 0); + cell.focus(); + fireEvent.keyDown(cell, { key: 'Enter' }); + fireEvent.keyDown(screen.queryByRole('option', { name: 'Nike' }), { key: 'ArrowDown' }); + fireEvent.keyDown(screen.queryByRole('option', { name: 'Adidas' }), { key: 'Enter' }); + await waitFor(() => { + // @ts-expect-error need to migrate helpers to TypeScript + expect(getCell(1, 0)).toHaveFocus(); + }); + }); + it('should not exit the edit mode when validateCell returns an object with error', async () => { render(