@12-apps/ui 6.21.0 → 6.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (688) hide show
  1. package/NATIVE.md +6 -4
  2. package/components-catalog.md +7 -0
  3. package/dist/_internal/components/data-display/Alert/Alert.js +4 -4
  4. package/dist/_internal/components/data-display/Alert/Alert.styles.js +2 -2
  5. package/dist/_internal/components/data-display/AsyncStateContainer/AsyncStateContainer.js +8 -8
  6. package/dist/_internal/components/data-display/Badge/Badge.js +3 -3
  7. package/dist/_internal/components/data-display/CardKit/CardKebab.js +4 -4
  8. package/dist/_internal/components/data-display/CardKit/card-actions-context.js +5 -5
  9. package/dist/_internal/components/data-display/CardKit/use-remove-confirm.js +9 -9
  10. package/dist/_internal/components/data-display/CardKit/use-row-confirm.js +4 -4
  11. package/dist/_internal/components/data-display/Chart/Chart.js +3 -3
  12. package/dist/_internal/components/data-display/Chart/SpecChart.js +5 -5
  13. package/dist/_internal/components/data-display/Chart/chart-renderers.js +2 -2
  14. package/dist/_internal/components/data-display/Chip/Chip.js +3 -3
  15. package/dist/_internal/components/data-display/Chip/Chip.styles.js +2 -2
  16. package/dist/_internal/components/data-display/DataGrid/DataGrid.js +2 -2
  17. package/dist/_internal/components/data-display/DataViews/DataViewsBoard.js +3 -3
  18. package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +50 -50
  19. package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +68 -65
  20. package/dist/_internal/components/data-display/DataViews/DeleteViewDialog.js +10 -7
  21. package/dist/_internal/components/data-display/DataViews/ManageViewsDialog.js +11 -8
  22. package/dist/_internal/components/data-display/DataViews/SaveViewModal.js +14 -11
  23. package/dist/_internal/components/data-display/DataViews/base-card.js +9 -7
  24. package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +7 -7
  25. package/dist/_internal/components/data-display/DataViews/base-list-card-gutters.js +3 -3
  26. package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +6 -6
  27. package/dist/_internal/components/data-display/DataViews/base-list-card.js +15 -13
  28. package/dist/_internal/components/data-display/DataViews/data-views-category-pill.js +12 -12
  29. package/dist/_internal/components/data-display/DataViews/data-views-columns-tab.js +3 -3
  30. package/dist/_internal/components/data-display/DataViews/data-views-columns.js +5 -5
  31. package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +8 -8
  32. package/dist/_internal/components/data-display/DataViews/data-views-display-tabs.js +3 -3
  33. package/dist/_internal/components/data-display/DataViews/data-views-empty.js +5 -5
  34. package/dist/_internal/components/data-display/DataViews/data-views-export.js +5 -5
  35. package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +15 -15
  36. package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +12 -12
  37. package/dist/_internal/components/data-display/DataViews/data-views-grid-helpers.js +4 -4
  38. package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +46 -46
  39. package/dist/_internal/components/data-display/DataViews/data-views-header-row.js +3 -3
  40. package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +21 -21
  41. package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +6 -6
  42. package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +9 -9
  43. package/dist/_internal/components/data-display/DataViews/data-views-pagination.js +3 -3
  44. package/dist/_internal/components/data-display/DataViews/data-views-range-pill.js +2 -2
  45. package/dist/_internal/components/data-display/DataViews/data-views-select-all-strip.js +5 -5
  46. package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +13 -13
  47. package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +21 -18
  48. package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +12 -12
  49. package/dist/_internal/components/data-display/DataViews/data-views-view-nav.js +5 -5
  50. package/dist/_internal/components/data-display/DataViews/list-card-rails.js +2 -2
  51. package/dist/_internal/components/data-display/DataViews/save-view-preview.js +3 -3
  52. package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +7 -7
  53. package/dist/_internal/components/data-display/DescriptionItem/DescriptionItem.js +3 -3
  54. package/dist/_internal/components/data-display/EmptyState/EmptyState.js +2 -2
  55. package/dist/_internal/components/data-display/ErrorState/ErrorState.js +2 -2
  56. package/dist/_internal/components/data-display/FleetMap/FleetBody.js +31 -0
  57. package/dist/_internal/components/data-display/FleetMap/FleetCanvas.js +23 -0
  58. package/dist/_internal/components/data-display/FleetMap/FleetCanvas.js.map +1 -0
  59. package/dist/_internal/components/data-display/FleetMap/FleetMap.fixtures.js +57 -0
  60. package/dist/_internal/components/data-display/FleetMap/FleetMap.fixtures.js.map +1 -0
  61. package/dist/_internal/components/data-display/FleetMap/FleetMap.helpers.js +14 -0
  62. package/dist/_internal/components/data-display/FleetMap/FleetMap.helpers.js.map +1 -0
  63. package/dist/_internal/components/data-display/FleetMap/FleetMap.hooks.js +9 -0
  64. package/dist/_internal/components/data-display/FleetMap/FleetMap.hooks.js.map +1 -0
  65. package/dist/_internal/components/data-display/FleetMap/FleetMap.js +46 -0
  66. package/dist/_internal/components/data-display/FleetMap/FleetMap.js.map +1 -0
  67. package/dist/_internal/components/data-display/FleetMap/FleetMap.types.js +1 -0
  68. package/dist/_internal/components/data-display/FleetMap/FleetMap.types.js.map +1 -0
  69. package/dist/_internal/components/data-display/FleetMap/FleetRoster.js +14 -0
  70. package/dist/_internal/components/data-display/FleetMap/FleetRoster.js.map +1 -0
  71. package/dist/_internal/components/data-display/LazyImage/LazyImage.js +4 -4
  72. package/dist/_internal/components/data-display/Lightbox/Lightbox.js +1 -1
  73. package/dist/_internal/components/data-display/LoadingState/LoadingState.js +4 -4
  74. package/dist/_internal/components/data-display/MapPreview/MapDecorations.js +2 -2
  75. package/dist/_internal/components/data-display/MapPreview/MapPreview.hooks.js +2 -2
  76. package/dist/_internal/components/data-display/MapPreview/MapPreview.js +7 -7
  77. package/dist/_internal/components/data-display/MapPreview/MapTiles.js +2 -2
  78. package/dist/_internal/components/data-display/MapPreview/StaticMapView.js +4 -4
  79. package/dist/_internal/components/data-display/MapPreview/useMapPreview.js +3 -3
  80. package/dist/_internal/components/data-display/Progress/Progress.js +2 -2
  81. package/dist/_internal/components/data-display/SectionOnboarding/SectionOnboarding.js +3 -3
  82. package/dist/_internal/components/data-display/Sheet/Sheet.js +3 -3
  83. package/dist/_internal/components/data-display/StatCard/StatCard.js +4 -4
  84. package/dist/_internal/components/data-display/Table/Table.js +2 -2
  85. package/dist/_internal/components/data-display/index.js +88 -68
  86. package/dist/_internal/components/feedback/ConfirmAction/ConfirmButton.js +4 -4
  87. package/dist/_internal/components/feedback/Dialog/Dialog.base.js +1 -0
  88. package/dist/_internal/components/feedback/Dialog/Dialog.base.js.map +1 -0
  89. package/dist/_internal/components/feedback/Dialog/Dialog.helpers.js +12 -0
  90. package/dist/_internal/components/feedback/Dialog/Dialog.helpers.js.map +1 -0
  91. package/dist/_internal/components/feedback/Dialog/Dialog.js +6 -2
  92. package/dist/_internal/components/feedback/Dialog/Dialog.metrics.js +42 -0
  93. package/dist/_internal/components/feedback/Dialog/Dialog.metrics.js.map +1 -0
  94. package/dist/_internal/components/feedback/Dialog/Dialog.styles.js +3 -1
  95. package/dist/_internal/components/feedback/TutorialOverlay/TutorialOverlay.js +2 -2
  96. package/dist/_internal/components/feedback/index.js +16 -13
  97. package/dist/_internal/components/form/AddressAutocomplete/AddressAutocomplete.hooks.js +3 -3
  98. package/dist/_internal/components/form/AddressAutocomplete/AddressAutocomplete.js +7 -7
  99. package/dist/_internal/components/form/AddressAutocomplete/AddressAutocompleteField.js +3 -3
  100. package/dist/_internal/components/form/Autocomplete/Autocomplete.js +2 -2
  101. package/dist/_internal/components/form/Button/Button.js +3 -3
  102. package/dist/_internal/components/form/Calendar/Calendar.js +4 -4
  103. package/dist/_internal/components/form/Calendar/CalendarDayCell.js +2 -2
  104. package/dist/_internal/components/form/Calendar/CalendarMonth.js +3 -3
  105. package/dist/_internal/components/form/CategorySelect/CategoryPanel.js +5 -5
  106. package/dist/_internal/components/form/CategorySelect/CategoryPanelList.js +3 -3
  107. package/dist/_internal/components/form/CategorySelect/CategoryRows.js +2 -2
  108. package/dist/_internal/components/form/CategorySelect/CategorySelect.js +10 -10
  109. package/dist/_internal/components/form/CepField/CepField.js +4 -4
  110. package/dist/_internal/components/form/Checkbox/Checkbox.js +2 -2
  111. package/dist/_internal/components/form/CodeEditor/CodeEditor.js +2 -2
  112. package/dist/_internal/components/form/Command/Command.js +2 -2
  113. package/dist/_internal/components/form/DateRangePicker/DateRangePicker.js +6 -6
  114. package/dist/_internal/components/form/Input/Input.js +3 -3
  115. package/dist/_internal/components/form/Label/Label.js +2 -2
  116. package/dist/_internal/components/form/Menubar/Menubar.js +5 -5
  117. package/dist/_internal/components/form/Menubar/Menubar.toolbar.js +2 -2
  118. package/dist/_internal/components/form/PhoneInput/PhoneInput.hooks.js +2 -2
  119. package/dist/_internal/components/form/PhoneInput/PhoneInput.js +3 -3
  120. package/dist/_internal/components/form/Select/Select.js +2 -2
  121. package/dist/_internal/components/form/Switch/Switch.js +2 -2
  122. package/dist/_internal/components/form/index.js +55 -55
  123. package/dist/_internal/components/form/total-form/Fields/CategoryField.js +11 -11
  124. package/dist/_internal/components/form/total-form/Fields/CepField.js +5 -5
  125. package/dist/_internal/components/form/total-form/Fields/SelectField.js +3 -3
  126. package/dist/_internal/components/form/total-form/Fields/TextField.js +4 -4
  127. package/dist/_internal/components/form/total-form/Fields/index.js +25 -25
  128. package/dist/_internal/components/form/total-form/SubmitButton.js +4 -4
  129. package/dist/_internal/components/index.js +198 -175
  130. package/dist/_internal/components/layout/Box/Box.js +2 -2
  131. package/dist/_internal/components/layout/Card/Card.base.js +1 -0
  132. package/dist/_internal/components/layout/Card/Card.base.js.map +1 -0
  133. package/dist/_internal/components/layout/Card/Card.helpers.js +1 -1
  134. package/dist/_internal/components/layout/Card/Card.js +6 -3
  135. package/dist/_internal/components/layout/Card/Card.metrics.js +44 -0
  136. package/dist/_internal/components/layout/Card/Card.metrics.js.map +1 -0
  137. package/dist/_internal/components/layout/Card/Card.styles.js +3 -1
  138. package/dist/_internal/components/layout/Container/Container.js +2 -2
  139. package/dist/_internal/components/layout/SettingsLayout/SettingsLayout.js +2 -2
  140. package/dist/_internal/components/layout/Skeleton/Skeleton.js +3 -3
  141. package/dist/_internal/components/layout/Spacer/Spacer.js +2 -2
  142. package/dist/_internal/components/layout/Stack/Stack.js +3 -3
  143. package/dist/_internal/components/layout/index.js +30 -28
  144. package/dist/_internal/components/navigation/AppHeader/AppHeader.details.js +12 -9
  145. package/dist/_internal/components/navigation/CommandPalette/CommandPalette.js +2 -2
  146. package/dist/_internal/components/navigation/Pagination/Pagination.js +2 -2
  147. package/dist/_internal/components/navigation/index.js +22 -19
  148. package/dist/_internal/components/typography/Heading/Heading.js +2 -2
  149. package/dist/_internal/components/typography/Paragraph/Paragraph.js +2 -2
  150. package/dist/_internal/components/typography/Text/Text.js +2 -2
  151. package/dist/_internal/components/typography/index.js +4 -4
  152. package/dist/_internal/components/utility/InfiniteScroll/InfiniteScroll.js +2 -2
  153. package/dist/_internal/components/utility/InstallPrompt/InstallPrompt.js +2 -2
  154. package/dist/_internal/components/utility/index.js +8 -8
  155. package/dist/_internal/icons/Icon.js +2 -2
  156. package/dist/_internal/platform/test-id.js +3 -1
  157. package/dist/_internal/pt-BR.data-display.js +2 -2
  158. package/dist/_internal/social-login-button/social-login-button.js +11 -9
  159. package/dist/_internal/tokens/mui-type.js +1 -0
  160. package/dist/_internal/tokens/mui-type.js.map +1 -1
  161. package/dist/_internal/tokens/shadow.js +18 -0
  162. package/dist/_internal/tokens/shadow.js.map +1 -0
  163. package/dist/_internal/user-avatar/user-avatar.js +10 -8
  164. package/dist/charts.js +6 -6
  165. package/dist/{chunk-NUE774AN.js → chunk-25R3ITGZ.js} +2 -2
  166. package/dist/{chunk-Z6UEOSL7.js → chunk-2FDBR77W.js} +3 -3
  167. package/dist/{chunk-IFNK5TPI.js → chunk-2HPP6RVC.js} +2 -2
  168. package/dist/chunk-2RQINU5T.js +41 -0
  169. package/dist/chunk-2RQINU5T.js.map +1 -0
  170. package/dist/{chunk-GCXYCDOA.js → chunk-2UGJIKVA.js} +2 -2
  171. package/dist/{chunk-26Z7QWID.js → chunk-343TTIHD.js} +2 -2
  172. package/dist/{chunk-BRSF5NRT.js → chunk-3FLVIVOK.js} +4 -4
  173. package/dist/{chunk-BDVNAU2C.js → chunk-4523RYE7.js} +5 -5
  174. package/dist/{chunk-4ETQRBZC.js → chunk-46UPILLK.js} +4 -4
  175. package/dist/{chunk-WMALDOF5.js → chunk-4G3FGCWX.js} +4 -4
  176. package/dist/{chunk-I3MDKPGG.js → chunk-4IVOHL32.js} +2 -2
  177. package/dist/{chunk-SAHQLXNN.js → chunk-4LRFGB3K.js} +4 -4
  178. package/dist/{chunk-ZOUWHGV3.js → chunk-4MGFUPQT.js} +4 -4
  179. package/dist/{chunk-TLX66HCW.js → chunk-4OHRZW7U.js} +5 -5
  180. package/dist/{chunk-2QFTAGDH.js → chunk-4X4KM4ZB.js} +4 -4
  181. package/dist/{chunk-7ZH7ZB33.js → chunk-4XZXLB4I.js} +4 -4
  182. package/dist/{chunk-6PRA45LC.js → chunk-5KEMPCW4.js} +54 -45
  183. package/dist/chunk-5KEMPCW4.js.map +1 -0
  184. package/dist/{chunk-77F36LQQ.js → chunk-5OIH36KX.js} +3 -3
  185. package/dist/chunk-5V4UPOWK.js +36 -0
  186. package/dist/chunk-5V4UPOWK.js.map +1 -0
  187. package/dist/{chunk-GDEXYUPF.js → chunk-67L7HMEP.js} +2 -2
  188. package/dist/{chunk-ZFPJBKVZ.js → chunk-6JGPPTLX.js} +5 -5
  189. package/dist/chunk-6Q6T3FW5.js +92 -0
  190. package/dist/chunk-6Q6T3FW5.js.map +1 -0
  191. package/dist/chunk-73BEVJCS.js +28 -0
  192. package/dist/chunk-73BEVJCS.js.map +1 -0
  193. package/dist/{chunk-VIK3HAUQ.js → chunk-73NJCGQG.js} +2 -2
  194. package/dist/{chunk-D4T646G4.js → chunk-7NSX7A5H.js} +2 -2
  195. package/dist/{chunk-QS7ZGRNS.js → chunk-7VN7LFBA.js} +6 -6
  196. package/dist/{chunk-3UOHKHOT.js → chunk-ACFGEZ4Q.js} +3 -3
  197. package/dist/{chunk-GBNOYRLP.js → chunk-AEGXHZQT.js} +8 -8
  198. package/dist/{chunk-D2IASECY.js → chunk-AIRWM7KK.js} +39 -28
  199. package/dist/chunk-AIRWM7KK.js.map +1 -0
  200. package/dist/{chunk-BEH4DN63.js → chunk-AJGYHDA5.js} +6 -6
  201. package/dist/{chunk-65DLYC4S.js → chunk-AVGTTWTE.js} +4 -4
  202. package/dist/{chunk-PXH24VIP.js → chunk-B6IURHSZ.js} +4 -4
  203. package/dist/chunk-BEBLRL5D.js +177 -0
  204. package/dist/chunk-BEBLRL5D.js.map +1 -0
  205. package/dist/{chunk-XEE7PLDR.js → chunk-BZTFPSWT.js} +4 -4
  206. package/dist/{chunk-B3BK2SNS.js → chunk-C3CMEDSO.js} +2 -2
  207. package/dist/{chunk-OH3YGJT5.js → chunk-CBTY36TU.js} +2 -2
  208. package/dist/chunk-CDCTLPMD.js +1 -0
  209. package/dist/chunk-CDCTLPMD.js.map +1 -0
  210. package/dist/chunk-CF3FAAPC.js +79 -0
  211. package/dist/chunk-CF3FAAPC.js.map +1 -0
  212. package/dist/{chunk-JIINGMEB.js → chunk-CHPZTF34.js} +7 -7
  213. package/dist/{chunk-PWXL3QQ6.js → chunk-CJBBGMIA.js} +2 -2
  214. package/dist/{chunk-BPYPUEM5.js → chunk-CZJLWCEG.js} +2 -2
  215. package/dist/{chunk-FPWB5ILF.js → chunk-DRHIIUDO.js} +5 -5
  216. package/dist/{chunk-BEGWE5O4.js → chunk-DTC224UJ.js} +4 -4
  217. package/dist/{chunk-UB76PBDF.js → chunk-DVFIE54C.js} +2 -2
  218. package/dist/{chunk-GO4MVQGC.js → chunk-DW5FRWRQ.js} +2 -2
  219. package/dist/{chunk-6Z4H2Y77.js → chunk-E27Y7FF2.js} +4 -4
  220. package/dist/{chunk-PANMJFDS.js → chunk-E55CJV65.js} +2 -2
  221. package/dist/{chunk-JXAYT6LX.js → chunk-EJQW2IYW.js} +2 -2
  222. package/dist/{chunk-TPIBJP4S.js → chunk-EOHKZGOZ.js} +2 -2
  223. package/dist/{chunk-MSUSZLRE.js → chunk-EWT3WMVY.js} +5 -5
  224. package/dist/chunk-F7VBGS4C.js +64 -0
  225. package/dist/chunk-F7VBGS4C.js.map +1 -0
  226. package/dist/{chunk-DH75UNF3.js → chunk-FGK2C7JR.js} +2 -2
  227. package/dist/{chunk-RI5JZLZL.js → chunk-FKUYRQSP.js} +1 -1
  228. package/dist/chunk-FKUYRQSP.js.map +1 -0
  229. package/dist/{chunk-AD776JPA.js → chunk-FR67FG2U.js} +2 -2
  230. package/dist/{chunk-SHQWIDD5.js → chunk-GJQYM3PM.js} +4 -4
  231. package/dist/{chunk-7KTU6YMQ.js → chunk-GMTM6EN7.js} +5 -5
  232. package/dist/{chunk-WROCSDVL.js → chunk-GSFNH4C5.js} +5 -5
  233. package/dist/{chunk-PF5HDFYY.js → chunk-GVA5CYKP.js} +4 -4
  234. package/dist/chunk-GYXUCS37.js +36 -0
  235. package/dist/chunk-GYXUCS37.js.map +1 -0
  236. package/dist/{chunk-Z5ABJLTM.js → chunk-HFXTAEYY.js} +2 -2
  237. package/dist/{chunk-FOMK3WPG.js → chunk-HLYPI5CO.js} +4 -4
  238. package/dist/{chunk-VR5HDUBK.js → chunk-HP2ODXNA.js} +2 -2
  239. package/dist/{chunk-GBRKP5GZ.js → chunk-I5SBTNV2.js} +2 -2
  240. package/dist/{chunk-TP4N3X2Q.js → chunk-IPVYEPXO.js} +5 -5
  241. package/dist/{chunk-RRO2EOJB.js → chunk-JB67KPGM.js} +4 -4
  242. package/dist/{chunk-5ZOJLYD2.js → chunk-JE6RZ5L6.js} +4 -4
  243. package/dist/{chunk-4HYXEMBP.js → chunk-JIKWZDNK.js} +2 -2
  244. package/dist/{chunk-4MLDWACO.js → chunk-JM64OEU6.js} +12 -12
  245. package/dist/{chunk-2QLVUVVR.js → chunk-JSH3HFDQ.js} +2 -2
  246. package/dist/{chunk-TZ4SFX3M.js → chunk-JWW2Z3RH.js} +4 -4
  247. package/dist/{chunk-QFHH2NU5.js → chunk-JXNT5TUP.js} +3 -3
  248. package/dist/{chunk-FINCVAAR.js → chunk-KHWCX4LI.js} +4 -4
  249. package/dist/{chunk-THZ2NAA4.js → chunk-KW7H5O3K.js} +7 -7
  250. package/dist/{chunk-XLJJ2ZAP.js → chunk-L4U23SBX.js} +11 -11
  251. package/dist/{chunk-ZXLIWOXC.js → chunk-LS4FMSHY.js} +5 -5
  252. package/dist/{chunk-SFAP5EH5.js → chunk-LUMF63BM.js} +4 -4
  253. package/dist/{chunk-CZPU5TW3.js → chunk-LYSSO6WC.js} +4 -4
  254. package/dist/{chunk-736HP6BL.js → chunk-M4LQRQFL.js} +2 -2
  255. package/dist/{chunk-426FTCMF.js → chunk-MESRKY67.js} +2 -2
  256. package/dist/{chunk-B5PYBEXO.js → chunk-MP4VSWHK.js} +2 -2
  257. package/dist/chunk-MQNKRIGC.js +205 -0
  258. package/dist/chunk-MQNKRIGC.js.map +1 -0
  259. package/dist/{chunk-UOPQOBQZ.js → chunk-MYGNIFZC.js} +3 -3
  260. package/dist/{chunk-6RGWDKUL.js → chunk-N2TUX4A5.js} +4 -4
  261. package/dist/{chunk-VWGR5XUP.js → chunk-NWNSUHEB.js} +2 -2
  262. package/dist/{chunk-4K7FDVAB.js → chunk-O3336DJ6.js} +2 -2
  263. package/dist/{chunk-YCCKY5VW.js → chunk-OFOYMZRY.js} +4 -4
  264. package/dist/{chunk-OCXCH2ZW.js → chunk-OIKQO73C.js} +7 -7
  265. package/dist/{chunk-QZDBWXZG.js → chunk-OP65D4UR.js} +2 -2
  266. package/dist/{chunk-MCRIT46W.js → chunk-OTH7H3IP.js} +5 -5
  267. package/dist/{chunk-BQQONDW5.js → chunk-OVLNF4AZ.js} +6 -6
  268. package/dist/{chunk-AGYGNNOM.js → chunk-PQECNGDE.js} +2 -2
  269. package/dist/{chunk-IIROZKW5.js → chunk-PRUSQQDT.js} +2 -2
  270. package/dist/{chunk-IPE5FFFD.js → chunk-PUBPZOQJ.js} +2 -2
  271. package/dist/{chunk-FB36IHCE.js → chunk-QFVFHIHE.js} +8 -8
  272. package/dist/{chunk-V5P5Q6HM.js → chunk-QJRDDVZ2.js} +3 -3
  273. package/dist/{chunk-WBKWIFXA.js → chunk-QYNCPS5W.js} +6 -6
  274. package/dist/{chunk-VPHOSIPB.js → chunk-R6SNYC3D.js} +10 -10
  275. package/dist/{chunk-STH66VLA.js → chunk-R7R3LOKW.js} +2 -2
  276. package/dist/{chunk-W2UTDN4T.js → chunk-RBGOGTT2.js} +4 -4
  277. package/dist/chunk-RQWZYD6H.js +1 -0
  278. package/dist/chunk-RQWZYD6H.js.map +1 -0
  279. package/dist/{chunk-VWBWKLXX.js → chunk-SX3V2DLV.js} +4 -4
  280. package/dist/{chunk-P7FQUGED.js → chunk-TNVO2DTB.js} +5 -5
  281. package/dist/{chunk-WTIOCG4M.js → chunk-TOYEP23N.js} +2 -2
  282. package/dist/{chunk-G2IPK2XE.js → chunk-TPLKJHNN.js} +8 -8
  283. package/dist/{chunk-U2AC4AQX.js → chunk-TU5EIKJA.js} +4 -4
  284. package/dist/{chunk-ZGHIHEND.js → chunk-TW3BXVEU.js} +2 -2
  285. package/dist/chunk-TWQYDKCA.js +113 -0
  286. package/dist/chunk-TWQYDKCA.js.map +1 -0
  287. package/dist/{chunk-BGYLL467.js → chunk-TXHJX2NG.js} +4 -4
  288. package/dist/{chunk-6F5IKY32.js → chunk-TYJR4GOF.js} +6 -2
  289. package/dist/{chunk-6F5IKY32.js.map → chunk-TYJR4GOF.js.map} +1 -1
  290. package/dist/{chunk-5RQ7N63M.js → chunk-TZDDL3DR.js} +2 -2
  291. package/dist/{chunk-RPQ3W2C6.js → chunk-U2ZDN2AL.js} +2 -2
  292. package/dist/{chunk-WPZT2JD4.js → chunk-U7Q2Y6WG.js} +2 -2
  293. package/dist/{chunk-E46PG577.js → chunk-URXT5TOY.js} +4 -4
  294. package/dist/chunk-VM3HRSAU.js +79 -0
  295. package/dist/chunk-VM3HRSAU.js.map +1 -0
  296. package/dist/{chunk-P6IPJYCS.js → chunk-VNNG46TS.js} +6 -6
  297. package/dist/{chunk-CXVMD6FE.js → chunk-VON4BFK4.js} +3 -3
  298. package/dist/{chunk-2SWQ6HIK.js → chunk-W3FAKT3D.js} +4 -4
  299. package/dist/{chunk-JDMYD6QC.js → chunk-W4SDVTZC.js} +2 -2
  300. package/dist/{chunk-7MAOQIWA.js → chunk-W4YWU7LQ.js} +2 -2
  301. package/dist/{chunk-Y46RBFBV.js → chunk-W7Y6RA6W.js} +6 -6
  302. package/dist/{chunk-XFU2S6XT.js → chunk-WGRS4PGY.js} +10 -10
  303. package/dist/{chunk-OOGEYCJH.js → chunk-WIT3Y7JT.js} +2 -2
  304. package/dist/{chunk-KT6HWAEN.js → chunk-WQA4LIIK.js} +4 -4
  305. package/dist/{chunk-J2KSG754.js → chunk-WRDPWEIC.js} +5 -5
  306. package/dist/{chunk-RPWEXIAW.js → chunk-X5MPHXG5.js} +6 -6
  307. package/dist/{chunk-UEIVXFUC.js → chunk-XELVDPKL.js} +5 -5
  308. package/dist/{chunk-RRZBATXK.js → chunk-XKV5ZIBG.js} +3 -3
  309. package/dist/{chunk-ZKFYBC6G.js → chunk-XSF6AXEU.js} +2 -2
  310. package/dist/{chunk-R6RVBYTU.js → chunk-XUJG2HFW.js} +3 -3
  311. package/dist/{chunk-S5LE2ARG.js → chunk-YANLN6HP.js} +66 -56
  312. package/dist/chunk-YANLN6HP.js.map +1 -0
  313. package/dist/{chunk-FRQ4HNGF.js → chunk-YJ4HM25H.js} +2 -2
  314. package/dist/{chunk-TVO5STZB.js → chunk-YQ6TNHAC.js} +3 -3
  315. package/dist/{chunk-BNNSO4MC.js → chunk-YTOYMJPM.js} +5 -5
  316. package/dist/{chunk-IH4RSRQA.js → chunk-ZA4U5GDU.js} +6 -6
  317. package/dist/data-display/Alert.js +4 -4
  318. package/dist/data-display/AsyncStateContainer.js +8 -8
  319. package/dist/data-display/Badge.js +3 -3
  320. package/dist/data-display/CardKit.js +13 -13
  321. package/dist/data-display/Chart.js +6 -6
  322. package/dist/data-display/Chip.js +3 -3
  323. package/dist/data-display/DataGrid.js +2 -2
  324. package/dist/data-display/DataViews.js +84 -80
  325. package/dist/data-display/DescriptionItem.js +3 -3
  326. package/dist/data-display/EmptyState.js +2 -2
  327. package/dist/data-display/ErrorState.js +2 -2
  328. package/dist/data-display/FleetMap.js +54 -0
  329. package/dist/data-display/FleetMap.js.map +1 -0
  330. package/dist/data-display/LazyImage.js +4 -4
  331. package/dist/data-display/Lightbox.js +1 -1
  332. package/dist/data-display/LoadingState.js +4 -4
  333. package/dist/data-display/MapPreview.js +7 -7
  334. package/dist/data-display/Progress.js +2 -2
  335. package/dist/data-display/SectionOnboarding.js +3 -3
  336. package/dist/data-display/Sheet.js +3 -3
  337. package/dist/data-display/StatCard.js +4 -4
  338. package/dist/data-display/Table.js +2 -2
  339. package/dist/feedback/ConfirmAction.js +4 -4
  340. package/dist/feedback/Dialog.js +6 -2
  341. package/dist/feedback/TutorialOverlay.js +2 -2
  342. package/dist/form/AddressAutocomplete.js +7 -7
  343. package/dist/form/Autocomplete.js +2 -2
  344. package/dist/form/Button.js +3 -3
  345. package/dist/form/Calendar.js +4 -4
  346. package/dist/form/CategorySelect.js +10 -10
  347. package/dist/form/CepField.js +4 -4
  348. package/dist/form/Checkbox.js +2 -2
  349. package/dist/form/CodeEditor.js +2 -2
  350. package/dist/form/Command.js +2 -2
  351. package/dist/form/DateRangePicker.js +11 -11
  352. package/dist/form/Input.js +3 -3
  353. package/dist/form/Label.js +2 -2
  354. package/dist/form/Menubar.js +5 -5
  355. package/dist/form/PhoneInput.js +3 -3
  356. package/dist/form/Select.js +2 -2
  357. package/dist/form/Switch.js +2 -2
  358. package/dist/form/total-form.js +30 -30
  359. package/dist/icons.js +2 -2
  360. package/dist/layout/Box.js +2 -2
  361. package/dist/layout/Card.js +6 -3
  362. package/dist/layout/Container.js +2 -2
  363. package/dist/layout/ContentToolbar.js +3 -3
  364. package/dist/layout/SettingsLayout.js +2 -2
  365. package/dist/layout/Skeleton.js +3 -3
  366. package/dist/layout/Spacer.js +2 -2
  367. package/dist/layout/Stack.js +3 -3
  368. package/dist/locales.js +4 -4
  369. package/dist/native/chunks/{chunk-HSIND52T.js → chunk-2UFNPDYT.js} +2 -1
  370. package/dist/native/chunks/chunk-2UFNPDYT.js.map +1 -0
  371. package/dist/native/chunks/{chunk-OGWPPQL4.js → chunk-75JQYVDZ.js} +3 -3
  372. package/dist/native/chunks/{chunk-WKMDCNIN.js → chunk-7LTVGW23.js} +2 -2
  373. package/dist/native/chunks/{chunk-QZAUOHDQ.js → chunk-AR5O4BEY.js} +6 -2
  374. package/dist/native/chunks/{chunk-QZAUOHDQ.js.map → chunk-AR5O4BEY.js.map} +1 -1
  375. package/dist/native/chunks/{chunk-RJVM5YDE.js → chunk-ATS7STZJ.js} +4 -4
  376. package/dist/native/chunks/{chunk-YTHR4Y5P.js → chunk-GWGIWQO7.js} +2 -2
  377. package/dist/native/chunks/{chunk-P3PL4WBO.js → chunk-LEMMXZFN.js} +24 -24
  378. package/dist/native/chunks/{chunk-P3PL4WBO.js.map → chunk-LEMMXZFN.js.map} +1 -1
  379. package/dist/native/chunks/chunk-NRN37A5K.js +67 -0
  380. package/dist/native/chunks/chunk-NRN37A5K.js.map +1 -0
  381. package/dist/native/chunks/{chunk-D4EYAXNG.js → chunk-QYUD3S6F.js} +5 -5
  382. package/dist/native/data-display/Alert.js +8 -8
  383. package/dist/native/data-display/Avatar.js +7 -7
  384. package/dist/native/data-display/Badge.js +8 -8
  385. package/dist/native/data-display/Chip.js +4 -4
  386. package/dist/native/data-display/EmptyState.js +11 -11
  387. package/dist/native/data-display/ErrorState.js +11 -11
  388. package/dist/native/data-display/LoadingState.js +7 -7
  389. package/dist/native/data-display/Progress.js +3 -3
  390. package/dist/native/feedback/Dialog.js +496 -0
  391. package/dist/native/feedback/Dialog.js.map +1 -0
  392. package/dist/native/form/Button.js +4 -4
  393. package/dist/native/form/Checkbox.js +5 -5
  394. package/dist/native/form/Input.js +5 -5
  395. package/dist/native/form/Select.js +6 -6
  396. package/dist/native/form/Switch.js +3 -3
  397. package/dist/native/icons.js +4 -4
  398. package/dist/native/layout/Box.js +4 -4
  399. package/dist/native/layout/Card.js +494 -0
  400. package/dist/native/layout/Card.js.map +1 -0
  401. package/dist/native/layout/Container.js +3 -3
  402. package/dist/native/layout/Skeleton.js +6 -6
  403. package/dist/native/layout/Spacer.js +3 -3
  404. package/dist/native/layout/Stack.js +4 -4
  405. package/dist/native/provider.js +2 -2
  406. package/dist/native/tokens.js +1 -1
  407. package/dist/native/typography/Heading.js +3 -3
  408. package/dist/native/typography/Paragraph.js +3 -3
  409. package/dist/native/typography/Text.js +3 -3
  410. package/dist/navigation/AppHeader.js +14 -11
  411. package/dist/navigation/CommandPalette.js +2 -2
  412. package/dist/navigation/Pagination.js +2 -2
  413. package/dist/pt-BR.js +4 -4
  414. package/dist/social-login-button.js +11 -9
  415. package/dist/types/components/data-display/FleetMap/FleetBody.d.ts +22 -0
  416. package/dist/types/components/data-display/FleetMap/FleetBody.d.ts.map +1 -0
  417. package/dist/types/components/data-display/FleetMap/FleetCanvas.d.ts +50 -0
  418. package/dist/types/components/data-display/FleetMap/FleetCanvas.d.ts.map +1 -0
  419. package/dist/types/components/data-display/FleetMap/FleetMap.d.ts +32 -0
  420. package/dist/types/components/data-display/FleetMap/FleetMap.d.ts.map +1 -0
  421. package/dist/types/components/data-display/FleetMap/FleetMap.fixtures.d.ts +23 -0
  422. package/dist/types/components/data-display/FleetMap/FleetMap.fixtures.d.ts.map +1 -0
  423. package/dist/types/components/data-display/FleetMap/FleetMap.helpers.d.ts +45 -0
  424. package/dist/types/components/data-display/FleetMap/FleetMap.helpers.d.ts.map +1 -0
  425. package/dist/types/components/data-display/FleetMap/FleetMap.hooks.d.ts +54 -0
  426. package/dist/types/components/data-display/FleetMap/FleetMap.hooks.d.ts.map +1 -0
  427. package/dist/types/components/data-display/FleetMap/FleetMap.types.d.ts +145 -0
  428. package/dist/types/components/data-display/FleetMap/FleetMap.types.d.ts.map +1 -0
  429. package/dist/types/components/data-display/FleetMap/FleetRoster.d.ts +15 -0
  430. package/dist/types/components/data-display/FleetMap/FleetRoster.d.ts.map +1 -0
  431. package/dist/types/components/data-display/FleetMap/index.d.ts +5 -0
  432. package/dist/types/components/data-display/FleetMap/index.d.ts.map +1 -0
  433. package/dist/types/components/data-display/index.d.ts +1 -0
  434. package/dist/types/components/data-display/index.d.ts.map +1 -1
  435. package/dist/types/components/feedback/Dialog/Dialog.base.d.ts +64 -0
  436. package/dist/types/components/feedback/Dialog/Dialog.base.d.ts.map +1 -0
  437. package/dist/types/components/feedback/Dialog/Dialog.d.ts.map +1 -1
  438. package/dist/types/components/feedback/Dialog/Dialog.helpers.d.ts +35 -0
  439. package/dist/types/components/feedback/Dialog/Dialog.helpers.d.ts.map +1 -0
  440. package/dist/types/components/feedback/Dialog/Dialog.metrics.d.ts +133 -0
  441. package/dist/types/components/feedback/Dialog/Dialog.metrics.d.ts.map +1 -0
  442. package/dist/types/components/feedback/Dialog/Dialog.styles.d.ts +4 -4
  443. package/dist/types/components/feedback/Dialog/Dialog.styles.d.ts.map +1 -1
  444. package/dist/types/components/feedback/Dialog/Dialog.types.d.ts +8 -41
  445. package/dist/types/components/feedback/Dialog/Dialog.types.d.ts.map +1 -1
  446. package/dist/types/components/feedback/Dialog/index.d.ts +1 -1
  447. package/dist/types/components/feedback/Dialog/index.d.ts.map +1 -1
  448. package/dist/types/components/layout/Card/Card.base.d.ts +77 -0
  449. package/dist/types/components/layout/Card/Card.base.d.ts.map +1 -0
  450. package/dist/types/components/layout/Card/Card.d.ts.map +1 -1
  451. package/dist/types/components/layout/Card/Card.helpers.d.ts +8 -3
  452. package/dist/types/components/layout/Card/Card.helpers.d.ts.map +1 -1
  453. package/dist/types/components/layout/Card/Card.metrics.d.ts +182 -0
  454. package/dist/types/components/layout/Card/Card.metrics.d.ts.map +1 -0
  455. package/dist/types/components/layout/Card/Card.styles.d.ts +2 -2
  456. package/dist/types/components/layout/Card/Card.styles.d.ts.map +1 -1
  457. package/dist/types/components/layout/Card/Card.types.d.ts +10 -44
  458. package/dist/types/components/layout/Card/Card.types.d.ts.map +1 -1
  459. package/dist/types/components/layout/Card/index.d.ts +1 -1
  460. package/dist/types/components/layout/Card/index.d.ts.map +1 -1
  461. package/dist/types/platform/test-id.d.ts +14 -0
  462. package/dist/types/platform/test-id.d.ts.map +1 -1
  463. package/dist/types/tokens/mui-type.d.ts +1 -1
  464. package/dist/types/tokens/mui-type.d.ts.map +1 -1
  465. package/dist/types/tokens/shadow.d.ts +40 -0
  466. package/dist/types/tokens/shadow.d.ts.map +1 -0
  467. package/dist/types-native/components/feedback/Dialog/Dialog.base.d.ts +64 -0
  468. package/dist/types-native/components/feedback/Dialog/Dialog.base.d.ts.map +1 -0
  469. package/dist/types-native/components/feedback/Dialog/Dialog.helpers.d.ts +35 -0
  470. package/dist/types-native/components/feedback/Dialog/Dialog.helpers.d.ts.map +1 -0
  471. package/dist/types-native/components/feedback/Dialog/Dialog.look.native.d.ts +44 -0
  472. package/dist/types-native/components/feedback/Dialog/Dialog.look.native.d.ts.map +1 -0
  473. package/dist/types-native/components/feedback/Dialog/Dialog.metrics.d.ts +133 -0
  474. package/dist/types-native/components/feedback/Dialog/Dialog.metrics.d.ts.map +1 -0
  475. package/dist/types-native/components/feedback/Dialog/Dialog.native.d.ts +8 -0
  476. package/dist/types-native/components/feedback/Dialog/Dialog.native.d.ts.map +1 -0
  477. package/dist/types-native/components/feedback/Dialog/Dialog.types.native.d.ts +25 -0
  478. package/dist/types-native/components/feedback/Dialog/Dialog.types.native.d.ts.map +1 -0
  479. package/dist/types-native/components/feedback/Dialog/DialogParts.native.d.ts +39 -0
  480. package/dist/types-native/components/feedback/Dialog/DialogParts.native.d.ts.map +1 -0
  481. package/dist/types-native/components/feedback/Dialog/index.native.d.ts +4 -0
  482. package/dist/types-native/components/feedback/Dialog/index.native.d.ts.map +1 -0
  483. package/dist/types-native/components/layout/Card/Card.base.d.ts +77 -0
  484. package/dist/types-native/components/layout/Card/Card.base.d.ts.map +1 -0
  485. package/dist/types-native/components/layout/Card/Card.helpers.d.ts +11 -0
  486. package/dist/types-native/components/layout/Card/Card.helpers.d.ts.map +1 -0
  487. package/dist/types-native/components/layout/Card/Card.look.native.d.ts +57 -0
  488. package/dist/types-native/components/layout/Card/Card.look.native.d.ts.map +1 -0
  489. package/dist/types-native/components/layout/Card/Card.metrics.d.ts +182 -0
  490. package/dist/types-native/components/layout/Card/Card.metrics.d.ts.map +1 -0
  491. package/dist/types-native/components/layout/Card/Card.native.d.ts +11 -0
  492. package/dist/types-native/components/layout/Card/Card.native.d.ts.map +1 -0
  493. package/dist/types-native/components/layout/Card/Card.types.native.d.ts +28 -0
  494. package/dist/types-native/components/layout/Card/Card.types.native.d.ts.map +1 -0
  495. package/dist/types-native/components/layout/Card/CardParts.native.d.ts +55 -0
  496. package/dist/types-native/components/layout/Card/CardParts.native.d.ts.map +1 -0
  497. package/dist/types-native/components/layout/Card/index.native.d.ts +4 -0
  498. package/dist/types-native/components/layout/Card/index.native.d.ts.map +1 -0
  499. package/dist/types-native/platform/pulse-ring.native.d.ts +35 -0
  500. package/dist/types-native/platform/pulse-ring.native.d.ts.map +1 -0
  501. package/dist/types-native/platform/test-id.d.ts +14 -0
  502. package/dist/types-native/platform/test-id.d.ts.map +1 -1
  503. package/dist/types-native/tokens/mui-type.d.ts +1 -1
  504. package/dist/types-native/tokens/mui-type.d.ts.map +1 -1
  505. package/dist/types-native/tokens/shadow.d.ts +40 -0
  506. package/dist/types-native/tokens/shadow.d.ts.map +1 -0
  507. package/dist/typography/Heading.js +2 -2
  508. package/dist/typography/Paragraph.js +2 -2
  509. package/dist/typography/Text.js +2 -2
  510. package/dist/user-avatar.js +10 -8
  511. package/dist/utility/InfiniteScroll.js +2 -2
  512. package/dist/utility/InstallPrompt.js +2 -2
  513. package/package.json +13 -1
  514. package/src/components/data-display/CardKit/NATIVE-NOTES.md +48 -0
  515. package/src/components/data-display/FleetMap/FleetBody.tsx +96 -0
  516. package/src/components/data-display/FleetMap/FleetCanvas.tsx +80 -0
  517. package/src/components/data-display/FleetMap/FleetMap.fixtures.ts +70 -0
  518. package/src/components/data-display/FleetMap/FleetMap.helpers.ts +85 -0
  519. package/src/components/data-display/FleetMap/FleetMap.hooks.ts +164 -0
  520. package/src/components/data-display/FleetMap/FleetMap.md +182 -0
  521. package/src/components/data-display/FleetMap/FleetMap.tsx +169 -0
  522. package/src/components/data-display/FleetMap/FleetMap.types.ts +148 -0
  523. package/src/components/data-display/FleetMap/FleetRoster.tsx +321 -0
  524. package/src/components/data-display/FleetMap/index.ts +9 -0
  525. package/src/components/data-display/FleetMap/tests.md +79 -0
  526. package/src/components/data-display/FleetMap/track.md +50 -0
  527. package/src/components/data-display/index.ts +1 -0
  528. package/src/components/feedback/ConfirmAction/ConfirmAction.md +10 -4
  529. package/src/components/feedback/Dialog/Dialog.base.ts +69 -0
  530. package/src/components/feedback/Dialog/Dialog.helpers.ts +75 -0
  531. package/src/components/feedback/Dialog/Dialog.look.native.ts +159 -0
  532. package/src/components/feedback/Dialog/Dialog.metrics.ts +140 -0
  533. package/src/components/feedback/Dialog/Dialog.native.tsx +149 -0
  534. package/src/components/feedback/Dialog/Dialog.styles.ts +63 -41
  535. package/src/components/feedback/Dialog/Dialog.tsx +58 -74
  536. package/src/components/feedback/Dialog/Dialog.types.native.ts +46 -0
  537. package/src/components/feedback/Dialog/Dialog.types.ts +24 -41
  538. package/src/components/feedback/Dialog/DialogParts.native.tsx +257 -0
  539. package/src/components/feedback/Dialog/NATIVE-NOTES.md +16 -0
  540. package/src/components/feedback/Dialog/index.native.ts +16 -0
  541. package/src/components/feedback/Dialog/index.ts +8 -2
  542. package/src/components/layout/Card/Card.base.ts +92 -0
  543. package/src/components/layout/Card/Card.helpers.ts +13 -7
  544. package/src/components/layout/Card/Card.look.native.ts +204 -0
  545. package/src/components/layout/Card/Card.metrics.ts +171 -0
  546. package/src/components/layout/Card/Card.native.tsx +130 -0
  547. package/src/components/layout/Card/Card.styles.ts +88 -48
  548. package/src/components/layout/Card/Card.tsx +41 -25
  549. package/src/components/layout/Card/Card.types.native.ts +59 -0
  550. package/src/components/layout/Card/Card.types.ts +30 -45
  551. package/src/components/layout/Card/CardParts.native.tsx +262 -0
  552. package/src/components/layout/Card/NATIVE-NOTES.md +15 -0
  553. package/src/components/layout/Card/index.native.ts +18 -0
  554. package/src/components/layout/Card/index.ts +9 -0
  555. package/src/platform/pulse-ring.native.tsx +82 -0
  556. package/src/platform/test-id.ts +17 -0
  557. package/src/tokens/mui-type.ts +2 -1
  558. package/src/tokens/shadow.ts +59 -0
  559. package/dist/chunk-6PRA45LC.js.map +0 -1
  560. package/dist/chunk-D2IASECY.js.map +0 -1
  561. package/dist/chunk-RI5JZLZL.js.map +0 -1
  562. package/dist/chunk-S5LE2ARG.js.map +0 -1
  563. package/dist/chunk-VMF3UXM4.js +0 -137
  564. package/dist/chunk-VMF3UXM4.js.map +0 -1
  565. package/dist/chunk-X3HL5C6H.js +0 -1
  566. package/dist/native/chunks/chunk-HSIND52T.js.map +0 -1
  567. /package/dist/{chunk-X3HL5C6H.js.map → _internal/components/data-display/FleetMap/FleetBody.js.map} +0 -0
  568. /package/dist/{chunk-NUE774AN.js.map → chunk-25R3ITGZ.js.map} +0 -0
  569. /package/dist/{chunk-Z6UEOSL7.js.map → chunk-2FDBR77W.js.map} +0 -0
  570. /package/dist/{chunk-IFNK5TPI.js.map → chunk-2HPP6RVC.js.map} +0 -0
  571. /package/dist/{chunk-GCXYCDOA.js.map → chunk-2UGJIKVA.js.map} +0 -0
  572. /package/dist/{chunk-26Z7QWID.js.map → chunk-343TTIHD.js.map} +0 -0
  573. /package/dist/{chunk-BRSF5NRT.js.map → chunk-3FLVIVOK.js.map} +0 -0
  574. /package/dist/{chunk-BDVNAU2C.js.map → chunk-4523RYE7.js.map} +0 -0
  575. /package/dist/{chunk-4ETQRBZC.js.map → chunk-46UPILLK.js.map} +0 -0
  576. /package/dist/{chunk-WMALDOF5.js.map → chunk-4G3FGCWX.js.map} +0 -0
  577. /package/dist/{chunk-I3MDKPGG.js.map → chunk-4IVOHL32.js.map} +0 -0
  578. /package/dist/{chunk-SAHQLXNN.js.map → chunk-4LRFGB3K.js.map} +0 -0
  579. /package/dist/{chunk-ZOUWHGV3.js.map → chunk-4MGFUPQT.js.map} +0 -0
  580. /package/dist/{chunk-TLX66HCW.js.map → chunk-4OHRZW7U.js.map} +0 -0
  581. /package/dist/{chunk-2QFTAGDH.js.map → chunk-4X4KM4ZB.js.map} +0 -0
  582. /package/dist/{chunk-7ZH7ZB33.js.map → chunk-4XZXLB4I.js.map} +0 -0
  583. /package/dist/{chunk-77F36LQQ.js.map → chunk-5OIH36KX.js.map} +0 -0
  584. /package/dist/{chunk-GDEXYUPF.js.map → chunk-67L7HMEP.js.map} +0 -0
  585. /package/dist/{chunk-ZFPJBKVZ.js.map → chunk-6JGPPTLX.js.map} +0 -0
  586. /package/dist/{chunk-VIK3HAUQ.js.map → chunk-73NJCGQG.js.map} +0 -0
  587. /package/dist/{chunk-D4T646G4.js.map → chunk-7NSX7A5H.js.map} +0 -0
  588. /package/dist/{chunk-QS7ZGRNS.js.map → chunk-7VN7LFBA.js.map} +0 -0
  589. /package/dist/{chunk-3UOHKHOT.js.map → chunk-ACFGEZ4Q.js.map} +0 -0
  590. /package/dist/{chunk-GBNOYRLP.js.map → chunk-AEGXHZQT.js.map} +0 -0
  591. /package/dist/{chunk-BEH4DN63.js.map → chunk-AJGYHDA5.js.map} +0 -0
  592. /package/dist/{chunk-65DLYC4S.js.map → chunk-AVGTTWTE.js.map} +0 -0
  593. /package/dist/{chunk-PXH24VIP.js.map → chunk-B6IURHSZ.js.map} +0 -0
  594. /package/dist/{chunk-XEE7PLDR.js.map → chunk-BZTFPSWT.js.map} +0 -0
  595. /package/dist/{chunk-B3BK2SNS.js.map → chunk-C3CMEDSO.js.map} +0 -0
  596. /package/dist/{chunk-OH3YGJT5.js.map → chunk-CBTY36TU.js.map} +0 -0
  597. /package/dist/{chunk-JIINGMEB.js.map → chunk-CHPZTF34.js.map} +0 -0
  598. /package/dist/{chunk-PWXL3QQ6.js.map → chunk-CJBBGMIA.js.map} +0 -0
  599. /package/dist/{chunk-BPYPUEM5.js.map → chunk-CZJLWCEG.js.map} +0 -0
  600. /package/dist/{chunk-FPWB5ILF.js.map → chunk-DRHIIUDO.js.map} +0 -0
  601. /package/dist/{chunk-BEGWE5O4.js.map → chunk-DTC224UJ.js.map} +0 -0
  602. /package/dist/{chunk-UB76PBDF.js.map → chunk-DVFIE54C.js.map} +0 -0
  603. /package/dist/{chunk-GO4MVQGC.js.map → chunk-DW5FRWRQ.js.map} +0 -0
  604. /package/dist/{chunk-6Z4H2Y77.js.map → chunk-E27Y7FF2.js.map} +0 -0
  605. /package/dist/{chunk-PANMJFDS.js.map → chunk-E55CJV65.js.map} +0 -0
  606. /package/dist/{chunk-JXAYT6LX.js.map → chunk-EJQW2IYW.js.map} +0 -0
  607. /package/dist/{chunk-TPIBJP4S.js.map → chunk-EOHKZGOZ.js.map} +0 -0
  608. /package/dist/{chunk-MSUSZLRE.js.map → chunk-EWT3WMVY.js.map} +0 -0
  609. /package/dist/{chunk-DH75UNF3.js.map → chunk-FGK2C7JR.js.map} +0 -0
  610. /package/dist/{chunk-AD776JPA.js.map → chunk-FR67FG2U.js.map} +0 -0
  611. /package/dist/{chunk-SHQWIDD5.js.map → chunk-GJQYM3PM.js.map} +0 -0
  612. /package/dist/{chunk-7KTU6YMQ.js.map → chunk-GMTM6EN7.js.map} +0 -0
  613. /package/dist/{chunk-WROCSDVL.js.map → chunk-GSFNH4C5.js.map} +0 -0
  614. /package/dist/{chunk-PF5HDFYY.js.map → chunk-GVA5CYKP.js.map} +0 -0
  615. /package/dist/{chunk-Z5ABJLTM.js.map → chunk-HFXTAEYY.js.map} +0 -0
  616. /package/dist/{chunk-FOMK3WPG.js.map → chunk-HLYPI5CO.js.map} +0 -0
  617. /package/dist/{chunk-VR5HDUBK.js.map → chunk-HP2ODXNA.js.map} +0 -0
  618. /package/dist/{chunk-GBRKP5GZ.js.map → chunk-I5SBTNV2.js.map} +0 -0
  619. /package/dist/{chunk-TP4N3X2Q.js.map → chunk-IPVYEPXO.js.map} +0 -0
  620. /package/dist/{chunk-RRO2EOJB.js.map → chunk-JB67KPGM.js.map} +0 -0
  621. /package/dist/{chunk-5ZOJLYD2.js.map → chunk-JE6RZ5L6.js.map} +0 -0
  622. /package/dist/{chunk-4HYXEMBP.js.map → chunk-JIKWZDNK.js.map} +0 -0
  623. /package/dist/{chunk-4MLDWACO.js.map → chunk-JM64OEU6.js.map} +0 -0
  624. /package/dist/{chunk-2QLVUVVR.js.map → chunk-JSH3HFDQ.js.map} +0 -0
  625. /package/dist/{chunk-TZ4SFX3M.js.map → chunk-JWW2Z3RH.js.map} +0 -0
  626. /package/dist/{chunk-QFHH2NU5.js.map → chunk-JXNT5TUP.js.map} +0 -0
  627. /package/dist/{chunk-FINCVAAR.js.map → chunk-KHWCX4LI.js.map} +0 -0
  628. /package/dist/{chunk-THZ2NAA4.js.map → chunk-KW7H5O3K.js.map} +0 -0
  629. /package/dist/{chunk-XLJJ2ZAP.js.map → chunk-L4U23SBX.js.map} +0 -0
  630. /package/dist/{chunk-ZXLIWOXC.js.map → chunk-LS4FMSHY.js.map} +0 -0
  631. /package/dist/{chunk-SFAP5EH5.js.map → chunk-LUMF63BM.js.map} +0 -0
  632. /package/dist/{chunk-CZPU5TW3.js.map → chunk-LYSSO6WC.js.map} +0 -0
  633. /package/dist/{chunk-736HP6BL.js.map → chunk-M4LQRQFL.js.map} +0 -0
  634. /package/dist/{chunk-426FTCMF.js.map → chunk-MESRKY67.js.map} +0 -0
  635. /package/dist/{chunk-B5PYBEXO.js.map → chunk-MP4VSWHK.js.map} +0 -0
  636. /package/dist/{chunk-UOPQOBQZ.js.map → chunk-MYGNIFZC.js.map} +0 -0
  637. /package/dist/{chunk-6RGWDKUL.js.map → chunk-N2TUX4A5.js.map} +0 -0
  638. /package/dist/{chunk-VWGR5XUP.js.map → chunk-NWNSUHEB.js.map} +0 -0
  639. /package/dist/{chunk-4K7FDVAB.js.map → chunk-O3336DJ6.js.map} +0 -0
  640. /package/dist/{chunk-YCCKY5VW.js.map → chunk-OFOYMZRY.js.map} +0 -0
  641. /package/dist/{chunk-OCXCH2ZW.js.map → chunk-OIKQO73C.js.map} +0 -0
  642. /package/dist/{chunk-QZDBWXZG.js.map → chunk-OP65D4UR.js.map} +0 -0
  643. /package/dist/{chunk-MCRIT46W.js.map → chunk-OTH7H3IP.js.map} +0 -0
  644. /package/dist/{chunk-BQQONDW5.js.map → chunk-OVLNF4AZ.js.map} +0 -0
  645. /package/dist/{chunk-AGYGNNOM.js.map → chunk-PQECNGDE.js.map} +0 -0
  646. /package/dist/{chunk-IIROZKW5.js.map → chunk-PRUSQQDT.js.map} +0 -0
  647. /package/dist/{chunk-IPE5FFFD.js.map → chunk-PUBPZOQJ.js.map} +0 -0
  648. /package/dist/{chunk-FB36IHCE.js.map → chunk-QFVFHIHE.js.map} +0 -0
  649. /package/dist/{chunk-V5P5Q6HM.js.map → chunk-QJRDDVZ2.js.map} +0 -0
  650. /package/dist/{chunk-WBKWIFXA.js.map → chunk-QYNCPS5W.js.map} +0 -0
  651. /package/dist/{chunk-VPHOSIPB.js.map → chunk-R6SNYC3D.js.map} +0 -0
  652. /package/dist/{chunk-STH66VLA.js.map → chunk-R7R3LOKW.js.map} +0 -0
  653. /package/dist/{chunk-W2UTDN4T.js.map → chunk-RBGOGTT2.js.map} +0 -0
  654. /package/dist/{chunk-VWBWKLXX.js.map → chunk-SX3V2DLV.js.map} +0 -0
  655. /package/dist/{chunk-P7FQUGED.js.map → chunk-TNVO2DTB.js.map} +0 -0
  656. /package/dist/{chunk-WTIOCG4M.js.map → chunk-TOYEP23N.js.map} +0 -0
  657. /package/dist/{chunk-G2IPK2XE.js.map → chunk-TPLKJHNN.js.map} +0 -0
  658. /package/dist/{chunk-U2AC4AQX.js.map → chunk-TU5EIKJA.js.map} +0 -0
  659. /package/dist/{chunk-ZGHIHEND.js.map → chunk-TW3BXVEU.js.map} +0 -0
  660. /package/dist/{chunk-BGYLL467.js.map → chunk-TXHJX2NG.js.map} +0 -0
  661. /package/dist/{chunk-5RQ7N63M.js.map → chunk-TZDDL3DR.js.map} +0 -0
  662. /package/dist/{chunk-RPQ3W2C6.js.map → chunk-U2ZDN2AL.js.map} +0 -0
  663. /package/dist/{chunk-WPZT2JD4.js.map → chunk-U7Q2Y6WG.js.map} +0 -0
  664. /package/dist/{chunk-E46PG577.js.map → chunk-URXT5TOY.js.map} +0 -0
  665. /package/dist/{chunk-P6IPJYCS.js.map → chunk-VNNG46TS.js.map} +0 -0
  666. /package/dist/{chunk-CXVMD6FE.js.map → chunk-VON4BFK4.js.map} +0 -0
  667. /package/dist/{chunk-2SWQ6HIK.js.map → chunk-W3FAKT3D.js.map} +0 -0
  668. /package/dist/{chunk-JDMYD6QC.js.map → chunk-W4SDVTZC.js.map} +0 -0
  669. /package/dist/{chunk-7MAOQIWA.js.map → chunk-W4YWU7LQ.js.map} +0 -0
  670. /package/dist/{chunk-Y46RBFBV.js.map → chunk-W7Y6RA6W.js.map} +0 -0
  671. /package/dist/{chunk-XFU2S6XT.js.map → chunk-WGRS4PGY.js.map} +0 -0
  672. /package/dist/{chunk-OOGEYCJH.js.map → chunk-WIT3Y7JT.js.map} +0 -0
  673. /package/dist/{chunk-KT6HWAEN.js.map → chunk-WQA4LIIK.js.map} +0 -0
  674. /package/dist/{chunk-J2KSG754.js.map → chunk-WRDPWEIC.js.map} +0 -0
  675. /package/dist/{chunk-RPWEXIAW.js.map → chunk-X5MPHXG5.js.map} +0 -0
  676. /package/dist/{chunk-UEIVXFUC.js.map → chunk-XELVDPKL.js.map} +0 -0
  677. /package/dist/{chunk-RRZBATXK.js.map → chunk-XKV5ZIBG.js.map} +0 -0
  678. /package/dist/{chunk-ZKFYBC6G.js.map → chunk-XSF6AXEU.js.map} +0 -0
  679. /package/dist/{chunk-R6RVBYTU.js.map → chunk-XUJG2HFW.js.map} +0 -0
  680. /package/dist/{chunk-FRQ4HNGF.js.map → chunk-YJ4HM25H.js.map} +0 -0
  681. /package/dist/{chunk-TVO5STZB.js.map → chunk-YQ6TNHAC.js.map} +0 -0
  682. /package/dist/{chunk-BNNSO4MC.js.map → chunk-YTOYMJPM.js.map} +0 -0
  683. /package/dist/{chunk-IH4RSRQA.js.map → chunk-ZA4U5GDU.js.map} +0 -0
  684. /package/dist/native/chunks/{chunk-OGWPPQL4.js.map → chunk-75JQYVDZ.js.map} +0 -0
  685. /package/dist/native/chunks/{chunk-WKMDCNIN.js.map → chunk-7LTVGW23.js.map} +0 -0
  686. /package/dist/native/chunks/{chunk-RJVM5YDE.js.map → chunk-ATS7STZJ.js.map} +0 -0
  687. /package/dist/native/chunks/{chunk-YTHR4Y5P.js.map → chunk-GWGIWQO7.js.map} +0 -0
  688. /package/dist/native/chunks/{chunk-D4EYAXNG.js.map → chunk-QYUD3S6F.js.map} +0 -0
@@ -0,0 +1,85 @@
1
+ import type { FleetFreshness, FleetUnit } from './FleetMap.types';
2
+
3
+ /**
4
+ * How current a fix is, on the two thresholds the caller supplied.
5
+ *
6
+ * Inclusive at both boundaries in the direction that reads better on a screen:
7
+ * a unit exactly at the lagging threshold is already lagging. A boundary has to
8
+ * fall somewhere, and the conservative side is the one that does not tell a
9
+ * dispatcher somebody is live when they are on the edge of not being.
10
+ */
11
+ export function freshnessOf(
12
+ staleSeconds: number,
13
+ laggingAfterSeconds: number,
14
+ staleAfterSeconds: number,
15
+ ): FleetFreshness {
16
+ if (staleSeconds >= staleAfterSeconds) return 'stale';
17
+ if (staleSeconds >= laggingAfterSeconds) return 'lagging';
18
+ return 'live';
19
+ }
20
+
21
+ /** A latitude/longitude pair, as the map wants its centre. */
22
+ export interface LatLng {
23
+ lat: number;
24
+ lng: number;
25
+ }
26
+
27
+ /**
28
+ * Where the map should point.
29
+ *
30
+ * The selected unit when there is one — a dispatcher who clicked a name is
31
+ * asking to look at them. Otherwise the fleet's own centroid, which keeps
32
+ * everybody in frame without the caller having to compute a bounding box.
33
+ *
34
+ * `null` for an empty fleet rather than a coordinate: (0, 0) is a real place in
35
+ * the Atlantic, and a map that quietly sails there is worse than one that says
36
+ * it has nothing to show.
37
+ */
38
+ export function mapCentre(
39
+ units: readonly FleetUnit[],
40
+ selectedId?: string | null,
41
+ ): LatLng | null {
42
+ if (units.length === 0) return null;
43
+ const selected = selectedId ? units.find((unit) => unit.id === selectedId) : undefined;
44
+ if (selected) return { lat: selected.latitude, lng: selected.longitude };
45
+ const sum = units.reduce(
46
+ (acc, unit) => ({ lat: acc.lat + unit.latitude, lng: acc.lng + unit.longitude }),
47
+ { lat: 0, lng: 0 },
48
+ );
49
+ return { lat: sum.lat / units.length, lng: sum.lng / units.length };
50
+ }
51
+
52
+ /**
53
+ * The roster's order: freshest first, then alphabetically.
54
+ *
55
+ * Not the caller's order, deliberately. The one question this panel answers is
56
+ * *who is moving right now*, and a list sorted by anything else buries the
57
+ * answer under whoever happens to sort first. Ties break on the label so the
58
+ * list does not reshuffle between polls when two units share a staleness.
59
+ */
60
+ export function rosterOrder(units: readonly FleetUnit[]): FleetUnit[] {
61
+ return [...units].sort(
62
+ (a, b) => a.staleSeconds - b.staleSeconds || a.label.localeCompare(b.label),
63
+ );
64
+ }
65
+
66
+ /**
67
+ * Move the selection by one row, wrapping at both ends.
68
+ *
69
+ * Wrapping rather than stopping: this is a short list a dispatcher arrows
70
+ * through repeatedly, and a selection that sticks at the last row makes the
71
+ * keyboard path feel broken next to the mouse one.
72
+ */
73
+ export function nextSelection(
74
+ units: readonly FleetUnit[],
75
+ currentId: string | null | undefined,
76
+ step: 1 | -1,
77
+ ): string | null {
78
+ if (units.length === 0) return null;
79
+ const index = units.findIndex((unit) => unit.id === currentId);
80
+ // Nothing selected: Down opens at the top and Up opens at the bottom, which
81
+ // is what every listbox in the house does.
82
+ if (index === -1) return (step === 1 ? units[0] : units[units.length - 1])?.id ?? null;
83
+ const next = (index + step + units.length) % units.length;
84
+ return units[next]?.id ?? null;
85
+ }
@@ -0,0 +1,164 @@
1
+ import React from 'react';
2
+
3
+ import { mapCentre, nextSelection, rosterOrder, type LatLng } from './FleetMap.helpers';
4
+ import type { FleetUnit } from './FleetMap.types';
5
+
6
+ /**
7
+ * Everything the board derives from its props, in one hook.
8
+ *
9
+ * Split out of the component so the component is layout and nothing else.
10
+ *
11
+ * The memos are honest about what they buy, which is less than it looks. `units`
12
+ * arrives as a fresh array on every poll, so `ordered` and `markers` are
13
+ * recomputed on every poll whatever these do — a new array is a new identity.
14
+ * What they buy is stability across the renders a poll does NOT cause: a parent
15
+ * re-render, a selection change (which re-runs `centre` but not `ordered`), a
16
+ * theme flip. Sorting a fleet is cheap either way; this is tidiness, not a
17
+ * measured win, and it should not be read as one.
18
+ *
19
+ * `centre` is the exception, and there it is load-bearing rather than tidy —
20
+ * see {@link useFleetMap}.
21
+ *
22
+ * ## Selection works with, without, or half-way through a handler
23
+ *
24
+ * `selectedId` and `onSelect` are both optional, so all four combinations
25
+ * arrive. Left purely controlled, the two useful ones broke: with neither prop
26
+ * the roster was a listbox that answered nothing, and arrowing it called
27
+ * `preventDefault` before a no-op `select`, so the keys did not move a
28
+ * selection AND did not scroll the page either.
29
+ *
30
+ * So the hook keeps its own selection and defers to `selectedId` only when the
31
+ * caller passes one — the ordinary controlled/uncontrolled split, the same one
32
+ * an `<input>` makes. `onSelect` still fires either way, so a consumer can
33
+ * observe the selection without owning it.
34
+ */
35
+
36
+ /** One pin, in the shape `MapPreview` takes. */
37
+ export interface FleetMarker {
38
+ position: LatLng;
39
+ title: string;
40
+ onClick: () => void;
41
+ }
42
+
43
+ export interface FleetMapState {
44
+ /** The units, freshest first — see {@link rosterOrder}. */
45
+ ordered: FleetUnit[];
46
+ /**
47
+ * The selection in force — the caller's when they own it, this hook's when
48
+ * they do not. Everything downstream reads THIS and never the raw prop.
49
+ */
50
+ active: string | null;
51
+ /** Where the map points, or `null` when there is nothing to show. */
52
+ centre: LatLng | null;
53
+ select: (id: string) => void;
54
+ markers: FleetMarker[];
55
+ onKeyDown: (event: React.KeyboardEvent<HTMLDivElement>) => void;
56
+ }
57
+
58
+ /** Which way an arrow moves the selection, or `0` when it is not ours. */
59
+ function stepFor(event: React.KeyboardEvent<HTMLDivElement>): 1 | -1 | 0 {
60
+ // A modified arrow is the PAGE's shortcut, not the roster's: Cmd+Down is
61
+ // "scroll to the end of the document" on macOS, and Shift+Arrow extends a
62
+ // selection. Capturing them would take a browser gesture away.
63
+ if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return 0;
64
+ if (event.key === 'ArrowDown') return 1;
65
+ if (event.key === 'ArrowUp') return -1;
66
+ return 0;
67
+ }
68
+
69
+ /**
70
+ * Who owns the selection, decided ONCE on the first render.
71
+ *
72
+ * Exactly as React decides it for an `<input>`, and for the same reason.
73
+ * `selectedId` is typed `string | null | undefined`, so `useState<string>()` —
74
+ * the natural shape for a caller — hands us `undefined` on the first render and
75
+ * again on every reset. Re-deriving the mode from the prop each time would make
76
+ * the component change its own semantics mid-life: it starts uncontrolled,
77
+ * silently becomes controlled the moment the caller's `onSelect` writes a value
78
+ * back, and then silently un-becomes it when they clear — resurrecting whatever
79
+ * was selected before the hand-off.
80
+ *
81
+ * Latched, `undefined` is unambiguous within each mode: to a controlled board it
82
+ * is "nobody is selected", so clearing the caller's state clears the roster; to
83
+ * an uncontrolled one it is simply the prop staying absent. A caller who wants
84
+ * control passes `string | null` from the first render.
85
+ */
86
+ function useSelection(
87
+ selectedId: string | null | undefined,
88
+ onSelect: ((id: string) => void) | undefined,
89
+ ): { active: string | null; select: (id: string) => void; controlled: boolean } {
90
+ const controlledRef = React.useRef(selectedId !== undefined);
91
+ const controlled = controlledRef.current;
92
+ const [own, setOwn] = React.useState<string | null>(null);
93
+
94
+ const select = React.useCallback(
95
+ (id: string) => {
96
+ if (!controlled) setOwn(id);
97
+ onSelect?.(id);
98
+ },
99
+ [controlled, onSelect],
100
+ );
101
+
102
+ return { active: controlled ? (selectedId ?? null) : own, select, controlled };
103
+ }
104
+
105
+ export function useFleetMap(
106
+ units: readonly FleetUnit[],
107
+ selectedId: string | null | undefined,
108
+ onSelect: ((id: string) => void) | undefined,
109
+ ): FleetMapState {
110
+ const ordered = React.useMemo(() => rosterOrder(units), [units]);
111
+ const { active, select, controlled } = useSelection(selectedId, onSelect);
112
+
113
+ // Memoised on the COORDINATES and not the object, because `mapCentre` builds
114
+ // a fresh literal every call and `MapPreview` re-centres from an effect keyed
115
+ // on `center`'s identity. A poll that changes nothing would otherwise hand it
116
+ // a new object, and the map would jump back to the centroid — throwing away a
117
+ // pan the dispatcher had just made, on a timer, for as long as they watch it.
118
+ //
119
+ // ROUNDED, because keying on the raw numbers was not enough. `mapCentre`
120
+ // sums over `ordered`, and floating-point addition is not associative — so
121
+ // re-sorting the SAME coordinates can change the centroid's last bit.
122
+ // `rosterOrder` sorts on `staleSeconds`, which moves on every poll, so rank
123
+ // swaps are the ordinary case for a fleet that is standing still: measured
124
+ // over 20k random three-rider fleets, a single adjacent swap changed the
125
+ // centroid 17% of the time. Six decimals is ~11cm, far finer than a map
126
+ // centre resolves and far coarser than the noise.
127
+ const raw = mapCentre(ordered, active);
128
+ const lat = raw === null ? null : Math.round(raw.lat * 1e6) / 1e6;
129
+ const lng = raw === null ? null : Math.round(raw.lng * 1e6) / 1e6;
130
+ const centre = React.useMemo(
131
+ () => (lat === null || lng === null ? null : { lat, lng }),
132
+ [lat, lng],
133
+ );
134
+
135
+ const onKeyDown = React.useCallback(
136
+ (event: React.KeyboardEvent<HTMLDivElement>) => {
137
+ const step = stepFor(event);
138
+ if (step === 0) return;
139
+ // Nothing can move a CONTROLLED selection without a handler, so the keys
140
+ // belong to the page. Swallowing them there left a keyboard user unable to
141
+ // move the selection and unable to scroll past the roster.
142
+ if (controlled && !onSelect) return;
143
+ const next = nextSelection(ordered, active, step);
144
+ // `preventDefault` only once a move is certain, so the page still scrolls
145
+ // with the arrow keys when the list is empty and there is nothing to move.
146
+ if (next === null) return;
147
+ event.preventDefault();
148
+ select(next);
149
+ },
150
+ [ordered, active, select, controlled, onSelect],
151
+ );
152
+
153
+ const markers = React.useMemo(
154
+ () =>
155
+ ordered.map((unit) => ({
156
+ position: { lat: unit.latitude, lng: unit.longitude },
157
+ title: unit.label,
158
+ onClick: () => select(unit.id),
159
+ })),
160
+ [ordered, select],
161
+ );
162
+
163
+ return { ordered, active, centre, select, markers, onKeyDown };
164
+ }
@@ -0,0 +1,182 @@
1
+ # FleetMap
2
+
3
+ Where a set of tracked units is **right now**: a map beside the roster that
4
+ reads it.
5
+
6
+ Product-free by construction. It draws labelled dots with a freshness state, and
7
+ every word — the heading, the three freshness names, how a duration and a
8
+ distance are written — arrives through `copy`. Couriers on motorbikes, service
9
+ vans and field engineers are all the same picture.
10
+
11
+ ## Use cases
12
+
13
+ - A dispatcher watching a delivery fleet during a shift.
14
+ - A field-service board showing which engineers are moving and which have gone
15
+ quiet.
16
+ - Any "where is everybody" panel where the answer is a small set of named people
17
+ with a last-known position and a staleness.
18
+
19
+ ## Three decisions that shape the API
20
+
21
+ ### The roster is the accessible representation, not a sidebar
22
+
23
+ A map is a picture, and a screen reader cannot read one. So the list carries the
24
+ information: everything a sighted user takes from a pin — who, how recently,
25
+ what they are carrying — is on the row, and the row's freshness is spelled out
26
+ in words rather than carried by the dot's colour.
27
+
28
+ The map is a **named landmark** (`role="region"` with a label) rather than an
29
+ `aria-hidden` one. Its controls are focusable, and `aria-hidden` over a
30
+ focusable subtree is the `aria-hidden-focus` violation: a keyboard user tabs
31
+ into a region a screen reader insists is not there. The landmark role is what
32
+ puts it in the rotor, so a reader can skip past it in one gesture.
33
+
34
+ When there is no centre to point at — a fleet that is still loading and has
35
+ reported nothing — the map renders **nothing** rather than falling back to
36
+ `0, 0`, which is a real place in the Gulf of Guinea.
37
+
38
+ ### Nothing here formats
39
+
40
+ `copy.lastSeen` and `copy.accuracy` are **functions**, not strings. A duration
41
+ and a distance are locale rules, and the same line `StatCard` holds for its
42
+ `value` applies: a component that wrote `"2 min ago"` would have made English
43
+ the only language it could ever render, and a `lastSeenTemplate` string would
44
+ have fixed the shape as well as the words.
45
+
46
+ ### An empty fleet is an empty STATE, never an empty map
47
+
48
+ A map with no pins is indistinguishable from a map that failed to load, and
49
+ telling those two apart is the entire question a dispatcher is asking.
50
+
51
+ ## Props
52
+
53
+ | prop | type | default | what it does |
54
+ |---|---|---|---|
55
+ | `units` | `readonly FleetUnit[]` | — | everyone currently reporting; empty renders the empty state |
56
+ | `copy` | `FleetMapCopy` | — | every word, plus the two formatters |
57
+ | `selectedId` | `string \| null` | — | pass it to CONTROL the selection; omit it and the component keeps its own |
58
+ | `onSelect` | `(id: string) => void` | — | a click on a row or a pin, and each arrow-key move |
59
+ | `laggingAfterSeconds` | `number` | `90` | when a unit stops reading as `live` |
60
+ | `staleAfterSeconds` | `number` | `300` | when it stops reading as `lagging` |
61
+ | `height` | `string` | `'420px'` | the map's height, any CSS length |
62
+ | `loading` | `boolean` | `false` | skeletons only before the first units land; `aria-busy` either way |
63
+ | `className` | `string` | — | on the panel root |
64
+ | `dataTestId` | `string` | `'fleet-map'` | every child TEST id derives from it; DOM ids are generated |
65
+
66
+ ### `FleetUnit`
67
+
68
+ ```ts
69
+ {
70
+ id: string;
71
+ label: string; // the name on the pin and the row
72
+ latitude: number;
73
+ longitude: number;
74
+ accuracyM?: number | null; // metres; a row with none renders none
75
+ staleSeconds: number; // since the fix was ACCEPTED, on the SERVER's clock
76
+ badge?: string; // pre-formatted, e.g. "2 deliveries"
77
+ }
78
+ ```
79
+
80
+ `staleSeconds` is measured against the **server's** clock, and the caller
81
+ computes it. The distinction is not pedantry: a device whose own clock is an
82
+ hour slow would otherwise report itself as an hour absent while reporting
83
+ perfectly.
84
+
85
+ ## Why the thresholds have no domain default
86
+
87
+ They are props because the answer belongs entirely to the fleet's own ping
88
+ cadence. A phone reporting every twenty seconds is late at ninety; a tracker
89
+ reporting every five minutes is not. The defaults are sized for the first case
90
+ and are a starting point, not a rule — a component that picked one would be
91
+ picking it for every consumer.
92
+
93
+ ## Usage
94
+
95
+ ```tsx
96
+ <FleetMap
97
+ units={couriers}
98
+ copy={{
99
+ title: 'Motoboys na rua',
100
+ emptyTitle: 'Ninguém reportando',
101
+ emptyDescription: 'Um motoboy aparece aqui quando o celular envia a primeira posição.',
102
+ rosterLabel: 'Motoboys, mais recentes primeiro',
103
+ mapLabel: 'Mapa de onde os motoboys estão',
104
+ freshness: { live: 'Ao vivo', lagging: 'Atrasado', stale: 'Sem sinal' },
105
+ lastSeen: (s) => (s < 60 ? `há ${s}s` : `há ${Math.floor(s / 60)} min`),
106
+ accuracy: (m) => `±${Math.round(m)} m`,
107
+ map: PT_BR_MAP_PREVIEW_COPY,
108
+ }}
109
+ selectedId={selected}
110
+ onSelect={setSelected}
111
+ />
112
+ ```
113
+
114
+ ## Accessibility
115
+
116
+ - The panel is a `region` labelled by its heading.
117
+ - The roster is a `listbox` with `option` rows, **one tab stop**, arrow keys
118
+ moving the selection and wrapping at both ends, and
119
+ `aria-activedescendant` naming the selected row.
120
+ - Freshness is stated in words on every row; the coloured dot is `aria-hidden`
121
+ so the state is not read twice, and colour is never the only carrier.
122
+ - The map region is a named landmark rather than hidden — see above.
123
+ - The active option is kept in view as the selection moves, so a keyboard user
124
+ is not walking it below the fold unseen. The ROSTER's own container is
125
+ scrolled, never the page: `scrollIntoView` walks every scrollable ancestor
126
+ including the document, which would drag a dispatcher back to this panel on
127
+ every poll.
128
+ - `aria-activedescendant` is emitted only when the selected id names a row that
129
+ is actually rendered: a controlled selection can outlive the unit it names.
130
+ - The active option's scroll effect also watches its POSITION, because the
131
+ roster re-sorts on every poll and a still-selected row can move under it.
132
+ - While `loading`, the MAP AND ROSTER are marked `aria-busy` and the heading
133
+ stays, so the layout does not reflow when the data lands. The panel root is
134
+ deliberately not the busy element: `aria-busy` tells assistive tech to hold
135
+ back changes inside it, and the announcement region is a SIBLING of the busy
136
+ half rather than a descendant of it.
137
+ - `aria-busy` is a state and utters nothing, so set `copy.loading` if the reload
138
+ should be ANNOUNCED — that string goes into a visually hidden `role="status"`.
139
+ Left unset, the reload is silent. The region is mounted as soon as
140
+ `copy.loading` is given and only its TEXT changes, because a screen reader
141
+ watches an existing region rather than announcing one that arrives already
142
+ populated. That covers a board that starts idle and reloads; a board MOUNTED
143
+ already loading is silent, as any live region is at mount.
144
+ - Skeletons replace the roster only while there are no units yet. A poll that
145
+ refreshes a populated list keeps the listbox mounted, because unmounting it
146
+ throws away the focus inside it.
147
+ - The map is a named landmark, so a reader can jump past it — but it is not
148
+ silent. `MapPreview` carries its own `aria-live="polite"` and announces its
149
+ centre coordinates, in English, on every re-centre. That string is the one
150
+ piece of user-facing text here that does not come through `copy`; fixing it
151
+ means changing `MapPreview`, which every consumer shares.
152
+
153
+ ## Best practices
154
+
155
+ - Sort nothing before passing `units`. The component orders freshest first and
156
+ breaks ties on the label, so a poll does not reshuffle the list.
157
+ - Keep `selectedId` in the consumer's state when something ELSE needs to know
158
+ the selection — a detail panel beside the board, a URL, a second map. That is
159
+ what controlling it buys; a click on the map and a click on the row are the
160
+ same event either way.
161
+ - Otherwise pass neither `selectedId` nor `onSelect` and let the component hold
162
+ it. Passing `selectedId` alone with no `onSelect` is a selection nothing can
163
+ move, and the arrow keys then belong to the page rather than the roster.
164
+ - Pre-format `badge`. It is rendered, never parsed.
165
+
166
+ ## Known limits
167
+
168
+ - **Not ported to React Native.** `@12-apps/ui` ships a native build for 26 of
169
+ its 141 subpaths; this is not one, and neither is the `MapPreview` it wraps.
170
+ Being unported is the ordinary state — 115 subpaths are, at the time of
171
+ writing — and it fails LOUDLY under Metro: an unported subpath resolves to the
172
+ web file and errors on `@mui/material` at import rather than rendering a blank
173
+ view. It is also the right call for this
174
+ component: a fleet board is a dispatcher's screen, and the tracked unit's own
175
+ device reports a position rather than drawing the fleet.
176
+ - **The map's own `aria-label` is English**, and comes from `MapPreview` rather
177
+ than from `copy`. Everything `FleetMap` itself renders is injected; that one
178
+ sentence is not, and a pt-BR consumer's screen reader will read it in English
179
+ until `MapPreview` takes a copy port.
180
+ - **Pin separation does not scale with zoom.** `MapPreview` places markers at a
181
+ fixed pixels-per-degree, so units a few hundred metres apart draw within a
182
+ pixel or two of each other. The roster distinguishes them; the map does not.
@@ -0,0 +1,169 @@
1
+ import Box from '@mui/material/Box/index.js';
2
+ import Typography from '@mui/material/Typography/index.js';
3
+ import { useTheme } from '@mui/material/styles/index.js';
4
+ import React from 'react';
5
+
6
+ import { SR_ONLY_SX } from '../../form/Label/Label.styles';
7
+ import { EmptyState } from '../EmptyState/EmptyState';
8
+
9
+ import { FleetBody } from './FleetBody';
10
+ import { useFleetMap } from './FleetMap.hooks';
11
+ import type { FleetMapProps } from './FleetMap.types';
12
+
13
+ /**
14
+ * How long a fix stays `live`, and then `lagging`, when the caller says nothing.
15
+ *
16
+ * Ninety seconds and five minutes: sized for a phone reporting every twenty
17
+ * seconds, which is the densest cadence a battery tolerates all day. They are
18
+ * DEFAULTS and not a rule — a fleet on five-minute trackers passes its own, and
19
+ * the props exist so it can.
20
+ */
21
+ const DEFAULT_LAGGING_AFTER_SECONDS = 90;
22
+ const DEFAULT_STALE_AFTER_SECONDS = 300;
23
+
24
+ /** The map's own default height. Overridable, and never a hardcoded viewport. */
25
+ const DEFAULT_HEIGHT = '420px';
26
+
27
+ /**
28
+ * The reload announcement, and nothing else.
29
+ *
30
+ * `aria-busy` marks the region stale for assistive technology but UTTERS
31
+ * nothing, and the skeletons beside it are `aria-hidden` — so a screen-reader
32
+ * user got silence while the roster reloaded. This is the utterance.
33
+ *
34
+ * Optional by design: the sentence is in the reader's language, which only the
35
+ * caller knows, and inventing an English one in a component whose whole premise
36
+ * is that every word arrives through `copy` would be the bug it exists to
37
+ * avoid. No `copy.loading`, no region.
38
+ *
39
+ * ## The node outlives the text, and that is the whole trick
40
+ *
41
+ * A live region has to be in the DOM BEFORE its content changes; a screen
42
+ * reader watches an existing region for mutations rather than announcing one
43
+ * that appears already populated. Mounting region-and-text together in a single
44
+ * commit is the classic silent case — it satisfies a DOM assertion while
45
+ * announcing nothing. So the region mounts as soon as the caller offers the
46
+ * copy and merely EMPTIES when idle, which is what `CepField`, `UploadButton`
47
+ * and `DateRangePickerFields` all do.
48
+ */
49
+ function FleetStatus({
50
+ announcement,
51
+ loading,
52
+ testId,
53
+ }: {
54
+ announcement: string | undefined;
55
+ loading: boolean;
56
+ testId: string;
57
+ }): React.JSX.Element | null {
58
+ // No copy, no region at all — the caller has not asked for an announcement.
59
+ if (announcement === undefined) return null;
60
+ return (
61
+ <Box role="status" aria-live="polite" data-testid={`${testId}-status`} sx={SR_ONLY_SX}>
62
+ {loading ? announcement : ''}
63
+ </Box>
64
+ );
65
+ }
66
+
67
+ /**
68
+ * FleetMap — where a set of tracked units is right now, as a map beside the
69
+ * roster that reads it.
70
+ *
71
+ * Product-free by construction: it draws labelled dots with a freshness, and
72
+ * every word — the heading, the three freshness states, how a duration and a
73
+ * distance are written — arrives through {@link FleetMapProps.copy}. Couriers,
74
+ * service vans and field engineers are all the same picture.
75
+ *
76
+ * ## Three decisions worth knowing before changing it
77
+ *
78
+ * **The roster is the accessible representation, not a sidebar.** A map is a
79
+ * picture and a screen reader cannot read one, so the list carries the
80
+ * information: everything a sighted user gets from a pin — who, how recently,
81
+ * what they are carrying — is on the row. The map is a NAMED region rather than
82
+ * an `aria-hidden` one, because its controls are focusable and hiding a
83
+ * focusable subtree is the `aria-hidden-focus` violation.
84
+ *
85
+ * **Nothing here formats.** `lastSeen` and `accuracy` are functions on the copy
86
+ * object, the same line `StatCard` holds for its `value`: a duration and a
87
+ * distance are locale rules, and a component that wrote "2 min ago" would have
88
+ * made English the only language it could ever render.
89
+ *
90
+ * **An empty fleet is an empty STATE, not an empty map.** A map with no pins is
91
+ * indistinguishable from a map that failed to load, and the difference is the
92
+ * whole question a dispatcher is asking.
93
+ */
94
+ export const FleetMap: React.FC<FleetMapProps> = React.memo(
95
+ ({
96
+ units,
97
+ copy,
98
+ // NO default. `undefined` is what tells the hook the caller does not own
99
+ // the selection; defaulting it to `null` here made every render look
100
+ // controlled and the uncontrolled path unreachable.
101
+ selectedId,
102
+ onSelect,
103
+ laggingAfterSeconds = DEFAULT_LAGGING_AFTER_SECONDS,
104
+ staleAfterSeconds = DEFAULT_STALE_AFTER_SECONDS,
105
+ height = DEFAULT_HEIGHT,
106
+ loading = false,
107
+ className,
108
+ dataTestId,
109
+ }) => {
110
+ const theme = useTheme();
111
+ const testId = dataTestId || 'fleet-map';
112
+ const headingId = React.useId();
113
+ const { ordered, active, centre, select, markers, onKeyDown } = useFleetMap(
114
+ units,
115
+ selectedId,
116
+ onSelect,
117
+ );
118
+
119
+ return (
120
+ <Box
121
+ role="region"
122
+ aria-labelledby={headingId}
123
+ className={className}
124
+ data-testid={testId}
125
+ sx={{ display: 'flex', flexDirection: 'column', gap: theme.spacing(1.5), minWidth: 0 }}
126
+ >
127
+ <Typography
128
+ id={headingId}
129
+ variant="subtitle1"
130
+ component="h2"
131
+ data-testid={`${testId}-title`}
132
+ sx={{ fontWeight: theme.typography.fontWeightMedium }}
133
+ >
134
+ {copy.title}
135
+ </Typography>
136
+
137
+ <FleetStatus announcement={copy.loading} loading={loading} testId={testId} />
138
+
139
+ {!loading && ordered.length === 0 ? (
140
+ <EmptyState
141
+ variant="minimal"
142
+ title={copy.emptyTitle}
143
+ description={copy.emptyDescription}
144
+ dataTestId={`${testId}-empty`}
145
+ />
146
+ ) : (
147
+ <FleetBody
148
+ ordered={ordered}
149
+ centre={centre}
150
+ markers={markers}
151
+ select={select}
152
+ onKeyDown={onKeyDown}
153
+ copy={copy}
154
+ selectedId={active}
155
+ laggingAfterSeconds={laggingAfterSeconds}
156
+ staleAfterSeconds={staleAfterSeconds}
157
+ height={height}
158
+ loading={loading}
159
+ testId={testId}
160
+ />
161
+ )}
162
+ </Box>
163
+ );
164
+ },
165
+ );
166
+
167
+ FleetMap.displayName = 'FleetMap';
168
+
169
+ export default FleetMap;