@mui/x-data-grid 7.0.0-beta.7 → 7.1.0

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 (203) hide show
  1. package/CHANGELOG.md +266 -12
  2. package/DataGrid/DataGrid.js +18 -17
  3. package/DataGrid/useDataGridProps.js +4 -5
  4. package/README.md +1 -1
  5. package/components/GridFooter.js +2 -3
  6. package/components/GridHeader.js +1 -2
  7. package/components/GridPagination.d.ts +6 -5
  8. package/components/GridPagination.js +12 -4
  9. package/components/GridRow.js +13 -17
  10. package/components/base/GridFooterPlaceholder.js +1 -2
  11. package/components/base/GridOverlays.js +3 -6
  12. package/components/cell/GridActionsCell.js +4 -6
  13. package/components/cell/GridActionsCellItem.d.ts +8 -25
  14. package/components/cell/GridActionsCellItem.js +8 -5
  15. package/components/cell/GridBooleanCell.d.ts +1 -0
  16. package/components/cell/GridBooleanCell.js +3 -2
  17. package/components/cell/GridCell.js +7 -8
  18. package/components/cell/GridEditBooleanCell.js +1 -2
  19. package/components/cell/GridEditDateCell.js +2 -3
  20. package/components/cell/GridEditInputCell.js +2 -2
  21. package/components/cell/GridEditSingleSelectCell.js +5 -8
  22. package/components/columnHeaders/ColumnHeaderMenuIcon.js +2 -3
  23. package/components/columnHeaders/GridColumnGroupHeader.js +4 -5
  24. package/components/columnHeaders/GridColumnHeaderFilterIconButton.js +2 -3
  25. package/components/columnHeaders/GridColumnHeaderItem.js +8 -7
  26. package/components/columnHeaders/GridColumnHeaderSortIcon.js +1 -2
  27. package/components/columnHeaders/GridColumnHeaderTitle.js +2 -3
  28. package/components/columnHeaders/GridGenericColumnHeaderItem.js +4 -2
  29. package/components/columnSelection/GridCellCheckboxRenderer.js +3 -5
  30. package/components/columnSelection/GridHeaderCheckbox.js +1 -2
  31. package/components/columnsManagement/GridColumnsManagement.js +17 -21
  32. package/components/containers/GridRoot.js +3 -3
  33. package/components/menu/GridMenu.js +4 -6
  34. package/components/menu/columnMenu/GridColumnHeaderMenu.js +1 -1
  35. package/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.js +2 -3
  36. package/components/panel/GridColumnsPanel.js +1 -2
  37. package/components/panel/GridPanel.d.ts +1 -10
  38. package/components/panel/GridPanel.js +1 -2
  39. package/components/panel/GridPreferencesPanel.js +2 -3
  40. package/components/panel/filterPanel/GridFilterForm.js +24 -27
  41. package/components/panel/filterPanel/GridFilterInputBoolean.d.ts +1 -1
  42. package/components/panel/filterPanel/GridFilterInputBoolean.js +6 -7
  43. package/components/panel/filterPanel/GridFilterInputDate.d.ts +1 -1
  44. package/components/panel/filterPanel/GridFilterInputDate.js +3 -4
  45. package/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +11 -15
  46. package/components/panel/filterPanel/GridFilterInputMultipleValue.js +10 -14
  47. package/components/panel/filterPanel/GridFilterInputSingleSelect.d.ts +1 -1
  48. package/components/panel/filterPanel/GridFilterInputSingleSelect.js +10 -11
  49. package/components/panel/filterPanel/GridFilterInputValue.d.ts +1 -1
  50. package/components/panel/filterPanel/GridFilterInputValue.js +5 -7
  51. package/components/panel/filterPanel/GridFilterPanel.js +5 -9
  52. package/components/panel/filterPanel/filterPanelUtils.js +1 -1
  53. package/components/toolbar/GridToolbarColumnsButton.js +3 -5
  54. package/components/toolbar/GridToolbarDensitySelector.js +8 -10
  55. package/components/toolbar/GridToolbarExport.js +2 -2
  56. package/components/toolbar/GridToolbarExportContainer.js +3 -5
  57. package/components/toolbar/GridToolbarFilterButton.js +3 -5
  58. package/components/toolbar/GridToolbarQuickFilter.js +21 -7
  59. package/components/virtualization/GridVirtualScrollerContent.js +1 -2
  60. package/components/virtualization/GridVirtualScrollerRenderZone.js +1 -2
  61. package/hooks/core/strategyProcessing/useGridStrategyProcessing.js +1 -2
  62. package/hooks/core/useGridApiInitialization.js +4 -6
  63. package/hooks/features/clipboard/useGridClipboard.js +6 -5
  64. package/hooks/features/columnGrouping/gridColumnGroupsSelector.js +4 -16
  65. package/hooks/features/columnGrouping/gridColumnGroupsUtils.js +4 -8
  66. package/hooks/features/columnGrouping/useGridColumnGrouping.js +12 -23
  67. package/hooks/features/columnHeaders/useGridColumnHeaders.js +6 -8
  68. package/hooks/features/columnMenu/useGridColumnMenuSlots.js +2 -2
  69. package/hooks/features/columnResize/useGridColumnResize.js +9 -19
  70. package/hooks/features/columns/gridColumnsSelector.js +1 -2
  71. package/hooks/features/columns/gridColumnsUtils.d.ts +0 -9
  72. package/hooks/features/columns/gridColumnsUtils.js +2 -22
  73. package/hooks/features/columns/useGridColumnSpanning.js +1 -2
  74. package/hooks/features/columns/useGridColumns.js +11 -19
  75. package/hooks/features/density/densitySelector.d.ts +4 -2
  76. package/hooks/features/density/densitySelector.js +8 -2
  77. package/hooks/features/density/densityState.d.ts +1 -4
  78. package/hooks/features/density/useGridDensity.d.ts +2 -4
  79. package/hooks/features/density/useGridDensity.js +21 -29
  80. package/hooks/features/dimensions/useGridDimensions.d.ts +1 -1
  81. package/hooks/features/dimensions/useGridDimensions.js +6 -7
  82. package/hooks/features/editing/useGridCellEditing.js +4 -6
  83. package/hooks/features/editing/useGridEditing.js +1 -2
  84. package/hooks/features/editing/useGridRowEditing.js +17 -10
  85. package/hooks/features/export/serializers/csvSerializer.d.ts +2 -0
  86. package/hooks/features/export/serializers/csvSerializer.js +25 -16
  87. package/hooks/features/export/useGridCsvExport.js +9 -10
  88. package/hooks/features/export/useGridPrintExport.js +9 -15
  89. package/hooks/features/export/utils.js +2 -3
  90. package/hooks/features/filter/gridFilterSelector.js +15 -22
  91. package/hooks/features/filter/gridFilterUtils.js +10 -16
  92. package/hooks/features/filter/useGridFilter.js +9 -15
  93. package/hooks/features/focus/useGridFocus.js +5 -6
  94. package/hooks/features/headerFiltering/gridHeaderFilteringSelectors.js +1 -4
  95. package/hooks/features/headerFiltering/useGridHeaderFiltering.js +12 -17
  96. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +1 -2
  97. package/hooks/features/pagination/gridPaginationSelector.js +1 -2
  98. package/hooks/features/pagination/useGridPagination.js +2 -3
  99. package/hooks/features/pagination/useGridPaginationModel.js +6 -11
  100. package/hooks/features/pagination/useGridRowCount.js +3 -6
  101. package/hooks/features/preferencesPanel/useGridPreferencesPanel.js +7 -12
  102. package/hooks/features/rowSelection/useGridRowSelection.js +11 -16
  103. package/hooks/features/rows/gridRowsSelector.js +11 -19
  104. package/hooks/features/rows/gridRowsUtils.js +7 -9
  105. package/hooks/features/rows/useGridParamsApi.js +1 -1
  106. package/hooks/features/rows/useGridRows.js +4 -13
  107. package/hooks/features/rows/useGridRowsMeta.js +7 -13
  108. package/hooks/features/scroll/useGridScroll.js +2 -3
  109. package/hooks/features/sorting/gridSortingSelector.js +4 -7
  110. package/hooks/features/sorting/useGridSorting.js +8 -14
  111. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +1 -1
  112. package/hooks/features/virtualization/useGridVirtualScroller.js +220 -71
  113. package/hooks/utils/useGridApiEventHandler.js +5 -10
  114. package/hooks/utils/useGridNativeEventListener.js +1 -2
  115. package/index.js +1 -1
  116. package/internals/index.d.ts +2 -0
  117. package/internals/index.js +1 -0
  118. package/internals/utils/useProps.js +1 -2
  119. package/joy/joySlots.js +7 -13
  120. package/models/api/gridRowsMetaApi.d.ts +1 -1
  121. package/models/api/index.d.ts +1 -1
  122. package/models/api/index.js +0 -1
  123. package/models/events/gridEventLookup.d.ts +7 -0
  124. package/models/gridExport.d.ts +6 -0
  125. package/models/gridStateCommunity.d.ts +1 -0
  126. package/models/props/DataGridProps.d.ts +26 -25
  127. package/modern/DataGrid/DataGrid.js +18 -17
  128. package/modern/DataGrid/useDataGridProps.js +4 -5
  129. package/modern/components/GridPagination.js +11 -2
  130. package/modern/components/cell/GridActionsCell.js +1 -1
  131. package/modern/components/cell/GridActionsCellItem.js +4 -0
  132. package/modern/components/cell/GridBooleanCell.js +3 -2
  133. package/modern/components/columnHeaders/GridColumnHeaderItem.js +3 -1
  134. package/modern/components/columnHeaders/GridGenericColumnHeaderItem.js +3 -1
  135. package/modern/components/containers/GridRoot.js +3 -3
  136. package/modern/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
  137. package/modern/components/panel/filterPanel/GridFilterInputDate.js +1 -1
  138. package/modern/components/panel/filterPanel/GridFilterInputSingleSelect.js +1 -1
  139. package/modern/components/panel/filterPanel/GridFilterInputValue.js +1 -1
  140. package/modern/components/toolbar/GridToolbarDensitySelector.js +5 -5
  141. package/modern/components/toolbar/GridToolbarQuickFilter.js +17 -2
  142. package/modern/hooks/features/clipboard/useGridClipboard.js +4 -2
  143. package/modern/hooks/features/columnResize/useGridColumnResize.js +1 -1
  144. package/modern/hooks/features/columns/gridColumnsUtils.js +0 -19
  145. package/modern/hooks/features/density/densitySelector.js +8 -2
  146. package/modern/hooks/features/density/useGridDensity.js +21 -29
  147. package/modern/hooks/features/dimensions/useGridDimensions.js +3 -2
  148. package/modern/hooks/features/editing/useGridCellEditing.js +1 -1
  149. package/modern/hooks/features/editing/useGridRowEditing.js +14 -5
  150. package/modern/hooks/features/export/serializers/csvSerializer.js +23 -12
  151. package/modern/hooks/features/export/useGridCsvExport.js +2 -1
  152. package/modern/hooks/features/filter/gridFilterUtils.js +1 -1
  153. package/modern/hooks/features/rowSelection/useGridRowSelection.js +3 -2
  154. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +211 -57
  155. package/modern/index.js +1 -1
  156. package/modern/internals/index.js +1 -0
  157. package/modern/models/api/index.js +0 -1
  158. package/modern/utils/createSelector.js +1 -1
  159. package/modern/utils/domUtils.js +1 -1
  160. package/modern/utils/keyboardUtils.js +1 -1
  161. package/modern/utils/throttle.js +19 -0
  162. package/node/DataGrid/DataGrid.js +18 -17
  163. package/node/DataGrid/useDataGridProps.js +4 -5
  164. package/node/components/GridPagination.js +9 -1
  165. package/node/components/cell/GridActionsCell.js +1 -1
  166. package/node/components/cell/GridActionsCellItem.js +4 -0
  167. package/node/components/cell/GridBooleanCell.js +3 -2
  168. package/node/components/columnHeaders/GridColumnHeaderItem.js +3 -1
  169. package/node/components/columnHeaders/GridGenericColumnHeaderItem.js +3 -1
  170. package/node/components/containers/GridRoot.js +2 -2
  171. package/node/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
  172. package/node/components/panel/filterPanel/GridFilterInputDate.js +1 -1
  173. package/node/components/panel/filterPanel/GridFilterInputSingleSelect.js +1 -1
  174. package/node/components/panel/filterPanel/GridFilterInputValue.js +1 -1
  175. package/node/components/toolbar/GridToolbarDensitySelector.js +4 -4
  176. package/node/components/toolbar/GridToolbarQuickFilter.js +17 -2
  177. package/node/hooks/features/clipboard/useGridClipboard.js +4 -2
  178. package/node/hooks/features/columnResize/useGridColumnResize.js +1 -1
  179. package/node/hooks/features/columns/gridColumnsUtils.js +0 -20
  180. package/node/hooks/features/density/densitySelector.js +9 -3
  181. package/node/hooks/features/density/useGridDensity.js +22 -30
  182. package/node/hooks/features/dimensions/useGridDimensions.js +2 -1
  183. package/node/hooks/features/editing/useGridCellEditing.js +1 -1
  184. package/node/hooks/features/editing/useGridRowEditing.js +14 -5
  185. package/node/hooks/features/export/serializers/csvSerializer.js +23 -12
  186. package/node/hooks/features/export/useGridCsvExport.js +2 -1
  187. package/node/hooks/features/filter/gridFilterUtils.js +1 -1
  188. package/node/hooks/features/rowSelection/useGridRowSelection.js +2 -1
  189. package/node/hooks/features/virtualization/useGridVirtualScroller.js +211 -57
  190. package/node/index.js +1 -1
  191. package/node/internals/index.js +12 -0
  192. package/node/models/api/index.js +0 -11
  193. package/node/utils/createSelector.js +1 -1
  194. package/node/utils/domUtils.js +1 -1
  195. package/node/utils/keyboardUtils.js +1 -1
  196. package/node/utils/throttle.js +25 -0
  197. package/package.json +4 -4
  198. package/utils/createSelector.js +9 -9
  199. package/utils/domUtils.js +4 -7
  200. package/utils/getGridLocalization.js +9 -12
  201. package/utils/keyboardUtils.js +1 -1
  202. package/utils/throttle.d.ts +4 -0
  203. package/utils/throttle.js +19 -0
@@ -304,25 +304,6 @@ export function getFirstNonSpannedColumnToRender({
304
304
  }
305
305
  return firstNonSpannedColumnToRender;
306
306
  }
307
- export function getFirstColumnIndexToRender({
308
- firstColumnIndex,
309
- minColumnIndex,
310
- columnBuffer,
311
- firstRowToRender,
312
- lastRowToRender,
313
- apiRef,
314
- visibleRows
315
- }) {
316
- const initialFirstColumnToRender = Math.max(firstColumnIndex - columnBuffer, minColumnIndex);
317
- const firstColumnToRender = getFirstNonSpannedColumnToRender({
318
- firstColumnToRender: initialFirstColumnToRender,
319
- apiRef,
320
- firstRowToRender,
321
- lastRowToRender,
322
- visibleRows
323
- });
324
- return firstColumnToRender;
325
- }
326
307
  export function getTotalHeaderHeight(apiRef, headerHeight) {
327
308
  const densityFactor = gridDensityFactorSelector(apiRef);
328
309
  const maxDepth = gridColumnGroupsHeaderMaxDepthSelector(apiRef);
@@ -1,4 +1,10 @@
1
1
  import { createSelector } from '../../../utils/createSelector';
2
+ export const COMPACT_DENSITY_FACTOR = 0.7;
3
+ export const COMFORTABLE_DENSITY_FACTOR = 1.3;
4
+ const DENSITY_FACTORS = {
5
+ compact: COMPACT_DENSITY_FACTOR,
6
+ comfortable: COMFORTABLE_DENSITY_FACTOR,
7
+ standard: 1
8
+ };
2
9
  export const gridDensitySelector = state => state.density;
3
- export const gridDensityValueSelector = createSelector(gridDensitySelector, density => density.value);
4
- export const gridDensityFactorSelector = createSelector(gridDensitySelector, density => density.factor);
10
+ export const gridDensityFactorSelector = createSelector(gridDensitySelector, density => DENSITY_FACTORS[density]);
@@ -1,43 +1,35 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
+ import useEventCallback from '@mui/utils/useEventCallback';
3
4
  import { useGridLogger } from '../../utils/useGridLogger';
4
5
  import { useGridApiMethod } from '../../utils/useGridApiMethod';
5
6
  import { gridDensitySelector } from './densitySelector';
6
- import { isDeepEqual } from '../../../utils/utils';
7
- export const COMPACT_DENSITY_FACTOR = 0.7;
8
- export const COMFORTABLE_DENSITY_FACTOR = 1.3;
9
- const DENSITY_FACTORS = {
10
- compact: COMPACT_DENSITY_FACTOR,
11
- comfortable: COMFORTABLE_DENSITY_FACTOR,
12
- standard: 1
13
- };
14
7
  export const densityStateInitializer = (state, props) => _extends({}, state, {
15
- density: {
16
- value: props.density,
17
- factor: DENSITY_FACTORS[props.density]
18
- }
8
+ density: props.initialState?.density ?? props.density ?? 'standard'
19
9
  });
20
10
  export const useGridDensity = (apiRef, props) => {
21
11
  const logger = useGridLogger(apiRef, 'useDensity');
22
- const setDensity = React.useCallback(newDensity => {
12
+ apiRef.current.registerControlState({
13
+ stateId: 'density',
14
+ propModel: props.density,
15
+ propOnChange: props.onDensityChange,
16
+ stateSelector: gridDensitySelector,
17
+ changeEvent: 'densityChange'
18
+ });
19
+ const setDensity = useEventCallback(newDensity => {
20
+ const currentDensity = gridDensitySelector(apiRef.current.state);
21
+ if (currentDensity === newDensity) {
22
+ return;
23
+ }
23
24
  logger.debug(`Set grid density to ${newDensity}`);
24
- apiRef.current.setState(state => {
25
- const currentDensityState = gridDensitySelector(state);
26
- const newDensityState = {
27
- value: newDensity,
28
- factor: DENSITY_FACTORS[newDensity]
29
- };
30
- if (isDeepEqual(currentDensityState, newDensityState)) {
31
- return state;
32
- }
33
- return _extends({}, state, {
34
- density: newDensityState
35
- });
36
- });
37
- apiRef.current.forceUpdate();
38
- }, [logger, apiRef]);
25
+ apiRef.current.setState(state => _extends({}, state, {
26
+ density: newDensity
27
+ }));
28
+ });
39
29
  React.useEffect(() => {
40
- apiRef.current.setDensity(props.density);
30
+ if (props.density) {
31
+ apiRef.current.setDensity(props.density);
32
+ }
41
33
  }, [apiRef, props.density]);
42
34
  const densityApi = {
43
35
  setDensity
@@ -1,8 +1,9 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
- import { unstable_debounce as debounce, unstable_ownerDocument as ownerDocument, unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback, unstable_ownerWindow as ownerWindow } from '@mui/utils';
3
+ import { unstable_ownerDocument as ownerDocument, unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback, unstable_ownerWindow as ownerWindow } from '@mui/utils';
4
4
  import { useGridApiEventHandler, useGridApiOptionHandler } from '../../utils/useGridApiEventHandler';
5
5
  import { useGridApiMethod } from '../../utils/useGridApiMethod';
6
+ import { throttle } from '../../../utils/throttle';
6
7
  import { useGridLogger } from '../../utils/useGridLogger';
7
8
  import { gridColumnsTotalWidthSelector, gridVisiblePinnedColumnDefinitionsSelector } from '../columns';
8
9
  import { gridDimensionsSelector } from './gridDimensionsSelectors';
@@ -57,7 +58,7 @@ export function useGridDimensions(apiRef, props) {
57
58
  const leftPinnedWidth = pinnedColumns.left.reduce((w, col) => w + col.computedWidth, 0);
58
59
  const rightPinnedWidth = pinnedColumns.right.reduce((w, col) => w + col.computedWidth, 0);
59
60
  const [savedSize, setSavedSize] = React.useState();
60
- const debouncedSetSavedSize = React.useMemo(() => debounce(setSavedSize, 60), []);
61
+ const debouncedSetSavedSize = React.useMemo(() => throttle(setSavedSize, props.resizeThrottleMs), [props.resizeThrottleMs]);
61
62
  const previousSize = React.useRef();
62
63
  const getRootDimensions = () => apiRef.current.state.dimensions;
63
64
  const setDimensions = useEventCallback(dimensions => {
@@ -14,7 +14,7 @@ import { buildWarning } from '../../../utils/warning';
14
14
  import { gridRowsDataRowIdToIdLookupSelector } from '../rows/gridRowsSelector';
15
15
  import { deepClone } from '../../../utils/utils';
16
16
  import { GridCellEditStartReasons, GridCellEditStopReasons } from '../../../models/params/gridEditCellParams';
17
- const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI X: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, e.g. `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/editing/#server-side-persistence.'], 'error');
17
+ const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI X: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, for example `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/editing/#server-side-persistence.'], 'error');
18
18
  export const useGridCellEditing = (apiRef, props) => {
19
19
  const [cellModesModel, setCellModesModel] = React.useState({});
20
20
  const cellModesModelRef = React.useRef(cellModesModel);
@@ -16,7 +16,7 @@ import { gridRowsDataRowIdToIdLookupSelector } from '../rows/gridRowsSelector';
16
16
  import { deepClone } from '../../../utils/utils';
17
17
  import { GridRowEditStopReasons, GridRowEditStartReasons } from '../../../models/params/gridRowParams';
18
18
  import { GRID_ACTIONS_COLUMN_TYPE } from '../../../colDef';
19
- const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI X: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, e.g. `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/editing/#server-side-persistence.'], 'error');
19
+ const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI X: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, for example `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/editing/#server-side-persistence.'], 'error');
20
20
  export const useGridRowEditing = (apiRef, props) => {
21
21
  const [rowModesModel, setRowModesModel] = React.useState({});
22
22
  const rowModesModelRef = React.useRef(rowModesModel);
@@ -45,6 +45,10 @@ export const useGridRowEditing = (apiRef, props) => {
45
45
  throw new Error(`MUI X: The row with id=${id} is not in ${mode} mode.`);
46
46
  }
47
47
  }, [apiRef]);
48
+ const hasFieldsWithErrors = React.useCallback(rowId => {
49
+ const editingState = gridEditRowsStateSelector(apiRef.current.state);
50
+ return Object.values(editingState[rowId]).some(fieldProps => fieldProps.error);
51
+ }, [apiRef]);
48
52
  const handleCellDoubleClick = React.useCallback((params, event) => {
49
53
  if (!params.isEditable) {
50
54
  return;
@@ -86,6 +90,9 @@ export const useGridRowEditing = (apiRef, props) => {
86
90
  if (apiRef.current.getRowMode(params.id) === GridRowModes.View) {
87
91
  return;
88
92
  }
93
+ if (hasFieldsWithErrors(params.id)) {
94
+ return;
95
+ }
89
96
  const rowParams = apiRef.current.getRowParams(params.id);
90
97
  const newParams = _extends({}, rowParams, {
91
98
  field: params.field,
@@ -94,7 +101,7 @@ export const useGridRowEditing = (apiRef, props) => {
94
101
  apiRef.current.publishEvent('rowEditStop', newParams, event);
95
102
  }
96
103
  });
97
- }, [apiRef]);
104
+ }, [apiRef, hasFieldsWithErrors]);
98
105
  React.useEffect(() => {
99
106
  return () => {
100
107
  clearTimeout(focusTimeout.current);
@@ -140,6 +147,9 @@ export const useGridRowEditing = (apiRef, props) => {
140
147
  }
141
148
  }
142
149
  if (reason) {
150
+ if (reason !== GridRowEditStopReasons.escapeKeyDown && hasFieldsWithErrors(params.id)) {
151
+ return;
152
+ }
143
153
  const newParams = _extends({}, apiRef.current.getRowParams(params.id), {
144
154
  reason,
145
155
  field: params.field
@@ -174,7 +184,7 @@ export const useGridRowEditing = (apiRef, props) => {
174
184
  apiRef.current.publishEvent('rowEditStart', newParams, event);
175
185
  }
176
186
  }
177
- }, [apiRef]);
187
+ }, [apiRef, hasFieldsWithErrors]);
178
188
  const handleRowEditStart = React.useCallback(params => {
179
189
  const {
180
190
  id,
@@ -358,8 +368,7 @@ export const useGridRowEditing = (apiRef, props) => {
358
368
  prevRowModesModel.current[id].mode = GridRowModes.Edit;
359
369
  return;
360
370
  }
361
- const hasSomeFieldWithError = Object.values(editingState[id]).some(fieldProps => fieldProps.error);
362
- if (hasSomeFieldWithError) {
371
+ if (hasFieldsWithErrors(id)) {
363
372
  prevRowModesModel.current[id].mode = GridRowModes.Edit;
364
373
  // Revert the mode in the rowModesModel prop back to "edit"
365
374
  updateRowInRowModesModel(id, {
@@ -1,10 +1,13 @@
1
1
  import { GRID_CHECKBOX_SELECTION_COL_DEF } from '../../../../colDef';
2
2
  import { buildWarning } from '../../../../utils/warning';
3
- function sanitizeCellValue(value, delimiterCharacter) {
3
+ function sanitizeCellValue(value, delimiterCharacter, shouldAppendQuotes) {
4
4
  if (typeof value === 'string') {
5
5
  // Make sure value containing delimiter or line break won't be split into multiple rows
6
6
  if ([delimiterCharacter, '\n', '\r', '"'].some(delimiter => value.includes(delimiter))) {
7
- return `"${value.replace(/"/g, '""')}"`;
7
+ if (shouldAppendQuotes) {
8
+ return `"${value.replace(/"/g, '""')}"`;
9
+ }
10
+ return `${value.replace(/"/g, '""')}`;
8
11
  }
9
12
  return value;
10
13
  }
@@ -13,7 +16,8 @@ function sanitizeCellValue(value, delimiterCharacter) {
13
16
  export const serializeCellValue = (cellParams, options) => {
14
17
  const {
15
18
  delimiterCharacter,
16
- ignoreValueFormatter
19
+ ignoreValueFormatter,
20
+ shouldAppendQuotes
17
21
  } = options;
18
22
  let value;
19
23
  if (ignoreValueFormatter) {
@@ -30,7 +34,7 @@ export const serializeCellValue = (cellParams, options) => {
30
34
  } else {
31
35
  value = cellParams.formattedValue;
32
36
  }
33
- return sanitizeCellValue(value, delimiterCharacter);
37
+ return sanitizeCellValue(value, delimiterCharacter, shouldAppendQuotes);
34
38
  };
35
39
  const objectFormattedValueWarning = buildWarning(['MUI X: When the value of a field is an object or a `renderCell` is provided, the CSV export might not display the value correctly.', 'You can provide a `valueFormatter` with a string representation to be used.']);
36
40
  class CSVRow {
@@ -47,7 +51,7 @@ class CSVRow {
47
51
  if (value === null || value === undefined) {
48
52
  this.rowString += '';
49
53
  } else if (typeof this.options.sanitizeCellValue === 'function') {
50
- this.rowString += this.options.sanitizeCellValue(value, this.options.delimiterCharacter);
54
+ this.rowString += this.options.sanitizeCellValue(value, this.options.delimiterCharacter, this.options.shouldAppendQuotes);
51
55
  } else {
52
56
  this.rowString += value;
53
57
  }
@@ -62,10 +66,12 @@ const serializeRow = ({
62
66
  columns,
63
67
  getCellParams,
64
68
  delimiterCharacter,
65
- ignoreValueFormatter
69
+ ignoreValueFormatter,
70
+ shouldAppendQuotes
66
71
  }) => {
67
72
  const row = new CSVRow({
68
- delimiterCharacter
73
+ delimiterCharacter,
74
+ shouldAppendQuotes
69
75
  });
70
76
  columns.forEach(column => {
71
77
  const cellParams = getCellParams(id, column.field);
@@ -76,7 +82,8 @@ const serializeRow = ({
76
82
  }
77
83
  row.addValue(serializeCellValue(cellParams, {
78
84
  delimiterCharacter,
79
- ignoreValueFormatter
85
+ ignoreValueFormatter,
86
+ shouldAppendQuotes
80
87
  }));
81
88
  });
82
89
  return row.getRowString();
@@ -89,14 +96,16 @@ export function buildCSV(options) {
89
96
  includeHeaders,
90
97
  includeColumnGroupsHeaders,
91
98
  ignoreValueFormatter,
92
- apiRef
99
+ apiRef,
100
+ shouldAppendQuotes
93
101
  } = options;
94
102
  const CSVBody = rowIds.reduce((acc, id) => `${acc}${serializeRow({
95
103
  id,
96
104
  columns,
97
105
  getCellParams: apiRef.current.getCellParams,
98
106
  delimiterCharacter,
99
- ignoreValueFormatter
107
+ ignoreValueFormatter,
108
+ shouldAppendQuotes
100
109
  })}\r\n`, '').trim();
101
110
  if (!includeHeaders) {
102
111
  return CSVBody;
@@ -115,7 +124,8 @@ export function buildCSV(options) {
115
124
  for (let i = 0; i < maxColumnGroupsDepth; i += 1) {
116
125
  const headerGroupRow = new CSVRow({
117
126
  delimiterCharacter,
118
- sanitizeCellValue
127
+ sanitizeCellValue,
128
+ shouldAppendQuotes
119
129
  });
120
130
  headerRows.push(headerGroupRow);
121
131
  filteredColumns.forEach(column => {
@@ -127,7 +137,8 @@ export function buildCSV(options) {
127
137
  }
128
138
  const mainHeaderRow = new CSVRow({
129
139
  delimiterCharacter,
130
- sanitizeCellValue
140
+ sanitizeCellValue,
141
+ shouldAppendQuotes
131
142
  });
132
143
  filteredColumns.forEach(column => {
133
144
  mainHeaderRow.addValue(column.headerName || column.field);
@@ -35,7 +35,8 @@ export const useGridCsvExport = (apiRef, props) => {
35
35
  includeHeaders: options.includeHeaders ?? true,
36
36
  includeColumnGroupsHeaders: options.includeColumnGroupsHeaders ?? true,
37
37
  ignoreValueFormatter,
38
- apiRef
38
+ apiRef,
39
+ shouldAppendQuotes: options.shouldAppendQuotes ?? true
39
40
  });
40
41
  }, [logger, apiRef, ignoreValueFormatter]);
41
42
  const exportDataAsCsv = React.useCallback(options => {
@@ -156,7 +156,7 @@ const buildAggregatedFilterItemsApplier = (filterModel, apiRef, disableEval) =>
156
156
  }
157
157
 
158
158
  // We generate a new function with `new Function()` to avoid expensive patterns for JS engines
159
- // such as a dynamic object assignment, e.g. `{ [dynamicKey]: value }`.
159
+ // such as a dynamic object assignment, for example `{ [dynamicKey]: value }`.
160
160
  const filterItemCore = new Function('appliers', 'row', 'shouldApplyFilter', `"use strict";
161
161
  ${appliers.map((applier, i) => `const shouldApply${i} = !shouldApplyFilter || shouldApplyFilter(${JSON.stringify(applier.item.field)});`).join('\n')}
162
162
 
@@ -7,7 +7,7 @@ import { gridRowsLookupSelector } from '../rows/gridRowsSelector';
7
7
  import { gridRowSelectionStateSelector, selectedGridRowsSelector, selectedIdsLookupSelector } from './gridRowSelectionSelector';
8
8
  import { gridPaginatedVisibleSortedGridRowIdsSelector } from '../pagination';
9
9
  import { gridFocusCellSelector } from '../focus/gridFocusStateSelector';
10
- import { gridExpandedSortedRowIdsSelector } from '../filter/gridFilterSelector';
10
+ import { gridExpandedSortedRowIdsSelector, gridFilterModelSelector } from '../filter/gridFilterSelector';
11
11
  import { GRID_CHECKBOX_SELECTION_COL_DEF, GRID_ACTIONS_COLUMN_TYPE } from '../../../colDef';
12
12
  import { GridCellModes } from '../../../models/gridEditRowModel';
13
13
  import { isKeyboardEvent, isNavigationKey } from '../../../utils/keyboardUtils';
@@ -274,7 +274,8 @@ export const useGridRowSelection = (apiRef, props) => {
274
274
  const handleHeaderSelectionCheckboxChange = React.useCallback(params => {
275
275
  const shouldLimitSelectionToCurrentPage = props.checkboxSelectionVisibleOnly && props.pagination;
276
276
  const rowsToBeSelected = shouldLimitSelectionToCurrentPage ? gridPaginatedVisibleSortedGridRowIdsSelector(apiRef) : gridExpandedSortedRowIdsSelector(apiRef);
277
- apiRef.current.selectRows(rowsToBeSelected, params.value);
277
+ const filterModel = gridFilterModelSelector(apiRef);
278
+ apiRef.current.selectRows(rowsToBeSelected, params.value, filterModel?.items.length > 0);
278
279
  }, [apiRef, props.checkboxSelectionVisibleOnly, props.pagination]);
279
280
  const handleCellKeyDown = React.useCallback((params, event) => {
280
281
  // Get the most recent cell mode because it may have been changed by another listener