@mui/x-data-grid 6.16.3 → 6.18.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 +127 -0
- package/DataGrid/DataGrid.js +13 -0
- package/DataGrid/useDataGridProps.js +3 -1
- package/colDef/gridStringOperators.js +1 -2
- package/components/containers/GridRootStyles.js +2 -1
- package/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.js +6 -2
- package/hooks/core/useGridInitialization.d.ts +1 -1
- package/hooks/core/useGridInitialization.js +3 -0
- package/hooks/features/filter/gridFilterUtils.d.ts +8 -25
- package/hooks/features/filter/gridFilterUtils.js +55 -24
- package/hooks/features/filter/useGridFilter.js +2 -2
- package/hooks/features/rows/useGridRowsMeta.d.ts +1 -1
- package/hooks/features/rows/useGridRowsMeta.js +1 -1
- package/hooks/features/virtualization/useGridVirtualScroller.js +9 -1
- package/index.js +1 -1
- package/legacy/DataGrid/DataGrid.js +13 -0
- package/legacy/DataGrid/useDataGridProps.js +3 -1
- package/legacy/colDef/gridStringOperators.js +1 -2
- package/legacy/components/containers/GridRootStyles.js +2 -1
- package/legacy/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.js +6 -2
- package/legacy/hooks/core/useGridInitialization.js +3 -0
- package/legacy/hooks/features/filter/gridFilterUtils.js +40 -17
- package/legacy/hooks/features/filter/useGridFilter.js +2 -2
- package/legacy/hooks/features/rows/useGridRowsMeta.js +2 -2
- package/legacy/hooks/features/virtualization/useGridVirtualScroller.js +9 -1
- package/legacy/index.js +1 -1
- package/legacy/locales/ptBR.js +13 -14
- package/legacy/utils/utils.js +1 -1
- package/locales/ptBR.js +13 -14
- package/models/api/gridApiCommon.d.ts +3 -2
- package/models/api/gridApiCommunity.d.ts +2 -1
- package/models/api/gridCoreApi.d.ts +7 -1
- package/models/api/gridEditingApi.d.ts +2 -2
- package/models/api/gridFilterApi.d.ts +1 -1
- package/models/api/gridLocaleTextApi.d.ts +3 -2
- package/models/props/DataGridProps.d.ts +13 -0
- package/modern/DataGrid/DataGrid.js +13 -0
- package/modern/DataGrid/useDataGridProps.js +3 -1
- package/modern/colDef/gridStringOperators.js +1 -2
- package/modern/components/containers/GridRootStyles.js +2 -1
- package/modern/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.js +6 -2
- package/modern/hooks/core/useGridInitialization.js +3 -0
- package/modern/hooks/features/filter/gridFilterUtils.js +55 -24
- package/modern/hooks/features/filter/useGridFilter.js +2 -2
- package/modern/hooks/features/rows/useGridRowsMeta.js +1 -1
- package/modern/hooks/features/virtualization/useGridVirtualScroller.js +9 -1
- package/modern/index.js +1 -1
- package/modern/locales/ptBR.js +13 -14
- package/modern/utils/utils.js +1 -1
- package/node/DataGrid/DataGrid.js +13 -0
- package/node/DataGrid/useDataGridProps.js +3 -1
- package/node/colDef/gridStringOperators.js +1 -2
- package/node/components/containers/GridRootStyles.js +2 -1
- package/node/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.js +6 -2
- package/node/hooks/core/useGridInitialization.js +3 -0
- package/node/hooks/features/filter/gridFilterUtils.js +56 -27
- package/node/hooks/features/filter/useGridFilter.js +2 -2
- package/node/hooks/features/rows/useGridRowsMeta.js +1 -1
- package/node/hooks/features/virtualization/useGridVirtualScroller.js +9 -1
- package/node/index.js +1 -1
- package/node/locales/ptBR.js +13 -14
- package/node/utils/utils.js +1 -1
- package/package.json +2 -2
- package/utils/utils.d.ts +1 -1
- package/utils/utils.js +1 -1
|
@@ -17,7 +17,7 @@ try {
|
|
|
17
17
|
/**
|
|
18
18
|
* Adds default values to the optional fields of a filter items.
|
|
19
19
|
* @param {GridFilterItem} item The raw filter item.
|
|
20
|
-
* @param {React.MutableRefObject<
|
|
20
|
+
* @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid.
|
|
21
21
|
* @return {GridFilterItem} The clean filter item with an uniq ID and an always-defined operator.
|
|
22
22
|
* TODO: Make the typing reflect the different between GridFilterInputItem and GridFilterItem.
|
|
23
23
|
*/
|
|
@@ -69,6 +69,12 @@ export const sanitizeFilterModel = (model, disableMultipleColumnsFiltering, apiR
|
|
|
69
69
|
export const mergeStateWithFilterModel = (filterModel, disableMultipleColumnsFiltering, apiRef) => filteringState => _extends({}, filteringState, {
|
|
70
70
|
filterModel: sanitizeFilterModel(filterModel, disableMultipleColumnsFiltering, apiRef)
|
|
71
71
|
});
|
|
72
|
+
const removeDiacritics = value => {
|
|
73
|
+
if (typeof value === 'string') {
|
|
74
|
+
return value.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
};
|
|
72
78
|
const getFilterCallbackFromItem = (filterItem, apiRef) => {
|
|
73
79
|
if (!filterItem.field || !filterItem.operator) {
|
|
74
80
|
return null;
|
|
@@ -84,6 +90,12 @@ const getFilterCallbackFromItem = (filterItem, apiRef) => {
|
|
|
84
90
|
} else {
|
|
85
91
|
parsedValue = filterItem.value;
|
|
86
92
|
}
|
|
93
|
+
const {
|
|
94
|
+
ignoreDiacritics
|
|
95
|
+
} = apiRef.current.rootProps;
|
|
96
|
+
if (ignoreDiacritics) {
|
|
97
|
+
parsedValue = removeDiacritics(parsedValue);
|
|
98
|
+
}
|
|
87
99
|
const newFilterItem = _extends({}, filterItem, {
|
|
88
100
|
value: parsedValue
|
|
89
101
|
});
|
|
@@ -106,7 +118,10 @@ const getFilterCallbackFromItem = (filterItem, apiRef) => {
|
|
|
106
118
|
v7: true,
|
|
107
119
|
item: newFilterItem,
|
|
108
120
|
fn: row => {
|
|
109
|
-
|
|
121
|
+
let value = apiRef.current.getRowValue(row, column);
|
|
122
|
+
if (ignoreDiacritics) {
|
|
123
|
+
value = removeDiacritics(value);
|
|
124
|
+
}
|
|
110
125
|
return applyFilterOnRow(value, row, column, apiRef);
|
|
111
126
|
}
|
|
112
127
|
};
|
|
@@ -121,6 +136,9 @@ const getFilterCallbackFromItem = (filterItem, apiRef) => {
|
|
|
121
136
|
fn: rowId => {
|
|
122
137
|
const params = apiRef.current.getCellParams(rowId, newFilterItem.field);
|
|
123
138
|
GLOBAL_API_REF.current = apiRef;
|
|
139
|
+
if (ignoreDiacritics) {
|
|
140
|
+
params.value = removeDiacritics(params.value);
|
|
141
|
+
}
|
|
124
142
|
const result = applyFilterOnRow(params);
|
|
125
143
|
GLOBAL_API_REF.current = null;
|
|
126
144
|
return result;
|
|
@@ -131,12 +149,11 @@ let filterItemsApplierId = 1;
|
|
|
131
149
|
|
|
132
150
|
/**
|
|
133
151
|
* Generates a method to easily check if a row is matching the current filter model.
|
|
134
|
-
* @param {GridRowIdGetter | undefined} getRowId The getter for row's id.
|
|
135
152
|
* @param {GridFilterModel} filterModel The model with which we want to filter the rows.
|
|
136
|
-
* @param {React.MutableRefObject<
|
|
153
|
+
* @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid.
|
|
137
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.
|
|
138
155
|
*/
|
|
139
|
-
|
|
156
|
+
const buildAggregatedFilterItemsApplier = (filterModel, apiRef, disableEval) => {
|
|
140
157
|
const {
|
|
141
158
|
items
|
|
142
159
|
} = filterModel;
|
|
@@ -151,7 +168,7 @@ export const buildAggregatedFilterItemsApplier = (getRowId, filterModel, apiRef,
|
|
|
151
168
|
for (let i = 0; i < appliers.length; i += 1) {
|
|
152
169
|
const applier = appliers[i];
|
|
153
170
|
if (!shouldApplyFilter || shouldApplyFilter(applier.item.field)) {
|
|
154
|
-
resultPerItemId[applier.item.id] = applier.v7 ? applier.fn(row) : applier.fn(getRowId
|
|
171
|
+
resultPerItemId[applier.item.id] = applier.v7 ? applier.fn(row) : applier.fn(apiRef.current.getRowId(row));
|
|
155
172
|
}
|
|
156
173
|
}
|
|
157
174
|
return resultPerItemId;
|
|
@@ -167,14 +184,14 @@ export const buildAggregatedFilterItemsApplier = (getRowId, filterModel, apiRef,
|
|
|
167
184
|
${appliers.map((applier, i) => `${JSON.stringify(String(applier.item.id))}:
|
|
168
185
|
!shouldApply${i} ?
|
|
169
186
|
false :
|
|
170
|
-
${applier.v7 ? `appliers[${i}].fn(row)` : `appliers[${i}].fn(
|
|
187
|
+
${applier.v7 ? `appliers[${i}].fn(row)` : `appliers[${i}].fn(getRowId(row))`},
|
|
171
188
|
`).join('\n')}};
|
|
172
189
|
|
|
173
190
|
return result$$;
|
|
174
191
|
})`;
|
|
175
192
|
const filterItemCore = evalCode(filterItemTemplate.replaceAll('$$', String(filterItemsApplierId)));
|
|
176
193
|
const filterItem = (row, shouldApplyItem) => {
|
|
177
|
-
return filterItemCore(getRowId, appliers, row, shouldApplyItem);
|
|
194
|
+
return filterItemCore(apiRef.current.getRowId, appliers, row, shouldApplyItem);
|
|
178
195
|
};
|
|
179
196
|
filterItemsApplierId += 1;
|
|
180
197
|
return filterItem;
|
|
@@ -182,12 +199,11 @@ export const buildAggregatedFilterItemsApplier = (getRowId, filterModel, apiRef,
|
|
|
182
199
|
|
|
183
200
|
/**
|
|
184
201
|
* Generates a method to easily check if a row is matching the current quick filter.
|
|
185
|
-
* @param {GridRowIdGetter | undefined} getRowId The getter for row's id.
|
|
186
202
|
* @param {any[]} filterModel The model with which we want to filter the rows.
|
|
187
|
-
* @param {React.MutableRefObject<
|
|
203
|
+
* @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid.
|
|
188
204
|
* @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.
|
|
189
205
|
*/
|
|
190
|
-
|
|
206
|
+
const buildAggregatedQuickFilterApplier = (filterModel, apiRef) => {
|
|
191
207
|
const quickFilterValues = filterModel.quickFilterValues?.filter(Boolean) ?? [];
|
|
192
208
|
if (quickFilterValues.length === 0) {
|
|
193
209
|
return null;
|
|
@@ -195,6 +211,9 @@ export const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef)
|
|
|
195
211
|
const quickFilterExcludeHiddenColumns = filterModel.quickFilterExcludeHiddenColumns ?? false;
|
|
196
212
|
const columnFields = quickFilterExcludeHiddenColumns ? gridVisibleColumnFieldsSelector(apiRef) : gridColumnFieldsSelector(apiRef);
|
|
197
213
|
const appliersPerField = [];
|
|
214
|
+
const {
|
|
215
|
+
ignoreDiacritics
|
|
216
|
+
} = apiRef.current.rootProps;
|
|
198
217
|
columnFields.forEach(field => {
|
|
199
218
|
const column = apiRef.current.getColumn(field);
|
|
200
219
|
const getApplyQuickFilterFn = column?.getApplyQuickFilterFn;
|
|
@@ -204,18 +223,24 @@ export const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef)
|
|
|
204
223
|
if (getApplyQuickFilterFnV7 && !(hasUserFunctionLegacy && !hasUserFunctionV7)) {
|
|
205
224
|
appliersPerField.push({
|
|
206
225
|
column,
|
|
207
|
-
appliers: quickFilterValues.map(
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
226
|
+
appliers: quickFilterValues.map(quickFilterValue => {
|
|
227
|
+
const value = ignoreDiacritics ? removeDiacritics(quickFilterValue) : quickFilterValue;
|
|
228
|
+
return {
|
|
229
|
+
v7: true,
|
|
230
|
+
fn: getApplyQuickFilterFnV7(value, column, apiRef)
|
|
231
|
+
};
|
|
232
|
+
})
|
|
211
233
|
});
|
|
212
234
|
} else if (getApplyQuickFilterFn) {
|
|
213
235
|
appliersPerField.push({
|
|
214
236
|
column,
|
|
215
|
-
appliers: quickFilterValues.map(
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
237
|
+
appliers: quickFilterValues.map(quickFilterValue => {
|
|
238
|
+
const value = ignoreDiacritics ? removeDiacritics(quickFilterValue) : quickFilterValue;
|
|
239
|
+
return {
|
|
240
|
+
v7: false,
|
|
241
|
+
fn: getApplyQuickFilterFn(value, column, apiRef)
|
|
242
|
+
};
|
|
243
|
+
})
|
|
219
244
|
});
|
|
220
245
|
}
|
|
221
246
|
});
|
|
@@ -238,18 +263,24 @@ export const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef)
|
|
|
238
263
|
continue;
|
|
239
264
|
}
|
|
240
265
|
const applier = appliers[v];
|
|
241
|
-
|
|
266
|
+
let value = apiRef.current.getRowFormattedValue(row, column);
|
|
242
267
|
if (applier.fn === null) {
|
|
243
268
|
continue;
|
|
244
269
|
}
|
|
245
270
|
if (applier.v7) {
|
|
271
|
+
if (ignoreDiacritics) {
|
|
272
|
+
value = removeDiacritics(value);
|
|
273
|
+
}
|
|
246
274
|
const isMatching = applier.fn(value, row, column, apiRef);
|
|
247
275
|
if (isMatching) {
|
|
248
276
|
result[filterValue] = true;
|
|
249
277
|
continue outer;
|
|
250
278
|
}
|
|
251
279
|
} else {
|
|
252
|
-
const cellParams = usedCellParams[field] ?? apiRef.current.getCellParams(getRowId
|
|
280
|
+
const cellParams = usedCellParams[field] ?? apiRef.current.getCellParams(apiRef.current.getRowId(row), field);
|
|
281
|
+
if (ignoreDiacritics) {
|
|
282
|
+
cellParams.value = removeDiacritics(cellParams.value);
|
|
283
|
+
}
|
|
253
284
|
usedCellParams[field] = cellParams;
|
|
254
285
|
const isMatching = applier.fn(cellParams);
|
|
255
286
|
if (isMatching) {
|
|
@@ -265,9 +296,9 @@ export const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef)
|
|
|
265
296
|
return result;
|
|
266
297
|
};
|
|
267
298
|
};
|
|
268
|
-
export const buildAggregatedFilterApplier = (
|
|
269
|
-
const isRowMatchingFilterItems = buildAggregatedFilterItemsApplier(
|
|
270
|
-
const isRowMatchingQuickFilter = buildAggregatedQuickFilterApplier(
|
|
299
|
+
export const buildAggregatedFilterApplier = (filterModel, apiRef, disableEval) => {
|
|
300
|
+
const isRowMatchingFilterItems = buildAggregatedFilterItemsApplier(filterModel, apiRef, disableEval);
|
|
301
|
+
const isRowMatchingQuickFilter = buildAggregatedQuickFilterApplier(filterModel, apiRef);
|
|
271
302
|
return function isRowMatchingFilters(row, shouldApplyFilter, result) {
|
|
272
303
|
result.passingFilterItems = isRowMatchingFilterItems?.(row, shouldApplyFilter) ?? null;
|
|
273
304
|
result.passingQuickFilterValues = isRowMatchingQuickFilter?.(row, shouldApplyFilter) ?? null;
|
|
@@ -59,7 +59,7 @@ export const useGridFilter = (apiRef, props) => {
|
|
|
59
59
|
const updateFilteredRows = React.useCallback(() => {
|
|
60
60
|
apiRef.current.setState(state => {
|
|
61
61
|
const filterModel = gridFilterModelSelector(state, apiRef.current.instanceId);
|
|
62
|
-
const isRowMatchingFilters = props.filterMode === 'client' ? buildAggregatedFilterApplier(
|
|
62
|
+
const isRowMatchingFilters = props.filterMode === 'client' ? buildAggregatedFilterApplier(filterModel, apiRef, props.disableEval) : null;
|
|
63
63
|
const filteringResult = apiRef.current.applyStrategyProcessor('filtering', {
|
|
64
64
|
isRowMatchingFilters,
|
|
65
65
|
filterModel: filterModel ?? getDefaultGridFilterModel()
|
|
@@ -73,7 +73,7 @@ export const useGridFilter = (apiRef, props) => {
|
|
|
73
73
|
});
|
|
74
74
|
});
|
|
75
75
|
apiRef.current.publishEvent('filteredRowsSet');
|
|
76
|
-
}, [apiRef, props.filterMode, props.
|
|
76
|
+
}, [apiRef, props.filterMode, props.disableEval]);
|
|
77
77
|
const addColumnMenuItem = React.useCallback((columnMenuItems, colDef) => {
|
|
78
78
|
if (colDef == null || colDef.filterable === false || props.disableColumnFilter) {
|
|
79
79
|
return columnMenuItems;
|
|
@@ -174,7 +174,7 @@ export const useGridRowsMeta = (apiRef, props) => {
|
|
|
174
174
|
rowsHeightLookup.current[id].needsFirstMeasurement = false;
|
|
175
175
|
hydrateRowsMeta();
|
|
176
176
|
}, [hydrateRowsMeta]);
|
|
177
|
-
const debouncedHydrateRowsMeta = React.useMemo(() => debounce(hydrateRowsMeta), [hydrateRowsMeta]);
|
|
177
|
+
const debouncedHydrateRowsMeta = React.useMemo(() => debounce(hydrateRowsMeta, props.rowPositionsDebounceMs), [hydrateRowsMeta, props.rowPositionsDebounceMs]);
|
|
178
178
|
const storeMeasuredRowHeight = React.useCallback((id, height, position) => {
|
|
179
179
|
if (!rowsHeightLookup.current[id] || !rowsHeightLookup.current[id].autoHeight) {
|
|
180
180
|
return;
|
|
@@ -464,6 +464,7 @@ export const useGridVirtualScroller = props => {
|
|
|
464
464
|
rowStyleCache.current = Object.create(null);
|
|
465
465
|
}
|
|
466
466
|
const rows = [];
|
|
467
|
+
let isRowWithFocusedCellRendered = false;
|
|
467
468
|
for (let i = 0; i < renderedRows.length; i += 1) {
|
|
468
469
|
const {
|
|
469
470
|
id,
|
|
@@ -498,6 +499,13 @@ export const useGridVirtualScroller = props => {
|
|
|
498
499
|
const style = _extends({}, rowStyle, rootRowStyle);
|
|
499
500
|
rowStyleCache.current[id] = style;
|
|
500
501
|
}
|
|
502
|
+
let index = rowIndexOffset + (currentPage?.range?.firstRowIndex || 0) + firstRowToRender + i;
|
|
503
|
+
if (isRowWithFocusedCellNotInRange && cellFocus?.id === id) {
|
|
504
|
+
index = indexOfRowWithFocusedCell;
|
|
505
|
+
isRowWithFocusedCellRendered = true;
|
|
506
|
+
} else if (isRowWithFocusedCellRendered) {
|
|
507
|
+
index -= 1;
|
|
508
|
+
}
|
|
501
509
|
rows.push( /*#__PURE__*/_jsx(rootProps.slots.row, _extends({
|
|
502
510
|
row: model,
|
|
503
511
|
rowId: id,
|
|
@@ -511,7 +519,7 @@ export const useGridVirtualScroller = props => {
|
|
|
511
519
|
firstColumnToRender: firstColumnToRender,
|
|
512
520
|
lastColumnToRender: lastColumnToRender,
|
|
513
521
|
selected: isSelected,
|
|
514
|
-
index:
|
|
522
|
+
index: index,
|
|
515
523
|
containerWidth: availableSpace,
|
|
516
524
|
isLastVisible: lastVisibleRowIndex,
|
|
517
525
|
position: position
|
package/modern/index.js
CHANGED
package/modern/locales/ptBR.js
CHANGED
|
@@ -60,13 +60,12 @@ const ptBRGrid = {
|
|
|
60
60
|
filterOperatorIsEmpty: 'está vazio',
|
|
61
61
|
filterOperatorIsNotEmpty: 'não está vazio',
|
|
62
62
|
filterOperatorIsAnyOf: 'é qualquer um dos',
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
63
|
+
'filterOperator=': 'igual à',
|
|
64
|
+
'filterOperator!=': 'diferente de',
|
|
65
|
+
'filterOperator>': 'maior que',
|
|
66
|
+
'filterOperator>=': 'maior ou igual que',
|
|
67
|
+
'filterOperator<': 'menor que',
|
|
68
|
+
'filterOperator<=': 'menor ou igual que',
|
|
70
69
|
// Header filter operators text
|
|
71
70
|
headerFilterOperatorContains: 'Contém',
|
|
72
71
|
headerFilterOperatorEquals: 'Igual',
|
|
@@ -74,13 +73,13 @@ const ptBRGrid = {
|
|
|
74
73
|
headerFilterOperatorEndsWith: 'Termina com',
|
|
75
74
|
headerFilterOperatorIs: 'É',
|
|
76
75
|
headerFilterOperatorNot: 'Não é',
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
76
|
+
headerFilterOperatorAfter: 'Depois de',
|
|
77
|
+
headerFilterOperatorOnOrAfter: 'Está entre ou depois de',
|
|
78
|
+
headerFilterOperatorBefore: 'Antes de',
|
|
79
|
+
headerFilterOperatorOnOrBefore: 'Está entre ou antes de',
|
|
80
|
+
headerFilterOperatorIsEmpty: 'É vazio',
|
|
81
|
+
headerFilterOperatorIsNotEmpty: 'Não é vazio',
|
|
82
|
+
headerFilterOperatorIsAnyOf: 'É algum',
|
|
84
83
|
'headerFilterOperator=': 'Igual',
|
|
85
84
|
'headerFilterOperator!=': 'Não igual',
|
|
86
85
|
'headerFilterOperator>': 'Maior que',
|
package/modern/utils/utils.js
CHANGED
|
@@ -286,6 +286,12 @@ DataGridRaw.propTypes = {
|
|
|
286
286
|
* @default false
|
|
287
287
|
*/
|
|
288
288
|
hideFooterSelectedRowCount: _propTypes.default.bool,
|
|
289
|
+
/**
|
|
290
|
+
* If `true`, the diacritics (accents) are ignored when filtering or quick filtering.
|
|
291
|
+
* E.g. when filter value is `cafe`, the rows with `café` will be visible.
|
|
292
|
+
* @default false
|
|
293
|
+
*/
|
|
294
|
+
ignoreDiacritics: _propTypes.default.bool,
|
|
289
295
|
/**
|
|
290
296
|
* The initial state of the DataGrid.
|
|
291
297
|
* The data in it will be set in the state on initialization but will not be controlled.
|
|
@@ -604,6 +610,13 @@ DataGridRaw.propTypes = {
|
|
|
604
610
|
* Controls the modes of the rows.
|
|
605
611
|
*/
|
|
606
612
|
rowModesModel: _propTypes.default.object,
|
|
613
|
+
/**
|
|
614
|
+
* The milliseconds delay to wait after measuring the row height before recalculating row positions.
|
|
615
|
+
* Setting it to a lower value could be useful when using dynamic row height,
|
|
616
|
+
* but might reduce performance when displaying a large number of rows.
|
|
617
|
+
* @default 166
|
|
618
|
+
*/
|
|
619
|
+
rowPositionsDebounceMs: _propTypes.default.number,
|
|
607
620
|
/**
|
|
608
621
|
* Set of rows of type [[GridRowsProp]].
|
|
609
622
|
*/
|
|
@@ -60,6 +60,7 @@ const DATA_GRID_PROPS_DEFAULT_VALUES = exports.DATA_GRID_PROPS_DEFAULT_VALUES =
|
|
|
60
60
|
hideFooterPagination: false,
|
|
61
61
|
hideFooterRowCount: false,
|
|
62
62
|
hideFooterSelectedRowCount: false,
|
|
63
|
+
ignoreDiacritics: false,
|
|
63
64
|
logger: console,
|
|
64
65
|
logLevel: process.env.NODE_ENV === 'production' ? 'error' : 'warn',
|
|
65
66
|
pagination: false,
|
|
@@ -77,7 +78,8 @@ const DATA_GRID_PROPS_DEFAULT_VALUES = exports.DATA_GRID_PROPS_DEFAULT_VALUES =
|
|
|
77
78
|
keepNonExistentRowsSelected: false,
|
|
78
79
|
keepColumnPositionIfDraggedOutside: false,
|
|
79
80
|
unstable_ignoreValueFormatterDuringExport: false,
|
|
80
|
-
clipboardCopyCellDelimiter: '\t'
|
|
81
|
+
clipboardCopyCellDelimiter: '\t',
|
|
82
|
+
rowPositionsDebounceMs: 166
|
|
81
83
|
};
|
|
82
84
|
const defaultSlots = (0, _utils.uncapitalizeObjectKeys)(_defaultGridSlotsComponents.DATA_GRID_DEFAULT_SLOTS_COMPONENTS);
|
|
83
85
|
const useDataGridProps = inProps => {
|
|
@@ -13,8 +13,7 @@ const getGridStringQuickFilterFn = exports.getGridStringQuickFilterFn = (0, _uti
|
|
|
13
13
|
return null;
|
|
14
14
|
}
|
|
15
15
|
const filterRegex = new RegExp((0, _utils.escapeRegExp)(value), 'i');
|
|
16
|
-
return
|
|
17
|
-
const columnValue = apiRef.current.getRowFormattedValue(row, column);
|
|
16
|
+
return columnValue => {
|
|
18
17
|
return columnValue != null ? filterRegex.test(columnValue.toString()) : false;
|
|
19
18
|
};
|
|
20
19
|
});
|
|
@@ -198,7 +198,8 @@ const GridRootStyles = exports.GridRootStyles = (0, _styles.styled)('div', {
|
|
|
198
198
|
overflow: 'visible !important'
|
|
199
199
|
},
|
|
200
200
|
[`& .${_gridClasses.gridClasses.cell} > *`]: {
|
|
201
|
-
overflow: 'visible !important'
|
|
201
|
+
overflow: 'visible !important',
|
|
202
|
+
whiteSpace: 'nowrap'
|
|
202
203
|
}
|
|
203
204
|
},
|
|
204
205
|
[`& .${_gridClasses.gridClasses['virtualScrollerContent--overflowed']} .${_gridClasses.gridClasses['row--lastVisible']} .${_gridClasses.gridClasses.cell}`]: {
|
|
@@ -41,6 +41,10 @@ function GridColumnMenuSortItem(props) {
|
|
|
41
41
|
if (!colDef || !colDef.sortable || !sortingOrder.some(item => !!item)) {
|
|
42
42
|
return null;
|
|
43
43
|
}
|
|
44
|
+
const getLabel = key => {
|
|
45
|
+
const label = apiRef.current.getLocaleText(key);
|
|
46
|
+
return typeof label === 'function' ? label(colDef) : label;
|
|
47
|
+
};
|
|
44
48
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(React.Fragment, {
|
|
45
49
|
children: [sortingOrder.includes('asc') && sortDirection !== 'asc' ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_MenuItem.default, {
|
|
46
50
|
onClick: onSortMenuItemClick,
|
|
@@ -50,7 +54,7 @@ function GridColumnMenuSortItem(props) {
|
|
|
50
54
|
fontSize: "small"
|
|
51
55
|
})
|
|
52
56
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_ListItemText.default, {
|
|
53
|
-
children:
|
|
57
|
+
children: getLabel('columnMenuSortAsc')
|
|
54
58
|
})]
|
|
55
59
|
}) : null, sortingOrder.includes('desc') && sortDirection !== 'desc' ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_MenuItem.default, {
|
|
56
60
|
onClick: onSortMenuItemClick,
|
|
@@ -60,7 +64,7 @@ function GridColumnMenuSortItem(props) {
|
|
|
60
64
|
fontSize: "small"
|
|
61
65
|
})
|
|
62
66
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_ListItemText.default, {
|
|
63
|
-
children:
|
|
67
|
+
children: getLabel('columnMenuSortDesc')
|
|
64
68
|
})]
|
|
65
69
|
}) : null, sortingOrder.includes(null) && sortDirection != null ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_MenuItem.default, {
|
|
66
70
|
onClick: onSortMenuItemClick,
|
|
@@ -20,6 +20,9 @@ const useGridInitialization = (inputApiRef, props) => {
|
|
|
20
20
|
(0, _pipeProcessing.useGridPipeProcessing)(privateApiRef);
|
|
21
21
|
(0, _strategyProcessing.useGridStrategyProcessing)(privateApiRef);
|
|
22
22
|
(0, _useGridLocaleText.useGridLocaleText)(privateApiRef, props);
|
|
23
|
+
privateApiRef.current.register('private', {
|
|
24
|
+
rootProps: props
|
|
25
|
+
});
|
|
23
26
|
return privateApiRef;
|
|
24
27
|
};
|
|
25
28
|
exports.useGridInitialization = useGridInitialization;
|
|
@@ -4,7 +4,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
|
|
|
4
4
|
Object.defineProperty(exports, "__esModule", {
|
|
5
5
|
value: true
|
|
6
6
|
});
|
|
7
|
-
exports.sanitizeFilterModel = exports.passFilterLogic = exports.mergeStateWithFilterModel = exports.cleanFilterItem = exports.
|
|
7
|
+
exports.sanitizeFilterModel = exports.passFilterLogic = exports.mergeStateWithFilterModel = exports.cleanFilterItem = exports.buildAggregatedFilterApplier = void 0;
|
|
8
8
|
var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
|
|
9
9
|
var _models = require("../../../models");
|
|
10
10
|
var _utils = require("../../../colDef/utils");
|
|
@@ -23,7 +23,7 @@ try {
|
|
|
23
23
|
/**
|
|
24
24
|
* Adds default values to the optional fields of a filter items.
|
|
25
25
|
* @param {GridFilterItem} item The raw filter item.
|
|
26
|
-
* @param {React.MutableRefObject<
|
|
26
|
+
* @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid.
|
|
27
27
|
* @return {GridFilterItem} The clean filter item with an uniq ID and an always-defined operator.
|
|
28
28
|
* TODO: Make the typing reflect the different between GridFilterInputItem and GridFilterItem.
|
|
29
29
|
*/
|
|
@@ -78,6 +78,12 @@ const mergeStateWithFilterModel = (filterModel, disableMultipleColumnsFiltering,
|
|
|
78
78
|
filterModel: sanitizeFilterModel(filterModel, disableMultipleColumnsFiltering, apiRef)
|
|
79
79
|
});
|
|
80
80
|
exports.mergeStateWithFilterModel = mergeStateWithFilterModel;
|
|
81
|
+
const removeDiacritics = value => {
|
|
82
|
+
if (typeof value === 'string') {
|
|
83
|
+
return value.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
|
|
84
|
+
}
|
|
85
|
+
return value;
|
|
86
|
+
};
|
|
81
87
|
const getFilterCallbackFromItem = (filterItem, apiRef) => {
|
|
82
88
|
if (!filterItem.field || !filterItem.operator) {
|
|
83
89
|
return null;
|
|
@@ -93,6 +99,12 @@ const getFilterCallbackFromItem = (filterItem, apiRef) => {
|
|
|
93
99
|
} else {
|
|
94
100
|
parsedValue = filterItem.value;
|
|
95
101
|
}
|
|
102
|
+
const {
|
|
103
|
+
ignoreDiacritics
|
|
104
|
+
} = apiRef.current.rootProps;
|
|
105
|
+
if (ignoreDiacritics) {
|
|
106
|
+
parsedValue = removeDiacritics(parsedValue);
|
|
107
|
+
}
|
|
96
108
|
const newFilterItem = (0, _extends2.default)({}, filterItem, {
|
|
97
109
|
value: parsedValue
|
|
98
110
|
});
|
|
@@ -115,7 +127,10 @@ const getFilterCallbackFromItem = (filterItem, apiRef) => {
|
|
|
115
127
|
v7: true,
|
|
116
128
|
item: newFilterItem,
|
|
117
129
|
fn: row => {
|
|
118
|
-
|
|
130
|
+
let value = apiRef.current.getRowValue(row, column);
|
|
131
|
+
if (ignoreDiacritics) {
|
|
132
|
+
value = removeDiacritics(value);
|
|
133
|
+
}
|
|
119
134
|
return applyFilterOnRow(value, row, column, apiRef);
|
|
120
135
|
}
|
|
121
136
|
};
|
|
@@ -130,6 +145,9 @@ const getFilterCallbackFromItem = (filterItem, apiRef) => {
|
|
|
130
145
|
fn: rowId => {
|
|
131
146
|
const params = apiRef.current.getCellParams(rowId, newFilterItem.field);
|
|
132
147
|
_utils.GLOBAL_API_REF.current = apiRef;
|
|
148
|
+
if (ignoreDiacritics) {
|
|
149
|
+
params.value = removeDiacritics(params.value);
|
|
150
|
+
}
|
|
133
151
|
const result = applyFilterOnRow(params);
|
|
134
152
|
_utils.GLOBAL_API_REF.current = null;
|
|
135
153
|
return result;
|
|
@@ -140,12 +158,11 @@ let filterItemsApplierId = 1;
|
|
|
140
158
|
|
|
141
159
|
/**
|
|
142
160
|
* Generates a method to easily check if a row is matching the current filter model.
|
|
143
|
-
* @param {GridRowIdGetter | undefined} getRowId The getter for row's id.
|
|
144
161
|
* @param {GridFilterModel} filterModel The model with which we want to filter the rows.
|
|
145
|
-
* @param {React.MutableRefObject<
|
|
162
|
+
* @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid.
|
|
146
163
|
* @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.
|
|
147
164
|
*/
|
|
148
|
-
const buildAggregatedFilterItemsApplier = (
|
|
165
|
+
const buildAggregatedFilterItemsApplier = (filterModel, apiRef, disableEval) => {
|
|
149
166
|
const {
|
|
150
167
|
items
|
|
151
168
|
} = filterModel;
|
|
@@ -160,7 +177,7 @@ const buildAggregatedFilterItemsApplier = (getRowId, filterModel, apiRef, disabl
|
|
|
160
177
|
for (let i = 0; i < appliers.length; i += 1) {
|
|
161
178
|
const applier = appliers[i];
|
|
162
179
|
if (!shouldApplyFilter || shouldApplyFilter(applier.item.field)) {
|
|
163
|
-
resultPerItemId[applier.item.id] = applier.v7 ? applier.fn(row) : applier.fn(getRowId
|
|
180
|
+
resultPerItemId[applier.item.id] = applier.v7 ? applier.fn(row) : applier.fn(apiRef.current.getRowId(row));
|
|
164
181
|
}
|
|
165
182
|
}
|
|
166
183
|
return resultPerItemId;
|
|
@@ -176,14 +193,14 @@ const buildAggregatedFilterItemsApplier = (getRowId, filterModel, apiRef, disabl
|
|
|
176
193
|
${appliers.map((applier, i) => `${JSON.stringify(String(applier.item.id))}:
|
|
177
194
|
!shouldApply${i} ?
|
|
178
195
|
false :
|
|
179
|
-
${applier.v7 ? `appliers[${i}].fn(row)` : `appliers[${i}].fn(
|
|
196
|
+
${applier.v7 ? `appliers[${i}].fn(row)` : `appliers[${i}].fn(getRowId(row))`},
|
|
180
197
|
`).join('\n')}};
|
|
181
198
|
|
|
182
199
|
return result$$;
|
|
183
200
|
})`;
|
|
184
201
|
const filterItemCore = evalCode(filterItemTemplate.replaceAll('$$', String(filterItemsApplierId)));
|
|
185
202
|
const filterItem = (row, shouldApplyItem) => {
|
|
186
|
-
return filterItemCore(getRowId, appliers, row, shouldApplyItem);
|
|
203
|
+
return filterItemCore(apiRef.current.getRowId, appliers, row, shouldApplyItem);
|
|
187
204
|
};
|
|
188
205
|
filterItemsApplierId += 1;
|
|
189
206
|
return filterItem;
|
|
@@ -191,13 +208,11 @@ const buildAggregatedFilterItemsApplier = (getRowId, filterModel, apiRef, disabl
|
|
|
191
208
|
|
|
192
209
|
/**
|
|
193
210
|
* Generates a method to easily check if a row is matching the current quick filter.
|
|
194
|
-
* @param {GridRowIdGetter | undefined} getRowId The getter for row's id.
|
|
195
211
|
* @param {any[]} filterModel The model with which we want to filter the rows.
|
|
196
|
-
* @param {React.MutableRefObject<
|
|
212
|
+
* @param {React.MutableRefObject<GridPrivateApiCommunity>} apiRef The API of the grid.
|
|
197
213
|
* @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.
|
|
198
214
|
*/
|
|
199
|
-
|
|
200
|
-
const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef) => {
|
|
215
|
+
const buildAggregatedQuickFilterApplier = (filterModel, apiRef) => {
|
|
201
216
|
const quickFilterValues = filterModel.quickFilterValues?.filter(Boolean) ?? [];
|
|
202
217
|
if (quickFilterValues.length === 0) {
|
|
203
218
|
return null;
|
|
@@ -205,6 +220,9 @@ const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef) => {
|
|
|
205
220
|
const quickFilterExcludeHiddenColumns = filterModel.quickFilterExcludeHiddenColumns ?? false;
|
|
206
221
|
const columnFields = quickFilterExcludeHiddenColumns ? (0, _columns.gridVisibleColumnFieldsSelector)(apiRef) : (0, _columns.gridColumnFieldsSelector)(apiRef);
|
|
207
222
|
const appliersPerField = [];
|
|
223
|
+
const {
|
|
224
|
+
ignoreDiacritics
|
|
225
|
+
} = apiRef.current.rootProps;
|
|
208
226
|
columnFields.forEach(field => {
|
|
209
227
|
const column = apiRef.current.getColumn(field);
|
|
210
228
|
const getApplyQuickFilterFn = column?.getApplyQuickFilterFn;
|
|
@@ -214,18 +232,24 @@ const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef) => {
|
|
|
214
232
|
if (getApplyQuickFilterFnV7 && !(hasUserFunctionLegacy && !hasUserFunctionV7)) {
|
|
215
233
|
appliersPerField.push({
|
|
216
234
|
column,
|
|
217
|
-
appliers: quickFilterValues.map(
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
235
|
+
appliers: quickFilterValues.map(quickFilterValue => {
|
|
236
|
+
const value = ignoreDiacritics ? removeDiacritics(quickFilterValue) : quickFilterValue;
|
|
237
|
+
return {
|
|
238
|
+
v7: true,
|
|
239
|
+
fn: getApplyQuickFilterFnV7(value, column, apiRef)
|
|
240
|
+
};
|
|
241
|
+
})
|
|
221
242
|
});
|
|
222
243
|
} else if (getApplyQuickFilterFn) {
|
|
223
244
|
appliersPerField.push({
|
|
224
245
|
column,
|
|
225
|
-
appliers: quickFilterValues.map(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
246
|
+
appliers: quickFilterValues.map(quickFilterValue => {
|
|
247
|
+
const value = ignoreDiacritics ? removeDiacritics(quickFilterValue) : quickFilterValue;
|
|
248
|
+
return {
|
|
249
|
+
v7: false,
|
|
250
|
+
fn: getApplyQuickFilterFn(value, column, apiRef)
|
|
251
|
+
};
|
|
252
|
+
})
|
|
229
253
|
});
|
|
230
254
|
}
|
|
231
255
|
});
|
|
@@ -248,18 +272,24 @@ const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef) => {
|
|
|
248
272
|
continue;
|
|
249
273
|
}
|
|
250
274
|
const applier = appliers[v];
|
|
251
|
-
|
|
275
|
+
let value = apiRef.current.getRowFormattedValue(row, column);
|
|
252
276
|
if (applier.fn === null) {
|
|
253
277
|
continue;
|
|
254
278
|
}
|
|
255
279
|
if (applier.v7) {
|
|
280
|
+
if (ignoreDiacritics) {
|
|
281
|
+
value = removeDiacritics(value);
|
|
282
|
+
}
|
|
256
283
|
const isMatching = applier.fn(value, row, column, apiRef);
|
|
257
284
|
if (isMatching) {
|
|
258
285
|
result[filterValue] = true;
|
|
259
286
|
continue outer;
|
|
260
287
|
}
|
|
261
288
|
} else {
|
|
262
|
-
const cellParams = usedCellParams[field] ?? apiRef.current.getCellParams(getRowId
|
|
289
|
+
const cellParams = usedCellParams[field] ?? apiRef.current.getCellParams(apiRef.current.getRowId(row), field);
|
|
290
|
+
if (ignoreDiacritics) {
|
|
291
|
+
cellParams.value = removeDiacritics(cellParams.value);
|
|
292
|
+
}
|
|
263
293
|
usedCellParams[field] = cellParams;
|
|
264
294
|
const isMatching = applier.fn(cellParams);
|
|
265
295
|
if (isMatching) {
|
|
@@ -275,10 +305,9 @@ const buildAggregatedQuickFilterApplier = (getRowId, filterModel, apiRef) => {
|
|
|
275
305
|
return result;
|
|
276
306
|
};
|
|
277
307
|
};
|
|
278
|
-
|
|
279
|
-
const
|
|
280
|
-
const
|
|
281
|
-
const isRowMatchingQuickFilter = buildAggregatedQuickFilterApplier(getRowId, filterModel, apiRef);
|
|
308
|
+
const buildAggregatedFilterApplier = (filterModel, apiRef, disableEval) => {
|
|
309
|
+
const isRowMatchingFilterItems = buildAggregatedFilterItemsApplier(filterModel, apiRef, disableEval);
|
|
310
|
+
const isRowMatchingQuickFilter = buildAggregatedQuickFilterApplier(filterModel, apiRef);
|
|
282
311
|
return function isRowMatchingFilters(row, shouldApplyFilter, result) {
|
|
283
312
|
result.passingFilterItems = isRowMatchingFilterItems?.(row, shouldApplyFilter) ?? null;
|
|
284
313
|
result.passingQuickFilterValues = isRowMatchingQuickFilter?.(row, shouldApplyFilter) ?? null;
|
|
@@ -69,7 +69,7 @@ const useGridFilter = (apiRef, props) => {
|
|
|
69
69
|
const updateFilteredRows = React.useCallback(() => {
|
|
70
70
|
apiRef.current.setState(state => {
|
|
71
71
|
const filterModel = (0, _gridFilterSelector.gridFilterModelSelector)(state, apiRef.current.instanceId);
|
|
72
|
-
const isRowMatchingFilters = props.filterMode === 'client' ? (0, _gridFilterUtils.buildAggregatedFilterApplier)(
|
|
72
|
+
const isRowMatchingFilters = props.filterMode === 'client' ? (0, _gridFilterUtils.buildAggregatedFilterApplier)(filterModel, apiRef, props.disableEval) : null;
|
|
73
73
|
const filteringResult = apiRef.current.applyStrategyProcessor('filtering', {
|
|
74
74
|
isRowMatchingFilters,
|
|
75
75
|
filterModel: filterModel ?? (0, _gridFilterState.getDefaultGridFilterModel)()
|
|
@@ -83,7 +83,7 @@ const useGridFilter = (apiRef, props) => {
|
|
|
83
83
|
});
|
|
84
84
|
});
|
|
85
85
|
apiRef.current.publishEvent('filteredRowsSet');
|
|
86
|
-
}, [apiRef, props.filterMode, props.
|
|
86
|
+
}, [apiRef, props.filterMode, props.disableEval]);
|
|
87
87
|
const addColumnMenuItem = React.useCallback((columnMenuItems, colDef) => {
|
|
88
88
|
if (colDef == null || colDef.filterable === false || props.disableColumnFilter) {
|
|
89
89
|
return columnMenuItems;
|
|
@@ -184,7 +184,7 @@ const useGridRowsMeta = (apiRef, props) => {
|
|
|
184
184
|
rowsHeightLookup.current[id].needsFirstMeasurement = false;
|
|
185
185
|
hydrateRowsMeta();
|
|
186
186
|
}, [hydrateRowsMeta]);
|
|
187
|
-
const debouncedHydrateRowsMeta = React.useMemo(() => (0, _utils.unstable_debounce)(hydrateRowsMeta), [hydrateRowsMeta]);
|
|
187
|
+
const debouncedHydrateRowsMeta = React.useMemo(() => (0, _utils.unstable_debounce)(hydrateRowsMeta, props.rowPositionsDebounceMs), [hydrateRowsMeta, props.rowPositionsDebounceMs]);
|
|
188
188
|
const storeMeasuredRowHeight = React.useCallback((id, height, position) => {
|
|
189
189
|
if (!rowsHeightLookup.current[id] || !rowsHeightLookup.current[id].autoHeight) {
|
|
190
190
|
return;
|