@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.
Files changed (61) hide show
  1. package/CHANGELOG.md +232 -114
  2. package/DataGrid/DataGrid.js +1 -0
  3. package/components/toolbar/GridToolbarQuickFilter.d.ts +1 -1
  4. package/components/toolbar/GridToolbarQuickFilter.js +12 -9
  5. package/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
  6. package/hooks/core/useGridApiInitialization.d.ts +1 -0
  7. package/hooks/core/useGridApiInitialization.js +59 -36
  8. package/hooks/features/export/serializers/csvSerializer.d.ts +9 -6
  9. package/hooks/features/export/serializers/csvSerializer.js +78 -15
  10. package/hooks/features/export/useGridCsvExport.js +4 -3
  11. package/hooks/features/filter/gridFilterUtils.js +6 -5
  12. package/hooks/features/filter/useGridFilter.js +8 -0
  13. package/hooks/features/rows/gridRowsUtils.js +1 -1
  14. package/hooks/utils/useGridApiMethod.js +7 -23
  15. package/index.js +1 -1
  16. package/internals/index.d.ts +1 -0
  17. package/internals/index.js +1 -0
  18. package/legacy/DataGrid/DataGrid.js +1 -0
  19. package/legacy/components/toolbar/GridToolbarQuickFilter.js +12 -12
  20. package/legacy/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
  21. package/legacy/hooks/core/useGridApiInitialization.js +62 -39
  22. package/legacy/hooks/features/export/serializers/csvSerializer.js +84 -11
  23. package/legacy/hooks/features/export/useGridCsvExport.js +4 -3
  24. package/legacy/hooks/features/filter/gridFilterUtils.js +6 -5
  25. package/legacy/hooks/features/filter/useGridFilter.js +8 -0
  26. package/legacy/hooks/features/rows/gridRowsUtils.js +1 -1
  27. package/legacy/hooks/utils/useGridApiMethod.js +7 -25
  28. package/legacy/index.js +1 -1
  29. package/legacy/internals/index.js +1 -0
  30. package/legacy/locales/plPL.js +7 -7
  31. package/locales/plPL.js +7 -7
  32. package/models/events/gridEventLookup.d.ts +0 -1
  33. package/models/gridExport.d.ts +8 -1
  34. package/models/gridFilterModel.d.ts +5 -0
  35. package/modern/DataGrid/DataGrid.js +1 -0
  36. package/modern/components/toolbar/GridToolbarQuickFilter.js +12 -9
  37. package/modern/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
  38. package/modern/hooks/core/useGridApiInitialization.js +58 -36
  39. package/modern/hooks/features/export/serializers/csvSerializer.js +78 -15
  40. package/modern/hooks/features/export/useGridCsvExport.js +3 -2
  41. package/modern/hooks/features/filter/gridFilterUtils.js +3 -2
  42. package/modern/hooks/features/filter/useGridFilter.js +8 -0
  43. package/modern/hooks/features/rows/gridRowsUtils.js +1 -1
  44. package/modern/hooks/utils/useGridApiMethod.js +7 -23
  45. package/modern/index.js +1 -1
  46. package/modern/internals/index.js +1 -0
  47. package/modern/locales/plPL.js +7 -7
  48. package/node/DataGrid/DataGrid.js +1 -0
  49. package/node/components/toolbar/GridToolbarQuickFilter.js +12 -9
  50. package/node/hooks/core/pipeProcessing/useGridPipeProcessing.js +4 -1
  51. package/node/hooks/core/useGridApiInitialization.js +59 -36
  52. package/node/hooks/features/export/serializers/csvSerializer.js +78 -15
  53. package/node/hooks/features/export/useGridCsvExport.js +3 -2
  54. package/node/hooks/features/filter/gridFilterUtils.js +2 -1
  55. package/node/hooks/features/filter/useGridFilter.js +8 -0
  56. package/node/hooks/features/rows/gridRowsUtils.js +1 -1
  57. package/node/hooks/utils/useGridApiMethod.js +7 -23
  58. package/node/index.js +1 -1
  59. package/node/internals/index.js +8 -0
  60. package/node/locales/plPL.js +7 -7
  61. package/package.json +1 -1
@@ -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 [prevQuickFilterValues, setPrevQuickFilterValues] = React.useState(quickFilterValues);
59
+ const prevQuickFilterValuesRef = React.useRef(quickFilterValues);
60
60
  React.useEffect(() => {
61
- if (!isDeepEqual(prevQuickFilterValues, quickFilterValues)) {
61
+ if (!isDeepEqual(prevQuickFilterValuesRef.current, quickFilterValues)) {
62
62
  // The model of quick filter value has been updated
63
- setPrevQuickFilterValues(quickFilterValues);
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
- }, [prevQuickFilterValues, quickFilterValues, quickFilterFormatter, quickFilterParser]);
68
+ }, [quickFilterValues, quickFilterFormatter, quickFilterParser]);
69
69
  const updateSearchValue = React.useCallback(newSearchValue => {
70
- apiRef.current.setQuickFilterValues(quickFilterParser(newSearchValue));
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
- InputProps: {
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
- }, other, (_rootProps$slotProps2 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps2.baseTextField));
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
- const wrapPublicApi = publicApi => {
11
- const privateOnlyApi = {};
12
- privateOnlyApi.getPublicApi = () => publicApi;
13
- privateOnlyApi.register = (visibility, methods) => {
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
- if (visibility === 'public') {
16
- publicApi[methodName] = methods[methodName];
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
- privateOnlyApi[methodName] = methods[methodName];
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
- const handler = {
23
- get: (obj, prop) => {
24
- if (prop in obj) {
25
- return obj[prop];
26
- }
27
- return privateOnlyApi[prop];
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
- set: (obj, prop, value) => {
30
- obj[prop] = value;
31
- return true;
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 new Proxy(publicApi, handler);
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 = wrapPublicApi(publicApiRef.current);
52
- privateApiRef.current.register('private', {
53
- caches: {},
54
- eventManager: new EventManager()
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
- import { GridRowId } from '../../../../models';
2
- import { GridCellParams } from '../../../../models/params/gridCellParams';
3
- import { GridStateColDef } from '../../../../models/colDef/gridColDef';
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
- getCellParams: (id: GridRowId, field: string) => GridCellParams;
12
- delimiterCharacter: string;
13
- includeHeaders: boolean;
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
- }) => columns.map(column => {
47
- const cellParams = getCellParams(id, column.field);
48
- if (process.env.NODE_ENV !== 'production') {
49
- if (String(cellParams.formattedValue) === '[object Object]') {
50
- objectFormattedValueWarning();
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
- return serializeCellValue(cellParams, {
54
- delimiterCharacter,
55
- ignoreValueFormatter
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
- ignoreValueFormatter
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
- }).join(delimiterCharacter)}\r\n`, '').trim();
104
+ })}\r\n`, '').trim();
74
105
  if (!includeHeaders) {
75
106
  return CSVBody;
76
107
  }
77
- const CSVHead = `${columns.filter(column => column.field !== GRID_CHECKBOX_SELECTION_COL_DEF.field).map(column => sanitizeCellValue(column.headerName || column.field, delimiterCharacter)).join(delimiterCharacter)}\r\n`;
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
- ignoreValueFormatter
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 columnFields = gridColumnFieldsSelector(apiRef);
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$quickFil3;
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$quickFil3 = filterModel.quickFilterLogicOperator) != null ? _filterModel$quickFil3 : getDefaultGridFilterModel().quickFilterLogicOperator;
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-autogenerated-id');
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 apiMethodsRef = React.useRef(apiMethods);
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
- apiMethodsRef.current = apiMethods;
22
- }, [apiMethods]);
23
- React.useEffect(() => {
24
- installMethods();
25
- }, [installMethods]);
26
- installMethods();
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
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v6.9.2
2
+ * @mui/x-data-grid v6.10.0
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the
@@ -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';
@@ -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 _React$useState3 = React.useState(quickFilterValues),
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(prevQuickFilterValues, quickFilterValues)) {
73
+ if (!isDeepEqual(prevQuickFilterValuesRef.current, quickFilterValues)) {
77
74
  // The model of quick filter value has been updated
78
- setPrevQuickFilterValues(quickFilterValues);
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
- }, [prevQuickFilterValues, quickFilterValues, quickFilterFormatter, quickFilterParser]);
82
+ }, [quickFilterValues, quickFilterFormatter, quickFilterParser]);
86
83
  var updateSearchValue = React.useCallback(function (newSearchValue) {
87
- apiRef.current.setQuickFilterValues(quickFilterParser(newSearchValue));
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
- InputProps: {
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
- }, other, (_rootProps$slotProps2 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps2.baseTextField));
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]) {