@mui/x-data-grid 7.0.0-beta.7 → 7.1.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 +266 -12
- package/DataGrid/DataGrid.js +18 -17
- package/DataGrid/useDataGridProps.js +4 -5
- package/README.md +1 -1
- package/components/GridFooter.js +2 -3
- package/components/GridHeader.js +1 -2
- package/components/GridPagination.d.ts +6 -5
- package/components/GridPagination.js +12 -4
- package/components/GridRow.js +13 -17
- package/components/base/GridFooterPlaceholder.js +1 -2
- package/components/base/GridOverlays.js +3 -6
- package/components/cell/GridActionsCell.js +4 -6
- package/components/cell/GridActionsCellItem.d.ts +8 -25
- package/components/cell/GridActionsCellItem.js +8 -5
- package/components/cell/GridBooleanCell.d.ts +1 -0
- package/components/cell/GridBooleanCell.js +3 -2
- package/components/cell/GridCell.js +7 -8
- package/components/cell/GridEditBooleanCell.js +1 -2
- package/components/cell/GridEditDateCell.js +2 -3
- package/components/cell/GridEditInputCell.js +2 -2
- package/components/cell/GridEditSingleSelectCell.js +5 -8
- package/components/columnHeaders/ColumnHeaderMenuIcon.js +2 -3
- package/components/columnHeaders/GridColumnGroupHeader.js +4 -5
- package/components/columnHeaders/GridColumnHeaderFilterIconButton.js +2 -3
- package/components/columnHeaders/GridColumnHeaderItem.js +8 -7
- package/components/columnHeaders/GridColumnHeaderSortIcon.js +1 -2
- package/components/columnHeaders/GridColumnHeaderTitle.js +2 -3
- package/components/columnHeaders/GridGenericColumnHeaderItem.js +4 -2
- package/components/columnSelection/GridCellCheckboxRenderer.js +3 -5
- package/components/columnSelection/GridHeaderCheckbox.js +1 -2
- package/components/columnsManagement/GridColumnsManagement.js +17 -21
- package/components/containers/GridRoot.js +3 -3
- package/components/menu/GridMenu.js +4 -6
- package/components/menu/columnMenu/GridColumnHeaderMenu.js +1 -1
- package/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.js +2 -3
- package/components/panel/GridColumnsPanel.js +1 -2
- package/components/panel/GridPanel.d.ts +1 -10
- package/components/panel/GridPanel.js +1 -2
- package/components/panel/GridPreferencesPanel.js +2 -3
- package/components/panel/filterPanel/GridFilterForm.js +24 -27
- package/components/panel/filterPanel/GridFilterInputBoolean.d.ts +1 -1
- package/components/panel/filterPanel/GridFilterInputBoolean.js +6 -7
- package/components/panel/filterPanel/GridFilterInputDate.d.ts +1 -1
- package/components/panel/filterPanel/GridFilterInputDate.js +3 -4
- package/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +11 -15
- package/components/panel/filterPanel/GridFilterInputMultipleValue.js +10 -14
- package/components/panel/filterPanel/GridFilterInputSingleSelect.d.ts +1 -1
- package/components/panel/filterPanel/GridFilterInputSingleSelect.js +10 -11
- package/components/panel/filterPanel/GridFilterInputValue.d.ts +1 -1
- package/components/panel/filterPanel/GridFilterInputValue.js +5 -7
- package/components/panel/filterPanel/GridFilterPanel.js +5 -9
- package/components/panel/filterPanel/filterPanelUtils.js +1 -1
- package/components/toolbar/GridToolbarColumnsButton.js +3 -5
- package/components/toolbar/GridToolbarDensitySelector.js +8 -10
- package/components/toolbar/GridToolbarExport.js +2 -2
- package/components/toolbar/GridToolbarExportContainer.js +3 -5
- package/components/toolbar/GridToolbarFilterButton.js +3 -5
- package/components/toolbar/GridToolbarQuickFilter.js +21 -7
- package/components/virtualization/GridVirtualScrollerContent.js +1 -2
- package/components/virtualization/GridVirtualScrollerRenderZone.js +1 -2
- package/hooks/core/strategyProcessing/useGridStrategyProcessing.js +1 -2
- package/hooks/core/useGridApiInitialization.js +4 -6
- package/hooks/features/clipboard/useGridClipboard.js +6 -5
- package/hooks/features/columnGrouping/gridColumnGroupsSelector.js +4 -16
- package/hooks/features/columnGrouping/gridColumnGroupsUtils.js +4 -8
- package/hooks/features/columnGrouping/useGridColumnGrouping.js +12 -23
- package/hooks/features/columnHeaders/useGridColumnHeaders.js +6 -8
- package/hooks/features/columnMenu/useGridColumnMenuSlots.js +2 -2
- package/hooks/features/columnResize/useGridColumnResize.js +9 -19
- package/hooks/features/columns/gridColumnsSelector.js +1 -2
- package/hooks/features/columns/gridColumnsUtils.d.ts +0 -9
- package/hooks/features/columns/gridColumnsUtils.js +2 -22
- package/hooks/features/columns/useGridColumnSpanning.js +1 -2
- package/hooks/features/columns/useGridColumns.js +11 -19
- package/hooks/features/density/densitySelector.d.ts +4 -2
- package/hooks/features/density/densitySelector.js +8 -2
- package/hooks/features/density/densityState.d.ts +1 -4
- package/hooks/features/density/useGridDensity.d.ts +2 -4
- package/hooks/features/density/useGridDensity.js +21 -29
- package/hooks/features/dimensions/useGridDimensions.d.ts +1 -1
- package/hooks/features/dimensions/useGridDimensions.js +6 -7
- package/hooks/features/editing/useGridCellEditing.js +4 -6
- package/hooks/features/editing/useGridEditing.js +1 -2
- package/hooks/features/editing/useGridRowEditing.js +17 -10
- package/hooks/features/export/serializers/csvSerializer.d.ts +2 -0
- package/hooks/features/export/serializers/csvSerializer.js +25 -16
- package/hooks/features/export/useGridCsvExport.js +9 -10
- package/hooks/features/export/useGridPrintExport.js +9 -15
- package/hooks/features/export/utils.js +2 -3
- package/hooks/features/filter/gridFilterSelector.js +15 -22
- package/hooks/features/filter/gridFilterUtils.js +10 -16
- package/hooks/features/filter/useGridFilter.js +9 -15
- package/hooks/features/focus/useGridFocus.js +5 -6
- package/hooks/features/headerFiltering/gridHeaderFilteringSelectors.js +1 -4
- package/hooks/features/headerFiltering/useGridHeaderFiltering.js +12 -17
- package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +1 -2
- package/hooks/features/pagination/gridPaginationSelector.js +1 -2
- package/hooks/features/pagination/useGridPagination.js +2 -3
- package/hooks/features/pagination/useGridPaginationModel.js +6 -11
- package/hooks/features/pagination/useGridRowCount.js +3 -6
- package/hooks/features/preferencesPanel/useGridPreferencesPanel.js +7 -12
- package/hooks/features/rowSelection/useGridRowSelection.js +11 -16
- package/hooks/features/rows/gridRowsSelector.js +11 -19
- package/hooks/features/rows/gridRowsUtils.js +7 -9
- package/hooks/features/rows/useGridParamsApi.js +1 -1
- package/hooks/features/rows/useGridRows.js +4 -13
- package/hooks/features/rows/useGridRowsMeta.js +7 -13
- package/hooks/features/scroll/useGridScroll.js +2 -3
- package/hooks/features/sorting/gridSortingSelector.js +4 -7
- package/hooks/features/sorting/useGridSorting.js +8 -14
- package/hooks/features/virtualization/useGridVirtualScroller.d.ts +1 -1
- package/hooks/features/virtualization/useGridVirtualScroller.js +220 -71
- package/hooks/utils/useGridApiEventHandler.js +5 -10
- package/hooks/utils/useGridNativeEventListener.js +1 -2
- package/index.js +1 -1
- package/internals/index.d.ts +2 -0
- package/internals/index.js +1 -0
- package/internals/utils/useProps.js +1 -2
- package/joy/joySlots.js +7 -13
- package/models/api/gridRowsMetaApi.d.ts +1 -1
- package/models/api/index.d.ts +1 -1
- package/models/api/index.js +0 -1
- package/models/events/gridEventLookup.d.ts +7 -0
- package/models/gridExport.d.ts +6 -0
- package/models/gridStateCommunity.d.ts +1 -0
- package/models/props/DataGridProps.d.ts +26 -25
- package/modern/DataGrid/DataGrid.js +18 -17
- package/modern/DataGrid/useDataGridProps.js +4 -5
- package/modern/components/GridPagination.js +11 -2
- package/modern/components/cell/GridActionsCell.js +1 -1
- package/modern/components/cell/GridActionsCellItem.js +4 -0
- package/modern/components/cell/GridBooleanCell.js +3 -2
- package/modern/components/columnHeaders/GridColumnHeaderItem.js +3 -1
- package/modern/components/columnHeaders/GridGenericColumnHeaderItem.js +3 -1
- package/modern/components/containers/GridRoot.js +3 -3
- package/modern/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
- package/modern/components/panel/filterPanel/GridFilterInputDate.js +1 -1
- package/modern/components/panel/filterPanel/GridFilterInputSingleSelect.js +1 -1
- package/modern/components/panel/filterPanel/GridFilterInputValue.js +1 -1
- package/modern/components/toolbar/GridToolbarDensitySelector.js +5 -5
- package/modern/components/toolbar/GridToolbarQuickFilter.js +17 -2
- package/modern/hooks/features/clipboard/useGridClipboard.js +4 -2
- package/modern/hooks/features/columnResize/useGridColumnResize.js +1 -1
- package/modern/hooks/features/columns/gridColumnsUtils.js +0 -19
- package/modern/hooks/features/density/densitySelector.js +8 -2
- package/modern/hooks/features/density/useGridDensity.js +21 -29
- package/modern/hooks/features/dimensions/useGridDimensions.js +3 -2
- package/modern/hooks/features/editing/useGridCellEditing.js +1 -1
- package/modern/hooks/features/editing/useGridRowEditing.js +14 -5
- package/modern/hooks/features/export/serializers/csvSerializer.js +23 -12
- package/modern/hooks/features/export/useGridCsvExport.js +2 -1
- package/modern/hooks/features/filter/gridFilterUtils.js +1 -1
- package/modern/hooks/features/rowSelection/useGridRowSelection.js +3 -2
- package/modern/hooks/features/virtualization/useGridVirtualScroller.js +211 -57
- package/modern/index.js +1 -1
- package/modern/internals/index.js +1 -0
- package/modern/models/api/index.js +0 -1
- package/modern/utils/createSelector.js +1 -1
- package/modern/utils/domUtils.js +1 -1
- package/modern/utils/keyboardUtils.js +1 -1
- package/modern/utils/throttle.js +19 -0
- package/node/DataGrid/DataGrid.js +18 -17
- package/node/DataGrid/useDataGridProps.js +4 -5
- package/node/components/GridPagination.js +9 -1
- package/node/components/cell/GridActionsCell.js +1 -1
- package/node/components/cell/GridActionsCellItem.js +4 -0
- package/node/components/cell/GridBooleanCell.js +3 -2
- package/node/components/columnHeaders/GridColumnHeaderItem.js +3 -1
- package/node/components/columnHeaders/GridGenericColumnHeaderItem.js +3 -1
- package/node/components/containers/GridRoot.js +2 -2
- package/node/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
- package/node/components/panel/filterPanel/GridFilterInputDate.js +1 -1
- package/node/components/panel/filterPanel/GridFilterInputSingleSelect.js +1 -1
- package/node/components/panel/filterPanel/GridFilterInputValue.js +1 -1
- package/node/components/toolbar/GridToolbarDensitySelector.js +4 -4
- package/node/components/toolbar/GridToolbarQuickFilter.js +17 -2
- package/node/hooks/features/clipboard/useGridClipboard.js +4 -2
- package/node/hooks/features/columnResize/useGridColumnResize.js +1 -1
- package/node/hooks/features/columns/gridColumnsUtils.js +0 -20
- package/node/hooks/features/density/densitySelector.js +9 -3
- package/node/hooks/features/density/useGridDensity.js +22 -30
- package/node/hooks/features/dimensions/useGridDimensions.js +2 -1
- package/node/hooks/features/editing/useGridCellEditing.js +1 -1
- package/node/hooks/features/editing/useGridRowEditing.js +14 -5
- package/node/hooks/features/export/serializers/csvSerializer.js +23 -12
- package/node/hooks/features/export/useGridCsvExport.js +2 -1
- package/node/hooks/features/filter/gridFilterUtils.js +1 -1
- package/node/hooks/features/rowSelection/useGridRowSelection.js +2 -1
- package/node/hooks/features/virtualization/useGridVirtualScroller.js +211 -57
- package/node/index.js +1 -1
- package/node/internals/index.js +12 -0
- package/node/models/api/index.js +0 -11
- package/node/utils/createSelector.js +1 -1
- package/node/utils/domUtils.js +1 -1
- package/node/utils/keyboardUtils.js +1 -1
- package/node/utils/throttle.js +25 -0
- package/package.json +4 -4
- package/utils/createSelector.js +9 -9
- package/utils/domUtils.js +4 -7
- package/utils/getGridLocalization.js +9 -12
- package/utils/keyboardUtils.js +1 -1
- package/utils/throttle.d.ts +4 -0
- package/utils/throttle.js +19 -0
|
@@ -304,25 +304,6 @@ export function getFirstNonSpannedColumnToRender({
|
|
|
304
304
|
}
|
|
305
305
|
return firstNonSpannedColumnToRender;
|
|
306
306
|
}
|
|
307
|
-
export function getFirstColumnIndexToRender({
|
|
308
|
-
firstColumnIndex,
|
|
309
|
-
minColumnIndex,
|
|
310
|
-
columnBuffer,
|
|
311
|
-
firstRowToRender,
|
|
312
|
-
lastRowToRender,
|
|
313
|
-
apiRef,
|
|
314
|
-
visibleRows
|
|
315
|
-
}) {
|
|
316
|
-
const initialFirstColumnToRender = Math.max(firstColumnIndex - columnBuffer, minColumnIndex);
|
|
317
|
-
const firstColumnToRender = getFirstNonSpannedColumnToRender({
|
|
318
|
-
firstColumnToRender: initialFirstColumnToRender,
|
|
319
|
-
apiRef,
|
|
320
|
-
firstRowToRender,
|
|
321
|
-
lastRowToRender,
|
|
322
|
-
visibleRows
|
|
323
|
-
});
|
|
324
|
-
return firstColumnToRender;
|
|
325
|
-
}
|
|
326
307
|
export function getTotalHeaderHeight(apiRef, headerHeight) {
|
|
327
308
|
const densityFactor = gridDensityFactorSelector(apiRef);
|
|
328
309
|
const maxDepth = gridColumnGroupsHeaderMaxDepthSelector(apiRef);
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { createSelector } from '../../../utils/createSelector';
|
|
2
|
+
export const COMPACT_DENSITY_FACTOR = 0.7;
|
|
3
|
+
export const COMFORTABLE_DENSITY_FACTOR = 1.3;
|
|
4
|
+
const DENSITY_FACTORS = {
|
|
5
|
+
compact: COMPACT_DENSITY_FACTOR,
|
|
6
|
+
comfortable: COMFORTABLE_DENSITY_FACTOR,
|
|
7
|
+
standard: 1
|
|
8
|
+
};
|
|
2
9
|
export const gridDensitySelector = state => state.density;
|
|
3
|
-
export const
|
|
4
|
-
export const gridDensityFactorSelector = createSelector(gridDensitySelector, density => density.factor);
|
|
10
|
+
export const gridDensityFactorSelector = createSelector(gridDensitySelector, density => DENSITY_FACTORS[density]);
|
|
@@ -1,43 +1,35 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import useEventCallback from '@mui/utils/useEventCallback';
|
|
3
4
|
import { useGridLogger } from '../../utils/useGridLogger';
|
|
4
5
|
import { useGridApiMethod } from '../../utils/useGridApiMethod';
|
|
5
6
|
import { gridDensitySelector } from './densitySelector';
|
|
6
|
-
import { isDeepEqual } from '../../../utils/utils';
|
|
7
|
-
export const COMPACT_DENSITY_FACTOR = 0.7;
|
|
8
|
-
export const COMFORTABLE_DENSITY_FACTOR = 1.3;
|
|
9
|
-
const DENSITY_FACTORS = {
|
|
10
|
-
compact: COMPACT_DENSITY_FACTOR,
|
|
11
|
-
comfortable: COMFORTABLE_DENSITY_FACTOR,
|
|
12
|
-
standard: 1
|
|
13
|
-
};
|
|
14
7
|
export const densityStateInitializer = (state, props) => _extends({}, state, {
|
|
15
|
-
density:
|
|
16
|
-
value: props.density,
|
|
17
|
-
factor: DENSITY_FACTORS[props.density]
|
|
18
|
-
}
|
|
8
|
+
density: props.initialState?.density ?? props.density ?? 'standard'
|
|
19
9
|
});
|
|
20
10
|
export const useGridDensity = (apiRef, props) => {
|
|
21
11
|
const logger = useGridLogger(apiRef, 'useDensity');
|
|
22
|
-
|
|
12
|
+
apiRef.current.registerControlState({
|
|
13
|
+
stateId: 'density',
|
|
14
|
+
propModel: props.density,
|
|
15
|
+
propOnChange: props.onDensityChange,
|
|
16
|
+
stateSelector: gridDensitySelector,
|
|
17
|
+
changeEvent: 'densityChange'
|
|
18
|
+
});
|
|
19
|
+
const setDensity = useEventCallback(newDensity => {
|
|
20
|
+
const currentDensity = gridDensitySelector(apiRef.current.state);
|
|
21
|
+
if (currentDensity === newDensity) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
23
24
|
logger.debug(`Set grid density to ${newDensity}`);
|
|
24
|
-
apiRef.current.setState(state => {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
factor: DENSITY_FACTORS[newDensity]
|
|
29
|
-
};
|
|
30
|
-
if (isDeepEqual(currentDensityState, newDensityState)) {
|
|
31
|
-
return state;
|
|
32
|
-
}
|
|
33
|
-
return _extends({}, state, {
|
|
34
|
-
density: newDensityState
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
apiRef.current.forceUpdate();
|
|
38
|
-
}, [logger, apiRef]);
|
|
25
|
+
apiRef.current.setState(state => _extends({}, state, {
|
|
26
|
+
density: newDensity
|
|
27
|
+
}));
|
|
28
|
+
});
|
|
39
29
|
React.useEffect(() => {
|
|
40
|
-
|
|
30
|
+
if (props.density) {
|
|
31
|
+
apiRef.current.setDensity(props.density);
|
|
32
|
+
}
|
|
41
33
|
}, [apiRef, props.density]);
|
|
42
34
|
const densityApi = {
|
|
43
35
|
setDensity
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { unstable_ownerDocument as ownerDocument, unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback, unstable_ownerWindow as ownerWindow } from '@mui/utils';
|
|
4
4
|
import { useGridApiEventHandler, useGridApiOptionHandler } from '../../utils/useGridApiEventHandler';
|
|
5
5
|
import { useGridApiMethod } from '../../utils/useGridApiMethod';
|
|
6
|
+
import { throttle } from '../../../utils/throttle';
|
|
6
7
|
import { useGridLogger } from '../../utils/useGridLogger';
|
|
7
8
|
import { gridColumnsTotalWidthSelector, gridVisiblePinnedColumnDefinitionsSelector } from '../columns';
|
|
8
9
|
import { gridDimensionsSelector } from './gridDimensionsSelectors';
|
|
@@ -57,7 +58,7 @@ export function useGridDimensions(apiRef, props) {
|
|
|
57
58
|
const leftPinnedWidth = pinnedColumns.left.reduce((w, col) => w + col.computedWidth, 0);
|
|
58
59
|
const rightPinnedWidth = pinnedColumns.right.reduce((w, col) => w + col.computedWidth, 0);
|
|
59
60
|
const [savedSize, setSavedSize] = React.useState();
|
|
60
|
-
const debouncedSetSavedSize = React.useMemo(() =>
|
|
61
|
+
const debouncedSetSavedSize = React.useMemo(() => throttle(setSavedSize, props.resizeThrottleMs), [props.resizeThrottleMs]);
|
|
61
62
|
const previousSize = React.useRef();
|
|
62
63
|
const getRootDimensions = () => apiRef.current.state.dimensions;
|
|
63
64
|
const setDimensions = useEventCallback(dimensions => {
|
|
@@ -14,7 +14,7 @@ import { buildWarning } from '../../../utils/warning';
|
|
|
14
14
|
import { gridRowsDataRowIdToIdLookupSelector } from '../rows/gridRowsSelector';
|
|
15
15
|
import { deepClone } from '../../../utils/utils';
|
|
16
16
|
import { GridCellEditStartReasons, GridCellEditStopReasons } from '../../../models/params/gridEditCellParams';
|
|
17
|
-
const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI X: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop,
|
|
17
|
+
const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI X: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, for example `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/editing/#server-side-persistence.'], 'error');
|
|
18
18
|
export const useGridCellEditing = (apiRef, props) => {
|
|
19
19
|
const [cellModesModel, setCellModesModel] = React.useState({});
|
|
20
20
|
const cellModesModelRef = React.useRef(cellModesModel);
|
|
@@ -16,7 +16,7 @@ import { gridRowsDataRowIdToIdLookupSelector } from '../rows/gridRowsSelector';
|
|
|
16
16
|
import { deepClone } from '../../../utils/utils';
|
|
17
17
|
import { GridRowEditStopReasons, GridRowEditStartReasons } from '../../../models/params/gridRowParams';
|
|
18
18
|
import { GRID_ACTIONS_COLUMN_TYPE } from '../../../colDef';
|
|
19
|
-
const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI X: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop,
|
|
19
|
+
const missingOnProcessRowUpdateErrorWarning = buildWarning(['MUI X: A call to `processRowUpdate` threw an error which was not handled because `onProcessRowUpdateError` is missing.', 'To handle the error pass a callback to the `onProcessRowUpdateError` prop, for example `<DataGrid onProcessRowUpdateError={(error) => ...} />`.', 'For more detail, see https://mui.com/x/react-data-grid/editing/#server-side-persistence.'], 'error');
|
|
20
20
|
export const useGridRowEditing = (apiRef, props) => {
|
|
21
21
|
const [rowModesModel, setRowModesModel] = React.useState({});
|
|
22
22
|
const rowModesModelRef = React.useRef(rowModesModel);
|
|
@@ -45,6 +45,10 @@ export const useGridRowEditing = (apiRef, props) => {
|
|
|
45
45
|
throw new Error(`MUI X: The row with id=${id} is not in ${mode} mode.`);
|
|
46
46
|
}
|
|
47
47
|
}, [apiRef]);
|
|
48
|
+
const hasFieldsWithErrors = React.useCallback(rowId => {
|
|
49
|
+
const editingState = gridEditRowsStateSelector(apiRef.current.state);
|
|
50
|
+
return Object.values(editingState[rowId]).some(fieldProps => fieldProps.error);
|
|
51
|
+
}, [apiRef]);
|
|
48
52
|
const handleCellDoubleClick = React.useCallback((params, event) => {
|
|
49
53
|
if (!params.isEditable) {
|
|
50
54
|
return;
|
|
@@ -86,6 +90,9 @@ export const useGridRowEditing = (apiRef, props) => {
|
|
|
86
90
|
if (apiRef.current.getRowMode(params.id) === GridRowModes.View) {
|
|
87
91
|
return;
|
|
88
92
|
}
|
|
93
|
+
if (hasFieldsWithErrors(params.id)) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
89
96
|
const rowParams = apiRef.current.getRowParams(params.id);
|
|
90
97
|
const newParams = _extends({}, rowParams, {
|
|
91
98
|
field: params.field,
|
|
@@ -94,7 +101,7 @@ export const useGridRowEditing = (apiRef, props) => {
|
|
|
94
101
|
apiRef.current.publishEvent('rowEditStop', newParams, event);
|
|
95
102
|
}
|
|
96
103
|
});
|
|
97
|
-
}, [apiRef]);
|
|
104
|
+
}, [apiRef, hasFieldsWithErrors]);
|
|
98
105
|
React.useEffect(() => {
|
|
99
106
|
return () => {
|
|
100
107
|
clearTimeout(focusTimeout.current);
|
|
@@ -140,6 +147,9 @@ export const useGridRowEditing = (apiRef, props) => {
|
|
|
140
147
|
}
|
|
141
148
|
}
|
|
142
149
|
if (reason) {
|
|
150
|
+
if (reason !== GridRowEditStopReasons.escapeKeyDown && hasFieldsWithErrors(params.id)) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
143
153
|
const newParams = _extends({}, apiRef.current.getRowParams(params.id), {
|
|
144
154
|
reason,
|
|
145
155
|
field: params.field
|
|
@@ -174,7 +184,7 @@ export const useGridRowEditing = (apiRef, props) => {
|
|
|
174
184
|
apiRef.current.publishEvent('rowEditStart', newParams, event);
|
|
175
185
|
}
|
|
176
186
|
}
|
|
177
|
-
}, [apiRef]);
|
|
187
|
+
}, [apiRef, hasFieldsWithErrors]);
|
|
178
188
|
const handleRowEditStart = React.useCallback(params => {
|
|
179
189
|
const {
|
|
180
190
|
id,
|
|
@@ -358,8 +368,7 @@ export const useGridRowEditing = (apiRef, props) => {
|
|
|
358
368
|
prevRowModesModel.current[id].mode = GridRowModes.Edit;
|
|
359
369
|
return;
|
|
360
370
|
}
|
|
361
|
-
|
|
362
|
-
if (hasSomeFieldWithError) {
|
|
371
|
+
if (hasFieldsWithErrors(id)) {
|
|
363
372
|
prevRowModesModel.current[id].mode = GridRowModes.Edit;
|
|
364
373
|
// Revert the mode in the rowModesModel prop back to "edit"
|
|
365
374
|
updateRowInRowModesModel(id, {
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { GRID_CHECKBOX_SELECTION_COL_DEF } from '../../../../colDef';
|
|
2
2
|
import { buildWarning } from '../../../../utils/warning';
|
|
3
|
-
function sanitizeCellValue(value, delimiterCharacter) {
|
|
3
|
+
function sanitizeCellValue(value, delimiterCharacter, shouldAppendQuotes) {
|
|
4
4
|
if (typeof value === 'string') {
|
|
5
5
|
// Make sure value containing delimiter or line break won't be split into multiple rows
|
|
6
6
|
if ([delimiterCharacter, '\n', '\r', '"'].some(delimiter => value.includes(delimiter))) {
|
|
7
|
-
|
|
7
|
+
if (shouldAppendQuotes) {
|
|
8
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
9
|
+
}
|
|
10
|
+
return `${value.replace(/"/g, '""')}`;
|
|
8
11
|
}
|
|
9
12
|
return value;
|
|
10
13
|
}
|
|
@@ -13,7 +16,8 @@ function sanitizeCellValue(value, delimiterCharacter) {
|
|
|
13
16
|
export const serializeCellValue = (cellParams, options) => {
|
|
14
17
|
const {
|
|
15
18
|
delimiterCharacter,
|
|
16
|
-
ignoreValueFormatter
|
|
19
|
+
ignoreValueFormatter,
|
|
20
|
+
shouldAppendQuotes
|
|
17
21
|
} = options;
|
|
18
22
|
let value;
|
|
19
23
|
if (ignoreValueFormatter) {
|
|
@@ -30,7 +34,7 @@ export const serializeCellValue = (cellParams, options) => {
|
|
|
30
34
|
} else {
|
|
31
35
|
value = cellParams.formattedValue;
|
|
32
36
|
}
|
|
33
|
-
return sanitizeCellValue(value, delimiterCharacter);
|
|
37
|
+
return sanitizeCellValue(value, delimiterCharacter, shouldAppendQuotes);
|
|
34
38
|
};
|
|
35
39
|
const objectFormattedValueWarning = buildWarning(['MUI X: When the value of a field is an object or a `renderCell` is provided, the CSV export might not display the value correctly.', 'You can provide a `valueFormatter` with a string representation to be used.']);
|
|
36
40
|
class CSVRow {
|
|
@@ -47,7 +51,7 @@ class CSVRow {
|
|
|
47
51
|
if (value === null || value === undefined) {
|
|
48
52
|
this.rowString += '';
|
|
49
53
|
} else if (typeof this.options.sanitizeCellValue === 'function') {
|
|
50
|
-
this.rowString += this.options.sanitizeCellValue(value, this.options.delimiterCharacter);
|
|
54
|
+
this.rowString += this.options.sanitizeCellValue(value, this.options.delimiterCharacter, this.options.shouldAppendQuotes);
|
|
51
55
|
} else {
|
|
52
56
|
this.rowString += value;
|
|
53
57
|
}
|
|
@@ -62,10 +66,12 @@ const serializeRow = ({
|
|
|
62
66
|
columns,
|
|
63
67
|
getCellParams,
|
|
64
68
|
delimiterCharacter,
|
|
65
|
-
ignoreValueFormatter
|
|
69
|
+
ignoreValueFormatter,
|
|
70
|
+
shouldAppendQuotes
|
|
66
71
|
}) => {
|
|
67
72
|
const row = new CSVRow({
|
|
68
|
-
delimiterCharacter
|
|
73
|
+
delimiterCharacter,
|
|
74
|
+
shouldAppendQuotes
|
|
69
75
|
});
|
|
70
76
|
columns.forEach(column => {
|
|
71
77
|
const cellParams = getCellParams(id, column.field);
|
|
@@ -76,7 +82,8 @@ const serializeRow = ({
|
|
|
76
82
|
}
|
|
77
83
|
row.addValue(serializeCellValue(cellParams, {
|
|
78
84
|
delimiterCharacter,
|
|
79
|
-
ignoreValueFormatter
|
|
85
|
+
ignoreValueFormatter,
|
|
86
|
+
shouldAppendQuotes
|
|
80
87
|
}));
|
|
81
88
|
});
|
|
82
89
|
return row.getRowString();
|
|
@@ -89,14 +96,16 @@ export function buildCSV(options) {
|
|
|
89
96
|
includeHeaders,
|
|
90
97
|
includeColumnGroupsHeaders,
|
|
91
98
|
ignoreValueFormatter,
|
|
92
|
-
apiRef
|
|
99
|
+
apiRef,
|
|
100
|
+
shouldAppendQuotes
|
|
93
101
|
} = options;
|
|
94
102
|
const CSVBody = rowIds.reduce((acc, id) => `${acc}${serializeRow({
|
|
95
103
|
id,
|
|
96
104
|
columns,
|
|
97
105
|
getCellParams: apiRef.current.getCellParams,
|
|
98
106
|
delimiterCharacter,
|
|
99
|
-
ignoreValueFormatter
|
|
107
|
+
ignoreValueFormatter,
|
|
108
|
+
shouldAppendQuotes
|
|
100
109
|
})}\r\n`, '').trim();
|
|
101
110
|
if (!includeHeaders) {
|
|
102
111
|
return CSVBody;
|
|
@@ -115,7 +124,8 @@ export function buildCSV(options) {
|
|
|
115
124
|
for (let i = 0; i < maxColumnGroupsDepth; i += 1) {
|
|
116
125
|
const headerGroupRow = new CSVRow({
|
|
117
126
|
delimiterCharacter,
|
|
118
|
-
sanitizeCellValue
|
|
127
|
+
sanitizeCellValue,
|
|
128
|
+
shouldAppendQuotes
|
|
119
129
|
});
|
|
120
130
|
headerRows.push(headerGroupRow);
|
|
121
131
|
filteredColumns.forEach(column => {
|
|
@@ -127,7 +137,8 @@ export function buildCSV(options) {
|
|
|
127
137
|
}
|
|
128
138
|
const mainHeaderRow = new CSVRow({
|
|
129
139
|
delimiterCharacter,
|
|
130
|
-
sanitizeCellValue
|
|
140
|
+
sanitizeCellValue,
|
|
141
|
+
shouldAppendQuotes
|
|
131
142
|
});
|
|
132
143
|
filteredColumns.forEach(column => {
|
|
133
144
|
mainHeaderRow.addValue(column.headerName || column.field);
|
|
@@ -35,7 +35,8 @@ export const useGridCsvExport = (apiRef, props) => {
|
|
|
35
35
|
includeHeaders: options.includeHeaders ?? true,
|
|
36
36
|
includeColumnGroupsHeaders: options.includeColumnGroupsHeaders ?? true,
|
|
37
37
|
ignoreValueFormatter,
|
|
38
|
-
apiRef
|
|
38
|
+
apiRef,
|
|
39
|
+
shouldAppendQuotes: options.shouldAppendQuotes ?? true
|
|
39
40
|
});
|
|
40
41
|
}, [logger, apiRef, ignoreValueFormatter]);
|
|
41
42
|
const exportDataAsCsv = React.useCallback(options => {
|
|
@@ -156,7 +156,7 @@ const buildAggregatedFilterItemsApplier = (filterModel, apiRef, disableEval) =>
|
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
// We generate a new function with `new Function()` to avoid expensive patterns for JS engines
|
|
159
|
-
// such as a dynamic object assignment,
|
|
159
|
+
// such as a dynamic object assignment, for example `{ [dynamicKey]: value }`.
|
|
160
160
|
const filterItemCore = new Function('appliers', 'row', 'shouldApplyFilter', `"use strict";
|
|
161
161
|
${appliers.map((applier, i) => `const shouldApply${i} = !shouldApplyFilter || shouldApplyFilter(${JSON.stringify(applier.item.field)});`).join('\n')}
|
|
162
162
|
|
|
@@ -7,7 +7,7 @@ import { gridRowsLookupSelector } from '../rows/gridRowsSelector';
|
|
|
7
7
|
import { gridRowSelectionStateSelector, selectedGridRowsSelector, selectedIdsLookupSelector } from './gridRowSelectionSelector';
|
|
8
8
|
import { gridPaginatedVisibleSortedGridRowIdsSelector } from '../pagination';
|
|
9
9
|
import { gridFocusCellSelector } from '../focus/gridFocusStateSelector';
|
|
10
|
-
import { gridExpandedSortedRowIdsSelector } from '../filter/gridFilterSelector';
|
|
10
|
+
import { gridExpandedSortedRowIdsSelector, gridFilterModelSelector } from '../filter/gridFilterSelector';
|
|
11
11
|
import { GRID_CHECKBOX_SELECTION_COL_DEF, GRID_ACTIONS_COLUMN_TYPE } from '../../../colDef';
|
|
12
12
|
import { GridCellModes } from '../../../models/gridEditRowModel';
|
|
13
13
|
import { isKeyboardEvent, isNavigationKey } from '../../../utils/keyboardUtils';
|
|
@@ -274,7 +274,8 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
274
274
|
const handleHeaderSelectionCheckboxChange = React.useCallback(params => {
|
|
275
275
|
const shouldLimitSelectionToCurrentPage = props.checkboxSelectionVisibleOnly && props.pagination;
|
|
276
276
|
const rowsToBeSelected = shouldLimitSelectionToCurrentPage ? gridPaginatedVisibleSortedGridRowIdsSelector(apiRef) : gridExpandedSortedRowIdsSelector(apiRef);
|
|
277
|
-
apiRef
|
|
277
|
+
const filterModel = gridFilterModelSelector(apiRef);
|
|
278
|
+
apiRef.current.selectRows(rowsToBeSelected, params.value, filterModel?.items.length > 0);
|
|
278
279
|
}, [apiRef, props.checkboxSelectionVisibleOnly, props.pagination]);
|
|
279
280
|
const handleCellKeyDown = React.useCallback((params, event) => {
|
|
280
281
|
// Get the most recent cell mode because it may have been changed by another listener
|