@mui/x-data-grid 5.12.0 → 5.12.3

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 (289) hide show
  1. package/CHANGELOG.md +160 -7
  2. package/colDef/gridCheckboxSelectionColDef.d.ts +1 -0
  3. package/colDef/gridCheckboxSelectionColDef.js +2 -1
  4. package/colDef/gridDateOperators.d.ts +1 -1
  5. package/colDef/gridNumericColDef.js +1 -1
  6. package/components/cell/GridBooleanCell.js +4 -3
  7. package/components/cell/GridEditBooleanCell.js +4 -3
  8. package/components/cell/GridEditDateCell.js +4 -3
  9. package/components/cell/GridEditInputCell.js +4 -3
  10. package/components/cell/GridEditSingleSelectCell.js +9 -7
  11. package/components/columnHeaders/GridColumnHeaderItem.js +5 -3
  12. package/components/columnSelection/GridCellCheckboxRenderer.js +0 -1
  13. package/components/columnSelection/GridHeaderCheckbox.js +0 -1
  14. package/components/containers/GridRootStyles.js +4 -1
  15. package/components/panel/GridColumnsPanel.js +3 -6
  16. package/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.d.ts +3 -2
  17. package/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +12 -5
  18. package/components/panel/filterPanel/GridFilterPanel.js +2 -5
  19. package/components/toolbar/GridToolbarColumnsButton.js +0 -1
  20. package/components/toolbar/GridToolbarDensitySelector.js +0 -1
  21. package/components/toolbar/GridToolbarExportContainer.js +0 -1
  22. package/components/toolbar/GridToolbarFilterButton.js +0 -1
  23. package/components/toolbar/GridToolbarQuickFilter.d.ts +7 -0
  24. package/components/toolbar/GridToolbarQuickFilter.js +57 -4
  25. package/constants/defaultGridSlotsComponents.js +2 -1
  26. package/constants/localeTextConstants.js +1 -0
  27. package/hooks/core/useGridStateInitialization.js +19 -6
  28. package/hooks/features/columnMenu/useGridColumnMenu.js +22 -0
  29. package/hooks/features/columns/useGridColumnSpanning.d.ts +1 -1
  30. package/hooks/features/columns/useGridColumnSpanning.js +1 -1
  31. package/hooks/features/columns/useGridColumns.d.ts +1 -1
  32. package/hooks/features/columns/useGridColumns.js +1 -1
  33. package/hooks/features/dimensions/gridDimensionsApi.d.ts +5 -0
  34. package/hooks/features/dimensions/useGridDimensions.js +9 -8
  35. package/hooks/features/editRows/useGridEditing.old.js +1 -1
  36. package/hooks/features/filter/gridFilterSelector.d.ts +5 -0
  37. package/hooks/features/filter/gridFilterSelector.js +6 -0
  38. package/hooks/features/filter/gridFilterState.d.ts +1 -1
  39. package/hooks/features/filter/gridFilterUtils.d.ts +1 -1
  40. package/hooks/features/filter/gridFilterUtils.js +10 -9
  41. package/hooks/features/filter/useGridFilter.d.ts +1 -1
  42. package/hooks/features/filter/useGridFilter.js +24 -7
  43. package/hooks/features/pagination/useGridPage.js +1 -1
  44. package/hooks/features/pagination/useGridPageSize.js +1 -1
  45. package/hooks/features/rows/useGridRows.js +15 -2
  46. package/hooks/features/rows/useGridRowsMeta.js +79 -77
  47. package/hooks/features/selection/useGridSelection.js +1 -1
  48. package/hooks/features/selection/useGridSelectionPreProcessors.js +8 -6
  49. package/hooks/features/sorting/useGridSorting.d.ts +1 -1
  50. package/hooks/features/sorting/useGridSorting.js +1 -1
  51. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +1 -1
  52. package/hooks/features/virtualization/useGridVirtualScroller.js +42 -8
  53. package/index.js +1 -1
  54. package/legacy/colDef/gridCheckboxSelectionColDef.js +2 -1
  55. package/legacy/colDef/gridNumericColDef.js +1 -1
  56. package/legacy/components/cell/GridBooleanCell.js +3 -1
  57. package/legacy/components/cell/GridEditBooleanCell.js +4 -2
  58. package/legacy/components/cell/GridEditDateCell.js +4 -2
  59. package/legacy/components/cell/GridEditInputCell.js +4 -2
  60. package/legacy/components/cell/GridEditSingleSelectCell.js +9 -7
  61. package/legacy/components/columnHeaders/GridColumnHeaderItem.js +5 -3
  62. package/legacy/components/columnSelection/GridCellCheckboxRenderer.js +0 -1
  63. package/legacy/components/columnSelection/GridHeaderCheckbox.js +0 -1
  64. package/legacy/components/containers/GridRootStyles.js +7 -5
  65. package/legacy/components/panel/GridColumnsPanel.js +5 -6
  66. package/legacy/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +12 -5
  67. package/legacy/components/panel/filterPanel/GridFilterPanel.js +3 -6
  68. package/legacy/components/toolbar/GridToolbarColumnsButton.js +0 -1
  69. package/legacy/components/toolbar/GridToolbarDensitySelector.js +0 -1
  70. package/legacy/components/toolbar/GridToolbarExportContainer.js +0 -1
  71. package/legacy/components/toolbar/GridToolbarFilterButton.js +0 -1
  72. package/legacy/components/toolbar/GridToolbarQuickFilter.js +67 -6
  73. package/legacy/constants/defaultGridSlotsComponents.js +2 -1
  74. package/legacy/constants/localeTextConstants.js +1 -0
  75. package/legacy/hooks/core/useGridStateInitialization.js +18 -6
  76. package/legacy/hooks/features/columnMenu/useGridColumnMenu.js +22 -0
  77. package/legacy/hooks/features/columns/useGridColumnSpanning.js +1 -1
  78. package/legacy/hooks/features/columns/useGridColumns.js +1 -1
  79. package/legacy/hooks/features/dimensions/useGridDimensions.js +9 -8
  80. package/legacy/hooks/features/editRows/useGridEditing.old.js +1 -1
  81. package/legacy/hooks/features/filter/gridFilterSelector.js +8 -0
  82. package/legacy/hooks/features/filter/gridFilterUtils.js +11 -10
  83. package/legacy/hooks/features/filter/useGridFilter.js +28 -7
  84. package/legacy/hooks/features/pagination/useGridPage.js +1 -1
  85. package/legacy/hooks/features/pagination/useGridPageSize.js +1 -1
  86. package/legacy/hooks/features/rows/useGridRows.js +17 -2
  87. package/legacy/hooks/features/rows/useGridRowsMeta.js +81 -77
  88. package/legacy/hooks/features/selection/useGridSelection.js +1 -1
  89. package/legacy/hooks/features/selection/useGridSelectionPreProcessors.js +8 -6
  90. package/legacy/hooks/features/sorting/useGridSorting.js +1 -1
  91. package/legacy/hooks/features/virtualization/useGridVirtualScroller.js +42 -8
  92. package/legacy/index.js +1 -1
  93. package/legacy/locales/arSD.js +1 -0
  94. package/legacy/locales/bgBG.js +1 -0
  95. package/legacy/locales/csCZ.js +1 -0
  96. package/legacy/locales/daDK.js +1 -0
  97. package/legacy/locales/deDE.js +1 -0
  98. package/legacy/locales/elGR.js +1 -0
  99. package/legacy/locales/esES.js +1 -0
  100. package/legacy/locales/faIR.js +1 -0
  101. package/legacy/locales/fiFI.js +1 -0
  102. package/legacy/locales/frFR.js +1 -0
  103. package/legacy/locales/heIL.js +1 -0
  104. package/legacy/locales/huHU.js +1 -0
  105. package/legacy/locales/index.js +1 -0
  106. package/legacy/locales/itIT.js +1 -0
  107. package/legacy/locales/jaJP.js +29 -24
  108. package/legacy/locales/koKR.js +1 -0
  109. package/legacy/locales/nbNO.js +1 -0
  110. package/legacy/locales/nlNL.js +1 -0
  111. package/legacy/locales/plPL.js +1 -0
  112. package/legacy/locales/ptBR.js +1 -0
  113. package/legacy/locales/ruRU.js +7 -6
  114. package/legacy/locales/skSK.js +1 -0
  115. package/legacy/locales/svSE.js +128 -0
  116. package/legacy/locales/trTR.js +1 -0
  117. package/legacy/locales/ukUA.js +1 -0
  118. package/legacy/locales/viVN.js +1 -0
  119. package/legacy/locales/zhCN.js +1 -0
  120. package/locales/arSD.js +1 -0
  121. package/locales/bgBG.js +1 -0
  122. package/locales/csCZ.js +1 -0
  123. package/locales/daDK.js +1 -0
  124. package/locales/deDE.js +1 -0
  125. package/locales/elGR.js +1 -0
  126. package/locales/esES.js +1 -0
  127. package/locales/faIR.js +1 -0
  128. package/locales/fiFI.js +1 -0
  129. package/locales/frFR.js +1 -0
  130. package/locales/heIL.js +1 -0
  131. package/locales/huHU.js +1 -0
  132. package/locales/index.d.ts +1 -0
  133. package/locales/index.js +1 -0
  134. package/locales/itIT.js +1 -0
  135. package/locales/jaJP.js +25 -24
  136. package/locales/koKR.js +1 -0
  137. package/locales/nbNO.js +1 -0
  138. package/locales/nlNL.js +1 -0
  139. package/locales/plPL.js +1 -0
  140. package/locales/ptBR.js +1 -0
  141. package/locales/ruRU.js +7 -6
  142. package/locales/skSK.js +1 -0
  143. package/locales/svSE.d.ts +2 -0
  144. package/locales/svSE.js +116 -0
  145. package/locales/trTR.js +1 -0
  146. package/locales/ukUA.js +1 -0
  147. package/locales/viVN.js +1 -0
  148. package/locales/zhCN.js +1 -0
  149. package/models/api/gridCallbackDetails.d.ts +6 -1
  150. package/models/api/gridFilterApi.d.ts +8 -1
  151. package/models/api/gridLocaleTextApi.d.ts +1 -0
  152. package/models/api/gridStateApi.d.ts +14 -3
  153. package/models/colDef/gridColDef.d.ts +1 -1
  154. package/models/events/gridEventLookup.d.ts +3 -0
  155. package/models/gridIconSlotsComponent.d.ts +5 -0
  156. package/models/props/DataGridProps.d.ts +1 -1
  157. package/modern/colDef/gridCheckboxSelectionColDef.js +2 -1
  158. package/modern/colDef/gridNumericColDef.js +1 -1
  159. package/modern/components/cell/GridBooleanCell.js +4 -3
  160. package/modern/components/cell/GridEditBooleanCell.js +4 -3
  161. package/modern/components/cell/GridEditDateCell.js +4 -3
  162. package/modern/components/cell/GridEditInputCell.js +4 -3
  163. package/modern/components/cell/GridEditSingleSelectCell.js +9 -7
  164. package/modern/components/columnHeaders/GridColumnHeaderItem.js +5 -3
  165. package/modern/components/columnSelection/GridCellCheckboxRenderer.js +0 -1
  166. package/modern/components/columnSelection/GridHeaderCheckbox.js +0 -1
  167. package/modern/components/containers/GridRootStyles.js +4 -1
  168. package/modern/components/panel/GridColumnsPanel.js +3 -6
  169. package/modern/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +12 -5
  170. package/modern/components/panel/filterPanel/GridFilterPanel.js +2 -5
  171. package/modern/components/toolbar/GridToolbarColumnsButton.js +0 -1
  172. package/modern/components/toolbar/GridToolbarDensitySelector.js +0 -1
  173. package/modern/components/toolbar/GridToolbarExportContainer.js +0 -1
  174. package/modern/components/toolbar/GridToolbarFilterButton.js +0 -1
  175. package/modern/components/toolbar/GridToolbarQuickFilter.js +57 -4
  176. package/modern/constants/defaultGridSlotsComponents.js +2 -1
  177. package/modern/constants/localeTextConstants.js +1 -0
  178. package/modern/hooks/core/useGridStateInitialization.js +19 -6
  179. package/modern/hooks/features/columnMenu/useGridColumnMenu.js +22 -0
  180. package/modern/hooks/features/columns/useGridColumnSpanning.js +1 -1
  181. package/modern/hooks/features/columns/useGridColumns.js +1 -1
  182. package/modern/hooks/features/dimensions/useGridDimensions.js +9 -8
  183. package/modern/hooks/features/editRows/useGridEditing.old.js +1 -1
  184. package/modern/hooks/features/filter/gridFilterSelector.js +6 -0
  185. package/modern/hooks/features/filter/gridFilterUtils.js +10 -9
  186. package/modern/hooks/features/filter/useGridFilter.js +24 -7
  187. package/modern/hooks/features/pagination/useGridPage.js +1 -1
  188. package/modern/hooks/features/pagination/useGridPageSize.js +1 -1
  189. package/modern/hooks/features/rows/useGridRows.js +15 -2
  190. package/modern/hooks/features/rows/useGridRowsMeta.js +77 -75
  191. package/modern/hooks/features/selection/useGridSelection.js +1 -1
  192. package/modern/hooks/features/selection/useGridSelectionPreProcessors.js +8 -6
  193. package/modern/hooks/features/sorting/useGridSorting.js +1 -1
  194. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +42 -8
  195. package/modern/index.js +1 -1
  196. package/modern/locales/arSD.js +1 -0
  197. package/modern/locales/bgBG.js +1 -0
  198. package/modern/locales/csCZ.js +1 -0
  199. package/modern/locales/daDK.js +1 -0
  200. package/modern/locales/deDE.js +1 -0
  201. package/modern/locales/elGR.js +1 -0
  202. package/modern/locales/esES.js +1 -0
  203. package/modern/locales/faIR.js +1 -0
  204. package/modern/locales/fiFI.js +1 -0
  205. package/modern/locales/frFR.js +1 -0
  206. package/modern/locales/heIL.js +1 -0
  207. package/modern/locales/huHU.js +1 -0
  208. package/modern/locales/index.js +1 -0
  209. package/modern/locales/itIT.js +1 -0
  210. package/modern/locales/jaJP.js +25 -24
  211. package/modern/locales/koKR.js +1 -0
  212. package/modern/locales/nbNO.js +1 -0
  213. package/modern/locales/nlNL.js +1 -0
  214. package/modern/locales/plPL.js +1 -0
  215. package/modern/locales/ptBR.js +1 -0
  216. package/modern/locales/ruRU.js +7 -6
  217. package/modern/locales/skSK.js +1 -0
  218. package/modern/locales/svSE.js +116 -0
  219. package/modern/locales/trTR.js +1 -0
  220. package/modern/locales/ukUA.js +1 -0
  221. package/modern/locales/viVN.js +1 -0
  222. package/modern/locales/zhCN.js +1 -0
  223. package/node/colDef/gridCheckboxSelectionColDef.js +4 -2
  224. package/node/colDef/gridNumericColDef.js +1 -1
  225. package/node/components/cell/GridBooleanCell.js +5 -3
  226. package/node/components/cell/GridEditBooleanCell.js +5 -3
  227. package/node/components/cell/GridEditDateCell.js +5 -3
  228. package/node/components/cell/GridEditInputCell.js +5 -3
  229. package/node/components/cell/GridEditSingleSelectCell.js +10 -7
  230. package/node/components/columnHeaders/GridColumnHeaderItem.js +5 -3
  231. package/node/components/columnSelection/GridCellCheckboxRenderer.js +0 -1
  232. package/node/components/columnSelection/GridHeaderCheckbox.js +0 -1
  233. package/node/components/containers/GridRootStyles.js +4 -1
  234. package/node/components/panel/GridColumnsPanel.js +3 -6
  235. package/node/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +12 -5
  236. package/node/components/panel/filterPanel/GridFilterPanel.js +2 -5
  237. package/node/components/toolbar/GridToolbarColumnsButton.js +0 -1
  238. package/node/components/toolbar/GridToolbarDensitySelector.js +0 -1
  239. package/node/components/toolbar/GridToolbarExportContainer.js +0 -1
  240. package/node/components/toolbar/GridToolbarFilterButton.js +0 -1
  241. package/node/components/toolbar/GridToolbarQuickFilter.js +61 -4
  242. package/node/constants/defaultGridSlotsComponents.js +2 -1
  243. package/node/constants/localeTextConstants.js +1 -0
  244. package/node/hooks/core/useGridStateInitialization.js +19 -6
  245. package/node/hooks/features/columnMenu/useGridColumnMenu.js +23 -0
  246. package/node/hooks/features/columns/useGridColumnSpanning.js +11 -16
  247. package/node/hooks/features/columns/useGridColumns.js +1 -1
  248. package/node/hooks/features/dimensions/useGridDimensions.js +9 -8
  249. package/node/hooks/features/editRows/useGridEditing.old.js +1 -1
  250. package/node/hooks/features/filter/gridFilterSelector.js +9 -2
  251. package/node/hooks/features/filter/gridFilterUtils.js +9 -8
  252. package/node/hooks/features/filter/useGridFilter.js +24 -7
  253. package/node/hooks/features/pagination/useGridPage.js +1 -1
  254. package/node/hooks/features/pagination/useGridPageSize.js +1 -1
  255. package/node/hooks/features/rows/useGridRows.js +15 -2
  256. package/node/hooks/features/rows/useGridRowsMeta.js +80 -77
  257. package/node/hooks/features/selection/useGridSelection.js +1 -1
  258. package/node/hooks/features/selection/useGridSelectionPreProcessors.js +7 -5
  259. package/node/hooks/features/sorting/useGridSorting.js +1 -1
  260. package/node/hooks/features/virtualization/useGridVirtualScroller.js +42 -9
  261. package/node/index.js +1 -1
  262. package/node/locales/arSD.js +1 -0
  263. package/node/locales/bgBG.js +1 -0
  264. package/node/locales/csCZ.js +1 -0
  265. package/node/locales/daDK.js +1 -0
  266. package/node/locales/deDE.js +1 -0
  267. package/node/locales/elGR.js +1 -0
  268. package/node/locales/esES.js +1 -0
  269. package/node/locales/faIR.js +1 -0
  270. package/node/locales/fiFI.js +1 -0
  271. package/node/locales/frFR.js +1 -0
  272. package/node/locales/heIL.js +1 -0
  273. package/node/locales/huHU.js +1 -0
  274. package/node/locales/index.js +13 -0
  275. package/node/locales/itIT.js +1 -0
  276. package/node/locales/jaJP.js +25 -24
  277. package/node/locales/koKR.js +1 -0
  278. package/node/locales/nbNO.js +1 -0
  279. package/node/locales/nlNL.js +1 -0
  280. package/node/locales/plPL.js +1 -0
  281. package/node/locales/ptBR.js +1 -0
  282. package/node/locales/ruRU.js +7 -6
  283. package/node/locales/skSK.js +1 -0
  284. package/node/locales/svSE.js +126 -0
  285. package/node/locales/trTR.js +1 -0
  286. package/node/locales/ukUA.js +1 -0
  287. package/node/locales/viVN.js +1 -0
  288. package/node/locales/zhCN.js +1 -0
  289. package/package.json +4 -3
@@ -52,7 +52,6 @@ export const GridToolbarExportContainer = /*#__PURE__*/React.forwardRef(function
52
52
  return /*#__PURE__*/_jsxs(React.Fragment, {
53
53
  children: [/*#__PURE__*/_jsx(rootProps.components.BaseButton, _extends({
54
54
  ref: handleRef,
55
- color: "primary",
56
55
  size: "small",
57
56
  startIcon: /*#__PURE__*/_jsx(rootProps.components.ExportIcon, {}),
58
57
  "aria-expanded": open ? 'true' : undefined,
@@ -108,7 +108,6 @@ const GridToolbarFilterButton = /*#__PURE__*/React.forwardRef(function GridToolb
108
108
  children: /*#__PURE__*/_jsx(rootProps.components.BaseButton, _extends({
109
109
  ref: ref,
110
110
  size: "small",
111
- color: "primary",
112
111
  "aria-label": apiRef.current.getLocaleText('toolbarFiltersLabel'),
113
112
  startIcon: /*#__PURE__*/_jsx(Badge, {
114
113
  badgeContent: activeFilters.length,
@@ -1,5 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { TextFieldProps } from '@mui/material/TextField';
3
+ import { GridFilterModel } from '../../models/gridFilterModel';
3
4
  export declare type GridToolbarQuickFilterProps = TextFieldProps & {
4
5
  /**
5
6
  * Function responsible for parsing text input in an array of independent values for quick filtering.
@@ -7,6 +8,12 @@ export declare type GridToolbarQuickFilterProps = TextFieldProps & {
7
8
  * @returns {any[]} The array of value on which quick filter is applied
8
9
  */
9
10
  quickFilterParser?: (input: string) => any[];
11
+ /**
12
+ * Function responsible for formatting values of quick filter in a string when the model is modified
13
+ * @param {any[]} values The new values passed to the quick filter model
14
+ * @returns {string} The string to display in the text field
15
+ */
16
+ quickFilterFormatter?: (values: GridFilterModel['quickFilterValues']) => string;
10
17
  /**
11
18
  * The debounce time in milliseconds.
12
19
  * @default 500
@@ -1,13 +1,17 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["quickFilterParser", "debounceMs"];
3
+ const _excluded = ["quickFilterParser", "quickFilterFormatter", "debounceMs"];
4
4
  import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import TextField from '@mui/material/TextField';
7
+ import IconButton from '@mui/material/IconButton';
7
8
  import { styled } from '@mui/material/styles';
8
9
  import { debounce } from '@mui/material/utils';
9
10
  import { useGridApiContext } from '../../hooks/utils/useGridApiContext';
10
11
  import { useGridRootProps } from '../../hooks/utils/useGridRootProps';
12
+ import { useGridSelector } from '../../hooks/utils/useGridSelector';
13
+ import { gridQuickFilterValuesSelector } from '../../hooks/features/filter';
14
+ import { isDeepEqual } from '../../utils/utils';
11
15
  import { jsx as _jsx } from "react/jsx-runtime";
12
16
  const GridToolbarQuickFilterRoot = styled(TextField, {
13
17
  name: 'MuiDataGrid',
@@ -18,28 +22,55 @@ const GridToolbarQuickFilterRoot = styled(TextField, {
18
22
  }) => ({
19
23
  width: 'auto',
20
24
  paddingBottom: theme.spacing(0.5),
21
- '& .MuiSvgIcon-root': {
22
- marginRight: theme.spacing(0.5)
25
+ '& input': {
26
+ marginLeft: theme.spacing(0.5)
23
27
  },
24
28
  '& .MuiInput-underline:before': {
25
29
  borderBottom: `1px solid ${theme.palette.divider}`
30
+ },
31
+ [`& input[type=search]::-ms-clear,
32
+ & input[type=search]::-ms-reveal`]: {
33
+ /* clears the 'X' icon from IE */
34
+ display: 'none',
35
+ width: 0,
36
+ height: 0
37
+ },
38
+ [`& input[type="search"]::-webkit-search-decoration,
39
+ & input[type="search"]::-webkit-search-cancel-button,
40
+ & input[type="search"]::-webkit-search-results-button,
41
+ & input[type="search"]::-webkit-search-results-decoration`]: {
42
+ /* clears the 'X' icon from Chrome */
43
+ display: 'none'
26
44
  }
27
45
  }));
28
46
 
29
47
  const defaultSearchValueParser = searchText => searchText.split(' ').filter(word => word !== '');
30
48
 
49
+ const defaultSearchValueFormatter = values => values.join(' ');
50
+
31
51
  function GridToolbarQuickFilter(props) {
32
52
  var _rootProps$components;
33
53
 
34
54
  const {
35
55
  quickFilterParser = defaultSearchValueParser,
56
+ quickFilterFormatter = defaultSearchValueFormatter,
36
57
  debounceMs = 500
37
58
  } = props,
38
59
  other = _objectWithoutPropertiesLoose(props, _excluded);
39
60
 
40
61
  const apiRef = useGridApiContext();
41
62
  const rootProps = useGridRootProps();
42
- const [searchValue, setSearchValue] = React.useState('');
63
+ const quickFilterValues = useGridSelector(apiRef, gridQuickFilterValuesSelector);
64
+ const [searchValue, setSearchValue] = React.useState(() => quickFilterFormatter(quickFilterValues != null ? quickFilterValues : []));
65
+ const [prevQuickFilterValues, setPrevQuickFilterValues] = React.useState(quickFilterValues);
66
+ React.useEffect(() => {
67
+ if (!isDeepEqual(prevQuickFilterValues, quickFilterValues)) {
68
+ // The model of quick filter value has been updated
69
+ setPrevQuickFilterValues(quickFilterValues); // Update the input value if needed to match the new model
70
+
71
+ setSearchValue(prevSearchValue => isDeepEqual(quickFilterParser(prevSearchValue), quickFilterValues) ? prevSearchValue : quickFilterFormatter(quickFilterValues != null ? quickFilterValues : []));
72
+ }
73
+ }, [prevQuickFilterValues, quickFilterValues, quickFilterFormatter, quickFilterParser]);
43
74
  const updateSearchValue = React.useCallback(newSearchValue => {
44
75
  apiRef.current.setQuickFilterValues(quickFilterParser(newSearchValue));
45
76
  }, [apiRef, quickFilterParser]);
@@ -49,6 +80,10 @@ function GridToolbarQuickFilter(props) {
49
80
  setSearchValue(newSearchValue);
50
81
  debouncedUpdateSearchValue(newSearchValue);
51
82
  }, [debouncedUpdateSearchValue]);
83
+ const handleSearchReset = React.useCallback(() => {
84
+ setSearchValue('');
85
+ updateSearchValue('');
86
+ }, [updateSearchValue]);
52
87
  return /*#__PURE__*/_jsx(GridToolbarQuickFilterRoot, _extends({
53
88
  as: rootProps.components.BaseTextField,
54
89
  variant: "standard",
@@ -60,6 +95,17 @@ function GridToolbarQuickFilter(props) {
60
95
  InputProps: {
61
96
  startAdornment: /*#__PURE__*/_jsx(rootProps.components.QuickFilterIcon, {
62
97
  fontSize: "small"
98
+ }),
99
+ endAdornment: /*#__PURE__*/_jsx(IconButton, {
100
+ "aria-label": apiRef.current.getLocaleText('toolbarQuickFilterDeleteIconLabel'),
101
+ size: "small",
102
+ sx: {
103
+ visibility: searchValue ? 'visible' : 'hidden'
104
+ },
105
+ onClick: handleSearchReset,
106
+ children: /*#__PURE__*/_jsx(rootProps.components.QuickFilterClearIcon, {
107
+ fontSize: "small"
108
+ })
63
109
  })
64
110
  }
65
111
  }, other, (_rootProps$components = rootProps.componentsProps) == null ? void 0 : _rootProps$components.baseTextField));
@@ -77,6 +123,13 @@ process.env.NODE_ENV !== "production" ? GridToolbarQuickFilter.propTypes = {
77
123
  */
78
124
  debounceMs: PropTypes.number,
79
125
 
126
+ /**
127
+ * Function responsible for formatting values of quick filter in a string when the model is modified
128
+ * @param {any[]} values The new values passed to the quick filter model
129
+ * @returns {string} The string to display in the text field
130
+ */
131
+ quickFilterFormatter: PropTypes.func,
132
+
80
133
  /**
81
134
  * Function responsible for parsing text input in an array of independent values for quick filtering.
82
135
  * @param {string} input The value entered by the user
@@ -35,7 +35,8 @@ const DEFAULT_GRID_ICON_SLOTS_COMPONENTS = {
35
35
  DetailPanelExpandIcon: GridAddIcon,
36
36
  DetailPanelCollapseIcon: GridRemoveIcon,
37
37
  RowReorderIcon: GridDragIcon,
38
- QuickFilterIcon: GridSearchIcon
38
+ QuickFilterIcon: GridSearchIcon,
39
+ QuickFilterClearIcon: GridCloseIcon
39
40
  };
40
41
  /**
41
42
  * TODO: Differentiate community and pro value and interface
@@ -105,6 +105,7 @@ export const GRID_DEFAULT_LOCALE_TEXT = {
105
105
  groupColumn: name => `Group by ${name}`,
106
106
  unGroupColumn: name => `Stop grouping by ${name}`,
107
107
  // Master/detail
108
+ detailPanelToggle: 'Detail panel toggle',
108
109
  expandDetailPanel: 'Expand',
109
110
  collapseDetailPanel: 'Collapse',
110
111
  // Used core components translation keys
@@ -8,7 +8,7 @@ import { isFunction } from '../../utils/utils';
8
8
  export const useGridStateInitialization = (apiRef, props) => {
9
9
  const controlStateMapRef = React.useRef({});
10
10
  const [, rawForceUpdate] = React.useState();
11
- const updateControlState = React.useCallback(controlStateItem => {
11
+ const registerControlState = React.useCallback(controlStateItem => {
12
12
  const {
13
13
  stateId
14
14
  } = controlStateItem,
@@ -18,7 +18,7 @@ export const useGridStateInitialization = (apiRef, props) => {
18
18
  stateId
19
19
  });
20
20
  }, []);
21
- const setState = React.useCallback(state => {
21
+ const setState = React.useCallback((state, reason) => {
22
22
  let newState;
23
23
 
24
24
  if (isFunction(state)) {
@@ -79,23 +79,36 @@ export const useGridStateInitialization = (apiRef, props) => {
79
79
 
80
80
  if (controlState.propOnChange && hasPropChanged) {
81
81
  const details = props.signature === GridSignature.DataGridPro ? {
82
- api: apiRef.current
83
- } : {};
82
+ api: apiRef.current,
83
+ reason
84
+ } : {
85
+ reason
86
+ };
84
87
  controlState.propOnChange(model, details);
85
88
  }
86
89
 
87
90
  if (!ignoreSetState) {
88
- apiRef.current.publishEvent(controlState.changeEvent, model);
91
+ apiRef.current.publishEvent(controlState.changeEvent, model, {
92
+ reason
93
+ });
89
94
  }
90
95
  }
91
96
 
92
97
  return !ignoreSetState;
93
98
  }, [apiRef, props.signature]);
99
+ const updateControlState = React.useCallback((key, state, reason) => {
100
+ return apiRef.current.setState(previousState => {
101
+ return _extends({}, previousState, {
102
+ [key]: state(previousState[key])
103
+ });
104
+ }, reason);
105
+ }, [apiRef]);
94
106
  const forceUpdate = React.useCallback(() => rawForceUpdate(() => apiRef.current.state), [apiRef]);
95
107
  const stateApi = {
96
108
  setState,
97
109
  forceUpdate,
98
- unstable_updateControlState: updateControlState
110
+ unstable_updateControlState: updateControlState,
111
+ unstable_registerControlState: registerControlState
99
112
  };
100
113
  useGridApiMethod(apiRef, stateApi, 'GridStateApi');
101
114
  };
@@ -2,6 +2,7 @@ import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import { useGridLogger, useGridApiMethod, useGridApiEventHandler } from '../../utils';
4
4
  import { gridColumnMenuSelector } from './columnMenuSelector';
5
+ import { gridClasses } from '../../../constants/gridClasses';
5
6
  export const columnMenuStateInitializer = state => _extends({}, state, {
6
7
  columnMenu: {
7
8
  open: false
@@ -77,7 +78,28 @@ export const useGridColumnMenu = apiRef => {
77
78
  * EVENTS
78
79
  */
79
80
 
81
+ const handleColumnHeaderFocus = React.useCallback((params, event) => {
82
+ // Check if the column menu button received focus
83
+ if (!event.target.classList.contains(gridClasses.menuIconButton)) {
84
+ return;
85
+ } // Check if there's an element which lost focus
86
+
87
+
88
+ if (!event.relatedTarget) {
89
+ return;
90
+ } // `true` if the focus was on the column menu itself, not on any item
91
+
92
+
93
+ const columnMenuLostFocus = event.relatedTarget.classList.contains(gridClasses.menuList); // `true` if the focus was on an item from the column menu
94
+
95
+ const columnMenuItemLostFocus = event.relatedTarget.getAttribute('role') === 'menuitem';
96
+
97
+ if (columnMenuLostFocus || columnMenuItemLostFocus) {
98
+ apiRef.current.setColumnHeaderFocus(params.field);
99
+ }
100
+ }, [apiRef]);
80
101
  useGridApiEventHandler(apiRef, 'columnResizeStart', hideColumnMenu);
102
+ useGridApiEventHandler(apiRef, 'columnHeaderFocus', handleColumnHeaderFocus);
81
103
  useGridApiEventHandler(apiRef, 'virtualScrollerWheel', apiRef.current.hideColumnMenu);
82
104
  useGridApiEventHandler(apiRef, 'virtualScrollerTouchMove', apiRef.current.hideColumnMenu);
83
105
  };
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import * as React from 'react';
2
2
  import { GridApiCommunity } from '../../../models/api/gridApiCommunity';
3
3
  /**
4
4
  * @requires useGridColumns (method, event)
@@ -1,4 +1,4 @@
1
- import React from 'react';
1
+ import * as React from 'react';
2
2
  import { useGridApiMethod } from '../../utils/useGridApiMethod';
3
3
  import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
4
4
 
@@ -8,4 +8,4 @@ export declare const columnsStateInitializer: GridStateInitializer<Pick<DataGrid
8
8
  * @requires useGridDimensions (method, event) - can be after
9
9
  * TODO: Impossible priority - useGridParamsApi also needs to be after useGridColumns
10
10
  */
11
- export declare function useGridColumns(apiRef: React.MutableRefObject<GridApiCommunity>, props: Pick<DataGridProcessedProps, 'initialState' | 'columns' | 'onColumnVisibilityChange' | 'columnVisibilityModel' | 'onColumnVisibilityModelChange' | 'columnTypes' | 'classes' | 'components' | 'componentsProps'>): void;
11
+ export declare function useGridColumns(apiRef: React.MutableRefObject<GridApiCommunity>, props: Pick<DataGridProcessedProps, 'columns' | 'onColumnVisibilityChange' | 'columnVisibilityModel' | 'onColumnVisibilityModelChange' | 'columnTypes' | 'components' | 'componentsProps'>): void;
@@ -42,7 +42,7 @@ export function useGridColumns(apiRef, props) {
42
42
  const columnTypes = React.useMemo(() => computeColumnTypes(props.columnTypes), [props.columnTypes]);
43
43
  const previousColumnsProp = React.useRef(props.columns);
44
44
  const previousColumnTypesProp = React.useRef(columnTypes);
45
- apiRef.current.unstable_updateControlState({
45
+ apiRef.current.unstable_registerControlState({
46
46
  stateId: 'visibleColumns',
47
47
  propModel: props.columnVisibilityModel,
48
48
  propOnChange: props.onColumnVisibilityModelChange,
@@ -16,6 +16,11 @@ export interface GridDimensions {
16
16
  * Indicates if a scroll is currently needed to go from the beginning of the first row to the end of the last row.
17
17
  */
18
18
  hasScrollY: boolean;
19
+ /**
20
+ * Size of the scrollbar used to scroll the rows in pixel.
21
+ * It is defined even when the scrollbar is currently not needed.
22
+ */
23
+ scrollBarSize: number;
19
24
  }
20
25
  export interface GridDimensionsApi {
21
26
  /**
@@ -37,7 +37,7 @@ const hasScroll = ({
37
37
 
38
38
  export function useGridDimensions(apiRef, props) {
39
39
  const logger = useGridLogger(apiRef, 'useResizeContainer');
40
- const warningShown = React.useRef(false);
40
+ const errorShown = React.useRef(false);
41
41
  const rootDimensionsRef = React.useRef(null);
42
42
  const fullDimensionsRef = React.useRef(null);
43
43
  const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector);
@@ -94,7 +94,8 @@ export function useGridDimensions(apiRef, props) {
94
94
  viewportOuterSize,
95
95
  viewportInnerSize,
96
96
  hasScrollX,
97
- hasScrollY
97
+ hasScrollY,
98
+ scrollBarSize
98
99
  };
99
100
  const prevDimensions = fullDimensionsRef.current;
100
101
  fullDimensionsRef.current = newFullDimensions;
@@ -144,14 +145,14 @@ export function useGridDimensions(apiRef, props) {
144
145
 
145
146
  const isJSDOM = /jsdom/.test(window.navigator.userAgent);
146
147
 
147
- if (size.height === 0 && !warningShown.current && !props.autoHeight && !isJSDOM) {
148
- logger.warn(['The parent of the grid has an empty height.', 'You need to make sure the container has an intrinsic height.', 'The grid displays with a height of 0px.', '', 'You can find a solution in the docs:', 'https://mui.com/x/react-data-grid/layout/'].join('\n'));
149
- warningShown.current = true;
148
+ if (size.height === 0 && !errorShown.current && !props.autoHeight && !isJSDOM) {
149
+ logger.error(['The parent DOM element of the data grid has an empty height.', 'Please make sure that this element has an intrinsic height.', 'The grid displays with a height of 0px.', '', 'More details: https://mui.com/r/x-data-grid-no-dimensions.'].join('\n'));
150
+ errorShown.current = true;
150
151
  }
151
152
 
152
- if (size.width === 0 && !warningShown.current && !isJSDOM) {
153
- logger.warn(['The parent of the grid has an empty width.', 'You need to make sure the container has an intrinsic width.', 'The grid displays with a width of 0px.', '', 'You can find a solution in the docs:', 'https://mui.com/x/react-data-grid/layout/'].join('\n'));
154
- warningShown.current = true;
153
+ if (size.width === 0 && !errorShown.current && !isJSDOM) {
154
+ logger.error(['The parent DOM element of the data grid has an empty width.', 'Please make sure that this element has an intrinsic width.', 'The grid displays with a width of 0px.', '', 'More details: https://mui.com/r/x-data-grid-no-dimensions.'].join('\n'));
155
+ errorShown.current = true;
155
156
  }
156
157
 
157
158
  if (isTestEnvironment) {
@@ -23,7 +23,7 @@ export function useGridEditing(apiRef, props) {
23
23
  useCellEditing(apiRef, props);
24
24
  useGridRowEditing(apiRef, props);
25
25
  const debounceMap = React.useRef({});
26
- apiRef.current.unstable_updateControlState({
26
+ apiRef.current.unstable_registerControlState({
27
27
  stateId: 'editRows',
28
28
  propModel: props.editRowsModel,
29
29
  propOnChange: props.onEditRowsModelChange,
@@ -9,6 +9,11 @@ export declare const gridFilterStateSelector: (state: GridStateCommunity) => imp
9
9
  * @category Filtering
10
10
  */
11
11
  export declare const gridFilterModelSelector: import("../../../utils/createSelector").OutputSelector<GridStateCommunity, import("../../..").GridFilterModel>;
12
+ /**
13
+ * Get the current quick filter values.
14
+ * @category Filtering
15
+ */
16
+ export declare const gridQuickFilterValuesSelector: import("../../../utils/createSelector").OutputSelector<GridStateCommunity, any[] | undefined>;
12
17
  /**
13
18
  * @category Filtering
14
19
  * @ignore - do not document.
@@ -13,6 +13,12 @@ export const gridFilterStateSelector = state => state.filter;
13
13
  */
14
14
 
15
15
  export const gridFilterModelSelector = createSelector(gridFilterStateSelector, filterState => filterState.filterModel);
16
+ /**
17
+ * Get the current quick filter values.
18
+ * @category Filtering
19
+ */
20
+
21
+ export const gridQuickFilterValuesSelector = createSelector(gridFilterModelSelector, filterModel => filterModel.quickFilterValues);
16
22
  /**
17
23
  * @category Filtering
18
24
  * @ignore - do not document.
@@ -19,7 +19,7 @@ export interface GridFilterState {
19
19
  /**
20
20
  * Amount of descendants that are passing the filters.
21
21
  * For the Tree Data, it includes all the intermediate depth levels (= amount of children + amount of grand children + ...).
22
- * For the Row Grouping by Column, it does not include the intermediate depth levels (= amount of descendant of maximum depth).
22
+ * For the Row grouping by column, it does not include the intermediate depth levels (= amount of descendant of maximum depth).
23
23
  * If a row is not registered in this lookup, it is supposed to have no descendant passing the filters.
24
24
  */
25
25
  filteredDescendantCountLookup: Record<GridRowId, number>;
@@ -12,7 +12,7 @@ import { GridAggregatedFilterItemApplier } from './gridFilterState';
12
12
  */
13
13
  export declare const cleanFilterItem: (item: GridFilterItem, apiRef: React.MutableRefObject<GridApiCommunity>) => GridFilterItem;
14
14
  export declare const sanitizeFilterModel: (model: GridFilterModel, disableMultipleColumnsFiltering: boolean, apiRef: React.MutableRefObject<GridApiCommunity>) => GridFilterModel;
15
- export declare const mergeStateWithFilterModel: (filterModel: GridFilterModel, disableMultipleColumnsFiltering: boolean, apiRef: React.MutableRefObject<GridApiCommunity>) => (state: GridStateCommunity) => GridStateCommunity;
15
+ export declare const mergeStateWithFilterModel: (filterModel: GridFilterModel, disableMultipleColumnsFiltering: boolean, apiRef: React.MutableRefObject<GridApiCommunity>) => (filteringState: GridStateCommunity['filter']) => GridStateCommunity['filter'];
16
16
  /**
17
17
  * Generates a method to easily check if a row is matching the current filter model.
18
18
  * @param {GridFilterModel} filterModel The model with which we want to filter the rows.
@@ -1,7 +1,7 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import { GridLinkOperator } from '../../../models';
3
3
  import { buildWarning } from '../../../utils/warning';
4
- import { gridColumnFieldsSelector } from '../columns';
4
+ import { gridColumnFieldsSelector, gridColumnLookupSelector } from '../columns';
5
5
 
6
6
  /**
7
7
  * Adds default values to the optional fields of a filter items.
@@ -18,8 +18,9 @@ export const cleanFilterItem = (item, apiRef) => {
18
18
  }
19
19
 
20
20
  if (cleanItem.operatorValue == null) {
21
- // we select a default operator
22
- const column = apiRef.current.getColumn(cleanItem.columnField);
21
+ // Selects a default operator
22
+ // We don't use `apiRef.current.getColumn` because it is not ready during state initialization
23
+ const column = gridColumnLookupSelector(apiRef)[cleanItem.columnField];
23
24
  cleanItem.operatorValue = column && column.filterOperators[0].value;
24
25
  }
25
26
 
@@ -64,10 +65,8 @@ export const sanitizeFilterModel = (model, disableMultipleColumnsFiltering, apiR
64
65
 
65
66
  return model;
66
67
  };
67
- export const mergeStateWithFilterModel = (filterModel, disableMultipleColumnsFiltering, apiRef) => state => _extends({}, state, {
68
- filter: _extends({}, state.filter, {
69
- filterModel: sanitizeFilterModel(filterModel, disableMultipleColumnsFiltering, apiRef)
70
- })
68
+ export const mergeStateWithFilterModel = (filterModel, disableMultipleColumnsFiltering, apiRef) => filteringState => _extends({}, filteringState, {
69
+ filterModel: sanitizeFilterModel(filterModel, disableMultipleColumnsFiltering, apiRef)
71
70
  });
72
71
  /**
73
72
  * Generates a method to easily check if a row is matching the current filter model.
@@ -187,14 +186,16 @@ export const buildAggregatedQuickFilterApplier = (filterModel, apiRef) => {
187
186
  const sanitizedQuickFilterValues = quickFilterValues.filter((value, index) => Object.keys(appliersPerColumnField).some(field => appliersPerColumnField[field][index] != null));
188
187
  return (rowId, shouldApplyFilter) => {
189
188
  const usedCellParams = {};
189
+ const columnsFieldsToFilter = [];
190
190
  Object.keys(appliersPerColumnField).forEach(columnField => {
191
191
  if (!shouldApplyFilter || shouldApplyFilter(columnField)) {
192
192
  usedCellParams[columnField] = apiRef.current.getCellParams(rowId, columnField);
193
+ columnsFieldsToFilter.push(columnField);
193
194
  }
194
195
  }); // Return `false` as soon as we have a quick filter value that does not match any column
195
196
 
196
197
  if (quickFilterLogicOperator === GridLinkOperator.And) {
197
- return sanitizedQuickFilterValues.every((value, index) => Object.keys(appliersPerColumnField).some(field => {
198
+ return sanitizedQuickFilterValues.every((value, index) => columnsFieldsToFilter.some(field => {
198
199
  var _appliersPerColumnFie, _appliersPerColumnFie2;
199
200
 
200
201
  if (appliersPerColumnField[field][index] == null) {
@@ -206,7 +207,7 @@ export const buildAggregatedQuickFilterApplier = (filterModel, apiRef) => {
206
207
  } // Return `true` as soon as we have have a quick filter value that match any column
207
208
 
208
209
 
209
- return sanitizedQuickFilterValues.some((value, index) => Object.keys(appliersPerColumnField).some(field => {
210
+ return sanitizedQuickFilterValues.some((value, index) => columnsFieldsToFilter.some(field => {
210
211
  var _appliersPerColumnFie3, _appliersPerColumnFie4;
211
212
 
212
213
  if (appliersPerColumnField[field][index] == null) {
@@ -8,4 +8,4 @@ export declare const filterStateInitializer: GridStateInitializer<Pick<DataGridP
8
8
  * @requires useGridParamsApi (method)
9
9
  * @requires useGridRows (event)
10
10
  */
11
- export declare const useGridFilter: (apiRef: React.MutableRefObject<GridApiCommunity>, props: Pick<DataGridProcessedProps, 'initialState' | 'filterModel' | 'onFilterModelChange' | 'filterMode' | 'disableMultipleColumnsFiltering' | 'components' | 'componentsProps'>) => void;
11
+ export declare const useGridFilter: (apiRef: React.MutableRefObject<GridApiCommunity>, props: Pick<DataGridProcessedProps, 'filterModel' | 'onFilterModelChange' | 'filterMode' | 'disableMultipleColumnsFiltering' | 'components' | 'componentsProps'>) => void;
@@ -37,7 +37,7 @@ export const useGridFilter = (apiRef, props) => {
37
37
  var _props$componentsProp2;
38
38
 
39
39
  const logger = useGridLogger(apiRef, 'useGridFilter');
40
- apiRef.current.unstable_updateControlState({
40
+ apiRef.current.unstable_registerControlState({
41
41
  stateId: 'filter',
42
42
  propModel: props.filterModel,
43
43
  propOnChange: props.onFilterModelChange,
@@ -78,7 +78,23 @@ export const useGridFilter = (apiRef, props) => {
78
78
 
79
79
  apiRef.current.setFilterModel(_extends({}, filterModel, {
80
80
  items
81
- }));
81
+ }), 'upsertFilterItem');
82
+ }, [apiRef]);
83
+ const upsertFilterItems = React.useCallback(items => {
84
+ const filterModel = gridFilterModelSelector(apiRef);
85
+ const existingItems = [...filterModel.items];
86
+ items.forEach(item => {
87
+ const itemIndex = items.findIndex(filterItem => filterItem.id === item.id);
88
+
89
+ if (itemIndex === -1) {
90
+ existingItems.push(item);
91
+ } else {
92
+ existingItems[itemIndex] = item;
93
+ }
94
+ });
95
+ apiRef.current.setFilterModel(_extends({}, filterModel, {
96
+ items
97
+ }), 'upsertFilterItems');
82
98
  }, [apiRef]);
83
99
  const deleteFilterItem = React.useCallback(itemToDelete => {
84
100
  const filterModel = gridFilterModelSelector(apiRef);
@@ -90,7 +106,7 @@ export const useGridFilter = (apiRef, props) => {
90
106
 
91
107
  apiRef.current.setFilterModel(_extends({}, filterModel, {
92
108
  items
93
- }));
109
+ }), 'deleteFilterItem');
94
110
  }, [apiRef]);
95
111
  const showFilterPanel = React.useCallback(targetColumnField => {
96
112
  logger.debug('Displaying filter panel');
@@ -133,7 +149,7 @@ export const useGridFilter = (apiRef, props) => {
133
149
 
134
150
  apiRef.current.setFilterModel(_extends({}, filterModel, {
135
151
  linkOperator
136
- }));
152
+ }), 'changeLogicOperator');
137
153
  }, [apiRef]);
138
154
  const setQuickFilterValues = React.useCallback(values => {
139
155
  const filterModel = gridFilterModelSelector(apiRef);
@@ -146,12 +162,12 @@ export const useGridFilter = (apiRef, props) => {
146
162
  quickFilterValues: [...values]
147
163
  }));
148
164
  }, [apiRef]);
149
- const setFilterModel = React.useCallback(model => {
165
+ const setFilterModel = React.useCallback((model, reason) => {
150
166
  const currentModel = gridFilterModelSelector(apiRef);
151
167
 
152
168
  if (currentModel !== model) {
153
169
  logger.debug('Setting filter model');
154
- apiRef.current.setState(mergeStateWithFilterModel(model, props.disableMultipleColumnsFiltering, apiRef));
170
+ apiRef.current.unstable_updateControlState('filter', mergeStateWithFilterModel(model, props.disableMultipleColumnsFiltering, apiRef), reason);
155
171
  apiRef.current.unstable_applyFilters();
156
172
  }
157
173
  }, [apiRef, logger, props.disableMultipleColumnsFiltering]);
@@ -164,6 +180,7 @@ export const useGridFilter = (apiRef, props) => {
164
180
  unstable_applyFilters: applyFilters,
165
181
  deleteFilterItem,
166
182
  upsertFilterItem,
183
+ upsertFilterItems,
167
184
  setFilterModel,
168
185
  showFilterPanel,
169
186
  hideFilterPanel,
@@ -197,7 +214,7 @@ export const useGridFilter = (apiRef, props) => {
197
214
  return params;
198
215
  }
199
216
 
200
- apiRef.current.setState(mergeStateWithFilterModel(filterModel, props.disableMultipleColumnsFiltering, apiRef));
217
+ apiRef.current.unstable_updateControlState('filter', mergeStateWithFilterModel(filterModel, props.disableMultipleColumnsFiltering, apiRef), 'restoreState');
201
218
  return _extends({}, params, {
202
219
  callbacks: [...params.callbacks, apiRef.current.unstable_applyFilters]
203
220
  });
@@ -39,7 +39,7 @@ export const useGridPage = (apiRef, props) => {
39
39
 
40
40
  const logger = useGridLogger(apiRef, 'useGridPage');
41
41
  const visibleTopLevelRowCount = useGridSelector(apiRef, gridVisibleTopLevelRowCountSelector);
42
- apiRef.current.unstable_updateControlState({
42
+ apiRef.current.unstable_registerControlState({
43
43
  stateId: 'page',
44
44
  propModel: props.page,
45
45
  propOnChange: props.onPageChange,
@@ -21,7 +21,7 @@ export const useGridPageSize = (apiRef, props) => {
21
21
 
22
22
  const logger = useGridLogger(apiRef, 'useGridPageSize');
23
23
  const rowHeight = useGridSelector(apiRef, gridDensityRowHeightSelector);
24
- apiRef.current.unstable_updateControlState({
24
+ apiRef.current.unstable_registerControlState({
25
25
  stateId: 'pageSize',
26
26
  propModel: props.pageSize,
27
27
  propOnChange: props.onPageSizeChange,
@@ -323,10 +323,23 @@ export const useGridRows = (apiRef, props) => {
323
323
  if (isFirstRender.current) {
324
324
  isFirstRender.current = false;
325
325
  return;
326
- } // The new rows have already been applied (most likely in the `'rowGroupsPreProcessingChange'` listener)
326
+ }
327
+
328
+ const areNewRowsAlreadyInState = apiRef.current.unstable_caches.rows.rowsBeforePartialUpdates === props.rows;
329
+ const isNewLoadingAlreadyInState = apiRef.current.unstable_caches.rows.loadingPropBeforePartialUpdates === props.loading; // The new rows have already been applied (most likely in the `'rowGroupsPreProcessingChange'` listener)
327
330
 
331
+ if (areNewRowsAlreadyInState) {
332
+ // If the loading prop has changed, we need to update its value in the state because it won't be done by `throttledRowsChange`
333
+ if (!isNewLoadingAlreadyInState) {
334
+ apiRef.current.setState(state => _extends({}, state, {
335
+ rows: _extends({}, state.rows, {
336
+ loading: props.loading
337
+ })
338
+ }));
339
+ apiRef.current.unstable_caches.rows.loadingPropBeforePartialUpdates = props.loading;
340
+ apiRef.current.forceUpdate();
341
+ }
328
342
 
329
- if (apiRef.current.unstable_caches.rows.rowsBeforePartialUpdates === props.rows && apiRef.current.unstable_caches.rows.loadingPropBeforePartialUpdates === props.loading) {
330
343
  return;
331
344
  }
332
345