@mui/x-data-grid 6.19.5 → 6.19.8
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 +89 -0
- package/components/GridPagination.d.ts +6 -5
- package/components/GridPagination.js +12 -3
- package/components/cell/GridActionsCellItem.d.ts +8 -25
- package/components/cell/GridActionsCellItem.js +4 -0
- package/hooks/features/clipboard/useGridClipboard.js +4 -2
- package/hooks/features/export/serializers/csvSerializer.d.ts +2 -0
- package/hooks/features/export/serializers/csvSerializer.js +23 -12
- package/hooks/features/export/useGridCsvExport.js +3 -2
- package/hooks/features/rowSelection/useGridRowSelection.js +3 -2
- package/hooks/features/rows/useGridRows.js +8 -4
- package/index.js +1 -1
- package/legacy/components/GridPagination.js +12 -3
- package/legacy/components/cell/GridActionsCellItem.js +4 -0
- package/legacy/hooks/features/clipboard/useGridClipboard.js +4 -2
- package/legacy/hooks/features/export/serializers/csvSerializer.js +23 -12
- package/legacy/hooks/features/export/useGridCsvExport.js +3 -2
- package/legacy/hooks/features/rowSelection/useGridRowSelection.js +3 -2
- package/legacy/hooks/features/rows/useGridRows.js +8 -4
- package/legacy/index.js +1 -1
- package/models/gridExport.d.ts +6 -0
- package/modern/components/GridPagination.js +12 -3
- package/modern/components/cell/GridActionsCellItem.js +4 -0
- package/modern/hooks/features/clipboard/useGridClipboard.js +4 -2
- package/modern/hooks/features/export/serializers/csvSerializer.js +23 -12
- package/modern/hooks/features/export/useGridCsvExport.js +2 -1
- package/modern/hooks/features/rowSelection/useGridRowSelection.js +3 -2
- package/modern/hooks/features/rows/useGridRows.js +8 -4
- package/modern/index.js +1 -1
- package/node/components/GridPagination.js +10 -2
- package/node/components/cell/GridActionsCellItem.js +4 -0
- package/node/hooks/features/clipboard/useGridClipboard.js +4 -2
- package/node/hooks/features/export/serializers/csvSerializer.js +23 -12
- package/node/hooks/features/export/useGridCsvExport.js +2 -1
- package/node/hooks/features/rowSelection/useGridRowSelection.js +2 -1
- package/node/hooks/features/rows/useGridRows.js +8 -4
- package/node/index.js +1 -1
- package/package.json +1 -1
|
@@ -2,13 +2,16 @@ import _classCallCheck from "@babel/runtime/helpers/esm/classCallCheck";
|
|
|
2
2
|
import _createClass from "@babel/runtime/helpers/esm/createClass";
|
|
3
3
|
import { GRID_CHECKBOX_SELECTION_COL_DEF } from '../../../../colDef';
|
|
4
4
|
import { buildWarning } from '../../../../utils/warning';
|
|
5
|
-
function sanitizeCellValue(value, delimiterCharacter) {
|
|
5
|
+
function sanitizeCellValue(value, delimiterCharacter, shouldAppendQuotes) {
|
|
6
6
|
if (typeof value === 'string') {
|
|
7
7
|
// Make sure value containing delimiter or line break won't be split into multiple rows
|
|
8
8
|
if ([delimiterCharacter, '\n', '\r', '"'].some(function (delimiter) {
|
|
9
9
|
return value.includes(delimiter);
|
|
10
10
|
})) {
|
|
11
|
-
|
|
11
|
+
if (shouldAppendQuotes) {
|
|
12
|
+
return "\"".concat(value.replace(/"/g, '""'), "\"");
|
|
13
|
+
}
|
|
14
|
+
return "".concat(value.replace(/"/g, '""'));
|
|
12
15
|
}
|
|
13
16
|
return value;
|
|
14
17
|
}
|
|
@@ -16,7 +19,8 @@ function sanitizeCellValue(value, delimiterCharacter) {
|
|
|
16
19
|
}
|
|
17
20
|
export var serializeCellValue = function serializeCellValue(cellParams, options) {
|
|
18
21
|
var delimiterCharacter = options.delimiterCharacter,
|
|
19
|
-
ignoreValueFormatter = options.ignoreValueFormatter
|
|
22
|
+
ignoreValueFormatter = options.ignoreValueFormatter,
|
|
23
|
+
shouldAppendQuotes = options.shouldAppendQuotes;
|
|
20
24
|
var value;
|
|
21
25
|
if (ignoreValueFormatter) {
|
|
22
26
|
var _cellParams$value2;
|
|
@@ -34,7 +38,7 @@ export var serializeCellValue = function serializeCellValue(cellParams, options)
|
|
|
34
38
|
} else {
|
|
35
39
|
value = cellParams.formattedValue;
|
|
36
40
|
}
|
|
37
|
-
return sanitizeCellValue(value, delimiterCharacter);
|
|
41
|
+
return sanitizeCellValue(value, delimiterCharacter, shouldAppendQuotes);
|
|
38
42
|
};
|
|
39
43
|
var objectFormattedValueWarning = buildWarning(['MUI: 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.']);
|
|
40
44
|
var CSVRow = /*#__PURE__*/function () {
|
|
@@ -54,7 +58,7 @@ var CSVRow = /*#__PURE__*/function () {
|
|
|
54
58
|
if (value === null || value === undefined) {
|
|
55
59
|
this.rowString += '';
|
|
56
60
|
} else if (typeof this.options.sanitizeCellValue === 'function') {
|
|
57
|
-
this.rowString += this.options.sanitizeCellValue(value, this.options.delimiterCharacter);
|
|
61
|
+
this.rowString += this.options.sanitizeCellValue(value, this.options.delimiterCharacter, this.options.shouldAppendQuotes);
|
|
58
62
|
} else {
|
|
59
63
|
this.rowString += value;
|
|
60
64
|
}
|
|
@@ -73,9 +77,11 @@ var serializeRow = function serializeRow(_ref) {
|
|
|
73
77
|
columns = _ref.columns,
|
|
74
78
|
getCellParams = _ref.getCellParams,
|
|
75
79
|
delimiterCharacter = _ref.delimiterCharacter,
|
|
76
|
-
ignoreValueFormatter = _ref.ignoreValueFormatter
|
|
80
|
+
ignoreValueFormatter = _ref.ignoreValueFormatter,
|
|
81
|
+
shouldAppendQuotes = _ref.shouldAppendQuotes;
|
|
77
82
|
var row = new CSVRow({
|
|
78
|
-
delimiterCharacter: delimiterCharacter
|
|
83
|
+
delimiterCharacter: delimiterCharacter,
|
|
84
|
+
shouldAppendQuotes: shouldAppendQuotes
|
|
79
85
|
});
|
|
80
86
|
columns.forEach(function (column) {
|
|
81
87
|
var cellParams = getCellParams(id, column.field);
|
|
@@ -86,7 +92,8 @@ var serializeRow = function serializeRow(_ref) {
|
|
|
86
92
|
}
|
|
87
93
|
row.addValue(serializeCellValue(cellParams, {
|
|
88
94
|
delimiterCharacter: delimiterCharacter,
|
|
89
|
-
ignoreValueFormatter: ignoreValueFormatter
|
|
95
|
+
ignoreValueFormatter: ignoreValueFormatter,
|
|
96
|
+
shouldAppendQuotes: shouldAppendQuotes
|
|
90
97
|
}));
|
|
91
98
|
});
|
|
92
99
|
return row.getRowString();
|
|
@@ -98,14 +105,16 @@ export function buildCSV(options) {
|
|
|
98
105
|
includeHeaders = options.includeHeaders,
|
|
99
106
|
includeColumnGroupsHeaders = options.includeColumnGroupsHeaders,
|
|
100
107
|
ignoreValueFormatter = options.ignoreValueFormatter,
|
|
101
|
-
apiRef = options.apiRef
|
|
108
|
+
apiRef = options.apiRef,
|
|
109
|
+
shouldAppendQuotes = options.shouldAppendQuotes;
|
|
102
110
|
var CSVBody = rowIds.reduce(function (acc, id) {
|
|
103
111
|
return "".concat(acc).concat(serializeRow({
|
|
104
112
|
id: id,
|
|
105
113
|
columns: columns,
|
|
106
114
|
getCellParams: apiRef.current.getCellParams,
|
|
107
115
|
delimiterCharacter: delimiterCharacter,
|
|
108
|
-
ignoreValueFormatter: ignoreValueFormatter
|
|
116
|
+
ignoreValueFormatter: ignoreValueFormatter,
|
|
117
|
+
shouldAppendQuotes: shouldAppendQuotes
|
|
109
118
|
}), "\r\n");
|
|
110
119
|
}, '').trim();
|
|
111
120
|
if (!includeHeaders) {
|
|
@@ -127,7 +136,8 @@ export function buildCSV(options) {
|
|
|
127
136
|
var _loop = function _loop(i) {
|
|
128
137
|
var headerGroupRow = new CSVRow({
|
|
129
138
|
delimiterCharacter: delimiterCharacter,
|
|
130
|
-
sanitizeCellValue: sanitizeCellValue
|
|
139
|
+
sanitizeCellValue: sanitizeCellValue,
|
|
140
|
+
shouldAppendQuotes: shouldAppendQuotes
|
|
131
141
|
});
|
|
132
142
|
headerRows.push(headerGroupRow);
|
|
133
143
|
filteredColumns.forEach(function (column) {
|
|
@@ -142,7 +152,8 @@ export function buildCSV(options) {
|
|
|
142
152
|
}
|
|
143
153
|
var mainHeaderRow = new CSVRow({
|
|
144
154
|
delimiterCharacter: delimiterCharacter,
|
|
145
|
-
sanitizeCellValue: sanitizeCellValue
|
|
155
|
+
sanitizeCellValue: sanitizeCellValue,
|
|
156
|
+
shouldAppendQuotes: shouldAppendQuotes
|
|
146
157
|
});
|
|
147
158
|
filteredColumns.forEach(function (column) {
|
|
148
159
|
mainHeaderRow.addValue(column.headerName || column.field);
|
|
@@ -21,7 +21,7 @@ export var useGridCsvExport = function useGridCsvExport(apiRef, props) {
|
|
|
21
21
|
var ignoreValueFormatterProp = props.unstable_ignoreValueFormatterDuringExport;
|
|
22
22
|
var ignoreValueFormatter = (_typeof(ignoreValueFormatterProp) === 'object' ? ignoreValueFormatterProp == null ? void 0 : ignoreValueFormatterProp.csvExport : ignoreValueFormatterProp) || false;
|
|
23
23
|
var getDataAsCsv = React.useCallback(function () {
|
|
24
|
-
var _options$getRowsToExp, _options$includeHeade, _options$includeColum;
|
|
24
|
+
var _options$getRowsToExp, _options$includeHeade, _options$includeColum, _options$shouldAppend;
|
|
25
25
|
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
26
26
|
logger.debug("Get data as CSV");
|
|
27
27
|
var exportedColumns = getColumnsToExport({
|
|
@@ -39,7 +39,8 @@ export var useGridCsvExport = function useGridCsvExport(apiRef, props) {
|
|
|
39
39
|
includeHeaders: (_options$includeHeade = options.includeHeaders) != null ? _options$includeHeade : true,
|
|
40
40
|
includeColumnGroupsHeaders: (_options$includeColum = options.includeColumnGroupsHeaders) != null ? _options$includeColum : true,
|
|
41
41
|
ignoreValueFormatter: ignoreValueFormatter,
|
|
42
|
-
apiRef: apiRef
|
|
42
|
+
apiRef: apiRef,
|
|
43
|
+
shouldAppendQuotes: (_options$shouldAppend = options.shouldAppendQuotes) != null ? _options$shouldAppend : true
|
|
43
44
|
});
|
|
44
45
|
}, [logger, apiRef, ignoreValueFormatter]);
|
|
45
46
|
var exportDataAsCsv = React.useCallback(function (options) {
|
|
@@ -8,7 +8,7 @@ import { gridRowsLookupSelector } from '../rows/gridRowsSelector';
|
|
|
8
8
|
import { gridRowSelectionStateSelector, selectedGridRowsSelector, selectedIdsLookupSelector } from './gridRowSelectionSelector';
|
|
9
9
|
import { gridPaginatedVisibleSortedGridRowIdsSelector } from '../pagination';
|
|
10
10
|
import { gridFocusCellSelector } from '../focus/gridFocusStateSelector';
|
|
11
|
-
import { gridExpandedSortedRowIdsSelector } from '../filter/gridFilterSelector';
|
|
11
|
+
import { gridExpandedSortedRowIdsSelector, gridFilterModelSelector } from '../filter/gridFilterSelector';
|
|
12
12
|
import { GRID_CHECKBOX_SELECTION_COL_DEF, GRID_ACTIONS_COLUMN_TYPE } from '../../../colDef';
|
|
13
13
|
import { GridCellModes } from '../../../models/gridEditRowModel';
|
|
14
14
|
import { isKeyboardEvent, isNavigationKey } from '../../../utils/keyboardUtils';
|
|
@@ -303,7 +303,8 @@ export var useGridRowSelection = function useGridRowSelection(apiRef, props) {
|
|
|
303
303
|
var handleHeaderSelectionCheckboxChange = React.useCallback(function (params) {
|
|
304
304
|
var shouldLimitSelectionToCurrentPage = props.checkboxSelectionVisibleOnly && props.pagination;
|
|
305
305
|
var rowsToBeSelected = shouldLimitSelectionToCurrentPage ? gridPaginatedVisibleSortedGridRowIdsSelector(apiRef) : gridExpandedSortedRowIdsSelector(apiRef);
|
|
306
|
-
apiRef
|
|
306
|
+
var filterModel = gridFilterModelSelector(apiRef);
|
|
307
|
+
apiRef.current.selectRows(rowsToBeSelected, params.value, (filterModel == null ? void 0 : filterModel.items.length) > 0);
|
|
307
308
|
}, [apiRef, props.checkboxSelectionVisibleOnly, props.pagination]);
|
|
308
309
|
var handleCellKeyDown = React.useCallback(function (params, event) {
|
|
309
310
|
// Get the most recent cell mode because it may have been changed by another listener
|
|
@@ -277,15 +277,18 @@ export var useGridRows = function useGridRows(apiRef, props) {
|
|
|
277
277
|
var dataRowIdToIdLookup = _extends({}, gridRowsDataRowIdToIdLookupSelector(apiRef));
|
|
278
278
|
var rootGroup = tree[GRID_ROOT_GROUP_ID];
|
|
279
279
|
var rootGroupChildren = _toConsumableArray(rootGroup.children);
|
|
280
|
+
var seenIds = new Set();
|
|
280
281
|
for (var i = 0; i < newRows.length; i += 1) {
|
|
281
282
|
var rowModel = newRows[i];
|
|
282
283
|
var rowId = getRowIdFromRowModel(rowModel, props.getRowId, 'A row was provided without id when calling replaceRows().');
|
|
283
284
|
var _rootGroupChildren$sp = rootGroupChildren.splice(firstRowToRender + i, 1, rowId),
|
|
284
285
|
_rootGroupChildren$sp2 = _slicedToArray(_rootGroupChildren$sp, 1),
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
286
|
+
removedRowId = _rootGroupChildren$sp2[0];
|
|
287
|
+
if (!seenIds.has(removedRowId)) {
|
|
288
|
+
delete dataRowIdToModelLookup[removedRowId];
|
|
289
|
+
delete dataRowIdToIdLookup[removedRowId];
|
|
290
|
+
delete tree[removedRowId];
|
|
291
|
+
}
|
|
289
292
|
var rowTreeNodeConfig = {
|
|
290
293
|
id: rowId,
|
|
291
294
|
depth: 0,
|
|
@@ -296,6 +299,7 @@ export var useGridRows = function useGridRows(apiRef, props) {
|
|
|
296
299
|
dataRowIdToModelLookup[rowId] = rowModel;
|
|
297
300
|
dataRowIdToIdLookup[rowId] = rowId;
|
|
298
301
|
tree[rowId] = rowTreeNodeConfig;
|
|
302
|
+
seenIds.add(rowId);
|
|
299
303
|
}
|
|
300
304
|
tree[GRID_ROOT_GROUP_ID] = _extends({}, rootGroup, {
|
|
301
305
|
children: rootGroupChildren
|
package/legacy/index.js
CHANGED
package/models/gridExport.d.ts
CHANGED
|
@@ -88,6 +88,12 @@ export interface GridCsvExportOptions extends GridFileExportOptions {
|
|
|
88
88
|
* @returns {GridRowId[]} The list of row ids to export.
|
|
89
89
|
*/
|
|
90
90
|
getRowsToExport?: (params: GridCsvGetRowsToExportParams) => GridRowId[];
|
|
91
|
+
/**
|
|
92
|
+
* @ignore
|
|
93
|
+
* If `false`, the quotes will not be appended to the cell value.
|
|
94
|
+
* @default true
|
|
95
|
+
*/
|
|
96
|
+
shouldAppendQuotes?: boolean;
|
|
91
97
|
}
|
|
92
98
|
/**
|
|
93
99
|
* The options to apply on the Print export.
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
3
4
|
import TablePagination, { tablePaginationClasses } from '@mui/material/TablePagination';
|
|
4
5
|
import { styled } from '@mui/material/styles';
|
|
5
6
|
import { useGridSelector } from '../hooks/utils/useGridSelector';
|
|
@@ -27,7 +28,7 @@ const GridPaginationRoot = styled(TablePagination)(({
|
|
|
27
28
|
|
|
28
29
|
// A mutable version of a readonly array.
|
|
29
30
|
|
|
30
|
-
|
|
31
|
+
const GridPagination = /*#__PURE__*/React.forwardRef(function GridPagination(props, ref) {
|
|
31
32
|
const apiRef = useGridApiContext();
|
|
32
33
|
const rootProps = useGridRootProps();
|
|
33
34
|
const paginationModel = useGridSelector(apiRef, gridPaginationModelSelector);
|
|
@@ -59,7 +60,7 @@ export const GridPagination = /*#__PURE__*/React.forwardRef(function GridPaginat
|
|
|
59
60
|
const warnedOnceMissingInPageSizeOptions = React.useRef(false);
|
|
60
61
|
const pageSize = rootProps.paginationModel?.pageSize ?? paginationModel.pageSize;
|
|
61
62
|
if (!warnedOnceMissingInPageSizeOptions.current && !rootProps.autoPageSize && !isPageSizeIncludedInPageSizeOptions(pageSize)) {
|
|
62
|
-
console.warn([`MUI: The page size \`${paginationModel.pageSize}\` is not preset in the \`pageSizeOptions
|
|
63
|
+
console.warn([`MUI X: The page size \`${paginationModel.pageSize}\` is not preset in the \`pageSizeOptions\`.`, `Add it to show the pagination select.`].join('\n'));
|
|
63
64
|
warnedOnceMissingInPageSizeOptions.current = true;
|
|
64
65
|
}
|
|
65
66
|
}
|
|
@@ -78,4 +79,12 @@ export const GridPagination = /*#__PURE__*/React.forwardRef(function GridPaginat
|
|
|
78
79
|
onPageChange: handlePageChange,
|
|
79
80
|
onRowsPerPageChange: handlePageSizeChange
|
|
80
81
|
}, apiRef.current.getLocaleText('MuiTablePagination'), props));
|
|
81
|
-
});
|
|
82
|
+
});
|
|
83
|
+
process.env.NODE_ENV !== "production" ? GridPagination.propTypes = {
|
|
84
|
+
// ----------------------------- Warning --------------------------------
|
|
85
|
+
// | These PropTypes are generated from the TypeScript type definitions |
|
|
86
|
+
// | To update them edit the TypeScript types and run "yarn proptypes" |
|
|
87
|
+
// ----------------------------------------------------------------------
|
|
88
|
+
component: PropTypes.elementType
|
|
89
|
+
} : void 0;
|
|
90
|
+
export { GridPagination };
|
|
@@ -62,6 +62,10 @@ process.env.NODE_ENV !== "production" ? GridActionsCellItem.propTypes = {
|
|
|
62
62
|
// | These PropTypes are generated from the TypeScript type definitions |
|
|
63
63
|
// | To update them edit the TypeScript types and run "yarn proptypes" |
|
|
64
64
|
// ----------------------------------------------------------------------
|
|
65
|
+
/**
|
|
66
|
+
* from https://mui.com/material-ui/api/button-base/#ButtonBase-prop-component
|
|
67
|
+
*/
|
|
68
|
+
component: PropTypes.elementType,
|
|
65
69
|
icon: PropTypes.element,
|
|
66
70
|
label: PropTypes.string.isRequired,
|
|
67
71
|
showInMenu: PropTypes.bool
|
|
@@ -67,7 +67,8 @@ export const useGridClipboard = (apiRef, props) => {
|
|
|
67
67
|
textToCopy = apiRef.current.getDataAsCsv({
|
|
68
68
|
includeHeaders: false,
|
|
69
69
|
// TODO: make it configurable
|
|
70
|
-
delimiter: clipboardCopyCellDelimiter
|
|
70
|
+
delimiter: clipboardCopyCellDelimiter,
|
|
71
|
+
shouldAppendQuotes: false
|
|
71
72
|
});
|
|
72
73
|
} else {
|
|
73
74
|
const focusedCell = gridFocusCellSelector(apiRef);
|
|
@@ -75,7 +76,8 @@ export const useGridClipboard = (apiRef, props) => {
|
|
|
75
76
|
const cellParams = apiRef.current.getCellParams(focusedCell.id, focusedCell.field);
|
|
76
77
|
textToCopy = serializeCellValue(cellParams, {
|
|
77
78
|
delimiterCharacter: clipboardCopyCellDelimiter,
|
|
78
|
-
ignoreValueFormatter
|
|
79
|
+
ignoreValueFormatter,
|
|
80
|
+
shouldAppendQuotes: false
|
|
79
81
|
});
|
|
80
82
|
}
|
|
81
83
|
}
|
|
@@ -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: 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 => {
|
|
@@ -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
|
|
@@ -260,13 +260,16 @@ export const useGridRows = (apiRef, props) => {
|
|
|
260
260
|
const dataRowIdToIdLookup = _extends({}, gridRowsDataRowIdToIdLookupSelector(apiRef));
|
|
261
261
|
const rootGroup = tree[GRID_ROOT_GROUP_ID];
|
|
262
262
|
const rootGroupChildren = [...rootGroup.children];
|
|
263
|
+
const seenIds = new Set();
|
|
263
264
|
for (let i = 0; i < newRows.length; i += 1) {
|
|
264
265
|
const rowModel = newRows[i];
|
|
265
266
|
const rowId = getRowIdFromRowModel(rowModel, props.getRowId, 'A row was provided without id when calling replaceRows().');
|
|
266
|
-
const [
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
267
|
+
const [removedRowId] = rootGroupChildren.splice(firstRowToRender + i, 1, rowId);
|
|
268
|
+
if (!seenIds.has(removedRowId)) {
|
|
269
|
+
delete dataRowIdToModelLookup[removedRowId];
|
|
270
|
+
delete dataRowIdToIdLookup[removedRowId];
|
|
271
|
+
delete tree[removedRowId];
|
|
272
|
+
}
|
|
270
273
|
const rowTreeNodeConfig = {
|
|
271
274
|
id: rowId,
|
|
272
275
|
depth: 0,
|
|
@@ -277,6 +280,7 @@ export const useGridRows = (apiRef, props) => {
|
|
|
277
280
|
dataRowIdToModelLookup[rowId] = rowModel;
|
|
278
281
|
dataRowIdToIdLookup[rowId] = rowId;
|
|
279
282
|
tree[rowId] = rowTreeNodeConfig;
|
|
283
|
+
seenIds.add(rowId);
|
|
280
284
|
}
|
|
281
285
|
tree[GRID_ROOT_GROUP_ID] = _extends({}, rootGroup, {
|
|
282
286
|
children: rootGroupChildren
|
package/modern/index.js
CHANGED
|
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
7
7
|
exports.GridPagination = void 0;
|
|
8
8
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
9
9
|
var React = _interopRequireWildcard(require("react"));
|
|
10
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
10
11
|
var _TablePagination = _interopRequireWildcard(require("@mui/material/TablePagination"));
|
|
11
12
|
var _styles = require("@mui/material/styles");
|
|
12
13
|
var _useGridSelector = require("../hooks/utils/useGridSelector");
|
|
@@ -68,7 +69,7 @@ const GridPagination = exports.GridPagination = /*#__PURE__*/React.forwardRef(fu
|
|
|
68
69
|
const warnedOnceMissingInPageSizeOptions = React.useRef(false);
|
|
69
70
|
const pageSize = rootProps.paginationModel?.pageSize ?? paginationModel.pageSize;
|
|
70
71
|
if (!warnedOnceMissingInPageSizeOptions.current && !rootProps.autoPageSize && !isPageSizeIncludedInPageSizeOptions(pageSize)) {
|
|
71
|
-
console.warn([`MUI: The page size \`${paginationModel.pageSize}\` is not preset in the \`pageSizeOptions
|
|
72
|
+
console.warn([`MUI X: The page size \`${paginationModel.pageSize}\` is not preset in the \`pageSizeOptions\`.`, `Add it to show the pagination select.`].join('\n'));
|
|
72
73
|
warnedOnceMissingInPageSizeOptions.current = true;
|
|
73
74
|
}
|
|
74
75
|
}
|
|
@@ -87,4 +88,11 @@ const GridPagination = exports.GridPagination = /*#__PURE__*/React.forwardRef(fu
|
|
|
87
88
|
onPageChange: handlePageChange,
|
|
88
89
|
onRowsPerPageChange: handlePageSizeChange
|
|
89
90
|
}, apiRef.current.getLocaleText('MuiTablePagination'), props));
|
|
90
|
-
});
|
|
91
|
+
});
|
|
92
|
+
process.env.NODE_ENV !== "production" ? GridPagination.propTypes = {
|
|
93
|
+
// ----------------------------- Warning --------------------------------
|
|
94
|
+
// | These PropTypes are generated from the TypeScript type definitions |
|
|
95
|
+
// | To update them edit the TypeScript types and run "yarn proptypes" |
|
|
96
|
+
// ----------------------------------------------------------------------
|
|
97
|
+
component: _propTypes.default.elementType
|
|
98
|
+
} : void 0;
|
|
@@ -70,6 +70,10 @@ process.env.NODE_ENV !== "production" ? GridActionsCellItem.propTypes = {
|
|
|
70
70
|
// | These PropTypes are generated from the TypeScript type definitions |
|
|
71
71
|
// | To update them edit the TypeScript types and run "yarn proptypes" |
|
|
72
72
|
// ----------------------------------------------------------------------
|
|
73
|
+
/**
|
|
74
|
+
* from https://mui.com/material-ui/api/button-base/#ButtonBase-prop-component
|
|
75
|
+
*/
|
|
76
|
+
component: _propTypes.default.elementType,
|
|
73
77
|
icon: _propTypes.default.element,
|
|
74
78
|
label: _propTypes.default.string.isRequired,
|
|
75
79
|
showInMenu: _propTypes.default.bool
|
|
@@ -75,7 +75,8 @@ const useGridClipboard = (apiRef, props) => {
|
|
|
75
75
|
textToCopy = apiRef.current.getDataAsCsv({
|
|
76
76
|
includeHeaders: false,
|
|
77
77
|
// TODO: make it configurable
|
|
78
|
-
delimiter: clipboardCopyCellDelimiter
|
|
78
|
+
delimiter: clipboardCopyCellDelimiter,
|
|
79
|
+
shouldAppendQuotes: false
|
|
79
80
|
});
|
|
80
81
|
} else {
|
|
81
82
|
const focusedCell = (0, _gridFocusStateSelector.gridFocusCellSelector)(apiRef);
|
|
@@ -83,7 +84,8 @@ const useGridClipboard = (apiRef, props) => {
|
|
|
83
84
|
const cellParams = apiRef.current.getCellParams(focusedCell.id, focusedCell.field);
|
|
84
85
|
textToCopy = (0, _csvSerializer.serializeCellValue)(cellParams, {
|
|
85
86
|
delimiterCharacter: clipboardCopyCellDelimiter,
|
|
86
|
-
ignoreValueFormatter
|
|
87
|
+
ignoreValueFormatter,
|
|
88
|
+
shouldAppendQuotes: false
|
|
87
89
|
});
|
|
88
90
|
}
|
|
89
91
|
}
|
|
@@ -7,11 +7,14 @@ exports.buildCSV = buildCSV;
|
|
|
7
7
|
exports.serializeCellValue = void 0;
|
|
8
8
|
var _colDef = require("../../../../colDef");
|
|
9
9
|
var _warning = require("../../../../utils/warning");
|
|
10
|
-
function sanitizeCellValue(value, delimiterCharacter) {
|
|
10
|
+
function sanitizeCellValue(value, delimiterCharacter, shouldAppendQuotes) {
|
|
11
11
|
if (typeof value === 'string') {
|
|
12
12
|
// Make sure value containing delimiter or line break won't be split into multiple rows
|
|
13
13
|
if ([delimiterCharacter, '\n', '\r', '"'].some(delimiter => value.includes(delimiter))) {
|
|
14
|
-
|
|
14
|
+
if (shouldAppendQuotes) {
|
|
15
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
16
|
+
}
|
|
17
|
+
return `${value.replace(/"/g, '""')}`;
|
|
15
18
|
}
|
|
16
19
|
return value;
|
|
17
20
|
}
|
|
@@ -20,7 +23,8 @@ function sanitizeCellValue(value, delimiterCharacter) {
|
|
|
20
23
|
const serializeCellValue = (cellParams, options) => {
|
|
21
24
|
const {
|
|
22
25
|
delimiterCharacter,
|
|
23
|
-
ignoreValueFormatter
|
|
26
|
+
ignoreValueFormatter,
|
|
27
|
+
shouldAppendQuotes
|
|
24
28
|
} = options;
|
|
25
29
|
let value;
|
|
26
30
|
if (ignoreValueFormatter) {
|
|
@@ -37,7 +41,7 @@ const serializeCellValue = (cellParams, options) => {
|
|
|
37
41
|
} else {
|
|
38
42
|
value = cellParams.formattedValue;
|
|
39
43
|
}
|
|
40
|
-
return sanitizeCellValue(value, delimiterCharacter);
|
|
44
|
+
return sanitizeCellValue(value, delimiterCharacter, shouldAppendQuotes);
|
|
41
45
|
};
|
|
42
46
|
exports.serializeCellValue = serializeCellValue;
|
|
43
47
|
const objectFormattedValueWarning = (0, _warning.buildWarning)(['MUI: 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.']);
|
|
@@ -55,7 +59,7 @@ class CSVRow {
|
|
|
55
59
|
if (value === null || value === undefined) {
|
|
56
60
|
this.rowString += '';
|
|
57
61
|
} else if (typeof this.options.sanitizeCellValue === 'function') {
|
|
58
|
-
this.rowString += this.options.sanitizeCellValue(value, this.options.delimiterCharacter);
|
|
62
|
+
this.rowString += this.options.sanitizeCellValue(value, this.options.delimiterCharacter, this.options.shouldAppendQuotes);
|
|
59
63
|
} else {
|
|
60
64
|
this.rowString += value;
|
|
61
65
|
}
|
|
@@ -70,10 +74,12 @@ const serializeRow = ({
|
|
|
70
74
|
columns,
|
|
71
75
|
getCellParams,
|
|
72
76
|
delimiterCharacter,
|
|
73
|
-
ignoreValueFormatter
|
|
77
|
+
ignoreValueFormatter,
|
|
78
|
+
shouldAppendQuotes
|
|
74
79
|
}) => {
|
|
75
80
|
const row = new CSVRow({
|
|
76
|
-
delimiterCharacter
|
|
81
|
+
delimiterCharacter,
|
|
82
|
+
shouldAppendQuotes
|
|
77
83
|
});
|
|
78
84
|
columns.forEach(column => {
|
|
79
85
|
const cellParams = getCellParams(id, column.field);
|
|
@@ -84,7 +90,8 @@ const serializeRow = ({
|
|
|
84
90
|
}
|
|
85
91
|
row.addValue(serializeCellValue(cellParams, {
|
|
86
92
|
delimiterCharacter,
|
|
87
|
-
ignoreValueFormatter
|
|
93
|
+
ignoreValueFormatter,
|
|
94
|
+
shouldAppendQuotes
|
|
88
95
|
}));
|
|
89
96
|
});
|
|
90
97
|
return row.getRowString();
|
|
@@ -97,14 +104,16 @@ function buildCSV(options) {
|
|
|
97
104
|
includeHeaders,
|
|
98
105
|
includeColumnGroupsHeaders,
|
|
99
106
|
ignoreValueFormatter,
|
|
100
|
-
apiRef
|
|
107
|
+
apiRef,
|
|
108
|
+
shouldAppendQuotes
|
|
101
109
|
} = options;
|
|
102
110
|
const CSVBody = rowIds.reduce((acc, id) => `${acc}${serializeRow({
|
|
103
111
|
id,
|
|
104
112
|
columns,
|
|
105
113
|
getCellParams: apiRef.current.getCellParams,
|
|
106
114
|
delimiterCharacter,
|
|
107
|
-
ignoreValueFormatter
|
|
115
|
+
ignoreValueFormatter,
|
|
116
|
+
shouldAppendQuotes
|
|
108
117
|
})}\r\n`, '').trim();
|
|
109
118
|
if (!includeHeaders) {
|
|
110
119
|
return CSVBody;
|
|
@@ -123,7 +132,8 @@ function buildCSV(options) {
|
|
|
123
132
|
for (let i = 0; i < maxColumnGroupsDepth; i += 1) {
|
|
124
133
|
const headerGroupRow = new CSVRow({
|
|
125
134
|
delimiterCharacter,
|
|
126
|
-
sanitizeCellValue
|
|
135
|
+
sanitizeCellValue,
|
|
136
|
+
shouldAppendQuotes
|
|
127
137
|
});
|
|
128
138
|
headerRows.push(headerGroupRow);
|
|
129
139
|
filteredColumns.forEach(column => {
|
|
@@ -135,7 +145,8 @@ function buildCSV(options) {
|
|
|
135
145
|
}
|
|
136
146
|
const mainHeaderRow = new CSVRow({
|
|
137
147
|
delimiterCharacter,
|
|
138
|
-
sanitizeCellValue
|
|
148
|
+
sanitizeCellValue,
|
|
149
|
+
shouldAppendQuotes
|
|
139
150
|
});
|
|
140
151
|
filteredColumns.forEach(column => {
|
|
141
152
|
mainHeaderRow.addValue(column.headerName || column.field);
|
|
@@ -43,7 +43,8 @@ const useGridCsvExport = (apiRef, props) => {
|
|
|
43
43
|
includeHeaders: options.includeHeaders ?? true,
|
|
44
44
|
includeColumnGroupsHeaders: options.includeColumnGroupsHeaders ?? true,
|
|
45
45
|
ignoreValueFormatter,
|
|
46
|
-
apiRef
|
|
46
|
+
apiRef,
|
|
47
|
+
shouldAppendQuotes: options.shouldAppendQuotes ?? true
|
|
47
48
|
});
|
|
48
49
|
}, [logger, apiRef, ignoreValueFormatter]);
|
|
49
50
|
const exportDataAsCsv = React.useCallback(options => {
|
|
@@ -284,7 +284,8 @@ const useGridRowSelection = (apiRef, props) => {
|
|
|
284
284
|
const handleHeaderSelectionCheckboxChange = React.useCallback(params => {
|
|
285
285
|
const shouldLimitSelectionToCurrentPage = props.checkboxSelectionVisibleOnly && props.pagination;
|
|
286
286
|
const rowsToBeSelected = shouldLimitSelectionToCurrentPage ? (0, _pagination.gridPaginatedVisibleSortedGridRowIdsSelector)(apiRef) : (0, _gridFilterSelector.gridExpandedSortedRowIdsSelector)(apiRef);
|
|
287
|
-
|
|
287
|
+
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(apiRef);
|
|
288
|
+
apiRef.current.selectRows(rowsToBeSelected, params.value, filterModel?.items.length > 0);
|
|
288
289
|
}, [apiRef, props.checkboxSelectionVisibleOnly, props.pagination]);
|
|
289
290
|
const handleCellKeyDown = React.useCallback((params, event) => {
|
|
290
291
|
// Get the most recent cell mode because it may have been changed by another listener
|