@mui/x-data-grid-pro 6.14.0 → 6.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +83 -0
- package/DataGridPro/DataGridPro.js +20 -0
- package/DataGridPro/useDataGridProComponent.js +3 -1
- package/DataGridPro/useDataGridProProps.js +2 -0
- package/components/headerFiltering/GridHeaderFilterCell.js +16 -2
- package/components/headerFiltering/GridHeaderFilterMenu.js +1 -1
- package/hooks/features/columnHeaders/useGridColumnHeaders.js +19 -2
- package/hooks/features/columnPinning/useGridColumnPinning.js +1 -44
- package/hooks/features/columnResize/gridColumnResizeApi.d.ts +44 -0
- package/hooks/features/columnResize/gridColumnResizeApi.js +10 -0
- package/hooks/features/columnResize/index.d.ts +1 -0
- package/hooks/features/columnResize/index.js +2 -1
- package/hooks/features/columnResize/useGridColumnResize.d.ts +1 -1
- package/hooks/features/columnResize/useGridColumnResize.js +236 -56
- package/index.js +1 -1
- package/legacy/DataGridPro/DataGridPro.js +20 -0
- package/legacy/DataGridPro/useDataGridProComponent.js +3 -1
- package/legacy/DataGridPro/useDataGridProProps.js +2 -0
- package/legacy/components/headerFiltering/GridHeaderFilterCell.js +17 -3
- package/legacy/components/headerFiltering/GridHeaderFilterMenu.js +1 -1
- package/legacy/hooks/features/columnHeaders/useGridColumnHeaders.js +22 -8
- package/legacy/hooks/features/columnPinning/useGridColumnPinning.js +1 -44
- package/legacy/hooks/features/columnResize/gridColumnResizeApi.js +10 -0
- package/legacy/hooks/features/columnResize/index.js +2 -1
- package/legacy/hooks/features/columnResize/useGridColumnResize.js +279 -57
- package/legacy/index.js +1 -1
- package/legacy/models/index.js +1 -0
- package/legacy/utils/domUtils.js +12 -0
- package/legacy/utils/releaseInfo.js +1 -1
- package/models/dataGridProProps.d.ts +15 -0
- package/models/gridApiPro.d.ts +2 -2
- package/models/index.d.ts +1 -0
- package/models/index.js +1 -0
- package/modern/DataGridPro/DataGridPro.js +20 -0
- package/modern/DataGridPro/useDataGridProComponent.js +3 -1
- package/modern/DataGridPro/useDataGridProProps.js +2 -0
- package/modern/components/headerFiltering/GridHeaderFilterCell.js +15 -2
- package/modern/components/headerFiltering/GridHeaderFilterMenu.js +1 -1
- package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +18 -1
- package/modern/hooks/features/columnPinning/useGridColumnPinning.js +1 -43
- package/modern/hooks/features/columnResize/gridColumnResizeApi.js +10 -0
- package/modern/hooks/features/columnResize/index.js +2 -1
- package/modern/hooks/features/columnResize/useGridColumnResize.js +225 -52
- package/modern/index.js +1 -1
- package/modern/models/index.js +1 -0
- package/modern/utils/domUtils.js +10 -0
- package/modern/utils/releaseInfo.js +1 -1
- package/node/DataGridPro/DataGridPro.js +20 -0
- package/node/DataGridPro/useDataGridProComponent.js +2 -0
- package/node/DataGridPro/useDataGridProProps.js +2 -0
- package/node/components/headerFiltering/GridHeaderFilterCell.js +15 -2
- package/node/components/headerFiltering/GridHeaderFilterMenu.js +1 -1
- package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +18 -1
- package/node/hooks/features/columnPinning/useGridColumnPinning.js +0 -42
- package/node/hooks/features/columnResize/gridColumnResizeApi.js +17 -0
- package/node/hooks/features/columnResize/index.js +11 -0
- package/node/hooks/features/columnResize/useGridColumnResize.js +222 -49
- package/node/index.js +1 -1
- package/node/models/index.js +11 -0
- package/node/utils/domUtils.js +12 -0
- package/node/utils/releaseInfo.js +1 -1
- package/package.json +2 -2
- package/utils/domUtils.d.ts +2 -0
- package/utils/domUtils.js +10 -0
- package/utils/releaseInfo.js +1 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import * as React from 'react';
|
|
3
3
|
import { unstable_ownerDocument as ownerDocument, unstable_useEventCallback as useEventCallback } from '@mui/utils';
|
|
4
|
-
import { gridClasses, useGridApiEventHandler, useGridApiOptionHandler, useGridNativeEventListener, useGridLogger } from '@mui/x-data-grid';
|
|
5
|
-
import { clamp, findParentElementFromClassName } from '@mui/x-data-grid/internals';
|
|
4
|
+
import { gridClasses, useGridApiEventHandler, useGridApiOptionHandler, useGridApiMethod, useGridNativeEventListener, useGridLogger, useGridSelector, gridVirtualizationColumnEnabledSelector } from '@mui/x-data-grid';
|
|
5
|
+
import { clamp, findParentElementFromClassName, gridColumnsStateSelector, useOnMount, useTimeout, createControllablePromise } from '@mui/x-data-grid/internals';
|
|
6
6
|
import { useTheme } from '@mui/material/styles';
|
|
7
|
-
import { findGridCellElementsFromCol, getFieldFromHeaderElem, findHeaderElementFromField, findGroupHeaderElementsFromField } from '../../../utils/domUtils';
|
|
7
|
+
import { findGridCellElementsFromCol, getFieldFromHeaderElem, findHeaderElementFromField, findGroupHeaderElementsFromField, findGridHeader, findGridCells } from '../../../utils/domUtils';
|
|
8
|
+
import { DEFAULT_GRID_AUTOSIZE_OPTIONS } from './gridColumnResizeApi';
|
|
8
9
|
// TODO: remove support for Safari < 13.
|
|
9
10
|
// https://caniuse.com/#search=touch-action
|
|
10
11
|
//
|
|
@@ -73,12 +74,104 @@ function getResizeDirection(element, direction) {
|
|
|
73
74
|
}
|
|
74
75
|
return side;
|
|
75
76
|
}
|
|
77
|
+
function preventClick(event) {
|
|
78
|
+
event.preventDefault();
|
|
79
|
+
event.stopImmediatePropagation();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Checker that returns a promise that resolves when the column virtualization
|
|
84
|
+
* is disabled.
|
|
85
|
+
*/
|
|
86
|
+
function useColumnVirtualizationDisabled(apiRef) {
|
|
87
|
+
const promise = React.useRef();
|
|
88
|
+
const selector = () => gridVirtualizationColumnEnabledSelector(apiRef);
|
|
89
|
+
const value = useGridSelector(apiRef, selector);
|
|
90
|
+
React.useEffect(() => {
|
|
91
|
+
if (promise.current && value === false) {
|
|
92
|
+
promise.current.resolve();
|
|
93
|
+
promise.current = undefined;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
const asyncCheck = () => {
|
|
97
|
+
if (!promise.current) {
|
|
98
|
+
if (selector() === false) {
|
|
99
|
+
return Promise.resolve();
|
|
100
|
+
}
|
|
101
|
+
promise.current = createControllablePromise();
|
|
102
|
+
}
|
|
103
|
+
return promise.current;
|
|
104
|
+
};
|
|
105
|
+
return asyncCheck;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Basic statistical outlier detection, checks if the value is `F * IQR` away from
|
|
110
|
+
* the Q1 and Q3 boundaries. IQR: interquartile range.
|
|
111
|
+
*/
|
|
112
|
+
function excludeOutliers(inputValues, factor) {
|
|
113
|
+
if (inputValues.length < 4) {
|
|
114
|
+
return inputValues;
|
|
115
|
+
}
|
|
116
|
+
const values = inputValues.slice();
|
|
117
|
+
values.sort((a, b) => a - b);
|
|
118
|
+
const q1 = values[Math.floor(values.length * 0.25)];
|
|
119
|
+
const q3 = values[Math.floor(values.length * 0.75) - 1];
|
|
120
|
+
const iqr = q3 - q1;
|
|
121
|
+
|
|
122
|
+
// We make a small adjustment if `iqr < 5` for the cases where the IQR is
|
|
123
|
+
// very small (e.g. zero) due to very close by values in the input data.
|
|
124
|
+
// Otherwise, with an IQR of `0`, anything outside that would be considered
|
|
125
|
+
// an outlier, but it makes more sense visually to allow for this 5px variance
|
|
126
|
+
// rather than showing a cropped cell.
|
|
127
|
+
const deviation = iqr < 5 ? 5 : iqr * factor;
|
|
128
|
+
return values.filter(v => v > q1 - deviation && v < q3 + deviation);
|
|
129
|
+
}
|
|
130
|
+
function extractColumnWidths(apiRef, options, columns) {
|
|
131
|
+
const widthByField = {};
|
|
132
|
+
columns.forEach(column => {
|
|
133
|
+
const cells = findGridCells(apiRef.current, column.field);
|
|
134
|
+
const widths = cells.map(cell => {
|
|
135
|
+
var _getAttribute, _cell$firstElementChi, _cell$firstElementChi2;
|
|
136
|
+
const id = (_getAttribute = cell.parentElement.getAttribute('data-id')) != null ? _getAttribute : '';
|
|
137
|
+
const hasAutoHeight = apiRef.current.rowHasAutoHeight(id);
|
|
138
|
+
if (hasAutoHeight) {
|
|
139
|
+
var _computedWidth;
|
|
140
|
+
return (_computedWidth = column.computedWidth) != null ? _computedWidth : column.width;
|
|
141
|
+
}
|
|
142
|
+
const style = window.getComputedStyle(cell, null);
|
|
143
|
+
const paddingWidth = parseInt(style.paddingLeft, 10) + parseInt(style.paddingRight, 10);
|
|
144
|
+
const contentWidth = ((_cell$firstElementChi = (_cell$firstElementChi2 = cell.firstElementChild) == null ? void 0 : _cell$firstElementChi2.scrollWidth) != null ? _cell$firstElementChi : -1) + 1;
|
|
145
|
+
return paddingWidth + contentWidth;
|
|
146
|
+
});
|
|
147
|
+
const filteredWidths = options.includeOutliers ? widths : excludeOutliers(widths, options.outliersFactor);
|
|
148
|
+
if (options.includeHeaders) {
|
|
149
|
+
const header = findGridHeader(apiRef.current, column.field);
|
|
150
|
+
if (header) {
|
|
151
|
+
const title = header.querySelector(`.${gridClasses.columnHeaderTitle}`);
|
|
152
|
+
const content = header.querySelector(`.${gridClasses.columnHeaderTitleContainerContent}`);
|
|
153
|
+
const element = title != null ? title : content;
|
|
154
|
+
const style = window.getComputedStyle(header, null);
|
|
155
|
+
const paddingWidth = parseInt(style.paddingLeft, 10) + parseInt(style.paddingRight, 10);
|
|
156
|
+
const contentWidth = element.scrollWidth + 1;
|
|
157
|
+
const width = paddingWidth + contentWidth;
|
|
158
|
+
filteredWidths.push(width);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
const hasColumnMin = column.minWidth !== -Infinity && column.minWidth !== undefined;
|
|
162
|
+
const hasColumnMax = column.maxWidth !== Infinity && column.maxWidth !== undefined;
|
|
163
|
+
const min = hasColumnMin ? column.minWidth : 0;
|
|
164
|
+
const max = hasColumnMax ? column.maxWidth : Infinity;
|
|
165
|
+
const maxContent = filteredWidths.length === 0 ? 0 : Math.max(...filteredWidths);
|
|
166
|
+
widthByField[column.field] = clamp(maxContent, min, max);
|
|
167
|
+
});
|
|
168
|
+
return widthByField;
|
|
169
|
+
}
|
|
76
170
|
export const columnResizeStateInitializer = state => _extends({}, state, {
|
|
77
171
|
columnResize: {
|
|
78
172
|
resizingColumnField: ''
|
|
79
173
|
}
|
|
80
174
|
});
|
|
81
|
-
|
|
82
175
|
/**
|
|
83
176
|
* @requires useGridColumns (method, event)
|
|
84
177
|
* TODO: improve experience for last column
|
|
@@ -97,7 +190,7 @@ export const useGridColumnResize = (apiRef, props) => {
|
|
|
97
190
|
// This ref stores the offset between the click and the separator.
|
|
98
191
|
const initialOffsetToSeparator = React.useRef();
|
|
99
192
|
const resizeDirection = React.useRef();
|
|
100
|
-
const stopResizeEventTimeout =
|
|
193
|
+
const stopResizeEventTimeout = useTimeout();
|
|
101
194
|
const touchId = React.useRef();
|
|
102
195
|
const updateWidth = newWidth => {
|
|
103
196
|
logger.debug(`Updating width to ${newWidth} for col ${colDefRef.current.field}`);
|
|
@@ -137,8 +230,7 @@ export const useGridColumnResize = (apiRef, props) => {
|
|
|
137
230
|
apiRef.current.setColumnWidth(colDefRef.current.field, colDefRef.current.width);
|
|
138
231
|
logger.debug(`Updating col ${colDefRef.current.field} with new width: ${colDefRef.current.width}`);
|
|
139
232
|
}
|
|
140
|
-
|
|
141
|
-
stopResizeEventTimeout.current = setTimeout(() => {
|
|
233
|
+
stopResizeEventTimeout.start(0, () => {
|
|
142
234
|
apiRef.current.publishEvent('columnResizeStop', null, nativeEvent);
|
|
143
235
|
});
|
|
144
236
|
};
|
|
@@ -159,44 +251,6 @@ export const useGridColumnResize = (apiRef, props) => {
|
|
|
159
251
|
};
|
|
160
252
|
apiRef.current.publishEvent('columnResize', params, nativeEvent);
|
|
161
253
|
});
|
|
162
|
-
const handleColumnResizeMouseDown = useEventCallback(({
|
|
163
|
-
colDef
|
|
164
|
-
}, event) => {
|
|
165
|
-
var _apiRef$current$colum, _apiRef$current$heade, _apiRef$current$colum2;
|
|
166
|
-
// Only handle left clicks
|
|
167
|
-
if (event.button !== 0) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
// Skip if the column isn't resizable
|
|
172
|
-
if (!event.currentTarget.classList.contains(gridClasses['columnSeparator--resizable'])) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// Avoid text selection
|
|
177
|
-
event.preventDefault();
|
|
178
|
-
logger.debug(`Start Resize on col ${colDef.field}`);
|
|
179
|
-
apiRef.current.publishEvent('columnResizeStart', {
|
|
180
|
-
field: colDef.field
|
|
181
|
-
}, event);
|
|
182
|
-
colDefRef.current = colDef;
|
|
183
|
-
colElementRef.current = (_apiRef$current$colum = apiRef.current.columnHeadersContainerElementRef) == null ? void 0 : _apiRef$current$colum.current.querySelector(`[data-field="${colDef.field}"]`);
|
|
184
|
-
const headerFilterRowElement = (_apiRef$current$heade = apiRef.current.headerFiltersElementRef) == null ? void 0 : _apiRef$current$heade.current;
|
|
185
|
-
if (headerFilterRowElement) {
|
|
186
|
-
headerFilterElementRef.current = headerFilterRowElement.querySelector(`[data-field="${colDef.field}"]`);
|
|
187
|
-
}
|
|
188
|
-
colGroupingElementRef.current = findGroupHeaderElementsFromField((_apiRef$current$colum2 = apiRef.current.columnHeadersContainerElementRef) == null ? void 0 : _apiRef$current$colum2.current, colDef.field);
|
|
189
|
-
colCellElementsRef.current = findGridCellElementsFromCol(colElementRef.current, apiRef.current);
|
|
190
|
-
const doc = ownerDocument(apiRef.current.rootElementRef.current);
|
|
191
|
-
doc.body.style.cursor = 'col-resize';
|
|
192
|
-
resizeDirection.current = getResizeDirection(event.currentTarget, theme.direction);
|
|
193
|
-
initialOffsetToSeparator.current = computeOffsetToSeparator(event.clientX, colElementRef.current.getBoundingClientRect(), resizeDirection.current);
|
|
194
|
-
doc.addEventListener('mousemove', handleResizeMouseMove);
|
|
195
|
-
doc.addEventListener('mouseup', handleResizeMouseUp);
|
|
196
|
-
|
|
197
|
-
// Fixes https://github.com/mui/mui-x/issues/4777
|
|
198
|
-
colElementRef.current.style.pointerEvents = 'none';
|
|
199
|
-
});
|
|
200
254
|
const handleTouchEnd = useEventCallback(nativeEvent => {
|
|
201
255
|
const finger = trackFinger(nativeEvent, touchId.current);
|
|
202
256
|
if (!finger) {
|
|
@@ -226,7 +280,7 @@ export const useGridColumnResize = (apiRef, props) => {
|
|
|
226
280
|
apiRef.current.publishEvent('columnResize', params, nativeEvent);
|
|
227
281
|
});
|
|
228
282
|
const handleTouchStart = useEventCallback(event => {
|
|
229
|
-
var _apiRef$current$
|
|
283
|
+
var _apiRef$current$colum, _apiRef$current$colum2;
|
|
230
284
|
const cellSeparator = findParentElementFromClassName(event.target, gridClasses['columnSeparator--resizable']);
|
|
231
285
|
// Let the event bubble if the target is not a col separator
|
|
232
286
|
if (!cellSeparator) {
|
|
@@ -244,13 +298,13 @@ export const useGridColumnResize = (apiRef, props) => {
|
|
|
244
298
|
colElementRef.current = findParentElementFromClassName(event.target, gridClasses.columnHeader);
|
|
245
299
|
const field = getFieldFromHeaderElem(colElementRef.current);
|
|
246
300
|
const colDef = apiRef.current.getColumn(field);
|
|
247
|
-
colGroupingElementRef.current = findGroupHeaderElementsFromField((_apiRef$current$
|
|
301
|
+
colGroupingElementRef.current = findGroupHeaderElementsFromField((_apiRef$current$colum = apiRef.current.columnHeadersContainerElementRef) == null ? void 0 : _apiRef$current$colum.current, field);
|
|
248
302
|
logger.debug(`Start Resize on col ${colDef.field}`);
|
|
249
303
|
apiRef.current.publishEvent('columnResizeStart', {
|
|
250
304
|
field
|
|
251
305
|
}, event);
|
|
252
306
|
colDefRef.current = colDef;
|
|
253
|
-
colElementRef.current = findHeaderElementFromField((_apiRef$current$
|
|
307
|
+
colElementRef.current = findHeaderElementFromField((_apiRef$current$colum2 = apiRef.current.columnHeadersElementRef) == null ? void 0 : _apiRef$current$colum2.current, colDef.field);
|
|
254
308
|
colCellElementsRef.current = findGridCellElementsFromCol(colElementRef.current, apiRef.current);
|
|
255
309
|
resizeDirection.current = getResizeDirection(event.target, theme.direction);
|
|
256
310
|
initialOffsetToSeparator.current = computeOffsetToSeparator(touch.clientX, colElementRef.current.getBoundingClientRect(), resizeDirection.current);
|
|
@@ -265,6 +319,11 @@ export const useGridColumnResize = (apiRef, props) => {
|
|
|
265
319
|
doc.removeEventListener('mouseup', handleResizeMouseUp);
|
|
266
320
|
doc.removeEventListener('touchmove', handleTouchMove);
|
|
267
321
|
doc.removeEventListener('touchend', handleTouchEnd);
|
|
322
|
+
// The click event runs right after the mouseup event, we want to wait until it
|
|
323
|
+
// has been canceled before removing our handler.
|
|
324
|
+
setTimeout(() => {
|
|
325
|
+
doc.removeEventListener('click', preventClick, true);
|
|
326
|
+
}, 100);
|
|
268
327
|
if (colElementRef.current) {
|
|
269
328
|
colElementRef.current.style.pointerEvents = 'unset';
|
|
270
329
|
}
|
|
@@ -287,21 +346,142 @@ export const useGridColumnResize = (apiRef, props) => {
|
|
|
287
346
|
}));
|
|
288
347
|
apiRef.current.forceUpdate();
|
|
289
348
|
}, [apiRef]);
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
349
|
+
const handleColumnResizeMouseDown = useEventCallback(({
|
|
350
|
+
colDef
|
|
351
|
+
}, event) => {
|
|
352
|
+
var _apiRef$current$colum3, _apiRef$current$heade, _apiRef$current$colum4;
|
|
353
|
+
// Only handle left clicks
|
|
354
|
+
if (event.button !== 0) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Skip if the column isn't resizable
|
|
359
|
+
if (!event.currentTarget.classList.contains(gridClasses['columnSeparator--resizable'])) {
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Avoid text selection
|
|
364
|
+
event.preventDefault();
|
|
365
|
+
logger.debug(`Start Resize on col ${colDef.field}`);
|
|
366
|
+
apiRef.current.publishEvent('columnResizeStart', {
|
|
367
|
+
field: colDef.field
|
|
368
|
+
}, event);
|
|
369
|
+
colDefRef.current = colDef;
|
|
370
|
+
colElementRef.current = (_apiRef$current$colum3 = apiRef.current.columnHeadersContainerElementRef) == null ? void 0 : _apiRef$current$colum3.current.querySelector(`[data-field="${colDef.field}"]`);
|
|
371
|
+
const headerFilterRowElement = (_apiRef$current$heade = apiRef.current.headerFiltersElementRef) == null ? void 0 : _apiRef$current$heade.current;
|
|
372
|
+
if (headerFilterRowElement) {
|
|
373
|
+
headerFilterElementRef.current = headerFilterRowElement.querySelector(`[data-field="${colDef.field}"]`);
|
|
374
|
+
}
|
|
375
|
+
colGroupingElementRef.current = findGroupHeaderElementsFromField((_apiRef$current$colum4 = apiRef.current.columnHeadersContainerElementRef) == null ? void 0 : _apiRef$current$colum4.current, colDef.field);
|
|
376
|
+
colCellElementsRef.current = findGridCellElementsFromCol(colElementRef.current, apiRef.current);
|
|
377
|
+
const doc = ownerDocument(apiRef.current.rootElementRef.current);
|
|
378
|
+
doc.body.style.cursor = 'col-resize';
|
|
379
|
+
resizeDirection.current = getResizeDirection(event.currentTarget, theme.direction);
|
|
380
|
+
initialOffsetToSeparator.current = computeOffsetToSeparator(event.clientX, colElementRef.current.getBoundingClientRect(), resizeDirection.current);
|
|
381
|
+
doc.addEventListener('mousemove', handleResizeMouseMove);
|
|
382
|
+
doc.addEventListener('mouseup', handleResizeMouseUp);
|
|
383
|
+
|
|
384
|
+
// Prevent the click event if we have resized the column.
|
|
385
|
+
// Fixes https://github.com/mui/mui-x/issues/4777
|
|
386
|
+
doc.addEventListener('click', preventClick, true);
|
|
387
|
+
});
|
|
388
|
+
const handleColumnSeparatorDoubleClick = useEventCallback((params, event) => {
|
|
389
|
+
if (props.disableAutosize) {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Only handle left clicks
|
|
394
|
+
if (event.button !== 0) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
const column = apiRef.current.state.columns.lookup[params.field];
|
|
398
|
+
if (column.resizable === false) {
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
apiRef.current.autosizeColumns(_extends({}, props.autosizeOptions, {
|
|
402
|
+
columns: [column.field]
|
|
403
|
+
}));
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* API METHODS
|
|
408
|
+
*/
|
|
409
|
+
|
|
410
|
+
const columnVirtualizationDisabled = useColumnVirtualizationDisabled(apiRef);
|
|
411
|
+
const isAutosizingRef = React.useRef(false);
|
|
412
|
+
const autosizeColumns = React.useCallback(async userOptions => {
|
|
413
|
+
var _apiRef$current$rootE, _userOptions$columns;
|
|
414
|
+
const root = (_apiRef$current$rootE = apiRef.current.rootElementRef) == null ? void 0 : _apiRef$current$rootE.current;
|
|
415
|
+
if (!root) {
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (isAutosizingRef.current) {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
isAutosizingRef.current = true;
|
|
422
|
+
const state = gridColumnsStateSelector(apiRef.current.state);
|
|
423
|
+
const options = _extends({}, DEFAULT_GRID_AUTOSIZE_OPTIONS, userOptions, {
|
|
424
|
+
columns: (_userOptions$columns = userOptions == null ? void 0 : userOptions.columns) != null ? _userOptions$columns : state.orderedFields
|
|
425
|
+
});
|
|
426
|
+
options.columns = options.columns.filter(c => state.columnVisibilityModel[c] !== false);
|
|
427
|
+
const columns = options.columns.map(c => apiRef.current.state.columns.lookup[c]);
|
|
428
|
+
try {
|
|
429
|
+
apiRef.current.unstable_setColumnVirtualization(false);
|
|
430
|
+
await columnVirtualizationDisabled();
|
|
431
|
+
const widthByField = extractColumnWidths(apiRef, options, columns);
|
|
432
|
+
const newColumns = columns.map(column => _extends({}, column, {
|
|
433
|
+
width: widthByField[column.field],
|
|
434
|
+
computedWidth: widthByField[column.field]
|
|
435
|
+
}));
|
|
436
|
+
if (options.expand) {
|
|
437
|
+
var _apiRef$current$getRo, _apiRef$current$getRo2;
|
|
438
|
+
const visibleColumns = state.orderedFields.map(field => state.lookup[field]).filter(c => state.columnVisibilityModel[c.field] !== false);
|
|
439
|
+
const totalWidth = visibleColumns.reduce((total, column) => {
|
|
440
|
+
var _ref, _widthByField$column$;
|
|
441
|
+
return total + ((_ref = (_widthByField$column$ = widthByField[column.field]) != null ? _widthByField$column$ : column.computedWidth) != null ? _ref : column.width);
|
|
442
|
+
}, 0);
|
|
443
|
+
const availableWidth = (_apiRef$current$getRo = (_apiRef$current$getRo2 = apiRef.current.getRootDimensions()) == null ? void 0 : _apiRef$current$getRo2.viewportInnerSize.width) != null ? _apiRef$current$getRo : 0;
|
|
444
|
+
const remainingWidth = availableWidth - totalWidth;
|
|
445
|
+
if (remainingWidth > 0) {
|
|
446
|
+
const widthPerColumn = remainingWidth / (newColumns.length || 1);
|
|
447
|
+
newColumns.forEach(column => {
|
|
448
|
+
column.width += widthPerColumn;
|
|
449
|
+
column.computedWidth += widthPerColumn;
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
apiRef.current.updateColumns(newColumns);
|
|
454
|
+
} finally {
|
|
455
|
+
apiRef.current.unstable_setColumnVirtualization(true);
|
|
456
|
+
isAutosizingRef.current = false;
|
|
457
|
+
}
|
|
458
|
+
}, [apiRef, columnVirtualizationDisabled]);
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* EFFECTS
|
|
462
|
+
*/
|
|
463
|
+
|
|
464
|
+
React.useEffect(() => stopListening, [stopListening]);
|
|
465
|
+
useOnMount(() => {
|
|
466
|
+
if (props.autosizeOnMount) {
|
|
467
|
+
Promise.resolve().then(() => {
|
|
468
|
+
apiRef.current.autosizeColumns(props.autosizeOptions);
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
});
|
|
296
472
|
useGridNativeEventListener(apiRef, () => {
|
|
297
473
|
var _apiRef$current$colum5;
|
|
298
474
|
return (_apiRef$current$colum5 = apiRef.current.columnHeadersElementRef) == null ? void 0 : _apiRef$current$colum5.current;
|
|
299
475
|
}, 'touchstart', handleTouchStart, {
|
|
300
476
|
passive: doesSupportTouchActionNone()
|
|
301
477
|
});
|
|
302
|
-
|
|
303
|
-
|
|
478
|
+
useGridApiMethod(apiRef, {
|
|
479
|
+
autosizeColumns
|
|
480
|
+
}, 'public');
|
|
304
481
|
useGridApiEventHandler(apiRef, 'columnResizeStop', handleResizeStop);
|
|
482
|
+
useGridApiEventHandler(apiRef, 'columnResizeStart', handleResizeStart);
|
|
483
|
+
useGridApiEventHandler(apiRef, 'columnSeparatorMouseDown', handleColumnResizeMouseDown);
|
|
484
|
+
useGridApiEventHandler(apiRef, 'columnSeparatorDoubleClick', handleColumnSeparatorDoubleClick);
|
|
305
485
|
useGridApiOptionHandler(apiRef, 'columnResize', props.onColumnResize);
|
|
306
486
|
useGridApiOptionHandler(apiRef, 'columnWidthChange', props.onColumnWidthChange);
|
|
307
487
|
};
|
package/index.js
CHANGED
|
@@ -69,6 +69,21 @@ DataGridProRaw.propTypes = {
|
|
|
69
69
|
* @default false
|
|
70
70
|
*/
|
|
71
71
|
autoPageSize: PropTypes.bool,
|
|
72
|
+
/**
|
|
73
|
+
* If `true`, columns are autosized after the datagrid is mounted.
|
|
74
|
+
* @default false
|
|
75
|
+
*/
|
|
76
|
+
autosizeOnMount: PropTypes.bool,
|
|
77
|
+
/**
|
|
78
|
+
* The options for autosize when user-initiated.
|
|
79
|
+
*/
|
|
80
|
+
autosizeOptions: PropTypes.shape({
|
|
81
|
+
columns: PropTypes.arrayOf(PropTypes.string),
|
|
82
|
+
expand: PropTypes.bool,
|
|
83
|
+
includeHeaders: PropTypes.bool,
|
|
84
|
+
includeOutliers: PropTypes.bool,
|
|
85
|
+
outliersFactor: PropTypes.number
|
|
86
|
+
}),
|
|
72
87
|
/**
|
|
73
88
|
* Controls the modes of the cells.
|
|
74
89
|
*/
|
|
@@ -148,6 +163,11 @@ DataGridProRaw.propTypes = {
|
|
|
148
163
|
* The row ids to show the detail panel.
|
|
149
164
|
*/
|
|
150
165
|
detailPanelExpandedRowIds: PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string]).isRequired),
|
|
166
|
+
/**
|
|
167
|
+
* If `true`, column autosizing on header separator double-click is disabled.
|
|
168
|
+
* @default false
|
|
169
|
+
*/
|
|
170
|
+
disableAutosize: PropTypes.bool,
|
|
151
171
|
/**
|
|
152
172
|
* If `true`, the filtering will only be applied to the top level rows when grouping rows with the `treeData` prop.
|
|
153
173
|
* @default false
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useGridInitialization, useGridInitializeState, useGridClipboard, useGridColumnMenu, useGridColumns, columnsStateInitializer, useGridDensity, useGridCsvExport, useGridPrintExport, useGridFilter, filterStateInitializer, useGridFocus, useGridKeyboardNavigation, useGridPagination, paginationStateInitializer, useGridPreferencesPanel, useGridEditing, editingStateInitializer, useGridRows, useGridRowsPreProcessors, rowsStateInitializer, useGridRowsMeta, useGridParamsApi, useGridRowSelection, useGridSorting, sortingStateInitializer, useGridScroll, useGridEvents, useGridDimensions, useGridStatePersistence, useGridRowSelectionPreProcessors, useGridColumnSpanning, columnMenuStateInitializer, densityStateInitializer, focusStateInitializer, preferencePanelStateInitializer, rowsMetaStateInitializer, rowSelectionStateInitializer, useGridColumnGrouping, columnGroupsStateInitializer, headerFilteringStateInitializer, useGridHeaderFiltering } from '@mui/x-data-grid/internals';
|
|
1
|
+
import { useGridInitialization, useGridInitializeState, useGridClipboard, useGridColumnMenu, useGridColumns, columnsStateInitializer, useGridDensity, useGridCsvExport, useGridPrintExport, useGridFilter, filterStateInitializer, useGridFocus, useGridKeyboardNavigation, useGridPagination, paginationStateInitializer, useGridPreferencesPanel, useGridEditing, editingStateInitializer, useGridRows, useGridRowsPreProcessors, rowsStateInitializer, useGridRowsMeta, useGridParamsApi, useGridRowSelection, useGridSorting, sortingStateInitializer, useGridScroll, useGridEvents, useGridDimensions, useGridStatePersistence, useGridRowSelectionPreProcessors, useGridColumnSpanning, columnMenuStateInitializer, densityStateInitializer, focusStateInitializer, preferencePanelStateInitializer, rowsMetaStateInitializer, rowSelectionStateInitializer, useGridColumnGrouping, columnGroupsStateInitializer, headerFilteringStateInitializer, useGridHeaderFiltering, virtualizationStateInitializer, useGridVirtualization } from '@mui/x-data-grid/internals';
|
|
2
2
|
// Pro-only features
|
|
3
3
|
import { useGridInfiniteLoader } from '../hooks/features/infiniteLoader/useGridInfiniteLoader';
|
|
4
4
|
import { useGridColumnReorder, columnReorderStateInitializer } from '../hooks/features/columnReorder/useGridColumnReorder';
|
|
@@ -54,6 +54,7 @@ export var useDataGridProComponent = function useDataGridProComponent(inputApiRe
|
|
|
54
54
|
useGridInitializeState(rowsMetaStateInitializer, apiRef, props);
|
|
55
55
|
useGridInitializeState(columnMenuStateInitializer, apiRef, props);
|
|
56
56
|
useGridInitializeState(columnGroupsStateInitializer, apiRef, props);
|
|
57
|
+
useGridInitializeState(virtualizationStateInitializer, apiRef, props);
|
|
57
58
|
useGridHeaderFiltering(apiRef, props);
|
|
58
59
|
useGridTreeData(apiRef);
|
|
59
60
|
useGridKeyboardNavigation(apiRef, props);
|
|
@@ -87,5 +88,6 @@ export var useDataGridProComponent = function useDataGridProComponent(inputApiRe
|
|
|
87
88
|
useGridDimensions(apiRef, props);
|
|
88
89
|
useGridEvents(apiRef, props);
|
|
89
90
|
useGridStatePersistence(apiRef);
|
|
91
|
+
useGridVirtualization(apiRef, props);
|
|
90
92
|
return apiRef;
|
|
91
93
|
};
|
|
@@ -13,6 +13,8 @@ export var DATA_GRID_PRO_PROPS_DEFAULT_VALUES = _extends({}, DATA_GRID_PROPS_DEF
|
|
|
13
13
|
scrollEndThreshold: 80,
|
|
14
14
|
treeData: false,
|
|
15
15
|
defaultGroupingExpansionDepth: 0,
|
|
16
|
+
autosizeOnMount: false,
|
|
17
|
+
disableAutosize: false,
|
|
16
18
|
disableColumnPinning: false,
|
|
17
19
|
keepColumnPositionIfDraggedOutside: false,
|
|
18
20
|
disableChildrenFiltering: false,
|
|
@@ -128,7 +128,7 @@ var GridHeaderFilterCell = /*#__PURE__*/React.forwardRef(function (props, ref) {
|
|
|
128
128
|
}, [apiRef, colDef.field]);
|
|
129
129
|
var onMouseDown = React.useCallback(function (event) {
|
|
130
130
|
if (!hasFocus) {
|
|
131
|
-
if (inputRef.current) {
|
|
131
|
+
if (inputRef.current && inputRef.current.contains(event.target)) {
|
|
132
132
|
inputRef.current.focus();
|
|
133
133
|
}
|
|
134
134
|
apiRef.current.setColumnHeaderFilterFocus(colDef.field, event);
|
|
@@ -175,8 +175,22 @@ var GridHeaderFilterCell = /*#__PURE__*/React.forwardRef(function (props, ref) {
|
|
|
175
175
|
onFocus: function onFocus() {
|
|
176
176
|
return apiRef.current.startHeaderFilterEditMode(colDef.field);
|
|
177
177
|
},
|
|
178
|
-
onBlur: function onBlur() {
|
|
179
|
-
|
|
178
|
+
onBlur: function onBlur(event) {
|
|
179
|
+
var _event$relatedTarget;
|
|
180
|
+
apiRef.current.stopHeaderFilterEditMode();
|
|
181
|
+
// Blurring an input element should reset focus state only if `relatedTarget` is not the header filter cell
|
|
182
|
+
if (!((_event$relatedTarget = event.relatedTarget) != null && _event$relatedTarget.className.includes('columnHeader'))) {
|
|
183
|
+
apiRef.current.setState(function (state) {
|
|
184
|
+
return _extends({}, state, {
|
|
185
|
+
focus: {
|
|
186
|
+
cell: null,
|
|
187
|
+
columnHeader: null,
|
|
188
|
+
columnHeaderFilter: null,
|
|
189
|
+
columnGroupHeader: null
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
}
|
|
180
194
|
},
|
|
181
195
|
label: capitalize(label),
|
|
182
196
|
placeholder: "",
|
|
@@ -28,6 +28,7 @@ var GridHeaderFilterRow = styled('div', {
|
|
|
28
28
|
display: 'flex'
|
|
29
29
|
};
|
|
30
30
|
});
|
|
31
|
+
var filterItemsCache = Object.create(null);
|
|
31
32
|
export var useGridColumnHeaders = function useGridColumnHeaders(props) {
|
|
32
33
|
var apiRef = useGridPrivateApiContext();
|
|
33
34
|
var headerGroupingMaxDepth = props.headerGroupingMaxDepth,
|
|
@@ -51,6 +52,24 @@ export var useGridColumnHeaders = function useGridColumnHeaders(props) {
|
|
|
51
52
|
var filterModel = useGridSelector(apiRef, gridFilterModelSelector);
|
|
52
53
|
var totalHeaderHeight = getTotalHeaderHeight(apiRef, rootProps.columnHeaderHeight) + (disableHeaderFiltering ? 0 : headerHeight);
|
|
53
54
|
var columnHeaderFilterFocus = useGridSelector(apiRef, unstable_gridFocusColumnHeaderFilterSelector);
|
|
55
|
+
var getFilterItem = React.useCallback(function (colDef) {
|
|
56
|
+
var filterModelItem = filterModel == null ? void 0 : filterModel.items.find(function (it) {
|
|
57
|
+
return it.field === colDef.field && it.operator !== 'isAnyOf';
|
|
58
|
+
});
|
|
59
|
+
if (filterModelItem != null) {
|
|
60
|
+
// there's a valid `filterModelItem` for this column
|
|
61
|
+
return filterModelItem;
|
|
62
|
+
}
|
|
63
|
+
var defaultCachedItem = filterItemsCache[colDef.field];
|
|
64
|
+
if (defaultCachedItem != null) {
|
|
65
|
+
// there's a cached `defaultItem` for this column
|
|
66
|
+
return defaultCachedItem;
|
|
67
|
+
}
|
|
68
|
+
// there's no cached `defaultItem` for this column, let's generate one and cache it
|
|
69
|
+
var defaultItem = getGridFilter(colDef);
|
|
70
|
+
filterItemsCache[colDef.field] = defaultItem;
|
|
71
|
+
return defaultItem;
|
|
72
|
+
}, [filterModel]);
|
|
54
73
|
var getColumnFilters = function getColumnFilters(params) {
|
|
55
74
|
var other = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
56
75
|
if (disableHeaderFiltering) {
|
|
@@ -63,8 +82,8 @@ export var useGridColumnHeaders = function useGridColumnHeaders(props) {
|
|
|
63
82
|
var renderedColumns = columnsToRender.renderedColumns,
|
|
64
83
|
firstColumnToRender = columnsToRender.firstColumnToRender;
|
|
65
84
|
var filters = [];
|
|
66
|
-
var
|
|
67
|
-
var _colDef$filterOperato, _colDef$filterOperato2,
|
|
85
|
+
for (var i = 0; i < renderedColumns.length; i += 1) {
|
|
86
|
+
var _colDef$filterOperato, _colDef$filterOperato2, _rootProps$slotProps;
|
|
68
87
|
var colDef = renderedColumns[i];
|
|
69
88
|
var columnIndex = firstColumnToRender + i;
|
|
70
89
|
var hasFocus = (columnHeaderFilterFocus == null ? void 0 : columnHeaderFilterFocus.field) === colDef.field;
|
|
@@ -80,9 +99,7 @@ export var useGridColumnHeaders = function useGridColumnHeaders(props) {
|
|
|
80
99
|
var filterOperators = (_colDef$filterOperato = (_colDef$filterOperato2 = colDef.filterOperators) == null ? void 0 : _colDef$filterOperato2.filter(function (operator) {
|
|
81
100
|
return operator.value !== 'isAnyOf';
|
|
82
101
|
})) != null ? _colDef$filterOperato : [];
|
|
83
|
-
var item = (
|
|
84
|
-
return it.field === colDef.field && it.operator !== 'isAnyOf';
|
|
85
|
-
})) != null ? _filterModel$items$fi : getGridFilter(colDef);
|
|
102
|
+
var item = getFilterItem(colDef);
|
|
86
103
|
filters.push( /*#__PURE__*/_jsx(rootProps.slots.headerFilterCell, _extends({
|
|
87
104
|
colIndex: columnIndex,
|
|
88
105
|
height: headerHeight,
|
|
@@ -96,9 +113,6 @@ export var useGridColumnHeaders = function useGridColumnHeaders(props) {
|
|
|
96
113
|
"data-field": colDef.field,
|
|
97
114
|
item: item
|
|
98
115
|
}, (_rootProps$slotProps = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps.headerFilterCell, other), "".concat(colDef.field, "-filter")));
|
|
99
|
-
};
|
|
100
|
-
for (var i = 0; i < renderedColumns.length; i += 1) {
|
|
101
|
-
_loop();
|
|
102
116
|
}
|
|
103
117
|
return /*#__PURE__*/_jsx(GridHeaderFilterRow, {
|
|
104
118
|
ref: headerFiltersRef,
|
|
@@ -4,7 +4,7 @@ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
|
|
4
4
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import { useTheme } from '@mui/material/styles';
|
|
7
|
-
import { useGridSelector, gridVisibleColumnDefinitionsSelector, gridColumnsTotalWidthSelector, gridColumnPositionsSelector, gridVisibleColumnFieldsSelector,
|
|
7
|
+
import { useGridSelector, gridVisibleColumnDefinitionsSelector, gridColumnsTotalWidthSelector, gridColumnPositionsSelector, gridVisibleColumnFieldsSelector, useGridApiMethod, useGridApiEventHandler, gridColumnFieldsSelector } from '@mui/x-data-grid';
|
|
8
8
|
import { useGridRegisterPipeProcessor } from '@mui/x-data-grid/internals';
|
|
9
9
|
import { GridPinnedPosition } from './gridColumnPinningInterface';
|
|
10
10
|
import { gridPinnedColumnsSelector } from './gridColumnPinningSelector';
|
|
@@ -40,49 +40,6 @@ export var useGridColumnPinning = function useGridColumnPinning(apiRef, props) {
|
|
|
40
40
|
var _props$initialState4;
|
|
41
41
|
var pinnedColumns = useGridSelector(apiRef, gridPinnedColumnsSelector);
|
|
42
42
|
var theme = useTheme();
|
|
43
|
-
// Each visible row (not to be confused with a filter result) is composed of a central .MuiDataGrid-row element
|
|
44
|
-
// and up to two additional .MuiDataGrid-row's, one for the columns pinned to the left and another
|
|
45
|
-
// for those on the right side. When hovering any of these elements, the :hover styles are applied only to
|
|
46
|
-
// the row element that was actually hovered, not its additional siblings. To make it look like a contiguous row,
|
|
47
|
-
// this method adds/removes the .Mui-hovered class to all of the row elements inside one visible row.
|
|
48
|
-
var updateHoveredClassOnSiblingRows = React.useCallback(function (event) {
|
|
49
|
-
var _pinnedColumns$left$l, _pinnedColumns$left, _pinnedColumns$right$, _pinnedColumns$right;
|
|
50
|
-
if (props.disableColumnPinning) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
if (!Array.isArray(pinnedColumns.left) && !Array.isArray(pinnedColumns.right)) {
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
var nbLeftPinnedColumns = (_pinnedColumns$left$l = (_pinnedColumns$left = pinnedColumns.left) == null ? void 0 : _pinnedColumns$left.length) != null ? _pinnedColumns$left$l : 0;
|
|
57
|
-
var nbRightPinnedColumns = (_pinnedColumns$right$ = (_pinnedColumns$right = pinnedColumns.right) == null ? void 0 : _pinnedColumns$right.length) != null ? _pinnedColumns$right$ : 0;
|
|
58
|
-
if (nbLeftPinnedColumns + nbRightPinnedColumns === 0) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
var rowContainer = apiRef.current.virtualScrollerRef.current;
|
|
62
|
-
if (!rowContainer) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
var index = event.currentTarget.dataset.rowindex;
|
|
66
|
-
var rowElements = rowContainer.querySelectorAll(".".concat(gridClasses.row, "[data-rowindex=\"").concat(index, "\"]"));
|
|
67
|
-
rowElements.forEach(function (row) {
|
|
68
|
-
// Ignore rows from other grid inside the hovered row
|
|
69
|
-
if (row.closest(".".concat(gridClasses.virtualScroller)) === apiRef.current.virtualScrollerRef.current) {
|
|
70
|
-
if (event.type === 'mouseenter') {
|
|
71
|
-
row.classList.add('Mui-hovered');
|
|
72
|
-
} else {
|
|
73
|
-
row.classList.remove('Mui-hovered');
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
});
|
|
77
|
-
}, [apiRef, pinnedColumns.left, pinnedColumns.right, props.disableColumnPinning]);
|
|
78
|
-
var handleMouseEnter = React.useCallback(function (params, event) {
|
|
79
|
-
updateHoveredClassOnSiblingRows(event);
|
|
80
|
-
}, [updateHoveredClassOnSiblingRows]);
|
|
81
|
-
var handleMouseLeave = React.useCallback(function (params, event) {
|
|
82
|
-
updateHoveredClassOnSiblingRows(event);
|
|
83
|
-
}, [updateHoveredClassOnSiblingRows]);
|
|
84
|
-
useGridApiEventHandler(apiRef, 'rowMouseEnter', handleMouseEnter);
|
|
85
|
-
useGridApiEventHandler(apiRef, 'rowMouseLeave', handleMouseLeave);
|
|
86
43
|
|
|
87
44
|
/**
|
|
88
45
|
* PRE-PROCESSING
|