@12-apps/ui 6.39.7 → 6.39.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (368) hide show
  1. package/dist/_internal/components/data-display/Alert/Alert.js +2 -2
  2. package/dist/_internal/components/data-display/Alert/Alert.metrics.js +2 -2
  3. package/dist/_internal/components/data-display/Alert/Alert.styles.js +2 -2
  4. package/dist/_internal/components/data-display/Badge/Badge.js +2 -2
  5. package/dist/_internal/components/data-display/Badge/Badge.styles.js +2 -2
  6. package/dist/_internal/components/data-display/Badge/BadgeContent.js +2 -2
  7. package/dist/_internal/components/data-display/Banner/Banner.js +2 -2
  8. package/dist/_internal/components/data-display/Banner/Banner.styles.js +2 -2
  9. package/dist/_internal/components/data-display/CardKit/CardKebab.js +2 -2
  10. package/dist/_internal/components/data-display/CardKit/card-actions-context.js +2 -2
  11. package/dist/_internal/components/data-display/CardKit/use-remove-confirm.js +2 -2
  12. package/dist/_internal/components/data-display/CardKit/use-row-confirm.js +2 -2
  13. package/dist/_internal/components/data-display/Carousel/Carousel.chrome.js +2 -2
  14. package/dist/_internal/components/data-display/Carousel/Carousel.js +2 -2
  15. package/dist/_internal/components/data-display/Carousel/Carousel.parts.js +2 -2
  16. package/dist/_internal/components/data-display/Carousel/Carousel.styles.js +2 -2
  17. package/dist/_internal/components/data-display/Chart/Chart.js +2 -2
  18. package/dist/_internal/components/data-display/Chart/SpecChart.js +2 -2
  19. package/dist/_internal/components/data-display/Chart/chart-context.js +2 -2
  20. package/dist/_internal/components/data-display/Chart/chart-internals.js +2 -2
  21. package/dist/_internal/components/data-display/Chart/chart-renderers.js +2 -2
  22. package/dist/_internal/components/data-display/DataViews/DataViewsBoard.js +5 -5
  23. package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +21 -21
  24. package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +27 -27
  25. package/dist/_internal/components/data-display/DataViews/DeleteViewDialog.js +5 -5
  26. package/dist/_internal/components/data-display/DataViews/ManageViewsDialog.js +5 -5
  27. package/dist/_internal/components/data-display/DataViews/SaveViewModal.js +6 -6
  28. package/dist/_internal/components/data-display/DataViews/base-card.js +5 -5
  29. package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +7 -7
  30. package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +6 -6
  31. package/dist/_internal/components/data-display/DataViews/base-list-card.js +8 -8
  32. package/dist/_internal/components/data-display/DataViews/data-views-bar-controls.js +1 -1
  33. package/dist/_internal/components/data-display/DataViews/data-views-category-pill.js +1 -1
  34. package/dist/_internal/components/data-display/DataViews/data-views-columns-tab.js +5 -5
  35. package/dist/_internal/components/data-display/DataViews/data-views-columns.js +2 -2
  36. package/dist/_internal/components/data-display/DataViews/data-views-day-input.js +1 -1
  37. package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +8 -8
  38. package/dist/_internal/components/data-display/DataViews/data-views-display-tabs.js +5 -5
  39. package/dist/_internal/components/data-display/DataViews/data-views-empty.js +5 -5
  40. package/dist/_internal/components/data-display/DataViews/data-views-export.js +5 -5
  41. package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +1 -1
  42. package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +7 -7
  43. package/dist/_internal/components/data-display/DataViews/data-views-grid-helpers.js +2 -2
  44. package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +20 -20
  45. package/dist/_internal/components/data-display/DataViews/data-views-header-row.js +5 -5
  46. package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +7 -7
  47. package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +5 -5
  48. package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +6 -6
  49. package/dist/_internal/components/data-display/DataViews/data-views-number-input.js +1 -1
  50. package/dist/_internal/components/data-display/DataViews/data-views-pagination.js +1 -1
  51. package/dist/_internal/components/data-display/DataViews/data-views-range-pill.js +1 -1
  52. package/dist/_internal/components/data-display/DataViews/data-views-search.js +1 -1
  53. package/dist/_internal/components/data-display/DataViews/data-views-select-all-strip.js +5 -5
  54. package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +11 -11
  55. package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +8 -8
  56. package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +10 -10
  57. package/dist/_internal/components/data-display/DataViews/data-views-view-nav.js +5 -5
  58. package/dist/_internal/components/data-display/DataViews/save-view-preview.js +5 -5
  59. package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +2 -2
  60. package/dist/_internal/components/data-display/DescriptionItem/DescriptionItem.js +5 -5
  61. package/dist/_internal/components/data-display/FleetMap/FleetBody.js +1 -1
  62. package/dist/_internal/components/data-display/FleetMap/FleetCanvas.js +1 -1
  63. package/dist/_internal/components/data-display/FleetMap/FleetMap.js +2 -2
  64. package/dist/_internal/components/data-display/MapPreview/MapLayers.js +1 -1
  65. package/dist/_internal/components/data-display/MapPreview/MapPreview.js +1 -1
  66. package/dist/_internal/components/data-display/MapPreview/MapSearchBar.js +1 -1
  67. package/dist/_internal/components/data-display/Progress/Progress.js +5 -5
  68. package/dist/_internal/components/data-display/Progress/Progress.metrics.js +3 -3
  69. package/dist/_internal/components/data-display/Progress/Progress.styles.js +4 -4
  70. package/dist/_internal/components/data-display/Sheet/Sheet.body.js +2 -2
  71. package/dist/_internal/components/data-display/Sheet/Sheet.js +2 -2
  72. package/dist/_internal/components/data-display/Sheet/Sheet.styles.js +2 -2
  73. package/dist/_internal/components/data-display/Table/Table.hooks.js +1 -1
  74. package/dist/_internal/components/data-display/Table/Table.js +5 -4
  75. package/dist/_internal/components/data-display/Table/Table.styles.js +1 -1
  76. package/dist/_internal/components/data-display/Table/TableParts.hooks.js +2 -1
  77. package/dist/_internal/components/data-display/Table/TableParts.js +2 -1
  78. package/dist/_internal/components/data-display/index.js +12 -12
  79. package/dist/_internal/components/feedback/ConfirmAction/ConfirmButton.js +2 -2
  80. package/dist/_internal/components/feedback/NotificationStatusNotice/NotificationStatusNotice.js +2 -2
  81. package/dist/_internal/components/feedback/index.js +2 -2
  82. package/dist/_internal/components/form/AddressAutocomplete/AddressAutocomplete.js +1 -1
  83. package/dist/_internal/components/form/AddressAutocomplete/AddressAutocompleteField.js +1 -1
  84. package/dist/_internal/components/form/AddressAutocomplete/AddressFallbackField.js +1 -1
  85. package/dist/_internal/components/form/AddressAutocomplete/AddressInputField.js +1 -1
  86. package/dist/_internal/components/form/AddressAutocomplete/AddressTextField.js +1 -1
  87. package/dist/_internal/components/form/Autocomplete/Autocomplete.helpers.js +1 -1
  88. package/dist/_internal/components/form/Autocomplete/Autocomplete.js +6 -6
  89. package/dist/_internal/components/form/Autocomplete/Autocomplete.keys.js +2 -2
  90. package/dist/_internal/components/form/Autocomplete/Autocomplete.parts.js +3 -3
  91. package/dist/_internal/components/form/Autocomplete/useAutocomplete.js +3 -3
  92. package/dist/_internal/components/form/Button/Button.js +2 -2
  93. package/dist/_internal/components/form/Button/Button.styles.js +2 -2
  94. package/dist/_internal/components/form/CategorySelect/CategoryPanel.js +1 -1
  95. package/dist/_internal/components/form/CategorySelect/CategoryPanelFoot.js +1 -1
  96. package/dist/_internal/components/form/CategorySelect/CategoryPanelHead.js +1 -1
  97. package/dist/_internal/components/form/CategorySelect/CategoryPanelList.js +1 -1
  98. package/dist/_internal/components/form/CategorySelect/CategoryRows.js +1 -1
  99. package/dist/_internal/components/form/CategorySelect/CategorySelect.js +1 -1
  100. package/dist/_internal/components/form/CategorySelect/CategorySelect.styles.js +1 -1
  101. package/dist/_internal/components/form/CategorySelect/CategoryTrigger.js +1 -1
  102. package/dist/_internal/components/form/CepField/CepField.js +1 -1
  103. package/dist/_internal/components/form/Command/Command.js +2 -2
  104. package/dist/_internal/components/form/Command/Command.styles.js +2 -2
  105. package/dist/_internal/components/form/CreatableSelect/CreatableSelect.js +1 -1
  106. package/dist/_internal/components/form/DateRangePicker/DateRangePicker.hooks.js +1 -1
  107. package/dist/_internal/components/form/DateRangePicker/DateRangePicker.js +1 -1
  108. package/dist/_internal/components/form/DateRangePicker/DateRangePicker.range.js +1 -1
  109. package/dist/_internal/components/form/DateRangePicker/DateRangePickerFields.js +1 -1
  110. package/dist/_internal/components/form/Input/Input.js +1 -1
  111. package/dist/_internal/components/form/Input/Input.styles.js +1 -1
  112. package/dist/_internal/components/form/InputOTP/InputOTP.js +1 -1
  113. package/dist/_internal/components/form/InputOTP/InputOTP.styles.js +1 -1
  114. package/dist/_internal/components/form/Label/Label.js +2 -2
  115. package/dist/_internal/components/form/Label/Label.styles.js +2 -2
  116. package/dist/_internal/components/form/Menubar/Menubar.item.js +2 -2
  117. package/dist/_internal/components/form/Menubar/Menubar.js +2 -2
  118. package/dist/_internal/components/form/Menubar/Menubar.styles.js +2 -2
  119. package/dist/_internal/components/form/Menubar/Menubar.toolbar.js +2 -2
  120. package/dist/_internal/components/form/PhoneInput/PhoneInput.js +1 -1
  121. package/dist/_internal/components/form/RadioGroup/RadioGroup.js +1 -1
  122. package/dist/_internal/components/form/RadioGroup/RadioGroup.styles.js +1 -1
  123. package/dist/_internal/components/form/RadioGroup/RadioGroup.variants.js +1 -1
  124. package/dist/_internal/components/form/Select/Select.js +1 -1
  125. package/dist/_internal/components/form/Switch/Switch.js +2 -2
  126. package/dist/_internal/components/form/Switch/Switch.parts.js +2 -2
  127. package/dist/_internal/components/form/Switch/Switch.styles.js +2 -2
  128. package/dist/_internal/components/form/Textarea/Textarea.js +2 -2
  129. package/dist/_internal/components/form/Textarea/TextareaRichEditor.js +1 -1
  130. package/dist/_internal/components/form/Toggle/Toggle.js +1 -1
  131. package/dist/_internal/components/form/Toggle/Toggle.styles.js +1 -1
  132. package/dist/_internal/components/form/ToggleGroup/ToggleGroup.js +1 -1
  133. package/dist/_internal/components/form/index.js +8 -8
  134. package/dist/_internal/components/form/total-form/Fields/CategoryField.js +1 -1
  135. package/dist/_internal/components/form/total-form/Fields/CepField.js +1 -1
  136. package/dist/_internal/components/form/total-form/Fields/SelectField.js +1 -1
  137. package/dist/_internal/components/form/total-form/Fields/TextField.js +1 -1
  138. package/dist/_internal/components/form/total-form/Fields/ToggleField.js +1 -1
  139. package/dist/_internal/components/form/total-form/Fields/index.js +1 -1
  140. package/dist/_internal/components/form/total-form/SubmitButton.js +2 -2
  141. package/dist/_internal/components/index.js +21 -21
  142. package/dist/_internal/components/layout/Box/Box.js +5 -5
  143. package/dist/_internal/components/layout/ContentToolbar/ColumnsMenu.js +1 -1
  144. package/dist/_internal/components/layout/ContentToolbar/FilterTrigger.js +1 -1
  145. package/dist/_internal/components/layout/ContentToolbar/MultiSelectDropdown.js +1 -1
  146. package/dist/_internal/components/layout/ContentToolbar/MultiSelectTriggers.js +1 -1
  147. package/dist/_internal/components/layout/ContentToolbar/SavedViewsMenu.js +1 -1
  148. package/dist/_internal/components/layout/ContentToolbar/SortByDropdown.js +1 -1
  149. package/dist/_internal/components/layout/ContentToolbar/ViewSelector.js +1 -1
  150. package/dist/_internal/components/layout/Stack/Stack.js +6 -6
  151. package/dist/_internal/components/layout/TableFilter/TableFilter.js +1 -1
  152. package/dist/_internal/components/layout/index.js +1 -1
  153. package/dist/_internal/components/navigation/AppHeader/AppHeader.details.js +2 -2
  154. package/dist/_internal/components/navigation/AppHeader/AppHeader.identity.js +2 -2
  155. package/dist/_internal/components/navigation/Pagination/Pagination.js +1 -1
  156. package/dist/_internal/components/navigation/Pagination/PaginationParts.js +1 -1
  157. package/dist/_internal/components/navigation/Tabs/Tabs.js +1 -1
  158. package/dist/_internal/components/navigation/Tabs/Tabs.styles.js +1 -1
  159. package/dist/_internal/components/navigation/index.js +2 -2
  160. package/dist/_internal/components/typography/Heading/Heading.js +5 -5
  161. package/dist/_internal/components/typography/Heading/Heading.metrics.js +3 -3
  162. package/dist/_internal/components/typography/Heading/Heading.styles.js +4 -4
  163. package/dist/_internal/components/typography/Text/Text.js +4 -4
  164. package/dist/_internal/components/typography/Text/Text.metrics.js +3 -3
  165. package/dist/_internal/components/typography/index.js +7 -7
  166. package/dist/_internal/components/utility/WorkflowStep/WorkflowStep.helpers.js +2 -2
  167. package/dist/_internal/components/utility/WorkflowStep/WorkflowStep.js +2 -2
  168. package/dist/_internal/components/utility/WorkflowStep/WorkflowStep.parts.js +2 -2
  169. package/dist/_internal/components/utility/WorkflowStep/WorkflowStepRow.js +2 -2
  170. package/dist/_internal/components/utility/index.js +2 -2
  171. package/dist/_internal/icons/Icon.js +5 -5
  172. package/dist/_internal/provider/UiProvider.js +4 -4
  173. package/dist/_internal/provider/mui-bridge.js +3 -3
  174. package/dist/_internal/provider/use-ui-theme.js +4 -4
  175. package/dist/_internal/social-login-button/social-login-button.js +8 -8
  176. package/dist/_internal/tokens/field-height.js +1 -1
  177. package/dist/_internal/tokens/theme.js +2 -2
  178. package/dist/_internal/user-avatar/user-avatar.js +5 -5
  179. package/dist/charts.js +2 -2
  180. package/dist/{chunk-OAEYCKBN.js → chunk-2K7WPHI3.js} +2 -2
  181. package/dist/{chunk-7RRXLCOO.js → chunk-2KWYNFVE.js} +4 -4
  182. package/dist/{chunk-JBI7ITL2.js → chunk-3BNQDOHC.js} +2 -2
  183. package/dist/{chunk-YCCY77W5.js → chunk-3IF3I3FI.js} +2 -2
  184. package/dist/{chunk-3KREF4ZF.js → chunk-3PQ5MZMJ.js} +2 -2
  185. package/dist/{chunk-L7NQCLFU.js → chunk-3RHZBO7L.js} +2 -2
  186. package/dist/{chunk-A4OCNJWW.js → chunk-3UABIEP3.js} +2 -2
  187. package/dist/{chunk-XIG3DXXX.js → chunk-5L7N5HER.js} +2 -2
  188. package/dist/{chunk-6WBKOM5K.js → chunk-7DK6YVJU.js} +2 -2
  189. package/dist/{chunk-ASYR22BJ.js → chunk-7XGHJD75.js} +3 -3
  190. package/dist/{chunk-OB56SZGL.js → chunk-B7CNP5HW.js} +2 -2
  191. package/dist/{chunk-PE4ZW3IA.js → chunk-BLW6KLDR.js} +4 -4
  192. package/dist/{chunk-POV2KL2P.js → chunk-CCK7FB2V.js} +16 -2
  193. package/dist/chunk-CCK7FB2V.js.map +1 -0
  194. package/dist/{chunk-QKMJUOVH.js → chunk-CRG24BGI.js} +2 -2
  195. package/dist/{chunk-LKMMJKXU.js → chunk-CYZZHWNK.js} +2 -2
  196. package/dist/{chunk-PH36XEB3.js → chunk-DQZCQV2C.js} +4 -4
  197. package/dist/{chunk-DUNG7D4B.js → chunk-DSF4VT7L.js} +1 -1
  198. package/dist/{chunk-YOJASBHJ.js → chunk-DYNJQ3HJ.js} +3 -3
  199. package/dist/{chunk-CXMVNYBY.js → chunk-GEB4WSZH.js} +3 -3
  200. package/dist/{chunk-RIF6L54B.js → chunk-H224XFFD.js} +2 -2
  201. package/dist/{chunk-BN742L2M.js → chunk-H6AWKLOV.js} +13 -5
  202. package/dist/chunk-H6AWKLOV.js.map +1 -0
  203. package/dist/{chunk-362OGE5J.js → chunk-HBRKA67N.js} +3 -3
  204. package/dist/{chunk-3RMDIO4G.js → chunk-I5T5PQQW.js} +2 -2
  205. package/dist/{chunk-IJFAF3A7.js → chunk-IWEUSZY3.js} +3 -3
  206. package/dist/{chunk-SZ3YFVO5.js → chunk-JGJFL3PF.js} +4 -4
  207. package/dist/{chunk-XEYLYUDM.js → chunk-JH5BKA3Y.js} +2 -2
  208. package/dist/{chunk-U4O47P6S.js → chunk-JQ3D5QP6.js} +2 -2
  209. package/dist/{chunk-XBHQT4BQ.js → chunk-JXS56EW5.js} +3 -3
  210. package/dist/{chunk-XBHQT4BQ.js.map → chunk-JXS56EW5.js.map} +1 -1
  211. package/dist/{chunk-5HQNHZ6Z.js → chunk-LH7KMYHC.js} +3 -4
  212. package/dist/chunk-LH7KMYHC.js.map +1 -0
  213. package/dist/{chunk-X4ZRPE37.js → chunk-MBHWVRV5.js} +2 -2
  214. package/dist/{chunk-JQWAANGN.js → chunk-OOCREE37.js} +2 -2
  215. package/dist/{chunk-R2XVTUVR.js → chunk-OQRG34VG.js} +2 -2
  216. package/dist/{chunk-RUEKY3VR.js → chunk-P52LYD6S.js} +2 -2
  217. package/dist/{chunk-JDFTIK4L.js → chunk-PELRSZFU.js} +2 -2
  218. package/dist/{chunk-CTKQCKRD.js → chunk-PK6TRXV4.js} +2 -2
  219. package/dist/{chunk-RGT6DM5W.js → chunk-PX6TWS5T.js} +68 -42
  220. package/dist/chunk-PX6TWS5T.js.map +1 -0
  221. package/dist/{chunk-3OBC6BOV.js → chunk-QFTBXHOY.js} +2 -2
  222. package/dist/{chunk-QTNHAX2Z.js → chunk-QS2DCLG6.js} +3 -3
  223. package/dist/{chunk-MYWROMGO.js → chunk-QU3JX53V.js} +3 -3
  224. package/dist/{chunk-5JSRM7WC.js → chunk-RB3X6CEE.js} +2 -2
  225. package/dist/{chunk-DW6F7354.js → chunk-S36NC22G.js} +2 -2
  226. package/dist/{chunk-6N4AA2Y7.js → chunk-SNYJSACF.js} +2 -2
  227. package/dist/{chunk-BOGTTXPA.js → chunk-TT3HZRU6.js} +9 -8
  228. package/dist/chunk-TT3HZRU6.js.map +1 -0
  229. package/dist/{chunk-TFMDZQK4.js → chunk-TTZPO345.js} +4 -4
  230. package/dist/{chunk-UITQ7KMK.js → chunk-TYNK662L.js} +3 -3
  231. package/dist/{chunk-YBH4SPMM.js → chunk-URHX4FAQ.js} +2 -2
  232. package/dist/{chunk-4CXCOR6F.js → chunk-V2UZQS2K.js} +2 -2
  233. package/dist/{chunk-VIRYHNEM.js → chunk-WY5PBZ7Q.js} +2 -2
  234. package/dist/{chunk-KAIUDBHM.js → chunk-WYUBTRRV.js} +6 -6
  235. package/dist/{chunk-ISFFETTG.js → chunk-XG7NTGUH.js} +3 -3
  236. package/dist/{chunk-GWEENWIS.js → chunk-Y2HPRRVP.js} +2 -2
  237. package/dist/{chunk-5CQ5HYJW.js → chunk-YMG4CXGI.js} +3 -3
  238. package/dist/{chunk-UGGJ3KDT.js → chunk-YTINPQKU.js} +2 -2
  239. package/dist/{chunk-U3PPLAFB.js → chunk-ZN6YATOG.js} +2 -2
  240. package/dist/{chunk-WHQKH57H.js → chunk-ZXIUIIUE.js} +2 -2
  241. package/dist/data-display/Alert.js +2 -2
  242. package/dist/data-display/Badge.js +2 -2
  243. package/dist/data-display/Banner.js +2 -2
  244. package/dist/data-display/CardKit.js +2 -2
  245. package/dist/data-display/Carousel.js +2 -2
  246. package/dist/data-display/Chart.js +2 -2
  247. package/dist/data-display/DataViews.js +32 -32
  248. package/dist/data-display/DescriptionItem.js +5 -5
  249. package/dist/data-display/FleetMap.js +2 -2
  250. package/dist/data-display/MapPreview.js +1 -1
  251. package/dist/data-display/Progress.js +5 -5
  252. package/dist/data-display/Sheet.js +2 -2
  253. package/dist/data-display/Table.js +5 -4
  254. package/dist/feedback/ConfirmAction.js +2 -2
  255. package/dist/feedback/NotificationStatusNotice.js +2 -2
  256. package/dist/form/AddressAutocomplete.js +1 -1
  257. package/dist/form/Autocomplete.js +6 -6
  258. package/dist/form/Button.js +2 -2
  259. package/dist/form/CategorySelect.js +1 -1
  260. package/dist/form/CepField.js +1 -1
  261. package/dist/form/Command.js +2 -2
  262. package/dist/form/CreatableSelect.js +1 -1
  263. package/dist/form/DateRangePicker.js +1 -1
  264. package/dist/form/Input.js +1 -1
  265. package/dist/form/InputOTP.js +1 -1
  266. package/dist/form/Label.js +2 -2
  267. package/dist/form/Menubar.js +2 -2
  268. package/dist/form/PhoneInput.js +1 -1
  269. package/dist/form/RadioGroup.js +1 -1
  270. package/dist/form/Select.js +1 -1
  271. package/dist/form/Switch.js +2 -2
  272. package/dist/form/Textarea.js +2 -2
  273. package/dist/form/Toggle.js +1 -1
  274. package/dist/form/ToggleGroup.js +1 -1
  275. package/dist/form/total-form.js +2 -2
  276. package/dist/icons.js +5 -5
  277. package/dist/layout/Box.js +5 -5
  278. package/dist/layout/ContentToolbar.js +1 -1
  279. package/dist/layout/Stack.js +6 -6
  280. package/dist/layout/TableFilter.js +1 -1
  281. package/dist/navigation/AppHeader.js +2 -2
  282. package/dist/navigation/Pagination.js +1 -1
  283. package/dist/navigation/Tabs.js +1 -1
  284. package/dist/provider.js +5 -5
  285. package/dist/social-login-button.js +8 -8
  286. package/dist/tokens.js +4 -4
  287. package/dist/types/components/data-display/Table/Table.d.ts.map +1 -1
  288. package/dist/types/components/data-display/Table/Table.hooks.d.ts +3 -2
  289. package/dist/types/components/data-display/Table/Table.hooks.d.ts.map +1 -1
  290. package/dist/types/components/data-display/Table/Table.styles.d.ts +3 -1
  291. package/dist/types/components/data-display/Table/Table.styles.d.ts.map +1 -1
  292. package/dist/types/components/data-display/Table/Table.types.d.ts +6 -4
  293. package/dist/types/components/data-display/Table/Table.types.d.ts.map +1 -1
  294. package/dist/types/components/data-display/Table/TableParts.d.ts +2 -3
  295. package/dist/types/components/data-display/Table/TableParts.d.ts.map +1 -1
  296. package/dist/types/components/data-display/Table/TableParts.hooks.d.ts +6 -2
  297. package/dist/types/components/data-display/Table/TableParts.hooks.d.ts.map +1 -1
  298. package/dist/types/components/form/Autocomplete/Autocomplete.helpers.d.ts +16 -3
  299. package/dist/types/components/form/Autocomplete/Autocomplete.helpers.d.ts.map +1 -1
  300. package/dist/types/components/form/Autocomplete/Autocomplete.parts.d.ts.map +1 -1
  301. package/dist/typography/Heading.js +5 -5
  302. package/dist/typography/Text.js +4 -4
  303. package/dist/user-avatar.js +5 -5
  304. package/dist/utility/WorkflowStep.js +2 -2
  305. package/package.json +1 -1
  306. package/src/components/data-display/Table/Table.hooks.ts +5 -4
  307. package/src/components/data-display/Table/Table.md +6 -0
  308. package/src/components/data-display/Table/Table.styles.ts +28 -1
  309. package/src/components/data-display/Table/Table.tsx +6 -4
  310. package/src/components/data-display/Table/Table.types.ts +6 -4
  311. package/src/components/data-display/Table/TableParts.hooks.tsx +23 -19
  312. package/src/components/data-display/Table/TableParts.tsx +112 -49
  313. package/src/components/form/Autocomplete/Autocomplete.helpers.ts +23 -5
  314. package/src/components/form/Autocomplete/Autocomplete.parts.tsx +17 -3
  315. package/dist/chunk-5HQNHZ6Z.js.map +0 -1
  316. package/dist/chunk-BN742L2M.js.map +0 -1
  317. package/dist/chunk-BOGTTXPA.js.map +0 -1
  318. package/dist/chunk-POV2KL2P.js.map +0 -1
  319. package/dist/chunk-RGT6DM5W.js.map +0 -1
  320. /package/dist/{chunk-OAEYCKBN.js.map → chunk-2K7WPHI3.js.map} +0 -0
  321. /package/dist/{chunk-7RRXLCOO.js.map → chunk-2KWYNFVE.js.map} +0 -0
  322. /package/dist/{chunk-JBI7ITL2.js.map → chunk-3BNQDOHC.js.map} +0 -0
  323. /package/dist/{chunk-YCCY77W5.js.map → chunk-3IF3I3FI.js.map} +0 -0
  324. /package/dist/{chunk-3KREF4ZF.js.map → chunk-3PQ5MZMJ.js.map} +0 -0
  325. /package/dist/{chunk-L7NQCLFU.js.map → chunk-3RHZBO7L.js.map} +0 -0
  326. /package/dist/{chunk-A4OCNJWW.js.map → chunk-3UABIEP3.js.map} +0 -0
  327. /package/dist/{chunk-XIG3DXXX.js.map → chunk-5L7N5HER.js.map} +0 -0
  328. /package/dist/{chunk-6WBKOM5K.js.map → chunk-7DK6YVJU.js.map} +0 -0
  329. /package/dist/{chunk-ASYR22BJ.js.map → chunk-7XGHJD75.js.map} +0 -0
  330. /package/dist/{chunk-OB56SZGL.js.map → chunk-B7CNP5HW.js.map} +0 -0
  331. /package/dist/{chunk-PE4ZW3IA.js.map → chunk-BLW6KLDR.js.map} +0 -0
  332. /package/dist/{chunk-QKMJUOVH.js.map → chunk-CRG24BGI.js.map} +0 -0
  333. /package/dist/{chunk-LKMMJKXU.js.map → chunk-CYZZHWNK.js.map} +0 -0
  334. /package/dist/{chunk-PH36XEB3.js.map → chunk-DQZCQV2C.js.map} +0 -0
  335. /package/dist/{chunk-DUNG7D4B.js.map → chunk-DSF4VT7L.js.map} +0 -0
  336. /package/dist/{chunk-YOJASBHJ.js.map → chunk-DYNJQ3HJ.js.map} +0 -0
  337. /package/dist/{chunk-CXMVNYBY.js.map → chunk-GEB4WSZH.js.map} +0 -0
  338. /package/dist/{chunk-RIF6L54B.js.map → chunk-H224XFFD.js.map} +0 -0
  339. /package/dist/{chunk-362OGE5J.js.map → chunk-HBRKA67N.js.map} +0 -0
  340. /package/dist/{chunk-3RMDIO4G.js.map → chunk-I5T5PQQW.js.map} +0 -0
  341. /package/dist/{chunk-IJFAF3A7.js.map → chunk-IWEUSZY3.js.map} +0 -0
  342. /package/dist/{chunk-SZ3YFVO5.js.map → chunk-JGJFL3PF.js.map} +0 -0
  343. /package/dist/{chunk-XEYLYUDM.js.map → chunk-JH5BKA3Y.js.map} +0 -0
  344. /package/dist/{chunk-U4O47P6S.js.map → chunk-JQ3D5QP6.js.map} +0 -0
  345. /package/dist/{chunk-X4ZRPE37.js.map → chunk-MBHWVRV5.js.map} +0 -0
  346. /package/dist/{chunk-JQWAANGN.js.map → chunk-OOCREE37.js.map} +0 -0
  347. /package/dist/{chunk-R2XVTUVR.js.map → chunk-OQRG34VG.js.map} +0 -0
  348. /package/dist/{chunk-RUEKY3VR.js.map → chunk-P52LYD6S.js.map} +0 -0
  349. /package/dist/{chunk-JDFTIK4L.js.map → chunk-PELRSZFU.js.map} +0 -0
  350. /package/dist/{chunk-CTKQCKRD.js.map → chunk-PK6TRXV4.js.map} +0 -0
  351. /package/dist/{chunk-3OBC6BOV.js.map → chunk-QFTBXHOY.js.map} +0 -0
  352. /package/dist/{chunk-QTNHAX2Z.js.map → chunk-QS2DCLG6.js.map} +0 -0
  353. /package/dist/{chunk-MYWROMGO.js.map → chunk-QU3JX53V.js.map} +0 -0
  354. /package/dist/{chunk-5JSRM7WC.js.map → chunk-RB3X6CEE.js.map} +0 -0
  355. /package/dist/{chunk-DW6F7354.js.map → chunk-S36NC22G.js.map} +0 -0
  356. /package/dist/{chunk-6N4AA2Y7.js.map → chunk-SNYJSACF.js.map} +0 -0
  357. /package/dist/{chunk-TFMDZQK4.js.map → chunk-TTZPO345.js.map} +0 -0
  358. /package/dist/{chunk-UITQ7KMK.js.map → chunk-TYNK662L.js.map} +0 -0
  359. /package/dist/{chunk-YBH4SPMM.js.map → chunk-URHX4FAQ.js.map} +0 -0
  360. /package/dist/{chunk-4CXCOR6F.js.map → chunk-V2UZQS2K.js.map} +0 -0
  361. /package/dist/{chunk-VIRYHNEM.js.map → chunk-WY5PBZ7Q.js.map} +0 -0
  362. /package/dist/{chunk-KAIUDBHM.js.map → chunk-WYUBTRRV.js.map} +0 -0
  363. /package/dist/{chunk-ISFFETTG.js.map → chunk-XG7NTGUH.js.map} +0 -0
  364. /package/dist/{chunk-GWEENWIS.js.map → chunk-Y2HPRRVP.js.map} +0 -0
  365. /package/dist/{chunk-5CQ5HYJW.js.map → chunk-YMG4CXGI.js.map} +0 -0
  366. /package/dist/{chunk-UGGJ3KDT.js.map → chunk-YTINPQKU.js.map} +0 -0
  367. /package/dist/{chunk-U3PPLAFB.js.map → chunk-ZN6YATOG.js.map} +0 -0
  368. /package/dist/{chunk-WHQKH57H.js.map → chunk-ZXIUIIUE.js.map} +0 -0
@@ -1,15 +1,15 @@
1
1
  import "../chunk-VUHLNYAE.js";
2
2
  import {
3
3
  Text
4
- } from "../chunk-YBH4SPMM.js";
5
- import "../chunk-U3PPLAFB.js";
4
+ } from "../chunk-URHX4FAQ.js";
5
+ import "../chunk-ZN6YATOG.js";
6
6
  import "../chunk-TYJR4GOF.js";
7
- import "../chunk-PE4ZW3IA.js";
7
+ import "../chunk-BLW6KLDR.js";
8
8
  import "../chunk-2BYKTBDL.js";
9
9
  import "../chunk-AG66JBNH.js";
10
10
  import "../chunk-FZXKH2ZT.js";
11
- import "../chunk-PZBK3F52.js";
12
11
  import "../chunk-26X4CZVR.js";
12
+ import "../chunk-PZBK3F52.js";
13
13
  import "../chunk-6JAIFIPW.js";
14
14
  import "../chunk-YKCAJ2TN.js";
15
15
  import "../chunk-PZ5AY32C.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  UserAvatar,
3
3
  UserMenu
4
- } from "./chunk-JQWAANGN.js";
4
+ } from "./chunk-OOCREE37.js";
5
5
  import "./chunk-UDQSIRAP.js";
6
6
  import "./chunk-EMEXXAQI.js";
7
7
  import "./chunk-Y6C4MYZE.js";
@@ -19,19 +19,19 @@ import "./chunk-2EAAWOZ2.js";
19
19
  import "./chunk-4WNFOBTH.js";
20
20
  import "./chunk-LN46DSMF.js";
21
21
  import "./chunk-TAMIZE4Q.js";
22
- import "./chunk-YBH4SPMM.js";
23
- import "./chunk-U3PPLAFB.js";
22
+ import "./chunk-URHX4FAQ.js";
23
+ import "./chunk-ZN6YATOG.js";
24
24
  import "./chunk-TYJR4GOF.js";
25
25
  import "./chunk-CGO452DC.js";
26
26
  import "./chunk-GDN2LUTZ.js";
27
27
  import "./chunk-7FDU3FIN.js";
28
28
  import "./chunk-EPEJMTCQ.js";
29
- import "./chunk-PE4ZW3IA.js";
29
+ import "./chunk-BLW6KLDR.js";
30
30
  import "./chunk-2BYKTBDL.js";
31
31
  import "./chunk-AG66JBNH.js";
32
32
  import "./chunk-FZXKH2ZT.js";
33
- import "./chunk-PZBK3F52.js";
34
33
  import "./chunk-26X4CZVR.js";
34
+ import "./chunk-PZBK3F52.js";
35
35
  import "./chunk-FQ6UW7IY.js";
36
36
  import "./chunk-6JAIFIPW.js";
37
37
  import "./chunk-N3GAFIXG.js";
@@ -12,12 +12,12 @@ import "../chunk-CGO452DC.js";
12
12
  import "../chunk-GDN2LUTZ.js";
13
13
  import "../chunk-7FDU3FIN.js";
14
14
  import "../chunk-EPEJMTCQ.js";
15
- import "../chunk-PE4ZW3IA.js";
15
+ import "../chunk-BLW6KLDR.js";
16
16
  import "../chunk-2BYKTBDL.js";
17
17
  import "../chunk-AG66JBNH.js";
18
18
  import "../chunk-FZXKH2ZT.js";
19
- import "../chunk-PZBK3F52.js";
20
19
  import "../chunk-26X4CZVR.js";
20
+ import "../chunk-PZBK3F52.js";
21
21
  import "../chunk-FQ6UW7IY.js";
22
22
  import "../chunk-6JAIFIPW.js";
23
23
  import "../chunk-N3GAFIXG.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/ui",
3
- "version": "6.39.7",
3
+ "version": "6.39.9",
4
4
  "license": "MIT",
5
5
  "packageManager": "pnpm@10.34.5",
6
6
  "type": "module",
@@ -2,15 +2,16 @@ import { useTheme } from '@mui/material/styles/index.js';
2
2
  import useMediaQuery from '@mui/material/useMediaQuery/index.js';
3
3
  import { useCallback, useEffect, useMemo, useState } from 'react';
4
4
 
5
- import { rem, remPx } from '../../../tokens/relative';
5
+ import { remPx } from '../../../tokens/relative';
6
6
 
7
7
  import type { ColumnConfig, TableProps, VirtualWindow } from './Table.types';
8
8
 
9
9
  /**
10
10
  * The virtual window. `rowHeight` and `containerHeight` are design px: the
11
11
  * window is computed in the px `scrollTop` is measured in (`remPx`), and what it
12
- * hands back to draw with stays in design px (`offsetY`) or is CSS already
13
- * (`totalHeight`), so the rows and the window share one pitch at any type scale.
12
+ * hands back to draw with stays in design px (`offsetY`, `trailingPx` — the
13
+ * spacer rows either side of the window), so the rows and the window share one
14
+ * pitch at any type scale.
14
15
  *
15
16
  * The scroller holds the header as well as the body, so the `<tbody>` starts
16
17
  * the header's height into it. `handleScroll` measures that height from
@@ -44,8 +45,8 @@ export const useVirtualScrolling = (
44
45
  startIndex: start,
45
46
  endIndex: end,
46
47
  items: data.slice(start, end),
47
- totalHeight: rem(theme, data.length * rowHeight),
48
48
  offsetY: start * rowHeight,
49
+ trailingPx: (data.length - end) * rowHeight,
49
50
  };
50
51
  }, [data, rowHeight, containerHeight, scroll, overscan, theme]);
51
52
 
@@ -127,6 +127,12 @@ Handle large datasets efficiently:
127
127
  />
128
128
  ```
129
129
 
130
+ Only a numeric `containerHeight` virtualises; a string only sizes the scroll box. On the virtual path:
131
+
132
+ - **Every row is exactly `rowHeight`** (default 52), whatever the `density`: the density still sets the header and the font size, but not the body's row height or vertical padding. A cell's content is centred vertically and clipped — taller or wider content does not grow the row — so pick a `rowHeight` the tallest cell fits in.
133
+ - **Column widths come from the header** (`table-layout: fixed`): a column's `width`, with the columns that declare none sharing what is left. They hold still while rows scroll in and out. **`minWidth` is ignored** on this path; give a column that must not shrink a `width` its content and the density's side padding fit in. With `selectable`, the checkbox column is MUI's 48 wide with MUI's own checkbox padding.
134
+ - The rows outside the window are two `aria-hidden` spacer rows at the top and bottom of the `<tbody>`, so `striped` stripes follow the mounted rows rather than the data index.
135
+
130
136
  ### Responsive Design
131
137
  Automatically hide/show columns based on viewport:
132
138
 
@@ -110,6 +110,29 @@ type VariantArgs = {
110
110
  const tableVariantStyles = (args: VariantArgs, customVariant?: string): CSSObject =>
111
111
  customVariant ? (TABLE_VARIANTS[customVariant]?.(args) ?? {}) : {};
112
112
 
113
+ /**
114
+ * A virtualised table (FUT-2668). Fixed layout takes the column widths from the
115
+ * header — a column's declared `width`, the rest sharing what is left — so they
116
+ * hold still while different rows mount (it ignores a column's `minWidth`). A
117
+ * body cell drops its vertical padding and the density's height: the pitch is
118
+ * `rowHeight`, and the cell's content wrapper is exactly that tall.
119
+ *
120
+ * The checkbox column is MUI's 48 wide, and fixed layout holds it there. The
121
+ * density's side padding would leave its checkbox 16 of that and clip it in the
122
+ * body, so it keeps MUI's own checkbox padding (4 on the left, none on the
123
+ * right), in the header and the body alike. After the sticky header's rule,
124
+ * which it would otherwise lose to.
125
+ */
126
+ const virtualisedStyles = (theme: Theme): CSSObject => ({
127
+ tableLayout: 'fixed',
128
+ '& .MuiTableBody-root .MuiTableCell-root': {
129
+ paddingTop: 0,
130
+ paddingBottom: 0,
131
+ height: 'auto' },
132
+ '& .MuiTableHead-root .MuiTableCell-paddingCheckbox, & .MuiTableBody-root .MuiTableCell-paddingCheckbox': {
133
+ paddingLeft: rem(theme, 4),
134
+ paddingRight: 0 } });
135
+
113
136
  // Sticky headers and row hover are independent of the variant.
114
137
  const stickyHeaderStyles = (
115
138
  theme: Theme,
@@ -183,7 +206,8 @@ export const tableStyles = ({
183
206
  hoverable,
184
207
  density,
185
208
  stickyHeader,
186
- stripeColor = 'neutral' }: {
209
+ stripeColor = 'neutral',
210
+ virtualised }: {
187
211
  theme: Theme;
188
212
  customVariant?: string;
189
213
  glow?: boolean;
@@ -192,6 +216,8 @@ export const tableStyles = ({
192
216
  density?: TableDensity;
193
217
  stickyHeader?: boolean;
194
218
  stripeColor?: TableStripeColor;
219
+ /** The body is a virtual window, drawn at `rowHeight`. */
220
+ virtualised?: boolean;
195
221
  }): CSSObject => {
196
222
  const densityConfig = getDensityConfig(theme, density);
197
223
 
@@ -212,6 +238,7 @@ export const tableStyles = ({
212
238
  ...(stickyHeader ? stickyHeaderStyles(theme, densityConfig) : {}),
213
239
  ...(hoverable ? hoverableRowStyles(theme) : {}),
214
240
  ...emphasisStyles(theme, glow, pulse),
241
+ ...(virtualised ? virtualisedStyles(theme) : {}),
215
242
 
216
243
 
217
244
  // Variant styles
@@ -37,7 +37,7 @@ import { rem } from '../../../tokens/relative';
37
37
  // Helper function to get stripe color from theme
38
38
  const StyledTable = styled(MuiTable, {
39
39
  shouldForwardProp: (prop) =>
40
- !['customVariant', 'glow', 'pulse', 'hoverable', 'density', 'stickyHeader', 'stripeColor'].includes(prop as string) })<{
40
+ !['customVariant', 'glow', 'pulse', 'hoverable', 'density', 'stickyHeader', 'stripeColor', 'virtualised'].includes(prop as string) })<{
41
41
  customVariant?: string;
42
42
  glow?: boolean;
43
43
  pulse?: boolean;
@@ -45,7 +45,8 @@ const StyledTable = styled(MuiTable, {
45
45
  density?: TableDensity;
46
46
  stickyHeader?: boolean;
47
47
  stripeColor?: TableStripeColor;
48
- }>(({ theme, customVariant, glow, pulse, hoverable, density, stickyHeader, stripeColor = 'neutral' }) => {
48
+ virtualised?: boolean;
49
+ }>(({ theme, customVariant, glow, pulse, hoverable, density, stickyHeader, stripeColor = 'neutral', virtualised }) => {
49
50
  return tableStyles({
50
51
  theme,
51
52
  customVariant,
@@ -54,7 +55,8 @@ const StyledTable = styled(MuiTable, {
54
55
  hoverable,
55
56
  density,
56
57
  stickyHeader,
57
- stripeColor });
58
+ stripeColor,
59
+ virtualised });
58
60
  });
59
61
 
60
62
  // Virtual Scrolling Hook
@@ -214,6 +216,7 @@ const AdvancedTable: React.FC<RendererProps> = ({ resolved: p, selection, innerR
214
216
  hoverable={p.hoverable}
215
217
  density={p.density}
216
218
  stickyHeader={p.stickyHeader}
219
+ virtualised={Boolean(windowHeight)}
217
220
  {...rest}
218
221
  >
219
222
  <EnhancedTableHeader
@@ -243,7 +246,6 @@ const AdvancedTable: React.FC<RendererProps> = ({ resolved: p, selection, innerR
243
246
  hoverable={p.hoverable}
244
247
  renderRow={p.renderRow}
245
248
  renderCell={p.renderCell}
246
- virtualScrolling={p.virtualScrolling}
247
249
  virtualWindow={windowHeight ? visibleItems : undefined}
248
250
  rowHeight={p.rowHeight}
249
251
  />
@@ -310,15 +310,18 @@ export interface TableHeaderProps {
310
310
  /**
311
311
  * The rows a virtualised body mounts. Computed by `useVirtualScrolling` in the
312
312
  * table, which owns the one scroll container, and handed down to the body.
313
+ *
314
+ * The mounted rows stay in the table's flow, between two spacer rows standing
315
+ * in for the rows above and below the window (FUT-2668).
313
316
  */
314
317
  export interface VirtualWindow {
315
318
  startIndex: number;
316
319
  endIndex: number;
317
320
  items: Record<string, unknown>[];
318
- /** Every row at the scaled pitch, as CSS. */
319
- totalHeight: string;
320
- /** Where the first mounted row sits, in design px. */
321
+ /** The rows above the window — `startIndex × rowHeight` — in design px. */
321
322
  offsetY: number;
323
+ /** The rows below the window — `(total − endIndex) × rowHeight` — in design px. */
324
+ trailingPx: number;
322
325
  }
323
326
 
324
327
  export interface TableBodyProps {
@@ -335,7 +338,6 @@ export interface TableBodyProps {
335
338
  hoverable?: boolean;
336
339
  renderRow?: (rowData: Record<string, unknown>, index: number, isSelected: boolean) => React.ReactNode;
337
340
  renderCell?: (value: unknown, column: ColumnConfig, rowData: Record<string, unknown>, rowIndex: number) => React.ReactNode;
338
- virtualScrolling?: boolean;
339
341
  /** Set only when the body is virtualised: the rows in view and where they sit. */
340
342
  virtualWindow?: VirtualWindow;
341
343
  rowHeight?: number;
@@ -31,6 +31,24 @@ const useRowSelection = ({
31
31
  [onSelectionChange, selectedRows],
32
32
  );
33
33
 
34
+ type RowRendererProps = Pick<
35
+ TableBodyProps,
36
+ | 'columns'
37
+ | 'onRowClick'
38
+ | 'onRowFocus'
39
+ | 'onRowBlur'
40
+ | 'onSelectionChange'
41
+ | 'rowKeyExtractor'
42
+ | 'selectable'
43
+ | 'renderRow'
44
+ | 'renderCell'
45
+ | 'rowHeight'
46
+ > & {
47
+ selectedRows: Array<string | number>;
48
+ /** Whether the rows are a virtual window's, drawn at exactly `rowHeight`. */
49
+ virtualised: boolean;
50
+ };
51
+
34
52
  export const useTableRowRenderer = ({
35
53
  columns,
36
54
  selectedRows,
@@ -42,22 +60,9 @@ export const useTableRowRenderer = ({
42
60
  selectable,
43
61
  renderRow,
44
62
  renderCell,
45
- virtualScrolling,
63
+ virtualised,
46
64
  rowHeight,
47
- }: Pick<
48
- TableBodyProps,
49
- | 'columns'
50
- | 'onRowClick'
51
- | 'onRowFocus'
52
- | 'onRowBlur'
53
- | 'onSelectionChange'
54
- | 'rowKeyExtractor'
55
- | 'selectable'
56
- | 'renderRow'
57
- | 'renderCell'
58
- | 'virtualScrolling'
59
- | 'rowHeight'
60
- > & { selectedRows: Array<string | number> }) => {
65
+ }: RowRendererProps) => {
61
66
  const getRowKey = useRowKey(rowKeyExtractor);
62
67
  const isRowSelected = useCallback(
63
68
  (rowKey: string | number) => selectedRows.includes(rowKey),
@@ -66,7 +71,7 @@ export const useTableRowRenderer = ({
66
71
  const handleRowSelection = useRowSelection({ selectedRows, onSelectionChange });
67
72
 
68
73
  const renderTableRow = useCallback(
69
- (rowData: Record<string, unknown>, index: number, offsetY: number = 0) => {
74
+ (rowData: Record<string, unknown>, index: number) => {
70
75
  const rowKey = getRowKey(rowData, index);
71
76
  const selected = isRowSelected(rowKey);
72
77
 
@@ -78,7 +83,6 @@ export const useTableRowRenderer = ({
78
83
  rowData={rowData}
79
84
  rowKey={rowKey}
80
85
  index={index}
81
- offsetY={offsetY}
82
86
  columns={columns}
83
87
  selected={selected}
84
88
  selectable={selectable}
@@ -87,7 +91,7 @@ export const useTableRowRenderer = ({
87
91
  onRowFocus={onRowFocus}
88
92
  onRowBlur={onRowBlur}
89
93
  onSelect={handleRowSelection}
90
- virtualScrolling={virtualScrolling}
94
+ virtualised={virtualised}
91
95
  renderCell={renderCell}
92
96
  />
93
97
  );
@@ -104,7 +108,7 @@ export const useTableRowRenderer = ({
104
108
  renderCell,
105
109
  rowHeight,
106
110
  selectable,
107
- virtualScrolling,
111
+ virtualised,
108
112
  ],
109
113
  );
110
114
 
@@ -7,6 +7,7 @@ import TableSortLabel from '@mui/material/TableSortLabel/index.js';
7
7
  import { useTheme, type Theme } from '@mui/material/styles/index.js';
8
8
  import React, { useCallback } from 'react';
9
9
 
10
+ import { FIELD_BORDER_WIDTH } from '../../../tokens/field-height.core';
10
11
  import { rem } from '../../../tokens/relative';
11
12
 
12
13
  import { tableRowHeight } from './Table.helpers';
@@ -125,14 +126,62 @@ export const EnhancedTableHeader: React.FC<TableHeaderProps> = React.memo(({
125
126
 
126
127
  EnhancedTableHeader.displayName = 'EnhancedTableHeader';
127
128
 
129
+ /** How a virtual cell's wrapper places its content along the row, per `align`. */
130
+ const JUSTIFY: Record<NonNullable<ColumnConfig['align']>, React.CSSProperties['justifyContent']> = {
131
+ left: 'flex-start',
132
+ center: 'center',
133
+ right: 'flex-end',
134
+ };
135
+
136
+ /**
137
+ * A virtual cell's content (FUT-2668). The cell has no vertical padding, and
138
+ * this fills its content box — the pitch less the cell's bottom rule, the one
139
+ * hairline every variant draws — so the cell's border box is exactly the pitch
140
+ * whatever it holds. Centred vertically, placed by the column's `align`, and
141
+ * clipped rather than allowed to grow the row.
142
+ */
143
+ const VirtualCellContent: React.FC<{
144
+ rowHeight: number;
145
+ align: NonNullable<ColumnConfig['align']>;
146
+ children: React.ReactNode;
147
+ }> = ({ rowHeight, align, children }) => {
148
+ const theme = useTheme();
149
+ return (
150
+ <div
151
+ style={{
152
+ height: `calc(${rem(theme, rowHeight)} - ${FIELD_BORDER_WIDTH}px)`,
153
+ display: 'flex',
154
+ alignItems: 'center',
155
+ justifyContent: JUSTIFY[align],
156
+ overflow: 'hidden',
157
+ }}
158
+ >
159
+ {children}
160
+ </div>
161
+ );
162
+ };
163
+
164
+ /** What one cell shows: the caller's `renderCell`, else the column's `render`, else the value. */
165
+ const cellContent = (
166
+ column: ColumnConfig,
167
+ rowData: Record<string, unknown>,
168
+ index: number,
169
+ renderCell: TableBodyProps['renderCell'],
170
+ ): React.ReactNode => {
171
+ const value = rowData[column.key];
172
+ if (renderCell) return renderCell(value, column, rowData, index);
173
+ return column.render ? column.render(value, rowData) : (value as React.ReactNode);
174
+ };
175
+
128
176
  // One data row. Split out of the memoised renderTableRow callback so the
129
177
  // callback stays a short dispatch and the row markup is readable on its own.
178
+ // A virtualised row stays in the table's flow at `rowHeight`, and each of its
179
+ // cells holds its content in a `VirtualCellContent` (FUT-2668); a plain row is
180
+ // drawn as MUI draws it.
130
181
  export const TableDataRow: React.FC<{
131
182
  rowData: Record<string, unknown>;
132
183
  rowKey: string | number;
133
184
  index: number;
134
- /** Where a virtualised row sits, in design px — drawn through `rem`, like its height. */
135
- offsetY: number;
136
185
  columns: ColumnConfig[];
137
186
  selected: boolean;
138
187
  selectable?: boolean;
@@ -142,13 +191,13 @@ export const TableDataRow: React.FC<{
142
191
  onRowFocus?: TableBodyProps['onRowFocus'];
143
192
  onRowBlur?: TableBodyProps['onRowBlur'];
144
193
  onSelect: (event: React.MouseEvent | React.ChangeEvent, rowKey: string | number) => void;
145
- virtualScrolling?: boolean;
194
+ /** Whether the row is one of a virtual window's. */
195
+ virtualised: boolean;
146
196
  renderCell?: TableBodyProps['renderCell'];
147
197
  }> = ({
148
198
  rowData,
149
199
  rowKey,
150
200
  index,
151
- offsetY,
152
201
  columns,
153
202
  selected,
154
203
  selectable,
@@ -157,9 +206,19 @@ export const TableDataRow: React.FC<{
157
206
  onRowFocus,
158
207
  onRowBlur,
159
208
  onSelect,
160
- virtualScrolling,
209
+ virtualised,
161
210
  renderCell }) => {
162
211
  const theme = useTheme();
212
+ const pitch = tableRowHeight(rowHeight);
213
+ const fit = (align: NonNullable<ColumnConfig['align']>, content: React.ReactNode) =>
214
+ virtualised ? (
215
+ <VirtualCellContent rowHeight={pitch} align={align}>
216
+ {content}
217
+ </VirtualCellContent>
218
+ ) : (
219
+ content
220
+ );
221
+
163
222
  return (
164
223
  <TableRow
165
224
  key={String(rowKey)}
@@ -168,62 +227,62 @@ export const TableDataRow: React.FC<{
168
227
  onClick={(event: React.MouseEvent<globalThis.HTMLTableRowElement>) => onRowClick?.(event, rowData)}
169
228
  onFocus={(event: React.FocusEvent<globalThis.HTMLTableRowElement>) => onRowFocus?.(event, rowData)}
170
229
  onBlur={(event: React.FocusEvent<globalThis.HTMLTableRowElement>) => onRowBlur?.(event, rowData)}
171
- style={virtualScrolling ? {
172
- transform: `translateY(${rem(theme, offsetY)})`,
173
- position: 'absolute',
174
- top: 0,
175
- left: 0,
176
- right: 0,
177
- height: rem(theme, tableRowHeight(rowHeight)) } : undefined}
230
+ style={virtualised ? { height: rem(theme, pitch) } : undefined}
178
231
  >
179
232
  {selectable && (
180
233
  <TableCell padding="checkbox">
181
- <Checkbox
182
- checked={selected}
183
- onChange={(event) => onSelect(event, rowKey)}
184
- onClick={(event) => event.stopPropagation()}
185
- inputProps={{ 'aria-label': `select row ${index + 1}` }}
186
- />
234
+ {fit(
235
+ 'left',
236
+ <Checkbox
237
+ checked={selected}
238
+ onChange={(event) => onSelect(event, rowKey)}
239
+ onClick={(event) => event.stopPropagation()}
240
+ inputProps={{ 'aria-label': `select row ${index + 1}` }}
241
+ />,
242
+ )}
187
243
  </TableCell>
188
244
  )}
189
- {columns.map((column) => {
190
- const value = rowData[column.key];
191
- return (
192
- <TableCell key={column.key} align={column.align || 'left'}>
193
- {renderCell
194
- ? renderCell(value, column, rowData, index)
195
- : column.render
196
- ? column.render(value, rowData)
197
- : (value as React.ReactNode)
198
- }
199
- </TableCell>
200
- );
201
- })}
245
+ {columns.map((column) => (
246
+ <TableCell key={column.key} align={column.align || 'left'}>
247
+ {fit(column.align || 'left', cellContent(column, rowData, index, renderCell))}
248
+ </TableCell>
249
+ ))}
202
250
  </TableRow>
203
251
  );
204
252
  };
205
253
 
206
- // Only the rows in view are rendered, positioned by absolute offset inside a
207
- // body sized to the full data set. `rowHeight` and every offset are design px,
254
+ /**
255
+ * A stand-in for the rows outside the window, `heightPx` design px tall. A bare
256
+ * `<tr>` and `<td>` with no padding or border: none of MUI's row or cell
257
+ * classes, so hover, striping and cell padding never reach it. Not rendered at
258
+ * all when there is nothing to stand in for.
259
+ */
260
+ const SpacerRow: React.FC<{ heightPx: number; colSpan: number }> = ({ heightPx, colSpan }) => {
261
+ const theme = useTheme();
262
+ if (heightPx <= 0) return null;
263
+ return (
264
+ <tr aria-hidden="true" style={{ height: rem(theme, heightPx) }}>
265
+ <td colSpan={colSpan} style={{ padding: 0, border: 0 }} />
266
+ </tr>
267
+ );
268
+ };
269
+
270
+ // Only the rows in view are rendered, in the table's own flow between two
271
+ // spacer rows standing in for the rest (FUT-2668) — an absolutely positioned
272
+ // `<tr>` is blockified and leaves the column grid. Every height is design px,
208
273
  // drawn through `rem`. The `<tbody>` sits directly in the `<table>`; the one
209
274
  // scroll container wraps the whole table, header included (FUT-2658).
210
275
  const VirtualisedBody: React.FC<{
211
276
  visibleItems: VirtualWindow;
212
- rowHeight: number;
213
- renderTableRow: (
214
- rowData: Record<string, unknown>,
215
- index: number,
216
- offsetY?: number,
217
- ) => React.ReactNode;
218
- }> = ({ visibleItems, rowHeight, renderTableRow }) => (
219
- <TableBody
220
- style={{
221
- height: visibleItems.totalHeight,
222
- position: 'relative' }}
223
- >
224
- {visibleItems.items.map((rowData, index) =>
225
- renderTableRow(rowData, visibleItems.startIndex + index, visibleItems.offsetY + index * rowHeight)
277
+ colSpan: number;
278
+ renderTableRow: (rowData: Record<string, unknown>, index: number) => React.ReactNode;
279
+ }> = ({ visibleItems, colSpan, renderTableRow }) => (
280
+ <TableBody>
281
+ <SpacerRow heightPx={visibleItems.offsetY} colSpan={colSpan} />
282
+ {visibleItems.items.map((rowData, index) =>
283
+ renderTableRow(rowData, visibleItems.startIndex + index)
226
284
  )}
285
+ <SpacerRow heightPx={visibleItems.trailingPx} colSpan={colSpan} />
227
286
  </TableBody>
228
287
  );
229
288
 
@@ -242,13 +301,17 @@ export const EnhancedTableBody: React.FC<TableBodyProps> = React.memo((props) =>
242
301
  const { data, virtualWindow } = props;
243
302
  // The row renderer takes the body's own props; its `rowHeight` stays the
244
303
  // caller's design px, and the row resolves the default where it draws it.
245
- const renderTableRow = useTableRowRenderer({ ...props, selectedRows: props.selectedRows ?? [] });
304
+ const renderTableRow = useTableRowRenderer({
305
+ ...props,
306
+ selectedRows: props.selectedRows ?? [],
307
+ virtualised: Boolean(virtualWindow),
308
+ });
246
309
 
247
310
  if (virtualWindow) {
248
311
  return (
249
312
  <VirtualisedBody
250
313
  visibleItems={virtualWindow}
251
- rowHeight={tableRowHeight(props.rowHeight)}
314
+ colSpan={props.columns.length + (props.selectable ? 1 : 0)}
252
315
  renderTableRow={renderTableRow}
253
316
  />
254
317
  );
@@ -104,12 +104,30 @@ function escapeRegExp(value: string): string {
104
104
  return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
105
105
  }
106
106
 
107
+ /** One run of a highlighted label: plain text, or text the query matched. */
108
+ export interface HighlightSegment {
109
+ text: string;
110
+ match: boolean;
111
+ }
112
+
107
113
  /**
108
- * Wrap query matches in `<mark>` for the default suggestion renderer. Skipped for
109
- * fuzzy mode (non-contiguous matches) and empty queries. Returns HTML.
114
+ * Split `label` into the runs the query matches and the runs between them, in
115
+ * order, for the default suggestion renderer to wrap the matches in `<mark>`.
116
+ * Every occurrence of the query matches, case-insensitively and literally (regex
117
+ * metacharacters are escaped). Fuzzy mode (non-contiguous matches) and an empty
118
+ * query yield the whole label as one unmatched run.
119
+ *
120
+ * Returns TEXT, never markup: a label is caller data (in a consumer, a user's
121
+ * own display name), so the renderer must hand each run to React as a text
122
+ * child, which escapes it. Building an HTML string here and injecting it is how
123
+ * a label of `<img onerror=…>` once ran script in the host page.
110
124
  */
111
- export function highlightLabel(label: string, query: string, matchMode: MatchMode): string {
112
- if (!query || matchMode === 'fuzzy') return label;
125
+ export function highlightLabel(label: string, query: string, matchMode: MatchMode): HighlightSegment[] {
126
+ if (!query || matchMode === 'fuzzy') return [{ text: label, match: false }];
127
+ // The capturing group makes `split` keep each match, at the odd indices.
113
128
  const regex = new RegExp(`(${escapeRegExp(query)})`, 'gi');
114
- return label.replace(regex, '<mark>$1</mark>');
129
+ return label
130
+ .split(regex)
131
+ .map((text, index) => ({ text, match: index % 2 === 1 }))
132
+ .filter((segment) => segment.text !== '');
115
133
  }
@@ -194,7 +194,8 @@ export function DefaultSuggestion<T>({
194
194
  }): React.JSX.Element {
195
195
  const label = getLabel(item);
196
196
  const description = getDescription?.(item);
197
- const displayLabel = highlightLabel(label, state.query, matchMode);
197
+ // Each run is a React text child, so the label is escaped however it reads.
198
+ const segments = highlightLabel(label, state.query, matchMode);
198
199
  return (
199
200
  <Box
200
201
  sx={{
@@ -202,13 +203,26 @@ export function DefaultSuggestion<T>({
202
203
  alignItems: 'center',
203
204
  gap: 1,
204
205
  width: '100%',
205
- // Bold the matched prefix (not a yellow <mark> highlight).
206
+ // Bold every run the query matched, in any match mode but fuzzy — not
207
+ // only a prefix, even under `startsWith` (not a yellow <mark> highlight).
206
208
  '& mark': { backgroundColor: 'transparent', color: 'inherit', fontWeight: 700 },
207
209
  }}
208
210
  >
209
211
  {suggestionTypeIcon(getSuggestionType(item))}
210
212
  <ListItemText
211
- primary={<span dangerouslySetInnerHTML={{ __html: displayLabel }} />}
213
+ primary={
214
+ <span>
215
+ {segments.map((segment, index) =>
216
+ // The runs are derived from one label and never reorder, so the
217
+ // position is a stable key.
218
+ segment.match ? (
219
+ <mark key={index}>{segment.text}</mark>
220
+ ) : (
221
+ <React.Fragment key={index}>{segment.text}</React.Fragment>
222
+ ),
223
+ )}
224
+ </span>
225
+ }
212
226
  secondary={description}
213
227
  />
214
228
  </Box>