@mui/x-data-grid-pro 5.12.3 → 5.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/DataGridPro/DataGridPro.js +1 -1
  3. package/components/DataGridProVirtualScroller.js +7 -18
  4. package/components/GridDetailPanel.d.ts +19 -0
  5. package/components/GridDetailPanel.js +65 -0
  6. package/hooks/features/detailPanel/gridDetailPanelInterface.d.ts +20 -1
  7. package/hooks/features/detailPanel/gridDetailPanelSelector.d.ts +14 -3
  8. package/hooks/features/detailPanel/gridDetailPanelSelector.js +9 -1
  9. package/hooks/features/detailPanel/index.d.ts +1 -1
  10. package/hooks/features/detailPanel/index.js +1 -1
  11. package/hooks/features/detailPanel/useGridDetailPanel.js +41 -7
  12. package/hooks/features/detailPanel/useGridDetailPanelCache.d.ts +4 -0
  13. package/hooks/features/detailPanel/useGridDetailPanelCache.js +64 -0
  14. package/index.js +1 -1
  15. package/legacy/DataGridPro/DataGridPro.js +1 -1
  16. package/legacy/components/DataGridProVirtualScroller.js +12 -26
  17. package/legacy/components/GridDetailPanel.js +72 -0
  18. package/legacy/hooks/features/detailPanel/gridDetailPanelSelector.js +15 -2
  19. package/legacy/hooks/features/detailPanel/index.js +1 -1
  20. package/legacy/hooks/features/detailPanel/useGridDetailPanel.js +40 -7
  21. package/legacy/hooks/features/detailPanel/useGridDetailPanelCache.js +64 -0
  22. package/legacy/index.js +1 -1
  23. package/legacy/utils/releaseInfo.js +1 -1
  24. package/models/dataGridProProps.d.ts +2 -2
  25. package/modern/DataGridPro/DataGridPro.js +1 -1
  26. package/modern/components/DataGridProVirtualScroller.js +7 -18
  27. package/modern/components/GridDetailPanel.js +65 -0
  28. package/modern/hooks/features/detailPanel/gridDetailPanelSelector.js +9 -1
  29. package/modern/hooks/features/detailPanel/index.js +1 -1
  30. package/modern/hooks/features/detailPanel/useGridDetailPanel.js +39 -7
  31. package/modern/hooks/features/detailPanel/useGridDetailPanelCache.js +62 -0
  32. package/modern/index.js +1 -1
  33. package/modern/utils/releaseInfo.js +1 -1
  34. package/node/DataGridPro/DataGridPro.js +1 -1
  35. package/node/components/DataGridProVirtualScroller.js +8 -19
  36. package/node/components/GridDetailPanel.js +83 -0
  37. package/node/hooks/features/detailPanel/gridDetailPanelSelector.js +12 -2
  38. package/node/hooks/features/detailPanel/index.js +25 -11
  39. package/node/hooks/features/detailPanel/useGridDetailPanel.js +40 -6
  40. package/node/hooks/features/detailPanel/useGridDetailPanelCache.js +81 -0
  41. package/node/index.js +1 -1
  42. package/node/utils/releaseInfo.js +1 -1
  43. package/package.json +3 -3
  44. package/utils/releaseInfo.js +1 -1
package/CHANGELOG.md CHANGED
@@ -3,6 +3,59 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## 5.13.0
7
+
8
+ _Jul 7, 2022_
9
+
10
+ We'd like to offer a big thanks to the 10 contributors who made this release possible. Here are some highlights ✨:
11
+
12
+ - 🎁 `@mui/x-date-pickers` and `@mui/x-date-pickers-pro` are now in beta!
13
+
14
+ - ✨ Allow detail panel's height to match its content (#5163) @m4theushw
15
+
16
+ ```tsx
17
+ <DataGridPro getDetailPanelHeight={() => 'auto'} />
18
+ ```
19
+
20
+ - 🌍 Add Romanian (ro-RO) locale on the data grid (#5345) @rolule
21
+ - 📚 Documentation improvements
22
+ - 🐞 Bugfixes
23
+
24
+ ### `@mui/x-data-grid@v5.13.0` / `@mui/x-data-grid-pro@v5.13.0` / `@mui/x-data-grid-premium@v5.13.0`
25
+
26
+ #### Changes
27
+
28
+ - [DataGrid] Allows to customize variant of value input in filter panel (#4826) @alexfauquette
29
+ - [DataGrid] Add Romanian (ro-RO) locale (#5345) @rolule
30
+ - [DataGrid] Export Norwegian (nb-NO) locale (#5407) @cherniavskii
31
+ - [DataGrid] Fix broken "start editing" integration with Japanese (#5414) @mnajdova
32
+ - [DataGrid] Fix "stop editing" integration with IME e.g. Japanese (#5257) @Gumichocopengin8
33
+ - [DataGrid] Fix dimensions computation with `autoHeight` and scroll x (#5401) @flaviendelangle
34
+ - [DataGrid] Improve Slovak (sk-SK) locale (#5332) @msidlo
35
+ - [DataGrid] Mention Premium plan in error messages and docs warnings (#5328) @cherniavskii
36
+ - [DataGrid] Remove trailing spaces in filter input (#5279) @alexfauquette
37
+ - [DataGridPro] Allow to infer detail panel height from content (#5163) @m4theushw
38
+ - [DataGridPro] Fix the depth of nodes when switching from a non-flat tree to a flat tree (#5362) @flaviendelangle
39
+
40
+ ### `@mui/x-date-pickers@v5.0.0-beta.0` / `@mui/x-date-picker-pro@5.0.0-beta.0`
41
+
42
+ #### Changes
43
+
44
+ - [DateRangePicker] Fix keyboard selection (#5265) @alexfauquette
45
+ - [DayPicker] Remove empty space at the bottom of the day view (#5073) @flaviendelangle
46
+ - [pickers] Add missing type dependencies (#5331) @Methuselah96
47
+ - [pickers] Pass the generics to the components in the theme augmentation (#5199) @toruticas
48
+
49
+ ### Docs
50
+
51
+ - [docs] Explain how to use hooks inside a cell renderer (#5158) @flaviendelangle
52
+ - [docs] Fix server-side pagination demo (#5361) @cherniavskii
53
+ - [docs] Fix typo in the quick filter docs (#5313) @alexfauquette
54
+ - [docs] Improve the "Getting started" page (#5293) @alexfauquette
55
+ - [docs] New page for the pickers action bar customization (#5267) @flaviendelangle
56
+ - [docs] Revise and split up "Overview" page into "Introduction" (#4692) @samuelsycamore
57
+ - [docs] Use `useKeepGroupedColumnsHiddren` from the grid package on remaining demo (#5382) @flaviendelangle
58
+
6
59
  ## v5.12.3
7
60
 
8
61
  _Jun 23, 2022_
@@ -318,7 +318,7 @@ DataGridProRaw.propTypes = {
318
318
  /**
319
319
  * Function that returns the height of the row detail panel.
320
320
  * @param {GridRowParams} params With all properties from [[GridRowParams]].
321
- * @returns {number} The height in pixels.
321
+ * @returns {number | string} The height in pixels or "auto" to use the content height.
322
322
  * @default "() => 500"
323
323
  */
324
324
  getDetailPanelHeight: PropTypes.func,
@@ -3,7 +3,6 @@ import _extends from "@babel/runtime/helpers/esm/extends";
3
3
  const _excluded = ["className", "disableVirtualization"];
4
4
  import * as React from 'react';
5
5
  import { styled, alpha } from '@mui/material/styles';
6
- import Box from '@mui/material/Box';
7
6
  import { unstable_composeClasses as composeClasses } from '@mui/material';
8
7
  import { useGridSelector, getDataGridUtilityClass, gridClasses, gridVisibleColumnFieldsSelector, gridRowsMetaSelector, useGridApiEventHandler } from '@mui/x-data-grid';
9
8
  import { GridVirtualScroller, GridVirtualScrollerContent, GridVirtualScrollerRenderZone, useGridVirtualScroller } from '@mui/x-data-grid/internals';
@@ -11,6 +10,7 @@ import { useGridApiContext } from '../hooks/utils/useGridApiContext';
11
10
  import { useGridRootProps } from '../hooks/utils/useGridRootProps';
12
11
  import { gridPinnedColumnsSelector, GridPinnedPosition } from '../hooks/features/columnPinning';
13
12
  import { gridDetailPanelExpandedRowsContentCacheSelector, gridDetailPanelExpandedRowsHeightCacheSelector, gridDetailPanelExpandedRowIdsSelector } from '../hooks/features/detailPanel';
13
+ import { GridDetailPanel } from './GridDetailPanel';
14
14
  import { jsx as _jsx } from "react/jsx-runtime";
15
15
  import { jsxs as _jsxs } from "react/jsx-runtime";
16
16
  export const filterColumns = (pinnedColumns, columns) => {
@@ -74,19 +74,6 @@ const VirtualScrollerDetailPanels = styled('div', {
74
74
  })({
75
75
  position: 'relative'
76
76
  });
77
- const VirtualScrollerDetailPanel = styled(Box, {
78
- name: 'MuiDataGrid',
79
- slot: 'DetailPanel',
80
- overridesResolver: (props, styles) => styles.detailPanel
81
- })(({
82
- theme
83
- }) => ({
84
- zIndex: 2,
85
- width: '100%',
86
- position: 'absolute',
87
- backgroundColor: theme.palette.background.default,
88
- overflow: 'auto'
89
- }));
90
77
  const VirtualScrollerPinnedColumns = styled('div', {
91
78
  name: 'MuiDataGrid',
92
79
  slot: 'PinnedColumns',
@@ -210,15 +197,17 @@ const DataGridProVirtualScroller = /*#__PURE__*/React.forwardRef(function DataGr
210
197
  const exists = rowIndex !== undefined;
211
198
 
212
199
  if ( /*#__PURE__*/React.isValidElement(content) && exists) {
213
- const height = detailPanelsHeights[id];
200
+ const hasAutoHeight = apiRef.current.unstable_detailPanelHasAutoHeight(id);
201
+ const height = hasAutoHeight ? 'auto' : detailPanelsHeights[id];
214
202
  const sizes = apiRef.current.unstable_getRowInternalSizes(id);
215
203
  const spacingTop = (sizes == null ? void 0 : sizes.spacingTop) || 0;
216
204
  const top = rowsMeta.positions[rowIndex] + apiRef.current.unstable_getRowHeight(id) + spacingTop;
217
- panels.push( /*#__PURE__*/_jsx(VirtualScrollerDetailPanel, {
205
+ panels.push( /*#__PURE__*/_jsx(GridDetailPanel, {
206
+ rowId: id,
218
207
  style: {
219
- top,
220
- height
208
+ top
221
209
  },
210
+ height: height,
222
211
  className: classes.detailPanel,
223
212
  children: content
224
213
  }, i));
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ import { SxProps, Theme } from '@mui/material/styles';
3
+ import { GridRowId } from '@mui/x-data-grid';
4
+ interface GridDetailPanelProps extends React.HTMLAttributes<HTMLDivElement> {
5
+ /**
6
+ * The system prop that allows defining system overrides as well as additional CSS styles.
7
+ */
8
+ sx?: SxProps<Theme>;
9
+ /**
10
+ * The panel height.
11
+ */
12
+ height: number | 'auto';
13
+ /**
14
+ * The row ID that this panel belongs to.
15
+ */
16
+ rowId: GridRowId;
17
+ }
18
+ declare const GridDetailPanel: (props: GridDetailPanelProps) => JSX.Element;
19
+ export { GridDetailPanel };
@@ -0,0 +1,65 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
+ const _excluded = ["rowId", "height", "style"];
4
+ import * as React from 'react';
5
+ import Box from '@mui/material/Box';
6
+ import { styled } from '@mui/material/styles';
7
+ import { useGridApiContext } from '../hooks/utils/useGridApiContext';
8
+ import { jsx as _jsx } from "react/jsx-runtime";
9
+ const DetailPanel = styled(Box, {
10
+ name: 'MuiDataGrid',
11
+ slot: 'DetailPanel',
12
+ overridesResolver: (props, styles) => styles.detailPanel
13
+ })(({
14
+ theme
15
+ }) => ({
16
+ zIndex: 2,
17
+ width: '100%',
18
+ position: 'absolute',
19
+ backgroundColor: theme.palette.background.default,
20
+ overflow: 'auto'
21
+ }));
22
+
23
+ const GridDetailPanel = props => {
24
+ const {
25
+ rowId,
26
+ height,
27
+ style: styleProp = {}
28
+ } = props,
29
+ other = _objectWithoutPropertiesLoose(props, _excluded);
30
+
31
+ const apiRef = useGridApiContext();
32
+ const ref = React.useRef();
33
+ React.useLayoutEffect(() => {
34
+ if (height === 'auto' && ref.current && typeof ResizeObserver === 'undefined') {
35
+ // Fallback for IE
36
+ apiRef.current.unstable_storeDetailPanelHeight(rowId, ref.current.clientHeight);
37
+ }
38
+ }, [apiRef, height, rowId]);
39
+ React.useLayoutEffect(() => {
40
+ const hasFixedHeight = height !== 'auto';
41
+
42
+ if (!ref.current || hasFixedHeight || typeof ResizeObserver === 'undefined') {
43
+ return undefined;
44
+ }
45
+
46
+ const resizeObserver = new ResizeObserver(entries => {
47
+ const [entry] = entries;
48
+ const observedHeight = entry.borderBoxSize && entry.borderBoxSize.length > 0 ? entry.borderBoxSize[0].blockSize : entry.contentRect.height;
49
+ apiRef.current.unstable_storeDetailPanelHeight(rowId, observedHeight);
50
+ });
51
+ resizeObserver.observe(ref.current);
52
+ return () => resizeObserver.disconnect();
53
+ }, [apiRef, height, rowId]);
54
+
55
+ const style = _extends({}, styleProp, {
56
+ height
57
+ });
58
+
59
+ return /*#__PURE__*/_jsx(DetailPanel, _extends({
60
+ ref: ref,
61
+ style: style
62
+ }, other));
63
+ };
64
+
65
+ export { GridDetailPanel };
@@ -1,5 +1,9 @@
1
1
  import * as React from 'react';
2
2
  import { GridRowId } from '@mui/x-data-grid';
3
+ declare type DetailPanelHeightCache = Record<GridRowId, {
4
+ autoHeight: boolean;
5
+ height: number;
6
+ }>;
3
7
  /**
4
8
  * The master/detail API interface that is available in the grid [[apiRef]].
5
9
  */
@@ -19,10 +23,25 @@ export interface GridDetailPanelApi {
19
23
  * @param {GridRowId[]} ids The ids of the rows to open the detail panel.
20
24
  */
21
25
  setExpandedDetailPanels: (ids: GridRowId[]) => void;
26
+ /**
27
+ * Stores the panel height measurement and triggers the row height pre-processing.
28
+ * @param {GridRowId} id The id of the row.
29
+ * @param {number} height The new height.
30
+ * @ignore - do not document.
31
+ */
32
+ unstable_storeDetailPanelHeight: (id: GridRowId, height: number) => void;
33
+ /**
34
+ * Determines if the height of a detail panel is "auto".
35
+ * @param {GridRowId} id The id of the row.
36
+ * @return {boolean} `true` if the detail panel height is "auto".
37
+ * @ignore - do not document.
38
+ */
39
+ unstable_detailPanelHasAutoHeight: (id: GridRowId) => boolean;
22
40
  }
23
41
  export interface GridDetailPanelState {
24
42
  expandedRowIds: GridRowId[];
25
43
  contentCache: Record<GridRowId, React.ReactNode>;
26
- heightCache: Record<GridRowId, number>;
44
+ heightCache: DetailPanelHeightCache;
27
45
  }
28
46
  export declare type GridDetailPanelInitialState = Pick<GridDetailPanelState, 'expandedRowIds'>;
47
+ export {};
@@ -1,5 +1,16 @@
1
1
  /// <reference types="react" />
2
+ import { GridRowId } from '@mui/x-data-grid';
2
3
  import { GridStatePro } from '../../../models/gridStatePro';
3
- export declare const gridDetailPanelExpandedRowIdsSelector: (state: GridStatePro) => import("@mui/x-data-grid").GridRowId[];
4
- export declare const gridDetailPanelExpandedRowsContentCacheSelector: (state: GridStatePro) => Record<import("@mui/x-data-grid").GridRowId, import("react").ReactNode>;
5
- export declare const gridDetailPanelExpandedRowsHeightCacheSelector: (state: GridStatePro) => Record<import("@mui/x-data-grid").GridRowId, number>;
4
+ export declare const gridDetailPanelExpandedRowIdsSelector: (state: GridStatePro) => GridRowId[];
5
+ export declare const gridDetailPanelExpandedRowsContentCacheSelector: (state: GridStatePro) => Record<GridRowId, import("react").ReactNode>;
6
+ export declare const gridDetailPanelRawHeightCacheSelector: (state: GridStatePro) => {
7
+ [x: string]: {
8
+ autoHeight: boolean;
9
+ height: number;
10
+ };
11
+ [x: number]: {
12
+ autoHeight: boolean;
13
+ height: number;
14
+ };
15
+ };
16
+ export declare const gridDetailPanelExpandedRowsHeightCacheSelector: import("@mui/x-data-grid").OutputSelector<GridStatePro, Record<GridRowId, number>>;
@@ -1,3 +1,11 @@
1
+ import { createSelector } from '@mui/x-data-grid/internals';
1
2
  export const gridDetailPanelExpandedRowIdsSelector = state => state.detailPanel.expandedRowIds;
2
3
  export const gridDetailPanelExpandedRowsContentCacheSelector = state => state.detailPanel.contentCache;
3
- export const gridDetailPanelExpandedRowsHeightCacheSelector = state => state.detailPanel.heightCache;
4
+ export const gridDetailPanelRawHeightCacheSelector = state => state.detailPanel.heightCache; // TODO v6: Make this selector return the full object, including the autoHeight flag
5
+
6
+ export const gridDetailPanelExpandedRowsHeightCacheSelector = createSelector(gridDetailPanelRawHeightCacheSelector, heightCache => Object.entries(heightCache).reduce((acc, [id, {
7
+ height
8
+ }]) => {
9
+ acc[id] = height || 0;
10
+ return acc;
11
+ }, {}));
@@ -1,3 +1,3 @@
1
1
  export * from './gridDetailPanelToggleColDef';
2
- export * from './gridDetailPanelSelector';
2
+ export { gridDetailPanelExpandedRowIdsSelector, gridDetailPanelExpandedRowsContentCacheSelector, gridDetailPanelExpandedRowsHeightCacheSelector, } from './gridDetailPanelSelector';
3
3
  export * from './gridDetailPanelInterface';
@@ -1,3 +1,3 @@
1
1
  export * from './gridDetailPanelToggleColDef';
2
- export * from './gridDetailPanelSelector';
2
+ export { gridDetailPanelExpandedRowIdsSelector, gridDetailPanelExpandedRowsContentCacheSelector, gridDetailPanelExpandedRowsHeightCacheSelector } from './gridDetailPanelSelector';
3
3
  export * from './gridDetailPanelInterface';
@@ -3,18 +3,19 @@ import * as React from 'react';
3
3
  import { useGridSelector, useGridApiEventHandler, useGridApiMethod, gridRowIdsSelector } from '@mui/x-data-grid';
4
4
  import { useGridRegisterPipeProcessor } from '@mui/x-data-grid/internals';
5
5
  import { GRID_DETAIL_PANEL_TOGGLE_FIELD } from './gridDetailPanelToggleColDef';
6
- import { gridDetailPanelExpandedRowIdsSelector, gridDetailPanelExpandedRowsContentCacheSelector, gridDetailPanelExpandedRowsHeightCacheSelector } from './gridDetailPanelSelector';
6
+ import { gridDetailPanelExpandedRowIdsSelector, gridDetailPanelExpandedRowsContentCacheSelector, gridDetailPanelExpandedRowsHeightCacheSelector, gridDetailPanelRawHeightCacheSelector } from './gridDetailPanelSelector';
7
7
  export const detailPanelStateInitializer = (state, props) => {
8
8
  var _ref, _props$detailPanelExp, _props$initialState, _props$initialState$d;
9
9
 
10
10
  return _extends({}, state, {
11
11
  detailPanel: {
12
+ heightCache: {},
12
13
  expandedRowIds: (_ref = (_props$detailPanelExp = props.detailPanelExpandedRowIds) != null ? _props$detailPanelExp : (_props$initialState = props.initialState) == null ? void 0 : (_props$initialState$d = _props$initialState.detailPanel) == null ? void 0 : _props$initialState$d.expandedRowIds) != null ? _ref : []
13
14
  }
14
15
  });
15
16
  };
16
17
 
17
- function cacheContentAndHeight(apiRef, getDetailPanelContent, getDetailPanelHeight) {
18
+ function cacheContentAndHeight(apiRef, getDetailPanelContent, getDetailPanelHeight, previousHeightCache) {
18
19
  if (typeof getDetailPanelContent !== 'function') {
19
20
  return {};
20
21
  } // TODO change to lazy approach using a Proxy
@@ -28,12 +29,19 @@ function cacheContentAndHeight(apiRef, getDetailPanelContent, getDetailPanelHeig
28
29
  return acc;
29
30
  }, {});
30
31
  const heightCache = rowIds.reduce((acc, id) => {
32
+ var _previousHeightCache$;
33
+
31
34
  if (contentCache[id] == null) {
32
35
  return acc;
33
36
  }
34
37
 
35
38
  const params = apiRef.current.getRowParams(id);
36
- acc[id] = getDetailPanelHeight(params);
39
+ const height = getDetailPanelHeight(params);
40
+ const autoHeight = height === 'auto';
41
+ acc[id] = {
42
+ autoHeight,
43
+ height: autoHeight ? (_previousHeightCache$ = previousHeightCache[id]) == null ? void 0 : _previousHeightCache$.height : height
44
+ };
37
45
  return acc;
38
46
  }, {});
39
47
  return {
@@ -112,10 +120,36 @@ export const useGridDetailPanel = (apiRef, props) => {
112
120
  });
113
121
  apiRef.current.forceUpdate();
114
122
  }, [apiRef]);
123
+ const storeDetailPanelHeight = React.useCallback((id, height) => {
124
+ const heightCache = gridDetailPanelRawHeightCacheSelector(apiRef.current.state);
125
+
126
+ if (!heightCache[id] || heightCache[id].height === height) {
127
+ return;
128
+ }
129
+
130
+ apiRef.current.setState(state => {
131
+ return _extends({}, state, {
132
+ detailPanel: _extends({}, state.detailPanel, {
133
+ heightCache: _extends({}, heightCache, {
134
+ [id]: _extends({}, heightCache[id], {
135
+ height
136
+ })
137
+ })
138
+ })
139
+ });
140
+ });
141
+ apiRef.current.unstable_requestPipeProcessorsApplication('rowHeight');
142
+ }, [apiRef]);
143
+ const detailPanelHasAutoHeight = React.useCallback(id => {
144
+ const heightCache = gridDetailPanelRawHeightCacheSelector(apiRef.current.state);
145
+ return heightCache[id] ? heightCache[id].autoHeight : false;
146
+ }, [apiRef]);
115
147
  const detailPanelApi = {
116
148
  toggleDetailPanel,
117
149
  getExpandedDetailPanels,
118
- setExpandedDetailPanels
150
+ setExpandedDetailPanels,
151
+ unstable_storeDetailPanelHeight: storeDetailPanelHeight,
152
+ unstable_detailPanelHasAutoHeight: detailPanelHasAutoHeight
119
153
  };
120
154
  useGridApiMethod(apiRef, detailPanelApi, 'detailPanelApi');
121
155
  React.useEffect(() => {
@@ -130,7 +164,7 @@ export const useGridDetailPanel = (apiRef, props) => {
130
164
  const updateCachesAndForceUpdate = React.useCallback(() => {
131
165
  apiRef.current.setState(state => {
132
166
  return _extends({}, state, {
133
- detailPanel: _extends({}, state.detailPanel, cacheContentAndHeight(apiRef, props.getDetailPanelContent, props.getDetailPanelHeight))
167
+ detailPanel: _extends({}, state.detailPanel, cacheContentAndHeight(apiRef, props.getDetailPanelContent, props.getDetailPanelHeight, state.detailPanel.heightCache))
134
168
  });
135
169
  });
136
170
  apiRef.current.forceUpdate();
@@ -145,7 +179,7 @@ export const useGridDetailPanel = (apiRef, props) => {
145
179
 
146
180
  apiRef.current.setState(state => {
147
181
  return _extends({}, state, {
148
- detailPanel: _extends({}, state.detailPanel, cacheContentAndHeight(apiRef, props.getDetailPanelContent, props.getDetailPanelHeight))
182
+ detailPanel: _extends({}, state.detailPanel, cacheContentAndHeight(apiRef, props.getDetailPanelContent, props.getDetailPanelHeight, state.detailPanel.heightCache))
149
183
  });
150
184
  });
151
185
  previousGetDetailPanelContentProp.current = props.getDetailPanelContent;
@@ -161,7 +195,7 @@ export const useGridDetailPanel = (apiRef, props) => {
161
195
  }
162
196
 
163
197
  updateCachesIfNeeded();
164
- const heightCache = gridDetailPanelExpandedRowsHeightCacheSelector(apiRef.current.state);
198
+ const heightCache = gridDetailPanelExpandedRowsHeightCacheSelector(apiRef);
165
199
  return _extends({}, initialValue, {
166
200
  detail: (_heightCache$row$id = heightCache[row.id]) != null ? _heightCache$row$id : 0 // Fallback to zero because the cache might not be ready yet (e.g. page was changed)
167
201
 
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import { GridApiPro } from '../../../models/gridApiPro';
3
+ import { DataGridProProcessedProps } from '../../../models/dataGridProProps';
4
+ export declare const useGridDetailPanelCache: (apiRef: React.MutableRefObject<GridApiPro>, props: Pick<DataGridProProcessedProps, 'getDetailPanelContent' | 'getDetailPanelHeight'>) => void;
@@ -0,0 +1,64 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import * as React from 'react';
3
+ import { useGridApiEventHandler, gridRowIdsSelector } from '@mui/x-data-grid';
4
+
5
+ function cacheContentAndHeight(apiRef, getDetailPanelContent, getDetailPanelHeight, previousHeightCache) {
6
+ if (typeof getDetailPanelContent !== 'function') {
7
+ return {};
8
+ } // TODO change to lazy approach using a Proxy
9
+ // only call getDetailPanelContent when asked for an id
10
+
11
+
12
+ const rowIds = gridRowIdsSelector(apiRef);
13
+ const contentCache = rowIds.reduce((acc, id) => {
14
+ const params = apiRef.current.getRowParams(id);
15
+ acc[id] = getDetailPanelContent(params);
16
+ return acc;
17
+ }, {});
18
+ const heightCache = rowIds.reduce((acc, id) => {
19
+ var _previousHeightCache$;
20
+
21
+ if (contentCache[id] == null) {
22
+ return acc;
23
+ }
24
+
25
+ const params = apiRef.current.getRowParams(id);
26
+ const height = getDetailPanelHeight(params);
27
+ const autoHeight = height === 'auto';
28
+ acc[id] = {
29
+ autoHeight,
30
+ height: !autoHeight ? height : (_previousHeightCache$ = previousHeightCache[id]) == null ? void 0 : _previousHeightCache$.height
31
+ };
32
+ return acc;
33
+ }, {});
34
+ return {
35
+ contentCache,
36
+ heightCache
37
+ };
38
+ }
39
+
40
+ export const useGridDetailPanelCache = (apiRef, props) => {
41
+ const updateCaches = React.useCallback(() => {
42
+ apiRef.current.setState(state => {
43
+ return _extends({}, state, {
44
+ detailPanel: _extends({}, state.detailPanel, cacheContentAndHeight(apiRef, props.getDetailPanelContent, props.getDetailPanelHeight, state.detailPanel.heightCache))
45
+ });
46
+ });
47
+ apiRef.current.forceUpdate();
48
+ }, [apiRef, props.getDetailPanelContent, props.getDetailPanelHeight]);
49
+ useGridApiEventHandler(apiRef, 'sortedRowsSet', updateCaches);
50
+ const isFirstRender = React.useRef(true);
51
+
52
+ if (isFirstRender.current) {
53
+ isFirstRender.current = false;
54
+ updateCaches();
55
+ }
56
+
57
+ React.useEffect(() => {
58
+ if (isFirstRender.current) {
59
+ return;
60
+ }
61
+
62
+ updateCaches();
63
+ }, [updateCaches]);
64
+ };
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- /** @license MUI v5.12.3
1
+ /** @license MUI v5.13.0
2
2
  *
3
3
  * This source code is licensed under the MIT license found in the
4
4
  * LICENSE file in the root directory of this source tree.
@@ -318,7 +318,7 @@ DataGridProRaw.propTypes = {
318
318
  /**
319
319
  * Function that returns the height of the row detail panel.
320
320
  * @param {GridRowParams} params With all properties from [[GridRowParams]].
321
- * @returns {number} The height in pixels.
321
+ * @returns {number | string} The height in pixels or "auto" to use the content height.
322
322
  * @default "() => 500"
323
323
  */
324
324
  getDetailPanelHeight: PropTypes.func,
@@ -6,7 +6,6 @@ import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
6
6
  var _excluded = ["className", "disableVirtualization"];
7
7
  import * as React from 'react';
8
8
  import { styled, alpha } from '@mui/material/styles';
9
- import Box from '@mui/material/Box';
10
9
  import { unstable_composeClasses as composeClasses } from '@mui/material';
11
10
  import { useGridSelector, getDataGridUtilityClass, gridClasses, gridVisibleColumnFieldsSelector, gridRowsMetaSelector, useGridApiEventHandler } from '@mui/x-data-grid';
12
11
  import { GridVirtualScroller, GridVirtualScrollerContent, GridVirtualScrollerRenderZone, useGridVirtualScroller } from '@mui/x-data-grid/internals';
@@ -14,6 +13,7 @@ import { useGridApiContext } from '../hooks/utils/useGridApiContext';
14
13
  import { useGridRootProps } from '../hooks/utils/useGridRootProps';
15
14
  import { gridPinnedColumnsSelector, GridPinnedPosition } from '../hooks/features/columnPinning';
16
15
  import { gridDetailPanelExpandedRowsContentCacheSelector, gridDetailPanelExpandedRowsHeightCacheSelector, gridDetailPanelExpandedRowIdsSelector } from '../hooks/features/detailPanel';
16
+ import { GridDetailPanel } from './GridDetailPanel';
17
17
  import { jsx as _jsx } from "react/jsx-runtime";
18
18
  import { jsxs as _jsxs } from "react/jsx-runtime";
19
19
  export var filterColumns = function filterColumns(pinnedColumns, columns) {
@@ -81,31 +81,15 @@ var VirtualScrollerDetailPanels = styled('div', {
81
81
  })({
82
82
  position: 'relative'
83
83
  });
84
- var VirtualScrollerDetailPanel = styled(Box, {
85
- name: 'MuiDataGrid',
86
- slot: 'DetailPanel',
87
- overridesResolver: function overridesResolver(props, styles) {
88
- return styles.detailPanel;
89
- }
90
- })(function (_ref) {
91
- var theme = _ref.theme;
92
- return {
93
- zIndex: 2,
94
- width: '100%',
95
- position: 'absolute',
96
- backgroundColor: theme.palette.background.default,
97
- overflow: 'auto'
98
- };
99
- });
100
84
  var VirtualScrollerPinnedColumns = styled('div', {
101
85
  name: 'MuiDataGrid',
102
86
  slot: 'PinnedColumns',
103
87
  overridesResolver: function overridesResolver(props, styles) {
104
88
  return [_defineProperty({}, "&.".concat(gridClasses['pinnedColumns--left']), styles['pinnedColumns--left']), _defineProperty({}, "&.".concat(gridClasses['pinnedColumns--right']), styles['pinnedColumns--right']), styles.pinnedColumns];
105
89
  }
106
- })(function (_ref4) {
107
- var theme = _ref4.theme,
108
- ownerState = _ref4.ownerState;
90
+ })(function (_ref3) {
91
+ var theme = _ref3.theme,
92
+ ownerState = _ref3.ownerState;
109
93
  return _extends({
110
94
  position: 'sticky',
111
95
  overflow: 'hidden',
@@ -135,8 +119,8 @@ var DataGridProVirtualScroller = /*#__PURE__*/React.forwardRef(function DataGrid
135
119
  var detailPanelsHeights = useGridSelector(apiRef, gridDetailPanelExpandedRowsHeightCacheSelector);
136
120
  var leftColumns = React.useRef(null);
137
121
  var rightColumns = React.useRef(null);
138
- var handleRenderZonePositioning = React.useCallback(function (_ref5) {
139
- var top = _ref5.top;
122
+ var handleRenderZonePositioning = React.useCallback(function (_ref4) {
123
+ var top = _ref4.top;
140
124
 
141
125
  if (leftColumns.current) {
142
126
  leftColumns.current.style.transform = "translate3d(0px, ".concat(top, "px, 0px)");
@@ -227,15 +211,17 @@ var DataGridProVirtualScroller = /*#__PURE__*/React.forwardRef(function DataGrid
227
211
  var exists = rowIndex !== undefined;
228
212
 
229
213
  if ( /*#__PURE__*/React.isValidElement(content) && exists) {
230
- var height = detailPanelsHeights[id];
214
+ var hasAutoHeight = apiRef.current.unstable_detailPanelHasAutoHeight(id);
215
+ var height = hasAutoHeight ? 'auto' : detailPanelsHeights[id];
231
216
  var sizes = apiRef.current.unstable_getRowInternalSizes(id);
232
217
  var spacingTop = (sizes == null ? void 0 : sizes.spacingTop) || 0;
233
218
  var top = rowsMeta.positions[rowIndex] + apiRef.current.unstable_getRowHeight(id) + spacingTop;
234
- panels.push( /*#__PURE__*/_jsx(VirtualScrollerDetailPanel, {
219
+ panels.push( /*#__PURE__*/_jsx(GridDetailPanel, {
220
+ rowId: id,
235
221
  style: {
236
- top: top,
237
- height: height
222
+ top: top
238
223
  },
224
+ height: height,
239
225
  className: classes.detailPanel,
240
226
  children: content
241
227
  }, i));
@@ -0,0 +1,72 @@
1
+ import _extends from "@babel/runtime/helpers/esm/extends";
2
+ import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
3
+ import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
4
+ var _excluded = ["rowId", "height", "style"];
5
+ import * as React from 'react';
6
+ import Box from '@mui/material/Box';
7
+ import { styled } from '@mui/material/styles';
8
+ import { useGridApiContext } from '../hooks/utils/useGridApiContext';
9
+ import { jsx as _jsx } from "react/jsx-runtime";
10
+ var DetailPanel = styled(Box, {
11
+ name: 'MuiDataGrid',
12
+ slot: 'DetailPanel',
13
+ overridesResolver: function overridesResolver(props, styles) {
14
+ return styles.detailPanel;
15
+ }
16
+ })(function (_ref) {
17
+ var theme = _ref.theme;
18
+ return {
19
+ zIndex: 2,
20
+ width: '100%',
21
+ position: 'absolute',
22
+ backgroundColor: theme.palette.background.default,
23
+ overflow: 'auto'
24
+ };
25
+ });
26
+
27
+ var GridDetailPanel = function GridDetailPanel(props) {
28
+ var rowId = props.rowId,
29
+ height = props.height,
30
+ _props$style = props.style,
31
+ styleProp = _props$style === void 0 ? {} : _props$style,
32
+ other = _objectWithoutProperties(props, _excluded);
33
+
34
+ var apiRef = useGridApiContext();
35
+ var ref = React.useRef();
36
+ React.useLayoutEffect(function () {
37
+ if (height === 'auto' && ref.current && typeof ResizeObserver === 'undefined') {
38
+ // Fallback for IE
39
+ apiRef.current.unstable_storeDetailPanelHeight(rowId, ref.current.clientHeight);
40
+ }
41
+ }, [apiRef, height, rowId]);
42
+ React.useLayoutEffect(function () {
43
+ var hasFixedHeight = height !== 'auto';
44
+
45
+ if (!ref.current || hasFixedHeight || typeof ResizeObserver === 'undefined') {
46
+ return undefined;
47
+ }
48
+
49
+ var resizeObserver = new ResizeObserver(function (entries) {
50
+ var _entries = _slicedToArray(entries, 1),
51
+ entry = _entries[0];
52
+
53
+ var observedHeight = entry.borderBoxSize && entry.borderBoxSize.length > 0 ? entry.borderBoxSize[0].blockSize : entry.contentRect.height;
54
+ apiRef.current.unstable_storeDetailPanelHeight(rowId, observedHeight);
55
+ });
56
+ resizeObserver.observe(ref.current);
57
+ return function () {
58
+ return resizeObserver.disconnect();
59
+ };
60
+ }, [apiRef, height, rowId]);
61
+
62
+ var style = _extends({}, styleProp, {
63
+ height: height
64
+ });
65
+
66
+ return /*#__PURE__*/_jsx(DetailPanel, _extends({
67
+ ref: ref,
68
+ style: style
69
+ }, other));
70
+ };
71
+
72
+ export { GridDetailPanel };