@mui/x-data-grid-pro 6.5.0 → 6.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +78 -2
  2. package/DataGridPro/DataGridPro.js +10 -3
  3. package/README.md +2 -2
  4. package/components/DataGridProVirtualScroller.js +12 -12
  5. package/components/GridColumnHeaders.js +9 -3
  6. package/components/GridColumnMenuPinningItem.d.ts +2 -2
  7. package/components/GridDetailPanel.d.ts +1 -1
  8. package/components/GridDetailPanelToggleCell.d.ts +2 -2
  9. package/components/GridRowReorderCell.d.ts +3 -3
  10. package/components/GridScrollArea.d.ts +10 -0
  11. package/components/GridScrollArea.js +140 -0
  12. package/components/GridTreeDataGroupingCell.d.ts +2 -2
  13. package/components/headerFiltering/GridHeaderFilterAdornment.d.ts +1 -1
  14. package/components/headerFiltering/GridHeaderFilterClearButton.d.ts +2 -2
  15. package/components/headerFiltering/GridHeaderFilterMenu.d.ts +1 -1
  16. package/hooks/features/columnHeaders/useGridColumnHeaders.d.ts +3 -3
  17. package/hooks/features/columnResize/useGridColumnResize.js +11 -12
  18. package/hooks/features/detailPanel/useGridDetailPanel.js +4 -6
  19. package/hooks/features/treeData/gridTreeDataUtils.js +0 -8
  20. package/hooks/features/treeData/useGridTreeDataPreProcessors.js +2 -0
  21. package/index.js +1 -1
  22. package/internals/index.d.ts +1 -1
  23. package/internals/index.js +1 -1
  24. package/legacy/DataGridPro/DataGridPro.js +10 -3
  25. package/legacy/components/DataGridProVirtualScroller.js +12 -12
  26. package/legacy/components/GridColumnHeaders.js +9 -3
  27. package/legacy/components/GridScrollArea.js +143 -0
  28. package/legacy/hooks/features/columnResize/useGridColumnResize.js +11 -12
  29. package/legacy/hooks/features/detailPanel/useGridDetailPanel.js +4 -6
  30. package/legacy/hooks/features/treeData/gridTreeDataUtils.js +0 -8
  31. package/legacy/hooks/features/treeData/useGridTreeDataPreProcessors.js +2 -0
  32. package/legacy/index.js +1 -1
  33. package/legacy/internals/index.js +1 -1
  34. package/legacy/utils/releaseInfo.js +1 -1
  35. package/legacy/utils/tree/utils.js +31 -0
  36. package/modern/DataGridPro/DataGridPro.js +10 -3
  37. package/modern/components/DataGridProVirtualScroller.js +12 -12
  38. package/modern/components/GridColumnHeaders.js +9 -3
  39. package/modern/components/GridScrollArea.js +140 -0
  40. package/modern/hooks/features/columnResize/useGridColumnResize.js +11 -12
  41. package/modern/hooks/features/detailPanel/useGridDetailPanel.js +4 -6
  42. package/modern/hooks/features/treeData/gridTreeDataUtils.js +0 -8
  43. package/modern/hooks/features/treeData/useGridTreeDataPreProcessors.js +2 -0
  44. package/modern/index.js +1 -1
  45. package/modern/internals/index.js +1 -1
  46. package/modern/utils/releaseInfo.js +1 -1
  47. package/modern/utils/tree/utils.js +33 -1
  48. package/node/DataGridPro/DataGridPro.js +10 -3
  49. package/node/components/DataGridProVirtualScroller.js +12 -12
  50. package/node/components/GridColumnHeaders.js +8 -3
  51. package/node/components/GridScrollArea.js +149 -0
  52. package/node/hooks/features/columnResize/useGridColumnResize.js +11 -12
  53. package/node/hooks/features/detailPanel/useGridDetailPanel.js +4 -6
  54. package/node/hooks/features/treeData/gridTreeDataUtils.js +0 -8
  55. package/node/hooks/features/treeData/useGridTreeDataPreProcessors.js +2 -0
  56. package/node/index.js +1 -1
  57. package/node/internals/index.js +8 -1
  58. package/node/utils/releaseInfo.js +1 -1
  59. package/node/utils/tree/utils.js +35 -2
  60. package/package.json +6 -6
  61. package/utils/releaseInfo.js +1 -1
  62. package/utils/tree/utils.d.ts +5 -1
  63. package/utils/tree/utils.js +33 -1
@@ -0,0 +1,140 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import * as React from 'react';
3
+ import PropTypes from 'prop-types';
4
+ import clsx from 'clsx';
5
+ import { unstable_composeClasses as composeClasses, unstable_useEventCallback as useEventCallback } from '@mui/utils';
6
+ import { styled } from '@mui/system';
7
+ import { getTotalHeaderHeight } from '@mui/x-data-grid/internals';
8
+ import { getDataGridUtilityClass, gridClasses, gridDensityFactorSelector, useGridApiContext, useGridApiEventHandler, useGridSelector, gridColumnsTotalWidthSelector } from '@mui/x-data-grid';
9
+ import { useGridRootProps } from '../hooks/utils/useGridRootProps';
10
+ import { jsx as _jsx } from "react/jsx-runtime";
11
+ const CLIFF = 1;
12
+ const SLOP = 1.5;
13
+ const useUtilityClasses = ownerState => {
14
+ const {
15
+ scrollDirection,
16
+ classes
17
+ } = ownerState;
18
+ const slots = {
19
+ root: ['scrollArea', `scrollArea--${scrollDirection}`]
20
+ };
21
+ return composeClasses(slots, getDataGridUtilityClass, classes);
22
+ };
23
+ const GridScrollAreaRawRoot = styled('div', {
24
+ name: 'MuiDataGrid',
25
+ slot: 'ScrollArea',
26
+ overridesResolver: (props, styles) => [{
27
+ [`&.${gridClasses['scrollArea--left']}`]: styles['scrollArea--left']
28
+ }, {
29
+ [`&.${gridClasses['scrollArea--right']}`]: styles['scrollArea--right']
30
+ }, styles.scrollArea]
31
+ })(() => ({
32
+ position: 'absolute',
33
+ top: 0,
34
+ zIndex: 101,
35
+ width: 20,
36
+ bottom: 0,
37
+ [`&.${gridClasses['scrollArea--left']}`]: {
38
+ left: 0
39
+ },
40
+ [`&.${gridClasses['scrollArea--right']}`]: {
41
+ right: 0
42
+ }
43
+ }));
44
+ function GridScrollAreaRaw(props) {
45
+ const {
46
+ scrollDirection
47
+ } = props;
48
+ const rootRef = React.useRef(null);
49
+ const apiRef = useGridApiContext();
50
+ const timeout = React.useRef();
51
+ const [dragging, setDragging] = React.useState(false);
52
+ const [canScrollMore, setCanScrollMore] = React.useState(true);
53
+ const densityFactor = useGridSelector(apiRef, gridDensityFactorSelector);
54
+ const columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector);
55
+ const scrollPosition = React.useRef({
56
+ left: 0,
57
+ top: 0
58
+ });
59
+ const rootProps = useGridRootProps();
60
+ const ownerState = _extends({}, rootProps, {
61
+ scrollDirection
62
+ });
63
+ const classes = useUtilityClasses(ownerState);
64
+ const totalHeaderHeight = getTotalHeaderHeight(apiRef, rootProps.columnHeaderHeight);
65
+ const headerHeight = Math.floor(rootProps.columnHeaderHeight * densityFactor);
66
+ const handleScrolling = React.useCallback(newScrollPosition => {
67
+ scrollPosition.current = newScrollPosition;
68
+ const dimensions = apiRef.current.getRootDimensions();
69
+ setCanScrollMore(() => {
70
+ if (scrollDirection === 'left') {
71
+ // Only render if the user has not reached yet the start of the list
72
+ return scrollPosition.current.left > 0;
73
+ }
74
+ if (scrollDirection === 'right') {
75
+ // Only render if the user has not reached yet the end of the list
76
+ const maxScrollLeft = columnsTotalWidth - dimensions.viewportInnerSize.width;
77
+ return scrollPosition.current.left < maxScrollLeft;
78
+ }
79
+ return false;
80
+ });
81
+ }, [apiRef, columnsTotalWidth, scrollDirection]);
82
+ const handleDragOver = React.useCallback(event => {
83
+ let offset;
84
+
85
+ // Prevents showing the forbidden cursor
86
+ event.preventDefault();
87
+ if (scrollDirection === 'left') {
88
+ offset = event.clientX - rootRef.current.getBoundingClientRect().right;
89
+ } else if (scrollDirection === 'right') {
90
+ offset = Math.max(1, event.clientX - rootRef.current.getBoundingClientRect().left);
91
+ } else {
92
+ throw new Error('MUI: Wrong drag direction');
93
+ }
94
+ offset = (offset - CLIFF) * SLOP + CLIFF;
95
+ clearTimeout(timeout.current);
96
+ // Avoid freeze and inertia.
97
+ timeout.current = setTimeout(() => {
98
+ apiRef.current.scroll({
99
+ left: scrollPosition.current.left + offset,
100
+ top: scrollPosition.current.top
101
+ });
102
+ });
103
+ }, [scrollDirection, apiRef]);
104
+ React.useEffect(() => {
105
+ return () => {
106
+ clearTimeout(timeout.current);
107
+ };
108
+ }, []);
109
+ const handleColumnHeaderDragStart = useEventCallback(() => {
110
+ setDragging(true);
111
+ });
112
+ const handleColumnHeaderDragEnd = useEventCallback(() => {
113
+ setDragging(false);
114
+ });
115
+ useGridApiEventHandler(apiRef, 'scrollPositionChange', handleScrolling);
116
+ useGridApiEventHandler(apiRef, 'columnHeaderDragStart', handleColumnHeaderDragStart);
117
+ useGridApiEventHandler(apiRef, 'columnHeaderDragEnd', handleColumnHeaderDragEnd);
118
+ if (!dragging || !canScrollMore) {
119
+ return null;
120
+ }
121
+ return /*#__PURE__*/_jsx(GridScrollAreaRawRoot, {
122
+ ref: rootRef,
123
+ className: clsx(classes.root),
124
+ ownerState: ownerState,
125
+ onDragOver: handleDragOver,
126
+ style: {
127
+ height: headerHeight,
128
+ top: totalHeaderHeight - headerHeight
129
+ }
130
+ });
131
+ }
132
+ process.env.NODE_ENV !== "production" ? GridScrollAreaRaw.propTypes = {
133
+ // ----------------------------- Warning --------------------------------
134
+ // | These PropTypes are generated from the TypeScript type definitions |
135
+ // | To update them edit the TypeScript types and run "yarn proptypes" |
136
+ // ----------------------------------------------------------------------
137
+ scrollDirection: PropTypes.oneOf(['left', 'right']).isRequired
138
+ } : void 0;
139
+ const GridScrollArea = /*#__PURE__*/React.memo(GridScrollAreaRaw);
140
+ export { GridScrollArea };
@@ -130,7 +130,7 @@ export const useGridColumnResize = (apiRef, props) => {
130
130
  div.style.maxWidth = finalWidth;
131
131
  });
132
132
  };
133
- const handleResizeMouseUp = useEventCallback(nativeEvent => {
133
+ const finishResize = nativeEvent => {
134
134
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
135
135
  stopListening();
136
136
  apiRef.current.updateColumns([colDefRef.current]);
@@ -146,7 +146,8 @@ export const useGridColumnResize = (apiRef, props) => {
146
146
  }
147
147
  });
148
148
  logger.debug(`Updating col ${colDefRef.current.field} with new width: ${colDefRef.current.width}`);
149
- });
149
+ };
150
+ const handleResizeMouseUp = useEventCallback(finishResize);
150
151
  const handleResizeMouseMove = useEventCallback(nativeEvent => {
151
152
  // Cancel move in case some other element consumed a mouseup event and it was not fired.
152
153
  if (nativeEvent.buttons === 0) {
@@ -196,21 +197,16 @@ export const useGridColumnResize = (apiRef, props) => {
196
197
  initialOffsetToSeparator.current = computeOffsetToSeparator(event.clientX, colElementRef.current.getBoundingClientRect(), resizeDirection.current);
197
198
  doc.addEventListener('mousemove', handleResizeMouseMove);
198
199
  doc.addEventListener('mouseup', handleResizeMouseUp);
200
+
201
+ // Fixes https://github.com/mui/mui-x/issues/4777
202
+ colElementRef.current.style.pointerEvents = 'none';
199
203
  });
200
204
  const handleTouchEnd = useEventCallback(nativeEvent => {
201
205
  const finger = trackFinger(nativeEvent, touchId.current);
202
206
  if (!finger) {
203
207
  return;
204
208
  }
205
-
206
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
207
- stopListening();
208
- apiRef.current.updateColumns([colDefRef.current]);
209
- clearTimeout(stopResizeEventTimeout.current);
210
- stopResizeEventTimeout.current = setTimeout(() => {
211
- apiRef.current.publishEvent('columnResizeStop', null, nativeEvent);
212
- });
213
- logger.debug(`Updating col ${colDefRef.current.field} with new width: ${colDefRef.current.width}`);
209
+ finishResize(nativeEvent);
214
210
  });
215
211
  const handleTouchMove = useEventCallback(nativeEvent => {
216
212
  const finger = trackFinger(nativeEvent, touchId.current);
@@ -272,7 +268,10 @@ export const useGridColumnResize = (apiRef, props) => {
272
268
  doc.removeEventListener('mouseup', handleResizeMouseUp);
273
269
  doc.removeEventListener('touchmove', handleTouchMove);
274
270
  doc.removeEventListener('touchend', handleTouchEnd);
275
- }, [apiRef, handleResizeMouseMove, handleResizeMouseUp, handleTouchMove, handleTouchEnd]);
271
+ if (colElementRef.current) {
272
+ colElementRef.current.style.pointerEvents = 'unset';
273
+ }
274
+ }, [apiRef, colElementRef, handleResizeMouseMove, handleResizeMouseUp, handleTouchMove, handleTouchEnd]);
276
275
  const handleResizeStart = React.useCallback(({
277
276
  field
278
277
  }) => {
@@ -166,15 +166,13 @@ export const useGridDetailPanel = (apiRef, props) => {
166
166
  }, [apiRef, props.getDetailPanelContent, props.getDetailPanelHeight]);
167
167
  const addDetailHeight = React.useCallback((initialValue, row) => {
168
168
  if (!expandedRowIds || expandedRowIds.length === 0 || !expandedRowIds.includes(row.id)) {
169
- return _extends({}, initialValue, {
170
- detail: 0
171
- });
169
+ initialValue.detail = 0;
170
+ return initialValue;
172
171
  }
173
172
  updateCachesIfNeeded();
174
173
  const heightCache = gridDetailPanelExpandedRowsHeightCacheSelector(apiRef);
175
- return _extends({}, initialValue, {
176
- detail: heightCache[row.id] ?? 0 // Fallback to zero because the cache might not be ready yet (e.g. page was changed)
177
- });
174
+ initialValue.detail = heightCache[row.id] ?? 0; // Fallback to zero because the cache might not be ready yet (e.g. page was changed)
175
+ return initialValue;
178
176
  }, [apiRef, expandedRowIds, updateCachesIfNeeded]);
179
177
  useGridRegisterPipeProcessor(apiRef, 'rowHeight', addDetailHeight);
180
178
  const isFirstRender = React.useRef(true);
@@ -12,7 +12,6 @@ export const filterRowTreeFromTreeData = params => {
12
12
  disableChildrenFiltering,
13
13
  isRowMatchingFilters
14
14
  } = params;
15
- const visibleRowsLookup = {};
16
15
  const filteredRowsLookup = {};
17
16
  const filteredDescendantCountLookup = {};
18
17
  const filterTreeNode = (node, isParentMatchingFilters, areAncestorsExpanded) => {
@@ -55,13 +54,7 @@ export const filterRowTreeFromTreeData = params => {
55
54
  break;
56
55
  }
57
56
  }
58
- visibleRowsLookup[node.id] = shouldPassFilters && areAncestorsExpanded;
59
57
  filteredRowsLookup[node.id] = shouldPassFilters;
60
-
61
- // TODO: Should we keep storing the visibility status of footer independently or rely on the group visibility in the selector ?
62
- if (node.type === 'group' && node.footerId != null) {
63
- visibleRowsLookup[node.footerId] = shouldPassFilters && areAncestorsExpanded && !!node.childrenExpanded;
64
- }
65
58
  if (!shouldPassFilters) {
66
59
  return 0;
67
60
  }
@@ -79,7 +72,6 @@ export const filterRowTreeFromTreeData = params => {
79
72
  }
80
73
  }
81
74
  return {
82
- visibleRowsLookup,
83
75
  filteredRowsLookup,
84
76
  filteredDescendantCountLookup
85
77
  };
@@ -10,6 +10,7 @@ import { GridTreeDataGroupingCell } from '../../../components';
10
10
  import { createRowTree } from '../../../utils/tree/createRowTree';
11
11
  import { sortRowTree } from '../../../utils/tree/sortRowTree';
12
12
  import { updateRowTree } from '../../../utils/tree/updateRowTree';
13
+ import { getVisibleRowsLookup } from '../../../utils/tree/utils';
13
14
  import { jsx as _jsx } from "react/jsx-runtime";
14
15
  export const useGridTreeDataPreProcessors = (privateApiRef, props) => {
15
16
  const setStrategyAvailability = React.useCallback(() => {
@@ -121,6 +122,7 @@ export const useGridTreeDataPreProcessors = (privateApiRef, props) => {
121
122
  useGridRegisterStrategyProcessor(privateApiRef, TREE_DATA_STRATEGY, 'rowTreeCreation', createRowTreeForTreeData);
122
123
  useGridRegisterStrategyProcessor(privateApiRef, TREE_DATA_STRATEGY, 'filtering', filterRows);
123
124
  useGridRegisterStrategyProcessor(privateApiRef, TREE_DATA_STRATEGY, 'sorting', sortRows);
125
+ useGridRegisterStrategyProcessor(privateApiRef, TREE_DATA_STRATEGY, 'visibleRowsLookupCreation', getVisibleRowsLookup);
124
126
 
125
127
  /**
126
128
  * 1ST RENDER
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid-pro v6.5.0
2
+ * @mui/x-data-grid-pro v6.6.0
3
3
  *
4
4
  * @license MUI X Commercial
5
5
  * This source code is licensed under the commercial license found in the
@@ -25,4 +25,4 @@ export { useGridLazyLoaderPreProcessors } from '../hooks/features/lazyLoader/use
25
25
  export { createRowTree } from '../utils/tree/createRowTree';
26
26
  export { updateRowTree } from '../utils/tree/updateRowTree';
27
27
  export { sortRowTree } from '../utils/tree/sortRowTree';
28
- export { insertNodeInTree, removeNodeFromTree } from '../utils/tree/utils';
28
+ export { insertNodeInTree, removeNodeFromTree, getVisibleRowsLookup } from '../utils/tree/utils';
@@ -1,6 +1,6 @@
1
1
  import { ponyfillGlobal } from '@mui/utils';
2
2
  export const getReleaseInfo = () => {
3
- const releaseInfo = "MTY4NDQ0MzYwMDAwMA==";
3
+ const releaseInfo = "MTY4NTU3MDQwMDAwMA==";
4
4
  if (process.env.NODE_ENV !== 'production') {
5
5
  // A simple hack to set the value in the test environment (has no build step).
6
6
  // eslint-disable-next-line no-useless-concat
@@ -176,4 +176,36 @@ export const createUpdatedGroupsManager = () => ({
176
176
  }
177
177
  this.value[groupId][action] = true;
178
178
  }
179
- });
179
+ });
180
+ export const getVisibleRowsLookup = ({
181
+ tree,
182
+ filteredRowsLookup
183
+ }) => {
184
+ if (!filteredRowsLookup) {
185
+ return {};
186
+ }
187
+ const visibleRowsLookup = {};
188
+ const handleTreeNode = (node, areAncestorsExpanded) => {
189
+ const isPassingFiltering = filteredRowsLookup[node.id];
190
+ if (node.type === 'group') {
191
+ node.children.forEach(childId => {
192
+ const childNode = tree[childId];
193
+ handleTreeNode(childNode, areAncestorsExpanded && !!node.childrenExpanded);
194
+ });
195
+ }
196
+ visibleRowsLookup[node.id] = isPassingFiltering && areAncestorsExpanded;
197
+
198
+ // TODO rows v6: Should we keep storing the visibility status of footer independently or rely on the group visibility in the selector ?
199
+ if (node.type === 'group' && node.footerId != null) {
200
+ visibleRowsLookup[node.footerId] = isPassingFiltering && areAncestorsExpanded && !!node.childrenExpanded;
201
+ }
202
+ };
203
+ const nodes = Object.values(tree);
204
+ for (let i = 0; i < nodes.length; i += 1) {
205
+ const node = nodes[i];
206
+ if (node.depth === 0) {
207
+ handleTreeNode(node, true);
208
+ }
209
+ }
210
+ return visibleRowsLookup;
211
+ };
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.DataGridPro = void 0;
8
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
8
9
  var React = _interopRequireWildcard(require("react"));
9
10
  var _propTypes = _interopRequireDefault(require("prop-types"));
10
11
  var _xLicensePro = require("@mui/x-license-pro");
@@ -27,11 +28,12 @@ const DataGridProRaw = /*#__PURE__*/React.forwardRef(function DataGridPro(inProp
27
28
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(_xDataGrid.GridContextProvider, {
28
29
  privateApiRef: privateApiRef,
29
30
  props: props,
30
- children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_xDataGrid.GridRoot, {
31
+ children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_xDataGrid.GridRoot, (0, _extends2.default)({
31
32
  className: props.className,
32
33
  style: props.style,
33
34
  sx: props.sx,
34
- ref: ref,
35
+ ref: ref
36
+ }, props.forwardedProps, {
35
37
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_xDataGrid.GridHeader, {}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_xDataGrid.GridBody, {
36
38
  VirtualScrollerComponent: _DataGridProVirtualScroller.DataGridProVirtualScroller,
37
39
  ColumnHeadersProps: {
@@ -42,7 +44,7 @@ const DataGridProRaw = /*#__PURE__*/React.forwardRef(function DataGridPro(inProp
42
44
  releaseInfo: releaseInfo
43
45
  })
44
46
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_xDataGrid.GridFooterPlaceholder, {})]
45
- })
47
+ }))
46
48
  });
47
49
  });
48
50
  const DataGridPro = /*#__PURE__*/React.memo(DataGridProRaw);
@@ -264,6 +266,11 @@ DataGridProRaw.propTypes = {
264
266
  quickFilterLogicOperator: _propTypes.default.oneOf(['and', 'or']),
265
267
  quickFilterValues: _propTypes.default.array
266
268
  }),
269
+ /**
270
+ * Forwarded props for the grid root element.
271
+ * @ignore - do not document.
272
+ */
273
+ forwardedProps: _propTypes.default.object,
267
274
  /**
268
275
  * Function that applies CSS classes dynamically on cells.
269
276
  * @param {GridCellParams} params With all properties from [[GridCellParams]].
@@ -185,8 +185,17 @@ const DataGridProVirtualScroller = /*#__PURE__*/React.forwardRef(function DataGr
185
185
  bottomPinnedRowsRenderZoneRef.current.style.transform = `translate3d(${left}px, 0px, 0px)`;
186
186
  }
187
187
  }, []);
188
+
189
+ // Create a lookup for faster check if the row is expanded
190
+ const expandedRowIdsLookup = React.useMemo(() => {
191
+ const lookup = new Set();
192
+ expandedRowIds.forEach(id => {
193
+ lookup.add(id);
194
+ });
195
+ return lookup;
196
+ }, [expandedRowIds]);
188
197
  const getRowProps = React.useCallback(id => {
189
- if (!expandedRowIds.includes(id)) {
198
+ if (!expandedRowIdsLookup.has(id)) {
190
199
  return null;
191
200
  }
192
201
  const height = detailPanelsHeights[id];
@@ -195,7 +204,7 @@ const DataGridProVirtualScroller = /*#__PURE__*/React.forwardRef(function DataGr
195
204
  marginBottom: height
196
205
  }
197
206
  };
198
- }, [detailPanelsHeights, expandedRowIds]);
207
+ }, [detailPanelsHeights, expandedRowIdsLookup]);
199
208
  const pinnedColumns = (0, _xDataGrid.useGridSelector)(apiRef, _columnPinning.gridPinnedColumnsSelector);
200
209
  const [leftPinnedColumns, rightPinnedColumns] = filterColumns(pinnedColumns, visibleColumnFields, theme.direction === 'rtl');
201
210
  const pinnedRows = (0, _xDataGrid.useGridSelector)(apiRef, _gridRowPinningSelector.gridPinnedRowsSelector);
@@ -235,15 +244,6 @@ const DataGridProVirtualScroller = /*#__PURE__*/React.forwardRef(function DataGr
235
244
  firstColumnIndex: visibleColumnFields.length - rightPinnedColumns.length,
236
245
  lastColumnIndex: visibleColumnFields.length
237
246
  }) : null;
238
-
239
- // Create a lookup for faster check if the row is expanded
240
- const expandedRowIdsLookup = React.useMemo(() => {
241
- const lookup = {};
242
- expandedRowIds.forEach(id => {
243
- lookup[id] = true;
244
- });
245
- return lookup;
246
- }, [expandedRowIds]);
247
247
  const getDetailPanel = rowId => {
248
248
  const rowsMeta = (0, _xDataGrid.gridRowsMetaSelector)(apiRef.current.state);
249
249
  const content = detailPanelsContent[rowId];
@@ -284,7 +284,7 @@ const DataGridProVirtualScroller = /*#__PURE__*/React.forwardRef(function DataGr
284
284
  if (rootProps.getDetailPanelContent == null) {
285
285
  return;
286
286
  }
287
- if (!expandedRowIdsLookup[rowId]) {
287
+ if (!expandedRowIdsLookup.has(rowId)) {
288
288
  return;
289
289
  }
290
290
  const detailPanel = getDetailPanel(rowId);
@@ -16,8 +16,9 @@ var _internals = require("@mui/x-data-grid/internals");
16
16
  var _useGridRootProps = require("../hooks/utils/useGridRootProps");
17
17
  var _useGridApiContext = require("../hooks/utils/useGridApiContext");
18
18
  var _columnPinning = require("../hooks/features/columnPinning");
19
- var _DataGridProVirtualScroller = require("./DataGridProVirtualScroller");
20
19
  var _useGridColumnHeaders = require("../hooks/features/columnHeaders/useGridColumnHeaders");
20
+ var _DataGridProVirtualScroller = require("./DataGridProVirtualScroller");
21
+ var _GridScrollArea = require("./GridScrollArea");
21
22
  var _jsxRuntime = require("react/jsx-runtime");
22
23
  const _excluded = ["style", "className", "innerRef", "visibleColumns", "sortColumnLookup", "filterColumnLookup", "columnPositions", "columnHeaderTabIndexState", "columnGroupHeaderTabIndexState", "columnHeaderFocus", "columnGroupHeaderFocus", "densityFactor", "headerGroupingMaxDepth", "columnMenuState", "columnVisibility", "columnGroupsHeaderStructure", "hasOtherElementInTabSequence", "pinnedColumns"];
23
24
  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); }
@@ -193,7 +194,9 @@ const GridColumnHeaders = /*#__PURE__*/React.forwardRef(function GridColumnHeade
193
194
  minFirstColumn: leftRenderContext.firstColumnIndex,
194
195
  maxLastColumn: leftRenderContext.lastColumnIndex
195
196
  })]
196
- })), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_internals.GridColumnHeadersInner, (0, _extends2.default)({
197
+ })), /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridScrollArea.GridScrollArea, {
198
+ scrollDirection: "left"
199
+ }), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_internals.GridColumnHeadersInner, (0, _extends2.default)({
197
200
  isDragging: isDragging
198
201
  }, innerProps, {
199
202
  children: [getColumnGroupHeaders({
@@ -209,7 +212,9 @@ const GridColumnHeaders = /*#__PURE__*/React.forwardRef(function GridColumnHeade
209
212
  minFirstColumn: leftPinnedColumns.length,
210
213
  maxLastColumn: visibleColumnFields.length - rightPinnedColumns.length
211
214
  })]
212
- })), rightRenderContext && /*#__PURE__*/(0, _jsxRuntime.jsxs)(GridColumnHeadersPinnedColumnHeaders, (0, _extends2.default)({
215
+ })), /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridScrollArea.GridScrollArea, {
216
+ scrollDirection: "right"
217
+ }), rightRenderContext && /*#__PURE__*/(0, _jsxRuntime.jsxs)(GridColumnHeadersPinnedColumnHeaders, (0, _extends2.default)({
213
218
  ownerState: (0, _extends2.default)({}, ownerState, {
214
219
  side: _columnPinning.GridPinnedPosition.right,
215
220
  showCellVerticalBorder: rootProps.showCellVerticalBorder
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.GridScrollArea = void 0;
8
+ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
9
+ var React = _interopRequireWildcard(require("react"));
10
+ var _propTypes = _interopRequireDefault(require("prop-types"));
11
+ var _clsx = _interopRequireDefault(require("clsx"));
12
+ var _utils = require("@mui/utils");
13
+ var _system = require("@mui/system");
14
+ var _internals = require("@mui/x-data-grid/internals");
15
+ var _xDataGrid = require("@mui/x-data-grid");
16
+ var _useGridRootProps = require("../hooks/utils/useGridRootProps");
17
+ var _jsxRuntime = require("react/jsx-runtime");
18
+ 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); }
19
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
20
+ const CLIFF = 1;
21
+ const SLOP = 1.5;
22
+ const useUtilityClasses = ownerState => {
23
+ const {
24
+ scrollDirection,
25
+ classes
26
+ } = ownerState;
27
+ const slots = {
28
+ root: ['scrollArea', `scrollArea--${scrollDirection}`]
29
+ };
30
+ return (0, _utils.unstable_composeClasses)(slots, _xDataGrid.getDataGridUtilityClass, classes);
31
+ };
32
+ const GridScrollAreaRawRoot = (0, _system.styled)('div', {
33
+ name: 'MuiDataGrid',
34
+ slot: 'ScrollArea',
35
+ overridesResolver: (props, styles) => [{
36
+ [`&.${_xDataGrid.gridClasses['scrollArea--left']}`]: styles['scrollArea--left']
37
+ }, {
38
+ [`&.${_xDataGrid.gridClasses['scrollArea--right']}`]: styles['scrollArea--right']
39
+ }, styles.scrollArea]
40
+ })(() => ({
41
+ position: 'absolute',
42
+ top: 0,
43
+ zIndex: 101,
44
+ width: 20,
45
+ bottom: 0,
46
+ [`&.${_xDataGrid.gridClasses['scrollArea--left']}`]: {
47
+ left: 0
48
+ },
49
+ [`&.${_xDataGrid.gridClasses['scrollArea--right']}`]: {
50
+ right: 0
51
+ }
52
+ }));
53
+ function GridScrollAreaRaw(props) {
54
+ const {
55
+ scrollDirection
56
+ } = props;
57
+ const rootRef = React.useRef(null);
58
+ const apiRef = (0, _xDataGrid.useGridApiContext)();
59
+ const timeout = React.useRef();
60
+ const [dragging, setDragging] = React.useState(false);
61
+ const [canScrollMore, setCanScrollMore] = React.useState(true);
62
+ const densityFactor = (0, _xDataGrid.useGridSelector)(apiRef, _xDataGrid.gridDensityFactorSelector);
63
+ const columnsTotalWidth = (0, _xDataGrid.useGridSelector)(apiRef, _xDataGrid.gridColumnsTotalWidthSelector);
64
+ const scrollPosition = React.useRef({
65
+ left: 0,
66
+ top: 0
67
+ });
68
+ const rootProps = (0, _useGridRootProps.useGridRootProps)();
69
+ const ownerState = (0, _extends2.default)({}, rootProps, {
70
+ scrollDirection
71
+ });
72
+ const classes = useUtilityClasses(ownerState);
73
+ const totalHeaderHeight = (0, _internals.getTotalHeaderHeight)(apiRef, rootProps.columnHeaderHeight);
74
+ const headerHeight = Math.floor(rootProps.columnHeaderHeight * densityFactor);
75
+ const handleScrolling = React.useCallback(newScrollPosition => {
76
+ scrollPosition.current = newScrollPosition;
77
+ const dimensions = apiRef.current.getRootDimensions();
78
+ setCanScrollMore(() => {
79
+ if (scrollDirection === 'left') {
80
+ // Only render if the user has not reached yet the start of the list
81
+ return scrollPosition.current.left > 0;
82
+ }
83
+ if (scrollDirection === 'right') {
84
+ // Only render if the user has not reached yet the end of the list
85
+ const maxScrollLeft = columnsTotalWidth - dimensions.viewportInnerSize.width;
86
+ return scrollPosition.current.left < maxScrollLeft;
87
+ }
88
+ return false;
89
+ });
90
+ }, [apiRef, columnsTotalWidth, scrollDirection]);
91
+ const handleDragOver = React.useCallback(event => {
92
+ let offset;
93
+
94
+ // Prevents showing the forbidden cursor
95
+ event.preventDefault();
96
+ if (scrollDirection === 'left') {
97
+ offset = event.clientX - rootRef.current.getBoundingClientRect().right;
98
+ } else if (scrollDirection === 'right') {
99
+ offset = Math.max(1, event.clientX - rootRef.current.getBoundingClientRect().left);
100
+ } else {
101
+ throw new Error('MUI: Wrong drag direction');
102
+ }
103
+ offset = (offset - CLIFF) * SLOP + CLIFF;
104
+ clearTimeout(timeout.current);
105
+ // Avoid freeze and inertia.
106
+ timeout.current = setTimeout(() => {
107
+ apiRef.current.scroll({
108
+ left: scrollPosition.current.left + offset,
109
+ top: scrollPosition.current.top
110
+ });
111
+ });
112
+ }, [scrollDirection, apiRef]);
113
+ React.useEffect(() => {
114
+ return () => {
115
+ clearTimeout(timeout.current);
116
+ };
117
+ }, []);
118
+ const handleColumnHeaderDragStart = (0, _utils.unstable_useEventCallback)(() => {
119
+ setDragging(true);
120
+ });
121
+ const handleColumnHeaderDragEnd = (0, _utils.unstable_useEventCallback)(() => {
122
+ setDragging(false);
123
+ });
124
+ (0, _xDataGrid.useGridApiEventHandler)(apiRef, 'scrollPositionChange', handleScrolling);
125
+ (0, _xDataGrid.useGridApiEventHandler)(apiRef, 'columnHeaderDragStart', handleColumnHeaderDragStart);
126
+ (0, _xDataGrid.useGridApiEventHandler)(apiRef, 'columnHeaderDragEnd', handleColumnHeaderDragEnd);
127
+ if (!dragging || !canScrollMore) {
128
+ return null;
129
+ }
130
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridScrollAreaRawRoot, {
131
+ ref: rootRef,
132
+ className: (0, _clsx.default)(classes.root),
133
+ ownerState: ownerState,
134
+ onDragOver: handleDragOver,
135
+ style: {
136
+ height: headerHeight,
137
+ top: totalHeaderHeight - headerHeight
138
+ }
139
+ });
140
+ }
141
+ process.env.NODE_ENV !== "production" ? GridScrollAreaRaw.propTypes = {
142
+ // ----------------------------- Warning --------------------------------
143
+ // | These PropTypes are generated from the TypeScript type definitions |
144
+ // | To update them edit the TypeScript types and run "yarn proptypes" |
145
+ // ----------------------------------------------------------------------
146
+ scrollDirection: _propTypes.default.oneOf(['left', 'right']).isRequired
147
+ } : void 0;
148
+ const GridScrollArea = /*#__PURE__*/React.memo(GridScrollAreaRaw);
149
+ exports.GridScrollArea = GridScrollArea;
@@ -140,7 +140,7 @@ const useGridColumnResize = (apiRef, props) => {
140
140
  div.style.maxWidth = finalWidth;
141
141
  });
142
142
  };
143
- const handleResizeMouseUp = (0, _utils.unstable_useEventCallback)(nativeEvent => {
143
+ const finishResize = nativeEvent => {
144
144
  // eslint-disable-next-line @typescript-eslint/no-use-before-define
145
145
  stopListening();
146
146
  apiRef.current.updateColumns([colDefRef.current]);
@@ -156,7 +156,8 @@ const useGridColumnResize = (apiRef, props) => {
156
156
  }
157
157
  });
158
158
  logger.debug(`Updating col ${colDefRef.current.field} with new width: ${colDefRef.current.width}`);
159
- });
159
+ };
160
+ const handleResizeMouseUp = (0, _utils.unstable_useEventCallback)(finishResize);
160
161
  const handleResizeMouseMove = (0, _utils.unstable_useEventCallback)(nativeEvent => {
161
162
  // Cancel move in case some other element consumed a mouseup event and it was not fired.
162
163
  if (nativeEvent.buttons === 0) {
@@ -206,21 +207,16 @@ const useGridColumnResize = (apiRef, props) => {
206
207
  initialOffsetToSeparator.current = computeOffsetToSeparator(event.clientX, colElementRef.current.getBoundingClientRect(), resizeDirection.current);
207
208
  doc.addEventListener('mousemove', handleResizeMouseMove);
208
209
  doc.addEventListener('mouseup', handleResizeMouseUp);
210
+
211
+ // Fixes https://github.com/mui/mui-x/issues/4777
212
+ colElementRef.current.style.pointerEvents = 'none';
209
213
  });
210
214
  const handleTouchEnd = (0, _utils.unstable_useEventCallback)(nativeEvent => {
211
215
  const finger = trackFinger(nativeEvent, touchId.current);
212
216
  if (!finger) {
213
217
  return;
214
218
  }
215
-
216
- // eslint-disable-next-line @typescript-eslint/no-use-before-define
217
- stopListening();
218
- apiRef.current.updateColumns([colDefRef.current]);
219
- clearTimeout(stopResizeEventTimeout.current);
220
- stopResizeEventTimeout.current = setTimeout(() => {
221
- apiRef.current.publishEvent('columnResizeStop', null, nativeEvent);
222
- });
223
- logger.debug(`Updating col ${colDefRef.current.field} with new width: ${colDefRef.current.width}`);
219
+ finishResize(nativeEvent);
224
220
  });
225
221
  const handleTouchMove = (0, _utils.unstable_useEventCallback)(nativeEvent => {
226
222
  const finger = trackFinger(nativeEvent, touchId.current);
@@ -282,7 +278,10 @@ const useGridColumnResize = (apiRef, props) => {
282
278
  doc.removeEventListener('mouseup', handleResizeMouseUp);
283
279
  doc.removeEventListener('touchmove', handleTouchMove);
284
280
  doc.removeEventListener('touchend', handleTouchEnd);
285
- }, [apiRef, handleResizeMouseMove, handleResizeMouseUp, handleTouchMove, handleTouchEnd]);
281
+ if (colElementRef.current) {
282
+ colElementRef.current.style.pointerEvents = 'unset';
283
+ }
284
+ }, [apiRef, colElementRef, handleResizeMouseMove, handleResizeMouseUp, handleTouchMove, handleTouchEnd]);
286
285
  const handleResizeStart = React.useCallback(({
287
286
  field
288
287
  }) => {