@12-apps/ui 6.42.0 → 6.43.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (396) hide show
  1. package/dist/_internal/components/data-display/Alert/Alert.js +3 -3
  2. package/dist/_internal/components/data-display/Alert/Alert.metrics.js +3 -3
  3. package/dist/_internal/components/data-display/Alert/Alert.styles.js +3 -3
  4. package/dist/_internal/components/data-display/Badge/Badge.js +4 -4
  5. package/dist/_internal/components/data-display/Badge/Badge.styles.js +4 -4
  6. package/dist/_internal/components/data-display/Badge/BadgeContent.js +4 -4
  7. package/dist/_internal/components/data-display/Banner/Banner.js +3 -3
  8. package/dist/_internal/components/data-display/Banner/Banner.styles.js +3 -3
  9. package/dist/_internal/components/data-display/CardKit/CardKebab.js +3 -3
  10. package/dist/_internal/components/data-display/CardKit/card-actions-context.js +3 -3
  11. package/dist/_internal/components/data-display/CardKit/use-remove-confirm.js +3 -3
  12. package/dist/_internal/components/data-display/CardKit/use-row-confirm.js +3 -3
  13. package/dist/_internal/components/data-display/Carousel/Carousel.chrome.js +4 -4
  14. package/dist/_internal/components/data-display/Carousel/Carousel.js +4 -4
  15. package/dist/_internal/components/data-display/Carousel/Carousel.parts.js +4 -4
  16. package/dist/_internal/components/data-display/Carousel/Carousel.styles.js +4 -4
  17. package/dist/_internal/components/data-display/Chart/Chart.js +4 -4
  18. package/dist/_internal/components/data-display/Chart/SpecChart.js +4 -4
  19. package/dist/_internal/components/data-display/Chart/chart-context.js +4 -4
  20. package/dist/_internal/components/data-display/Chart/chart-internals.js +4 -4
  21. package/dist/_internal/components/data-display/Chart/chart-renderers.js +4 -4
  22. package/dist/_internal/components/data-display/DataGrid/DataGrid.js +11 -2
  23. package/dist/_internal/components/data-display/DataGrid/DataGrid.model.js +12 -1
  24. package/dist/_internal/components/data-display/DataViews/DataViewsBoard.js +6 -6
  25. package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +28 -27
  26. package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +34 -33
  27. package/dist/_internal/components/data-display/DataViews/DeleteViewDialog.js +6 -6
  28. package/dist/_internal/components/data-display/DataViews/ManageViewsDialog.js +6 -6
  29. package/dist/_internal/components/data-display/DataViews/SaveViewModal.js +7 -7
  30. package/dist/_internal/components/data-display/DataViews/base-card.js +6 -6
  31. package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +15 -10
  32. package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +14 -9
  33. package/dist/_internal/components/data-display/DataViews/base-list-card.js +16 -11
  34. package/dist/_internal/components/data-display/DataViews/data-views-bar-controls.js +1 -1
  35. package/dist/_internal/components/data-display/DataViews/data-views-category-pill.js +1 -1
  36. package/dist/_internal/components/data-display/DataViews/data-views-columns-tab.js +6 -6
  37. package/dist/_internal/components/data-display/DataViews/data-views-columns.js +3 -3
  38. package/dist/_internal/components/data-display/DataViews/data-views-day-input.js +1 -1
  39. package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +11 -10
  40. package/dist/_internal/components/data-display/DataViews/data-views-display-tabs.js +12 -7
  41. package/dist/_internal/components/data-display/DataViews/data-views-empty.js +6 -6
  42. package/dist/_internal/components/data-display/DataViews/data-views-export.js +6 -6
  43. package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +1 -1
  44. package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +13 -12
  45. package/dist/_internal/components/data-display/DataViews/data-views-grid-helpers.js +3 -3
  46. package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +27 -26
  47. package/dist/_internal/components/data-display/DataViews/data-views-header-row.js +6 -6
  48. package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +8 -8
  49. package/dist/_internal/components/data-display/DataViews/data-views-layout-context.js +11 -1
  50. package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +6 -6
  51. package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +7 -7
  52. package/dist/_internal/components/data-display/DataViews/data-views-number-input.js +1 -1
  53. package/dist/_internal/components/data-display/DataViews/data-views-pagination.js +1 -1
  54. package/dist/_internal/components/data-display/DataViews/data-views-range-pill.js +1 -1
  55. package/dist/_internal/components/data-display/DataViews/data-views-scope-tabs.js +10 -2
  56. package/dist/_internal/components/data-display/DataViews/data-views-search.js +1 -1
  57. package/dist/_internal/components/data-display/DataViews/data-views-select-all-strip.js +6 -6
  58. package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +14 -13
  59. package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +9 -9
  60. package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +13 -12
  61. package/dist/_internal/components/data-display/DataViews/data-views-view-nav.js +6 -6
  62. package/dist/_internal/components/data-display/DataViews/list-card-rails.js +10 -2
  63. package/dist/_internal/components/data-display/DataViews/save-view-preview.js +6 -6
  64. package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +3 -3
  65. package/dist/_internal/components/data-display/DescriptionItem/DescriptionItem.js +6 -6
  66. package/dist/_internal/components/data-display/FleetMap/FleetBody.js +1 -1
  67. package/dist/_internal/components/data-display/FleetMap/FleetCanvas.js +1 -1
  68. package/dist/_internal/components/data-display/FleetMap/FleetMap.js +4 -4
  69. package/dist/_internal/components/data-display/MapPreview/MapLayers.js +1 -1
  70. package/dist/_internal/components/data-display/MapPreview/MapPreview.js +1 -1
  71. package/dist/_internal/components/data-display/MapPreview/MapSearchBar.js +1 -1
  72. package/dist/_internal/components/data-display/Progress/Progress.js +6 -6
  73. package/dist/_internal/components/data-display/Progress/Progress.metrics.js +4 -4
  74. package/dist/_internal/components/data-display/Progress/Progress.styles.js +5 -5
  75. package/dist/_internal/components/data-display/Sheet/Sheet.body.js +4 -4
  76. package/dist/_internal/components/data-display/Sheet/Sheet.js +4 -4
  77. package/dist/_internal/components/data-display/Sheet/Sheet.styles.js +4 -4
  78. package/dist/_internal/components/data-display/Table/Table.helpers.js +3 -1
  79. package/dist/_internal/components/data-display/Table/Table.js +11 -3
  80. package/dist/_internal/components/data-display/Table/TableParts.hooks.js +2 -2
  81. package/dist/_internal/components/data-display/Table/TableParts.js +2 -2
  82. package/dist/_internal/components/data-display/index.js +15 -15
  83. package/dist/_internal/components/feedback/ConfirmAction/ConfirmButton.js +3 -3
  84. package/dist/_internal/components/feedback/NotificationStatusNotice/NotificationStatusNotice.js +3 -3
  85. package/dist/_internal/components/feedback/index.js +3 -3
  86. package/dist/_internal/components/form/AddressAutocomplete/AddressAutocomplete.js +1 -1
  87. package/dist/_internal/components/form/AddressAutocomplete/AddressAutocompleteField.js +1 -1
  88. package/dist/_internal/components/form/AddressAutocomplete/AddressFallbackField.js +1 -1
  89. package/dist/_internal/components/form/AddressAutocomplete/AddressInputField.js +1 -1
  90. package/dist/_internal/components/form/AddressAutocomplete/AddressTextField.js +1 -1
  91. package/dist/_internal/components/form/Autocomplete/Autocomplete.js +1 -1
  92. package/dist/_internal/components/form/Autocomplete/Autocomplete.parts.js +1 -1
  93. package/dist/_internal/components/form/Button/Button.js +3 -3
  94. package/dist/_internal/components/form/Button/Button.styles.js +3 -3
  95. package/dist/_internal/components/form/CategorySelect/CategoryPanel.js +1 -1
  96. package/dist/_internal/components/form/CategorySelect/CategoryPanelFoot.js +1 -1
  97. package/dist/_internal/components/form/CategorySelect/CategoryPanelHead.js +1 -1
  98. package/dist/_internal/components/form/CategorySelect/CategoryPanelList.js +1 -1
  99. package/dist/_internal/components/form/CategorySelect/CategoryRows.js +1 -1
  100. package/dist/_internal/components/form/CategorySelect/CategorySelect.js +1 -1
  101. package/dist/_internal/components/form/CategorySelect/CategorySelect.styles.js +1 -1
  102. package/dist/_internal/components/form/CategorySelect/CategoryTrigger.js +1 -1
  103. package/dist/_internal/components/form/CepField/CepField.js +1 -1
  104. package/dist/_internal/components/form/Command/Command.js +4 -4
  105. package/dist/_internal/components/form/Command/Command.styles.js +4 -4
  106. package/dist/_internal/components/form/CreatableSelect/CreatableSelect.js +1 -1
  107. package/dist/_internal/components/form/DateRangePicker/DateRangePicker.hooks.js +1 -1
  108. package/dist/_internal/components/form/DateRangePicker/DateRangePicker.js +1 -1
  109. package/dist/_internal/components/form/DateRangePicker/DateRangePicker.range.js +1 -1
  110. package/dist/_internal/components/form/DateRangePicker/DateRangePickerFields.js +1 -1
  111. package/dist/_internal/components/form/Input/Input.js +1 -1
  112. package/dist/_internal/components/form/Input/Input.styles.js +1 -1
  113. package/dist/_internal/components/form/InputOTP/InputOTP.js +1 -1
  114. package/dist/_internal/components/form/InputOTP/InputOTP.styles.js +1 -1
  115. package/dist/_internal/components/form/Label/Label.js +4 -4
  116. package/dist/_internal/components/form/Label/Label.styles.js +4 -4
  117. package/dist/_internal/components/form/Menubar/Menubar.item.js +4 -4
  118. package/dist/_internal/components/form/Menubar/Menubar.js +4 -4
  119. package/dist/_internal/components/form/Menubar/Menubar.styles.js +4 -4
  120. package/dist/_internal/components/form/Menubar/Menubar.toolbar.js +4 -4
  121. package/dist/_internal/components/form/NumberField/NumberField.js +1 -1
  122. package/dist/_internal/components/form/PhoneInput/PhoneInput.js +1 -1
  123. package/dist/_internal/components/form/RadioGroup/RadioGroup.js +1 -1
  124. package/dist/_internal/components/form/RadioGroup/RadioGroup.styles.js +1 -1
  125. package/dist/_internal/components/form/RadioGroup/RadioGroup.variants.js +1 -1
  126. package/dist/_internal/components/form/Select/Select.js +1 -1
  127. package/dist/_internal/components/form/Switch/Switch.js +3 -3
  128. package/dist/_internal/components/form/Switch/Switch.parts.js +3 -3
  129. package/dist/_internal/components/form/Switch/Switch.styles.js +3 -3
  130. package/dist/_internal/components/form/Textarea/Textarea.js +2 -2
  131. package/dist/_internal/components/form/Textarea/TextareaRichEditor.js +1 -1
  132. package/dist/_internal/components/form/Toggle/Toggle.js +1 -1
  133. package/dist/_internal/components/form/Toggle/Toggle.styles.js +1 -1
  134. package/dist/_internal/components/form/ToggleGroup/ToggleGroup.js +1 -1
  135. package/dist/_internal/components/form/index.js +5 -5
  136. package/dist/_internal/components/form/total-form/Fields/CategoryField.js +1 -1
  137. package/dist/_internal/components/form/total-form/Fields/CepField.js +1 -1
  138. package/dist/_internal/components/form/total-form/Fields/SelectField.js +1 -1
  139. package/dist/_internal/components/form/total-form/Fields/TextField.js +1 -1
  140. package/dist/_internal/components/form/total-form/Fields/ToggleField.js +1 -1
  141. package/dist/_internal/components/form/total-form/Fields/index.js +1 -1
  142. package/dist/_internal/components/form/total-form/SubmitButton.js +3 -3
  143. package/dist/_internal/components/index.js +28 -28
  144. package/dist/_internal/components/layout/Box/Box.js +7 -7
  145. package/dist/_internal/components/layout/ContentToolbar/ColumnsMenu.js +1 -1
  146. package/dist/_internal/components/layout/ContentToolbar/FilterTrigger.js +1 -1
  147. package/dist/_internal/components/layout/ContentToolbar/MultiSelectDropdown.js +1 -1
  148. package/dist/_internal/components/layout/ContentToolbar/MultiSelectTriggers.js +1 -1
  149. package/dist/_internal/components/layout/ContentToolbar/SavedViewsMenu.js +1 -1
  150. package/dist/_internal/components/layout/ContentToolbar/SortByDropdown.js +1 -1
  151. package/dist/_internal/components/layout/ContentToolbar/ViewSelector.js +1 -1
  152. package/dist/_internal/components/layout/SettingCard/SettingCard.js +9 -9
  153. package/dist/_internal/components/layout/SettingCard/SettingCard.parts.js +8 -8
  154. package/dist/_internal/components/layout/SettingCard/SettingGrid.js +9 -9
  155. package/dist/_internal/components/layout/SettingCard/SettingGroup.js +10 -10
  156. package/dist/_internal/components/layout/SettingCard/SettingSwitch.js +9 -9
  157. package/dist/_internal/components/layout/SettingCard/SettingToggle.js +10 -10
  158. package/dist/_internal/components/layout/SettingsLayout/SettingsLayout.js +4 -4
  159. package/dist/_internal/components/layout/SettingsLayout/SettingsPanel.js +3 -3
  160. package/dist/_internal/components/layout/SettingsLayout/SettingsSectionChips.js +2 -2
  161. package/dist/_internal/components/layout/SettingsLayout/SettingsSectionChips.scroll.js +1 -1
  162. package/dist/_internal/components/layout/Stack/Stack.js +8 -8
  163. package/dist/_internal/components/layout/TableFilter/TableFilter.js +1 -1
  164. package/dist/_internal/components/layout/index.js +13 -13
  165. package/dist/_internal/components/navigation/AppHeader/AppHeader.details.js +4 -4
  166. package/dist/_internal/components/navigation/AppHeader/AppHeader.identity.js +4 -4
  167. package/dist/_internal/components/navigation/Pagination/Pagination.js +1 -1
  168. package/dist/_internal/components/navigation/Pagination/PaginationParts.js +1 -1
  169. package/dist/_internal/components/navigation/Tabs/Tabs.js +1 -1
  170. package/dist/_internal/components/navigation/Tabs/Tabs.styles.js +1 -1
  171. package/dist/_internal/components/navigation/index.js +4 -4
  172. package/dist/_internal/components/typography/Heading/Heading.js +6 -6
  173. package/dist/_internal/components/typography/Heading/Heading.metrics.js +4 -4
  174. package/dist/_internal/components/typography/Heading/Heading.styles.js +5 -5
  175. package/dist/_internal/components/typography/Text/Text.js +5 -5
  176. package/dist/_internal/components/typography/Text/Text.metrics.js +4 -4
  177. package/dist/_internal/components/typography/index.js +8 -8
  178. package/dist/_internal/components/utility/WorkflowStep/WorkflowStep.helpers.js +4 -4
  179. package/dist/_internal/components/utility/WorkflowStep/WorkflowStep.js +4 -4
  180. package/dist/_internal/components/utility/WorkflowStep/WorkflowStep.parts.js +4 -4
  181. package/dist/_internal/components/utility/WorkflowStep/WorkflowStepRow.js +4 -4
  182. package/dist/_internal/components/utility/index.js +4 -4
  183. package/dist/_internal/icons/Icon.js +7 -7
  184. package/dist/_internal/provider/UiProvider.js +6 -6
  185. package/dist/_internal/provider/mui-bridge.js +5 -5
  186. package/dist/_internal/provider/use-ui-theme.js +6 -6
  187. package/dist/_internal/social-login-button/social-login-button.js +9 -9
  188. package/dist/_internal/tokens/density.js +1 -1
  189. package/dist/_internal/tokens/field-height.js +1 -1
  190. package/dist/_internal/tokens/theme.js +3 -3
  191. package/dist/_internal/user-avatar/user-avatar.js +6 -6
  192. package/dist/charts.js +4 -4
  193. package/dist/{chunk-YPIVLPXF.js → chunk-33NBMNTB.js} +2 -2
  194. package/dist/{chunk-JE6GQB5J.js → chunk-4Z2HIHA5.js} +4 -4
  195. package/dist/{chunk-FHW3ATT7.js → chunk-53HQNN3C.js} +2 -2
  196. package/dist/{chunk-53O2TNSR.js → chunk-5DAVXZPY.js} +3 -3
  197. package/dist/{chunk-DH5UJD2I.js → chunk-5FHPZOYK.js} +2 -2
  198. package/dist/{chunk-NSVSC6ZC.js → chunk-5PJM772Y.js} +4 -4
  199. package/dist/{chunk-VYM2GPR6.js → chunk-5PTCT3LF.js} +2 -2
  200. package/dist/{chunk-ZH2SZ6B3.js → chunk-652PYSML.js} +6 -6
  201. package/dist/{chunk-PEOOCQ2T.js → chunk-6IRJAIS4.js} +2 -2
  202. package/dist/{chunk-PAT2BQOQ.js → chunk-6IWO7CM2.js} +2 -2
  203. package/dist/{chunk-YFODI4KT.js → chunk-6WZUZHJM.js} +8 -8
  204. package/dist/{chunk-KCDNOMMT.js → chunk-6Z6PUG4C.js} +9 -3
  205. package/dist/chunk-6Z6PUG4C.js.map +1 -0
  206. package/dist/{chunk-QEI5DC6S.js → chunk-7KJOODQB.js} +1 -1
  207. package/dist/{chunk-6ZD3FI5P.js → chunk-AOFI3GDS.js} +4 -4
  208. package/dist/{chunk-H72YKEGD.js → chunk-AOKLEE64.js} +2 -2
  209. package/dist/{chunk-RDFPM2AQ.js → chunk-BJGUDLWZ.js} +4 -4
  210. package/dist/{chunk-TBMGYQJF.js → chunk-BKBELIUR.js} +2 -2
  211. package/dist/{chunk-X66E5WSX.js → chunk-C4QKXFZN.js} +3 -3
  212. package/dist/{chunk-OJUORFGO.js → chunk-C6JUGWAU.js} +4 -4
  213. package/dist/{chunk-DLWLIPCP.js → chunk-CKFZQQ6T.js} +2 -2
  214. package/dist/{chunk-Z2NN53E5.js → chunk-DCT2PKMQ.js} +2 -2
  215. package/dist/{chunk-JMEPGXJG.js → chunk-DHW5UMUG.js} +2 -2
  216. package/dist/{chunk-G6ZPQHBL.js → chunk-DSHM7VN6.js} +2 -2
  217. package/dist/{chunk-WV62BSWA.js → chunk-F5BYZNXY.js} +2 -2
  218. package/dist/{chunk-RDZGXJOD.js → chunk-F5GXWK6B.js} +2 -2
  219. package/dist/{chunk-4Z7GEO2R.js → chunk-G7RYAWPZ.js} +2 -2
  220. package/dist/{chunk-4S2LWZ7L.js → chunk-GO6XDMBB.js} +2 -2
  221. package/dist/{chunk-KHOAXZW2.js → chunk-H3GYVR7S.js} +3 -3
  222. package/dist/{chunk-XZJM6EPC.js → chunk-HUAQQ5ZL.js} +12 -2
  223. package/dist/chunk-HUAQQ5ZL.js.map +1 -0
  224. package/dist/{chunk-C6OVO6AT.js → chunk-I6MVJWUO.js} +2 -2
  225. package/dist/{chunk-4XHVGUOM.js → chunk-J2SFOLGZ.js} +2 -2
  226. package/dist/{chunk-7TE4TMS3.js → chunk-JSOJKHEI.js} +3 -3
  227. package/dist/{chunk-ZNBLGS66.js → chunk-K62RHTFB.js} +3 -3
  228. package/dist/{chunk-6N2EDWMG.js → chunk-KWU62UPM.js} +2 -2
  229. package/dist/{chunk-NHEWST3N.js → chunk-L3MRRAZM.js} +3 -2
  230. package/dist/chunk-L3MRRAZM.js.map +1 -0
  231. package/dist/{chunk-CJ45OL7L.js → chunk-M2GVHVE4.js} +2 -2
  232. package/dist/{chunk-BX7QWHKC.js → chunk-MBNXCCRG.js} +4 -4
  233. package/dist/{chunk-ZSTUKSTJ.js → chunk-MLUUF7OZ.js} +2 -2
  234. package/dist/{chunk-KW3H5FUS.js → chunk-MPYIEIBA.js} +2 -2
  235. package/dist/{chunk-DFI2RKVQ.js → chunk-MRWYKNBY.js} +2 -2
  236. package/dist/{chunk-AP4LSXRK.js → chunk-NYT3UVOH.js} +8 -8
  237. package/dist/{chunk-YWJDUJAR.js → chunk-O6IF4BZT.js} +2 -2
  238. package/dist/{chunk-3UEZ6NUI.js → chunk-OCQ6GDCF.js} +2 -2
  239. package/dist/{chunk-JAGAFEZL.js → chunk-OD3L6GX5.js} +2 -2
  240. package/dist/{chunk-RPBGUWNF.js → chunk-ON4TRXCM.js} +3 -3
  241. package/dist/{chunk-NOLSQK4J.js → chunk-PGV2FLE3.js} +2 -2
  242. package/dist/{chunk-GT2RCOHM.js → chunk-QLAFJZDS.js} +31 -13
  243. package/dist/chunk-QLAFJZDS.js.map +1 -0
  244. package/dist/{chunk-C2TERIB4.js → chunk-QSNLIWEB.js} +2 -2
  245. package/dist/{chunk-XZY7O7JJ.js → chunk-RHKT2XW2.js} +2 -2
  246. package/dist/{chunk-TDXEO2UI.js → chunk-RJ35IXFD.js} +2 -2
  247. package/dist/{chunk-4SHMSLFA.js → chunk-RRG75JJS.js} +2 -2
  248. package/dist/{chunk-6MD5QXXJ.js → chunk-RWRPF24F.js} +4 -4
  249. package/dist/{chunk-VPAOVEI2.js → chunk-SJGYMI6Y.js} +3 -3
  250. package/dist/{chunk-EQXIW5MQ.js → chunk-TCMH3FXD.js} +2 -2
  251. package/dist/{chunk-STTULW2K.js → chunk-TE3XYCX7.js} +2 -2
  252. package/dist/{chunk-TJ3334AJ.js → chunk-TMW7RBW7.js} +3 -3
  253. package/dist/{chunk-DGMDQHMI.js → chunk-U6DOF5CR.js} +14 -2
  254. package/dist/chunk-U6DOF5CR.js.map +1 -0
  255. package/dist/{chunk-3GYPZ5MI.js → chunk-UP7SSTCZ.js} +6 -6
  256. package/dist/{chunk-IWGW2E35.js → chunk-WF4XK5AS.js} +2 -2
  257. package/dist/{chunk-6REPQ352.js → chunk-WL7IG7TT.js} +2 -2
  258. package/dist/{chunk-U67ZQ6VM.js → chunk-YIWVHEPW.js} +2 -2
  259. package/dist/{chunk-DH77PLFF.js → chunk-YTVXT5TD.js} +2 -2
  260. package/dist/{chunk-MKLIMY3D.js → chunk-YZHX2HTC.js} +2 -2
  261. package/dist/{chunk-SQNQQTP7.js → chunk-Z6LTEJ7F.js} +7 -5
  262. package/dist/chunk-Z6LTEJ7F.js.map +1 -0
  263. package/dist/data-display/Alert.js +3 -3
  264. package/dist/data-display/Badge.js +4 -4
  265. package/dist/data-display/Banner.js +3 -3
  266. package/dist/data-display/CardKit.js +3 -3
  267. package/dist/data-display/Carousel.js +4 -4
  268. package/dist/data-display/Chart.js +4 -4
  269. package/dist/data-display/DataGrid.js +11 -2
  270. package/dist/data-display/DataViews.js +39 -38
  271. package/dist/data-display/DescriptionItem.js +6 -6
  272. package/dist/data-display/FleetMap.js +4 -4
  273. package/dist/data-display/MapPreview.js +1 -1
  274. package/dist/data-display/Progress.js +6 -6
  275. package/dist/data-display/Sheet.js +4 -4
  276. package/dist/data-display/Table.js +11 -3
  277. package/dist/feedback/ConfirmAction.js +3 -3
  278. package/dist/feedback/NotificationStatusNotice.js +3 -3
  279. package/dist/form/AddressAutocomplete.js +1 -1
  280. package/dist/form/Autocomplete.js +1 -1
  281. package/dist/form/Button.js +3 -3
  282. package/dist/form/CategorySelect.js +1 -1
  283. package/dist/form/CepField.js +1 -1
  284. package/dist/form/Command.js +4 -4
  285. package/dist/form/CreatableSelect.js +1 -1
  286. package/dist/form/DateRangePicker.js +1 -1
  287. package/dist/form/Input.js +1 -1
  288. package/dist/form/InputOTP.js +1 -1
  289. package/dist/form/Label.js +4 -4
  290. package/dist/form/Menubar.js +4 -4
  291. package/dist/form/NumberField.js +1 -1
  292. package/dist/form/PhoneInput.js +1 -1
  293. package/dist/form/RadioGroup.js +1 -1
  294. package/dist/form/Select.js +1 -1
  295. package/dist/form/Switch.js +3 -3
  296. package/dist/form/Textarea.js +2 -2
  297. package/dist/form/Toggle.js +1 -1
  298. package/dist/form/ToggleGroup.js +1 -1
  299. package/dist/form/total-form.js +3 -3
  300. package/dist/icons.js +7 -7
  301. package/dist/layout/Box.js +7 -7
  302. package/dist/layout/ContentToolbar.js +1 -1
  303. package/dist/layout/SettingCard.js +13 -13
  304. package/dist/layout/SettingsLayout.js +4 -4
  305. package/dist/layout/Stack.js +8 -8
  306. package/dist/layout/TableFilter.js +1 -1
  307. package/dist/navigation/AppHeader.js +4 -4
  308. package/dist/navigation/Pagination.js +1 -1
  309. package/dist/navigation/Tabs.js +1 -1
  310. package/dist/provider.js +7 -7
  311. package/dist/social-login-button.js +9 -9
  312. package/dist/tokens.js +15 -15
  313. package/dist/types/components/data-display/DataGrid/DataGrid.d.ts.map +1 -1
  314. package/dist/types/components/data-display/DataGrid/DataGrid.model.d.ts +19 -1
  315. package/dist/types/components/data-display/DataGrid/DataGrid.model.d.ts.map +1 -1
  316. package/dist/types/components/data-display/DataViews/data-views-layout-context.d.ts +12 -0
  317. package/dist/types/components/data-display/DataViews/data-views-layout-context.d.ts.map +1 -1
  318. package/dist/types/components/data-display/Table/Table.d.ts.map +1 -1
  319. package/dist/types/components/data-display/Table/Table.helpers.d.ts +10 -1
  320. package/dist/types/components/data-display/Table/Table.helpers.d.ts.map +1 -1
  321. package/dist/types/components/layout/SettingsLayout/SettingsSectionChips.scroll.d.ts.map +1 -1
  322. package/dist/typography/Heading.js +6 -6
  323. package/dist/typography/Text.js +5 -5
  324. package/dist/user-avatar.js +6 -6
  325. package/dist/utility/WorkflowStep.js +4 -4
  326. package/package.json +1 -1
  327. package/src/components/data-display/DataGrid/DataGrid.model.ts +30 -1
  328. package/src/components/data-display/DataGrid/DataGrid.tsx +9 -4
  329. package/src/components/data-display/DataViews/data-views-layout-context.tsx +24 -1
  330. package/src/components/data-display/Table/Table.helpers.ts +20 -2
  331. package/src/components/data-display/Table/Table.tsx +5 -2
  332. package/src/components/layout/SettingsLayout/SettingsSectionChips.scroll.ts +52 -16
  333. package/dist/chunk-DGMDQHMI.js.map +0 -1
  334. package/dist/chunk-GT2RCOHM.js.map +0 -1
  335. package/dist/chunk-KCDNOMMT.js.map +0 -1
  336. package/dist/chunk-NHEWST3N.js.map +0 -1
  337. package/dist/chunk-SQNQQTP7.js.map +0 -1
  338. package/dist/chunk-XZJM6EPC.js.map +0 -1
  339. /package/dist/{chunk-YPIVLPXF.js.map → chunk-33NBMNTB.js.map} +0 -0
  340. /package/dist/{chunk-JE6GQB5J.js.map → chunk-4Z2HIHA5.js.map} +0 -0
  341. /package/dist/{chunk-FHW3ATT7.js.map → chunk-53HQNN3C.js.map} +0 -0
  342. /package/dist/{chunk-53O2TNSR.js.map → chunk-5DAVXZPY.js.map} +0 -0
  343. /package/dist/{chunk-DH5UJD2I.js.map → chunk-5FHPZOYK.js.map} +0 -0
  344. /package/dist/{chunk-NSVSC6ZC.js.map → chunk-5PJM772Y.js.map} +0 -0
  345. /package/dist/{chunk-VYM2GPR6.js.map → chunk-5PTCT3LF.js.map} +0 -0
  346. /package/dist/{chunk-ZH2SZ6B3.js.map → chunk-652PYSML.js.map} +0 -0
  347. /package/dist/{chunk-PEOOCQ2T.js.map → chunk-6IRJAIS4.js.map} +0 -0
  348. /package/dist/{chunk-PAT2BQOQ.js.map → chunk-6IWO7CM2.js.map} +0 -0
  349. /package/dist/{chunk-YFODI4KT.js.map → chunk-6WZUZHJM.js.map} +0 -0
  350. /package/dist/{chunk-QEI5DC6S.js.map → chunk-7KJOODQB.js.map} +0 -0
  351. /package/dist/{chunk-6ZD3FI5P.js.map → chunk-AOFI3GDS.js.map} +0 -0
  352. /package/dist/{chunk-H72YKEGD.js.map → chunk-AOKLEE64.js.map} +0 -0
  353. /package/dist/{chunk-RDFPM2AQ.js.map → chunk-BJGUDLWZ.js.map} +0 -0
  354. /package/dist/{chunk-TBMGYQJF.js.map → chunk-BKBELIUR.js.map} +0 -0
  355. /package/dist/{chunk-X66E5WSX.js.map → chunk-C4QKXFZN.js.map} +0 -0
  356. /package/dist/{chunk-OJUORFGO.js.map → chunk-C6JUGWAU.js.map} +0 -0
  357. /package/dist/{chunk-DLWLIPCP.js.map → chunk-CKFZQQ6T.js.map} +0 -0
  358. /package/dist/{chunk-Z2NN53E5.js.map → chunk-DCT2PKMQ.js.map} +0 -0
  359. /package/dist/{chunk-JMEPGXJG.js.map → chunk-DHW5UMUG.js.map} +0 -0
  360. /package/dist/{chunk-G6ZPQHBL.js.map → chunk-DSHM7VN6.js.map} +0 -0
  361. /package/dist/{chunk-WV62BSWA.js.map → chunk-F5BYZNXY.js.map} +0 -0
  362. /package/dist/{chunk-RDZGXJOD.js.map → chunk-F5GXWK6B.js.map} +0 -0
  363. /package/dist/{chunk-4Z7GEO2R.js.map → chunk-G7RYAWPZ.js.map} +0 -0
  364. /package/dist/{chunk-4S2LWZ7L.js.map → chunk-GO6XDMBB.js.map} +0 -0
  365. /package/dist/{chunk-KHOAXZW2.js.map → chunk-H3GYVR7S.js.map} +0 -0
  366. /package/dist/{chunk-C6OVO6AT.js.map → chunk-I6MVJWUO.js.map} +0 -0
  367. /package/dist/{chunk-4XHVGUOM.js.map → chunk-J2SFOLGZ.js.map} +0 -0
  368. /package/dist/{chunk-7TE4TMS3.js.map → chunk-JSOJKHEI.js.map} +0 -0
  369. /package/dist/{chunk-ZNBLGS66.js.map → chunk-K62RHTFB.js.map} +0 -0
  370. /package/dist/{chunk-6N2EDWMG.js.map → chunk-KWU62UPM.js.map} +0 -0
  371. /package/dist/{chunk-CJ45OL7L.js.map → chunk-M2GVHVE4.js.map} +0 -0
  372. /package/dist/{chunk-BX7QWHKC.js.map → chunk-MBNXCCRG.js.map} +0 -0
  373. /package/dist/{chunk-ZSTUKSTJ.js.map → chunk-MLUUF7OZ.js.map} +0 -0
  374. /package/dist/{chunk-KW3H5FUS.js.map → chunk-MPYIEIBA.js.map} +0 -0
  375. /package/dist/{chunk-DFI2RKVQ.js.map → chunk-MRWYKNBY.js.map} +0 -0
  376. /package/dist/{chunk-AP4LSXRK.js.map → chunk-NYT3UVOH.js.map} +0 -0
  377. /package/dist/{chunk-YWJDUJAR.js.map → chunk-O6IF4BZT.js.map} +0 -0
  378. /package/dist/{chunk-3UEZ6NUI.js.map → chunk-OCQ6GDCF.js.map} +0 -0
  379. /package/dist/{chunk-JAGAFEZL.js.map → chunk-OD3L6GX5.js.map} +0 -0
  380. /package/dist/{chunk-RPBGUWNF.js.map → chunk-ON4TRXCM.js.map} +0 -0
  381. /package/dist/{chunk-NOLSQK4J.js.map → chunk-PGV2FLE3.js.map} +0 -0
  382. /package/dist/{chunk-C2TERIB4.js.map → chunk-QSNLIWEB.js.map} +0 -0
  383. /package/dist/{chunk-XZY7O7JJ.js.map → chunk-RHKT2XW2.js.map} +0 -0
  384. /package/dist/{chunk-TDXEO2UI.js.map → chunk-RJ35IXFD.js.map} +0 -0
  385. /package/dist/{chunk-4SHMSLFA.js.map → chunk-RRG75JJS.js.map} +0 -0
  386. /package/dist/{chunk-6MD5QXXJ.js.map → chunk-RWRPF24F.js.map} +0 -0
  387. /package/dist/{chunk-VPAOVEI2.js.map → chunk-SJGYMI6Y.js.map} +0 -0
  388. /package/dist/{chunk-EQXIW5MQ.js.map → chunk-TCMH3FXD.js.map} +0 -0
  389. /package/dist/{chunk-STTULW2K.js.map → chunk-TE3XYCX7.js.map} +0 -0
  390. /package/dist/{chunk-TJ3334AJ.js.map → chunk-TMW7RBW7.js.map} +0 -0
  391. /package/dist/{chunk-3GYPZ5MI.js.map → chunk-UP7SSTCZ.js.map} +0 -0
  392. /package/dist/{chunk-IWGW2E35.js.map → chunk-WF4XK5AS.js.map} +0 -0
  393. /package/dist/{chunk-6REPQ352.js.map → chunk-WL7IG7TT.js.map} +0 -0
  394. /package/dist/{chunk-U67ZQ6VM.js.map → chunk-YIWVHEPW.js.map} +0 -0
  395. /package/dist/{chunk-DH77PLFF.js.map → chunk-YTVXT5TD.js.map} +0 -0
  396. /package/dist/{chunk-MKLIMY3D.js.map → chunk-YZHX2HTC.js.map} +0 -0
@@ -7,6 +7,7 @@ import GridViewOutlinedIcon from "@mui/icons-material/GridViewOutlined";
7
7
  import { Slider } from "../../form/Slider";
8
8
  import { Box } from "../../../mui/Box";
9
9
  import { sxRem } from "../../../tokens/relative";
10
+ import { useDensity, type DensityLevel } from "../../../tokens/density";
10
11
 
11
12
  import { useDataViewsCopy } from "./data-views-copy-context";
12
13
  import { DATA_VIEWS_LAYOUTS, type DataViewsLayout } from "./data-views-types";
@@ -166,6 +167,22 @@ function isDensity(value: unknown): value is DataViewsDensity {
166
167
  return DENSITIES.includes(value as DataViewsDensity);
167
168
  }
168
169
 
170
+ /**
171
+ * The theme's density level, aliased to `DataViewsDensity` (FUT-2769 —
172
+ * umbrella Decision 7, non-breaking): `DataViewsDensity`'s three names are not
173
+ * the theme's three names, so this is an alias table rather than a verbatim
174
+ * read. `'normal'` (the theme's own default, and what a theme with no density
175
+ * at all resolves to) maps to `'cozy'` — today's literal default, unchanged —
176
+ * so the mapping is a no-op exactly when nothing about density has been said.
177
+ * The STORED per-viewer preference still wins over this default, unchanged
178
+ * from today (below).
179
+ */
180
+ export function mapThemeToDataViewsDensity(level: DensityLevel): DataViewsDensity {
181
+ if (level === 'compact') return 'compact';
182
+ if (level === 'comfortable') return 'comfortable';
183
+ return 'cozy';
184
+ }
185
+
169
186
  /** The remembered density, or undefined (no window, no value, junk). */
170
187
  function readStoredDensity(): DataViewsDensity | undefined {
171
188
  try {
@@ -258,6 +275,10 @@ export function DataViewsLayoutProvider({
258
275
  children,
259
276
  }: LayoutProviderProps): React.JSX.Element {
260
277
  const availability = { canUseCards, canUseList, canUseBoard };
278
+ // Read once, outside the lazy initializer below: a hook cannot be called
279
+ // from inside one (FUT-2769 — the theme is only a fallback when nothing is
280
+ // stored, same precedence as before this ticket).
281
+ const themeDensity = useDensity();
261
282
  const [layout, setLayoutState] = useState<DataViewsLayout>(() =>
262
283
  pinLayout(
263
284
  viewLayout ?? (ignoreStoredLayout ? undefined : readStoredLayout()) ?? defaultLayout,
@@ -265,7 +286,9 @@ export function DataViewsLayoutProvider({
265
286
  ),
266
287
  );
267
288
  const [density, setDensityState] = useState<DataViewsDensity>(
268
- () => (ignoreStoredLayout ? undefined : readStoredDensity()) ?? "cozy",
289
+ () =>
290
+ (ignoreStoredLayout ? undefined : readStoredDensity()) ??
291
+ mapThemeToDataViewsDensity(themeDensity.level ?? "normal"),
269
292
  );
270
293
  const [zoom, setZoom] = useState(DEFAULT_ZOOM);
271
294
  // A newly applied view carrying a layout switches to it (its reference-change
@@ -3,8 +3,9 @@ import type { Theme } from '@mui/material/styles/index.js';
3
3
  import type React from 'react';
4
4
 
5
5
  import { rem } from '../../../tokens/relative';
6
+ import type { DensityLevel } from '../../../tokens/density';
6
7
 
7
- import type { TableProps } from './Table.types';
8
+ import type { TableDensity, TableProps } from './Table.types';
8
9
 
9
10
  /**
10
11
  * A virtualised row's height in design px: the caller's `rowHeight`, else 52.
@@ -13,6 +14,18 @@ import type { TableProps } from './Table.types';
13
14
  */
14
15
  export const tableRowHeight = (rowHeight: number | undefined): number => rowHeight ?? 52;
15
16
 
17
+ /**
18
+ * `density`'s default (FUT-2769): the caller's own prop, else the theme's
19
+ * level — `'normal'` for a theme with no density at all (`useDensity()`'s own
20
+ * fallback) or an unnamed numeric one. `TableDensity` is a verbatim match for
21
+ * the theme's `DensityLevel`, so no alias table is needed, unlike `DataGrid`'s
22
+ * `mapThemeToGridDensity` or `DataViews`' `mapThemeToDataViewsDensity`.
23
+ */
24
+ export const resolveTableDensity = (
25
+ explicit: TableDensity | undefined,
26
+ themeLevel: DensityLevel | undefined,
27
+ ): TableDensity => explicit ?? themeLevel ?? 'normal';
28
+
16
29
  /** The scroll box's height: a number is design px, 400 unless the caller says otherwise. */
17
30
  const scrollHeight = (theme: Theme, containerHeight: number | string | undefined): string => {
18
31
  const box = containerHeight || 400;
@@ -71,6 +84,12 @@ export const virtualHeight = (p: TableProps): number | undefined =>
71
84
  ? p.containerHeight
72
85
  : undefined;
73
86
 
87
+ // `density` is NOT here (FUT-2769): `TableDensity` is a verbatim match for
88
+ // the theme's `DensityLevel`, so `Table.tsx` resolves it itself —
89
+ // `props.density ?? (useDensity().level ?? 'normal')` — reading the theme
90
+ // requires a hook, which this module-level constant cannot call. At
91
+ // `theme.density` unset, or its level `'normal'`, that reproduces this
92
+ // object's OTHER defaults' shape exactly: today's literal `'normal'`.
74
93
  export const TABLE_DEFAULTS: Partial<TableProps> = {
75
94
  variant: 'default',
76
95
  stripeColor: 'neutral',
@@ -78,7 +97,6 @@ export const TABLE_DEFAULTS: Partial<TableProps> = {
78
97
  pulse: false,
79
98
  hoverable: false,
80
99
  loading: false,
81
- density: 'normal',
82
100
  stickyHeader: false,
83
101
  selectable: false,
84
102
  selectedRows: [],
@@ -24,6 +24,7 @@ import {
24
24
  containerStyle,
25
25
  definedProps,
26
26
  headerRefFor,
27
+ resolveTableDensity,
27
28
  scrollerRadiusStyle,
28
29
  tableDomProps,
29
30
  tableRowHeight,
@@ -32,9 +33,9 @@ import {
32
33
  import { useTableSelection, useVirtualScrolling } from './Table.hooks';
33
34
  import { EnhancedTableBody, EnhancedTableHeader } from './TableParts';
34
35
  import { EmptyRow, NoDataPlaceholder } from './TableStates';
35
- import {
36
- tableStyles } from './Table.styles';
36
+ import { tableStyles } from './Table.styles';
37
37
  import { rem } from '../../../tokens/relative';
38
+ import { useDensity } from '../../../tokens/density';
38
39
 
39
40
  // Helper function to get stripe color from theme
40
41
  const StyledTable = styled(MuiTable, {
@@ -329,7 +330,9 @@ const TableEmptyState: React.FC<{
329
330
 
330
331
  export const Table = React.forwardRef<globalThis.HTMLTableElement, TableProps>(
331
332
  (tableProps, ref) => {
333
+ const themeDensity = useDensity(); // FUT-2769 — density's default; see resolveTableDensity
332
334
  const resolved = { ...TABLE_DEFAULTS, ...definedProps(tableProps) } as TableProps;
335
+ resolved.density = resolveTableDensity(resolved.density, themeDensity.level);
333
336
  const {
334
337
  columns,
335
338
  data,
@@ -39,6 +39,13 @@ const SCROLL_DELTA_EPSILON = 2;
39
39
  */
40
40
  const POINTER_MOVE_EPSILON = 2;
41
41
 
42
+ /**
43
+ * How long a key, sideways wheel or pan stays armed through a scroll the strip
44
+ * made itself (FUT-2848): a busy thread can finish a re-centre before the key's
45
+ * scroll ticks once. Past this it lapses, so a later clamp is not the visitor.
46
+ */
47
+ const NUDGE_FRESH_MS = 1000;
48
+
42
49
  interface VisitorScrollWatch {
43
50
  /** True once the visitor has moved the strip themselves. */
44
51
  hasScrolled: () => boolean;
@@ -79,6 +86,9 @@ interface WatchState {
79
86
  pointer: boolean;
80
87
  touch: boolean;
81
88
  nudged: boolean;
89
+ /** When `nudged` was set (`Date.now()` ms), and whether it outlived an own verdict. */
90
+ nudgedAt: number;
91
+ nudgeKept: boolean;
82
92
  undecided: boolean;
83
93
  scrolled: boolean;
84
94
  aimed: number;
@@ -177,6 +187,11 @@ export function toRawScrollLeft(strip: HTMLElement, physical: number): number {
177
187
  return physical;
178
188
  }
179
189
 
190
+ /** Whether the gesture that armed `nudged` happened within {@link NUDGE_FRESH_MS}. */
191
+ function nudgeIsFresh(state: WatchState): boolean {
192
+ return Date.now() - state.nudgedAt <= NUDGE_FRESH_MS;
193
+ }
194
+
180
195
  /** Whether the strip came to rest where it last aimed itself — clamped as the browser would. */
181
196
  function restsOnAim(strip: HTMLElement, aimed: number): boolean {
182
197
  const reachable = Math.min(aimed, strip.scrollWidth - strip.clientWidth);
@@ -222,15 +237,18 @@ function createGestureListeners(state: WatchState): { onStrip: Listeners; onView
222
237
  state.touch = false;
223
238
  state.touchDownAt = Number.NaN;
224
239
  };
225
- const onPointerCancel = (): void => {
240
+ const nudge = (): void => {
226
241
  state.nudged = true;
227
- onPointerUp();
242
+ state.nudgedAt = Date.now();
243
+ state.nudgeKept = false;
228
244
  };
229
- const onKeydown = (): void => {
230
- state.nudged = true;
245
+ const onPointerCancel = (): void => {
246
+ nudge();
247
+ onPointerUp();
231
248
  };
249
+ const onKeydown = nudge;
232
250
  const onWheel = (event: Event): void => {
233
- if (horizontalDelta(event) !== 0) state.nudged = true;
251
+ if (horizontalDelta(event) !== 0) nudge();
234
252
  };
235
253
  return {
236
254
  onStrip: [
@@ -252,6 +270,31 @@ function createGestureListeners(state: WatchState): { onStrip: Listeners; onView
252
270
  };
253
271
  }
254
272
 
273
+ /**
274
+ * Judge the scroll under judgement once the strip rests. Only a scroll UNDER
275
+ * JUDGEMENT disarms: Chromium can fire `scrollend` for the strip's own scroll
276
+ * cut off by another BEFORE that one's first `scroll`, and disarming there
277
+ * would hand the visitor's scroll to nobody.
278
+ */
279
+ function settleJudgement(strip: HTMLElement, state: WatchState): void {
280
+ if (!state.undecided) return;
281
+ state.undecided = false;
282
+ const own = restsOnAim(strip, state.aimed);
283
+ if (!own) state.scrolled = true;
284
+ // The strip's own scroll does not use up a gesture armed moments ago: the
285
+ // scroll that gesture causes may still be on its way (FUT-2848).
286
+ state.nudgeKept = own && nudgeIsFresh(state);
287
+ if (!state.nudgeKept) state.nudged = false;
288
+ state.settled();
289
+ }
290
+
291
+ /** A gesture kept through the strip's own scroll lapses once stale (FUT-2848). */
292
+ function dropStaleNudge(state: WatchState): void {
293
+ if (!state.nudgeKept || nudgeIsFresh(state)) return;
294
+ state.nudged = false;
295
+ state.nudgeKept = false;
296
+ }
297
+
255
298
  /**
256
299
  * Tell a scroll the VISITOR made from every other one.
257
300
  *
@@ -291,6 +334,8 @@ export function watchVisitorScroll(strip: HTMLElement): VisitorScrollWatch {
291
334
  pointer: false,
292
335
  touch: false,
293
336
  nudged: false,
337
+ nudgedAt: Number.NaN,
338
+ nudgeKept: false,
294
339
  undecided: false,
295
340
  scrolled: false,
296
341
  aimed: Number.NaN,
@@ -302,17 +347,7 @@ export function watchVisitorScroll(strip: HTMLElement): VisitorScrollWatch {
302
347
  touchDownAt: Number.NaN,
303
348
  touchMoved: false,
304
349
  };
305
- const settle = (): void => {
306
- // Only a scroll that was UNDER JUDGEMENT disarms. Chromium can end the
307
- // strip's own smooth scroll with a `scrollend` when another scroll cuts it
308
- // off, fired BEFORE that scroll's first `scroll` (seen with an instant one);
309
- // disarming there would hand the visitor's scroll to nobody.
310
- if (!state.undecided) return;
311
- state.undecided = false;
312
- state.nudged = false;
313
- if (!restsOnAim(strip, state.aimed)) state.scrolled = true;
314
- state.settled();
315
- };
350
+ const settle = (): void => settleJudgement(strip, state);
316
351
  const onScroll = (): void => {
317
352
  const now = physicalScrollLeft(strip);
318
353
  const movedFarEnough = Math.abs(now - state.lastScrollLeft) > SCROLL_DELTA_EPSILON;
@@ -324,6 +359,7 @@ export function watchVisitorScroll(strip: HTMLElement): VisitorScrollWatch {
324
359
  // arm under a delta-only check (`pointerMoved`/`touchMoved` rules that out);
325
360
  // a pointer that drifts a sub-epsilon amount while resting would arm under
326
361
  // a moved-only check with no delta floor (`movedFarEnough` rules that out).
362
+ dropStaleNudge(state);
327
363
  const pointerDrag = state.pointer && state.pointerMoved && movedFarEnough;
328
364
  const touchDrag = state.touch && state.touchMoved && movedFarEnough;
329
365
  // `nudged` (a keypress, a sideways wheel, the browser taking the pointer
@@ -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 { useTheme } from '@mui/material/styles/index.js';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type React from 'react';\n\nimport { rem, remPx } from '../../../tokens/relative';\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_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 /** A row's height as CSS: the design height, density applied, through `rem`. */\n rowHeight: string;\n /**\n * The same height in px (`remPx`) — what the window divides `scrollTop` by.\n * One design number drawn two ways, so the rows and the window never disagree.\n */\n rowPitch: 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, in design px. */\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. `rowPitch` is\n * px, like the `scrollTop` and `clientHeight` it is divided into.\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 rowPitch: 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 / rowPitch);\n const visible = Math.ceil(clientHeight / rowPitch);\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, rowPitch, 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 theme = useTheme();\n const containerRef = useRef<HTMLDivElement>(null);\n const [editingCell, setEditingCell] = useState<EditingCell | null>(null);\n const { sortBy, filters, setInternalSortBy } = useSortAndFilter(props);\n // 52 design px unless the caller says; the density scales it, then the type scale does.\n const designRowHeight = densityHeight(props.rowHeight ?? 52, props.density);\n const rowPitch = remPx(theme, designRowHeight);\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, rowPitch, virtualized);\n const onSort = useSortHandler(props, sortBy, filters, setInternalSortBy);\n\n return {\n containerRef,\n rowHeight: rem(theme, designRowHeight),\n rowPitch,\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/SettingsLayout/SettingsSectionChips.scroll.ts"],"sourcesContent":["/**\n * Telling the strip's own scrolls from the visitor's (FUT-2606).\n *\n * Split from `SettingsSectionChips.tsx` so the chips stay a component file and\n * the rule for \"who moved the strip\" can be read in one place.\n */\n\n/**\n * How near to where the strip aimed itself it has to come to rest for the scroll\n * to count as the strip's own. A smooth scroll lands on a device pixel, and the\n * target it was given is fractional.\n */\nconst LANDED_SLACK = 1;\n\n/**\n * Where `scrollend` is missing: how long the strip has to go without a `scroll`\n * before it counts as settled. Generous on purpose — a busy main thread can go\n * several frames between ticks of a smooth scroll, and judging one mid-flight\n * would read the strip's own animation as the visitor's. Too long only delays a\n * re-centre; too short can latch the strip for good.\n */\nconst QUIET_BEFORE_SETTLED_MS = 250;\n\n/**\n * How much `scrollLeft` has to move, tick to tick, before a `scroll` event is\n * even a CANDIDATE for arming (FUT-2775). Below this, a browser's own rounding\n * or a repeated event carrying no real motion cannot arm anything by itself.\n *\n * This alone does not stop the false latch the ticket describes: the strip's\n * own `scrollTo` produces real per-tick deltas well past this line, same as a\n * drag would. It only rules out a scroll event that moved nothing.\n */\nconst SCROLL_DELTA_EPSILON = 2;\n\n/**\n * How far a pointer or touch has to travel from where it went down before it\n * counts as having MOVED, rather than merely resting (FUT-2775). Below this,\n * an held-still finger's sub-pixel tremor does not count as a drag.\n */\nconst POINTER_MOVE_EPSILON = 2;\n\ninterface VisitorScrollWatch {\n /** True once the visitor has moved the strip themselves. */\n hasScrolled: () => boolean;\n /**\n * True while a scroll the visitor MAY be making has not come to rest yet. The\n * strip must not scroll itself under it: that would yank a drag in progress.\n */\n isUndecided: () => boolean;\n /**\n * Where the strip last aimed itself, PHYSICAL pixels (see {@link physicalScrollLeft}) —\n * direction-blind, like every other geometry read in this file. `NaN` before it has.\n */\n aimedAt: () => number;\n /**\n * The strip is about to scroll itself to `left` (physical pixels). Records the\n * aim and NOTHING\n * else: it used to disarm too, and a re-centre landing between a visitor's key\n * press (or wheel, or pan) and the first tick of the scroll it causes wiped\n * the arming — their scroll went unclaimed, read as the strip's own. Left\n * armed, the worst a stale arming does is put the strip's OWN next scroll\n * under judgement, which rests on its aim, is not latched, and disarms.\n */\n beforeOwnScroll: (left: number) => void;\n /** Called once an undecided scroll has come to rest and been judged. */\n onSettled: (listener: () => void) => void;\n detach: () => void;\n}\n\ntype Listeners = Array<[string, (event: Event) => void]>;\n\n/** A wheel's sideways travel: `deltaX`, or `deltaY` with Shift held, as browsers read it. */\nfunction horizontalDelta(event: Event): number {\n if (!(event instanceof WheelEvent)) return 0;\n return event.deltaX !== 0 ? event.deltaX : event.shiftKey ? event.deltaY : 0;\n}\n\ninterface WatchState {\n pointer: boolean;\n touch: boolean;\n nudged: boolean;\n undecided: boolean;\n scrolled: boolean;\n aimed: number;\n quiet: ReturnType<typeof setTimeout> | undefined;\n settled: () => void;\n /** `scrollLeft` as of the last `scroll` tick, updated every tick regardless of arming. */\n lastScrollLeft: number;\n /** Where a `pointerdown` on the strip landed, in viewport `clientX`. `NaN` while up. */\n pointerDownAt: number;\n /** True once that pointer has travelled past {@link POINTER_MOVE_EPSILON} from `pointerDownAt`. */\n pointerMoved: boolean;\n /** Same pair, for `touchstart`/`touchmove` — a distinct event stream on some engines. */\n touchDownAt: number;\n touchMoved: boolean;\n}\n\ntype RtlScrollType = 'default' | 'negative' | 'reverse';\n\nlet cachedRtlScrollType: RtlScrollType | undefined;\n\n/**\n * Which of the three incompatible conventions this engine reports an RTL\n * scroller's `scrollLeft` in, probed once and cached (FUT-2775).\n *\n * Per the CSSOM View spec, an RTL scroller's `scrollLeft` is `0` at its\n * (right-hand) start and goes NEGATIVE toward the end — `'negative'` below,\n * what every current evergreen engine implements. Older WebKit mirrored that\n * (`'reverse'`: `0` at the start, growing toward `+max`), and older\n * Chromium/Safari ignored `dir` altogether and kept the plain left-to-right\n * numbering (`'default'`). A hidden probe, not a version sniff, tells them\n * apart — the same technique `@mui/utils`'s `detectScrollType` uses for\n * `Tabs`; reimplemented here rather than taking a new dependency for one\n * probe.\n */\nfunction detectRtlScrollType(doc: Document): RtlScrollType {\n if (cachedRtlScrollType) return cachedRtlScrollType;\n // The exact pixel values below are the probe's mechanism, not a design size:\n // what matters is only that the INNER box is wider than the OUTER one, so the\n // outer one has something to scroll — same technique `@mui/utils` uses,\n // detached and off-screen either way.\n const probe = doc.createElement('div');\n const inner = doc.createElement('div');\n inner.style.width = '10px';\n probe.appendChild(inner);\n probe.dir = 'rtl';\n probe.style.width = '4px';\n probe.style.position = 'absolute';\n probe.style.top = '-1000px';\n probe.style.overflow = 'scroll';\n doc.body.appendChild(probe);\n let type: RtlScrollType = 'reverse';\n if (probe.scrollLeft > 0) {\n type = 'default';\n } else {\n probe.scrollLeft = 1;\n if (probe.scrollLeft === 0) type = 'negative';\n }\n doc.body.removeChild(probe);\n cachedRtlScrollType = type;\n return type;\n}\n\n/** True when the strip's own computed direction is right-to-left. */\nexport function isRtlStrip(strip: HTMLElement): boolean {\n const view = strip.ownerDocument.defaultView;\n const getComputedStyle = view?.getComputedStyle ?? globalThis.getComputedStyle;\n return getComputedStyle(strip).direction === 'rtl';\n}\n\n/**\n * `strip.scrollLeft`, renumbered so `0` is always the strip's physical LEFT\n * edge and larger is always further physically right — whatever `direction`\n * and whatever convention this engine uses to report it raw (FUT-2775).\n *\n * Every geometry read in this file (`getBoundingClientRect`) is already in\n * that same physical, direction-blind coordinate space, so this is what makes\n * `scrollLeft` combinable with it at all.\n */\nexport function physicalScrollLeft(strip: HTMLElement): number {\n const raw = strip.scrollLeft;\n if (!isRtlStrip(strip)) return raw;\n const max = strip.scrollWidth - strip.clientWidth;\n const type = detectRtlScrollType(strip.ownerDocument);\n if (type === 'negative') return raw + max;\n if (type === 'reverse') return max - raw;\n return raw;\n}\n\n/** The inverse of {@link physicalScrollLeft}: a physical offset back to this engine's raw `scrollLeft`. */\nexport function toRawScrollLeft(strip: HTMLElement, physical: number): number {\n if (!isRtlStrip(strip)) return physical;\n const max = strip.scrollWidth - strip.clientWidth;\n const type = detectRtlScrollType(strip.ownerDocument);\n if (type === 'negative') return physical - max;\n if (type === 'reverse') return max - physical;\n return physical;\n}\n\n/** Whether the strip came to rest where it last aimed itself — clamped as the browser would. */\nfunction restsOnAim(strip: HTMLElement, aimed: number): boolean {\n const reachable = Math.min(aimed, strip.scrollWidth - strip.clientWidth);\n // Written so that `NaN` — the strip never aimed — reads as \"not on aim\".\n return Math.abs(physicalScrollLeft(strip) - reachable) <= LANDED_SLACK;\n}\n\n/** The pointer/touch/keydown/wheel listeners that arm `state`, split out of `watchVisitorScroll` (line budget). */\nfunction createGestureListeners(state: WatchState): { onStrip: Listeners; onView: Listeners } {\n // `MouseEvent`, not `PointerEvent`: a real `PointerEvent` IS one (it extends\n // `MouseEvent`), so this reads `clientX` off it just the same in a browser —\n // but jsdom (this file's own test environment) has never implemented\n // `PointerEvent` at all, and the bare identifier throws a `ReferenceError`\n // the moment anything evaluates `instanceof PointerEvent`, pointer event or\n // not. Same reasoning as feature-checking `scrollTo` elsewhere in this file:\n // nothing in here is worth a crash over which constructor a probe prefers.\n const onPointerDown = (event: Event): void => {\n state.pointer = true;\n state.pointerMoved = false;\n state.pointerDownAt = event instanceof MouseEvent ? event.clientX : Number.NaN;\n };\n const onPointerMove = (event: Event): void => {\n if (!(event instanceof MouseEvent) || Number.isNaN(state.pointerDownAt)) return;\n if (Math.abs(event.clientX - state.pointerDownAt) > POINTER_MOVE_EPSILON) state.pointerMoved = true;\n };\n const onPointerUp = (): void => {\n state.pointer = false;\n state.pointerDownAt = Number.NaN;\n };\n const onTouchStart = (event: Event): void => {\n state.touch = true;\n state.touchMoved = false;\n state.touchDownAt = event instanceof TouchEvent ? (event.touches[0]?.clientX ?? Number.NaN) : Number.NaN;\n };\n const onTouchMove = (event: Event): void => {\n if (!(event instanceof TouchEvent) || Number.isNaN(state.touchDownAt)) return;\n const clientX = event.touches[0]?.clientX;\n if (clientX !== undefined && Math.abs(clientX - state.touchDownAt) > POINTER_MOVE_EPSILON) {\n state.touchMoved = true;\n }\n };\n const onTouchEnd = (): void => {\n state.touch = false;\n state.touchDownAt = Number.NaN;\n };\n const onPointerCancel = (): void => {\n state.nudged = true;\n onPointerUp();\n };\n const onKeydown = (): void => {\n state.nudged = true;\n };\n const onWheel = (event: Event): void => {\n if (horizontalDelta(event) !== 0) state.nudged = true;\n };\n return {\n onStrip: [\n ['pointerdown', onPointerDown],\n ['pointermove', onPointerMove],\n ['touchstart', onTouchStart],\n ['touchmove', onTouchMove],\n ['pointercancel', onPointerCancel],\n ['keydown', onKeydown],\n ['wheel', onWheel],\n ],\n // A gesture can END off the strip, so its end is heard on the window.\n onView: [\n ['pointerup', onPointerUp],\n ['pointercancel', onPointerUp],\n ['touchend', onTouchEnd],\n ['touchcancel', onTouchEnd],\n ],\n };\n}\n\n/**\n * Tell a scroll the VISITOR made from every other one.\n *\n * The `scroll` event cannot say: the strip's own `scrollTo` fires it, and so does\n * the browser clamping a strip whose content shrank. So a scroll is only a\n * CANDIDATE when it arrives during something only a visitor does:\n *\n * - a finger held on the strip (`touchstart` until `touchend`) — a drag;\n * - a pointer held on it (`pointerdown` until `pointerup`);\n * - a key press, a SIDEWAYS wheel, or the browser taking a pointer over to pan\n * it (`pointercancel`), each armed until the next scroll under judgement has\n * been judged — whoever's it turns out to be.\n *\n * and the verdict waits until the strip comes to REST (`scrollend`, or a quiet\n * spell where the browser has no `scrollend`): it is the visitor's only if the\n * strip rests somewhere other than where it last aimed itself.\n *\n * Judged at rest rather than per `scroll` because the strip's own smooth scroll\n * fires `scroll` for a third of a second, and a visitor who presses Tab or puts\n * a finger on a chip to scroll the PAGE in that window is not scrolling the\n * strip. Every tick of that animation used to count as theirs, the strip stopped\n * re-centring for good, and the open chip could be left clipped (FUT-2606\n * again, by another door). A visitor who really drags or wheels the strip\n * mid-animation cancels it, so the strip rests where THEY left it — and that\n * still counts. The one loss: a visitor who happens to leave it within a pixel\n * of the strip's own aim is not told apart from it, and the strip there is\n * already where it would have put itself.\n *\n * A tap is a pointer held with no scroll under it, so it never counts. A\n * vertical wheel scrolls the PAGE — the strip is `overflowY: hidden` — and is\n * not armed at all.\n */\nexport function watchVisitorScroll(strip: HTMLElement): VisitorScrollWatch {\n const view = strip.ownerDocument.defaultView;\n const hasScrollEnd = 'onscrollend' in strip;\n const state: WatchState = {\n pointer: false,\n touch: false,\n nudged: false,\n undecided: false,\n scrolled: false,\n aimed: Number.NaN,\n quiet: undefined,\n settled: () => undefined,\n lastScrollLeft: physicalScrollLeft(strip),\n pointerDownAt: Number.NaN,\n pointerMoved: false,\n touchDownAt: Number.NaN,\n touchMoved: false,\n };\n const settle = (): void => {\n // Only a scroll that was UNDER JUDGEMENT disarms. Chromium can end the\n // strip's own smooth scroll with a `scrollend` when another scroll cuts it\n // off, fired BEFORE that scroll's first `scroll` (seen with an instant one);\n // disarming there would hand the visitor's scroll to nobody.\n if (!state.undecided) return;\n state.undecided = false;\n state.nudged = false;\n if (!restsOnAim(strip, state.aimed)) state.scrolled = true;\n state.settled();\n };\n const onScroll = (): void => {\n const now = physicalScrollLeft(strip);\n const movedFarEnough = Math.abs(now - state.lastScrollLeft) > SCROLL_DELTA_EPSILON;\n state.lastScrollLeft = now;\n // Pointer/touch need BOTH signals (FUT-2775): the pointer/finger must have\n // itself MOVED since going down, AND this tick's delta must be real. Either\n // alone still latches on the other's shape — a pointer merely resting on\n // the strip while its OWN `scrollTo` produces real per-tick deltas would\n // arm under a delta-only check (`pointerMoved`/`touchMoved` rules that out);\n // a pointer that drifts a sub-epsilon amount while resting would arm under\n // a moved-only check with no delta floor (`movedFarEnough` rules that out).\n const pointerDrag = state.pointer && state.pointerMoved && movedFarEnough;\n const touchDrag = state.touch && state.touchMoved && movedFarEnough;\n // `nudged` (a keypress, a sideways wheel, the browser taking the pointer\n // over to pan) is already a discrete, one-shot gesture with no \"resting\n // pointer coincides with an unrelated animation\" shape to rule out — unlike\n // pointer/touch, requiring a delta on the SAME tick that arms it would only\n // race the strip's own scroll ending before a qualifying tick arrives (seen:\n // it broke the existing \"keeps a wheel/drag scroll\" stories against a real\n // browser's `scrollend` timing). So it arms as it always has.\n if (pointerDrag || touchDrag || state.nudged) state.undecided = true;\n if (!state.undecided || hasScrollEnd) return;\n // Every tick while undecided, armed or not: a quiet spell that began while\n // the strip was still moving would judge it mid-flight, away from its aim.\n clearTimeout(state.quiet);\n state.quiet = setTimeout(settle, QUIET_BEFORE_SETTLED_MS);\n };\n const gestures = createGestureListeners(state);\n const onStrip: Listeners = [...gestures.onStrip, ['scroll', onScroll], ['scrollend', settle]];\n const onView = gestures.onView;\n for (const [type, listener] of onStrip) strip.addEventListener(type, listener, { passive: true });\n for (const [type, listener] of onView) view?.addEventListener(type, listener, { passive: true });\n return {\n hasScrolled: () => state.scrolled,\n isUndecided: () => state.undecided,\n aimedAt: () => state.aimed,\n beforeOwnScroll: (left) => {\n state.aimed = left;\n },\n onSettled: (listener) => {\n state.settled = listener;\n },\n detach: () => {\n clearTimeout(state.quiet);\n for (const [type, listener] of onStrip) strip.removeEventListener(type, listener);\n for (const [type, listener] of onView) view?.removeEventListener(type, listener);\n },\n };\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Table/Table.tsx"],"sourcesContent":["import MoreVertIcon from '@mui/icons-material/MoreVert';\nimport Box from '@mui/material/Box/index.js';\nimport FormControlLabel from '@mui/material/FormControlLabel/index.js';\nimport IconButton from '@mui/material/IconButton/index.js';\nimport Menu from '@mui/material/Menu/index.js';\nimport MenuItem from '@mui/material/MenuItem/index.js';\nimport Skeleton from '@mui/material/Skeleton/index.js';\nimport Switch from '@mui/material/Switch/index.js';\nimport MuiTable from '@mui/material/Table/index.js';\nimport TableBody from '@mui/material/TableBody/index.js';\nimport TableCell from '@mui/material/TableCell/index.js';\nimport TableContainer from '@mui/material/TableContainer/index.js';\nimport TableRow from '@mui/material/TableRow/index.js';\nimport { styled, useTheme } from '@mui/material/styles/index.js';\nimport React from 'react';\n\nimport type {\n ColumnConfig,\n TableDensity,\n TableProps,\n TableStripeColor} from './Table.types';\nimport {\n TABLE_DEFAULTS,\n containerStyle,\n definedProps,\n headerRefFor,\n scrollerRadiusStyle,\n tableDomProps,\n tableRowHeight,\n virtualHeight,\n} from './Table.helpers';\nimport { useTableSelection, useVirtualScrolling } from './Table.hooks';\nimport { EnhancedTableBody, EnhancedTableHeader } from './TableParts';\nimport { EmptyRow, NoDataPlaceholder } from './TableStates';\nimport {\n tableStyles } from './Table.styles';\nimport { rem } from '../../../tokens/relative';\n\n// Helper function to get stripe color from theme\nconst StyledTable = styled(MuiTable, {\n shouldForwardProp: (prop) =>\n !['customVariant', 'glow', 'pulse', 'hoverable', 'density', 'stickyHeader', 'stripeColor', 'virtualised'].includes(prop as string) })<{\n customVariant?: string;\n glow?: boolean;\n pulse?: boolean;\n hoverable?: boolean;\n density?: TableDensity;\n stickyHeader?: boolean;\n stripeColor?: TableStripeColor;\n virtualised?: boolean;\n}>(({ theme, customVariant, glow, pulse, hoverable, density, stickyHeader, stripeColor = 'neutral', virtualised }) => {\n return tableStyles({\n theme,\n customVariant,\n glow,\n pulse,\n hoverable,\n density,\n stickyHeader,\n stripeColor,\n virtualised });\n});\n\n// Virtual Scrolling Hook\nconst TableShell: React.FC<{\n innerRef: React.Ref<globalThis.HTMLTableElement>;\n variant?: string;\n stripeColor?: TableStripeColor;\n glow?: boolean;\n pulse?: boolean;\n hoverable?: boolean;\n density?: TableDensity;\n stickyHeader?: boolean;\n header: React.ReactNode;\n rest: Record<string, unknown>;\n children: React.ReactNode;\n}> = ({\n innerRef,\n variant,\n stripeColor,\n glow,\n pulse,\n hoverable,\n density,\n stickyHeader,\n header,\n rest,\n children }) => (\n // The loading and empty shells are not scrollers (no `containerHeight`), so\n // they get only the rounded clip `stickyHeader` moves off the `<table>`,\n // never a height (FUT-2677).\n <TableContainer style={scrollerRadiusStyle(useTheme(), stickyHeader)}>\n <StyledTable\n ref={innerRef}\n customVariant={variant}\n stripeColor={stripeColor}\n glow={glow}\n pulse={pulse}\n hoverable={hoverable}\n density={density}\n stickyHeader={stickyHeader}\n {...rest}\n >\n {header}\n {children}\n </StyledTable>\n </TableContainer>\n);\n\nconst SKELETON_ROW_COUNT = 5;\n\nconst LoadingSkeletonRows: React.FC<{ columns?: ColumnConfig[] }> = ({ columns }) => {\n const theme = useTheme();\n return (\n <>\n {Array.from({ length: SKELETON_ROW_COUNT }, (_, index) => (\n <TableRow key={index}>\n {columns?.map((column) => (\n <TableCell key={column.key}>\n <Skeleton height={rem(theme, 20)} />\n </TableCell>\n ))}\n </TableRow>\n ))}\n </>\n );\n};\n\nexport type TableShellProps = Omit<React.ComponentProps<typeof TableShell>, 'children'>;\n\ntype Selection = ReturnType<typeof useTableSelection>;\n\ninterface RendererProps {\n resolved: TableProps;\n selection: Selection;\n innerRef: React.Ref<globalThis.HTMLTableElement>;\n rest: Record<string, unknown>;\n}\n\n// The column-visibility control, shown only when responsive mode has actually\n// hidden something on a narrow viewport.\nconst ColumnToggleMenu: React.FC<{\n columns: ColumnConfig[];\n hiddenColumns: number[];\n anchor: HTMLElement | null;\n setAnchor: (element: HTMLElement | null) => void;\n setHiddenColumns: (next: number[]) => void;\n}> = ({ columns, hiddenColumns, anchor, setAnchor, setHiddenColumns }) => (\n <Box position=\"absolute\" top={8} right={8}>\n <IconButton onClick={(event) => setAnchor(event.currentTarget)} size=\"small\">\n <MoreVertIcon />\n </IconButton>\n <Menu anchorEl={anchor} open={Boolean(anchor)} onClose={() => setAnchor(null)}>\n {columns.map((column, index) => (\n <MenuItem key={column.key}>\n <FormControlLabel\n control={\n <Switch\n checked={!hiddenColumns.includes(index)}\n onChange={(event) =>\n setHiddenColumns(\n event.target.checked\n ? hiddenColumns.filter((i: number) => i !== index)\n : [...hiddenColumns, index],\n )\n }\n size=\"small\"\n />\n }\n label={column.label}\n />\n </MenuItem>\n ))}\n </Menu>\n </Box>\n);\n\n// The populated table. Local because StyledTable cannot cross a module\n// boundary (TS2742).\nconst columnsFor = (resolved: TableProps, selection: Selection): ColumnConfig[] =>\n (resolved.responsive ? selection.visibleColumns : resolved.columns) ?? [];\n\n// The toggle only earns its place when responsive mode has actually hidden\n// something on a narrow viewport.\nconst showsColumnToggle = (resolved: TableProps, selection: Selection): boolean =>\n Boolean(\n resolved.responsive &&\n selection.isMobile &&\n resolved.showColumnToggle &&\n selection.hiddenColumns.length > 0,\n );\n\n// The virtual window lives here, with the one scroller whose offset drives it;\n// the header's ref lets it subtract the height the `<thead>` pushes the body down.\nconst AdvancedTable: React.FC<RendererProps> = ({ resolved: p, selection, innerRef, rest }) => {\n const theme = useTheme();\n const finalColumns = columnsFor(p, selection);\n const showToggle = showsColumnToggle(p, selection);\n const headRef = React.useRef<globalThis.HTMLTableSectionElement>(null);\n const windowHeight = virtualHeight(p);\n const { visibleItems, handleScroll } = useVirtualScrolling(\n p.data ?? [],\n tableRowHeight(p.rowHeight) || 40,\n windowHeight ?? 400,\n p.overscan,\n headerRefFor(windowHeight, headRef),\n );\n\n return (\n <Box position=\"relative\">\n <TableContainer\n style={containerStyle(theme, p)}\n onScroll={windowHeight ? handleScroll : undefined}\n >\n <StyledTable\n ref={innerRef}\n customVariant={p.variant}\n stripeColor={p.stripeColor}\n glow={p.glow}\n pulse={p.pulse}\n hoverable={p.hoverable}\n density={p.density}\n stickyHeader={p.stickyHeader}\n virtualised={Boolean(windowHeight)}\n {...rest}\n >\n <EnhancedTableHeader\n columns={finalColumns}\n data={p.data ?? []}\n sortable={p.sortable}\n sortConfig={p.sortConfig}\n onSortChange={p.onSortChange}\n selectable={p.selectable}\n selectedRows={p.selectedRows}\n onSelectAll={selection.handleSelectAll}\n density={p.density}\n stickyHeader={p.stickyHeader}\n headRef={headRef}\n />\n <EnhancedTableBody\n data={p.data ?? []}\n columns={finalColumns}\n selectedRows={p.selectedRows}\n onRowClick={p.onRowClick}\n onRowFocus={p.onRowFocus}\n onRowBlur={p.onRowBlur}\n onSelectionChange={selection.handleSelectionChange}\n rowKeyExtractor={p.rowKeyExtractor}\n density={p.density}\n selectable={p.selectable}\n hoverable={p.hoverable}\n renderRow={p.renderRow}\n renderCell={p.renderCell}\n virtualWindow={windowHeight ? visibleItems : undefined}\n rowHeight={p.rowHeight}\n />\n </StyledTable>\n </TableContainer>\n\n {showToggle && (\n <ColumnToggleMenu\n columns={p.columns ?? []}\n hiddenColumns={selection.hiddenColumns}\n anchor={selection.columnMenuAnchor}\n setAnchor={selection.setColumnMenuAnchor}\n setHiddenColumns={selection.setHiddenColumns}\n />\n )}\n </Box>\n );\n};\n\n// The loading and empty states render the same shell as the populated table, so\n// they share TableShell rather than repeating it three times.\nconst buildShell = ({\n resolved,\n selection,\n innerRef,\n rest,\n finalColumns }: RendererProps & { finalColumns?: ColumnConfig[] }) => ({\n innerRef,\n variant: resolved.variant,\n stripeColor: resolved.stripeColor,\n glow: resolved.glow,\n pulse: resolved.pulse,\n hoverable: resolved.hoverable,\n density: resolved.density,\n stickyHeader: resolved.stickyHeader,\n header: resolved.columns ? (\n <EnhancedTableHeader\n columns={finalColumns ?? []}\n data={[]}\n sortable={resolved.sortable}\n sortConfig={resolved.sortConfig}\n onSortChange={resolved.onSortChange}\n selectable={resolved.selectable}\n selectedRows={resolved.selectedRows}\n onSelectAll={selection.handleSelectAll}\n density={resolved.density}\n stickyHeader={resolved.stickyHeader}\n />\n ) : null,\n rest: rest as Record<string, unknown> });\n\nconst TableLoadingState: React.FC<{\n shell: TableShellProps;\n loadingComponent?: React.ReactNode;\n columns?: ColumnConfig[];\n}> = ({ shell, loadingComponent, columns }) => (\n <TableShell {...shell}>\n <TableBody data-testid=\"table-loading\">\n {loadingComponent || <LoadingSkeletonRows columns={columns} />}\n </TableBody>\n </TableShell>\n);\n\nconst TableEmptyState: React.FC<{\n shell: TableShellProps;\n emptyStateComponent?: React.ReactNode;\n emptyText: string;\n colSpan: number;\n}> = ({ shell, emptyStateComponent, emptyText, colSpan }) => (\n <TableShell {...shell}>\n <EmptyRow colSpan={colSpan}>\n {emptyStateComponent || <NoDataPlaceholder emptyText={emptyText} />}\n </EmptyRow>\n </TableShell>\n);\n\nexport const Table = React.forwardRef<globalThis.HTMLTableElement, TableProps>(\n (tableProps, ref) => {\n const resolved = { ...TABLE_DEFAULTS, ...definedProps(tableProps) } as TableProps;\n const {\n columns,\n data,\n responsive,\n loading,\n loadingComponent,\n emptyStateComponent,\n emptyText,\n children,\n } = resolved;\n\n const selection = useTableSelection({\n columns,\n data,\n responsive,\n columnPriorities: resolved.columnPriorities,\n selectedRows: resolved.selectedRows ?? [],\n rowKeyExtractor: resolved.rowKeyExtractor,\n onSelectionChange: resolved.onSelectionChange });\n\n // Only MUI's and the DOM's own props reach the `<table>` (FUT-2658).\n const rest = tableDomProps(tableProps);\n const renderer: RendererProps = { resolved, selection, innerRef: ref, rest };\n const finalColumns = responsive ? selection.visibleColumns : columns;\n const shell = buildShell({ ...renderer, finalColumns });\n\n if (loading) {\n return (\n <TableLoadingState shell={shell} loadingComponent={loadingComponent} columns={columns} />\n );\n }\n\n if (data && data.length === 0) {\n return (\n <TableEmptyState\n shell={shell}\n emptyStateComponent={emptyStateComponent}\n emptyText={emptyText}\n colSpan={finalColumns?.length || 1}\n />\n );\n }\n\n if (columns && data) return <AdvancedTable {...renderer} />;\n\n // Basic table (backward compatibility)\n return (\n <StyledTable\n ref={ref}\n customVariant={resolved.variant}\n stripeColor={resolved.stripeColor}\n glow={resolved.glow}\n pulse={resolved.pulse}\n hoverable={resolved.hoverable}\n density={resolved.density}\n stickyHeader={resolved.stickyHeader}\n {...rest}\n >\n {children}\n </StyledTable>\n );\n },\n);\n\nTable.displayName = 'Table';"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/Table/Table.helpers.ts"],"sourcesContent":["import type { TableProps as MuiTableProps } from '@mui/material/Table/index.js';\nimport type { Theme } from '@mui/material/styles/index.js';\nimport type React from 'react';\n\nimport { rem } from '../../../tokens/relative';\n\nimport type { TableProps } from './Table.types';\n\n/**\n * A virtualised row's height in design px: the caller's `rowHeight`, else 52.\n * Resolved here rather than in {@link TABLE_DEFAULTS} so the one number is read\n * where it is drawn (`rem`) and where the window is positioned with it (`remPx`).\n */\nexport const tableRowHeight = (rowHeight: number | undefined): number => rowHeight ?? 52;\n\n/** The scroll box's height: a number is design px, 400 unless the caller says otherwise. */\nconst scrollHeight = (theme: Theme, containerHeight: number | string | undefined): string => {\n const box = containerHeight || 400;\n return typeof box === 'number' ? rem(theme, box) : box;\n};\n\n/**\n * The table's one scroll container (FUT-2658): `containerHeight` tall\n * whenever it is set, or 400 when `virtualScrolling` is on and it is not,\n * holding the header and the body. `containerHeight` sizes the scroller with\n * or without `virtualScrolling` (FUT-2677) — no consumer relies on the old\n * virtual-only gate, and `stickyHeader` needs this box to stick inside.\n * Inline, so the height it was given reads back off the element. A\n * `containerHeight` of 0 counts as unset: a zero-height scroller shows nothing.\n */\nexport const scrollerStyle = (theme: Theme, p: TableProps): React.CSSProperties | undefined =>\n p.virtualScrolling || p.containerHeight\n ? { height: scrollHeight(theme, p.containerHeight), overflow: 'auto' }\n : undefined;\n\n/**\n * With `stickyHeader`, the scroller takes over the rounded clip the `<table>`\n * gives up (`tableStyles`, FUT-2677) — the caller's container owns it on the\n * basic (children) path, and the loading/empty shells get it too, so their\n * corners do not change between states.\n */\nexport const scrollerRadiusStyle = (\n theme: Theme,\n stickyHeader: boolean | undefined,\n): React.CSSProperties | undefined => (stickyHeader ? { borderRadius: theme.spacing(1) } : undefined);\n\n/** `scrollerStyle` and, with `stickyHeader`, the rounded clip it takes over. */\nexport const containerStyle = (theme: Theme, p: TableProps): React.CSSProperties | undefined => {\n const scroller = scrollerStyle(theme, p);\n const radius = scrollerRadiusStyle(theme, p.stickyHeader);\n return scroller || radius ? { ...scroller, ...radius } : undefined;\n};\n\n/**\n * Only a virtualised table needs its header measured — a plain one never\n * reads `scroll.headerPx`, so it gets no `ResizeObserver` either (FUT-2678).\n */\nexport const headerRefFor = (\n windowHeight: number | undefined,\n headRef: React.RefObject<globalThis.HTMLTableSectionElement | null>,\n): React.RefObject<globalThis.HTMLTableSectionElement | null> | undefined =>\n windowHeight ? headRef : undefined;\n\n/**\n * The window's height in design px when the body is virtualised — only a\n * numeric `containerHeight` virtualises; a string sizes the scroller alone.\n */\nexport const virtualHeight = (p: TableProps): number | undefined =>\n p.virtualScrolling && typeof p.containerHeight === 'number' && p.containerHeight > 0 &&\n tableRowHeight(p.rowHeight) > 0\n ? p.containerHeight\n : undefined;\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 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\n/** A key `Table` declares on top of MUI's own `TableProps`. */\ntype TableOwnKey = Exclude<keyof TableProps, keyof MuiTableProps>;\n\n/**\n * Every key {@link TableOwnKey} names. None is an HTML attribute: each is read\n * by the table and drawn by its parts, so none may reach the `<table>`\n * (FUT-2658). A `Record` over the key union makes the list exhaustive — a prop\n * added to `Table.types.ts` does not compile until it is named here.\n */\nconst TABLE_OWN_KEYS: Record<TableOwnKey, true> = {\n emptyText: true,\n variant: true,\n stripeColor: true,\n glow: true,\n pulse: true,\n hoverable: true,\n loading: true,\n onRowClick: true,\n onRowFocus: true,\n onRowBlur: true,\n density: true,\n selectable: true,\n selectedRows: true,\n onSelectionChange: true,\n rowKeyExtractor: true,\n sortable: true,\n sortConfig: true,\n onSortChange: true,\n filterable: true,\n filterConfig: true,\n onFilterChange: true,\n columns: true,\n data: true,\n virtualScrolling: true,\n rowHeight: true,\n overscan: true,\n responsive: true,\n columnPriorities: true,\n responsiveBreakpoints: true,\n showColumnToggle: true,\n containerHeight: true,\n loadingComponent: true,\n emptyStateComponent: true,\n keyboardNavigation: true,\n renderRow: true,\n renderCell: true,\n draggableRows: true,\n onRowsReorder: true,\n fixedColumns: true,\n rowStyleConfig: true,\n};\n\nconst NOT_FORWARDED = new Set<string>([...Object.keys(TABLE_OWN_KEYS), 'children']);\n\n/**\n * What the caller passed that is MUI's or the DOM's — `className`, `id`,\n * `style`, `aria-*`, `data-*`, DOM handlers, `sx`, `size`, `padding`,\n * `component` — for `MuiTable` to spread onto the `<table>`. `children` is\n * placed by the table itself.\n */\nexport const tableDomProps = (props: TableProps): Record<string, unknown> =>\n Object.fromEntries(Object.entries(props).filter(([key]) => !NOT_FORWARDED.has(key)));\n"],"mappings":";;;;;AAaO,IAAM,iBAAiB,CAAC,cAA0C,aAAa;AAGtF,IAAM,eAAe,CAAC,OAAc,oBAAyD;AAC3F,QAAM,MAAM,mBAAmB;AAC/B,SAAO,OAAO,QAAQ,WAAW,IAAI,OAAO,GAAG,IAAI;AACrD;AAWO,IAAM,gBAAgB,CAAC,OAAc,MAC1C,EAAE,oBAAoB,EAAE,kBACpB,EAAE,QAAQ,aAAa,OAAO,EAAE,eAAe,GAAG,UAAU,OAAO,IACnE;AAQC,IAAM,sBAAsB,CACjC,OACA,iBACqC,eAAe,EAAE,cAAc,MAAM,QAAQ,CAAC,EAAE,IAAI;AAGpF,IAAM,iBAAiB,CAAC,OAAc,MAAmD;AAC9F,QAAM,WAAW,cAAc,OAAO,CAAC;AACvC,QAAM,SAAS,oBAAoB,OAAO,EAAE,YAAY;AACxD,SAAO,YAAY,SAAS,EAAE,GAAG,UAAU,GAAG,OAAO,IAAI;AAC3D;AAMO,IAAM,eAAe,CAC1B,cACA,YAEA,eAAe,UAAU;AAMpB,IAAM,gBAAgB,CAAC,MAC5B,EAAE,oBAAoB,OAAO,EAAE,oBAAoB,YAAY,EAAE,kBAAkB,KACnF,eAAe,EAAE,SAAS,IAAI,IAC1B,EAAE,kBACF;AAEC,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,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;AAcF,IAAM,iBAA4C;AAAA,EAChD,WAAW;AAAA,EACX,SAAS;AAAA,EACT,aAAa;AAAA,EACb,MAAM;AAAA,EACN,OAAO;AAAA,EACP,WAAW;AAAA,EACX,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,YAAY;AAAA,EACZ,WAAW;AAAA,EACX,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,iBAAiB;AAAA,EACjB,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,YAAY;AAAA,EACZ,cAAc;AAAA,EACd,gBAAgB;AAAA,EAChB,SAAS;AAAA,EACT,MAAM;AAAA,EACN,kBAAkB;AAAA,EAClB,WAAW;AAAA,EACX,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,kBAAkB;AAAA,EAClB,uBAAuB;AAAA,EACvB,kBAAkB;AAAA,EAClB,iBAAiB;AAAA,EACjB,kBAAkB;AAAA,EAClB,qBAAqB;AAAA,EACrB,oBAAoB;AAAA,EACpB,WAAW;AAAA,EACX,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,eAAe;AAAA,EACf,cAAc;AAAA,EACd,gBAAgB;AAClB;AAEA,IAAM,gBAAgB,oBAAI,IAAY,CAAC,GAAG,OAAO,KAAK,cAAc,GAAG,UAAU,CAAC;AAQ3E,IAAM,gBAAgB,CAAC,UAC5B,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,OAAO,CAAC,CAAC,GAAG,MAAM,CAAC,cAAc,IAAI,GAAG,CAAC,CAAC;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/data-display/DataGrid/DataGrid.tsx"],"sourcesContent":["/**\n * `DataGrid` — the shell.\n *\n * Everything that is not \"which of the four renders is this, and what wraps the\n * table\" lives beside it: the state in `DataGrid.model.ts`, the client-mode row\n * pipeline in `DataGrid.rows.ts`, the cells and rows in `DataGrid.cells.tsx`,\n * the head/body in `DataGrid.body.tsx`, and the loading/error/empty renders in\n * `DataGrid.states.tsx`.\n *\n * All FOUR renders carry the caller's `data-testid`. It used to be applied only\n * on the populated one, so a grid whose first paint had no rows could not be\n * found by a test at all — see `DataGrid.states.tsx` for the full story.\n */\nimport Paper from '@mui/material/Paper/index.js';\nimport Table from '@mui/material/Table/index.js';\nimport TableContainer from '@mui/material/TableContainer/index.js';\nimport type React from 'react';\n\nimport { GridBody, GridHeader } from './DataGrid.body';\nimport { useDataGridModel } from './DataGrid.model';\nimport { DataGridEmpty, DataGridError, DataGridLoading } from './DataGrid.states';\nimport type { DataGridProps } from './DataGrid.types';\n\n/**\n * The chrome every render needs, with the defaults resolved ONCE.\n *\n * Extracted from the component body because a dozen destructuring defaults are\n * a dozen branches: the gate counted them, correctly, as complexity the render\n * did not need to carry.\n */\nfunction resolveChrome<T extends Record<string, unknown>>(props: DataGridProps<T>): {\n dataAttrs: Record<string, unknown>;\n placeholder: {\n dataTestId?: string;\n ariaLabel: string;\n className?: string;\n style?: React.CSSProperties;\n htmlProps: React.HTMLAttributes<HTMLElement>;\n };\n} {\n const { className, style, 'data-testid': dataTestId, ...rest } = props;\n const stickyHeader = props.stickyHeader ?? true;\n return {\n dataAttrs: {\n 'data-ui': 'datagrid',\n 'data-density': props.density ?? 'comfortable',\n 'data-size-mode': props.sizeMode ?? 'auto',\n 'data-virtual-rows': props.virtualizeRows ?? true,\n 'data-virtual-cols': props.virtualizeColumns ?? false,\n 'data-sticky-header': stickyHeader,\n },\n placeholder: {\n dataTestId,\n ariaLabel: props.ariaLabel ?? props.copy.gridLabel,\n className,\n style,\n // Only the DOM-safe leftovers reach the element: every grid-specific prop\n // is named in `GRID_ONLY_PROPS`, so this cannot smuggle `rows` onto a div.\n htmlProps: omitGridProps(rest as Record<string, unknown>),\n },\n };\n}\n\nexport const DataGrid = <T extends Record<string, unknown> = Record<string, unknown>>(\n props: DataGridProps<T>,\n): React.JSX.Element => {\n const model = useDataGridModel(props);\n const { dataAttrs, placeholder } = resolveChrome(props);\n\n if (props.loading) return <DataGridLoading {...placeholder} />;\n if (props.error) return <DataGridError {...placeholder} error={props.error} />;\n if (model.processedRows.length === 0) {\n return <DataGridEmpty {...placeholder} emptyState={props.emptyState} emptyText={props.emptyText} />;\n }\n\n const leadingColumns = (props.selection?.mode ?? 'none') !== 'none' ? 1 : 0;\n const totalColumns =\n model.visibleColumns.length + leadingColumns + (props.expansion ? 1 : 0);\n const section = { model, props, totalColumns };\n\n return (\n <Paper\n ref={model.containerRef}\n {...dataAttrs}\n data-testid={placeholder.dataTestId}\n className={placeholder.className}\n style={placeholder.style}\n role=\"grid\"\n aria-label={placeholder.ariaLabel}\n aria-description={props.ariaDescription}\n aria-rowcount={model.processedRows.length + 1} // +1 for the header row\n aria-colcount={totalColumns}\n sx={{ height: '100%', overflow: 'hidden', display: 'flex', flexDirection: 'column' }}\n {...placeholder.htmlProps}\n >\n <TableContainer\n sx={{ flex: 1, overflow: 'auto', position: 'relative' }}\n onScroll={model.onScroll}\n >\n <Table stickyHeader={props.stickyHeader ?? true}>\n <GridHeader {...section} />\n <GridBody {...section} />\n </Table>\n </TableContainer>\n </Paper>\n );\n};\n\n/**\n * The grid props that are NOT HTML attributes.\n *\n * `DataGridProps` extends `HTMLAttributes`, so the rest-spread carries the\n * grid's own configuration too. React would warn (or worse, serialize an array\n * of rows into an attribute) if any of it reached the DOM.\n *\n * Exported so a test can render a grid carrying every name on it and assert\n * none reaches the DOM — the check that would have caught `emptyText` missing.\n */\nexport const GRID_ONLY_PROPS = [\n 'copy',\n 'rows',\n 'columns',\n 'getRowId',\n 'sizeMode',\n 'density',\n 'rowHeight',\n 'headerHeight',\n 'footerHeight',\n 'selection',\n 'pagination',\n 'sorting',\n 'filtering',\n 'expansion',\n 'editing',\n 'virtualizeRows',\n 'virtualizeColumns',\n 'stickyHeader',\n 'stickyFooter',\n 'loading',\n 'error',\n 'emptyState',\n 'emptyText',\n 'onRequestData',\n 'ariaLabel',\n 'ariaDescription',\n] as const;\n\nfunction omitGridProps(rest: Record<string, unknown>): React.HTMLAttributes<HTMLElement> {\n const html: Record<string, unknown> = { ...rest };\n for (const key of GRID_ONLY_PROPS) delete html[key];\n return html as React.HTMLAttributes<HTMLElement>;\n}\n\nDataGrid.displayName = 'DataGrid';\n"],"mappings":";;;;;;;;;;;;;;AAaA,OAAO,WAAW;AAClB,OAAO,WAAW;AAClB,OAAO,oBAAoB;AAsDC,cA8BpB,YA9BoB;AAvC5B,SAAS,cAAiD,OASxD;AACA,QAAM,EAAE,WAAW,OAAO,eAAe,YAAY,GAAG,KAAK,IAAI;AACjE,QAAM,eAAe,MAAM,gBAAgB;AAC3C,SAAO;AAAA,IACL,WAAW;AAAA,MACT,WAAW;AAAA,MACX,gBAAgB,MAAM,WAAW;AAAA,MACjC,kBAAkB,MAAM,YAAY;AAAA,MACpC,qBAAqB,MAAM,kBAAkB;AAAA,MAC7C,qBAAqB,MAAM,qBAAqB;AAAA,MAChD,sBAAsB;AAAA,IACxB;AAAA,IACA,aAAa;AAAA,MACX;AAAA,MACA,WAAW,MAAM,aAAa,MAAM,KAAK;AAAA,MACzC;AAAA,MACA;AAAA;AAAA;AAAA,MAGA,WAAW,cAAc,IAA+B;AAAA,IAC1D;AAAA,EACF;AACF;AAEO,IAAM,WAAW,CACtB,UACsB;AACtB,QAAM,QAAQ,iBAAiB,KAAK;AACpC,QAAM,EAAE,WAAW,YAAY,IAAI,cAAc,KAAK;AAEtD,MAAI,MAAM,QAAS,QAAO,oBAAC,mBAAiB,GAAG,aAAa;AAC5D,MAAI,MAAM,MAAO,QAAO,oBAAC,iBAAe,GAAG,aAAa,OAAO,MAAM,OAAO;AAC5E,MAAI,MAAM,cAAc,WAAW,GAAG;AACpC,WAAO,oBAAC,iBAAe,GAAG,aAAa,YAAY,MAAM,YAAY,WAAW,MAAM,WAAW;AAAA,EACnG;AAEA,QAAM,kBAAkB,MAAM,WAAW,QAAQ,YAAY,SAAS,IAAI;AAC1E,QAAM,eACJ,MAAM,eAAe,SAAS,kBAAkB,MAAM,YAAY,IAAI;AACxE,QAAM,UAAU,EAAE,OAAO,OAAO,aAAa;AAE7C,SACE;AAAA,IAAC;AAAA;AAAA,MACC,KAAK,MAAM;AAAA,MACV,GAAG;AAAA,MACJ,eAAa,YAAY;AAAA,MACzB,WAAW,YAAY;AAAA,MACvB,OAAO,YAAY;AAAA,MACnB,MAAK;AAAA,MACL,cAAY,YAAY;AAAA,MACxB,oBAAkB,MAAM;AAAA,MACxB,iBAAe,MAAM,cAAc,SAAS;AAAA,MAC5C,iBAAe;AAAA,MACf,IAAI,EAAE,QAAQ,QAAQ,UAAU,UAAU,SAAS,QAAQ,eAAe,SAAS;AAAA,MAClF,GAAG,YAAY;AAAA,MAEhB;AAAA,QAAC;AAAA;AAAA,UACC,IAAI,EAAE,MAAM,GAAG,UAAU,QAAQ,UAAU,WAAW;AAAA,UACtD,UAAU,MAAM;AAAA,UAEhB,+BAAC,SAAM,cAAc,MAAM,gBAAgB,MACzC;AAAA,gCAAC,cAAY,GAAG,SAAS;AAAA,YACzB,oBAAC,YAAU,GAAG,SAAS;AAAA,aACzB;AAAA;AAAA,MACF;AAAA;AAAA,EACF;AAEJ;AAYO,IAAM,kBAAkB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,SAAS,cAAc,MAAkE;AACvF,QAAM,OAAgC,EAAE,GAAG,KAAK;AAChD,aAAW,OAAO,gBAAiB,QAAO,KAAK,GAAG;AAClD,SAAO;AACT;AAEA,SAAS,cAAc;","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\";\nimport { sxRem } from \"../../../tokens/relative\";\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 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, in design px: 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 its 180 design px × 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/**\n * The card grid's min column width in DESIGN px: the card's width at scale 1 —\n * 180 — times the zoom size multiplier. Drawn through `rem` where the track is\n * built (`cardGridTracks`), so it scales with the theme's type scale.\n */\nexport function cardMinWidthForZoom(zoom: number): number {\n return Math.round(180 * 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: sxRem(14) }} />\n <Box sx={{ width: sxRem(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: sxRem(20) }} />\n </Box>\n );\n}\n"],"mappings":"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","names":["default"]}