@mui/x-data-grid 6.9.2 → 6.10.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 +232 -114
- package/DataGrid/DataGrid.js +1 -0
- package/components/toolbar/GridToolbarQuickFilter.d.ts +1 -1
- package/components/toolbar/GridToolbarQuickFilter.js +12 -9
- package/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
- package/hooks/core/useGridApiInitialization.d.ts +1 -0
- package/hooks/core/useGridApiInitialization.js +59 -36
- package/hooks/features/export/serializers/csvSerializer.d.ts +9 -6
- package/hooks/features/export/serializers/csvSerializer.js +78 -15
- package/hooks/features/export/useGridCsvExport.js +4 -3
- package/hooks/features/filter/gridFilterUtils.js +6 -5
- package/hooks/features/filter/useGridFilter.js +8 -0
- package/hooks/features/rows/gridRowsUtils.js +1 -1
- package/hooks/utils/useGridApiMethod.js +7 -23
- package/index.js +1 -1
- package/internals/index.d.ts +1 -0
- package/internals/index.js +1 -0
- package/legacy/DataGrid/DataGrid.js +1 -0
- package/legacy/components/toolbar/GridToolbarQuickFilter.js +12 -12
- package/legacy/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
- package/legacy/hooks/core/useGridApiInitialization.js +62 -39
- package/legacy/hooks/features/export/serializers/csvSerializer.js +84 -11
- package/legacy/hooks/features/export/useGridCsvExport.js +4 -3
- package/legacy/hooks/features/filter/gridFilterUtils.js +6 -5
- package/legacy/hooks/features/filter/useGridFilter.js +8 -0
- package/legacy/hooks/features/rows/gridRowsUtils.js +1 -1
- package/legacy/hooks/utils/useGridApiMethod.js +7 -25
- package/legacy/index.js +1 -1
- package/legacy/internals/index.js +1 -0
- package/legacy/locales/plPL.js +7 -7
- package/locales/plPL.js +7 -7
- package/models/events/gridEventLookup.d.ts +0 -1
- package/models/gridExport.d.ts +8 -1
- package/models/gridFilterModel.d.ts +5 -0
- package/modern/DataGrid/DataGrid.js +1 -0
- package/modern/components/toolbar/GridToolbarQuickFilter.js +12 -9
- package/modern/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
- package/modern/hooks/core/useGridApiInitialization.js +58 -36
- package/modern/hooks/features/export/serializers/csvSerializer.js +78 -15
- package/modern/hooks/features/export/useGridCsvExport.js +3 -2
- package/modern/hooks/features/filter/gridFilterUtils.js +3 -2
- package/modern/hooks/features/filter/useGridFilter.js +8 -0
- package/modern/hooks/features/rows/gridRowsUtils.js +1 -1
- package/modern/hooks/utils/useGridApiMethod.js +7 -23
- package/modern/index.js +1 -1
- package/modern/internals/index.js +1 -0
- package/modern/locales/plPL.js +7 -7
- package/node/DataGrid/DataGrid.js +1 -0
- package/node/components/toolbar/GridToolbarQuickFilter.js +12 -9
- package/node/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
- package/node/hooks/core/useGridApiInitialization.js +59 -36
- package/node/hooks/features/export/serializers/csvSerializer.js +78 -15
- package/node/hooks/features/export/useGridCsvExport.js +3 -2
- package/node/hooks/features/filter/gridFilterUtils.js +2 -1
- package/node/hooks/features/filter/useGridFilter.js +8 -0
- package/node/hooks/features/rows/gridRowsUtils.js +1 -1
- package/node/hooks/utils/useGridApiMethod.js +7 -23
- package/node/index.js +1 -1
- package/node/internals/index.js +8 -0
- package/node/locales/plPL.js +7 -7
- package/package.json +1 -1
package/DataGrid/DataGrid.js
CHANGED
|
@@ -181,6 +181,7 @@ DataGridRaw.propTypes = {
|
|
|
181
181
|
value: PropTypes.any
|
|
182
182
|
})).isRequired,
|
|
183
183
|
logicOperator: PropTypes.oneOf(['and', 'or']),
|
|
184
|
+
quickFilterExcludeHiddenColumns: PropTypes.bool,
|
|
184
185
|
quickFilterLogicOperator: PropTypes.oneOf(['and', 'or']),
|
|
185
186
|
quickFilterValues: PropTypes.array
|
|
186
187
|
}),
|
|
@@ -13,7 +13,7 @@ export type GridToolbarQuickFilterProps = TextFieldProps & {
|
|
|
13
13
|
* @param {any[]} values The new values passed to the quick filter model
|
|
14
14
|
* @returns {string} The string to display in the text field
|
|
15
15
|
*/
|
|
16
|
-
quickFilterFormatter?: (values: GridFilterModel['quickFilterValues']) => string;
|
|
16
|
+
quickFilterFormatter?: (values: NonNullable<GridFilterModel['quickFilterValues']>) => string;
|
|
17
17
|
/**
|
|
18
18
|
* The debounce time in milliseconds.
|
|
19
19
|
* @default 500
|
|
@@ -56,18 +56,20 @@ function GridToolbarQuickFilter(props) {
|
|
|
56
56
|
const rootProps = useGridRootProps();
|
|
57
57
|
const quickFilterValues = useGridSelector(apiRef, gridQuickFilterValuesSelector);
|
|
58
58
|
const [searchValue, setSearchValue] = React.useState(() => quickFilterFormatter(quickFilterValues != null ? quickFilterValues : []));
|
|
59
|
-
const
|
|
59
|
+
const prevQuickFilterValuesRef = React.useRef(quickFilterValues);
|
|
60
60
|
React.useEffect(() => {
|
|
61
|
-
if (!isDeepEqual(
|
|
61
|
+
if (!isDeepEqual(prevQuickFilterValuesRef.current, quickFilterValues)) {
|
|
62
62
|
// The model of quick filter value has been updated
|
|
63
|
-
|
|
63
|
+
prevQuickFilterValuesRef.current = quickFilterValues;
|
|
64
64
|
|
|
65
65
|
// Update the input value if needed to match the new model
|
|
66
66
|
setSearchValue(prevSearchValue => isDeepEqual(quickFilterParser(prevSearchValue), quickFilterValues) ? prevSearchValue : quickFilterFormatter(quickFilterValues != null ? quickFilterValues : []));
|
|
67
67
|
}
|
|
68
|
-
}, [
|
|
68
|
+
}, [quickFilterValues, quickFilterFormatter, quickFilterParser]);
|
|
69
69
|
const updateSearchValue = React.useCallback(newSearchValue => {
|
|
70
|
-
|
|
70
|
+
const newQuickFilterValues = quickFilterParser(newSearchValue);
|
|
71
|
+
prevQuickFilterValuesRef.current = newQuickFilterValues;
|
|
72
|
+
apiRef.current.setQuickFilterValues(newQuickFilterValues);
|
|
71
73
|
}, [apiRef, quickFilterParser]);
|
|
72
74
|
const debouncedUpdateSearchValue = React.useMemo(() => debounce(updateSearchValue, debounceMs), [updateSearchValue, debounceMs]);
|
|
73
75
|
const handleSearchValueChange = React.useCallback(event => {
|
|
@@ -87,8 +89,9 @@ function GridToolbarQuickFilter(props) {
|
|
|
87
89
|
onChange: handleSearchValueChange,
|
|
88
90
|
placeholder: apiRef.current.getLocaleText('toolbarQuickFilterPlaceholder'),
|
|
89
91
|
"aria-label": apiRef.current.getLocaleText('toolbarQuickFilterLabel'),
|
|
90
|
-
type: "search"
|
|
91
|
-
|
|
92
|
+
type: "search"
|
|
93
|
+
}, other, {
|
|
94
|
+
InputProps: _extends({
|
|
92
95
|
startAdornment: /*#__PURE__*/_jsx(rootProps.slots.quickFilterIcon, {
|
|
93
96
|
fontSize: "small"
|
|
94
97
|
}),
|
|
@@ -104,8 +107,8 @@ function GridToolbarQuickFilter(props) {
|
|
|
104
107
|
fontSize: "small"
|
|
105
108
|
})
|
|
106
109
|
}))
|
|
107
|
-
}
|
|
108
|
-
},
|
|
110
|
+
}, other.InputProps)
|
|
111
|
+
}, (_rootProps$slotProps2 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps2.baseTextField));
|
|
109
112
|
}
|
|
110
113
|
process.env.NODE_ENV !== "production" ? GridToolbarQuickFilter.propTypes = {
|
|
111
114
|
// ----------------------------- Warning --------------------------------
|
|
@@ -33,13 +33,16 @@ import { useGridApiMethod } from '../../utils/useGridApiMethod';
|
|
|
33
33
|
*/
|
|
34
34
|
export const useGridPipeProcessing = apiRef => {
|
|
35
35
|
const processorsCache = React.useRef({});
|
|
36
|
+
const isRunning = React.useRef(false);
|
|
36
37
|
const runAppliers = React.useCallback(groupCache => {
|
|
37
|
-
if (!groupCache) {
|
|
38
|
+
if (isRunning.current || !groupCache) {
|
|
38
39
|
return;
|
|
39
40
|
}
|
|
41
|
+
isRunning.current = true;
|
|
40
42
|
Object.values(groupCache.appliers).forEach(callback => {
|
|
41
43
|
callback();
|
|
42
44
|
});
|
|
45
|
+
isRunning.current = false;
|
|
43
46
|
}, []);
|
|
44
47
|
const registerPipeProcessor = React.useCallback((group, id, processor) => {
|
|
45
48
|
if (!processorsCache.current[group]) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import { DataGridProcessedProps } from '../../models/props/DataGridProps';
|
|
3
3
|
import type { GridApiCommon, GridPrivateApiCommon } from '../../models/api/gridApiCommon';
|
|
4
|
+
export declare function unwrapPrivateAPI<PrivateApi extends GridPrivateApiCommon, Api extends GridApiCommon>(publicApi: Api): PrivateApi;
|
|
4
5
|
export declare function useGridApiInitialization<PrivateApi extends GridPrivateApiCommon, Api extends GridApiCommon>(inputApiRef: React.MutableRefObject<Api> | undefined, props: Pick<DataGridProcessedProps, 'signature'>): React.MutableRefObject<PrivateApi>;
|
|
@@ -3,58 +3,80 @@ import { Store } from '../../utils/Store';
|
|
|
3
3
|
import { useGridApiMethod } from '../utils/useGridApiMethod';
|
|
4
4
|
import { GridSignature } from '../utils/useGridApiEventHandler';
|
|
5
5
|
import { EventManager } from '../../utils/EventManager';
|
|
6
|
+
const SYMBOL_API_PRIVATE = Symbol('mui.api_private');
|
|
6
7
|
const isSyntheticEvent = event => {
|
|
7
8
|
return event.isPropagationStopped !== undefined;
|
|
8
9
|
};
|
|
10
|
+
export function unwrapPrivateAPI(publicApi) {
|
|
11
|
+
return publicApi[SYMBOL_API_PRIVATE];
|
|
12
|
+
}
|
|
9
13
|
let globalId = 0;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
function createPrivateAPI(publicApiRef) {
|
|
15
|
+
var _publicApiRef$current;
|
|
16
|
+
const existingPrivateApi = (_publicApiRef$current = publicApiRef.current) == null ? void 0 : _publicApiRef$current[SYMBOL_API_PRIVATE];
|
|
17
|
+
if (existingPrivateApi) {
|
|
18
|
+
return existingPrivateApi;
|
|
19
|
+
}
|
|
20
|
+
const state = {};
|
|
21
|
+
const privateApi = {
|
|
22
|
+
state,
|
|
23
|
+
store: Store.create(state),
|
|
24
|
+
instanceId: {
|
|
25
|
+
id: globalId
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
globalId += 1;
|
|
29
|
+
privateApi.getPublicApi = () => publicApiRef.current;
|
|
30
|
+
privateApi.register = (visibility, methods) => {
|
|
14
31
|
Object.keys(methods).forEach(methodName => {
|
|
15
|
-
|
|
16
|
-
|
|
32
|
+
const method = methods[methodName];
|
|
33
|
+
const currentPrivateMethod = privateApi[methodName];
|
|
34
|
+
if ((currentPrivateMethod == null ? void 0 : currentPrivateMethod.spying) === true) {
|
|
35
|
+
currentPrivateMethod.target = method;
|
|
17
36
|
} else {
|
|
18
|
-
|
|
37
|
+
privateApi[methodName] = method;
|
|
38
|
+
}
|
|
39
|
+
if (visibility === 'public') {
|
|
40
|
+
const publicApi = publicApiRef.current;
|
|
41
|
+
const currentPublicMethod = publicApi[methodName];
|
|
42
|
+
if ((currentPublicMethod == null ? void 0 : currentPublicMethod.spying) === true) {
|
|
43
|
+
currentPublicMethod.target = method;
|
|
44
|
+
} else {
|
|
45
|
+
publicApi[methodName] = method;
|
|
46
|
+
}
|
|
19
47
|
}
|
|
20
48
|
});
|
|
21
49
|
};
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
50
|
+
privateApi.register('private', {
|
|
51
|
+
caches: {},
|
|
52
|
+
eventManager: new EventManager()
|
|
53
|
+
});
|
|
54
|
+
return privateApi;
|
|
55
|
+
}
|
|
56
|
+
function createPublicAPI(privateApiRef) {
|
|
57
|
+
const publicApi = {
|
|
58
|
+
get state() {
|
|
59
|
+
return privateApiRef.current.state;
|
|
28
60
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
61
|
+
get store() {
|
|
62
|
+
return privateApiRef.current.store;
|
|
63
|
+
},
|
|
64
|
+
get instanceId() {
|
|
65
|
+
return privateApiRef.current.instanceId;
|
|
66
|
+
},
|
|
67
|
+
[SYMBOL_API_PRIVATE]: privateApiRef.current
|
|
33
68
|
};
|
|
34
|
-
return
|
|
35
|
-
}
|
|
69
|
+
return publicApi;
|
|
70
|
+
}
|
|
36
71
|
export function useGridApiInitialization(inputApiRef, props) {
|
|
37
72
|
const publicApiRef = React.useRef();
|
|
38
|
-
if (!publicApiRef.current) {
|
|
39
|
-
const state = {};
|
|
40
|
-
publicApiRef.current = {
|
|
41
|
-
state,
|
|
42
|
-
store: Store.create(state),
|
|
43
|
-
instanceId: {
|
|
44
|
-
id: globalId
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
globalId += 1;
|
|
48
|
-
}
|
|
49
73
|
const privateApiRef = React.useRef();
|
|
50
74
|
if (!privateApiRef.current) {
|
|
51
|
-
privateApiRef.current =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
});
|
|
75
|
+
privateApiRef.current = createPrivateAPI(publicApiRef);
|
|
76
|
+
}
|
|
77
|
+
if (!publicApiRef.current) {
|
|
78
|
+
publicApiRef.current = createPublicAPI(privateApiRef);
|
|
56
79
|
}
|
|
57
|
-
React.useImperativeHandle(inputApiRef, () => publicApiRef.current, [publicApiRef]);
|
|
58
80
|
const publishEvent = React.useCallback((...args) => {
|
|
59
81
|
const [name, params, event = {}] = args;
|
|
60
82
|
event.defaultMuiPrevented = false;
|
|
@@ -77,6 +99,7 @@ export function useGridApiInitialization(inputApiRef, props) {
|
|
|
77
99
|
subscribeEvent,
|
|
78
100
|
publishEvent
|
|
79
101
|
}, 'public');
|
|
102
|
+
React.useImperativeHandle(inputApiRef, () => publicApiRef.current, [publicApiRef]);
|
|
80
103
|
React.useEffect(() => {
|
|
81
104
|
const api = privateApiRef.current;
|
|
82
105
|
return () => {
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import type { GridCsvExportOptions, GridRowId } from '../../../../models';
|
|
3
|
+
import type { GridCellParams } from '../../../../models/params/gridCellParams';
|
|
4
|
+
import type { GridStateColDef } from '../../../../models/colDef/gridColDef';
|
|
5
|
+
import type { GridApiCommunity } from '../../../../models/api/gridApiCommunity';
|
|
4
6
|
export declare const serializeCellValue: (cellParams: GridCellParams, options: {
|
|
5
7
|
delimiterCharacter: string;
|
|
6
8
|
ignoreValueFormatter: boolean;
|
|
@@ -8,10 +10,11 @@ export declare const serializeCellValue: (cellParams: GridCellParams, options: {
|
|
|
8
10
|
interface BuildCSVOptions {
|
|
9
11
|
columns: GridStateColDef[];
|
|
10
12
|
rowIds: GridRowId[];
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
delimiterCharacter: NonNullable<GridCsvExportOptions['delimiter']>;
|
|
14
|
+
includeHeaders: NonNullable<GridCsvExportOptions['includeHeaders']>;
|
|
15
|
+
includeColumnGroupsHeaders: NonNullable<GridCsvExportOptions['includeColumnGroupsHeaders']>;
|
|
14
16
|
ignoreValueFormatter: boolean;
|
|
17
|
+
apiRef: React.MutableRefObject<GridApiCommunity>;
|
|
15
18
|
}
|
|
16
19
|
export declare function buildCSV(options: BuildCSVOptions): string;
|
|
17
20
|
export {};
|
|
@@ -37,43 +37,106 @@ export const serializeCellValue = (cellParams, options) => {
|
|
|
37
37
|
return sanitizeCellValue(value, delimiterCharacter);
|
|
38
38
|
};
|
|
39
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.']);
|
|
40
|
+
class CSVRow {
|
|
41
|
+
constructor(options) {
|
|
42
|
+
this.options = void 0;
|
|
43
|
+
this.rowString = '';
|
|
44
|
+
this.isEmpty = true;
|
|
45
|
+
this.options = options;
|
|
46
|
+
}
|
|
47
|
+
addValue(value) {
|
|
48
|
+
if (!this.isEmpty) {
|
|
49
|
+
this.rowString += this.options.delimiterCharacter;
|
|
50
|
+
}
|
|
51
|
+
if (value === null || value === undefined) {
|
|
52
|
+
this.rowString += '';
|
|
53
|
+
} else if (typeof this.options.sanitizeCellValue === 'function') {
|
|
54
|
+
this.rowString += this.options.sanitizeCellValue(value, this.options.delimiterCharacter);
|
|
55
|
+
} else {
|
|
56
|
+
this.rowString += value;
|
|
57
|
+
}
|
|
58
|
+
this.isEmpty = false;
|
|
59
|
+
}
|
|
60
|
+
getRowString() {
|
|
61
|
+
return this.rowString;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
40
64
|
const serializeRow = ({
|
|
41
65
|
id,
|
|
42
66
|
columns,
|
|
43
67
|
getCellParams,
|
|
44
68
|
delimiterCharacter,
|
|
45
69
|
ignoreValueFormatter
|
|
46
|
-
}) =>
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
70
|
+
}) => {
|
|
71
|
+
const row = new CSVRow({
|
|
72
|
+
delimiterCharacter
|
|
73
|
+
});
|
|
74
|
+
columns.forEach(column => {
|
|
75
|
+
const cellParams = getCellParams(id, column.field);
|
|
76
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
77
|
+
if (String(cellParams.formattedValue) === '[object Object]') {
|
|
78
|
+
objectFormattedValueWarning();
|
|
79
|
+
}
|
|
51
80
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
81
|
+
row.addValue(serializeCellValue(cellParams, {
|
|
82
|
+
delimiterCharacter,
|
|
83
|
+
ignoreValueFormatter
|
|
84
|
+
}));
|
|
56
85
|
});
|
|
57
|
-
|
|
86
|
+
return row.getRowString();
|
|
87
|
+
};
|
|
58
88
|
export function buildCSV(options) {
|
|
59
89
|
const {
|
|
60
90
|
columns,
|
|
61
91
|
rowIds,
|
|
62
|
-
getCellParams,
|
|
63
92
|
delimiterCharacter,
|
|
64
93
|
includeHeaders,
|
|
65
|
-
|
|
94
|
+
includeColumnGroupsHeaders,
|
|
95
|
+
ignoreValueFormatter,
|
|
96
|
+
apiRef
|
|
66
97
|
} = options;
|
|
67
98
|
const CSVBody = rowIds.reduce((acc, id) => `${acc}${serializeRow({
|
|
68
99
|
id,
|
|
69
100
|
columns,
|
|
70
|
-
getCellParams,
|
|
101
|
+
getCellParams: apiRef.current.getCellParams,
|
|
71
102
|
delimiterCharacter,
|
|
72
103
|
ignoreValueFormatter
|
|
73
|
-
})
|
|
104
|
+
})}\r\n`, '').trim();
|
|
74
105
|
if (!includeHeaders) {
|
|
75
106
|
return CSVBody;
|
|
76
107
|
}
|
|
77
|
-
const
|
|
108
|
+
const filteredColumns = columns.filter(column => column.field !== GRID_CHECKBOX_SELECTION_COL_DEF.field);
|
|
109
|
+
const headerRows = [];
|
|
110
|
+
if (includeColumnGroupsHeaders) {
|
|
111
|
+
const columnGroupLookup = apiRef.current.unstable_getAllGroupDetails();
|
|
112
|
+
let maxColumnGroupsDepth = 0;
|
|
113
|
+
const columnGroupPathsLookup = filteredColumns.reduce((acc, column) => {
|
|
114
|
+
const columnGroupPath = apiRef.current.unstable_getColumnGroupPath(column.field);
|
|
115
|
+
acc[column.field] = columnGroupPath;
|
|
116
|
+
maxColumnGroupsDepth = Math.max(maxColumnGroupsDepth, columnGroupPath.length);
|
|
117
|
+
return acc;
|
|
118
|
+
}, {});
|
|
119
|
+
for (let i = 0; i < maxColumnGroupsDepth; i += 1) {
|
|
120
|
+
const headerGroupRow = new CSVRow({
|
|
121
|
+
delimiterCharacter,
|
|
122
|
+
sanitizeCellValue
|
|
123
|
+
});
|
|
124
|
+
headerRows.push(headerGroupRow);
|
|
125
|
+
filteredColumns.forEach(column => {
|
|
126
|
+
const columnGroupId = (columnGroupPathsLookup[column.field] || [])[i];
|
|
127
|
+
const columnGroup = columnGroupLookup[columnGroupId];
|
|
128
|
+
headerGroupRow.addValue(columnGroup ? columnGroup.headerName || columnGroup.groupId : '');
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
const mainHeaderRow = new CSVRow({
|
|
133
|
+
delimiterCharacter,
|
|
134
|
+
sanitizeCellValue
|
|
135
|
+
});
|
|
136
|
+
filteredColumns.forEach(column => {
|
|
137
|
+
mainHeaderRow.addValue(column.headerName || column.field);
|
|
138
|
+
});
|
|
139
|
+
headerRows.push(mainHeaderRow);
|
|
140
|
+
const CSVHead = `${headerRows.map(row => row.getRowString()).join('\r\n')}\r\n`;
|
|
78
141
|
return `${CSVHead}${CSVBody}`.trim();
|
|
79
142
|
}
|
|
@@ -19,7 +19,7 @@ export const useGridCsvExport = (apiRef, props) => {
|
|
|
19
19
|
const ignoreValueFormatterProp = props.unstable_ignoreValueFormatterDuringExport;
|
|
20
20
|
const ignoreValueFormatter = (typeof ignoreValueFormatterProp === 'object' ? ignoreValueFormatterProp == null ? void 0 : ignoreValueFormatterProp.csvExport : ignoreValueFormatterProp) || false;
|
|
21
21
|
const getDataAsCsv = React.useCallback((options = {}) => {
|
|
22
|
-
var _options$getRowsToExp, _options$includeHeade;
|
|
22
|
+
var _options$getRowsToExp, _options$includeHeade, _options$includeColum;
|
|
23
23
|
logger.debug(`Get data as CSV`);
|
|
24
24
|
const exportedColumns = getColumnsToExport({
|
|
25
25
|
apiRef,
|
|
@@ -32,10 +32,11 @@ export const useGridCsvExport = (apiRef, props) => {
|
|
|
32
32
|
return buildCSV({
|
|
33
33
|
columns: exportedColumns,
|
|
34
34
|
rowIds: exportedRowIds,
|
|
35
|
-
getCellParams: apiRef.current.getCellParams,
|
|
36
35
|
delimiterCharacter: options.delimiter || ',',
|
|
37
36
|
includeHeaders: (_options$includeHeade = options.includeHeaders) != null ? _options$includeHeade : true,
|
|
38
|
-
|
|
37
|
+
includeColumnGroupsHeaders: (_options$includeColum = options.includeColumnGroupsHeaders) != null ? _options$includeColum : true,
|
|
38
|
+
ignoreValueFormatter,
|
|
39
|
+
apiRef
|
|
39
40
|
});
|
|
40
41
|
}, [logger, apiRef, ignoreValueFormatter]);
|
|
41
42
|
const exportDataAsCsv = React.useCallback(options => {
|
|
@@ -3,7 +3,7 @@ import { GridLogicOperator } from '../../../models';
|
|
|
3
3
|
import { GLOBAL_API_REF, isInternalFilter } from '../../../colDef/utils';
|
|
4
4
|
import { getDefaultGridFilterModel } from './gridFilterState';
|
|
5
5
|
import { buildWarning } from '../../../utils/warning';
|
|
6
|
-
import { gridColumnFieldsSelector, gridColumnLookupSelector } from '../columns';
|
|
6
|
+
import { gridColumnFieldsSelector, gridColumnLookupSelector, gridVisibleColumnFieldsSelector } from '../columns';
|
|
7
7
|
/**
|
|
8
8
|
* Adds default values to the optional fields of a filter items.
|
|
9
9
|
* @param {GridFilterItem} item The raw filter item.
|
|
@@ -154,12 +154,13 @@ export const buildAggregatedFilterItemsApplier = (getRowId, filterModel, apiRef)
|
|
|
154
154
|
* @returns {GridAggregatedFilterItemApplier | null} A method that checks if a row is matching the current filter model. If `null`, we consider that all the rows are matching the filters.
|
|
155
155
|
*/
|
|
156
156
|
export const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef) => {
|
|
157
|
-
var _filterModel$quickFil, _filterModel$quickFil2;
|
|
157
|
+
var _filterModel$quickFil, _filterModel$quickFil2, _filterModel$quickFil3;
|
|
158
158
|
const quickFilterValues = (_filterModel$quickFil = (_filterModel$quickFil2 = filterModel.quickFilterValues) == null ? void 0 : _filterModel$quickFil2.filter(Boolean)) != null ? _filterModel$quickFil : [];
|
|
159
159
|
if (quickFilterValues.length === 0) {
|
|
160
160
|
return null;
|
|
161
161
|
}
|
|
162
|
-
const
|
|
162
|
+
const quickFilterExcludeHiddenColumns = (_filterModel$quickFil3 = filterModel.quickFilterExcludeHiddenColumns) != null ? _filterModel$quickFil3 : false;
|
|
163
|
+
const columnFields = quickFilterExcludeHiddenColumns ? gridVisibleColumnFieldsSelector(apiRef) : gridColumnFieldsSelector(apiRef);
|
|
163
164
|
const appliersPerField = [];
|
|
164
165
|
columnFields.forEach(field => {
|
|
165
166
|
const column = apiRef.current.getColumn(field);
|
|
@@ -276,12 +277,12 @@ export const passFilterLogic = (allFilterItemResults, allQuickFilterResults, fil
|
|
|
276
277
|
|
|
277
278
|
// get result for quick filter model
|
|
278
279
|
if (cleanedQuickFilterResults.length > 0 && filterModel.quickFilterValues != null) {
|
|
279
|
-
var _filterModel$
|
|
280
|
+
var _filterModel$quickFil4;
|
|
280
281
|
// Return true if the item pass with one of the rows
|
|
281
282
|
const quickFilterValuePredicate = value => {
|
|
282
283
|
return cleanedQuickFilterResults.some(quickFilterValueResult => quickFilterValueResult[value]);
|
|
283
284
|
};
|
|
284
|
-
const quickFilterLogicOperator = (_filterModel$
|
|
285
|
+
const quickFilterLogicOperator = (_filterModel$quickFil4 = filterModel.quickFilterLogicOperator) != null ? _filterModel$quickFil4 : getDefaultGridFilterModel().quickFilterLogicOperator;
|
|
285
286
|
if (quickFilterLogicOperator === GridLogicOperator.And) {
|
|
286
287
|
const passesAllQuickFilterValues = filterModel.quickFilterValues.every(quickFilterValuePredicate);
|
|
287
288
|
if (!passesAllQuickFilterValues) {
|
|
@@ -21,6 +21,7 @@ export const filterStateInitializer = (state, props, apiRef) => {
|
|
|
21
21
|
return _extends({}, state, {
|
|
22
22
|
filter: {
|
|
23
23
|
filterModel: sanitizeFilterModel(filterModel, props.disableMultipleColumnsFiltering, apiRef),
|
|
24
|
+
filteredRowsLookup: {},
|
|
24
25
|
filteredDescendantCountLookup: {}
|
|
25
26
|
},
|
|
26
27
|
visibleRowsLookup: {}
|
|
@@ -336,6 +337,13 @@ export const useGridFilter = (apiRef, props) => {
|
|
|
336
337
|
useGridApiEventHandler(apiRef, 'columnsChange', handleColumnsChange);
|
|
337
338
|
useGridApiEventHandler(apiRef, 'activeStrategyProcessorChange', handleStrategyProcessorChange);
|
|
338
339
|
useGridApiEventHandler(apiRef, 'rowExpansionChange', updateVisibleRowsLookupState);
|
|
340
|
+
useGridApiEventHandler(apiRef, 'columnVisibilityModelChange', () => {
|
|
341
|
+
const filterModel = gridFilterModelSelector(apiRef);
|
|
342
|
+
if (filterModel.quickFilterValues && filterModel.quickFilterExcludeHiddenColumns) {
|
|
343
|
+
// re-apply filters because the quick filter results may have changed
|
|
344
|
+
apiRef.current.unstable_applyFilters();
|
|
345
|
+
}
|
|
346
|
+
});
|
|
339
347
|
|
|
340
348
|
/**
|
|
341
349
|
* 1ST RENDER
|
|
@@ -2,7 +2,7 @@ import _extends from "@babel/runtime/helpers/esm/extends";
|
|
|
2
2
|
import { gridPinnedRowsSelector } from './gridRowsSelector';
|
|
3
3
|
import { gridDensityFactorSelector } from '../density/densitySelector';
|
|
4
4
|
export const GRID_ROOT_GROUP_ID = `auto-generated-group-node-root`;
|
|
5
|
-
export const GRID_ID_AUTOGENERATED = Symbol('mui
|
|
5
|
+
export const GRID_ID_AUTOGENERATED = Symbol('mui.id_autogenerated');
|
|
6
6
|
export const buildRootGroup = () => ({
|
|
7
7
|
type: 'group',
|
|
8
8
|
id: GRID_ROOT_GROUP_ID,
|
|
@@ -1,27 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
export function useGridApiMethod(privateApiRef, apiMethods, visibility) {
|
|
3
|
-
const
|
|
4
|
-
const [apiMethodsNames] = React.useState(Object.keys(apiMethods));
|
|
5
|
-
const installMethods = React.useCallback(() => {
|
|
6
|
-
if (!privateApiRef.current) {
|
|
7
|
-
return;
|
|
8
|
-
}
|
|
9
|
-
apiMethodsNames.forEach(methodName => {
|
|
10
|
-
if (!privateApiRef.current.hasOwnProperty(methodName)) {
|
|
11
|
-
privateApiRef.current.register(visibility, {
|
|
12
|
-
[methodName]: (...args) => {
|
|
13
|
-
const fn = apiMethodsRef.current[methodName];
|
|
14
|
-
return fn(...args);
|
|
15
|
-
}
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
});
|
|
19
|
-
}, [apiMethodsNames, privateApiRef, visibility]);
|
|
3
|
+
const isFirstRender = React.useRef(true);
|
|
20
4
|
React.useEffect(() => {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
5
|
+
isFirstRender.current = false;
|
|
6
|
+
privateApiRef.current.register(visibility, apiMethods);
|
|
7
|
+
}, [privateApiRef, visibility, apiMethods]);
|
|
8
|
+
if (isFirstRender.current) {
|
|
9
|
+
privateApiRef.current.register(visibility, apiMethods);
|
|
10
|
+
}
|
|
27
11
|
}
|
package/index.js
CHANGED
package/internals/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export type { GridPipeProcessor } from '../hooks/core/pipeProcessing';
|
|
|
11
11
|
export { useGridRegisterStrategyProcessor, GRID_DEFAULT_STRATEGY, } from '../hooks/core/strategyProcessing';
|
|
12
12
|
export type { GridStrategyProcessor } from '../hooks/core/strategyProcessing';
|
|
13
13
|
export { useGridInitialization } from '../hooks/core/useGridInitialization';
|
|
14
|
+
export { unwrapPrivateAPI } from '../hooks/core/useGridApiInitialization';
|
|
14
15
|
export { useGridClipboard } from '../hooks/features/clipboard/useGridClipboard';
|
|
15
16
|
export { useGridColumnHeaders } from '../hooks/features/columnHeaders/useGridColumnHeaders';
|
|
16
17
|
export { unstable_gridHeaderFilteringEditFieldSelector, unstable_gridHeaderFilteringMenuSelector, } from '../hooks/features/headerFiltering/gridHeaderFilteringSelectors';
|
package/internals/index.js
CHANGED
|
@@ -8,6 +8,7 @@ export { getGridFilter } from '../components/panel/filterPanel/GridFilterPanel';
|
|
|
8
8
|
export { useGridRegisterPipeProcessor } from '../hooks/core/pipeProcessing';
|
|
9
9
|
export { useGridRegisterStrategyProcessor, GRID_DEFAULT_STRATEGY } from '../hooks/core/strategyProcessing';
|
|
10
10
|
export { useGridInitialization } from '../hooks/core/useGridInitialization';
|
|
11
|
+
export { unwrapPrivateAPI } from '../hooks/core/useGridApiInitialization';
|
|
11
12
|
export { useGridClipboard } from '../hooks/features/clipboard/useGridClipboard';
|
|
12
13
|
export { useGridColumnHeaders } from '../hooks/features/columnHeaders/useGridColumnHeaders';
|
|
13
14
|
export { unstable_gridHeaderFilteringEditFieldSelector, unstable_gridHeaderFilteringMenuSelector } from '../hooks/features/headerFiltering/gridHeaderFilteringSelectors';
|
|
@@ -183,6 +183,7 @@ DataGridRaw.propTypes = {
|
|
|
183
183
|
value: PropTypes.any
|
|
184
184
|
})).isRequired,
|
|
185
185
|
logicOperator: PropTypes.oneOf(['and', 'or']),
|
|
186
|
+
quickFilterExcludeHiddenColumns: PropTypes.bool,
|
|
186
187
|
quickFilterLogicOperator: PropTypes.oneOf(['and', 'or']),
|
|
187
188
|
quickFilterValues: PropTypes.array
|
|
188
189
|
}),
|
|
@@ -68,23 +68,22 @@ function GridToolbarQuickFilter(props) {
|
|
|
68
68
|
_React$useState2 = _slicedToArray(_React$useState, 2),
|
|
69
69
|
searchValue = _React$useState2[0],
|
|
70
70
|
setSearchValue = _React$useState2[1];
|
|
71
|
-
var
|
|
72
|
-
_React$useState4 = _slicedToArray(_React$useState3, 2),
|
|
73
|
-
prevQuickFilterValues = _React$useState4[0],
|
|
74
|
-
setPrevQuickFilterValues = _React$useState4[1];
|
|
71
|
+
var prevQuickFilterValuesRef = React.useRef(quickFilterValues);
|
|
75
72
|
React.useEffect(function () {
|
|
76
|
-
if (!isDeepEqual(
|
|
73
|
+
if (!isDeepEqual(prevQuickFilterValuesRef.current, quickFilterValues)) {
|
|
77
74
|
// The model of quick filter value has been updated
|
|
78
|
-
|
|
75
|
+
prevQuickFilterValuesRef.current = quickFilterValues;
|
|
79
76
|
|
|
80
77
|
// Update the input value if needed to match the new model
|
|
81
78
|
setSearchValue(function (prevSearchValue) {
|
|
82
79
|
return isDeepEqual(quickFilterParser(prevSearchValue), quickFilterValues) ? prevSearchValue : quickFilterFormatter(quickFilterValues != null ? quickFilterValues : []);
|
|
83
80
|
});
|
|
84
81
|
}
|
|
85
|
-
}, [
|
|
82
|
+
}, [quickFilterValues, quickFilterFormatter, quickFilterParser]);
|
|
86
83
|
var updateSearchValue = React.useCallback(function (newSearchValue) {
|
|
87
|
-
|
|
84
|
+
var newQuickFilterValues = quickFilterParser(newSearchValue);
|
|
85
|
+
prevQuickFilterValuesRef.current = newQuickFilterValues;
|
|
86
|
+
apiRef.current.setQuickFilterValues(newQuickFilterValues);
|
|
88
87
|
}, [apiRef, quickFilterParser]);
|
|
89
88
|
var debouncedUpdateSearchValue = React.useMemo(function () {
|
|
90
89
|
return debounce(updateSearchValue, debounceMs);
|
|
@@ -106,8 +105,9 @@ function GridToolbarQuickFilter(props) {
|
|
|
106
105
|
onChange: handleSearchValueChange,
|
|
107
106
|
placeholder: apiRef.current.getLocaleText('toolbarQuickFilterPlaceholder'),
|
|
108
107
|
"aria-label": apiRef.current.getLocaleText('toolbarQuickFilterLabel'),
|
|
109
|
-
type: "search"
|
|
110
|
-
|
|
108
|
+
type: "search"
|
|
109
|
+
}, other, {
|
|
110
|
+
InputProps: _extends({
|
|
111
111
|
startAdornment: /*#__PURE__*/_jsx(rootProps.slots.quickFilterIcon, {
|
|
112
112
|
fontSize: "small"
|
|
113
113
|
}),
|
|
@@ -123,8 +123,8 @@ function GridToolbarQuickFilter(props) {
|
|
|
123
123
|
fontSize: "small"
|
|
124
124
|
})
|
|
125
125
|
}))
|
|
126
|
-
}
|
|
127
|
-
},
|
|
126
|
+
}, other.InputProps)
|
|
127
|
+
}, (_rootProps$slotProps2 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps2.baseTextField));
|
|
128
128
|
}
|
|
129
129
|
process.env.NODE_ENV !== "production" ? GridToolbarQuickFilter.propTypes = {
|
|
130
130
|
// ----------------------------- Warning --------------------------------
|
|
@@ -34,13 +34,16 @@ import { useGridApiMethod } from '../../utils/useGridApiMethod';
|
|
|
34
34
|
*/
|
|
35
35
|
export var useGridPipeProcessing = function useGridPipeProcessing(apiRef) {
|
|
36
36
|
var processorsCache = React.useRef({});
|
|
37
|
+
var isRunning = React.useRef(false);
|
|
37
38
|
var runAppliers = React.useCallback(function (groupCache) {
|
|
38
|
-
if (!groupCache) {
|
|
39
|
+
if (isRunning.current || !groupCache) {
|
|
39
40
|
return;
|
|
40
41
|
}
|
|
42
|
+
isRunning.current = true;
|
|
41
43
|
Object.values(groupCache.appliers).forEach(function (callback) {
|
|
42
44
|
callback();
|
|
43
45
|
});
|
|
46
|
+
isRunning.current = false;
|
|
44
47
|
}, []);
|
|
45
48
|
var registerPipeProcessor = React.useCallback(function (group, id, processor) {
|
|
46
49
|
if (!processorsCache.current[group]) {
|