wip:milestone 0 fixes
Some checks failed
CI/CD Pipeline / unit-tests (push) Failing after 1m16s
CI/CD Pipeline / integration-tests (push) Failing after 2m32s
CI/CD Pipeline / lint (push) Successful in 5m22s
CI/CD Pipeline / e2e-tests (push) Has been skipped
CI/CD Pipeline / build (push) Has been skipped

This commit is contained in:
2026-03-15 12:35:42 +02:00
parent 6708cf28a7
commit cffdf8af86
61266 changed files with 4511646 additions and 1938 deletions

View File

@@ -0,0 +1,24 @@
import { createSelector } from '../../../utils/createSelector';
/**
* Get the columns state
* @category Virtualization
*/
export var gridVirtualizationSelector = function gridVirtualizationSelector(state) {
return state.virtualization;
};
/**
* Get the enabled state for virtualization
* @category Virtualization
*/
export var gridVirtualizationEnabledSelector = createSelector(gridVirtualizationSelector, function (state) {
return state.enabled;
});
/**
* Get the enabled state for virtualization
* @category Virtualization
*/
export var gridVirtualizationColumnEnabledSelector = createSelector(gridVirtualizationSelector, function (state) {
return state.enabledForColumns;
});

View File

@@ -0,0 +1,2 @@
export * from './useGridVirtualization';
export * from './gridVirtualizationSelectors';

View File

@@ -0,0 +1,636 @@
import _extends from "@babel/runtime/helpers/esm/extends";
import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
var _excluded = ["style"],
_excluded2 = ["style"];
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { unstable_useForkRef as useForkRef, unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback } from '@mui/utils';
import { useTheme } from '@mui/material/styles';
import { defaultMemoize } from 'reselect';
import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext';
import { useGridRootProps } from '../../utils/useGridRootProps';
import { useGridSelector } from '../../utils/useGridSelector';
import { gridVisibleColumnDefinitionsSelector, gridColumnsTotalWidthSelector, gridColumnPositionsSelector } from '../columns/gridColumnsSelector';
import { gridFocusCellSelector, gridTabIndexCellSelector } from '../focus/gridFocusStateSelector';
import { useGridVisibleRows } from '../../utils/useGridVisibleRows';
import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
import { clamp } from '../../../utils/utils';
import { selectedIdsLookupSelector } from '../rowSelection/gridRowSelectionSelector';
import { gridRowsMetaSelector } from '../rows/gridRowsMetaSelector';
import { getFirstNonSpannedColumnToRender } from '../columns/gridColumnsUtils';
import { getMinimalContentHeight } from '../rows/gridRowsUtils';
import { gridVirtualizationEnabledSelector, gridVirtualizationColumnEnabledSelector } from './gridVirtualizationSelectors';
// Uses binary search to avoid looping through all possible positions
import { jsx as _jsx } from "react/jsx-runtime";
export function binarySearch(offset, positions) {
var sliceStart = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var sliceEnd = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : positions.length;
if (positions.length <= 0) {
return -1;
}
if (sliceStart >= sliceEnd) {
return sliceStart;
}
var pivot = sliceStart + Math.floor((sliceEnd - sliceStart) / 2);
var itemOffset = positions[pivot];
return offset <= itemOffset ? binarySearch(offset, positions, sliceStart, pivot) : binarySearch(offset, positions, pivot + 1, sliceEnd);
}
function exponentialSearch(offset, positions, index) {
var interval = 1;
while (index < positions.length && Math.abs(positions[index]) < offset) {
index += interval;
interval *= 2;
}
return binarySearch(offset, positions, Math.floor(index / 2), Math.min(index, positions.length));
}
export var getRenderableIndexes = function getRenderableIndexes(_ref) {
var firstIndex = _ref.firstIndex,
lastIndex = _ref.lastIndex,
buffer = _ref.buffer,
minFirstIndex = _ref.minFirstIndex,
maxLastIndex = _ref.maxLastIndex;
return [clamp(firstIndex - buffer, minFirstIndex, maxLastIndex), clamp(lastIndex + buffer, minFirstIndex, maxLastIndex)];
};
export var areRenderContextsEqual = function areRenderContextsEqual(context1, context2) {
if (context1 === context2) {
return true;
}
return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
};
// The `maxSize` is 3 so that reselect caches the `renderedColumns` values for the pinned left,
// unpinned, and pinned right sections.
var MEMOIZE_OPTIONS = {
maxSize: 3
};
export var useGridVirtualScroller = function useGridVirtualScroller(props) {
var apiRef = useGridPrivateApiContext();
var rootProps = useGridRootProps();
var visibleColumns = useGridSelector(apiRef, gridVisibleColumnDefinitionsSelector);
var enabled = useGridSelector(apiRef, gridVirtualizationEnabledSelector);
var enabledForColumns = useGridSelector(apiRef, gridVirtualizationColumnEnabledSelector);
var ref = props.ref,
onRenderZonePositioning = props.onRenderZonePositioning,
_props$renderZoneMinC = props.renderZoneMinColumnIndex,
renderZoneMinColumnIndex = _props$renderZoneMinC === void 0 ? 0 : _props$renderZoneMinC,
_props$renderZoneMaxC = props.renderZoneMaxColumnIndex,
renderZoneMaxColumnIndex = _props$renderZoneMaxC === void 0 ? visibleColumns.length : _props$renderZoneMaxC,
getRowProps = props.getRowProps;
var theme = useTheme();
var columnPositions = useGridSelector(apiRef, gridColumnPositionsSelector);
var columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector);
var cellFocus = useGridSelector(apiRef, gridFocusCellSelector);
var cellTabIndex = useGridSelector(apiRef, gridTabIndexCellSelector);
var rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector);
var selectedRowsLookup = useGridSelector(apiRef, selectedIdsLookupSelector);
var currentPage = useGridVisibleRows(apiRef, rootProps);
var renderZoneRef = React.useRef(null);
var rootRef = React.useRef(null);
var handleRef = useForkRef(ref, rootRef);
var _React$useState = React.useState(null),
_React$useState2 = _slicedToArray(_React$useState, 2),
renderContext = _React$useState2[0],
setRenderContextState = _React$useState2[1];
var prevRenderContext = React.useRef(renderContext);
var scrollPosition = React.useRef({
top: 0,
left: 0
});
var _React$useState3 = React.useState({
width: null,
height: null
}),
_React$useState4 = _slicedToArray(_React$useState3, 2),
containerDimensions = _React$useState4[0],
setContainerDimensions = _React$useState4[1];
var prevTotalWidth = React.useRef(columnsTotalWidth);
// Each visible row (not to be confused with a filter result) is composed of a central row element
// and up to two additional row elements for pinned columns (left and right).
// When hovering any of these elements, the :hover styles are applied only to the row element that
// was actually hovered, not its additional siblings. To make it look like a contiguous row,
// we add/remove the .Mui-hovered class to all of the row elements inside one visible row.
var _React$useState5 = React.useState(null),
_React$useState6 = _slicedToArray(_React$useState5, 2),
hoveredRowId = _React$useState6[0],
setHoveredRowId = _React$useState6[1];
var rowStyleCache = React.useRef(Object.create(null));
var prevGetRowProps = React.useRef();
var prevRootRowStyle = React.useRef();
var getRenderedColumnsRef = React.useRef(defaultMemoize(function (columns, firstColumnToRender, lastColumnToRender, minFirstColumn, maxLastColumn, indexOfColumnWithFocusedCell) {
// If the selected column is not within the current range of columns being displayed,
// we need to render it at either the left or right of the columns,
// depending on whether it is above or below the range.
var focusedCellColumnIndexNotInRange;
var renderedColumns = columns.slice(firstColumnToRender, lastColumnToRender);
if (indexOfColumnWithFocusedCell > -1) {
// check if it is not on the left pinned column.
if (firstColumnToRender > indexOfColumnWithFocusedCell && indexOfColumnWithFocusedCell >= minFirstColumn) {
focusedCellColumnIndexNotInRange = indexOfColumnWithFocusedCell;
}
// check if it is not on the right pinned column.
else if (lastColumnToRender < indexOfColumnWithFocusedCell && indexOfColumnWithFocusedCell < maxLastColumn) {
focusedCellColumnIndexNotInRange = indexOfColumnWithFocusedCell;
}
}
return {
focusedCellColumnIndexNotInRange: focusedCellColumnIndexNotInRange,
renderedColumns: renderedColumns
};
}, MEMOIZE_OPTIONS));
var indexOfColumnWithFocusedCell = React.useMemo(function () {
if (cellFocus !== null) {
return visibleColumns.findIndex(function (column) {
return column.field === cellFocus.field;
});
}
return -1;
}, [cellFocus, visibleColumns]);
var computeRenderContext = React.useCallback(function () {
if (!enabled) {
return {
firstRowIndex: 0,
lastRowIndex: currentPage.rows.length,
firstColumnIndex: 0,
lastColumnIndex: visibleColumns.length
};
}
var _ref2 = scrollPosition.current,
top = _ref2.top,
left = _ref2.left;
// Clamp the value because the search may return an index out of bounds.
// In the last index, this is not needed because Array.slice doesn't include it.
var firstRowIndex = Math.min(getNearestIndexToRender(apiRef, currentPage, rowsMeta, top), rowsMeta.positions.length - 1);
var lastRowIndex = rootProps.autoHeight ? firstRowIndex + currentPage.rows.length : getNearestIndexToRender(apiRef, currentPage, rowsMeta, top + containerDimensions.height);
var firstColumnIndex = 0;
var lastColumnIndex = columnPositions.length;
if (enabledForColumns) {
var hasRowWithAutoHeight = false;
var _getRenderableIndexes = getRenderableIndexes({
firstIndex: firstRowIndex,
lastIndex: lastRowIndex,
minFirstIndex: 0,
maxLastIndex: currentPage.rows.length,
buffer: rootProps.rowBuffer
}),
_getRenderableIndexes2 = _slicedToArray(_getRenderableIndexes, 2),
firstRowToRender = _getRenderableIndexes2[0],
lastRowToRender = _getRenderableIndexes2[1];
for (var i = firstRowToRender; i < lastRowToRender && !hasRowWithAutoHeight; i += 1) {
var row = currentPage.rows[i];
hasRowWithAutoHeight = apiRef.current.rowHasAutoHeight(row.id);
}
if (!hasRowWithAutoHeight) {
firstColumnIndex = binarySearch(Math.abs(left), columnPositions);
lastColumnIndex = binarySearch(Math.abs(left) + containerDimensions.width, columnPositions);
}
}
return {
firstRowIndex: firstRowIndex,
lastRowIndex: lastRowIndex,
firstColumnIndex: firstColumnIndex,
lastColumnIndex: lastColumnIndex
};
}, [enabled, enabledForColumns, rowsMeta, rootProps.autoHeight, rootProps.rowBuffer, currentPage, columnPositions, visibleColumns.length, apiRef, containerDimensions]);
useEnhancedEffect(function () {
if (enabled) {
// TODO a scroll reset should not be necessary
rootRef.current.scrollLeft = 0;
rootRef.current.scrollTop = 0;
} else {
renderZoneRef.current.style.transform = "translate3d(0px, 0px, 0px)";
}
}, [enabled]);
useEnhancedEffect(function () {
setContainerDimensions({
width: rootRef.current.clientWidth,
height: rootRef.current.clientHeight
});
}, [rowsMeta.currentPageTotalHeight]);
var handleResize = React.useCallback(function () {
if (rootRef.current) {
setContainerDimensions({
width: rootRef.current.clientWidth,
height: rootRef.current.clientHeight
});
}
}, []);
useGridApiEventHandler(apiRef, 'debouncedResize', handleResize);
var updateRenderZonePosition = React.useCallback(function (nextRenderContext) {
var _getRenderableIndexes3 = getRenderableIndexes({
firstIndex: nextRenderContext.firstRowIndex,
lastIndex: nextRenderContext.lastRowIndex,
minFirstIndex: 0,
maxLastIndex: currentPage.rows.length,
buffer: rootProps.rowBuffer
}),
_getRenderableIndexes4 = _slicedToArray(_getRenderableIndexes3, 2),
firstRowToRender = _getRenderableIndexes4[0],
lastRowToRender = _getRenderableIndexes4[1];
var _getRenderableIndexes5 = getRenderableIndexes({
firstIndex: nextRenderContext.firstColumnIndex,
lastIndex: nextRenderContext.lastColumnIndex,
minFirstIndex: renderZoneMinColumnIndex,
maxLastIndex: renderZoneMaxColumnIndex,
buffer: rootProps.columnBuffer
}),
_getRenderableIndexes6 = _slicedToArray(_getRenderableIndexes5, 1),
initialFirstColumnToRender = _getRenderableIndexes6[0];
var firstColumnToRender = getFirstNonSpannedColumnToRender({
firstColumnToRender: initialFirstColumnToRender,
apiRef: apiRef,
firstRowToRender: firstRowToRender,
lastRowToRender: lastRowToRender,
visibleRows: currentPage.rows
});
var direction = theme.direction === 'ltr' ? 1 : -1;
var top = gridRowsMetaSelector(apiRef.current.state).positions[firstRowToRender];
var left = direction * gridColumnPositionsSelector(apiRef)[firstColumnToRender]; // Call directly the selector because it might be outdated when this method is called
renderZoneRef.current.style.transform = "translate3d(".concat(left, "px, ").concat(top, "px, 0px)");
if (typeof onRenderZonePositioning === 'function') {
onRenderZonePositioning({
top: top,
left: left
});
}
}, [apiRef, currentPage.rows, onRenderZonePositioning, renderZoneMinColumnIndex, renderZoneMaxColumnIndex, rootProps.columnBuffer, rootProps.rowBuffer, theme.direction]);
var getRenderContext = React.useCallback(function () {
return prevRenderContext.current;
}, []);
var setRenderContext = React.useCallback(function (nextRenderContext) {
if (prevRenderContext.current && areRenderContextsEqual(nextRenderContext, prevRenderContext.current)) {
updateRenderZonePosition(nextRenderContext);
return;
}
setRenderContextState(nextRenderContext);
updateRenderZonePosition(nextRenderContext);
var _getRenderableIndexes7 = getRenderableIndexes({
firstIndex: nextRenderContext.firstRowIndex,
lastIndex: nextRenderContext.lastRowIndex,
minFirstIndex: 0,
maxLastIndex: currentPage.rows.length,
buffer: rootProps.rowBuffer
}),
_getRenderableIndexes8 = _slicedToArray(_getRenderableIndexes7, 2),
firstRowToRender = _getRenderableIndexes8[0],
lastRowToRender = _getRenderableIndexes8[1];
apiRef.current.publishEvent('renderedRowsIntervalChange', {
firstRowToRender: firstRowToRender,
lastRowToRender: lastRowToRender
});
prevRenderContext.current = nextRenderContext;
}, [apiRef, setRenderContextState, prevRenderContext, currentPage.rows.length, rootProps.rowBuffer, updateRenderZonePosition]);
useEnhancedEffect(function () {
if (containerDimensions.width == null) {
return;
}
var initialRenderContext = computeRenderContext();
setRenderContext(initialRenderContext);
var _ref3 = scrollPosition.current,
top = _ref3.top,
left = _ref3.left;
var params = {
top: top,
left: left,
renderContext: initialRenderContext
};
apiRef.current.publishEvent('scrollPositionChange', params);
}, [apiRef, computeRenderContext, containerDimensions.width, setRenderContext]);
var handleScroll = useEventCallback(function (event) {
var _event$currentTarget = event.currentTarget,
scrollTop = _event$currentTarget.scrollTop,
scrollLeft = _event$currentTarget.scrollLeft;
scrollPosition.current.top = scrollTop;
scrollPosition.current.left = scrollLeft;
// On iOS and macOS, negative offsets are possible when swiping past the start
if (!prevRenderContext.current || scrollTop < 0) {
return;
}
if (theme.direction === 'ltr') {
if (scrollLeft < 0) {
return;
}
}
if (theme.direction === 'rtl') {
if (scrollLeft > 0) {
return;
}
}
// When virtualization is disabled, the context never changes during scroll
var nextRenderContext = enabled ? computeRenderContext() : prevRenderContext.current;
var topRowsScrolledSincePreviousRender = Math.abs(nextRenderContext.firstRowIndex - prevRenderContext.current.firstRowIndex);
var bottomRowsScrolledSincePreviousRender = Math.abs(nextRenderContext.lastRowIndex - prevRenderContext.current.lastRowIndex);
var topColumnsScrolledSincePreviousRender = Math.abs(nextRenderContext.firstColumnIndex - prevRenderContext.current.firstColumnIndex);
var bottomColumnsScrolledSincePreviousRender = Math.abs(nextRenderContext.lastColumnIndex - prevRenderContext.current.lastColumnIndex);
var shouldSetState = topRowsScrolledSincePreviousRender >= rootProps.rowThreshold || bottomRowsScrolledSincePreviousRender >= rootProps.rowThreshold || topColumnsScrolledSincePreviousRender >= rootProps.columnThreshold || bottomColumnsScrolledSincePreviousRender >= rootProps.columnThreshold || prevTotalWidth.current !== columnsTotalWidth;
apiRef.current.publishEvent('scrollPositionChange', {
top: scrollTop,
left: scrollLeft,
renderContext: shouldSetState ? nextRenderContext : prevRenderContext.current
}, event);
if (shouldSetState) {
// Prevents batching render context changes
ReactDOM.flushSync(function () {
setRenderContext(nextRenderContext);
});
prevTotalWidth.current = columnsTotalWidth;
}
});
var handleWheel = useEventCallback(function (event) {
apiRef.current.publishEvent('virtualScrollerWheel', {}, event);
});
var handleTouchMove = useEventCallback(function (event) {
apiRef.current.publishEvent('virtualScrollerTouchMove', {}, event);
});
var indexOfRowWithFocusedCell = React.useMemo(function () {
if (cellFocus !== null) {
return currentPage.rows.findIndex(function (row) {
return row.id === cellFocus.id;
});
}
return -1;
}, [cellFocus, currentPage.rows]);
useGridApiEventHandler(apiRef, 'rowMouseOver', function (params, event) {
var _params$id;
if (event.currentTarget.contains(event.relatedTarget)) {
return;
}
setHoveredRowId((_params$id = params.id) != null ? _params$id : null);
});
useGridApiEventHandler(apiRef, 'rowMouseOut', function (params, event) {
if (event.currentTarget.contains(event.relatedTarget)) {
return;
}
setHoveredRowId(null);
});
var getRows = function getRows() {
var _rootProps$slotProps;
var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
renderContext: renderContext
};
var onRowRender = params.onRowRender,
nextRenderContext = params.renderContext,
_params$minFirstColum = params.minFirstColumn,
minFirstColumn = _params$minFirstColum === void 0 ? renderZoneMinColumnIndex : _params$minFirstColum,
_params$maxLastColumn = params.maxLastColumn,
maxLastColumn = _params$maxLastColumn === void 0 ? renderZoneMaxColumnIndex : _params$maxLastColumn,
_params$availableSpac = params.availableSpace,
availableSpace = _params$availableSpac === void 0 ? containerDimensions.width : _params$availableSpac,
_params$rowIndexOffse = params.rowIndexOffset,
rowIndexOffset = _params$rowIndexOffse === void 0 ? 0 : _params$rowIndexOffse,
_params$position = params.position,
position = _params$position === void 0 ? 'center' : _params$position;
if (!nextRenderContext || availableSpace == null) {
return null;
}
var rowBuffer = enabled ? rootProps.rowBuffer : 0;
var columnBuffer = enabled ? rootProps.columnBuffer : 0;
var _getRenderableIndexes9 = getRenderableIndexes({
firstIndex: nextRenderContext.firstRowIndex,
lastIndex: nextRenderContext.lastRowIndex,
minFirstIndex: 0,
maxLastIndex: currentPage.rows.length,
buffer: rowBuffer
}),
_getRenderableIndexes10 = _slicedToArray(_getRenderableIndexes9, 2),
firstRowToRender = _getRenderableIndexes10[0],
lastRowToRender = _getRenderableIndexes10[1];
var renderedRows = [];
if (params.rows) {
params.rows.forEach(function (row) {
renderedRows.push(row);
apiRef.current.calculateColSpan({
rowId: row.id,
minFirstColumn: minFirstColumn,
maxLastColumn: maxLastColumn,
columns: visibleColumns
});
});
} else {
if (!currentPage.range) {
return null;
}
for (var i = firstRowToRender; i < lastRowToRender; i += 1) {
var row = currentPage.rows[i];
renderedRows.push(row);
apiRef.current.calculateColSpan({
rowId: row.id,
minFirstColumn: minFirstColumn,
maxLastColumn: maxLastColumn,
columns: visibleColumns
});
}
}
// If the selected row is not within the current range of rows being displayed,
// we need to render it at either the top or bottom of the rows,
// depending on whether it is above or below the range.
var isRowWithFocusedCellNotInRange = false;
if (indexOfRowWithFocusedCell > -1) {
var rowWithFocusedCell = currentPage.rows[indexOfRowWithFocusedCell];
if (firstRowToRender > indexOfRowWithFocusedCell || lastRowToRender < indexOfRowWithFocusedCell) {
isRowWithFocusedCellNotInRange = true;
if (indexOfRowWithFocusedCell > firstRowToRender) {
renderedRows.push(rowWithFocusedCell);
} else {
renderedRows.unshift(rowWithFocusedCell);
}
apiRef.current.calculateColSpan({
rowId: rowWithFocusedCell.id,
minFirstColumn: minFirstColumn,
maxLastColumn: maxLastColumn,
columns: visibleColumns
});
}
}
var _getRenderableIndexes11 = getRenderableIndexes({
firstIndex: nextRenderContext.firstColumnIndex,
lastIndex: nextRenderContext.lastColumnIndex,
minFirstIndex: minFirstColumn,
maxLastIndex: maxLastColumn,
buffer: columnBuffer
}),
_getRenderableIndexes12 = _slicedToArray(_getRenderableIndexes11, 2),
initialFirstColumnToRender = _getRenderableIndexes12[0],
lastColumnToRender = _getRenderableIndexes12[1];
var firstColumnToRender = getFirstNonSpannedColumnToRender({
firstColumnToRender: initialFirstColumnToRender,
apiRef: apiRef,
firstRowToRender: firstRowToRender,
lastRowToRender: lastRowToRender,
visibleRows: currentPage.rows
});
var isColumnWihFocusedCellNotInRange = false;
if (firstColumnToRender > indexOfColumnWithFocusedCell || lastColumnToRender < indexOfColumnWithFocusedCell) {
isColumnWihFocusedCellNotInRange = true;
}
var _getRenderedColumnsRe = getRenderedColumnsRef.current(visibleColumns, firstColumnToRender, lastColumnToRender, minFirstColumn, maxLastColumn, isColumnWihFocusedCellNotInRange ? indexOfColumnWithFocusedCell : -1),
focusedCellColumnIndexNotInRange = _getRenderedColumnsRe.focusedCellColumnIndexNotInRange,
renderedColumns = _getRenderedColumnsRe.renderedColumns;
var _ref4 = ((_rootProps$slotProps = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps.row) || {},
rootRowStyle = _ref4.style,
rootRowProps = _objectWithoutProperties(_ref4, _excluded);
var invalidatesCachedRowStyle = prevGetRowProps.current !== getRowProps || prevRootRowStyle.current !== rootRowStyle;
if (invalidatesCachedRowStyle) {
rowStyleCache.current = Object.create(null);
}
var rows = [];
var isRowWithFocusedCellRendered = false;
for (var _i = 0; _i < renderedRows.length; _i += 1) {
var _currentPage$range;
var _renderedRows$_i = renderedRows[_i],
_id = _renderedRows$_i.id,
_model = _renderedRows$_i.model;
var isRowNotVisible = isRowWithFocusedCellNotInRange && cellFocus.id === _id;
var lastVisibleRowIndex = isRowWithFocusedCellNotInRange ? firstRowToRender + _i === currentPage.rows.length : firstRowToRender + _i === currentPage.rows.length - 1;
var baseRowHeight = !apiRef.current.rowHasAutoHeight(_id) ? apiRef.current.unstable_getRowHeight(_id) : 'auto';
var isSelected = void 0;
if (selectedRowsLookup[_id] == null) {
isSelected = false;
} else {
isSelected = apiRef.current.isRowSelectable(_id);
}
if (onRowRender) {
onRowRender(_id);
}
var focusedCell = cellFocus !== null && cellFocus.id === _id ? cellFocus.field : null;
var columnWithFocusedCellNotInRange = focusedCellColumnIndexNotInRange !== undefined && visibleColumns[focusedCellColumnIndexNotInRange];
var renderedColumnsWithFocusedCell = columnWithFocusedCellNotInRange && focusedCell ? [columnWithFocusedCellNotInRange].concat(_toConsumableArray(renderedColumns)) : renderedColumns;
var tabbableCell = null;
if (cellTabIndex !== null && cellTabIndex.id === _id) {
var cellParams = apiRef.current.getCellParams(_id, cellTabIndex.field);
tabbableCell = cellParams.cellMode === 'view' ? cellTabIndex.field : null;
}
var _ref5 = typeof getRowProps === 'function' && getRowProps(_id, _model) || {},
rowStyle = _ref5.style,
rowProps = _objectWithoutProperties(_ref5, _excluded2);
if (!rowStyleCache.current[_id]) {
var style = _extends({}, rowStyle, rootRowStyle);
rowStyleCache.current[_id] = style;
}
var index = rowIndexOffset + ((currentPage == null || (_currentPage$range = currentPage.range) == null ? void 0 : _currentPage$range.firstRowIndex) || 0) + firstRowToRender + _i;
if (isRowWithFocusedCellNotInRange && (cellFocus == null ? void 0 : cellFocus.id) === _id) {
index = indexOfRowWithFocusedCell;
isRowWithFocusedCellRendered = true;
} else if (isRowWithFocusedCellRendered) {
index -= 1;
}
rows.push( /*#__PURE__*/_jsx(rootProps.slots.row, _extends({
row: _model,
rowId: _id,
focusedCellColumnIndexNotInRange: focusedCellColumnIndexNotInRange,
isNotVisible: isRowNotVisible,
rowHeight: baseRowHeight,
focusedCell: focusedCell,
tabbableCell: tabbableCell,
renderedColumns: renderedColumnsWithFocusedCell,
visibleColumns: visibleColumns,
firstColumnToRender: firstColumnToRender,
lastColumnToRender: lastColumnToRender,
selected: isSelected,
index: index,
containerWidth: availableSpace,
isLastVisible: lastVisibleRowIndex,
position: position
}, rowProps, rootRowProps, {
hovered: hoveredRowId === _id,
style: rowStyleCache.current[_id]
}), _id));
}
prevGetRowProps.current = getRowProps;
prevRootRowStyle.current = rootRowStyle;
return rows;
};
var needsHorizontalScrollbar = containerDimensions.width && columnsTotalWidth >= containerDimensions.width;
var contentSize = React.useMemo(function () {
// In cases where the columns exceed the available width,
// the horizontal scrollbar should be shown even when there're no rows.
// Keeping 1px as minimum height ensures that the scrollbar will visible if necessary.
var height = Math.max(rowsMeta.currentPageTotalHeight, 1);
var shouldExtendContent = false;
if (rootRef != null && rootRef.current && height <= (rootRef == null ? void 0 : rootRef.current.clientHeight)) {
shouldExtendContent = true;
}
var size = {
width: needsHorizontalScrollbar ? columnsTotalWidth : 'auto',
height: height,
minHeight: shouldExtendContent ? '100%' : 'auto'
};
if (rootProps.autoHeight && currentPage.rows.length === 0) {
size.height = getMinimalContentHeight(apiRef, rootProps.rowHeight); // Give room to show the overlay when there no rows.
}
return size;
}, [apiRef, rootRef, columnsTotalWidth, rowsMeta.currentPageTotalHeight, needsHorizontalScrollbar, rootProps.autoHeight, rootProps.rowHeight, currentPage.rows.length]);
React.useEffect(function () {
apiRef.current.publishEvent('virtualScrollerContentSizeChange');
}, [apiRef, contentSize]);
var rootStyle = React.useMemo(function () {
var style = {};
if (!needsHorizontalScrollbar) {
style.overflowX = 'hidden';
}
if (rootProps.autoHeight) {
style.overflowY = 'hidden';
}
return style;
}, [needsHorizontalScrollbar, rootProps.autoHeight]);
apiRef.current.register('private', {
getRenderContext: getRenderContext
});
return {
renderContext: renderContext,
updateRenderZonePosition: updateRenderZonePosition,
getRows: getRows,
getRootProps: function getRootProps() {
var inputProps = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
return _extends({
ref: handleRef,
onScroll: handleScroll,
onWheel: handleWheel,
onTouchMove: handleTouchMove
}, inputProps, {
style: inputProps.style ? _extends({}, inputProps.style, rootStyle) : rootStyle,
role: 'presentation'
});
},
getContentProps: function getContentProps() {
var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
style = _ref6.style;
return {
style: style ? _extends({}, style, contentSize) : contentSize,
role: 'presentation'
};
},
getRenderZoneProps: function getRenderZoneProps() {
return {
ref: renderZoneRef,
role: 'rowgroup'
};
}
};
};
function getNearestIndexToRender(apiRef, currentPage, rowsMeta, offset) {
var _currentPage$range2, _currentPage$range3;
var lastMeasuredIndexRelativeToAllRows = apiRef.current.getLastMeasuredRowIndex();
var allRowsMeasured = lastMeasuredIndexRelativeToAllRows === Infinity;
if ((_currentPage$range2 = currentPage.range) != null && _currentPage$range2.lastRowIndex && !allRowsMeasured) {
// Check if all rows in this page are already measured
allRowsMeasured = lastMeasuredIndexRelativeToAllRows >= currentPage.range.lastRowIndex;
}
var lastMeasuredIndexRelativeToCurrentPage = clamp(lastMeasuredIndexRelativeToAllRows - (((_currentPage$range3 = currentPage.range) == null ? void 0 : _currentPage$range3.firstRowIndex) || 0), 0, rowsMeta.positions.length);
if (allRowsMeasured || rowsMeta.positions[lastMeasuredIndexRelativeToCurrentPage] >= offset) {
// If all rows were measured (when no row has "auto" as height) or all rows before the offset
// were measured, then use a binary search because it's faster.
return binarySearch(offset, rowsMeta.positions);
}
// Otherwise, use an exponential search.
// If rows have "auto" as height, their positions will be based on estimated heights.
// In this case, we can skip several steps until we find a position higher than the offset.
// Inspired by https://github.com/bvaughn/react-virtualized/blob/master/source/Grid/utils/CellSizeAndPositionManager.js
return exponentialSearch(offset, rowsMeta.positions, lastMeasuredIndexRelativeToCurrentPage);
}

View File

@@ -0,0 +1,51 @@
import _extends from "@babel/runtime/helpers/esm/extends";
import * as React from 'react';
import { useGridApiMethod } from '../../utils/useGridApiMethod';
export var virtualizationStateInitializer = function virtualizationStateInitializer(state, props) {
var virtualization = {
enabled: !props.disableVirtualization,
enabledForColumns: true
};
return _extends({}, state, {
virtualization: virtualization
});
};
export function useGridVirtualization(apiRef, props) {
/*
* API METHODS
*/
var setVirtualization = function setVirtualization(enabled) {
apiRef.current.setState(function (state) {
return _extends({}, state, {
virtualization: _extends({}, state.virtualization, {
enabled: enabled
})
});
});
};
var setColumnVirtualization = function setColumnVirtualization(enabled) {
apiRef.current.setState(function (state) {
return _extends({}, state, {
virtualization: _extends({}, state.virtualization, {
enabledForColumns: enabled
})
});
});
};
var api = {
unstable_setVirtualization: setVirtualization,
unstable_setColumnVirtualization: setColumnVirtualization
};
useGridApiMethod(apiRef, api, 'public');
/*
* EFFECTS
*/
/* eslint-disable react-hooks/exhaustive-deps */
React.useEffect(function () {
setVirtualization(!props.disableVirtualization);
}, [props.disableVirtualization]);
/* eslint-enable react-hooks/exhaustive-deps */
}