@mui/x-data-grid-pro 8.3.1 → 8.4.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,116 @@
5
5
  All notable changes to this project will be documented in this file.
6
6
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
7
7
 
8
+ ## 8.4.0
9
+
10
+ _May 21, 2025_
11
+
12
+ We'd like to offer a big thanks to the 21 contributors who made this release possible. Here are some highlights ✨:
13
+
14
+ - 🔺 Support regular [`pyramid` variation in the `<FunnelChart />` component](https://mui.com/x/react-charts/funnel/#pyramid-chart):
15
+
16
+ <img width="398" alt="Pyramid funnel chart" src="https://github.com/user-attachments/assets/90ccb221-3a48-4ffa-8878-89c6db16da86" />
17
+
18
+ - 📚 Documentation improvements
19
+ - 🌎 Improve Icelandic (is-IS) locale on the Data Grid
20
+ - 🐞 Bugfixes
21
+
22
+ Special thanks go out to the community members for their valuable contributions:
23
+ @aizerin, @arminmeh, @campmarc, @jyash97, @mapache-salvaje, @noraleonte, @nusr, @ragnarr18, @romgrk, @whereisrmsqhs.
24
+ Following are all team members who have contributed to this release:
25
+ @alexfauquette, @bernardobelchior, @flaviendelangle, @JCQuintas, @KenanYusuf, @LukasTy, @MBilalShafi, @rita-codes.
26
+
27
+ <!--/ HIGHLIGHT_ABOVE_SEPARATOR /-->
28
+
29
+ ### Data Grid
30
+
31
+ #### `@mui/x-data-grid@8.4.0`
32
+
33
+ - [DataGrid] Fix content rendering for large rows while using automatic page size (#14737) @campmarc
34
+ - [DataGrid] Fix disabled typography variants crashing grid (#17934) @KenanYusuf
35
+ - [DataGrid] Fix tree data demo crash (#17904) @MBilalShafi
36
+ - [DataGrid] Use `exclude` selection model type if quick filter does not have actual values (#17899) @arminmeh
37
+ - [DataGrid] Fix clipboard copy behavior for cell ranges with empty cells (#16797) @nusr
38
+ - [l10n] Improve Icelandic (is-IS) locale (#17915) @ragnarr18
39
+
40
+ #### `@mui/x-data-grid-pro@8.4.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
41
+
42
+ Same changes as in `@mui/x-data-grid@8.4.0`, plus:
43
+
44
+ - [DataGridPro] Add `aria-expanded` attribute to the master detail toggle button (#17122) @whereisrmsqhs
45
+ - [DataGridPro] Preserve row state during server-side lazy loading (#17743) @arminmeh
46
+ - [DataGridPro] Prevent text selection when reordering rows (#16568) @jyash97
47
+
48
+ #### `@mui/x-data-grid-premium@8.4.0` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link 'Premium plan')
49
+
50
+ Same changes as in `@mui/x-data-grid-pro@8.4.0`.
51
+
52
+ ### Date and Time Pickers
53
+
54
+ #### `@mui/x-date-pickers@8.4.0`
55
+
56
+ - [fields] Ensure fresh `disabled` value is used when focusing or clicking (#17914) @aizerin
57
+ - [fields] Improve the field controlled edition (#17816) @flaviendelangle
58
+ - [pickers] Fix `PickersTextField` overflow (#17942) @noraleonte
59
+
60
+ #### `@mui/x-date-pickers-pro@8.4.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
61
+
62
+ Same changes as in `@mui/x-date-pickers@8.4.0`.
63
+
64
+ ### Charts
65
+
66
+ #### `@mui/x-charts@8.4.0`
67
+
68
+ - [charts] Add grouped axes demo (#17848) @bernardobelchior
69
+ - [charts] Enable tooltip disable portal (#17871) @alexfauquette
70
+ - [charts] Improve performance in scatter chart (#17849) @bernardobelchior
71
+ - [charts] Recreate `isPointInside` less often (#17850) @bernardobelchior
72
+ - [charts] Try fix for flaky `useAnimate` test (#17777) @JCQuintas
73
+ - [charts] Add `isXInside` and `isYInside` (#17911) @bernardobelchior
74
+
75
+ #### `@mui/x-charts-pro@8.4.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
76
+
77
+ Same changes as in `@mui/x-charts@8.4.0`, plus:
78
+
79
+ - [charts-pro] Add size for zoom slider (#17736) @bernardobelchior
80
+ - [charts-pro] Add zoom slider tooltip (#17733) @bernardobelchior
81
+ - [charts-pro] Clean and document Heatmap Tooltip (#17933) @alexfauquette
82
+ - [charts-pro] Introduce `Pyramid` chart (#17783) @JCQuintas
83
+ - [charts-pro] Update zoom slider nomenclature (#17938) @bernardobelchior
84
+ - [charts-pro] Fix error when importing rasterizehtml (#17897) @bernardobelchior
85
+
86
+ ### Tree View
87
+
88
+ #### `@mui/x-tree-view@8.4.0`
89
+
90
+ - [TreeView] Add `getItemChildren` prop in `RichTreeView` (#17894) @rita-codes
91
+ - [TreeView] Add a method in the `apiRef` to toggle the editing status of an item (#17768) @rita-codes
92
+ - [TreeView] Add missing sx prop on the Tree Item component (#17930) @flaviendelangle
93
+
94
+ #### `@mui/x-tree-view-pro@8.4.0` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link 'Pro plan')
95
+
96
+ Same changes as in `@mui/x-tree-view@8.4.0`.
97
+
98
+ ### Docs
99
+
100
+ - [docs] Add a recipe for drag and drop row grouping (#17638) @KenanYusuf
101
+ - [docs] Add introductory text to Data Grid component pages (#17902) @KenanYusuf
102
+ - [docs] Refactor embedded CodeSandbox on Data Grid—Quickstart page (#17749) @rita-codes
103
+ - [docs] Remove double border on Data Grid—Quickstart demo (#17932) @rita-codes
104
+ - [docs] Standardize `apiRef` copy (#17776) @mapache-salvaje
105
+ - [docs][DataGrid] Revise server-side data docs (#17007) @mapache-salvaje
106
+ - [docs][DataGrid] Audit and revise the tree data doc (#17650) @mapache-salvaje
107
+ - [docs][pickers] Fix migration guide references to range fields (#17861) @LukasTy
108
+ - [docs][charts] Reorganize the Tooltip documentation (#17917) @alexfauquette
109
+
110
+ ### Core
111
+
112
+ - [core] refactor: remove manual `displayName` (#17845) @romgrk
113
+ - [code-infra] Document how to use `vitest` cli (#17847) @JCQuintas
114
+ - [code-infra] Increase charts export test timeout (#17909) @JCQuintas
115
+ - [code-infra] Set `isolatedModules=true` in tsconfig (#17781) @JCQuintas
116
+ - [infra] Ensure proper docs preview path resolution (#17863) @LukasTy
117
+
8
118
  ## 8.3.1
9
119
 
10
120
  _May 14, 2025_
@@ -29,7 +29,7 @@ const configuration = {
29
29
  useCellAggregationResult: () => null
30
30
  }
31
31
  };
32
- const releaseInfo = "MTc0NzE3MzYwMDAwMA==";
32
+ const releaseInfo = "MTc0Nzc3ODQwMDAwMA==";
33
33
  const watermark = /*#__PURE__*/(0, _jsxRuntime.jsx)(_xLicense.Watermark, {
34
34
  packageName: "x-data-grid-pro",
35
35
  releaseInfo: releaseInfo
@@ -64,6 +64,7 @@ const DataGridProRaw = (0, _forwardRef.forwardRef)(function DataGridPro(inProps,
64
64
  * - [DataGridPro API](https://mui.com/x/api/data-grid/data-grid-pro/)
65
65
  */
66
66
  const DataGridPro = exports.DataGridPro = /*#__PURE__*/React.memo(DataGridProRaw);
67
+ if (process.env.NODE_ENV !== "production") DataGridPro.displayName = "DataGridPro";
67
68
  DataGridProRaw.propTypes = {
68
69
  // ----------------------------- Warning --------------------------------
69
70
  // | These PropTypes are generated from the TypeScript type definitions |
@@ -54,6 +54,7 @@ function GridDetailPanelToggleCell(props) {
54
54
  tabIndex: -1,
55
55
  disabled: !hasContent,
56
56
  className: classes.root,
57
+ "aria-expanded": isExpanded,
57
58
  "aria-label": isExpanded ? apiRef.current.getLocaleText('collapseDetailPanel') : apiRef.current.getLocaleText('expandDetailPanel')
58
59
  }, rootProps.slotProps?.baseIconButton, {
59
60
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(Icon, {
@@ -57,10 +57,23 @@ function GridRowReorderCell(params) {
57
57
  propHandler(event);
58
58
  }
59
59
  }, [apiRef, params.id]);
60
+ const handleMouseDown = React.useCallback(() => {
61
+ // Prevent text selection as it will block all the drag events. More context: https://github.com/mui/mui-x/issues/16303
62
+ apiRef.current.rootElementRef?.current?.classList.add(_xDataGrid.gridClasses['root--disableUserSelection']);
63
+ }, [apiRef]);
64
+ const handleMouseUp = React.useCallback(() => {
65
+ apiRef.current.rootElementRef?.current?.classList.remove(_xDataGrid.gridClasses['root--disableUserSelection']);
66
+ }, [apiRef]);
67
+ const handleDragEnd = React.useCallback(event => {
68
+ handleMouseUp();
69
+ publish('rowDragEnd')(event);
70
+ }, [publish, handleMouseUp]);
60
71
  const draggableEventHandlers = isDraggable ? {
61
72
  onDragStart: publish('rowDragStart'),
62
73
  onDragOver: publish('rowDragOver'),
63
- onDragEnd: publish('rowDragEnd')
74
+ onDragEnd: handleDragEnd,
75
+ onMouseDown: handleMouseDown,
76
+ onMouseUp: handleMouseUp
64
77
  } : null;
65
78
  if (params.rowNode.type === 'footer') {
66
79
  return null;
@@ -146,4 +159,5 @@ const renderRowReorderCell = params => {
146
159
  }
147
160
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridRowReorderCell, (0, _extends2.default)({}, params));
148
161
  };
149
- exports.renderRowReorderCell = renderRowReorderCell;
162
+ exports.renderRowReorderCell = renderRowReorderCell;
163
+ if (process.env.NODE_ENV !== "production") renderRowReorderCell.displayName = "renderRowReorderCell";
@@ -22,7 +22,7 @@ const configuration = {
22
22
  useCellAggregationResult: () => null
23
23
  }
24
24
  };
25
- const releaseInfo = "MTc0NzE3MzYwMDAwMA==";
25
+ const releaseInfo = "MTc0Nzc3ODQwMDAwMA==";
26
26
  const watermark = /*#__PURE__*/_jsx(Watermark, {
27
27
  packageName: "x-data-grid-pro",
28
28
  releaseInfo: releaseInfo
@@ -57,6 +57,7 @@ const DataGridProRaw = forwardRef(function DataGridPro(inProps, ref) {
57
57
  * - [DataGridPro API](https://mui.com/x/api/data-grid/data-grid-pro/)
58
58
  */
59
59
  export const DataGridPro = /*#__PURE__*/React.memo(DataGridProRaw);
60
+ if (process.env.NODE_ENV !== "production") DataGridPro.displayName = "DataGridPro";
60
61
  DataGridProRaw.propTypes = {
61
62
  // ----------------------------- Warning --------------------------------
62
63
  // | These PropTypes are generated from the TypeScript type definitions |
@@ -46,6 +46,7 @@ function GridDetailPanelToggleCell(props) {
46
46
  tabIndex: -1,
47
47
  disabled: !hasContent,
48
48
  className: classes.root,
49
+ "aria-expanded": isExpanded,
49
50
  "aria-label": isExpanded ? apiRef.current.getLocaleText('collapseDetailPanel') : apiRef.current.getLocaleText('expandDetailPanel')
50
51
  }, rootProps.slotProps?.baseIconButton, {
51
52
  children: /*#__PURE__*/_jsx(Icon, {
@@ -2,7 +2,7 @@ import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import * as React from 'react';
3
3
  import PropTypes from 'prop-types';
4
4
  import composeClasses from '@mui/utils/composeClasses';
5
- import { gridRowMaximumTreeDepthSelector, gridSortModelSelector, useGridApiContext, useGridSelector, getDataGridUtilityClass } from '@mui/x-data-grid';
5
+ import { gridRowMaximumTreeDepthSelector, gridSortModelSelector, useGridApiContext, useGridSelector, getDataGridUtilityClass, gridClasses } from '@mui/x-data-grid';
6
6
  import { gridEditRowsStateSelector, isEventTargetInPortal } from '@mui/x-data-grid/internals';
7
7
  import { useGridRootProps } from "../hooks/utils/useGridRootProps.js";
8
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
@@ -48,10 +48,23 @@ function GridRowReorderCell(params) {
48
48
  propHandler(event);
49
49
  }
50
50
  }, [apiRef, params.id]);
51
+ const handleMouseDown = React.useCallback(() => {
52
+ // Prevent text selection as it will block all the drag events. More context: https://github.com/mui/mui-x/issues/16303
53
+ apiRef.current.rootElementRef?.current?.classList.add(gridClasses['root--disableUserSelection']);
54
+ }, [apiRef]);
55
+ const handleMouseUp = React.useCallback(() => {
56
+ apiRef.current.rootElementRef?.current?.classList.remove(gridClasses['root--disableUserSelection']);
57
+ }, [apiRef]);
58
+ const handleDragEnd = React.useCallback(event => {
59
+ handleMouseUp();
60
+ publish('rowDragEnd')(event);
61
+ }, [publish, handleMouseUp]);
51
62
  const draggableEventHandlers = isDraggable ? {
52
63
  onDragStart: publish('rowDragStart'),
53
64
  onDragOver: publish('rowDragOver'),
54
- onDragEnd: publish('rowDragEnd')
65
+ onDragEnd: handleDragEnd,
66
+ onMouseDown: handleMouseDown,
67
+ onMouseUp: handleMouseUp
55
68
  } : null;
56
69
  if (params.rowNode.type === 'footer') {
57
70
  return null;
@@ -137,4 +150,5 @@ export const renderRowReorderCell = params => {
137
150
  return null;
138
151
  }
139
152
  return /*#__PURE__*/_jsx(GridRowReorderCell, _extends({}, params));
140
- };
153
+ };
154
+ if (process.env.NODE_ENV !== "production") renderRowReorderCell.displayName = "renderRowReorderCell";
@@ -137,6 +137,7 @@ export const useGridColumnHeaders = props => {
137
137
  })]
138
138
  });
139
139
  };
140
+ if (process.env.NODE_ENV !== "production") getColumnFiltersRow.displayName = "getColumnFiltersRow";
140
141
  return _extends({}, otherProps, {
141
142
  getColumnFiltersRow
142
143
  });
@@ -48,6 +48,44 @@ export const useGridColumnReorder = (apiRef, props) => {
48
48
  clearTimeout(removeDnDStylesTimeout.current);
49
49
  };
50
50
  }, []);
51
+ const handleDragEnd = React.useCallback((params, event) => {
52
+ const dragColField = gridColumnReorderDragColSelector(apiRef);
53
+ if (props.disableColumnReorder || !dragColField) {
54
+ return;
55
+ }
56
+ logger.debug('End dragging col');
57
+ event.preventDefault();
58
+ // Prevent drag events propagation.
59
+ // For more information check here https://github.com/mui/mui-x/issues/2680.
60
+ event.stopPropagation();
61
+ clearTimeout(removeDnDStylesTimeout.current);
62
+
63
+ // For more information check here https://github.com/mui/mui-x/issues/14678
64
+ if (dragColNode.current.classList.contains(classes.columnHeaderDragging)) {
65
+ dragColNode.current.classList.remove(classes.columnHeaderDragging);
66
+ }
67
+ dragColNode.current = null;
68
+
69
+ // Check if the column was dropped outside the grid.
70
+ if (event.dataTransfer.dropEffect === 'none' && !props.keepColumnPositionIfDraggedOutside) {
71
+ // Accessing params.field may contain the wrong field as header elements are reused
72
+ apiRef.current.setColumnIndex(dragColField, originColumnIndex.current);
73
+ originColumnIndex.current = null;
74
+ } else {
75
+ // Emit the columnOrderChange event only once when the reordering stops.
76
+ const columnOrderChangeParams = {
77
+ column: apiRef.current.getColumn(dragColField),
78
+ targetIndex: apiRef.current.getColumnIndexRelativeToVisibleColumns(dragColField),
79
+ oldIndex: originColumnIndex.current
80
+ };
81
+ apiRef.current.publishEvent('columnOrderChange', columnOrderChangeParams);
82
+ }
83
+ apiRef.current.setState(state => _extends({}, state, {
84
+ columnReorder: _extends({}, state.columnReorder, {
85
+ dragCol: ''
86
+ })
87
+ }));
88
+ }, [apiRef, props.disableColumnReorder, props.keepColumnPositionIfDraggedOutside, logger, classes.columnHeaderDragging]);
51
89
  const handleDragStart = React.useCallback((params, event) => {
52
90
  if (props.disableColumnReorder || params.colDef.disableReorder) {
53
91
  return;
@@ -58,6 +96,11 @@ export const useGridColumnReorder = (apiRef, props) => {
58
96
  event.stopPropagation();
59
97
  dragColNode.current = event.currentTarget;
60
98
  dragColNode.current.classList.add(classes.columnHeaderDragging);
99
+ const handleDragEndEvent = dragEndEvent => {
100
+ dragColNode.current.removeEventListener('dragend', handleDragEndEvent);
101
+ apiRef.current.publishEvent('columnHeaderDragEndNative', params, dragEndEvent);
102
+ };
103
+ dragColNode.current.addEventListener('dragend', handleDragEndEvent);
61
104
  if (event.dataTransfer) {
62
105
  event.dataTransfer.effectAllowed = 'move';
63
106
  }
@@ -194,48 +237,10 @@ export const useGridColumnReorder = (apiRef, props) => {
194
237
  cursorPosition.current = coordinates;
195
238
  }
196
239
  }, [apiRef, logger, isRtl]);
197
- const handleDragEnd = React.useCallback((params, event) => {
198
- const dragColField = gridColumnReorderDragColSelector(apiRef);
199
- if (props.disableColumnReorder || !dragColField) {
200
- return;
201
- }
202
- logger.debug('End dragging col');
203
- event.preventDefault();
204
- // Prevent drag events propagation.
205
- // For more information check here https://github.com/mui/mui-x/issues/2680.
206
- event.stopPropagation();
207
- clearTimeout(removeDnDStylesTimeout.current);
208
-
209
- // For more information check here https://github.com/mui/mui-x/issues/14678
210
- if (dragColNode.current.classList.contains(classes.columnHeaderDragging)) {
211
- dragColNode.current.classList.remove(classes.columnHeaderDragging);
212
- }
213
- dragColNode.current = null;
214
-
215
- // Check if the column was dropped outside the grid.
216
- if (event.dataTransfer.dropEffect === 'none' && !props.keepColumnPositionIfDraggedOutside) {
217
- // Accessing params.field may contain the wrong field as header elements are reused
218
- apiRef.current.setColumnIndex(dragColField, originColumnIndex.current);
219
- originColumnIndex.current = null;
220
- } else {
221
- // Emit the columnOrderChange event only once when the reordering stops.
222
- const columnOrderChangeParams = {
223
- column: apiRef.current.getColumn(dragColField),
224
- targetIndex: apiRef.current.getColumnIndexRelativeToVisibleColumns(dragColField),
225
- oldIndex: originColumnIndex.current
226
- };
227
- apiRef.current.publishEvent('columnOrderChange', columnOrderChangeParams);
228
- }
229
- apiRef.current.setState(state => _extends({}, state, {
230
- columnReorder: _extends({}, state.columnReorder, {
231
- dragCol: ''
232
- })
233
- }));
234
- }, [apiRef, props.disableColumnReorder, props.keepColumnPositionIfDraggedOutside, logger, classes.columnHeaderDragging]);
235
240
  useGridEvent(apiRef, 'columnHeaderDragStart', handleDragStart);
236
241
  useGridEvent(apiRef, 'columnHeaderDragEnter', handleDragEnter);
237
242
  useGridEvent(apiRef, 'columnHeaderDragOver', handleDragOver);
238
- useGridEvent(apiRef, 'columnHeaderDragEnd', handleDragEnd);
243
+ useGridEvent(apiRef, 'columnHeaderDragEndNative', handleDragEnd);
239
244
  useGridEvent(apiRef, 'cellDragEnter', handleDragEnter);
240
245
  useGridEvent(apiRef, 'cellDragOver', handleDragOver);
241
246
  useGridEventPriority(apiRef, 'columnOrderChange', props.onColumnOrderChange);
@@ -32,6 +32,7 @@ export const useGridDataSourceLazyLoader = (privateApiRef, props) => {
32
32
  const previousLastRowIndex = React.useRef(0);
33
33
  const loadingTrigger = React.useRef(null);
34
34
  const rowsStale = React.useRef(false);
35
+ const draggedRowId = React.useRef(null);
35
36
  const fetchRows = React.useCallback(params => {
36
37
  privateApiRef.current.dataSource.fetchRows(GRID_ROOT_GROUP_ID, params);
37
38
  }, [privateApiRef]);
@@ -87,7 +88,6 @@ export const useGridDataSourceLazyLoader = (privateApiRef, props) => {
87
88
  }, [privateApiRef, resetGrid]);
88
89
  const addSkeletonRows = React.useCallback(() => {
89
90
  const tree = privateApiRef.current.state.rows.tree;
90
- const dataRowIdToModelLookup = privateApiRef.current.state.rows.dataRowIdToModelLookup;
91
91
  const rootGroup = tree[GRID_ROOT_GROUP_ID];
92
92
  const rootGroupChildren = [...rootGroup.children];
93
93
  const pageRowCount = privateApiRef.current.state.pagination.rowCount;
@@ -111,21 +111,20 @@ export const useGridDataSourceLazyLoader = (privateApiRef, props) => {
111
111
  break;
112
112
  }
113
113
  // replace the rows not in the viewport with skeleton rows
114
- if (pageToSkip.start <= i && i <= pageToSkip.end || tree[rootGroupChildren[i]]?.type === 'skeletonRow') {
114
+ if (pageToSkip.start <= i && i <= pageToSkip.end || tree[rootGroupChildren[i]]?.type === 'skeletonRow' ||
115
+ // ignore rows that are already skeleton rows
116
+ tree[rootGroupChildren[i]]?.id === draggedRowId.current // ignore row that is being dragged (https://github.com/mui/mui-x/issues/17854)
117
+ ) {
115
118
  continue;
116
119
  }
117
- const skeletonId = getSkeletonRowId(i); // to avoid duplicate keys on rebuild
118
- const removedRow = rootGroupChildren[i];
119
- rootGroupChildren[i] = skeletonId;
120
+ const rowId = tree[rootGroupChildren[i]].id; // keep the id, so that row related state is maintained
120
121
  const skeletonRowNode = {
121
122
  type: 'skeletonRow',
122
- id: skeletonId,
123
+ id: rowId,
123
124
  parent: GRID_ROOT_GROUP_ID,
124
125
  depth: 0
125
126
  };
126
- tree[skeletonId] = skeletonRowNode;
127
- delete tree[removedRow];
128
- delete dataRowIdToModelLookup[removedRow];
127
+ tree[rowId] = skeletonRowNode;
129
128
  hasChanged = true;
130
129
  }
131
130
 
@@ -153,8 +152,7 @@ export const useGridDataSourceLazyLoader = (privateApiRef, props) => {
153
152
  });
154
153
  privateApiRef.current.setState(state => _extends({}, state, {
155
154
  rows: _extends({}, state.rows, {
156
- tree,
157
- dataRowIdToModelLookup
155
+ tree
158
156
  })
159
157
  }), 'addSkeletonRows');
160
158
  }, [privateApiRef, adjustRowParams]);
@@ -341,6 +339,12 @@ export const useGridDataSourceLazyLoader = (privateApiRef, props) => {
341
339
  privateApiRef.current.setLoading(true);
342
340
  debouncedFetchRows(getRowsParams);
343
341
  }, [privateApiRef, debouncedFetchRows, throttledHandleRenderedRowsIntervalChange]);
342
+ const handleDragStart = React.useCallback(row => {
343
+ draggedRowId.current = row.id;
344
+ }, []);
345
+ const handleDragEnd = React.useCallback(() => {
346
+ draggedRowId.current = null;
347
+ }, []);
344
348
  const handleStrategyActivityChange = React.useCallback(() => {
345
349
  setLazyLoadingRowsUpdateStrategyActive(privateApiRef.current.getActiveStrategy(GridStrategyGroup.DataSource) === DataSourceRowsUpdateStrategy.LazyLoading);
346
350
  }, [privateApiRef]);
@@ -351,6 +355,8 @@ export const useGridDataSourceLazyLoader = (privateApiRef, props) => {
351
355
  useGridEvent(privateApiRef, 'renderedRowsIntervalChange', runIf(lazyLoadingRowsUpdateStrategyActive, throttledHandleRenderedRowsIntervalChange));
352
356
  useGridEvent(privateApiRef, 'sortModelChange', runIf(lazyLoadingRowsUpdateStrategyActive, handleGridSortModelChange));
353
357
  useGridEvent(privateApiRef, 'filterModelChange', runIf(lazyLoadingRowsUpdateStrategyActive, handleGridFilterModelChange));
358
+ useGridEvent(privateApiRef, 'rowDragStart', runIf(lazyLoadingRowsUpdateStrategyActive, handleDragStart));
359
+ useGridEvent(privateApiRef, 'rowDragEnd', runIf(lazyLoadingRowsUpdateStrategyActive, handleDragEnd));
354
360
  React.useEffect(() => {
355
361
  setStrategyAvailability();
356
362
  }, [setStrategyAvailability]);
package/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid-pro v8.3.1
2
+ * @mui/x-data-grid-pro v8.4.0
3
3
  *
4
4
  * @license MUI X Commercial
5
5
  * This source code is licensed under the commercial license found in the
@@ -145,6 +145,7 @@ const useGridColumnHeaders = props => {
145
145
  })]
146
146
  });
147
147
  };
148
+ if (process.env.NODE_ENV !== "production") getColumnFiltersRow.displayName = "getColumnFiltersRow";
148
149
  return (0, _extends2.default)({}, otherProps, {
149
150
  getColumnFiltersRow
150
151
  });
@@ -57,6 +57,44 @@ const useGridColumnReorder = (apiRef, props) => {
57
57
  clearTimeout(removeDnDStylesTimeout.current);
58
58
  };
59
59
  }, []);
60
+ const handleDragEnd = React.useCallback((params, event) => {
61
+ const dragColField = (0, _columnReorderSelector.gridColumnReorderDragColSelector)(apiRef);
62
+ if (props.disableColumnReorder || !dragColField) {
63
+ return;
64
+ }
65
+ logger.debug('End dragging col');
66
+ event.preventDefault();
67
+ // Prevent drag events propagation.
68
+ // For more information check here https://github.com/mui/mui-x/issues/2680.
69
+ event.stopPropagation();
70
+ clearTimeout(removeDnDStylesTimeout.current);
71
+
72
+ // For more information check here https://github.com/mui/mui-x/issues/14678
73
+ if (dragColNode.current.classList.contains(classes.columnHeaderDragging)) {
74
+ dragColNode.current.classList.remove(classes.columnHeaderDragging);
75
+ }
76
+ dragColNode.current = null;
77
+
78
+ // Check if the column was dropped outside the grid.
79
+ if (event.dataTransfer.dropEffect === 'none' && !props.keepColumnPositionIfDraggedOutside) {
80
+ // Accessing params.field may contain the wrong field as header elements are reused
81
+ apiRef.current.setColumnIndex(dragColField, originColumnIndex.current);
82
+ originColumnIndex.current = null;
83
+ } else {
84
+ // Emit the columnOrderChange event only once when the reordering stops.
85
+ const columnOrderChangeParams = {
86
+ column: apiRef.current.getColumn(dragColField),
87
+ targetIndex: apiRef.current.getColumnIndexRelativeToVisibleColumns(dragColField),
88
+ oldIndex: originColumnIndex.current
89
+ };
90
+ apiRef.current.publishEvent('columnOrderChange', columnOrderChangeParams);
91
+ }
92
+ apiRef.current.setState(state => (0, _extends2.default)({}, state, {
93
+ columnReorder: (0, _extends2.default)({}, state.columnReorder, {
94
+ dragCol: ''
95
+ })
96
+ }));
97
+ }, [apiRef, props.disableColumnReorder, props.keepColumnPositionIfDraggedOutside, logger, classes.columnHeaderDragging]);
60
98
  const handleDragStart = React.useCallback((params, event) => {
61
99
  if (props.disableColumnReorder || params.colDef.disableReorder) {
62
100
  return;
@@ -67,6 +105,11 @@ const useGridColumnReorder = (apiRef, props) => {
67
105
  event.stopPropagation();
68
106
  dragColNode.current = event.currentTarget;
69
107
  dragColNode.current.classList.add(classes.columnHeaderDragging);
108
+ const handleDragEndEvent = dragEndEvent => {
109
+ dragColNode.current.removeEventListener('dragend', handleDragEndEvent);
110
+ apiRef.current.publishEvent('columnHeaderDragEndNative', params, dragEndEvent);
111
+ };
112
+ dragColNode.current.addEventListener('dragend', handleDragEndEvent);
70
113
  if (event.dataTransfer) {
71
114
  event.dataTransfer.effectAllowed = 'move';
72
115
  }
@@ -203,48 +246,10 @@ const useGridColumnReorder = (apiRef, props) => {
203
246
  cursorPosition.current = coordinates;
204
247
  }
205
248
  }, [apiRef, logger, isRtl]);
206
- const handleDragEnd = React.useCallback((params, event) => {
207
- const dragColField = (0, _columnReorderSelector.gridColumnReorderDragColSelector)(apiRef);
208
- if (props.disableColumnReorder || !dragColField) {
209
- return;
210
- }
211
- logger.debug('End dragging col');
212
- event.preventDefault();
213
- // Prevent drag events propagation.
214
- // For more information check here https://github.com/mui/mui-x/issues/2680.
215
- event.stopPropagation();
216
- clearTimeout(removeDnDStylesTimeout.current);
217
-
218
- // For more information check here https://github.com/mui/mui-x/issues/14678
219
- if (dragColNode.current.classList.contains(classes.columnHeaderDragging)) {
220
- dragColNode.current.classList.remove(classes.columnHeaderDragging);
221
- }
222
- dragColNode.current = null;
223
-
224
- // Check if the column was dropped outside the grid.
225
- if (event.dataTransfer.dropEffect === 'none' && !props.keepColumnPositionIfDraggedOutside) {
226
- // Accessing params.field may contain the wrong field as header elements are reused
227
- apiRef.current.setColumnIndex(dragColField, originColumnIndex.current);
228
- originColumnIndex.current = null;
229
- } else {
230
- // Emit the columnOrderChange event only once when the reordering stops.
231
- const columnOrderChangeParams = {
232
- column: apiRef.current.getColumn(dragColField),
233
- targetIndex: apiRef.current.getColumnIndexRelativeToVisibleColumns(dragColField),
234
- oldIndex: originColumnIndex.current
235
- };
236
- apiRef.current.publishEvent('columnOrderChange', columnOrderChangeParams);
237
- }
238
- apiRef.current.setState(state => (0, _extends2.default)({}, state, {
239
- columnReorder: (0, _extends2.default)({}, state.columnReorder, {
240
- dragCol: ''
241
- })
242
- }));
243
- }, [apiRef, props.disableColumnReorder, props.keepColumnPositionIfDraggedOutside, logger, classes.columnHeaderDragging]);
244
249
  (0, _xDataGrid.useGridEvent)(apiRef, 'columnHeaderDragStart', handleDragStart);
245
250
  (0, _xDataGrid.useGridEvent)(apiRef, 'columnHeaderDragEnter', handleDragEnter);
246
251
  (0, _xDataGrid.useGridEvent)(apiRef, 'columnHeaderDragOver', handleDragOver);
247
- (0, _xDataGrid.useGridEvent)(apiRef, 'columnHeaderDragEnd', handleDragEnd);
252
+ (0, _xDataGrid.useGridEvent)(apiRef, 'columnHeaderDragEndNative', handleDragEnd);
248
253
  (0, _xDataGrid.useGridEvent)(apiRef, 'cellDragEnter', handleDragEnter);
249
254
  (0, _xDataGrid.useGridEvent)(apiRef, 'cellDragOver', handleDragOver);
250
255
  (0, _xDataGrid.useGridEventPriority)(apiRef, 'columnOrderChange', props.onColumnOrderChange);
@@ -40,6 +40,7 @@ const useGridDataSourceLazyLoader = (privateApiRef, props) => {
40
40
  const previousLastRowIndex = React.useRef(0);
41
41
  const loadingTrigger = React.useRef(null);
42
42
  const rowsStale = React.useRef(false);
43
+ const draggedRowId = React.useRef(null);
43
44
  const fetchRows = React.useCallback(params => {
44
45
  privateApiRef.current.dataSource.fetchRows(_xDataGrid.GRID_ROOT_GROUP_ID, params);
45
46
  }, [privateApiRef]);
@@ -95,7 +96,6 @@ const useGridDataSourceLazyLoader = (privateApiRef, props) => {
95
96
  }, [privateApiRef, resetGrid]);
96
97
  const addSkeletonRows = React.useCallback(() => {
97
98
  const tree = privateApiRef.current.state.rows.tree;
98
- const dataRowIdToModelLookup = privateApiRef.current.state.rows.dataRowIdToModelLookup;
99
99
  const rootGroup = tree[_xDataGrid.GRID_ROOT_GROUP_ID];
100
100
  const rootGroupChildren = [...rootGroup.children];
101
101
  const pageRowCount = privateApiRef.current.state.pagination.rowCount;
@@ -119,21 +119,20 @@ const useGridDataSourceLazyLoader = (privateApiRef, props) => {
119
119
  break;
120
120
  }
121
121
  // replace the rows not in the viewport with skeleton rows
122
- if (pageToSkip.start <= i && i <= pageToSkip.end || tree[rootGroupChildren[i]]?.type === 'skeletonRow') {
122
+ if (pageToSkip.start <= i && i <= pageToSkip.end || tree[rootGroupChildren[i]]?.type === 'skeletonRow' ||
123
+ // ignore rows that are already skeleton rows
124
+ tree[rootGroupChildren[i]]?.id === draggedRowId.current // ignore row that is being dragged (https://github.com/mui/mui-x/issues/17854)
125
+ ) {
123
126
  continue;
124
127
  }
125
- const skeletonId = getSkeletonRowId(i); // to avoid duplicate keys on rebuild
126
- const removedRow = rootGroupChildren[i];
127
- rootGroupChildren[i] = skeletonId;
128
+ const rowId = tree[rootGroupChildren[i]].id; // keep the id, so that row related state is maintained
128
129
  const skeletonRowNode = {
129
130
  type: 'skeletonRow',
130
- id: skeletonId,
131
+ id: rowId,
131
132
  parent: _xDataGrid.GRID_ROOT_GROUP_ID,
132
133
  depth: 0
133
134
  };
134
- tree[skeletonId] = skeletonRowNode;
135
- delete tree[removedRow];
136
- delete dataRowIdToModelLookup[removedRow];
135
+ tree[rowId] = skeletonRowNode;
137
136
  hasChanged = true;
138
137
  }
139
138
 
@@ -161,8 +160,7 @@ const useGridDataSourceLazyLoader = (privateApiRef, props) => {
161
160
  });
162
161
  privateApiRef.current.setState(state => (0, _extends2.default)({}, state, {
163
162
  rows: (0, _extends2.default)({}, state.rows, {
164
- tree,
165
- dataRowIdToModelLookup
163
+ tree
166
164
  })
167
165
  }), 'addSkeletonRows');
168
166
  }, [privateApiRef, adjustRowParams]);
@@ -349,6 +347,12 @@ const useGridDataSourceLazyLoader = (privateApiRef, props) => {
349
347
  privateApiRef.current.setLoading(true);
350
348
  debouncedFetchRows(getRowsParams);
351
349
  }, [privateApiRef, debouncedFetchRows, throttledHandleRenderedRowsIntervalChange]);
350
+ const handleDragStart = React.useCallback(row => {
351
+ draggedRowId.current = row.id;
352
+ }, []);
353
+ const handleDragEnd = React.useCallback(() => {
354
+ draggedRowId.current = null;
355
+ }, []);
352
356
  const handleStrategyActivityChange = React.useCallback(() => {
353
357
  setLazyLoadingRowsUpdateStrategyActive(privateApiRef.current.getActiveStrategy(_internals.GridStrategyGroup.DataSource) === _internals.DataSourceRowsUpdateStrategy.LazyLoading);
354
358
  }, [privateApiRef]);
@@ -359,6 +363,8 @@ const useGridDataSourceLazyLoader = (privateApiRef, props) => {
359
363
  (0, _xDataGrid.useGridEvent)(privateApiRef, 'renderedRowsIntervalChange', (0, _internals.runIf)(lazyLoadingRowsUpdateStrategyActive, throttledHandleRenderedRowsIntervalChange));
360
364
  (0, _xDataGrid.useGridEvent)(privateApiRef, 'sortModelChange', (0, _internals.runIf)(lazyLoadingRowsUpdateStrategyActive, handleGridSortModelChange));
361
365
  (0, _xDataGrid.useGridEvent)(privateApiRef, 'filterModelChange', (0, _internals.runIf)(lazyLoadingRowsUpdateStrategyActive, handleGridFilterModelChange));
366
+ (0, _xDataGrid.useGridEvent)(privateApiRef, 'rowDragStart', (0, _internals.runIf)(lazyLoadingRowsUpdateStrategyActive, handleDragStart));
367
+ (0, _xDataGrid.useGridEvent)(privateApiRef, 'rowDragEnd', (0, _internals.runIf)(lazyLoadingRowsUpdateStrategyActive, handleDragEnd));
362
368
  React.useEffect(() => {
363
369
  setStrategyAvailability();
364
370
  }, [setStrategyAvailability]);
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid-pro v8.3.1
2
+ * @mui/x-data-grid-pro v8.4.0
3
3
  *
4
4
  * @license MUI X Commercial
5
5
  * This source code is licensed under the commercial license found in the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/x-data-grid-pro",
3
- "version": "8.3.1",
3
+ "version": "8.4.0",
4
4
  "author": "MUI Team",
5
5
  "description": "The Pro plan edition of the MUI X Data Grid components.",
6
6
  "main": "./index.js",
@@ -41,9 +41,9 @@
41
41
  "clsx": "^2.1.1",
42
42
  "prop-types": "^15.8.1",
43
43
  "reselect": "^5.1.1",
44
- "@mui/x-license": "8.3.1",
45
- "@mui/x-data-grid": "8.3.1",
46
- "@mui/x-internals": "8.3.1"
44
+ "@mui/x-internals": "8.4.0",
45
+ "@mui/x-license": "8.4.0",
46
+ "@mui/x-data-grid": "8.4.0"
47
47
  },
48
48
  "peerDependencies": {
49
49
  "@emotion/react": "^11.9.0",