@mui/x-data-grid 7.0.0-alpha.5 → 7.0.0-alpha.6

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 (72) hide show
  1. package/CHANGELOG.md +226 -6
  2. package/DataGrid/DataGrid.js +25 -19
  3. package/DataGrid/useDataGridProps.js +0 -1
  4. package/colDef/gridDateOperators.js +13 -6
  5. package/colDef/gridSingleSelectColDef.js +6 -15
  6. package/components/cell/GridEditSingleSelectCell.d.ts +1 -2
  7. package/components/cell/GridEditSingleSelectCell.js +9 -29
  8. package/components/columnSelection/GridHeaderCheckbox.js +3 -1
  9. package/components/panel/filterPanel/GridFilterForm.js +44 -9
  10. package/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
  11. package/components/panel/filterPanel/GridFilterInputDate.js +25 -8
  12. package/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.d.ts +2 -2
  13. package/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +7 -48
  14. package/components/panel/filterPanel/GridFilterInputSingleSelect.d.ts +1 -2
  15. package/components/panel/filterPanel/GridFilterInputSingleSelect.js +15 -57
  16. package/components/panel/filterPanel/filterPanelUtils.d.ts +3 -2
  17. package/components/panel/filterPanel/filterPanelUtils.js +10 -5
  18. package/hooks/features/rowSelection/useGridRowSelection.js +9 -9
  19. package/hooks/features/rowSelection/utils.d.ts +2 -0
  20. package/hooks/features/rowSelection/utils.js +8 -0
  21. package/hooks/utils/useGridAriaAttributes.js +2 -1
  22. package/index.js +1 -1
  23. package/legacy/DataGrid/DataGrid.js +25 -19
  24. package/legacy/DataGrid/useDataGridProps.js +0 -1
  25. package/legacy/colDef/gridDateOperators.js +13 -13
  26. package/legacy/colDef/gridSingleSelectColDef.js +6 -15
  27. package/legacy/components/cell/GridEditSingleSelectCell.js +8 -28
  28. package/legacy/components/columnSelection/GridHeaderCheckbox.js +3 -1
  29. package/legacy/components/panel/filterPanel/GridFilterForm.js +51 -19
  30. package/legacy/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
  31. package/legacy/components/panel/filterPanel/GridFilterInputDate.js +27 -8
  32. package/legacy/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +6 -53
  33. package/legacy/components/panel/filterPanel/GridFilterInputSingleSelect.js +14 -59
  34. package/legacy/components/panel/filterPanel/filterPanelUtils.js +10 -6
  35. package/legacy/hooks/features/rowSelection/useGridRowSelection.js +9 -9
  36. package/legacy/hooks/features/rowSelection/utils.js +8 -0
  37. package/legacy/hooks/utils/useGridAriaAttributes.js +2 -1
  38. package/legacy/index.js +1 -1
  39. package/models/props/DataGridProps.d.ts +26 -25
  40. package/modern/DataGrid/DataGrid.js +25 -19
  41. package/modern/DataGrid/useDataGridProps.js +0 -1
  42. package/modern/colDef/gridDateOperators.js +13 -6
  43. package/modern/colDef/gridSingleSelectColDef.js +6 -15
  44. package/modern/components/cell/GridEditSingleSelectCell.js +9 -29
  45. package/modern/components/columnSelection/GridHeaderCheckbox.js +3 -1
  46. package/modern/components/panel/filterPanel/GridFilterForm.js +44 -9
  47. package/modern/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
  48. package/modern/components/panel/filterPanel/GridFilterInputDate.js +24 -6
  49. package/modern/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +7 -47
  50. package/modern/components/panel/filterPanel/GridFilterInputSingleSelect.js +15 -56
  51. package/modern/components/panel/filterPanel/filterPanelUtils.js +10 -5
  52. package/modern/hooks/features/rowSelection/useGridRowSelection.js +9 -9
  53. package/modern/hooks/features/rowSelection/utils.js +8 -0
  54. package/modern/hooks/utils/useGridAriaAttributes.js +2 -1
  55. package/modern/index.js +1 -1
  56. package/node/DataGrid/DataGrid.js +25 -19
  57. package/node/DataGrid/useDataGridProps.js +0 -1
  58. package/node/colDef/gridDateOperators.js +13 -6
  59. package/node/colDef/gridSingleSelectColDef.js +5 -14
  60. package/node/components/cell/GridEditSingleSelectCell.js +8 -28
  61. package/node/components/columnSelection/GridHeaderCheckbox.js +3 -1
  62. package/node/components/panel/filterPanel/GridFilterForm.js +44 -9
  63. package/node/components/panel/filterPanel/GridFilterInputBoolean.js +1 -1
  64. package/node/components/panel/filterPanel/GridFilterInputDate.js +24 -6
  65. package/node/components/panel/filterPanel/GridFilterInputMultipleSingleSelect.js +6 -46
  66. package/node/components/panel/filterPanel/GridFilterInputSingleSelect.js +14 -55
  67. package/node/components/panel/filterPanel/filterPanelUtils.js +12 -7
  68. package/node/hooks/features/rowSelection/useGridRowSelection.js +9 -9
  69. package/node/hooks/features/rowSelection/utils.js +14 -0
  70. package/node/hooks/utils/useGridAriaAttributes.js +2 -1
  71. package/node/index.js +1 -1
  72. package/package.json +3 -3
@@ -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";
@@ -131,23 +132,39 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
131
132
  const hasLogicOperatorColumn = hasMultipleFilters && logicOperators.length > 0;
132
133
  const baseFormControlProps = ((_rootProps$slotProps = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps.baseFormControl) || {};
133
134
  const baseSelectProps = ((_rootProps$slotProps2 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps2.baseSelect) || {};
134
- const isBaseSelectNative = (_baseSelectProps$nati = baseSelectProps.native) != null ? _baseSelectProps$nati : true;
135
+ const isBaseSelectNative = (_baseSelectProps$nati = baseSelectProps.native) != null ? _baseSelectProps$nati : false;
135
136
  const baseInputLabelProps = ((_rootProps$slotProps3 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps3.baseInputLabel) || {};
136
137
  const baseSelectOptionProps = ((_rootProps$slotProps4 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps4.baseSelectOption) || {};
137
138
  const {
138
139
  InputComponentProps
139
140
  } = valueInputProps,
140
141
  valueInputPropsOther = _objectWithoutPropertiesLoose(valueInputProps, _excluded2);
141
- const filteredColumns = React.useMemo(() => {
142
+ const {
143
+ filteredColumns,
144
+ selectedField
145
+ } = React.useMemo(() => {
146
+ let itemField = item.field;
142
147
  if (filterColumns === undefined || typeof filterColumns !== 'function') {
143
- return filterableColumns;
148
+ return {
149
+ filteredColumns: filterableColumns,
150
+ selectedField: itemField
151
+ };
144
152
  }
145
153
  const filteredFields = filterColumns({
146
154
  field: item.field,
147
155
  columns: filterableColumns,
148
156
  currentFilters: (filterModel == null ? void 0 : filterModel.items) || []
149
157
  });
150
- return filterableColumns.filter(column => filteredFields.includes(column.field));
158
+ return {
159
+ filteredColumns: filterableColumns.filter(column => {
160
+ const isFieldIncluded = filteredFields.includes(column.field);
161
+ if (column.field === item.field && !isFieldIncluded) {
162
+ itemField = undefined;
163
+ }
164
+ return isFieldIncluded;
165
+ }),
166
+ selectedField: itemField
167
+ };
151
168
  }, [filterColumns, filterModel == null ? void 0 : filterModel.items, filterableColumns, item.field]);
152
169
  const sortedFilteredColumns = React.useMemo(() => {
153
170
  switch (columnsSort) {
@@ -179,11 +196,29 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
179
196
  const newOperator = column.filterOperators.find(operator => operator.value === item.operator) || column.filterOperators[0];
180
197
 
181
198
  // Erase filter value if the input component or filtered column type is modified
182
- const eraseItemValue = !newOperator.InputComponent || newOperator.InputComponent !== (currentOperator == null ? void 0 : currentOperator.InputComponent) || column.type !== currentColumn.type;
199
+ const eraseFilterValue = !newOperator.InputComponent || newOperator.InputComponent !== (currentOperator == null ? void 0 : currentOperator.InputComponent) || column.type !== currentColumn.type;
200
+ let filterValue = eraseFilterValue ? undefined : item.value;
201
+
202
+ // Check filter value against the new valueOptions
203
+ if (column.type === 'singleSelect' && filterValue !== undefined) {
204
+ const colDef = column;
205
+ const valueOptions = getValueOptions(colDef);
206
+ if (Array.isArray(filterValue)) {
207
+ filterValue = filterValue.filter(val => {
208
+ return (
209
+ // Only keep values that are in the new value options
210
+ getValueFromValueOptions(val, valueOptions, colDef == null ? void 0 : colDef.getOptionValue) !== undefined
211
+ );
212
+ });
213
+ } else if (getValueFromValueOptions(item.value, valueOptions, colDef == null ? void 0 : colDef.getOptionValue) === undefined) {
214
+ // Reset the filter value if it is not in the new value options
215
+ filterValue = undefined;
216
+ }
217
+ }
183
218
  applyFilterChanges(_extends({}, item, {
184
219
  field,
185
220
  operator: newOperator.value,
186
- value: eraseItemValue ? undefined : item.value
221
+ value: filterValue
187
222
  }));
188
223
  }, [apiRef, applyFilterChanges, item, currentColumn, currentOperator]);
189
224
  const changeOperator = React.useCallback(event => {
@@ -259,7 +294,7 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
259
294
  inputProps: {
260
295
  'aria-label': apiRef.current.getLocaleText('filterPanelLogicOperator')
261
296
  },
262
- value: multiFilterOperator,
297
+ value: multiFilterOperator != null ? multiFilterOperator : '',
263
298
  onChange: changeLogicOperator,
264
299
  disabled: !!disableMultiFilterOperator || logicOperators.length === 1,
265
300
  native: isBaseSelectNative
@@ -284,7 +319,7 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
284
319
  labelId: columnSelectLabelId,
285
320
  id: columnSelectId,
286
321
  label: apiRef.current.getLocaleText('filterPanelColumns'),
287
- value: item.field || '',
322
+ value: selectedField != null ? selectedField : '',
288
323
  onChange: changeColumn,
289
324
  native: isBaseSelectNative
290
325
  }, (_rootProps$slotProps7 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps7.baseSelect, {
@@ -330,7 +365,7 @@ const GridFilterForm = /*#__PURE__*/React.forwardRef(function GridFilterForm(pro
330
365
  item: item,
331
366
  applyValue: applyFilterChanges,
332
367
  focusElementRef: valueRef
333
- }, currentOperator.InputComponentProps, InputComponentProps)) : null
368
+ }, currentOperator.InputComponentProps, InputComponentProps), item.field) : null
334
369
  }))]
335
370
  }));
336
371
  });
@@ -33,7 +33,7 @@ function GridFilterInputBoolean(props) {
33
33
  const labelId = useId();
34
34
  const selectId = useId();
35
35
  const baseSelectProps = ((_rootProps$slotProps = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps.baseSelect) || {};
36
- const isSelectNative = (_baseSelectProps$nati = baseSelectProps.native) != null ? _baseSelectProps$nati : true;
36
+ const isSelectNative = (_baseSelectProps$nati = baseSelectProps.native) != null ? _baseSelectProps$nati : false;
37
37
  const baseSelectOptionProps = ((_rootProps$slotProps2 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps2.baseSelectOption) || {};
38
38
  const onFilterChange = React.useCallback(event => {
39
39
  const value = event.target.value;
@@ -7,8 +7,25 @@ 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
- var _item$value, _rootProps$slotProps;
28
+ var _rootProps$slotProps;
12
29
  const {
13
30
  item,
14
31
  applyValue,
@@ -22,26 +39,26 @@ function GridFilterInputDate(props) {
22
39
  } = props,
23
40
  other = _objectWithoutPropertiesLoose(props, _excluded);
24
41
  const filterTimeout = useTimeout();
25
- const [filterValueState, setFilterValueState] = React.useState((_item$value = item.value) != null ? _item$value : '');
42
+ const [filterValueState, setFilterValueState] = React.useState(() => convertFilterItemValueToInputValue(item.value, type));
26
43
  const [applying, setIsApplying] = React.useState(false);
27
44
  const id = useId();
28
45
  const rootProps = useGridRootProps();
29
46
  const onFilterChange = React.useCallback(event => {
47
+ filterTimeout.clear();
30
48
  const value = event.target.value;
31
- setFilterValueState(String(value));
49
+ setFilterValueState(value);
32
50
  setIsApplying(true);
33
51
  filterTimeout.start(rootProps.filterDebounceMs, () => {
34
52
  applyValue(_extends({}, item, {
35
- value
53
+ value: new Date(value)
36
54
  }));
37
55
  setIsApplying(false);
38
56
  });
39
57
  }, [applyValue, item, rootProps.filterDebounceMs, filterTimeout]);
40
58
  React.useEffect(() => {
41
- var _item$value2;
42
- const itemValue = (_item$value2 = item.value) != null ? _item$value2 : '';
43
- setFilterValueState(String(itemValue));
44
- }, [item.value]);
59
+ const value = convertFilterItemValueToInputValue(item.value, type);
60
+ setFilterValueState(value);
61
+ }, [item.value, type]);
45
62
  return /*#__PURE__*/_jsx(rootProps.slots.baseTextField, _extends({
46
63
  fullWidth: true,
47
64
  id: id,
@@ -1,8 +1,8 @@
1
1
  import * as React from 'react';
2
2
  import { AutocompleteProps } from '@mui/material/Autocomplete';
3
3
  import { GridFilterInputValueProps } from './GridFilterInputValueProps';
4
- import type { GridSingleSelectColDef, ValueOptions } from '../../../models/colDef/gridColDef';
5
- export interface GridFilterInputMultipleSingleSelectProps extends Omit<AutocompleteProps<ValueOptions, true, false, true>, 'options' | 'renderInput' | 'onChange' | 'value' | 'id' | 'filterOptions' | 'isOptionEqualToValue' | 'multiple' | 'color' | 'getOptionLabel'>, Pick<GridSingleSelectColDef, 'getOptionLabel' | 'getOptionValue'>, GridFilterInputValueProps {
4
+ import type { ValueOptions } from '../../../models/colDef/gridColDef';
5
+ export interface GridFilterInputMultipleSingleSelectProps extends Omit<AutocompleteProps<ValueOptions, true, false, true>, 'options' | 'renderInput' | 'onChange' | 'value' | 'id' | 'filterOptions' | 'isOptionEqualToValue' | 'multiple' | 'color' | 'getOptionLabel'>, GridFilterInputValueProps {
6
6
  type?: 'singleSelect';
7
7
  }
8
8
  declare function GridFilterInputMultipleSingleSelect(props: GridFilterInputMultipleSingleSelectProps): React.JSX.Element;
@@ -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", "getOptionLabel", "getOptionValue"];
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();
@@ -20,9 +20,7 @@ function GridFilterInputMultipleSingleSelect(props) {
20
20
  error,
21
21
  helperText,
22
22
  size,
23
- variant = 'standard',
24
- getOptionLabel: getOptionLabelProp,
25
- getOptionValue: getOptionValueProp
23
+ variant = 'standard'
26
24
  } = props,
27
25
  other = _objectWithoutPropertiesLoose(props, _excluded);
28
26
  const TextFieldProps = {
@@ -41,24 +39,12 @@ function GridFilterInputMultipleSingleSelect(props) {
41
39
  resolvedColumn = column;
42
40
  }
43
41
  }
44
- const getOptionValue = getOptionValueProp || ((_resolvedColumn = resolvedColumn) == null ? void 0 : _resolvedColumn.getOptionValue);
45
- const getOptionLabel = getOptionLabelProp || ((_resolvedColumn2 = resolvedColumn) == null ? void 0 : _resolvedColumn2.getOptionLabel);
42
+ const getOptionValue = (_resolvedColumn = resolvedColumn) == null ? void 0 : _resolvedColumn.getOptionValue;
43
+ const getOptionLabel = (_resolvedColumn2 = resolvedColumn) == null ? void 0 : _resolvedColumn2.getOptionLabel;
46
44
  const isOptionEqualToValue = React.useCallback((option, value) => getOptionValue(option) === getOptionValue(value), [getOptionValue]);
47
45
  const resolvedValueOptions = React.useMemo(() => {
48
- var _resolvedColumn3;
49
- if (!((_resolvedColumn3 = resolvedColumn) != null && _resolvedColumn3.valueOptions)) {
50
- return [];
51
- }
52
- if (typeof resolvedColumn.valueOptions === 'function') {
53
- return resolvedColumn.valueOptions({
54
- field: resolvedColumn.field
55
- });
56
- }
57
- return resolvedColumn.valueOptions;
46
+ return getValueOptions(resolvedColumn) || [];
58
47
  }, [resolvedColumn]);
59
- const resolvedFormattedValueOptions = React.useMemo(() => {
60
- return resolvedValueOptions == null ? void 0 : resolvedValueOptions.map(getOptionValue);
61
- }, [resolvedValueOptions, getOptionValue]);
62
48
 
63
49
  // The value is computed from the item.value and used directly
64
50
  // If it was done by a useEffect/useState, the Autocomplete could receive incoherent value and options
@@ -66,23 +52,8 @@ function GridFilterInputMultipleSingleSelect(props) {
66
52
  if (!Array.isArray(item.value)) {
67
53
  return [];
68
54
  }
69
- if (resolvedValueOptions !== undefined) {
70
- const itemValueIndexes = item.value.map(element => {
71
- // Gets the index matching between values and valueOptions
72
- return resolvedFormattedValueOptions == null ? void 0 : resolvedFormattedValueOptions.findIndex(formattedOption => formattedOption === element);
73
- });
74
- return itemValueIndexes.filter(index => index >= 0).map(index => resolvedValueOptions[index]);
75
- }
76
55
  return item.value;
77
- }, [item.value, resolvedValueOptions, resolvedFormattedValueOptions]);
78
- React.useEffect(() => {
79
- if (!Array.isArray(item.value) || filteredValues.length !== item.value.length) {
80
- // Updates the state if the filter value has been cleaned by the component
81
- applyValue(_extends({}, item, {
82
- value: filteredValues.map(getOptionValue)
83
- }));
84
- }
85
- }, [item, filteredValues, applyValue, getOptionValue]);
56
+ }, [item.value]);
86
57
  const handleChange = React.useCallback((event, value) => {
87
58
  applyValue(_extends({}, item, {
88
59
  value: value.map(getOptionValue)
@@ -128,18 +99,6 @@ process.env.NODE_ENV !== "production" ? GridFilterInputMultipleSingleSelect.prop
128
99
  }).isRequired,
129
100
  applyValue: PropTypes.func.isRequired,
130
101
  focusElementRef: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.func, PropTypes.object]),
131
- /**
132
- * Used to determine the label displayed for a given value option.
133
- * @param {ValueOptions} value The current value option.
134
- * @returns {string} The text to be displayed.
135
- */
136
- getOptionLabel: PropTypes.func,
137
- /**
138
- * Used to determine the value used for a value option.
139
- * @param {ValueOptions} value The current value option.
140
- * @returns {string} The value to be used.
141
- */
142
- getOptionValue: PropTypes.func,
143
102
  item: PropTypes.shape({
144
103
  field: PropTypes.string.isRequired,
145
104
  id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
@@ -1,8 +1,7 @@
1
1
  import * as React from 'react';
2
2
  import { TextFieldProps } from '@mui/material/TextField';
3
3
  import { GridFilterInputValueProps } from './GridFilterInputValueProps';
4
- import { GridSingleSelectColDef } from '../../../models/colDef/gridColDef';
5
- export type GridFilterInputSingleSelectProps = GridFilterInputValueProps & TextFieldProps & Pick<GridSingleSelectColDef, 'getOptionLabel' | 'getOptionValue'> & {
4
+ export type GridFilterInputSingleSelectProps = GridFilterInputValueProps & TextFieldProps & {
6
5
  clearButton?: React.ReactNode | null;
7
6
  /**
8
7
  * It is `true` if the filter either has a value or an operator with no value
@@ -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", "getOptionLabel", "getOptionValue", "placeholder", "tabIndex", "label", "isFilterActive", "clearButton", "InputLabelProps"];
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 = typeof valueOptions === 'function' ? ['', ...valueOptions({
25
- field
26
- })] : ['', ...(valueOptions || [])];
21
+ const iterableColumnValues = ['', ...(getValueOptions(column) || [])];
27
22
  return iterableColumnValues.map(option => {
28
23
  const value = getOptionValue(option);
29
- const label = getOptionLabel(option);
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,
@@ -50,19 +48,17 @@ function GridFilterInputSingleSelect(props) {
50
48
  type,
51
49
  apiRef,
52
50
  focusElementRef,
53
- getOptionLabel: getOptionLabelProp,
54
- getOptionValue: getOptionValueProp,
55
51
  placeholder,
56
52
  tabIndex,
57
53
  label: labelProp,
58
54
  clearButton
59
55
  } = props,
60
56
  others = _objectWithoutPropertiesLoose(props, _excluded);
61
- const [filterValueState, setFilterValueState] = React.useState((_item$value = item.value) != null ? _item$value : '');
57
+ const filterValue = (_item$value = item.value) != null ? _item$value : '';
62
58
  const id = useId();
63
59
  const labelId = useId();
64
60
  const rootProps = useGridRootProps();
65
- const isSelectNative = (_rootProps$slotProps$ = (_rootProps$slotProps = rootProps.slotProps) == null || (_rootProps$slotProps = _rootProps$slotProps.baseSelect) == null ? void 0 : _rootProps$slotProps.native) != null ? _rootProps$slotProps$ : true;
61
+ const isSelectNative = (_rootProps$slotProps$ = (_rootProps$slotProps = rootProps.slotProps) == null || (_rootProps$slotProps = _rootProps$slotProps.baseSelect) == null ? void 0 : _rootProps$slotProps.native) != null ? _rootProps$slotProps$ : false;
66
62
  let resolvedColumn = null;
67
63
  if (item.field) {
68
64
  const column = apiRef.current.getColumn(item.field);
@@ -70,53 +66,27 @@ function GridFilterInputSingleSelect(props) {
70
66
  resolvedColumn = column;
71
67
  }
72
68
  }
73
- const getOptionValue = getOptionValueProp || ((_resolvedColumn = resolvedColumn) == null ? void 0 : _resolvedColumn.getOptionValue);
74
- const getOptionLabel = getOptionLabelProp || ((_resolvedColumn2 = resolvedColumn) == null ? void 0 : _resolvedColumn2.getOptionLabel);
69
+ const getOptionValue = (_resolvedColumn = resolvedColumn) == null ? void 0 : _resolvedColumn.getOptionValue;
70
+ const getOptionLabel = (_resolvedColumn2 = resolvedColumn) == null ? void 0 : _resolvedColumn2.getOptionLabel;
75
71
  const currentValueOptions = React.useMemo(() => {
76
- if (!resolvedColumn) {
77
- return undefined;
78
- }
79
- return typeof resolvedColumn.valueOptions === 'function' ? resolvedColumn.valueOptions({
80
- field: resolvedColumn.field
81
- }) : resolvedColumn.valueOptions;
72
+ return getValueOptions(resolvedColumn);
82
73
  }, [resolvedColumn]);
83
74
  const onFilterChange = React.useCallback(event => {
84
75
  let value = event.target.value;
85
76
 
86
77
  // NativeSelect casts the value to a string.
87
78
  value = getValueFromValueOptions(value, currentValueOptions, getOptionValue);
88
- setFilterValueState(String(value));
89
79
  applyValue(_extends({}, item, {
90
80
  value
91
81
  }));
92
82
  }, [currentValueOptions, getOptionValue, applyValue, item]);
93
- React.useEffect(() => {
94
- var _itemValue;
95
- let itemValue;
96
- if (currentValueOptions !== undefined) {
97
- // sanitize if valueOptions are provided
98
- itemValue = getValueFromValueOptions(item.value, currentValueOptions, getOptionValue);
99
- if (itemValue !== item.value) {
100
- applyValue(_extends({}, item, {
101
- value: itemValue
102
- }));
103
- return;
104
- }
105
- } else {
106
- itemValue = item.value;
107
- }
108
- itemValue = (_itemValue = itemValue) != null ? _itemValue : '';
109
- setFilterValueState(String(itemValue));
110
- }, [item, currentValueOptions, applyValue, getOptionValue]);
111
- if (!isSingleSelectColDef(resolvedColumn)) {
112
- return null;
113
- }
114
83
  if (!isSingleSelectColDef(resolvedColumn)) {
115
84
  return null;
116
85
  }
117
86
  const label = labelProp != null ? labelProp : apiRef.current.getLocaleText('filterPanelInputLabel');
118
87
  return /*#__PURE__*/_jsxs(SingleSelectOperatorContainer, {
119
88
  children: [/*#__PURE__*/_jsxs(rootProps.slots.baseFormControl, {
89
+ fullWidth: true,
120
90
  children: [/*#__PURE__*/_jsx(rootProps.slots.baseInputLabel, _extends({}, (_rootProps$slotProps2 = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps2.baseInputLabel, {
121
91
  id: labelId,
122
92
  htmlFor: id,
@@ -127,7 +97,7 @@ function GridFilterInputSingleSelect(props) {
127
97
  id: id,
128
98
  label: label,
129
99
  labelId: labelId,
130
- value: filterValueState,
100
+ value: filterValue,
131
101
  onChange: onFilterChange,
132
102
  variant: "standard",
133
103
  type: type || 'text',
@@ -161,18 +131,6 @@ process.env.NODE_ENV !== "production" ? GridFilterInputSingleSelect.propTypes =
161
131
  applyValue: PropTypes.func.isRequired,
162
132
  clearButton: PropTypes.node,
163
133
  focusElementRef: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([PropTypes.func, PropTypes.object]),
164
- /**
165
- * Used to determine the label displayed for a given value option.
166
- * @param {ValueOptions} value The current value option.
167
- * @returns {string} The text to be displayed.
168
- */
169
- getOptionLabel: PropTypes.func,
170
- /**
171
- * Used to determine the value used for a value option.
172
- * @param {ValueOptions} value The current value option.
173
- * @returns {string} The value to be used.
174
- */
175
- getOptionValue: PropTypes.func,
176
134
  /**
177
135
  * It is `true` if the filter either has a value or an operator with no value
178
136
  * required is selected (e.g. `isEmpty`)
@@ -1,4 +1,5 @@
1
- import type { GridColDef, GridSingleSelectColDef, ValueOptions } from '../../../models/colDef/gridColDef';
1
+ import type { GridColDef, GridSingleSelectColDef } from '../../../models/colDef/gridColDef';
2
+ import type { GridValueOptionsParams } from '../../../models/params/gridValueOptionsParams';
2
3
  export declare function isSingleSelectColDef(colDef: GridColDef | null): colDef is GridSingleSelectColDef;
4
+ export declare function getValueOptions(column: GridSingleSelectColDef, additionalParams?: Omit<GridValueOptionsParams, 'field'>): import("../../../models/colDef/gridColDef").ValueOptions[] | undefined;
3
5
  export declare function getValueFromValueOptions(value: string, valueOptions: any[] | undefined, getOptionValue: NonNullable<GridSingleSelectColDef['getOptionValue']>): any;
4
- export declare const getLabelFromValueOption: (valueOption: ValueOptions) => string;
@@ -1,6 +1,15 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
1
2
  export function isSingleSelectColDef(colDef) {
2
3
  return (colDef == null ? void 0 : 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
+ }
@@ -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;
@@ -60,11 +61,10 @@ export const useGridRowSelection = (apiRef, props) => {
60
61
  });
61
62
  const {
62
63
  checkboxSelection,
63
- disableMultipleRowSelection,
64
64
  disableRowSelectionOnClick,
65
65
  isRowSelectable: propIsRowSelectable
66
66
  } = props;
67
- const canHaveMultipleSelection = !disableMultipleRowSelection || checkboxSelection;
67
+ const canHaveMultipleSelection = isMultipleRowSelectionEnabled(props);
68
68
  const visibleRows = useGridVisibleRows(apiRef, props);
69
69
  const expandMouseRowRangeSelection = React.useCallback(id => {
70
70
  var _lastRowToggled$curre;
@@ -95,7 +95,7 @@ export const useGridRowSelection = (apiRef, props) => {
95
95
  * API METHODS
96
96
  */
97
97
  const setRowSelectionModel = React.useCallback(model => {
98
- if (props.signature === GridSignature.DataGrid && !props.checkboxSelection && Array.isArray(model) && model.length > 1) {
98
+ if (props.signature === GridSignature.DataGrid && !canHaveMultipleSelection && Array.isArray(model) && model.length > 1) {
99
99
  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'));
100
100
  }
101
101
  const currentModel = gridRowSelectionStateSelector(apiRef.current.state);
@@ -106,7 +106,7 @@ export const useGridRowSelection = (apiRef, props) => {
106
106
  }));
107
107
  apiRef.current.forceUpdate();
108
108
  }
109
- }, [apiRef, logger, props.rowSelection, props.signature, props.checkboxSelection]);
109
+ }, [apiRef, logger, props.rowSelection, props.signature, canHaveMultipleSelection]);
110
110
  const isRowSelected = React.useCallback(id => gridRowSelectionStateSelector(apiRef.current.state).includes(id), [apiRef]);
111
111
  const isRowSelectable = React.useCallback(id => {
112
112
  if (propIsRowSelectable && !propIsRowSelectable(apiRef.current.getRowParams(id))) {
@@ -258,12 +258,12 @@ export const useGridRowSelection = (apiRef, props) => {
258
258
  if (rowNode.type === 'pinnedRow') {
259
259
  return;
260
260
  }
261
- if (event.shiftKey && (canHaveMultipleSelection || checkboxSelection)) {
261
+ if (event.shiftKey && canHaveMultipleSelection) {
262
262
  expandMouseRowRangeSelection(params.id);
263
263
  } else {
264
264
  handleSingleRowSelection(params.id, event);
265
265
  }
266
- }, [disableRowSelectionOnClick, canHaveMultipleSelection, checkboxSelection, apiRef, expandMouseRowRangeSelection, handleSingleRowSelection]);
266
+ }, [disableRowSelectionOnClick, canHaveMultipleSelection, apiRef, expandMouseRowRangeSelection, handleSingleRowSelection]);
267
267
  const preventSelectionOnShift = React.useCallback((params, event) => {
268
268
  if (canHaveMultipleSelection && event.shiftKey) {
269
269
  var _window$getSelection;
@@ -271,12 +271,12 @@ export const useGridRowSelection = (apiRef, props) => {
271
271
  }
272
272
  }, [canHaveMultipleSelection]);
273
273
  const handleRowSelectionCheckboxChange = React.useCallback((params, event) => {
274
- if (event.nativeEvent.shiftKey) {
274
+ if (canHaveMultipleSelection && event.nativeEvent.shiftKey) {
275
275
  expandMouseRowRangeSelection(params.id);
276
276
  } else {
277
- apiRef.current.selectRow(params.id, params.value);
277
+ apiRef.current.selectRow(params.id, params.value, !canHaveMultipleSelection);
278
278
  }
279
- }, [apiRef, expandMouseRowRangeSelection]);
279
+ }, [apiRef, expandMouseRowRangeSelection, canHaveMultipleSelection]);
280
280
  const handleHeaderSelectionCheckboxChange = React.useCallback(params => {
281
281
  const shouldLimitSelectionToCurrentPage = props.checkboxSelectionVisibleOnly && props.pagination;
282
282
  const rowsToBeSelected = shouldLimitSelectionToCurrentPage ? gridPaginatedVisibleSortedGridRowIdsSelector(apiRef) : gridExpandedSortedRowIdsSelector(apiRef);
@@ -0,0 +1,2 @@
1
+ import type { DataGridProcessedProps } from '../../../models/props/DataGridProps';
2
+ export declare function isMultipleRowSelectionEnabled(props: Pick<DataGridProcessedProps, 'signature' | 'disableMultipleRowSelection' | 'checkboxSelection'>): boolean;
@@ -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
  var _rootProps$experiment;
9
10
  const apiRef = useGridPrivateApiContext();
@@ -20,6 +21,6 @@ export const useGridAriaAttributes = () => {
20
21
  role,
21
22
  'aria-colcount': visibleColumns.length,
22
23
  'aria-rowcount': headerGroupingMaxDepth + 1 + pinnedRowsCount + totalRowCount,
23
- 'aria-multiselectable': !rootProps.disableMultipleRowSelection
24
+ 'aria-multiselectable': isMultipleRowSelectionEnabled(rootProps)
24
25
  };
25
26
  };
package/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @mui/x-data-grid v7.0.0-alpha.5
2
+ * @mui/x-data-grid v7.0.0-alpha.6
3
3
  *
4
4
  * @license MIT
5
5
  * This source code is licensed under the MIT license found in the