@12-apps/ui 6.38.0 → 6.39.1

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 (334) hide show
  1. package/dist/_internal/components/data-display/DataGrid/DataGrid.body.js +3 -2
  2. package/dist/_internal/components/data-display/DataGrid/DataGrid.cells.js +2 -1
  3. package/dist/_internal/components/data-display/DataGrid/DataGrid.js +4 -4
  4. package/dist/_internal/components/data-display/DataGrid/DataGrid.model.js +2 -1
  5. package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +19 -19
  6. package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +26 -26
  7. package/dist/_internal/components/data-display/DataViews/SaveViewModal.js +5 -5
  8. package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +4 -4
  9. package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +3 -3
  10. package/dist/_internal/components/data-display/DataViews/base-list-card.js +5 -5
  11. package/dist/_internal/components/data-display/DataViews/data-views-columns.js +2 -2
  12. package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +3 -3
  13. package/dist/_internal/components/data-display/DataViews/data-views-display-tabs.js +2 -2
  14. package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +8 -8
  15. package/dist/_internal/components/data-display/DataViews/data-views-grid-helpers.js +1 -1
  16. package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +16 -16
  17. package/dist/_internal/components/data-display/DataViews/data-views-layout-context.js +1 -1
  18. package/dist/_internal/components/data-display/DataViews/data-views-overflow-costs.js +4 -3
  19. package/dist/_internal/components/data-display/DataViews/data-views-overflow.js +3 -2
  20. package/dist/_internal/components/data-display/DataViews/data-views-scope-tabs.js +2 -2
  21. package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +6 -6
  22. package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +6 -6
  23. package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +5 -5
  24. package/dist/_internal/components/data-display/DataViews/list-card-rails.js +2 -2
  25. package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +3 -3
  26. package/dist/_internal/components/data-display/FleetMap/FleetBody.js +9 -9
  27. package/dist/_internal/components/data-display/FleetMap/FleetCanvas.js +8 -8
  28. package/dist/_internal/components/data-display/FleetMap/FleetMap.js +10 -10
  29. package/dist/_internal/components/data-display/LazyImage/LazyImage.js +1 -1
  30. package/dist/_internal/components/data-display/MapPreview/MapDecorations.js +2 -2
  31. package/dist/_internal/components/data-display/MapPreview/MapPreview.hooks.js +2 -2
  32. package/dist/_internal/components/data-display/MapPreview/MapPreview.js +7 -7
  33. package/dist/_internal/components/data-display/MapPreview/MapTiles.js +2 -2
  34. package/dist/_internal/components/data-display/MapPreview/StaticMapView.js +4 -4
  35. package/dist/_internal/components/data-display/MapPreview/mapProjection.js +3 -3
  36. package/dist/_internal/components/data-display/MapPreview/useMapPreview.js +3 -3
  37. package/dist/_internal/components/data-display/Table/Table.helpers.js +5 -3
  38. package/dist/_internal/components/data-display/Table/Table.hooks.js +2 -1
  39. package/dist/_internal/components/data-display/Table/Table.js +4 -4
  40. package/dist/_internal/components/data-display/Table/TableParts.hooks.js +4 -2
  41. package/dist/_internal/components/data-display/Table/TableParts.js +4 -2
  42. package/dist/_internal/components/data-display/index.js +19 -19
  43. package/dist/_internal/components/form/Calendar/Calendar.js +5 -4
  44. package/dist/_internal/components/form/Calendar/CalendarDay.js +2 -1
  45. package/dist/_internal/components/form/Calendar/CalendarDayCell.js +3 -2
  46. package/dist/_internal/components/form/Calendar/CalendarMonth.js +4 -3
  47. package/dist/_internal/components/form/DateRangePicker/DateRangePicker.js +5 -5
  48. package/dist/_internal/components/form/Switch/Switch.js +4 -4
  49. package/dist/_internal/components/form/Switch/Switch.metrics.js +5 -1
  50. package/dist/_internal/components/form/Switch/Switch.parts.js +3 -3
  51. package/dist/_internal/components/form/Switch/Switch.styles.js +2 -2
  52. package/dist/_internal/components/form/index.js +9 -9
  53. package/dist/_internal/components/index.js +38 -38
  54. package/dist/_internal/components/layout/CardGrid/CardGrid.js +2 -1
  55. package/dist/_internal/components/layout/Resizable/Resizable.helpers.js +8 -3
  56. package/dist/_internal/components/layout/Resizable/Resizable.hooks.js +3 -2
  57. package/dist/_internal/components/layout/Resizable/Resizable.js +4 -3
  58. package/dist/_internal/components/layout/ScrollArea/ScrollArea.helpers.js +1 -1
  59. package/dist/_internal/components/layout/ScrollArea/ScrollArea.js +2 -2
  60. package/dist/_internal/components/layout/index.js +5 -5
  61. package/dist/_internal/components/utility/InfiniteScroll/InfiniteScroll.hooks.js +1 -1
  62. package/dist/_internal/components/utility/InfiniteScroll/InfiniteScroll.js +4 -3
  63. package/dist/_internal/components/utility/InfiniteScroll/InfiniteScroll.parts.js +2 -1
  64. package/dist/_internal/components/utility/VirtualList/VirtualList.hooks.js +6 -3
  65. package/dist/_internal/components/utility/VirtualList/VirtualList.js +3 -2
  66. package/dist/_internal/components/utility/index.js +5 -5
  67. package/dist/{chunk-J2DAQQQH.js → chunk-222HN7GK.js} +33 -64
  68. package/dist/chunk-222HN7GK.js.map +1 -0
  69. package/dist/{chunk-MR2HKBHS.js → chunk-27LOJVR3.js} +2 -2
  70. package/dist/{chunk-S3D5VBHW.js → chunk-3YOXVNO4.js} +7 -7
  71. package/dist/{chunk-CZIX4BW2.js → chunk-4ALF5PB5.js} +3 -3
  72. package/dist/{chunk-XJPJ6ESI.js → chunk-4OAKGKK5.js} +3 -3
  73. package/dist/{chunk-4CHROSWR.js → chunk-5ETBB2DG.js} +2 -2
  74. package/dist/{chunk-ATSHKSSD.js → chunk-5KNDAC24.js} +20 -7
  75. package/dist/chunk-5KNDAC24.js.map +1 -0
  76. package/dist/{chunk-ULTOQ6ZV.js → chunk-5LWB4BYX.js} +80 -89
  77. package/dist/chunk-5LWB4BYX.js.map +1 -0
  78. package/dist/{chunk-46UPILLK.js → chunk-5NT2M2JI.js} +2 -2
  79. package/dist/{chunk-H5BEWPEY.js → chunk-6N2EDWMG.js} +2 -2
  80. package/dist/{chunk-GJQYM3PM.js → chunk-6PU3JYVY.js} +2 -2
  81. package/dist/{chunk-PUBPZOQJ.js → chunk-AG3DY5TH.js} +8 -5
  82. package/dist/chunk-AG3DY5TH.js.map +1 -0
  83. package/dist/{chunk-PPRV4LTM.js → chunk-BWHOCNGW.js} +4 -4
  84. package/dist/chunk-BWHOCNGW.js.map +1 -0
  85. package/dist/{chunk-TUBCN4DJ.js → chunk-CB6DTWD5.js} +7 -7
  86. package/dist/chunk-CB6DTWD5.js.map +1 -0
  87. package/dist/{chunk-ZAY6OA6F.js → chunk-D4FZ3ANG.js} +15 -5
  88. package/dist/chunk-D4FZ3ANG.js.map +1 -0
  89. package/dist/{chunk-Y7F5JBAT.js → chunk-DDRKYNPB.js} +2 -2
  90. package/dist/{chunk-DLJGBJZW.js → chunk-DGMDQHMI.js} +16 -9
  91. package/dist/chunk-DGMDQHMI.js.map +1 -0
  92. package/dist/{chunk-IAGOUTI6.js → chunk-DNT5PZLF.js} +21 -12
  93. package/dist/chunk-DNT5PZLF.js.map +1 -0
  94. package/dist/{chunk-DZA7RSLX.js → chunk-DVSO3EG6.js} +19 -11
  95. package/dist/chunk-DVSO3EG6.js.map +1 -0
  96. package/dist/{chunk-OS6KPL4D.js → chunk-EHYI2WCJ.js} +4 -4
  97. package/dist/{chunk-NB3FGWU4.js → chunk-EQXIW5MQ.js} +2 -2
  98. package/dist/{chunk-C66RGVAS.js → chunk-ERY6D2OV.js} +6 -4
  99. package/dist/chunk-ERY6D2OV.js.map +1 -0
  100. package/dist/{chunk-M2JTIH5M.js → chunk-F44R7US6.js} +2 -2
  101. package/dist/{chunk-AROBXRC5.js → chunk-F7JTIHV5.js} +18 -7
  102. package/dist/chunk-F7JTIHV5.js.map +1 -0
  103. package/dist/{chunk-T7DE44SP.js → chunk-FF2D7V7T.js} +6 -4
  104. package/dist/chunk-FF2D7V7T.js.map +1 -0
  105. package/dist/{chunk-XJJXBUPN.js → chunk-FX26DAFF.js} +2 -2
  106. package/dist/{chunk-R6SN73RX.js → chunk-GLHNMTP6.js} +7 -7
  107. package/dist/{chunk-YU26GBNX.js → chunk-H3AQQOTI.js} +9 -4
  108. package/dist/chunk-H3AQQOTI.js.map +1 -0
  109. package/dist/{chunk-HTZNB6IV.js → chunk-H5ZTIELC.js} +23 -8
  110. package/dist/chunk-H5ZTIELC.js.map +1 -0
  111. package/dist/{chunk-GSFNH4C5.js → chunk-HBP2OU4Q.js} +15 -8
  112. package/dist/chunk-HBP2OU4Q.js.map +1 -0
  113. package/dist/{chunk-I4QA2F4L.js → chunk-HBRQPG7H.js} +5 -5
  114. package/dist/{chunk-HGMBY5LP.js → chunk-HQWJUHR4.js} +18 -11
  115. package/dist/chunk-HQWJUHR4.js.map +1 -0
  116. package/dist/{chunk-CNQUCNEA.js → chunk-I3F4C5SS.js} +3 -3
  117. package/dist/{chunk-UFJYJHQI.js → chunk-J5VWGQSR.js} +2 -2
  118. package/dist/{chunk-MTFCPPZ5.js → chunk-JWZJSXI5.js} +3 -2
  119. package/dist/chunk-JWZJSXI5.js.map +1 -0
  120. package/dist/{chunk-4JFL62K3.js → chunk-K7FSTB2K.js} +3 -3
  121. package/dist/{chunk-FFCJ7NR2.js → chunk-KRQUPE4K.js} +4 -4
  122. package/dist/{chunk-2OYFTSG4.js → chunk-KXLUMEDX.js} +2 -2
  123. package/dist/{chunk-DVAAUWTC.js → chunk-LCHCE2G5.js} +2 -2
  124. package/dist/{chunk-G4HBNILE.js → chunk-LEHMWJNZ.js} +3 -3
  125. package/dist/{chunk-P6TNXBDA.js → chunk-MYKWJCR7.js} +9 -9
  126. package/dist/chunk-MYKWJCR7.js.map +1 -0
  127. package/dist/{chunk-TQ6FPOPD.js → chunk-ODW2D5PN.js} +39 -30
  128. package/dist/chunk-ODW2D5PN.js.map +1 -0
  129. package/dist/{chunk-RZYSKQTS.js → chunk-PCBZYORN.js} +3 -3
  130. package/dist/{chunk-5OBXEMQO.js → chunk-PRIBOWX4.js} +3 -3
  131. package/dist/{chunk-F42MJOHM.js → chunk-PVM7XTLZ.js} +64 -62
  132. package/dist/chunk-PVM7XTLZ.js.map +1 -0
  133. package/dist/{chunk-3TDVGZZN.js → chunk-QBTBRJ2Q.js} +37 -13
  134. package/dist/chunk-QBTBRJ2Q.js.map +1 -0
  135. package/dist/{chunk-2WFDHFK4.js → chunk-QNCWSDXE.js} +26 -11
  136. package/dist/chunk-QNCWSDXE.js.map +1 -0
  137. package/dist/{chunk-PQECNGDE.js → chunk-QSRZOXQI.js} +2 -2
  138. package/dist/{chunk-RHIDWUK7.js → chunk-QUWK7SYN.js} +1 -2
  139. package/dist/chunk-QUWK7SYN.js.map +1 -0
  140. package/dist/{chunk-UN5INW6K.js → chunk-R53ZOW4B.js} +8 -4
  141. package/dist/chunk-R53ZOW4B.js.map +1 -0
  142. package/dist/{chunk-DCJSHYE5.js → chunk-RSDYS5B3.js} +4 -4
  143. package/dist/{chunk-N5GVW6RO.js → chunk-S6IWKDWT.js} +2 -2
  144. package/dist/{chunk-TKC6WHGB.js → chunk-SBIZXZPP.js} +2 -2
  145. package/dist/{chunk-D5SZXH7Q.js → chunk-TNBJ4DK4.js} +7 -3
  146. package/dist/chunk-TNBJ4DK4.js.map +1 -0
  147. package/dist/{chunk-PMOEG36E.js → chunk-XZJM6EPC.js} +8 -6
  148. package/dist/chunk-XZJM6EPC.js.map +1 -0
  149. package/dist/{chunk-QF6LTUCE.js → chunk-Y2X7LYIN.js} +4 -4
  150. package/dist/chunk-Y2X7LYIN.js.map +1 -0
  151. package/dist/{chunk-UEVHI62V.js → chunk-YCCY77W5.js} +2 -2
  152. package/dist/{chunk-DF4K5XVW.js → chunk-YZVR5ROE.js} +14 -6
  153. package/dist/chunk-YZVR5ROE.js.map +1 -0
  154. package/dist/{chunk-AUSUCZYR.js → chunk-ZBVU2YWV.js} +5 -5
  155. package/dist/chunk-ZBVU2YWV.js.map +1 -0
  156. package/dist/{chunk-VZIB5W5L.js → chunk-ZGCPDA3F.js} +2 -2
  157. package/dist/data-display/DataGrid.js +4 -4
  158. package/dist/data-display/DataViews.js +29 -29
  159. package/dist/data-display/FleetMap.js +10 -10
  160. package/dist/data-display/LazyImage.js +1 -1
  161. package/dist/data-display/MapPreview.js +7 -7
  162. package/dist/data-display/Table.js +4 -4
  163. package/dist/form/Calendar.js +5 -4
  164. package/dist/form/DateRangePicker.js +5 -5
  165. package/dist/form/Switch.js +4 -4
  166. package/dist/layout/CardGrid.js +2 -1
  167. package/dist/layout/Resizable.js +4 -3
  168. package/dist/layout/ScrollArea.js +2 -2
  169. package/dist/native/form/Switch.js +3 -1
  170. package/dist/native/form/Switch.js.map +1 -1
  171. package/dist/types/components/data-display/DataGrid/DataGrid.body.d.ts.map +1 -1
  172. package/dist/types/components/data-display/DataGrid/DataGrid.cells.d.ts +4 -2
  173. package/dist/types/components/data-display/DataGrid/DataGrid.cells.d.ts.map +1 -1
  174. package/dist/types/components/data-display/DataGrid/DataGrid.model.d.ts +7 -1
  175. package/dist/types/components/data-display/DataGrid/DataGrid.model.d.ts.map +1 -1
  176. package/dist/types/components/data-display/DataGrid/DataGrid.types.d.ts +10 -4
  177. package/dist/types/components/data-display/DataGrid/DataGrid.types.d.ts.map +1 -1
  178. package/dist/types/components/data-display/DataViews/data-views-columns.d.ts.map +1 -1
  179. package/dist/types/components/data-display/DataViews/data-views-grid-helpers.d.ts +2 -0
  180. package/dist/types/components/data-display/DataViews/data-views-grid-helpers.d.ts.map +1 -1
  181. package/dist/types/components/data-display/DataViews/data-views-layout-context.d.ts +7 -3
  182. package/dist/types/components/data-display/DataViews/data-views-layout-context.d.ts.map +1 -1
  183. package/dist/types/components/data-display/DataViews/data-views-overflow-costs.d.ts +19 -9
  184. package/dist/types/components/data-display/DataViews/data-views-overflow-costs.d.ts.map +1 -1
  185. package/dist/types/components/data-display/DataViews/data-views-overflow.d.ts.map +1 -1
  186. package/dist/types/components/data-display/LazyImage/LazyImage.d.ts.map +1 -1
  187. package/dist/types/components/data-display/LazyImage/LazyImage.types.d.ts +3 -1
  188. package/dist/types/components/data-display/LazyImage/LazyImage.types.d.ts.map +1 -1
  189. package/dist/types/components/data-display/MapPreview/MapTiles.d.ts.map +1 -1
  190. package/dist/types/components/data-display/MapPreview/mapProjection.d.ts +6 -1
  191. package/dist/types/components/data-display/MapPreview/mapProjection.d.ts.map +1 -1
  192. package/dist/types/components/data-display/Table/Table.helpers.d.ts +6 -0
  193. package/dist/types/components/data-display/Table/Table.helpers.d.ts.map +1 -1
  194. package/dist/types/components/data-display/Table/Table.hooks.d.ts +9 -1
  195. package/dist/types/components/data-display/Table/Table.hooks.d.ts.map +1 -1
  196. package/dist/types/components/data-display/Table/Table.types.d.ts +6 -2
  197. package/dist/types/components/data-display/Table/Table.types.d.ts.map +1 -1
  198. package/dist/types/components/data-display/Table/TableParts.d.ts +2 -0
  199. package/dist/types/components/data-display/Table/TableParts.d.ts.map +1 -1
  200. package/dist/types/components/form/Calendar/Calendar.d.ts.map +1 -1
  201. package/dist/types/components/form/Calendar/CalendarDay.d.ts.map +1 -1
  202. package/dist/types/components/form/Calendar/CalendarMonth.d.ts.map +1 -1
  203. package/dist/types/components/form/Switch/Switch.metrics.d.ts +13 -3
  204. package/dist/types/components/form/Switch/Switch.metrics.d.ts.map +1 -1
  205. package/dist/types/components/form/Switch/Switch.styles.d.ts.map +1 -1
  206. package/dist/types/components/layout/CardGrid/CardGrid.d.ts +9 -7
  207. package/dist/types/components/layout/CardGrid/CardGrid.d.ts.map +1 -1
  208. package/dist/types/components/layout/Resizable/Resizable.d.ts.map +1 -1
  209. package/dist/types/components/layout/Resizable/Resizable.helpers.d.ts +21 -9
  210. package/dist/types/components/layout/Resizable/Resizable.helpers.d.ts.map +1 -1
  211. package/dist/types/components/layout/Resizable/Resizable.hooks.d.ts +13 -3
  212. package/dist/types/components/layout/Resizable/Resizable.hooks.d.ts.map +1 -1
  213. package/dist/types/components/layout/Resizable/Resizable.types.d.ts +10 -0
  214. package/dist/types/components/layout/Resizable/Resizable.types.d.ts.map +1 -1
  215. package/dist/types/components/layout/ScrollArea/ScrollArea.d.ts.map +1 -1
  216. package/dist/types/components/layout/ScrollArea/ScrollArea.helpers.d.ts +1 -1
  217. package/dist/types/components/layout/ScrollArea/ScrollArea.helpers.d.ts.map +1 -1
  218. package/dist/types/components/layout/ScrollArea/ScrollArea.types.d.ts +4 -1
  219. package/dist/types/components/layout/ScrollArea/ScrollArea.types.d.ts.map +1 -1
  220. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.d.ts.map +1 -1
  221. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.hooks.d.ts +3 -2
  222. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.hooks.d.ts.map +1 -1
  223. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.parts.d.ts +3 -2
  224. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.parts.d.ts.map +1 -1
  225. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.types.d.ts +9 -0
  226. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.types.d.ts.map +1 -1
  227. package/dist/types/components/utility/VirtualList/VirtualList.d.ts.map +1 -1
  228. package/dist/types/components/utility/VirtualList/VirtualList.hooks.d.ts +24 -28
  229. package/dist/types/components/utility/VirtualList/VirtualList.hooks.d.ts.map +1 -1
  230. package/dist/types/components/utility/VirtualList/VirtualList.types.d.ts +17 -0
  231. package/dist/types/components/utility/VirtualList/VirtualList.types.d.ts.map +1 -1
  232. package/dist/types-native/components/form/Switch/Switch.metrics.d.ts +13 -3
  233. package/dist/types-native/components/form/Switch/Switch.metrics.d.ts.map +1 -1
  234. package/dist/utility/InfiniteScroll.js +4 -3
  235. package/dist/utility/VirtualList.js +3 -2
  236. package/package.json +1 -1
  237. package/src/components/data-display/DataGrid/DataGrid.body.tsx +27 -7
  238. package/src/components/data-display/DataGrid/DataGrid.cells.tsx +33 -9
  239. package/src/components/data-display/DataGrid/DataGrid.model.ts +24 -11
  240. package/src/components/data-display/DataGrid/DataGrid.types.ts +12 -6
  241. package/src/components/data-display/DataViews/data-views-columns.ts +14 -3
  242. package/src/components/data-display/DataViews/data-views-grid-helpers.tsx +5 -3
  243. package/src/components/data-display/DataViews/data-views-layout-context.tsx +12 -9
  244. package/src/components/data-display/DataViews/data-views-overflow-costs.ts +32 -14
  245. package/src/components/data-display/DataViews/data-views-overflow.ts +40 -26
  246. package/src/components/data-display/LazyImage/LazyImage.tsx +5 -3
  247. package/src/components/data-display/LazyImage/LazyImage.types.ts +3 -1
  248. package/src/components/data-display/MapPreview/MapTiles.tsx +16 -9
  249. package/src/components/data-display/MapPreview/mapProjection.ts +10 -5
  250. package/src/components/data-display/Table/Table.helpers.ts +7 -1
  251. package/src/components/data-display/Table/Table.hooks.ts +16 -5
  252. package/src/components/data-display/Table/Table.types.ts +6 -2
  253. package/src/components/data-display/Table/TableParts.tsx +38 -42
  254. package/src/components/form/Calendar/Calendar.tsx +4 -2
  255. package/src/components/form/Calendar/CalendarDay.tsx +6 -3
  256. package/src/components/form/Calendar/CalendarMonth.tsx +6 -3
  257. package/src/components/form/Switch/Switch.metrics.ts +19 -5
  258. package/src/components/form/Switch/Switch.styles.ts +5 -3
  259. package/src/components/layout/CardGrid/CardGrid.tsx +37 -24
  260. package/src/components/layout/Resizable/Resizable.helpers.ts +43 -21
  261. package/src/components/layout/Resizable/Resizable.hooks.ts +17 -9
  262. package/src/components/layout/Resizable/Resizable.md +9 -5
  263. package/src/components/layout/Resizable/Resizable.tsx +20 -8
  264. package/src/components/layout/Resizable/Resizable.types.ts +10 -0
  265. package/src/components/layout/ScrollArea/ScrollArea.helpers.ts +0 -2
  266. package/src/components/layout/ScrollArea/ScrollArea.tsx +5 -3
  267. package/src/components/layout/ScrollArea/ScrollArea.types.ts +4 -1
  268. package/src/components/utility/InfiniteScroll/InfiniteScroll.hooks.ts +5 -4
  269. package/src/components/utility/InfiniteScroll/InfiniteScroll.parts.tsx +29 -12
  270. package/src/components/utility/InfiniteScroll/InfiniteScroll.tsx +11 -5
  271. package/src/components/utility/InfiniteScroll/InfiniteScroll.types.ts +10 -2
  272. package/src/components/utility/VirtualList/VirtualList.hooks.ts +101 -112
  273. package/src/components/utility/VirtualList/VirtualList.tsx +36 -65
  274. package/src/components/utility/VirtualList/VirtualList.types.ts +20 -3
  275. package/dist/chunk-2WFDHFK4.js.map +0 -1
  276. package/dist/chunk-3TDVGZZN.js.map +0 -1
  277. package/dist/chunk-AROBXRC5.js.map +0 -1
  278. package/dist/chunk-ATSHKSSD.js.map +0 -1
  279. package/dist/chunk-AUSUCZYR.js.map +0 -1
  280. package/dist/chunk-C66RGVAS.js.map +0 -1
  281. package/dist/chunk-D5SZXH7Q.js.map +0 -1
  282. package/dist/chunk-DF4K5XVW.js.map +0 -1
  283. package/dist/chunk-DLJGBJZW.js.map +0 -1
  284. package/dist/chunk-DZA7RSLX.js.map +0 -1
  285. package/dist/chunk-F42MJOHM.js.map +0 -1
  286. package/dist/chunk-GSFNH4C5.js.map +0 -1
  287. package/dist/chunk-HGMBY5LP.js.map +0 -1
  288. package/dist/chunk-HTZNB6IV.js.map +0 -1
  289. package/dist/chunk-IAGOUTI6.js.map +0 -1
  290. package/dist/chunk-J2DAQQQH.js.map +0 -1
  291. package/dist/chunk-MTFCPPZ5.js.map +0 -1
  292. package/dist/chunk-P6TNXBDA.js.map +0 -1
  293. package/dist/chunk-PMOEG36E.js.map +0 -1
  294. package/dist/chunk-PPRV4LTM.js.map +0 -1
  295. package/dist/chunk-PUBPZOQJ.js.map +0 -1
  296. package/dist/chunk-QF6LTUCE.js.map +0 -1
  297. package/dist/chunk-RHIDWUK7.js.map +0 -1
  298. package/dist/chunk-T7DE44SP.js.map +0 -1
  299. package/dist/chunk-TQ6FPOPD.js.map +0 -1
  300. package/dist/chunk-TUBCN4DJ.js.map +0 -1
  301. package/dist/chunk-ULTOQ6ZV.js.map +0 -1
  302. package/dist/chunk-UN5INW6K.js.map +0 -1
  303. package/dist/chunk-YU26GBNX.js.map +0 -1
  304. package/dist/chunk-ZAY6OA6F.js.map +0 -1
  305. /package/dist/{chunk-MR2HKBHS.js.map → chunk-27LOJVR3.js.map} +0 -0
  306. /package/dist/{chunk-S3D5VBHW.js.map → chunk-3YOXVNO4.js.map} +0 -0
  307. /package/dist/{chunk-CZIX4BW2.js.map → chunk-4ALF5PB5.js.map} +0 -0
  308. /package/dist/{chunk-XJPJ6ESI.js.map → chunk-4OAKGKK5.js.map} +0 -0
  309. /package/dist/{chunk-4CHROSWR.js.map → chunk-5ETBB2DG.js.map} +0 -0
  310. /package/dist/{chunk-46UPILLK.js.map → chunk-5NT2M2JI.js.map} +0 -0
  311. /package/dist/{chunk-H5BEWPEY.js.map → chunk-6N2EDWMG.js.map} +0 -0
  312. /package/dist/{chunk-GJQYM3PM.js.map → chunk-6PU3JYVY.js.map} +0 -0
  313. /package/dist/{chunk-Y7F5JBAT.js.map → chunk-DDRKYNPB.js.map} +0 -0
  314. /package/dist/{chunk-OS6KPL4D.js.map → chunk-EHYI2WCJ.js.map} +0 -0
  315. /package/dist/{chunk-NB3FGWU4.js.map → chunk-EQXIW5MQ.js.map} +0 -0
  316. /package/dist/{chunk-M2JTIH5M.js.map → chunk-F44R7US6.js.map} +0 -0
  317. /package/dist/{chunk-XJJXBUPN.js.map → chunk-FX26DAFF.js.map} +0 -0
  318. /package/dist/{chunk-R6SN73RX.js.map → chunk-GLHNMTP6.js.map} +0 -0
  319. /package/dist/{chunk-I4QA2F4L.js.map → chunk-HBRQPG7H.js.map} +0 -0
  320. /package/dist/{chunk-CNQUCNEA.js.map → chunk-I3F4C5SS.js.map} +0 -0
  321. /package/dist/{chunk-UFJYJHQI.js.map → chunk-J5VWGQSR.js.map} +0 -0
  322. /package/dist/{chunk-4JFL62K3.js.map → chunk-K7FSTB2K.js.map} +0 -0
  323. /package/dist/{chunk-FFCJ7NR2.js.map → chunk-KRQUPE4K.js.map} +0 -0
  324. /package/dist/{chunk-2OYFTSG4.js.map → chunk-KXLUMEDX.js.map} +0 -0
  325. /package/dist/{chunk-DVAAUWTC.js.map → chunk-LCHCE2G5.js.map} +0 -0
  326. /package/dist/{chunk-G4HBNILE.js.map → chunk-LEHMWJNZ.js.map} +0 -0
  327. /package/dist/{chunk-RZYSKQTS.js.map → chunk-PCBZYORN.js.map} +0 -0
  328. /package/dist/{chunk-5OBXEMQO.js.map → chunk-PRIBOWX4.js.map} +0 -0
  329. /package/dist/{chunk-PQECNGDE.js.map → chunk-QSRZOXQI.js.map} +0 -0
  330. /package/dist/{chunk-DCJSHYE5.js.map → chunk-RSDYS5B3.js.map} +0 -0
  331. /package/dist/{chunk-N5GVW6RO.js.map → chunk-S6IWKDWT.js.map} +0 -0
  332. /package/dist/{chunk-TKC6WHGB.js.map → chunk-SBIZXZPP.js.map} +0 -0
  333. /package/dist/{chunk-UEVHI62V.js.map → chunk-YCCY77W5.js.map} +0 -0
  334. /package/dist/{chunk-VZIB5W5L.js.map → chunk-ZGCPDA3F.js.map} +0 -0
@@ -2,27 +2,33 @@ import Alert from '@mui/material/Alert/index.js';
2
2
  import Box from '@mui/material/Box/index.js';
3
3
  import CircularProgress from '@mui/material/CircularProgress/index.js';
4
4
  import Typography from '@mui/material/Typography/index.js';
5
+ import { useTheme, type SxProps, type Theme } from '@mui/material/styles/index.js';
5
6
  import React from 'react';
6
7
 
8
+ import { rem } from '../../../tokens/relative';
9
+
7
10
  import type { InfiniteScrollProps } from './InfiniteScroll.types';
8
11
 
9
12
  type Variant = NonNullable<InfiniteScrollProps['variant']>;
10
13
 
11
- const CENTERED = {
14
+ const CENTERED: SxProps<Theme> = {
12
15
  display: 'flex',
13
16
  justifyContent: 'center',
14
17
  alignItems: 'center',
15
18
  p: 2,
16
- } as const;
19
+ };
17
20
 
18
- export const DefaultLoader: React.FC<{ loadingText: string }> = ({ loadingText }) => (
19
- <Box sx={CENTERED}>
20
- <CircularProgress size={24} />
21
- <Typography variant="body2" sx={{ ml: 1 }}>
22
- {loadingText}
23
- </Typography>
24
- </Box>
25
- );
21
+ export const DefaultLoader: React.FC<{ loadingText: string }> = ({ loadingText }) => {
22
+ const theme = useTheme();
23
+ return (
24
+ <Box sx={CENTERED}>
25
+ <CircularProgress size={rem(theme, 24)} />
26
+ <Typography variant="body2" sx={{ ml: 1 }}>
27
+ {loadingText}
28
+ </Typography>
29
+ </Box>
30
+ );
31
+ };
26
32
 
27
33
  export const DefaultEndMessage: React.FC<{ endText: string }> = ({ endText }) => (
28
34
  <Box sx={CENTERED}>
@@ -38,14 +44,25 @@ export const DefaultError: React.FC<{ error: Error }> = ({ error }) => (
38
44
  </Alert>
39
45
  );
40
46
 
47
+ /**
48
+ * The horizontal variant's `width` as CSS: a number of 1 or less stays the
49
+ * fraction `sx` reads it as, a larger one is design px, a string is as given;
50
+ * unset (or 0) fills the parent.
51
+ */
52
+ const horizontalWidth = (theme: Theme, width: number | string | undefined): string => {
53
+ if (!width) return '100%';
54
+ if (typeof width !== 'number') return width;
55
+ return width <= 1 ? `${width * 100}%` : rem(theme, width);
56
+ };
57
+
41
58
  /**
42
59
  * `horizontal` scrolls along a row; `reverse` stacks bottom-up, for a chat log
43
60
  * that loads older messages as you scroll away from the newest.
44
61
  */
45
- export const containerStyles = (variant: Variant, width?: number | string) => {
62
+ export const containerStyles = (theme: Theme, variant: Variant, width?: number | string) => {
46
63
  const horizontal = variant === 'horizontal';
47
64
  const base = {
48
- width: horizontal ? width || '100%' : '100%',
65
+ width: horizontal ? horizontalWidth(theme, width) : '100%',
49
66
  height: horizontal ? '100%' : 'auto',
50
67
  overflowX: horizontal ? 'auto' : 'hidden',
51
68
  overflowY: horizontal ? 'hidden' : 'visible',
@@ -1,6 +1,9 @@
1
1
  import Box from '@mui/material/Box/index.js';
2
+ import { useTheme } from '@mui/material/styles/index.js';
2
3
  import React from 'react';
3
4
 
5
+ import { rem, remPx } from '../../../tokens/relative';
6
+
4
7
  import { useLoadMore, useSentinel } from './InfiniteScroll.hooks';
5
8
  import {
6
9
  containerStyles,
@@ -15,7 +18,7 @@ export const InfiniteScroll: React.FC<InfiniteScrollProps> = ({
15
18
  variant = 'default',
16
19
  hasMore,
17
20
  loading,
18
- threshold = 150,
21
+ threshold,
19
22
  loadMore,
20
23
  loader,
21
24
  loadingText,
@@ -31,7 +34,10 @@ export const InfiniteScroll: React.FC<InfiniteScrollProps> = ({
31
34
  testMode = false,
32
35
  testTriggerRef,
33
36
  }) => {
34
- const { sentinelRef, isIntersecting } = useSentinel({ testMode, threshold, scrollableTarget });
37
+ const theme = useTheme();
38
+ // 150 design px unless the caller says; `rootMargin` only takes px.
39
+ const rootMargin = `${remPx(theme, threshold ?? 150)}px`;
40
+ const { sentinelRef, isIntersecting } = useSentinel({ testMode, rootMargin, scrollableTarget });
35
41
 
36
42
  useLoadMore({
37
43
  hasMore,
@@ -56,8 +62,8 @@ export const InfiniteScroll: React.FC<InfiniteScrollProps> = ({
56
62
  ref={sentinelRef}
57
63
  data-testid="infinite-scroll-sentinel"
58
64
  style={{
59
- height: variant === 'horizontal' ? '100%' : '1px',
60
- width: variant === 'horizontal' ? '1px' : '100%',
65
+ height: variant === 'horizontal' ? '100%' : rem(theme, 1),
66
+ width: variant === 'horizontal' ? rem(theme, 1) : '100%',
61
67
  }}
62
68
  />
63
69
  );
@@ -67,7 +73,7 @@ export const InfiniteScroll: React.FC<InfiniteScrollProps> = ({
67
73
  <Box
68
74
  className={className}
69
75
  sx={{
70
- ...containerStyles(variant, width),
76
+ ...containerStyles(theme, variant, width),
71
77
  ...style,
72
78
  }}
73
79
  >
@@ -13,7 +13,11 @@ export interface InfiniteScrollProps {
13
13
  variant?: InfiniteScrollVariant;
14
14
  hasMore: boolean;
15
15
  loading: boolean;
16
- threshold?: number; // Distance from bottom/edge to trigger loading
16
+ /**
17
+ * How far before the end the next page is requested (default 150) — design
18
+ * px, scaled with the theme's type scale.
19
+ */
20
+ threshold?: number;
17
21
  loadMore: () => void | Promise<void>;
18
22
  loader?: ReactNode;
19
23
  endMessage?: ReactNode;
@@ -22,7 +26,11 @@ export interface InfiniteScrollProps {
22
26
  onError?: (error: Error) => void;
23
27
  className?: string;
24
28
  style?: React.CSSProperties;
25
- // Horizontal specific
29
+ /**
30
+ * The `horizontal` variant's width. A number of 1 or less is a fraction of
31
+ * the parent (as in `sx`); a larger number is design px, scaled with the
32
+ * theme's type scale; a string is used as given.
33
+ */
26
34
  width?: number | string;
27
35
  scrollableTarget?: string | HTMLElement; // For custom scroll containers
28
36
  /**
@@ -1,18 +1,21 @@
1
- import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
1
+ import { useTheme, type Theme } from '@mui/material/styles/index.js';
2
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
3
+
4
+ import { rem, remPx } from '../../../tokens/relative';
2
5
 
3
6
  import type { VirtualGridProps, VirtualListProps } from './VirtualList.types';
4
7
 
5
8
  type ScrollEvent = React.UIEvent<HTMLDivElement> | Event;
6
9
  type ListItems = VirtualListProps['items'];
7
10
  type ListVariant = NonNullable<VirtualListProps['variant']>;
8
- type ItemHeight = (index: number) => number;
11
+ type ItemSize = (index: number) => number;
9
12
 
10
13
  // Handles both React synthetic events and native DOM events, since the same
11
14
  // handler serves an internal onScroll and an external container's listener.
12
15
  const scrollOffsets = (event: ScrollEvent) => {
13
16
  const target = (event as React.UIEvent<HTMLDivElement>).currentTarget || (event as Event).target;
14
17
  const element = target as HTMLElement;
15
- return { top: element.scrollTop, left: element.scrollLeft };
18
+ return { scrollTop: element.scrollTop, scrollLeft: element.scrollLeft };
16
19
  };
17
20
 
18
21
  /**
@@ -47,7 +50,7 @@ const useScrollTop = (
47
50
 
48
51
  const handleScroll = useCallback(
49
52
  (event: ScrollEvent) => {
50
- const { top, left } = scrollOffsets(event);
53
+ const { scrollTop: top, scrollLeft: left } = scrollOffsets(event);
51
54
  setScrollTop(top);
52
55
  report(top, left);
53
56
  },
@@ -59,63 +62,60 @@ const useScrollTop = (
59
62
  return { scrollTop, handleScroll };
60
63
  };
61
64
 
62
- interface HeightArgs {
63
- items: ListItems;
64
- variant: ListVariant;
65
- itemHeight: number;
66
- estimatedItemHeight: number;
67
- }
68
65
 
69
66
  /**
70
- * Fixed lists know every height up front. Variable ones prefer the item's own
71
- * declared height, fall back to a measurement taken on a previous render, and
72
- * only then guess.
67
+ * A `width` prop as CSS. `sx` reads a number of 1 or less as a fraction of the
68
+ * parent, and that stays so; a larger number is design px, through the type
69
+ * scale; a string is as given.
73
70
  */
74
- const useItemHeight = ({
75
- items,
76
- variant,
77
- itemHeight,
78
- estimatedItemHeight,
79
- }: HeightArgs): ItemHeight => {
80
- const measured = useRef<Map<number, number>>(new Map());
81
-
82
- return useCallback(
83
- (index: number): number => {
84
- if (variant !== 'variable') {
85
- return itemHeight;
86
- }
87
-
88
- return items[index]?.height || measured.current.get(index) || estimatedItemHeight;
89
- },
90
- [variant, itemHeight, estimatedItemHeight, items],
91
- );
71
+ export const widthCss = (theme: Theme, width: number | string): string => {
72
+ if (typeof width !== 'number') return width;
73
+ return width <= 1 && width !== 0 ? `${width * 100}%` : rem(theme, width);
92
74
  };
93
75
 
94
- const useTotalHeight = (
76
+ /** Every item's height, its offset from the top, and their sum — all in DESIGN px. */
77
+ interface DesignHeights {
78
+ size: ItemSize;
79
+ offset: ItemSize;
80
+ total: number;
81
+ }
82
+
83
+ /**
84
+ * Fixed lists know every height up front; variable ones take the item's own
85
+ * declared height and otherwise the estimate.
86
+ *
87
+ * Kept in the caller's DESIGN px on purpose: the CSS draws a height with `rem`
88
+ * and the range maths reads it through `remPx`, so the two are one number at
89
+ * any type scale — never a row drawn at one pitch and positioned at another.
90
+ */
91
+ const useDesignHeights = (
95
92
  items: ListItems,
96
93
  variant: ListVariant,
97
- itemHeight: number,
98
- getItemHeight: ItemHeight,
99
- ) =>
94
+ fixed: number,
95
+ estimated: number,
96
+ ): DesignHeights =>
100
97
  useMemo(() => {
101
- if (variant === 'fixed') {
102
- return items.length * itemHeight;
98
+ if (variant !== 'variable') {
99
+ return { size: () => fixed, offset: (index) => index * fixed, total: items.length * fixed };
103
100
  }
104
101
 
105
- let sum = 0;
102
+ const size = (index: number): number => items[index]?.height || estimated;
103
+ // Running sums, so an offset is a lookup rather than a walk from the top.
104
+ const starts = [0];
106
105
  for (let i = 0; i < items.length; i++) {
107
- sum += getItemHeight(i);
106
+ starts.push((starts[i] ?? 0) + size(i));
108
107
  }
109
- return sum;
110
- }, [items.length, variant, itemHeight, getItemHeight]);
108
+ return { size, offset: (index) => starts[index] ?? 0, total: starts[items.length] ?? 0 };
109
+ }, [items, variant, fixed, estimated]);
111
110
 
111
+ /** The range maths' inputs, in the px the scroll offset is measured in. */
112
112
  interface RangeArgs {
113
113
  count: number;
114
114
  scrollTop: number;
115
115
  height: number;
116
116
  overscan: number;
117
117
  itemHeight: number;
118
- getItemHeight: ItemHeight;
118
+ getItemHeight: ItemSize;
119
119
  }
120
120
 
121
121
  // Walks forward accumulating heights until it passes the viewport's top edge, then
@@ -155,56 +155,38 @@ const fixedRange = ({ count, scrollTop, height, overscan, itemHeight }: RangeArg
155
155
  endIndex: Math.min(count - 1, Math.ceil((scrollTop + height) / itemHeight) + overscan),
156
156
  });
157
157
 
158
- const useItemOffset = (
159
- variant: ListVariant,
160
- itemHeight: number,
161
- getItemHeight: ItemHeight,
162
- ): ItemHeight =>
163
- useCallback(
164
- (index: number): number => {
165
- if (variant === 'fixed') {
166
- return index * itemHeight;
167
- }
168
-
169
- let offset = 0;
170
- for (let i = 0; i < index; i++) {
171
- offset += getItemHeight(i);
172
- }
173
- return offset;
174
- },
175
- [variant, itemHeight, getItemHeight],
176
- );
177
-
178
- interface ListArgs {
179
- items: ListItems;
180
- variant: ListVariant;
181
- height: number;
182
- itemHeight: number;
183
- estimatedItemHeight: number;
184
- overscan: number;
185
- onScroll: VirtualListProps['onScroll'];
186
- scrollContainerRef: VirtualListProps['scrollContainerRef'];
187
- }
188
-
158
+ /**
159
+ * `height`, `itemHeight`, `estimatedItemHeight` and an item's own `height` are
160
+ * design px. The range is computed in the px `scrollTop` is measured in
161
+ * (`remPx`), the viewport and the scroll content are drawn in `rem`, and each
162
+ * item's `top`/`height` is the `remPx` of its design offset and height.
163
+ */
189
164
  export const useVirtualList = ({
190
165
  items,
191
- variant,
166
+ variant = 'fixed',
192
167
  height,
193
168
  itemHeight,
194
169
  estimatedItemHeight,
195
- overscan,
170
+ overscan = 5,
196
171
  onScroll,
197
172
  scrollContainerRef,
198
- }: ListArgs) => {
199
- const getItemHeight = useItemHeight({ items, variant, itemHeight, estimatedItemHeight });
200
- const getItemOffset = useItemOffset(variant, itemHeight, getItemHeight);
201
- const totalHeight = useTotalHeight(items, variant, itemHeight, getItemHeight);
173
+ }: VirtualListProps) => {
174
+ const theme = useTheme();
175
+ // 40 design px when the caller does not size a row.
176
+ const design = useDesignHeights(items, variant, itemHeight ?? 40, estimatedItemHeight ?? 40);
202
177
 
203
178
  const report = useCallback((top: number) => onScroll?.(top), [onScroll]);
204
179
  const { scrollTop, handleScroll } = useScrollTop(scrollContainerRef, report);
205
180
 
206
181
  const visibleItems = useMemo(() => {
207
- const args = { count: items.length, scrollTop, height, overscan, itemHeight, getItemHeight };
182
+ const args = {
183
+ count: items.length,
184
+ scrollTop,
185
+ height: remPx(theme, height),
186
+ overscan,
187
+ itemHeight: remPx(theme, design.size(0)),
188
+ getItemHeight: (index: number) => remPx(theme, design.size(index)),
189
+ };
208
190
  const { startIndex, endIndex } = variant === 'fixed' ? fixedRange(args) : variableRange(args);
209
191
  const result = [];
210
192
 
@@ -217,33 +199,26 @@ export const useVirtualList = ({
217
199
  index: i,
218
200
  style: {
219
201
  position: 'absolute' as const,
220
- top: getItemOffset(i),
202
+ top: remPx(theme, design.offset(i)),
221
203
  left: 0,
222
204
  width: '100%',
223
- height: getItemHeight(i),
205
+ height: remPx(theme, design.size(i)),
224
206
  },
225
207
  });
226
208
  }
227
209
 
228
210
  return result;
229
- }, [items, scrollTop, height, overscan, variant, itemHeight, getItemOffset, getItemHeight]);
230
-
231
- return { totalHeight, visibleItems, handleScroll };
211
+ }, [items, scrollTop, height, overscan, variant, design, theme]);
212
+
213
+ return {
214
+ totalHeight: rem(theme, design.total),
215
+ viewportHeight: rem(theme, height),
216
+ visibleItems,
217
+ handleScroll,
218
+ };
232
219
  };
233
220
 
234
- interface GridArgs {
235
- items: VirtualGridProps['items'];
236
- height: number;
237
- width: number | string;
238
- columnCount: number;
239
- rowHeight: number;
240
- columnWidth?: number;
241
- gap: number;
242
- overscan: number;
243
- onScroll: VirtualGridProps['onScroll'];
244
- scrollContainerRef: VirtualGridProps['scrollContainerRef'];
245
- }
246
-
221
+ /** The column width in DESIGN px: the caller's, or an even share of a numeric width. */
247
222
  const useColumnWidth = (
248
223
  columnWidth: number | undefined,
249
224
  width: number | string,
@@ -257,21 +232,26 @@ const useColumnWidth = (
257
232
  return (containerWidth - (columnCount - 1) * gap) / columnCount;
258
233
  }, [columnWidth, width, columnCount, gap]);
259
234
 
235
+ /**
236
+ * `height`, `rowHeight`, `columnWidth` and `gap` are design px: the range and
237
+ * every cell's box are computed through `remPx`, the viewport and the content
238
+ * are drawn through `rem`.
239
+ */
260
240
  export const useVirtualGrid = ({
261
241
  items,
262
242
  height,
263
- width,
243
+ width = '100%',
264
244
  columnCount,
265
245
  rowHeight,
266
246
  columnWidth,
267
- gap,
268
- overscan,
247
+ gap = 0,
248
+ overscan = 5,
269
249
  onScroll,
270
250
  scrollContainerRef,
271
- }: GridArgs) => {
251
+ }: VirtualGridProps) => {
252
+ const theme = useTheme();
272
253
  const rowCount = Math.ceil(items.length / columnCount);
273
- const totalHeight = rowCount * (rowHeight + gap) - gap;
274
- const computedColumnWidth = useColumnWidth(columnWidth, width, columnCount, gap);
254
+ const designColumn = useColumnWidth(columnWidth, width, columnCount, gap);
275
255
 
276
256
  const report = useCallback(
277
257
  (top: number, left: number) => onScroll?.(top, left),
@@ -280,9 +260,13 @@ export const useVirtualGrid = ({
280
260
  const { scrollTop, handleScroll } = useScrollTop(scrollContainerRef, report);
281
261
 
282
262
  const visibleItems = useMemo(() => {
283
- const pitch = rowHeight + gap;
263
+ const pitch = remPx(theme, rowHeight + gap);
264
+ const stride = remPx(theme, designColumn + gap);
284
265
  const startRow = Math.max(0, Math.floor(scrollTop / pitch) - overscan);
285
- const endRow = Math.min(rowCount - 1, Math.ceil((scrollTop + height) / pitch) + overscan);
266
+ const endRow = Math.min(
267
+ rowCount - 1,
268
+ Math.ceil((scrollTop + remPx(theme, height)) / pitch) + overscan,
269
+ );
286
270
 
287
271
  // Rows are contiguous in `items`, so the visible block is one index range
288
272
  // rather than a row loop wrapping a column loop.
@@ -305,15 +289,20 @@ export const useVirtualGrid = ({
305
289
  style: {
306
290
  position: 'absolute' as const,
307
291
  top: rowIndex * pitch,
308
- left: columnIndex * (computedColumnWidth + gap),
309
- width: computedColumnWidth,
310
- height: rowHeight,
292
+ left: columnIndex * stride,
293
+ width: remPx(theme, designColumn),
294
+ height: remPx(theme, rowHeight),
311
295
  },
312
296
  });
313
297
  }
314
298
 
315
299
  return result;
316
- }, [items, scrollTop, height, overscan, rowCount, columnCount, rowHeight, gap, computedColumnWidth]);
317
-
318
- return { totalHeight, visibleItems, handleScroll };
300
+ }, [items, scrollTop, height, overscan, rowCount, columnCount, rowHeight, gap, designColumn, theme]);
301
+
302
+ return {
303
+ totalHeight: rem(theme, rowCount * (rowHeight + gap) - gap),
304
+ viewportHeight: rem(theme, height),
305
+ visibleItems,
306
+ handleScroll,
307
+ };
319
308
  };
@@ -1,15 +1,19 @@
1
1
  import Box from '@mui/material/Box/index.js';
2
+ import { useTheme } from '@mui/material/styles/index.js';
2
3
  import React, { useRef } from 'react';
3
4
 
4
- import { useVirtualGrid, useVirtualList } from './VirtualList.hooks';
5
+ import { useVirtualGrid, useVirtualList, widthCss } from './VirtualList.hooks';
5
6
  import type { VirtualGridProps, VirtualListProps } from './VirtualList.types';
6
7
 
7
8
  interface ContainerProps {
8
9
  children: React.ReactNode;
9
10
  role: 'list' | 'grid';
10
- totalHeight: number;
11
- height: number;
12
- width: number | string;
11
+ /** The scroll content's height, as CSS. */
12
+ totalHeight: string;
13
+ /** The viewport's height, as CSS. */
14
+ height: string;
15
+ /** The viewport's width, as CSS. */
16
+ width: string;
13
17
  disableInternalScroll: boolean;
14
18
  onScroll: (event: React.UIEvent<HTMLDivElement>) => void;
15
19
  className?: string;
@@ -64,40 +68,25 @@ const VirtualContainer: React.FC<ContainerProps> = ({
64
68
  );
65
69
  };
66
70
 
67
- export const VirtualList: React.FC<VirtualListProps> = ({
68
- items,
69
- variant = 'fixed',
70
- height,
71
- width = '100%',
72
- itemHeight = 40,
73
- estimatedItemHeight = 40,
74
- overscan = 5,
75
- renderItem,
76
- onScroll,
77
- className,
78
- style,
79
- 'data-testid': dataTestId,
80
- 'aria-label': ariaLabel,
81
- scrollContainerRef,
82
- disableInternalScroll = false,
83
- }) => {
84
- const { totalHeight, visibleItems, handleScroll } = useVirtualList({
85
- items,
86
- variant,
87
- height,
88
- itemHeight,
89
- estimatedItemHeight,
90
- overscan,
91
- onScroll,
92
- scrollContainerRef,
93
- });
71
+ export const VirtualList: React.FC<VirtualListProps> = (props) => {
72
+ const {
73
+ width = '100%',
74
+ renderItem,
75
+ className,
76
+ style,
77
+ 'data-testid': dataTestId,
78
+ 'aria-label': ariaLabel,
79
+ disableInternalScroll = false,
80
+ } = props;
81
+ const theme = useTheme();
82
+ const { totalHeight, viewportHeight, visibleItems, handleScroll } = useVirtualList(props);
94
83
 
95
84
  return (
96
85
  <VirtualContainer
97
86
  role="list"
98
87
  totalHeight={totalHeight}
99
- height={height}
100
- width={width}
88
+ height={viewportHeight}
89
+ width={widthCss(theme, width)}
101
90
  disableInternalScroll={disableInternalScroll}
102
91
  onScroll={handleScroll}
103
92
  className={className}
@@ -112,43 +101,25 @@ export const VirtualList: React.FC<VirtualListProps> = ({
112
101
  );
113
102
  };
114
103
 
115
- export const VirtualGrid: React.FC<VirtualGridProps> = ({
116
- items,
117
- height,
118
- width = '100%',
119
- columnCount,
120
- rowHeight,
121
- columnWidth,
122
- gap = 0,
123
- overscan = 5,
124
- renderItem,
125
- onScroll,
126
- className,
127
- style,
128
- 'data-testid': dataTestId,
129
- 'aria-label': ariaLabel,
130
- scrollContainerRef,
131
- disableInternalScroll = false,
132
- }) => {
133
- const { totalHeight, visibleItems, handleScroll } = useVirtualGrid({
134
- items,
135
- height,
136
- width,
137
- columnCount,
138
- rowHeight,
139
- columnWidth,
140
- gap,
141
- overscan,
142
- onScroll,
143
- scrollContainerRef,
144
- });
104
+ export const VirtualGrid: React.FC<VirtualGridProps> = (props) => {
105
+ const {
106
+ width = '100%',
107
+ renderItem,
108
+ className,
109
+ style,
110
+ 'data-testid': dataTestId,
111
+ 'aria-label': ariaLabel,
112
+ disableInternalScroll = false,
113
+ } = props;
114
+ const theme = useTheme();
115
+ const { totalHeight, viewportHeight, visibleItems, handleScroll } = useVirtualGrid(props);
145
116
 
146
117
  return (
147
118
  <VirtualContainer
148
119
  role="grid"
149
120
  totalHeight={totalHeight}
150
- height={height}
151
- width={width}
121
+ height={viewportHeight}
122
+ width={widthCss(theme, width)}
152
123
  disableInternalScroll={disableInternalScroll}
153
124
  onScroll={handleScroll}
154
125
  className={className}
@@ -4,17 +4,25 @@ export type VirtualListVariant = 'fixed' | 'variable' | 'grid';
4
4
 
5
5
  export interface VirtualListItem {
6
6
  id: string | number;
7
- height?: number; // For variable height items
7
+ /** This item's own height, for a `variable` list — design px, scaled with the theme's type scale. */
8
+ height?: number;
8
9
  data?: unknown;
9
10
  }
10
11
 
11
12
  export interface VirtualListProps {
12
13
  items: VirtualListItem[];
13
14
  variant?: VirtualListVariant;
15
+ /** The viewport's height — design px, scaled with the theme's type scale. */
14
16
  height: number;
17
+ /**
18
+ * The viewport's width. A number of 1 or less is a fraction of the parent (as
19
+ * in `sx`); a larger number is design px, scaled with the theme's type scale; a string is used as given.
20
+ */
15
21
  width?: number | string;
16
- itemHeight?: number; // For fixed height items
17
- estimatedItemHeight?: number; // For variable height items
22
+ /** Every row's height in a `fixed` list (default 40) — design px, scaled with the theme's type scale. */
23
+ itemHeight?: number;
24
+ /** The height assumed for a `variable` item that declares none (default 40) — design px, scaled with the theme's type scale. */
25
+ estimatedItemHeight?: number;
18
26
  overscan?: number; // Number of items to render outside visible area
19
27
  renderItem: (params: { item: VirtualListItem; index: number; style: CSSProperties }) => ReactNode;
20
28
  onScroll?: (scrollTop: number) => void;
@@ -30,11 +38,20 @@ export interface VirtualListProps {
30
38
 
31
39
  export interface VirtualGridProps {
32
40
  items: VirtualListItem[];
41
+ /** The viewport's height — design px, scaled with the theme's type scale. */
33
42
  height: number;
43
+ /**
44
+ * The viewport's width. A number of 1 or less is a fraction of the parent (as
45
+ * in `sx`); a larger number is design px, scaled with the theme's type scale, and also what an unset
46
+ * `columnWidth` is shared out of; a string is used as given.
47
+ */
34
48
  width?: number | string;
35
49
  columnCount: number;
50
+ /** Every row's height — design px, scaled with the theme's type scale. */
36
51
  rowHeight: number;
52
+ /** Every column's width — design px, scaled with the theme's type scale. */
37
53
  columnWidth?: number;
54
+ /** The space between two rows and between two columns — design px, scaled with the theme's type scale. */
38
55
  gap?: number;
39
56
  overscan?: number;
40
57
  renderItem: (params: {