UNPKG

@mui/x-data-grid

Version:

The community edition of the data grid component (MUI X).

224 lines (219 loc) 10.8 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.useGridDimensions = useGridDimensions; var React = _interopRequireWildcard(require("react")); var _utils = require("@mui/utils"); var _useGridApiEventHandler = require("../../utils/useGridApiEventHandler"); var _useGridApiMethod = require("../../utils/useGridApiMethod"); var _useGridLogger = require("../../utils/useGridLogger"); var _columns = require("../columns"); var _density = require("../density"); var _utils2 = require("../../utils"); var _useGridVisibleRows = require("../../utils/useGridVisibleRows"); var _gridRowsMetaSelector = require("../rows/gridRowsMetaSelector"); var _gridRowsUtils = require("../rows/gridRowsUtils"); var _gridColumnsUtils = require("../columns/gridColumnsUtils"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } const isTestEnvironment = process.env.NODE_ENV === 'test'; const hasScroll = ({ content, container, scrollBarSize }) => { const hasScrollXIfNoYScrollBar = content.width > container.width; const hasScrollYIfNoXScrollBar = content.height > container.height; let hasScrollX = false; let hasScrollY = false; if (hasScrollXIfNoYScrollBar || hasScrollYIfNoXScrollBar) { hasScrollX = hasScrollXIfNoYScrollBar; hasScrollY = content.height + (hasScrollX ? scrollBarSize : 0) > container.height; // We recalculate the scroll x to consider the size of the y scrollbar. if (hasScrollY) { hasScrollX = content.width + scrollBarSize > container.width; } } return { hasScrollX, hasScrollY }; }; function useGridDimensions(apiRef, props) { const logger = (0, _useGridLogger.useGridLogger)(apiRef, 'useResizeContainer'); const errorShown = React.useRef(false); const rootDimensionsRef = React.useRef(null); const fullDimensionsRef = React.useRef(null); const rowsMeta = (0, _utils2.useGridSelector)(apiRef, _gridRowsMetaSelector.gridRowsMetaSelector); const densityFactor = (0, _utils2.useGridSelector)(apiRef, _density.gridDensityFactorSelector); const rowHeight = Math.floor(props.rowHeight * densityFactor); const totalHeaderHeight = (0, _gridColumnsUtils.getTotalHeaderHeight)(apiRef, props.columnHeaderHeight); const updateGridDimensionsRef = React.useCallback(() => { const rootElement = apiRef.current.rootElementRef?.current; const columnsTotalWidth = (0, _columns.gridColumnsTotalWidthSelector)(apiRef); const pinnedRowsHeight = (0, _gridRowsUtils.calculatePinnedRowsHeight)(apiRef); if (!rootDimensionsRef.current) { return; } let scrollBarSize; if (props.scrollbarSize != null) { scrollBarSize = props.scrollbarSize; } else if (!columnsTotalWidth || !rootElement) { scrollBarSize = 0; } else { const doc = (0, _utils.unstable_ownerDocument)(rootElement); const scrollDiv = doc.createElement('div'); scrollDiv.style.width = '99px'; scrollDiv.style.height = '99px'; scrollDiv.style.position = 'absolute'; scrollDiv.style.overflow = 'scroll'; scrollDiv.className = 'scrollDiv'; rootElement.appendChild(scrollDiv); scrollBarSize = scrollDiv.offsetWidth - scrollDiv.clientWidth; rootElement.removeChild(scrollDiv); } let viewportOuterSize; let hasScrollX; let hasScrollY; if (props.autoHeight) { hasScrollY = false; hasScrollX = Math.round(columnsTotalWidth) > Math.round(rootDimensionsRef.current.width); viewportOuterSize = { width: rootDimensionsRef.current.width, height: rowsMeta.currentPageTotalHeight + (hasScrollX ? scrollBarSize : 0) }; } else { viewportOuterSize = { width: rootDimensionsRef.current.width, height: Math.max(rootDimensionsRef.current.height - totalHeaderHeight, 0) }; const scrollInformation = hasScroll({ content: { width: Math.round(columnsTotalWidth), height: rowsMeta.currentPageTotalHeight }, container: { width: Math.round(viewportOuterSize.width), height: viewportOuterSize.height - pinnedRowsHeight.top - pinnedRowsHeight.bottom }, scrollBarSize }); hasScrollY = scrollInformation.hasScrollY; hasScrollX = scrollInformation.hasScrollX; } const viewportInnerSize = { width: viewportOuterSize.width - (hasScrollY ? scrollBarSize : 0), height: viewportOuterSize.height - (hasScrollX ? scrollBarSize : 0) }; const newFullDimensions = { viewportOuterSize, viewportInnerSize, hasScrollX, hasScrollY, scrollBarSize }; const prevDimensions = fullDimensionsRef.current; fullDimensionsRef.current = newFullDimensions; if (newFullDimensions.viewportInnerSize.width !== prevDimensions?.viewportInnerSize.width || newFullDimensions.viewportInnerSize.height !== prevDimensions?.viewportInnerSize.height) { apiRef.current.publishEvent('viewportInnerSizeChange', newFullDimensions.viewportInnerSize); } }, [apiRef, props.scrollbarSize, props.autoHeight, rowsMeta.currentPageTotalHeight, totalHeaderHeight]); const [savedSize, setSavedSize] = React.useState(); const debouncedSetSavedSize = React.useMemo(() => (0, _utils.unstable_debounce)(setSavedSize, 60), []); const previousSize = React.useRef(); (0, _utils.unstable_useEnhancedEffect)(() => { if (savedSize) { updateGridDimensionsRef(); apiRef.current.publishEvent('debouncedResize', rootDimensionsRef.current); } }, [apiRef, savedSize, updateGridDimensionsRef]); // This is the function called by apiRef.current.resize() const resize = React.useCallback(() => { apiRef.current.computeSizeAndPublishResizeEvent(); }, [apiRef]); const getRootDimensions = React.useCallback(() => fullDimensionsRef.current, []); const getViewportPageSize = React.useCallback(() => { const dimensions = apiRef.current.getRootDimensions(); if (!dimensions) { return 0; } const currentPage = (0, _useGridVisibleRows.getVisibleRows)(apiRef, { pagination: props.pagination, paginationMode: props.paginationMode }); // TODO: Use a combination of scrollTop, dimensions.viewportInnerSize.height and rowsMeta.possitions // to find out the maximum number of rows that can fit in the visible part of the grid if (props.getRowHeight) { const renderContext = apiRef.current.getRenderContext(); const viewportPageSize = renderContext.lastRowIndex - renderContext.firstRowIndex; return Math.min(viewportPageSize - 1, currentPage.rows.length); } const maximumPageSizeWithoutScrollBar = Math.floor(dimensions.viewportInnerSize.height / rowHeight); return Math.min(maximumPageSizeWithoutScrollBar, currentPage.rows.length); }, [apiRef, props.pagination, props.paginationMode, props.getRowHeight, rowHeight]); const computeSizeAndPublishResizeEvent = React.useCallback(() => { const mainEl = apiRef.current.mainElementRef?.current; if (!mainEl) { return; } const win = (0, _utils.unstable_ownerWindow)(mainEl); const computedStyle = win.getComputedStyle(mainEl); const height = parseFloat(computedStyle.height) || 0; const width = parseFloat(computedStyle.width) || 0; const hasHeightChanged = height !== previousSize.current?.height; const hasWidthChanged = width !== previousSize.current?.width; if (!previousSize.current || hasHeightChanged || hasWidthChanged) { const size = { width, height }; apiRef.current.publishEvent('resize', size); previousSize.current = size; } }, [apiRef]); const dimensionsApi = { resize, getRootDimensions }; const dimensionsPrivateApi = { getViewportPageSize, updateGridDimensionsRef, computeSizeAndPublishResizeEvent }; (0, _useGridApiMethod.useGridApiMethod)(apiRef, dimensionsApi, 'public'); (0, _useGridApiMethod.useGridApiMethod)(apiRef, dimensionsPrivateApi, 'private'); const isFirstSizing = React.useRef(true); const handleResize = React.useCallback(size => { rootDimensionsRef.current = size; // jsdom has no layout capabilities const isJSDOM = /jsdom/.test(window.navigator.userAgent); 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; } if (isTestEnvironment) { // We don't need to debounce the resize for tests. setSavedSize(size); isFirstSizing.current = false; return; } if (isFirstSizing.current) { // We want to initialize the grid dimensions as soon as possible to avoid flickering setSavedSize(size); isFirstSizing.current = false; return; } debouncedSetSavedSize(size); }, [props.autoHeight, debouncedSetSavedSize, logger]); (0, _utils.unstable_useEnhancedEffect)(() => updateGridDimensionsRef(), [updateGridDimensionsRef]); (0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'sortedRowsSet', updateGridDimensionsRef); (0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'paginationModelChange', updateGridDimensionsRef); (0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'columnsChange', updateGridDimensionsRef); (0, _useGridApiEventHandler.useGridApiEventHandler)(apiRef, 'resize', handleResize); (0, _useGridApiEventHandler.useGridApiOptionHandler)(apiRef, 'debouncedResize', props.onResize); }