@mui/x-data-grid 7.29.8 → 7.29.9

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
@@ -3,6 +3,47 @@
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
+ ## 7.29.9
7
+
8
+ _Aug 7, 2025_
9
+
10
+ We'd like to extend a big thank you to the 5 contributors who made this release possible. Here are some highlights ✨:
11
+
12
+ - 🐞 Bugfixes
13
+
14
+ Special thanks go out to the community members for their valuable contributions:
15
+ @nusr
16
+
17
+ The following are all team members who have contributed to this release:
18
+ @cherniavskii, @mapache-salvaje, @MBilalShafi, @rita-codes
19
+
20
+ <!--/ HIGHLIGHT_ABOVE_SEPARATOR /-->
21
+
22
+ ### Data Grid
23
+
24
+ #### `@mui/x-data-grid@7.29.9`
25
+
26
+ - [DataGrid] Do not call `preProcessEditCellProps()` if cell is not editable based on `isCellEditable()` (#19082) @nusr
27
+
28
+ #### `@mui/x-data-grid-pro@7.29.9` [![pro](https://mui.com/r/x-pro-svg)](https://mui.com/r/x-pro-svg-link "Pro plan")
29
+
30
+ Same changes as in `@mui/x-data-grid@7.29.9`, plus:
31
+
32
+ - [DataGridPro] Fix row ordering not auto-scrolling when moving beyond viewport (#18718) @MBilalShafi
33
+
34
+ #### `@mui/x-data-grid-premium@7.29.9` [![premium](https://mui.com/r/x-premium-svg)](https://mui.com/r/x-premium-svg-link "Premium plan")
35
+
36
+ Same changes as in `@mui/x-data-grid-pro@7.29.9`.
37
+
38
+ ### Docs
39
+
40
+ - [docs] Audit and revise the Data Grid Pro row docs (#18629) @mapache-salvaje
41
+ - [docs] Fix `size` column filtering in files tree demo (#18728) @cherniavskii
42
+
43
+ ### Miscellaneous
44
+
45
+ - Update readme publish release command V7 (#18684) @rita-codes
46
+
6
47
  ## v7.29.8
7
48
 
8
49
  _Jul 4, 2025_
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import { RefObject } from '@mui/x-internals/types';
3
3
  import { GridScrollParams } from '../models/params/gridScrollParams';
4
4
  interface ScrollAreaProps {
5
- scrollDirection: 'left' | 'right';
5
+ scrollDirection: 'left' | 'right' | 'up' | 'down';
6
6
  scrollPosition: RefObject<GridScrollParams>;
7
7
  }
8
8
  declare function GridScrollAreaWrapper(props: ScrollAreaProps): React.JSX.Element | null;
@@ -1,11 +1,12 @@
1
1
  'use client';
2
2
 
3
+ /* eslint-disable @typescript-eslint/no-use-before-define */
3
4
  import _extends from "@babel/runtime/helpers/esm/extends";
4
5
  import * as React from 'react';
5
- import clsx from 'clsx';
6
6
  import { unstable_composeClasses as composeClasses, unstable_useEventCallback as useEventCallback } from '@mui/utils';
7
7
  import { styled } from '@mui/system';
8
8
  import { fastMemo } from '@mui/x-internals/fastMemo';
9
+ import { forwardRef } from '@mui/x-internals/forwardRef';
9
10
  import { useGridRootProps } from "../hooks/utils/useGridRootProps.js";
10
11
  import { getDataGridUtilityClass, gridClasses } from "../constants/index.js";
11
12
  import { useGridApiContext } from "../hooks/utils/useGridApiContext.js";
@@ -16,6 +17,7 @@ import { gridDensityFactorSelector } from "../hooks/features/density/densitySele
16
17
  import { useTimeout } from "../hooks/utils/useTimeout.js";
17
18
  import { getTotalHeaderHeight } from "../hooks/features/columns/gridColumnsUtils.js";
18
19
  import { createSelectorV8 } from "../utils/createSelector.js";
20
+ import { gridRowsMetaSelector } from "../hooks/features/rows/gridRowsMetaSelector.js";
19
21
  import { jsx as _jsx } from "react/jsx-runtime";
20
22
  const CLIFF = 1;
21
23
  const SLOP = 1.5;
@@ -36,18 +38,39 @@ const GridScrollAreaRawRoot = styled('div', {
36
38
  [`&.${gridClasses['scrollArea--left']}`]: styles['scrollArea--left']
37
39
  }, {
38
40
  [`&.${gridClasses['scrollArea--right']}`]: styles['scrollArea--right']
41
+ }, {
42
+ [`&.${gridClasses['scrollArea--up']}`]: styles['scrollArea--up']
43
+ }, {
44
+ [`&.${gridClasses['scrollArea--down']}`]: styles['scrollArea--down']
39
45
  }, styles.scrollArea]
40
46
  })(() => ({
41
47
  position: 'absolute',
42
- top: 0,
43
48
  zIndex: 101,
44
- width: 20,
45
- bottom: 0,
49
+ // Horizontal scroll areas
46
50
  [`&.${gridClasses['scrollArea--left']}`]: {
47
- left: 0
51
+ top: 0,
52
+ left: 0,
53
+ width: 20,
54
+ bottom: 0
48
55
  },
49
56
  [`&.${gridClasses['scrollArea--right']}`]: {
50
- right: 0
57
+ top: 0,
58
+ right: 0,
59
+ width: 20,
60
+ bottom: 0
61
+ },
62
+ // Vertical scroll areas
63
+ [`&.${gridClasses['scrollArea--up']}`]: {
64
+ top: 0,
65
+ left: 0,
66
+ right: 0,
67
+ height: 20
68
+ },
69
+ [`&.${gridClasses['scrollArea--down']}`]: {
70
+ bottom: 0,
71
+ left: 0,
72
+ right: 0,
73
+ height: 20
51
74
  }
52
75
  }));
53
76
  const offsetSelector = createSelectorV8(gridDimensionsSelector, (dimensions, direction) => {
@@ -57,19 +80,27 @@ const offsetSelector = createSelectorV8(gridDimensionsSelector, (dimensions, dir
57
80
  if (direction === 'right') {
58
81
  return dimensions.rightPinnedWidth + (dimensions.hasScrollX ? dimensions.scrollbarSize : 0);
59
82
  }
83
+ // For vertical scroll areas, we don't need horizontal offset
60
84
  return 0;
61
85
  });
62
86
  function GridScrollAreaWrapper(props) {
63
87
  const apiRef = useGridApiContext();
64
- const [dragging, setDragging] = React.useState(false);
65
- useGridApiEventHandler(apiRef, 'columnHeaderDragStart', () => setDragging(true));
66
- useGridApiEventHandler(apiRef, 'columnHeaderDragEnd', () => setDragging(false));
67
- if (!dragging) {
88
+ const [dragDirection, setDragDirection] = React.useState('none');
89
+
90
+ // Listen for both column and row drag events
91
+ useGridApiEventHandler(apiRef, 'columnHeaderDragStart', () => setDragDirection('horizontal'));
92
+ useGridApiEventHandler(apiRef, 'columnHeaderDragEnd', () => setDragDirection('none'));
93
+ useGridApiEventHandler(apiRef, 'rowDragStart', () => setDragDirection('vertical'));
94
+ useGridApiEventHandler(apiRef, 'rowDragEnd', () => setDragDirection('none'));
95
+ if (dragDirection === 'none') {
68
96
  return null;
69
97
  }
70
- return /*#__PURE__*/_jsx(GridScrollAreaContent, _extends({}, props));
98
+ if (dragDirection === 'horizontal') {
99
+ return /*#__PURE__*/_jsx(GridHorizontalScrollAreaContent, _extends({}, props));
100
+ }
101
+ return /*#__PURE__*/_jsx(GridVerticalScrollAreaContent, _extends({}, props));
71
102
  }
72
- function GridScrollAreaContent(props) {
103
+ function GridHorizontalScrollAreaContent(props) {
73
104
  const {
74
105
  scrollDirection,
75
106
  scrollPosition
@@ -93,26 +124,17 @@ function GridScrollAreaContent(props) {
93
124
  }
94
125
  return false;
95
126
  };
96
- const [canScrollMore, setCanScrollMore] = React.useState(getCanScrollMore);
97
127
  const rootProps = useGridRootProps();
98
- const ownerState = _extends({}, rootProps, {
99
- scrollDirection
100
- });
101
- const classes = useUtilityClasses(ownerState);
102
128
  const totalHeaderHeight = getTotalHeaderHeight(apiRef, rootProps);
103
129
  const headerHeight = Math.floor(rootProps.columnHeaderHeight * densityFactor);
104
- const style = {
130
+ const style = _extends({
105
131
  height: headerHeight,
106
132
  top: totalHeaderHeight - headerHeight
107
- };
108
- if (scrollDirection === 'left') {
109
- style.left = sideOffset;
110
- } else if (scrollDirection === 'right') {
111
- style.right = sideOffset;
112
- }
113
- const handleScrolling = () => {
114
- setCanScrollMore(getCanScrollMore);
115
- };
133
+ }, scrollDirection === 'left' ? {
134
+ left: sideOffset
135
+ } : {}, scrollDirection === 'right' ? {
136
+ right: sideOffset
137
+ } : {});
116
138
  const handleDragOver = useEventCallback(event => {
117
139
  let offset;
118
140
 
@@ -135,16 +157,98 @@ function GridScrollAreaContent(props) {
135
157
  });
136
158
  });
137
159
  });
160
+ return /*#__PURE__*/_jsx(GridScrollAreaContent, _extends({}, props, {
161
+ ref: rootRef,
162
+ getCanScrollMore: getCanScrollMore,
163
+ style: style,
164
+ handleDragOver: handleDragOver
165
+ }));
166
+ }
167
+ function GridVerticalScrollAreaContent(props) {
168
+ const {
169
+ scrollDirection,
170
+ scrollPosition
171
+ } = props;
172
+ const rootRef = React.useRef(null);
173
+ const apiRef = useGridApiContext();
174
+ const timeout = useTimeout();
175
+ const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector);
176
+ const getCanScrollMore = () => {
177
+ const dimensions = gridDimensionsSelector(apiRef.current.state);
178
+ if (scrollDirection === 'up') {
179
+ // Only render if the user has not reached yet the top of the list
180
+ return scrollPosition.current.top > 0;
181
+ }
182
+ if (scrollDirection === 'down') {
183
+ // Only render if the user has not reached yet the bottom of the list
184
+ const totalRowsHeight = rowsMeta.currentPageTotalHeight || 0;
185
+ const maxScrollTop = totalRowsHeight - dimensions.viewportInnerSize.height - dimensions.scrollbarSize;
186
+ return scrollPosition.current.top < maxScrollTop;
187
+ }
188
+ return false;
189
+ };
190
+ const rootProps = useGridRootProps();
191
+ const totalHeaderHeight = getTotalHeaderHeight(apiRef, rootProps);
192
+ const style = {
193
+ top: scrollDirection === 'up' ? totalHeaderHeight : undefined,
194
+ bottom: scrollDirection === 'down' ? 0 : undefined
195
+ };
196
+ const handleDragOver = useEventCallback(event => {
197
+ let offset;
198
+
199
+ // Prevents showing the forbidden cursor
200
+ event.preventDefault();
201
+ if (scrollDirection === 'up') {
202
+ offset = event.clientY - rootRef.current.getBoundingClientRect().bottom;
203
+ } else if (scrollDirection === 'down') {
204
+ offset = Math.max(1, event.clientY - rootRef.current.getBoundingClientRect().top);
205
+ } else {
206
+ throw new Error('MUI X: Wrong drag direction');
207
+ }
208
+ offset = (offset - CLIFF) * SLOP + CLIFF;
209
+
210
+ // Avoid freeze and inertia.
211
+ timeout.start(0, () => {
212
+ apiRef.current.scroll({
213
+ left: scrollPosition.current.left,
214
+ top: scrollPosition.current.top + offset
215
+ });
216
+ });
217
+ });
218
+ return /*#__PURE__*/_jsx(GridScrollAreaContent, _extends({}, props, {
219
+ ref: rootRef,
220
+ getCanScrollMore: getCanScrollMore,
221
+ style: style,
222
+ handleDragOver: handleDragOver
223
+ }));
224
+ }
225
+ const GridScrollAreaContent = forwardRef(function GridScrollAreaContent(props, ref) {
226
+ const {
227
+ scrollDirection,
228
+ getCanScrollMore,
229
+ style,
230
+ handleDragOver
231
+ } = props;
232
+ const apiRef = useGridApiContext();
233
+ const [canScrollMore, setCanScrollMore] = React.useState(getCanScrollMore);
234
+ const rootProps = useGridRootProps();
235
+ const ownerState = _extends({}, rootProps, {
236
+ scrollDirection
237
+ });
238
+ const classes = useUtilityClasses(ownerState);
239
+ const handleScrolling = () => {
240
+ setCanScrollMore(getCanScrollMore);
241
+ };
138
242
  useGridApiEventHandler(apiRef, 'scrollPositionChange', handleScrolling);
139
243
  if (!canScrollMore) {
140
244
  return null;
141
245
  }
142
246
  return /*#__PURE__*/_jsx(GridScrollAreaRawRoot, {
143
- ref: rootRef,
144
- className: clsx(classes.root),
247
+ ref: ref,
248
+ className: classes.root,
145
249
  ownerState: ownerState,
146
250
  onDragOver: handleDragOver,
147
251
  style: style
148
252
  });
149
- }
253
+ });
150
254
  export const GridScrollArea = fastMemo(GridScrollAreaWrapper);
@@ -95,6 +95,10 @@ function GridVirtualScroller(props) {
95
95
  scrollDirection: "left"
96
96
  }, getScrollAreaProps())), /*#__PURE__*/_jsx(GridScrollArea, _extends({
97
97
  scrollDirection: "right"
98
+ }, getScrollAreaProps())), /*#__PURE__*/_jsx(GridScrollArea, _extends({
99
+ scrollDirection: "up"
100
+ }, getScrollAreaProps())), /*#__PURE__*/_jsx(GridScrollArea, _extends({
101
+ scrollDirection: "down"
98
102
  }, getScrollAreaProps())), /*#__PURE__*/_jsxs(Scroller, _extends({
99
103
  className: classes.scroller
100
104
  }, getScrollerProps(), {
@@ -533,6 +533,14 @@ export interface GridClasses {
533
533
  * Styles applied to the right scroll area element.
534
534
  */
535
535
  'scrollArea--right': string;
536
+ /**
537
+ * Styles applied to the top scroll area element.
538
+ */
539
+ 'scrollArea--up': string;
540
+ /**
541
+ * Styles applied to the bottom scroll area element.
542
+ */
543
+ 'scrollArea--down': string;
536
544
  /**
537
545
  * Styles applied to the scrollbars.
538
546
  */
@@ -2,4 +2,4 @@ import { unstable_generateUtilityClasses as generateUtilityClasses, unstable_gen
2
2
  export function getDataGridUtilityClass(slot) {
3
3
  return generateUtilityClass('MuiDataGrid', slot);
4
4
  }
5
- export const gridClasses = generateUtilityClasses('MuiDataGrid', ['actionsCell', 'aggregationColumnHeader', 'aggregationColumnHeader--alignLeft', 'aggregationColumnHeader--alignCenter', 'aggregationColumnHeader--alignRight', 'aggregationColumnHeaderLabel', 'autoHeight', 'autosizing', 'booleanCell', 'cell--editable', 'cell--editing', 'cell--flex', 'cell--textCenter', 'cell--textLeft', 'cell--textRight', 'cell--rangeTop', 'cell--rangeBottom', 'cell--rangeLeft', 'cell--rangeRight', 'cell--pinnedLeft', 'cell--pinnedRight', 'cell--selectionMode', 'cell', 'cellCheckbox', 'cellEmpty', 'cellSkeleton', 'cellOffsetLeft', 'checkboxInput', 'columnHeader', 'columnHeader--alignCenter', 'columnHeader--alignLeft', 'columnHeader--alignRight', 'columnHeader--dragging', 'columnHeader--moving', 'columnHeader--numeric', 'columnHeader--sortable', 'columnHeader--sorted', 'columnHeader--filtered', 'columnHeader--pinnedLeft', 'columnHeader--pinnedRight', 'columnHeader--last', 'columnHeader--lastUnpinned', 'columnHeader--siblingFocused', 'columnHeaderCheckbox', 'columnHeaderDraggableContainer', 'columnHeaderTitle', 'columnHeaderTitleContainer', 'columnHeaderTitleContainerContent', 'columnHeader--filledGroup', 'columnHeader--emptyGroup', 'columnHeaders', 'columnSeparator--resizable', 'columnSeparator--resizing', 'columnSeparator--sideLeft', 'columnSeparator--sideRight', 'columnSeparator', 'columnsManagement', 'columnsManagementRow', 'columnsManagementHeader', 'columnsManagementSearchInput', 'columnsManagementFooter', 'container--top', 'container--bottom', 'detailPanel', 'detailPanels', 'detailPanelToggleCell', 'detailPanelToggleCell--expanded', 'footerCell', 'panel', 'panelHeader', 'panelWrapper', 'panelContent', 'panelFooter', 'paper', 'editBooleanCell', 'editInputCell', 'filler', 'filler--borderBottom', 'filler--pinnedLeft', 'filler--pinnedRight', 'filterForm', 'filterFormDeleteIcon', 'filterFormLogicOperatorInput', 'filterFormColumnInput', 'filterFormOperatorInput', 'filterFormValueInput', 'filterIcon', 'footerContainer', 'headerFilterRow', 'iconButtonContainer', 'iconSeparator', 'main', 'main--hasPinnedRight', 'main--hasSkeletonLoadingOverlay', 'menu', 'menuIcon', 'menuIconButton', 'menuOpen', 'menuList', 'overlay', 'overlayWrapper', 'overlayWrapperInner', 'root', 'root--densityStandard', 'root--densityComfortable', 'root--densityCompact', 'root--disableUserSelection', 'root--noToolbar', 'row', 'row--editable', 'row--editing', 'row--firstVisible', 'row--lastVisible', 'row--dragging', 'row--dynamicHeight', 'row--detailPanelExpanded', 'row--borderBottom', 'rowReorderCellPlaceholder', 'rowCount', 'rowReorderCellContainer', 'rowReorderCell', 'rowReorderCell--draggable', 'rowSkeleton', 'scrollArea--left', 'scrollArea--right', 'scrollArea', 'scrollbar', 'scrollbar--vertical', 'scrollbar--horizontal', 'scrollbarFiller', 'scrollbarFiller--header', 'scrollbarFiller--borderTop', 'scrollbarFiller--borderBottom', 'scrollbarFiller--pinnedRight', 'selectedRowCount', 'sortButton', 'sortIcon', 'toolbarContainer', 'toolbarFilterList', 'virtualScroller', 'virtualScroller--hasScrollX', 'virtualScrollerContent', 'virtualScrollerContent--overflowed', 'virtualScrollerRenderZone', 'pinnedColumns', 'withVerticalBorder', 'withBorderColor', 'cell--withRightBorder', 'cell--withLeftBorder', 'columnHeader--withRightBorder', 'columnHeader--withLeftBorder', 'treeDataGroupingCell', 'treeDataGroupingCellToggle', 'treeDataGroupingCellLoadingContainer', 'groupingCriteriaCell', 'groupingCriteriaCellToggle', 'groupingCriteriaCellLoadingContainer', 'pinnedRows', 'pinnedRows--top', 'pinnedRows--bottom', 'pinnedRowsRenderZone']);
5
+ export const gridClasses = generateUtilityClasses('MuiDataGrid', ['actionsCell', 'aggregationColumnHeader', 'aggregationColumnHeader--alignLeft', 'aggregationColumnHeader--alignCenter', 'aggregationColumnHeader--alignRight', 'aggregationColumnHeaderLabel', 'autoHeight', 'autosizing', 'booleanCell', 'cell--editable', 'cell--editing', 'cell--flex', 'cell--textCenter', 'cell--textLeft', 'cell--textRight', 'cell--rangeTop', 'cell--rangeBottom', 'cell--rangeLeft', 'cell--rangeRight', 'cell--pinnedLeft', 'cell--pinnedRight', 'cell--selectionMode', 'cell', 'cellCheckbox', 'cellEmpty', 'cellSkeleton', 'cellOffsetLeft', 'checkboxInput', 'columnHeader', 'columnHeader--alignCenter', 'columnHeader--alignLeft', 'columnHeader--alignRight', 'columnHeader--dragging', 'columnHeader--moving', 'columnHeader--numeric', 'columnHeader--sortable', 'columnHeader--sorted', 'columnHeader--filtered', 'columnHeader--pinnedLeft', 'columnHeader--pinnedRight', 'columnHeader--last', 'columnHeader--lastUnpinned', 'columnHeader--siblingFocused', 'columnHeaderCheckbox', 'columnHeaderDraggableContainer', 'columnHeaderTitle', 'columnHeaderTitleContainer', 'columnHeaderTitleContainerContent', 'columnHeader--filledGroup', 'columnHeader--emptyGroup', 'columnHeaders', 'columnSeparator--resizable', 'columnSeparator--resizing', 'columnSeparator--sideLeft', 'columnSeparator--sideRight', 'columnSeparator', 'columnsManagement', 'columnsManagementRow', 'columnsManagementHeader', 'columnsManagementSearchInput', 'columnsManagementFooter', 'container--top', 'container--bottom', 'detailPanel', 'detailPanels', 'detailPanelToggleCell', 'detailPanelToggleCell--expanded', 'footerCell', 'panel', 'panelHeader', 'panelWrapper', 'panelContent', 'panelFooter', 'paper', 'editBooleanCell', 'editInputCell', 'filler', 'filler--borderBottom', 'filler--pinnedLeft', 'filler--pinnedRight', 'filterForm', 'filterFormDeleteIcon', 'filterFormLogicOperatorInput', 'filterFormColumnInput', 'filterFormOperatorInput', 'filterFormValueInput', 'filterIcon', 'footerContainer', 'headerFilterRow', 'iconButtonContainer', 'iconSeparator', 'main', 'main--hasPinnedRight', 'main--hasSkeletonLoadingOverlay', 'menu', 'menuIcon', 'menuIconButton', 'menuOpen', 'menuList', 'overlay', 'overlayWrapper', 'overlayWrapperInner', 'root', 'root--densityStandard', 'root--densityComfortable', 'root--densityCompact', 'root--disableUserSelection', 'root--noToolbar', 'row', 'row--editable', 'row--editing', 'row--firstVisible', 'row--lastVisible', 'row--dragging', 'row--dynamicHeight', 'row--detailPanelExpanded', 'row--borderBottom', 'rowReorderCellPlaceholder', 'rowCount', 'rowReorderCellContainer', 'rowReorderCell', 'rowReorderCell--draggable', 'rowSkeleton', 'scrollArea--left', 'scrollArea--right', 'scrollArea--up', 'scrollArea--down', 'scrollArea', 'scrollbar', 'scrollbar--vertical', 'scrollbar--horizontal', 'scrollbarFiller', 'scrollbarFiller--header', 'scrollbarFiller--borderTop', 'scrollbarFiller--borderBottom', 'scrollbarFiller--pinnedRight', 'selectedRowCount', 'sortButton', 'sortIcon', 'toolbarContainer', 'toolbarFilterList', 'virtualScroller', 'virtualScroller--hasScrollX', 'virtualScrollerContent', 'virtualScrollerContent--overflowed', 'virtualScrollerRenderZone', 'pinnedColumns', 'withVerticalBorder', 'withBorderColor', 'cell--withRightBorder', 'cell--withLeftBorder', 'columnHeader--withRightBorder', 'columnHeader--withLeftBorder', 'treeDataGroupingCell', 'treeDataGroupingCellToggle', 'treeDataGroupingCellLoadingContainer', 'groupingCriteriaCell', 'groupingCriteriaCellToggle', 'groupingCriteriaCellLoadingContainer', 'pinnedRows', 'pinnedRows--top', 'pinnedRows--bottom', 'pinnedRowsRenderZone']);
@@ -341,7 +341,10 @@ export const useGridRowEditing = (apiRef, props) => {
341
341
  if (fieldToFocus) {
342
342
  apiRef.current.setCellFocus(id, fieldToFocus);
343
343
  }
344
- columns.filter(column => column.editable && !!column.preProcessEditCellProps && deleteValue).forEach(column => {
344
+ columns.filter(column => {
345
+ const isCellEditable = apiRef.current.getCellParams(id, column.field).isEditable;
346
+ return isCellEditable && column.editable && !!column.preProcessEditCellProps && deleteValue;
347
+ }).forEach(column => {
345
348
  const field = column.field;
346
349
  const value = apiRef.current.getCellValue(id, field);
347
350
  const newValue = deleteValue ? getDefaultCellValue(column) : initialValue ?? value;
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v7.29.8
2
+ * @mui/x-data-grid v7.29.9
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -1,11 +1,12 @@
1
1
  'use client';
2
2
 
3
+ /* eslint-disable @typescript-eslint/no-use-before-define */
3
4
  import _extends from "@babel/runtime/helpers/esm/extends";
4
5
  import * as React from 'react';
5
- import clsx from 'clsx';
6
6
  import { unstable_composeClasses as composeClasses, unstable_useEventCallback as useEventCallback } from '@mui/utils';
7
7
  import { styled } from '@mui/system';
8
8
  import { fastMemo } from '@mui/x-internals/fastMemo';
9
+ import { forwardRef } from '@mui/x-internals/forwardRef';
9
10
  import { useGridRootProps } from "../hooks/utils/useGridRootProps.js";
10
11
  import { getDataGridUtilityClass, gridClasses } from "../constants/index.js";
11
12
  import { useGridApiContext } from "../hooks/utils/useGridApiContext.js";
@@ -16,6 +17,7 @@ import { gridDensityFactorSelector } from "../hooks/features/density/densitySele
16
17
  import { useTimeout } from "../hooks/utils/useTimeout.js";
17
18
  import { getTotalHeaderHeight } from "../hooks/features/columns/gridColumnsUtils.js";
18
19
  import { createSelectorV8 } from "../utils/createSelector.js";
20
+ import { gridRowsMetaSelector } from "../hooks/features/rows/gridRowsMetaSelector.js";
19
21
  import { jsx as _jsx } from "react/jsx-runtime";
20
22
  const CLIFF = 1;
21
23
  const SLOP = 1.5;
@@ -36,18 +38,39 @@ const GridScrollAreaRawRoot = styled('div', {
36
38
  [`&.${gridClasses['scrollArea--left']}`]: styles['scrollArea--left']
37
39
  }, {
38
40
  [`&.${gridClasses['scrollArea--right']}`]: styles['scrollArea--right']
41
+ }, {
42
+ [`&.${gridClasses['scrollArea--up']}`]: styles['scrollArea--up']
43
+ }, {
44
+ [`&.${gridClasses['scrollArea--down']}`]: styles['scrollArea--down']
39
45
  }, styles.scrollArea]
40
46
  })(() => ({
41
47
  position: 'absolute',
42
- top: 0,
43
48
  zIndex: 101,
44
- width: 20,
45
- bottom: 0,
49
+ // Horizontal scroll areas
46
50
  [`&.${gridClasses['scrollArea--left']}`]: {
47
- left: 0
51
+ top: 0,
52
+ left: 0,
53
+ width: 20,
54
+ bottom: 0
48
55
  },
49
56
  [`&.${gridClasses['scrollArea--right']}`]: {
50
- right: 0
57
+ top: 0,
58
+ right: 0,
59
+ width: 20,
60
+ bottom: 0
61
+ },
62
+ // Vertical scroll areas
63
+ [`&.${gridClasses['scrollArea--up']}`]: {
64
+ top: 0,
65
+ left: 0,
66
+ right: 0,
67
+ height: 20
68
+ },
69
+ [`&.${gridClasses['scrollArea--down']}`]: {
70
+ bottom: 0,
71
+ left: 0,
72
+ right: 0,
73
+ height: 20
51
74
  }
52
75
  }));
53
76
  const offsetSelector = createSelectorV8(gridDimensionsSelector, (dimensions, direction) => {
@@ -57,19 +80,27 @@ const offsetSelector = createSelectorV8(gridDimensionsSelector, (dimensions, dir
57
80
  if (direction === 'right') {
58
81
  return dimensions.rightPinnedWidth + (dimensions.hasScrollX ? dimensions.scrollbarSize : 0);
59
82
  }
83
+ // For vertical scroll areas, we don't need horizontal offset
60
84
  return 0;
61
85
  });
62
86
  function GridScrollAreaWrapper(props) {
63
87
  const apiRef = useGridApiContext();
64
- const [dragging, setDragging] = React.useState(false);
65
- useGridApiEventHandler(apiRef, 'columnHeaderDragStart', () => setDragging(true));
66
- useGridApiEventHandler(apiRef, 'columnHeaderDragEnd', () => setDragging(false));
67
- if (!dragging) {
88
+ const [dragDirection, setDragDirection] = React.useState('none');
89
+
90
+ // Listen for both column and row drag events
91
+ useGridApiEventHandler(apiRef, 'columnHeaderDragStart', () => setDragDirection('horizontal'));
92
+ useGridApiEventHandler(apiRef, 'columnHeaderDragEnd', () => setDragDirection('none'));
93
+ useGridApiEventHandler(apiRef, 'rowDragStart', () => setDragDirection('vertical'));
94
+ useGridApiEventHandler(apiRef, 'rowDragEnd', () => setDragDirection('none'));
95
+ if (dragDirection === 'none') {
68
96
  return null;
69
97
  }
70
- return /*#__PURE__*/_jsx(GridScrollAreaContent, _extends({}, props));
98
+ if (dragDirection === 'horizontal') {
99
+ return /*#__PURE__*/_jsx(GridHorizontalScrollAreaContent, _extends({}, props));
100
+ }
101
+ return /*#__PURE__*/_jsx(GridVerticalScrollAreaContent, _extends({}, props));
71
102
  }
72
- function GridScrollAreaContent(props) {
103
+ function GridHorizontalScrollAreaContent(props) {
73
104
  const {
74
105
  scrollDirection,
75
106
  scrollPosition
@@ -93,26 +124,17 @@ function GridScrollAreaContent(props) {
93
124
  }
94
125
  return false;
95
126
  };
96
- const [canScrollMore, setCanScrollMore] = React.useState(getCanScrollMore);
97
127
  const rootProps = useGridRootProps();
98
- const ownerState = _extends({}, rootProps, {
99
- scrollDirection
100
- });
101
- const classes = useUtilityClasses(ownerState);
102
128
  const totalHeaderHeight = getTotalHeaderHeight(apiRef, rootProps);
103
129
  const headerHeight = Math.floor(rootProps.columnHeaderHeight * densityFactor);
104
- const style = {
130
+ const style = _extends({
105
131
  height: headerHeight,
106
132
  top: totalHeaderHeight - headerHeight
107
- };
108
- if (scrollDirection === 'left') {
109
- style.left = sideOffset;
110
- } else if (scrollDirection === 'right') {
111
- style.right = sideOffset;
112
- }
113
- const handleScrolling = () => {
114
- setCanScrollMore(getCanScrollMore);
115
- };
133
+ }, scrollDirection === 'left' ? {
134
+ left: sideOffset
135
+ } : {}, scrollDirection === 'right' ? {
136
+ right: sideOffset
137
+ } : {});
116
138
  const handleDragOver = useEventCallback(event => {
117
139
  let offset;
118
140
 
@@ -135,16 +157,98 @@ function GridScrollAreaContent(props) {
135
157
  });
136
158
  });
137
159
  });
160
+ return /*#__PURE__*/_jsx(GridScrollAreaContent, _extends({}, props, {
161
+ ref: rootRef,
162
+ getCanScrollMore: getCanScrollMore,
163
+ style: style,
164
+ handleDragOver: handleDragOver
165
+ }));
166
+ }
167
+ function GridVerticalScrollAreaContent(props) {
168
+ const {
169
+ scrollDirection,
170
+ scrollPosition
171
+ } = props;
172
+ const rootRef = React.useRef(null);
173
+ const apiRef = useGridApiContext();
174
+ const timeout = useTimeout();
175
+ const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector);
176
+ const getCanScrollMore = () => {
177
+ const dimensions = gridDimensionsSelector(apiRef.current.state);
178
+ if (scrollDirection === 'up') {
179
+ // Only render if the user has not reached yet the top of the list
180
+ return scrollPosition.current.top > 0;
181
+ }
182
+ if (scrollDirection === 'down') {
183
+ // Only render if the user has not reached yet the bottom of the list
184
+ const totalRowsHeight = rowsMeta.currentPageTotalHeight || 0;
185
+ const maxScrollTop = totalRowsHeight - dimensions.viewportInnerSize.height - dimensions.scrollbarSize;
186
+ return scrollPosition.current.top < maxScrollTop;
187
+ }
188
+ return false;
189
+ };
190
+ const rootProps = useGridRootProps();
191
+ const totalHeaderHeight = getTotalHeaderHeight(apiRef, rootProps);
192
+ const style = {
193
+ top: scrollDirection === 'up' ? totalHeaderHeight : undefined,
194
+ bottom: scrollDirection === 'down' ? 0 : undefined
195
+ };
196
+ const handleDragOver = useEventCallback(event => {
197
+ let offset;
198
+
199
+ // Prevents showing the forbidden cursor
200
+ event.preventDefault();
201
+ if (scrollDirection === 'up') {
202
+ offset = event.clientY - rootRef.current.getBoundingClientRect().bottom;
203
+ } else if (scrollDirection === 'down') {
204
+ offset = Math.max(1, event.clientY - rootRef.current.getBoundingClientRect().top);
205
+ } else {
206
+ throw new Error('MUI X: Wrong drag direction');
207
+ }
208
+ offset = (offset - CLIFF) * SLOP + CLIFF;
209
+
210
+ // Avoid freeze and inertia.
211
+ timeout.start(0, () => {
212
+ apiRef.current.scroll({
213
+ left: scrollPosition.current.left,
214
+ top: scrollPosition.current.top + offset
215
+ });
216
+ });
217
+ });
218
+ return /*#__PURE__*/_jsx(GridScrollAreaContent, _extends({}, props, {
219
+ ref: rootRef,
220
+ getCanScrollMore: getCanScrollMore,
221
+ style: style,
222
+ handleDragOver: handleDragOver
223
+ }));
224
+ }
225
+ const GridScrollAreaContent = forwardRef(function GridScrollAreaContent(props, ref) {
226
+ const {
227
+ scrollDirection,
228
+ getCanScrollMore,
229
+ style,
230
+ handleDragOver
231
+ } = props;
232
+ const apiRef = useGridApiContext();
233
+ const [canScrollMore, setCanScrollMore] = React.useState(getCanScrollMore);
234
+ const rootProps = useGridRootProps();
235
+ const ownerState = _extends({}, rootProps, {
236
+ scrollDirection
237
+ });
238
+ const classes = useUtilityClasses(ownerState);
239
+ const handleScrolling = () => {
240
+ setCanScrollMore(getCanScrollMore);
241
+ };
138
242
  useGridApiEventHandler(apiRef, 'scrollPositionChange', handleScrolling);
139
243
  if (!canScrollMore) {
140
244
  return null;
141
245
  }
142
246
  return /*#__PURE__*/_jsx(GridScrollAreaRawRoot, {
143
- ref: rootRef,
144
- className: clsx(classes.root),
247
+ ref: ref,
248
+ className: classes.root,
145
249
  ownerState: ownerState,
146
250
  onDragOver: handleDragOver,
147
251
  style: style
148
252
  });
149
- }
253
+ });
150
254
  export const GridScrollArea = fastMemo(GridScrollAreaWrapper);
@@ -95,6 +95,10 @@ function GridVirtualScroller(props) {
95
95
  scrollDirection: "left"
96
96
  }, getScrollAreaProps())), /*#__PURE__*/_jsx(GridScrollArea, _extends({
97
97
  scrollDirection: "right"
98
+ }, getScrollAreaProps())), /*#__PURE__*/_jsx(GridScrollArea, _extends({
99
+ scrollDirection: "up"
100
+ }, getScrollAreaProps())), /*#__PURE__*/_jsx(GridScrollArea, _extends({
101
+ scrollDirection: "down"
98
102
  }, getScrollAreaProps())), /*#__PURE__*/_jsxs(Scroller, _extends({
99
103
  className: classes.scroller
100
104
  }, getScrollerProps(), {
@@ -2,4 +2,4 @@ import { unstable_generateUtilityClasses as generateUtilityClasses, unstable_gen
2
2
  export function getDataGridUtilityClass(slot) {
3
3
  return generateUtilityClass('MuiDataGrid', slot);
4
4
  }
5
- export const gridClasses = generateUtilityClasses('MuiDataGrid', ['actionsCell', 'aggregationColumnHeader', 'aggregationColumnHeader--alignLeft', 'aggregationColumnHeader--alignCenter', 'aggregationColumnHeader--alignRight', 'aggregationColumnHeaderLabel', 'autoHeight', 'autosizing', 'booleanCell', 'cell--editable', 'cell--editing', 'cell--flex', 'cell--textCenter', 'cell--textLeft', 'cell--textRight', 'cell--rangeTop', 'cell--rangeBottom', 'cell--rangeLeft', 'cell--rangeRight', 'cell--pinnedLeft', 'cell--pinnedRight', 'cell--selectionMode', 'cell', 'cellCheckbox', 'cellEmpty', 'cellSkeleton', 'cellOffsetLeft', 'checkboxInput', 'columnHeader', 'columnHeader--alignCenter', 'columnHeader--alignLeft', 'columnHeader--alignRight', 'columnHeader--dragging', 'columnHeader--moving', 'columnHeader--numeric', 'columnHeader--sortable', 'columnHeader--sorted', 'columnHeader--filtered', 'columnHeader--pinnedLeft', 'columnHeader--pinnedRight', 'columnHeader--last', 'columnHeader--lastUnpinned', 'columnHeader--siblingFocused', 'columnHeaderCheckbox', 'columnHeaderDraggableContainer', 'columnHeaderTitle', 'columnHeaderTitleContainer', 'columnHeaderTitleContainerContent', 'columnHeader--filledGroup', 'columnHeader--emptyGroup', 'columnHeaders', 'columnSeparator--resizable', 'columnSeparator--resizing', 'columnSeparator--sideLeft', 'columnSeparator--sideRight', 'columnSeparator', 'columnsManagement', 'columnsManagementRow', 'columnsManagementHeader', 'columnsManagementSearchInput', 'columnsManagementFooter', 'container--top', 'container--bottom', 'detailPanel', 'detailPanels', 'detailPanelToggleCell', 'detailPanelToggleCell--expanded', 'footerCell', 'panel', 'panelHeader', 'panelWrapper', 'panelContent', 'panelFooter', 'paper', 'editBooleanCell', 'editInputCell', 'filler', 'filler--borderBottom', 'filler--pinnedLeft', 'filler--pinnedRight', 'filterForm', 'filterFormDeleteIcon', 'filterFormLogicOperatorInput', 'filterFormColumnInput', 'filterFormOperatorInput', 'filterFormValueInput', 'filterIcon', 'footerContainer', 'headerFilterRow', 'iconButtonContainer', 'iconSeparator', 'main', 'main--hasPinnedRight', 'main--hasSkeletonLoadingOverlay', 'menu', 'menuIcon', 'menuIconButton', 'menuOpen', 'menuList', 'overlay', 'overlayWrapper', 'overlayWrapperInner', 'root', 'root--densityStandard', 'root--densityComfortable', 'root--densityCompact', 'root--disableUserSelection', 'root--noToolbar', 'row', 'row--editable', 'row--editing', 'row--firstVisible', 'row--lastVisible', 'row--dragging', 'row--dynamicHeight', 'row--detailPanelExpanded', 'row--borderBottom', 'rowReorderCellPlaceholder', 'rowCount', 'rowReorderCellContainer', 'rowReorderCell', 'rowReorderCell--draggable', 'rowSkeleton', 'scrollArea--left', 'scrollArea--right', 'scrollArea', 'scrollbar', 'scrollbar--vertical', 'scrollbar--horizontal', 'scrollbarFiller', 'scrollbarFiller--header', 'scrollbarFiller--borderTop', 'scrollbarFiller--borderBottom', 'scrollbarFiller--pinnedRight', 'selectedRowCount', 'sortButton', 'sortIcon', 'toolbarContainer', 'toolbarFilterList', 'virtualScroller', 'virtualScroller--hasScrollX', 'virtualScrollerContent', 'virtualScrollerContent--overflowed', 'virtualScrollerRenderZone', 'pinnedColumns', 'withVerticalBorder', 'withBorderColor', 'cell--withRightBorder', 'cell--withLeftBorder', 'columnHeader--withRightBorder', 'columnHeader--withLeftBorder', 'treeDataGroupingCell', 'treeDataGroupingCellToggle', 'treeDataGroupingCellLoadingContainer', 'groupingCriteriaCell', 'groupingCriteriaCellToggle', 'groupingCriteriaCellLoadingContainer', 'pinnedRows', 'pinnedRows--top', 'pinnedRows--bottom', 'pinnedRowsRenderZone']);
5
+ export const gridClasses = generateUtilityClasses('MuiDataGrid', ['actionsCell', 'aggregationColumnHeader', 'aggregationColumnHeader--alignLeft', 'aggregationColumnHeader--alignCenter', 'aggregationColumnHeader--alignRight', 'aggregationColumnHeaderLabel', 'autoHeight', 'autosizing', 'booleanCell', 'cell--editable', 'cell--editing', 'cell--flex', 'cell--textCenter', 'cell--textLeft', 'cell--textRight', 'cell--rangeTop', 'cell--rangeBottom', 'cell--rangeLeft', 'cell--rangeRight', 'cell--pinnedLeft', 'cell--pinnedRight', 'cell--selectionMode', 'cell', 'cellCheckbox', 'cellEmpty', 'cellSkeleton', 'cellOffsetLeft', 'checkboxInput', 'columnHeader', 'columnHeader--alignCenter', 'columnHeader--alignLeft', 'columnHeader--alignRight', 'columnHeader--dragging', 'columnHeader--moving', 'columnHeader--numeric', 'columnHeader--sortable', 'columnHeader--sorted', 'columnHeader--filtered', 'columnHeader--pinnedLeft', 'columnHeader--pinnedRight', 'columnHeader--last', 'columnHeader--lastUnpinned', 'columnHeader--siblingFocused', 'columnHeaderCheckbox', 'columnHeaderDraggableContainer', 'columnHeaderTitle', 'columnHeaderTitleContainer', 'columnHeaderTitleContainerContent', 'columnHeader--filledGroup', 'columnHeader--emptyGroup', 'columnHeaders', 'columnSeparator--resizable', 'columnSeparator--resizing', 'columnSeparator--sideLeft', 'columnSeparator--sideRight', 'columnSeparator', 'columnsManagement', 'columnsManagementRow', 'columnsManagementHeader', 'columnsManagementSearchInput', 'columnsManagementFooter', 'container--top', 'container--bottom', 'detailPanel', 'detailPanels', 'detailPanelToggleCell', 'detailPanelToggleCell--expanded', 'footerCell', 'panel', 'panelHeader', 'panelWrapper', 'panelContent', 'panelFooter', 'paper', 'editBooleanCell', 'editInputCell', 'filler', 'filler--borderBottom', 'filler--pinnedLeft', 'filler--pinnedRight', 'filterForm', 'filterFormDeleteIcon', 'filterFormLogicOperatorInput', 'filterFormColumnInput', 'filterFormOperatorInput', 'filterFormValueInput', 'filterIcon', 'footerContainer', 'headerFilterRow', 'iconButtonContainer', 'iconSeparator', 'main', 'main--hasPinnedRight', 'main--hasSkeletonLoadingOverlay', 'menu', 'menuIcon', 'menuIconButton', 'menuOpen', 'menuList', 'overlay', 'overlayWrapper', 'overlayWrapperInner', 'root', 'root--densityStandard', 'root--densityComfortable', 'root--densityCompact', 'root--disableUserSelection', 'root--noToolbar', 'row', 'row--editable', 'row--editing', 'row--firstVisible', 'row--lastVisible', 'row--dragging', 'row--dynamicHeight', 'row--detailPanelExpanded', 'row--borderBottom', 'rowReorderCellPlaceholder', 'rowCount', 'rowReorderCellContainer', 'rowReorderCell', 'rowReorderCell--draggable', 'rowSkeleton', 'scrollArea--left', 'scrollArea--right', 'scrollArea--up', 'scrollArea--down', 'scrollArea', 'scrollbar', 'scrollbar--vertical', 'scrollbar--horizontal', 'scrollbarFiller', 'scrollbarFiller--header', 'scrollbarFiller--borderTop', 'scrollbarFiller--borderBottom', 'scrollbarFiller--pinnedRight', 'selectedRowCount', 'sortButton', 'sortIcon', 'toolbarContainer', 'toolbarFilterList', 'virtualScroller', 'virtualScroller--hasScrollX', 'virtualScrollerContent', 'virtualScrollerContent--overflowed', 'virtualScrollerRenderZone', 'pinnedColumns', 'withVerticalBorder', 'withBorderColor', 'cell--withRightBorder', 'cell--withLeftBorder', 'columnHeader--withRightBorder', 'columnHeader--withLeftBorder', 'treeDataGroupingCell', 'treeDataGroupingCellToggle', 'treeDataGroupingCellLoadingContainer', 'groupingCriteriaCell', 'groupingCriteriaCellToggle', 'groupingCriteriaCellLoadingContainer', 'pinnedRows', 'pinnedRows--top', 'pinnedRows--bottom', 'pinnedRowsRenderZone']);
@@ -341,7 +341,10 @@ export const useGridRowEditing = (apiRef, props) => {
341
341
  if (fieldToFocus) {
342
342
  apiRef.current.setCellFocus(id, fieldToFocus);
343
343
  }
344
- columns.filter(column => column.editable && !!column.preProcessEditCellProps && deleteValue).forEach(column => {
344
+ columns.filter(column => {
345
+ const isCellEditable = apiRef.current.getCellParams(id, column.field).isEditable;
346
+ return isCellEditable && column.editable && !!column.preProcessEditCellProps && deleteValue;
347
+ }).forEach(column => {
345
348
  const field = column.field;
346
349
  const value = apiRef.current.getCellValue(id, field);
347
350
  const newValue = deleteValue ? getDefaultCellValue(column) : initialValue ?? value;
package/modern/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v7.29.8
2
+ * @mui/x-data-grid v7.29.9
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  'use client';
3
3
 
4
+ /* eslint-disable @typescript-eslint/no-use-before-define */
4
5
  var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
6
  var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
6
7
  Object.defineProperty(exports, "__esModule", {
@@ -9,10 +10,10 @@ Object.defineProperty(exports, "__esModule", {
9
10
  exports.GridScrollArea = void 0;
10
11
  var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
11
12
  var React = _interopRequireWildcard(require("react"));
12
- var _clsx = _interopRequireDefault(require("clsx"));
13
13
  var _utils = require("@mui/utils");
14
14
  var _system = require("@mui/system");
15
15
  var _fastMemo = require("@mui/x-internals/fastMemo");
16
+ var _forwardRef = require("@mui/x-internals/forwardRef");
16
17
  var _useGridRootProps = require("../hooks/utils/useGridRootProps");
17
18
  var _constants = require("../constants");
18
19
  var _useGridApiContext = require("../hooks/utils/useGridApiContext");
@@ -23,6 +24,7 @@ var _densitySelector = require("../hooks/features/density/densitySelector");
23
24
  var _useTimeout = require("../hooks/utils/useTimeout");
24
25
  var _gridColumnsUtils = require("../hooks/features/columns/gridColumnsUtils");
25
26
  var _createSelector = require("../utils/createSelector");
27
+ var _gridRowsMetaSelector = require("../hooks/features/rows/gridRowsMetaSelector");
26
28
  var _jsxRuntime = require("react/jsx-runtime");
27
29
  const CLIFF = 1;
28
30
  const SLOP = 1.5;
@@ -43,18 +45,39 @@ const GridScrollAreaRawRoot = (0, _system.styled)('div', {
43
45
  [`&.${_constants.gridClasses['scrollArea--left']}`]: styles['scrollArea--left']
44
46
  }, {
45
47
  [`&.${_constants.gridClasses['scrollArea--right']}`]: styles['scrollArea--right']
48
+ }, {
49
+ [`&.${_constants.gridClasses['scrollArea--up']}`]: styles['scrollArea--up']
50
+ }, {
51
+ [`&.${_constants.gridClasses['scrollArea--down']}`]: styles['scrollArea--down']
46
52
  }, styles.scrollArea]
47
53
  })(() => ({
48
54
  position: 'absolute',
49
- top: 0,
50
55
  zIndex: 101,
51
- width: 20,
52
- bottom: 0,
56
+ // Horizontal scroll areas
53
57
  [`&.${_constants.gridClasses['scrollArea--left']}`]: {
54
- left: 0
58
+ top: 0,
59
+ left: 0,
60
+ width: 20,
61
+ bottom: 0
55
62
  },
56
63
  [`&.${_constants.gridClasses['scrollArea--right']}`]: {
57
- right: 0
64
+ top: 0,
65
+ right: 0,
66
+ width: 20,
67
+ bottom: 0
68
+ },
69
+ // Vertical scroll areas
70
+ [`&.${_constants.gridClasses['scrollArea--up']}`]: {
71
+ top: 0,
72
+ left: 0,
73
+ right: 0,
74
+ height: 20
75
+ },
76
+ [`&.${_constants.gridClasses['scrollArea--down']}`]: {
77
+ bottom: 0,
78
+ left: 0,
79
+ right: 0,
80
+ height: 20
58
81
  }
59
82
  }));
60
83
  const offsetSelector = (0, _createSelector.createSelectorV8)(_gridDimensionsSelectors.gridDimensionsSelector, (dimensions, direction) => {
@@ -64,19 +87,27 @@ const offsetSelector = (0, _createSelector.createSelectorV8)(_gridDimensionsSele
64
87
  if (direction === 'right') {
65
88
  return dimensions.rightPinnedWidth + (dimensions.hasScrollX ? dimensions.scrollbarSize : 0);
66
89
  }
90
+ // For vertical scroll areas, we don't need horizontal offset
67
91
  return 0;
68
92
  });
69
93
  function GridScrollAreaWrapper(props) {
70
94
  const apiRef = (0, _useGridApiContext.useGridApiContext)();
71
- const [dragging, setDragging] = React.useState(false);
72
- (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderDragStart', () => setDragging(true));
73
- (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderDragEnd', () => setDragging(false));
74
- if (!dragging) {
95
+ const [dragDirection, setDragDirection] = React.useState('none');
96
+
97
+ // Listen for both column and row drag events
98
+ (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderDragStart', () => setDragDirection('horizontal'));
99
+ (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'columnHeaderDragEnd', () => setDragDirection('none'));
100
+ (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowDragStart', () => setDragDirection('vertical'));
101
+ (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'rowDragEnd', () => setDragDirection('none'));
102
+ if (dragDirection === 'none') {
75
103
  return null;
76
104
  }
77
- return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridScrollAreaContent, (0, _extends2.default)({}, props));
105
+ if (dragDirection === 'horizontal') {
106
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridHorizontalScrollAreaContent, (0, _extends2.default)({}, props));
107
+ }
108
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridVerticalScrollAreaContent, (0, _extends2.default)({}, props));
78
109
  }
79
- function GridScrollAreaContent(props) {
110
+ function GridHorizontalScrollAreaContent(props) {
80
111
  const {
81
112
  scrollDirection,
82
113
  scrollPosition
@@ -100,26 +131,17 @@ function GridScrollAreaContent(props) {
100
131
  }
101
132
  return false;
102
133
  };
103
- const [canScrollMore, setCanScrollMore] = React.useState(getCanScrollMore);
104
134
  const rootProps = (0, _useGridRootProps.useGridRootProps)();
105
- const ownerState = (0, _extends2.default)({}, rootProps, {
106
- scrollDirection
107
- });
108
- const classes = useUtilityClasses(ownerState);
109
135
  const totalHeaderHeight = (0, _gridColumnsUtils.getTotalHeaderHeight)(apiRef, rootProps);
110
136
  const headerHeight = Math.floor(rootProps.columnHeaderHeight * densityFactor);
111
- const style = {
137
+ const style = (0, _extends2.default)({
112
138
  height: headerHeight,
113
139
  top: totalHeaderHeight - headerHeight
114
- };
115
- if (scrollDirection === 'left') {
116
- style.left = sideOffset;
117
- } else if (scrollDirection === 'right') {
118
- style.right = sideOffset;
119
- }
120
- const handleScrolling = () => {
121
- setCanScrollMore(getCanScrollMore);
122
- };
140
+ }, scrollDirection === 'left' ? {
141
+ left: sideOffset
142
+ } : {}, scrollDirection === 'right' ? {
143
+ right: sideOffset
144
+ } : {});
123
145
  const handleDragOver = (0, _utils.unstable_useEventCallback)(event => {
124
146
  let offset;
125
147
 
@@ -142,16 +164,98 @@ function GridScrollAreaContent(props) {
142
164
  });
143
165
  });
144
166
  });
167
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridScrollAreaContent, (0, _extends2.default)({}, props, {
168
+ ref: rootRef,
169
+ getCanScrollMore: getCanScrollMore,
170
+ style: style,
171
+ handleDragOver: handleDragOver
172
+ }));
173
+ }
174
+ function GridVerticalScrollAreaContent(props) {
175
+ const {
176
+ scrollDirection,
177
+ scrollPosition
178
+ } = props;
179
+ const rootRef = React.useRef(null);
180
+ const apiRef = (0, _useGridApiContext.useGridApiContext)();
181
+ const timeout = (0, _useTimeout.useTimeout)();
182
+ const rowsMeta = (0, _useGridSelector.useGridSelector)(apiRef, _gridRowsMetaSelector.gridRowsMetaSelector);
183
+ const getCanScrollMore = () => {
184
+ const dimensions = (0, _gridDimensionsSelectors.gridDimensionsSelector)(apiRef.current.state);
185
+ if (scrollDirection === 'up') {
186
+ // Only render if the user has not reached yet the top of the list
187
+ return scrollPosition.current.top > 0;
188
+ }
189
+ if (scrollDirection === 'down') {
190
+ // Only render if the user has not reached yet the bottom of the list
191
+ const totalRowsHeight = rowsMeta.currentPageTotalHeight || 0;
192
+ const maxScrollTop = totalRowsHeight - dimensions.viewportInnerSize.height - dimensions.scrollbarSize;
193
+ return scrollPosition.current.top < maxScrollTop;
194
+ }
195
+ return false;
196
+ };
197
+ const rootProps = (0, _useGridRootProps.useGridRootProps)();
198
+ const totalHeaderHeight = (0, _gridColumnsUtils.getTotalHeaderHeight)(apiRef, rootProps);
199
+ const style = {
200
+ top: scrollDirection === 'up' ? totalHeaderHeight : undefined,
201
+ bottom: scrollDirection === 'down' ? 0 : undefined
202
+ };
203
+ const handleDragOver = (0, _utils.unstable_useEventCallback)(event => {
204
+ let offset;
205
+
206
+ // Prevents showing the forbidden cursor
207
+ event.preventDefault();
208
+ if (scrollDirection === 'up') {
209
+ offset = event.clientY - rootRef.current.getBoundingClientRect().bottom;
210
+ } else if (scrollDirection === 'down') {
211
+ offset = Math.max(1, event.clientY - rootRef.current.getBoundingClientRect().top);
212
+ } else {
213
+ throw new Error('MUI X: Wrong drag direction');
214
+ }
215
+ offset = (offset - CLIFF) * SLOP + CLIFF;
216
+
217
+ // Avoid freeze and inertia.
218
+ timeout.start(0, () => {
219
+ apiRef.current.scroll({
220
+ left: scrollPosition.current.left,
221
+ top: scrollPosition.current.top + offset
222
+ });
223
+ });
224
+ });
225
+ return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridScrollAreaContent, (0, _extends2.default)({}, props, {
226
+ ref: rootRef,
227
+ getCanScrollMore: getCanScrollMore,
228
+ style: style,
229
+ handleDragOver: handleDragOver
230
+ }));
231
+ }
232
+ const GridScrollAreaContent = (0, _forwardRef.forwardRef)(function GridScrollAreaContent(props, ref) {
233
+ const {
234
+ scrollDirection,
235
+ getCanScrollMore,
236
+ style,
237
+ handleDragOver
238
+ } = props;
239
+ const apiRef = (0, _useGridApiContext.useGridApiContext)();
240
+ const [canScrollMore, setCanScrollMore] = React.useState(getCanScrollMore);
241
+ const rootProps = (0, _useGridRootProps.useGridRootProps)();
242
+ const ownerState = (0, _extends2.default)({}, rootProps, {
243
+ scrollDirection
244
+ });
245
+ const classes = useUtilityClasses(ownerState);
246
+ const handleScrolling = () => {
247
+ setCanScrollMore(getCanScrollMore);
248
+ };
145
249
  (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'scrollPositionChange', handleScrolling);
146
250
  if (!canScrollMore) {
147
251
  return null;
148
252
  }
149
253
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(GridScrollAreaRawRoot, {
150
- ref: rootRef,
151
- className: (0, _clsx.default)(classes.root),
254
+ ref: ref,
255
+ className: classes.root,
152
256
  ownerState: ownerState,
153
257
  onDragOver: handleDragOver,
154
258
  style: style
155
259
  });
156
- }
260
+ });
157
261
  const GridScrollArea = exports.GridScrollArea = (0, _fastMemo.fastMemo)(GridScrollAreaWrapper);
@@ -103,6 +103,10 @@ function GridVirtualScroller(props) {
103
103
  scrollDirection: "left"
104
104
  }, getScrollAreaProps())), /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridScrollArea.GridScrollArea, (0, _extends2.default)({
105
105
  scrollDirection: "right"
106
+ }, getScrollAreaProps())), /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridScrollArea.GridScrollArea, (0, _extends2.default)({
107
+ scrollDirection: "up"
108
+ }, getScrollAreaProps())), /*#__PURE__*/(0, _jsxRuntime.jsx)(_GridScrollArea.GridScrollArea, (0, _extends2.default)({
109
+ scrollDirection: "down"
106
110
  }, getScrollAreaProps())), /*#__PURE__*/(0, _jsxRuntime.jsxs)(Scroller, (0, _extends2.default)({
107
111
  className: classes.scroller
108
112
  }, getScrollerProps(), {
@@ -9,4 +9,4 @@ var _utils = require("@mui/utils");
9
9
  function getDataGridUtilityClass(slot) {
10
10
  return (0, _utils.unstable_generateUtilityClass)('MuiDataGrid', slot);
11
11
  }
12
- const gridClasses = exports.gridClasses = (0, _utils.unstable_generateUtilityClasses)('MuiDataGrid', ['actionsCell', 'aggregationColumnHeader', 'aggregationColumnHeader--alignLeft', 'aggregationColumnHeader--alignCenter', 'aggregationColumnHeader--alignRight', 'aggregationColumnHeaderLabel', 'autoHeight', 'autosizing', 'booleanCell', 'cell--editable', 'cell--editing', 'cell--flex', 'cell--textCenter', 'cell--textLeft', 'cell--textRight', 'cell--rangeTop', 'cell--rangeBottom', 'cell--rangeLeft', 'cell--rangeRight', 'cell--pinnedLeft', 'cell--pinnedRight', 'cell--selectionMode', 'cell', 'cellCheckbox', 'cellEmpty', 'cellSkeleton', 'cellOffsetLeft', 'checkboxInput', 'columnHeader', 'columnHeader--alignCenter', 'columnHeader--alignLeft', 'columnHeader--alignRight', 'columnHeader--dragging', 'columnHeader--moving', 'columnHeader--numeric', 'columnHeader--sortable', 'columnHeader--sorted', 'columnHeader--filtered', 'columnHeader--pinnedLeft', 'columnHeader--pinnedRight', 'columnHeader--last', 'columnHeader--lastUnpinned', 'columnHeader--siblingFocused', 'columnHeaderCheckbox', 'columnHeaderDraggableContainer', 'columnHeaderTitle', 'columnHeaderTitleContainer', 'columnHeaderTitleContainerContent', 'columnHeader--filledGroup', 'columnHeader--emptyGroup', 'columnHeaders', 'columnSeparator--resizable', 'columnSeparator--resizing', 'columnSeparator--sideLeft', 'columnSeparator--sideRight', 'columnSeparator', 'columnsManagement', 'columnsManagementRow', 'columnsManagementHeader', 'columnsManagementSearchInput', 'columnsManagementFooter', 'container--top', 'container--bottom', 'detailPanel', 'detailPanels', 'detailPanelToggleCell', 'detailPanelToggleCell--expanded', 'footerCell', 'panel', 'panelHeader', 'panelWrapper', 'panelContent', 'panelFooter', 'paper', 'editBooleanCell', 'editInputCell', 'filler', 'filler--borderBottom', 'filler--pinnedLeft', 'filler--pinnedRight', 'filterForm', 'filterFormDeleteIcon', 'filterFormLogicOperatorInput', 'filterFormColumnInput', 'filterFormOperatorInput', 'filterFormValueInput', 'filterIcon', 'footerContainer', 'headerFilterRow', 'iconButtonContainer', 'iconSeparator', 'main', 'main--hasPinnedRight', 'main--hasSkeletonLoadingOverlay', 'menu', 'menuIcon', 'menuIconButton', 'menuOpen', 'menuList', 'overlay', 'overlayWrapper', 'overlayWrapperInner', 'root', 'root--densityStandard', 'root--densityComfortable', 'root--densityCompact', 'root--disableUserSelection', 'root--noToolbar', 'row', 'row--editable', 'row--editing', 'row--firstVisible', 'row--lastVisible', 'row--dragging', 'row--dynamicHeight', 'row--detailPanelExpanded', 'row--borderBottom', 'rowReorderCellPlaceholder', 'rowCount', 'rowReorderCellContainer', 'rowReorderCell', 'rowReorderCell--draggable', 'rowSkeleton', 'scrollArea--left', 'scrollArea--right', 'scrollArea', 'scrollbar', 'scrollbar--vertical', 'scrollbar--horizontal', 'scrollbarFiller', 'scrollbarFiller--header', 'scrollbarFiller--borderTop', 'scrollbarFiller--borderBottom', 'scrollbarFiller--pinnedRight', 'selectedRowCount', 'sortButton', 'sortIcon', 'toolbarContainer', 'toolbarFilterList', 'virtualScroller', 'virtualScroller--hasScrollX', 'virtualScrollerContent', 'virtualScrollerContent--overflowed', 'virtualScrollerRenderZone', 'pinnedColumns', 'withVerticalBorder', 'withBorderColor', 'cell--withRightBorder', 'cell--withLeftBorder', 'columnHeader--withRightBorder', 'columnHeader--withLeftBorder', 'treeDataGroupingCell', 'treeDataGroupingCellToggle', 'treeDataGroupingCellLoadingContainer', 'groupingCriteriaCell', 'groupingCriteriaCellToggle', 'groupingCriteriaCellLoadingContainer', 'pinnedRows', 'pinnedRows--top', 'pinnedRows--bottom', 'pinnedRowsRenderZone']);
12
+ const gridClasses = exports.gridClasses = (0, _utils.unstable_generateUtilityClasses)('MuiDataGrid', ['actionsCell', 'aggregationColumnHeader', 'aggregationColumnHeader--alignLeft', 'aggregationColumnHeader--alignCenter', 'aggregationColumnHeader--alignRight', 'aggregationColumnHeaderLabel', 'autoHeight', 'autosizing', 'booleanCell', 'cell--editable', 'cell--editing', 'cell--flex', 'cell--textCenter', 'cell--textLeft', 'cell--textRight', 'cell--rangeTop', 'cell--rangeBottom', 'cell--rangeLeft', 'cell--rangeRight', 'cell--pinnedLeft', 'cell--pinnedRight', 'cell--selectionMode', 'cell', 'cellCheckbox', 'cellEmpty', 'cellSkeleton', 'cellOffsetLeft', 'checkboxInput', 'columnHeader', 'columnHeader--alignCenter', 'columnHeader--alignLeft', 'columnHeader--alignRight', 'columnHeader--dragging', 'columnHeader--moving', 'columnHeader--numeric', 'columnHeader--sortable', 'columnHeader--sorted', 'columnHeader--filtered', 'columnHeader--pinnedLeft', 'columnHeader--pinnedRight', 'columnHeader--last', 'columnHeader--lastUnpinned', 'columnHeader--siblingFocused', 'columnHeaderCheckbox', 'columnHeaderDraggableContainer', 'columnHeaderTitle', 'columnHeaderTitleContainer', 'columnHeaderTitleContainerContent', 'columnHeader--filledGroup', 'columnHeader--emptyGroup', 'columnHeaders', 'columnSeparator--resizable', 'columnSeparator--resizing', 'columnSeparator--sideLeft', 'columnSeparator--sideRight', 'columnSeparator', 'columnsManagement', 'columnsManagementRow', 'columnsManagementHeader', 'columnsManagementSearchInput', 'columnsManagementFooter', 'container--top', 'container--bottom', 'detailPanel', 'detailPanels', 'detailPanelToggleCell', 'detailPanelToggleCell--expanded', 'footerCell', 'panel', 'panelHeader', 'panelWrapper', 'panelContent', 'panelFooter', 'paper', 'editBooleanCell', 'editInputCell', 'filler', 'filler--borderBottom', 'filler--pinnedLeft', 'filler--pinnedRight', 'filterForm', 'filterFormDeleteIcon', 'filterFormLogicOperatorInput', 'filterFormColumnInput', 'filterFormOperatorInput', 'filterFormValueInput', 'filterIcon', 'footerContainer', 'headerFilterRow', 'iconButtonContainer', 'iconSeparator', 'main', 'main--hasPinnedRight', 'main--hasSkeletonLoadingOverlay', 'menu', 'menuIcon', 'menuIconButton', 'menuOpen', 'menuList', 'overlay', 'overlayWrapper', 'overlayWrapperInner', 'root', 'root--densityStandard', 'root--densityComfortable', 'root--densityCompact', 'root--disableUserSelection', 'root--noToolbar', 'row', 'row--editable', 'row--editing', 'row--firstVisible', 'row--lastVisible', 'row--dragging', 'row--dynamicHeight', 'row--detailPanelExpanded', 'row--borderBottom', 'rowReorderCellPlaceholder', 'rowCount', 'rowReorderCellContainer', 'rowReorderCell', 'rowReorderCell--draggable', 'rowSkeleton', 'scrollArea--left', 'scrollArea--right', 'scrollArea--up', 'scrollArea--down', 'scrollArea', 'scrollbar', 'scrollbar--vertical', 'scrollbar--horizontal', 'scrollbarFiller', 'scrollbarFiller--header', 'scrollbarFiller--borderTop', 'scrollbarFiller--borderBottom', 'scrollbarFiller--pinnedRight', 'selectedRowCount', 'sortButton', 'sortIcon', 'toolbarContainer', 'toolbarFilterList', 'virtualScroller', 'virtualScroller--hasScrollX', 'virtualScrollerContent', 'virtualScrollerContent--overflowed', 'virtualScrollerRenderZone', 'pinnedColumns', 'withVerticalBorder', 'withBorderColor', 'cell--withRightBorder', 'cell--withLeftBorder', 'columnHeader--withRightBorder', 'columnHeader--withLeftBorder', 'treeDataGroupingCell', 'treeDataGroupingCellToggle', 'treeDataGroupingCellLoadingContainer', 'groupingCriteriaCell', 'groupingCriteriaCellToggle', 'groupingCriteriaCellLoadingContainer', 'pinnedRows', 'pinnedRows--top', 'pinnedRows--bottom', 'pinnedRowsRenderZone']);
@@ -349,7 +349,10 @@ const useGridRowEditing = (apiRef, props) => {
349
349
  if (fieldToFocus) {
350
350
  apiRef.current.setCellFocus(id, fieldToFocus);
351
351
  }
352
- columns.filter(column => column.editable && !!column.preProcessEditCellProps && deleteValue).forEach(column => {
352
+ columns.filter(column => {
353
+ const isCellEditable = apiRef.current.getCellParams(id, column.field).isEditable;
354
+ return isCellEditable && column.editable && !!column.preProcessEditCellProps && deleteValue;
355
+ }).forEach(column => {
353
356
  const field = column.field;
354
357
  const value = apiRef.current.getCellValue(id, field);
355
358
  const newValue = deleteValue ? (0, _utils3.getDefaultCellValue)(column) : initialValue ?? value;
package/node/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v7.29.8
2
+ * @mui/x-data-grid v7.29.9
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mui/x-data-grid",
3
- "version": "7.29.8",
3
+ "version": "7.29.9",
4
4
  "description": "The Community plan edition of the Data Grid components (MUI X).",
5
5
  "author": "MUI Team",
6
6
  "main": "./node/index.js",