@mui/x-data-grid 7.0.0-alpha.8 → 7.0.0-alpha.9

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 (410) hide show
  1. package/CHANGELOG.md +379 -2
  2. package/DataGrid/DataGrid.js +6 -6
  3. package/DataGrid/useDataGridComponent.js +2 -1
  4. package/DataGrid/useDataGridProps.js +1 -0
  5. package/README.md +1 -1
  6. package/components/GridColumnHeaders.d.ts +3 -2
  7. package/components/GridColumnHeaders.js +3 -11
  8. package/components/GridDetailPanels.d.ts +5 -0
  9. package/components/GridDetailPanels.js +4 -0
  10. package/components/GridHeaders.d.ts +4 -0
  11. package/components/GridHeaders.js +53 -0
  12. package/components/GridPinnedRows.d.ts +7 -0
  13. package/components/GridPinnedRows.js +4 -0
  14. package/components/GridRow.d.ts +7 -4
  15. package/components/GridRow.js +260 -97
  16. package/components/GridScrollbarFillerCell.d.ts +7 -0
  17. package/components/GridScrollbarFillerCell.js +39 -0
  18. package/components/base/GridBody.d.ts +2 -13
  19. package/components/base/GridBody.js +2 -116
  20. package/components/base/GridOverlays.js +10 -21
  21. package/components/cell/GridActionsCellItem.d.ts +2 -2
  22. package/components/cell/GridCell.d.ts +15 -21
  23. package/components/cell/GridCell.js +67 -372
  24. package/components/columnHeaders/GridBaseColumnHeaders.js +1 -6
  25. package/components/columnHeaders/GridColumnHeaderItem.d.ts +2 -1
  26. package/components/columnHeaders/GridColumnHeaderItem.js +7 -3
  27. package/components/columnHeaders/GridColumnHeaderSortIcon.d.ts +1 -0
  28. package/components/columnHeaders/GridColumnHeaderSortIcon.js +5 -2
  29. package/components/columnHeaders/GridColumnHeadersInner.js +1 -2
  30. package/components/containers/GridRoot.js +18 -15
  31. package/components/containers/GridRootStyles.js +307 -204
  32. package/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.js +1 -1
  33. package/components/panel/GridPanel.js +3 -4
  34. package/components/panel/filterPanel/GridFilterForm.d.ts +6 -4
  35. package/components/panel/filterPanel/GridFilterForm.js +31 -14
  36. package/components/panel/filterPanel/GridFilterPanel.js +46 -20
  37. package/components/toolbar/GridToolbarColumnsButton.d.ts +13 -1
  38. package/components/toolbar/GridToolbarColumnsButton.js +40 -22
  39. package/components/toolbar/GridToolbarDensitySelector.d.ts +13 -1
  40. package/components/toolbar/GridToolbarDensitySelector.js +40 -22
  41. package/components/toolbar/GridToolbarExport.d.ts +10 -1
  42. package/components/toolbar/GridToolbarExport.js +6 -1
  43. package/components/toolbar/GridToolbarExportContainer.d.ts +15 -1
  44. package/components/toolbar/GridToolbarExportContainer.js +41 -23
  45. package/components/toolbar/GridToolbarFilterButton.d.ts +5 -4
  46. package/components/toolbar/GridToolbarFilterButton.js +6 -10
  47. package/components/virtualization/GridBottomContainer.d.ts +2 -0
  48. package/components/virtualization/GridBottomContainer.js +25 -0
  49. package/components/{containers → virtualization}/GridMainContainer.d.ts +2 -0
  50. package/components/virtualization/GridMainContainer.js +20 -0
  51. package/components/virtualization/GridTopContainer.d.ts +2 -0
  52. package/components/virtualization/GridTopContainer.js +35 -0
  53. package/components/virtualization/GridVirtualScrollbar.d.ts +7 -0
  54. package/components/virtualization/GridVirtualScrollbar.js +131 -0
  55. package/components/virtualization/GridVirtualScroller.d.ts +4 -4
  56. package/components/virtualization/GridVirtualScroller.js +69 -16
  57. package/components/virtualization/GridVirtualScrollerFiller.d.ts +4 -0
  58. package/components/virtualization/GridVirtualScrollerFiller.js +71 -0
  59. package/components/virtualization/GridVirtualScrollerRenderZone.js +2 -1
  60. package/constants/defaultGridSlotsComponents.js +6 -2
  61. package/constants/gridClasses.d.ts +60 -8
  62. package/constants/gridClasses.js +1 -1
  63. package/hooks/core/gridCoreSelector.d.ts +6 -0
  64. package/hooks/core/gridCoreSelector.js +5 -0
  65. package/hooks/core/useGridInitialization.js +4 -0
  66. package/hooks/core/useGridRefs.d.ts +3 -0
  67. package/hooks/core/useGridRefs.js +13 -0
  68. package/hooks/core/useGridTheme.d.ts +3 -0
  69. package/hooks/core/useGridTheme.js +19 -0
  70. package/hooks/features/columnGrouping/useGridColumnGrouping.d.ts +1 -1
  71. package/hooks/features/columnGrouping/useGridColumnGrouping.js +7 -14
  72. package/hooks/features/columnHeaders/useGridColumnHeaders.d.ts +13 -18
  73. package/hooks/features/columnHeaders/useGridColumnHeaders.js +68 -162
  74. package/hooks/features/columnMenu/useGridColumnMenu.js +28 -23
  75. package/hooks/features/columns/gridColumnsInterfaces.d.ts +17 -0
  76. package/hooks/features/columns/gridColumnsInterfaces.js +9 -1
  77. package/hooks/features/columns/gridColumnsSelector.d.ts +14 -1
  78. package/hooks/features/columns/gridColumnsSelector.js +52 -0
  79. package/hooks/features/columns/gridColumnsUtils.d.ts +1 -5
  80. package/hooks/features/columns/gridColumnsUtils.js +10 -12
  81. package/hooks/features/columns/index.d.ts +2 -2
  82. package/hooks/features/columns/index.js +2 -1
  83. package/hooks/features/columns/useGridColumnSpanning.js +62 -61
  84. package/hooks/features/columns/useGridColumns.js +20 -23
  85. package/hooks/features/dimensions/gridDimensionsApi.d.ts +60 -11
  86. package/hooks/features/dimensions/gridDimensionsSelectors.d.ts +2 -0
  87. package/hooks/features/dimensions/gridDimensionsSelectors.js +1 -0
  88. package/hooks/features/dimensions/index.d.ts +2 -0
  89. package/hooks/features/dimensions/index.js +1 -0
  90. package/hooks/features/dimensions/useGridDimensions.d.ts +7 -1
  91. package/hooks/features/dimensions/useGridDimensions.js +216 -148
  92. package/hooks/features/export/serializers/csvSerializer.js +2 -2
  93. package/hooks/features/filter/useGridFilter.js +3 -3
  94. package/hooks/features/focus/gridFocusStateSelector.d.ts +2 -2
  95. package/hooks/features/focus/gridFocusStateSelector.js +2 -6
  96. package/hooks/features/focus/useGridFocus.js +3 -3
  97. package/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +3 -16
  98. package/hooks/features/pagination/useGridPagination.js +3 -5
  99. package/hooks/features/rows/gridRowsInterfaces.d.ts +1 -0
  100. package/hooks/features/rows/gridRowsSelector.d.ts +2 -2
  101. package/hooks/features/rows/gridRowsSelector.js +5 -5
  102. package/hooks/features/rows/gridRowsUtils.d.ts +1 -1
  103. package/hooks/features/rows/gridRowsUtils.js +4 -4
  104. package/hooks/features/rows/useGridRowsMeta.js +7 -4
  105. package/hooks/features/scroll/useGridScroll.js +8 -10
  106. package/hooks/features/sorting/gridSortingUtils.js +1 -1
  107. package/hooks/features/sorting/useGridSorting.d.ts +1 -1
  108. package/hooks/features/sorting/useGridSorting.js +15 -10
  109. package/hooks/features/virtualization/gridVirtualizationSelectors.d.ts +14 -0
  110. package/hooks/features/virtualization/gridVirtualizationSelectors.js +22 -2
  111. package/hooks/features/virtualization/useGridVirtualScroller.d.ts +27 -42
  112. package/hooks/features/virtualization/useGridVirtualScroller.js +441 -438
  113. package/hooks/features/virtualization/useGridVirtualization.d.ts +8 -0
  114. package/hooks/features/virtualization/useGridVirtualization.js +8 -1
  115. package/hooks/utils/index.d.ts +3 -0
  116. package/hooks/utils/index.js +4 -1
  117. package/hooks/utils/useGridAriaAttributes.js +1 -2
  118. package/hooks/utils/useGridNativeEventListener.js +4 -9
  119. package/hooks/utils/useResizeObserver.d.ts +2 -0
  120. package/hooks/utils/useResizeObserver.js +36 -0
  121. package/hooks/utils/useRunOnce.d.ts +5 -0
  122. package/hooks/utils/useRunOnce.js +18 -0
  123. package/index.js +1 -1
  124. package/internals/index.d.ts +12 -9
  125. package/internals/index.js +9 -7
  126. package/legacy/DataGrid/DataGrid.js +6 -6
  127. package/legacy/DataGrid/useDataGridComponent.js +2 -1
  128. package/legacy/DataGrid/useDataGridProps.js +1 -0
  129. package/legacy/components/GridColumnHeaders.js +3 -11
  130. package/legacy/components/GridDetailPanels.js +4 -0
  131. package/legacy/components/GridHeaders.js +53 -0
  132. package/legacy/components/GridPinnedRows.js +4 -0
  133. package/legacy/components/GridRow.js +258 -98
  134. package/legacy/components/GridScrollbarFillerCell.js +36 -0
  135. package/legacy/components/base/GridBody.js +2 -114
  136. package/legacy/components/base/GridOverlays.js +10 -25
  137. package/legacy/components/cell/GridCell.js +69 -377
  138. package/legacy/components/columnHeaders/GridBaseColumnHeaders.js +1 -6
  139. package/legacy/components/columnHeaders/GridColumnHeaderItem.js +7 -3
  140. package/legacy/components/columnHeaders/GridColumnHeaderSortIcon.js +5 -2
  141. package/legacy/components/columnHeaders/GridColumnHeadersInner.js +1 -2
  142. package/legacy/components/containers/GridRoot.js +18 -15
  143. package/legacy/components/containers/GridRootStyles.js +215 -137
  144. package/legacy/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.js +1 -1
  145. package/legacy/components/panel/GridPanel.js +3 -4
  146. package/legacy/components/panel/filterPanel/GridFilterForm.js +30 -13
  147. package/legacy/components/panel/filterPanel/GridFilterPanel.js +49 -20
  148. package/legacy/components/toolbar/GridToolbarColumnsButton.js +40 -21
  149. package/legacy/components/toolbar/GridToolbarDensitySelector.js +40 -21
  150. package/legacy/components/toolbar/GridToolbarExport.js +6 -1
  151. package/legacy/components/toolbar/GridToolbarExportContainer.js +40 -21
  152. package/legacy/components/toolbar/GridToolbarFilterButton.js +6 -10
  153. package/legacy/components/virtualization/GridBottomContainer.js +25 -0
  154. package/legacy/components/virtualization/GridMainContainer.js +20 -0
  155. package/legacy/components/virtualization/GridTopContainer.js +35 -0
  156. package/legacy/components/virtualization/GridVirtualScrollbar.js +129 -0
  157. package/legacy/components/virtualization/GridVirtualScroller.js +67 -16
  158. package/legacy/components/virtualization/GridVirtualScrollerFiller.js +70 -0
  159. package/legacy/components/virtualization/GridVirtualScrollerRenderZone.js +2 -1
  160. package/legacy/constants/defaultGridSlotsComponents.js +6 -2
  161. package/legacy/constants/gridClasses.js +1 -1
  162. package/legacy/hooks/core/gridCoreSelector.js +7 -0
  163. package/legacy/hooks/core/useGridInitialization.js +4 -0
  164. package/legacy/hooks/core/useGridRefs.js +13 -0
  165. package/legacy/hooks/core/useGridTheme.js +21 -0
  166. package/legacy/hooks/features/columnGrouping/useGridColumnGrouping.js +7 -14
  167. package/legacy/hooks/features/columnHeaders/useGridColumnHeaders.js +69 -181
  168. package/legacy/hooks/features/columnMenu/useGridColumnMenu.js +28 -23
  169. package/legacy/hooks/features/columns/gridColumnsInterfaces.js +9 -1
  170. package/legacy/hooks/features/columns/gridColumnsSelector.js +62 -0
  171. package/legacy/hooks/features/columns/gridColumnsUtils.js +10 -16
  172. package/legacy/hooks/features/columns/index.js +2 -1
  173. package/legacy/hooks/features/columns/useGridColumnSpanning.js +60 -59
  174. package/legacy/hooks/features/columns/useGridColumns.js +22 -23
  175. package/legacy/hooks/features/dimensions/gridDimensionsSelectors.js +3 -0
  176. package/legacy/hooks/features/dimensions/index.js +1 -0
  177. package/legacy/hooks/features/dimensions/useGridDimensions.js +226 -151
  178. package/legacy/hooks/features/export/serializers/csvSerializer.js +2 -2
  179. package/legacy/hooks/features/filter/useGridFilter.js +3 -3
  180. package/legacy/hooks/features/focus/gridFocusStateSelector.js +2 -6
  181. package/legacy/hooks/features/focus/useGridFocus.js +3 -3
  182. package/legacy/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +3 -16
  183. package/legacy/hooks/features/pagination/useGridPagination.js +3 -5
  184. package/legacy/hooks/features/rows/gridRowsSelector.js +5 -5
  185. package/legacy/hooks/features/rows/gridRowsUtils.js +4 -4
  186. package/legacy/hooks/features/rows/useGridRowsMeta.js +7 -4
  187. package/legacy/hooks/features/scroll/useGridScroll.js +8 -10
  188. package/legacy/hooks/features/sorting/gridSortingUtils.js +1 -1
  189. package/legacy/hooks/features/sorting/useGridSorting.js +15 -10
  190. package/legacy/hooks/features/virtualization/gridVirtualizationSelectors.js +29 -1
  191. package/legacy/hooks/features/virtualization/useGridVirtualScroller.js +490 -483
  192. package/legacy/hooks/features/virtualization/useGridVirtualization.js +8 -1
  193. package/legacy/hooks/utils/index.js +4 -1
  194. package/legacy/hooks/utils/useGridAriaAttributes.js +1 -2
  195. package/legacy/hooks/utils/useGridNativeEventListener.js +4 -9
  196. package/legacy/hooks/utils/useResizeObserver.js +36 -0
  197. package/legacy/hooks/utils/useRunOnce.js +18 -0
  198. package/legacy/index.js +1 -1
  199. package/legacy/internals/index.js +9 -7
  200. package/legacy/locales/hrHR.js +161 -0
  201. package/legacy/locales/index.js +4 -1
  202. package/legacy/locales/ptPT.js +161 -0
  203. package/legacy/locales/zhHK.js +161 -0
  204. package/legacy/models/index.js +0 -1
  205. package/legacy/models/params/index.js +1 -2
  206. package/legacy/utils/utils.js +10 -1
  207. package/locales/hrHR.d.ts +1 -0
  208. package/locales/hrHR.js +149 -0
  209. package/locales/index.d.ts +3 -0
  210. package/locales/index.js +4 -1
  211. package/locales/ptPT.d.ts +1 -0
  212. package/locales/ptPT.js +149 -0
  213. package/locales/zhHK.d.ts +1 -0
  214. package/locales/zhHK.js +149 -0
  215. package/models/api/gridColumnGroupingApi.d.ts +2 -2
  216. package/models/api/gridCoreApi.d.ts +16 -16
  217. package/models/api/gridRowsMetaApi.d.ts +1 -1
  218. package/models/api/gridVirtualizationApi.d.ts +2 -3
  219. package/models/events/gridEventLookup.d.ts +3 -3
  220. package/models/gridFilterModel.d.ts +1 -1
  221. package/models/gridSlotsComponent.d.ts +16 -2
  222. package/models/gridStateCommunity.d.ts +5 -1
  223. package/models/index.d.ts +0 -1
  224. package/models/index.js +0 -1
  225. package/models/params/index.d.ts +0 -1
  226. package/models/params/index.js +1 -2
  227. package/models/props/DataGridProps.d.ts +6 -11
  228. package/modern/DataGrid/DataGrid.js +6 -6
  229. package/modern/DataGrid/useDataGridComponent.js +2 -1
  230. package/modern/DataGrid/useDataGridProps.js +1 -0
  231. package/modern/components/GridColumnHeaders.js +3 -11
  232. package/modern/components/GridDetailPanels.js +4 -0
  233. package/modern/components/GridHeaders.js +53 -0
  234. package/modern/components/GridPinnedRows.js +4 -0
  235. package/modern/components/GridRow.js +258 -96
  236. package/modern/components/GridScrollbarFillerCell.js +39 -0
  237. package/modern/components/base/GridBody.js +2 -116
  238. package/modern/components/base/GridOverlays.js +10 -16
  239. package/modern/components/cell/GridCell.js +65 -369
  240. package/modern/components/columnHeaders/GridBaseColumnHeaders.js +1 -6
  241. package/modern/components/columnHeaders/GridColumnHeaderItem.js +7 -3
  242. package/modern/components/columnHeaders/GridColumnHeaderSortIcon.js +5 -2
  243. package/modern/components/columnHeaders/GridColumnHeadersInner.js +1 -1
  244. package/modern/components/containers/GridRoot.js +18 -14
  245. package/modern/components/containers/GridRootStyles.js +307 -204
  246. package/modern/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.js +1 -1
  247. package/modern/components/panel/GridPanel.js +3 -4
  248. package/modern/components/panel/filterPanel/GridFilterForm.js +30 -13
  249. package/modern/components/panel/filterPanel/GridFilterPanel.js +46 -20
  250. package/modern/components/toolbar/GridToolbarColumnsButton.js +38 -21
  251. package/modern/components/toolbar/GridToolbarDensitySelector.js +38 -21
  252. package/modern/components/toolbar/GridToolbarExport.js +6 -1
  253. package/modern/components/toolbar/GridToolbarExportContainer.js +39 -22
  254. package/modern/components/toolbar/GridToolbarFilterButton.js +6 -10
  255. package/modern/components/virtualization/GridBottomContainer.js +25 -0
  256. package/modern/components/virtualization/GridMainContainer.js +20 -0
  257. package/modern/components/virtualization/GridTopContainer.js +35 -0
  258. package/modern/components/virtualization/GridVirtualScrollbar.js +131 -0
  259. package/modern/components/virtualization/GridVirtualScroller.js +69 -16
  260. package/modern/components/virtualization/GridVirtualScrollerFiller.js +71 -0
  261. package/modern/components/virtualization/GridVirtualScrollerRenderZone.js +2 -1
  262. package/modern/constants/defaultGridSlotsComponents.js +6 -2
  263. package/modern/constants/gridClasses.js +1 -1
  264. package/modern/hooks/core/gridCoreSelector.js +5 -0
  265. package/modern/hooks/core/useGridInitialization.js +4 -0
  266. package/modern/hooks/core/useGridRefs.js +13 -0
  267. package/modern/hooks/core/useGridTheme.js +19 -0
  268. package/modern/hooks/features/columnGrouping/useGridColumnGrouping.js +5 -12
  269. package/modern/hooks/features/columnHeaders/useGridColumnHeaders.js +67 -160
  270. package/modern/hooks/features/columnMenu/useGridColumnMenu.js +28 -23
  271. package/modern/hooks/features/columns/gridColumnsInterfaces.js +9 -1
  272. package/modern/hooks/features/columns/gridColumnsSelector.js +51 -0
  273. package/modern/hooks/features/columns/gridColumnsUtils.js +10 -12
  274. package/modern/hooks/features/columns/index.js +2 -1
  275. package/modern/hooks/features/columns/useGridColumnSpanning.js +62 -61
  276. package/modern/hooks/features/columns/useGridColumns.js +19 -21
  277. package/modern/hooks/features/dimensions/gridDimensionsSelectors.js +1 -0
  278. package/modern/hooks/features/dimensions/index.js +1 -0
  279. package/modern/hooks/features/dimensions/useGridDimensions.js +214 -146
  280. package/modern/hooks/features/export/serializers/csvSerializer.js +2 -2
  281. package/modern/hooks/features/filter/useGridFilter.js +3 -3
  282. package/modern/hooks/features/focus/gridFocusStateSelector.js +2 -6
  283. package/modern/hooks/features/focus/useGridFocus.js +3 -3
  284. package/modern/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +3 -16
  285. package/modern/hooks/features/pagination/useGridPagination.js +3 -5
  286. package/modern/hooks/features/rows/gridRowsSelector.js +2 -2
  287. package/modern/hooks/features/rows/gridRowsUtils.js +4 -4
  288. package/modern/hooks/features/rows/useGridRowsMeta.js +7 -4
  289. package/modern/hooks/features/scroll/useGridScroll.js +8 -9
  290. package/modern/hooks/features/sorting/gridSortingUtils.js +1 -1
  291. package/modern/hooks/features/sorting/useGridSorting.js +15 -10
  292. package/modern/hooks/features/virtualization/gridVirtualizationSelectors.js +22 -2
  293. package/modern/hooks/features/virtualization/useGridVirtualScroller.js +435 -432
  294. package/modern/hooks/features/virtualization/useGridVirtualization.js +8 -1
  295. package/modern/hooks/utils/index.js +4 -1
  296. package/modern/hooks/utils/useGridAriaAttributes.js +1 -1
  297. package/modern/hooks/utils/useGridNativeEventListener.js +3 -9
  298. package/modern/hooks/utils/useResizeObserver.js +36 -0
  299. package/modern/hooks/utils/useRunOnce.js +18 -0
  300. package/modern/index.js +1 -1
  301. package/modern/internals/index.js +9 -7
  302. package/modern/locales/hrHR.js +149 -0
  303. package/modern/locales/index.js +4 -1
  304. package/modern/locales/ptPT.js +149 -0
  305. package/modern/locales/zhHK.js +149 -0
  306. package/modern/models/index.js +0 -1
  307. package/modern/models/params/index.js +1 -2
  308. package/modern/utils/utils.js +10 -1
  309. package/node/DataGrid/DataGrid.js +6 -6
  310. package/node/DataGrid/useDataGridComponent.js +1 -0
  311. package/node/DataGrid/useDataGridProps.js +1 -0
  312. package/node/components/GridColumnHeaders.js +3 -11
  313. package/node/components/GridDetailPanels.js +10 -0
  314. package/node/components/GridHeaders.js +60 -0
  315. package/node/components/GridPinnedRows.js +10 -0
  316. package/node/components/GridRow.js +256 -94
  317. package/node/components/GridScrollbarFillerCell.js +47 -0
  318. package/node/components/base/GridBody.js +7 -118
  319. package/node/components/base/GridOverlays.js +9 -15
  320. package/node/components/cell/GridCell.js +66 -369
  321. package/node/components/columnHeaders/GridBaseColumnHeaders.js +1 -6
  322. package/node/components/columnHeaders/GridColumnHeaderItem.js +8 -4
  323. package/node/components/columnHeaders/GridColumnHeaderSortIcon.js +5 -2
  324. package/node/components/columnHeaders/GridColumnHeadersInner.js +1 -1
  325. package/node/components/containers/GridRoot.js +17 -14
  326. package/node/components/containers/GridRootStyles.js +175 -72
  327. package/node/components/menu/columnMenu/menuItems/GridColumnMenuSortItem.js +1 -1
  328. package/node/components/panel/GridPanel.js +3 -4
  329. package/node/components/panel/filterPanel/GridFilterForm.js +29 -12
  330. package/node/components/panel/filterPanel/GridFilterPanel.js +45 -19
  331. package/node/components/toolbar/GridToolbarColumnsButton.js +36 -20
  332. package/node/components/toolbar/GridToolbarDensitySelector.js +36 -20
  333. package/node/components/toolbar/GridToolbarExport.js +6 -1
  334. package/node/components/toolbar/GridToolbarExportContainer.js +37 -21
  335. package/node/components/toolbar/GridToolbarFilterButton.js +6 -10
  336. package/node/components/virtualization/GridBottomContainer.js +34 -0
  337. package/node/components/{containers → virtualization}/GridMainContainer.js +7 -29
  338. package/node/components/virtualization/GridTopContainer.js +44 -0
  339. package/node/components/virtualization/GridVirtualScrollbar.js +138 -0
  340. package/node/components/virtualization/GridVirtualScroller.js +69 -17
  341. package/node/components/virtualization/GridVirtualScrollerFiller.js +77 -0
  342. package/node/components/virtualization/GridVirtualScrollerRenderZone.js +2 -1
  343. package/node/constants/defaultGridSlotsComponents.js +5 -1
  344. package/node/constants/gridClasses.js +1 -1
  345. package/node/hooks/core/gridCoreSelector.js +12 -0
  346. package/node/hooks/core/useGridInitialization.js +4 -0
  347. package/node/hooks/core/useGridRefs.js +22 -0
  348. package/node/hooks/core/useGridTheme.js +29 -0
  349. package/node/hooks/features/columnGrouping/useGridColumnGrouping.js +5 -12
  350. package/node/hooks/features/columnHeaders/useGridColumnHeaders.js +65 -159
  351. package/node/hooks/features/columnMenu/useGridColumnMenu.js +28 -23
  352. package/node/hooks/features/columns/gridColumnsInterfaces.js +11 -1
  353. package/node/hooks/features/columns/gridColumnsSelector.js +52 -1
  354. package/node/hooks/features/columns/gridColumnsUtils.js +10 -13
  355. package/node/hooks/features/columns/index.js +22 -61
  356. package/node/hooks/features/columns/useGridColumnSpanning.js +62 -61
  357. package/node/hooks/features/columns/useGridColumns.js +20 -22
  358. package/node/hooks/features/dimensions/gridDimensionsSelectors.js +8 -0
  359. package/node/hooks/features/dimensions/index.js +11 -0
  360. package/node/hooks/features/dimensions/useGridDimensions.js +215 -144
  361. package/node/hooks/features/export/serializers/csvSerializer.js +2 -2
  362. package/node/hooks/features/filter/useGridFilter.js +2 -2
  363. package/node/hooks/features/focus/gridFocusStateSelector.js +3 -7
  364. package/node/hooks/features/focus/useGridFocus.js +2 -2
  365. package/node/hooks/features/keyboardNavigation/useGridKeyboardNavigation.js +2 -15
  366. package/node/hooks/features/pagination/useGridPagination.js +3 -5
  367. package/node/hooks/features/rows/gridRowsSelector.js +2 -2
  368. package/node/hooks/features/rows/gridRowsUtils.js +4 -4
  369. package/node/hooks/features/rows/useGridRowsMeta.js +5 -3
  370. package/node/hooks/features/scroll/useGridScroll.js +8 -9
  371. package/node/hooks/features/sorting/gridSortingUtils.js +1 -1
  372. package/node/hooks/features/sorting/useGridSorting.js +15 -10
  373. package/node/hooks/features/virtualization/gridVirtualizationSelectors.js +22 -2
  374. package/node/hooks/features/virtualization/useGridVirtualScroller.js +434 -431
  375. package/node/hooks/features/virtualization/useGridVirtualization.js +9 -1
  376. package/node/hooks/utils/index.js +36 -0
  377. package/node/hooks/utils/useGridAriaAttributes.js +1 -1
  378. package/node/hooks/utils/useGridNativeEventListener.js +3 -9
  379. package/node/hooks/utils/useResizeObserver.js +44 -0
  380. package/node/hooks/utils/useRunOnce.js +27 -0
  381. package/node/index.js +1 -1
  382. package/node/internals/index.js +86 -71
  383. package/node/locales/hrHR.js +155 -0
  384. package/node/locales/index.js +33 -0
  385. package/node/locales/ptPT.js +155 -0
  386. package/node/locales/zhHK.js +155 -0
  387. package/node/models/index.js +0 -11
  388. package/node/models/params/index.js +0 -11
  389. package/node/utils/utils.js +11 -1
  390. package/package.json +6 -6
  391. package/utils/utils.d.ts +6 -0
  392. package/utils/utils.js +10 -1
  393. package/components/DataGridVirtualScroller.d.ts +0 -3
  394. package/components/DataGridVirtualScroller.js +0 -35
  395. package/components/containers/GridMainContainer.js +0 -43
  396. package/legacy/components/DataGridVirtualScroller.js +0 -32
  397. package/legacy/components/containers/GridMainContainer.js +0 -45
  398. package/legacy/models/gridRootContainerRef.js +0 -1
  399. package/legacy/models/params/gridRenderedRowsIntervalChangeParams.js +0 -1
  400. package/models/gridRootContainerRef.d.ts +0 -5
  401. package/models/gridRootContainerRef.js +0 -1
  402. package/models/params/gridRenderedRowsIntervalChangeParams.d.ts +0 -10
  403. package/models/params/gridRenderedRowsIntervalChangeParams.js +0 -1
  404. package/modern/components/DataGridVirtualScroller.js +0 -35
  405. package/modern/components/containers/GridMainContainer.js +0 -42
  406. package/modern/models/gridRootContainerRef.js +0 -1
  407. package/modern/models/params/gridRenderedRowsIntervalChangeParams.js +0 -1
  408. package/node/components/DataGridVirtualScroller.js +0 -42
  409. package/node/models/gridRootContainerRef.js +0 -5
  410. package/node/models/params/gridRenderedRowsIntervalChangeParams.js +0 -5
@@ -1,310 +1,144 @@
1
1
  import _extends from "@babel/runtime/helpers/esm/extends";
2
- import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWithoutPropertiesLoose";
3
- const _excluded = ["style"],
4
- _excluded2 = ["style"];
5
2
  import * as React from 'react';
6
3
  import * as ReactDOM from 'react-dom';
7
- import { unstable_useForkRef as useForkRef, unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback } from '@mui/utils';
4
+ import { unstable_useEnhancedEffect as useEnhancedEffect, unstable_useEventCallback as useEventCallback } from '@mui/utils';
8
5
  import { useTheme } from '@mui/material/styles';
9
6
  import { defaultMemoize } from 'reselect';
10
7
  import { useGridPrivateApiContext } from '../../utils/useGridPrivateApiContext';
11
8
  import { useGridRootProps } from '../../utils/useGridRootProps';
12
9
  import { useGridSelector } from '../../utils/useGridSelector';
13
- import { gridVisibleColumnDefinitionsSelector, gridColumnsTotalWidthSelector, gridColumnPositionsSelector } from '../columns/gridColumnsSelector';
10
+ import { useLazyRef } from '../../utils/useLazyRef';
11
+ import { useResizeObserver } from '../../utils/useResizeObserver';
12
+ import { useRunOnce } from '../../utils/useRunOnce';
13
+ import { gridVisibleColumnDefinitionsSelector, gridVisiblePinnedColumnDefinitionsSelector, gridColumnPositionsSelector } from '../columns/gridColumnsSelector';
14
+ import { gridDimensionsSelector } from '../dimensions/gridDimensionsSelectors';
15
+ import { gridPinnedRowsSelector } from '../rows/gridRowsSelector';
14
16
  import { gridFocusCellSelector, gridTabIndexCellSelector } from '../focus/gridFocusStateSelector';
15
- import { useGridVisibleRows } from '../../utils/useGridVisibleRows';
16
- import { useGridApiEventHandler } from '../../utils/useGridApiEventHandler';
17
+ import { useGridVisibleRows, getVisibleRows } from '../../utils/useGridVisibleRows';
17
18
  import { clamp } from '../../../utils/utils';
18
19
  import { selectedIdsLookupSelector } from '../rowSelection/gridRowSelectionSelector';
19
20
  import { gridRowsMetaSelector } from '../rows/gridRowsMetaSelector';
20
21
  import { getFirstNonSpannedColumnToRender } from '../columns/gridColumnsUtils';
21
22
  import { getMinimalContentHeight } from '../rows/gridRowsUtils';
22
- import { gridVirtualizationEnabledSelector, gridVirtualizationColumnEnabledSelector } from './gridVirtualizationSelectors';
23
-
24
- // Uses binary search to avoid looping through all possible positions
23
+ import { gridRenderContextSelector, gridVirtualizationEnabledSelector, gridVirtualizationColumnEnabledSelector } from './gridVirtualizationSelectors';
24
+ import { EMPTY_RENDER_CONTEXT } from './useGridVirtualization';
25
25
  import { jsx as _jsx } from "react/jsx-runtime";
26
- export function binarySearch(offset, positions, sliceStart = 0, sliceEnd = positions.length) {
27
- if (positions.length <= 0) {
28
- return -1;
29
- }
30
- if (sliceStart >= sliceEnd) {
31
- return sliceStart;
32
- }
33
- const pivot = sliceStart + Math.floor((sliceEnd - sliceStart) / 2);
34
- const itemOffset = positions[pivot];
35
- return offset <= itemOffset ? binarySearch(offset, positions, sliceStart, pivot) : binarySearch(offset, positions, pivot + 1, sliceEnd);
36
- }
37
- function exponentialSearch(offset, positions, index) {
38
- let interval = 1;
39
- while (index < positions.length && Math.abs(positions[index]) < offset) {
40
- index += interval;
41
- interval *= 2;
42
- }
43
- return binarySearch(offset, positions, Math.floor(index / 2), Math.min(index, positions.length));
44
- }
45
- export const getRenderableIndexes = ({
46
- firstIndex,
47
- lastIndex,
48
- buffer,
49
- minFirstIndex,
50
- maxLastIndex
51
- }) => {
52
- return [clamp(firstIndex - buffer, minFirstIndex, maxLastIndex), clamp(lastIndex + buffer, minFirstIndex, maxLastIndex)];
53
- };
54
- export const areRenderContextsEqual = (context1, context2) => {
55
- if (context1 === context2) {
56
- return true;
57
- }
58
- return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
59
- };
60
- // The `maxSize` is 3 so that reselect caches the `renderedColumns` values for the pinned left,
61
- // unpinned, and pinned right sections.
62
- const MEMOIZE_OPTIONS = {
63
- maxSize: 3
64
- };
65
- export const useGridVirtualScroller = props => {
66
- var _currentPage$range3, _currentPage$range4;
26
+ export const EMPTY_DETAIL_PANELS = Object.freeze(new Map());
27
+ export const useGridVirtualScroller = () => {
67
28
  const apiRef = useGridPrivateApiContext();
68
29
  const rootProps = useGridRootProps();
69
30
  const visibleColumns = useGridSelector(apiRef, gridVisibleColumnDefinitionsSelector);
70
31
  const enabled = useGridSelector(apiRef, gridVirtualizationEnabledSelector);
71
32
  const enabledForColumns = useGridSelector(apiRef, gridVirtualizationColumnEnabledSelector);
72
- const {
73
- ref,
74
- onRenderZonePositioning,
75
- renderZoneMinColumnIndex = 0,
76
- renderZoneMaxColumnIndex = visibleColumns.length,
77
- getRowProps
78
- } = props;
33
+ const dimensions = useGridSelector(apiRef, gridDimensionsSelector);
34
+ const outerSize = dimensions.viewportOuterSize;
35
+ const pinnedRows = useGridSelector(apiRef, gridPinnedRowsSelector);
36
+ const pinnedColumns = useGridSelector(apiRef, gridVisiblePinnedColumnDefinitionsSelector);
37
+ const hasBottomPinnedRows = pinnedRows.bottom.length > 0;
38
+ const [panels, setPanels] = React.useState(EMPTY_DETAIL_PANELS);
79
39
  const theme = useTheme();
80
40
  const columnPositions = useGridSelector(apiRef, gridColumnPositionsSelector);
81
- const columnsTotalWidth = useGridSelector(apiRef, gridColumnsTotalWidthSelector);
82
41
  const cellFocus = useGridSelector(apiRef, gridFocusCellSelector);
83
42
  const cellTabIndex = useGridSelector(apiRef, gridTabIndexCellSelector);
84
43
  const rowsMeta = useGridSelector(apiRef, gridRowsMetaSelector);
85
44
  const selectedRowsLookup = useGridSelector(apiRef, selectedIdsLookupSelector);
86
45
  const currentPage = useGridVisibleRows(apiRef, rootProps);
46
+ const gridRootRef = apiRef.current.rootElementRef;
47
+ const mainRef = apiRef.current.mainElementRef;
48
+ const scrollerRef = apiRef.current.virtualScrollerRef;
87
49
  const renderZoneRef = React.useRef(null);
88
- const rootRef = React.useRef(null);
89
- const handleRef = useForkRef(ref, rootRef);
90
- const [renderContext, setRenderContextState] = React.useState(null);
91
- const prevRenderContext = React.useRef(renderContext);
50
+ const scrollbarVerticalRef = React.useRef(null);
51
+ const scrollbarHorizontalRef = React.useRef(null);
52
+ const contentHeight = dimensions.contentSize.height;
53
+ const columnsTotalWidth = dimensions.columnsTotalWidth;
54
+ useResizeObserver(mainRef, () => apiRef.current.resize());
55
+ const previousContext = React.useRef(EMPTY_RENDER_CONTEXT);
56
+ const previousRowContext = React.useRef(EMPTY_RENDER_CONTEXT);
57
+ const renderContext = useGridSelector(apiRef, gridRenderContextSelector);
92
58
  const scrollPosition = React.useRef({
93
59
  top: 0,
94
60
  left: 0
95
- });
96
- const [containerDimensions, setContainerDimensions] = React.useState({
97
- width: null,
98
- height: null
99
- });
61
+ }).current;
100
62
  const prevTotalWidth = React.useRef(columnsTotalWidth);
101
- // Each visible row (not to be confused with a filter result) is composed of a central row element
102
- // and up to two additional row elements for pinned columns (left and right).
103
- // When hovering any of these elements, the :hover styles are applied only to the row element that
104
- // was actually hovered, not its additional siblings. To make it look like a contiguous row,
105
- // we add/remove the .Mui-hovered class to all of the row elements inside one visible row.
106
- const [hoveredRowId, setHoveredRowId] = React.useState(null);
107
- const rowStyleCache = React.useRef(Object.create(null));
108
- const prevGetRowProps = React.useRef();
109
- const prevRootRowStyle = React.useRef();
110
- const getRenderedColumnsRef = React.useRef(defaultMemoize((columns, firstColumnToRender, lastColumnToRender, minFirstColumn, maxLastColumn, indexOfColumnWithFocusedCell) => {
111
- // If the selected column is not within the current range of columns being displayed,
112
- // we need to render it at either the left or right of the columns,
113
- // depending on whether it is above or below the range.
114
- let focusedCellColumnIndexNotInRange;
115
- const renderedColumns = columns.slice(firstColumnToRender, lastColumnToRender);
116
- if (indexOfColumnWithFocusedCell > -1) {
117
- // check if it is not on the left pinned column.
118
- if (firstColumnToRender > indexOfColumnWithFocusedCell && indexOfColumnWithFocusedCell >= minFirstColumn) {
119
- focusedCellColumnIndexNotInRange = indexOfColumnWithFocusedCell;
120
- }
121
- // check if it is not on the right pinned column.
122
- else if (lastColumnToRender < indexOfColumnWithFocusedCell && indexOfColumnWithFocusedCell < maxLastColumn) {
123
- focusedCellColumnIndexNotInRange = indexOfColumnWithFocusedCell;
124
- }
63
+ const getRenderedColumns = useLazyRef(createGetRenderedColumns).current;
64
+ const indexOfRowWithFocusedCell = React.useMemo(() => {
65
+ if (cellFocus !== null) {
66
+ return currentPage.rows.findIndex(row => row.id === cellFocus.id);
125
67
  }
126
- return {
127
- focusedCellColumnIndexNotInRange,
128
- renderedColumns
129
- };
130
- }, MEMOIZE_OPTIONS));
68
+ return -1;
69
+ }, [cellFocus, currentPage.rows]);
131
70
  const indexOfColumnWithFocusedCell = React.useMemo(() => {
132
71
  if (cellFocus !== null) {
133
72
  return visibleColumns.findIndex(column => column.field === cellFocus.field);
134
73
  }
135
74
  return -1;
136
75
  }, [cellFocus, visibleColumns]);
137
- const getNearestIndexToRender = React.useCallback(offset => {
138
- var _currentPage$range, _currentPage$range2;
139
- const lastMeasuredIndexRelativeToAllRows = apiRef.current.getLastMeasuredRowIndex();
140
- let allRowsMeasured = lastMeasuredIndexRelativeToAllRows === Infinity;
141
- if ((_currentPage$range = currentPage.range) != null && _currentPage$range.lastRowIndex && !allRowsMeasured) {
142
- // Check if all rows in this page are already measured
143
- allRowsMeasured = lastMeasuredIndexRelativeToAllRows >= currentPage.range.lastRowIndex;
144
- }
145
- const lastMeasuredIndexRelativeToCurrentPage = clamp(lastMeasuredIndexRelativeToAllRows - (((_currentPage$range2 = currentPage.range) == null ? void 0 : _currentPage$range2.firstRowIndex) || 0), 0, rowsMeta.positions.length);
146
- if (allRowsMeasured || rowsMeta.positions[lastMeasuredIndexRelativeToCurrentPage] >= offset) {
147
- // If all rows were measured (when no row has "auto" as height) or all rows before the offset
148
- // were measured, then use a binary search because it's faster.
149
- return binarySearch(offset, rowsMeta.positions);
150
- }
151
-
152
- // Otherwise, use an exponential search.
153
- // If rows have "auto" as height, their positions will be based on estimated heights.
154
- // In this case, we can skip several steps until we find a position higher than the offset.
155
- // Inspired by https://github.com/bvaughn/react-virtualized/blob/master/source/Grid/utils/CellSizeAndPositionManager.js
156
- return exponentialSearch(offset, rowsMeta.positions, lastMeasuredIndexRelativeToCurrentPage);
157
- }, [apiRef, (_currentPage$range3 = currentPage.range) == null ? void 0 : _currentPage$range3.firstRowIndex, (_currentPage$range4 = currentPage.range) == null ? void 0 : _currentPage$range4.lastRowIndex, rowsMeta.positions]);
158
- const computeRenderContext = React.useCallback(() => {
159
- if (!enabled) {
160
- return {
161
- firstRowIndex: 0,
162
- lastRowIndex: currentPage.rows.length,
163
- firstColumnIndex: 0,
164
- lastColumnIndex: visibleColumns.length
165
- };
166
- }
167
- const {
168
- top,
169
- left
170
- } = scrollPosition.current;
171
-
172
- // Clamp the value because the search may return an index out of bounds.
173
- // In the last index, this is not needed because Array.slice doesn't include it.
174
- const firstRowIndex = Math.min(getNearestIndexToRender(top), rowsMeta.positions.length - 1);
175
- const lastRowIndex = rootProps.autoHeight ? firstRowIndex + currentPage.rows.length : getNearestIndexToRender(top + containerDimensions.height);
176
- let firstColumnIndex = 0;
177
- let lastColumnIndex = columnPositions.length;
178
- if (enabledForColumns) {
179
- let hasRowWithAutoHeight = false;
180
- const [firstRowToRender, lastRowToRender] = getRenderableIndexes({
181
- firstIndex: firstRowIndex,
182
- lastIndex: lastRowIndex,
183
- minFirstIndex: 0,
184
- maxLastIndex: currentPage.rows.length,
185
- buffer: rootProps.rowBuffer
186
- });
187
- for (let i = firstRowToRender; i < lastRowToRender && !hasRowWithAutoHeight; i += 1) {
188
- const row = currentPage.rows[i];
189
- hasRowWithAutoHeight = apiRef.current.rowHasAutoHeight(row.id);
190
- }
191
- if (!hasRowWithAutoHeight) {
192
- firstColumnIndex = binarySearch(Math.abs(left), columnPositions);
193
- lastColumnIndex = binarySearch(Math.abs(left) + containerDimensions.width, columnPositions);
194
- }
195
- }
196
- return {
197
- firstRowIndex,
198
- lastRowIndex,
199
- firstColumnIndex,
200
- lastColumnIndex
201
- };
202
- }, [enabled, enabledForColumns, getNearestIndexToRender, rowsMeta.positions.length, rootProps.autoHeight, rootProps.rowBuffer, currentPage.rows, columnPositions, visibleColumns.length, apiRef, containerDimensions]);
203
- useEnhancedEffect(() => {
204
- if (enabled) {
205
- // TODO a scroll reset should not be necessary
206
- rootRef.current.scrollLeft = 0;
207
- rootRef.current.scrollTop = 0;
208
- } else {
209
- renderZoneRef.current.style.transform = `translate3d(0px, 0px, 0px)`;
76
+ React.useEffect(() => {
77
+ var _gridRootRef$current, _gridRootRef$current2;
78
+ const direction = theme.direction === 'ltr' ? 1 : -1;
79
+ const top = gridRowsMetaSelector(apiRef.current.state).positions[renderContext.firstRowIndex];
80
+ const left = direction * columnPositions[renderContext.firstColumnIndex] - columnPositions[pinnedColumns.left.length];
81
+ (_gridRootRef$current = gridRootRef.current) == null || _gridRootRef$current.style.setProperty('--DataGrid-offsetTop', `${top}px`);
82
+ (_gridRootRef$current2 = gridRootRef.current) == null || _gridRootRef$current2.style.setProperty('--DataGrid-offsetLeft', `${left}px`);
83
+ }, [apiRef, gridRootRef, theme.direction, columnPositions, pinnedColumns.left.length, renderContext]);
84
+ const updateRenderContext = React.useCallback((nextRenderContext, rawRenderContext) => {
85
+ if (areRenderContextsEqual(nextRenderContext, apiRef.current.state.virtualization.renderContext)) {
86
+ return;
210
87
  }
211
- }, [enabled]);
212
- useEnhancedEffect(() => {
213
- setContainerDimensions({
214
- width: rootRef.current.clientWidth,
215
- height: rootRef.current.clientHeight
216
- });
217
- }, [rowsMeta.currentPageTotalHeight]);
218
- const handleResize = React.useCallback(() => {
219
- if (rootRef.current) {
220
- setContainerDimensions({
221
- width: rootRef.current.clientWidth,
222
- height: rootRef.current.clientHeight
88
+ const didRowsIntervalChange = nextRenderContext.firstRowIndex !== previousRowContext.current.firstRowIndex || nextRenderContext.lastRowIndex !== previousRowContext.current.lastRowIndex;
89
+ apiRef.current.setState(state => {
90
+ return _extends({}, state, {
91
+ virtualization: _extends({}, state.virtualization, {
92
+ renderContext: nextRenderContext
93
+ })
223
94
  });
224
- }
225
- }, []);
226
- useGridApiEventHandler(apiRef, 'debouncedResize', handleResize);
227
- const updateRenderZonePosition = React.useCallback(nextRenderContext => {
228
- const [firstRowToRender, lastRowToRender] = getRenderableIndexes({
229
- firstIndex: nextRenderContext.firstRowIndex,
230
- lastIndex: nextRenderContext.lastRowIndex,
231
- minFirstIndex: 0,
232
- maxLastIndex: currentPage.rows.length,
233
- buffer: rootProps.rowBuffer
234
- });
235
- const [initialFirstColumnToRender] = getRenderableIndexes({
236
- firstIndex: nextRenderContext.firstColumnIndex,
237
- lastIndex: nextRenderContext.lastColumnIndex,
238
- minFirstIndex: renderZoneMinColumnIndex,
239
- maxLastIndex: renderZoneMaxColumnIndex,
240
- buffer: rootProps.columnBuffer
241
95
  });
242
- const firstColumnToRender = getFirstNonSpannedColumnToRender({
243
- firstColumnToRender: initialFirstColumnToRender,
244
- apiRef,
245
- firstRowToRender,
246
- lastRowToRender,
247
- visibleRows: currentPage.rows
248
- });
249
- const direction = theme.direction === 'ltr' ? 1 : -1;
250
- const top = gridRowsMetaSelector(apiRef.current.state).positions[firstRowToRender];
251
- const left = direction * gridColumnPositionsSelector(apiRef)[firstColumnToRender]; // Call directly the selector because it might be outdated when this method is called
252
- renderZoneRef.current.style.transform = `translate3d(${left}px, ${top}px, 0px)`;
253
- if (typeof onRenderZonePositioning === 'function') {
254
- onRenderZonePositioning({
255
- top,
256
- left
257
- });
96
+
97
+ // The lazy-loading hook is listening to `renderedRowsIntervalChange`,
98
+ // but only does something if the dimensions are also available.
99
+ // So we wait until we have valid dimensions before publishing the first event.
100
+ if (dimensions.isReady && didRowsIntervalChange) {
101
+ previousRowContext.current = nextRenderContext;
102
+ apiRef.current.publishEvent('renderedRowsIntervalChange', nextRenderContext);
258
103
  }
259
- }, [apiRef, currentPage.rows, onRenderZonePositioning, renderZoneMinColumnIndex, renderZoneMaxColumnIndex, rootProps.columnBuffer, rootProps.rowBuffer, theme.direction]);
260
- const getRenderContext = React.useCallback(() => prevRenderContext.current, []);
261
- const setRenderContext = React.useCallback(nextRenderContext => {
262
- if (prevRenderContext.current && areRenderContextsEqual(nextRenderContext, prevRenderContext.current)) {
263
- updateRenderZonePosition(nextRenderContext);
264
- return;
104
+ previousContext.current = rawRenderContext;
105
+ prevTotalWidth.current = dimensions.columnsTotalWidth;
106
+ }, [apiRef, dimensions.isReady, dimensions.columnsTotalWidth]);
107
+ const triggerUpdateRenderContext = () => {
108
+ const inputs = inputsSelector(apiRef, rootProps, enabled, enabledForColumns);
109
+ const [nextRenderContext, rawRenderContext] = computeRenderContext(inputs, scrollPosition);
110
+
111
+ // Since previous render, we have scrolled...
112
+ const topRowsScrolled = Math.abs(rawRenderContext.firstRowIndex - previousContext.current.firstRowIndex);
113
+ const bottomRowsScrolled = Math.abs(rawRenderContext.lastRowIndex - previousContext.current.lastRowIndex);
114
+ const topColumnsScrolled = Math.abs(rawRenderContext.firstColumnIndex - previousContext.current.firstColumnIndex);
115
+ const bottomColumnsScrolled = Math.abs(rawRenderContext.lastColumnIndex - previousContext.current.lastColumnIndex);
116
+ const shouldUpdate = topRowsScrolled >= rootProps.rowThreshold || bottomRowsScrolled >= rootProps.rowThreshold || topColumnsScrolled >= rootProps.columnThreshold || bottomColumnsScrolled >= rootProps.columnThreshold || prevTotalWidth.current !== dimensions.columnsTotalWidth;
117
+ if (!shouldUpdate) {
118
+ return previousContext.current;
265
119
  }
266
- setRenderContextState(nextRenderContext);
267
- updateRenderZonePosition(nextRenderContext);
268
- const [firstRowToRender, lastRowToRender] = getRenderableIndexes({
269
- firstIndex: nextRenderContext.firstRowIndex,
270
- lastIndex: nextRenderContext.lastRowIndex,
271
- minFirstIndex: 0,
272
- maxLastIndex: currentPage.rows.length,
273
- buffer: rootProps.rowBuffer
274
- });
275
- apiRef.current.publishEvent('renderedRowsIntervalChange', {
276
- firstRowToRender,
277
- lastRowToRender
120
+
121
+ // Prevents batching render context changes
122
+ ReactDOM.flushSync(() => {
123
+ updateRenderContext(nextRenderContext, rawRenderContext);
278
124
  });
279
- prevRenderContext.current = nextRenderContext;
280
- }, [apiRef, setRenderContextState, prevRenderContext, currentPage.rows.length, rootProps.rowBuffer, updateRenderZonePosition]);
281
- useEnhancedEffect(() => {
282
- if (containerDimensions.width == null) {
283
- return;
284
- }
285
- const initialRenderContext = computeRenderContext();
286
- setRenderContext(initialRenderContext);
287
- const {
288
- top,
289
- left
290
- } = scrollPosition.current;
291
- const params = {
292
- top,
293
- left,
294
- renderContext: initialRenderContext
295
- };
296
- apiRef.current.publishEvent('scrollPositionChange', params);
297
- }, [apiRef, computeRenderContext, containerDimensions.width, setRenderContext]);
125
+ return nextRenderContext;
126
+ };
127
+ const forceUpdateRenderContext = () => {
128
+ const inputs = inputsSelector(apiRef, rootProps, enabled, enabledForColumns);
129
+ const [nextRenderContext, rawRenderContext] = computeRenderContext(inputs, scrollPosition);
130
+ updateRenderContext(nextRenderContext, rawRenderContext);
131
+ };
298
132
  const handleScroll = useEventCallback(event => {
299
133
  const {
300
134
  scrollTop,
301
135
  scrollLeft
302
136
  } = event.currentTarget;
303
- scrollPosition.current.top = scrollTop;
304
- scrollPosition.current.left = scrollLeft;
137
+ scrollPosition.top = scrollTop;
138
+ scrollPosition.left = scrollLeft;
305
139
 
306
140
  // On iOS and macOS, negative offsets are possible when swiping past the start
307
- if (!prevRenderContext.current || scrollTop < 0) {
141
+ if (scrollTop < 0) {
308
142
  return;
309
143
  }
310
144
  if (theme.direction === 'ltr') {
@@ -317,26 +151,12 @@ export const useGridVirtualScroller = props => {
317
151
  return;
318
152
  }
319
153
  }
320
-
321
- // When virtualization is disabled, the context never changes during scroll
322
- const nextRenderContext = enabled ? computeRenderContext() : prevRenderContext.current;
323
- const topRowsScrolledSincePreviousRender = Math.abs(nextRenderContext.firstRowIndex - prevRenderContext.current.firstRowIndex);
324
- const bottomRowsScrolledSincePreviousRender = Math.abs(nextRenderContext.lastRowIndex - prevRenderContext.current.lastRowIndex);
325
- const topColumnsScrolledSincePreviousRender = Math.abs(nextRenderContext.firstColumnIndex - prevRenderContext.current.firstColumnIndex);
326
- const bottomColumnsScrolledSincePreviousRender = Math.abs(nextRenderContext.lastColumnIndex - prevRenderContext.current.lastColumnIndex);
327
- const shouldSetState = topRowsScrolledSincePreviousRender >= rootProps.rowThreshold || bottomRowsScrolledSincePreviousRender >= rootProps.rowThreshold || topColumnsScrolledSincePreviousRender >= rootProps.columnThreshold || bottomColumnsScrolledSincePreviousRender >= rootProps.columnThreshold || prevTotalWidth.current !== columnsTotalWidth;
154
+ const nextRenderContext = triggerUpdateRenderContext();
328
155
  apiRef.current.publishEvent('scrollPositionChange', {
329
156
  top: scrollTop,
330
157
  left: scrollLeft,
331
- renderContext: shouldSetState ? nextRenderContext : prevRenderContext.current
332
- }, event);
333
- if (shouldSetState) {
334
- // Prevents batching render context changes
335
- ReactDOM.flushSync(() => {
336
- setRenderContext(nextRenderContext);
337
- });
338
- prevTotalWidth.current = columnsTotalWidth;
339
- }
158
+ renderContext: nextRenderContext
159
+ });
340
160
  });
341
161
  const handleWheel = useEventCallback(event => {
342
162
  apiRef.current.publishEvent('virtualScrollerWheel', {}, event);
@@ -344,139 +164,90 @@ export const useGridVirtualScroller = props => {
344
164
  const handleTouchMove = useEventCallback(event => {
345
165
  apiRef.current.publishEvent('virtualScrollerTouchMove', {}, event);
346
166
  });
347
- const indexOfRowWithFocusedCell = React.useMemo(() => {
348
- if (cellFocus !== null) {
349
- return currentPage.rows.findIndex(row => row.id === cellFocus.id);
167
+ const minFirstColumn = pinnedColumns.left.length;
168
+ const maxLastColumn = visibleColumns.length - pinnedColumns.right.length;
169
+ const getRows = (params = {}) => {
170
+ var _params$rows, _rootProps$slotProps;
171
+ const isLastSection = !hasBottomPinnedRows && params.position === undefined || hasBottomPinnedRows && params.position === 'bottom';
172
+ const isPinnedSection = params.position !== undefined;
173
+ let rowIndexOffset;
174
+ // FIXME: Why is the switch check exhaustiveness not validated with typescript-eslint?
175
+ // eslint-disable-next-line default-case
176
+ switch (params.position) {
177
+ case 'top':
178
+ rowIndexOffset = 0;
179
+ break;
180
+ case 'bottom':
181
+ rowIndexOffset = pinnedRows.top.length + currentPage.rows.length;
182
+ break;
183
+ case undefined:
184
+ rowIndexOffset = pinnedRows.top.length;
185
+ break;
350
186
  }
351
- return -1;
352
- }, [cellFocus, currentPage.rows]);
353
- useGridApiEventHandler(apiRef, 'rowMouseOver', (params, event) => {
354
- var _params$id;
355
- if (event.currentTarget.contains(event.relatedTarget)) {
356
- return;
357
- }
358
- setHoveredRowId((_params$id = params.id) != null ? _params$id : null);
359
- });
360
- useGridApiEventHandler(apiRef, 'rowMouseOut', (params, event) => {
361
- if (event.currentTarget.contains(event.relatedTarget)) {
362
- return;
363
- }
364
- setHoveredRowId(null);
365
- });
366
- const getRows = (params = {
367
- renderContext
368
- }) => {
369
- var _rootProps$slotProps;
370
- const {
371
- onRowRender,
372
- renderContext: nextRenderContext,
373
- minFirstColumn = renderZoneMinColumnIndex,
374
- maxLastColumn = renderZoneMaxColumnIndex,
375
- availableSpace = containerDimensions.width,
376
- rowIndexOffset = 0,
377
- position = 'center'
378
- } = params;
379
- if (!nextRenderContext || availableSpace == null) {
380
- return null;
381
- }
382
- const rowBuffer = enabled ? rootProps.rowBuffer : 0;
383
- const columnBuffer = enabled ? rootProps.columnBuffer : 0;
384
- const [firstRowToRender, lastRowToRender] = getRenderableIndexes({
385
- firstIndex: nextRenderContext.firstRowIndex,
386
- lastIndex: nextRenderContext.lastRowIndex,
387
- minFirstIndex: 0,
388
- maxLastIndex: currentPage.rows.length,
389
- buffer: rowBuffer
390
- });
391
- const renderedRows = [];
392
- if (params.rows) {
393
- params.rows.forEach(row => {
394
- renderedRows.push(row);
395
- apiRef.current.calculateColSpan({
396
- rowId: row.id,
397
- minFirstColumn,
398
- maxLastColumn,
399
- columns: visibleColumns
400
- });
401
- });
402
- } else {
403
- if (!currentPage.range) {
404
- return null;
405
- }
406
- for (let i = firstRowToRender; i < lastRowToRender; i += 1) {
407
- const row = currentPage.rows[i];
408
- renderedRows.push(row);
409
- apiRef.current.calculateColSpan({
410
- rowId: row.id,
411
- minFirstColumn,
412
- maxLastColumn,
413
- columns: visibleColumns
414
- });
415
- }
187
+ const firstRowToRender = renderContext.firstRowIndex;
188
+ const lastRowToRender = renderContext.lastRowIndex;
189
+ const firstColumnToRender = renderContext.firstColumnIndex;
190
+ const lastColumnToRender = renderContext.lastColumnIndex;
191
+ if (!params.rows && !currentPage.range) {
192
+ return [];
416
193
  }
194
+ const renderedRows = (_params$rows = params.rows) != null ? _params$rows : currentPage.rows.slice(firstRowToRender, lastRowToRender);
195
+
417
196
  // If the selected row is not within the current range of rows being displayed,
418
197
  // we need to render it at either the top or bottom of the rows,
419
198
  // depending on whether it is above or below the range.
420
-
421
199
  let isRowWithFocusedCellNotInRange = false;
422
- if (indexOfRowWithFocusedCell > -1) {
200
+ if (!isPinnedSection && indexOfRowWithFocusedCell > -1 && (firstRowToRender > indexOfRowWithFocusedCell || lastRowToRender < indexOfRowWithFocusedCell)) {
201
+ isRowWithFocusedCellNotInRange = true;
423
202
  const rowWithFocusedCell = currentPage.rows[indexOfRowWithFocusedCell];
424
- if (firstRowToRender > indexOfRowWithFocusedCell || lastRowToRender < indexOfRowWithFocusedCell) {
425
- isRowWithFocusedCellNotInRange = true;
426
- if (indexOfRowWithFocusedCell > firstRowToRender) {
427
- renderedRows.push(rowWithFocusedCell);
428
- } else {
429
- renderedRows.unshift(rowWithFocusedCell);
430
- }
431
- apiRef.current.calculateColSpan({
432
- rowId: rowWithFocusedCell.id,
433
- minFirstColumn,
434
- maxLastColumn,
435
- columns: visibleColumns
436
- });
203
+ if (indexOfRowWithFocusedCell > firstRowToRender) {
204
+ renderedRows.push(rowWithFocusedCell);
205
+ } else {
206
+ renderedRows.unshift(rowWithFocusedCell);
437
207
  }
438
208
  }
439
- const [initialFirstColumnToRender, lastColumnToRender] = getRenderableIndexes({
440
- firstIndex: nextRenderContext.firstColumnIndex,
441
- lastIndex: nextRenderContext.lastColumnIndex,
442
- minFirstIndex: minFirstColumn,
443
- maxLastIndex: maxLastColumn,
444
- buffer: columnBuffer
445
- });
446
- const firstColumnToRender = getFirstNonSpannedColumnToRender({
447
- firstColumnToRender: initialFirstColumnToRender,
448
- apiRef,
449
- firstRowToRender,
450
- lastRowToRender,
451
- visibleRows: currentPage.rows
452
- });
453
209
  let isColumnWihFocusedCellNotInRange = false;
454
- if (firstColumnToRender > indexOfColumnWithFocusedCell || lastColumnToRender < indexOfColumnWithFocusedCell) {
210
+ if (!isPinnedSection && (firstColumnToRender > indexOfColumnWithFocusedCell || lastColumnToRender < indexOfColumnWithFocusedCell)) {
455
211
  isColumnWihFocusedCellNotInRange = true;
456
212
  }
457
213
  const {
458
214
  focusedCellColumnIndexNotInRange,
459
215
  renderedColumns
460
- } = getRenderedColumnsRef.current(visibleColumns, firstColumnToRender, lastColumnToRender, minFirstColumn, maxLastColumn, isColumnWihFocusedCellNotInRange ? indexOfColumnWithFocusedCell : -1);
461
- const _ref = ((_rootProps$slotProps = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps.row) || {},
462
- {
463
- style: rootRowStyle
464
- } = _ref,
465
- rootRowProps = _objectWithoutPropertiesLoose(_ref, _excluded);
466
- const invalidatesCachedRowStyle = prevGetRowProps.current !== getRowProps || prevRootRowStyle.current !== rootRowStyle;
467
- if (invalidatesCachedRowStyle) {
468
- rowStyleCache.current = Object.create(null);
469
- }
216
+ } = getRenderedColumns(visibleColumns, firstColumnToRender, lastColumnToRender, minFirstColumn, maxLastColumn, isColumnWihFocusedCellNotInRange ? indexOfColumnWithFocusedCell : -1);
217
+ renderedRows.forEach(row => {
218
+ apiRef.current.calculateColSpan({
219
+ rowId: row.id,
220
+ minFirstColumn,
221
+ maxLastColumn,
222
+ columns: visibleColumns
223
+ });
224
+ if (pinnedColumns.left.length > 0) {
225
+ apiRef.current.calculateColSpan({
226
+ rowId: row.id,
227
+ minFirstColumn: 0,
228
+ maxLastColumn: pinnedColumns.left.length,
229
+ columns: visibleColumns
230
+ });
231
+ }
232
+ if (pinnedColumns.right.length > 0) {
233
+ apiRef.current.calculateColSpan({
234
+ rowId: row.id,
235
+ minFirstColumn: visibleColumns.length - pinnedColumns.right.length,
236
+ maxLastColumn: visibleColumns.length,
237
+ columns: visibleColumns
238
+ });
239
+ }
240
+ });
470
241
  const rows = [];
242
+ const rowProps = (_rootProps$slotProps = rootProps.slotProps) == null ? void 0 : _rootProps$slotProps.row;
471
243
  let isRowWithFocusedCellRendered = false;
472
244
  for (let i = 0; i < renderedRows.length; i += 1) {
473
- var _currentPage$range5;
245
+ var _currentPage$range;
474
246
  const {
475
247
  id,
476
248
  model
477
249
  } = renderedRows[i];
478
250
  const isRowNotVisible = isRowWithFocusedCellNotInRange && cellFocus.id === id;
479
- const lastVisibleRowIndex = isRowWithFocusedCellNotInRange ? firstRowToRender + i === currentPage.rows.length : firstRowToRender + i === currentPage.rows.length - 1;
480
251
  const baseRowHeight = !apiRef.current.rowHasAutoHeight(id) ? apiRef.current.unstable_getRowHeight(id) : 'auto';
481
252
  let isSelected;
482
253
  if (selectedRowsLookup[id] == null) {
@@ -484,8 +255,21 @@ export const useGridVirtualScroller = props => {
484
255
  } else {
485
256
  isSelected = apiRef.current.isRowSelectable(id);
486
257
  }
487
- if (onRowRender) {
488
- onRowRender(id);
258
+ let isFirstVisible = false;
259
+ if (params.position === undefined) {
260
+ isFirstVisible = i === 0;
261
+ }
262
+ let isLastVisible = false;
263
+ if (isLastSection) {
264
+ if (!isPinnedSection) {
265
+ const lastIndex = currentPage.rows.length - 1;
266
+ const isLastVisibleRowIndex = isRowWithFocusedCellNotInRange ? firstRowToRender + i === lastIndex + 1 : firstRowToRender + i === lastIndex;
267
+ if (isLastVisibleRowIndex) {
268
+ isLastVisible = true;
269
+ }
270
+ } else {
271
+ isLastVisible = i === renderedRows.length - 1;
272
+ }
489
273
  }
490
274
  const focusedCell = cellFocus !== null && cellFocus.id === id ? cellFocus.field : null;
491
275
  const columnWithFocusedCellNotInRange = focusedCellColumnIndexNotInRange !== undefined && visibleColumns[focusedCellColumnIndexNotInRange];
@@ -495,16 +279,7 @@ export const useGridVirtualScroller = props => {
495
279
  const cellParams = apiRef.current.getCellParams(id, cellTabIndex.field);
496
280
  tabbableCell = cellParams.cellMode === 'view' ? cellTabIndex.field : null;
497
281
  }
498
- const _ref2 = typeof getRowProps === 'function' && getRowProps(id, model) || {},
499
- {
500
- style: rowStyle
501
- } = _ref2,
502
- rowProps = _objectWithoutPropertiesLoose(_ref2, _excluded2);
503
- if (!rowStyleCache.current[id]) {
504
- const style = _extends({}, rowStyle, rootRowStyle);
505
- rowStyleCache.current[id] = style;
506
- }
507
- let index = rowIndexOffset + ((currentPage == null || (_currentPage$range5 = currentPage.range) == null ? void 0 : _currentPage$range5.firstRowIndex) || 0) + firstRowToRender + i;
282
+ let index = rowIndexOffset + ((currentPage == null || (_currentPage$range = currentPage.range) == null ? void 0 : _currentPage$range.firstRowIndex) || 0) + firstRowToRender + i;
508
283
  if (isRowWithFocusedCellNotInRange && (cellFocus == null ? void 0 : cellFocus.id) === id) {
509
284
  index = indexOfRowWithFocusedCell;
510
285
  isRowWithFocusedCellRendered = true;
@@ -514,87 +289,315 @@ export const useGridVirtualScroller = props => {
514
289
  rows.push( /*#__PURE__*/_jsx(rootProps.slots.row, _extends({
515
290
  row: model,
516
291
  rowId: id,
517
- focusedCellColumnIndexNotInRange: focusedCellColumnIndexNotInRange,
518
- isNotVisible: isRowNotVisible,
292
+ index: index,
519
293
  rowHeight: baseRowHeight,
520
294
  focusedCell: focusedCell,
521
295
  tabbableCell: tabbableCell,
296
+ focusedCellColumnIndexNotInRange: focusedCellColumnIndexNotInRange,
522
297
  renderedColumns: renderedColumnsWithFocusedCell,
523
298
  visibleColumns: visibleColumns,
299
+ pinnedColumns: pinnedColumns,
524
300
  firstColumnToRender: firstColumnToRender,
525
301
  lastColumnToRender: lastColumnToRender,
526
302
  selected: isSelected,
527
- index: index,
528
- containerWidth: availableSpace,
529
- isLastVisible: lastVisibleRowIndex,
530
- position: position
531
- }, rowProps, rootRowProps, {
532
- hovered: hoveredRowId === id,
533
- style: rowStyleCache.current[id]
534
- }), id));
303
+ dimensions: dimensions,
304
+ isFirstVisible: isFirstVisible,
305
+ isLastVisible: isLastVisible,
306
+ isNotVisible: isRowNotVisible
307
+ }, rowProps), id));
308
+ const panel = panels.get(id);
309
+ if (panel) {
310
+ rows.push(panel);
311
+ }
535
312
  }
536
- prevGetRowProps.current = getRowProps;
537
- prevRootRowStyle.current = rootRowStyle;
538
313
  return rows;
539
314
  };
540
- const needsHorizontalScrollbar = containerDimensions.width && columnsTotalWidth >= containerDimensions.width;
315
+ const needsHorizontalScrollbar = outerSize.width && columnsTotalWidth >= outerSize.width;
316
+ const scrollerStyle = React.useMemo(() => ({
317
+ overflowX: !needsHorizontalScrollbar ? 'hidden' : undefined,
318
+ overflowY: rootProps.autoHeight ? 'hidden' : undefined
319
+ }), [needsHorizontalScrollbar, rootProps.autoHeight]);
541
320
  const contentSize = React.useMemo(() => {
542
321
  // In cases where the columns exceed the available width,
543
322
  // the horizontal scrollbar should be shown even when there're no rows.
544
323
  // Keeping 1px as minimum height ensures that the scrollbar will visible if necessary.
545
- const height = Math.max(rowsMeta.currentPageTotalHeight, 1);
546
- let shouldExtendContent = false;
547
- if (rootRef != null && rootRef.current && height <= (rootRef == null ? void 0 : rootRef.current.clientHeight)) {
548
- shouldExtendContent = true;
549
- }
324
+ const height = Math.max(contentHeight, 1);
550
325
  const size = {
551
326
  width: needsHorizontalScrollbar ? columnsTotalWidth : 'auto',
552
- height,
553
- minHeight: shouldExtendContent ? '100%' : 'auto'
327
+ height
554
328
  };
555
- if (rootProps.autoHeight && currentPage.rows.length === 0) {
556
- size.height = getMinimalContentHeight(apiRef, rootProps.rowHeight); // Give room to show the overlay when there no rows.
329
+ if (rootProps.autoHeight) {
330
+ if (currentPage.rows.length === 0) {
331
+ size.height = getMinimalContentHeight(apiRef); // Give room to show the overlay when there no rows.
332
+ } else {
333
+ size.height = contentHeight;
334
+ }
557
335
  }
558
336
  return size;
559
- }, [apiRef, rootRef, columnsTotalWidth, rowsMeta.currentPageTotalHeight, needsHorizontalScrollbar, rootProps.autoHeight, rootProps.rowHeight, currentPage.rows.length]);
337
+ }, [apiRef, columnsTotalWidth, contentHeight, needsHorizontalScrollbar, rootProps.autoHeight, currentPage.rows.length]);
560
338
  React.useEffect(() => {
561
339
  apiRef.current.publishEvent('virtualScrollerContentSizeChange');
562
340
  }, [apiRef, contentSize]);
563
- const rootStyle = React.useMemo(() => {
564
- const style = {};
565
- if (!needsHorizontalScrollbar) {
566
- style.overflowX = 'hidden';
567
- }
568
- if (rootProps.autoHeight) {
569
- style.overflowY = 'hidden';
341
+ useEnhancedEffect(() => {
342
+ // FIXME: Is this really necessary?
343
+ apiRef.current.resize();
344
+ }, [apiRef, rowsMeta.currentPageTotalHeight]);
345
+ useEnhancedEffect(() => {
346
+ if (enabled) {
347
+ // TODO a scroll reset should not be necessary
348
+ scrollerRef.current.scrollLeft = 0;
349
+ scrollerRef.current.scrollTop = 0;
350
+ } else {
351
+ var _gridRootRef$current3, _gridRootRef$current4;
352
+ (_gridRootRef$current3 = gridRootRef.current) == null || _gridRootRef$current3.style.setProperty('--DataGrid-offsetTop', '0px');
353
+ (_gridRootRef$current4 = gridRootRef.current) == null || _gridRootRef$current4.style.setProperty('--DataGrid-offsetLeft', '0px');
570
354
  }
571
- return style;
572
- }, [needsHorizontalScrollbar, rootProps.autoHeight]);
355
+ }, [enabled, gridRootRef, scrollerRef]);
356
+ useRunOnce(outerSize.width !== 0, () => {
357
+ const inputs = inputsSelector(apiRef, rootProps, enabled, enabledForColumns);
358
+ const [initialRenderContext, rawRenderContext] = computeRenderContext(inputs, scrollPosition);
359
+ updateRenderContext(initialRenderContext, rawRenderContext);
360
+ apiRef.current.publishEvent('scrollPositionChange', {
361
+ top: scrollPosition.top,
362
+ left: scrollPosition.left,
363
+ renderContext: initialRenderContext
364
+ });
365
+ });
573
366
  apiRef.current.register('private', {
574
- getRenderContext
367
+ updateRenderContext: forceUpdateRenderContext
575
368
  });
576
369
  return {
577
370
  renderContext,
578
- updateRenderZonePosition,
371
+ setPanels,
579
372
  getRows,
580
- getRootProps: (inputProps = {}) => _extends({
581
- ref: handleRef,
373
+ getContainerProps: () => ({
374
+ ref: mainRef
375
+ }),
376
+ getScrollerProps: () => ({
377
+ ref: scrollerRef,
378
+ tabIndex: -1,
582
379
  onScroll: handleScroll,
583
380
  onWheel: handleWheel,
584
- onTouchMove: handleTouchMove
585
- }, inputProps, {
586
- style: inputProps.style ? _extends({}, inputProps.style, rootStyle) : rootStyle,
381
+ onTouchMove: handleTouchMove,
382
+ style: scrollerStyle,
587
383
  role: 'presentation'
588
384
  }),
589
- getContentProps: ({
590
- style
591
- } = {}) => ({
592
- style: style ? _extends({}, style, contentSize) : contentSize,
385
+ getContentProps: () => ({
386
+ style: contentSize,
593
387
  role: 'presentation'
594
388
  }),
595
389
  getRenderZoneProps: () => ({
596
390
  ref: renderZoneRef,
597
391
  role: 'rowgroup'
392
+ }),
393
+ getScrollbarVerticalProps: () => ({
394
+ ref: scrollbarVerticalRef,
395
+ role: 'presentation'
396
+ }),
397
+ getScrollbarHorizontalProps: () => ({
398
+ ref: scrollbarHorizontalRef,
399
+ role: 'presentation'
598
400
  })
599
401
  };
600
- };
402
+ };
403
+ function createGetRenderedColumns() {
404
+ return defaultMemoize((columns, firstColumnToRender, lastColumnToRender, minFirstColumn, maxLastColumn, indexOfColumnWithFocusedCell) => {
405
+ // If the selected column is not within the current range of columns being displayed,
406
+ // we need to render it at either the left or right of the columns,
407
+ // depending on whether it is above or below the range.
408
+ let focusedCellColumnIndexNotInRange;
409
+ const renderedColumns = columns.slice(firstColumnToRender, lastColumnToRender);
410
+ if (indexOfColumnWithFocusedCell > -1) {
411
+ // check if it is not on the left pinned column.
412
+ if (firstColumnToRender > indexOfColumnWithFocusedCell && indexOfColumnWithFocusedCell >= minFirstColumn) {
413
+ focusedCellColumnIndexNotInRange = indexOfColumnWithFocusedCell;
414
+ }
415
+ // check if it is not on the right pinned column.
416
+ else if (lastColumnToRender < indexOfColumnWithFocusedCell && indexOfColumnWithFocusedCell < maxLastColumn) {
417
+ focusedCellColumnIndexNotInRange = indexOfColumnWithFocusedCell;
418
+ }
419
+ }
420
+ return {
421
+ focusedCellColumnIndexNotInRange,
422
+ renderedColumns
423
+ };
424
+ });
425
+ }
426
+ function inputsSelector(apiRef, rootProps, enabled, enabledForColumns) {
427
+ const dimensions = gridDimensionsSelector(apiRef.current.state);
428
+ const currentPage = getVisibleRows(apiRef, rootProps);
429
+ return {
430
+ enabled,
431
+ enabledForColumns,
432
+ apiRef,
433
+ autoHeight: rootProps.autoHeight,
434
+ rowBuffer: rootProps.rowBuffer,
435
+ columnBuffer: rootProps.columnBuffer,
436
+ leftPinnedWidth: dimensions.leftPinnedWidth,
437
+ columnsTotalWidth: dimensions.columnsTotalWidth,
438
+ viewportInnerWidth: dimensions.viewportInnerSize.width,
439
+ viewportInnerHeight: dimensions.viewportInnerSize.height,
440
+ rowsMeta: gridRowsMetaSelector(apiRef.current.state),
441
+ columnPositions: gridColumnPositionsSelector(apiRef),
442
+ rows: currentPage.rows,
443
+ range: currentPage.range,
444
+ pinnedColumns: gridVisiblePinnedColumnDefinitionsSelector(apiRef),
445
+ visibleColumns: gridVisibleColumnDefinitionsSelector(apiRef)
446
+ };
447
+ }
448
+ function computeRenderContext(inputs, scrollPosition) {
449
+ let renderContext;
450
+ if (!inputs.enabled) {
451
+ renderContext = {
452
+ firstRowIndex: 0,
453
+ lastRowIndex: inputs.rows.length,
454
+ firstColumnIndex: 0,
455
+ lastColumnIndex: inputs.visibleColumns.length
456
+ };
457
+ } else {
458
+ const {
459
+ top,
460
+ left
461
+ } = scrollPosition;
462
+ const realLeft = Math.abs(left) + inputs.leftPinnedWidth;
463
+
464
+ // Clamp the value because the search may return an index out of bounds.
465
+ // In the last index, this is not needed because Array.slice doesn't include it.
466
+ const firstRowIndex = Math.min(getNearestIndexToRender(inputs, top), inputs.rowsMeta.positions.length - 1);
467
+ const lastRowIndex = inputs.autoHeight ? firstRowIndex + inputs.rows.length : getNearestIndexToRender(inputs, top + inputs.viewportInnerHeight);
468
+ let firstColumnIndex = 0;
469
+ let lastColumnIndex = inputs.columnPositions.length;
470
+ if (inputs.enabledForColumns) {
471
+ let hasRowWithAutoHeight = false;
472
+ const [firstRowToRender, lastRowToRender] = getIndexesToRender({
473
+ firstIndex: firstRowIndex,
474
+ lastIndex: lastRowIndex,
475
+ minFirstIndex: 0,
476
+ maxLastIndex: inputs.rows.length,
477
+ buffer: inputs.rowBuffer
478
+ });
479
+ for (let i = firstRowToRender; i < lastRowToRender && !hasRowWithAutoHeight; i += 1) {
480
+ const row = inputs.rows[i];
481
+ hasRowWithAutoHeight = inputs.apiRef.current.rowHasAutoHeight(row.id);
482
+ }
483
+ if (!hasRowWithAutoHeight) {
484
+ firstColumnIndex = binarySearch(realLeft, inputs.columnPositions, {
485
+ atStart: true,
486
+ lastPosition: inputs.columnsTotalWidth
487
+ });
488
+ lastColumnIndex = binarySearch(realLeft + inputs.viewportInnerWidth, inputs.columnPositions);
489
+ }
490
+ }
491
+ renderContext = {
492
+ firstRowIndex,
493
+ lastRowIndex,
494
+ firstColumnIndex,
495
+ lastColumnIndex
496
+ };
497
+ }
498
+ const actualRenderContext = deriveRenderContext(inputs.apiRef, inputs.rowBuffer, inputs.columnBuffer, inputs.rows, inputs.pinnedColumns, inputs.visibleColumns, renderContext);
499
+ return [actualRenderContext, renderContext];
500
+ }
501
+ function getNearestIndexToRender(inputs, offset) {
502
+ var _inputs$range, _inputs$range2;
503
+ const lastMeasuredIndexRelativeToAllRows = inputs.apiRef.current.getLastMeasuredRowIndex();
504
+ let allRowsMeasured = lastMeasuredIndexRelativeToAllRows === Infinity;
505
+ if ((_inputs$range = inputs.range) != null && _inputs$range.lastRowIndex && !allRowsMeasured) {
506
+ // Check if all rows in this page are already measured
507
+ allRowsMeasured = lastMeasuredIndexRelativeToAllRows >= inputs.range.lastRowIndex;
508
+ }
509
+ const lastMeasuredIndexRelativeToCurrentPage = clamp(lastMeasuredIndexRelativeToAllRows - (((_inputs$range2 = inputs.range) == null ? void 0 : _inputs$range2.firstRowIndex) || 0), 0, inputs.rowsMeta.positions.length);
510
+ if (allRowsMeasured || inputs.rowsMeta.positions[lastMeasuredIndexRelativeToCurrentPage] >= offset) {
511
+ // If all rows were measured (when no row has "auto" as height) or all rows before the offset
512
+ // were measured, then use a binary search because it's faster.
513
+ return binarySearch(offset, inputs.rowsMeta.positions);
514
+ }
515
+
516
+ // Otherwise, use an exponential search.
517
+ // If rows have "auto" as height, their positions will be based on estimated heights.
518
+ // In this case, we can skip several steps until we find a position higher than the offset.
519
+ // Inspired by https://github.com/bvaughn/react-virtualized/blob/master/source/Grid/utils/CellSizeAndPositionManager.js
520
+ return exponentialSearch(offset, inputs.rowsMeta.positions, lastMeasuredIndexRelativeToCurrentPage);
521
+ }
522
+
523
+ /**
524
+ * Accepts as input a raw render context (the area visible in the viewport) and adds
525
+ * computes the actual render context based on pinned elements, buffer dimensions and
526
+ * spanning.
527
+ */
528
+ function deriveRenderContext(apiRef, rowBuffer, columnBuffer, rows, pinnedColumns, visibleColumns, nextRenderContext) {
529
+ const [firstRowToRender, lastRowToRender] = getIndexesToRender({
530
+ firstIndex: nextRenderContext.firstRowIndex,
531
+ lastIndex: nextRenderContext.lastRowIndex,
532
+ minFirstIndex: 0,
533
+ maxLastIndex: rows.length,
534
+ buffer: rowBuffer
535
+ });
536
+ const [initialFirstColumnToRender, lastColumnToRender] = getIndexesToRender({
537
+ firstIndex: nextRenderContext.firstColumnIndex,
538
+ lastIndex: nextRenderContext.lastColumnIndex,
539
+ minFirstIndex: pinnedColumns.left.length,
540
+ maxLastIndex: visibleColumns.length - pinnedColumns.right.length,
541
+ buffer: columnBuffer
542
+ });
543
+ const firstColumnToRender = getFirstNonSpannedColumnToRender({
544
+ firstColumnToRender: initialFirstColumnToRender,
545
+ apiRef,
546
+ firstRowToRender,
547
+ lastRowToRender,
548
+ visibleRows: rows
549
+ });
550
+ return {
551
+ firstRowIndex: firstRowToRender,
552
+ lastRowIndex: lastRowToRender,
553
+ firstColumnIndex: firstColumnToRender,
554
+ lastColumnIndex: lastColumnToRender
555
+ };
556
+ }
557
+ /**
558
+ * Use binary search to avoid looping through all possible positions.
559
+ * The `options.atStart` provides the possibility to match for the first element that
560
+ * intersects the screen, even if said element's start position is before `offset`. In
561
+ * other words, we search for `offset + width`.
562
+ */
563
+ function binarySearch(offset, positions, options = undefined, sliceStart = 0, sliceEnd = positions.length) {
564
+ if (positions.length <= 0) {
565
+ return -1;
566
+ }
567
+ if (sliceStart >= sliceEnd) {
568
+ return sliceStart;
569
+ }
570
+ const pivot = sliceStart + Math.floor((sliceEnd - sliceStart) / 2);
571
+ const position = positions[pivot];
572
+ let isBefore;
573
+ if (options != null && options.atStart) {
574
+ const width = (pivot === positions.length - 1 ? options.lastPosition : positions[pivot + 1]) - position;
575
+ isBefore = offset - width < position;
576
+ } else {
577
+ isBefore = offset <= position;
578
+ }
579
+ return isBefore ? binarySearch(offset, positions, options, sliceStart, pivot) : binarySearch(offset, positions, options, pivot + 1, sliceEnd);
580
+ }
581
+ function exponentialSearch(offset, positions, index) {
582
+ let interval = 1;
583
+ while (index < positions.length && Math.abs(positions[index]) < offset) {
584
+ index += interval;
585
+ interval *= 2;
586
+ }
587
+ return binarySearch(offset, positions, undefined, Math.floor(index / 2), Math.min(index, positions.length));
588
+ }
589
+ function getIndexesToRender({
590
+ firstIndex,
591
+ lastIndex,
592
+ buffer,
593
+ minFirstIndex,
594
+ maxLastIndex
595
+ }) {
596
+ return [clamp(firstIndex - buffer, minFirstIndex, maxLastIndex), clamp(lastIndex + buffer, minFirstIndex, maxLastIndex)];
597
+ }
598
+ export function areRenderContextsEqual(context1, context2) {
599
+ if (context1 === context2) {
600
+ return true;
601
+ }
602
+ return context1.firstRowIndex === context2.firstRowIndex && context1.lastRowIndex === context2.lastRowIndex && context1.firstColumnIndex === context2.firstColumnIndex && context1.lastColumnIndex === context2.lastColumnIndex;
603
+ }