@mui/x-data-grid 8.8.0 → 8.9.2

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 (196) hide show
  1. package/CHANGELOG.md +225 -24
  2. package/DataGrid/DataGrid.js +5 -0
  3. package/DataGrid/index.d.ts +0 -1
  4. package/DataGrid/useDataGridComponent.js +10 -0
  5. package/colDef/gridCheckboxSelectionColDef.js +1 -0
  6. package/components/GridDetailPanels.d.ts +2 -2
  7. package/components/GridPinnedRows.d.ts +2 -2
  8. package/components/GridRow.js +5 -0
  9. package/components/GridScrollArea.js +1 -1
  10. package/components/cell/GridCell.js +7 -5
  11. package/components/cell/GridEditSingleSelectCell.js +1 -1
  12. package/components/columnsManagement/GridColumnsManagement.d.ts +6 -0
  13. package/components/columnsManagement/GridColumnsManagement.js +17 -5
  14. package/components/containers/GridRootStyles.d.ts +1 -1
  15. package/components/containers/GridRootStyles.js +39 -0
  16. package/components/toolbarV8/Toolbar.d.ts +1 -1
  17. package/components/virtualization/GridVirtualScroller.js +5 -5
  18. package/constants/dataGridPropsDefaultValues.js +1 -0
  19. package/constants/gridClasses.d.ts +12 -0
  20. package/constants/gridClasses.js +3 -1
  21. package/esm/DataGrid/DataGrid.js +5 -0
  22. package/esm/DataGrid/index.d.ts +0 -1
  23. package/esm/DataGrid/useDataGridComponent.js +10 -0
  24. package/esm/colDef/gridCheckboxSelectionColDef.js +1 -0
  25. package/esm/components/GridDetailPanels.d.ts +2 -2
  26. package/esm/components/GridPinnedRows.d.ts +2 -2
  27. package/esm/components/GridRow.js +5 -0
  28. package/esm/components/GridScrollArea.js +1 -1
  29. package/esm/components/cell/GridCell.js +7 -5
  30. package/esm/components/cell/GridEditSingleSelectCell.js +1 -1
  31. package/esm/components/columnsManagement/GridColumnsManagement.d.ts +6 -0
  32. package/esm/components/columnsManagement/GridColumnsManagement.js +17 -5
  33. package/esm/components/containers/GridRootStyles.d.ts +1 -1
  34. package/esm/components/containers/GridRootStyles.js +39 -0
  35. package/esm/components/toolbarV8/Toolbar.d.ts +1 -1
  36. package/esm/components/virtualization/GridVirtualScroller.js +5 -5
  37. package/esm/constants/dataGridPropsDefaultValues.js +1 -0
  38. package/esm/constants/gridClasses.d.ts +12 -0
  39. package/esm/constants/gridClasses.js +3 -1
  40. package/esm/hooks/core/pipeProcessing/gridPipeProcessingApi.d.ts +5 -0
  41. package/esm/hooks/core/pipeProcessing/useGridPipeProcessing.js +20 -5
  42. package/esm/hooks/core/useGridProps.d.ts +2 -2
  43. package/esm/hooks/core/useGridProps.js +3 -1
  44. package/esm/hooks/core/useGridVirtualizer.d.ts +9 -0
  45. package/esm/hooks/core/useGridVirtualizer.js +223 -0
  46. package/esm/hooks/features/columnGrouping/gridColumnGroupsInterfaces.d.ts +4 -1
  47. package/esm/hooks/features/columnGrouping/gridColumnGroupsUtils.js +35 -32
  48. package/esm/hooks/features/columnGrouping/useGridColumnGrouping.js +18 -13
  49. package/esm/hooks/features/columnHeaders/useGridColumnHeaders.d.ts +1 -1
  50. package/esm/hooks/features/columnHeaders/useGridColumnHeaders.js +3 -2
  51. package/esm/hooks/features/columns/gridColumnsInterfaces.d.ts +3 -3
  52. package/esm/hooks/features/columns/gridColumnsSelector.js +6 -2
  53. package/esm/hooks/features/columns/gridColumnsUtils.js +6 -4
  54. package/esm/hooks/features/columns/useGridColumnSpanning.js +5 -90
  55. package/esm/hooks/features/columns/useGridColumns.js +8 -10
  56. package/esm/hooks/features/dimensions/useGridDimensions.js +18 -188
  57. package/esm/hooks/features/export/utils.js +1 -1
  58. package/esm/hooks/features/filter/useGridFilter.js +3 -3
  59. package/esm/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
  60. package/esm/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +6 -10
  61. package/esm/hooks/features/keyboardNavigation/utils.d.ts +3 -3
  62. package/esm/hooks/features/keyboardNavigation/utils.js +5 -5
  63. package/esm/hooks/features/listView/gridListViewSelectors.d.ts +8 -1
  64. package/esm/hooks/features/listView/gridListViewSelectors.js +7 -0
  65. package/esm/hooks/features/pivoting/gridPivotingInterfaces.d.ts +0 -1
  66. package/esm/hooks/features/pivoting/gridPivotingSelectors.d.ts +1 -4
  67. package/esm/hooks/features/pivoting/gridPivotingSelectors.js +1 -2
  68. package/esm/hooks/features/rowSelection/useGridRowSelection.js +5 -4
  69. package/esm/hooks/features/rows/gridRowsMetaInterfaces.d.ts +2 -8
  70. package/esm/hooks/features/rows/gridRowsMetaState.d.ts +2 -18
  71. package/esm/hooks/features/rows/gridRowsUtils.d.ts +1 -1
  72. package/esm/hooks/features/rows/gridRowsUtils.js +5 -2
  73. package/esm/hooks/features/rows/useGridRowAriaAttributes.js +3 -1
  74. package/esm/hooks/features/rows/useGridRowSpanning.d.ts +2 -12
  75. package/esm/hooks/features/rows/useGridRowSpanning.js +54 -85
  76. package/esm/hooks/features/rows/useGridRows.js +4 -3
  77. package/esm/hooks/features/rows/useGridRowsMeta.d.ts +1 -1
  78. package/esm/hooks/features/rows/useGridRowsMeta.js +17 -187
  79. package/esm/hooks/features/scroll/useGridScroll.d.ts +1 -1
  80. package/esm/hooks/features/scroll/useGridScroll.js +2 -3
  81. package/esm/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +1 -1
  82. package/esm/hooks/features/virtualization/index.d.ts +1 -0
  83. package/esm/hooks/features/virtualization/index.js +1 -0
  84. package/esm/hooks/features/virtualization/useGridVirtualization.d.ts +5 -16
  85. package/esm/hooks/features/virtualization/useGridVirtualization.js +41 -22
  86. package/esm/hooks/utils/index.d.ts +2 -1
  87. package/esm/hooks/utils/index.js +2 -1
  88. package/esm/hooks/utils/useFirstRender.d.ts +1 -1
  89. package/esm/hooks/utils/useFirstRender.js +1 -8
  90. package/esm/hooks/utils/useGridInitializeState.d.ts +1 -1
  91. package/esm/hooks/utils/useGridInitializeState.js +6 -1
  92. package/esm/hooks/utils/useRunOncePerLoop.d.ts +1 -0
  93. package/esm/hooks/utils/useRunOncePerLoop.js +26 -0
  94. package/esm/index.js +1 -1
  95. package/esm/internals/index.d.ts +1 -1
  96. package/esm/internals/index.js +1 -1
  97. package/esm/internals/utils/getPinnedCellOffset.js +5 -0
  98. package/esm/locales/frFR.js +18 -21
  99. package/esm/locales/heIL.js +12 -12
  100. package/esm/locales/plPL.js +22 -24
  101. package/esm/models/api/gridApiCommon.d.ts +4 -1
  102. package/esm/models/api/gridColumnSpanning.d.ts +5 -11
  103. package/esm/models/api/gridRowApi.d.ts +5 -0
  104. package/esm/models/events/gridEventLookup.d.ts +2 -1
  105. package/esm/models/gridApiCaches.d.ts +8 -2
  106. package/esm/models/gridStateCommunity.d.ts +2 -2
  107. package/esm/models/props/DataGridProps.d.ts +5 -0
  108. package/esm/utils/roundToDecimalPlaces.d.ts +1 -1
  109. package/esm/utils/roundToDecimalPlaces.js +1 -3
  110. package/hooks/core/pipeProcessing/gridPipeProcessingApi.d.ts +5 -0
  111. package/hooks/core/pipeProcessing/useGridPipeProcessing.js +20 -5
  112. package/hooks/core/useGridProps.d.ts +2 -2
  113. package/hooks/core/useGridProps.js +3 -1
  114. package/hooks/core/useGridVirtualizer.d.ts +9 -0
  115. package/hooks/core/useGridVirtualizer.js +231 -0
  116. package/hooks/features/columnGrouping/gridColumnGroupsInterfaces.d.ts +4 -1
  117. package/hooks/features/columnGrouping/gridColumnGroupsUtils.js +35 -32
  118. package/hooks/features/columnGrouping/useGridColumnGrouping.js +18 -13
  119. package/hooks/features/columnHeaders/useGridColumnHeaders.d.ts +1 -1
  120. package/hooks/features/columnHeaders/useGridColumnHeaders.js +4 -3
  121. package/hooks/features/columns/gridColumnsInterfaces.d.ts +3 -3
  122. package/hooks/features/columns/gridColumnsSelector.js +6 -2
  123. package/hooks/features/columns/gridColumnsUtils.js +6 -4
  124. package/hooks/features/columns/useGridColumnSpanning.js +5 -91
  125. package/hooks/features/columns/useGridColumns.js +8 -10
  126. package/hooks/features/dimensions/useGridDimensions.js +18 -188
  127. package/hooks/features/export/utils.js +1 -1
  128. package/hooks/features/filter/useGridFilter.js +3 -3
  129. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.d.ts +1 -1
  130. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +6 -10
  131. package/hooks/features/keyboardNavigation/utils.d.ts +3 -3
  132. package/hooks/features/keyboardNavigation/utils.js +5 -5
  133. package/hooks/features/listView/gridListViewSelectors.d.ts +8 -1
  134. package/hooks/features/listView/gridListViewSelectors.js +8 -1
  135. package/hooks/features/pivoting/gridPivotingInterfaces.d.ts +0 -1
  136. package/hooks/features/pivoting/gridPivotingSelectors.d.ts +1 -4
  137. package/hooks/features/pivoting/gridPivotingSelectors.js +2 -3
  138. package/hooks/features/rowSelection/useGridRowSelection.js +5 -4
  139. package/hooks/features/rows/gridRowsMetaInterfaces.d.ts +2 -8
  140. package/hooks/features/rows/gridRowsMetaState.d.ts +2 -18
  141. package/hooks/features/rows/gridRowsUtils.d.ts +1 -1
  142. package/hooks/features/rows/gridRowsUtils.js +5 -2
  143. package/hooks/features/rows/useGridRowAriaAttributes.js +3 -1
  144. package/hooks/features/rows/useGridRowSpanning.d.ts +2 -12
  145. package/hooks/features/rows/useGridRowSpanning.js +54 -85
  146. package/hooks/features/rows/useGridRows.js +4 -3
  147. package/hooks/features/rows/useGridRowsMeta.d.ts +1 -1
  148. package/hooks/features/rows/useGridRowsMeta.js +15 -186
  149. package/hooks/features/scroll/useGridScroll.d.ts +1 -1
  150. package/hooks/features/scroll/useGridScroll.js +2 -3
  151. package/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +1 -1
  152. package/hooks/features/virtualization/index.d.ts +1 -0
  153. package/hooks/features/virtualization/index.js +12 -0
  154. package/hooks/features/virtualization/useGridVirtualization.d.ts +5 -16
  155. package/hooks/features/virtualization/useGridVirtualization.js +42 -24
  156. package/hooks/utils/index.d.ts +2 -1
  157. package/hooks/utils/index.js +16 -4
  158. package/hooks/utils/useFirstRender.d.ts +1 -1
  159. package/hooks/utils/useFirstRender.js +11 -11
  160. package/hooks/utils/useGridInitializeState.d.ts +1 -1
  161. package/hooks/utils/useGridInitializeState.js +6 -1
  162. package/hooks/utils/useRunOncePerLoop.d.ts +1 -0
  163. package/hooks/utils/useRunOncePerLoop.js +33 -0
  164. package/index.js +1 -1
  165. package/internals/index.d.ts +1 -1
  166. package/internals/index.js +4 -11
  167. package/internals/utils/getPinnedCellOffset.js +5 -0
  168. package/locales/frFR.js +18 -21
  169. package/locales/heIL.js +12 -12
  170. package/locales/plPL.js +22 -24
  171. package/models/api/gridApiCommon.d.ts +4 -1
  172. package/models/api/gridColumnSpanning.d.ts +5 -11
  173. package/models/api/gridRowApi.d.ts +5 -0
  174. package/models/events/gridEventLookup.d.ts +2 -1
  175. package/models/gridApiCaches.d.ts +8 -2
  176. package/models/gridStateCommunity.d.ts +2 -2
  177. package/models/props/DataGridProps.d.ts +5 -0
  178. package/package.json +5 -5
  179. package/utils/roundToDecimalPlaces.d.ts +1 -1
  180. package/utils/roundToDecimalPlaces.js +7 -4
  181. package/esm/hooks/features/rows/gridRowSpanningSelectors.d.ts +0 -10
  182. package/esm/hooks/features/rows/gridRowSpanningSelectors.js +0 -5
  183. package/esm/hooks/features/virtualization/useGridVirtualScroller.d.ts +0 -56
  184. package/esm/hooks/features/virtualization/useGridVirtualScroller.js +0 -846
  185. package/esm/hooks/utils/useRunOnce.d.ts +0 -5
  186. package/esm/hooks/utils/useRunOnce.js +0 -18
  187. package/esm/utils/platform.d.ts +0 -1
  188. package/esm/utils/platform.js +0 -2
  189. package/hooks/features/rows/gridRowSpanningSelectors.d.ts +0 -10
  190. package/hooks/features/rows/gridRowSpanningSelectors.js +0 -11
  191. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +0 -56
  192. package/hooks/features/virtualization/useGridVirtualScroller.js +0 -857
  193. package/hooks/utils/useRunOnce.d.ts +0 -5
  194. package/hooks/utils/useRunOnce.js +0 -27
  195. package/utils/platform.d.ts +0 -1
  196. package/utils/platform.js +0 -8
@@ -1,857 +0,0 @@
1
- "use strict";
2
- 'use client';
3
-
4
- var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
- var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
6
- Object.defineProperty(exports, "__esModule", {
7
- value: true
8
- });
9
- exports.EMPTY_DETAIL_PANELS = void 0;
10
- exports.areRenderContextsEqual = areRenderContextsEqual;
11
- exports.computeOffsetLeft = computeOffsetLeft;
12
- exports.useGridVirtualScroller = void 0;
13
- var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends"));
14
- var React = _interopRequireWildcard(require("react"));
15
- var ReactDOM = _interopRequireWildcard(require("react-dom"));
16
- var _useEventCallback = _interopRequireDefault(require("@mui/utils/useEventCallback"));
17
- var _useEnhancedEffect = _interopRequireDefault(require("@mui/utils/useEnhancedEffect"));
18
- var _useLazyRef = _interopRequireDefault(require("@mui/utils/useLazyRef"));
19
- var _useTimeout = _interopRequireDefault(require("@mui/utils/useTimeout"));
20
- var _RtlProvider = require("@mui/system/RtlProvider");
21
- var _reactMajor = _interopRequireDefault(require("@mui/x-internals/reactMajor"));
22
- var _gridDimensionsSelectors = require("../dimensions/gridDimensionsSelectors");
23
- var _useGridPrivateApiContext = require("../../utils/useGridPrivateApiContext");
24
- var _useGridRootProps = require("../../utils/useGridRootProps");
25
- var _useGridSelector = require("../../utils/useGridSelector");
26
- var _useRunOnce = require("../../utils/useRunOnce");
27
- var _gridColumnsSelector = require("../columns/gridColumnsSelector");
28
- var _gridRowsSelector = require("../rows/gridRowsSelector");
29
- var _useGridVisibleRows = require("../../utils/useGridVisibleRows");
30
- var _utils = require("../../utils");
31
- var platform = _interopRequireWildcard(require("../../../utils/platform"));
32
- var _utils2 = require("../../../utils/utils");
33
- var _gridRowsMetaSelector = require("../rows/gridRowsMetaSelector");
34
- var _gridColumnsUtils = require("../columns/gridColumnsUtils");
35
- var _gridVirtualizationSelectors = require("./gridVirtualizationSelectors");
36
- var _useGridVirtualization = require("./useGridVirtualization");
37
- var _gridRowSpanningSelectors = require("../rows/gridRowSpanningSelectors");
38
- var _gridListViewSelectors = require("../listView/gridListViewSelectors");
39
- var _gridRowsUtils = require("../rows/gridRowsUtils");
40
- var _columns = require("../columns");
41
- var _gridFocusedVirtualCellSelector = require("./gridFocusedVirtualCellSelector");
42
- var _roundToDecimalPlaces = require("../../../utils/roundToDecimalPlaces");
43
- var _isJSDOM = require("../../../utils/isJSDOM");
44
- var _rowSelection = require("../rowSelection");
45
- var _jsxRuntime = require("react/jsx-runtime");
46
- const MINIMUM_COLUMN_WIDTH = 50;
47
- var ScrollDirection = /*#__PURE__*/function (ScrollDirection) {
48
- ScrollDirection[ScrollDirection["NONE"] = 0] = "NONE";
49
- ScrollDirection[ScrollDirection["UP"] = 1] = "UP";
50
- ScrollDirection[ScrollDirection["DOWN"] = 2] = "DOWN";
51
- ScrollDirection[ScrollDirection["LEFT"] = 3] = "LEFT";
52
- ScrollDirection[ScrollDirection["RIGHT"] = 4] = "RIGHT";
53
- return ScrollDirection;
54
- }(ScrollDirection || {});
55
- const EMPTY_SCROLL_POSITION = {
56
- top: 0,
57
- left: 0
58
- };
59
- const EMPTY_DETAIL_PANELS = exports.EMPTY_DETAIL_PANELS = Object.freeze(new Map());
60
- const createScrollCache = (isRtl, rowBufferPx, columnBufferPx, verticalBuffer, horizontalBuffer) => ({
61
- direction: ScrollDirection.NONE,
62
- buffer: bufferForDirection(isRtl, ScrollDirection.NONE, rowBufferPx, columnBufferPx, verticalBuffer, horizontalBuffer)
63
- });
64
- const useGridVirtualScroller = () => {
65
- const apiRef = (0, _useGridPrivateApiContext.useGridPrivateApiContext)();
66
- const rootProps = (0, _useGridRootProps.useGridRootProps)();
67
- const {
68
- listView
69
- } = rootProps;
70
- const visibleColumns = (0, _useGridSelector.useGridSelector)(apiRef, () => listView ? [(0, _gridListViewSelectors.gridListColumnSelector)(apiRef)] : (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef));
71
- const enabledForRows = (0, _useGridSelector.useGridSelector)(apiRef, _gridVirtualizationSelectors.gridVirtualizationRowEnabledSelector) && !_isJSDOM.isJSDOM;
72
- const enabledForColumns = (0, _useGridSelector.useGridSelector)(apiRef, _gridVirtualizationSelectors.gridVirtualizationColumnEnabledSelector) && !_isJSDOM.isJSDOM;
73
- const pinnedRows = (0, _useGridSelector.useGridSelector)(apiRef, _gridRowsSelector.gridPinnedRowsSelector);
74
- const pinnedColumnDefinitions = (0, _gridColumnsSelector.gridVisiblePinnedColumnDefinitionsSelector)(apiRef);
75
- const pinnedColumns = listView ? _columns.EMPTY_PINNED_COLUMN_FIELDS : pinnedColumnDefinitions;
76
- const hasBottomPinnedRows = pinnedRows.bottom.length > 0;
77
- const [panels, setPanels] = React.useState(EMPTY_DETAIL_PANELS);
78
- const isRtl = (0, _RtlProvider.useRtl)();
79
- const rowSelectionManager = (0, _useGridSelector.useGridSelector)(apiRef, _rowSelection.gridRowSelectionManagerSelector);
80
- const currentPage = (0, _useGridVisibleRows.useGridVisibleRows)(apiRef);
81
- const mainRef = apiRef.current.mainElementRef;
82
- const scrollerRef = apiRef.current.virtualScrollerRef;
83
- const scrollbarVerticalRef = apiRef.current.virtualScrollbarVerticalRef;
84
- const scrollbarHorizontalRef = apiRef.current.virtualScrollbarHorizontalRef;
85
- const hasColSpan = (0, _useGridSelector.useGridSelector)(apiRef, _gridColumnsSelector.gridHasColSpanSelector);
86
- const isRenderContextReady = React.useRef(false);
87
- const rowHeight = (0, _useGridSelector.useGridSelector)(apiRef, _gridDimensionsSelectors.gridRowHeightSelector);
88
- const contentHeight = (0, _useGridSelector.useGridSelector)(apiRef, _gridDimensionsSelectors.gridContentHeightSelector);
89
- const columnsTotalWidth = (0, _useGridSelector.useGridSelector)(apiRef, _gridDimensionsSelectors.gridColumnsTotalWidthSelector);
90
- const needsHorizontalScrollbar = (0, _useGridSelector.useGridSelector)(apiRef, needsHorizontalScrollbarSelector);
91
- const verticalScrollbarWidth = (0, _useGridSelector.useGridSelector)(apiRef, _gridDimensionsSelectors.gridVerticalScrollbarWidthSelector);
92
- const gridHasFiller = (0, _useGridSelector.useGridSelector)(apiRef, _gridDimensionsSelectors.gridHasFillerSelector);
93
- const previousSize = React.useRef(null);
94
- const mainRefCallback = React.useCallback(node => {
95
- mainRef.current = node;
96
- if (!node) {
97
- return undefined;
98
- }
99
- const initialRect = node.getBoundingClientRect();
100
- let lastSize = {
101
- width: (0, _roundToDecimalPlaces.roundToDecimalPlaces)(initialRect.width, 1),
102
- height: (0, _roundToDecimalPlaces.roundToDecimalPlaces)(initialRect.height, 1)
103
- };
104
- if (!previousSize.current || lastSize.width !== previousSize.current.width && lastSize.height !== previousSize.current.height) {
105
- previousSize.current = lastSize;
106
- apiRef.current.publishEvent('resize', lastSize);
107
- }
108
- if (typeof ResizeObserver === 'undefined') {
109
- return undefined;
110
- }
111
- const observer = new ResizeObserver(entries => {
112
- const entry = entries[0];
113
- if (!entry) {
114
- return;
115
- }
116
- const newSize = {
117
- width: (0, _roundToDecimalPlaces.roundToDecimalPlaces)(entry.contentRect.width, 1),
118
- height: (0, _roundToDecimalPlaces.roundToDecimalPlaces)(entry.contentRect.height, 1)
119
- };
120
- if (newSize.width === lastSize.width && newSize.height === lastSize.height) {
121
- return;
122
- }
123
- apiRef.current.publishEvent('resize', newSize);
124
- lastSize = newSize;
125
- });
126
- observer.observe(node);
127
- if (_reactMajor.default >= 19) {
128
- return () => {
129
- mainRef.current = null;
130
- observer.disconnect();
131
- };
132
- }
133
- return undefined;
134
- }, [apiRef, mainRef]);
135
-
136
- /*
137
- * Scroll context logic
138
- * ====================
139
- * We only render the cells contained in the `renderContext`. However, when the user starts scrolling the grid
140
- * in a direction, we want to render as many cells as possible in that direction, as to avoid presenting white
141
- * areas if the user scrolls too fast/far and the viewport ends up in a region we haven't rendered yet. To render
142
- * more cells, we store some offsets to add to the viewport in `scrollCache.buffer`. Those offsets make the render
143
- * context wider in the direction the user is going, but also makes the buffer around the viewport `0` for the
144
- * dimension (horizontal or vertical) in which the user is not scrolling. So if the normal viewport is 8 columns
145
- * wide, with a 1 column buffer (10 columns total), then we want it to be exactly 8 columns wide during vertical
146
- * scroll.
147
- * However, we don't want the rows in the old context to re-render from e.g. 10 columns to 8 columns, because that's
148
- * work that's not necessary. Thus we store the context at the start of the scroll in `frozenContext`, and the rows
149
- * that are part of this old context will keep their same render context as to avoid re-rendering.
150
- */
151
- const scrollPosition = React.useRef(rootProps.initialState?.scroll ?? EMPTY_SCROLL_POSITION);
152
- const ignoreNextScrollEvent = React.useRef(false);
153
- const previousContextScrollPosition = React.useRef(EMPTY_SCROLL_POSITION);
154
- const previousRowContext = React.useRef(_useGridVirtualization.EMPTY_RENDER_CONTEXT);
155
- const renderContext = (0, _useGridSelector.useGridSelector)(apiRef, _gridVirtualizationSelectors.gridRenderContextSelector);
156
- const focusedVirtualCell = (0, _useGridSelector.useGridSelector)(apiRef, _gridFocusedVirtualCellSelector.gridFocusedVirtualCellSelector);
157
- const scrollTimeout = (0, _useTimeout.default)();
158
- const frozenContext = React.useRef(undefined);
159
- const scrollCache = (0, _useLazyRef.default)(() => createScrollCache(isRtl, rootProps.rowBufferPx, rootProps.columnBufferPx, rowHeight * 15, MINIMUM_COLUMN_WIDTH * 6)).current;
160
- const updateRenderContext = React.useCallback(nextRenderContext => {
161
- if (areRenderContextsEqual(nextRenderContext, apiRef.current.state.virtualization.renderContext)) {
162
- return;
163
- }
164
- const didRowsIntervalChange = nextRenderContext.firstRowIndex !== previousRowContext.current.firstRowIndex || nextRenderContext.lastRowIndex !== previousRowContext.current.lastRowIndex;
165
- apiRef.current.setState(state => {
166
- return (0, _extends2.default)({}, state, {
167
- virtualization: (0, _extends2.default)({}, state.virtualization, {
168
- renderContext: nextRenderContext
169
- })
170
- });
171
- });
172
-
173
- // The lazy-loading hook is listening to `renderedRowsIntervalChange`,
174
- // but only does something if we already have a render context, because
175
- // otherwise we would call an update directly on mount
176
- const isReady = (0, _gridDimensionsSelectors.gridDimensionsSelector)(apiRef).isReady;
177
- if (isReady && didRowsIntervalChange) {
178
- previousRowContext.current = nextRenderContext;
179
- apiRef.current.publishEvent('renderedRowsIntervalChange', nextRenderContext);
180
- }
181
- previousContextScrollPosition.current = scrollPosition.current;
182
- }, [apiRef]);
183
- const triggerUpdateRenderContext = (0, _useEventCallback.default)(() => {
184
- const scroller = scrollerRef.current;
185
- if (!scroller) {
186
- return undefined;
187
- }
188
- const dimensions = (0, _gridDimensionsSelectors.gridDimensionsSelector)(apiRef);
189
- const maxScrollTop = Math.ceil(dimensions.minimumSize.height - dimensions.viewportOuterSize.height);
190
- const maxScrollLeft = Math.ceil(dimensions.minimumSize.width - dimensions.viewportInnerSize.width);
191
-
192
- // Clamp the scroll position to the viewport to avoid re-calculating the render context for scroll bounce
193
- const newScroll = {
194
- top: (0, _utils2.clamp)(scroller.scrollTop, 0, maxScrollTop),
195
- left: isRtl ? (0, _utils2.clamp)(scroller.scrollLeft, -maxScrollLeft, 0) : (0, _utils2.clamp)(scroller.scrollLeft, 0, maxScrollLeft)
196
- };
197
- const dx = newScroll.left - scrollPosition.current.left;
198
- const dy = newScroll.top - scrollPosition.current.top;
199
- const isScrolling = dx !== 0 || dy !== 0;
200
- scrollPosition.current = newScroll;
201
- const direction = isScrolling ? directionForDelta(dx, dy) : ScrollDirection.NONE;
202
-
203
- // Since previous render, we have scrolled...
204
- const rowScroll = Math.abs(scrollPosition.current.top - previousContextScrollPosition.current.top);
205
- const columnScroll = Math.abs(scrollPosition.current.left - previousContextScrollPosition.current.left);
206
-
207
- // PERF: use the computed minimum column width instead of a static one
208
- const didCrossThreshold = rowScroll >= rowHeight || columnScroll >= MINIMUM_COLUMN_WIDTH;
209
- const didChangeDirection = scrollCache.direction !== direction;
210
- const shouldUpdate = didCrossThreshold || didChangeDirection;
211
- if (!shouldUpdate) {
212
- return renderContext;
213
- }
214
-
215
- // Render a new context
216
-
217
- if (didChangeDirection) {
218
- switch (direction) {
219
- case ScrollDirection.NONE:
220
- case ScrollDirection.LEFT:
221
- case ScrollDirection.RIGHT:
222
- frozenContext.current = undefined;
223
- break;
224
- default:
225
- frozenContext.current = renderContext;
226
- break;
227
- }
228
- }
229
- scrollCache.direction = direction;
230
- scrollCache.buffer = bufferForDirection(isRtl, direction, rootProps.rowBufferPx, rootProps.columnBufferPx, rowHeight * 15, MINIMUM_COLUMN_WIDTH * 6);
231
- const inputs = inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns);
232
- const nextRenderContext = computeRenderContext(inputs, scrollPosition.current, scrollCache);
233
- if (!areRenderContextsEqual(nextRenderContext, renderContext)) {
234
- // Prevents batching render context changes
235
- ReactDOM.flushSync(() => {
236
- updateRenderContext(nextRenderContext);
237
- });
238
- scrollTimeout.start(1000, triggerUpdateRenderContext);
239
- }
240
- return nextRenderContext;
241
- });
242
- const forceUpdateRenderContext = () => {
243
- // skip update if dimensions are not ready and virtualization is enabled
244
- if (!(0, _gridDimensionsSelectors.gridDimensionsSelector)(apiRef).isReady && (enabledForRows || enabledForColumns)) {
245
- return;
246
- }
247
- const inputs = inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns);
248
- const nextRenderContext = computeRenderContext(inputs, scrollPosition.current, scrollCache);
249
- // Reset the frozen context when the render context changes, see the illustration in https://github.com/mui/mui-x/pull/12353
250
- frozenContext.current = undefined;
251
- updateRenderContext(nextRenderContext);
252
- };
253
- const handleScroll = (0, _useEventCallback.default)(() => {
254
- if (ignoreNextScrollEvent.current) {
255
- ignoreNextScrollEvent.current = false;
256
- return;
257
- }
258
- const nextRenderContext = triggerUpdateRenderContext();
259
- apiRef.current.publishEvent('scrollPositionChange', {
260
- top: scrollPosition.current.top,
261
- left: scrollPosition.current.left,
262
- renderContext: nextRenderContext
263
- });
264
- });
265
- const handleWheel = (0, _useEventCallback.default)(event => {
266
- apiRef.current.publishEvent('virtualScrollerWheel', {}, event);
267
- });
268
- const handleTouchMove = (0, _useEventCallback.default)(event => {
269
- apiRef.current.publishEvent('virtualScrollerTouchMove', {}, event);
270
- });
271
- const getRows = (params = {}) => {
272
- if (!params.rows && !currentPage.range) {
273
- return [];
274
- }
275
- const rowTree = (0, _gridRowsSelector.gridRowTreeSelector)(apiRef);
276
- let baseRenderContext = renderContext;
277
- if (params.renderContext) {
278
- baseRenderContext = params.renderContext;
279
- baseRenderContext.firstColumnIndex = renderContext.firstColumnIndex;
280
- baseRenderContext.lastColumnIndex = renderContext.lastColumnIndex;
281
- }
282
- const isLastSection = !hasBottomPinnedRows && params.position === undefined || hasBottomPinnedRows && params.position === 'bottom';
283
- const isPinnedSection = params.position !== undefined;
284
- let rowIndexOffset;
285
- // FIXME: Why is the switch check exhaustiveness not validated with typescript-eslint?
286
- // eslint-disable-next-line default-case
287
- switch (params.position) {
288
- case 'top':
289
- rowIndexOffset = 0;
290
- break;
291
- case 'bottom':
292
- rowIndexOffset = pinnedRows.top.length + currentPage.rows.length;
293
- break;
294
- case undefined:
295
- rowIndexOffset = pinnedRows.top.length;
296
- break;
297
- }
298
- const rowModels = params.rows ?? currentPage.rows;
299
- const firstRowToRender = baseRenderContext.firstRowIndex;
300
- const lastRowToRender = Math.min(baseRenderContext.lastRowIndex, rowModels.length);
301
- const rowIndexes = params.rows ? (0, _utils2.range)(0, params.rows.length) : (0, _utils2.range)(firstRowToRender, lastRowToRender);
302
- let virtualRowIndex = -1;
303
- if (!isPinnedSection && focusedVirtualCell) {
304
- if (focusedVirtualCell.rowIndex < firstRowToRender) {
305
- rowIndexes.unshift(focusedVirtualCell.rowIndex);
306
- virtualRowIndex = focusedVirtualCell.rowIndex;
307
- }
308
- if (focusedVirtualCell.rowIndex > lastRowToRender) {
309
- rowIndexes.push(focusedVirtualCell.rowIndex);
310
- virtualRowIndex = focusedVirtualCell.rowIndex;
311
- }
312
- }
313
- const rows = [];
314
- const rowProps = rootProps.slotProps?.row;
315
- const columnPositions = (0, _gridColumnsSelector.gridColumnPositionsSelector)(apiRef);
316
- rowIndexes.forEach(rowIndexInPage => {
317
- const {
318
- id,
319
- model
320
- } = rowModels[rowIndexInPage];
321
-
322
- // In certain cases, the state might already be updated and `currentPage.rows` (which sets `rowModels`)
323
- // contains stale data.
324
- // In that case, skip any further row processing.
325
- // See:
326
- // - https://github.com/mui/mui-x/issues/16638
327
- // - https://github.com/mui/mui-x/issues/17022
328
- if (!rowTree[id]) {
329
- return;
330
- }
331
- const rowIndex = (currentPage?.range?.firstRowIndex || 0) + rowIndexOffset + rowIndexInPage;
332
-
333
- // NOTE: This is an expensive feature, the colSpan code could be optimized.
334
- if (hasColSpan) {
335
- const minFirstColumn = pinnedColumns.left.length;
336
- const maxLastColumn = visibleColumns.length - pinnedColumns.right.length;
337
- apiRef.current.calculateColSpan({
338
- rowId: id,
339
- minFirstColumn,
340
- maxLastColumn,
341
- columns: visibleColumns
342
- });
343
- if (pinnedColumns.left.length > 0) {
344
- apiRef.current.calculateColSpan({
345
- rowId: id,
346
- minFirstColumn: 0,
347
- maxLastColumn: pinnedColumns.left.length,
348
- columns: visibleColumns
349
- });
350
- }
351
- if (pinnedColumns.right.length > 0) {
352
- apiRef.current.calculateColSpan({
353
- rowId: id,
354
- minFirstColumn: visibleColumns.length - pinnedColumns.right.length,
355
- maxLastColumn: visibleColumns.length,
356
- columns: visibleColumns
357
- });
358
- }
359
- }
360
- const baseRowHeight = !apiRef.current.rowHasAutoHeight(id) ? apiRef.current.unstable_getRowHeight(id) : 'auto';
361
- const isSelected = rowSelectionManager.has(id) && apiRef.current.isRowSelectable(id);
362
- let isFirstVisible = false;
363
- if (params.position === undefined) {
364
- isFirstVisible = rowIndexInPage === 0;
365
- }
366
- let isLastVisible = false;
367
- const isLastVisibleInSection = rowIndexInPage === rowModels.length - 1;
368
- if (isLastSection) {
369
- if (!isPinnedSection) {
370
- const lastIndex = currentPage.rows.length - 1;
371
- const isLastVisibleRowIndex = rowIndexInPage === lastIndex;
372
- if (isLastVisibleRowIndex) {
373
- isLastVisible = true;
374
- }
375
- } else {
376
- isLastVisible = isLastVisibleInSection;
377
- }
378
- }
379
- let currentRenderContext = baseRenderContext;
380
- if (frozenContext.current && rowIndexInPage >= frozenContext.current.firstRowIndex && rowIndexInPage < frozenContext.current.lastRowIndex) {
381
- currentRenderContext = frozenContext.current;
382
- }
383
- const isVirtualFocusRow = rowIndexInPage === virtualRowIndex;
384
- const isVirtualFocusColumn = focusedVirtualCell?.rowIndex === rowIndex;
385
- const offsetLeft = computeOffsetLeft(columnPositions, currentRenderContext, pinnedColumns.left.length);
386
- const showBottomBorder = isLastVisibleInSection && params.position === 'top';
387
- const firstColumnIndex = currentRenderContext.firstColumnIndex;
388
- const lastColumnIndex = currentRenderContext.lastColumnIndex;
389
- rows.push(/*#__PURE__*/(0, _jsxRuntime.jsx)(rootProps.slots.row, (0, _extends2.default)({
390
- row: model,
391
- rowId: id,
392
- index: rowIndex,
393
- selected: isSelected,
394
- offsetLeft: offsetLeft,
395
- columnsTotalWidth: columnsTotalWidth,
396
- rowHeight: baseRowHeight,
397
- pinnedColumns: pinnedColumns,
398
- visibleColumns: visibleColumns,
399
- firstColumnIndex: firstColumnIndex,
400
- lastColumnIndex: lastColumnIndex,
401
- focusedColumnIndex: isVirtualFocusColumn ? focusedVirtualCell.columnIndex : undefined,
402
- isFirstVisible: isFirstVisible,
403
- isLastVisible: isLastVisible,
404
- isNotVisible: isVirtualFocusRow,
405
- showBottomBorder: showBottomBorder,
406
- scrollbarWidth: verticalScrollbarWidth,
407
- gridHasFiller: gridHasFiller
408
- }, rowProps), id));
409
- if (isVirtualFocusRow) {
410
- return;
411
- }
412
- const panel = panels.get(id);
413
- if (panel) {
414
- rows.push(panel);
415
- }
416
- if (params.position === undefined && isLastVisibleInSection) {
417
- rows.push(apiRef.current.getInfiniteLoadingTriggerElement?.({
418
- lastRowId: id
419
- }));
420
- }
421
- });
422
- return rows;
423
- };
424
- const scrollerStyle = React.useMemo(() => ({
425
- overflowX: !needsHorizontalScrollbar || listView ? 'hidden' : undefined,
426
- overflowY: rootProps.autoHeight ? 'hidden' : undefined
427
- }), [needsHorizontalScrollbar, rootProps.autoHeight, listView]);
428
- const contentSize = React.useMemo(() => {
429
- const size = {
430
- width: needsHorizontalScrollbar ? columnsTotalWidth : 'auto',
431
- flexBasis: contentHeight,
432
- flexShrink: 0
433
- };
434
- if (size.flexBasis === 0) {
435
- size.flexBasis = _gridRowsUtils.minimalContentHeight; // Give room to show the overlay when there no rows.
436
- }
437
- return size;
438
- }, [columnsTotalWidth, contentHeight, needsHorizontalScrollbar]);
439
- const onContentSizeApplied = React.useCallback(node => {
440
- if (!node) {
441
- return;
442
- }
443
- apiRef.current.publishEvent('virtualScrollerContentSizeChange', {
444
- columnsTotalWidth,
445
- contentHeight
446
- });
447
- }, [apiRef, columnsTotalWidth, contentHeight]);
448
- (0, _useEnhancedEffect.default)(() => {
449
- if (!isRenderContextReady.current) {
450
- return;
451
- }
452
- apiRef.current.updateRenderContext?.();
453
- }, [apiRef, enabledForColumns, enabledForRows]);
454
- (0, _useEnhancedEffect.default)(() => {
455
- if (listView) {
456
- scrollerRef.current.scrollLeft = 0;
457
- }
458
- }, [listView, scrollerRef]);
459
- (0, _useRunOnce.useRunOnce)(renderContext !== _useGridVirtualization.EMPTY_RENDER_CONTEXT, () => {
460
- apiRef.current.publishEvent('scrollPositionChange', {
461
- top: scrollPosition.current.top,
462
- left: scrollPosition.current.left,
463
- renderContext
464
- });
465
- isRenderContextReady.current = true;
466
- if (rootProps.initialState?.scroll && scrollerRef.current) {
467
- const scroller = scrollerRef.current;
468
- const {
469
- top,
470
- left
471
- } = rootProps.initialState.scroll;
472
-
473
- // On initial mount, if we have columns available, we can restore the horizontal scroll immediately, but we need to skip the resulting scroll event, otherwise we would recalculate the render context at position top=0, left=restoredValue, but the initial render context is already calculated based on the initial value of scrollPosition ref.
474
- const isScrollRestored = {
475
- top: !(top > 0),
476
- left: !(left > 0)
477
- };
478
- if (!isScrollRestored.left && columnsTotalWidth) {
479
- scroller.scrollLeft = left;
480
- ignoreNextScrollEvent.current = true;
481
- isScrollRestored.left = true;
482
- }
483
-
484
- // For the sake of completeness, but I'm not sure if contentHeight is ever available at this point. Maybe when virtualisation is disabled?
485
- if (!isScrollRestored.top && contentHeight) {
486
- scroller.scrollTop = top;
487
- ignoreNextScrollEvent.current = true;
488
- isScrollRestored.top = true;
489
- }
490
-
491
- // To restore the vertical scroll, we need to wait until the rows are available in the DOM (otherwise there's nowhere to scroll), but before paint to avoid reflows
492
- if (!isScrollRestored.top || !isScrollRestored.left) {
493
- const unsubscribeContentSizeChange = apiRef.current.subscribeEvent('virtualScrollerContentSizeChange', params => {
494
- if (!isScrollRestored.left && params.columnsTotalWidth) {
495
- scroller.scrollLeft = left;
496
- ignoreNextScrollEvent.current = true;
497
- isScrollRestored.left = true;
498
- }
499
- if (!isScrollRestored.top && params.contentHeight) {
500
- scroller.scrollTop = top;
501
- ignoreNextScrollEvent.current = true;
502
- isScrollRestored.top = true;
503
- }
504
- if (isScrollRestored.left && isScrollRestored.top) {
505
- unsubscribeContentSizeChange();
506
- }
507
- });
508
- return unsubscribeContentSizeChange;
509
- }
510
- }
511
- return undefined;
512
- });
513
- apiRef.current.register('private', {
514
- updateRenderContext: forceUpdateRenderContext
515
- });
516
- (0, _utils.useGridEventPriority)(apiRef, 'sortedRowsSet', forceUpdateRenderContext);
517
- (0, _utils.useGridEventPriority)(apiRef, 'paginationModelChange', forceUpdateRenderContext);
518
- (0, _utils.useGridEventPriority)(apiRef, 'columnsChange', forceUpdateRenderContext);
519
- return {
520
- renderContext,
521
- setPanels,
522
- getRows,
523
- getContainerProps: () => ({
524
- ref: mainRefCallback
525
- }),
526
- getScrollerProps: () => ({
527
- ref: scrollerRef,
528
- onScroll: handleScroll,
529
- onWheel: handleWheel,
530
- onTouchMove: handleTouchMove,
531
- style: scrollerStyle,
532
- role: 'presentation',
533
- // `tabIndex` shouldn't be used along role=presentation, but it fixes a Firefox bug
534
- // https://github.com/mui/mui-x/pull/13891#discussion_r1683416024
535
- tabIndex: platform.isFirefox ? -1 : undefined
536
- }),
537
- getContentProps: () => ({
538
- style: contentSize,
539
- role: 'presentation',
540
- ref: onContentSizeApplied
541
- }),
542
- getRenderZoneProps: () => ({
543
- role: 'rowgroup'
544
- }),
545
- getScrollbarVerticalProps: () => ({
546
- ref: scrollbarVerticalRef,
547
- scrollPosition
548
- }),
549
- getScrollbarHorizontalProps: () => ({
550
- ref: scrollbarHorizontalRef,
551
- scrollPosition
552
- }),
553
- getScrollAreaProps: () => ({
554
- scrollPosition
555
- })
556
- };
557
- };
558
- exports.useGridVirtualScroller = useGridVirtualScroller;
559
- // dimension selectors
560
- function needsHorizontalScrollbarSelector(apiRef) {
561
- return apiRef.current.state.dimensions.viewportOuterSize.width > 0 && apiRef.current.state.dimensions.columnsTotalWidth > apiRef.current.state.dimensions.viewportOuterSize.width;
562
- }
563
- function inputsSelector(apiRef, rootProps, enabledForRows, enabledForColumns) {
564
- const dimensions = (0, _gridDimensionsSelectors.gridDimensionsSelector)(apiRef);
565
- const currentPage = (0, _useGridVisibleRows.getVisibleRows)(apiRef, rootProps);
566
- const visibleColumns = rootProps.listView ? [(0, _gridListViewSelectors.gridListColumnSelector)(apiRef)] : (0, _gridColumnsSelector.gridVisibleColumnDefinitionsSelector)(apiRef);
567
- const hiddenCellsOriginMap = (0, _gridRowSpanningSelectors.gridRowSpanningHiddenCellsOriginMapSelector)(apiRef);
568
- const lastRowId = apiRef.current.state.rows.dataRowIds.at(-1);
569
- const lastColumn = visibleColumns.at(-1);
570
- return {
571
- enabledForRows,
572
- enabledForColumns,
573
- apiRef,
574
- autoHeight: rootProps.autoHeight,
575
- rowBufferPx: rootProps.rowBufferPx,
576
- columnBufferPx: rootProps.columnBufferPx,
577
- leftPinnedWidth: dimensions.leftPinnedWidth,
578
- columnsTotalWidth: dimensions.columnsTotalWidth,
579
- viewportInnerWidth: dimensions.viewportInnerSize.width,
580
- viewportInnerHeight: dimensions.viewportInnerSize.height,
581
- lastRowHeight: lastRowId !== undefined ? apiRef.current.unstable_getRowHeight(lastRowId) : 0,
582
- lastColumnWidth: lastColumn?.computedWidth ?? 0,
583
- rowsMeta: (0, _gridRowsMetaSelector.gridRowsMetaSelector)(apiRef),
584
- columnPositions: (0, _gridColumnsSelector.gridColumnPositionsSelector)(apiRef),
585
- rows: currentPage.rows,
586
- range: currentPage.range,
587
- pinnedColumns: (0, _gridColumnsSelector.gridVisiblePinnedColumnDefinitionsSelector)(apiRef),
588
- visibleColumns,
589
- hiddenCellsOriginMap,
590
- listView: rootProps.listView ?? false,
591
- virtualizeColumnsWithAutoRowHeight: rootProps.virtualizeColumnsWithAutoRowHeight
592
- };
593
- }
594
- function computeRenderContext(inputs, scrollPosition, scrollCache) {
595
- const renderContext = {
596
- firstRowIndex: 0,
597
- lastRowIndex: inputs.rows.length,
598
- firstColumnIndex: 0,
599
- lastColumnIndex: inputs.visibleColumns.length
600
- };
601
- const {
602
- top,
603
- left
604
- } = scrollPosition;
605
- const realLeft = Math.abs(left) + inputs.leftPinnedWidth;
606
- if (inputs.enabledForRows) {
607
- // Clamp the value because the search may return an index out of bounds.
608
- // In the last index, this is not needed because Array.slice doesn't include it.
609
- let firstRowIndex = Math.min(getNearestIndexToRender(inputs, top, {
610
- atStart: true,
611
- lastPosition: inputs.rowsMeta.positions[inputs.rowsMeta.positions.length - 1] + inputs.lastRowHeight
612
- }), inputs.rowsMeta.positions.length - 1);
613
-
614
- // If any of the cells in the `firstRowIndex` is hidden due to an extended row span,
615
- // Make sure the row from where the rowSpan is originated is visible.
616
- const rowSpanHiddenCellOrigin = inputs.hiddenCellsOriginMap[firstRowIndex];
617
- if (rowSpanHiddenCellOrigin) {
618
- const minSpannedRowIndex = Math.min(...Object.values(rowSpanHiddenCellOrigin));
619
- firstRowIndex = Math.min(firstRowIndex, minSpannedRowIndex);
620
- }
621
- const lastRowIndex = inputs.autoHeight ? firstRowIndex + inputs.rows.length : getNearestIndexToRender(inputs, top + inputs.viewportInnerHeight);
622
- renderContext.firstRowIndex = firstRowIndex;
623
- renderContext.lastRowIndex = lastRowIndex;
624
- }
625
- if (inputs.listView) {
626
- return (0, _extends2.default)({}, renderContext, {
627
- lastColumnIndex: 1
628
- });
629
- }
630
- if (inputs.enabledForColumns) {
631
- let firstColumnIndex = 0;
632
- let lastColumnIndex = inputs.columnPositions.length;
633
- let hasRowWithAutoHeight = false;
634
- const [firstRowToRender, lastRowToRender] = getIndexesToRender({
635
- firstIndex: renderContext.firstRowIndex,
636
- lastIndex: renderContext.lastRowIndex,
637
- minFirstIndex: 0,
638
- maxLastIndex: inputs.rows.length,
639
- bufferBefore: scrollCache.buffer.rowBefore,
640
- bufferAfter: scrollCache.buffer.rowAfter,
641
- positions: inputs.rowsMeta.positions,
642
- lastSize: inputs.lastRowHeight
643
- });
644
- if (!inputs.virtualizeColumnsWithAutoRowHeight) {
645
- for (let i = firstRowToRender; i < lastRowToRender && !hasRowWithAutoHeight; i += 1) {
646
- const row = inputs.rows[i];
647
- hasRowWithAutoHeight = inputs.apiRef.current.rowHasAutoHeight(row.id);
648
- }
649
- }
650
- if (!hasRowWithAutoHeight || inputs.virtualizeColumnsWithAutoRowHeight) {
651
- firstColumnIndex = binarySearch(realLeft, inputs.columnPositions, {
652
- atStart: true,
653
- lastPosition: inputs.columnsTotalWidth
654
- });
655
- lastColumnIndex = binarySearch(realLeft + inputs.viewportInnerWidth, inputs.columnPositions);
656
- }
657
- renderContext.firstColumnIndex = firstColumnIndex;
658
- renderContext.lastColumnIndex = lastColumnIndex;
659
- }
660
- const actualRenderContext = deriveRenderContext(inputs, renderContext, scrollCache);
661
- return actualRenderContext;
662
- }
663
- function getNearestIndexToRender(inputs, offset, options) {
664
- const lastMeasuredIndexRelativeToAllRows = inputs.apiRef.current.getLastMeasuredRowIndex();
665
- let allRowsMeasured = lastMeasuredIndexRelativeToAllRows === Infinity;
666
- if (inputs.range?.lastRowIndex && !allRowsMeasured) {
667
- // Check if all rows in this page are already measured
668
- allRowsMeasured = lastMeasuredIndexRelativeToAllRows >= inputs.range.lastRowIndex;
669
- }
670
- const lastMeasuredIndexRelativeToCurrentPage = (0, _utils2.clamp)(lastMeasuredIndexRelativeToAllRows - (inputs.range?.firstRowIndex || 0), 0, inputs.rowsMeta.positions.length);
671
- if (allRowsMeasured || inputs.rowsMeta.positions[lastMeasuredIndexRelativeToCurrentPage] >= offset) {
672
- // If all rows were measured (when no row has "auto" as height) or all rows before the offset
673
- // were measured, then use a binary search because it's faster.
674
- return binarySearch(offset, inputs.rowsMeta.positions, options);
675
- }
676
-
677
- // Otherwise, use an exponential search.
678
- // If rows have "auto" as height, their positions will be based on estimated heights.
679
- // In this case, we can skip several steps until we find a position higher than the offset.
680
- // Inspired by https://github.com/bvaughn/react-virtualized/blob/master/source/Grid/utils/CellSizeAndPositionManager.js
681
- return exponentialSearch(offset, inputs.rowsMeta.positions, lastMeasuredIndexRelativeToCurrentPage, options);
682
- }
683
-
684
- /**
685
- * Accepts as input a raw render context (the area visible in the viewport) and adds
686
- * computes the actual render context based on pinned elements, buffer dimensions and
687
- * spanning.
688
- */
689
- function deriveRenderContext(inputs, nextRenderContext, scrollCache) {
690
- const [firstRowToRender, lastRowToRender] = getIndexesToRender({
691
- firstIndex: nextRenderContext.firstRowIndex,
692
- lastIndex: nextRenderContext.lastRowIndex,
693
- minFirstIndex: 0,
694
- maxLastIndex: inputs.rows.length,
695
- bufferBefore: scrollCache.buffer.rowBefore,
696
- bufferAfter: scrollCache.buffer.rowAfter,
697
- positions: inputs.rowsMeta.positions,
698
- lastSize: inputs.lastRowHeight
699
- });
700
- const [initialFirstColumnToRender, lastColumnToRender] = getIndexesToRender({
701
- firstIndex: nextRenderContext.firstColumnIndex,
702
- lastIndex: nextRenderContext.lastColumnIndex,
703
- minFirstIndex: inputs.pinnedColumns.left.length,
704
- maxLastIndex: inputs.visibleColumns.length - inputs.pinnedColumns.right.length,
705
- bufferBefore: scrollCache.buffer.columnBefore,
706
- bufferAfter: scrollCache.buffer.columnAfter,
707
- positions: inputs.columnPositions,
708
- lastSize: inputs.lastColumnWidth
709
- });
710
- const firstColumnToRender = (0, _gridColumnsUtils.getFirstNonSpannedColumnToRender)({
711
- firstColumnToRender: initialFirstColumnToRender,
712
- apiRef: inputs.apiRef,
713
- firstRowToRender,
714
- lastRowToRender,
715
- visibleRows: inputs.rows
716
- });
717
- return {
718
- firstRowIndex: firstRowToRender,
719
- lastRowIndex: lastRowToRender,
720
- firstColumnIndex: firstColumnToRender,
721
- lastColumnIndex: lastColumnToRender
722
- };
723
- }
724
- /**
725
- * Use binary search to avoid looping through all possible positions.
726
- * The `options.atStart` provides the possibility to match for the first element that
727
- * intersects the screen, even if said element's start position is before `offset`. In
728
- * other words, we search for `offset + width`.
729
- */
730
- function binarySearch(offset, positions, options = undefined, sliceStart = 0, sliceEnd = positions.length) {
731
- if (positions.length <= 0) {
732
- return -1;
733
- }
734
- if (sliceStart >= sliceEnd) {
735
- return sliceStart;
736
- }
737
- const pivot = sliceStart + Math.floor((sliceEnd - sliceStart) / 2);
738
- const position = positions[pivot];
739
- let isBefore;
740
- if (options?.atStart) {
741
- const width = (pivot === positions.length - 1 ? options.lastPosition : positions[pivot + 1]) - position;
742
- isBefore = offset - width < position;
743
- } else {
744
- isBefore = offset <= position;
745
- }
746
- return isBefore ? binarySearch(offset, positions, options, sliceStart, pivot) : binarySearch(offset, positions, options, pivot + 1, sliceEnd);
747
- }
748
- function exponentialSearch(offset, positions, index, options = undefined) {
749
- let interval = 1;
750
- while (index < positions.length && Math.abs(positions[index]) < offset) {
751
- index += interval;
752
- interval *= 2;
753
- }
754
- return binarySearch(offset, positions, options, Math.floor(index / 2), Math.min(index, positions.length));
755
- }
756
- function getIndexesToRender({
757
- firstIndex,
758
- lastIndex,
759
- bufferBefore,
760
- bufferAfter,
761
- minFirstIndex,
762
- maxLastIndex,
763
- positions,
764
- lastSize
765
- }) {
766
- const firstPosition = positions[firstIndex] - bufferBefore;
767
- const lastPosition = positions[lastIndex] + bufferAfter;
768
- const firstIndexPadded = binarySearch(firstPosition, positions, {
769
- atStart: true,
770
- lastPosition: positions[positions.length - 1] + lastSize
771
- });
772
- const lastIndexPadded = binarySearch(lastPosition, positions);
773
- return [(0, _utils2.clamp)(firstIndexPadded, minFirstIndex, maxLastIndex), (0, _utils2.clamp)(lastIndexPadded, minFirstIndex, maxLastIndex)];
774
- }
775
- function areRenderContextsEqual(context1, context2) {
776
- if (context1 === context2) {
777
- return true;
778
- }
779
- return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
780
- }
781
- function computeOffsetLeft(columnPositions, renderContext, pinnedLeftLength) {
782
- const left = (columnPositions[renderContext.firstColumnIndex] ?? 0) - (columnPositions[pinnedLeftLength] ?? 0);
783
- return Math.abs(left);
784
- }
785
- function directionForDelta(dx, dy) {
786
- if (dx === 0 && dy === 0) {
787
- return ScrollDirection.NONE;
788
- }
789
- /* eslint-disable */
790
- if (Math.abs(dy) >= Math.abs(dx)) {
791
- if (dy > 0) {
792
- return ScrollDirection.DOWN;
793
- } else {
794
- return ScrollDirection.UP;
795
- }
796
- } else {
797
- if (dx > 0) {
798
- return ScrollDirection.RIGHT;
799
- } else {
800
- return ScrollDirection.LEFT;
801
- }
802
- }
803
- /* eslint-enable */
804
- }
805
- function bufferForDirection(isRtl, direction, rowBufferPx, columnBufferPx, verticalBuffer, horizontalBuffer) {
806
- if (isRtl) {
807
- switch (direction) {
808
- case ScrollDirection.LEFT:
809
- direction = ScrollDirection.RIGHT;
810
- break;
811
- case ScrollDirection.RIGHT:
812
- direction = ScrollDirection.LEFT;
813
- break;
814
- default:
815
- }
816
- }
817
- switch (direction) {
818
- case ScrollDirection.NONE:
819
- return {
820
- rowAfter: rowBufferPx,
821
- rowBefore: rowBufferPx,
822
- columnAfter: columnBufferPx,
823
- columnBefore: columnBufferPx
824
- };
825
- case ScrollDirection.LEFT:
826
- return {
827
- rowAfter: 0,
828
- rowBefore: 0,
829
- columnAfter: 0,
830
- columnBefore: horizontalBuffer
831
- };
832
- case ScrollDirection.RIGHT:
833
- return {
834
- rowAfter: 0,
835
- rowBefore: 0,
836
- columnAfter: horizontalBuffer,
837
- columnBefore: 0
838
- };
839
- case ScrollDirection.UP:
840
- return {
841
- rowAfter: 0,
842
- rowBefore: verticalBuffer,
843
- columnAfter: 0,
844
- columnBefore: 0
845
- };
846
- case ScrollDirection.DOWN:
847
- return {
848
- rowAfter: verticalBuffer,
849
- rowBefore: 0,
850
- columnAfter: 0,
851
- columnBefore: 0
852
- };
853
- default:
854
- // eslint unable to figure out enum exhaustiveness
855
- throw new Error('unreachable');
856
- }
857
- }