@mui/x-data-grid 5.17.22 → 5.17.24

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 (32) hide show
  1. package/CHANGELOG.md +58 -0
  2. package/components/panel/GridColumnsPanel.js +11 -0
  3. package/components/panel/GridPanelWrapper.d.ts +4 -0
  4. package/components/panel/GridPanelWrapper.js +25 -5
  5. package/components/toolbar/GridToolbarFilterButton.js +11 -8
  6. package/hooks/features/rows/useGridRows.js +9 -4
  7. package/hooks/features/virtualization/useGridVirtualScroller.js +14 -0
  8. package/index.js +1 -1
  9. package/legacy/components/panel/GridColumnsPanel.js +11 -0
  10. package/legacy/components/panel/GridPanelWrapper.js +25 -4
  11. package/legacy/components/toolbar/GridToolbarFilterButton.js +10 -3
  12. package/legacy/hooks/features/rows/useGridRows.js +8 -5
  13. package/legacy/hooks/features/virtualization/useGridVirtualScroller.js +14 -0
  14. package/legacy/index.js +1 -1
  15. package/legacy/utils/domUtils.js +10 -8
  16. package/models/gridFilterOperator.d.ts +6 -0
  17. package/modern/components/panel/GridColumnsPanel.js +11 -0
  18. package/modern/components/panel/GridPanelWrapper.js +25 -5
  19. package/modern/components/toolbar/GridToolbarFilterButton.js +8 -1
  20. package/modern/hooks/features/rows/useGridRows.js +9 -4
  21. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +14 -0
  22. package/modern/index.js +1 -1
  23. package/modern/utils/domUtils.js +10 -8
  24. package/node/components/panel/GridColumnsPanel.js +11 -0
  25. package/node/components/panel/GridPanelWrapper.js +27 -6
  26. package/node/components/toolbar/GridToolbarFilterButton.js +11 -8
  27. package/node/hooks/features/rows/useGridRows.js +9 -4
  28. package/node/hooks/features/virtualization/useGridVirtualScroller.js +13 -0
  29. package/node/index.js +1 -1
  30. package/node/utils/domUtils.js +9 -8
  31. package/package.json +1 -1
  32. package/utils/domUtils.js +10 -8
package/CHANGELOG.md CHANGED
@@ -3,6 +3,64 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## 5.17.24
7
+
8
+ _Feb 16, 2023_
9
+
10
+ We'd like to offer a big thanks to the 5 contributors who made this release possible. Here are some highlights ✨:
11
+
12
+ - 🌍 Add Hungarian (hu-HU) locale
13
+ - 🐞 Bugfixes
14
+
15
+ ### `@mui/x-data-grid@v5.17.24` / `@mui/x-data-grid-pro@v5.17.24` / `@mui/x-data-grid-premium@v5.17.24`
16
+
17
+ #### Changes
18
+
19
+ - [DataGrid] Allow to pass props to the `TrapFocus` inside the panel wrapper (#7897) @Vivek-Prajapatii
20
+ - [DataGrid] Avoid unnecessary rerenders after `updateRows` (#7945) @cherniavskii
21
+ - [DataGridPro] Change cursor when dragging a column (#7878) @sai6855
22
+ - [DataGridPremium] Fix `leafField` to have correct focus value (#7959) @MBilalShafi
23
+
24
+ ### `@mui/x-date-pickers@v5.0.19` / `@mui/x-date-pickers-pro@v5.0.19`
25
+
26
+ #### Changes
27
+
28
+ - [l10n] Add Hungarian (hu-HU) locale (#7796) @noherczeg
29
+
30
+ ## 5.17.23
31
+
32
+ _Feb 9, 2023_
33
+
34
+ We'd like to offer a big thanks to the 6 contributors who made this release possible. Here are some highlights ✨:
35
+
36
+ - 🌍 Improve Brazilian Portuguese (pt-BR) locale
37
+ - 🎉 Add banner and callouts to inform about MUI X v6 beta
38
+ - 🐞 Bugfixes
39
+
40
+ ### `@mui/x-data-grid@v5.17.23` / `@mui/x-data-grid-pro@v5.17.23` / `@mui/x-data-grid-premium@v5.17.23`
41
+
42
+ #### Changes
43
+
44
+ - [DataGrid] Allow to customize the value displayed in the filter button tooltip (#7816) @ithrforu
45
+ - [DataGrid] Fix `getCellElement` method not working with pinned columns (#7844) @yaredtsy
46
+ - [DataGrid] Fix stale rows issue in `unstable_replaceRows` (#7694) @MBilalShafi
47
+ - [l10n] Improve Brazilian Portuguese (pt-BR) locale (#7850) @ed-ateixeira
48
+
49
+ ### `@mui/x-date-pickers@v_5.0.18` / `@mui/x-date-pickers-pro@v_5.0.18`
50
+
51
+ #### Changes
52
+
53
+ - [pickers] Update pickers when new value has a distinct timezone (#7853) @alexfauquette
54
+
55
+ ### Docs
56
+
57
+ - [docs] Add messages in v5 doc to inform people about v6 (#7838) @flaviendelangle
58
+ - [docs] Fix 301 link @oliviertassinari
59
+
60
+ ### Core
61
+
62
+ - [core] Upgrade monorepo (#7849) @cherniavskii
63
+
6
64
  ## v5.17.22
7
65
 
8
66
  _Feb 2, 2023_
@@ -226,6 +226,17 @@ process.env.NODE_ENV !== "production" ? GridColumnsPanel.propTypes = {
226
226
  // ----------------------------------------------------------------------
227
227
  autoFocusSearchField: PropTypes.bool,
228
228
  searchPredicate: PropTypes.func,
229
+ slotProps: PropTypes.shape({
230
+ TrapFocus: PropTypes.shape({
231
+ children: PropTypes.element.isRequired,
232
+ disableAutoFocus: PropTypes.bool,
233
+ disableEnforceFocus: PropTypes.bool,
234
+ disableRestoreFocus: PropTypes.bool,
235
+ getTabbable: PropTypes.func,
236
+ isEnabled: PropTypes.func,
237
+ open: PropTypes.bool.isRequired
238
+ })
239
+ }),
229
240
  sort: PropTypes.oneOf(['asc', 'desc'])
230
241
  } : void 0;
231
242
  export { GridColumnsPanel };
@@ -1,7 +1,11 @@
1
1
  import * as React from 'react';
2
+ import { TrapFocusProps } from '@mui/material/Unstable_TrapFocus';
2
3
  import { Theme } from '@mui/material/styles';
3
4
  import { MUIStyledCommonProps } from '@mui/system';
4
5
  export interface GridPanelWrapperProps extends React.PropsWithChildren<React.HTMLAttributes<HTMLDivElement>>, MUIStyledCommonProps<Theme> {
6
+ slotProps?: {
7
+ TrapFocus?: TrapFocusProps;
8
+ };
5
9
  }
6
10
  declare const GridPanelWrapper: React.ForwardRefExoticComponent<GridPanelWrapperProps & React.RefAttributes<HTMLDivElement>>;
7
11
  export { GridPanelWrapper };
@@ -1,7 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["className"];
3
+ const _excluded = ["className", "slotProps"];
4
4
  import * as React from 'react';
5
+ import PropTypes from 'prop-types';
5
6
  import clsx from 'clsx';
6
7
  import TrapFocus from '@mui/material/Unstable_TrapFocus';
7
8
  import { styled } from '@mui/material/styles';
@@ -37,7 +38,8 @@ const isEnabled = () => true;
37
38
 
38
39
  const GridPanelWrapper = /*#__PURE__*/React.forwardRef(function GridPanelWrapper(props, ref) {
39
40
  const {
40
- className
41
+ className,
42
+ slotProps = {}
41
43
  } = props,
42
44
  other = _objectWithoutPropertiesLoose(props, _excluded);
43
45
 
@@ -46,15 +48,33 @@ const GridPanelWrapper = /*#__PURE__*/React.forwardRef(function GridPanelWrapper
46
48
  classes: rootProps.classes
47
49
  };
48
50
  const classes = useUtilityClasses(ownerState);
49
- return /*#__PURE__*/_jsx(TrapFocus, {
51
+ return /*#__PURE__*/_jsx(TrapFocus, _extends({
50
52
  open: true,
51
53
  disableEnforceFocus: true,
52
- isEnabled: isEnabled,
54
+ isEnabled: isEnabled
55
+ }, slotProps.TrapFocus, {
53
56
  children: /*#__PURE__*/_jsx(GridPanelWrapperRoot, _extends({
54
57
  ref: ref,
55
58
  tabIndex: -1,
56
59
  className: clsx(className, classes.root)
57
60
  }, other))
58
- });
61
+ }));
59
62
  });
63
+ process.env.NODE_ENV !== "production" ? GridPanelWrapper.propTypes = {
64
+ // ----------------------------- Warning --------------------------------
65
+ // | These PropTypes are generated from the TypeScript type definitions |
66
+ // | To update them edit the TypeScript types and run "yarn proptypes" |
67
+ // ----------------------------------------------------------------------
68
+ slotProps: PropTypes.shape({
69
+ TrapFocus: PropTypes.shape({
70
+ children: PropTypes.element.isRequired,
71
+ disableAutoFocus: PropTypes.bool,
72
+ disableEnforceFocus: PropTypes.bool,
73
+ disableRestoreFocus: PropTypes.bool,
74
+ getTabbable: PropTypes.func,
75
+ isEnabled: PropTypes.func,
76
+ open: PropTypes.bool.isRequired
77
+ })
78
+ })
79
+ } : void 0;
60
80
  export { GridPanelWrapper };
@@ -67,18 +67,21 @@ const GridToolbarFilterButton = /*#__PURE__*/React.forwardRef(function GridToolb
67
67
 
68
68
  const getOperatorLabel = item => lookup[item.columnField].filterOperators.find(operator => operator.value === item.operatorValue).label || apiRef.current.getLocaleText(`filterOperator${capitalize(item.operatorValue)}`).toString();
69
69
 
70
+ const getFilterItemValue = item => {
71
+ const {
72
+ getValueAsString
73
+ } = lookup[item.columnField].filterOperators.find(operator => operator.value === item.operatorValue);
74
+ return getValueAsString ? getValueAsString(item.value) : item.value;
75
+ };
76
+
70
77
  return /*#__PURE__*/_jsxs("div", {
71
78
  children: [apiRef.current.getLocaleText('toolbarFiltersTooltipActive')(activeFilters.length), /*#__PURE__*/_jsx(GridToolbarFilterListRoot, {
72
79
  className: classes.root,
73
- children: activeFilters.map((item, index) => {
74
- var _item$value;
75
-
76
- return _extends({}, lookup[item.columnField] && /*#__PURE__*/_jsx("li", {
77
- children: `${lookup[item.columnField].headerName || item.columnField}
80
+ children: activeFilters.map((item, index) => _extends({}, lookup[item.columnField] && /*#__PURE__*/_jsx("li", {
81
+ children: `${lookup[item.columnField].headerName || item.columnField}
78
82
  ${getOperatorLabel(item)}
79
- ${(_item$value = item.value) != null ? _item$value : ''}`
80
- }, index));
81
- })
83
+ ${item.value ? getFilterItemValue(item) : ''}`
84
+ }, index)))
82
85
  })]
83
86
  });
84
87
  }, [apiRef, preferencePanel.open, activeFilters, lookup, classes]);
@@ -299,14 +299,19 @@ export const useGridRows = (apiRef, props) => {
299
299
  apiRef.current.unstable_caches.rows.idRowsLookup = updatedIdRowsLookup;
300
300
  apiRef.current.unstable_caches.rows.idToIdLookup = updatedIdToIdLookup;
301
301
  apiRef.current.unstable_caches.rows.ids = updatedRows;
302
- apiRef.current.setState(state => _extends({}, state, {
303
- rows: _extends({}, state.rows, {
302
+ apiRef.current.setState(state => {
303
+ const newRowsState = {
304
304
  idRowsLookup: updatedIdRowsLookup,
305
305
  idToIdLookup: updatedIdToIdLookup,
306
306
  tree: updatedTree,
307
307
  ids: updatedRows
308
- })
309
- }));
308
+ };
309
+ return _extends({}, state, {
310
+ rows: _extends({}, state.rows, newRowsState, {
311
+ groupingResponseBeforeRowHydration: _extends({}, state.rows.groupingResponseBeforeRowHydration, newRowsState)
312
+ })
313
+ });
314
+ });
310
315
  apiRef.current.publishEvent('rowsSet');
311
316
  }, [apiRef, props.signature, props.getRowId]);
312
317
  const rowApi = {
@@ -53,6 +53,15 @@ export const getRenderableIndexes = ({
53
53
  }) => {
54
54
  return [clamp(firstIndex - buffer, minFirstIndex, maxLastIndex), clamp(lastIndex + buffer, minFirstIndex, maxLastIndex)];
55
55
  };
56
+
57
+ const areRenderContextsEqual = (context1, context2) => {
58
+ if (context1 === context2) {
59
+ return true;
60
+ }
61
+
62
+ return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
63
+ };
64
+
56
65
  export const useGridVirtualScroller = props => {
57
66
  var _currentPage$range3, _currentPage$range4;
58
67
 
@@ -218,6 +227,11 @@ export const useGridVirtualScroller = props => {
218
227
  }
219
228
  }, [apiRef, currentPage.rows, onRenderZonePositioning, renderZoneMinColumnIndex, renderZoneMaxColumnIndex, rootProps.columnBuffer, rootProps.rowBuffer]);
220
229
  const updateRenderContext = React.useCallback(nextRenderContext => {
230
+ if (prevRenderContext.current && areRenderContextsEqual(nextRenderContext, prevRenderContext.current)) {
231
+ updateRenderZonePosition(nextRenderContext);
232
+ return;
233
+ }
234
+
221
235
  setRenderContext(nextRenderContext);
222
236
  updateRenderZonePosition(nextRenderContext);
223
237
  const [firstRowToRender, lastRowToRender] = getRenderableIndexes({
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /** @license MUI X v5.17.22
1
+ /** @license MUI X v5.17.24
2
2
  *
3
3
  * This source code is licensed under the MIT license found in the
4
4
  * LICENSE file in the root directory of this source tree.
@@ -247,6 +247,17 @@ process.env.NODE_ENV !== "production" ? GridColumnsPanel.propTypes = {
247
247
  // ----------------------------------------------------------------------
248
248
  autoFocusSearchField: PropTypes.bool,
249
249
  searchPredicate: PropTypes.func,
250
+ slotProps: PropTypes.shape({
251
+ TrapFocus: PropTypes.shape({
252
+ children: PropTypes.element.isRequired,
253
+ disableAutoFocus: PropTypes.bool,
254
+ disableEnforceFocus: PropTypes.bool,
255
+ disableRestoreFocus: PropTypes.bool,
256
+ getTabbable: PropTypes.func,
257
+ isEnabled: PropTypes.func,
258
+ open: PropTypes.bool.isRequired
259
+ })
260
+ }),
250
261
  sort: PropTypes.oneOf(['asc', 'desc'])
251
262
  } : void 0;
252
263
  export { GridColumnsPanel };
@@ -1,7 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
3
- var _excluded = ["className"];
3
+ var _excluded = ["className", "slotProps"];
4
4
  import * as React from 'react';
5
+ import PropTypes from 'prop-types';
5
6
  import clsx from 'clsx';
6
7
  import TrapFocus from '@mui/material/Unstable_TrapFocus';
7
8
  import { styled } from '@mui/material/styles';
@@ -39,6 +40,8 @@ var isEnabled = function isEnabled() {
39
40
 
40
41
  var GridPanelWrapper = /*#__PURE__*/React.forwardRef(function GridPanelWrapper(props, ref) {
41
42
  var className = props.className,
43
+ _props$slotProps = props.slotProps,
44
+ slotProps = _props$slotProps === void 0 ? {} : _props$slotProps,
42
45
  other = _objectWithoutProperties(props, _excluded);
43
46
 
44
47
  var rootProps = useGridRootProps();
@@ -46,15 +49,33 @@ var GridPanelWrapper = /*#__PURE__*/React.forwardRef(function GridPanelWrapper(p
46
49
  classes: rootProps.classes
47
50
  };
48
51
  var classes = useUtilityClasses(ownerState);
49
- return /*#__PURE__*/_jsx(TrapFocus, {
52
+ return /*#__PURE__*/_jsx(TrapFocus, _extends({
50
53
  open: true,
51
54
  disableEnforceFocus: true,
52
- isEnabled: isEnabled,
55
+ isEnabled: isEnabled
56
+ }, slotProps.TrapFocus, {
53
57
  children: /*#__PURE__*/_jsx(GridPanelWrapperRoot, _extends({
54
58
  ref: ref,
55
59
  tabIndex: -1,
56
60
  className: clsx(className, classes.root)
57
61
  }, other))
58
- });
62
+ }));
59
63
  });
64
+ process.env.NODE_ENV !== "production" ? GridPanelWrapper.propTypes = {
65
+ // ----------------------------- Warning --------------------------------
66
+ // | These PropTypes are generated from the TypeScript type definitions |
67
+ // | To update them edit the TypeScript types and run "yarn proptypes" |
68
+ // ----------------------------------------------------------------------
69
+ slotProps: PropTypes.shape({
70
+ TrapFocus: PropTypes.shape({
71
+ children: PropTypes.element.isRequired,
72
+ disableAutoFocus: PropTypes.bool,
73
+ disableEnforceFocus: PropTypes.bool,
74
+ disableRestoreFocus: PropTypes.bool,
75
+ getTabbable: PropTypes.func,
76
+ isEnabled: PropTypes.func,
77
+ open: PropTypes.bool.isRequired
78
+ })
79
+ })
80
+ } : void 0;
60
81
  export { GridPanelWrapper };
@@ -71,14 +71,21 @@ var GridToolbarFilterButton = /*#__PURE__*/React.forwardRef(function GridToolbar
71
71
  }).label || apiRef.current.getLocaleText("filterOperator".concat(capitalize(item.operatorValue))).toString();
72
72
  };
73
73
 
74
+ var getFilterItemValue = function getFilterItemValue(item) {
75
+ var _ref2 = lookup[item.columnField].filterOperators.find(function (operator) {
76
+ return operator.value === item.operatorValue;
77
+ }),
78
+ getValueAsString = _ref2.getValueAsString;
79
+
80
+ return getValueAsString ? getValueAsString(item.value) : item.value;
81
+ };
82
+
74
83
  return /*#__PURE__*/_jsxs("div", {
75
84
  children: [apiRef.current.getLocaleText('toolbarFiltersTooltipActive')(activeFilters.length), /*#__PURE__*/_jsx(GridToolbarFilterListRoot, {
76
85
  className: classes.root,
77
86
  children: activeFilters.map(function (item, index) {
78
- var _item$value;
79
-
80
87
  return _extends({}, lookup[item.columnField] && /*#__PURE__*/_jsx("li", {
81
- children: "".concat(lookup[item.columnField].headerName || item.columnField, "\n ").concat(getOperatorLabel(item), "\n ").concat((_item$value = item.value) != null ? _item$value : '')
88
+ children: "".concat(lookup[item.columnField].headerName || item.columnField, "\n ").concat(getOperatorLabel(item), "\n ").concat(item.value ? getFilterItemValue(item) : '')
82
89
  }, index));
83
90
  })
84
91
  })]
@@ -329,12 +329,15 @@ export var useGridRows = function useGridRows(apiRef, props) {
329
329
  apiRef.current.unstable_caches.rows.idToIdLookup = updatedIdToIdLookup;
330
330
  apiRef.current.unstable_caches.rows.ids = updatedRows;
331
331
  apiRef.current.setState(function (state) {
332
+ var newRowsState = {
333
+ idRowsLookup: updatedIdRowsLookup,
334
+ idToIdLookup: updatedIdToIdLookup,
335
+ tree: updatedTree,
336
+ ids: updatedRows
337
+ };
332
338
  return _extends({}, state, {
333
- rows: _extends({}, state.rows, {
334
- idRowsLookup: updatedIdRowsLookup,
335
- idToIdLookup: updatedIdToIdLookup,
336
- tree: updatedTree,
337
- ids: updatedRows
339
+ rows: _extends({}, state.rows, newRowsState, {
340
+ groupingResponseBeforeRowHydration: _extends({}, state.rows.groupingResponseBeforeRowHydration, newRowsState)
338
341
  })
339
342
  });
340
343
  });
@@ -56,6 +56,15 @@ export var getRenderableIndexes = function getRenderableIndexes(_ref) {
56
56
  maxLastIndex = _ref.maxLastIndex;
57
57
  return [clamp(firstIndex - buffer, minFirstIndex, maxLastIndex), clamp(lastIndex + buffer, minFirstIndex, maxLastIndex)];
58
58
  };
59
+
60
+ var areRenderContextsEqual = function areRenderContextsEqual(context1, context2) {
61
+ if (context1 === context2) {
62
+ return true;
63
+ }
64
+
65
+ return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
66
+ };
67
+
59
68
  export var useGridVirtualScroller = function useGridVirtualScroller(props) {
60
69
  var _currentPage$range3, _currentPage$range4;
61
70
 
@@ -241,6 +250,11 @@ export var useGridVirtualScroller = function useGridVirtualScroller(props) {
241
250
  }
242
251
  }, [apiRef, currentPage.rows, onRenderZonePositioning, renderZoneMinColumnIndex, renderZoneMaxColumnIndex, rootProps.columnBuffer, rootProps.rowBuffer]);
243
252
  var updateRenderContext = React.useCallback(function (nextRenderContext) {
253
+ if (prevRenderContext.current && areRenderContextsEqual(nextRenderContext, prevRenderContext.current)) {
254
+ updateRenderZonePosition(nextRenderContext);
255
+ return;
256
+ }
257
+
244
258
  setRenderContext(nextRenderContext);
245
259
  updateRenderZonePosition(nextRenderContext);
246
260
 
package/legacy/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /** @license MUI X v5.17.22
1
+ /** @license MUI X v5.17.24
2
2
  *
3
3
  * This source code is licensed under the MIT license found in the
4
4
  * LICENSE file in the root directory of this source tree.
@@ -27,17 +27,19 @@ function escapeOperandAttributeSelector(operand) {
27
27
  export function getGridColumnHeaderElement(root, field) {
28
28
  return root.querySelector("[role=\"columnheader\"][data-field=\"".concat(escapeOperandAttributeSelector(field), "\"]"));
29
29
  }
30
+
31
+ function getGridRowElementSelector(id) {
32
+ return ".".concat(gridClasses.row, "[data-id=\"").concat(escapeOperandAttributeSelector(String(id)), "\"]");
33
+ }
34
+
30
35
  export function getGridRowElement(root, id) {
31
- return root.querySelector(".".concat(gridClasses.row, "[data-id=\"").concat(escapeOperandAttributeSelector(String(id)), "\"]"));
36
+ return root.querySelector(getGridRowElementSelector(id));
32
37
  }
33
38
  export function getGridCellElement(root, _ref) {
34
39
  var id = _ref.id,
35
40
  field = _ref.field;
36
- var row = getGridRowElement(root, id);
37
-
38
- if (!row) {
39
- return null;
40
- }
41
-
42
- return row.querySelector(".".concat(gridClasses.cell, "[data-field=\"").concat(escapeOperandAttributeSelector(field), "\"]"));
41
+ var rowSelector = getGridRowElementSelector(id);
42
+ var cellSelector = ".".concat(gridClasses.cell, "[data-field=\"").concat(escapeOperandAttributeSelector(field), "\"]");
43
+ var selector = "".concat(rowSelector, " ").concat(cellSelector);
44
+ return root.querySelector(selector);
43
45
  }
@@ -35,6 +35,12 @@ export interface GridFilterOperator<R extends GridValidRowModel = any, V = any,
35
35
  * The props to pass to the input component in the filter panel for this filter operator.
36
36
  */
37
37
  InputComponentProps?: Record<string, any>;
38
+ /**
39
+ * Converts the value of a filter item to a human-readable form.
40
+ * @param {GridFilterItem['value']} value The filter item value.
41
+ * @returns {string} The value formatted to be displayed in the UI of filter button tooltip.
42
+ */
43
+ getValueAsString?: (value: GridFilterItem['value']) => string;
38
44
  /**
39
45
  * If `false`, filter operator doesn't require user-entered value to work.
40
46
  * Usually should be set to `false` for filter operators that don't have `InputComponent` (for example `isEmpty`)
@@ -220,6 +220,17 @@ process.env.NODE_ENV !== "production" ? GridColumnsPanel.propTypes = {
220
220
  // ----------------------------------------------------------------------
221
221
  autoFocusSearchField: PropTypes.bool,
222
222
  searchPredicate: PropTypes.func,
223
+ slotProps: PropTypes.shape({
224
+ TrapFocus: PropTypes.shape({
225
+ children: PropTypes.element.isRequired,
226
+ disableAutoFocus: PropTypes.bool,
227
+ disableEnforceFocus: PropTypes.bool,
228
+ disableRestoreFocus: PropTypes.bool,
229
+ getTabbable: PropTypes.func,
230
+ isEnabled: PropTypes.func,
231
+ open: PropTypes.bool.isRequired
232
+ })
233
+ }),
223
234
  sort: PropTypes.oneOf(['asc', 'desc'])
224
235
  } : void 0;
225
236
  export { GridColumnsPanel };
@@ -1,7 +1,8 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["className"];
3
+ const _excluded = ["className", "slotProps"];
4
4
  import * as React from 'react';
5
+ import PropTypes from 'prop-types';
5
6
  import clsx from 'clsx';
6
7
  import TrapFocus from '@mui/material/Unstable_TrapFocus';
7
8
  import { styled } from '@mui/material/styles';
@@ -37,7 +38,8 @@ const isEnabled = () => true;
37
38
 
38
39
  const GridPanelWrapper = /*#__PURE__*/React.forwardRef(function GridPanelWrapper(props, ref) {
39
40
  const {
40
- className
41
+ className,
42
+ slotProps = {}
41
43
  } = props,
42
44
  other = _objectWithoutPropertiesLoose(props, _excluded);
43
45
 
@@ -46,15 +48,33 @@ const GridPanelWrapper = /*#__PURE__*/React.forwardRef(function GridPanelWrapper
46
48
  classes: rootProps.classes
47
49
  };
48
50
  const classes = useUtilityClasses(ownerState);
49
- return /*#__PURE__*/_jsx(TrapFocus, {
51
+ return /*#__PURE__*/_jsx(TrapFocus, _extends({
50
52
  open: true,
51
53
  disableEnforceFocus: true,
52
- isEnabled: isEnabled,
54
+ isEnabled: isEnabled
55
+ }, slotProps.TrapFocus, {
53
56
  children: /*#__PURE__*/_jsx(GridPanelWrapperRoot, _extends({
54
57
  ref: ref,
55
58
  tabIndex: -1,
56
59
  className: clsx(className, classes.root)
57
60
  }, other))
58
- });
61
+ }));
59
62
  });
63
+ process.env.NODE_ENV !== "production" ? GridPanelWrapper.propTypes = {
64
+ // ----------------------------- Warning --------------------------------
65
+ // | These PropTypes are generated from the TypeScript type definitions |
66
+ // | To update them edit the TypeScript types and run "yarn proptypes" |
67
+ // ----------------------------------------------------------------------
68
+ slotProps: PropTypes.shape({
69
+ TrapFocus: PropTypes.shape({
70
+ children: PropTypes.element.isRequired,
71
+ disableAutoFocus: PropTypes.bool,
72
+ disableEnforceFocus: PropTypes.bool,
73
+ disableRestoreFocus: PropTypes.bool,
74
+ getTabbable: PropTypes.func,
75
+ isEnabled: PropTypes.func,
76
+ open: PropTypes.bool.isRequired
77
+ })
78
+ })
79
+ } : void 0;
60
80
  export { GridPanelWrapper };
@@ -65,13 +65,20 @@ const GridToolbarFilterButton = /*#__PURE__*/React.forwardRef(function GridToolb
65
65
 
66
66
  const getOperatorLabel = item => lookup[item.columnField].filterOperators.find(operator => operator.value === item.operatorValue).label || apiRef.current.getLocaleText(`filterOperator${capitalize(item.operatorValue)}`).toString();
67
67
 
68
+ const getFilterItemValue = item => {
69
+ const {
70
+ getValueAsString
71
+ } = lookup[item.columnField].filterOperators.find(operator => operator.value === item.operatorValue);
72
+ return getValueAsString ? getValueAsString(item.value) : item.value;
73
+ };
74
+
68
75
  return /*#__PURE__*/_jsxs("div", {
69
76
  children: [apiRef.current.getLocaleText('toolbarFiltersTooltipActive')(activeFilters.length), /*#__PURE__*/_jsx(GridToolbarFilterListRoot, {
70
77
  className: classes.root,
71
78
  children: activeFilters.map((item, index) => _extends({}, lookup[item.columnField] && /*#__PURE__*/_jsx("li", {
72
79
  children: `${lookup[item.columnField].headerName || item.columnField}
73
80
  ${getOperatorLabel(item)}
74
- ${item.value ?? ''}`
81
+ ${item.value ? getFilterItemValue(item) : ''}`
75
82
  }, index)))
76
83
  })]
77
84
  });
@@ -291,14 +291,19 @@ export const useGridRows = (apiRef, props) => {
291
291
  apiRef.current.unstable_caches.rows.idRowsLookup = updatedIdRowsLookup;
292
292
  apiRef.current.unstable_caches.rows.idToIdLookup = updatedIdToIdLookup;
293
293
  apiRef.current.unstable_caches.rows.ids = updatedRows;
294
- apiRef.current.setState(state => _extends({}, state, {
295
- rows: _extends({}, state.rows, {
294
+ apiRef.current.setState(state => {
295
+ const newRowsState = {
296
296
  idRowsLookup: updatedIdRowsLookup,
297
297
  idToIdLookup: updatedIdToIdLookup,
298
298
  tree: updatedTree,
299
299
  ids: updatedRows
300
- })
301
- }));
300
+ };
301
+ return _extends({}, state, {
302
+ rows: _extends({}, state.rows, newRowsState, {
303
+ groupingResponseBeforeRowHydration: _extends({}, state.rows.groupingResponseBeforeRowHydration, newRowsState)
304
+ })
305
+ });
306
+ });
302
307
  apiRef.current.publishEvent('rowsSet');
303
308
  }, [apiRef, props.signature, props.getRowId]);
304
309
  const rowApi = {
@@ -53,6 +53,15 @@ export const getRenderableIndexes = ({
53
53
  }) => {
54
54
  return [clamp(firstIndex - buffer, minFirstIndex, maxLastIndex), clamp(lastIndex + buffer, minFirstIndex, maxLastIndex)];
55
55
  };
56
+
57
+ const areRenderContextsEqual = (context1, context2) => {
58
+ if (context1 === context2) {
59
+ return true;
60
+ }
61
+
62
+ return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
63
+ };
64
+
56
65
  export const useGridVirtualScroller = props => {
57
66
  const apiRef = useGridApiContext();
58
67
  const rootProps = useGridRootProps();
@@ -214,6 +223,11 @@ export const useGridVirtualScroller = props => {
214
223
  }
215
224
  }, [apiRef, currentPage.rows, onRenderZonePositioning, renderZoneMinColumnIndex, renderZoneMaxColumnIndex, rootProps.columnBuffer, rootProps.rowBuffer]);
216
225
  const updateRenderContext = React.useCallback(nextRenderContext => {
226
+ if (prevRenderContext.current && areRenderContextsEqual(nextRenderContext, prevRenderContext.current)) {
227
+ updateRenderZonePosition(nextRenderContext);
228
+ return;
229
+ }
230
+
217
231
  setRenderContext(nextRenderContext);
218
232
  updateRenderZonePosition(nextRenderContext);
219
233
  const [firstRowToRender, lastRowToRender] = getRenderableIndexes({
package/modern/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /** @license MUI X v5.17.22
1
+ /** @license MUI X v5.17.24
2
2
  *
3
3
  * This source code is licensed under the MIT license found in the
4
4
  * LICENSE file in the root directory of this source tree.
@@ -27,18 +27,20 @@ function escapeOperandAttributeSelector(operand) {
27
27
  export function getGridColumnHeaderElement(root, field) {
28
28
  return root.querySelector(`[role="columnheader"][data-field="${escapeOperandAttributeSelector(field)}"]`);
29
29
  }
30
+
31
+ function getGridRowElementSelector(id) {
32
+ return `.${gridClasses.row}[data-id="${escapeOperandAttributeSelector(String(id))}"]`;
33
+ }
34
+
30
35
  export function getGridRowElement(root, id) {
31
- return root.querySelector(`.${gridClasses.row}[data-id="${escapeOperandAttributeSelector(String(id))}"]`);
36
+ return root.querySelector(getGridRowElementSelector(id));
32
37
  }
33
38
  export function getGridCellElement(root, {
34
39
  id,
35
40
  field
36
41
  }) {
37
- const row = getGridRowElement(root, id);
38
-
39
- if (!row) {
40
- return null;
41
- }
42
-
43
- return row.querySelector(`.${gridClasses.cell}[data-field="${escapeOperandAttributeSelector(field)}"]`);
42
+ const rowSelector = getGridRowElementSelector(id);
43
+ const cellSelector = `.${gridClasses.cell}[data-field="${escapeOperandAttributeSelector(field)}"]`;
44
+ const selector = `${rowSelector} ${cellSelector}`;
45
+ return root.querySelector(selector);
44
46
  }
@@ -255,5 +255,16 @@ process.env.NODE_ENV !== "production" ? GridColumnsPanel.propTypes = {
255
255
  // ----------------------------------------------------------------------
256
256
  autoFocusSearchField: _propTypes.default.bool,
257
257
  searchPredicate: _propTypes.default.func,
258
+ slotProps: _propTypes.default.shape({
259
+ TrapFocus: _propTypes.default.shape({
260
+ children: _propTypes.default.element.isRequired,
261
+ disableAutoFocus: _propTypes.default.bool,
262
+ disableEnforceFocus: _propTypes.default.bool,
263
+ disableRestoreFocus: _propTypes.default.bool,
264
+ getTabbable: _propTypes.default.func,
265
+ isEnabled: _propTypes.default.func,
266
+ open: _propTypes.default.bool.isRequired
267
+ })
268
+ }),
258
269
  sort: _propTypes.default.oneOf(['asc', 'desc'])
259
270
  } : void 0;
@@ -13,6 +13,8 @@ var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runt
13
13
 
14
14
  var React = _interopRequireWildcard(require("react"));
15
15
 
16
+ var _propTypes = _interopRequireDefault(require("prop-types"));
17
+
16
18
  var _clsx = _interopRequireDefault(require("clsx"));
17
19
 
18
20
  var _Unstable_TrapFocus = _interopRequireDefault(require("@mui/material/Unstable_TrapFocus"));
@@ -27,7 +29,7 @@ var _useGridRootProps = require("../../hooks/utils/useGridRootProps");
27
29
 
28
30
  var _jsxRuntime = require("react/jsx-runtime");
29
31
 
30
- const _excluded = ["className"];
32
+ const _excluded = ["className", "slotProps"];
31
33
 
32
34
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
33
35
 
@@ -60,7 +62,8 @@ const isEnabled = () => true;
60
62
 
61
63
  const GridPanelWrapper = /*#__PURE__*/React.forwardRef(function GridPanelWrapper(props, ref) {
62
64
  const {
63
- className
65
+ className,
66
+ slotProps = {}
64
67
  } = props,
65
68
  other = (0, _objectWithoutPropertiesLoose2.default)(props, _excluded);
66
69
  const rootProps = (0, _useGridRootProps.useGridRootProps)();
@@ -68,15 +71,33 @@ const GridPanelWrapper = /*#__PURE__*/React.forwardRef(function GridPanelWrapper
68
71
  classes: rootProps.classes
69
72
  };
70
73
  const classes = useUtilityClasses(ownerState);
71
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Unstable_TrapFocus.default, {
74
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Unstable_TrapFocus.default, (0, _extends2.default)({
72
75
  open: true,
73
76
  disableEnforceFocus: true,
74
- isEnabled: isEnabled,
77
+ isEnabled: isEnabled
78
+ }, slotProps.TrapFocus, {
75
79
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(GridPanelWrapperRoot, (0, _extends2.default)({
76
80
  ref: ref,
77
81
  tabIndex: -1,
78
82
  className: (0, _clsx.default)(className, classes.root)
79
83
  }, other))
80
- });
84
+ }));
81
85
  });
82
- exports.GridPanelWrapper = GridPanelWrapper;
86
+ exports.GridPanelWrapper = GridPanelWrapper;
87
+ process.env.NODE_ENV !== "production" ? GridPanelWrapper.propTypes = {
88
+ // ----------------------------- Warning --------------------------------
89
+ // | These PropTypes are generated from the TypeScript type definitions |
90
+ // | To update them edit the TypeScript types and run "yarn proptypes" |
91
+ // ----------------------------------------------------------------------
92
+ slotProps: _propTypes.default.shape({
93
+ TrapFocus: _propTypes.default.shape({
94
+ children: _propTypes.default.element.isRequired,
95
+ disableAutoFocus: _propTypes.default.bool,
96
+ disableEnforceFocus: _propTypes.default.bool,
97
+ disableRestoreFocus: _propTypes.default.bool,
98
+ getTabbable: _propTypes.default.func,
99
+ isEnabled: _propTypes.default.func,
100
+ open: _propTypes.default.bool.isRequired
101
+ })
102
+ })
103
+ } : void 0;
@@ -95,18 +95,21 @@ const GridToolbarFilterButton = /*#__PURE__*/React.forwardRef(function GridToolb
95
95
 
96
96
  const getOperatorLabel = item => lookup[item.columnField].filterOperators.find(operator => operator.value === item.operatorValue).label || apiRef.current.getLocaleText(`filterOperator${(0, _utils.capitalize)(item.operatorValue)}`).toString();
97
97
 
98
+ const getFilterItemValue = item => {
99
+ const {
100
+ getValueAsString
101
+ } = lookup[item.columnField].filterOperators.find(operator => operator.value === item.operatorValue);
102
+ return getValueAsString ? getValueAsString(item.value) : item.value;
103
+ };
104
+
98
105
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
99
106
  children: [apiRef.current.getLocaleText('toolbarFiltersTooltipActive')(activeFilters.length), /*#__PURE__*/(0, _jsxRuntime.jsx)(GridToolbarFilterListRoot, {
100
107
  className: classes.root,
101
- children: activeFilters.map((item, index) => {
102
- var _item$value;
103
-
104
- return (0, _extends2.default)({}, lookup[item.columnField] && /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
105
- children: `${lookup[item.columnField].headerName || item.columnField}
108
+ children: activeFilters.map((item, index) => (0, _extends2.default)({}, lookup[item.columnField] && /*#__PURE__*/(0, _jsxRuntime.jsx)("li", {
109
+ children: `${lookup[item.columnField].headerName || item.columnField}
106
110
  ${getOperatorLabel(item)}
107
- ${(_item$value = item.value) != null ? _item$value : ''}`
108
- }, index));
109
- })
111
+ ${item.value ? getFilterItemValue(item) : ''}`
112
+ }, index)))
110
113
  })]
111
114
  });
112
115
  }, [apiRef, preferencePanel.open, activeFilters, lookup, classes]);
@@ -321,14 +321,19 @@ const useGridRows = (apiRef, props) => {
321
321
  apiRef.current.unstable_caches.rows.idRowsLookup = updatedIdRowsLookup;
322
322
  apiRef.current.unstable_caches.rows.idToIdLookup = updatedIdToIdLookup;
323
323
  apiRef.current.unstable_caches.rows.ids = updatedRows;
324
- apiRef.current.setState(state => (0, _extends2.default)({}, state, {
325
- rows: (0, _extends2.default)({}, state.rows, {
324
+ apiRef.current.setState(state => {
325
+ const newRowsState = {
326
326
  idRowsLookup: updatedIdRowsLookup,
327
327
  idToIdLookup: updatedIdToIdLookup,
328
328
  tree: updatedTree,
329
329
  ids: updatedRows
330
- })
331
- }));
330
+ };
331
+ return (0, _extends2.default)({}, state, {
332
+ rows: (0, _extends2.default)({}, state.rows, newRowsState, {
333
+ groupingResponseBeforeRowHydration: (0, _extends2.default)({}, state.rows.groupingResponseBeforeRowHydration, newRowsState)
334
+ })
335
+ });
336
+ });
332
337
  apiRef.current.publishEvent('rowsSet');
333
338
  }, [apiRef, props.signature, props.getRowId]);
334
339
  const rowApi = {
@@ -90,6 +90,14 @@ const getRenderableIndexes = ({
90
90
 
91
91
  exports.getRenderableIndexes = getRenderableIndexes;
92
92
 
93
+ const areRenderContextsEqual = (context1, context2) => {
94
+ if (context1 === context2) {
95
+ return true;
96
+ }
97
+
98
+ return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
99
+ };
100
+
93
101
  const useGridVirtualScroller = props => {
94
102
  var _currentPage$range3, _currentPage$range4;
95
103
 
@@ -255,6 +263,11 @@ const useGridVirtualScroller = props => {
255
263
  }
256
264
  }, [apiRef, currentPage.rows, onRenderZonePositioning, renderZoneMinColumnIndex, renderZoneMaxColumnIndex, rootProps.columnBuffer, rootProps.rowBuffer]);
257
265
  const updateRenderContext = React.useCallback(nextRenderContext => {
266
+ if (prevRenderContext.current && areRenderContextsEqual(nextRenderContext, prevRenderContext.current)) {
267
+ updateRenderZonePosition(nextRenderContext);
268
+ return;
269
+ }
270
+
258
271
  setRenderContext(nextRenderContext);
259
272
  updateRenderZonePosition(nextRenderContext);
260
273
  const [firstRowToRender, lastRowToRender] = getRenderableIndexes({
package/node/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /** @license MUI X v5.17.22
1
+ /** @license MUI X v5.17.24
2
2
  *
3
3
  * This source code is licensed under the MIT license found in the
4
4
  * LICENSE file in the root directory of this source tree.
@@ -47,19 +47,20 @@ function getGridColumnHeaderElement(root, field) {
47
47
  return root.querySelector(`[role="columnheader"][data-field="${escapeOperandAttributeSelector(field)}"]`);
48
48
  }
49
49
 
50
+ function getGridRowElementSelector(id) {
51
+ return `.${_gridClasses.gridClasses.row}[data-id="${escapeOperandAttributeSelector(String(id))}"]`;
52
+ }
53
+
50
54
  function getGridRowElement(root, id) {
51
- return root.querySelector(`.${_gridClasses.gridClasses.row}[data-id="${escapeOperandAttributeSelector(String(id))}"]`);
55
+ return root.querySelector(getGridRowElementSelector(id));
52
56
  }
53
57
 
54
58
  function getGridCellElement(root, {
55
59
  id,
56
60
  field
57
61
  }) {
58
- const row = getGridRowElement(root, id);
59
-
60
- if (!row) {
61
- return null;
62
- }
63
-
64
- return row.querySelector(`.${_gridClasses.gridClasses.cell}[data-field="${escapeOperandAttributeSelector(field)}"]`);
62
+ const rowSelector = getGridRowElementSelector(id);
63
+ const cellSelector = `.${_gridClasses.gridClasses.cell}[data-field="${escapeOperandAttributeSelector(field)}"]`;
64
+ const selector = `${rowSelector} ${cellSelector}`;
65
+ return root.querySelector(selector);
65
66
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/x-data-grid",
3
- "version": "5.17.22",
3
+ "version": "5.17.24",
4
4
  "description": "The community edition of the data grid component (MUI X).",
5
5
  "author": "MUI Team",
6
6
  "main": "./node/index.js",
package/utils/domUtils.js CHANGED
@@ -27,18 +27,20 @@ function escapeOperandAttributeSelector(operand) {
27
27
  export function getGridColumnHeaderElement(root, field) {
28
28
  return root.querySelector(`[role="columnheader"][data-field="${escapeOperandAttributeSelector(field)}"]`);
29
29
  }
30
+
31
+ function getGridRowElementSelector(id) {
32
+ return `.${gridClasses.row}[data-id="${escapeOperandAttributeSelector(String(id))}"]`;
33
+ }
34
+
30
35
  export function getGridRowElement(root, id) {
31
- return root.querySelector(`.${gridClasses.row}[data-id="${escapeOperandAttributeSelector(String(id))}"]`);
36
+ return root.querySelector(getGridRowElementSelector(id));
32
37
  }
33
38
  export function getGridCellElement(root, {
34
39
  id,
35
40
  field
36
41
  }) {
37
- const row = getGridRowElement(root, id);
38
-
39
- if (!row) {
40
- return null;
41
- }
42
-
43
- return row.querySelector(`.${gridClasses.cell}[data-field="${escapeOperandAttributeSelector(field)}"]`);
42
+ const rowSelector = getGridRowElementSelector(id);
43
+ const cellSelector = `.${gridClasses.cell}[data-field="${escapeOperandAttributeSelector(field)}"]`;
44
+ const selector = `${rowSelector} ${cellSelector}`;
45
+ return root.querySelector(selector);
44
46
  }