diff --git a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts index bc1bfcb48f18b..188040859bc20 100644 --- a/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts +++ b/packages/x-data-grid/src/hooks/features/rows/useGridRowsMeta.ts @@ -1,5 +1,6 @@ import * as React from 'react'; import { unstable_debounce as debounce } from '@mui/utils'; +import useLazyRef from '@mui/utils/useLazyRef'; import { GridPrivateApiCommunity } from '../../../models/api/gridApiCommunity'; import { GridRowsMetaApi, GridRowsMetaPrivateApi } from '../../../models/api/gridRowsMetaApi'; import { DataGridProcessedProps } from '../../../models/props/DataGridProps'; @@ -18,6 +19,16 @@ import { DATA_GRID_PROPS_DEFAULT_VALUES } from '../../../DataGrid/useDataGridPro // TODO: I think the row heights can now be encoded as a single `size` instead of `sizes.baseXxxx` +// HACK: Minimal shim to get jsdom to work. +const ResizeObserverImpl = ( + typeof ResizeObserver !== 'undefined' + ? ResizeObserver + : class ResizeObserver { + observe() {} + unobserve() {} + } +) as typeof ResizeObserver; + export const rowsMetaStateInitializer: GridStateInitializer = (state) => ({ ...state, rowsMeta: { @@ -100,6 +111,29 @@ export const useGridRowsMeta = ( ); const rowHeight = Math.floor(validRowHeight * densityFactor); + const resizeObserver = useLazyRef( + () => + new ResizeObserverImpl((entries) => { + for (let i = 0; i < entries.length; i++) { + const entry = entries[i]; + const height = + entry.borderBoxSize && entry.borderBoxSize.length > 0 + ? entry.borderBoxSize[0].blockSize + : entry.contentRect.height; + const rowId = (entry.target as any).__mui_id; + apiRef.current.unstable_storeRowHeightMeasurement(rowId, height); + } + }), + ).current; + + const observeRow: GridRowsMetaPrivateApi['observeRow'] = (element, rowId) => { + (element as any).__mui_id = rowId; + + resizeObserver.observe(element); + + return () => resizeObserver.unobserve(element); + }; + const hydrateRowsMeta = React.useCallback(() => { hasRowWithAutoHeight.current = false; @@ -257,7 +291,7 @@ export const useGridRowsMeta = ( GridRowsMetaApi['unstable_storeRowHeightMeasurement'] >( (id, height) => { - if (!rowsHeightLookup.current[id] || !rowsHeightLookup.current[id].autoHeight) { + if (!rowsHeightLookup.current[id]?.autoHeight) { return; } @@ -315,8 +349,9 @@ export const useGridRowsMeta = ( }; const rowsMetaPrivateApi: GridRowsMetaPrivateApi = { - getLastMeasuredRowIndex, + observeRow, rowHasAutoHeight, + getLastMeasuredRowIndex, }; useGridApiMethod(apiRef, rowsMetaApi, 'public'); diff --git a/packages/x-data-grid/src/models/api/gridRowsMetaApi.ts b/packages/x-data-grid/src/models/api/gridRowsMetaApi.ts index 77e744b599aa5..5e53912048b30 100644 --- a/packages/x-data-grid/src/models/api/gridRowsMetaApi.ts +++ b/packages/x-data-grid/src/models/api/gridRowsMetaApi.ts @@ -46,6 +46,10 @@ export interface GridRowsMetaApi { } export interface GridRowsMetaPrivateApi { + /** + * Observe row for 'auto' height changes. + */ + observeRow: (element: Element, rowId: GridRowId) => ReturnType; /** * Determines if the height of a row is "auto". * @param {GridRowId} id The id of the row.