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

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