@mui/x-data-grid 5.14.0 → 5.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (290) hide show
  1. package/CHANGELOG.md +147 -5
  2. package/DataGrid/DataGrid.js +7 -1
  3. package/DataGrid/useDataGridProps.js +1 -0
  4. package/colDef/gridStringColDef.js +1 -1
  5. package/components/GridRow.js +5 -1
  6. package/components/base/GridOverlays.js +2 -2
  7. package/components/cell/GridEditInputCell.d.ts +2 -5
  8. package/components/cell/GridEditInputCell.js +13 -14
  9. package/components/cell/GridEditSingleSelectCell.d.ts +4 -0
  10. package/components/cell/GridEditSingleSelectCell.js +11 -4
  11. package/components/columnSelection/GridCellCheckboxRenderer.js +5 -0
  12. package/components/containers/GridRoot.js +4 -2
  13. package/components/toolbar/GridToolbarDensitySelector.js +13 -4
  14. package/components/toolbar/GridToolbarExportContainer.js +13 -2
  15. package/constants/envConstants.d.ts +1 -1
  16. package/constants/envConstants.js +2 -11
  17. package/constants/gridClasses.d.ts +16 -0
  18. package/constants/gridClasses.js +1 -1
  19. package/constants/localeTextConstants.js +1 -1
  20. package/hooks/features/dimensions/useGridDimensions.js +6 -1
  21. package/hooks/features/editRows/useGridCellEditing.new.d.ts +1 -1
  22. package/hooks/features/editRows/useGridCellEditing.new.js +26 -16
  23. package/hooks/features/editRows/useGridCellEditing.old.js +2 -2
  24. package/hooks/features/editRows/useGridEditing.new.d.ts +1 -1
  25. package/hooks/features/editRows/useGridEditing.new.js +4 -0
  26. package/hooks/features/editRows/useGridEditing.old.js +1 -1
  27. package/hooks/features/editRows/useGridRowEditing.new.d.ts +1 -1
  28. package/hooks/features/editRows/useGridRowEditing.new.js +16 -10
  29. package/hooks/features/export/utils.js +8 -1
  30. package/hooks/features/filter/gridFilterState.d.ts +12 -1
  31. package/hooks/features/filter/gridFilterUtils.d.ts +8 -5
  32. package/hooks/features/filter/gridFilterUtils.js +74 -43
  33. package/hooks/features/filter/useGridFilter.js +16 -3
  34. package/hooks/features/focus/useGridFocus.js +11 -6
  35. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
  36. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +42 -34
  37. package/hooks/features/pagination/useGridPageSize.js +3 -1
  38. package/hooks/features/rows/gridRowsSelector.d.ts +14 -0
  39. package/hooks/features/rows/gridRowsSelector.js +20 -1
  40. package/hooks/features/rows/gridRowsState.d.ts +8 -1
  41. package/hooks/features/rows/gridRowsUtils.d.ts +4 -0
  42. package/hooks/features/rows/gridRowsUtils.js +21 -3
  43. package/hooks/features/rows/index.d.ts +1 -1
  44. package/hooks/features/rows/index.js +1 -1
  45. package/hooks/features/rows/useGridRows.js +5 -2
  46. package/hooks/features/rows/useGridRowsMeta.js +19 -4
  47. package/hooks/features/rows/useGridRowsPreProcessors.js +2 -1
  48. package/hooks/features/scroll/useGridScroll.js +7 -2
  49. package/hooks/features/selection/useGridSelection.js +7 -3
  50. package/hooks/features/sorting/useGridSorting.js +8 -0
  51. package/hooks/features/statePersistence/gridStatePersistenceInterface.d.ts +3 -0
  52. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +3 -1
  53. package/hooks/features/virtualization/useGridVirtualScroller.js +31 -16
  54. package/index.js +1 -1
  55. package/internals/index.d.ts +5 -1
  56. package/internals/index.js +4 -0
  57. package/legacy/DataGrid/DataGrid.js +7 -1
  58. package/legacy/DataGrid/useDataGridProps.js +1 -0
  59. package/legacy/colDef/gridStringColDef.js +1 -1
  60. package/legacy/components/GridRow.js +5 -1
  61. package/legacy/components/base/GridOverlays.js +2 -2
  62. package/legacy/components/cell/GridEditInputCell.js +13 -14
  63. package/legacy/components/cell/GridEditSingleSelectCell.js +11 -3
  64. package/legacy/components/columnSelection/GridCellCheckboxRenderer.js +5 -0
  65. package/legacy/components/containers/GridRoot.js +4 -2
  66. package/legacy/components/toolbar/GridToolbarDensitySelector.js +14 -5
  67. package/legacy/components/toolbar/GridToolbarExportContainer.js +15 -2
  68. package/legacy/constants/envConstants.js +2 -11
  69. package/legacy/constants/gridClasses.js +1 -1
  70. package/legacy/constants/localeTextConstants.js +1 -1
  71. package/legacy/hooks/features/dimensions/useGridDimensions.js +6 -1
  72. package/legacy/hooks/features/editRows/useGridCellEditing.new.js +27 -17
  73. package/legacy/hooks/features/editRows/useGridCellEditing.old.js +2 -2
  74. package/legacy/hooks/features/editRows/useGridEditing.new.js +4 -0
  75. package/legacy/hooks/features/editRows/useGridEditing.old.js +1 -1
  76. package/legacy/hooks/features/editRows/useGridRowEditing.new.js +16 -10
  77. package/legacy/hooks/features/export/utils.js +13 -1
  78. package/legacy/hooks/features/filter/gridFilterUtils.js +84 -55
  79. package/legacy/hooks/features/filter/useGridFilter.js +16 -3
  80. package/legacy/hooks/features/focus/useGridFocus.js +11 -6
  81. package/legacy/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +47 -34
  82. package/legacy/hooks/features/pagination/useGridPageSize.js +3 -1
  83. package/legacy/hooks/features/rows/gridRowsSelector.js +23 -0
  84. package/legacy/hooks/features/rows/gridRowsUtils.js +21 -3
  85. package/legacy/hooks/features/rows/index.js +1 -1
  86. package/legacy/hooks/features/rows/useGridRows.js +5 -2
  87. package/legacy/hooks/features/rows/useGridRowsMeta.js +19 -4
  88. package/legacy/hooks/features/rows/useGridRowsPreProcessors.js +2 -1
  89. package/legacy/hooks/features/scroll/useGridScroll.js +7 -2
  90. package/legacy/hooks/features/selection/useGridSelection.js +7 -3
  91. package/legacy/hooks/features/sorting/useGridSorting.js +8 -0
  92. package/legacy/hooks/features/virtualization/useGridVirtualScroller.js +32 -16
  93. package/legacy/index.js +1 -1
  94. package/legacy/internals/index.js +4 -0
  95. package/legacy/locales/arSD.js +1 -1
  96. package/legacy/locales/bgBG.js +1 -1
  97. package/legacy/locales/csCZ.js +1 -1
  98. package/legacy/locales/daDK.js +1 -1
  99. package/legacy/locales/deDE.js +9 -9
  100. package/legacy/locales/elGR.js +1 -1
  101. package/legacy/locales/esES.js +1 -1
  102. package/legacy/locales/faIR.js +1 -1
  103. package/legacy/locales/fiFI.js +1 -1
  104. package/legacy/locales/frFR.js +1 -1
  105. package/legacy/locales/heIL.js +1 -1
  106. package/legacy/locales/huHU.js +1 -1
  107. package/legacy/locales/itIT.js +15 -15
  108. package/legacy/locales/jaJP.js +3 -3
  109. package/legacy/locales/koKR.js +34 -30
  110. package/legacy/locales/nbNO.js +1 -1
  111. package/legacy/locales/nlNL.js +1 -1
  112. package/legacy/locales/plPL.js +1 -1
  113. package/legacy/locales/ptBR.js +1 -1
  114. package/legacy/locales/roRO.js +1 -1
  115. package/legacy/locales/ruRU.js +1 -1
  116. package/legacy/locales/skSK.js +1 -1
  117. package/legacy/locales/svSE.js +1 -1
  118. package/legacy/locales/trTR.js +1 -1
  119. package/legacy/locales/ukUA.js +1 -1
  120. package/legacy/locales/viVN.js +1 -1
  121. package/legacy/locales/zhCN.js +37 -33
  122. package/legacy/locales/zhTW.js +1 -1
  123. package/legacy/utils/keyboardUtils.js +8 -5
  124. package/locales/arSD.js +1 -1
  125. package/locales/bgBG.js +1 -1
  126. package/locales/csCZ.js +1 -1
  127. package/locales/daDK.js +1 -1
  128. package/locales/deDE.js +9 -9
  129. package/locales/elGR.js +1 -1
  130. package/locales/esES.js +1 -1
  131. package/locales/faIR.js +1 -1
  132. package/locales/fiFI.js +1 -1
  133. package/locales/frFR.js +1 -1
  134. package/locales/heIL.js +1 -1
  135. package/locales/huHU.js +1 -1
  136. package/locales/itIT.js +15 -15
  137. package/locales/jaJP.js +3 -3
  138. package/locales/koKR.js +30 -30
  139. package/locales/nbNO.js +1 -1
  140. package/locales/nlNL.js +1 -1
  141. package/locales/plPL.js +1 -1
  142. package/locales/ptBR.js +1 -1
  143. package/locales/roRO.js +1 -1
  144. package/locales/ruRU.js +1 -1
  145. package/locales/skSK.js +1 -1
  146. package/locales/svSE.js +1 -1
  147. package/locales/trTR.js +1 -1
  148. package/locales/ukUA.js +1 -1
  149. package/locales/viVN.js +1 -1
  150. package/locales/zhCN.js +33 -33
  151. package/locales/zhTW.js +1 -1
  152. package/models/gridRows.d.ts +5 -0
  153. package/models/props/DataGridProps.d.ts +8 -3
  154. package/modern/DataGrid/DataGrid.js +7 -1
  155. package/modern/DataGrid/useDataGridProps.js +1 -0
  156. package/modern/colDef/gridStringColDef.js +1 -1
  157. package/modern/components/GridRow.js +5 -1
  158. package/modern/components/base/GridOverlays.js +2 -2
  159. package/modern/components/cell/GridEditInputCell.js +13 -14
  160. package/modern/components/cell/GridEditSingleSelectCell.js +11 -4
  161. package/modern/components/columnSelection/GridCellCheckboxRenderer.js +5 -0
  162. package/modern/components/containers/GridRoot.js +4 -2
  163. package/modern/components/toolbar/GridToolbarDensitySelector.js +11 -4
  164. package/modern/components/toolbar/GridToolbarExportContainer.js +11 -2
  165. package/modern/constants/envConstants.js +2 -11
  166. package/modern/constants/gridClasses.js +1 -1
  167. package/modern/constants/localeTextConstants.js +1 -1
  168. package/modern/hooks/features/dimensions/useGridDimensions.js +6 -1
  169. package/modern/hooks/features/editRows/useGridCellEditing.new.js +24 -16
  170. package/modern/hooks/features/editRows/useGridCellEditing.old.js +2 -2
  171. package/modern/hooks/features/editRows/useGridEditing.new.js +4 -0
  172. package/modern/hooks/features/editRows/useGridEditing.old.js +1 -1
  173. package/modern/hooks/features/editRows/useGridRowEditing.new.js +16 -10
  174. package/modern/hooks/features/export/utils.js +6 -1
  175. package/modern/hooks/features/filter/gridFilterUtils.js +73 -42
  176. package/modern/hooks/features/filter/useGridFilter.js +16 -3
  177. package/modern/hooks/features/focus/useGridFocus.js +11 -6
  178. package/modern/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +42 -30
  179. package/modern/hooks/features/pagination/useGridPageSize.js +3 -1
  180. package/modern/hooks/features/rows/gridRowsSelector.js +18 -1
  181. package/modern/hooks/features/rows/gridRowsUtils.js +19 -3
  182. package/modern/hooks/features/rows/index.js +1 -1
  183. package/modern/hooks/features/rows/useGridRows.js +5 -2
  184. package/modern/hooks/features/rows/useGridRowsMeta.js +17 -4
  185. package/modern/hooks/features/rows/useGridRowsPreProcessors.js +2 -1
  186. package/modern/hooks/features/scroll/useGridScroll.js +5 -2
  187. package/modern/hooks/features/selection/useGridSelection.js +7 -1
  188. package/modern/hooks/features/sorting/useGridSorting.js +8 -0
  189. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +30 -15
  190. package/modern/index.js +1 -1
  191. package/modern/internals/index.js +4 -0
  192. package/modern/locales/arSD.js +1 -1
  193. package/modern/locales/bgBG.js +1 -1
  194. package/modern/locales/csCZ.js +1 -1
  195. package/modern/locales/daDK.js +1 -1
  196. package/modern/locales/deDE.js +9 -9
  197. package/modern/locales/elGR.js +1 -1
  198. package/modern/locales/esES.js +1 -1
  199. package/modern/locales/faIR.js +1 -1
  200. package/modern/locales/fiFI.js +1 -1
  201. package/modern/locales/frFR.js +1 -1
  202. package/modern/locales/heIL.js +1 -1
  203. package/modern/locales/huHU.js +1 -1
  204. package/modern/locales/itIT.js +15 -15
  205. package/modern/locales/jaJP.js +3 -3
  206. package/modern/locales/koKR.js +30 -30
  207. package/modern/locales/nbNO.js +1 -1
  208. package/modern/locales/nlNL.js +1 -1
  209. package/modern/locales/plPL.js +1 -1
  210. package/modern/locales/ptBR.js +1 -1
  211. package/modern/locales/roRO.js +1 -1
  212. package/modern/locales/ruRU.js +1 -1
  213. package/modern/locales/skSK.js +1 -1
  214. package/modern/locales/svSE.js +1 -1
  215. package/modern/locales/trTR.js +1 -1
  216. package/modern/locales/ukUA.js +1 -1
  217. package/modern/locales/viVN.js +1 -1
  218. package/modern/locales/zhCN.js +33 -33
  219. package/modern/locales/zhTW.js +1 -1
  220. package/modern/utils/keyboardUtils.js +7 -2
  221. package/node/DataGrid/DataGrid.js +7 -1
  222. package/node/DataGrid/useDataGridProps.js +1 -0
  223. package/node/colDef/gridStringColDef.js +1 -1
  224. package/node/components/GridRow.js +5 -1
  225. package/node/components/base/GridOverlays.js +2 -2
  226. package/node/components/cell/GridEditInputCell.js +15 -16
  227. package/node/components/cell/GridEditSingleSelectCell.js +10 -4
  228. package/node/components/columnSelection/GridCellCheckboxRenderer.js +5 -0
  229. package/node/components/containers/GridRoot.js +3 -1
  230. package/node/components/toolbar/GridToolbarDensitySelector.js +13 -4
  231. package/node/components/toolbar/GridToolbarExportContainer.js +13 -2
  232. package/node/constants/envConstants.js +2 -13
  233. package/node/constants/gridClasses.js +1 -1
  234. package/node/constants/localeTextConstants.js +1 -1
  235. package/node/hooks/features/dimensions/useGridDimensions.js +7 -1
  236. package/node/hooks/features/editRows/useGridCellEditing.new.js +26 -16
  237. package/node/hooks/features/editRows/useGridCellEditing.old.js +2 -2
  238. package/node/hooks/features/editRows/useGridEditing.new.js +4 -0
  239. package/node/hooks/features/editRows/useGridEditing.old.js +1 -1
  240. package/node/hooks/features/editRows/useGridRowEditing.new.js +16 -10
  241. package/node/hooks/features/export/utils.js +7 -0
  242. package/node/hooks/features/filter/gridFilterUtils.js +81 -47
  243. package/node/hooks/features/filter/useGridFilter.js +15 -2
  244. package/node/hooks/features/focus/useGridFocus.js +11 -6
  245. package/node/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +43 -34
  246. package/node/hooks/features/pagination/useGridPageSize.js +4 -1
  247. package/node/hooks/features/rows/gridRowsSelector.js +24 -2
  248. package/node/hooks/features/rows/gridRowsUtils.js +23 -2
  249. package/node/hooks/features/rows/index.js +70 -12
  250. package/node/hooks/features/rows/useGridRows.js +5 -2
  251. package/node/hooks/features/rows/useGridRowsMeta.js +20 -4
  252. package/node/hooks/features/rows/useGridRowsPreProcessors.js +2 -1
  253. package/node/hooks/features/scroll/useGridScroll.js +7 -1
  254. package/node/hooks/features/selection/useGridSelection.js +7 -3
  255. package/node/hooks/features/sorting/useGridSorting.js +8 -0
  256. package/node/hooks/features/virtualization/useGridVirtualScroller.js +31 -16
  257. package/node/index.js +1 -1
  258. package/node/internals/index.js +36 -0
  259. package/node/locales/arSD.js +1 -1
  260. package/node/locales/bgBG.js +1 -1
  261. package/node/locales/csCZ.js +1 -1
  262. package/node/locales/daDK.js +1 -1
  263. package/node/locales/deDE.js +9 -9
  264. package/node/locales/elGR.js +1 -1
  265. package/node/locales/esES.js +1 -1
  266. package/node/locales/faIR.js +1 -1
  267. package/node/locales/fiFI.js +1 -1
  268. package/node/locales/frFR.js +1 -1
  269. package/node/locales/heIL.js +1 -1
  270. package/node/locales/huHU.js +1 -1
  271. package/node/locales/itIT.js +15 -15
  272. package/node/locales/jaJP.js +3 -3
  273. package/node/locales/koKR.js +30 -30
  274. package/node/locales/nbNO.js +1 -1
  275. package/node/locales/nlNL.js +1 -1
  276. package/node/locales/plPL.js +1 -1
  277. package/node/locales/ptBR.js +1 -1
  278. package/node/locales/roRO.js +1 -1
  279. package/node/locales/ruRU.js +1 -1
  280. package/node/locales/skSK.js +1 -1
  281. package/node/locales/svSE.js +1 -1
  282. package/node/locales/trTR.js +1 -1
  283. package/node/locales/ukUA.js +1 -1
  284. package/node/locales/viVN.js +1 -1
  285. package/node/locales/zhCN.js +33 -33
  286. package/node/locales/zhTW.js +1 -1
  287. package/node/utils/keyboardUtils.js +10 -4
  288. package/package.json +1 -1
  289. package/utils/keyboardUtils.d.ts +2 -2
  290. package/utils/keyboardUtils.js +7 -2
@@ -42,6 +42,7 @@ const missingOnProcessRowUpdateErrorWarning = (0, _warning.buildWarning)(['MUI:
42
42
 
43
43
  const useGridCellEditing = (apiRef, props) => {
44
44
  const [cellModesModel, setCellModesModel] = React.useState({});
45
+ const cellModesModelRef = React.useRef(cellModesModel);
45
46
  const prevCellModesModel = React.useRef({});
46
47
  const {
47
48
  processRowUpdate,
@@ -88,6 +89,10 @@ const useGridCellEditing = (apiRef, props) => {
88
89
  return;
89
90
  }
90
91
 
92
+ if (apiRef.current.getCellMode(params.id, params.field) === _gridEditRowModel.GridCellModes.View) {
93
+ return;
94
+ }
95
+
91
96
  const newParams = (0, _extends2.default)({}, params, {
92
97
  reason: _gridEditCellParams.GridCellEditStopReasons.cellFocusOut
93
98
  });
@@ -121,15 +126,14 @@ const useGridCellEditing = (apiRef, props) => {
121
126
  } else if (params.isEditable) {
122
127
  let reason;
123
128
 
124
- if ((0, _keyboardUtils.isPrintableKey)(event.key)) {
125
- if (event.ctrlKey && event.key !== 'v' || event.metaKey && event.key !== 'v' || event.altKey) {
126
- return;
127
- }
128
-
129
+ if ((0, _keyboardUtils.isPrintableKey)(event)) {
130
+ reason = _gridEditCellParams.GridCellEditStartReasons.printableKeyDown;
131
+ } else if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
129
132
  reason = _gridEditCellParams.GridCellEditStartReasons.printableKeyDown;
130
133
  } else if (event.key === 'Enter') {
131
134
  reason = _gridEditCellParams.GridCellEditStartReasons.enterKeyDown;
132
- } else if (event.key === 'Delete') {
135
+ } else if (event.key === 'Delete' || event.key === 'Backspace') {
136
+ // Delete on Windows, Backspace on macOS
133
137
  reason = _gridEditCellParams.GridCellEditStartReasons.deleteKeyDown;
134
138
  }
135
139
 
@@ -164,6 +168,7 @@ const useGridCellEditing = (apiRef, props) => {
164
168
  field,
165
169
  reason
166
170
  } = params;
171
+ apiRef.current.unstable_runPendingEditCellValueMutation(id, field);
167
172
  let cellToFocusAfter;
168
173
 
169
174
  if (reason === _gridEditCellParams.GridCellEditStopReasons.enterKeyDown) {
@@ -177,7 +182,7 @@ const useGridCellEditing = (apiRef, props) => {
177
182
  let ignoreModifications = reason === 'escapeKeyDown';
178
183
  const editingState = (0, _gridEditRowsSelector.gridEditRowsStateSelector)(apiRef.current.state);
179
184
 
180
- if (editingState[id][field].isProcessingProps) {
185
+ if (editingState[id][field].isProcessingProps && !props.disableIgnoreModificationsIfProcessingProps) {
181
186
  // The user wants to stop editing the cell but we can't wait for the props to be processed.
182
187
  // In this case, discard the modifications.
183
188
  ignoreModifications = true;
@@ -189,7 +194,7 @@ const useGridCellEditing = (apiRef, props) => {
189
194
  ignoreModifications,
190
195
  cellToFocusAfter
191
196
  });
192
- }, [apiRef]);
197
+ }, [apiRef, props.disableIgnoreModificationsIfProcessingProps]);
193
198
  (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellDoubleClick', runIfEditModeIsCell(handleCellDoubleClick));
194
199
  (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellFocusOut', runIfEditModeIsCell(handleCellFocusOut));
195
200
  (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellKeyDown', runIfEditModeIsCell(handleCellKeyDown));
@@ -217,18 +222,21 @@ const useGridCellEditing = (apiRef, props) => {
217
222
  }
218
223
 
219
224
  setCellModesModel(newModel);
225
+ cellModesModelRef.current = newModel;
220
226
  apiRef.current.publishEvent('cellModesModelChange', newModel);
221
227
  }, [apiRef, onCellModesModelChange, props.cellModesModel, signature]);
222
228
  const updateFieldInCellModesModel = React.useCallback((id, field, newProps) => {
223
- const newModel = (0, _extends2.default)({}, cellModesModel);
229
+ // We use the ref because it always contain the up-to-date value, different from the state
230
+ // that needs a rerender to reflect the new value
231
+ const newModel = (0, _extends2.default)({}, cellModesModelRef.current);
224
232
 
225
233
  if (newProps !== null) {
226
234
  newModel[id] = (0, _extends2.default)({}, newModel[id], {
227
235
  [field]: (0, _extends2.default)({}, newProps)
228
236
  });
229
237
  } else {
230
- const _cellModesModel$id = cellModesModel[id],
231
- otherFields = (0, _objectWithoutPropertiesLoose2.default)(_cellModesModel$id, [field].map(_toPropertyKey2.default)); // Ensure that we have a new object, not a reference
238
+ const _newModel$id = newModel[id],
239
+ otherFields = (0, _objectWithoutPropertiesLoose2.default)(_newModel$id, [field].map(_toPropertyKey2.default)); // Ensure that we have a new object, not a reference
232
240
 
233
241
  newModel[id] = otherFields;
234
242
 
@@ -238,7 +246,7 @@ const useGridCellEditing = (apiRef, props) => {
238
246
  }
239
247
 
240
248
  updateCellModesModel(newModel);
241
- }, [cellModesModel, updateCellModesModel]);
249
+ }, [updateCellModesModel]);
242
250
  const updateOrDeleteFieldState = React.useCallback((id, field, newProps) => {
243
251
  apiRef.current.setState(state => {
244
252
  const newEditingState = (0, _extends2.default)({}, state.editRows);
@@ -309,12 +317,12 @@ const useGridCellEditing = (apiRef, props) => {
309
317
  apiRef.current.unstable_runPendingEditCellValueMutation(id, field);
310
318
 
311
319
  const finishCellEditMode = () => {
320
+ updateOrDeleteFieldState(id, field, null);
321
+ updateFieldInCellModesModel(id, field, null);
322
+
312
323
  if (cellToFocusAfter !== 'none') {
313
324
  apiRef.current.unstable_moveFocusToRelativeCell(id, field, cellToFocusAfter);
314
325
  }
315
-
316
- updateOrDeleteFieldState(id, field, null);
317
- updateFieldInCellModesModel(id, field, null);
318
326
  };
319
327
 
320
328
  if (ignoreModifications) {
@@ -363,6 +371,8 @@ const useGridCellEditing = (apiRef, props) => {
363
371
  }
364
372
  }, [apiRef, onProcessRowUpdateError, processRowUpdate, throwIfNotInMode, updateFieldInCellModesModel, updateOrDeleteFieldState]);
365
373
  const setCellEditingEditCellValue = React.useCallback(async params => {
374
+ var _editingState$id, _editingState$id$fiel;
375
+
366
376
  const {
367
377
  id,
368
378
  field,
@@ -413,7 +423,7 @@ const useGridCellEditing = (apiRef, props) => {
413
423
  newProps.value = column.preProcessEditCellProps ? editingState[id][field].value : parsedValue;
414
424
  updateOrDeleteFieldState(id, field, newProps);
415
425
  editingState = (0, _gridEditRowsSelector.gridEditRowsStateSelector)(apiRef.current.state);
416
- return !editingState[id][field].error;
426
+ return !((_editingState$id = editingState[id]) != null && (_editingState$id$fiel = _editingState$id[field]) != null && _editingState$id$fiel.error);
417
427
  }, [apiRef, throwIfNotEditable, throwIfNotInMode, updateOrDeleteFieldState]);
418
428
  const getRowWithUpdatedValuesFromCellEditing = React.useCallback((id, field) => {
419
429
  const column = apiRef.current.getColumn(field);
@@ -219,7 +219,7 @@ const useCellEditing = (apiRef, props) => {
219
219
  const isEditMode = cellMode === _gridEditRowModel.GridCellModes.Edit;
220
220
  const isModifierKeyPressed = event.ctrlKey || event.metaKey || event.altKey;
221
221
 
222
- if (!isEditMode && (0, _keyboardUtils.isCellEnterEditModeKeys)(event.key) && !isModifierKeyPressed && !(event.key === ' ' && event.shiftKey)) {
222
+ if (!isEditMode && (0, _keyboardUtils.isCellEnterEditModeKeys)(event) && !isModifierKeyPressed && !(event.key === ' ' && event.shiftKey)) {
223
223
  apiRef.current.publishEvent('cellEditStart', params, event);
224
224
  }
225
225
 
@@ -289,7 +289,7 @@ const useCellEditing = (apiRef, props) => {
289
289
 
290
290
  apiRef.current.setCellMode(params.id, params.field, _gridEditRowModel.GridCellModes.Edit);
291
291
 
292
- if ((0, _keyboardUtils.isKeyboardEvent)(event) && (0, _keyboardUtils.isPrintableKey)(event.key)) {
292
+ if ((0, _keyboardUtils.isKeyboardEvent)(event) && (0, _keyboardUtils.isPrintableKey)(event)) {
293
293
  apiRef.current.unstable_setEditCellProps({
294
294
  id: params.id,
295
295
  field: params.field,
@@ -53,6 +53,10 @@ const useGridEditing = (apiRef, props) => {
53
53
  return isCellEditableProp(params);
54
54
  }
55
55
 
56
+ if (params.rowNode.isPinned) {
57
+ return false;
58
+ }
59
+
56
60
  return true;
57
61
  }, [isCellEditableProp]);
58
62
 
@@ -56,7 +56,7 @@ function useGridEditing(apiRef, props) {
56
56
  stateSelector: _gridEditRowsSelector.gridEditRowsStateSelector,
57
57
  changeEvent: 'editRowsModelChange'
58
58
  });
59
- const isCellEditable = React.useCallback(params => !params.rowNode.isAutoGenerated && !!params.colDef.editable && !!params.colDef.renderEditCell && (!props.isCellEditable || props.isCellEditable(params)), // eslint-disable-next-line react-hooks/exhaustive-deps
59
+ const isCellEditable = React.useCallback(params => !params.rowNode.isAutoGenerated && !params.rowNode.isPinned && !!params.colDef.editable && !!params.colDef.renderEditCell && (!props.isCellEditable || props.isCellEditable(params)), // eslint-disable-next-line react-hooks/exhaustive-deps
60
60
  [props.isCellEditable]);
61
61
 
62
62
  const maybeDebounce = (id, field, debounceMs, callback) => {
@@ -44,6 +44,7 @@ const missingOnProcessRowUpdateErrorWarning = (0, _warning.buildWarning)(['MUI:
44
44
 
45
45
  const useGridRowEditing = (apiRef, props) => {
46
46
  const [rowModesModel, setRowModesModel] = React.useState({});
47
+ const rowModesModelRef = React.useRef(rowModesModel);
47
48
  const prevRowModesModel = React.useRef({});
48
49
  const focusTimeout = React.useRef(null);
49
50
  const nextFocusedCell = React.useRef(null);
@@ -116,6 +117,11 @@ const useGridRowEditing = (apiRef, props) => {
116
117
  // The row might have been deleted during the click
117
118
  if (!apiRef.current.getRow(params.id)) {
118
119
  return;
120
+ } // The row may already changed its mode
121
+
122
+
123
+ if (apiRef.current.getRowMode(params.id) === _gridEditRowModel.GridRowModes.View) {
124
+ return;
119
125
  }
120
126
 
121
127
  const rowParams = apiRef.current.getRowParams(params.id);
@@ -175,15 +181,14 @@ const useGridRowEditing = (apiRef, props) => {
175
181
  } else if (params.isEditable) {
176
182
  let reason;
177
183
 
178
- if ((0, _keyboardUtils.isPrintableKey)(event.key)) {
179
- if (event.ctrlKey && event.key !== 'v' || event.metaKey && event.key !== 'v' || event.altKey) {
180
- return;
181
- }
182
-
184
+ if ((0, _keyboardUtils.isPrintableKey)(event)) {
185
+ reason = _gridRowParams.GridRowEditStartReasons.printableKeyDown;
186
+ } else if ((event.ctrlKey || event.metaKey) && event.key === 'v') {
183
187
  reason = _gridRowParams.GridRowEditStartReasons.printableKeyDown;
184
188
  } else if (event.key === 'Enter') {
185
189
  reason = _gridRowParams.GridRowEditStartReasons.enterKeyDown;
186
- } else if (event.key === 'Delete') {
190
+ } else if (event.key === 'Delete' || event.key === 'Backspace') {
191
+ // Delete on Windows, Backspace on macOS
187
192
  reason = _gridRowParams.GridRowEditStartReasons.deleteKeyDown;
188
193
  }
189
194
 
@@ -234,7 +239,7 @@ const useGridRowEditing = (apiRef, props) => {
234
239
  let ignoreModifications = reason === 'escapeKeyDown';
235
240
  const editingState = (0, _gridEditRowsSelector.gridEditRowsStateSelector)(apiRef.current.state);
236
241
 
237
- if (!ignoreModifications) {
242
+ if (!ignoreModifications && !props.disableIgnoreModificationsIfProcessingProps) {
238
243
  // The user wants to stop editing the cell but we can't wait for the props to be processed.
239
244
  // In this case, discard the modifications if any field is processing its props.
240
245
  ignoreModifications = Object.values(editingState[id]).some(fieldProps => {
@@ -248,7 +253,7 @@ const useGridRowEditing = (apiRef, props) => {
248
253
  field,
249
254
  cellToFocusAfter
250
255
  });
251
- }, [apiRef]);
256
+ }, [apiRef, props.disableIgnoreModificationsIfProcessingProps]);
252
257
  (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellDoubleClick', runIfEditModeIsRow(handleCellDoubleClick));
253
258
  (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellFocusIn', runIfEditModeIsRow(handleCellFocusIn));
254
259
  (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'cellFocusOut', runIfEditModeIsRow(handleCellFocusOut));
@@ -281,10 +286,11 @@ const useGridRowEditing = (apiRef, props) => {
281
286
  }
282
287
 
283
288
  setRowModesModel(newModel);
289
+ rowModesModelRef.current = newModel;
284
290
  apiRef.current.publishEvent('rowModesModelChange', newModel);
285
291
  }, [apiRef, onRowModesModelChange, props.rowModesModel, signature]);
286
292
  const updateRowInRowModesModel = React.useCallback((id, newProps) => {
287
- const newModel = (0, _extends2.default)({}, rowModesModel);
293
+ const newModel = (0, _extends2.default)({}, rowModesModelRef.current);
288
294
 
289
295
  if (newProps !== null) {
290
296
  newModel[id] = (0, _extends2.default)({}, newProps);
@@ -293,7 +299,7 @@ const useGridRowEditing = (apiRef, props) => {
293
299
  }
294
300
 
295
301
  updateRowModesModel(newModel);
296
- }, [rowModesModel, updateRowModesModel]);
302
+ }, [updateRowModesModel]);
297
303
  const updateOrDeleteRowState = React.useCallback((id, newProps) => {
298
304
  apiRef.current.setState(state => {
299
305
  const newEditingState = (0, _extends2.default)({}, state.editRows);
@@ -30,6 +30,8 @@ exports.getColumnsToExport = getColumnsToExport;
30
30
  const defaultGetRowsToExport = ({
31
31
  apiRef
32
32
  }) => {
33
+ var _pinnedRows$top, _pinnedRows$bottom;
34
+
33
35
  const filteredSortedRowIds = (0, _filter.gridFilteredSortedRowIdsSelector)(apiRef);
34
36
  const rowTree = (0, _gridRowsSelector.gridRowTreeSelector)(apiRef);
35
37
  const selectedRows = apiRef.current.getSelectedRows();
@@ -38,6 +40,11 @@ const defaultGetRowsToExport = ({
38
40
 
39
41
  return ((_rowTree$id$position = rowTree[id].position) != null ? _rowTree$id$position : 'body') === 'body';
40
42
  });
43
+ const pinnedRows = (0, _gridRowsSelector.gridPinnedRowsSelector)(apiRef);
44
+ const topPinnedRowsIds = (pinnedRows == null ? void 0 : (_pinnedRows$top = pinnedRows.top) == null ? void 0 : _pinnedRows$top.map(row => row.id)) || [];
45
+ const bottomPinnedRowsIds = (pinnedRows == null ? void 0 : (_pinnedRows$bottom = pinnedRows.bottom) == null ? void 0 : _pinnedRows$bottom.map(row => row.id)) || [];
46
+ bodyRows.unshift(...topPinnedRowsIds);
47
+ bodyRows.push(...bottomPinnedRowsIds);
41
48
 
42
49
  if (selectedRows.size > 0) {
43
50
  return bodyRows.filter(id => selectedRows.has(id));
@@ -5,18 +5,18 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.sanitizeFilterModel = exports.mergeStateWithFilterModel = exports.cleanFilterItem = exports.buildAggregatedQuickFilterApplier = exports.buildAggregatedFilterItemsApplier = exports.buildAggregatedFilterApplier = void 0;
8
+ exports.sanitizeFilterModel = exports.passFilterLogic = exports.mergeStateWithFilterModel = exports.cleanFilterItem = exports.buildAggregatedQuickFilterApplier = exports.buildAggregatedFilterItemsApplier = exports.buildAggregatedFilterApplier = void 0;
9
9
 
10
10
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
11
11
 
12
12
  var _models = require("../../../models");
13
13
 
14
+ var _gridFilterState = require("./gridFilterState");
15
+
14
16
  var _warning = require("../../../utils/warning");
15
17
 
16
18
  var _columns = require("../columns");
17
19
 
18
- var _gridRowsSelector = require("../rows/gridRowsSelector");
19
-
20
20
  /**
21
21
  * Adds default values to the optional fields of a filter items.
22
22
  * @param {GridFilterItem} item The raw filter item.
@@ -100,10 +100,8 @@ exports.mergeStateWithFilterModel = mergeStateWithFilterModel;
100
100
 
101
101
  const buildAggregatedFilterItemsApplier = (filterModel, apiRef) => {
102
102
  const {
103
- items,
104
- linkOperator = _models.GridLinkOperator.And
103
+ items
105
104
  } = filterModel;
106
- const tree = (0, _gridRowsSelector.gridRowTreeSelector)(apiRef);
107
105
 
108
106
  const getFilterCallbackFromItem = filterItem => {
109
107
  if (!filterItem.columnField || !filterItem.operatorValue) {
@@ -166,18 +164,12 @@ const buildAggregatedFilterItemsApplier = (filterModel, apiRef) => {
166
164
  }
167
165
 
168
166
  return (rowId, shouldApplyFilter) => {
169
- if (tree[rowId].position === 'footer') {
170
- return true;
171
- }
172
-
173
- const filteredAppliers = shouldApplyFilter ? appliers.filter(applier => shouldApplyFilter(applier.item.columnField)) : appliers; // Return `false` as soon as we have a failing filter
174
-
175
- if (linkOperator === _models.GridLinkOperator.And) {
176
- return filteredAppliers.every(applier => applier.fn(rowId));
177
- } // Return `true` as soon as we have a passing filter
178
-
179
-
180
- return filteredAppliers.some(applier => applier.fn(rowId));
167
+ const resultPerItemId = {};
168
+ const filteredAppliers = shouldApplyFilter ? appliers.filter(applier => shouldApplyFilter(applier.item.columnField)) : appliers;
169
+ filteredAppliers.forEach(applier => {
170
+ resultPerItemId[applier.item.id] = applier.fn(rowId);
171
+ });
172
+ return resultPerItemId;
181
173
  };
182
174
  };
183
175
  /**
@@ -192,8 +184,7 @@ exports.buildAggregatedFilterItemsApplier = buildAggregatedFilterItemsApplier;
192
184
 
193
185
  const buildAggregatedQuickFilterApplier = (filterModel, apiRef) => {
194
186
  const {
195
- quickFilterValues = [],
196
- quickFilterLogicOperator = _models.GridLinkOperator.And
187
+ quickFilterValues = []
197
188
  } = filterModel;
198
189
 
199
190
  if (quickFilterValues.length === 0) {
@@ -214,6 +205,11 @@ const buildAggregatedQuickFilterApplier = (filterModel, apiRef) => {
214
205
  }); // If some value does not have an applier we ignore them
215
206
 
216
207
  const sanitizedQuickFilterValues = quickFilterValues.filter((value, index) => Object.keys(appliersPerColumnField).some(field => appliersPerColumnField[field][index] != null));
208
+
209
+ if (sanitizedQuickFilterValues.length === 0) {
210
+ return null;
211
+ }
212
+
217
213
  return (rowId, shouldApplyFilter) => {
218
214
  const usedCellParams = {};
219
215
  const columnsFieldsToFilter = [];
@@ -222,10 +218,10 @@ const buildAggregatedQuickFilterApplier = (filterModel, apiRef) => {
222
218
  usedCellParams[columnField] = apiRef.current.getCellParams(rowId, columnField);
223
219
  columnsFieldsToFilter.push(columnField);
224
220
  }
225
- }); // Return `false` as soon as we have a quick filter value that does not match any column
226
-
227
- if (quickFilterLogicOperator === _models.GridLinkOperator.And) {
228
- return sanitizedQuickFilterValues.every((value, index) => columnsFieldsToFilter.some(field => {
221
+ });
222
+ const quickFilterValueResult = {};
223
+ sanitizedQuickFilterValues.forEach((value, index) => {
224
+ const isPassing = columnsFieldsToFilter.some(field => {
229
225
  var _appliersPerColumnFie, _appliersPerColumnFie2;
230
226
 
231
227
  if (appliersPerColumnField[field][index] == null) {
@@ -233,19 +229,10 @@ const buildAggregatedQuickFilterApplier = (filterModel, apiRef) => {
233
229
  }
234
230
 
235
231
  return (_appliersPerColumnFie = (_appliersPerColumnFie2 = appliersPerColumnField[field])[index]) == null ? void 0 : _appliersPerColumnFie.call(_appliersPerColumnFie2, usedCellParams[field]);
236
- }));
237
- } // Return `true` as soon as we have have a quick filter value that match any column
238
-
239
-
240
- return sanitizedQuickFilterValues.some((value, index) => columnsFieldsToFilter.some(field => {
241
- var _appliersPerColumnFie3, _appliersPerColumnFie4;
242
-
243
- if (appliersPerColumnField[field][index] == null) {
244
- return false;
245
- }
246
-
247
- return (_appliersPerColumnFie3 = (_appliersPerColumnFie4 = appliersPerColumnField[field])[index]) == null ? void 0 : _appliersPerColumnFie3.call(_appliersPerColumnFie4, usedCellParams[field]);
248
- }));
232
+ });
233
+ quickFilterValueResult[value] = isPassing;
234
+ });
235
+ return quickFilterValueResult;
249
236
  };
250
237
  };
251
238
 
@@ -254,20 +241,67 @@ exports.buildAggregatedQuickFilterApplier = buildAggregatedQuickFilterApplier;
254
241
  const buildAggregatedFilterApplier = (filterModel, apiRef) => {
255
242
  const isRowMatchingFilterItems = buildAggregatedFilterItemsApplier(filterModel, apiRef);
256
243
  const isRowMatchingQuickFilter = buildAggregatedQuickFilterApplier(filterModel, apiRef);
244
+ return (rowId, shouldApplyFilter) => ({
245
+ passingFilterItems: isRowMatchingFilterItems && isRowMatchingFilterItems(rowId, shouldApplyFilter),
246
+ passingQuickFilterValues: isRowMatchingQuickFilter && isRowMatchingQuickFilter(rowId, shouldApplyFilter)
247
+ });
248
+ };
257
249
 
258
- if (isRowMatchingFilterItems == null && isRowMatchingQuickFilter == null) {
259
- return null;
260
- }
250
+ exports.buildAggregatedFilterApplier = buildAggregatedFilterApplier;
261
251
 
262
- if (isRowMatchingFilterItems == null) {
263
- return isRowMatchingQuickFilter;
264
- }
252
+ const passFilterLogic = (allFilterItemResults, allQuickFilterResults, filterModel) => {
253
+ var _filterModel$quickFil, _filterModel$linkOper;
265
254
 
266
- if (isRowMatchingQuickFilter == null) {
267
- return isRowMatchingFilterItems;
255
+ const cleanedAllFilterItemResults = allFilterItemResults.filter(result => result != null);
256
+ const cleanedAllQuickFilterResults = allQuickFilterResults.filter(result => result != null); // Defaultize operators
257
+
258
+ const quickFilterLogicOperator = (_filterModel$quickFil = filterModel.quickFilterLogicOperator) != null ? _filterModel$quickFil : (0, _gridFilterState.getDefaultGridFilterModel)().quickFilterLogicOperator;
259
+ const linkOperator = (_filterModel$linkOper = filterModel.linkOperator) != null ? _filterModel$linkOper : (0, _gridFilterState.getDefaultGridFilterModel)().linkOperator; // get result for filter items model
260
+
261
+ if (cleanedAllFilterItemResults.length > 0) {
262
+ // Return true if the item pass with one of the rows
263
+ const filterItemPredicate = item => {
264
+ return cleanedAllFilterItemResults.some(filterItemResult => filterItemResult[item.id]);
265
+ };
266
+
267
+ if (linkOperator === _models.GridLinkOperator.And) {
268
+ const passesAllFilters = filterModel.items.every(filterItemPredicate);
269
+
270
+ if (!passesAllFilters) {
271
+ return false;
272
+ }
273
+ } else {
274
+ const passesSomeFilters = filterModel.items.some(filterItemPredicate);
275
+
276
+ if (!passesSomeFilters) {
277
+ return false;
278
+ }
279
+ }
280
+ } // get result for quick filter model
281
+
282
+
283
+ if (cleanedAllQuickFilterResults.length > 0 && filterModel.quickFilterValues != null) {
284
+ // Return true if the item pass with one of the rows
285
+ const quickFilterValuePredicate = value => {
286
+ return cleanedAllQuickFilterResults.some(quickFilterValueResult => quickFilterValueResult[value]);
287
+ };
288
+
289
+ if (quickFilterLogicOperator === _models.GridLinkOperator.And) {
290
+ const passesAllQuickFilterValues = filterModel.quickFilterValues.every(quickFilterValuePredicate);
291
+
292
+ if (!passesAllQuickFilterValues) {
293
+ return false;
294
+ }
295
+ } else {
296
+ const passesSomeQuickFilterValues = filterModel.quickFilterValues.some(quickFilterValuePredicate);
297
+
298
+ if (!passesSomeQuickFilterValues) {
299
+ return false;
300
+ }
301
+ }
268
302
  }
269
303
 
270
- return (rowId, shouldApplyFilter) => isRowMatchingFilterItems(rowId, shouldApplyFilter) && isRowMatchingQuickFilter(rowId, shouldApplyFilter);
304
+ return true;
271
305
  };
272
306
 
273
- exports.buildAggregatedFilterApplier = buildAggregatedFilterApplier;
307
+ exports.passFilterLogic = passFilterLogic;
@@ -82,7 +82,8 @@ const useGridFilter = (apiRef, props) => {
82
82
  const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(state, apiRef.current.instanceId);
83
83
  const isRowMatchingFilters = props.filterMode === _gridFeatureMode.GridFeatureModeConstant.client ? (0, _gridFilterUtils.buildAggregatedFilterApplier)(filterModel, apiRef) : null;
84
84
  const filteringResult = apiRef.current.unstable_applyStrategyProcessor('filtering', {
85
- isRowMatchingFilters
85
+ isRowMatchingFilters,
86
+ filterModel: filterModel != null ? filterModel : (0, _gridFilterState.getDefaultGridFilterModel)()
86
87
  });
87
88
  return (0, _extends2.default)({}, state, {
88
89
  filter: (0, _extends2.default)({}, state.filter, filteringResult)
@@ -294,7 +295,19 @@ const useGridFilter = (apiRef, props) => {
294
295
 
295
296
  for (let i = 0; i < rowIds.length; i += 1) {
296
297
  const rowId = rowIds[i];
297
- filteredRowsLookup[rowId] = params.isRowMatchingFilters(rowId);
298
+ let isRowPassing;
299
+
300
+ if (typeof rowId === 'string' && rowId.startsWith('auto-generated-group-footer')) {
301
+ isRowPassing = true;
302
+ } else {
303
+ const {
304
+ passingFilterItems,
305
+ passingQuickFilterValues
306
+ } = params.isRowMatchingFilters(rowId);
307
+ isRowPassing = (0, _gridFilterUtils.passFilterLogic)([passingFilterItems], [passingQuickFilterValues], params.filterModel);
308
+ }
309
+
310
+ filteredRowsLookup[rowId] = isRowPassing;
298
311
  }
299
312
 
300
313
  return {
@@ -87,6 +87,12 @@ const useGridFocus = (apiRef, props) => {
87
87
  return;
88
88
  }
89
89
 
90
+ if (focusedCell) {
91
+ // There's a focused cell but another cell was clicked
92
+ // Publishes an event to notify that the focus was lost
93
+ apiRef.current.publishEvent('cellFocusOut', apiRef.current.getCellParams(focusedCell.id, focusedCell.field));
94
+ }
95
+
90
96
  apiRef.current.publishEvent('cellFocusIn', apiRef.current.getCellParams(id, field));
91
97
  }, [apiRef, logger]);
92
98
  const setColumnHeaderFocus = React.useCallback((field, event = {}) => {
@@ -218,11 +224,7 @@ const useGridFocus = (apiRef, props) => {
218
224
 
219
225
  if (!apiRef.current.getRow(focusedCell.id)) {
220
226
  return;
221
- } // There's a focused cell but another cell was clicked
222
- // Publishes an event to notify that the focus was lost
223
-
224
-
225
- apiRef.current.publishEvent('cellFocusOut', apiRef.current.getCellParams(focusedCell.id, focusedCell.field), event);
227
+ }
226
228
 
227
229
  if (cellParams) {
228
230
  apiRef.current.setCellFocus(cellParams.id, cellParams.field);
@@ -233,7 +235,10 @@ const useGridFocus = (apiRef, props) => {
233
235
  columnHeader: null
234
236
  }
235
237
  }));
236
- apiRef.current.forceUpdate();
238
+ apiRef.current.forceUpdate(); // There's a focused cell but another element (not a cell) was clicked
239
+ // Publishes an event to notify that the focus was lost
240
+
241
+ apiRef.current.publishEvent('cellFocusOut', apiRef.current.getCellParams(focusedCell.id, focusedCell.field), event);
237
242
  }
238
243
  }, [apiRef]);
239
244
  const handleCellModeChange = React.useCallback(params => {