@mui/x-data-grid 8.0.0-beta.0 → 8.0.0-beta.2

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 (135) hide show
  1. package/CHANGELOG.md +171 -0
  2. package/DataGrid/DataGrid.js +2 -0
  3. package/components/GridRow.js +3 -8
  4. package/components/GridShadowScrollArea.js +43 -35
  5. package/components/cell/GridBooleanCell.d.ts +1 -2
  6. package/components/cell/GridEditSingleSelectCell.d.ts +4 -4
  7. package/components/cell/GridEditSingleSelectCell.js +1 -1
  8. package/components/columnSelection/GridHeaderCheckbox.js +2 -2
  9. package/components/containers/GridToolbarContainer.js +5 -3
  10. package/components/quickFilter/QuickFilter.d.ts +26 -3
  11. package/components/quickFilter/QuickFilter.js +103 -19
  12. package/components/quickFilter/QuickFilterClear.js +10 -4
  13. package/components/quickFilter/QuickFilterContext.d.ts +4 -1
  14. package/components/quickFilter/QuickFilterControl.js +36 -10
  15. package/components/quickFilter/QuickFilterTrigger.d.ts +28 -0
  16. package/components/quickFilter/QuickFilterTrigger.js +211 -0
  17. package/components/quickFilter/index.d.ts +2 -1
  18. package/components/quickFilter/index.js +11 -0
  19. package/components/toolbar/GridToolbarColumnsButton.d.ts +3 -4
  20. package/components/toolbar/GridToolbarDensitySelector.d.ts +3 -4
  21. package/components/toolbar/GridToolbarExport.d.ts +3 -4
  22. package/components/toolbar/GridToolbarExportContainer.d.ts +3 -4
  23. package/components/toolbar/GridToolbarFilterButton.d.ts +4 -6
  24. package/components/toolbar/GridToolbarFilterButton.js +1 -4
  25. package/components/toolbar/GridToolbarQuickFilter.js +101 -41
  26. package/components/toolbarV8/GridToolbar.js +22 -19
  27. package/components/toolbarV8/Toolbar.d.ts +1 -1
  28. package/components/toolbarV8/Toolbar.js +76 -23
  29. package/components/toolbarV8/ToolbarButton.js +34 -14
  30. package/components/toolbarV8/ToolbarContext.d.ts +4 -2
  31. package/constants/gridClasses.d.ts +12 -0
  32. package/constants/gridClasses.js +1 -1
  33. package/esm/DataGrid/DataGrid.js +2 -0
  34. package/esm/components/GridRow.js +4 -9
  35. package/esm/components/GridShadowScrollArea.js +43 -35
  36. package/esm/components/cell/GridBooleanCell.d.ts +1 -2
  37. package/esm/components/cell/GridEditSingleSelectCell.d.ts +4 -4
  38. package/esm/components/cell/GridEditSingleSelectCell.js +1 -1
  39. package/esm/components/columnSelection/GridHeaderCheckbox.js +2 -2
  40. package/esm/components/containers/GridToolbarContainer.js +5 -3
  41. package/esm/components/quickFilter/QuickFilter.d.ts +26 -3
  42. package/esm/components/quickFilter/QuickFilter.js +101 -17
  43. package/esm/components/quickFilter/QuickFilterClear.js +10 -4
  44. package/esm/components/quickFilter/QuickFilterContext.d.ts +4 -1
  45. package/esm/components/quickFilter/QuickFilterControl.js +36 -10
  46. package/esm/components/quickFilter/QuickFilterTrigger.d.ts +28 -0
  47. package/esm/components/quickFilter/QuickFilterTrigger.js +204 -0
  48. package/esm/components/quickFilter/index.d.ts +2 -1
  49. package/esm/components/quickFilter/index.js +2 -1
  50. package/esm/components/toolbar/GridToolbarColumnsButton.d.ts +3 -4
  51. package/esm/components/toolbar/GridToolbarDensitySelector.d.ts +3 -4
  52. package/esm/components/toolbar/GridToolbarExport.d.ts +3 -4
  53. package/esm/components/toolbar/GridToolbarExportContainer.d.ts +3 -4
  54. package/esm/components/toolbar/GridToolbarFilterButton.d.ts +4 -6
  55. package/esm/components/toolbar/GridToolbarFilterButton.js +1 -4
  56. package/esm/components/toolbar/GridToolbarQuickFilter.js +102 -44
  57. package/esm/components/toolbarV8/GridToolbar.js +22 -19
  58. package/esm/components/toolbarV8/Toolbar.d.ts +1 -1
  59. package/esm/components/toolbarV8/Toolbar.js +75 -22
  60. package/esm/components/toolbarV8/ToolbarButton.js +34 -14
  61. package/esm/components/toolbarV8/ToolbarContext.d.ts +4 -2
  62. package/esm/constants/gridClasses.d.ts +12 -0
  63. package/esm/constants/gridClasses.js +1 -1
  64. package/esm/hooks/features/columnGrouping/gridColumnGroupsUtils.js +1 -1
  65. package/esm/hooks/features/columns/useGridColumns.js +0 -1
  66. package/esm/hooks/features/dimensions/useGridDimensions.js +1 -1
  67. package/esm/hooks/features/editing/useGridRowEditing.js +1 -1
  68. package/esm/hooks/features/filter/useGridFilter.js +1 -1
  69. package/esm/hooks/features/pagination/useGridPaginationModel.js +1 -1
  70. package/esm/hooks/features/virtualization/useGridVirtualScroller.js +12 -1
  71. package/esm/index.js +1 -1
  72. package/esm/locales/deDE.js +13 -13
  73. package/esm/material/index.js +1 -2
  74. package/esm/models/props/DataGridProps.d.ts +6 -2
  75. package/esm/utils/utils.d.ts +0 -27
  76. package/esm/utils/utils.js +0 -122
  77. package/hooks/features/columnGrouping/gridColumnGroupsUtils.js +2 -2
  78. package/hooks/features/columns/useGridColumns.js +0 -1
  79. package/hooks/features/dimensions/useGridDimensions.js +2 -2
  80. package/hooks/features/editing/useGridRowEditing.js +1 -1
  81. package/hooks/features/filter/useGridFilter.js +3 -3
  82. package/hooks/features/pagination/useGridPaginationModel.js +2 -2
  83. package/hooks/features/virtualization/useGridVirtualScroller.js +11 -0
  84. package/index.js +1 -1
  85. package/locales/deDE.js +13 -13
  86. package/material/index.js +1 -2
  87. package/models/props/DataGridProps.d.ts +6 -2
  88. package/modern/DataGrid/DataGrid.js +2 -0
  89. package/modern/components/GridRow.js +4 -9
  90. package/modern/components/GridShadowScrollArea.js +43 -35
  91. package/modern/components/cell/GridBooleanCell.d.ts +1 -2
  92. package/modern/components/cell/GridEditSingleSelectCell.d.ts +4 -4
  93. package/modern/components/cell/GridEditSingleSelectCell.js +1 -1
  94. package/modern/components/columnSelection/GridHeaderCheckbox.js +2 -2
  95. package/modern/components/containers/GridToolbarContainer.js +5 -3
  96. package/modern/components/quickFilter/QuickFilter.d.ts +26 -3
  97. package/modern/components/quickFilter/QuickFilter.js +101 -17
  98. package/modern/components/quickFilter/QuickFilterClear.js +10 -4
  99. package/modern/components/quickFilter/QuickFilterContext.d.ts +4 -1
  100. package/modern/components/quickFilter/QuickFilterControl.js +36 -10
  101. package/modern/components/quickFilter/QuickFilterTrigger.d.ts +28 -0
  102. package/modern/components/quickFilter/QuickFilterTrigger.js +204 -0
  103. package/modern/components/quickFilter/index.d.ts +2 -1
  104. package/modern/components/quickFilter/index.js +2 -1
  105. package/modern/components/toolbar/GridToolbarColumnsButton.d.ts +3 -4
  106. package/modern/components/toolbar/GridToolbarDensitySelector.d.ts +3 -4
  107. package/modern/components/toolbar/GridToolbarExport.d.ts +3 -4
  108. package/modern/components/toolbar/GridToolbarExportContainer.d.ts +3 -4
  109. package/modern/components/toolbar/GridToolbarFilterButton.d.ts +4 -6
  110. package/modern/components/toolbar/GridToolbarFilterButton.js +1 -4
  111. package/modern/components/toolbar/GridToolbarQuickFilter.js +102 -44
  112. package/modern/components/toolbarV8/GridToolbar.js +22 -19
  113. package/modern/components/toolbarV8/Toolbar.d.ts +1 -1
  114. package/modern/components/toolbarV8/Toolbar.js +75 -22
  115. package/modern/components/toolbarV8/ToolbarButton.js +34 -14
  116. package/modern/components/toolbarV8/ToolbarContext.d.ts +4 -2
  117. package/modern/constants/gridClasses.d.ts +12 -0
  118. package/modern/constants/gridClasses.js +1 -1
  119. package/modern/hooks/features/columnGrouping/gridColumnGroupsUtils.js +1 -1
  120. package/modern/hooks/features/columns/useGridColumns.js +0 -1
  121. package/modern/hooks/features/dimensions/useGridDimensions.js +1 -1
  122. package/modern/hooks/features/editing/useGridRowEditing.js +1 -1
  123. package/modern/hooks/features/filter/useGridFilter.js +1 -1
  124. package/modern/hooks/features/pagination/useGridPaginationModel.js +1 -1
  125. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +12 -1
  126. package/modern/index.js +1 -1
  127. package/modern/locales/deDE.js +13 -13
  128. package/modern/material/index.js +1 -2
  129. package/modern/models/props/DataGridProps.d.ts +6 -2
  130. package/modern/utils/utils.d.ts +0 -27
  131. package/modern/utils/utils.js +0 -122
  132. package/package.json +2 -2
  133. package/tsconfig.build.tsbuildinfo +1 -1
  134. package/utils/utils.d.ts +0 -27
  135. package/utils/utils.js +0 -123
@@ -17,48 +17,56 @@ const detectScroll = keyframes({
17
17
  '--scrollable': '" "'
18
18
  }
19
19
  });
20
+
21
+ // This `styled()` function invokes keyframes. `styled-components` only supports keyframes
22
+ // in string templates. Do not convert these styles in JS object as it will break.
20
23
  const ShadowScrollArea = styled('div', {
21
24
  name: 'MuiDataGrid',
22
25
  slot: 'ShadowScrollArea'
23
- })({
24
- flex: 1,
25
- display: 'flex',
26
- flexDirection: 'column',
27
- animation: detectScroll,
28
- animationTimeline: '--scroll-timeline',
29
- animationFillMode: 'none',
30
- boxSizing: 'border-box',
31
- overflow: 'auto',
32
- scrollTimeline: '--scroll-timeline block',
33
- '&::before, &::after': {
34
- content: '""',
35
- flexShrink: 0,
36
- display: 'block',
37
- position: 'sticky',
38
- left: 0,
39
- width: '100%',
40
- height: '4px',
41
- animation: `${reveal} linear both`,
42
- animationTimeline: '--scroll-timeline',
26
+ })`
27
+ flex: 1;
28
+ display: flex;
29
+ flex-direction: column;
30
+ animation: ${detectScroll};
31
+ animation-timeline: --scroll-timeline;
32
+ animation-fill-mode: none;
33
+ box-sizing: border-box;
34
+ overflow: auto;
35
+ scroll-timeline: --scroll-timeline block;
36
+
37
+ &::before,
38
+ &::after {
39
+ content: '';
40
+ flex-shrink: 0;
41
+ display: block;
42
+ position: sticky;
43
+ left: 0;
44
+ width: 100%;
45
+ height: 4px;
46
+ animation: ${reveal} linear both;
47
+ animation-timeline: --scroll-timeline;
48
+
43
49
  // Custom property toggle trick:
44
50
  // - Detects if the element is scrollable
45
51
  // - https://css-tricks.com/the-css-custom-property-toggle-trick/
46
- '--visibility-scrollable': 'var(--scrollable) visible',
47
- '--visibility-not-scrollable': 'hidden',
48
- visibility: 'var(--visibility-scrollable, var(--visibility-not-scrollable))'
49
- },
50
- '&::before': {
51
- top: 0,
52
- background: 'linear-gradient(to bottom, rgba(0,0,0,0.05) 0, transparent 100%)',
53
- animationRange: '0 4px'
54
- },
55
- '&::after': {
56
- bottom: 0,
57
- background: 'linear-gradient(to top, rgba(0,0,0,0.05) 0, transparent 100%)',
58
- animationDirection: 'reverse',
59
- animationRange: 'calc(100% - 4px) 100%'
52
+ --visibility-scrollable: var(--scrollable) visible;
53
+ --visibility-not-scrollable: hidden;
54
+ visibility: var(--visibility-scrollable, var(--visibility-not-scrollable));
60
55
  }
61
- });
56
+
57
+ &::before {
58
+ top: 0;
59
+ background: linear-gradient(to bottom, rgba(0, 0, 0, 0.05) 0, transparent 100%);
60
+ animation-range: 0 4px;
61
+ }
62
+
63
+ &::after {
64
+ bottom: 0;
65
+ background: linear-gradient(to top, rgba(0, 0, 0, 0.05) 0, transparent 100%);
66
+ animation-direction: reverse;
67
+ animation-range: calc(100% - 4px) 100%;
68
+ }
69
+ `;
62
70
 
63
71
  /**
64
72
  * Adds scroll shadows above and below content in a scrollable container.
@@ -1,8 +1,7 @@
1
1
  import * as React from 'react';
2
- import { SvgIconProps } from '@mui/material/SvgIcon';
3
2
  import type { GridColDef } from '../../models/colDef/gridColDef';
4
3
  import type { GridRenderCellParams } from '../../models/params/gridCellParams';
5
- interface GridBooleanCellProps extends GridRenderCellParams, Omit<SvgIconProps, 'tabIndex' | 'id'> {
4
+ interface GridBooleanCellProps extends GridRenderCellParams {
6
5
  hideDescendantCount?: boolean;
7
6
  }
8
7
  declare function GridBooleanCellRaw(props: GridBooleanCellProps): React.JSX.Element | null;
@@ -1,14 +1,14 @@
1
1
  import * as React from 'react';
2
- import { SelectProps, SelectChangeEvent } from '@mui/material/Select';
2
+ import type { GridSlotProps } from '../../models/gridSlotsComponentsProps';
3
3
  import { GridRenderEditCellParams } from "../../models/params/gridCellParams.js";
4
- export interface GridEditSingleSelectCellProps extends GridRenderEditCellParams, Omit<SelectProps, 'id' | 'tabIndex' | 'value'> {
4
+ export interface GridEditSingleSelectCellProps extends GridRenderEditCellParams {
5
5
  /**
6
6
  * Callback called when the value is changed by the user.
7
- * @param {SelectChangeEvent<any>} event The event source of the callback.
7
+ * @param {Event<any>} event The event source of the callback.
8
8
  * @param {any} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
9
9
  * @returns {Promise<void> | void} A promise to be awaited before calling `apiRef.current.setEditCellValue`
10
10
  */
11
- onValueChange?: (event: SelectChangeEvent<any>, newValue: any) => Promise<void> | void;
11
+ onValueChange?: (event: Parameters<NonNullable<GridSlotProps['baseSelect']['onOpen']>>[0], newValue: any) => Promise<void> | void;
12
12
  /**
13
13
  * If true, the select opens by default.
14
14
  */
@@ -162,7 +162,7 @@ process.env.NODE_ENV !== "production" ? GridEditSingleSelectCell.propTypes = {
162
162
  isValidating: PropTypes.bool,
163
163
  /**
164
164
  * Callback called when the value is changed by the user.
165
- * @param {SelectChangeEvent<any>} event The event source of the callback.
165
+ * @param {Event<any>} event The event source of the callback.
166
166
  * @param {any} newValue The value that is going to be passed to `apiRef.current.setEditCellValue`.
167
167
  * @returns {Promise<void> | void} A promise to be awaited before calling `apiRef.current.setEditCellValue`
168
168
  */
@@ -69,7 +69,7 @@ const GridHeaderCheckbox = forwardRef(function GridHeaderCheckbox(props, ref) {
69
69
 
70
70
  // All the rows that could be selected / unselected by toggling this checkbox
71
71
  const selectionCandidates = React.useMemo(() => {
72
- const rowIds = !rootProps.pagination || !rootProps.checkboxSelectionVisibleOnly ? visibleRowIds : paginatedVisibleRowIds;
72
+ const rowIds = !rootProps.pagination || !rootProps.checkboxSelectionVisibleOnly || rootProps.paginationMode === 'server' ? visibleRowIds : paginatedVisibleRowIds;
73
73
 
74
74
  // Convert to a Set to make O(1) checking if a row exists or not
75
75
  const candidates = new Set();
@@ -80,7 +80,7 @@ const GridHeaderCheckbox = forwardRef(function GridHeaderCheckbox(props, ref) {
80
80
  }
81
81
  }
82
82
  return candidates;
83
- }, [apiRef, rootProps.pagination, rootProps.checkboxSelectionVisibleOnly, paginatedVisibleRowIds, visibleRowIds]);
83
+ }, [apiRef, rootProps.pagination, rootProps.paginationMode, rootProps.checkboxSelectionVisibleOnly, paginatedVisibleRowIds, visibleRowIds]);
84
84
 
85
85
  // Amount of rows selected and that are visible in the current page
86
86
  const currentSelectionSize = React.useMemo(() => {
@@ -10,6 +10,7 @@ import { forwardRef } from '@mui/x-internals/forwardRef';
10
10
  import { vars } from "../../constants/cssVariables.js";
11
11
  import { getDataGridUtilityClass } from "../../constants/gridClasses.js";
12
12
  import { useGridRootProps } from "../../hooks/utils/useGridRootProps.js";
13
+ import { Toolbar } from "../toolbarV8/index.js";
13
14
  import { jsx as _jsx } from "react/jsx-runtime";
14
15
  const useUtilityClasses = ownerState => {
15
16
  const {
@@ -20,16 +21,17 @@ const useUtilityClasses = ownerState => {
20
21
  };
21
22
  return composeClasses(slots, getDataGridUtilityClass, classes);
22
23
  };
23
- const GridToolbarContainerRoot = styled('div', {
24
+ const GridToolbarContainerRoot = styled(Toolbar, {
24
25
  name: 'MuiDataGrid',
25
26
  slot: 'ToolbarContainer',
26
- overridesResolver: (_, styles) => styles.toolbarContainer
27
+ shouldForwardProp: prop => prop !== 'ownerState'
27
28
  })({
28
29
  display: 'flex',
29
30
  alignItems: 'center',
30
31
  flexWrap: 'wrap',
31
32
  gap: vars.spacing(1),
32
- padding: vars.spacing(0.5, 0.5, 0)
33
+ padding: vars.spacing(0.5),
34
+ minHeight: 'auto'
33
35
  });
34
36
  const GridToolbarContainer = forwardRef(function GridToolbarContainer(props, ref) {
35
37
  const {
@@ -1,7 +1,8 @@
1
1
  import * as React from 'react';
2
+ import { QuickFilterState } from "./QuickFilterContext.js";
3
+ import { RenderProp } from "../../hooks/utils/useGridComponentRenderer.js";
2
4
  import type { GridFilterModel } from '../../models';
3
- export type QuickFilterProps = {
4
- children: React.ReactNode;
5
+ export type QuickFilterProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'className'> & {
5
6
  /**
6
7
  * Function responsible for parsing text input in an array of independent values for quick filtering.
7
8
  * @param {string} input The value entered by the user
@@ -21,10 +22,32 @@ export type QuickFilterProps = {
21
22
  * @default 150
22
23
  */
23
24
  debounceMs?: number;
25
+ /**
26
+ * The default expanded state of the quick filter control.
27
+ * @default false
28
+ */
29
+ defaultExpanded?: boolean;
30
+ /**
31
+ * The expanded state of the quick filter control.
32
+ */
33
+ expanded?: boolean;
34
+ /**
35
+ * A function to customize rendering of the component.
36
+ */
37
+ render?: RenderProp<React.ComponentProps<'div'>, QuickFilterState>;
38
+ /**
39
+ * Override or extend the styles applied to the component.
40
+ */
41
+ className?: string | ((state: QuickFilterState) => string);
42
+ /**
43
+ * Callback function that is called when the quick filter input is expanded or collapsed.
44
+ * @param {boolean} expanded The new expanded state of the quick filter control
45
+ */
46
+ onExpandedChange?: (expanded: boolean) => void;
24
47
  };
25
48
  /**
26
49
  * The top level Quick Filter component that provides context to child components.
27
- * It does not render any DOM elements.
50
+ * It renders a `<div />` element.
28
51
  *
29
52
  * Demos:
30
53
  *
@@ -1,19 +1,25 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
+ const _excluded = ["render", "className", "parser", "formatter", "debounceMs", "defaultExpanded", "expanded", "onExpandedChange"];
1
4
  import * as React from 'react';
2
5
  import PropTypes from 'prop-types';
3
6
  import { unstable_debounce as debounce } from '@mui/utils';
7
+ import useEnhancedEffect from '@mui/utils/useEnhancedEffect';
8
+ import useId from '@mui/utils/useId';
9
+ import { isDeepEqual } from '@mui/x-internals/isDeepEqual';
4
10
  import { QuickFilterContext } from "./QuickFilterContext.js";
11
+ import { useGridComponentRenderer } from "../../hooks/utils/useGridComponentRenderer.js";
5
12
  import { useGridApiContext } from "../../hooks/utils/useGridApiContext.js";
6
13
  import { useGridSelector } from "../../hooks/utils/useGridSelector.js";
7
14
  import { gridQuickFilterValuesSelector } from "../../hooks/features/filter/index.js";
8
15
  import { useGridRootProps } from "../../hooks/utils/useGridRootProps.js";
9
- import { isDeepEqual } from "../../utils/utils.js";
10
16
  import { jsx as _jsx } from "react/jsx-runtime";
11
17
  const DEFAULT_PARSER = searchText => searchText.split(' ').filter(word => word !== '');
12
18
  const DEFAULT_FORMATTER = values => values.join(' ');
13
19
 
14
20
  /**
15
21
  * The top level Quick Filter component that provides context to child components.
16
- * It does not render any DOM elements.
22
+ * It renders a `<div />` element.
17
23
  *
18
24
  * Demos:
19
25
  *
@@ -26,16 +32,38 @@ const DEFAULT_FORMATTER = values => values.join(' ');
26
32
  function QuickFilter(props) {
27
33
  const rootProps = useGridRootProps();
28
34
  const {
29
- parser = DEFAULT_PARSER,
30
- formatter = DEFAULT_FORMATTER,
31
- debounceMs = rootProps.filterDebounceMs,
32
- children
33
- } = props;
35
+ render,
36
+ className,
37
+ parser = DEFAULT_PARSER,
38
+ formatter = DEFAULT_FORMATTER,
39
+ debounceMs = rootProps.filterDebounceMs,
40
+ defaultExpanded,
41
+ expanded,
42
+ onExpandedChange
43
+ } = props,
44
+ other = _objectWithoutPropertiesLoose(props, _excluded);
34
45
  const apiRef = useGridApiContext();
35
46
  const controlRef = React.useRef(null);
36
47
  const triggerRef = React.useRef(null);
37
48
  const quickFilterValues = useGridSelector(apiRef, gridQuickFilterValuesSelector);
38
49
  const [value, setValue] = React.useState(formatter(quickFilterValues ?? []));
50
+ const [internalExpanded, setInternalExpanded] = React.useState(defaultExpanded ?? value.length > 0);
51
+ const expandedValue = expanded ?? internalExpanded;
52
+ const state = React.useMemo(() => ({
53
+ value,
54
+ expanded: expandedValue
55
+ }), [value, expandedValue]);
56
+ const resolvedClassName = typeof className === 'function' ? className(state) : className;
57
+ const ref = React.useRef(null);
58
+ const controlId = useId();
59
+ const handleExpandedChange = React.useCallback(newExpanded => {
60
+ if (onExpandedChange) {
61
+ onExpandedChange(newExpanded);
62
+ }
63
+ if (expanded === undefined) {
64
+ setInternalExpanded(newExpanded);
65
+ }
66
+ }, [onExpandedChange, expanded]);
39
67
  const prevQuickFilterValuesRef = React.useRef(quickFilterValues);
40
68
  React.useEffect(() => {
41
69
  if (!isDeepEqual(prevQuickFilterValuesRef.current, quickFilterValues)) {
@@ -46,6 +74,31 @@ function QuickFilter(props) {
46
74
  setValue(prevSearchValue => isDeepEqual(parser(prevSearchValue), quickFilterValues) ? prevSearchValue : formatter(quickFilterValues ?? []));
47
75
  }
48
76
  }, [quickFilterValues, formatter, parser]);
77
+ const isFirstRender = React.useRef(true);
78
+ const previousExpandedValue = React.useRef(expandedValue);
79
+ React.useEffect(() => {
80
+ if (isFirstRender.current) {
81
+ isFirstRender.current = false;
82
+ return;
83
+ }
84
+
85
+ // Ensure the expanded state has actually changed before focusing
86
+ if (previousExpandedValue.current !== expandedValue) {
87
+ if (expandedValue) {
88
+ // Ensures the focus does not interupt CSS transitions and animations on the control
89
+ requestAnimationFrame(() => {
90
+ controlRef.current?.focus({
91
+ preventScroll: true
92
+ });
93
+ });
94
+ } else {
95
+ triggerRef.current?.focus({
96
+ preventScroll: true
97
+ });
98
+ }
99
+ previousExpandedValue.current = expandedValue;
100
+ }
101
+ }, [expandedValue]);
49
102
  const setQuickFilterValueDebounced = React.useMemo(() => debounce(newValue => {
50
103
  const newQuickFilterValues = parser(newValue);
51
104
  prevQuickFilterValuesRef.current = newQuickFilterValues;
@@ -57,7 +110,7 @@ function QuickFilter(props) {
57
110
  setValue(newValue);
58
111
  setQuickFilterValueDebounced(newValue);
59
112
  }, [setQuickFilterValueDebounced]);
60
- const handleClear = React.useCallback(() => {
113
+ const handleClearValue = React.useCallback(() => {
61
114
  setValue('');
62
115
  apiRef.current.setQuickFilterValues([]);
63
116
  controlRef.current?.focus();
@@ -65,15 +118,25 @@ function QuickFilter(props) {
65
118
  const contextValue = React.useMemo(() => ({
66
119
  controlRef,
67
120
  triggerRef,
68
- state: {
69
- value
70
- },
71
- clearValue: handleClear,
72
- onValueChange: handleValueChange
73
- }), [value, handleValueChange, handleClear]);
121
+ state,
122
+ controlId,
123
+ clearValue: handleClearValue,
124
+ onValueChange: handleValueChange,
125
+ onExpandedChange: handleExpandedChange
126
+ }), [controlId, state, handleValueChange, handleClearValue, handleExpandedChange]);
127
+ useEnhancedEffect(() => {
128
+ if (ref.current && triggerRef.current) {
129
+ ref.current.style.setProperty('--trigger-width', `${triggerRef.current?.offsetWidth}px`);
130
+ }
131
+ }, []);
132
+ const element = useGridComponentRenderer('div', render, _extends({
133
+ className: resolvedClassName
134
+ }, other, {
135
+ ref
136
+ }), state);
74
137
  return /*#__PURE__*/_jsx(QuickFilterContext.Provider, {
75
138
  value: contextValue,
76
- children: children
139
+ children: element
77
140
  });
78
141
  }
79
142
  process.env.NODE_ENV !== "production" ? QuickFilter.propTypes = {
@@ -81,12 +144,24 @@ process.env.NODE_ENV !== "production" ? QuickFilter.propTypes = {
81
144
  // | These PropTypes are generated from the TypeScript type definitions |
82
145
  // | To update them edit the TypeScript types and run "pnpm proptypes" |
83
146
  // ----------------------------------------------------------------------
84
- children: PropTypes.node,
147
+ /**
148
+ * Override or extend the styles applied to the component.
149
+ */
150
+ className: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
85
151
  /**
86
152
  * The debounce time in milliseconds.
87
153
  * @default 150
88
154
  */
89
155
  debounceMs: PropTypes.number,
156
+ /**
157
+ * The default expanded state of the quick filter control.
158
+ * @default false
159
+ */
160
+ defaultExpanded: PropTypes.bool,
161
+ /**
162
+ * The expanded state of the quick filter control.
163
+ */
164
+ expanded: PropTypes.bool,
90
165
  /**
91
166
  * Function responsible for formatting values of quick filter in a string when the model is modified
92
167
  * @param {any[]} values The new values passed to the quick filter model
@@ -94,12 +169,21 @@ process.env.NODE_ENV !== "production" ? QuickFilter.propTypes = {
94
169
  * @default (values: string[]) => values.join(' ')
95
170
  */
96
171
  formatter: PropTypes.func,
172
+ /**
173
+ * Callback function that is called when the quick filter input is expanded or collapsed.
174
+ * @param {boolean} expanded The new expanded state of the quick filter control
175
+ */
176
+ onExpandedChange: PropTypes.func,
97
177
  /**
98
178
  * Function responsible for parsing text input in an array of independent values for quick filtering.
99
179
  * @param {string} input The value entered by the user
100
180
  * @returns {any[]} The array of value on which quick filter is applied
101
181
  * @default (searchText: string) => searchText.split(' ').filter((word) => word !== '')
102
182
  */
103
- parser: PropTypes.func
183
+ parser: PropTypes.func,
184
+ /**
185
+ * A function to customize rendering of the component.
186
+ */
187
+ render: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
104
188
  } : void 0;
105
189
  export { QuickFilter };
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["render", "className"];
3
+ const _excluded = ["render", "className", "onClick"];
4
4
  import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import { forwardRef } from '@mui/x-internals/forwardRef';
@@ -23,7 +23,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
23
23
  const QuickFilterClear = forwardRef(function QuickFilterClear(props, ref) {
24
24
  const {
25
25
  render,
26
- className
26
+ className,
27
+ onClick
27
28
  } = props,
28
29
  other = _objectWithoutPropertiesLoose(props, _excluded);
29
30
  const rootProps = useGridRootProps();
@@ -32,10 +33,15 @@ const QuickFilterClear = forwardRef(function QuickFilterClear(props, ref) {
32
33
  clearValue
33
34
  } = useQuickFilterContext();
34
35
  const resolvedClassName = typeof className === 'function' ? className(state) : className;
36
+ const handleClick = event => {
37
+ clearValue();
38
+ onClick?.(event);
39
+ };
35
40
  const element = useGridComponentRenderer(rootProps.slots.baseIconButton, render, _extends({}, rootProps.slotProps?.baseIconButton, {
36
- onClick: clearValue,
37
- className: resolvedClassName
41
+ className: resolvedClassName,
42
+ tabIndex: -1
38
43
  }, other, {
44
+ onClick: handleClick,
39
45
  ref
40
46
  }), state);
41
47
  return /*#__PURE__*/_jsx(React.Fragment, {
@@ -1,13 +1,16 @@
1
1
  import * as React from 'react';
2
2
  export interface QuickFilterState {
3
3
  value: string;
4
+ expanded: boolean;
4
5
  }
5
6
  export interface QuickFilterContextValue {
6
7
  state: QuickFilterState;
8
+ controlId: string | undefined;
7
9
  controlRef: React.RefObject<HTMLInputElement | null>;
8
10
  triggerRef: React.RefObject<HTMLButtonElement | null>;
9
- onValueChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
10
11
  clearValue: () => void;
12
+ onValueChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
13
+ onExpandedChange: (expanded: boolean) => void;
11
14
  }
12
15
  export declare const QuickFilterContext: React.Context<QuickFilterContextValue | undefined>;
13
16
  export declare function useQuickFilterContext(): QuickFilterContextValue;
@@ -1,6 +1,6 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
2
  import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["render", "className"];
3
+ const _excluded = ["render", "className", "slotProps", "onKeyDown", "onChange"];
4
4
  import * as React from 'react';
5
5
  import PropTypes from 'prop-types';
6
6
  import { unstable_useForkRef as useForkRef } from '@mui/utils';
@@ -24,35 +24,61 @@ import { jsx as _jsx } from "react/jsx-runtime";
24
24
  const QuickFilterControl = forwardRef(function QuickFilterControl(props, ref) {
25
25
  const {
26
26
  render,
27
- className
27
+ className,
28
+ slotProps,
29
+ onKeyDown,
30
+ onChange
28
31
  } = props,
29
32
  other = _objectWithoutPropertiesLoose(props, _excluded);
30
33
  const rootProps = useGridRootProps();
31
34
  const {
32
35
  state,
36
+ controlId,
33
37
  controlRef,
34
38
  onValueChange,
39
+ onExpandedChange,
35
40
  clearValue
36
41
  } = useQuickFilterContext();
37
42
  const resolvedClassName = typeof className === 'function' ? className(state) : className;
38
43
  const handleRef = useForkRef(controlRef, ref);
39
44
  const handleKeyDown = event => {
40
45
  if (event.key === 'Escape') {
41
- clearValue();
46
+ if (state.value === '') {
47
+ onExpandedChange(false);
48
+ } else {
49
+ clearValue();
50
+ }
42
51
  }
43
- props.onKeyDown?.(event);
52
+ onKeyDown?.(event);
53
+ };
54
+ const handleBlur = event => {
55
+ if (state.value === '') {
56
+ onExpandedChange(false);
57
+ }
58
+ slotProps?.htmlInput?.onBlur?.(event);
59
+ };
60
+ const handleChange = event => {
61
+ if (!state.expanded) {
62
+ onExpandedChange(true);
63
+ }
64
+ onValueChange(event);
65
+ onChange?.(event);
44
66
  };
45
67
  const element = useGridComponentRenderer(rootProps.slots.baseTextField, render, _extends({}, rootProps.slotProps?.baseTextField, {
46
68
  slotProps: _extends({
47
69
  htmlInput: _extends({
48
- role: 'searchbox'
49
- }, props.slotProps?.htmlInput)
50
- }, props.slotProps),
70
+ role: 'searchbox',
71
+ id: controlId,
72
+ tabIndex: state.expanded ? undefined : -1
73
+ }, slotProps?.htmlInput, {
74
+ onBlur: handleBlur
75
+ })
76
+ }, slotProps),
51
77
  value: state.value,
52
- className: resolvedClassName,
53
- onChange: onValueChange,
54
- onKeyDown: handleKeyDown
78
+ className: resolvedClassName
55
79
  }, other, {
80
+ onChange: handleChange,
81
+ onKeyDown: handleKeyDown,
56
82
  ref: handleRef
57
83
  }), state);
58
84
  return /*#__PURE__*/_jsx(React.Fragment, {
@@ -0,0 +1,28 @@
1
+ import * as React from 'react';
2
+ import { RenderProp } from "../../hooks/utils/useGridComponentRenderer.js";
3
+ import type { GridSlotProps } from '../../models';
4
+ import { QuickFilterState } from "./QuickFilterContext.js";
5
+ export type QuickFilterTriggerProps = Omit<GridSlotProps['baseButton'], 'className'> & {
6
+ /**
7
+ * A function to customize rendering of the component.
8
+ */
9
+ render?: RenderProp<GridSlotProps['baseButton'], QuickFilterState>;
10
+ /**
11
+ * Override or extend the styles applied to the component.
12
+ */
13
+ className?: string | ((state: QuickFilterState) => string);
14
+ };
15
+ /**
16
+ * A button that expands/collapses the quick filter.
17
+ * It renders the `baseButton` slot.
18
+ *
19
+ * Demos:
20
+ *
21
+ * - [Quick Filter](https://mui.com/x/react-data-grid/components/quick-filter/)
22
+ *
23
+ * API:
24
+ *
25
+ * - [QuickFilterTrigger API](https://mui.com/x/api/data-grid/quick-filter-trigger/)
26
+ */
27
+ declare const QuickFilterTrigger: React.ForwardRefExoticComponent<QuickFilterTriggerProps> | React.ForwardRefExoticComponent<Omit<QuickFilterTriggerProps, "ref"> & React.RefAttributes<HTMLButtonElement>>;
28
+ export { QuickFilterTrigger };