@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
@@ -3,58 +3,79 @@ 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
+ const existingPrivateApi = publicApiRef.current?.[SYMBOL_API_PRIVATE];
16
+ if (existingPrivateApi) {
17
+ return existingPrivateApi;
18
+ }
19
+ const state = {};
20
+ const privateApi = {
21
+ state,
22
+ store: Store.create(state),
23
+ instanceId: {
24
+ id: globalId
25
+ }
26
+ };
27
+ globalId += 1;
28
+ privateApi.getPublicApi = () => publicApiRef.current;
29
+ privateApi.register = (visibility, methods) => {
14
30
  Object.keys(methods).forEach(methodName => {
15
- if (visibility === 'public') {
16
- publicApi[methodName] = methods[methodName];
31
+ const method = methods[methodName];
32
+ const currentPrivateMethod = privateApi[methodName];
33
+ if (currentPrivateMethod?.spying === true) {
34
+ currentPrivateMethod.target = method;
17
35
  } else {
18
- privateOnlyApi[methodName] = methods[methodName];
36
+ privateApi[methodName] = method;
37
+ }
38
+ if (visibility === 'public') {
39
+ const publicApi = publicApiRef.current;
40
+ const currentPublicMethod = publicApi[methodName];
41
+ if (currentPublicMethod?.spying === true) {
42
+ currentPublicMethod.target = method;
43
+ } else {
44
+ publicApi[methodName] = method;
45
+ }
19
46
  }
20
47
  });
21
48
  };
22
- const handler = {
23
- get: (obj, prop) => {
24
- if (prop in obj) {
25
- return obj[prop];
26
- }
27
- return privateOnlyApi[prop];
49
+ privateApi.register('private', {
50
+ caches: {},
51
+ eventManager: new EventManager()
52
+ });
53
+ return privateApi;
54
+ }
55
+ function createPublicAPI(privateApiRef) {
56
+ const publicApi = {
57
+ get state() {
58
+ return privateApiRef.current.state;
28
59
  },
29
- set: (obj, prop, value) => {
30
- obj[prop] = value;
31
- return true;
32
- }
60
+ get store() {
61
+ return privateApiRef.current.store;
62
+ },
63
+ get instanceId() {
64
+ return privateApiRef.current.instanceId;
65
+ },
66
+ [SYMBOL_API_PRIVATE]: privateApiRef.current
33
67
  };
34
- return new Proxy(publicApi, handler);
35
- };
68
+ return publicApi;
69
+ }
36
70
  export function useGridApiInitialization(inputApiRef, props) {
37
71
  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
72
  const privateApiRef = React.useRef();
50
73
  if (!privateApiRef.current) {
51
- privateApiRef.current = wrapPublicApi(publicApiRef.current);
52
- privateApiRef.current.register('private', {
53
- caches: {},
54
- eventManager: new EventManager()
55
- });
74
+ privateApiRef.current = createPrivateAPI(publicApiRef);
75
+ }
76
+ if (!publicApiRef.current) {
77
+ publicApiRef.current = createPublicAPI(privateApiRef);
56
78
  }
57
- React.useImperativeHandle(inputApiRef, () => publicApiRef.current, [publicApiRef]);
58
79
  const publishEvent = React.useCallback((...args) => {
59
80
  const [name, params, event = {}] = args;
60
81
  event.defaultMuiPrevented = false;
@@ -77,6 +98,7 @@ export function useGridApiInitialization(inputApiRef, props) {
77
98
  subscribeEvent,
78
99
  publishEvent
79
100
  }, 'public');
101
+ React.useImperativeHandle(inputApiRef, () => publicApiRef.current, [publicApiRef]);
80
102
  React.useEffect(() => {
81
103
  const api = privateApiRef.current;
82
104
  return () => {
@@ -35,43 +35,106 @@ export const serializeCellValue = (cellParams, options) => {
35
35
  return sanitizeCellValue(value, delimiterCharacter);
36
36
  };
37
37
  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.']);
38
+ class CSVRow {
39
+ constructor(options) {
40
+ this.options = void 0;
41
+ this.rowString = '';
42
+ this.isEmpty = true;
43
+ this.options = options;
44
+ }
45
+ addValue(value) {
46
+ if (!this.isEmpty) {
47
+ this.rowString += this.options.delimiterCharacter;
48
+ }
49
+ if (value === null || value === undefined) {
50
+ this.rowString += '';
51
+ } else if (typeof this.options.sanitizeCellValue === 'function') {
52
+ this.rowString += this.options.sanitizeCellValue(value, this.options.delimiterCharacter);
53
+ } else {
54
+ this.rowString += value;
55
+ }
56
+ this.isEmpty = false;
57
+ }
58
+ getRowString() {
59
+ return this.rowString;
60
+ }
61
+ }
38
62
  const serializeRow = ({
39
63
  id,
40
64
  columns,
41
65
  getCellParams,
42
66
  delimiterCharacter,
43
67
  ignoreValueFormatter
44
- }) => columns.map(column => {
45
- const cellParams = getCellParams(id, column.field);
46
- if (process.env.NODE_ENV !== 'production') {
47
- if (String(cellParams.formattedValue) === '[object Object]') {
48
- objectFormattedValueWarning();
68
+ }) => {
69
+ const row = new CSVRow({
70
+ delimiterCharacter
71
+ });
72
+ columns.forEach(column => {
73
+ const cellParams = getCellParams(id, column.field);
74
+ if (process.env.NODE_ENV !== 'production') {
75
+ if (String(cellParams.formattedValue) === '[object Object]') {
76
+ objectFormattedValueWarning();
77
+ }
49
78
  }
50
- }
51
- return serializeCellValue(cellParams, {
52
- delimiterCharacter,
53
- ignoreValueFormatter
79
+ row.addValue(serializeCellValue(cellParams, {
80
+ delimiterCharacter,
81
+ ignoreValueFormatter
82
+ }));
54
83
  });
55
- });
84
+ return row.getRowString();
85
+ };
56
86
  export function buildCSV(options) {
57
87
  const {
58
88
  columns,
59
89
  rowIds,
60
- getCellParams,
61
90
  delimiterCharacter,
62
91
  includeHeaders,
63
- ignoreValueFormatter
92
+ includeColumnGroupsHeaders,
93
+ ignoreValueFormatter,
94
+ apiRef
64
95
  } = options;
65
96
  const CSVBody = rowIds.reduce((acc, id) => `${acc}${serializeRow({
66
97
  id,
67
98
  columns,
68
- getCellParams,
99
+ getCellParams: apiRef.current.getCellParams,
69
100
  delimiterCharacter,
70
101
  ignoreValueFormatter
71
- }).join(delimiterCharacter)}\r\n`, '').trim();
102
+ })}\r\n`, '').trim();
72
103
  if (!includeHeaders) {
73
104
  return CSVBody;
74
105
  }
75
- 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`;
106
+ const filteredColumns = columns.filter(column => column.field !== GRID_CHECKBOX_SELECTION_COL_DEF.field);
107
+ const headerRows = [];
108
+ if (includeColumnGroupsHeaders) {
109
+ const columnGroupLookup = apiRef.current.unstable_getAllGroupDetails();
110
+ let maxColumnGroupsDepth = 0;
111
+ const columnGroupPathsLookup = filteredColumns.reduce((acc, column) => {
112
+ const columnGroupPath = apiRef.current.unstable_getColumnGroupPath(column.field);
113
+ acc[column.field] = columnGroupPath;
114
+ maxColumnGroupsDepth = Math.max(maxColumnGroupsDepth, columnGroupPath.length);
115
+ return acc;
116
+ }, {});
117
+ for (let i = 0; i < maxColumnGroupsDepth; i += 1) {
118
+ const headerGroupRow = new CSVRow({
119
+ delimiterCharacter,
120
+ sanitizeCellValue
121
+ });
122
+ headerRows.push(headerGroupRow);
123
+ filteredColumns.forEach(column => {
124
+ const columnGroupId = (columnGroupPathsLookup[column.field] || [])[i];
125
+ const columnGroup = columnGroupLookup[columnGroupId];
126
+ headerGroupRow.addValue(columnGroup ? columnGroup.headerName || columnGroup.groupId : '');
127
+ });
128
+ }
129
+ }
130
+ const mainHeaderRow = new CSVRow({
131
+ delimiterCharacter,
132
+ sanitizeCellValue
133
+ });
134
+ filteredColumns.forEach(column => {
135
+ mainHeaderRow.addValue(column.headerName || column.field);
136
+ });
137
+ headerRows.push(mainHeaderRow);
138
+ const CSVHead = `${headerRows.map(row => row.getRowString()).join('\r\n')}\r\n`;
76
139
  return `${CSVHead}${CSVBody}`.trim();
77
140
  }
@@ -31,10 +31,11 @@ export const useGridCsvExport = (apiRef, props) => {
31
31
  return buildCSV({
32
32
  columns: exportedColumns,
33
33
  rowIds: exportedRowIds,
34
- getCellParams: apiRef.current.getCellParams,
35
34
  delimiterCharacter: options.delimiter || ',',
36
35
  includeHeaders: options.includeHeaders ?? true,
37
- ignoreValueFormatter
36
+ includeColumnGroupsHeaders: options.includeColumnGroupsHeaders ?? true,
37
+ ignoreValueFormatter,
38
+ apiRef
38
39
  });
39
40
  }, [logger, apiRef, ignoreValueFormatter]);
40
41
  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.
@@ -157,7 +157,8 @@ export const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef)
157
157
  if (quickFilterValues.length === 0) {
158
158
  return null;
159
159
  }
160
- const columnFields = gridColumnFieldsSelector(apiRef);
160
+ const quickFilterExcludeHiddenColumns = filterModel.quickFilterExcludeHiddenColumns ?? false;
161
+ const columnFields = quickFilterExcludeHiddenColumns ? gridVisibleColumnFieldsSelector(apiRef) : gridColumnFieldsSelector(apiRef);
161
162
  const appliersPerField = [];
162
163
  columnFields.forEach(field => {
163
164
  const column = apiRef.current.getColumn(field);
@@ -20,6 +20,7 @@ export const filterStateInitializer = (state, props, apiRef) => {
20
20
  return _extends({}, state, {
21
21
  filter: {
22
22
  filterModel: sanitizeFilterModel(filterModel, props.disableMultipleColumnsFiltering, apiRef),
23
+ filteredRowsLookup: {},
23
24
  filteredDescendantCountLookup: {}
24
25
  },
25
26
  visibleRowsLookup: {}
@@ -330,6 +331,13 @@ export const useGridFilter = (apiRef, props) => {
330
331
  useGridApiEventHandler(apiRef, 'columnsChange', handleColumnsChange);
331
332
  useGridApiEventHandler(apiRef, 'activeStrategyProcessorChange', handleStrategyProcessorChange);
332
333
  useGridApiEventHandler(apiRef, 'rowExpansionChange', updateVisibleRowsLookupState);
334
+ useGridApiEventHandler(apiRef, 'columnVisibilityModelChange', () => {
335
+ const filterModel = gridFilterModelSelector(apiRef);
336
+ if (filterModel.quickFilterValues && filterModel.quickFilterExcludeHiddenColumns) {
337
+ // re-apply filters because the quick filter results may have changed
338
+ apiRef.current.unstable_applyFilters();
339
+ }
340
+ });
333
341
 
334
342
  /**
335
343
  * 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/modern/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
@@ -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';
@@ -37,7 +37,7 @@ const plPLGrid = {
37
37
  columnsPanelHideAllButton: 'Ukryj wszystko',
38
38
  // Filter panel text
39
39
  filterPanelAddFilter: 'Dodaj filtr',
40
- // filterPanelRemoveAll: 'Remove all',
40
+ filterPanelRemoveAll: 'Usuń wszystkie',
41
41
  filterPanelDeleteIconLabel: 'Usuń',
42
42
  filterPanelLogicOperator: 'Operator logiczny',
43
43
  filterPanelOperator: 'Operator',
@@ -68,12 +68,12 @@ const plPLGrid = {
68
68
  // 'filterOperator<=': '<=',
69
69
 
70
70
  // Header filter operators text
71
- // headerFilterOperatorContains: 'Contains',
72
- // headerFilterOperatorEquals: 'Equals',
73
- // headerFilterOperatorStartsWith: 'Starts with',
74
- // headerFilterOperatorEndsWith: 'Ends with',
71
+ headerFilterOperatorContains: 'Zawiera',
72
+ headerFilterOperatorEquals: 'Równa się',
73
+ headerFilterOperatorStartsWith: 'Zaczyna się od',
74
+ headerFilterOperatorEndsWith: 'Kończy się na',
75
75
  // headerFilterOperatorIs: 'Is',
76
- // headerFilterOperatorNot: 'Is not',
76
+ headerFilterOperatorNot: 'Niepuste',
77
77
  // headerFilterOperatorAfter: 'Is after',
78
78
  // headerFilterOperatorOnOrAfter: 'Is on or after',
79
79
  // headerFilterOperatorBefore: 'Is before',
@@ -95,7 +95,7 @@ const plPLGrid = {
95
95
  // Column menu text
96
96
  columnMenuLabel: 'Menu',
97
97
  columnMenuShowColumns: 'Pokaż wszystkie kolumny',
98
- // columnMenuManageColumns: 'Manage columns',
98
+ columnMenuManageColumns: 'Zarządzaj kolumnami',
99
99
  columnMenuFilter: 'Filtr',
100
100
  columnMenuHideColumn: 'Ukryj',
101
101
  columnMenuUnsort: 'Anuluj sortowanie',
@@ -190,6 +190,7 @@ DataGridRaw.propTypes = {
190
190
  value: _propTypes.default.any
191
191
  })).isRequired,
192
192
  logicOperator: _propTypes.default.oneOf(['and', 'or']),
193
+ quickFilterExcludeHiddenColumns: _propTypes.default.bool,
193
194
  quickFilterLogicOperator: _propTypes.default.oneOf(['and', 'or']),
194
195
  quickFilterValues: _propTypes.default.array
195
196
  }),
@@ -64,18 +64,20 @@ function GridToolbarQuickFilter(props) {
64
64
  const rootProps = (0, _useGridRootProps.useGridRootProps)();
65
65
  const quickFilterValues = (0, _useGridSelector.useGridSelector)(apiRef, _filter.gridQuickFilterValuesSelector);
66
66
  const [searchValue, setSearchValue] = React.useState(() => quickFilterFormatter(quickFilterValues ?? []));
67
- const [prevQuickFilterValues, setPrevQuickFilterValues] = React.useState(quickFilterValues);
67
+ const prevQuickFilterValuesRef = React.useRef(quickFilterValues);
68
68
  React.useEffect(() => {
69
- if (!(0, _utils2.isDeepEqual)(prevQuickFilterValues, quickFilterValues)) {
69
+ if (!(0, _utils2.isDeepEqual)(prevQuickFilterValuesRef.current, quickFilterValues)) {
70
70
  // The model of quick filter value has been updated
71
- setPrevQuickFilterValues(quickFilterValues);
71
+ prevQuickFilterValuesRef.current = quickFilterValues;
72
72
 
73
73
  // Update the input value if needed to match the new model
74
74
  setSearchValue(prevSearchValue => (0, _utils2.isDeepEqual)(quickFilterParser(prevSearchValue), quickFilterValues) ? prevSearchValue : quickFilterFormatter(quickFilterValues ?? []));
75
75
  }
76
- }, [prevQuickFilterValues, quickFilterValues, quickFilterFormatter, quickFilterParser]);
76
+ }, [quickFilterValues, quickFilterFormatter, quickFilterParser]);
77
77
  const updateSearchValue = React.useCallback(newSearchValue => {
78
- apiRef.current.setQuickFilterValues(quickFilterParser(newSearchValue));
78
+ const newQuickFilterValues = quickFilterParser(newSearchValue);
79
+ prevQuickFilterValuesRef.current = newQuickFilterValues;
80
+ apiRef.current.setQuickFilterValues(newQuickFilterValues);
79
81
  }, [apiRef, quickFilterParser]);
80
82
  const debouncedUpdateSearchValue = React.useMemo(() => (0, _utils.unstable_debounce)(updateSearchValue, debounceMs), [updateSearchValue, debounceMs]);
81
83
  const handleSearchValueChange = React.useCallback(event => {
@@ -95,8 +97,9 @@ function GridToolbarQuickFilter(props) {
95
97
  onChange: handleSearchValueChange,
96
98
  placeholder: apiRef.current.getLocaleText('toolbarQuickFilterPlaceholder'),
97
99
  "aria-label": apiRef.current.getLocaleText('toolbarQuickFilterLabel'),
98
- type: "search",
99
- InputProps: {
100
+ type: "search"
101
+ }, other, {
102
+ InputProps: (0, _extends2.default)({
100
103
  startAdornment: /*#__PURE__*/(0, _jsxRuntime.jsx)(rootProps.slots.quickFilterIcon, {
101
104
  fontSize: "small"
102
105
  }),
@@ -112,8 +115,8 @@ function GridToolbarQuickFilter(props) {
112
115
  fontSize: "small"
113
116
  })
114
117
  }))
115
- }
116
- }, other, rootProps.slotProps?.baseTextField));
118
+ }, other.InputProps)
119
+ }, rootProps.slotProps?.baseTextField));
117
120
  }
118
121
  process.env.NODE_ENV !== "production" ? GridToolbarQuickFilter.propTypes = {
119
122
  // ----------------------------- Warning --------------------------------
@@ -42,13 +42,16 @@ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj &&
42
42
  */
43
43
  const useGridPipeProcessing = apiRef => {
44
44
  const processorsCache = React.useRef({});
45
+ const isRunning = React.useRef(false);
45
46
  const runAppliers = React.useCallback(groupCache => {
46
- if (!groupCache) {
47
+ if (isRunning.current || !groupCache) {
47
48
  return;
48
49
  }
50
+ isRunning.current = true;
49
51
  Object.values(groupCache.appliers).forEach(callback => {
50
52
  callback();
51
53
  });
54
+ isRunning.current = false;
52
55
  }, []);
53
56
  const registerPipeProcessor = React.useCallback((group, id, processor) => {
54
57
  if (!processorsCache.current[group]) {
@@ -3,6 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.unwrapPrivateAPI = unwrapPrivateAPI;
6
7
  exports.useGridApiInitialization = useGridApiInitialization;
7
8
  var React = _interopRequireWildcard(require("react"));
8
9
  var _Store = require("../../utils/Store");
@@ -11,58 +12,79 @@ var _useGridApiEventHandler = require("../utils/useGridApiEventHandler");
11
12
  var _EventManager = require("../../utils/EventManager");
12
13
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
13
14
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
15
+ const SYMBOL_API_PRIVATE = Symbol('mui.api_private');
14
16
  const isSyntheticEvent = event => {
15
17
  return event.isPropagationStopped !== undefined;
16
18
  };
19
+ function unwrapPrivateAPI(publicApi) {
20
+ return publicApi[SYMBOL_API_PRIVATE];
21
+ }
17
22
  let globalId = 0;
18
- const wrapPublicApi = publicApi => {
19
- const privateOnlyApi = {};
20
- privateOnlyApi.getPublicApi = () => publicApi;
21
- privateOnlyApi.register = (visibility, methods) => {
23
+ function createPrivateAPI(publicApiRef) {
24
+ const existingPrivateApi = publicApiRef.current?.[SYMBOL_API_PRIVATE];
25
+ if (existingPrivateApi) {
26
+ return existingPrivateApi;
27
+ }
28
+ const state = {};
29
+ const privateApi = {
30
+ state,
31
+ store: _Store.Store.create(state),
32
+ instanceId: {
33
+ id: globalId
34
+ }
35
+ };
36
+ globalId += 1;
37
+ privateApi.getPublicApi = () => publicApiRef.current;
38
+ privateApi.register = (visibility, methods) => {
22
39
  Object.keys(methods).forEach(methodName => {
23
- if (visibility === 'public') {
24
- publicApi[methodName] = methods[methodName];
40
+ const method = methods[methodName];
41
+ const currentPrivateMethod = privateApi[methodName];
42
+ if (currentPrivateMethod?.spying === true) {
43
+ currentPrivateMethod.target = method;
25
44
  } else {
26
- privateOnlyApi[methodName] = methods[methodName];
45
+ privateApi[methodName] = method;
46
+ }
47
+ if (visibility === 'public') {
48
+ const publicApi = publicApiRef.current;
49
+ const currentPublicMethod = publicApi[methodName];
50
+ if (currentPublicMethod?.spying === true) {
51
+ currentPublicMethod.target = method;
52
+ } else {
53
+ publicApi[methodName] = method;
54
+ }
27
55
  }
28
56
  });
29
57
  };
30
- const handler = {
31
- get: (obj, prop) => {
32
- if (prop in obj) {
33
- return obj[prop];
34
- }
35
- return privateOnlyApi[prop];
58
+ privateApi.register('private', {
59
+ caches: {},
60
+ eventManager: new _EventManager.EventManager()
61
+ });
62
+ return privateApi;
63
+ }
64
+ function createPublicAPI(privateApiRef) {
65
+ const publicApi = {
66
+ get state() {
67
+ return privateApiRef.current.state;
36
68
  },
37
- set: (obj, prop, value) => {
38
- obj[prop] = value;
39
- return true;
40
- }
69
+ get store() {
70
+ return privateApiRef.current.store;
71
+ },
72
+ get instanceId() {
73
+ return privateApiRef.current.instanceId;
74
+ },
75
+ [SYMBOL_API_PRIVATE]: privateApiRef.current
41
76
  };
42
- return new Proxy(publicApi, handler);
43
- };
77
+ return publicApi;
78
+ }
44
79
  function useGridApiInitialization(inputApiRef, props) {
45
80
  const publicApiRef = React.useRef();
46
- if (!publicApiRef.current) {
47
- const state = {};
48
- publicApiRef.current = {
49
- state,
50
- store: _Store.Store.create(state),
51
- instanceId: {
52
- id: globalId
53
- }
54
- };
55
- globalId += 1;
56
- }
57
81
  const privateApiRef = React.useRef();
58
82
  if (!privateApiRef.current) {
59
- privateApiRef.current = wrapPublicApi(publicApiRef.current);
60
- privateApiRef.current.register('private', {
61
- caches: {},
62
- eventManager: new _EventManager.EventManager()
63
- });
83
+ privateApiRef.current = createPrivateAPI(publicApiRef);
84
+ }
85
+ if (!publicApiRef.current) {
86
+ publicApiRef.current = createPublicAPI(privateApiRef);
64
87
  }
65
- React.useImperativeHandle(inputApiRef, () => publicApiRef.current, [publicApiRef]);
66
88
  const publishEvent = React.useCallback((...args) => {
67
89
  const [name, params, event = {}] = args;
68
90
  event.defaultMuiPrevented = false;
@@ -85,6 +107,7 @@ function useGridApiInitialization(inputApiRef, props) {
85
107
  subscribeEvent,
86
108
  publishEvent
87
109
  }, 'public');
110
+ React.useImperativeHandle(inputApiRef, () => publicApiRef.current, [publicApiRef]);
88
111
  React.useEffect(() => {
89
112
  const api = privateApiRef.current;
90
113
  return () => {