UNPKG

@mui/x-data-grid

Version:

The Community plan edition of the MUI X Data Grid components.

131 lines (130 loc) 6.43 kB
'use client'; import _extends from "@babel/runtime/helpers/esm/extends"; import * as React from 'react'; import { useStoreEffect } from '@mui/x-internals/store'; import { Dimensions } from '@mui/x-virtualizer'; import { useGridEventPriority } from "../../utils/useGridEvent.js"; import { useGridApiMethod } from "../../utils/useGridApiMethod.js"; import { createSelector } from "../../../utils/createSelector.js"; import { useGridLogger } from "../../utils/useGridLogger.js"; import { gridColumnPositionsSelector, gridVisibleColumnDefinitionsSelector, gridVisiblePinnedColumnDefinitionsSelector } from "../columns/index.js"; import { gridDimensionsSelector } from "./gridDimensionsSelectors.js"; import { gridDensityFactorSelector } from "../density/index.js"; import { getValidRowHeight, rowHeightWarning } from "../rows/gridRowsUtils.js"; import { getTotalHeaderHeight } from "../columns/gridColumnsUtils.js"; import { DATA_GRID_PROPS_DEFAULT_VALUES } from "../../../constants/dataGridPropsDefaultValues.js"; import { roundToDecimalPlaces } from "../../../utils/roundToDecimalPlaces.js"; import { isJSDOM } from "../../../utils/isJSDOM.js"; const EMPTY_SIZE = { width: 0, height: 0 }; const EMPTY_DIMENSIONS = { isReady: false, root: EMPTY_SIZE, viewportOuterSize: EMPTY_SIZE, viewportInnerSize: EMPTY_SIZE, contentSize: EMPTY_SIZE, minimumSize: EMPTY_SIZE, hasScrollX: false, hasScrollY: false, scrollbarSize: 0, headerHeight: 0, groupHeaderHeight: 0, headerFilterHeight: 0, rowWidth: 0, rowHeight: 0, columnsTotalWidth: 0, leftPinnedWidth: 0, rightPinnedWidth: 0, headersTotalHeight: 0, topContainerHeight: 0, bottomContainerHeight: 0 }; export const dimensionsStateInitializer = (state, props, apiRef) => { const dimensions = EMPTY_DIMENSIONS; const density = gridDensityFactorSelector(apiRef); return _extends({}, state, { dimensions: _extends({}, dimensions, getStaticDimensions(props, apiRef, density, gridVisiblePinnedColumnDefinitionsSelector(apiRef))) }); }; const columnsTotalWidthSelector = createSelector(gridVisibleColumnDefinitionsSelector, gridColumnPositionsSelector, (visibleColumns, positions) => { const colCount = visibleColumns.length; if (colCount === 0) { return 0; } return roundToDecimalPlaces(positions[colCount - 1] + visibleColumns[colCount - 1].computedWidth, 1); }); export function useGridDimensions(apiRef, props) { const logger = useGridLogger(apiRef, 'useResizeContainer'); const errorShown = React.useRef(false); const virtualizer = apiRef.current.virtualizer; const updateDimensions = virtualizer.api.updateDimensions; const getViewportPageSize = virtualizer.api.getViewportPageSize; const getRootDimensions = React.useCallback(() => gridDimensionsSelector(apiRef), [apiRef]); const apiPublic = { getRootDimensions }; const apiPrivate = { updateDimensions, getViewportPageSize }; useGridApiMethod(apiRef, apiPublic, 'public'); useGridApiMethod(apiRef, apiPrivate, 'private'); const handleRootMount = root => { setCSSVariables(root, gridDimensionsSelector(apiRef)); }; const handleResize = size => { if (size.height === 0 && !errorShown.current && !props.autoHeight && !isJSDOM) { logger.error(['The parent DOM element of the Data Grid has an empty height.', 'Please make sure that this element has an intrinsic height.', 'The grid displays with a height of 0px.', '', 'More details: https://mui.com/r/x-data-grid-no-dimensions.'].join('\n')); errorShown.current = true; } if (size.width === 0 && !errorShown.current && !isJSDOM) { logger.error(['The parent DOM element of the Data Grid has an empty width.', 'Please make sure that this element has an intrinsic width.', 'The grid displays with a width of 0px.', '', 'More details: https://mui.com/r/x-data-grid-no-dimensions.'].join('\n')); errorShown.current = true; } }; useGridEventPriority(apiRef, 'rootMount', handleRootMount); useGridEventPriority(apiRef, 'resize', handleResize); useGridEventPriority(apiRef, 'debouncedResize', props.onResize); useStoreEffect(virtualizer.store, Dimensions.selectors.dimensions, (previous, next) => { if (apiRef.current.rootElementRef.current) { setCSSVariables(apiRef.current.rootElementRef.current, next); } if (!areElementSizesEqual(next.viewportInnerSize, previous.viewportInnerSize)) { apiRef.current.publishEvent('viewportInnerSizeChange', next.viewportInnerSize); } apiRef.current.publishEvent('debouncedResize', next.root); }); } function setCSSVariables(root, dimensions) { const set = (k, v) => root.style.setProperty(k, v); set('--DataGrid-hasScrollX', `${Number(dimensions.hasScrollX)}`); set('--DataGrid-hasScrollY', `${Number(dimensions.hasScrollY)}`); set('--DataGrid-scrollbarSize', `${dimensions.scrollbarSize}px`); set('--DataGrid-rowWidth', `${dimensions.rowWidth}px`); set('--DataGrid-columnsTotalWidth', `${dimensions.columnsTotalWidth}px`); set('--DataGrid-leftPinnedWidth', `${dimensions.leftPinnedWidth}px`); set('--DataGrid-rightPinnedWidth', `${dimensions.rightPinnedWidth}px`); set('--DataGrid-headerHeight', `${dimensions.headerHeight}px`); set('--DataGrid-headersTotalHeight', `${dimensions.headersTotalHeight}px`); set('--DataGrid-topContainerHeight', `${dimensions.topContainerHeight}px`); set('--DataGrid-bottomContainerHeight', `${dimensions.bottomContainerHeight}px`); set('--height', `${dimensions.rowHeight}px`); } function getStaticDimensions(props, apiRef, density, pinnedColumnns) { const validRowHeight = getValidRowHeight(props.rowHeight, DATA_GRID_PROPS_DEFAULT_VALUES.rowHeight, rowHeightWarning); return { rowHeight: Math.floor(validRowHeight * density), headerHeight: Math.floor(props.columnHeaderHeight * density), groupHeaderHeight: Math.floor((props.columnGroupHeaderHeight ?? props.columnHeaderHeight) * density), headerFilterHeight: Math.floor((props.headerFilterHeight ?? props.columnHeaderHeight) * density), columnsTotalWidth: columnsTotalWidthSelector(apiRef), headersTotalHeight: getTotalHeaderHeight(apiRef, props), leftPinnedWidth: pinnedColumnns.left.reduce((w, col) => w + col.computedWidth, 0), rightPinnedWidth: pinnedColumnns.right.reduce((w, col) => w + col.computedWidth, 0) }; } function areElementSizesEqual(a, b) { return a.width === b.width && a.height === b.height; }