@mui/x-data-grid 7.0.0-alpha.5 → 7.0.0-alpha.7
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 +408 -6
- package/DataGrid/DataGrid.js +31 -21
- package/DataGrid/useDataGridProps.js +0 -1
- package/colDef/gridDateOperators.js +13 -6
- package/colDef/gridSingleSelectColDef.js +6 -15
- package/components/GridPagination.d.ts +2 -2
- package/components/cell/GridEditSingleSelectCell.d.ts +1 -2
- package/components/cell/GridEditSingleSelectCell.js +9 -29
- package/components/columnSelection/GridHeaderCheckbox.js +3 -1
- package/components/panel/filterPanel/GridFilterForm.js +44 -9
- package/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
- package/components/panel/filterPanel/GridFilterInputDate.js +25 -8
- package/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.d.ts +2 -2
- package/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +7 -48
- package/components/panel/filterPanel/GridFilterInputSingleSelect.d.ts +1 -2
- package/components/panel/filterPanel/GridFilterInputSingleSelect.js +15 -57
- package/components/panel/filterPanel/filterPanelUtils.d.ts +3 -2
- package/components/panel/filterPanel/filterPanelUtils.js +10 -5
- package/hooks/features/filter/gridFilterUtils.js +21 -24
- package/hooks/features/rowSelection/useGridRowSelection.js +9 -9
- package/hooks/features/rowSelection/utils.d.ts +2 -0
- package/hooks/features/rowSelection/utils.js +8 -0
- package/hooks/utils/useGridAriaAttributes.js +2 -1
- package/index.js +1 -1
- package/legacy/DataGrid/DataGrid.js +31 -21
- package/legacy/DataGrid/useDataGridProps.js +0 -1
- package/legacy/colDef/gridDateOperators.js +13 -13
- package/legacy/colDef/gridSingleSelectColDef.js +6 -15
- package/legacy/components/cell/GridEditSingleSelectCell.js +8 -28
- package/legacy/components/columnSelection/GridHeaderCheckbox.js +3 -1
- package/legacy/components/panel/filterPanel/GridFilterForm.js +51 -19
- package/legacy/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
- package/legacy/components/panel/filterPanel/GridFilterInputDate.js +27 -8
- package/legacy/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +6 -53
- package/legacy/components/panel/filterPanel/GridFilterInputSingleSelect.js +14 -59
- package/legacy/components/panel/filterPanel/filterPanelUtils.js +10 -6
- package/legacy/hooks/features/filter/gridFilterUtils.js +20 -17
- package/legacy/hooks/features/rowSelection/useGridRowSelection.js +9 -9
- package/legacy/hooks/features/rowSelection/utils.js +8 -0
- package/legacy/hooks/utils/useGridAriaAttributes.js +2 -1
- package/legacy/index.js +1 -1
- package/legacy/locales/csCZ.js +2 -2
- package/locales/csCZ.js +2 -2
- package/models/props/DataGridProps.d.ts +26 -26
- package/modern/DataGrid/DataGrid.js +31 -21
- package/modern/DataGrid/useDataGridProps.js +0 -1
- package/modern/colDef/gridDateOperators.js +13 -6
- package/modern/colDef/gridSingleSelectColDef.js +6 -15
- package/modern/components/cell/GridEditSingleSelectCell.js +9 -29
- package/modern/components/columnSelection/GridHeaderCheckbox.js +3 -1
- package/modern/components/panel/filterPanel/GridFilterForm.js +44 -9
- package/modern/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
- package/modern/components/panel/filterPanel/GridFilterInputDate.js +24 -6
- package/modern/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +7 -47
- package/modern/components/panel/filterPanel/GridFilterInputSingleSelect.js +15 -56
- package/modern/components/panel/filterPanel/filterPanelUtils.js +10 -5
- package/modern/hooks/features/filter/gridFilterUtils.js +21 -24
- package/modern/hooks/features/rowSelection/useGridRowSelection.js +9 -9
- package/modern/hooks/features/rowSelection/utils.js +8 -0
- package/modern/hooks/utils/useGridAriaAttributes.js +2 -1
- package/modern/index.js +1 -1
- package/modern/locales/csCZ.js +2 -2
- package/node/DataGrid/DataGrid.js +31 -21
- package/node/DataGrid/useDataGridProps.js +0 -1
- package/node/colDef/gridDateOperators.js +13 -6
- package/node/colDef/gridSingleSelectColDef.js +5 -14
- package/node/components/cell/GridEditSingleSelectCell.js +8 -28
- package/node/components/columnSelection/GridHeaderCheckbox.js +3 -1
- package/node/components/panel/filterPanel/GridFilterForm.js +44 -9
- package/node/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
- package/node/components/panel/filterPanel/GridFilterInputDate.js +24 -6
- package/node/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +6 -46
- package/node/components/panel/filterPanel/GridFilterInputSingleSelect.js +14 -55
- package/node/components/panel/filterPanel/filterPanelUtils.js +12 -7
- package/node/hooks/features/filter/gridFilterUtils.js +21 -23
- package/node/hooks/features/rowSelection/useGridRowSelection.js +9 -9
- package/node/hooks/features/rowSelection/utils.js +14 -0
- package/node/hooks/utils/useGridAriaAttributes.js +2 -1
- package/node/index.js +1 -1
- package/node/locales/csCZ.js +2 -2
- package/package.json +4 -4
|
@@ -14,6 +14,7 @@ import { GridLogicOperator } from '../../../models/gridFilterItem';
|
|
|
14
14
|
import { useGridApiContext } from '../../../hooks/utils/useGridApiContext';
|
|
15
15
|
import { useGridRootProps } from '../../../hooks/utils/useGridRootProps';
|
|
16
16
|
import { getDataGridUtilityClass } from '../../../constants/gridClasses';
|
|
17
|
+
import { getValueFromValueOptions, getValueOptions } from './filterPanelUtils';
|
|
17
18
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
18
19
|
import { createElement as _createElement } from "react";
|
|
19
20
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
@@ -130,23 +131,39 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
|
|
|
130
131
|
const hasLogicOperatorColumn = hasMultipleFilters && logicOperators.length > 0;
|
|
131
132
|
const baseFormControlProps = rootProps.slotProps?.baseFormControl || {};
|
|
132
133
|
const baseSelectProps = rootProps.slotProps?.baseSelect || {};
|
|
133
|
-
const isBaseSelectNative = baseSelectProps.native ??
|
|
134
|
+
const isBaseSelectNative = baseSelectProps.native ?? false;
|
|
134
135
|
const baseInputLabelProps = rootProps.slotProps?.baseInputLabel || {};
|
|
135
136
|
const baseSelectOptionProps = rootProps.slotProps?.baseSelectOption || {};
|
|
136
137
|
const {
|
|
137
138
|
InputComponentProps
|
|
138
139
|
} = valueInputProps,
|
|
139
140
|
valueInputPropsOther = _objectWithoutPropertiesLoose(valueInputProps, _excluded2);
|
|
140
|
-
const
|
|
141
|
+
const {
|
|
142
|
+
filteredColumns,
|
|
143
|
+
selectedField
|
|
144
|
+
} = React.useMemo(() => {
|
|
145
|
+
let itemField = item.field;
|
|
141
146
|
if (filterColumns === undefined || typeof filterColumns !== 'function') {
|
|
142
|
-
return
|
|
147
|
+
return {
|
|
148
|
+
filteredColumns: filterableColumns,
|
|
149
|
+
selectedField: itemField
|
|
150
|
+
};
|
|
143
151
|
}
|
|
144
152
|
const filteredFields = filterColumns({
|
|
145
153
|
field: item.field,
|
|
146
154
|
columns: filterableColumns,
|
|
147
155
|
currentFilters: filterModel?.items || []
|
|
148
156
|
});
|
|
149
|
-
return
|
|
157
|
+
return {
|
|
158
|
+
filteredColumns: filterableColumns.filter(column => {
|
|
159
|
+
const isFieldIncluded = filteredFields.includes(column.field);
|
|
160
|
+
if (column.field === item.field && !isFieldIncluded) {
|
|
161
|
+
itemField = undefined;
|
|
162
|
+
}
|
|
163
|
+
return isFieldIncluded;
|
|
164
|
+
}),
|
|
165
|
+
selectedField: itemField
|
|
166
|
+
};
|
|
150
167
|
}, [filterColumns, filterModel?.items, filterableColumns, item.field]);
|
|
151
168
|
const sortedFilteredColumns = React.useMemo(() => {
|
|
152
169
|
switch (columnsSort) {
|
|
@@ -177,11 +194,29 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
|
|
|
177
194
|
const newOperator = column.filterOperators.find(operator => operator.value === item.operator) || column.filterOperators[0];
|
|
178
195
|
|
|
179
196
|
// Erase filter value if the input component or filtered column type is modified
|
|
180
|
-
const
|
|
197
|
+
const eraseFilterValue = !newOperator.InputComponent || newOperator.InputComponent !== currentOperator?.InputComponent || column.type !== currentColumn.type;
|
|
198
|
+
let filterValue = eraseFilterValue ? undefined : item.value;
|
|
199
|
+
|
|
200
|
+
// Check filter value against the new valueOptions
|
|
201
|
+
if (column.type === 'singleSelect' && filterValue !== undefined) {
|
|
202
|
+
const colDef = column;
|
|
203
|
+
const valueOptions = getValueOptions(colDef);
|
|
204
|
+
if (Array.isArray(filterValue)) {
|
|
205
|
+
filterValue = filterValue.filter(val => {
|
|
206
|
+
return (
|
|
207
|
+
// Only keep values that are in the new value options
|
|
208
|
+
getValueFromValueOptions(val, valueOptions, colDef?.getOptionValue) !== undefined
|
|
209
|
+
);
|
|
210
|
+
});
|
|
211
|
+
} else if (getValueFromValueOptions(item.value, valueOptions, colDef?.getOptionValue) === undefined) {
|
|
212
|
+
// Reset the filter value if it is not in the new value options
|
|
213
|
+
filterValue = undefined;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
181
216
|
applyFilterChanges(_extends({}, item, {
|
|
182
217
|
field,
|
|
183
218
|
operator: newOperator.value,
|
|
184
|
-
value:
|
|
219
|
+
value: filterValue
|
|
185
220
|
}));
|
|
186
221
|
}, [apiRef, applyFilterChanges, item, currentColumn, currentOperator]);
|
|
187
222
|
const changeOperator = React.useCallback(event => {
|
|
@@ -256,7 +291,7 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
|
|
|
256
291
|
inputProps: {
|
|
257
292
|
'aria-label': apiRef.current.getLocaleText('filterPanelLogicOperator')
|
|
258
293
|
},
|
|
259
|
-
value: multiFilterOperator,
|
|
294
|
+
value: multiFilterOperator ?? '',
|
|
260
295
|
onChange: changeLogicOperator,
|
|
261
296
|
disabled: !!disableMultiFilterOperator || logicOperators.length === 1,
|
|
262
297
|
native: isBaseSelectNative
|
|
@@ -281,7 +316,7 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
|
|
|
281
316
|
labelId: columnSelectLabelId,
|
|
282
317
|
id: columnSelectId,
|
|
283
318
|
label: apiRef.current.getLocaleText('filterPanelColumns'),
|
|
284
|
-
value:
|
|
319
|
+
value: selectedField ?? '',
|
|
285
320
|
onChange: changeColumn,
|
|
286
321
|
native: isBaseSelectNative
|
|
287
322
|
}, rootProps.slotProps?.baseSelect, {
|
|
@@ -327,7 +362,7 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
|
|
|
327
362
|
item: item,
|
|
328
363
|
applyValue: applyFilterChanges,
|
|
329
364
|
focusElementRef: valueRef
|
|
330
|
-
}, currentOperator.InputComponentProps, InputComponentProps)) : null
|
|
365
|
+
}, currentOperator.InputComponentProps, InputComponentProps), item.field) : null
|
|
331
366
|
}))]
|
|
332
367
|
}));
|
|
333
368
|
});
|
|
@@ -32,7 +32,7 @@ function GridFilterInputBoolean(props) {
|
|
|
32
32
|
const labelId = useId();
|
|
33
33
|
const selectId = useId();
|
|
34
34
|
const baseSelectProps = rootProps.slotProps?.baseSelect || {};
|
|
35
|
-
const isSelectNative = baseSelectProps.native ??
|
|
35
|
+
const isSelectNative = baseSelectProps.native ?? false;
|
|
36
36
|
const baseSelectOptionProps = rootProps.slotProps?.baseSelectOption || {};
|
|
37
37
|
const onFilterChange = React.useCallback(event => {
|
|
38
38
|
const value = event.target.value;
|
|
@@ -7,6 +7,23 @@ import { unstable_useId as useId } from '@mui/utils';
|
|
|
7
7
|
import { useTimeout } from '../../../hooks/utils/useTimeout';
|
|
8
8
|
import { useGridRootProps } from '../../../hooks/utils/useGridRootProps';
|
|
9
9
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
10
|
+
function convertFilterItemValueToInputValue(itemValue, inputType) {
|
|
11
|
+
if (itemValue == null) {
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
const dateCopy = new Date(itemValue);
|
|
15
|
+
// The date picker expects the date to be in the local timezone.
|
|
16
|
+
// But .toISOString() converts it to UTC with zero offset.
|
|
17
|
+
// So we need to subtract the timezone offset.
|
|
18
|
+
dateCopy.setMinutes(dateCopy.getMinutes() - dateCopy.getTimezoneOffset());
|
|
19
|
+
if (inputType === 'date') {
|
|
20
|
+
return dateCopy.toISOString().substring(0, 10);
|
|
21
|
+
}
|
|
22
|
+
if (inputType === 'datetime-local') {
|
|
23
|
+
return dateCopy.toISOString().substring(0, 19);
|
|
24
|
+
}
|
|
25
|
+
return dateCopy.toISOString().substring(0, 10);
|
|
26
|
+
}
|
|
10
27
|
function GridFilterInputDate(props) {
|
|
11
28
|
const {
|
|
12
29
|
item,
|
|
@@ -21,25 +38,26 @@ function GridFilterInputDate(props) {
|
|
|
21
38
|
} = props,
|
|
22
39
|
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
23
40
|
const filterTimeout = useTimeout();
|
|
24
|
-
const [filterValueState, setFilterValueState] = React.useState(item.value
|
|
41
|
+
const [filterValueState, setFilterValueState] = React.useState(() => convertFilterItemValueToInputValue(item.value, type));
|
|
25
42
|
const [applying, setIsApplying] = React.useState(false);
|
|
26
43
|
const id = useId();
|
|
27
44
|
const rootProps = useGridRootProps();
|
|
28
45
|
const onFilterChange = React.useCallback(event => {
|
|
46
|
+
filterTimeout.clear();
|
|
29
47
|
const value = event.target.value;
|
|
30
|
-
setFilterValueState(
|
|
48
|
+
setFilterValueState(value);
|
|
31
49
|
setIsApplying(true);
|
|
32
50
|
filterTimeout.start(rootProps.filterDebounceMs, () => {
|
|
33
51
|
applyValue(_extends({}, item, {
|
|
34
|
-
value
|
|
52
|
+
value: new Date(value)
|
|
35
53
|
}));
|
|
36
54
|
setIsApplying(false);
|
|
37
55
|
});
|
|
38
56
|
}, [applyValue, item, rootProps.filterDebounceMs, filterTimeout]);
|
|
39
57
|
React.useEffect(() => {
|
|
40
|
-
const
|
|
41
|
-
setFilterValueState(
|
|
42
|
-
}, [item.value]);
|
|
58
|
+
const value = convertFilterItemValueToInputValue(item.value, type);
|
|
59
|
+
setFilterValueState(value);
|
|
60
|
+
}, [item.value, type]);
|
|
43
61
|
return /*#__PURE__*/_jsx(rootProps.slots.baseTextField, _extends({
|
|
44
62
|
fullWidth: true,
|
|
45
63
|
id: id,
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
2
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
3
|
-
const _excluded = ["item", "applyValue", "type", "apiRef", "focusElementRef", "color", "error", "helperText", "size", "variant"
|
|
3
|
+
const _excluded = ["item", "applyValue", "type", "apiRef", "focusElementRef", "color", "error", "helperText", "size", "variant"];
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
6
|
import Autocomplete, { createFilterOptions } from '@mui/material/Autocomplete';
|
|
7
7
|
import { unstable_useId as useId } from '@mui/utils';
|
|
8
|
-
import { isSingleSelectColDef } from './filterPanelUtils';
|
|
8
|
+
import { getValueOptions, isSingleSelectColDef } from './filterPanelUtils';
|
|
9
9
|
import { useGridRootProps } from '../../../hooks/utils/useGridRootProps';
|
|
10
10
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
11
11
|
const filter = createFilterOptions();
|
|
@@ -19,9 +19,7 @@ function GridFilterInputMultipleSingleSelect(props) {
|
|
|
19
19
|
error,
|
|
20
20
|
helperText,
|
|
21
21
|
size,
|
|
22
|
-
variant = 'standard'
|
|
23
|
-
getOptionLabel: getOptionLabelProp,
|
|
24
|
-
getOptionValue: getOptionValueProp
|
|
22
|
+
variant = 'standard'
|
|
25
23
|
} = props,
|
|
26
24
|
other = _objectWithoutPropertiesLoose(props, _excluded);
|
|
27
25
|
const TextFieldProps = {
|
|
@@ -40,23 +38,12 @@ function GridFilterInputMultipleSingleSelect(props) {
|
|
|
40
38
|
resolvedColumn = column;
|
|
41
39
|
}
|
|
42
40
|
}
|
|
43
|
-
const getOptionValue =
|
|
44
|
-
const getOptionLabel =
|
|
41
|
+
const getOptionValue = resolvedColumn?.getOptionValue;
|
|
42
|
+
const getOptionLabel = resolvedColumn?.getOptionLabel;
|
|
45
43
|
const isOptionEqualToValue = React.useCallback((option, value) => getOptionValue(option) === getOptionValue(value), [getOptionValue]);
|
|
46
44
|
const resolvedValueOptions = React.useMemo(() => {
|
|
47
|
-
|
|
48
|
-
return [];
|
|
49
|
-
}
|
|
50
|
-
if (typeof resolvedColumn.valueOptions === 'function') {
|
|
51
|
-
return resolvedColumn.valueOptions({
|
|
52
|
-
field: resolvedColumn.field
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
return resolvedColumn.valueOptions;
|
|
45
|
+
return getValueOptions(resolvedColumn) || [];
|
|
56
46
|
}, [resolvedColumn]);
|
|
57
|
-
const resolvedFormattedValueOptions = React.useMemo(() => {
|
|
58
|
-
return resolvedValueOptions?.map(getOptionValue);
|
|
59
|
-
}, [resolvedValueOptions, getOptionValue]);
|
|
60
47
|
|
|
61
48
|
// The value is computed from the item.value and used directly
|
|
62
49
|
// If it was done by a useEffect/useState, the Autocomplete could receive incoherent value and options
|
|
@@ -64,23 +51,8 @@ function GridFilterInputMultipleSingleSelect(props) {
|
|
|
64
51
|
if (!Array.isArray(item.value)) {
|
|
65
52
|
return [];
|
|
66
53
|
}
|
|
67
|
-
if (resolvedValueOptions !== undefined) {
|
|
68
|
-
const itemValueIndexes = item.value.map(element => {
|
|
69
|
-
// Gets the index matching between values and valueOptions
|
|
70
|
-
return resolvedFormattedValueOptions?.findIndex(formattedOption => formattedOption === element);
|
|
71
|
-
});
|
|
72
|
-
return itemValueIndexes.filter(index => index >= 0).map(index => resolvedValueOptions[index]);
|
|
73
|
-
}
|
|
74
54
|
return item.value;
|
|
75
|
-
}, [item.value
|
|
76
|
-
React.useEffect(() => {
|
|
77
|
-
if (!Array.isArray(item.value) || filteredValues.length !== item.value.length) {
|
|
78
|
-
// Updates the state if the filter value has been cleaned by the component
|
|
79
|
-
applyValue(_extends({}, item, {
|
|
80
|
-
value: filteredValues.map(getOptionValue)
|
|
81
|
-
}));
|
|
82
|
-
}
|
|
83
|
-
}, [item, filteredValues, applyValue, getOptionValue]);
|
|
55
|
+
}, [item.value]);
|
|
84
56
|
const handleChange = React.useCallback((event, value) => {
|
|
85
57
|
applyValue(_extends({}, item, {
|
|
86
58
|
value: value.map(getOptionValue)
|
|
@@ -123,18 +95,6 @@ process.env.NODE_ENV !== "production" ? GridFilterInputMultipleSingleSelect.prop
|
|
|
123
95
|
}).isRequired,
|
|
124
96
|
applyValue: PropTypes.func.isRequired,
|
|
125
97
|
focusElementRef: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.func, PropTypes.object]),
|
|
126
|
-
/**
|
|
127
|
-
* Used to determine the label displayed for a given value option.
|
|
128
|
-
* @param {ValueOptions} value The current value option.
|
|
129
|
-
* @returns {string} The text to be displayed.
|
|
130
|
-
*/
|
|
131
|
-
getOptionLabel: PropTypes.func,
|
|
132
|
-
/**
|
|
133
|
-
* Used to determine the value used for a value option.
|
|
134
|
-
* @param {ValueOptions} value The current value option.
|
|
135
|
-
* @returns {string} The value to be used.
|
|
136
|
-
*/
|
|
137
|
-
getOptionValue: PropTypes.func,
|
|
138
98
|
item: PropTypes.shape({
|
|
139
99
|
field: PropTypes.string.isRequired,
|
|
140
100
|
id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
@@ -1,32 +1,30 @@
|
|
|
1
1
|
import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
|
|
2
2
|
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
3
|
-
const _excluded = ["item", "applyValue", "type", "apiRef", "focusElementRef", "
|
|
3
|
+
const _excluded = ["item", "applyValue", "type", "apiRef", "focusElementRef", "placeholder", "tabIndex", "label", "isFilterActive", "clearButton", "InputLabelProps"];
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import PropTypes from 'prop-types';
|
|
6
6
|
import { unstable_useId as useId } from '@mui/utils';
|
|
7
7
|
import { styled } from '@mui/material/styles';
|
|
8
8
|
import { useGridRootProps } from '../../../hooks/utils/useGridRootProps';
|
|
9
|
-
import { getValueFromValueOptions, isSingleSelectColDef } from './filterPanelUtils';
|
|
9
|
+
import { getValueFromValueOptions, getValueOptions, isSingleSelectColDef } from './filterPanelUtils';
|
|
10
10
|
import { createElement as _createElement } from "react";
|
|
11
11
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
12
12
|
import { jsxs as _jsxs } from "react/jsx-runtime";
|
|
13
13
|
const renderSingleSelectOptions = ({
|
|
14
|
-
column
|
|
15
|
-
valueOptions,
|
|
16
|
-
field
|
|
17
|
-
},
|
|
14
|
+
column,
|
|
18
15
|
OptionComponent,
|
|
19
16
|
getOptionLabel,
|
|
20
17
|
getOptionValue,
|
|
21
18
|
isSelectNative,
|
|
22
19
|
baseSelectOptionProps
|
|
23
20
|
}) => {
|
|
24
|
-
const iterableColumnValues =
|
|
25
|
-
field
|
|
26
|
-
})] : ['', ...(valueOptions || [])];
|
|
21
|
+
const iterableColumnValues = ['', ...(getValueOptions(column) || [])];
|
|
27
22
|
return iterableColumnValues.map(option => {
|
|
28
23
|
const value = getOptionValue(option);
|
|
29
|
-
|
|
24
|
+
let label = getOptionLabel(option);
|
|
25
|
+
if (label === '') {
|
|
26
|
+
label = ' '; // To force the height of the empty option
|
|
27
|
+
}
|
|
30
28
|
return /*#__PURE__*/_createElement(OptionComponent, _extends({}, baseSelectOptionProps, {
|
|
31
29
|
native: isSelectNative,
|
|
32
30
|
key: value,
|
|
@@ -49,19 +47,17 @@ function GridFilterInputSingleSelect(props) {
|
|
|
49
47
|
type,
|
|
50
48
|
apiRef,
|
|
51
49
|
focusElementRef,
|
|
52
|
-
getOptionLabel: getOptionLabelProp,
|
|
53
|
-
getOptionValue: getOptionValueProp,
|
|
54
50
|
placeholder,
|
|
55
51
|
tabIndex,
|
|
56
52
|
label: labelProp,
|
|
57
53
|
clearButton
|
|
58
54
|
} = props,
|
|
59
55
|
others = _objectWithoutPropertiesLoose(props, _excluded);
|
|
60
|
-
const
|
|
56
|
+
const filterValue = item.value ?? '';
|
|
61
57
|
const id = useId();
|
|
62
58
|
const labelId = useId();
|
|
63
59
|
const rootProps = useGridRootProps();
|
|
64
|
-
const isSelectNative = rootProps.slotProps?.baseSelect?.native ??
|
|
60
|
+
const isSelectNative = rootProps.slotProps?.baseSelect?.native ?? false;
|
|
65
61
|
let resolvedColumn = null;
|
|
66
62
|
if (item.field) {
|
|
67
63
|
const column = apiRef.current.getColumn(item.field);
|
|
@@ -69,52 +65,27 @@ function GridFilterInputSingleSelect(props) {
|
|
|
69
65
|
resolvedColumn = column;
|
|
70
66
|
}
|
|
71
67
|
}
|
|
72
|
-
const getOptionValue =
|
|
73
|
-
const getOptionLabel =
|
|
68
|
+
const getOptionValue = resolvedColumn?.getOptionValue;
|
|
69
|
+
const getOptionLabel = resolvedColumn?.getOptionLabel;
|
|
74
70
|
const currentValueOptions = React.useMemo(() => {
|
|
75
|
-
|
|
76
|
-
return undefined;
|
|
77
|
-
}
|
|
78
|
-
return typeof resolvedColumn.valueOptions === 'function' ? resolvedColumn.valueOptions({
|
|
79
|
-
field: resolvedColumn.field
|
|
80
|
-
}) : resolvedColumn.valueOptions;
|
|
71
|
+
return getValueOptions(resolvedColumn);
|
|
81
72
|
}, [resolvedColumn]);
|
|
82
73
|
const onFilterChange = React.useCallback(event => {
|
|
83
74
|
let value = event.target.value;
|
|
84
75
|
|
|
85
76
|
// NativeSelect casts the value to a string.
|
|
86
77
|
value = getValueFromValueOptions(value, currentValueOptions, getOptionValue);
|
|
87
|
-
setFilterValueState(String(value));
|
|
88
78
|
applyValue(_extends({}, item, {
|
|
89
79
|
value
|
|
90
80
|
}));
|
|
91
81
|
}, [currentValueOptions, getOptionValue, applyValue, item]);
|
|
92
|
-
React.useEffect(() => {
|
|
93
|
-
let itemValue;
|
|
94
|
-
if (currentValueOptions !== undefined) {
|
|
95
|
-
// sanitize if valueOptions are provided
|
|
96
|
-
itemValue = getValueFromValueOptions(item.value, currentValueOptions, getOptionValue);
|
|
97
|
-
if (itemValue !== item.value) {
|
|
98
|
-
applyValue(_extends({}, item, {
|
|
99
|
-
value: itemValue
|
|
100
|
-
}));
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
itemValue = item.value;
|
|
105
|
-
}
|
|
106
|
-
itemValue = itemValue ?? '';
|
|
107
|
-
setFilterValueState(String(itemValue));
|
|
108
|
-
}, [item, currentValueOptions, applyValue, getOptionValue]);
|
|
109
|
-
if (!isSingleSelectColDef(resolvedColumn)) {
|
|
110
|
-
return null;
|
|
111
|
-
}
|
|
112
82
|
if (!isSingleSelectColDef(resolvedColumn)) {
|
|
113
83
|
return null;
|
|
114
84
|
}
|
|
115
85
|
const label = labelProp ?? apiRef.current.getLocaleText('filterPanelInputLabel');
|
|
116
86
|
return /*#__PURE__*/_jsxs(SingleSelectOperatorContainer, {
|
|
117
87
|
children: [/*#__PURE__*/_jsxs(rootProps.slots.baseFormControl, {
|
|
88
|
+
fullWidth: true,
|
|
118
89
|
children: [/*#__PURE__*/_jsx(rootProps.slots.baseInputLabel, _extends({}, rootProps.slotProps?.baseInputLabel, {
|
|
119
90
|
id: labelId,
|
|
120
91
|
htmlFor: id,
|
|
@@ -125,7 +96,7 @@ function GridFilterInputSingleSelect(props) {
|
|
|
125
96
|
id: id,
|
|
126
97
|
label: label,
|
|
127
98
|
labelId: labelId,
|
|
128
|
-
value:
|
|
99
|
+
value: filterValue,
|
|
129
100
|
onChange: onFilterChange,
|
|
130
101
|
variant: "standard",
|
|
131
102
|
type: type || 'text',
|
|
@@ -159,18 +130,6 @@ process.env.NODE_ENV !== "production" ? GridFilterInputSingleSelect.propTypes =
|
|
|
159
130
|
applyValue: PropTypes.func.isRequired,
|
|
160
131
|
clearButton: PropTypes.node,
|
|
161
132
|
focusElementRef: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.func, PropTypes.object]),
|
|
162
|
-
/**
|
|
163
|
-
* Used to determine the label displayed for a given value option.
|
|
164
|
-
* @param {ValueOptions} value The current value option.
|
|
165
|
-
* @returns {string} The text to be displayed.
|
|
166
|
-
*/
|
|
167
|
-
getOptionLabel: PropTypes.func,
|
|
168
|
-
/**
|
|
169
|
-
* Used to determine the value used for a value option.
|
|
170
|
-
* @param {ValueOptions} value The current value option.
|
|
171
|
-
* @returns {string} The value to be used.
|
|
172
|
-
*/
|
|
173
|
-
getOptionValue: PropTypes.func,
|
|
174
133
|
/**
|
|
175
134
|
* It is `true` if the filter either has a value or an operator with no value
|
|
176
135
|
* required is selected (e.g. `isEmpty`)
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
1
2
|
export function isSingleSelectColDef(colDef) {
|
|
2
3
|
return colDef?.type === 'singleSelect';
|
|
3
4
|
}
|
|
5
|
+
export function getValueOptions(column, additionalParams) {
|
|
6
|
+
if (!column) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
return typeof column.valueOptions === 'function' ? column.valueOptions(_extends({
|
|
10
|
+
field: column.field
|
|
11
|
+
}, additionalParams)) : column.valueOptions;
|
|
12
|
+
}
|
|
4
13
|
export function getValueFromValueOptions(value, valueOptions, getOptionValue) {
|
|
5
14
|
if (valueOptions === undefined) {
|
|
6
15
|
return undefined;
|
|
@@ -10,8 +19,4 @@ export function getValueFromValueOptions(value, valueOptions, getOptionValue) {
|
|
|
10
19
|
return String(optionValue) === String(value);
|
|
11
20
|
});
|
|
12
21
|
return getOptionValue(result);
|
|
13
|
-
}
|
|
14
|
-
export const getLabelFromValueOption = valueOption => {
|
|
15
|
-
const label = typeof valueOption === 'object' ? valueOption.label : valueOption;
|
|
16
|
-
return label != null ? String(label) : '';
|
|
17
|
-
};
|
|
22
|
+
}
|
|
@@ -4,15 +4,17 @@ import { getDefaultGridFilterModel } from './gridFilterState';
|
|
|
4
4
|
import { buildWarning } from '../../../utils/warning';
|
|
5
5
|
import { getPublicApiRef } from '../../../utils/getPublicApiRef';
|
|
6
6
|
import { gridColumnFieldsSelector, gridColumnLookupSelector, gridVisibleColumnFieldsSelector } from '../columns';
|
|
7
|
-
|
|
8
|
-
// Fixes https://github.com/mui/mui-x/issues/10056
|
|
9
|
-
const globalScope = typeof window === 'undefined' ? globalThis : window;
|
|
10
|
-
const evalCode = globalScope[atob('ZXZhbA==')];
|
|
11
7
|
let hasEval;
|
|
12
|
-
|
|
13
|
-
hasEval
|
|
14
|
-
|
|
15
|
-
|
|
8
|
+
function getHasEval() {
|
|
9
|
+
if (hasEval !== undefined) {
|
|
10
|
+
return hasEval;
|
|
11
|
+
}
|
|
12
|
+
try {
|
|
13
|
+
hasEval = new Function('return true')();
|
|
14
|
+
} catch (_) {
|
|
15
|
+
hasEval = false;
|
|
16
|
+
}
|
|
17
|
+
return hasEval;
|
|
16
18
|
}
|
|
17
19
|
/**
|
|
18
20
|
* Adds default values to the optional fields of a filter items.
|
|
@@ -139,7 +141,7 @@ const buildAggregatedFilterItemsApplier = (filterModel, apiRef, disableEval) =>
|
|
|
139
141
|
if (appliers.length === 0) {
|
|
140
142
|
return null;
|
|
141
143
|
}
|
|
142
|
-
if (
|
|
144
|
+
if (disableEval || !getHasEval()) {
|
|
143
145
|
// This is the original logic, which is used if `eval()` is not supported (aka prevented by CSP).
|
|
144
146
|
return (row, shouldApplyFilter) => {
|
|
145
147
|
const resultPerItemId = {};
|
|
@@ -153,25 +155,20 @@ const buildAggregatedFilterItemsApplier = (filterModel, apiRef, disableEval) =>
|
|
|
153
155
|
};
|
|
154
156
|
}
|
|
155
157
|
|
|
156
|
-
// We generate a new function with `
|
|
158
|
+
// We generate a new function with `new Function()` to avoid expensive patterns for JS engines
|
|
157
159
|
// such as a dynamic object assignment, e.g. `{ [dynamicKey]: value }`.
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
+
const filterItemCore = new Function('appliers', 'row', 'shouldApplyFilter', `"use strict";
|
|
161
|
+
${appliers.map((applier, i) => `const shouldApply${i} = !shouldApplyFilter || shouldApplyFilter(${JSON.stringify(applier.item.field)});`).join('\n')}
|
|
160
162
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
false :
|
|
165
|
-
appliers[${i}].fn(row),
|
|
166
|
-
`).join('\n')}};
|
|
163
|
+
const result$$ = {
|
|
164
|
+
${appliers.map((applier, i) => ` ${JSON.stringify(String(applier.item.id))}: !shouldApply${i} ? false : appliers[${i}].fn(row),`).join('\n')}
|
|
165
|
+
};
|
|
167
166
|
|
|
168
|
-
|
|
169
|
-
})`;
|
|
170
|
-
const filterItemCore = evalCode(filterItemTemplate.replaceAll('$$', String(filterItemsApplierId)));
|
|
171
|
-
const filterItem = (row, shouldApplyItem) => {
|
|
172
|
-
return filterItemCore(apiRef.current.getRowId, appliers, row, shouldApplyItem);
|
|
173
|
-
};
|
|
167
|
+
return result$$;`.replaceAll('$$', String(filterItemsApplierId)));
|
|
174
168
|
filterItemsApplierId += 1;
|
|
169
|
+
|
|
170
|
+
// Assign to the arrow function a name to help debugging
|
|
171
|
+
const filterItem = (row, shouldApplyItem) => filterItemCore(appliers, row, shouldApplyItem);
|
|
175
172
|
return filterItem;
|
|
176
173
|
};
|
|
177
174
|
export const shouldQuickFilterExcludeHiddenColumns = filterModel => {
|
|
@@ -15,6 +15,7 @@ import { useGridVisibleRows } from '../../utils/useGridVisibleRows';
|
|
|
15
15
|
import { GRID_DETAIL_PANEL_TOGGLE_FIELD } from '../../../constants/gridDetailPanelToggleField';
|
|
16
16
|
import { gridClasses } from '../../../constants/gridClasses';
|
|
17
17
|
import { isEventTargetInPortal } from '../../../utils/domUtils';
|
|
18
|
+
import { isMultipleRowSelectionEnabled } from './utils';
|
|
18
19
|
const getSelectionModelPropValue = (selectionModelProp, prevSelectionModel) => {
|
|
19
20
|
if (selectionModelProp == null) {
|
|
20
21
|
return selectionModelProp;
|
|
@@ -57,11 +58,10 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
57
58
|
});
|
|
58
59
|
const {
|
|
59
60
|
checkboxSelection,
|
|
60
|
-
disableMultipleRowSelection,
|
|
61
61
|
disableRowSelectionOnClick,
|
|
62
62
|
isRowSelectable: propIsRowSelectable
|
|
63
63
|
} = props;
|
|
64
|
-
const canHaveMultipleSelection =
|
|
64
|
+
const canHaveMultipleSelection = isMultipleRowSelectionEnabled(props);
|
|
65
65
|
const visibleRows = useGridVisibleRows(apiRef, props);
|
|
66
66
|
const expandMouseRowRangeSelection = React.useCallback(id => {
|
|
67
67
|
let endId = id;
|
|
@@ -91,7 +91,7 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
91
91
|
* API METHODS
|
|
92
92
|
*/
|
|
93
93
|
const setRowSelectionModel = React.useCallback(model => {
|
|
94
|
-
if (props.signature === GridSignature.DataGrid && !
|
|
94
|
+
if (props.signature === GridSignature.DataGrid && !canHaveMultipleSelection && Array.isArray(model) && model.length > 1) {
|
|
95
95
|
throw new Error(['MUI: `rowSelectionModel` can only contain 1 item in DataGrid.', 'You need to upgrade to DataGridPro or DataGridPremium component to unlock multiple selection.'].join('\n'));
|
|
96
96
|
}
|
|
97
97
|
const currentModel = gridRowSelectionStateSelector(apiRef.current.state);
|
|
@@ -102,7 +102,7 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
102
102
|
}));
|
|
103
103
|
apiRef.current.forceUpdate();
|
|
104
104
|
}
|
|
105
|
-
}, [apiRef, logger, props.rowSelection, props.signature,
|
|
105
|
+
}, [apiRef, logger, props.rowSelection, props.signature, canHaveMultipleSelection]);
|
|
106
106
|
const isRowSelected = React.useCallback(id => gridRowSelectionStateSelector(apiRef.current.state).includes(id), [apiRef]);
|
|
107
107
|
const isRowSelectable = React.useCallback(id => {
|
|
108
108
|
if (propIsRowSelectable && !propIsRowSelectable(apiRef.current.getRowParams(id))) {
|
|
@@ -253,24 +253,24 @@ export const useGridRowSelection = (apiRef, props) => {
|
|
|
253
253
|
if (rowNode.type === 'pinnedRow') {
|
|
254
254
|
return;
|
|
255
255
|
}
|
|
256
|
-
if (event.shiftKey &&
|
|
256
|
+
if (event.shiftKey && canHaveMultipleSelection) {
|
|
257
257
|
expandMouseRowRangeSelection(params.id);
|
|
258
258
|
} else {
|
|
259
259
|
handleSingleRowSelection(params.id, event);
|
|
260
260
|
}
|
|
261
|
-
}, [disableRowSelectionOnClick, canHaveMultipleSelection,
|
|
261
|
+
}, [disableRowSelectionOnClick, canHaveMultipleSelection, apiRef, expandMouseRowRangeSelection, handleSingleRowSelection]);
|
|
262
262
|
const preventSelectionOnShift = React.useCallback((params, event) => {
|
|
263
263
|
if (canHaveMultipleSelection && event.shiftKey) {
|
|
264
264
|
window.getSelection()?.removeAllRanges();
|
|
265
265
|
}
|
|
266
266
|
}, [canHaveMultipleSelection]);
|
|
267
267
|
const handleRowSelectionCheckboxChange = React.useCallback((params, event) => {
|
|
268
|
-
if (event.nativeEvent.shiftKey) {
|
|
268
|
+
if (canHaveMultipleSelection && event.nativeEvent.shiftKey) {
|
|
269
269
|
expandMouseRowRangeSelection(params.id);
|
|
270
270
|
} else {
|
|
271
|
-
apiRef.current.selectRow(params.id, params.value);
|
|
271
|
+
apiRef.current.selectRow(params.id, params.value, !canHaveMultipleSelection);
|
|
272
272
|
}
|
|
273
|
-
}, [apiRef, expandMouseRowRangeSelection]);
|
|
273
|
+
}, [apiRef, expandMouseRowRangeSelection, canHaveMultipleSelection]);
|
|
274
274
|
const handleHeaderSelectionCheckboxChange = React.useCallback(params => {
|
|
275
275
|
const shouldLimitSelectionToCurrentPage = props.checkboxSelectionVisibleOnly && props.pagination;
|
|
276
276
|
const rowsToBeSelected = shouldLimitSelectionToCurrentPage ? gridPaginatedVisibleSortedGridRowIdsSelector(apiRef) : gridExpandedSortedRowIdsSelector(apiRef);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { GridSignature } from '../../utils/useGridApiEventHandler';
|
|
2
|
+
export function isMultipleRowSelectionEnabled(props) {
|
|
3
|
+
if (props.signature === GridSignature.DataGrid) {
|
|
4
|
+
// DataGrid Community has multiple row selection enabled only if checkbox selection is enabled.
|
|
5
|
+
return props.checkboxSelection && props.disableMultipleRowSelection !== true;
|
|
6
|
+
}
|
|
7
|
+
return !props.disableMultipleRowSelection;
|
|
8
|
+
}
|
|
@@ -4,6 +4,7 @@ import { useGridRootProps } from './useGridRootProps';
|
|
|
4
4
|
import { gridColumnGroupsHeaderMaxDepthSelector } from '../features/columnGrouping/gridColumnGroupsSelector';
|
|
5
5
|
import { gridPinnedRowsCountSelector, gridRowCountSelector } from '../features/rows/gridRowsSelector';
|
|
6
6
|
import { useGridPrivateApiContext } from './useGridPrivateApiContext';
|
|
7
|
+
import { isMultipleRowSelectionEnabled } from '../features/rowSelection/utils';
|
|
7
8
|
export const useGridAriaAttributes = () => {
|
|
8
9
|
const apiRef = useGridPrivateApiContext();
|
|
9
10
|
const rootProps = useGridRootProps();
|
|
@@ -19,6 +20,6 @@ export const useGridAriaAttributes = () => {
|
|
|
19
20
|
role,
|
|
20
21
|
'aria-colcount': visibleColumns.length,
|
|
21
22
|
'aria-rowcount': headerGroupingMaxDepth + 1 + pinnedRowsCount + totalRowCount,
|
|
22
|
-
'aria-multiselectable':
|
|
23
|
+
'aria-multiselectable': isMultipleRowSelectionEnabled(rootProps)
|
|
23
24
|
};
|
|
24
25
|
};
|
package/modern/index.js
CHANGED
package/modern/locales/csCZ.js
CHANGED
|
@@ -159,8 +159,8 @@ const csCZGrid = {
|
|
|
159
159
|
treeDataCollapse: 'skrýt potomky',
|
|
160
160
|
// Grouping columns
|
|
161
161
|
groupingColumnHeaderName: 'Skupina',
|
|
162
|
-
groupColumn: name => `
|
|
163
|
-
unGroupColumn: name => `Přestat
|
|
162
|
+
groupColumn: name => `Seskupit podle ${name}`,
|
|
163
|
+
unGroupColumn: name => `Přestat seskupovat podle ${name}`,
|
|
164
164
|
// Master/detail
|
|
165
165
|
detailPanelToggle: 'Přepnout detail panelu',
|
|
166
166
|
expandDetailPanel: 'Rozbalit',
|