@12-apps/ui 6.38.0 → 6.39.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 (324) 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/MapPreview/MapDecorations.js +2 -2
  30. package/dist/_internal/components/data-display/MapPreview/MapPreview.hooks.js +2 -2
  31. package/dist/_internal/components/data-display/MapPreview/MapPreview.js +7 -7
  32. package/dist/_internal/components/data-display/MapPreview/MapTiles.js +2 -2
  33. package/dist/_internal/components/data-display/MapPreview/StaticMapView.js +4 -4
  34. package/dist/_internal/components/data-display/MapPreview/mapProjection.js +3 -3
  35. package/dist/_internal/components/data-display/MapPreview/useMapPreview.js +3 -3
  36. package/dist/_internal/components/data-display/Table/Table.helpers.js +5 -3
  37. package/dist/_internal/components/data-display/Table/Table.hooks.js +2 -1
  38. package/dist/_internal/components/data-display/Table/Table.js +4 -4
  39. package/dist/_internal/components/data-display/Table/TableParts.hooks.js +4 -2
  40. package/dist/_internal/components/data-display/Table/TableParts.js +4 -2
  41. package/dist/_internal/components/data-display/index.js +18 -18
  42. package/dist/_internal/components/form/Calendar/Calendar.js +5 -4
  43. package/dist/_internal/components/form/Calendar/CalendarDay.js +2 -1
  44. package/dist/_internal/components/form/Calendar/CalendarDayCell.js +3 -2
  45. package/dist/_internal/components/form/Calendar/CalendarMonth.js +4 -3
  46. package/dist/_internal/components/form/DateRangePicker/DateRangePicker.js +5 -5
  47. package/dist/_internal/components/form/Switch/Switch.js +4 -4
  48. package/dist/_internal/components/form/Switch/Switch.metrics.js +5 -1
  49. package/dist/_internal/components/form/Switch/Switch.parts.js +3 -3
  50. package/dist/_internal/components/form/Switch/Switch.styles.js +2 -2
  51. package/dist/_internal/components/form/index.js +9 -9
  52. package/dist/_internal/components/index.js +37 -37
  53. package/dist/_internal/components/layout/CardGrid/CardGrid.js +2 -1
  54. package/dist/_internal/components/layout/Resizable/Resizable.helpers.js +8 -3
  55. package/dist/_internal/components/layout/Resizable/Resizable.hooks.js +3 -2
  56. package/dist/_internal/components/layout/Resizable/Resizable.js +4 -3
  57. package/dist/_internal/components/layout/ScrollArea/ScrollArea.helpers.js +1 -1
  58. package/dist/_internal/components/layout/ScrollArea/ScrollArea.js +2 -2
  59. package/dist/_internal/components/layout/index.js +5 -5
  60. package/dist/_internal/components/utility/InfiniteScroll/InfiniteScroll.hooks.js +1 -1
  61. package/dist/_internal/components/utility/InfiniteScroll/InfiniteScroll.js +4 -3
  62. package/dist/_internal/components/utility/InfiniteScroll/InfiniteScroll.parts.js +2 -1
  63. package/dist/_internal/components/utility/VirtualList/VirtualList.hooks.js +6 -3
  64. package/dist/_internal/components/utility/VirtualList/VirtualList.js +3 -2
  65. package/dist/_internal/components/utility/index.js +5 -5
  66. package/dist/{chunk-J2DAQQQH.js → chunk-222HN7GK.js} +33 -64
  67. package/dist/chunk-222HN7GK.js.map +1 -0
  68. package/dist/{chunk-MR2HKBHS.js → chunk-27LOJVR3.js} +2 -2
  69. package/dist/{chunk-S3D5VBHW.js → chunk-3YOXVNO4.js} +7 -7
  70. package/dist/{chunk-CZIX4BW2.js → chunk-4ALF5PB5.js} +3 -3
  71. package/dist/{chunk-XJPJ6ESI.js → chunk-4OAKGKK5.js} +3 -3
  72. package/dist/{chunk-4CHROSWR.js → chunk-5ETBB2DG.js} +2 -2
  73. package/dist/{chunk-ATSHKSSD.js → chunk-5KNDAC24.js} +20 -7
  74. package/dist/chunk-5KNDAC24.js.map +1 -0
  75. package/dist/{chunk-ULTOQ6ZV.js → chunk-5LWB4BYX.js} +80 -89
  76. package/dist/chunk-5LWB4BYX.js.map +1 -0
  77. package/dist/{chunk-46UPILLK.js → chunk-5NT2M2JI.js} +2 -2
  78. package/dist/{chunk-H5BEWPEY.js → chunk-6N2EDWMG.js} +2 -2
  79. package/dist/{chunk-GJQYM3PM.js → chunk-6PU3JYVY.js} +2 -2
  80. package/dist/{chunk-PUBPZOQJ.js → chunk-AG3DY5TH.js} +8 -5
  81. package/dist/chunk-AG3DY5TH.js.map +1 -0
  82. package/dist/{chunk-PPRV4LTM.js → chunk-BWHOCNGW.js} +4 -4
  83. package/dist/chunk-BWHOCNGW.js.map +1 -0
  84. package/dist/{chunk-TUBCN4DJ.js → chunk-CB6DTWD5.js} +7 -7
  85. package/dist/chunk-CB6DTWD5.js.map +1 -0
  86. package/dist/{chunk-ZAY6OA6F.js → chunk-D4FZ3ANG.js} +15 -5
  87. package/dist/chunk-D4FZ3ANG.js.map +1 -0
  88. package/dist/{chunk-Y7F5JBAT.js → chunk-DDRKYNPB.js} +2 -2
  89. package/dist/{chunk-DLJGBJZW.js → chunk-DGMDQHMI.js} +16 -9
  90. package/dist/chunk-DGMDQHMI.js.map +1 -0
  91. package/dist/{chunk-IAGOUTI6.js → chunk-DNT5PZLF.js} +21 -12
  92. package/dist/chunk-DNT5PZLF.js.map +1 -0
  93. package/dist/{chunk-DZA7RSLX.js → chunk-DVSO3EG6.js} +19 -11
  94. package/dist/chunk-DVSO3EG6.js.map +1 -0
  95. package/dist/{chunk-OS6KPL4D.js → chunk-EHYI2WCJ.js} +4 -4
  96. package/dist/{chunk-NB3FGWU4.js → chunk-EQXIW5MQ.js} +2 -2
  97. package/dist/{chunk-C66RGVAS.js → chunk-ERY6D2OV.js} +6 -4
  98. package/dist/chunk-ERY6D2OV.js.map +1 -0
  99. package/dist/{chunk-M2JTIH5M.js → chunk-F44R7US6.js} +2 -2
  100. package/dist/{chunk-AROBXRC5.js → chunk-F7JTIHV5.js} +18 -7
  101. package/dist/chunk-F7JTIHV5.js.map +1 -0
  102. package/dist/{chunk-XJJXBUPN.js → chunk-FX26DAFF.js} +2 -2
  103. package/dist/{chunk-R6SN73RX.js → chunk-GLHNMTP6.js} +7 -7
  104. package/dist/{chunk-YU26GBNX.js → chunk-H3AQQOTI.js} +9 -4
  105. package/dist/chunk-H3AQQOTI.js.map +1 -0
  106. package/dist/{chunk-HTZNB6IV.js → chunk-H5ZTIELC.js} +23 -8
  107. package/dist/chunk-H5ZTIELC.js.map +1 -0
  108. package/dist/{chunk-GSFNH4C5.js → chunk-HBP2OU4Q.js} +15 -8
  109. package/dist/chunk-HBP2OU4Q.js.map +1 -0
  110. package/dist/{chunk-I4QA2F4L.js → chunk-HBRQPG7H.js} +5 -5
  111. package/dist/{chunk-HGMBY5LP.js → chunk-HQWJUHR4.js} +18 -11
  112. package/dist/chunk-HQWJUHR4.js.map +1 -0
  113. package/dist/{chunk-CNQUCNEA.js → chunk-I3F4C5SS.js} +3 -3
  114. package/dist/{chunk-UFJYJHQI.js → chunk-J5VWGQSR.js} +2 -2
  115. package/dist/{chunk-MTFCPPZ5.js → chunk-JWZJSXI5.js} +3 -2
  116. package/dist/chunk-JWZJSXI5.js.map +1 -0
  117. package/dist/{chunk-4JFL62K3.js → chunk-K7FSTB2K.js} +3 -3
  118. package/dist/{chunk-FFCJ7NR2.js → chunk-KRQUPE4K.js} +4 -4
  119. package/dist/{chunk-2OYFTSG4.js → chunk-KXLUMEDX.js} +2 -2
  120. package/dist/{chunk-DVAAUWTC.js → chunk-LCHCE2G5.js} +2 -2
  121. package/dist/{chunk-G4HBNILE.js → chunk-LEHMWJNZ.js} +3 -3
  122. package/dist/{chunk-P6TNXBDA.js → chunk-MYKWJCR7.js} +9 -9
  123. package/dist/chunk-MYKWJCR7.js.map +1 -0
  124. package/dist/{chunk-TQ6FPOPD.js → chunk-ODW2D5PN.js} +39 -30
  125. package/dist/chunk-ODW2D5PN.js.map +1 -0
  126. package/dist/{chunk-RZYSKQTS.js → chunk-PCBZYORN.js} +3 -3
  127. package/dist/{chunk-5OBXEMQO.js → chunk-PRIBOWX4.js} +3 -3
  128. package/dist/{chunk-F42MJOHM.js → chunk-PVM7XTLZ.js} +64 -62
  129. package/dist/chunk-PVM7XTLZ.js.map +1 -0
  130. package/dist/{chunk-3TDVGZZN.js → chunk-QBTBRJ2Q.js} +37 -13
  131. package/dist/chunk-QBTBRJ2Q.js.map +1 -0
  132. package/dist/{chunk-2WFDHFK4.js → chunk-QNCWSDXE.js} +26 -11
  133. package/dist/chunk-QNCWSDXE.js.map +1 -0
  134. package/dist/{chunk-PQECNGDE.js → chunk-QSRZOXQI.js} +2 -2
  135. package/dist/{chunk-RHIDWUK7.js → chunk-QUWK7SYN.js} +1 -2
  136. package/dist/chunk-QUWK7SYN.js.map +1 -0
  137. package/dist/{chunk-UN5INW6K.js → chunk-R53ZOW4B.js} +8 -4
  138. package/dist/chunk-R53ZOW4B.js.map +1 -0
  139. package/dist/{chunk-DCJSHYE5.js → chunk-RSDYS5B3.js} +4 -4
  140. package/dist/{chunk-N5GVW6RO.js → chunk-S6IWKDWT.js} +2 -2
  141. package/dist/{chunk-TKC6WHGB.js → chunk-SBIZXZPP.js} +2 -2
  142. package/dist/{chunk-D5SZXH7Q.js → chunk-TNBJ4DK4.js} +7 -3
  143. package/dist/chunk-TNBJ4DK4.js.map +1 -0
  144. package/dist/{chunk-PMOEG36E.js → chunk-XZJM6EPC.js} +8 -6
  145. package/dist/chunk-XZJM6EPC.js.map +1 -0
  146. package/dist/{chunk-QF6LTUCE.js → chunk-Y2X7LYIN.js} +4 -4
  147. package/dist/chunk-Y2X7LYIN.js.map +1 -0
  148. package/dist/{chunk-UEVHI62V.js → chunk-YCCY77W5.js} +2 -2
  149. package/dist/{chunk-DF4K5XVW.js → chunk-YZVR5ROE.js} +14 -6
  150. package/dist/chunk-YZVR5ROE.js.map +1 -0
  151. package/dist/{chunk-AUSUCZYR.js → chunk-ZBVU2YWV.js} +5 -5
  152. package/dist/chunk-ZBVU2YWV.js.map +1 -0
  153. package/dist/{chunk-VZIB5W5L.js → chunk-ZGCPDA3F.js} +2 -2
  154. package/dist/data-display/DataGrid.js +4 -4
  155. package/dist/data-display/DataViews.js +29 -29
  156. package/dist/data-display/FleetMap.js +10 -10
  157. package/dist/data-display/MapPreview.js +7 -7
  158. package/dist/data-display/Table.js +4 -4
  159. package/dist/form/Calendar.js +5 -4
  160. package/dist/form/DateRangePicker.js +5 -5
  161. package/dist/form/Switch.js +4 -4
  162. package/dist/layout/CardGrid.js +2 -1
  163. package/dist/layout/Resizable.js +4 -3
  164. package/dist/layout/ScrollArea.js +2 -2
  165. package/dist/native/form/Switch.js +3 -1
  166. package/dist/native/form/Switch.js.map +1 -1
  167. package/dist/types/components/data-display/DataGrid/DataGrid.body.d.ts.map +1 -1
  168. package/dist/types/components/data-display/DataGrid/DataGrid.cells.d.ts +4 -2
  169. package/dist/types/components/data-display/DataGrid/DataGrid.cells.d.ts.map +1 -1
  170. package/dist/types/components/data-display/DataGrid/DataGrid.model.d.ts +7 -1
  171. package/dist/types/components/data-display/DataGrid/DataGrid.model.d.ts.map +1 -1
  172. package/dist/types/components/data-display/DataGrid/DataGrid.types.d.ts +10 -4
  173. package/dist/types/components/data-display/DataGrid/DataGrid.types.d.ts.map +1 -1
  174. package/dist/types/components/data-display/DataViews/data-views-columns.d.ts.map +1 -1
  175. package/dist/types/components/data-display/DataViews/data-views-grid-helpers.d.ts +2 -0
  176. package/dist/types/components/data-display/DataViews/data-views-grid-helpers.d.ts.map +1 -1
  177. package/dist/types/components/data-display/DataViews/data-views-layout-context.d.ts +7 -3
  178. package/dist/types/components/data-display/DataViews/data-views-layout-context.d.ts.map +1 -1
  179. package/dist/types/components/data-display/DataViews/data-views-overflow-costs.d.ts +19 -9
  180. package/dist/types/components/data-display/DataViews/data-views-overflow-costs.d.ts.map +1 -1
  181. package/dist/types/components/data-display/DataViews/data-views-overflow.d.ts.map +1 -1
  182. package/dist/types/components/data-display/MapPreview/MapTiles.d.ts.map +1 -1
  183. package/dist/types/components/data-display/MapPreview/mapProjection.d.ts +6 -1
  184. package/dist/types/components/data-display/MapPreview/mapProjection.d.ts.map +1 -1
  185. package/dist/types/components/data-display/Table/Table.helpers.d.ts +6 -0
  186. package/dist/types/components/data-display/Table/Table.helpers.d.ts.map +1 -1
  187. package/dist/types/components/data-display/Table/Table.hooks.d.ts +9 -1
  188. package/dist/types/components/data-display/Table/Table.hooks.d.ts.map +1 -1
  189. package/dist/types/components/data-display/Table/Table.types.d.ts +6 -2
  190. package/dist/types/components/data-display/Table/Table.types.d.ts.map +1 -1
  191. package/dist/types/components/data-display/Table/TableParts.d.ts +2 -0
  192. package/dist/types/components/data-display/Table/TableParts.d.ts.map +1 -1
  193. package/dist/types/components/form/Calendar/Calendar.d.ts.map +1 -1
  194. package/dist/types/components/form/Calendar/CalendarDay.d.ts.map +1 -1
  195. package/dist/types/components/form/Calendar/CalendarMonth.d.ts.map +1 -1
  196. package/dist/types/components/form/Switch/Switch.metrics.d.ts +13 -3
  197. package/dist/types/components/form/Switch/Switch.metrics.d.ts.map +1 -1
  198. package/dist/types/components/form/Switch/Switch.styles.d.ts.map +1 -1
  199. package/dist/types/components/layout/CardGrid/CardGrid.d.ts +9 -7
  200. package/dist/types/components/layout/CardGrid/CardGrid.d.ts.map +1 -1
  201. package/dist/types/components/layout/Resizable/Resizable.d.ts.map +1 -1
  202. package/dist/types/components/layout/Resizable/Resizable.helpers.d.ts +21 -9
  203. package/dist/types/components/layout/Resizable/Resizable.helpers.d.ts.map +1 -1
  204. package/dist/types/components/layout/Resizable/Resizable.hooks.d.ts +13 -3
  205. package/dist/types/components/layout/Resizable/Resizable.hooks.d.ts.map +1 -1
  206. package/dist/types/components/layout/Resizable/Resizable.types.d.ts +10 -0
  207. package/dist/types/components/layout/Resizable/Resizable.types.d.ts.map +1 -1
  208. package/dist/types/components/layout/ScrollArea/ScrollArea.d.ts.map +1 -1
  209. package/dist/types/components/layout/ScrollArea/ScrollArea.helpers.d.ts +1 -1
  210. package/dist/types/components/layout/ScrollArea/ScrollArea.helpers.d.ts.map +1 -1
  211. package/dist/types/components/layout/ScrollArea/ScrollArea.types.d.ts +4 -1
  212. package/dist/types/components/layout/ScrollArea/ScrollArea.types.d.ts.map +1 -1
  213. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.d.ts.map +1 -1
  214. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.hooks.d.ts +3 -2
  215. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.hooks.d.ts.map +1 -1
  216. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.parts.d.ts +3 -2
  217. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.parts.d.ts.map +1 -1
  218. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.types.d.ts +9 -0
  219. package/dist/types/components/utility/InfiniteScroll/InfiniteScroll.types.d.ts.map +1 -1
  220. package/dist/types/components/utility/VirtualList/VirtualList.d.ts.map +1 -1
  221. package/dist/types/components/utility/VirtualList/VirtualList.hooks.d.ts +24 -28
  222. package/dist/types/components/utility/VirtualList/VirtualList.hooks.d.ts.map +1 -1
  223. package/dist/types/components/utility/VirtualList/VirtualList.types.d.ts +17 -0
  224. package/dist/types/components/utility/VirtualList/VirtualList.types.d.ts.map +1 -1
  225. package/dist/types-native/components/form/Switch/Switch.metrics.d.ts +13 -3
  226. package/dist/types-native/components/form/Switch/Switch.metrics.d.ts.map +1 -1
  227. package/dist/utility/InfiniteScroll.js +4 -3
  228. package/dist/utility/VirtualList.js +3 -2
  229. package/package.json +1 -1
  230. package/src/components/data-display/DataGrid/DataGrid.body.tsx +27 -7
  231. package/src/components/data-display/DataGrid/DataGrid.cells.tsx +33 -9
  232. package/src/components/data-display/DataGrid/DataGrid.model.ts +24 -11
  233. package/src/components/data-display/DataGrid/DataGrid.types.ts +12 -6
  234. package/src/components/data-display/DataViews/data-views-columns.ts +14 -3
  235. package/src/components/data-display/DataViews/data-views-grid-helpers.tsx +5 -3
  236. package/src/components/data-display/DataViews/data-views-layout-context.tsx +12 -9
  237. package/src/components/data-display/DataViews/data-views-overflow-costs.ts +32 -14
  238. package/src/components/data-display/DataViews/data-views-overflow.ts +40 -26
  239. package/src/components/data-display/MapPreview/MapTiles.tsx +16 -9
  240. package/src/components/data-display/MapPreview/mapProjection.ts +10 -5
  241. package/src/components/data-display/Table/Table.helpers.ts +7 -1
  242. package/src/components/data-display/Table/Table.hooks.ts +16 -5
  243. package/src/components/data-display/Table/Table.types.ts +6 -2
  244. package/src/components/data-display/Table/TableParts.tsx +38 -42
  245. package/src/components/form/Calendar/Calendar.tsx +4 -2
  246. package/src/components/form/Calendar/CalendarDay.tsx +6 -3
  247. package/src/components/form/Calendar/CalendarMonth.tsx +6 -3
  248. package/src/components/form/Switch/Switch.metrics.ts +19 -5
  249. package/src/components/form/Switch/Switch.styles.ts +5 -3
  250. package/src/components/layout/CardGrid/CardGrid.tsx +37 -24
  251. package/src/components/layout/Resizable/Resizable.helpers.ts +43 -21
  252. package/src/components/layout/Resizable/Resizable.hooks.ts +17 -9
  253. package/src/components/layout/Resizable/Resizable.md +9 -5
  254. package/src/components/layout/Resizable/Resizable.tsx +20 -8
  255. package/src/components/layout/Resizable/Resizable.types.ts +10 -0
  256. package/src/components/layout/ScrollArea/ScrollArea.helpers.ts +0 -2
  257. package/src/components/layout/ScrollArea/ScrollArea.tsx +5 -3
  258. package/src/components/layout/ScrollArea/ScrollArea.types.ts +4 -1
  259. package/src/components/utility/InfiniteScroll/InfiniteScroll.hooks.ts +5 -4
  260. package/src/components/utility/InfiniteScroll/InfiniteScroll.parts.tsx +29 -12
  261. package/src/components/utility/InfiniteScroll/InfiniteScroll.tsx +11 -5
  262. package/src/components/utility/InfiniteScroll/InfiniteScroll.types.ts +10 -2
  263. package/src/components/utility/VirtualList/VirtualList.hooks.ts +101 -112
  264. package/src/components/utility/VirtualList/VirtualList.tsx +36 -65
  265. package/src/components/utility/VirtualList/VirtualList.types.ts +20 -3
  266. package/dist/chunk-2WFDHFK4.js.map +0 -1
  267. package/dist/chunk-3TDVGZZN.js.map +0 -1
  268. package/dist/chunk-AROBXRC5.js.map +0 -1
  269. package/dist/chunk-ATSHKSSD.js.map +0 -1
  270. package/dist/chunk-AUSUCZYR.js.map +0 -1
  271. package/dist/chunk-C66RGVAS.js.map +0 -1
  272. package/dist/chunk-D5SZXH7Q.js.map +0 -1
  273. package/dist/chunk-DF4K5XVW.js.map +0 -1
  274. package/dist/chunk-DLJGBJZW.js.map +0 -1
  275. package/dist/chunk-DZA7RSLX.js.map +0 -1
  276. package/dist/chunk-F42MJOHM.js.map +0 -1
  277. package/dist/chunk-GSFNH4C5.js.map +0 -1
  278. package/dist/chunk-HGMBY5LP.js.map +0 -1
  279. package/dist/chunk-HTZNB6IV.js.map +0 -1
  280. package/dist/chunk-IAGOUTI6.js.map +0 -1
  281. package/dist/chunk-J2DAQQQH.js.map +0 -1
  282. package/dist/chunk-MTFCPPZ5.js.map +0 -1
  283. package/dist/chunk-P6TNXBDA.js.map +0 -1
  284. package/dist/chunk-PMOEG36E.js.map +0 -1
  285. package/dist/chunk-PPRV4LTM.js.map +0 -1
  286. package/dist/chunk-PUBPZOQJ.js.map +0 -1
  287. package/dist/chunk-QF6LTUCE.js.map +0 -1
  288. package/dist/chunk-RHIDWUK7.js.map +0 -1
  289. package/dist/chunk-TQ6FPOPD.js.map +0 -1
  290. package/dist/chunk-TUBCN4DJ.js.map +0 -1
  291. package/dist/chunk-ULTOQ6ZV.js.map +0 -1
  292. package/dist/chunk-UN5INW6K.js.map +0 -1
  293. package/dist/chunk-YU26GBNX.js.map +0 -1
  294. package/dist/chunk-ZAY6OA6F.js.map +0 -1
  295. /package/dist/{chunk-MR2HKBHS.js.map → chunk-27LOJVR3.js.map} +0 -0
  296. /package/dist/{chunk-S3D5VBHW.js.map → chunk-3YOXVNO4.js.map} +0 -0
  297. /package/dist/{chunk-CZIX4BW2.js.map → chunk-4ALF5PB5.js.map} +0 -0
  298. /package/dist/{chunk-XJPJ6ESI.js.map → chunk-4OAKGKK5.js.map} +0 -0
  299. /package/dist/{chunk-4CHROSWR.js.map → chunk-5ETBB2DG.js.map} +0 -0
  300. /package/dist/{chunk-46UPILLK.js.map → chunk-5NT2M2JI.js.map} +0 -0
  301. /package/dist/{chunk-H5BEWPEY.js.map → chunk-6N2EDWMG.js.map} +0 -0
  302. /package/dist/{chunk-GJQYM3PM.js.map → chunk-6PU3JYVY.js.map} +0 -0
  303. /package/dist/{chunk-Y7F5JBAT.js.map → chunk-DDRKYNPB.js.map} +0 -0
  304. /package/dist/{chunk-OS6KPL4D.js.map → chunk-EHYI2WCJ.js.map} +0 -0
  305. /package/dist/{chunk-NB3FGWU4.js.map → chunk-EQXIW5MQ.js.map} +0 -0
  306. /package/dist/{chunk-M2JTIH5M.js.map → chunk-F44R7US6.js.map} +0 -0
  307. /package/dist/{chunk-XJJXBUPN.js.map → chunk-FX26DAFF.js.map} +0 -0
  308. /package/dist/{chunk-R6SN73RX.js.map → chunk-GLHNMTP6.js.map} +0 -0
  309. /package/dist/{chunk-I4QA2F4L.js.map → chunk-HBRQPG7H.js.map} +0 -0
  310. /package/dist/{chunk-CNQUCNEA.js.map → chunk-I3F4C5SS.js.map} +0 -0
  311. /package/dist/{chunk-UFJYJHQI.js.map → chunk-J5VWGQSR.js.map} +0 -0
  312. /package/dist/{chunk-4JFL62K3.js.map → chunk-K7FSTB2K.js.map} +0 -0
  313. /package/dist/{chunk-FFCJ7NR2.js.map → chunk-KRQUPE4K.js.map} +0 -0
  314. /package/dist/{chunk-2OYFTSG4.js.map → chunk-KXLUMEDX.js.map} +0 -0
  315. /package/dist/{chunk-DVAAUWTC.js.map → chunk-LCHCE2G5.js.map} +0 -0
  316. /package/dist/{chunk-G4HBNILE.js.map → chunk-LEHMWJNZ.js.map} +0 -0
  317. /package/dist/{chunk-RZYSKQTS.js.map → chunk-PCBZYORN.js.map} +0 -0
  318. /package/dist/{chunk-5OBXEMQO.js.map → chunk-PRIBOWX4.js.map} +0 -0
  319. /package/dist/{chunk-PQECNGDE.js.map → chunk-QSRZOXQI.js.map} +0 -0
  320. /package/dist/{chunk-DCJSHYE5.js.map → chunk-RSDYS5B3.js.map} +0 -0
  321. /package/dist/{chunk-N5GVW6RO.js.map → chunk-S6IWKDWT.js.map} +0 -0
  322. /package/dist/{chunk-TKC6WHGB.js.map → chunk-SBIZXZPP.js.map} +0 -0
  323. /package/dist/{chunk-UEVHI62V.js.map → chunk-YCCY77W5.js.map} +0 -0
  324. /package/dist/{chunk-VZIB5W5L.js.map → chunk-ZGCPDA3F.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/layout/ScrollArea/ScrollArea.tsx"],"sourcesContent":["import KeyboardArrowUp from '@mui/icons-material/KeyboardArrowUp';\nimport Box from '@mui/material/Box/index.js';\nimport CircularProgress from '@mui/material/CircularProgress/index.js';\nimport Fab from '@mui/material/Fab/index.js';\nimport Zoom from '@mui/material/Zoom/index.js';\nimport { alpha, useTheme } from '@mui/material/styles/index.js';\nimport type { SxProps, Theme } from '@mui/material/styles/index.js';\nimport type { FC } from 'react';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { rem, sxRem } from '../../../tokens/relative';\n\nimport type { ResolvedScrollAreaProps } from './ScrollArea.helpers';\nimport { resolveScrollAreaProps } from './ScrollArea.helpers';\nimport { sizeCss } from './ScrollArea.styles';\nimport type { ScrollAreaProps } from './ScrollArea.types';\nimport { ScrollAreaContent } from './ScrollAreaContent';\nimport { ScrollViewport } from './ScrollViewport';\n\n// Owns the scroll container ref (merging in any ref the caller passed) and\n// reports size changes through a ResizeObserver.\nconst useObservedScrollRef = ({\n externalScrollRef,\n onResize }: {\n externalScrollRef?: React.Ref<HTMLDivElement>;\n onResize?: ScrollAreaProps['onResize'];\n}) => {\n const internalScrollRef = useRef<HTMLDivElement>(null);\n const [containerDimensions, setContainerDimensions] = useState({ width: 0, height: 0 });\n\n // Track container dimensions with ResizeObserver\n useEffect(() => {\n if (!internalScrollRef.current) return;\n\n const resizeObserver = new ResizeObserver((entries) => {\n const entry = entries[0];\n if (entry) {\n const { width, height } = entry.contentRect;\n setContainerDimensions({ width, height });\n onResize?.({ width, height });\n }\n });\n\n resizeObserver.observe(internalScrollRef.current);\n return () => resizeObserver.disconnect();\n }, [onResize]);\n\n // Callback ref that updates both internal and external refs\n const setScrollRef = useCallback(\n (node: HTMLDivElement | null) => {\n // Update internal ref\n (internalScrollRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n // Update external ref if provided\n if (externalScrollRef) {\n (externalScrollRef as React.MutableRefObject<HTMLDivElement | null>).current = node;\n }\n },\n [externalScrollRef],\n );\n\n // Use internal ref for accessing the element\n\n return { scrollRef: internalScrollRef, setScrollRef, containerDimensions };\n};\n\n// Scroll position, the transient \"is scrolling\" flag that drives auto-hide, the\n// observed container size, and the scroll-to-top affordance.\n// The scrollbar shows while scrolling and hides once movement stops.\nconst useAutoHide = ({\n autoHide,\n alwaysShowScrollbar,\n autoHideDelay }: {\n autoHide: boolean;\n alwaysShowScrollbar: boolean;\n autoHideDelay: number;\n}) => {\n const [isScrolling, setIsScrolling] = useState(false);\n const timeoutRef = useRef<number | undefined>(undefined);\n\n const noteScroll = useCallback(() => {\n if (!autoHide || alwaysShowScrollbar) return;\n\n setIsScrolling(true);\n window.clearTimeout(timeoutRef.current);\n timeoutRef.current = window.setTimeout(() => setIsScrolling(false), autoHideDelay);\n }, [autoHide, alwaysShowScrollbar, autoHideDelay]);\n\n useEffect(() => () => window.clearTimeout(timeoutRef.current), []);\n\n return { isScrolling, noteScroll };\n};\n\nconst useScrollArea = (\n props: ResolvedScrollAreaProps & { externalScrollRef?: React.Ref<HTMLDivElement> },\n) => {\n const {\n disabled,\n onScroll,\n onResize,\n externalScrollRef,\n autoHide,\n autoHideDelay,\n alwaysShowScrollbar,\n scrollToTopButton,\n scrollToTopThreshold,\n smoothScroll } = props;\n\n const { scrollRef, setScrollRef, containerDimensions } = useObservedScrollRef({\n externalScrollRef,\n onResize });\n const [showScrollToTop, setShowScrollToTop] = useState(false);\n const { isScrolling, noteScroll } = useAutoHide({\n autoHide,\n alwaysShowScrollbar,\n autoHideDelay });\n\n const handleScroll = useCallback(\n (event: React.UIEvent<HTMLDivElement>) => {\n if (disabled) return;\n\n noteScroll();\n\n if (scrollToTopButton && scrollRef.current) {\n setShowScrollToTop(scrollRef.current.scrollTop > scrollToTopThreshold);\n }\n\n onScroll?.(event);\n },\n [disabled, noteScroll, scrollToTopButton, scrollToTopThreshold, onScroll, scrollRef],\n );\n\n const scrollToTop = useCallback(() => {\n scrollRef.current?.scrollTo({ top: 0, behavior: smoothScroll ? 'smooth' : 'auto' });\n }, [smoothScroll, scrollRef]);\n\n return {\n scrollRef,\n setScrollRef,\n isScrolling,\n showScrollToTop,\n containerDimensions,\n handleScroll,\n scrollToTop };\n};\n\nconst LoadingOverlay: FC = () => (\n <Box\n sx={{\n position: 'absolute',\n top: '50%',\n left: '50%',\n transform: 'translate(-50%, -50%)',\n zIndex: 10 }}\n >\n <CircularProgress />\n </Box>\n);\n\n// The label is guarded at the call site rather than defaulted: the props union\n// already makes it required alongside `scrollToTopButton`, and a fab with an\n// empty accessible name is the exact failure this port exists to remove.\nconst ScrollToTopFab: FC<{\n visible: boolean;\n glass: boolean;\n scrollToTopLabel: string;\n onClick: () => void;\n}> = ({\n visible,\n glass,\n scrollToTopLabel,\n onClick }) => {\n const theme = useTheme();\n\n return (\n <Zoom in={visible}>\n <Fab\n size=\"small\"\n aria-label={scrollToTopLabel}\n onClick={onClick}\n sx={{\n position: 'absolute',\n bottom: sxRem(16),\n right: sxRem(16),\n zIndex: 1,\n backgroundColor: glass\n ? alpha(theme.palette.primary.main, 0.2)\n : theme.palette.primary.main,\n backdropFilter: glass ? `blur(${rem(theme, 10)})` : 'none',\n '&:hover': {\n backgroundColor: glass\n ? alpha(theme.palette.primary.main, 0.3)\n : theme.palette.primary.dark } }}\n >\n <KeyboardArrowUp />\n </Fab>\n </Zoom>\n );\n};\n\n/** The outer box: its size props through the type scale, then the caller's `sx`. */\nfunction outerBoxSx(\n theme: Theme,\n size: Pick<ScrollAreaProps, 'width' | 'height' | 'maxHeight' | 'maxWidth'>,\n sx: ScrollAreaProps['sx'],\n): SxProps<Theme> {\n return {\n position: 'relative',\n width: sizeCss(theme, size.width),\n height: sizeCss(theme, size.height),\n maxHeight: sizeCss(theme, size.maxHeight),\n maxWidth: sizeCss(theme, size.maxWidth),\n ...sx,\n } as SxProps<Theme>;\n}\n\nexport const ScrollArea: React.FC<ScrollAreaProps> = (componentProps) => {\n const theme = useTheme();\n const resolved = resolveScrollAreaProps(componentProps);\n const {\n regionLabel,\n scrollToTopLabel,\n children,\n width: _width,\n height: _height,\n maxHeight: _maxHeight,\n maxWidth: _maxWidth,\n orientation: _orientation,\n scrollbarSize: _scrollbarSize,\n autoHide,\n autoHideDelay: _autoHideDelay,\n smoothScroll: _smoothScroll,\n variant,\n onScroll: _onScroll,\n scrollToTopButton,\n scrollToTopThreshold: _scrollToTopThreshold,\n scrollbarColor: _scrollbarColor,\n scrollbarTrackColor: _scrollbarTrackColor,\n contentPadding: _contentPadding,\n alwaysShowScrollbar,\n disabled,\n loading,\n emptyContent,\n testId,\n scrollRef: externalScrollRef,\n onResize: _onResize,\n sx,\n ...props\n } = resolved;\n\n const { scrollRef, setScrollRef, isScrolling, showScrollToTop, containerDimensions, handleScroll, scrollToTop } =\n useScrollArea({ ...resolved, externalScrollRef });\n\n // Auto-hide keeps the scrollbar out of the way until the user is scrolling.\n const shouldShowScrollbar = alwaysShowScrollbar || !autoHide || isScrolling;\n\n return (\n <Box\n data-testid={testId}\n sx={outerBoxSx(theme, resolved, sx)}\n {...props}\n >\n <ScrollViewport\n {...resolved}\n regionLabel={regionLabel}\n shouldShowScrollbar={shouldShowScrollbar}\n setScrollRef={setScrollRef}\n onScroll={handleScroll}\n >\n <ScrollAreaContent\n emptyContent={emptyContent}\n scrollRef={scrollRef}\n containerWidth={containerDimensions.width}\n >\n {children}\n </ScrollAreaContent>\n </ScrollViewport>\n\n {loading && <LoadingOverlay />}\n\n {scrollToTopButton && scrollToTopLabel && !disabled && !loading && (\n <ScrollToTopFab\n scrollToTopLabel={scrollToTopLabel}\n visible={showScrollToTop}\n glass={variant === 'glass'}\n onClick={scrollToTop}\n />\n )}\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA,OAAO,qBAAqB;AAC5B,OAAO,SAAS;AAChB,OAAO,sBAAsB;AAC7B,OAAO,SAAS;AAChB,OAAO,UAAU;AACjB,SAAS,OAAO,gBAAgB;AAGhC,SAAgB,aAAa,WAAW,QAAQ,gBAAgB;AAkJ5D,cAsGA,YAtGA;AArIJ,IAAM,uBAAuB,CAAC;AAAA,EAC5B;AAAA,EACA;AAAS,MAGL;AACJ,QAAM,oBAAoB,OAAuB,IAAI;AACrD,QAAM,CAAC,qBAAqB,sBAAsB,IAAI,SAAS,EAAE,OAAO,GAAG,QAAQ,EAAE,CAAC;AAGtF,YAAU,MAAM;AACd,QAAI,CAAC,kBAAkB,QAAS;AAEhC,UAAM,iBAAiB,IAAI,eAAe,CAAC,YAAY;AACrD,YAAM,QAAQ,QAAQ,CAAC;AACvB,UAAI,OAAO;AACT,cAAM,EAAE,OAAO,OAAO,IAAI,MAAM;AAChC,+BAAuB,EAAE,OAAO,OAAO,CAAC;AACxC,mBAAW,EAAE,OAAO,OAAO,CAAC;AAAA,MAC9B;AAAA,IACF,CAAC;AAED,mBAAe,QAAQ,kBAAkB,OAAO;AAChD,WAAO,MAAM,eAAe,WAAW;AAAA,EACzC,GAAG,CAAC,QAAQ,CAAC;AAGb,QAAM,eAAe;AAAA,IACnB,CAAC,SAAgC;AAE/B,MAAC,kBAAoE,UAAU;AAE/E,UAAI,mBAAmB;AACrB,QAAC,kBAAoE,UAAU;AAAA,MACjF;AAAA,IACF;AAAA,IACA,CAAC,iBAAiB;AAAA,EACpB;AAIA,SAAO,EAAE,WAAW,mBAAmB,cAAc,oBAAoB;AAC3E;AAKA,IAAM,cAAc,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAc,MAIV;AACJ,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,KAAK;AACpD,QAAM,aAAa,OAA2B,MAAS;AAEvD,QAAM,aAAa,YAAY,MAAM;AACnC,QAAI,CAAC,YAAY,oBAAqB;AAEtC,mBAAe,IAAI;AACnB,WAAO,aAAa,WAAW,OAAO;AACtC,eAAW,UAAU,OAAO,WAAW,MAAM,eAAe,KAAK,GAAG,aAAa;AAAA,EACnF,GAAG,CAAC,UAAU,qBAAqB,aAAa,CAAC;AAEjD,YAAU,MAAM,MAAM,OAAO,aAAa,WAAW,OAAO,GAAG,CAAC,CAAC;AAEjE,SAAO,EAAE,aAAa,WAAW;AACnC;AAEA,IAAM,gBAAgB,CACpB,UACG;AACH,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAa,IAAI;AAEnB,QAAM,EAAE,WAAW,cAAc,oBAAoB,IAAI,qBAAqB;AAAA,IAC5E;AAAA,IACA;AAAA,EAAS,CAAC;AACZ,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAS,KAAK;AAC5D,QAAM,EAAE,aAAa,WAAW,IAAI,YAAY;AAAA,IAC9C;AAAA,IACA;AAAA,IACA;AAAA,EAAc,CAAC;AAEjB,QAAM,eAAe;AAAA,IACnB,CAAC,UAAyC;AACxC,UAAI,SAAU;AAEd,iBAAW;AAEX,UAAI,qBAAqB,UAAU,SAAS;AAC1C,2BAAmB,UAAU,QAAQ,YAAY,oBAAoB;AAAA,MACvE;AAEA,iBAAW,KAAK;AAAA,IAClB;AAAA,IACA,CAAC,UAAU,YAAY,mBAAmB,sBAAsB,UAAU,SAAS;AAAA,EACrF;AAEA,QAAM,cAAc,YAAY,MAAM;AACpC,cAAU,SAAS,SAAS,EAAE,KAAK,GAAG,UAAU,eAAe,WAAW,OAAO,CAAC;AAAA,EACpF,GAAG,CAAC,cAAc,SAAS,CAAC;AAE5B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAY;AAChB;AAEA,IAAM,iBAAqB,MACzB;AAAA,EAAC;AAAA;AAAA,IACC,IAAI;AAAA,MACF,UAAU;AAAA,MACV,KAAK;AAAA,MACL,MAAM;AAAA,MACN,WAAW;AAAA,MACX,QAAQ;AAAA,IAAG;AAAA,IAEb,8BAAC,oBAAiB;AAAA;AACpB;AAMF,IAAM,iBAKD,CAAC;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAQ,MAAM;AACd,QAAM,QAAQ,SAAS;AAEvB,SACE,oBAAC,QAAK,IAAI,SACR;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL,cAAY;AAAA,MACZ;AAAA,MACA,IAAI;AAAA,QACF,UAAU;AAAA,QACV,QAAQ,MAAM,EAAE;AAAA,QAChB,OAAO,MAAM,EAAE;AAAA,QACf,QAAQ;AAAA,QACR,iBAAiB,QACb,MAAM,MAAM,QAAQ,QAAQ,MAAM,GAAG,IACrC,MAAM,QAAQ,QAAQ;AAAA,QAC1B,gBAAgB,QAAQ,QAAQ,IAAI,OAAO,EAAE,CAAC,MAAM;AAAA,QACpD,WAAW;AAAA,UACT,iBAAiB,QACb,MAAM,MAAM,QAAQ,QAAQ,MAAM,GAAG,IACrC,MAAM,QAAQ,QAAQ;AAAA,QAAK;AAAA,MAAE;AAAA,MAErC,8BAAC,mBAAgB;AAAA;AAAA,EACnB,GACF;AAEJ;AAGA,SAAS,WACP,OACA,MACA,IACgB;AAChB,SAAO;AAAA,IACL,UAAU;AAAA,IACV,OAAO,QAAQ,OAAO,KAAK,KAAK;AAAA,IAChC,QAAQ,QAAQ,OAAO,KAAK,MAAM;AAAA,IAClC,WAAW,QAAQ,OAAO,KAAK,SAAS;AAAA,IACxC,UAAU,QAAQ,OAAO,KAAK,QAAQ;AAAA,IACtC,GAAG;AAAA,EACL;AACF;AAEO,IAAM,aAAwC,CAAC,mBAAmB;AACvE,QAAM,QAAQ,SAAS;AACvB,QAAM,WAAW,uBAAuB,cAAc;AACtD,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,UAAU;AAAA,IACV,aAAa;AAAA,IACb,eAAe;AAAA,IACf;AAAA,IACA,eAAe;AAAA,IACf,cAAc;AAAA,IACd;AAAA,IACA,UAAU;AAAA,IACV;AAAA,IACA,sBAAsB;AAAA,IACtB,gBAAgB;AAAA,IAChB,qBAAqB;AAAA,IACrB,gBAAgB;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,WAAW;AAAA,IACX,UAAU;AAAA,IACV;AAAA,IACA,GAAG;AAAA,EACL,IAAI;AAEJ,QAAM,EAAE,WAAW,cAAc,aAAa,iBAAiB,qBAAqB,cAAc,YAAY,IAC5G,cAAc,EAAE,GAAG,UAAU,kBAAkB,CAAC;AAGlD,QAAM,sBAAsB,uBAAuB,CAAC,YAAY;AAEhE,SACE;AAAA,IAAC;AAAA;AAAA,MACC,eAAa;AAAA,MACb,IAAI,WAAW,OAAO,UAAU,EAAE;AAAA,MACjC,GAAG;AAAA,MAEJ;AAAA;AAAA,UAAC;AAAA;AAAA,YACE,GAAG;AAAA,YACJ;AAAA,YACA;AAAA,YACA;AAAA,YACA,UAAU;AAAA,YAEV;AAAA,cAAC;AAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA,gBAAgB,oBAAoB;AAAA,gBAEnC;AAAA;AAAA,YACH;AAAA;AAAA,QACF;AAAA,QAEC,WAAW,oBAAC,kBAAe;AAAA,QAE3B,qBAAqB,oBAAoB,CAAC,YAAY,CAAC,WACtD;AAAA,UAAC;AAAA;AAAA,YACC;AAAA,YACA,SAAS;AAAA,YACT,OAAO,YAAY;AAAA,YACnB,SAAS;AAAA;AAAA,QACX;AAAA;AAAA;AAAA,EAEJ;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/form/Switch/Switch.metrics.ts"],"sourcesContent":["import type { SwitchVariant } from './Switch.base';\nimport { alpha } from '../../../tokens/color';\nimport { ABSOLUTE_INK, ELEVATION_SHADOWS, NEUTRAL_RAMP } from '../../../tokens/ink.core';\nimport type { SizeValue } from '../../../tokens/vocabulary';\n\n/**\n * THE NUMBERS BOTH `Switch` RENDERERS DRAW WITH.\n *\n * `Switch.styles.ts` (web, emotion over MUI's `Switch`) and\n * `Switch.native.tsx` (React Native, drawing the track and thumb itself) read\n * this one table: the geometry per size, the four looks' radii and shadows,\n * the resting track colours, and the type the label, the description and the\n * helper are set in.\n *\n * Spacing is in SPACING UNITS where the web writes `theme.spacing(n)`;\n * everything else is px, a ratio or an alpha.\n */\n\n/** MUI's `palette.common.black`, which `UiTheme` does not carry. */\nexport const SWITCH_BLACK = ABSOLUTE_INK.black;\n\nexport interface SwitchGeometry {\n width: number;\n height: number;\n padding: number;\n thumbSize: number;\n}\n\nexport const SWITCH_SIZES: Record<SizeValue, SwitchGeometry> = {\n xs: { width: 34, height: 18, padding: 1, thumbSize: 14 },\n sm: { width: 42, height: 22, padding: 1, thumbSize: 18 },\n md: { width: 50, height: 26, padding: 1, thumbSize: 22 },\n lg: { width: 58, height: 30, padding: 2, thumbSize: 24 },\n xl: { width: 66, height: 34, padding: 2, thumbSize: 28 },\n};\n\n/** The four platform looks. `label` prints its wording on a `default` track. */\nexport type SwitchLook = 'ios' | 'android' | 'material' | 'default';\n\nexport const lookOf = (variant?: string): SwitchLook => {\n if (variant === 'ios') return 'ios';\n if (variant === 'android') return 'android';\n if (variant === 'material') return 'material';\n return 'default';\n};\n\n/** Track geometry once the caller's overrides and the size preset are combined. */\nexport const geometryOf = (size: SizeValue | undefined, width?: number, height?: number): SwitchGeometry => {\n const preset = SWITCH_SIZES[size as SizeValue] ?? SWITCH_SIZES.md;\n return { ...preset, width: width || preset.width, height: height || preset.height };\n};\n\n/**\n * The thumb's corner. `'50%'` is what the web emits; a renderer with no\n * percentage radius asks {@link thumbRadius} for the px instead.\n */\nexport const THUMB_RADIUS: Record<SwitchLook, (thumbSize: number) => number | string> = {\n ios: () => '50%',\n android: () => 4,\n material: (thumbSize) => thumbSize / 3,\n default: () => '50%',\n};\n\nexport const TRACK_RADIUS: Record<SwitchLook, (height: number) => number> = {\n ios: (height) => height / 2,\n android: (height) => height / 3,\n material: (height) => height / 2.5,\n default: (height) => height / 2,\n};\n\n/** The web's `'50%'` as the px a circle of this size needs. */\nexport const thumbRadius = (look: SwitchLook, thumbSize: number): number => {\n const radius = THUMB_RADIUS[look](thumbSize);\n return typeof radius === 'number' ? radius : thumbSize / 2;\n};\n\n/**\n * The elevation the thumb rests at per look — an INDEX into `theme.shadows`,\n * not the shadow itself, so a host that re-themes MUI's elevations keeps\n * moving the web. {@link MUI_SHADOWS} carries MUI's own values for the native\n * side, which has no `theme.shadows` to read.\n */\nexport const THUMB_ELEVATION: Record<SwitchLook, number> = { ios: 0, android: 3, material: 2, default: 2 };\n\nexport const MUI_SHADOWS: Record<number, string> = {\n 2: ELEVATION_SHADOWS[2],\n 3: ELEVATION_SHADOWS[3],\n};\n\n/** The iOS thumb's own three-layer shadow, which the web writes out literally. */\nexport const IOS_THUMB_SHADOW = `0 3px 1px 0 ${alpha(SWITCH_BLACK, 0.04)}, 0 3px 8px 0 ${alpha(SWITCH_BLACK, 0.12)}, 0 1px 0 0 ${alpha(SWITCH_BLACK, 0.08)}`;\n\n/** The iOS track's inset hairline. */\nexport const iosTrackShadow = (): string =>\n `inset 0 0 0 0.5px ${alpha(SWITCH_BLACK, 0.1)}, inset 0 2px 3px ${alpha(SWITCH_BLACK, 0.12)}`;\n\n/** The resting track: a black wash on iOS, the disabled ink elsewhere. */\nexport const TRACK_ALPHA = { ios: 0.1, android: 0.2, other: 0.3 } as const;\n\n/**\n * `black` is MUI's `palette.common.black` on the web and {@link SWITCH_BLACK}\n * on native, whose theme has no `common` — the same `#000` either way, passed\n * in rather than assumed so a host that themes it still moves the web.\n */\nexport const trackColor = (ink: { black: string; disabled: string }, look: SwitchLook): string => {\n if (look === 'ios') return alpha(ink.black, TRACK_ALPHA.ios);\n const strength = look === 'android' ? TRACK_ALPHA.android : TRACK_ALPHA.other;\n return alpha(ink.disabled, strength);\n};\n\n/** How far the thumb travels, and where it starts. iOS insets differently. */\nexport const thumbTravel = (look: SwitchLook, geometry: SwitchGeometry): { rest: number; travel: number } => {\n const { width, thumbSize, padding } = geometry;\n if (look === 'ios') {\n // The web nudges the whole switch base 2px right and shortens the trip.\n return { rest: padding + IOS_BASE_OFFSET, travel: width - thumbSize - IOS_TRAVEL_INSET };\n }\n return { rest: padding, travel: width - thumbSize - padding * 2 };\n};\n\nexport const IOS_BASE_OFFSET = 2;\nexport const IOS_TRAVEL_INSET = 4;\n\n/** MUI's 300ms `cubic-bezier(0.4, 0, 0.2, 1)`, on everything the switch moves. */\nexport const SWITCH_TRANSITION = { ms: 300, easing: 'cubic-bezier(0.4, 0, 0.2, 1)' } as const;\n\n/** The disabled treatment: the thumb greys and the track fades. */\nexport const DISABLED = { trackOpacity: 0.3, checkedTrackOpacity: 0.5, thumbGrey: 100 } as const;\n\n/** `glass`: a paper wash under a blur, inside a faint divider hairline. */\nexport const SWITCH_GLASS = {\n trackAlpha: 0.1,\n thumbAlpha: 0.9,\n borderAlpha: 0.2,\n trackBlur: 20,\n thumbBlur: 10,\n} as const;\n\n/** `gradient`: the checked track runs light → main → dark; the resting one is fainter. */\nexport const SWITCH_GRADIENT = {\n checked: { angleDeg: 90, stops: [0, 50, 100] },\n resting: { angleDeg: 135, lightAlpha: 0.3, mainAlpha: 0.2 },\n shimmerMs: 3000,\n} as const;\n\n/** `glow`: a halo of the hue around the checked track, breathing every two seconds. */\nexport const SWITCH_GLOW = { blur: 10, alpha: 0.6, insetBlur: 10, insetAlpha: 0.2, ms: 2000 } as const;\n\n/** `pulse`: the thumb breathes; `ripple`: a wash of the hue expands under the pointer. */\nexport const SWITCH_PULSE = { ms: 2000, minOpacity: 0.7, minScale: 0.95 } as const;\nexport const SWITCH_RIPPLE = { alpha: 0.2, ms: 600, scale: 2 } as const;\n\n/** `loading`: a 2px ring inside the thumb, turning once a second. */\nexport const SWITCH_SPINNER = { sizeRatio: 0.6, borderWidth: 2, ms: 1000 } as const;\n\n/** The two icons overlaid on the track, at their own size per step of the scale. */\nexport const SWITCH_ICON_SIZES: Record<SizeValue, number> = { xs: 12, sm: 14, md: 16, lg: 18, xl: 20 };\n/** Where a shown icon sits, and how small a hidden one is drawn. */\nexport const SWITCH_ICON = { inset: 4, hiddenScale: 0.8 } as const;\n\n/** The wording the `label` variant prints inside the track: 0.75rem at 500, 8px in. */\nexport const TRACK_LABEL = { fontSize: 12, fontWeight: 500, insetUnits: 1 } as const;\n\n/** MUI's `body2` for the label, `caption` for the description and the helper text. */\nexport const SWITCH_LABEL = { fontSize: 14, lineHeight: 1.43, fontWeight: 500 } as const;\nexport const SWITCH_DESCRIPTION = { fontSize: 12, lineHeight: 1.66, marginTopUnits: 0.5 } as const;\nexport const SWITCH_HELPER = { fontSize: 12, lineHeight: 1.66, marginTopUnits: 1 } as const;\n\n/** The label row: 16px from the control beside it, 8px above or below it. */\nexport const LABEL_GAP_UNITS = { beside: 2, stacked: 1 } as const;\n\n/**\n * The minimum height of a touch target, in px (FUT-1905).\n *\n * No entry in {@link SWITCH_SIZES} reaches it — `xl`, the largest, is 34px tall\n * and `md` is 26 — so a consumer cannot buy a legal target by passing a bigger\n * `size`. The label is what clears it: see `SwitchLabel` in `Switch.parts.tsx`.\n */\nexport const TAP_TARGET_MIN = 40;\n\n/**\n * `neutral`'s three greys, and the literals the web falls back to for a theme\n * whose grey ramp omits a step. Same three steps `Button` draws its neutral\n * from.\n */\nexport const NEUTRAL_GREY = { main: 700, dark: 800, light: 500 } as const;\nexport const NEUTRAL_FALLBACK = {\n main: NEUTRAL_RAMP[NEUTRAL_GREY.main],\n dark: NEUTRAL_RAMP[NEUTRAL_GREY.dark],\n light: NEUTRAL_RAMP[NEUTRAL_GREY.light],\n} as const;\nexport const NEUTRAL_CONTRAST = ABSOLUTE_INK.white;\n\n/**\n * The RESTING thumb — the knob while the switch is off (FUT-1924).\n *\n * It stays white, and the reason is worth stating because the checked thumb no\n * longer is: the resting track is `theme.palette.action.disabled` washed over\n * the page, which no tenant picks, and a white knob on it is the conventional\n * look in both modes. The CHECKED track is `palette.main`, a colour the tenant\n * does pick, and that is where a stated white was a defect. See `checkedInk`\n * in `Switch.styles.ts` and its native twin.\n */\nexport const RESTING_THUMB = ABSOLUTE_INK.white;\n\n/** Hover: the thumb lifts a shade and takes a halo of the hue. */\nexport const SWITCH_HOVER = { thumbScale: 1.05, elevation: 4, blur: 12, alpha: 0.2 } as const;\n\n/** Focus: MUI rings the thumb rather than moving it. */\nexport const SWITCH_FOCUS_RING = { width: 6, alpha: 0.2 } as const;\n\n/** A duration as the CSS the web has always emitted: `2000` → `2s`. */\nexport const seconds = (ms: number): string => `${ms / 1000}s`;\n\n/** Whether this variant prints its wording inside the track. */\nexport const showsTrackLabels = (variant: SwitchVariant | undefined, onText?: string, offText?: string): boolean =>\n variant === 'label' && Boolean(onText ?? offText);\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Table/Table.hooks.ts"],"sourcesContent":["import { useTheme } from '@mui/material/styles/index.js';\nimport useMediaQuery from '@mui/material/useMediaQuery/index.js';\nimport { useCallback, useEffect, useMemo, useState } from 'react';\n\nimport type { ColumnConfig, TableProps } from './Table.types';\n\nexport const useVirtualScrolling = (\n data: Record<string, unknown>[],\n rowHeight: number,\n containerHeight: number,\n overscan: number = 5\n) => {\n const [scrollTop, setScrollTop] = useState(0);\n \n const visibleItems = useMemo(() => {\n const visibleHeight = containerHeight;\n const startIndex = Math.floor(scrollTop / rowHeight);\n const endIndex = Math.min(\n data.length,\n Math.ceil((scrollTop + visibleHeight) / rowHeight)\n );\n \n const start = Math.max(0, startIndex - overscan);\n const end = Math.min(data.length, endIndex + overscan);\n \n return {\n startIndex: start,\n endIndex: end,\n items: data.slice(start, end),\n totalHeight: data.length * rowHeight,\n offsetY: start * rowHeight,\n };\n }, [data, rowHeight, containerHeight, scrollTop, overscan]);\n\n const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {\n setScrollTop(e.currentTarget.scrollTop);\n }, []);\n\n return { visibleItems, handleScroll };\n};\n\n// Responsive Hook\n\nconst useResponsive = (\n columns: ColumnConfig[],\n columnPriorities?: number[]\n) => {\n const theme = useTheme();\n const isMobile = useMediaQuery(theme.breakpoints.down('md'));\n const isTablet = useMediaQuery(theme.breakpoints.down('lg'));\n \n const [hiddenColumns, setHiddenColumns] = useState<number[]>([]);\n const [columnMenuAnchor, setColumnMenuAnchor] = useState<null | HTMLElement>(null);\n\n useEffect(() => {\n if (!columnPriorities) return;\n \n let columnsToHide: number[] = [];\n \n if (isMobile) {\n // Hide lowest priority columns on mobile\n columnsToHide = columnPriorities\n .map((priority, index) => ({ priority, index }))\n .sort((a, b) => b.priority - a.priority)\n .slice(0, Math.floor(columns.length / 2))\n .map(item => item.index);\n } else if (isTablet) {\n // Hide some columns on tablet\n columnsToHide = columnPriorities\n .map((priority, index) => ({ priority, index }))\n .sort((a, b) => b.priority - a.priority)\n .slice(0, Math.floor(columns.length / 3))\n .map(item => item.index);\n }\n \n setHiddenColumns(columnsToHide);\n }, [isMobile, isTablet, columnPriorities, columns.length]);\n\n const visibleColumns = columns.filter((_, index) => !hiddenColumns.includes(index));\n\n return {\n visibleColumns,\n hiddenColumns,\n isMobile,\n columnMenuAnchor,\n setColumnMenuAnchor,\n setHiddenColumns,\n };\n};\n\n// Enhanced Table Header Component\n// Visible/hidden column split for responsive mode, plus row selection.\nexport const useTableSelection = ({\n columns,\n data,\n responsive,\n columnPriorities,\n selectedRows,\n rowKeyExtractor,\n onSelectionChange,\n}: {\n columns?: ColumnConfig[];\n data: TableProps['data'];\n responsive?: boolean;\n columnPriorities?: number[];\n selectedRows: (string | number)[];\n rowKeyExtractor?: (row: Record<string, unknown>, index: number) => string | number;\n onSelectionChange?: TableProps['onSelectionChange'];\n}) => {\n \n // Use responsive hook if responsive mode is enabled\n const {\n visibleColumns,\n hiddenColumns,\n isMobile,\n columnMenuAnchor,\n setColumnMenuAnchor,\n setHiddenColumns,\n } = useResponsive(\n columns || [],\n responsive ? columnPriorities : undefined\n );\n\n // Handle selection changes\n const handleSelectionChange = useCallback((rowKey: string | number, selected: boolean) => {\n if (!onSelectionChange) return;\n \n let newSelection: (string | number)[];\n if (selected) {\n newSelection = [...selectedRows, rowKey];\n } else {\n newSelection = selectedRows.filter(key => key !== rowKey);\n }\n onSelectionChange(newSelection);\n }, [selectedRows, onSelectionChange]);\n\n const handleSelectAll = useCallback((selected: boolean) => {\n if (!onSelectionChange || !data) return;\n \n if (selected) {\n const allKeys = data.map((rowData, index) => \n rowKeyExtractor ? rowKeyExtractor(rowData, index) : (rowData.id as string | number) || index\n );\n onSelectionChange(allKeys);\n } else {\n onSelectionChange([]);\n }\n }, [data, onSelectionChange, rowKeyExtractor]);\n\n // Loading state\n\n return {\n visibleColumns,\n hiddenColumns,\n isMobile,\n columnMenuAnchor,\n setColumnMenuAnchor,\n setHiddenColumns,\n handleSelectionChange,\n handleSelectAll,\n };\n};\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataGrid/DataGrid.model.ts"],"sourcesContent":["/**\n * The DataGrid's STATE, in one hook.\n *\n * The component used to hold all of it inline, which made its body 700 lines\n * long and put the row pipeline, the virtualization window and the JSX in one\n * scope where any of them could reach any other. Split out, each piece is a\n * hook with named inputs and the render is left with nothing to do but render.\n *\n * Controlled/uncontrolled is resolved in ONE place per feature: a caller that\n * passes `sorting.sortBy` owns the sort, and a caller that does not gets the\n * internal state — the component never holds a second, divergent copy.\n */\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type React from 'react';\n\nimport { processRows } from './DataGrid.rows';\nimport type {\n DataGridProps,\n GridColumn,\n GridFilter,\n GridSort,\n SortDirection,\n} from './DataGrid.types';\n\nconst DEFAULT_ROW_HEIGHT = 52;\nconst DEFAULT_PAGE_SIZE = 50;\n/** Rows rendered on either side of the window, so a fast scroll stays filled. */\nconst OVERSCAN_COUNT = 20;\n/** Below this many rows, virtualization costs more than it saves. */\nconst VIRTUALIZATION_THRESHOLD = 100;\n/** The initial (and reset) window size, before a scroll has measured anything. */\nconst INITIAL_WINDOW = 50;\n/** Re-window only past this much drift, so a scroll is not one setState per pixel. */\nconst WINDOW_DRIFT = 5;\n\n/** Which id is being edited, or `null`. */\nexport interface EditingCell {\n rowId: string | number;\n colId: string;\n}\n\n/** The visible slice of a virtualized body. */\nexport interface VisibleRange {\n start: number;\n end: number;\n}\n\n/** Everything the render needs, and nothing it has to derive. */\nexport interface DataGridModel<T extends Record<string, unknown>> {\n containerRef: React.RefObject<HTMLDivElement | null>;\n rowHeight: number;\n visibleColumns: GridColumn<T>[];\n processedRows: T[];\n visibleRows: T[];\n visibleRange: VisibleRange;\n virtualized: boolean;\n sortBy: readonly GridSort[];\n selectedRowIds: Array<string | number>;\n selectedRowIdsSet: ReadonlySet<string | number>;\n expandedRowIdsSet: ReadonlySet<string | number>;\n editingCell: EditingCell | null;\n setEditingCell: (cell: EditingCell | null) => void;\n setSelectedRowIds: (ids: Array<string | number>) => void;\n onSort: (columnId: string) => void;\n onToggleRow: (rowId: string | number, isSelected: boolean) => void;\n onToggleExpansion: (rowId: string | number) => void;\n onScroll: (event: React.UIEvent<HTMLDivElement>) => void;\n}\n\n/** The row height a density implies. */\nfunction densityHeight(base: number, density: DataGridProps['density']): number {\n if (density === 'compact') return Math.max(base * 0.8, 32);\n if (density === 'spacious') return base * 1.2;\n return base;\n}\n\n/** The rows this render should show, with every client-mode step resolved. */\nfunction useProcessedRows<T extends Record<string, unknown>>(\n props: DataGridProps<T>,\n columnMap: ReadonlyMap<string, GridColumn<T>>,\n sortBy: readonly GridSort[],\n filters: readonly GridFilter[],\n): T[] {\n const { rows, filtering = {}, sorting = {}, pagination, virtualizeRows = true } = props;\n const pageIndex = pagination?.pageIndex ?? 0;\n const pageSize = pagination?.pageSize ?? DEFAULT_PAGE_SIZE;\n return useMemo(\n () =>\n processRows({\n rows,\n columnMap,\n filters,\n sortBy,\n needsFiltering: filtering.mode === 'client' && filters.length > 0,\n needsSorting: sorting.mode === 'client' && sortBy.length > 0,\n // Virtualization already slices; doing both would page a page.\n needsPagination: pagination?.mode === 'client' && !virtualizeRows,\n pageIndex,\n pageSize,\n }),\n [\n rows,\n columnMap,\n filters,\n sortBy,\n filtering.mode,\n sorting.mode,\n pagination?.mode,\n virtualizeRows,\n pageIndex,\n pageSize,\n ],\n );\n}\n\n/**\n * The virtualization window and the scroll handler that moves it.\n *\n * Throttled through `requestAnimationFrame`, and only committed once the window\n * has drifted meaningfully — a `setState` per scroll event re-renders every\n * visible row for a movement the eye cannot see.\n */\nfunction useRowWindow(\n rowCount: number,\n rowHeight: number,\n enabled: boolean,\n): { range: VisibleRange; onScroll: (event: React.UIEvent<HTMLDivElement>) => void } {\n const [range, setRange] = useState<VisibleRange>({ start: 0, end: INITIAL_WINDOW });\n const rafRef = useRef<number | null>(null);\n\n useEffect(() => {\n if (rowCount < range.end) setRange({ start: 0, end: Math.min(INITIAL_WINDOW, rowCount) });\n }, [rowCount, range.end]);\n\n useEffect(\n () => () => {\n if (rafRef.current !== null) window.cancelAnimationFrame(rafRef.current);\n },\n [],\n );\n\n const onScroll = useCallback(\n (event: React.UIEvent<HTMLDivElement>) => {\n if (!enabled) return;\n const { scrollTop, clientHeight } = event.currentTarget;\n if (rafRef.current !== null) window.cancelAnimationFrame(rafRef.current);\n rafRef.current = window.requestAnimationFrame(() => {\n const first = Math.floor(scrollTop / rowHeight);\n const visible = Math.ceil(clientHeight / rowHeight);\n const start = Math.max(0, first - OVERSCAN_COUNT);\n const end = Math.min(first + visible + OVERSCAN_COUNT, rowCount);\n setRange((current) =>\n Math.abs(start - current.start) > WINDOW_DRIFT ||\n Math.abs(end - current.end) > WINDOW_DRIFT\n ? { start, end }\n : current,\n );\n rafRef.current = null;\n });\n },\n [enabled, rowHeight, rowCount],\n );\n\n return { range, onScroll };\n}\n\n/** The next `sortBy` for a header press: asc → desc → unsorted. */\nfunction nextSortBy(current: readonly GridSort[], columnId: string): GridSort[] {\n const existing = current.find((sort) => sort.id === columnId);\n let dir: SortDirection = 'asc';\n if (existing?.dir === 'asc') dir = 'desc';\n else if (existing?.dir === 'desc') dir = null;\n return dir ? [{ id: columnId, dir }] : current.filter((sort) => sort.id !== columnId);\n}\n\n/** Selection + expansion, each resolved once against its controlled prop. */\nfunction useRowFlags<T extends Record<string, unknown>>(\n props: DataGridProps<T>,\n): Pick<\n DataGridModel<T>,\n | 'selectedRowIds'\n | 'selectedRowIdsSet'\n | 'expandedRowIdsSet'\n | 'setSelectedRowIds'\n | 'onToggleRow'\n | 'onToggleExpansion'\n> {\n const { selection = { mode: 'none' }, expansion } = props;\n const [internalSelected, setInternalSelected] = useState(selection.defaultSelectedRowIds ?? []);\n const [internalExpanded, setInternalExpanded] = useState(expansion?.defaultExpandedRowIds ?? []);\n const selectedRowIds = selection.selectedRowIds ?? internalSelected;\n const expandedRowIds = expansion?.expandedRowIds ?? internalExpanded;\n\n const commitSelected = useCallback(\n (ids: Array<string | number>) => {\n if (selection.onChangeSelected) selection.onChangeSelected(ids);\n else setInternalSelected(ids);\n },\n [selection],\n );\n\n return {\n selectedRowIds,\n selectedRowIdsSet: useMemo(() => new Set(selectedRowIds), [selectedRowIds]),\n expandedRowIdsSet: useMemo(() => new Set(expandedRowIds), [expandedRowIds]),\n setSelectedRowIds: commitSelected,\n onToggleRow: (rowId, isSelected) => {\n if (selection.mode === 'single') commitSelected(isSelected ? [rowId] : []);\n else if (selection.mode === 'multi') {\n commitSelected(\n isSelected\n ? [...selectedRowIds, rowId]\n : selectedRowIds.filter((id) => id !== rowId),\n );\n }\n },\n onToggleExpansion: (rowId) => {\n if (!expansion) return;\n const next = expandedRowIds.includes(rowId)\n ? expandedRowIds.filter((id) => id !== rowId)\n : [...expandedRowIds, rowId];\n if (expansion.onChangeExpanded) expansion.onChangeExpanded(next);\n else setInternalExpanded(next);\n },\n };\n}\n\n/**\n * A header press, routed to whoever owns the sort: the server (which must\n * re-query — sorting the current page locally would reorder one page of a\n * dataset and call it sorted), the caller's `onChangeSortBy`, or internal state.\n */\nfunction useSortHandler<T extends Record<string, unknown>>(\n props: DataGridProps<T>,\n sortBy: readonly GridSort[],\n filters: readonly GridFilter[],\n setInternalSortBy: (next: GridSort[]) => void,\n): (columnId: string) => void {\n const { sorting = {}, pagination, onRequestData } = props;\n return useCallback(\n (columnId: string) => {\n const next = nextSortBy(sortBy, columnId);\n if (sorting.mode === 'server' && onRequestData) {\n onRequestData({\n pageIndex: pagination?.pageIndex ?? 0,\n pageSize: pagination?.pageSize ?? DEFAULT_PAGE_SIZE,\n sortBy: next,\n filters: [...filters],\n });\n return;\n }\n if (sorting.onChangeSortBy) sorting.onChangeSortBy(next);\n else setInternalSortBy(next);\n },\n [sortBy, sorting, onRequestData, pagination, filters, setInternalSortBy],\n );\n}\n\n/**\n * Sort and filter, each resolved ONCE against its controlled prop: a caller\n * that passes `sorting.sortBy` owns the sort, and one that does not gets the\n * internal state. The grid never holds a second, divergent copy.\n */\nfunction useSortAndFilter<T extends Record<string, unknown>>(\n props: DataGridProps<T>,\n): {\n sortBy: readonly GridSort[];\n filters: readonly GridFilter[];\n setInternalSortBy: (next: GridSort[]) => void;\n} {\n const { sorting = {}, filtering = {} } = props;\n const [internalSortBy, setInternalSortBy] = useState<GridSort[]>(sorting.defaultSortBy ?? []);\n const [internalFilters] = useState<GridFilter[]>(filtering.defaultFilters ?? []);\n return {\n sortBy: sorting.sortBy ?? internalSortBy,\n filters: filtering.filters ?? internalFilters,\n setInternalSortBy,\n };\n}\n\nexport function useDataGridModel<T extends Record<string, unknown>>(\n props: DataGridProps<T>,\n): DataGridModel<T> {\n const { columns } = props;\n const containerRef = useRef<HTMLDivElement>(null);\n const [editingCell, setEditingCell] = useState<EditingCell | null>(null);\n const { sortBy, filters, setInternalSortBy } = useSortAndFilter(props);\n const rowHeight = densityHeight(props.rowHeight ?? DEFAULT_ROW_HEIGHT, props.density);\n const columnMap = useMemo(\n () => new Map(columns.map((column) => [column.id, column])),\n [columns],\n );\n const visibleColumns = useMemo(() => columns.filter((column) => !column.hidden), [columns]);\n const processedRows = useProcessedRows(props, columnMap, sortBy, filters);\n const virtualized =\n (props.virtualizeRows ?? true) && processedRows.length > VIRTUALIZATION_THRESHOLD;\n const { range, onScroll } = useRowWindow(processedRows.length, rowHeight, virtualized);\n const onSort = useSortHandler(props, sortBy, filters, setInternalSortBy);\n\n return {\n containerRef,\n rowHeight,\n visibleColumns,\n processedRows,\n visibleRows: virtualized ? processedRows.slice(range.start, range.end) : processedRows,\n visibleRange: range,\n virtualized,\n sortBy,\n editingCell,\n setEditingCell,\n onSort,\n onScroll,\n ...useRowFlags(props),\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/layout/Resizable/Resizable.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport { useTheme } from '@mui/material/styles/index.js';\nimport React, { useMemo } from 'react';\n\nimport { defaultHandles, handleStyle, resolveResizableProps } from './Resizable.helpers';\nimport { useResize } from './Resizable.hooks';\nimport type { ResizableProps } from './Resizable.types';\n\nexport const Resizable: React.FC<ResizableProps> = (rawProps) => {\n const {\n children,\n variant,\n width: initialWidth,\n height: initialHeight,\n minWidth,\n maxWidth,\n minHeight,\n maxHeight,\n onResize,\n disabled,\n handles,\n className,\n 'data-testid': dataTestId,\n ...rest\n } = resolveResizableProps(rawProps);\n const theme = useTheme();\n const bounds = useMemo(\n () => ({\n width: { min: minWidth, max: maxWidth },\n height: { min: minHeight, max: maxHeight },\n }),\n [minWidth, maxWidth, minHeight, maxHeight],\n );\n\n const { size, isResizing, activeHandle, handleMouseDown } = useResize({\n width: initialWidth,\n height: initialHeight,\n bounds,\n disabled,\n onResize,\n });\n\n const activeHandles = handles || defaultHandles(variant);\n\n return (\n <Box\n {...rest}\n className={className}\n data-testid={dataTestId}\n sx={{\n position: 'relative',\n width: size.width,\n height: size.height,\n border: `1px solid ${theme.palette.divider}`,\n borderRadius: theme.spacing(0.5),\n overflow: 'hidden',\n userSelect: isResizing ? 'none' : 'auto',\n '&:hover .resize-handle': {\n opacity: 0.3,\n },\n }}\n >\n {children}\n {!disabled &&\n activeHandles.map((handle) => (\n <Box\n key={handle}\n className=\"resize-handle\"\n data-testid={dataTestId ? `${dataTestId}-handle-${handle}` : undefined}\n sx={handleStyle(theme, handle, isResizing && activeHandle.current === handle)}\n onMouseDown={(e) => handleMouseDown(e, handle)}\n />\n ))}\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;;AAAA,OAAO,SAAS;AAChB,SAAS,gBAAgB;AACzB,SAAgB,eAAe;AA2C3B,SAoBM,KApBN;AArCG,IAAM,YAAsC,CAAC,aAAa;AAC/D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,GAAG;AAAA,EACL,IAAI,sBAAsB,QAAQ;AAClC,QAAM,QAAQ,SAAS;AACvB,QAAM,SAAS;AAAA,IACb,OAAO;AAAA,MACL,OAAO,EAAE,KAAK,UAAU,KAAK,SAAS;AAAA,MACtC,QAAQ,EAAE,KAAK,WAAW,KAAK,UAAU;AAAA,IAC3C;AAAA,IACA,CAAC,UAAU,UAAU,WAAW,SAAS;AAAA,EAC3C;AAEA,QAAM,EAAE,MAAM,YAAY,cAAc,gBAAgB,IAAI,UAAU;AAAA,IACpE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,QAAM,gBAAgB,WAAW,eAAe,OAAO;AAEvD,SACE;AAAA,IAAC;AAAA;AAAA,MACE,GAAG;AAAA,MACJ;AAAA,MACA,eAAa;AAAA,MACb,IAAI;AAAA,QACF,UAAU;AAAA,QACV,OAAO,KAAK;AAAA,QACZ,QAAQ,KAAK;AAAA,QACb,QAAQ,aAAa,MAAM,QAAQ,OAAO;AAAA,QAC1C,cAAc,MAAM,QAAQ,GAAG;AAAA,QAC/B,UAAU;AAAA,QACV,YAAY,aAAa,SAAS;AAAA,QAClC,0BAA0B;AAAA,UACxB,SAAS;AAAA,QACX;AAAA,MACF;AAAA,MAEC;AAAA;AAAA,QACA,CAAC,YACA,cAAc,IAAI,CAAC,WACjB;AAAA,UAAC;AAAA;AAAA,YAEC,WAAU;AAAA,YACV,eAAa,aAAa,GAAG,UAAU,WAAW,MAAM,KAAK;AAAA,YAC7D,IAAI,YAAY,OAAO,QAAQ,cAAc,aAAa,YAAY,MAAM;AAAA,YAC5E,aAAa,CAAC,MAAM,gBAAgB,GAAG,MAAM;AAAA;AAAA,UAJxC;AAAA,QAKP,CACD;AAAA;AAAA;AAAA,EACL;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/utility/VirtualList/VirtualList.hooks.ts"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';\n\nimport type { VirtualGridProps, VirtualListProps } from './VirtualList.types';\n\ntype ScrollEvent = React.UIEvent<HTMLDivElement> | Event;\ntype ListItems = VirtualListProps['items'];\ntype ListVariant = NonNullable<VirtualListProps['variant']>;\ntype ItemHeight = (index: number) => number;\n\n// Handles both React synthetic events and native DOM events, since the same\n// handler serves an internal onScroll and an external container's listener.\nconst scrollOffsets = (event: ScrollEvent) => {\n const target = (event as React.UIEvent<HTMLDivElement>).currentTarget || (event as Event).target;\n const element = target as HTMLElement;\n return { top: element.scrollTop, left: element.scrollLeft };\n};\n\n/**\n * When the caller owns the scroll container, the component cannot attach\n * `onScroll` through JSX and has to subscribe to that element directly.\n */\nconst useExternalScrollListener = (\n scrollContainerRef: VirtualListProps['scrollContainerRef'],\n handleScroll: (event: Event) => void,\n) => {\n useEffect(() => {\n if (!scrollContainerRef?.current) return;\n\n const element = scrollContainerRef.current;\n const scrollHandler = (e: Event) => handleScroll(e);\n\n element.addEventListener('scroll', scrollHandler);\n return () => element.removeEventListener('scroll', scrollHandler);\n }, [scrollContainerRef, handleScroll]);\n};\n\n/**\n * Tracks the scroll offset whether it arrives through our own `onScroll` or\n * through a container the caller owns, and hands both offsets to `report` so a\n * grid can pass on the horizontal one too.\n */\nconst useScrollTop = (\n scrollContainerRef: VirtualListProps['scrollContainerRef'],\n report: (top: number, left: number) => void,\n) => {\n const [scrollTop, setScrollTop] = useState(0);\n\n const handleScroll = useCallback(\n (event: ScrollEvent) => {\n const { top, left } = scrollOffsets(event);\n setScrollTop(top);\n report(top, left);\n },\n [report],\n );\n\n useExternalScrollListener(scrollContainerRef, handleScroll);\n\n return { scrollTop, handleScroll };\n};\n\ninterface HeightArgs {\n items: ListItems;\n variant: ListVariant;\n itemHeight: number;\n estimatedItemHeight: number;\n}\n\n/**\n * Fixed lists know every height up front. Variable ones prefer the item's own\n * declared height, fall back to a measurement taken on a previous render, and\n * only then guess.\n */\nconst useItemHeight = ({\n items,\n variant,\n itemHeight,\n estimatedItemHeight,\n}: HeightArgs): ItemHeight => {\n const measured = useRef<Map<number, number>>(new Map());\n\n return useCallback(\n (index: number): number => {\n if (variant !== 'variable') {\n return itemHeight;\n }\n\n return items[index]?.height || measured.current.get(index) || estimatedItemHeight;\n },\n [variant, itemHeight, estimatedItemHeight, items],\n );\n};\n\nconst useTotalHeight = (\n items: ListItems,\n variant: ListVariant,\n itemHeight: number,\n getItemHeight: ItemHeight,\n) =>\n useMemo(() => {\n if (variant === 'fixed') {\n return items.length * itemHeight;\n }\n\n let sum = 0;\n for (let i = 0; i < items.length; i++) {\n sum += getItemHeight(i);\n }\n return sum;\n }, [items.length, variant, itemHeight, getItemHeight]);\n\ninterface RangeArgs {\n count: number;\n scrollTop: number;\n height: number;\n overscan: number;\n itemHeight: number;\n getItemHeight: ItemHeight;\n}\n\n// Walks forward accumulating heights until it passes the viewport's top edge, then\n// its bottom edge. Linear in the number of items, which is why fixed lists take\n// the arithmetic shortcut instead.\nconst variableRange = ({ count, scrollTop, height, overscan, getItemHeight }: RangeArgs) => {\n let accumulated = 0;\n let startIndex = 0;\n let endIndex = count - 1;\n\n for (let i = 0; i < count; i++) {\n if (accumulated + getItemHeight(i) > scrollTop) {\n startIndex = Math.max(0, i - overscan);\n break;\n }\n accumulated += getItemHeight(i);\n }\n\n accumulated = 0;\n for (let i = 0; i <= startIndex; i++) {\n accumulated += getItemHeight(i);\n }\n\n for (let i = startIndex; i < count; i++) {\n if (accumulated > scrollTop + height) {\n endIndex = Math.min(count - 1, i + overscan);\n break;\n }\n accumulated += getItemHeight(i);\n }\n\n return { startIndex, endIndex };\n};\n\nconst fixedRange = ({ count, scrollTop, height, overscan, itemHeight }: RangeArgs) => ({\n startIndex: Math.max(0, Math.floor(scrollTop / itemHeight) - overscan),\n endIndex: Math.min(count - 1, Math.ceil((scrollTop + height) / itemHeight) + overscan),\n});\n\nconst useItemOffset = (\n variant: ListVariant,\n itemHeight: number,\n getItemHeight: ItemHeight,\n): ItemHeight =>\n useCallback(\n (index: number): number => {\n if (variant === 'fixed') {\n return index * itemHeight;\n }\n\n let offset = 0;\n for (let i = 0; i < index; i++) {\n offset += getItemHeight(i);\n }\n return offset;\n },\n [variant, itemHeight, getItemHeight],\n );\n\ninterface ListArgs {\n items: ListItems;\n variant: ListVariant;\n height: number;\n itemHeight: number;\n estimatedItemHeight: number;\n overscan: number;\n onScroll: VirtualListProps['onScroll'];\n scrollContainerRef: VirtualListProps['scrollContainerRef'];\n}\n\nexport const useVirtualList = ({\n items,\n variant,\n height,\n itemHeight,\n estimatedItemHeight,\n overscan,\n onScroll,\n scrollContainerRef,\n}: ListArgs) => {\n const getItemHeight = useItemHeight({ items, variant, itemHeight, estimatedItemHeight });\n const getItemOffset = useItemOffset(variant, itemHeight, getItemHeight);\n const totalHeight = useTotalHeight(items, variant, itemHeight, getItemHeight);\n\n const report = useCallback((top: number) => onScroll?.(top), [onScroll]);\n const { scrollTop, handleScroll } = useScrollTop(scrollContainerRef, report);\n\n const visibleItems = useMemo(() => {\n const args = { count: items.length, scrollTop, height, overscan, itemHeight, getItemHeight };\n const { startIndex, endIndex } = variant === 'fixed' ? fixedRange(args) : variableRange(args);\n const result = [];\n\n for (let i = startIndex; i <= endIndex; i++) {\n const item = items[i];\n if (!item) continue;\n\n result.push({\n item,\n index: i,\n style: {\n position: 'absolute' as const,\n top: getItemOffset(i),\n left: 0,\n width: '100%',\n height: getItemHeight(i),\n },\n });\n }\n\n return result;\n }, [items, scrollTop, height, overscan, variant, itemHeight, getItemOffset, getItemHeight]);\n\n return { totalHeight, visibleItems, handleScroll };\n};\n\ninterface GridArgs {\n items: VirtualGridProps['items'];\n height: number;\n width: number | string;\n columnCount: number;\n rowHeight: number;\n columnWidth?: number;\n gap: number;\n overscan: number;\n onScroll: VirtualGridProps['onScroll'];\n scrollContainerRef: VirtualGridProps['scrollContainerRef'];\n}\n\nconst useColumnWidth = (\n columnWidth: number | undefined,\n width: number | string,\n columnCount: number,\n gap: number,\n) =>\n useMemo(() => {\n if (columnWidth) return columnWidth;\n\n const containerWidth = typeof width === 'number' ? width : 300; // fallback\n return (containerWidth - (columnCount - 1) * gap) / columnCount;\n }, [columnWidth, width, columnCount, gap]);\n\nexport const useVirtualGrid = ({\n items,\n height,\n width,\n columnCount,\n rowHeight,\n columnWidth,\n gap,\n overscan,\n onScroll,\n scrollContainerRef,\n}: GridArgs) => {\n const rowCount = Math.ceil(items.length / columnCount);\n const totalHeight = rowCount * (rowHeight + gap) - gap;\n const computedColumnWidth = useColumnWidth(columnWidth, width, columnCount, gap);\n\n const report = useCallback(\n (top: number, left: number) => onScroll?.(top, left),\n [onScroll],\n );\n const { scrollTop, handleScroll } = useScrollTop(scrollContainerRef, report);\n\n const visibleItems = useMemo(() => {\n const pitch = rowHeight + gap;\n const startRow = Math.max(0, Math.floor(scrollTop / pitch) - overscan);\n const endRow = Math.min(rowCount - 1, Math.ceil((scrollTop + height) / pitch) + overscan);\n\n // Rows are contiguous in `items`, so the visible block is one index range\n // rather than a row loop wrapping a column loop.\n const firstIndex = startRow * columnCount;\n const lastIndex = Math.min((endRow + 1) * columnCount - 1, items.length - 1);\n const result = [];\n\n for (let index = firstIndex; index <= lastIndex; index++) {\n const item = items[index];\n if (!item) continue;\n\n const rowIndex = Math.floor(index / columnCount);\n const columnIndex = index % columnCount;\n\n result.push({\n item,\n index,\n columnIndex,\n rowIndex,\n style: {\n position: 'absolute' as const,\n top: rowIndex * pitch,\n left: columnIndex * (computedColumnWidth + gap),\n width: computedColumnWidth,\n height: rowHeight,\n },\n });\n }\n\n return result;\n }, [items, scrollTop, height, overscan, rowCount, columnCount, rowHeight, gap, computedColumnWidth]);\n\n return { totalHeight, visibleItems, handleScroll };\n};\n"],"mappings":";AAAA,SAAgB,aAAa,WAAW,SAAS,QAAQ,gBAAgB;AAWzE,IAAM,gBAAgB,CAAC,UAAuB;AAC5C,QAAM,SAAU,MAAwC,iBAAkB,MAAgB;AAC1F,QAAM,UAAU;AAChB,SAAO,EAAE,KAAK,QAAQ,WAAW,MAAM,QAAQ,WAAW;AAC5D;AAMA,IAAM,4BAA4B,CAChC,oBACA,iBACG;AACH,YAAU,MAAM;AACd,QAAI,CAAC,oBAAoB,QAAS;AAElC,UAAM,UAAU,mBAAmB;AACnC,UAAM,gBAAgB,CAAC,MAAa,aAAa,CAAC;AAElD,YAAQ,iBAAiB,UAAU,aAAa;AAChD,WAAO,MAAM,QAAQ,oBAAoB,UAAU,aAAa;AAAA,EAClE,GAAG,CAAC,oBAAoB,YAAY,CAAC;AACvC;AAOA,IAAM,eAAe,CACnB,oBACA,WACG;AACH,QAAM,CAAC,WAAW,YAAY,IAAI,SAAS,CAAC;AAE5C,QAAM,eAAe;AAAA,IACnB,CAAC,UAAuB;AACtB,YAAM,EAAE,KAAK,KAAK,IAAI,cAAc,KAAK;AACzC,mBAAa,GAAG;AAChB,aAAO,KAAK,IAAI;AAAA,IAClB;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AAEA,4BAA0B,oBAAoB,YAAY;AAE1D,SAAO,EAAE,WAAW,aAAa;AACnC;AAcA,IAAM,gBAAgB,CAAC;AAAA,EACrB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAA8B;AAC5B,QAAM,WAAW,OAA4B,oBAAI,IAAI,CAAC;AAEtD,SAAO;AAAA,IACL,CAAC,UAA0B;AACzB,UAAI,YAAY,YAAY;AAC1B,eAAO;AAAA,MACT;AAEA,aAAO,MAAM,KAAK,GAAG,UAAU,SAAS,QAAQ,IAAI,KAAK,KAAK;AAAA,IAChE;AAAA,IACA,CAAC,SAAS,YAAY,qBAAqB,KAAK;AAAA,EAClD;AACF;AAEA,IAAM,iBAAiB,CACrB,OACA,SACA,YACA,kBAEA,QAAQ,MAAM;AACZ,MAAI,YAAY,SAAS;AACvB,WAAO,MAAM,SAAS;AAAA,EACxB;AAEA,MAAI,MAAM;AACV,WAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,WAAO,cAAc,CAAC;AAAA,EACxB;AACA,SAAO;AACT,GAAG,CAAC,MAAM,QAAQ,SAAS,YAAY,aAAa,CAAC;AAcvD,IAAM,gBAAgB,CAAC,EAAE,OAAO,WAAW,QAAQ,UAAU,cAAc,MAAiB;AAC1F,MAAI,cAAc;AAClB,MAAI,aAAa;AACjB,MAAI,WAAW,QAAQ;AAEvB,WAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,QAAI,cAAc,cAAc,CAAC,IAAI,WAAW;AAC9C,mBAAa,KAAK,IAAI,GAAG,IAAI,QAAQ;AACrC;AAAA,IACF;AACA,mBAAe,cAAc,CAAC;AAAA,EAChC;AAEA,gBAAc;AACd,WAAS,IAAI,GAAG,KAAK,YAAY,KAAK;AACpC,mBAAe,cAAc,CAAC;AAAA,EAChC;AAEA,WAAS,IAAI,YAAY,IAAI,OAAO,KAAK;AACvC,QAAI,cAAc,YAAY,QAAQ;AACpC,iBAAW,KAAK,IAAI,QAAQ,GAAG,IAAI,QAAQ;AAC3C;AAAA,IACF;AACA,mBAAe,cAAc,CAAC;AAAA,EAChC;AAEA,SAAO,EAAE,YAAY,SAAS;AAChC;AAEA,IAAM,aAAa,CAAC,EAAE,OAAO,WAAW,QAAQ,UAAU,WAAW,OAAkB;AAAA,EACrF,YAAY,KAAK,IAAI,GAAG,KAAK,MAAM,YAAY,UAAU,IAAI,QAAQ;AAAA,EACrE,UAAU,KAAK,IAAI,QAAQ,GAAG,KAAK,MAAM,YAAY,UAAU,UAAU,IAAI,QAAQ;AACvF;AAEA,IAAM,gBAAgB,CACpB,SACA,YACA,kBAEA;AAAA,EACE,CAAC,UAA0B;AACzB,QAAI,YAAY,SAAS;AACvB,aAAO,QAAQ;AAAA,IACjB;AAEA,QAAI,SAAS;AACb,aAAS,IAAI,GAAG,IAAI,OAAO,KAAK;AAC9B,gBAAU,cAAc,CAAC;AAAA,IAC3B;AACA,WAAO;AAAA,EACT;AAAA,EACA,CAAC,SAAS,YAAY,aAAa;AACrC;AAaK,IAAM,iBAAiB,CAAC;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAgB;AACd,QAAM,gBAAgB,cAAc,EAAE,OAAO,SAAS,YAAY,oBAAoB,CAAC;AACvF,QAAM,gBAAgB,cAAc,SAAS,YAAY,aAAa;AACtE,QAAM,cAAc,eAAe,OAAO,SAAS,YAAY,aAAa;AAE5E,QAAM,SAAS,YAAY,CAAC,QAAgB,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC;AACvE,QAAM,EAAE,WAAW,aAAa,IAAI,aAAa,oBAAoB,MAAM;AAE3E,QAAM,eAAe,QAAQ,MAAM;AACjC,UAAM,OAAO,EAAE,OAAO,MAAM,QAAQ,WAAW,QAAQ,UAAU,YAAY,cAAc;AAC3F,UAAM,EAAE,YAAY,SAAS,IAAI,YAAY,UAAU,WAAW,IAAI,IAAI,cAAc,IAAI;AAC5F,UAAM,SAAS,CAAC;AAEhB,aAAS,IAAI,YAAY,KAAK,UAAU,KAAK;AAC3C,YAAM,OAAO,MAAM,CAAC;AACpB,UAAI,CAAC,KAAM;AAEX,aAAO,KAAK;AAAA,QACV;AAAA,QACA,OAAO;AAAA,QACP,OAAO;AAAA,UACL,UAAU;AAAA,UACV,KAAK,cAAc,CAAC;AAAA,UACpB,MAAM;AAAA,UACN,OAAO;AAAA,UACP,QAAQ,cAAc,CAAC;AAAA,QACzB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,OAAO,WAAW,QAAQ,UAAU,SAAS,YAAY,eAAe,aAAa,CAAC;AAE1F,SAAO,EAAE,aAAa,cAAc,aAAa;AACnD;AAeA,IAAM,iBAAiB,CACrB,aACA,OACA,aACA,QAEA,QAAQ,MAAM;AACZ,MAAI,YAAa,QAAO;AAExB,QAAM,iBAAiB,OAAO,UAAU,WAAW,QAAQ;AAC3D,UAAQ,kBAAkB,cAAc,KAAK,OAAO;AACtD,GAAG,CAAC,aAAa,OAAO,aAAa,GAAG,CAAC;AAEpC,IAAM,iBAAiB,CAAC;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAgB;AACd,QAAM,WAAW,KAAK,KAAK,MAAM,SAAS,WAAW;AACrD,QAAM,cAAc,YAAY,YAAY,OAAO;AACnD,QAAM,sBAAsB,eAAe,aAAa,OAAO,aAAa,GAAG;AAE/E,QAAM,SAAS;AAAA,IACb,CAAC,KAAa,SAAiB,WAAW,KAAK,IAAI;AAAA,IACnD,CAAC,QAAQ;AAAA,EACX;AACA,QAAM,EAAE,WAAW,aAAa,IAAI,aAAa,oBAAoB,MAAM;AAE3E,QAAM,eAAe,QAAQ,MAAM;AACjC,UAAM,QAAQ,YAAY;AAC1B,UAAM,WAAW,KAAK,IAAI,GAAG,KAAK,MAAM,YAAY,KAAK,IAAI,QAAQ;AACrE,UAAM,SAAS,KAAK,IAAI,WAAW,GAAG,KAAK,MAAM,YAAY,UAAU,KAAK,IAAI,QAAQ;AAIxF,UAAM,aAAa,WAAW;AAC9B,UAAM,YAAY,KAAK,KAAK,SAAS,KAAK,cAAc,GAAG,MAAM,SAAS,CAAC;AAC3E,UAAM,SAAS,CAAC;AAEhB,aAAS,QAAQ,YAAY,SAAS,WAAW,SAAS;AACxD,YAAM,OAAO,MAAM,KAAK;AACxB,UAAI,CAAC,KAAM;AAEX,YAAM,WAAW,KAAK,MAAM,QAAQ,WAAW;AAC/C,YAAM,cAAc,QAAQ;AAE5B,aAAO,KAAK;AAAA,QACV;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,OAAO;AAAA,UACL,UAAU;AAAA,UACV,KAAK,WAAW;AAAA,UAChB,MAAM,eAAe,sBAAsB;AAAA,UAC3C,OAAO;AAAA,UACP,QAAQ;AAAA,QACV;AAAA,MACF,CAAC;AAAA,IACH;AAEA,WAAO;AAAA,EACT,GAAG,CAAC,OAAO,WAAW,QAAQ,UAAU,UAAU,aAAa,WAAW,KAAK,mBAAmB,CAAC;AAEnG,SAAO,EAAE,aAAa,cAAc,aAAa;AACnD;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/utility/InfiniteScroll/InfiniteScroll.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport React from 'react';\n\nimport { useLoadMore, useSentinel } from './InfiniteScroll.hooks';\nimport {\n containerStyles,\n DefaultEndMessage,\n DefaultError,\n DefaultLoader,\n} from './InfiniteScroll.parts';\nimport type { InfiniteScrollProps } from './InfiniteScroll.types';\n\nexport const InfiniteScroll: React.FC<InfiniteScrollProps> = ({\n children,\n variant = 'default',\n hasMore,\n loading,\n threshold = 150,\n loadMore,\n loader,\n loadingText,\n endText,\n endMessage,\n error,\n errorComponent,\n onError,\n className,\n style,\n width,\n scrollableTarget,\n testMode = false,\n testTriggerRef,\n}) => {\n const { sentinelRef, isIntersecting } = useSentinel({ testMode, threshold, scrollableTarget });\n\n useLoadMore({\n hasMore,\n loading,\n error,\n loadMore,\n onError,\n isIntersecting,\n testMode,\n testTriggerRef,\n });\n\n // The tail of the list is one of four things: the end message, an error, a\n // spinner, or the sentinel that asks for the next page.\n const renderSentinel = () => {\n if (!hasMore) return endMessage || <DefaultEndMessage endText={endText} />;\n if (error) return errorComponent || <DefaultError error={error} />;\n if (loading) return loader || <DefaultLoader loadingText={loadingText} />;\n\n return (\n <div\n ref={sentinelRef}\n data-testid=\"infinite-scroll-sentinel\"\n style={{\n height: variant === 'horizontal' ? '100%' : '1px',\n width: variant === 'horizontal' ? '1px' : '100%',\n }}\n />\n );\n };\n\n return (\n <Box\n className={className}\n sx={{\n ...containerStyles(variant, width),\n ...style,\n }}\n >\n {variant === 'reverse' && renderSentinel()}\n\n {variant === 'horizontal' ? (\n <Box sx={{ display: 'flex', flexDirection: 'row' }}>{children}</Box>\n ) : (\n children\n )}\n\n {variant !== 'reverse' && renderSentinel()}\n\n {variant === 'horizontal' && renderSentinel()}\n </Box>\n );\n};\n"],"mappings":";;;;;;;;;;;;AAAA,OAAO,SAAS;AAiDuB,cAiBnC,YAjBmC;AArChC,IAAM,iBAAgD,CAAC;AAAA,EAC5D;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AAAA,EACX;AACF,MAAM;AACJ,QAAM,EAAE,aAAa,eAAe,IAAI,YAAY,EAAE,UAAU,WAAW,iBAAiB,CAAC;AAE7F,cAAY;AAAA,IACV;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAID,QAAM,iBAAiB,MAAM;AAC3B,QAAI,CAAC,QAAS,QAAO,cAAc,oBAAC,qBAAkB,SAAkB;AACxE,QAAI,MAAO,QAAO,kBAAkB,oBAAC,gBAAa,OAAc;AAChE,QAAI,QAAS,QAAO,UAAU,oBAAC,iBAAc,aAA0B;AAEvE,WACE;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,eAAY;AAAA,QACZ,OAAO;AAAA,UACL,QAAQ,YAAY,eAAe,SAAS;AAAA,UAC5C,OAAO,YAAY,eAAe,QAAQ;AAAA,QAC5C;AAAA;AAAA,IACF;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,IAAI;AAAA,QACF,GAAG,gBAAgB,SAAS,KAAK;AAAA,QACjC,GAAG;AAAA,MACL;AAAA,MAEC;AAAA,oBAAY,aAAa,eAAe;AAAA,QAExC,YAAY,eACX,oBAAC,OAAI,IAAI,EAAE,SAAS,QAAQ,eAAe,MAAM,GAAI,UAAS,IAE9D;AAAA,QAGD,YAAY,aAAa,eAAe;AAAA,QAExC,YAAY,gBAAgB,eAAe;AAAA;AAAA;AAAA,EAC9C;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/MapPreview/MapTiles.tsx"],"sourcesContent":["import { alpha, useTheme } from '@mui/material/styles/index.js';\nimport type { FC } from 'react';\nimport React from 'react';\n\nimport { TILE_SIZE } from './mapProjection';\nimport { tileBackground } from './mapSurface';\nimport type { MapType } from './MapPreview.types';\n\n// Two extra rows and columns so panning does not expose an edge.\nconst VISIBLE_TILES = Math.ceil(800 / TILE_SIZE) + 2;\n// Tile coordinates are only legible once the grid is reasonably fine.\nconst LABEL_MIN_ZOOM = 10;\n\nexport interface MapTilesProps {\n origin: { x: number; y: number } | null;\n zoom: number;\n mapType: MapType;\n panOffset: { x: number; y: number };\n}\n\nexport const MapTiles: FC<MapTilesProps> = ({ origin, zoom, mapType, panOffset }) => {\n const theme = useTheme();\n const borderOpacity = theme.palette.mode === 'dark' ? 0.15 : 0.1;\n const background = tileBackground(mapType, theme);\n const half = Math.floor(VISIBLE_TILES / 2);\n\n return (\n <div\n style={{\n position: 'absolute',\n top: '50%',\n left: '50%',\n transform: `translate(calc(-50% + ${panOffset.x}px), calc(-50% + ${panOffset.y}px))`,\n width: TILE_SIZE * VISIBLE_TILES,\n height: TILE_SIZE * VISIBLE_TILES,\n display: 'grid',\n gridTemplateColumns: `repeat(${VISIBLE_TILES}, ${TILE_SIZE}px)`,\n gridTemplateRows: `repeat(${VISIBLE_TILES}, ${TILE_SIZE}px)`,\n transition: 'transform 0.1s ease-out',\n }}\n >\n {Array.from({ length: VISIBLE_TILES * VISIBLE_TILES }).map((_, index) => {\n // The grid is centred on the origin tile, so indices run from -half.\n const tileX = (origin?.x || 0) + (index % VISIBLE_TILES) - half;\n const tileY = (origin?.y || 0) + Math.floor(index / VISIBLE_TILES) - half;\n\n return (\n <div\n key={`tile-${tileX}-${tileY}`}\n style={{\n width: TILE_SIZE,\n height: TILE_SIZE,\n border: `1px solid ${alpha(theme.palette.divider, borderOpacity)}`,\n background,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: '10px',\n color: alpha(theme.palette.text.secondary, 0.3),\n fontFamily: 'monospace',\n userSelect: 'none',\n }}\n >\n {zoom > LABEL_MIN_ZOOM && `${tileX},${tileY}`}\n </div>\n );\n })}\n </div>\n );\n};\n"],"mappings":";;;;;;;;AAAA,SAAS,OAAO,gBAAgB;AA+CtB;AAtCV,IAAM,gBAAgB,KAAK,KAAK,MAAM,SAAS,IAAI;AAEnD,IAAM,iBAAiB;AAShB,IAAM,WAA8B,CAAC,EAAE,QAAQ,MAAM,SAAS,UAAU,MAAM;AACnF,QAAM,QAAQ,SAAS;AACvB,QAAM,gBAAgB,MAAM,QAAQ,SAAS,SAAS,OAAO;AAC7D,QAAM,aAAa,eAAe,SAAS,KAAK;AAChD,QAAM,OAAO,KAAK,MAAM,gBAAgB,CAAC;AAEzC,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,UAAU;AAAA,QACV,KAAK;AAAA,QACL,MAAM;AAAA,QACN,WAAW,yBAAyB,UAAU,CAAC,oBAAoB,UAAU,CAAC;AAAA,QAC9E,OAAO,YAAY;AAAA,QACnB,QAAQ,YAAY;AAAA,QACpB,SAAS;AAAA,QACT,qBAAqB,UAAU,aAAa,KAAK,SAAS;AAAA,QAC1D,kBAAkB,UAAU,aAAa,KAAK,SAAS;AAAA,QACvD,YAAY;AAAA,MACd;AAAA,MAEC,gBAAM,KAAK,EAAE,QAAQ,gBAAgB,cAAc,CAAC,EAAE,IAAI,CAAC,GAAG,UAAU;AAEvE,cAAM,SAAS,QAAQ,KAAK,KAAM,QAAQ,gBAAiB;AAC3D,cAAM,SAAS,QAAQ,KAAK,KAAK,KAAK,MAAM,QAAQ,aAAa,IAAI;AAErE,eACE;AAAA,UAAC;AAAA;AAAA,YAEC,OAAO;AAAA,cACL,OAAO;AAAA,cACP,QAAQ;AAAA,cACR,QAAQ,aAAa,MAAM,MAAM,QAAQ,SAAS,aAAa,CAAC;AAAA,cAChE;AAAA,cACA,SAAS;AAAA,cACT,YAAY;AAAA,cACZ,gBAAgB;AAAA,cAChB,UAAU;AAAA,cACV,OAAO,MAAM,MAAM,QAAQ,KAAK,WAAW,GAAG;AAAA,cAC9C,YAAY;AAAA,cACZ,YAAY;AAAA,YACd;AAAA,YAEC,iBAAO,kBAAkB,GAAG,KAAK,IAAI,KAAK;AAAA;AAAA,UAftC,QAAQ,KAAK,IAAI,KAAK;AAAA,QAgB7B;AAAA,MAEJ,CAAC;AAAA;AAAA,EACH;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataGrid/DataGrid.body.tsx"],"sourcesContent":["/**\n * The DataGrid's `<thead>` and `<tbody>`.\n *\n * Split from the shell so each stays inside the size budget and so the\n * virtualization spacers — which are pure layout, not data — sit next to the\n * rows they pad rather than in the middle of the component that owns the paper.\n */\nimport Checkbox from '@mui/material/Checkbox/index.js';\nimport TableBody from '@mui/material/TableBody/index.js';\nimport TableCell from '@mui/material/TableCell/index.js';\nimport TableHead from '@mui/material/TableHead/index.js';\nimport TableRow from '@mui/material/TableRow/index.js';\nimport { useTheme } from '@mui/material/styles/index.js';\nimport type React from 'react';\n\nimport { GridRow, HeaderCell } from './DataGrid.cells';\nimport type { DataGridModel } from './DataGrid.model';\nimport type { DataGridProps } from './DataGrid.types';\n\nexport interface GridSectionProps<T extends Record<string, unknown>> {\n model: DataGridModel<T>;\n props: DataGridProps<T>;\n totalColumns: number;\n}\n\n/** The leading header cells for the selection / expansion columns. */\nfunction HeaderControls<T extends Record<string, unknown>>({\n model,\n props,\n}: GridSectionProps<T>): React.JSX.Element {\n const theme = useTheme();\n const { selection = { mode: 'none' }, expansion, stickyHeader = true } = props;\n const sticky = {\n position: stickyHeader ? ('sticky' as const) : ('static' as const),\n top: 0,\n zIndex: 1,\n backgroundColor: theme.palette.background.paper,\n };\n const total = model.processedRows.length;\n const picked = model.selectedRowIds.length;\n return (\n <>\n {selection.mode !== 'none' && (\n <TableCell padding=\"checkbox\" sx={sticky}>\n {selection.mode === 'multi' && (\n <Checkbox\n indeterminate={picked > 0 && picked < total}\n checked={total > 0 && picked === total}\n onChange={(event) =>\n model.setSelectedRowIds(\n event.target.checked\n ? model.processedRows.map((row, index) => rowIdOf(props, row, index))\n : [],\n )\n }\n inputProps={{ 'aria-label': 'Select all rows' }}\n />\n )}\n </TableCell>\n )}\n {expansion && <TableCell padding=\"checkbox\" sx={sticky} />}\n </>\n );\n}\n\n/** The caller's `getRowId`, or the row's own `id`, or its index. */\nexport function rowIdOf<T extends Record<string, unknown>>(\n props: DataGridProps<T>,\n row: T,\n index: number,\n): string | number {\n if (props.getRowId) return props.getRowId(row, index);\n const candidate = (row as { id?: string | number }).id;\n return candidate ?? index;\n}\n\nexport function GridHeader<T extends Record<string, unknown>>(\n section: GridSectionProps<T>,\n): React.JSX.Element {\n const { model, props } = section;\n const { sorting = {}, stickyHeader = true, headerHeight = 56 } = props;\n const sortable = sorting.mode === 'client' || sorting.mode === 'server';\n return (\n <TableHead data-slot=\"header\">\n <TableRow data-slot=\"header-row\" role=\"row\">\n <HeaderControls {...section} />\n {model.visibleColumns.map((column) => (\n <HeaderCell\n key={column.id}\n column={column}\n sort={model.sortBy.find((entry) => entry.id === column.id)}\n sortable={column.enableSort !== false && sortable}\n stickyHeader={stickyHeader}\n headerHeight={headerHeight}\n onSort={model.onSort}\n />\n ))}\n </TableRow>\n </TableHead>\n );\n}\n\n/** An invisible row standing in for the rows the window is not rendering. */\nfunction Spacer({ height, colSpan }: { height: number; colSpan: number }): React.JSX.Element | null {\n if (height <= 0) return null;\n return (\n <TableRow>\n <TableCell colSpan={colSpan} sx={{ height, border: 'none', p: 0 }} />\n </TableRow>\n );\n}\n\nexport function GridBody<T extends Record<string, unknown>>(\n section: GridSectionProps<T>,\n): React.JSX.Element {\n const { model, props, totalColumns } = section;\n const { start, end } = model.visibleRange;\n const trailing = model.virtualized ? model.processedRows.length - end : 0;\n return (\n <TableBody data-slot=\"body\">\n {model.virtualized ? (\n <Spacer height={start * model.rowHeight} colSpan={totalColumns} />\n ) : null}\n {model.visibleRows.map((row, offset) => {\n const index = model.virtualized ? start + offset : offset;\n const rowId = rowIdOf(props, row, index);\n return (\n <GridRow\n key={rowId}\n row={row}\n index={index}\n rowId={rowId}\n isSelected={model.selectedRowIdsSet.has(rowId)}\n isExpanded={model.expandedRowIdsSet.has(rowId)}\n totalColumns={totalColumns}\n model={model}\n props={props}\n />\n );\n })}\n {model.virtualized ? (\n <Spacer height={trailing * model.rowHeight} colSpan={totalColumns} />\n ) : null}\n </TableBody>\n );\n}\n"],"mappings":";;;;;;AAOA,OAAO,cAAc;AACrB,OAAO,eAAe;AACtB,OAAO,eAAe;AACtB,OAAO,eAAe;AACtB,OAAO,cAAc;AACrB,SAAS,gBAAgB;AA6BrB,mBAIQ,KAJR;AAfJ,SAAS,eAAkD;AAAA,EACzD;AAAA,EACA;AACF,GAA2C;AACzC,QAAM,QAAQ,SAAS;AACvB,QAAM,EAAE,YAAY,EAAE,MAAM,OAAO,GAAG,WAAW,eAAe,KAAK,IAAI;AACzE,QAAM,SAAS;AAAA,IACb,UAAU,eAAgB,WAAsB;AAAA,IAChD,KAAK;AAAA,IACL,QAAQ;AAAA,IACR,iBAAiB,MAAM,QAAQ,WAAW;AAAA,EAC5C;AACA,QAAM,QAAQ,MAAM,cAAc;AAClC,QAAM,SAAS,MAAM,eAAe;AACpC,SACE,iCACG;AAAA,cAAU,SAAS,UAClB,oBAAC,aAAU,SAAQ,YAAW,IAAI,QAC/B,oBAAU,SAAS,WAClB;AAAA,MAAC;AAAA;AAAA,QACC,eAAe,SAAS,KAAK,SAAS;AAAA,QACtC,SAAS,QAAQ,KAAK,WAAW;AAAA,QACjC,UAAU,CAAC,UACT,MAAM;AAAA,UACJ,MAAM,OAAO,UACT,MAAM,cAAc,IAAI,CAAC,KAAK,UAAU,QAAQ,OAAO,KAAK,KAAK,CAAC,IAClE,CAAC;AAAA,QACP;AAAA,QAEF,YAAY,EAAE,cAAc,kBAAkB;AAAA;AAAA,IAChD,GAEJ;AAAA,IAED,aAAa,oBAAC,aAAU,SAAQ,YAAW,IAAI,QAAQ;AAAA,KAC1D;AAEJ;AAGO,SAAS,QACd,OACA,KACA,OACiB;AACjB,MAAI,MAAM,SAAU,QAAO,MAAM,SAAS,KAAK,KAAK;AACpD,QAAM,YAAa,IAAiC;AACpD,SAAO,aAAa;AACtB;AAEO,SAAS,WACd,SACmB;AACnB,QAAM,EAAE,OAAO,MAAM,IAAI;AACzB,QAAM,EAAE,UAAU,CAAC,GAAG,eAAe,MAAM,eAAe,GAAG,IAAI;AACjE,QAAM,WAAW,QAAQ,SAAS,YAAY,QAAQ,SAAS;AAC/D,SACE,oBAAC,aAAU,aAAU,UACnB,+BAAC,YAAS,aAAU,cAAa,MAAK,OACpC;AAAA,wBAAC,kBAAgB,GAAG,SAAS;AAAA,IAC5B,MAAM,eAAe,IAAI,CAAC,WACzB;AAAA,MAAC;AAAA;AAAA,QAEC;AAAA,QACA,MAAM,MAAM,OAAO,KAAK,CAAC,UAAU,MAAM,OAAO,OAAO,EAAE;AAAA,QACzD,UAAU,OAAO,eAAe,SAAS;AAAA,QACzC;AAAA,QACA;AAAA,QACA,QAAQ,MAAM;AAAA;AAAA,MANT,OAAO;AAAA,IAOd,CACD;AAAA,KACH,GACF;AAEJ;AAGA,SAAS,OAAO,EAAE,QAAQ,QAAQ,GAAkE;AAClG,MAAI,UAAU,EAAG,QAAO;AACxB,SACE,oBAAC,YACC,8BAAC,aAAU,SAAkB,IAAI,EAAE,QAAQ,QAAQ,QAAQ,GAAG,EAAE,GAAG,GACrE;AAEJ;AAEO,SAAS,SACd,SACmB;AACnB,QAAM,EAAE,OAAO,OAAO,aAAa,IAAI;AACvC,QAAM,EAAE,OAAO,IAAI,IAAI,MAAM;AAC7B,QAAM,WAAW,MAAM,cAAc,MAAM,cAAc,SAAS,MAAM;AACxE,SACE,qBAAC,aAAU,aAAU,QAClB;AAAA,UAAM,cACL,oBAAC,UAAO,QAAQ,QAAQ,MAAM,WAAW,SAAS,cAAc,IAC9D;AAAA,IACH,MAAM,YAAY,IAAI,CAAC,KAAK,WAAW;AACtC,YAAM,QAAQ,MAAM,cAAc,QAAQ,SAAS;AACnD,YAAM,QAAQ,QAAQ,OAAO,KAAK,KAAK;AACvC,aACE;AAAA,QAAC;AAAA;AAAA,UAEC;AAAA,UACA;AAAA,UACA;AAAA,UACA,YAAY,MAAM,kBAAkB,IAAI,KAAK;AAAA,UAC7C,YAAY,MAAM,kBAAkB,IAAI,KAAK;AAAA,UAC7C;AAAA,UACA;AAAA,UACA;AAAA;AAAA,QARK;AAAA,MASP;AAAA,IAEJ,CAAC;AAAA,IACA,MAAM,cACL,oBAAC,UAAO,QAAQ,WAAW,MAAM,WAAW,SAAS,cAAc,IACjE;AAAA,KACN;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/data-views-overflow-costs.ts"],"sourcesContent":["/**\n * WHAT EACH THING ON THE TOOLBAR COSTS, IN PIXELS.\n *\n * The pricing half of the collapse ladder, split from `data-views-overflow` at\n * the file-size gate. Pure arithmetic and constants: no React, no measurement,\n * no decisions. `data-views-overflow` measures the row and spends what this\n * says it has.\n *\n * Every number here is either MEASURED in a browser (and says so) or\n * deliberately generous. Over-pricing sheds one control too early, which the\n * \"Mais\" button absorbs invisibly; under-pricing breaks the line.\n */\nimport type { OverflowField } from \"./data-views-overflow\";\nimport type { RangeValue } from \"./data-views-types\";\n\n/**\n * Rough rendered width of a control, in px.\n *\n * An ESTIMATE from the label text rather than a real measurement, deliberately:\n * measuring the true width needs every control mounted first, and mounting them\n * to decide whether to mount them is the layout thrash this hook exists to\n * avoid. The estimate only has to rank controls and find the cut point — being\n * a few px out moves the cut by at most one control, and the overflow catches it.\n */\nexport function estimateWidth(text: string, extra: number): number {\n /**\n * ~7.6px per character at the toolbar's font size, plus 76px of chrome:\n * horizontal padding, the border, and the dropdown chevron. The chrome used\n * to be 52, which under-priced every control by roughly a chevron's width —\n * six of them then \"fitted\" a row they overflowed, and because they are flex\n * children the row paid for it by squeezing labels to \"D…\" and \"V…\" rather\n * than by shedding a control into the overflow.\n *\n * Deliberately generous: over-pricing sheds one control too early, which the\n * \"Mais\" button absorbs invisibly. Under-pricing breaks the line.\n *\n * The chrome was 76, and generous had turned into wrong. MEASURED on the\n * Pedidos bar: \"Pagamento\" renders at 123px against an estimate of 144, and\n * \"Situação\" at 107 against 137 — every pill over-priced by ~22%, which on a\n * phone is the whole difference between one pill on the bar and none. 56 is\n * still above the ~50 measured, so the slack the comment above asks for is\n * intact; it is just slack rather than a second control's worth of budget.\n */\n return Math.round(text.length * 7.6) + 56 + extra;\n}\n\n/** Is a range bounded at either end? */\nexport function isRangeSet(range: RangeValue | undefined): boolean {\n return Boolean(range && (range.min !== undefined || range.max !== undefined));\n}\n\n/** The label a pill actually renders, which is what decides its width. */\nexport function pillText<T extends Record<string, unknown>>(field: OverflowField<T>, values: string[]): string {\n if (values.length === 0) return field.label;\n if (values.length === 1) {\n const option = field.pill?.options.find((entry) => entry.value === values[0]);\n return `${field.label}: ${option?.label ?? values[0]}`;\n }\n return `${field.label}: ${values.length}`;\n}\n\n/** Fixed toolbar furniture the filters have to fit around, in px. */\nexport const RESERVED = {\n /** The search box never shrinks below this. */\n search: 200,\n /**\n * The \"N de N\" counter.\n *\n * MEASURED at 35px, plus its divider and gap. The old 96 was priced for a\n * counter reading \"1.234 de 5.678\"; a phone shows \"3 de 3\", and charging\n * nearly triple its rendered width came straight out of the filter budget.\n */\n counter: 56,\n /**\n * ONE right-hand control (Exibir, or Exportar) WITH its text label.\n *\n * Priced per control rather than for the pair, because the pair is not what\n * every page renders: \"Exportar\" exists only when the host passes an\n * `exportConfig`, and several pages (Pedidos among them) put their export in\n * the PAGE HEADER instead. Charging 216 there billed the filters for a button\n * that was never on the bar — ~108px of budget spent on nothing, which on a\n * phone is the difference between one filter pill and none.\n */\n displayControl: 108,\n /**\n * The same control as an icon only — step 2 of the ladder.\n *\n * MEASURED at 133px for the PAIR (66 each: a Button's minimum tap target is\n * a good deal wider than the 20px glyph inside it); 70 keeps that total's\n * slack at one control's granularity.\n */\n displayControlCompact: 70,\n /**\n * What step 4 leaves behind: the search as a bare magnifier.\n *\n * MEASURED at 30px on the Pedidos bar (`…-search-all-collapsed`); 38 keeps a\n * tap target's worth of slack over it.\n */\n searchIcon: 38,\n /**\n * The narrowest keyword box still worth typing into — below it the operator\n * cannot read back what they wrote, and the box takes over the cluster\n * instead of sharing it (see `searchTakeover`).\n *\n * 120 rather than 140 because this is compared against the ESTIMATE, which\n * over-prices on purpose (see `estimateWidth`). At 140 a large phone took the\n * whole cluster to produce a box barely wider than the one it could have had\n * while keeping its filters — paying for nothing.\n */\n usableSearch: 120,\n /**\n * The \"Mais\" button, only charged when there IS an overflow — and priced by\n * the state it is actually in, like the right-hand cluster beside it.\n *\n * MEASURED: 128px with its label, badge and chevron; 69px once the ladder has\n * it down to icon + badge. One number for both was wrong in BOTH directions —\n * it under-priced the wide bar (the row's own failure mode) and over-priced\n * the narrow one by a whole pill.\n */\n overflowButton: 136,\n overflowButtonCompact: 80,\n /**\n * \"Limpar\", only charged when there IS something to clear.\n *\n * It appears exactly when the row is at its widest — every applied filter\n * has a longer label than the idle one it replaced — so leaving it unpriced\n * would break the line at the one moment the operator most needs it.\n * Measured at 64 as an icon; 72 with slack.\n */\n clearAll: 72,\n /**\n * The row's own padding, plus the gaps BETWEEN the fixed furniture.\n *\n * Not the per-control gaps — `splitFilters` already adds a `GAP` for every\n * filter it keeps, so counting a fourth one here charged one gap twice.\n * MEASURED: 32px of padding (16 each side) + three 8px gaps between the\n * search, the counter and the right cluster.\n */\n chrome: 56,\n} as const;\n\n/** The gap between two controls. */\nexport const GAP = 8;\n\n/** What the right-hand cluster costs, given what the host actually renders. */\nexport function rightClusterCost(hasExport: boolean, compact: boolean): number {\n const one = compact ? RESERVED.displayControlCompact : RESERVED.displayControl;\n return hasExport ? one * 2 : one;\n}\n\n/**\n * What the toolbar furniture costs at a given rung of the ladder — the budget\n * the filter controls have to fit AROUND.\n *\n * This exists because the two halves used to disagree. `splitFilters` priced\n * the furniture at its widest (search 200 + counter 96 + right 216) and shed\n * every filter to make room; the ladder then collapsed those very controls to\n * 44 + 0 + 140 and nobody handed the ~330px back. On a 428px phone that showed\n * as a bar carrying a magnifier, a \"Mais 5\" pill, and a band of nothing.\n */\nexport function furnitureCost(\n flags: { searchCollapsed: boolean; counterHidden: boolean; compactControls: boolean },\n hasExport: boolean,\n): number {\n return (\n (flags.searchCollapsed ? RESERVED.searchIcon : RESERVED.search) +\n (flags.counterHidden ? 0 : RESERVED.counter) +\n rightClusterCost(hasExport, flags.compactControls) +\n RESERVED.chrome\n );\n}\n"],"mappings":";AAwBO,SAAS,cAAc,MAAc,OAAuB;AAmBjE,SAAO,KAAK,MAAM,KAAK,SAAS,GAAG,IAAI,KAAK;AAC9C;AAGO,SAAS,WAAW,OAAwC;AACjE,SAAO,QAAQ,UAAU,MAAM,QAAQ,UAAa,MAAM,QAAQ,OAAU;AAC9E;AAGO,SAAS,SAA4C,OAAyB,QAA0B;AAC7G,MAAI,OAAO,WAAW,EAAG,QAAO,MAAM;AACtC,MAAI,OAAO,WAAW,GAAG;AACvB,UAAM,SAAS,MAAM,MAAM,QAAQ,KAAK,CAAC,UAAU,MAAM,UAAU,OAAO,CAAC,CAAC;AAC5E,WAAO,GAAG,MAAM,KAAK,KAAK,QAAQ,SAAS,OAAO,CAAC,CAAC;AAAA,EACtD;AACA,SAAO,GAAG,MAAM,KAAK,KAAK,OAAO,MAAM;AACzC;AAGO,IAAM,WAAW;AAAA;AAAA,EAEtB,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQR,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWT,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQhB,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOvB,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWZ,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUd,gBAAgB;AAAA,EAChB,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASvB,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASV,QAAQ;AACV;AAGO,IAAM,MAAM;AAGZ,SAAS,iBAAiB,WAAoB,SAA0B;AAC7E,QAAM,MAAM,UAAU,SAAS,wBAAwB,SAAS;AAChE,SAAO,YAAY,MAAM,IAAI;AAC/B;AAYO,SAAS,cACd,OACA,WACQ;AACR,UACG,MAAM,kBAAkB,SAAS,aAAa,SAAS,WACvD,MAAM,gBAAgB,IAAI,SAAS,WACpC,iBAAiB,WAAW,MAAM,eAAe,IACjD,SAAS;AAEb;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/utility/VirtualList/VirtualList.tsx"],"sourcesContent":["import Box from '@mui/material/Box/index.js';\nimport React, { useRef } from 'react';\n\nimport { useVirtualGrid, useVirtualList } from './VirtualList.hooks';\nimport type { VirtualGridProps, VirtualListProps } from './VirtualList.types';\n\ninterface ContainerProps {\n children: React.ReactNode;\n role: 'list' | 'grid';\n totalHeight: number;\n height: number;\n width: number | string;\n disableInternalScroll: boolean;\n onScroll: (event: React.UIEvent<HTMLDivElement>) => void;\n className?: string;\n style?: React.CSSProperties;\n dataTestId?: string;\n ariaLabel?: string;\n}\n\n/**\n * Two shapes, shared by the list and the grid: when the caller owns the scroll\n * container we render only the full-height content, so their element does the\n * scrolling; otherwise we render our own viewport around it.\n */\nconst VirtualContainer: React.FC<ContainerProps> = ({\n children,\n role,\n totalHeight,\n height,\n width,\n disableInternalScroll,\n onScroll,\n className,\n style,\n dataTestId,\n ariaLabel,\n}) => {\n const internalContainerRef = useRef<HTMLDivElement>(null);\n const identity = {\n className,\n 'data-testid': dataTestId,\n role,\n 'aria-label': ariaLabel,\n };\n\n if (disableInternalScroll) {\n return (\n <Box {...identity} sx={{ height: totalHeight, width, position: 'relative', ...style }}>\n {children}\n </Box>\n );\n }\n\n return (\n <Box\n ref={internalContainerRef}\n {...identity}\n sx={{ height, width, overflow: 'auto', position: 'relative', ...style }}\n onScroll={onScroll}\n >\n <Box sx={{ height: totalHeight, position: 'relative' }}>{children}</Box>\n </Box>\n );\n};\n\nexport const VirtualList: React.FC<VirtualListProps> = ({\n items,\n variant = 'fixed',\n height,\n width = '100%',\n itemHeight = 40,\n estimatedItemHeight = 40,\n overscan = 5,\n renderItem,\n onScroll,\n className,\n style,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n scrollContainerRef,\n disableInternalScroll = false,\n}) => {\n const { totalHeight, visibleItems, handleScroll } = useVirtualList({\n items,\n variant,\n height,\n itemHeight,\n estimatedItemHeight,\n overscan,\n onScroll,\n scrollContainerRef,\n });\n\n return (\n <VirtualContainer\n role=\"list\"\n totalHeight={totalHeight}\n height={height}\n width={width}\n disableInternalScroll={disableInternalScroll}\n onScroll={handleScroll}\n className={className}\n style={style}\n dataTestId={dataTestId}\n ariaLabel={ariaLabel}\n >\n {visibleItems.map(({ item, index, style: itemStyle }) =>\n renderItem({ item, index, style: itemStyle }),\n )}\n </VirtualContainer>\n );\n};\n\nexport const VirtualGrid: React.FC<VirtualGridProps> = ({\n items,\n height,\n width = '100%',\n columnCount,\n rowHeight,\n columnWidth,\n gap = 0,\n overscan = 5,\n renderItem,\n onScroll,\n className,\n style,\n 'data-testid': dataTestId,\n 'aria-label': ariaLabel,\n scrollContainerRef,\n disableInternalScroll = false,\n}) => {\n const { totalHeight, visibleItems, handleScroll } = useVirtualGrid({\n items,\n height,\n width,\n columnCount,\n rowHeight,\n columnWidth,\n gap,\n overscan,\n onScroll,\n scrollContainerRef,\n });\n\n return (\n <VirtualContainer\n role=\"grid\"\n totalHeight={totalHeight}\n height={height}\n width={width}\n disableInternalScroll={disableInternalScroll}\n onScroll={handleScroll}\n className={className}\n style={style}\n dataTestId={dataTestId}\n ariaLabel={ariaLabel}\n >\n {visibleItems.map(({ item, index, columnIndex, rowIndex, style: itemStyle }) =>\n renderItem({ item, index, columnIndex, rowIndex, style: itemStyle }),\n )}\n </VirtualContainer>\n );\n};\n"],"mappings":";;;;;;AAAA,OAAO,SAAS;AAChB,SAAgB,cAAc;AA+CxB;AAvBN,IAAM,mBAA6C,CAAC;AAAA,EAClD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,uBAAuB,OAAuB,IAAI;AACxD,QAAM,WAAW;AAAA,IACf;AAAA,IACA,eAAe;AAAA,IACf;AAAA,IACA,cAAc;AAAA,EAChB;AAEA,MAAI,uBAAuB;AACzB,WACE,oBAAC,OAAK,GAAG,UAAU,IAAI,EAAE,QAAQ,aAAa,OAAO,UAAU,YAAY,GAAG,MAAM,GACjF,UACH;AAAA,EAEJ;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK;AAAA,MACJ,GAAG;AAAA,MACJ,IAAI,EAAE,QAAQ,OAAO,UAAU,QAAQ,UAAU,YAAY,GAAG,MAAM;AAAA,MACtE;AAAA,MAEA,8BAAC,OAAI,IAAI,EAAE,QAAQ,aAAa,UAAU,WAAW,GAAI,UAAS;AAAA;AAAA,EACpE;AAEJ;AAEO,IAAM,cAA0C,CAAC;AAAA,EACtD;AAAA,EACA,UAAU;AAAA,EACV;AAAA,EACA,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,sBAAsB;AAAA,EACtB,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,cAAc;AAAA,EACd;AAAA,EACA,wBAAwB;AAC1B,MAAM;AACJ,QAAM,EAAE,aAAa,cAAc,aAAa,IAAI,eAAe;AAAA,IACjE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEC,uBAAa;AAAA,QAAI,CAAC,EAAE,MAAM,OAAO,OAAO,UAAU,MACjD,WAAW,EAAE,MAAM,OAAO,OAAO,UAAU,CAAC;AAAA,MAC9C;AAAA;AAAA,EACF;AAEJ;AAEO,IAAM,cAA0C,CAAC;AAAA,EACtD;AAAA,EACA;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,WAAW;AAAA,EACX;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf,cAAc;AAAA,EACd;AAAA,EACA,wBAAwB;AAC1B,MAAM;AACJ,QAAM,EAAE,aAAa,cAAc,aAAa,IAAI,eAAe;AAAA,IACjE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEC,uBAAa;AAAA,QAAI,CAAC,EAAE,MAAM,OAAO,aAAa,UAAU,OAAO,UAAU,MACxE,WAAW,EAAE,MAAM,OAAO,aAAa,UAAU,OAAO,UAAU,CAAC;AAAA,MACrE;AAAA;AAAA,EACF;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Table/Table.helpers.ts"],"sourcesContent":["import type { TableProps } from './Table.types';\n\nexport const TABLE_DEFAULTS: Partial<TableProps> = {\n variant: 'default',\n stripeColor: 'neutral',\n glow: false,\n pulse: false,\n hoverable: false,\n loading: false,\n density: 'normal',\n stickyHeader: false,\n selectable: false,\n selectedRows: [],\n sortable: false,\n virtualScrolling: false,\n rowHeight: 52,\n overscan: 5,\n responsive: false,\n showColumnToggle: true,\n};\n\n// Strips explicitly-undefined props before the merge, so `prop={undefined}` still\n// falls back to the default as a destructuring default would. Eighteen separate\n// destructuring defaults were most of this component's branch count.\nexport const definedProps = (props: TableProps): Partial<TableProps> =>\n Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<TableProps>;\n\n// The container + styled table + optional header, shared by the loading, empty\n// and populated renders.\n"],"mappings":";AAEO,IAAM,iBAAsC;AAAA,EACjD,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,SAAS;AAAA,EACT,SAAS;AAAA,EACT,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,cAAc,CAAC;AAAA,EACf,UAAU;AAAA,EACV,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,kBAAkB;AACpB;AAKO,IAAM,eAAe,CAAC,UAC3B,OAAO;AAAA,EACL,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAS;AACjE;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/layout/Resizable/Resizable.hooks.ts"],"sourcesContent":["import React, { useCallback, useRef, useState } from 'react';\n\nimport type { Bounds } from './Resizable.helpers';\nimport { resizedTo } from './Resizable.helpers';\nimport type { ResizeHandle } from './Resizable.types';\n\ninterface ResizeArgs {\n width: number;\n height: number;\n bounds: Bounds;\n disabled: boolean;\n onResize?: (width: number, height: number) => void;\n}\n\n/**\n * Tracks the box's size across a drag. The listeners live on the document rather\n * than the handle, so the pointer can leave the handle — or the component — mid\n * drag without the resize sticking.\n */\nexport const useResize = ({ width, height, bounds, disabled, onResize }: ResizeArgs) => {\n const [size, setSize] = useState({ width, height });\n const [isResizing, setIsResizing] = useState(false);\n const startPos = useRef({ x: 0, y: 0 });\n const startSize = useRef({ width: 0, height: 0 });\n const activeHandle = useRef<ResizeHandle | null>(null);\n\n React.useEffect(() => {\n setSize({ width, height });\n }, [width, height]);\n\n const handleMouseDown = useCallback(\n (e: React.MouseEvent, handle: ResizeHandle) => {\n if (disabled) return;\n\n e.preventDefault();\n e.stopPropagation();\n\n setIsResizing(true);\n activeHandle.current = handle;\n startPos.current = { x: e.clientX, y: e.clientY };\n startSize.current = { width: size.width, height: size.height };\n\n const handleMouseMove = (move: globalThis.MouseEvent) => {\n const delta = {\n x: move.clientX - startPos.current.x,\n y: move.clientY - startPos.current.y,\n };\n const next = resizedTo(handle, delta, startSize.current, bounds);\n\n setSize(next);\n onResize?.(next.width, next.height);\n };\n\n const handleMouseUp = () => {\n setIsResizing(false);\n activeHandle.current = null;\n document.removeEventListener('mousemove', handleMouseMove);\n document.removeEventListener('mouseup', handleMouseUp);\n };\n\n document.addEventListener('mousemove', handleMouseMove);\n document.addEventListener('mouseup', handleMouseUp);\n },\n [disabled, size, bounds, onResize],\n );\n\n return { size, isResizing, activeHandle, handleMouseDown };\n};\n"],"mappings":";;;;;AAAA,OAAO,SAAS,aAAa,QAAQ,gBAAgB;AAmB9C,IAAM,YAAY,CAAC,EAAE,OAAO,QAAQ,QAAQ,UAAU,SAAS,MAAkB;AACtF,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE,OAAO,OAAO,CAAC;AAClD,QAAM,CAAC,YAAY,aAAa,IAAI,SAAS,KAAK;AAClD,QAAM,WAAW,OAAO,EAAE,GAAG,GAAG,GAAG,EAAE,CAAC;AACtC,QAAM,YAAY,OAAO,EAAE,OAAO,GAAG,QAAQ,EAAE,CAAC;AAChD,QAAM,eAAe,OAA4B,IAAI;AAErD,QAAM,UAAU,MAAM;AACpB,YAAQ,EAAE,OAAO,OAAO,CAAC;AAAA,EAC3B,GAAG,CAAC,OAAO,MAAM,CAAC;AAElB,QAAM,kBAAkB;AAAA,IACtB,CAAC,GAAqB,WAAyB;AAC7C,UAAI,SAAU;AAEd,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAElB,oBAAc,IAAI;AAClB,mBAAa,UAAU;AACvB,eAAS,UAAU,EAAE,GAAG,EAAE,SAAS,GAAG,EAAE,QAAQ;AAChD,gBAAU,UAAU,EAAE,OAAO,KAAK,OAAO,QAAQ,KAAK,OAAO;AAE7D,YAAM,kBAAkB,CAAC,SAAgC;AACvD,cAAM,QAAQ;AAAA,UACZ,GAAG,KAAK,UAAU,SAAS,QAAQ;AAAA,UACnC,GAAG,KAAK,UAAU,SAAS,QAAQ;AAAA,QACrC;AACA,cAAM,OAAO,UAAU,QAAQ,OAAO,UAAU,SAAS,MAAM;AAE/D,gBAAQ,IAAI;AACZ,mBAAW,KAAK,OAAO,KAAK,MAAM;AAAA,MACpC;AAEA,YAAM,gBAAgB,MAAM;AAC1B,sBAAc,KAAK;AACnB,qBAAa,UAAU;AACvB,iBAAS,oBAAoB,aAAa,eAAe;AACzD,iBAAS,oBAAoB,WAAW,aAAa;AAAA,MACvD;AAEA,eAAS,iBAAiB,aAAa,eAAe;AACtD,eAAS,iBAAiB,WAAW,aAAa;AAAA,IACpD;AAAA,IACA,CAAC,UAAU,MAAM,QAAQ,QAAQ;AAAA,EACnC;AAEA,SAAO,EAAE,MAAM,YAAY,cAAc,gBAAgB;AAC3D;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/data-views-layout-context.tsx"],"sourcesContent":["\"use client\";\n\nimport { createContext, useContext, useEffect, useMemo, useState, type ReactNode } from \"react\";\n\nimport GridViewOutlinedIcon from \"@mui/icons-material/GridViewOutlined\";\n\nimport { Slider } from \"../../form/Slider\";\nimport { Box } from \"../../../mui/Box\";\n\nimport { useDataViewsCopy } from \"./data-views-copy-context\";\nimport { DATA_VIEWS_LAYOUTS, type DataViewsLayout } from \"./data-views-types\";\n\n/**\n * The DataViews layout (view type): the dense \"Tabela\" grid, the \"Grade\" of\n * cards, the \"Lista\" of full-width rows, or the \"Quadro\" board of state columns.\n * Shared across the toolbar (the toggle) and the body (the selector) via context\n * so a single source of truth drives what renders — each layout only appears\n * when the table opts into it (`renderCard` for the grade, `renderListRow` for\n * the lista, `board` + `renderCard` for the quadro).\n */\nexport type { DataViewsLayout };\n\ninterface DataViewsLayoutValue {\n layout: DataViewsLayout;\n setLayout: (layout: DataViewsLayout) => void;\n /** How much air each record gets — see {@link DataViewsDensity}. */\n density: DataViewsDensity;\n setDensity: (density: DataViewsDensity) => void;\n /** Whether the cards layout is available (a `renderCard` was supplied). */\n canUseCards: boolean;\n /** Whether the list layout is available (a `renderListRow` was supplied). */\n canUseList: boolean;\n /** Whether the board layout is available (a `board` config AND a `renderCard`). */\n canUseBoard: boolean;\n /** Card-size zoom (0–100); drives the card grid's min column width. */\n zoom: number;\n setZoom: (zoom: number) => void;\n}\n\nconst DataViewsLayoutContext = createContext<DataViewsLayoutValue | null>(null);\n\n/** Default card zoom (0–100). */\nconst DEFAULT_ZOOM = 35;\n/** The card's width in px at scale 1 — the zoom slider multiplies this. */\nconst BASE_CARD_WIDTH = 180;\n/** The size multiplier the zoom slider spans (0.75× to 2×). */\nconst CARD_SCALE_RANGE = { min: 0.75, max: 2 } as const;\n\n/**\n * Where the user's layout preference is remembered. ONE key for every DataViews\n * table in the app, on purpose: picking \"Grade\" on Produtos is a statement about\n * how this operator likes to read lists, not about that one screen. Every other\n * screen that CAN render cards then opens in cards, and one that cannot falls\n * back without forgetting the preference.\n */\nconst LAYOUT_STORAGE_KEY = \"dataviews:layout\";\n\n/**\n * The density preference, remembered app-wide for the same reason as the layout:\n * an operator who wants tight rows wants them on every list, not on one.\n */\nconst DENSITY_STORAGE_KEY = \"dataviews:density\";\n\n/**\n * How much room each record gets. It means different things per layout, and\n * that is the point — one control, phrased in the terms of what is on screen:\n *\n * - table / list → row height (\"Baixa / Média / Alta\")\n * - cards → how many fit per row (\"Muitos / Médio / Poucos\")\n *\n * The board is unaffected: its cards are already sized by the zoom slider.\n */\nexport type DataViewsDensity = \"compact\" | \"cozy\" | \"comfortable\";\n\n/** Every density this build knows — the guard's single source. */\nconst DENSITIES: readonly DataViewsDensity[] = [\"compact\", \"cozy\", \"comfortable\"];\n\n/** Vertical padding (theme spacing units) per density, for a table or list row. */\nexport const DENSITY_ROW_PADDING: Record<DataViewsDensity, number> = {\n compact: 0.25,\n cozy: 0.75,\n comfortable: 1.5,\n};\n\n/**\n * The card WIDTH each density aims for, as a multiple of the base card width.\n *\n * Density used to cap the column COUNT, with a track floor of\n * `max(baseWidth, 100% / count)`. That base is a constant, so wherever it won\n * the arithmetic every density produced an identical track — \"Muitos\" and\n * \"Medio\" both drew 3 cards of 279px at md — and where the percentage won\n * instead, on a wide screen, the count was pinned and each card grew to a share\n * of the viewport: ~430px of card holding one chip and two lines of text.\n *\n * One width per density fixes both, because the number `auto-fill` divides by\n * now differs per density at every size. The spread is chosen so the three land\n * on DIFFERENT column counts across the range rather than by eye — 4/3/2 at md,\n * 6/4/3 at lg, 7/5/4 at xl, 13/9/8 at 2560.\n */\nexport const DENSITY_CARD_SCALE: Record<DataViewsDensity, number> = {\n compact: 0.84,\n cozy: 1.15,\n comfortable: 1.4,\n};\n\n/** The width a card aims for: the base width, scaled by zoom, then by density. */\nexport function cardTargetWidthFor(zoom: number, density: DataViewsDensity): number {\n return Math.round(cardMinWidthForZoom(zoom) * DENSITY_CARD_SCALE[density]);\n}\n\n/**\n * The BOARD's column-width multiplier per density.\n *\n * Density means \"how much air a record gets\", and on a board that is the column\n * width — narrow columns fit more etapas on screen, wide ones give each card\n * room to be read. Without this the board was the one layout the Exibição tab\n * offered nothing for: the format tile switched to Quadro and the whole density\n * section vanished, which reads as a control that broke rather than one that\n * does not apply.\n *\n * The spread is deliberately narrower than the card grid's. A board column has\n * a hard floor (`MIN_COLUMN_WIDTH` — a card below it stops being readable), so\n * a multiplier that undershoots it buys nothing and makes \"Estreita\" a tile\n * that does nothing on a phone.\n */\nexport const DENSITY_BOARD_SCALE: Record<DataViewsDensity, number> = {\n compact: 0.95,\n cozy: 1,\n comfortable: 1.25,\n};\n\n/**\n * Map the 0–100 zoom to the card SIZE multiplier. This is the single knob: the\n * card's width is {@link BASE_CARD_WIDTH} × scale and its padding + typography\n * scale by the same factor, so the whole card grows together (scale 2 → twice\n * the size, proportion preserved by the aspect ratio). Passed to a card via\n * `DataViewCardSelection.scale`.\n */\nexport function cardScaleForZoom(zoom: number): number {\n const clamped = Math.max(0, Math.min(100, zoom));\n return CARD_SCALE_RANGE.min + (clamped / 100) * (CARD_SCALE_RANGE.max - CARD_SCALE_RANGE.min);\n}\n\n/** The card grid's min column width in px = base width × the zoom size multiplier. */\nexport function cardMinWidthForZoom(zoom: number): number {\n return Math.round(BASE_CARD_WIDTH * cardScaleForZoom(zoom));\n}\n\n/** Which layouts this table can actually render. */\ninterface LayoutAvailability {\n canUseCards: boolean;\n canUseList: boolean;\n canUseBoard: boolean;\n}\n\n/** Is this a layout string this build knows? Guards whatever is in storage. */\nfunction isLayout(value: unknown): value is DataViewsLayout {\n return DATA_VIEWS_LAYOUTS.includes(value as DataViewsLayout);\n}\n\n/** Is this a density this build knows? Guards whatever is in storage. */\nfunction isDensity(value: unknown): value is DataViewsDensity {\n return DENSITIES.includes(value as DataViewsDensity);\n}\n\n/** The remembered density, or undefined (no window, no value, junk). */\nfunction readStoredDensity(): DataViewsDensity | undefined {\n try {\n if (typeof window === \"undefined\") return undefined;\n const stored = window.localStorage.getItem(DENSITY_STORAGE_KEY);\n return isDensity(stored) ? stored : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Pin a layout to one this table can render. \"Tabela\" is always available, so it\n * is the floor: a page with no `renderCard` never renders a cards body, one with\n * no `renderListRow` never renders a list, and one with no `board` config never\n * renders a board — whatever is stored, saved in a view, or requested.\n */\nfunction pinLayout(layout: DataViewsLayout, available: LayoutAvailability): DataViewsLayout {\n if (layout === \"cards\") return available.canUseCards ? \"cards\" : \"table\";\n if (layout === \"list\") return available.canUseList ? \"list\" : \"table\";\n if (layout === \"board\") return available.canUseBoard ? \"board\" : \"table\";\n return \"table\";\n}\n\n/** The stored cross-screen preference, or undefined (no window, no value, junk). */\nfunction readStoredLayout(): DataViewsLayout | undefined {\n // Guarded rather than assumed: this module is also imported in Node (tests,\n // any SSR host), and a `localStorage` access can throw outright under a\n // restrictive privacy setting — a thrown read must not take the grid with it.\n try {\n if (typeof window === \"undefined\") return undefined;\n const stored = window.localStorage.getItem(LAYOUT_STORAGE_KEY);\n return isLayout(stored) ? stored : undefined;\n } catch {\n return undefined;\n }\n}\n\n/** Remember a preference for every other screen. A failed write is not an error. */\nfunction writeStored(key: string, value: string): void {\n try {\n if (typeof window === \"undefined\") return;\n window.localStorage.setItem(key, value);\n } catch {\n // Private mode / quota / disabled storage: the preference simply does not\n // survive the session. Nothing about the current view depends on it.\n }\n}\n\ninterface LayoutProviderProps extends Partial<LayoutAvailability> {\n /** Which layout to show first when the user has expressed no preference. */\n defaultLayout?: DataViewsLayout;\n /**\n * The layout an APPLIED SAVED VIEW pins, when it stored one. It wins over the\n * remembered preference for as long as that view is applied — the view is a\n * snapshot someone chose to keep — but it does NOT overwrite the preference:\n * only the toggle does that, because only the toggle is the user saying so.\n */\n viewLayout?: DataViewsLayout;\n /**\n * Ignore — and stop writing — the remembered cross-screen preference, making\n * `defaultLayout` authoritative for this table.\n *\n * For a table that exists to SHOW a particular layout rather than to be\n * browsed: a Storybook story called \"Board\", a docs example, a screenshot\n * harness. Without it the remembered preference wins, so opening \"Board\"\n * after having clicked Tabela anywhere renders a table — the demonstration\n * silently showing the wrong thing, and a shared link doing it for everyone\n * whose preference differs.\n *\n * A real screen leaves this off: remembering how someone likes to read\n * lists is the point.\n */\n ignoreStoredLayout?: boolean;\n children: ReactNode;\n}\n\n/**\n * Provides the view-type state, seeded from (in order) the applied saved view's\n * layout, the user's remembered cross-screen preference, then `defaultLayout` —\n * each pinned to what this table can actually render.\n */\nexport function DataViewsLayoutProvider({\n canUseCards = false,\n canUseList = false,\n canUseBoard = false,\n defaultLayout = \"table\",\n viewLayout,\n ignoreStoredLayout = false,\n children,\n}: LayoutProviderProps): React.JSX.Element {\n const availability = { canUseCards, canUseList, canUseBoard };\n const [layout, setLayoutState] = useState<DataViewsLayout>(() =>\n pinLayout(\n viewLayout ?? (ignoreStoredLayout ? undefined : readStoredLayout()) ?? defaultLayout,\n availability,\n ),\n );\n const [density, setDensityState] = useState<DataViewsDensity>(\n () => (ignoreStoredLayout ? undefined : readStoredDensity()) ?? \"cozy\",\n );\n const [zoom, setZoom] = useState(DEFAULT_ZOOM);\n // A newly applied view carrying a layout switches to it (its reference-change\n // is the signal, exactly as `appliedState` works for the filters).\n useEffect(() => {\n if (viewLayout) setLayoutState(pinLayout(viewLayout, availability));\n // Availability is derived from props that do not change for a mounted table.\n }, [viewLayout]);\n // Pin again on read: `canUseCards`/`canUseBoard` can flip for a mounted table\n // (a page that supplies `renderCard` only once its card data has loaded), and\n // a stale \"cards\" would otherwise render a cards body with no renderer.\n const effective = pinLayout(layout, availability);\n\n const value = useMemo<DataViewsLayoutValue>(\n () => ({\n layout: effective,\n setLayout: (next: DataViewsLayout) => {\n const pinned = pinLayout(next, availability);\n setLayoutState(pinned);\n // Remember the user's own choice across every screen — see LAYOUT_STORAGE_KEY.\n // A table pinned to a layout does not write: it would teach the\n // preference a value the operator never chose.\n if (!ignoreStoredLayout) writeStored(LAYOUT_STORAGE_KEY, pinned);\n },\n density,\n setDensity: (next: DataViewsDensity) => {\n setDensityState(next);\n if (!ignoreStoredLayout) writeStored(DENSITY_STORAGE_KEY, next);\n },\n canUseCards,\n canUseList,\n canUseBoard,\n zoom,\n setZoom,\n }),\n [effective, density, canUseCards, canUseList, canUseBoard, zoom],\n );\n return <DataViewsLayoutContext.Provider value={value}>{children}</DataViewsLayoutContext.Provider>;\n}\n\n/** Read the current DataViews layout. Throws outside a provider. */\nexport function useDataViewsLayout(): DataViewsLayoutValue {\n const ctx = useContext(DataViewsLayoutContext);\n if (!ctx) {\n throw new Error(\"useDataViewsLayout must be used within a DataViewsLayoutProvider\");\n }\n return ctx;\n}\n\n/**\n * Card-size slider for the toolbar — shown in the CARD-BASED layouts (\"Grade\"\n * and \"Quadro\"), mirroring the tabwoah view-selector's zoom. The board reuses\n * the same `renderCard`, so the same knob scales both.\n *\n * Deliberately ABSENT in \"Lista\" and \"Tabela\" (FUT-733): a list row is\n * full-width and sized by its content, so a card-size multiplier has nothing to\n * act on — a slider that moved and changed nothing would be worse than none.\n */\nexport function DataViewsZoomSlider({ testIdPrefix }: { testIdPrefix: string }): React.JSX.Element | null {\n const { layout, zoom, setZoom } = useDataViewsLayout();\n const copy = useDataViewsCopy();\n if (layout !== \"cards\" && layout !== \"board\") return null;\n return (\n <Box\n sx={{\n display: { xs: \"none\", sm: \"flex\" },\n alignItems: \"center\",\n gap: 1,\n color: \"text.secondary\",\n }}\n >\n <GridViewOutlinedIcon sx={{ fontSize: 14 }} />\n <Box sx={{ width: 88, display: \"flex\", alignItems: \"center\" }}>\n <Slider\n size=\"sm\"\n showValue={false}\n value={zoom}\n min={0}\n max={100}\n step={5}\n onChange={(_event, next) => setZoom(Array.isArray(next) ? (next[0] ?? 0) : next)}\n aria-label={copy.display.cardZoom}\n data-testid={`${testIdPrefix}-card-zoom`}\n />\n </Box>\n <GridViewOutlinedIcon sx={{ fontSize: 20 }} />\n </Box>\n );\n}\n"],"mappings":"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","names":["default"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/data-views-grid-helpers.tsx"],"sourcesContent":["\"use client\";\n\nimport type { Theme } from \"@mui/material/styles/index.js\";\n\nimport { useDataViewsCopy } from \"./data-views-copy-context\";\nimport { type GridColumn } from \"../DataGrid\";\nimport { type SortFieldDefinition } from \"../../layout/ContentToolbar\";\nimport { Box } from \"../../../mui/Box\";\nimport { rem, sxRem } from \"../../../tokens/relative\";\nimport { Button } from \"../../form/Button\";\nimport { DropdownMenu, type DropdownMenuItem } from \"../../navigation/DropdownMenu\";\n\nimport type {\n DataViewColumn,\n DataViewState,\n FilterFieldConfig,\n RangeFieldConfig,\n RowAction,\n} from \"./data-views-types\";\n\n/** Is this the non-clickable actions column? */\nexport function isActionsColumn<T extends Record<string, unknown>>(col: GridColumn<T>): boolean {\n return col.type === \"actions\" || col.id === \"actions\";\n}\n\n/**\n * Map the DataView columns to grid columns, applying visibility and — when a row\n * click handler is present — wrapping each non-actions cell so clicking opens the row.\n */\nexport function buildGridColumns<T extends Record<string, unknown>>(\n columns: DataViewColumn<T>[],\n visibleColumns: string[],\n onRowClick: ((row: T) => void) | undefined,\n): GridColumn<T>[] {\n return columns.map((col) => {\n const hidden = col.hideable !== false && !visibleColumns.includes(col.id);\n if (!onRowClick || isActionsColumn(col)) return { ...col, hidden };\n return {\n ...col,\n hidden,\n cell: (ctx) => {\n const content = col.cell ? col.cell(ctx) : ctx.value == null ? \"\" : String(ctx.value);\n return (\n <Box\n onClick={() => onRowClick(ctx.row)}\n sx={{ cursor: \"pointer\", width: \"100%\", height: \"100%\", display: \"flex\", alignItems: \"center\" }}\n >\n {content}\n </Box>\n );\n },\n };\n });\n}\n\ninterface ActionsColumnConfig<T extends Record<string, unknown>> {\n /** Actions that build the auto \"⋮\" kebab. Ignored when `renderRowMenu` is set. */\n rowActions: RowAction<T>[];\n /** Optional leading slot (e.g. a favourite star) rendered before the kebab. */\n leading?: (row: T) => React.ReactNode;\n testIdPrefix: string;\n getRowId: (row: T) => string | number;\n /**\n * Escape hatch: render a bespoke per-row menu (e.g. an entity's self-contained\n * 3-dots menu that owns its own popups) INSTEAD of the auto kebab built from\n * `rowActions`. This is how the table row and the card share ONE menu component.\n * `rowActions`/`bulkActions` still drive the multi-row bulk menu, which a\n * single-row menu intentionally does not replace.\n */\n renderRowMenu?: (row: T) => React.ReactNode;\n}\n\n/**\n * The auto \"⋮\" kebab actions column built from the reusable `rowActions` — the\n * SAME definitions that feed the bulk menu, so the two never drift. Each item\n * acts on just this row; `rowLabel` provides a per-row label when set. An\n * optional `leading` slot (e.g. a favourite star) renders before the kebab.\n * When `renderRowMenu` is supplied, the cell renders that bespoke menu instead.\n */\nexport function buildRowActionsColumn<T extends Record<string, unknown>>(\n config: ActionsColumnConfig<T>,\n): DataViewColumn<T> {\n const { rowActions, leading, testIdPrefix, getRowId, renderRowMenu } = config;\n const kebabActions = rowActions.filter((action) => action.row !== false);\n return {\n id: \"actions\",\n header: \"\",\n type: \"actions\",\n enableSort: false,\n hideable: false,\n // Narrow: the column only holds the \"⋮\" kebab (plus an optional leading icon),\n // so it needs room for just one or two icons.\n width: leading ? 72 : 44,\n cell: ({ row }) => (\n <Box component=\"span\" sx={{ display: \"inline-flex\", alignItems: \"center\", gap: sxRem(2), justifyContent: \"flex-end\" }}>\n {leading?.(row)}\n {renderRowMenu\n ? renderRowMenu(row)\n : renderAutoKebab(kebabActions, row, testIdPrefix, getRowId)}\n </Box>\n ),\n };\n}\n\n/** The built-in kebab menu for one row, derived from `rowActions`. */\nfunction renderAutoKebab<T extends Record<string, unknown>>(\n kebabActions: RowAction<T>[],\n row: T,\n testIdPrefix: string,\n getRowId: (row: T) => string | number,\n): React.ReactNode {\n const copy = useDataViewsCopy();\n const items: DropdownMenuItem[] = kebabActions\n .filter((action) => action.isVisible?.(row) ?? true)\n .map((action) => ({\n id: action.id,\n label: action.rowLabel ? action.rowLabel(row) : action.label,\n color: action.color,\n onClick: () => void action.onSelect([row]),\n }));\n if (items.length === 0) return null;\n return (\n <DropdownMenu\n size=\"sm\"\n items={items}\n trigger={\n <Button variant=\"text\" size=\"sm\" dataTestId={`${testIdPrefix}-actions-${getRowId(row)}`} aria-label={copy.grid.rowActions}>\n ⋮\n </Button>\n }\n />\n );\n}\n\n/** Sort options derived from the sortable columns when a page supplies none. */\nexport function defaultSortFields<T extends Record<string, unknown>>(\n columns: DataViewColumn<T>[],\n): SortFieldDefinition[] {\n return columns\n .filter(\n (col) =>\n col.enableSort !== false &&\n col.type !== \"actions\" &&\n col.id !== \"actions\" &&\n typeof col.header === \"string\" &&\n col.header !== \"\",\n )\n .map((col) => ({\n value: col.id,\n label: col.header as string,\n orderOptions: [\n { value: \"asc\", label: \"Crescente\" },\n { value: \"desc\", label: \"Decrescente\" },\n ],\n }));\n}\n\n/** Count active filters (search + selected pills + bounded ranges) for the badge. */\nexport function computeActiveFilterCount<T extends Record<string, unknown>>(\n state: DataViewState,\n fields: FilterFieldConfig<T>[],\n rangeFields: RangeFieldConfig<T>[],\n): number {\n const ranges = state.ranges ?? {};\n const pillCount = fields.reduce((n, field) => n + ((state.pills[field.id]?.length ?? 0) > 0 ? 1 : 0), 0);\n const rangeCount = rangeFields.reduce((n, field) => {\n const range = ranges[field.id];\n return n + (range && (range.min != null || range.max != null) ? 1 : 0);\n }, 0);\n return (state.search.trim() ? 1 : 0) + pillCount + rangeCount;\n}\n\nfunction bulkMenuItems<T extends Record<string, unknown>>(\n rowActions: RowAction<T>[],\n selectedRows: T[],\n clearSelection: () => void,\n): DropdownMenuItem[] {\n return rowActions\n .filter((action) => action.bulk !== false)\n .map((action) => {\n // State-machine guards: the action runs only on the rows it applies to,\n // and disappears from the menu when none of the selection qualifies.\n const targets = action.isVisible ? selectedRows.filter(action.isVisible) : selectedRows;\n return { action, targets };\n })\n .filter(({ targets }) => targets.length > 0)\n .map(({ action, targets }) => ({\n id: action.id,\n label: action.label,\n color: action.color,\n onClick: () => {\n // Run the (possibly async) handler on the captured selection, then clear\n // it — but only once the work settles. On failure keep the selection so\n // the user can see which rows still need action and retry.\n const result = action.onSelect(targets);\n if (result instanceof Promise) {\n void result.then(\n () => clearSelection(),\n () => {\n /* keep the selection on failure so the user can retry */\n },\n );\n } else {\n clearSelection();\n }\n },\n }));\n}\n\ninterface RenderBulkArgs<T extends Record<string, unknown>> {\n rowActions: RowAction<T>[] | undefined;\n bulkActions: ((selectedRows: T[], clearSelection: () => void) => React.ReactNode) | undefined;\n selectedRows: T[];\n clearSelection: () => void;\n testIdPrefix: string;\n}\n\n/**\n * The selection bulk control shown in the toolbar. Prefers the reusable\n * `rowActions` (an \"Ações\" dropdown mirroring the row kebab); falls back to the\n * low-level `bulkActions` render prop. Renders nothing with no selection.\n */\nexport function renderBulkActions<T extends Record<string, unknown>>({\n rowActions,\n bulkActions,\n selectedRows,\n clearSelection,\n testIdPrefix,\n}: RenderBulkArgs<T>): React.ReactNode {\n const copy = useDataViewsCopy();\n if (selectedRows.length === 0) return undefined;\n if (rowActions) {\n const items = bulkMenuItems(rowActions, selectedRows, clearSelection);\n if (items.length === 0) return undefined;\n return (\n <DropdownMenu\n size=\"sm\"\n items={items}\n trigger={\n <Button variant=\"outline\" size=\"sm\" dataTestId={`${testIdPrefix}-bulk-actions`}>\n {copy.grid.bulkActions(selectedRows.length)}\n </Button>\n }\n />\n );\n }\n return bulkActions ? bulkActions(selectedRows, clearSelection) : undefined;\n}\n\n/** Toggle a single value in a pill's selected-list (returns the next list). */\nexport function togglePillValues(current: string[] | undefined, value: string, checked: boolean): string[] {\n const list = current ?? [];\n return checked ? [...list, value] : list.filter((v) => v !== value);\n}\n\n/**\n * The card grid's `grid-template-columns`, as an sx fragment.\n *\n * One rule at every width: each card asks for `targetWidth` and `auto-fill`\n * decides how many fit. Density moves the target, so it changes the count at\n * every size — which the previous column-count cap could not do, because its\n * track floor bottomed out at a constant shared by all three densities.\n *\n * Below `sm` this is a single column, and no target changes that. That is why\n * the density control hides itself there rather than offering three settings\n * that all draw the same thing.\n */\nexport function cardGridTracks(targetWidth: number) {\n return {\n gridTemplateColumns: (theme: Theme) => ({\n xs: \"1fr\",\n sm: `repeat(auto-fill, minmax(${rem(theme, targetWidth)}, 1fr))`,\n }),\n };\n}\n"],"mappings":"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","names":["default"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/form/Calendar/CalendarMonth.tsx"],"sourcesContent":["import ChevronLeft from '@mui/icons-material/ChevronLeft';\nimport ChevronRight from '@mui/icons-material/ChevronRight';\nimport Box from '@mui/material/Box/index.js';\nimport IconButton from '@mui/material/IconButton/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport type { FC } from 'react';\nimport React from 'react';\n\nimport { getMonthName } from './Calendar.dates';\nimport type { CalendarProps, MonthMatrix } from './Calendar.types';\nimport type { DayCellContext } from './CalendarDayCell';\nimport { CalendarDayCell } from './CalendarDayCell';\n\nconst SPACER_WIDTH = 32;\n\nconst GRID_SX = { display: 'grid', gridTemplateColumns: 'repeat(7, 1fr)', gap: 0.5 } as const;\n\n// Only the outermost months carry arrows; the ones between get a spacer so their\n// titles stay centred.\nconst MonthNavHeader: FC<{\n title: React.ReactNode;\n showPrevious: boolean;\n showNext: boolean;\n onPreviousMonth: () => void;\n onNextMonth: () => void;\n}> = ({ title, showPrevious, showNext, onPreviousMonth, onNextMonth }) => (\n <Box\n sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 2 }}\n data-testid=\"calendar-header\"\n >\n {showPrevious && (\n <IconButton onClick={onPreviousMonth} size=\"small\" data-testid=\"calendar-prev-month\">\n <ChevronLeft />\n </IconButton>\n )}\n\n <Typography\n variant=\"h6\"\n component=\"h2\"\n sx={{ fontWeight: 'bold', flex: 1, textAlign: 'center' }}\n >\n {title}\n </Typography>\n\n {showNext && (\n <IconButton onClick={onNextMonth} size=\"small\" data-testid=\"calendar-next-month\">\n <ChevronRight />\n </IconButton>\n )}\n\n {!showPrevious && !showNext && <Box sx={{ width: SPACER_WIDTH }} />}\n </Box>\n);\n\nconst WeekdayHeader: FC<{ weekdayNames: string[] }> = ({ weekdayNames }) => (\n <Box sx={{ ...GRID_SX, mb: 1 }}>\n {weekdayNames.map((weekday, index) => (\n <Box\n // Narrow weekday names repeat within a week ('S', 'T'), so position is\n // the only stable key here.\n key={`weekday-${index}`}\n role=\"columnheader\"\n data-testid={`calendar-weekday-${index}`}\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: SPACER_WIDTH,\n fontSize: '0.875rem',\n fontWeight: 'bold',\n color: 'text.secondary',\n }}\n >\n {weekday}\n </Box>\n ))}\n </Box>\n);\n\nexport interface CalendarMonthProps {\n matrix: MonthMatrix;\n monthIndex: number;\n monthsToShow: number;\n locale: string;\n weekdayNames: string[];\n renderHeader?: CalendarProps['renderHeader'];\n onPreviousMonth: () => void;\n onNextMonth: () => void;\n dayContext: DayCellContext;\n}\n\nexport const CalendarMonth: FC<CalendarMonthProps> = ({\n matrix,\n monthIndex,\n monthsToShow,\n locale,\n weekdayNames,\n renderHeader,\n onPreviousMonth,\n onNextMonth,\n dayContext,\n}) => {\n const monthName = getMonthName(matrix.month, matrix.year, locale);\n const title = renderHeader ? renderHeader({ month: matrix.month, year: matrix.year }) : monthName;\n\n return (\n /* The month is addressable by its position, because in a multi-month\n calendar every day number appears once PER MONTH — `calendar-date-5` is\n January's 5th and February's. Without a per-month hook a test can only\n reach a day positionally, which is exactly what the flakiness gate\n refuses. Additive: `calendar-grid` below is unchanged. */\n <Box sx={{ minWidth: 280 }} data-testid={`calendar-month-${monthIndex}`}>\n <MonthNavHeader\n title={title}\n showPrevious={monthIndex === 0}\n showNext={monthIndex === monthsToShow - 1}\n onPreviousMonth={onPreviousMonth}\n onNextMonth={onNextMonth}\n />\n\n <WeekdayHeader weekdayNames={weekdayNames} />\n\n <Box\n role=\"grid\"\n aria-labelledby={`month-${monthIndex}`}\n data-testid=\"calendar-grid\"\n sx={GRID_SX}\n >\n {matrix.weeks.flat().map((day) => (\n <CalendarDayCell key={day.key} day={day} {...dayContext} />\n ))}\n </Box>\n </Box>\n );\n};\n"],"mappings":";;;;;;;;AAAA,OAAO,iBAAiB;AACxB,OAAO,kBAAkB;AACzB,OAAO,SAAS;AAChB,OAAO,gBAAgB;AACvB,OAAO,gBAAgB;AAsBrB,SAMM,KANN;AAbF,IAAM,eAAe;AAErB,IAAM,UAAU,EAAE,SAAS,QAAQ,qBAAqB,kBAAkB,KAAK,IAAI;AAInF,IAAM,iBAMD,CAAC,EAAE,OAAO,cAAc,UAAU,iBAAiB,YAAY,MAClE;AAAA,EAAC;AAAA;AAAA,IACC,IAAI,EAAE,SAAS,QAAQ,YAAY,UAAU,gBAAgB,iBAAiB,IAAI,EAAE;AAAA,IACpF,eAAY;AAAA,IAEX;AAAA,sBACC,oBAAC,cAAW,SAAS,iBAAiB,MAAK,SAAQ,eAAY,uBAC7D,8BAAC,eAAY,GACf;AAAA,MAGF;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,WAAU;AAAA,UACV,IAAI,EAAE,YAAY,QAAQ,MAAM,GAAG,WAAW,SAAS;AAAA,UAEtD;AAAA;AAAA,MACH;AAAA,MAEC,YACC,oBAAC,cAAW,SAAS,aAAa,MAAK,SAAQ,eAAY,uBACzD,8BAAC,gBAAa,GAChB;AAAA,MAGD,CAAC,gBAAgB,CAAC,YAAY,oBAAC,OAAI,IAAI,EAAE,OAAO,aAAa,GAAG;AAAA;AAAA;AACnE;AAGF,IAAM,gBAAgD,CAAC,EAAE,aAAa,MACpE,oBAAC,OAAI,IAAI,EAAE,GAAG,SAAS,IAAI,EAAE,GAC1B,uBAAa,IAAI,CAAC,SAAS,UAC1B;AAAA,EAAC;AAAA;AAAA,IAIC,MAAK;AAAA,IACL,eAAa,oBAAoB,KAAK;AAAA,IACtC,IAAI;AAAA,MACF,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,MACZ,OAAO;AAAA,IACT;AAAA,IAEC;AAAA;AAAA,EAbI,WAAW,KAAK;AAcvB,CACD,GACH;AAeK,IAAM,gBAAwC,CAAC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,YAAY,aAAa,OAAO,OAAO,OAAO,MAAM,MAAM;AAChE,QAAM,QAAQ,eAAe,aAAa,EAAE,OAAO,OAAO,OAAO,MAAM,OAAO,KAAK,CAAC,IAAI;AAExF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAME,qBAAC,OAAI,IAAI,EAAE,UAAU,IAAI,GAAG,eAAa,kBAAkB,UAAU,IACnE;AAAA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,cAAc,eAAe;AAAA,UAC7B,UAAU,eAAe,eAAe;AAAA,UACxC;AAAA,UACA;AAAA;AAAA,MACF;AAAA,MAEA,oBAAC,iBAAc,cAA4B;AAAA,MAE3C;AAAA,QAAC;AAAA;AAAA,UACC,MAAK;AAAA,UACL,mBAAiB,SAAS,UAAU;AAAA,UACpC,eAAY;AAAA,UACZ,IAAI;AAAA,UAEH,iBAAO,MAAM,KAAK,EAAE,IAAI,CAAC,QACxB,oBAAC,mBAA8B,KAAW,GAAG,cAAvB,IAAI,GAA+B,CAC1D;AAAA;AAAA,MACH;AAAA,OACF;AAAA;AAEJ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/utility/InfiniteScroll/InfiniteScroll.hooks.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport type { InfiniteScrollProps } from './InfiniteScroll.types';\n\ntype ScrollableTarget = InfiniteScrollProps['scrollableTarget'];\n\n/** A string target is looked up by id first, then as a selector. */\nconst resolveScrollable = (scrollableTarget: ScrollableTarget): Element | null => {\n if (!scrollableTarget) return null;\n\n if (typeof scrollableTarget === 'string') {\n return (\n document.getElementById(scrollableTarget) || document.querySelector(scrollableTarget)\n );\n }\n\n return scrollableTarget;\n};\n\ninterface ObserverArgs {\n testMode: boolean;\n threshold: number;\n scrollableTarget: ScrollableTarget;\n}\n\n/**\n * Watches a zero-size sentinel at the end of the list. `rootMargin` is what makes\n * it fire before the sentinel is actually on screen, so the next page is already\n * loading by the time the user reaches the bottom.\n */\nexport const useSentinel = ({ testMode, threshold, scrollableTarget }: ObserverArgs) => {\n const sentinelRef = useRef<HTMLDivElement>(null);\n const [isIntersecting, setIsIntersecting] = useState(false);\n\n useEffect(() => {\n if (testMode || !sentinelRef.current) return;\n\n const observer = new window.IntersectionObserver(\n ([entry]) => {\n if (entry) {\n setIsIntersecting(entry.isIntersecting);\n }\n },\n {\n root: resolveScrollable(scrollableTarget) || undefined,\n rootMargin: `${threshold}px`,\n threshold: 0,\n },\n );\n\n observer.observe(sentinelRef.current);\n\n return () => observer.disconnect();\n }, [testMode, threshold, scrollableTarget]);\n\n return { sentinelRef, isIntersecting };\n};\n\ntype LoadArgs = Pick<\n InfiniteScrollProps,\n 'hasMore' | 'loading' | 'error' | 'loadMore' | 'onError' | 'testTriggerRef'\n> & {\n isIntersecting: boolean;\n testMode: boolean;\n};\n\n/**\n * A ref rather than state guards re-entry, so a second intersection landing while\n * the first `loadMore` is still in flight is dropped rather than queued.\n */\nexport const useLoadMore = ({\n hasMore,\n loading,\n error,\n loadMore,\n onError,\n isIntersecting,\n testMode,\n testTriggerRef,\n}: LoadArgs) => {\n const loadingRef = useRef(false);\n\n const handleLoadMore = useCallback(async () => {\n if (loadingRef.current || !hasMore || error) {\n return;\n }\n\n loadingRef.current = true;\n\n try {\n await loadMore();\n } catch (err) {\n const errorObj = err instanceof Error ? err : new Error('Unknown error');\n onError?.(errorObj);\n } finally {\n loadingRef.current = false;\n }\n }, [hasMore, error, loadMore, onError]);\n\n // Expose test trigger for test mode\n useEffect(() => {\n if (testMode && testTriggerRef) {\n testTriggerRef.current = handleLoadMore;\n }\n\n return () => {\n if (testMode && testTriggerRef) {\n testTriggerRef.current = undefined;\n }\n };\n }, [testMode, testTriggerRef, handleLoadMore]);\n\n useEffect(() => {\n if (isIntersecting && hasMore && !loading && !error) {\n handleLoadMore();\n }\n }, [isIntersecting, hasMore, loading, error, handleLoadMore]);\n};\n"],"mappings":";AAAA,SAAS,aAAa,WAAW,QAAQ,gBAAgB;AAOzD,IAAM,oBAAoB,CAAC,qBAAuD;AAChF,MAAI,CAAC,iBAAkB,QAAO;AAE9B,MAAI,OAAO,qBAAqB,UAAU;AACxC,WACE,SAAS,eAAe,gBAAgB,KAAK,SAAS,cAAc,gBAAgB;AAAA,EAExF;AAEA,SAAO;AACT;AAaO,IAAM,cAAc,CAAC,EAAE,UAAU,WAAW,iBAAiB,MAAoB;AACtF,QAAM,cAAc,OAAuB,IAAI;AAC/C,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAAS,KAAK;AAE1D,YAAU,MAAM;AACd,QAAI,YAAY,CAAC,YAAY,QAAS;AAEtC,UAAM,WAAW,IAAI,OAAO;AAAA,MAC1B,CAAC,CAAC,KAAK,MAAM;AACX,YAAI,OAAO;AACT,4BAAkB,MAAM,cAAc;AAAA,QACxC;AAAA,MACF;AAAA,MACA;AAAA,QACE,MAAM,kBAAkB,gBAAgB,KAAK;AAAA,QAC7C,YAAY,GAAG,SAAS;AAAA,QACxB,WAAW;AAAA,MACb;AAAA,IACF;AAEA,aAAS,QAAQ,YAAY,OAAO;AAEpC,WAAO,MAAM,SAAS,WAAW;AAAA,EACnC,GAAG,CAAC,UAAU,WAAW,gBAAgB,CAAC;AAE1C,SAAO,EAAE,aAAa,eAAe;AACvC;AAcO,IAAM,cAAc,CAAC;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAgB;AACd,QAAM,aAAa,OAAO,KAAK;AAE/B,QAAM,iBAAiB,YAAY,YAAY;AAC7C,QAAI,WAAW,WAAW,CAAC,WAAW,OAAO;AAC3C;AAAA,IACF;AAEA,eAAW,UAAU;AAErB,QAAI;AACF,YAAM,SAAS;AAAA,IACjB,SAAS,KAAK;AACZ,YAAM,WAAW,eAAe,QAAQ,MAAM,IAAI,MAAM,eAAe;AACvE,gBAAU,QAAQ;AAAA,IACpB,UAAE;AACA,iBAAW,UAAU;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,SAAS,OAAO,UAAU,OAAO,CAAC;AAGtC,YAAU,MAAM;AACd,QAAI,YAAY,gBAAgB;AAC9B,qBAAe,UAAU;AAAA,IAC3B;AAEA,WAAO,MAAM;AACX,UAAI,YAAY,gBAAgB;AAC9B,uBAAe,UAAU;AAAA,MAC3B;AAAA,IACF;AAAA,EACF,GAAG,CAAC,UAAU,gBAAgB,cAAc,CAAC;AAE7C,YAAU,MAAM;AACd,QAAI,kBAAkB,WAAW,CAAC,WAAW,CAAC,OAAO;AACnD,qBAAe;AAAA,IACjB;AAAA,EACF,GAAG,CAAC,gBAAgB,SAAS,SAAS,OAAO,cAAc,CAAC;AAC9D;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/layout/ScrollArea/ScrollArea.helpers.ts"],"sourcesContent":["import type { ScrollAreaProps } from './ScrollArea.types';\n\ntype ScrollAreaDefaultedKeys =\n | 'width'\n | 'height'\n | 'orientation'\n | 'scrollbarSize'\n | 'autoHide'\n | 'autoHideDelay'\n | 'smoothScroll'\n | 'variant'\n | 'scrollToTopButton'\n | 'scrollToTopThreshold'\n | 'contentPadding'\n | 'alwaysShowScrollbar'\n | 'disabled'\n | 'loading'\n | 'testId';\n\nexport type ResolvedScrollAreaProps = ScrollAreaProps &\n Required<Pick<ScrollAreaProps, ScrollAreaDefaultedKeys>>;\n\nconst SCROLL_AREA_DEFAULTS: Pick<ScrollAreaProps, ScrollAreaDefaultedKeys> = {\n width: '100%',\n height: '100%',\n orientation: 'vertical',\n scrollbarSize: 'medium',\n autoHide: true,\n autoHideDelay: 1000,\n smoothScroll: true,\n variant: 'default',\n scrollToTopButton: false,\n scrollToTopThreshold: 100,\n contentPadding: 0,\n alwaysShowScrollbar: false,\n disabled: false,\n loading: false,\n testId: 'scroll-area',\n};\n\n// Strips explicitly-undefined props before the merge, so `prop={undefined}` still\n// falls back to the default exactly as a destructuring default would. Applied as\n// a merge rather than destructuring defaults, which would otherwise put fifteen\n// branches into the component's own complexity budget.\nexport const resolveScrollAreaProps = (props: ScrollAreaProps): ResolvedScrollAreaProps =>\n ({\n ...SCROLL_AREA_DEFAULTS,\n ...(Object.fromEntries(\n Object.entries(props).filter(([, value]) => value !== undefined),\n ) as Partial<ScrollAreaProps>),\n }) as ResolvedScrollAreaProps;\n"],"mappings":";AAsBA,IAAM,uBAAuE;AAAA,EAC3E,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,eAAe;AAAA,EACf,UAAU;AAAA,EACV,eAAe;AAAA,EACf,cAAc;AAAA,EACd,SAAS;AAAA,EACT,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,qBAAqB;AAAA,EACrB,UAAU;AAAA,EACV,SAAS;AAAA,EACT,QAAQ;AACV;AAMO,IAAM,yBAAyB,CAAC,WACpC;AAAA,EACC,GAAG;AAAA,EACH,GAAI,OAAO;AAAA,IACT,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,EAAE,KAAK,MAAM,UAAU,MAAS;AAAA,EACjE;AACF;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/data-views-overflow.ts"],"sourcesContent":["\"use client\";\n\nimport { useRef } from \"react\";\n\nimport { splitToFit, useMeasuredWidth } from \"../../utility/Overflow\";\nimport {\n estimateWidth,\n furnitureCost,\n GAP,\n isRangeSet,\n pillText,\n RESERVED,\n rightClusterCost,\n} from \"./data-views-overflow-costs\";\nimport type { FilterFieldConfig, RangeFieldConfig, RangeValue } from \"./data-views-types\";\n\n/**\n * PROGRESSIVE COLLAPSE — which filter controls fit on the toolbar, measured.\n *\n * Two rules, and both come from watching the all-or-nothing version fail:\n *\n * 1. Controls shed ONE AT A TIME into an overflow, never all at once. With four\n * filters and room for three, hiding all four throws away the room that was\n * there.\n * 2. An APPLIED filter is ranked first, not exempt. Applied controls take the\n * visible slots ahead of idle ones, and go into \"Mais\" like anything else\n * when even those slots run out. Exempting them outright — the earlier rule\n * — meant four applied filters on a phone claimed more width than the row\n * had, and the bar painted past its own edge: the pills were reachable only\n * by scrolling the toolbar sideways. Hiding one is safe because \"Mais\" says\n * how many applied filters are behind it; scrolling one off-screen says\n * nothing at all.\n *\n * It MEASURES rather than picking a breakpoint, which is what\n * `FILTERS-CONTRACT.md` asks for: pages declare different numbers of filters\n * with different label lengths, and the same page collapses at a different\n * width in another language. A shared breakpoint is wrong for at least one\n * table by construction.\n *\n * Collapsing is presentation only — nothing here emits a query, drops a filter\n * or changes a rendered row.\n */\n\n/** A filter control on the bar: a multi-select pill or a min/max range. */\nexport interface OverflowField<T extends Record<string, unknown>> {\n id: string;\n label: string;\n /** Which control it is — the caller renders the right one. */\n group: \"pill\" | \"range\";\n pill?: FilterFieldConfig<T>;\n range?: RangeFieldConfig<T>;\n}\n\n/** What the caller renders inline, and what goes behind \"Mais\". */\nexport interface OverflowSplit<T extends Record<string, unknown>> {\n inline: OverflowField<T>[];\n overflow: OverflowField<T>[];\n /**\n * Step 2 — Exibir/Exportar drop their text labels and become icons.\n * Cheap: both keep their icon, their tooltip and their position.\n */\n compactControls: boolean;\n /**\n * Step 5, and the LAST resort — the \"N de N\" counter is dropped.\n *\n * Only once every control has already collapsed and the row STILL does not\n * fit, which on a six-filter table is below about 400px. The counter goes\n * last because it is the only thing left that reports rather than does: an\n * operator can act without knowing the total, but not without the search.\n */\n counterHidden: boolean;\n /**\n * Step 4 — the search collapses to a magnifier that expands on click.\n * The most expensive step, so it is taken last: the search is the one\n * control on the bar that cannot be guessed from an icon's position.\n */\n searchCollapsed: boolean;\n /**\n * Step 6, below even the counter — \"Limpar\" leaves the bar.\n *\n * The one control here with a second home: the overflow panel's footer\n * carries \"Limpar todos os filtros\". So it goes before the search icon or\n * \"Mais\", neither of which has anywhere else to be.\n */\n clearAllHidden: boolean;\n /**\n * Expanding the magnifier must take the whole cluster, filters and all.\n *\n * Only on the rungs where what is left over would be too narrow to read —\n * on a large phone the box simply shrinks and the filters stay, which is why\n * this is its own answer rather than `searchCollapsed` reused.\n */\n searchTakeover: boolean;\n /** Attach to the toolbar row being measured. */\n barRef: React.RefObject<HTMLDivElement | null>;\n}\n\n/** Every declared control, pills first, in the order the bar renders them. */\nexport function toOverflowFields<T extends Record<string, unknown>>(\n fields: FilterFieldConfig<T>[],\n rangeFields: RangeFieldConfig<T>[],\n): OverflowField<T>[] {\n return [\n ...fields.map((pill) => ({ id: pill.id, label: pill.label, group: \"pill\" as const, pill })),\n ...rangeFields.map((range) => ({ id: range.id, label: range.label, group: \"range\" as const, range })),\n ];\n}\n\n\n/** Is this control carrying a value the operator set? */\nfunction isActiveField<T extends Record<string, unknown>>(\n field: OverflowField<T>,\n pills: Record<string, string[]>,\n ranges: Record<string, RangeValue>,\n): boolean {\n return field.group === \"pill\"\n ? (pills[field.id]?.length ?? 0) > 0\n : isRangeSet(ranges[field.id]);\n}\n\n/** Estimated rendered width of one control at its CURRENT value. */\nfunction fieldWidth<T extends Record<string, unknown>>(\n field: OverflowField<T>,\n pills: Record<string, string[]>,\n ranges: Record<string, RangeValue>,\n): number {\n if (field.group === \"pill\") return estimateWidth(pillText(field, pills[field.id] ?? []), 0);\n // A bounded range renders two number inputs beside its label.\n return estimateWidth(field.label, isRangeSet(ranges[field.id]) ? 100 : 0);\n}\n\n/** What one split costs on the bar, so the ladder below can price the next step. */\ntype Split<T extends Record<string, unknown>> = {\n inline: OverflowField<T>[];\n overflow: OverflowField<T>[];\n /** Width the surviving inline controls occupy, incl. the \"Mais\" button. */\n used: number;\n};\n\n/** Step 1 — shed filter controls into the overflow. Pure. */\nfunction splitFilters<T extends Record<string, unknown>>(\n all: OverflowField<T>[],\n pills: Record<string, string[]>,\n ranges: Record<string, RangeValue>,\n width: number,\n /** Search + counter + right cluster + chrome, at the rung being considered. */\n furniture: number,\n /** Is the bar already down to icons? \"Mais\" shrinks with everything else. */\n compact: boolean,\n): Split<T> {\n const active = all.filter((field) => isActiveField(field, pills, ranges));\n const idle = all.filter((field) => !isActiveField(field, pills, ranges));\n\n // \"Limpar\" rides the end of the cluster whenever anything is applied.\n const clearCost = active.length > 0 ? RESERVED.clearAll + GAP : 0;\n // APPLIED FIRST, BUT NOT EXEMPT.\n //\n // Applied controls take the visible slots ahead of idle ones — that part was\n // always right. Exempting them from the overflow entirely was not: applying\n // a value LENGTHENS a control (\"Pagamento (1)\"), so on a phone four applied\n // filters claimed more width than the row had and the bar simply painted\n // past its own edge, leaving pills reachable only by scrolling sideways.\n //\n // An applied filter hidden in \"Mais\" is not lost the way it would be if it\n // vanished silently: the trigger goes to the applied tone and says how many\n // are in there (see `MoreTrigger`), which is the same signal the pill itself\n // was carrying. A control you scroll off-screen carries no signal at all.\n //\n // The keep-what-fits loop itself is `splitToFit` (`utility/Overflow`) — the\n // one part of this that is not filter-shaped, and the part a second cluster\n // in the design system would otherwise have had to reimplement.\n const split = splitToFit(all, {\n widthOf: (field) => fieldWidth(field, pills, ranges),\n keyOf: (field) => field.id,\n gap: GAP,\n available: width - furniture - clearCost,\n // The overflow button at the width it will actually have, which on a phone\n // is the icon-and-badge one.\n overflowCost: compact ? RESERVED.overflowButtonCompact : RESERVED.overflowButton,\n priority: [...active, ...idle],\n });\n return { ...split, used: split.used + clearCost };\n}\n\n/**\n * THE DEGRADATION LADDER — cheapest loss first, and each rung taken only if\n * the one before it did not free enough:\n *\n * 1. filter controls move into the \"Mais\" overflow (`splitFilters`)\n * 2. Exibir / Exportar drop their text labels (`compactControls`)\n * 3. the search shrinks toward its minimum (CSS: it is `flex: 1`)\n * 4. the search itself collapses to an icon (`searchCollapsed`)\n *\n * Step 3 needs no flag — the search is a flex child, so it gives up width on\n * its own until it hits `RESERVED.search`. The flags mark the two steps that\n * change what is RENDERED rather than how wide it is.\n *\n * Measured against what is CURRENTLY on the bar, never a breakpoint: a\n * two-filter page and a five-filter page would otherwise collapse at the same\n * width, and only one of them would be right.\n */\nfunction computeSplit<T extends Record<string, unknown>>(\n all: OverflowField<T>[],\n pills: Record<string, string[]>,\n ranges: Record<string, RangeValue>,\n width: number,\n /** Does the host render \"Exportar\" beside \"Exibir\"? Half the cluster if not. */\n hasExport: boolean,\n): Omit<OverflowSplit<T>, \"barRef\"> {\n // Unmeasured (SSR, or jsdom without a ResizeObserver) ⇒ degrade nothing.\n if (width === 0) {\n return {\n inline: all,\n overflow: [],\n compactControls: false,\n counterHidden: false,\n searchCollapsed: false,\n clearAllHidden: false,\n searchTakeover: false,\n };\n }\n // Pass 1 prices the furniture at its widest — no rung has been taken yet.\n let split = splitFilters(all, pills, ranges, width, furnitureCost(UNCOLLAPSED, hasExport), false);\n let flags = ladderFlags(split, width, hasExport);\n // RE-SPEND WHAT THE LATER RUNGS FREED.\n //\n // Rungs 2/4/5 turn 200 + 96 + 216 of furniture into 44 + 0 + 140, and until\n // this loop existed nobody handed those ~330px back to the filters: the\n // split was decided once, against the uncollapsed row, so a phone shed every\n // control and then sat with a band of empty bar beside \"Mais 5\".\n //\n // Settles rather than oscillates, and cannot overfill: a cheaper furniture\n // can only give the filters MORE room, more filter width can only push the\n // ladder FURTHER down, and a further rung can only make the furniture\n // cheaper again — so the budget decreases monotonically and the loop exits\n // the moment it stops moving. The bound is a backstop, not the exit.\n let budget = furnitureCost(UNCOLLAPSED, hasExport);\n for (let pass = 0; pass < 3; pass += 1) {\n const freed = furnitureCost(flags, hasExport);\n if (freed >= budget) break;\n budget = freed;\n split = splitFilters(all, pills, ranges, width, budget, flags.compactControls);\n flags = ladderFlags(split, width, hasExport);\n }\n return { inline: split.inline, overflow: split.overflow, ...flags };\n}\n\n/** The widest the furniture ever is — every rung still untaken. */\nconst UNCOLLAPSED = { searchCollapsed: false, counterHidden: false, compactControls: false };\n\n/** Rungs 2 and 4-6, priced against what the filters actually took. */\nfunction ladderFlags<T extends Record<string, unknown>>(\n split: Split<T>,\n width: number,\n hasExport: boolean,\n): Omit<OverflowSplit<T>, \"barRef\" | \"inline\" | \"overflow\"> {\n const { overflow, used } = split;\n const base = width - used - RESERVED.chrome;\n\n // Would the search still make its minimum with the labels on?\n const compactControls = base - RESERVED.counter - rightClusterCost(hasExport, false) < RESERVED.search;\n const rightCost = rightClusterCost(hasExport, compactControls);\n // …and with them off?\n const searchCollapsed = base - RESERVED.counter - rightCost < RESERVED.search;\n // Everything has collapsed and the row STILL overflows. The controls cannot\n // shrink further — they are `flexShrink: 0` precisely so an over-packed row\n // sheds rather than squeezes — so without this last rung they simply paint\n // outside the toolbar, which is what a narrow phone was doing.\n const counterHidden =\n searchCollapsed && base - RESERVED.counter - rightCost < RESERVED.searchIcon;\n // Step 6 — below even that, \"Limpar\" leaves the bar. It is the ONLY control\n // here with a second home: the overflow panel's footer carries \"Limpar todos\n // os filtros\", so nothing is lost, which is exactly why it goes before the\n // search icon or \"Mais\" (neither of which has anywhere else to be). Guarded\n // on there BEING an overflow, because with no panel the footer does not\n // exist and dropping this would strand the operator.\n const clearAllHidden = counterHidden && overflow.length > 0;\n // What the keyword box would get if the operator expanded the magnifier.\n // `searchCollapsed` is a different question — it asks whether the box fits at\n // its PREFERRED 200px, and is deliberately pessimistic — so reusing it to\n // decide the takeover evicted the filters on screens where the box had plenty\n // of room to simply shrink.\n //\n // Asked with the inline filters SHED, because shedding them is exactly what\n // expanding the box does: the row re-splits and they go behind \"Mais\".\n // Measuring against the resting row instead made a filter argue for its own\n // eviction — now that a large phone keeps one, its width came out of `base`,\n // pushed the box under `usableSearch`, and tipped a row that had ample space\n // to share into a full takeover.\n const overflowButton = compactControls\n ? RESERVED.overflowButtonCompact\n : RESERVED.overflowButton;\n const shedRoom = width - RESERVED.chrome - (overflow.length > 0 ? overflowButton : 0);\n const searchBoxRoom = shedRoom - (counterHidden ? 0 : RESERVED.counter) - rightCost;\n // Below this a box is too narrow to read what you typed into it, and shrinking\n // further buys nothing; that is the only point at which taking the whole\n // cluster is worth losing the filters.\n const searchTakeover = searchCollapsed && searchBoxRoom < RESERVED.usableSearch;\n\n return { compactControls, counterHidden, searchCollapsed, clearAllHidden, searchTakeover };\n}\n\n/**\n * Split the declared filter controls into what fits and what goes behind\n * \"Mais\", measured against the live toolbar width.\n *\n * Cached on a SIGNATURE rather than by `useMemo` over the inputs: hosts declare\n * their fields inline, so `all` is a fresh array on every render while the\n * configuration is unchanged, and a reference-keyed memo would never hit.\n */\nexport function useFilterOverflow<T extends Record<string, unknown>>(\n all: OverflowField<T>[],\n pills: Record<string, string[]>,\n ranges: Record<string, RangeValue>,\n /**\n * A filter control is open — hold the current answer until it closes.\n *\n * Applying a filter changes that control's LABEL (\"Valor\" becomes \"Valor: ≥\n * R$ 1\"), which changes its measured width, which re-runs the whole split\n * while its popover is open on top of it. Measured: setting a minimum moved\n * the trigger 192px left, took the popover with it, and pushed two other\n * controls into a newly-appeared \"Mais 2\" — so reaching for the second bound\n * meant chasing the control across the row. Nobody sets a range that way.\n *\n * Frozen only for the duration: closing re-measures against the new labels,\n * so the row still ends up correct, it just does not rearrange under a hand\n * that is mid-edit.\n */\n frozen = false,\n /** Whether \"Exportar\" is on the bar — see `rightClusterCost`. */\n hasExport = true,\n): OverflowSplit<T> {\n // The measurement is `useMeasuredWidth` (`utility/Overflow`): the same\n // ResizeObserver every collapsing cluster in the design system reads, so\n // there is one loop to get right rather than one per bar. `0` until the\n // first measurement lands (and forever under SSR or jsdom), which\n // `computeSplit` reads as \"degrade nothing\".\n const { ref: barRef, width } = useMeasuredWidth<HTMLDivElement>();\n const signature = JSON.stringify({\n ids: all.map((field) => field.id),\n pills,\n ranges,\n width,\n hasExport,\n });\n const cache = useRef<{ signature: string; split: ReturnType<typeof computeSplit<T>> } | null>(null);\n if (cache.current === null || (!frozen && cache.current.signature !== signature)) {\n cache.current = { signature, split: computeSplit(all, pills, ranges, width, hasExport) };\n }\n return { ...cache.current.split, barRef };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/MapPreview/mapProjection.ts"],"sourcesContent":["export const TILE_SIZE = 256;\n\n// Metres covered by one pixel at zoom 0 on the equator; each zoom level halves it.\nconst EQUATOR_METRES_PER_PIXEL = 156543.03392;\nconst SCALE_BAR_PIXELS = 100;\nconst GEOCODE_DELAY_MS = 300;\n\n// Web Mercator. Longitude maps linearly; latitude goes through the log of the\n// tangent, clamped just short of the poles where that diverges.\nconst project = (lat: number, lng: number) => {\n const siny = Math.sin((lat * Math.PI) / 180);\n const boundedSiny = Math.max(-0.9999, Math.min(0.9999, siny));\n\n return {\n x: TILE_SIZE * (0.5 + lng / 360),\n y: TILE_SIZE * (0.5 - Math.log((1 + boundedSiny) / (1 - boundedSiny)) / (4 * Math.PI)),\n };\n};\n\nexport const getTileCoordinates = (lat: number, lng: number, zoom: number) => {\n const scale = 1 << zoom;\n const world = project(lat, lng);\n\n return {\n x: Math.floor(Math.floor(world.x * scale) / TILE_SIZE),\n y: Math.floor(Math.floor(world.y * scale) / TILE_SIZE),\n };\n};\n\nexport const getScaleDistance = (zoom: number): string => {\n const distance = (EQUATOR_METRES_PER_PIXEL / Math.pow(2, zoom)) * SCALE_BAR_PIXELS;\n\n if (distance >= 1000) return `${Math.round(distance / 1000)} km`;\n // Round to the nearest 100m so the bar reads as a round number.\n if (distance >= 100) return `${Math.round(distance / 100) * 100} m`;\n return `${Math.round(distance)} m`;\n};\n\nconst MOCK_GEOCODE_RESULTS: Record<string, { lat: number; lng: number }> = {\n 'san francisco': { lat: 37.7749, lng: -122.4194 },\n 'new york': { lat: 40.7128, lng: -74.006 },\n london: { lat: 51.5074, lng: -0.1278 },\n tokyo: { lat: 35.6762, lng: 139.6503 },\n paris: { lat: 48.8566, lng: 2.3522 },\n};\n\n// Stands in for a Places lookup, delay included so the disabled search field is\n// actually observable.\nexport const geocode = async (address: string): Promise<{ lat: number; lng: number } | null> => {\n await new Promise((resolve) => window.setTimeout(resolve, GEOCODE_DELAY_MS));\n return MOCK_GEOCODE_RESULTS[address.toLowerCase().trim()] || null;\n};\n"],"mappings":";AAAO,IAAM,YAAY;AAGzB,IAAM,2BAA2B;AACjC,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AAIzB,IAAM,UAAU,CAAC,KAAa,QAAgB;AAC5C,QAAM,OAAO,KAAK,IAAK,MAAM,KAAK,KAAM,GAAG;AAC3C,QAAM,cAAc,KAAK,IAAI,SAAS,KAAK,IAAI,QAAQ,IAAI,CAAC;AAE5D,SAAO;AAAA,IACL,GAAG,aAAa,MAAM,MAAM;AAAA,IAC5B,GAAG,aAAa,MAAM,KAAK,KAAK,IAAI,gBAAgB,IAAI,YAAY,KAAK,IAAI,KAAK;AAAA,EACpF;AACF;AAEO,IAAM,qBAAqB,CAAC,KAAa,KAAa,SAAiB;AAC5E,QAAM,QAAQ,KAAK;AACnB,QAAM,QAAQ,QAAQ,KAAK,GAAG;AAE9B,SAAO;AAAA,IACL,GAAG,KAAK,MAAM,KAAK,MAAM,MAAM,IAAI,KAAK,IAAI,SAAS;AAAA,IACrD,GAAG,KAAK,MAAM,KAAK,MAAM,MAAM,IAAI,KAAK,IAAI,SAAS;AAAA,EACvD;AACF;AAEO,IAAM,mBAAmB,CAAC,SAAyB;AACxD,QAAM,WAAY,2BAA2B,KAAK,IAAI,GAAG,IAAI,IAAK;AAElE,MAAI,YAAY,IAAM,QAAO,GAAG,KAAK,MAAM,WAAW,GAAI,CAAC;AAE3D,MAAI,YAAY,IAAK,QAAO,GAAG,KAAK,MAAM,WAAW,GAAG,IAAI,GAAG;AAC/D,SAAO,GAAG,KAAK,MAAM,QAAQ,CAAC;AAChC;AAEA,IAAM,uBAAqE;AAAA,EACzE,iBAAiB,EAAE,KAAK,SAAS,KAAK,UAAU;AAAA,EAChD,YAAY,EAAE,KAAK,SAAS,KAAK,QAAQ;AAAA,EACzC,QAAQ,EAAE,KAAK,SAAS,KAAK,QAAQ;AAAA,EACrC,OAAO,EAAE,KAAK,SAAS,KAAK,SAAS;AAAA,EACrC,OAAO,EAAE,KAAK,SAAS,KAAK,OAAO;AACrC;AAIO,IAAM,UAAU,OAAO,YAAkE;AAC9F,QAAM,IAAI,QAAQ,CAAC,YAAY,OAAO,WAAW,SAAS,gBAAgB,CAAC;AAC3E,SAAO,qBAAqB,QAAQ,YAAY,EAAE,KAAK,CAAC,KAAK;AAC/D;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Table/TableParts.hooks.tsx","../src/components/data-display/Table/TableParts.tsx"],"sourcesContent":["import type React from 'react';\nimport { useCallback } from 'react';\n\nimport { TableDataRow } from './TableParts';\nimport type { TableBodyProps } from './Table.types';\n\n// Row identity, selection and the row element itself. Split out of\n// EnhancedTableBody so that component is just the virtualised/plain choice.\n// A row's identity: the caller's extractor, else its id, else its position.\nconst useRowKey = (rowKeyExtractor: TableBodyProps['rowKeyExtractor']) =>\n useCallback(\n (rowData: Record<string, unknown>, index: number): string | number =>\n rowKeyExtractor ? rowKeyExtractor(rowData, index) : (rowData.id as string | number) || index,\n [rowKeyExtractor],\n );\n\nconst useRowSelection = ({\n selectedRows,\n onSelectionChange,\n}: {\n selectedRows: Array<string | number>;\n onSelectionChange: TableBodyProps['onSelectionChange'];\n}) =>\n useCallback(\n (event: React.MouseEvent | React.ChangeEvent, rowKey: string | number) => {\n // Stop propagation so selecting does not also fire the row click.\n event.stopPropagation();\n if (!onSelectionChange) return;\n onSelectionChange(rowKey, !selectedRows.includes(rowKey));\n },\n [onSelectionChange, selectedRows],\n );\n\nexport const useTableRowRenderer = ({\n columns,\n selectedRows,\n onRowClick,\n onRowFocus,\n onRowBlur,\n onSelectionChange,\n rowKeyExtractor,\n selectable,\n renderRow,\n renderCell,\n virtualScrolling,\n rowHeight,\n}: Pick<\n TableBodyProps,\n | 'columns'\n | 'onRowClick'\n | 'onRowFocus'\n | 'onRowBlur'\n | 'onSelectionChange'\n | 'rowKeyExtractor'\n | 'selectable'\n | 'renderRow'\n | 'renderCell'\n | 'virtualScrolling'\n | 'rowHeight'\n> & { selectedRows: Array<string | number> }) => {\n const getRowKey = useRowKey(rowKeyExtractor);\n const isRowSelected = useCallback(\n (rowKey: string | number) => selectedRows.includes(rowKey),\n [selectedRows],\n );\n const handleRowSelection = useRowSelection({ selectedRows, onSelectionChange });\n\n const renderTableRow = useCallback(\n (rowData: Record<string, unknown>, index: number, offsetY: number = 0) => {\n const rowKey = getRowKey(rowData, index);\n const selected = isRowSelected(rowKey);\n\n if (renderRow) return renderRow(rowData, index, selected);\n\n return (\n <TableDataRow\n key={rowKey}\n rowData={rowData}\n rowKey={rowKey}\n index={index}\n offsetY={offsetY}\n columns={columns}\n selected={selected}\n selectable={selectable}\n rowHeight={rowHeight}\n onRowClick={onRowClick}\n onRowFocus={onRowFocus}\n onRowBlur={onRowBlur}\n onSelect={handleRowSelection}\n virtualScrolling={virtualScrolling}\n renderCell={renderCell}\n />\n );\n },\n [\n columns,\n getRowKey,\n isRowSelected,\n handleRowSelection,\n onRowClick,\n onRowFocus,\n onRowBlur,\n renderRow,\n renderCell,\n rowHeight,\n selectable,\n virtualScrolling,\n ],\n );\n\n return renderTableRow;\n};\n","import Box from '@mui/material/Box/index.js';\nimport Checkbox from '@mui/material/Checkbox/index.js';\nimport TableBody from '@mui/material/TableBody/index.js';\nimport TableCell from '@mui/material/TableCell/index.js';\nimport TableHead from '@mui/material/TableHead/index.js';\nimport TableRow from '@mui/material/TableRow/index.js';\nimport TableSortLabel from '@mui/material/TableSortLabel/index.js';\nimport React, { useCallback } from 'react';\n\nimport { useVirtualScrolling } from './Table.hooks';\nimport { useTableRowRenderer } from './TableParts.hooks';\nimport type { ColumnConfig, TableBodyProps, TableHeaderProps } from './Table.types';\n\n// Mirrors the visible sort indicator for assistive technology; undefined when\n// the column is not sorted, which is what removes the attribute entirely.\nconst ariaSortFor = (\n canSort: boolean,\n isSorted: boolean,\n direction?: 'asc' | 'desc',\n): 'ascending' | 'descending' | undefined => {\n if (!canSort || !isSorted) return undefined;\n\n return direction === 'asc' ? 'ascending' : 'descending';\n};\n\n// One header cell. Sorting is offered when the table is sortable and the column\n// has not opted out; aria-sort mirrors the visible indicator.\nconst HeaderCell: React.FC<{\n column: ColumnConfig;\n sortable?: boolean;\n sortConfig?: { key: string; direction: 'asc' | 'desc' };\n onSort: (columnKey: string) => void;\n}> = ({ column, sortable, sortConfig, onSort }) => {\n const canSort = Boolean(sortable) && column.sortable !== false;\n const isSorted = sortConfig?.key === column.key;\n\n return (\n <TableCell\n align={column.align || 'left'}\n style={{ minWidth: column.minWidth, width: column.width }}\n aria-sort={ariaSortFor(canSort, isSorted, sortConfig?.direction)}\n >\n {canSort ? (\n <TableSortLabel\n active={isSorted}\n direction={isSorted ? sortConfig?.direction : 'asc'}\n onClick={() => onSort(column.key)}\n data-testid=\"sort-indicator\"\n aria-label={`Sort by ${column.label}`}\n >\n {column.label}\n </TableSortLabel>\n ) : (\n column.label\n )}\n </TableCell>\n );\n};\n\nexport const EnhancedTableHeader: React.FC<TableHeaderProps> = React.memo(({\n columns,\n data,\n sortable,\n sortConfig,\n onSortChange,\n selectable,\n selectedRows = [],\n onSelectAll }) => {\n const handleSort = useCallback(\n (columnKey: string) => {\n if (!sortable || !onSortChange) return;\n \n const direction = \n sortConfig?.key === columnKey && sortConfig.direction === 'asc' ? 'desc' : 'asc';\n onSortChange(columnKey, direction);\n },\n [sortable, onSortChange, sortConfig]\n );\n\n const handleSelectAll = useCallback(\n (event: React.ChangeEvent<globalThis.HTMLInputElement>) => {\n if (!onSelectAll) return;\n onSelectAll(event.target.checked);\n },\n [onSelectAll]\n );\n\n return (\n <TableHead>\n <TableRow>\n {selectable && (\n <TableCell padding=\"checkbox\">\n <Checkbox\n indeterminate={selectedRows.length > 0 && selectedRows.length < data.length}\n checked={selectedRows.length === data.length && data.length > 0}\n onChange={handleSelectAll}\n inputProps={{ 'aria-label': 'select all' }}\n />\n </TableCell>\n )}\n {columns.map((column) => (\n <HeaderCell\n key={column.key}\n column={column}\n sortable={sortable}\n sortConfig={sortConfig}\n onSort={handleSort}\n />\n ))}\n </TableRow>\n </TableHead>\n );\n});\n\nEnhancedTableHeader.displayName = 'EnhancedTableHeader';\n\n// One data row. Split out of the memoised renderTableRow callback so the\n// callback stays a short dispatch and the row markup is readable on its own.\nexport const TableDataRow: React.FC<{\n rowData: Record<string, unknown>;\n rowKey: string | number;\n index: number;\n offsetY: number;\n columns: ColumnConfig[];\n selected: boolean;\n selectable?: boolean;\n rowHeight?: number;\n onRowClick?: TableBodyProps['onRowClick'];\n onRowFocus?: TableBodyProps['onRowFocus'];\n onRowBlur?: TableBodyProps['onRowBlur'];\n onSelect: (event: React.MouseEvent | React.ChangeEvent, rowKey: string | number) => void;\n virtualScrolling?: boolean;\n renderCell?: TableBodyProps['renderCell'];\n}> = ({\n rowData,\n rowKey,\n index,\n offsetY,\n columns,\n selected,\n selectable,\n rowHeight,\n onRowClick,\n onRowFocus,\n onRowBlur,\n onSelect,\n virtualScrolling,\n renderCell }) => (\n\n <TableRow\n key={String(rowKey)}\n selected={selected}\n className={selected ? 'selected' : ''}\n onClick={(event: React.MouseEvent<globalThis.HTMLTableRowElement>) => onRowClick?.(event, rowData)}\n onFocus={(event: React.FocusEvent<globalThis.HTMLTableRowElement>) => onRowFocus?.(event, rowData)}\n onBlur={(event: React.FocusEvent<globalThis.HTMLTableRowElement>) => onRowBlur?.(event, rowData)}\n style={virtualScrolling ? { \n transform: `translateY(${offsetY}px)`,\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n height: rowHeight } : undefined}\n >\n {selectable && (\n <TableCell padding=\"checkbox\">\n <Checkbox\n checked={selected}\n onChange={(event) => onSelect(event, rowKey)}\n onClick={(event) => event.stopPropagation()}\n inputProps={{ 'aria-label': `select row ${index + 1}` }}\n />\n </TableCell>\n )}\n {columns.map((column) => {\n const value = rowData[column.key];\n return (\n <TableCell key={column.key} align={column.align || 'left'}>\n {renderCell \n ? renderCell(value, column, rowData, index)\n : column.render \n ? column.render(value, rowData) \n : (value as React.ReactNode)\n }\n </TableCell>\n );\n })}\n </TableRow>\n);\n\n// Only the rows in view are rendered, positioned by absolute offset inside a\n// spacer sized to the full data set.\nconst VirtualisedBody: React.FC<{\n visibleItems: {\n items: Record<string, unknown>[];\n startIndex: number;\n offsetY: number;\n totalHeight: number;\n };\n rowHeight: number;\n containerHeight: number;\n onScroll: (event: React.UIEvent<HTMLDivElement>) => void;\n renderTableRow: (\n rowData: Record<string, unknown>,\n index: number,\n offsetY?: number,\n ) => React.ReactNode;\n}> = ({ visibleItems, rowHeight, containerHeight, onScroll, renderTableRow }) => (\n\n <Box\n onScroll={onScroll}\n style={{\n height: containerHeight,\n overflow: 'auto',\n position: 'relative' }}\n >\n <TableBody\n style={{\n height: visibleItems.totalHeight,\n position: 'relative' }}\n >\n {visibleItems.items.map((rowData, index) => \n renderTableRow(rowData, visibleItems.startIndex + index, visibleItems.offsetY + index * rowHeight)\n )}\n </TableBody>\n </Box>\n \n);\n\nconst PlainBody: React.FC<{\n data: TableBodyProps['data'];\n renderTableRow: (rowData: Record<string, unknown>, index: number) => React.ReactNode;\n}> = ({ data, renderTableRow }) => (\n\n <TableBody>\n {data.map((rowData, index) => renderTableRow(rowData, index))}\n </TableBody>\n);\n\n// Enhanced Table Body Component \nexport const EnhancedTableBody: React.FC<TableBodyProps> = React.memo(({\n data,\n columns,\n selectedRows = [],\n onRowClick,\n onRowFocus,\n onRowBlur,\n onSelectionChange,\n rowKeyExtractor,\n selectable,\n renderRow,\n renderCell,\n virtualScrolling,\n containerHeight,\n rowHeight,\n overscan = 5 }) => {\n const renderTableRow = useTableRowRenderer({\n columns,\n selectedRows,\n onRowClick,\n onRowFocus,\n onRowBlur,\n onSelectionChange,\n rowKeyExtractor,\n selectable,\n renderRow,\n renderCell,\n virtualScrolling,\n rowHeight });\n\n const { visibleItems, handleScroll } = useVirtualScrolling(\n data, \n rowHeight || 40, \n typeof containerHeight === 'number' ? containerHeight : 400, \n overscan\n );\n\n if (virtualScrolling && containerHeight && rowHeight) {\n return (\n <VirtualisedBody\n visibleItems={visibleItems}\n rowHeight={rowHeight}\n containerHeight={containerHeight}\n onScroll={handleScroll}\n renderTableRow={renderTableRow}\n />\n );\n }\n\n return (\n <PlainBody data={data} renderTableRow={renderTableRow} />\n );\n});\n\nEnhancedTableBody.displayName = 'EnhancedTableBody';\n\n// Main Table Component\n"],"mappings":"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","names":["useCallback","jsx","useCallback"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/form/Calendar/Calendar.tsx"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material/styles/index.js';\nimport Box from '@mui/material/Box/index.js';\nimport Paper from '@mui/material/Paper/index.js';\nimport React from 'react';\n\nimport { resolveCalendarProps } from './Calendar.helpers';\nimport { useCalendar } from './Calendar.hooks';\nimport type { CalendarProps } from './Calendar.types';\nimport type { DayCellContext } from './CalendarDayCell';\nimport { CalendarMonth } from './CalendarMonth';\n\nconst containerSx = (monthsToShow: number): SxProps<Theme> => ({\n p: 3,\n display: 'flex',\n flexDirection: monthsToShow > 1 ? 'row' : 'column',\n gap: 3,\n outline: 'none',\n '&:focus-within': {\n outline: '2px solid',\n outlineColor: 'primary.main',\n outlineOffset: 2,\n },\n});\n\nexport const Calendar = React.forwardRef<HTMLDivElement, CalendarProps>((componentProps, ref) => {\n const props = resolveCalendarProps(componentProps);\n const { monthsToShow, locale, renderHeader, renderFooter, className, ariaLabel } = props;\n\n const calendar = useCalendar(props);\n\n const dayContext: DayCellContext = {\n selectionMode: props.selectionMode,\n value: props.value,\n range: props.range,\n showOutsideDays: props.showOutsideDays,\n renderDay: props.renderDay,\n dayClassName: props.dayClassName,\n hoveredDate: calendar.hoveredDate,\n focusedDate: calendar.focusedDate,\n today: calendar.today,\n isDisabled: calendar.isDisabled,\n onSelect: calendar.handleDateClick,\n onHover: calendar.handleDateMouseEnter,\n onHoverEnd: calendar.handleDateMouseLeave,\n };\n\n return (\n <Paper\n ref={ref}\n className={className}\n role=\"application\"\n aria-label={ariaLabel}\n tabIndex={0}\n onKeyDown={calendar.handleKeyDown}\n data-testid=\"calendar-container\"\n sx={containerSx(monthsToShow)}\n >\n <Box ref={calendar.gridRef} sx={{ display: 'flex', gap: 3, flexWrap: 'wrap' }}>\n {calendar.monthMatrices.map((matrix, index) => (\n <CalendarMonth\n key={`month-${matrix.year}-${matrix.month}`}\n matrix={matrix}\n monthIndex={index}\n monthsToShow={monthsToShow}\n locale={locale}\n weekdayNames={calendar.weekdayNames}\n renderHeader={renderHeader}\n onPreviousMonth={calendar.goToPreviousMonth}\n onNextMonth={calendar.goToNextMonth}\n dayContext={dayContext}\n />\n ))}\n </Box>\n\n {renderFooter && (\n <Box sx={{ mt: 2, pt: 2, borderTop: 1, borderColor: 'divider' }}>{renderFooter}</Box>\n )}\n </Paper>\n );\n});\n\nCalendar.displayName = 'Calendar';\n\nexport default Calendar;\n"],"mappings":";;;;;;;;;;;AACA,OAAO,SAAS;AAChB,OAAO,WAAW;AAClB,OAAO,WAAW;AA4Cd,SAYM,KAZN;AApCJ,IAAM,cAAc,CAAC,kBAA0C;AAAA,EAC7D,GAAG;AAAA,EACH,SAAS;AAAA,EACT,eAAe,eAAe,IAAI,QAAQ;AAAA,EAC1C,KAAK;AAAA,EACL,SAAS;AAAA,EACT,kBAAkB;AAAA,IAChB,SAAS;AAAA,IACT,cAAc;AAAA,IACd,eAAe;AAAA,EACjB;AACF;AAEO,IAAM,WAAW,MAAM,WAA0C,CAAC,gBAAgB,QAAQ;AAC/F,QAAM,QAAQ,qBAAqB,cAAc;AACjD,QAAM,EAAE,cAAc,QAAQ,cAAc,cAAc,WAAW,UAAU,IAAI;AAEnF,QAAM,WAAW,YAAY,KAAK;AAElC,QAAM,aAA6B;AAAA,IACjC,eAAe,MAAM;AAAA,IACrB,OAAO,MAAM;AAAA,IACb,OAAO,MAAM;AAAA,IACb,iBAAiB,MAAM;AAAA,IACvB,WAAW,MAAM;AAAA,IACjB,cAAc,MAAM;AAAA,IACpB,aAAa,SAAS;AAAA,IACtB,aAAa,SAAS;AAAA,IACtB,OAAO,SAAS;AAAA,IAChB,YAAY,SAAS;AAAA,IACrB,UAAU,SAAS;AAAA,IACnB,SAAS,SAAS;AAAA,IAClB,YAAY,SAAS;AAAA,EACvB;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA,MAAK;AAAA,MACL,cAAY;AAAA,MACZ,UAAU;AAAA,MACV,WAAW,SAAS;AAAA,MACpB,eAAY;AAAA,MACZ,IAAI,YAAY,YAAY;AAAA,MAE5B;AAAA,4BAAC,OAAI,KAAK,SAAS,SAAS,IAAI,EAAE,SAAS,QAAQ,KAAK,GAAG,UAAU,OAAO,GACzE,mBAAS,cAAc,IAAI,CAAC,QAAQ,UACnC;AAAA,UAAC;AAAA;AAAA,YAEC;AAAA,YACA,YAAY;AAAA,YACZ;AAAA,YACA;AAAA,YACA,cAAc,SAAS;AAAA,YACvB;AAAA,YACA,iBAAiB,SAAS;AAAA,YAC1B,aAAa,SAAS;AAAA,YACtB;AAAA;AAAA,UATK,SAAS,OAAO,IAAI,IAAI,OAAO,KAAK;AAAA,QAU3C,CACD,GACH;AAAA,QAEC,gBACC,oBAAC,OAAI,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,WAAW,GAAG,aAAa,UAAU,GAAI,wBAAa;AAAA;AAAA;AAAA,EAEnF;AAEJ,CAAC;AAED,SAAS,cAAc;AAEvB,IAAO,mBAAQ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/form/Calendar/CalendarDay.tsx"],"sourcesContent":["import type { SxProps, Theme } from '@mui/material/styles/index.js';\nimport Box from '@mui/material/Box/index.js';\nimport type { FC } from 'react';\nimport React from 'react';\n\nimport type { DayRenderArgs } from './Calendar.types';\n\nconst CELL_SIZE = 40;\n\ninterface DayState extends DayRenderArgs {\n outside: boolean;\n focused: boolean;\n}\n\n// Order matters: these land on the element in the order listed.\nconst CLASS_FLAGS: Array<[keyof DayState, string]> = [\n ['selected', 'selected'],\n ['inRange', 'in-range'],\n ['rangeStart', 'range-start'],\n ['rangeEnd', 'range-end'],\n ['disabled', 'disabled'],\n ['today', 'today'],\n ['outside', 'outside'],\n ['hovered', 'hovered'],\n ['focused', 'focused'],\n];\n\nconst dayClassNames = (state: DayState, custom?: string): string =>\n [\n 'calendar-day',\n ...CLASS_FLAGS.filter(([flag]) => state[flag]).map(([, name]) => name),\n ...(custom ? [custom] : []),\n ].join(' ');\n\nconst isEndpoint = (day: DayRenderArgs): boolean =>\n day.selected || day.rangeStart || day.rangeEnd;\n\nconst backgroundFor = (day: DayRenderArgs): string => {\n if (isEndpoint(day)) return 'primary.main';\n if (day.inRange || day.hovered) return 'primary.light';\n return 'transparent';\n};\n\nconst colorFor = (day: DayRenderArgs, visible: boolean): string => {\n if (isEndpoint(day)) return 'primary.contrastText';\n if (day.disabled) return 'text.disabled';\n // Outside days that are switched off still occupy the grid, they just have\n // nothing to show.\n if (!visible) return 'transparent';\n return 'text.primary';\n};\n\nconst hoverBackgroundFor = (day: DayRenderArgs): string | undefined => {\n if (day.disabled) return undefined;\n return day.selected ? 'primary.dark' : 'action.hover';\n};\n\nconst dayCellSx = (day: DayRenderArgs, visible: boolean): SxProps<Theme> => ({\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n width: CELL_SIZE,\n height: CELL_SIZE,\n border: 'none',\n borderRadius: 1,\n cursor: day.disabled ? 'not-allowed' : 'pointer',\n backgroundColor: backgroundFor(day),\n color: colorFor(day, visible),\n opacity: !day.inCurrentMonth && visible ? 0.5 : 1,\n fontWeight: day.today ? 'bold' : 'normal',\n '&:hover': {\n backgroundColor: hoverBackgroundFor(day),\n },\n '&:focus': {\n outline: '2px solid',\n outlineColor: 'primary.main',\n outlineOffset: 1,\n },\n});\n\nexport interface CalendarDayProps {\n day: DayRenderArgs;\n focused: boolean;\n showOutsideDays: boolean;\n dayClassName?: (args: DayRenderArgs) => string;\n onSelect: (date: Date) => void;\n onHover: (date: Date) => void;\n onHoverEnd: () => void;\n}\n\nexport const CalendarDay: FC<CalendarDayProps> = ({\n day,\n focused,\n showOutsideDays,\n dayClassName,\n onSelect,\n onHover,\n onHoverEnd,\n}) => {\n const visible = day.inCurrentMonth || showOutsideDays;\n const state: DayState = { ...day, outside: !day.inCurrentMonth, focused };\n\n return (\n <Box\n component=\"button\"\n role=\"gridcell\"\n tabIndex={focused ? 0 : -1}\n aria-selected={day.selected}\n aria-disabled={day.disabled}\n aria-current={day.today ? 'date' : undefined}\n className={dayClassNames(state, dayClassName?.(day))}\n data-testid={`calendar-date-${day.date.getDate()}`}\n onClick={() => onSelect(day.date)}\n onMouseEnter={() => onHover(day.date)}\n onMouseLeave={onHoverEnd}\n sx={dayCellSx(day, visible)}\n >\n {day.selected && (\n <Box component=\"span\" data-testid=\"calendar-selected-date\" sx={{ display: 'none' }} />\n )}\n {day.today && (\n <Box component=\"span\" data-testid=\"calendar-today\" sx={{ display: 'none' }} />\n )}\n {visible ? day.date.getDate() : ''}\n </Box>\n );\n};\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataViews/data-views-columns.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo } from \"react\";\n\nimport { type GridColumn } from \"../DataGrid\";\n\nimport {\n buildGridColumns,\n buildRowActionsColumn,\n isActionsColumn,\n} from \"./data-views-grid-helpers\";\nimport type { DataViewColumn, RowAction } from \"./data-views-types\";\n\n/**\n * Every column derivation the DataViews grid needs, in one place: the auto kebab\n * actions column, the id list that seeds a pristine view state, what the grid\n * actually renders once visibility is applied, and the show/hide menu's list.\n */\n\n/** A column the user may show/hide via the toolbar's ColumnsMenu. */\nexport interface HideableColumn {\n id: string;\n label: string;\n}\n\n/**\n * The columns the user may show/hide: explicitly hideable (not `hideable:false`,\n * which marks structural columns like the image thumbnail or actions kebab) and\n * carrying a text header to label the checkbox.\n */\nfunction computeHideableColumns<T extends Record<string, unknown>>(\n columns: DataViewColumn<T>[],\n): HideableColumn[] {\n return columns\n .filter((col) => col.hideable !== false && typeof col.header === \"string\" && col.header !== \"\")\n .map((col) => ({ id: col.id, label: col.header as string }));\n}\n\n/**\n * Append the auto kebab actions column unless the page already defines one. The\n * column is added when there are `rowActions` OR a bespoke `renderRowMenu` (an\n * entity's self-contained menu that owns its own popups).\n */\nfunction appendActionsColumn<T extends Record<string, unknown>>(\n columns: DataViewColumn<T>[],\n opts: {\n rowActions?: RowAction<T>[];\n rowActionsLeading?: (row: T) => React.ReactNode;\n renderRowMenu?: (row: T) => React.ReactNode;\n testIdPrefix: string;\n getRowId: (row: T) => string | number;\n },\n): DataViewColumn<T>[] {\n const { rowActions, rowActionsLeading, renderRowMenu, testIdPrefix, getRowId } = opts;\n if ((!rowActions && !renderRowMenu) || columns.some(isActionsColumn)) return columns;\n return [\n ...columns,\n buildRowActionsColumn({\n rowActions: rowActions ?? [],\n leading: rowActionsLeading,\n testIdPrefix,\n getRowId,\n renderRowMenu,\n }),\n ];\n}\n\n/** Options {@link appendActionsColumn} needs to build the auto kebab column. */\ntype ActionsColumnOpts<T extends Record<string, unknown>> = {\n rowActions?: RowAction<T>[];\n rowActionsLeading?: (row: T) => React.ReactNode;\n renderRowMenu?: (row: T) => React.ReactNode;\n testIdPrefix: string;\n getRowId: (row: T) => string | number;\n};\n\n/**\n * The declared columns plus the auto kebab column (unless the page defines its\n * own), and every column id — which is what seeds a pristine view state's\n * `visibleColumns`, so it is derived BEFORE the state exists.\n */\nexport function useColumnsWithActions<T extends Record<string, unknown>>(\n columns: DataViewColumn<T>[],\n opts: ActionsColumnOpts<T>,\n): { columnsWithActions: DataViewColumn<T>[]; allColumnIds: string[] } {\n const { rowActions, rowActionsLeading, renderRowMenu, testIdPrefix, getRowId } = opts;\n const columnsWithActions = useMemo(\n () =>\n appendActionsColumn(columns, { rowActions, rowActionsLeading, renderRowMenu, testIdPrefix, getRowId }),\n [columns, rowActions, rowActionsLeading, renderRowMenu, testIdPrefix, getRowId],\n );\n const allColumnIds = useMemo(() => columnsWithActions.map((col) => col.id), [columnsWithActions]);\n return { columnsWithActions, allColumnIds };\n}\n\n/**\n * Apply a stored column ORDER, tolerantly.\n *\n * A stored list goes stale in both directions and neither may lose a column: an\n * id the table no longer declares is dropped, and a column the table declares\n * but the list never mentioned (added since the view was saved) falls in AFTER\n * the ordered ones rather than vanishing. Absent order ⇒ declaration order.\n */\nfunction applyOrder<T extends Record<string, unknown>>(\n columns: DataViewColumn<T>[],\n order: string[] | undefined,\n): DataViewColumn<T>[] {\n if (!order || order.length === 0) return columns;\n const byId = new Map(columns.map((column) => [column.id, column]));\n const ordered = order.map((id) => byId.get(id)).filter((c): c is DataViewColumn<T> => Boolean(c));\n const seen = new Set(ordered.map((column) => column.id));\n return [...ordered, ...columns.filter((column) => !seen.has(column.id))];\n}\n\n/** What the grid actually renders: order + visibility applied, plus the menu's list. */\nexport function useRenderedColumns<T extends Record<string, unknown>>(\n columnsWithActions: DataViewColumn<T>[],\n visibleColumns: string[],\n onRowClick: ((row: T) => void) | undefined,\n order?: string[],\n): { gridColumns: GridColumn<T>[]; hideableColumns: HideableColumn[] } {\n const gridColumns = useMemo(\n () => buildGridColumns(applyOrder(columnsWithActions, order), visibleColumns, onRowClick),\n [columnsWithActions, onRowClick, visibleColumns, order],\n );\n const hideableColumns = useMemo(() => computeHideableColumns(columnsWithActions), [columnsWithActions]);\n return { gridColumns, hideableColumns };\n}\n\n"],"mappings":";;;;;;;AAEA,SAAS,eAAe;AA4BxB,SAAS,uBACP,SACkB;AAClB,SAAO,QACJ,OAAO,CAAC,QAAQ,IAAI,aAAa,SAAS,OAAO,IAAI,WAAW,YAAY,IAAI,WAAW,EAAE,EAC7F,IAAI,CAAC,SAAS,EAAE,IAAI,IAAI,IAAI,OAAO,IAAI,OAAiB,EAAE;AAC/D;AAOA,SAAS,oBACP,SACA,MAOqB;AACrB,QAAM,EAAE,YAAY,mBAAmB,eAAe,cAAc,SAAS,IAAI;AACjF,MAAK,CAAC,cAAc,CAAC,iBAAkB,QAAQ,KAAK,eAAe,EAAG,QAAO;AAC7E,SAAO;AAAA,IACL,GAAG;AAAA,IACH,sBAAsB;AAAA,MACpB,YAAY,cAAc,CAAC;AAAA,MAC3B,SAAS;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAgBO,SAAS,sBACd,SACA,MACqE;AACrE,QAAM,EAAE,YAAY,mBAAmB,eAAe,cAAc,SAAS,IAAI;AACjF,QAAM,qBAAqB;AAAA,IACzB,MACE,oBAAoB,SAAS,EAAE,YAAY,mBAAmB,eAAe,cAAc,SAAS,CAAC;AAAA,IACvG,CAAC,SAAS,YAAY,mBAAmB,eAAe,cAAc,QAAQ;AAAA,EAChF;AACA,QAAM,eAAe,QAAQ,MAAM,mBAAmB,IAAI,CAAC,QAAQ,IAAI,EAAE,GAAG,CAAC,kBAAkB,CAAC;AAChG,SAAO,EAAE,oBAAoB,aAAa;AAC5C;AAUA,SAAS,WACP,SACA,OACqB;AACrB,MAAI,CAAC,SAAS,MAAM,WAAW,EAAG,QAAO;AACzC,QAAM,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,CAAC,OAAO,IAAI,MAAM,CAAC,CAAC;AACjE,QAAM,UAAU,MAAM,IAAI,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC,EAAE,OAAO,CAAC,MAA8B,QAAQ,CAAC,CAAC;AAChG,QAAM,OAAO,IAAI,IAAI,QAAQ,IAAI,CAAC,WAAW,OAAO,EAAE,CAAC;AACvD,SAAO,CAAC,GAAG,SAAS,GAAG,QAAQ,OAAO,CAAC,WAAW,CAAC,KAAK,IAAI,OAAO,EAAE,CAAC,CAAC;AACzE;AAGO,SAAS,mBACd,oBACA,gBACA,YACA,OACqE;AACrE,QAAM,cAAc;AAAA,IAClB,MAAM,iBAAiB,WAAW,oBAAoB,KAAK,GAAG,gBAAgB,UAAU;AAAA,IACxF,CAAC,oBAAoB,YAAY,gBAAgB,KAAK;AAAA,EACxD;AACA,QAAM,kBAAkB,QAAQ,MAAM,uBAAuB,kBAAkB,GAAG,CAAC,kBAAkB,CAAC;AACtG,SAAO,EAAE,aAAa,gBAAgB;AACxC;","names":[]}