@nextelco/common-ui 2.1.98 → 2.1.99

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 (356) hide show
  1. package/dist/esm/index.js +222 -0
  2. package/dist/esm/index.js.map +1 -0
  3. package/dist/esm/legacy/assets/svgs/proef-footer-logo.svg.js +5 -0
  4. package/dist/esm/legacy/assets/svgs/proef-footer-logo.svg.js.map +1 -0
  5. package/dist/esm/legacy/components/atoms/Acronym/Acronym.css +43 -0
  6. package/dist/esm/legacy/components/atoms/Acronym/Acronym.js +31 -0
  7. package/dist/esm/legacy/components/atoms/Acronym/Acronym.js.map +1 -0
  8. package/dist/esm/legacy/components/atoms/BreadCrumb/BreadCrumb.css +36 -0
  9. package/dist/esm/legacy/components/atoms/BreadCrumb/BreadCrumb.js +57 -0
  10. package/dist/esm/legacy/components/atoms/BreadCrumb/BreadCrumb.js.map +1 -0
  11. package/dist/esm/legacy/components/atoms/Button/variants/ActionButton.css +218 -0
  12. package/dist/esm/legacy/components/atoms/Button/variants/ActionButton.js +50 -0
  13. package/dist/esm/legacy/components/atoms/Button/variants/ActionButton.js.map +1 -0
  14. package/dist/esm/legacy/components/atoms/Button/variants/FilterButton.css +56 -0
  15. package/dist/esm/legacy/components/atoms/Button/variants/FilterButton.js +34 -0
  16. package/dist/esm/legacy/components/atoms/Button/variants/FilterButton.js.map +1 -0
  17. package/dist/esm/legacy/components/atoms/Button/variants/IconButton.css +74 -0
  18. package/dist/esm/legacy/components/atoms/Button/variants/IconButton.js +29 -0
  19. package/dist/esm/legacy/components/atoms/Button/variants/IconButton.js.map +1 -0
  20. package/dist/esm/legacy/components/atoms/Button/variants/MainButton.css +99 -0
  21. package/dist/esm/legacy/components/atoms/Button/variants/MainButton.js +36 -0
  22. package/dist/esm/legacy/components/atoms/Button/variants/MainButton.js.map +1 -0
  23. package/dist/esm/legacy/components/atoms/Button/variants/TabButton.css +63 -0
  24. package/dist/esm/legacy/components/atoms/Button/variants/TabButton.js +21 -0
  25. package/dist/esm/legacy/components/atoms/Button/variants/TabButton.js.map +1 -0
  26. package/dist/esm/legacy/components/atoms/Field/Field.css +171 -0
  27. package/dist/esm/legacy/components/atoms/Field/Field.js +70 -0
  28. package/dist/esm/legacy/components/atoms/Field/Field.js.map +1 -0
  29. package/dist/esm/legacy/components/atoms/IconText/IconText.css +10 -0
  30. package/dist/esm/legacy/components/atoms/IconText/IconText.js +25 -0
  31. package/dist/esm/legacy/components/atoms/IconText/IconText.js.map +1 -0
  32. package/dist/esm/legacy/components/atoms/Icone/Icone.js +24 -0
  33. package/dist/esm/legacy/components/atoms/Icone/Icone.js.map +1 -0
  34. package/dist/esm/legacy/components/atoms/Input/Input.css +12 -0
  35. package/dist/esm/legacy/components/atoms/Input/Input.js +28 -0
  36. package/dist/esm/legacy/components/atoms/Input/Input.js.map +1 -0
  37. package/dist/esm/legacy/components/atoms/InputData/InputData.js +36 -0
  38. package/dist/esm/legacy/components/atoms/InputData/InputData.js.map +1 -0
  39. package/dist/esm/legacy/components/atoms/Label/Label.css +192 -0
  40. package/dist/esm/legacy/components/atoms/Label/Label.js +13 -0
  41. package/dist/esm/legacy/components/atoms/Label/Label.js.map +1 -0
  42. package/dist/esm/legacy/components/atoms/MultiTagPickerTag/MultiTagPickerTag.css +40 -0
  43. package/dist/esm/legacy/components/atoms/MultiTagPickerTag/MultiTagPickerTag.js +21 -0
  44. package/dist/esm/legacy/components/atoms/MultiTagPickerTag/MultiTagPickerTag.js.map +1 -0
  45. package/dist/esm/legacy/components/atoms/Select/Select.css +16 -0
  46. package/dist/esm/legacy/components/atoms/Select/Select.js +27 -0
  47. package/dist/esm/legacy/components/atoms/Select/Select.js.map +1 -0
  48. package/dist/esm/legacy/components/atoms/Stack/Stack.js +20 -0
  49. package/dist/esm/legacy/components/atoms/Stack/Stack.js.map +1 -0
  50. package/dist/esm/legacy/components/atoms/Switch/CustomSwitch.css +36 -0
  51. package/dist/esm/legacy/components/atoms/Switch/CustomSwitch.js +29 -0
  52. package/dist/esm/legacy/components/atoms/Switch/CustomSwitch.js.map +1 -0
  53. package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.css +17 -0
  54. package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.js +41 -0
  55. package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.js.map +1 -0
  56. package/dist/esm/legacy/components/charts/Charts.js +259 -0
  57. package/dist/esm/legacy/components/charts/Charts.js.map +1 -0
  58. package/dist/esm/legacy/components/layout/AppLauncher/AppLauncher.js +100 -0
  59. package/dist/esm/legacy/components/layout/AppLauncher/AppLauncher.js.map +1 -0
  60. package/dist/esm/legacy/components/layout/Error/Error.css +20 -0
  61. package/dist/esm/legacy/components/layout/Error/Error.js +12 -0
  62. package/dist/esm/legacy/components/layout/Error/Error.js.map +1 -0
  63. package/dist/esm/legacy/components/layout/Footer/Footer.css +42 -0
  64. package/dist/esm/legacy/components/layout/Footer/Footer.js +23 -0
  65. package/dist/esm/legacy/components/layout/Footer/Footer.js.map +1 -0
  66. package/dist/esm/legacy/components/layout/Header/Header.css +66 -0
  67. package/dist/esm/legacy/components/layout/Header/Header.js +37 -0
  68. package/dist/esm/legacy/components/layout/Header/Header.js.map +1 -0
  69. package/dist/esm/legacy/components/layout/Layout/Layout.js +92 -0
  70. package/dist/esm/legacy/components/layout/Layout/Layout.js.map +1 -0
  71. package/dist/esm/legacy/components/layout/Sidebar/Sidebar.js +227 -0
  72. package/dist/esm/legacy/components/layout/Sidebar/Sidebar.js.map +1 -0
  73. package/dist/esm/legacy/components/layout/Spinner/Spinner.css +10 -0
  74. package/dist/esm/legacy/components/layout/Spinner/Spinner.js +19 -0
  75. package/dist/esm/legacy/components/layout/Spinner/Spinner.js.map +1 -0
  76. package/dist/esm/legacy/components/layout/TopBar/TopBar.js +34 -0
  77. package/dist/esm/legacy/components/layout/TopBar/TopBar.js.map +1 -0
  78. package/dist/esm/legacy/components/layout/TopNavLayout/TopNavLayout.js +82 -0
  79. package/dist/esm/legacy/components/layout/TopNavLayout/TopNavLayout.js.map +1 -0
  80. package/dist/esm/legacy/components/molecules/BarraValor/BarraValor.js +25 -0
  81. package/dist/esm/legacy/components/molecules/BarraValor/BarraValor.js.map +1 -0
  82. package/dist/esm/legacy/components/molecules/ColumnPicker/ColumnPicker.js +179 -0
  83. package/dist/esm/legacy/components/molecules/ColumnPicker/ColumnPicker.js.map +1 -0
  84. package/dist/esm/legacy/components/molecules/ConfirmModal/ConfirmModal.css +3 -0
  85. package/dist/esm/legacy/components/molecules/ConfirmModal/ConfirmModal.js +33 -0
  86. package/dist/esm/legacy/components/molecules/ConfirmModal/ConfirmModal.js.map +1 -0
  87. package/dist/esm/legacy/components/molecules/DataTable/DataTable.js +1145 -0
  88. package/dist/esm/legacy/components/molecules/DataTable/DataTable.js.map +1 -0
  89. package/dist/esm/legacy/components/molecules/FileDropzone/FileDropzone.js +68 -0
  90. package/dist/esm/legacy/components/molecules/FileDropzone/FileDropzone.js.map +1 -0
  91. package/dist/esm/legacy/components/molecules/LanguageSwitcher/LanguageSwitcher.js +96 -0
  92. package/dist/esm/legacy/components/molecules/LanguageSwitcher/LanguageSwitcher.js.map +1 -0
  93. package/dist/esm/legacy/components/molecules/Modal/Modal.css +54 -0
  94. package/dist/esm/legacy/components/molecules/Modal/Modal.js +64 -0
  95. package/dist/esm/legacy/components/molecules/Modal/Modal.js.map +1 -0
  96. package/dist/esm/legacy/components/molecules/MultiTagPicker/MultiTagPicker.css +97 -0
  97. package/dist/esm/legacy/components/molecules/MultiTagPicker/MultiTagPicker.js +113 -0
  98. package/dist/esm/legacy/components/molecules/MultiTagPicker/MultiTagPicker.js.map +1 -0
  99. package/dist/esm/legacy/components/molecules/PhotoAvatar/PhotoAvatar.js +107 -0
  100. package/dist/esm/legacy/components/molecules/PhotoAvatar/PhotoAvatar.js.map +1 -0
  101. package/dist/esm/legacy/components/molecules/Search/Search.css +18 -0
  102. package/dist/esm/legacy/components/molecules/Search/Search.js +30 -0
  103. package/dist/esm/legacy/components/molecules/Search/Search.js.map +1 -0
  104. package/dist/esm/legacy/components/molecules/SeletorPesquisa/SeletorPesquisa.js +116 -0
  105. package/dist/esm/legacy/components/molecules/SeletorPesquisa/SeletorPesquisa.js.map +1 -0
  106. package/dist/esm/legacy/components/molecules/Sidebar/Sidebar.css +69 -0
  107. package/dist/esm/legacy/components/molecules/Sidebar/Sidebar.js +62 -0
  108. package/dist/esm/legacy/components/molecules/Sidebar/Sidebar.js.map +1 -0
  109. package/dist/esm/legacy/components/molecules/UserAvatar/UserAvatar.js +105 -0
  110. package/dist/esm/legacy/components/molecules/UserAvatar/UserAvatar.js.map +1 -0
  111. package/dist/esm/legacy/components/organisms/GanttChart/GanttChart.js +162 -0
  112. package/dist/esm/legacy/components/organisms/GanttChart/GanttChart.js.map +1 -0
  113. package/dist/esm/legacy/components/organisms/Kanban/Kanban.js +88 -0
  114. package/dist/esm/legacy/components/organisms/Kanban/Kanban.js.map +1 -0
  115. package/dist/esm/legacy/components/organisms/LazyLoader/LazyLoader.js +87 -0
  116. package/dist/esm/legacy/components/organisms/LazyLoader/LazyLoader.js.map +1 -0
  117. package/dist/esm/legacy/components/organisms/MapaPontos/MapaPontos.js +427 -0
  118. package/dist/esm/legacy/components/organisms/MapaPontos/MapaPontos.js.map +1 -0
  119. package/dist/esm/legacy/components/organisms/PainelFiltros/PainelFiltros.js +206 -0
  120. package/dist/esm/legacy/components/organisms/PainelFiltros/PainelFiltros.js.map +1 -0
  121. package/dist/esm/legacy/components/organisms/PesquisaRapida/PesquisaRapida.js +147 -0
  122. package/dist/esm/legacy/components/organisms/PesquisaRapida/PesquisaRapida.js.map +1 -0
  123. package/dist/esm/legacy/components/organisms/Profile/Profile.css +26 -0
  124. package/dist/esm/legacy/components/organisms/Profile/Profile.js +26 -0
  125. package/dist/esm/legacy/components/organisms/Profile/Profile.js.map +1 -0
  126. package/dist/esm/legacy/components/organisms/RoleGuard/RoleGuard.js +68 -0
  127. package/dist/esm/legacy/components/organisms/RoleGuard/RoleGuard.js.map +1 -0
  128. package/dist/esm/legacy/components/organisms/Selector/Selector.css +87 -0
  129. package/dist/esm/legacy/components/organisms/Selector/Selector.js +181 -0
  130. package/dist/esm/legacy/components/organisms/Selector/Selector.js.map +1 -0
  131. package/dist/esm/legacy/components/organisms/StatusMatrix/StatusMatrix.js +115 -0
  132. package/dist/esm/legacy/components/organisms/StatusMatrix/StatusMatrix.js.map +1 -0
  133. package/dist/esm/legacy/components/ui/Avisos.js +86 -0
  134. package/dist/esm/legacy/components/ui/Avisos.js.map +1 -0
  135. package/dist/esm/legacy/components/ui/BarraAcoes.js +19 -0
  136. package/dist/esm/legacy/components/ui/BarraAcoes.js.map +1 -0
  137. package/dist/esm/legacy/components/ui/CabecalhoPagina.js +32 -0
  138. package/dist/esm/legacy/components/ui/CabecalhoPagina.js.map +1 -0
  139. package/dist/esm/legacy/components/ui/CaixaPesquisa.js +57 -0
  140. package/dist/esm/legacy/components/ui/CaixaPesquisa.js.map +1 -0
  141. package/dist/esm/legacy/components/ui/Confirmacao.js +52 -0
  142. package/dist/esm/legacy/components/ui/Confirmacao.js.map +1 -0
  143. package/dist/esm/legacy/components/ui/Escolha.js +157 -0
  144. package/dist/esm/legacy/components/ui/Escolha.js.map +1 -0
  145. package/dist/esm/legacy/components/ui/FaixaAviso.js +17 -0
  146. package/dist/esm/legacy/components/ui/FaixaAviso.js.map +1 -0
  147. package/dist/esm/legacy/components/ui/MenuAcoes.js +116 -0
  148. package/dist/esm/legacy/components/ui/MenuAcoes.js.map +1 -0
  149. package/dist/esm/legacy/components/ui/Passos.js +32 -0
  150. package/dist/esm/legacy/components/ui/Passos.js.map +1 -0
  151. package/dist/esm/legacy/components/ui/Separadores.js +52 -0
  152. package/dist/esm/legacy/components/ui/Separadores.js.map +1 -0
  153. package/dist/esm/legacy/components/ui/TextoAuto.js +33 -0
  154. package/dist/esm/legacy/components/ui/TextoAuto.js.map +1 -0
  155. package/dist/esm/legacy/components/ui/Ui.js +360 -0
  156. package/dist/esm/legacy/components/ui/Ui.js.map +1 -0
  157. package/dist/esm/legacy/components/ui/painelFlutuante.js +52 -0
  158. package/dist/esm/legacy/components/ui/painelFlutuante.js.map +1 -0
  159. package/dist/esm/legacy/constants/Colors.js +33 -0
  160. package/dist/esm/legacy/constants/Colors.js.map +1 -0
  161. package/dist/esm/legacy/constants/FontWeight.js +35 -0
  162. package/dist/esm/legacy/constants/FontWeight.js.map +1 -0
  163. package/dist/esm/legacy/contexts/apiContext.js +25 -0
  164. package/dist/esm/legacy/contexts/apiContext.js.map +1 -0
  165. package/dist/esm/legacy/contexts/authContext.js +85 -0
  166. package/dist/esm/legacy/contexts/authContext.js.map +1 -0
  167. package/dist/esm/legacy/contexts/socketContext.js +34 -0
  168. package/dist/esm/legacy/contexts/socketContext.js.map +1 -0
  169. package/dist/esm/legacy/hooks/useApi.js +62 -0
  170. package/dist/esm/legacy/hooks/useApi.js.map +1 -0
  171. package/dist/esm/legacy/hooks/useTheme.js +39 -0
  172. package/dist/esm/legacy/hooks/useTheme.js.map +1 -0
  173. package/dist/esm/legacy/pages/Error/ErrorPage.css +18 -0
  174. package/dist/esm/legacy/pages/Error/ErrorPage.js +50 -0
  175. package/dist/esm/legacy/pages/Error/ErrorPage.js.map +1 -0
  176. package/dist/esm/legacy/pages/Loading/Loading.css +46 -0
  177. package/dist/esm/legacy/pages/Loading/Loading.js +9 -0
  178. package/dist/esm/legacy/pages/Loading/Loading.js.map +1 -0
  179. package/dist/esm/legacy/pages/Login/LoginScreen.js +46 -0
  180. package/dist/esm/legacy/pages/Login/LoginScreen.js.map +1 -0
  181. package/dist/esm/legacy/pages/NotFound/NotFound.css +21 -0
  182. package/dist/esm/legacy/pages/NotFound/NotFound.js +24 -0
  183. package/dist/esm/legacy/pages/NotFound/NotFound.js.map +1 -0
  184. package/dist/esm/legacy/styles/themes/ButtonThemes.js +28 -0
  185. package/dist/esm/legacy/styles/themes/ButtonThemes.js.map +1 -0
  186. package/dist/esm/legacy/styles/utils/utils.js +7 -0
  187. package/dist/esm/legacy/styles/utils/utils.js.map +1 -0
  188. package/dist/esm/legacy/utils/stringUtils.js +35 -0
  189. package/dist/esm/legacy/utils/stringUtils.js.map +1 -0
  190. package/dist/esm/v1/capabilities/documents/QRScanning/scanQRCodes.js +157 -0
  191. package/dist/esm/v1/capabilities/documents/QRScanning/scanQRCodes.js.map +1 -0
  192. package/dist/esm/v1/components/documents/DocumentDropzone/DocumentDropzone.js +307 -0
  193. package/dist/esm/v1/components/documents/DocumentDropzone/DocumentDropzone.js.map +1 -0
  194. package/dist/esm/v1/components/forms/FormField/FormField.js +59 -0
  195. package/dist/esm/v1/components/forms/FormField/FormField.js.map +1 -0
  196. package/dist/esm/v1/components/forms/FormGrid/FormGrid.js +20 -0
  197. package/dist/esm/v1/components/forms/FormGrid/FormGrid.js.map +1 -0
  198. package/dist/esm/v1/components/overlays/Dialog/Dialog.js +87 -0
  199. package/dist/esm/v1/components/overlays/Dialog/Dialog.js.map +1 -0
  200. package/dist/esm/v1/foundations/icons/icons.js +76 -0
  201. package/dist/esm/v1/foundations/icons/icons.js.map +1 -0
  202. package/dist/esm/v1/primitives/buttons/Button/Button.js +27 -0
  203. package/dist/esm/v1/primitives/buttons/Button/Button.js.map +1 -0
  204. package/dist/esm/v1/primitives/documents/PdfPreview/PdfPreview.js +137 -0
  205. package/dist/esm/v1/primitives/documents/PdfPreview/PdfPreview.js.map +1 -0
  206. package/dist/esm/v1/primitives/documents/PdfPreview/pdfjs.js +26 -0
  207. package/dist/esm/v1/primitives/documents/PdfPreview/pdfjs.js.map +1 -0
  208. package/dist/esm/v1/primitives/forms/LookupInput/LookupInput.js +37 -0
  209. package/dist/esm/v1/primitives/forms/LookupInput/LookupInput.js.map +1 -0
  210. package/dist/esm/v1/primitives/forms/SelectInput/SelectInput.js +29 -0
  211. package/dist/esm/v1/primitives/forms/SelectInput/SelectInput.js.map +1 -0
  212. package/dist/esm/v1/primitives/forms/TextArea/TextArea.js +75 -0
  213. package/dist/esm/v1/primitives/forms/TextArea/TextArea.js.map +1 -0
  214. package/dist/esm/v1/primitives/forms/TextInput/TextInput.js +21 -0
  215. package/dist/esm/v1/primitives/forms/TextInput/TextInput.js.map +1 -0
  216. package/dist/esm/v1/primitives/forms/field.js +12 -0
  217. package/dist/esm/v1/primitives/forms/field.js.map +1 -0
  218. package/dist/style.css +1 -1
  219. package/dist/style.layered.css +1 -1
  220. package/dist/types/index.d.ts +14 -13
  221. package/dist/types/{components → legacy/components}/atoms/Acronym/Acronym.d.ts +1 -0
  222. package/dist/types/{components → legacy/components}/atoms/BreadCrumb/BreadCrumb.d.ts +1 -0
  223. package/dist/types/{components → legacy/components}/atoms/Button/variants/ActionButton.d.ts +1 -0
  224. package/dist/types/{components → legacy/components}/atoms/Button/variants/FilterButton.d.ts +1 -0
  225. package/dist/types/{components → legacy/components}/atoms/Button/variants/IconButton.d.ts +1 -0
  226. package/dist/types/{components → legacy/components}/atoms/Button/variants/MainButton.d.ts +1 -0
  227. package/dist/types/{components → legacy/components}/atoms/Button/variants/TabButton.d.ts +1 -0
  228. package/dist/types/{components → legacy/components}/atoms/Field/Field.d.ts +1 -0
  229. package/dist/types/{components → legacy/components}/atoms/IconText/IconText.d.ts +1 -0
  230. package/dist/types/{components → legacy/components}/atoms/Icone/Icone.d.ts +2 -0
  231. package/dist/types/{components → legacy/components}/atoms/Input/Input.d.ts +1 -0
  232. package/dist/types/{components → legacy/components}/atoms/InputData/InputData.d.ts +4 -0
  233. package/dist/types/{components → legacy/components}/atoms/Label/Label.d.ts +1 -0
  234. package/dist/types/{components → legacy/components}/atoms/Select/Select.d.ts +1 -0
  235. package/dist/types/{components → legacy/components}/atoms/Stack/Stack.d.ts +1 -0
  236. package/dist/types/{components → legacy/components}/atoms/Switch/CustomSwitch.d.ts +1 -0
  237. package/dist/types/{components → legacy/components}/atoms/Tooltip/Tooltip.d.ts +1 -0
  238. package/dist/types/{components → legacy/components}/charts/Charts.d.ts +29 -6
  239. package/dist/types/{components → legacy/components}/layout/AppLauncher/AppLauncher.d.ts +3 -0
  240. package/dist/types/{components → legacy/components}/layout/Error/Error.d.ts +1 -0
  241. package/dist/types/{components → legacy/components}/layout/Footer/Footer.d.ts +1 -0
  242. package/dist/types/{components → legacy/components}/layout/Header/Header.d.ts +1 -0
  243. package/dist/types/{components → legacy/components}/layout/Layout/Layout.d.ts +2 -0
  244. package/dist/types/{components → legacy/components}/layout/Sidebar/Sidebar.d.ts +5 -0
  245. package/dist/types/{components → legacy/components}/layout/Spinner/Spinner.d.ts +1 -0
  246. package/dist/types/{components → legacy/components}/layout/TopBar/TopBar.d.ts +2 -0
  247. package/dist/types/{components → legacy/components}/layout/TopNavLayout/TopNavLayout.d.ts +3 -0
  248. package/dist/types/{components → legacy/components}/molecules/BarraValor/BarraValor.d.ts +3 -0
  249. package/dist/types/{components → legacy/components}/molecules/ColumnPicker/ColumnPicker.d.ts +8 -1
  250. package/dist/types/{components → legacy/components}/molecules/ConfirmModal/ConfirmModal.d.ts +2 -0
  251. package/dist/types/{components → legacy/components}/molecules/DataTable/DataTable.d.ts +6 -0
  252. package/dist/types/{components → legacy/components}/molecules/FileDropzone/FileDropzone.d.ts +3 -0
  253. package/dist/types/{components → legacy/components}/molecules/LanguageSwitcher/LanguageSwitcher.d.ts +3 -0
  254. package/dist/types/{components → legacy/components}/molecules/Modal/Modal.d.ts +2 -0
  255. package/dist/types/{components → legacy/components}/molecules/MultiTagPicker/MultiTagPicker.d.ts +2 -0
  256. package/dist/types/{components → legacy/components}/molecules/PhotoAvatar/PhotoAvatar.d.ts +1 -0
  257. package/dist/types/{components → legacy/components}/molecules/SeletorPesquisa/SeletorPesquisa.d.ts +3 -0
  258. package/dist/types/{components → legacy/components}/molecules/Sidebar/Sidebar.d.ts +1 -0
  259. package/dist/types/{components → legacy/components}/molecules/UserAvatar/UserAvatar.d.ts +1 -0
  260. package/dist/types/{components → legacy/components}/organisms/GanttChart/GanttChart.d.ts +8 -1
  261. package/dist/types/{components → legacy/components}/organisms/Kanban/Kanban.d.ts +3 -0
  262. package/dist/types/{components → legacy/components}/organisms/LazyLoader/LazyLoader.d.ts +1 -0
  263. package/dist/types/{components → legacy/components}/organisms/MapaPontos/MapaPontos.d.ts +12 -2
  264. package/dist/types/{components → legacy/components}/organisms/PainelFiltros/PainelFiltros.d.ts +7 -0
  265. package/dist/types/{components → legacy/components}/organisms/PesquisaRapida/PesquisaRapida.d.ts +5 -0
  266. package/dist/types/{components → legacy/components}/organisms/Profile/Profile.d.ts +1 -0
  267. package/dist/types/{components → legacy/components}/organisms/RoleGuard/RoleGuard.d.ts +6 -1
  268. package/dist/types/{components → legacy/components}/organisms/Selector/Selector.d.ts +1 -0
  269. package/dist/types/{components → legacy/components}/organisms/StatusMatrix/StatusMatrix.d.ts +6 -0
  270. package/dist/types/{components → legacy/components}/ui/Avisos.d.ts +9 -1
  271. package/dist/types/{components → legacy/components}/ui/BarraAcoes.d.ts +2 -0
  272. package/dist/types/{components → legacy/components}/ui/CabecalhoPagina.d.ts +6 -1
  273. package/dist/types/{components → legacy/components}/ui/Confirmacao.d.ts +2 -0
  274. package/dist/types/{components → legacy/components}/ui/FaixaAviso.d.ts +3 -0
  275. package/dist/types/{components → legacy/components}/ui/Passos.d.ts +3 -0
  276. package/dist/types/{components → legacy/components}/ui/Separadores.d.ts +3 -0
  277. package/dist/types/{components → legacy/components}/ui/TextoAuto.d.ts +2 -0
  278. package/dist/types/{components → legacy/components}/ui/Ui.d.ts +41 -7
  279. package/dist/types/{constants → legacy/constants}/FontWeight.d.ts +1 -0
  280. package/dist/types/{contexts → legacy/contexts}/apiContext.d.ts +1 -0
  281. package/dist/types/{contexts → legacy/contexts}/authContext.d.ts +2 -0
  282. package/dist/types/{contexts → legacy/contexts}/socketContext.d.ts +2 -0
  283. package/dist/types/{exports → legacy/exports}/hooks.d.ts +1 -1
  284. package/dist/types/{exports → legacy/exports}/molecules.d.ts +2 -1
  285. package/dist/types/legacy/exports/types.d.ts +7 -0
  286. package/dist/types/{hooks → legacy/hooks}/useApi.d.ts +2 -0
  287. package/dist/types/{hooks → legacy/hooks}/useTheme.d.ts +2 -0
  288. package/dist/types/{pages → legacy/pages}/Error/ErrorPage.d.ts +1 -0
  289. package/dist/types/{pages → legacy/pages}/Loading/Loading.d.ts +1 -0
  290. package/dist/types/{pages → legacy/pages}/Login/LoginScreen.d.ts +2 -0
  291. package/dist/types/{pages → legacy/pages}/NotFound/NotFound.d.ts +1 -0
  292. package/dist/types/legacy/styles/utils/utils.d.ts +2 -0
  293. package/dist/types/{types → legacy/types}/Fetcher.d.ts +1 -0
  294. package/dist/types/{types → legacy/types}/LoggedUser.d.ts +1 -0
  295. package/dist/types/{types → legacy/types}/SidebarMenu.d.ts +2 -0
  296. package/dist/types/legacy/types/themes/AcronymThemes.d.ts +4 -0
  297. package/dist/types/{types → legacy/types}/themes/ButtonThemes.d.ts +3 -0
  298. package/dist/types/legacy/types/themes/CustomSwitchThemes.d.ts +4 -0
  299. package/dist/types/{types → legacy/types}/themes/IconTextThemes.d.ts +1 -0
  300. package/dist/types/legacy/utils/stringUtils.d.ts +6 -0
  301. package/dist/types/v1/capabilities/documents/QRScanning/scanQRCodes.d.ts +25 -0
  302. package/dist/types/v1/components/documents/DocumentDropzone/DocumentDropzone.d.ts +60 -0
  303. package/dist/types/v1/components/forms/FormField/FormField.d.ts +44 -0
  304. package/dist/types/v1/components/forms/FormGrid/FormGrid.d.ts +21 -0
  305. package/dist/types/v1/components/overlays/Dialog/Dialog.d.ts +55 -0
  306. package/dist/types/v1/foundations/icons/icons.d.ts +24 -0
  307. package/dist/types/v1/index.d.ts +25 -0
  308. package/dist/types/v1/primitives/buttons/Button/Button.d.ts +18 -0
  309. package/dist/types/v1/primitives/documents/PdfPreview/PdfPreview.d.ts +17 -0
  310. package/dist/types/v1/primitives/documents/PdfPreview/pdfjs.d.ts +11 -0
  311. package/dist/types/v1/primitives/forms/LookupInput/LookupInput.d.ts +25 -0
  312. package/dist/types/v1/primitives/forms/SelectInput/SelectInput.d.ts +19 -0
  313. package/dist/types/v1/primitives/forms/TextArea/TextArea.d.ts +37 -0
  314. package/dist/types/v1/primitives/forms/TextInput/TextInput.d.ts +16 -0
  315. package/dist/types/v1/primitives/forms/field.d.ts +20 -0
  316. package/package.json +38 -33
  317. package/dist/bundle.js +0 -2
  318. package/dist/bundle.js.LICENSE.txt +0 -80
  319. package/dist/types/components/atoms/Icone/Icone.test.d.ts +0 -1
  320. package/dist/types/components/layout/Sidebar/Sidebar.test.d.ts +0 -1
  321. package/dist/types/components/molecules/BarraValor/BarraValor.test.d.ts +0 -1
  322. package/dist/types/components/molecules/DataTable/DataTable.test.d.ts +0 -1
  323. package/dist/types/components/molecules/SeletorPesquisa/SeletorPesquisa.test.d.ts +0 -1
  324. package/dist/types/components/organisms/Kanban/Kanban.test.d.ts +0 -1
  325. package/dist/types/components/organisms/RoleGuard/RoleGuard.test.d.ts +0 -1
  326. package/dist/types/components/ui/CaixaPesquisa.test.d.ts +0 -1
  327. package/dist/types/components/ui/Escolha.test.d.ts +0 -1
  328. package/dist/types/components/ui/Paginas.test.d.ts +0 -1
  329. package/dist/types/exports/types.d.ts +0 -7
  330. package/dist/types/styles/utils/utils.d.ts +0 -1
  331. package/dist/types/test/setup.d.ts +0 -1
  332. package/dist/types/types/themes/AcronymThemes.d.ts +0 -3
  333. package/dist/types/types/themes/CustomSwitchThemes.d.ts +0 -3
  334. package/dist/types/utils/stringUtils.d.ts +0 -3
  335. /package/dist/types/{components → legacy/components}/atoms/MultiTagPickerTag/MultiTagPickerTag.d.ts +0 -0
  336. /package/dist/types/{components → legacy/components}/atoms/SearchSelect/SearchSelect.d.ts +0 -0
  337. /package/dist/types/{components → legacy/components}/molecules/Search/Search.d.ts +0 -0
  338. /package/dist/types/{components → legacy/components}/ui/CaixaPesquisa.d.ts +0 -0
  339. /package/dist/types/{components → legacy/components}/ui/Escolha.d.ts +0 -0
  340. /package/dist/types/{components → legacy/components}/ui/MenuAcoes.d.ts +0 -0
  341. /package/dist/types/{components → legacy/components}/ui/painelFlutuante.d.ts +0 -0
  342. /package/dist/types/{constants → legacy/constants}/Colors.d.ts +0 -0
  343. /package/dist/types/{exports → legacy/exports}/assets.d.ts +0 -0
  344. /package/dist/types/{exports → legacy/exports}/atoms.d.ts +0 -0
  345. /package/dist/types/{exports → legacy/exports}/charts.d.ts +0 -0
  346. /package/dist/types/{exports → legacy/exports}/constants.d.ts +0 -0
  347. /package/dist/types/{exports → legacy/exports}/contexts.d.ts +0 -0
  348. /package/dist/types/{exports → legacy/exports}/layout.d.ts +0 -0
  349. /package/dist/types/{exports → legacy/exports}/organisms.d.ts +0 -0
  350. /package/dist/types/{exports → legacy/exports}/pages.d.ts +0 -0
  351. /package/dist/types/{exports → legacy/exports}/styles.d.ts +0 -0
  352. /package/dist/types/{exports → legacy/exports}/ui.d.ts +0 -0
  353. /package/dist/types/{exports → legacy/exports}/utils.d.ts +0 -0
  354. /package/dist/types/{styles → legacy/styles}/themes/ButtonThemes.d.ts +0 -0
  355. /package/dist/types/{types → legacy/types}/SelectableElement.d.ts +0 -0
  356. /package/dist/types/{utils → legacy/utils}/keycloak.d.ts +0 -0
@@ -0,0 +1,427 @@
1
+ import { jsxs, jsx } from "react/jsx-runtime";
2
+ import { useRef, useState, useCallback, useEffect, useMemo } from "react";
3
+ import L from "leaflet";
4
+ import "leaflet.markercluster";
5
+ import "leaflet.heat";
6
+ function garantirVisivel(camada) {
7
+ const repor = () => camada.setOpacity?.(1);
8
+ camada.on("load", repor);
9
+ repor();
10
+ }
11
+ const LABELS_POR_OMISSAO = {
12
+ semPontos: "Sem pontos para mostrar.",
13
+ semBiblioteca: "Mapa indisponível: falta instalar leaflet e leaflet.markercluster.",
14
+ aCarregar: "A carregar o mapa…",
15
+ truncado: "{n} pontos não mostrados.",
16
+ fecharAviso: "Fechar aviso"
17
+ };
18
+ const TILES_OMISSAO = "https://tile.openstreetmap.org/{z}/{x}/{y}.png";
19
+ const ATRIBUICAO_OMISSAO = '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a>';
20
+ const CENTRO_OMISSAO = [39.6, -8];
21
+ const COR_OMISSAO = "#1F4E79";
22
+ const TAMANHO_PIN = 28;
23
+ function pinSvg(cor, aproximado) {
24
+ return `<svg xmlns="http://www.w3.org/2000/svg" width="${TAMANHO_PIN}" height="${TAMANHO_PIN}" viewBox="0 0 24 24"
25
+ style="filter:drop-shadow(0 1px 2px rgba(0,0,0,.45));opacity:${aproximado ? 0.55 : 1}">
26
+ <path d="M12 2C8.13 2 5 5.13 5 9c0 1.36.4 2.63 1.09 3.7L12 23l5.91-10.3A6.94 6.94 0 0 0 19 9c0-3.87-3.13-7-7-7z"
27
+ fill="${cor}" stroke="#ffffff" stroke-width="1.2"${aproximado ? ' stroke-dasharray="2 1.5"' : ""}/>
28
+ <circle cx="12" cy="9" r="2.6" fill="#ffffff"/>
29
+ </svg>`;
30
+ }
31
+ function escapar(texto) {
32
+ return texto.replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[c]);
33
+ }
34
+ function anelCss(fatias) {
35
+ const comValor = fatias.filter((f) => f.n > 0);
36
+ if (!comValor.length) return "#CBD5E1";
37
+ if (comValor.length === 1) return comValor[0].cor;
38
+ const total = comValor.reduce((s, f) => s + f.n, 0);
39
+ let acc = 0;
40
+ const partes = comValor.map((f) => {
41
+ const ini = acc / total * 100;
42
+ acc += f.n;
43
+ return `${f.cor} ${ini.toFixed(2)}% ${(acc / total * 100).toFixed(2)}%`;
44
+ });
45
+ return `conic-gradient(${partes.join(",")})`;
46
+ }
47
+ function anelHtml(fatias, texto, lado, selo, contorno) {
48
+ const espessura = lado < 32 ? 4 : lado < 44 ? 5 : 7;
49
+ const titulo = fatias.filter((f) => f.n > 0).map((f) => `${f.n}${f.rotulo ? ` ${f.rotulo}` : ""}`).join(" · ");
50
+ const d = Math.round(lado * 0.4);
51
+ const marca = selo ? `<div title="${escapar(selo.titulo ?? selo.texto)}" style="position:absolute;top:${-d * 0.18}px;right:${-d * 0.18}px;width:${d}px;height:${d}px;border-radius:9999px;background:${selo.cor};border:1.5px solid #fff;box-shadow:0 1px 2px rgba(0,0,0,.35);display:flex;align-items:center;justify-content:center;color:#fff;font:800 ${Math.round(d * 0.66)}px/1 system-ui,sans-serif">${escapar(selo.texto)}</div>` : "";
52
+ const corpo = Math.max(9, Math.round(lado * (texto.length > 4 ? 0.26 : 0.32)));
53
+ const risco = contorno ? `,0 0 0 2.5px ${contorno}` : "";
54
+ return `<div title="${escapar(titulo)}" style="width:${lado}px;height:${lado}px;border-radius:9999px;background:${anelCss(fatias)};box-shadow:0 1px 3px rgba(0,0,0,.4)${risco};position:relative"><div style="position:absolute;inset:${espessura}px;border-radius:9999px;background:#fff;display:flex;align-items:center;justify-content:center;color:#1e293b;font:700 ${corpo}px/1 system-ui,sans-serif">${escapar(texto)}</div>${marca}</div>`;
55
+ }
56
+ function MapaPontos({
57
+ pontos,
58
+ cor,
59
+ balao,
60
+ forma = "circulo",
61
+ fatias,
62
+ selo,
63
+ contorno,
64
+ raio,
65
+ rotulo,
66
+ aproximado,
67
+ onPontoClick,
68
+ centro,
69
+ zoom = 7,
70
+ altura = "100%",
71
+ agrupar = true,
72
+ tema = "suave",
73
+ urlTiles = TILES_OMISSAO,
74
+ atribuicaoTiles = ATRIBUICAO_OMISSAO,
75
+ truncadoEm,
76
+ percurso,
77
+ calor = false,
78
+ pesoCalor,
79
+ fundos,
80
+ onSeleccionarArea,
81
+ legenda,
82
+ labels,
83
+ className
84
+ }) {
85
+ const txt = { ...LABELS_POR_OMISSAO, ...labels };
86
+ const divRef = useRef(null);
87
+ const mapaRef = useRef(null);
88
+ const camadaRef = useRef(null);
89
+ const tilesRef = useRef(null);
90
+ const limitesRef = useRef(null);
91
+ const mexidoRef = useRef(false);
92
+ const chaveEnquadradaRef = useRef(null);
93
+ const nossoMovimentoRef = useRef(false);
94
+ const [avisoFechadoEm, setAvisoFechadoEm] = useState(null);
95
+ const [pronto, setPronto] = useState(false);
96
+ const [fundo, setFundo] = useState(fundos?.[0]?.id ?? "");
97
+ const enquadrar = useCallback((mapa, limites) => {
98
+ nossoMovimentoRef.current = true;
99
+ mapa.once("moveend", () => {
100
+ nossoMovimentoRef.current = false;
101
+ });
102
+ mapa.fitBounds(limites, { padding: [24, 24], maxZoom: 14 });
103
+ }, []);
104
+ useEffect(() => {
105
+ if (!divRef.current || mapaRef.current) return;
106
+ mapaRef.current = L.map(divRef.current, {
107
+ center: centro ?? CENTRO_OMISSAO,
108
+ zoom,
109
+ // Scroll da página não deve dar zoom sem querer; exige Ctrl.
110
+ scrollWheelZoom: "center"
111
+ });
112
+ const inicial = fundos?.[0];
113
+ tilesRef.current = L.tileLayer(inicial?.url ?? urlTiles, {
114
+ attribution: inicial?.atribuicao ?? atribuicaoTiles,
115
+ maxZoom: 19,
116
+ ...inicial?.tamanhoTile ? { tileSize: inicial.tamanhoTile } : {},
117
+ ...inicial?.deslocamentoZoom != null ? { zoomOffset: inicial.deslocamentoZoom } : {}
118
+ }).addTo(mapaRef.current);
119
+ garantirVisivel(tilesRef.current);
120
+ setPronto(true);
121
+ const observador = new ResizeObserver(() => {
122
+ mapaRef.current?.invalidateSize();
123
+ if (!mexidoRef.current && limitesRef.current?.isValid() && mapaRef.current) {
124
+ enquadrar(mapaRef.current, limitesRef.current);
125
+ }
126
+ });
127
+ observador.observe(divRef.current);
128
+ const marcarMexido = () => {
129
+ if (nossoMovimentoRef.current) return;
130
+ mexidoRef.current = true;
131
+ };
132
+ mapaRef.current.on("zoomstart dragstart", marcarMexido);
133
+ return () => {
134
+ observador.disconnect();
135
+ mapaRef.current?.remove();
136
+ mapaRef.current = null;
137
+ };
138
+ }, []);
139
+ useEffect(() => {
140
+ const mapa = mapaRef.current;
141
+ if (!mapa) return;
142
+ if (!onSeleccionarArea) {
143
+ mapa.boxZoom?.enable();
144
+ return;
145
+ }
146
+ mapa.boxZoom?.disable();
147
+ let inicio = null;
148
+ let caixa = null;
149
+ const posicionar = (a, b) => {
150
+ if (!caixa) return;
151
+ caixa.style.left = `${Math.min(a.x, b.x)}px`;
152
+ caixa.style.top = `${Math.min(a.y, b.y)}px`;
153
+ caixa.style.width = `${Math.abs(a.x - b.x)}px`;
154
+ caixa.style.height = `${Math.abs(a.y - b.y)}px`;
155
+ };
156
+ const aoPremir = (e) => {
157
+ const original = e.originalEvent;
158
+ if (!original.shiftKey) return;
159
+ inicio = e.latlng;
160
+ mapa.dragging.disable();
161
+ caixa = L.DomUtil.create("div", "", mapa.getPanes().overlayPane);
162
+ caixa.style.cssText = "position:absolute;border:2px dashed #1F4E79;background:rgba(31,78,121,.12);pointer-events:none;z-index:600";
163
+ posicionar(mapa.latLngToLayerPoint(inicio), mapa.latLngToLayerPoint(inicio));
164
+ };
165
+ const aoMover = (e) => {
166
+ if (!inicio || !caixa) return;
167
+ posicionar(mapa.latLngToLayerPoint(inicio), mapa.latLngToLayerPoint(e.latlng));
168
+ };
169
+ const aoLargar = (e) => {
170
+ if (!inicio) return;
171
+ const limites = L.latLngBounds(inicio, e.latlng);
172
+ caixa?.remove();
173
+ caixa = null;
174
+ inicio = null;
175
+ mapa.dragging.enable();
176
+ if (limites.getNorth() === limites.getSouth()) return;
177
+ onSeleccionarArea(pontos.filter((p) => limites.contains([p.lat, p.lng])));
178
+ };
179
+ mapa.on("mousedown", aoPremir);
180
+ mapa.on("mousemove", aoMover);
181
+ mapa.on("mouseup", aoLargar);
182
+ return () => {
183
+ mapa.off("mousedown", aoPremir);
184
+ mapa.off("mousemove", aoMover);
185
+ mapa.off("mouseup", aoLargar);
186
+ caixa?.remove();
187
+ mapa.dragging.enable();
188
+ };
189
+ }, [pronto, onSeleccionarArea, pontos]);
190
+ const fundoAplicadoRef = useRef(null);
191
+ useEffect(() => {
192
+ const mapa = mapaRef.current;
193
+ const escolhido = fundos?.find((f) => f.id === fundo);
194
+ if (!mapa || !escolhido || !tilesRef.current) return;
195
+ if (fundoAplicadoRef.current === escolhido.id) return;
196
+ if (fundoAplicadoRef.current === null) {
197
+ fundoAplicadoRef.current = escolhido.id;
198
+ return;
199
+ }
200
+ const centroActual = mapa.getCenter();
201
+ const zoomActual = mapa.getZoom();
202
+ const anterior = tilesRef.current;
203
+ const nova = L.tileLayer(escolhido.url, {
204
+ attribution: escolhido.atribuicao ?? atribuicaoTiles,
205
+ maxZoom: 19,
206
+ ...escolhido.tamanhoTile ? { tileSize: escolhido.tamanhoTile } : {},
207
+ ...escolhido.deslocamentoZoom != null ? { zoomOffset: escolhido.deslocamentoZoom } : {}
208
+ }).addTo(mapa);
209
+ nova.bringToBack();
210
+ garantirVisivel(nova);
211
+ tilesRef.current = nova;
212
+ fundoAplicadoRef.current = escolhido.id;
213
+ anterior.remove();
214
+ mapa.setView(centroActual, zoomActual, { animate: false });
215
+ requestAnimationFrame(() => mapaRef.current?.invalidateSize());
216
+ }, [pronto, fundo]);
217
+ const chavePontos = useMemo(() => `${pontos.length}:${pontos[0]?.id ?? ""}:${pontos[pontos.length - 1]?.id ?? ""}`, [pontos]);
218
+ const calorRef = useRef(null);
219
+ useEffect(() => {
220
+ const mapa = mapaRef.current;
221
+ if (!mapa) return;
222
+ calorRef.current?.remove();
223
+ calorRef.current = null;
224
+ if (!calor) return;
225
+ const dados = pontos.filter((p) => Number.isFinite(p.lat) && Number.isFinite(p.lng)).map((p) => [p.lat, p.lng, pesoCalor?.(p) ?? 1]);
226
+ if (!dados.length) return;
227
+ const heat = L.heatLayer;
228
+ if (typeof heat !== "function") return;
229
+ calorRef.current = heat(dados, {
230
+ radius: 22,
231
+ blur: 18,
232
+ // Sem tecto, um concelho com 2 000 ordens saturava o país inteiro a
233
+ // vermelho e a mancha deixava de distinguir fosse o que fosse.
234
+ max: Math.max(1, ...dados.map((d) => d[2])),
235
+ minOpacity: 0.25
236
+ });
237
+ calorRef.current.addTo(mapa);
238
+ calorRef.current.getPane?.();
239
+ const el = calorRef.current._canvas;
240
+ if (el) el.style.zIndex = "350";
241
+ return () => {
242
+ calorRef.current?.remove();
243
+ calorRef.current = null;
244
+ };
245
+ }, [pronto, calor, chavePontos, pesoCalor]);
246
+ const percursoRef = useRef(null);
247
+ useEffect(() => {
248
+ const mapa = mapaRef.current;
249
+ if (!mapa) return;
250
+ percursoRef.current?.remove();
251
+ percursoRef.current = null;
252
+ if (!percurso?.length) return;
253
+ percursoRef.current = L.polyline(percurso, {
254
+ color: "#1F4E79",
255
+ weight: 3,
256
+ opacity: 0.75,
257
+ // Tracejado: lembra que é um percurso proposto, não um registo do que
258
+ // foi feito.
259
+ dashArray: "6 6"
260
+ }).addTo(mapa);
261
+ percursoRef.current.bringToBack();
262
+ tilesRef.current?.bringToBack();
263
+ }, [pronto, percurso]);
264
+ useEffect(() => {
265
+ const mapa = mapaRef.current;
266
+ if (!mapa) return;
267
+ camadaRef.current?.remove();
268
+ const iconeGrupo = (c) => {
269
+ const filhos = c.getAllChildMarkers().map((mk) => mk.options.ponto).filter(Boolean);
270
+ const soma = /* @__PURE__ */ new Map();
271
+ for (const f of filhos.flatMap((p) => fatias?.(p) ?? [{ cor: cor?.(p) ?? COR_OMISSAO, n: 1 }])) {
272
+ const anterior = soma.get(f.cor);
273
+ if (anterior) anterior.n += f.n;
274
+ else soma.set(f.cor, { ...f });
275
+ }
276
+ const total = filhos.length ? filhos.reduce((n, p) => n + ((fatias?.(p) ?? []).reduce((x, f) => x + f.n, 0) || 1), 0) : c.getChildCount();
277
+ const lado = total < 10 ? 26 : total < 100 ? 32 : total < 1e3 ? 38 : 46;
278
+ return L.divIcon({
279
+ className: "",
280
+ iconSize: [lado, lado],
281
+ html: anelHtml([...soma.values()], total.toLocaleString("pt-PT"), lado)
282
+ });
283
+ };
284
+ const camada = agrupar && L.markerClusterGroup ? L.markerClusterGroup({
285
+ chunkedLoading: true,
286
+ maxClusterRadius: 50,
287
+ showCoverageOnHover: false,
288
+ // Sem isto, marcadores na MESMA coordenada nunca se separam por muito
289
+ // zoom que se faça, e os de baixo ficam inalcançáveis.
290
+ spiderfyOnMaxZoom: true,
291
+ ...forma === "anel" || fatias ? { iconCreateFunction: iconeGrupo } : {}
292
+ }) : L.layerGroup();
293
+ for (const p of pontos) {
294
+ if (!Number.isFinite(p.lat) || !Number.isFinite(p.lng)) continue;
295
+ const estimado = aproximado?.(p) ?? false;
296
+ if (forma === "anel") {
297
+ const composicao = fatias?.(p) ?? [{ cor: cor?.(p) ?? COR_OMISSAO, n: 1 }];
298
+ const lado = Math.round((raio?.(p) ?? 18) * 2);
299
+ const marcadorAnel = L.marker([p.lat, p.lng], {
300
+ icon: L.divIcon({
301
+ className: "",
302
+ iconSize: [lado, lado],
303
+ iconAnchor: [lado / 2, lado / 2],
304
+ popupAnchor: [0, -lado / 2],
305
+ html: anelHtml(composicao, rotulo?.(p) ?? "", lado, selo?.(p), contorno?.(p))
306
+ })
307
+ });
308
+ const htmlAnel = balao?.(p);
309
+ if (htmlAnel) marcadorAnel.bindPopup(htmlAnel);
310
+ if (onPontoClick) marcadorAnel.on("click", () => onPontoClick(p));
311
+ marcadorAnel.options.ponto = p;
312
+ camada.addLayer(marcadorAnel);
313
+ continue;
314
+ }
315
+ const marcador = forma === "pin" ? L.marker([p.lat, p.lng], {
316
+ icon: L.divIcon({
317
+ className: "",
318
+ // A ponta do pin é que assenta na coordenada, não o centro do
319
+ // ícone — daí a âncora no fundo, a meio da largura.
320
+ iconSize: [TAMANHO_PIN, TAMANHO_PIN],
321
+ iconAnchor: [TAMANHO_PIN / 2, TAMANHO_PIN],
322
+ popupAnchor: [0, -TAMANHO_PIN + 4],
323
+ html: pinSvg(cor?.(p) ?? COR_OMISSAO, estimado)
324
+ })
325
+ }) : L.circleMarker([p.lat, p.lng], {
326
+ radius: raio?.(p) ?? 6,
327
+ color: cor?.(p) ?? COR_OMISSAO,
328
+ weight: estimado ? 1 : 2,
329
+ // Tracejado e mais transparente: a posição é estimada, e o mapa não
330
+ // deve sugerir uma precisão que não tem.
331
+ dashArray: estimado ? "2,3" : void 0,
332
+ fillOpacity: estimado ? 0.25 : 0.75,
333
+ fillColor: cor?.(p) ?? COR_OMISSAO
334
+ });
335
+ marcador.options.ponto = p;
336
+ const html = balao?.(p);
337
+ if (html) marcador.bindPopup(html);
338
+ if (onPontoClick) marcador.on("click", () => onPontoClick(p));
339
+ camada.addLayer(marcador);
340
+ const texto = rotulo?.(p);
341
+ if (texto) {
342
+ camada.addLayer(
343
+ L.marker([p.lat, p.lng], {
344
+ interactive: false,
345
+ icon: L.divIcon({
346
+ className: "",
347
+ iconSize: [0, 0],
348
+ html: `<div style="transform:translate(-50%,-50%);white-space:nowrap;font:700 11px/1 system-ui,sans-serif;color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.7);pointer-events:none">${texto}</div>`
349
+ })
350
+ })
351
+ );
352
+ }
353
+ }
354
+ camada.addTo(mapa);
355
+ camadaRef.current = camada;
356
+ if (pontos.length) {
357
+ const limites = L.latLngBounds(pontos.map((p) => [p.lat, p.lng]));
358
+ limitesRef.current = limites.isValid() ? limites : null;
359
+ if (limitesRef.current && !centro && chaveEnquadradaRef.current !== chavePontos) {
360
+ chaveEnquadradaRef.current = chavePontos;
361
+ mexidoRef.current = false;
362
+ enquadrar(mapa, limitesRef.current);
363
+ }
364
+ }
365
+ }, [pronto, chavePontos, agrupar, rotulo, forma, fatias, contorno]);
366
+ const suavizar = tema === "suave" && !fundos?.find((f) => f.id === fundo)?.semFiltro;
367
+ return (
368
+ /*
369
+ `overflow-hidden` e `isolate` não são decoração.
370
+
371
+ O CORTE: os painéis do Leaflet são absolutos e deslocados por
372
+ transformações. Se o mapa ficar com uma posição interna inconsistente —
373
+ ao trocar de fundo, por exemplo — os marcadores pintam-se por cima do
374
+ resto da página. Aconteceu. O corte garante que o pior caso é um mapa
375
+ vazio, não a página desfeita.
376
+
377
+ O ISOLAMENTO: o Leaflet dá z-index 1000 aos seus controlos e 400 aos
378
+ painéis. `relative` sozinho NÃO cria contexto de empilhamento — só o cria
379
+ com um `z-index` — por isso esses valores subiam até à raiz da página e
380
+ competiam de igual para igual com tudo o resto. Um modal a z-50 ficava por
381
+ baixo do mapa: abria-se uma ordem e o mapa pintava-se por cima da ficha.
382
+
383
+ `isolate` fecha-os cá dentro. O mapa passa a valer como um elemento só na
384
+ ordem de empilhamento da página, e deixa de haver maneira de uma peça
385
+ interna dele passar à frente de um modal, de um menu ou de um tooltip.
386
+ */
387
+ /* @__PURE__ */ jsxs(
388
+ "div",
389
+ {
390
+ className: `relative isolate overflow-hidden ${suavizar ? "mapa-suave" : ""} ${className ?? ""}`,
391
+ style: { height: altura },
392
+ children: [
393
+ suavizar && /* @__PURE__ */ jsx("style", { children: `.mapa-suave .leaflet-tile-pane{filter:grayscale(.85) brightness(1.06) contrast(.95)}` }),
394
+ /* @__PURE__ */ jsx("div", { ref: divRef, style: { height: "100%", width: "100%" }, "aria-label": "Mapa" }),
395
+ pronto && !pontos.length && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 flex items-center justify-center text-sm text-slate-500 pointer-events-none", children: txt.semPontos }),
396
+ !!fundos?.length && /* @__PURE__ */ jsx("div", { className: "absolute top-2 left-12 z-[400] bg-white/90 backdrop-blur-sm shadow-sm rounded flex text-[11px] overflow-hidden", children: fundos.map((f) => /* @__PURE__ */ jsx(
397
+ "button",
398
+ {
399
+ onClick: () => setFundo(f.id),
400
+ className: `px-1.5 py-0.5 ${fundo === f.id ? "bg-proef-navy text-white font-semibold" : "text-slate-600 hover:bg-slate-100"}`,
401
+ children: f.rotulo
402
+ },
403
+ f.id
404
+ )) }),
405
+ legenda && /* @__PURE__ */ jsx("div", { className: "absolute bottom-2 left-2 z-[400] bg-white/90 backdrop-blur-sm rounded shadow-sm px-2 py-1 text-[11px] leading-tight", children: legenda }),
406
+ !!truncadoEm && txt.truncado && avisoFechadoEm !== truncadoEm && /* @__PURE__ */ jsxs("div", { className: "absolute top-3 right-3 z-[400] flex items-start gap-2 bg-amber-50 border border-amber-300 text-amber-900 shadow rounded-lg px-2.5 py-1 text-[11px] max-w-[22rem]", children: [
407
+ /* @__PURE__ */ jsx("span", { children: txt.truncado.replace("{n}", String(truncadoEm)) }),
408
+ /* @__PURE__ */ jsx(
409
+ "button",
410
+ {
411
+ onClick: () => setAvisoFechadoEm(truncadoEm),
412
+ "aria-label": txt.fecharAviso ?? "Fechar",
413
+ title: txt.fecharAviso ?? "Fechar",
414
+ className: "text-amber-700 hover:text-amber-900 leading-none font-bold",
415
+ children: "×"
416
+ }
417
+ )
418
+ ] })
419
+ ]
420
+ }
421
+ )
422
+ );
423
+ }
424
+ export {
425
+ MapaPontos as default
426
+ };
427
+ //# sourceMappingURL=MapaPontos.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MapaPontos.js","sources":["../../../../../../src/legacy/components/organisms/MapaPontos/MapaPontos.tsx"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\r\nimport L from 'leaflet'\r\nimport 'leaflet.markercluster'\r\nimport 'leaflet.heat'\r\n\r\n/**\r\n * Mapa de pontos com agrupamento, para listas grandes.\r\n *\r\n * Genérico de propósito: recebe pontos com coordenadas e devolve as funções de\r\n * cor e de rótulo a quem o usa. Não sabe o que é uma ordem de trabalho nem um\r\n * cliente — quem sabe é o ecrã que o monta.\r\n *\r\n * O Leaflet entra por import ESTÁTICO, e não dinâmico.\r\n *\r\n * As duas alternativas falharam, cada uma à sua maneira:\r\n * - import dinâmico + webpack `externals` → o UMD gera\r\n * `try{return require(\"leaflet\")}catch{}`, e no browser não há `require`:\r\n * o catch engole o erro e o componente diz que falta a biblioteca;\r\n * - import dinâmico sem `externals` → o Leaflet fica em chunks separados\r\n * (481.bundle.js) que vivem no node_modules da biblioteca e nunca chegam ao\r\n * dist da aplicação: o pedido devolve o index.html e dá\r\n * `Unexpected token '<'`.\r\n *\r\n * Estático, o bundler da aplicação resolve-o como qualquer outro import. Custa\r\n * ~150 KB a quem não usa mapas — o preço de funcionar sempre.\r\n *\r\n * As folhas de estilo do Leaflet têm de ser importadas pelo projeto:\r\n * import 'leaflet/dist/leaflet.css'\r\n * import 'leaflet.markercluster/dist/MarkerCluster.css'\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\n\r\nexport interface PontoMapa {\r\n id: string\r\n lat: number\r\n lng: number\r\n}\r\n\r\n/**\r\n * Garante que uma camada de tiles fica mesmo visível.\r\n *\r\n * O Leaflet faz os tiles aparecerem com uma animação de opacidade. Se a camada\r\n * for mexida enquanto essa animação decorre — uma troca de fundo, um\r\n * `invalidateSize` fora de horas — há casos em que a opacidade fica em 0 e lá\r\n * fica: os tiles chegam do servidor, entram no DOM, e o mapa continua branco\r\n * sem um único erro na consola.\r\n *\r\n * Repor a opacidade quando a camada termina de carregar custa nada e tira o\r\n * assunto do caminho, mesmo que a causa seja outra.\r\n */\r\nfunction garantirVisivel(camada: any): void {\r\n const repor = (): void => camada.setOpacity?.(1)\r\n camada.on('load', repor)\r\n repor()\r\n}\r\n\r\n/**\r\n * Um fundo de mapa: o que o selector mostra e o que o Leaflet carrega.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport interface FundoMapa {\r\n id: string\r\n rotulo: string\r\n url: string\r\n atribuicao?: string\r\n /** Fundos de satélite ficam melhor sem a dessaturação do tema `suave`. */\r\n semFiltro?: boolean\r\n /**\r\n * Lado do tile em píxeis. 256 por omissão, que é o do OpenStreetMap.\r\n *\r\n * Importa para quem paga por pedido: um tile de 512 cobre a área de quatro\r\n * de 256, e o mesmo ecrã passa a custar um quarto. Com 512 é preciso\r\n * `deslocamentoZoom: -1`, senão o mapa desenha um nível de zoom ao lado.\r\n */\r\n tamanhoTile?: number\r\n deslocamentoZoom?: number\r\n}\r\n\r\n/**\r\n * Uma fatia do anel de um marcador: uma cor e quantos registos ela representa.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport interface FatiaMapa {\r\n cor: string\r\n n: number\r\n /** Nome legível, para a dica nativa do marcador. */\r\n rotulo?: string\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface MapaPontosLabels {\r\n semPontos: string\r\n semBiblioteca: string\r\n aCarregar: string\r\n /** {n} é substituído pelo número de pontos fora do limite. */\r\n truncado?: string\r\n fecharAviso?: string\r\n}\r\n\r\nconst LABELS_POR_OMISSAO: MapaPontosLabels = {\r\n semPontos: 'Sem pontos para mostrar.',\r\n semBiblioteca: 'Mapa indisponível: falta instalar leaflet e leaflet.markercluster.',\r\n aCarregar: 'A carregar o mapa…',\r\n truncado: '{n} pontos não mostrados.',\r\n fecharAviso: 'Fechar aviso',\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface MapaPontosProps<T extends PontoMapa> {\r\n pontos: T[]\r\n /** Cor do marcador. Devolver a mesma cor para todos é perfeitamente válido. */\r\n cor?: (ponto: T) => string\r\n /** HTML do balão. Sem isto não há balão. */\r\n balao?: (ponto: T) => string\r\n /**\r\n * Forma do marcador.\r\n *\r\n * `circulo` para agregados — o tamanho pode variar com a contagem e lê-se\r\n * como densidade. `pin` para registos individuais: a ponta assenta na\r\n * coordenada exata, e é isso que se quer quando o ponto é um sítio e não um\r\n * número.\r\n */\r\n forma?: 'circulo' | 'pin' | 'anel'\r\n\r\n /**\r\n * Composição do marcador, para a forma `anel`.\r\n *\r\n * Um agregado pintado de UMA cor — a do caso mais grave, ou a da contagem —\r\n * diz \"há aqui pelo menos um destes\" e esconde tudo o resto: cinquenta\r\n * registos misturados liam-se como cinquenta urgentes. As fatias mostram a\r\n * composição sem obrigar a abrir o grupo, e deixam a cor dizer SITUAÇÃO\r\n * enquanto o tamanho diz VOLUME — duas perguntas diferentes, dois canais.\r\n */\r\n fatias?: (ponto: T) => FatiaMapa[]\r\n\r\n /**\r\n * Selo por cima do marcador: uma marca que se soma à cor em vez de competir\r\n * com ela (ex: \"está suspensa\"). Null não desenha nada.\r\n */\r\n selo?: (ponto: T) => { texto: string; cor: string; titulo?: string } | null\r\n\r\n /**\r\n * Contorno do marcador, por fora das fatias.\r\n *\r\n * Para uma segunda dimensão que não é exclusiva da primeira — um prazo\r\n * excedido pode acontecer em qualquer estado, e por isso não pode ser uma\r\n * fatia: somá-la ao anel faria as fatias deixarem de somar o total.\r\n */\r\n contorno?: (ponto: T) => string | null\r\n\r\n /** Raio do marcador em píxeis. Só se aplica à forma `circulo`. */\r\n raio?: (ponto: T) => number\r\n /**\r\n * Texto por cima do marcador (ex: a contagem de uma zona).\r\n *\r\n * Pensado para o modo agregado: em vez de desenhar dezenas de milhares de\r\n * pontos, desenha-se um círculo por concelho com o número dentro. O mapa\r\n * deixa de precisar de zoom para dizer alguma coisa.\r\n */\r\n rotulo?: (ponto: T) => string | null\r\n /**\r\n * Marca o ponto como aproximado — desenhado a tracejado.\r\n * Serve para distinguir uma morada confirmada de uma posição estimada, que\r\n * no mapa parecem iguais e não são.\r\n */\r\n aproximado?: (ponto: T) => boolean\r\n onPontoClick?: (ponto: T) => void\r\n\r\n /** Centro inicial. Sem isto, enquadra-se pelos pontos. */\r\n centro?: [number, number]\r\n zoom?: number\r\n altura?: string\r\n\r\n /**\r\n * Aspeto do fundo.\r\n *\r\n * `suave` dessatura os tiles por CSS, deixando os marcadores com cor — num\r\n * mapa de dados, o fundo não deve disputar atenção com o que está em cima.\r\n * Faz o que o basemap claro do CARTO fazia, sem precisar de chave.\r\n */\r\n tema?: 'normal' | 'suave'\r\n\r\n /** Agrupar pontos próximos. Com milhares de pontos, desligar trava o browser. */\r\n agrupar?: boolean\r\n /** Tiles. Por omissão, OpenStreetMap — sem necessidade de chave. */\r\n urlTiles?: string\r\n atribuicaoTiles?: string\r\n\r\n /**\r\n * Fundos alternativos, com um selector no canto do mapa.\r\n *\r\n * Os que precisam de chave ficam de fora por omissão: quem a tiver passa-os\r\n * aqui, e a chave fica do lado de quem a tem em vez de vir na biblioteca.\r\n */\r\n fundos?: FundoMapa[]\r\n\r\n /** Quantos pontos ficaram de fora, para avisar quem vê. */\r\n truncadoEm?: number\r\n\r\n /**\r\n * Um traçado a unir pontos, em [lat, lng].\r\n *\r\n * Serve para mostrar um percurso — a ordem por que se visita, e por onde se\r\n * passa. Sem ele, uma sequência numerada obriga a segui-la com o olho de\r\n * número em número, que é exactamente o trabalho que o mapa devia poupar.\r\n *\r\n * Quem passa o traçado decide o que ele é: se vier de um serviço de rotas,\r\n * são estradas; se forem só as paragens, são linhas rectas. O componente\r\n * desenha o que recebe e não opina — mas quem o usa deve dizer ao\r\n * utilizador qual dos dois é.\r\n */\r\n percurso?: [number, number][] | null\r\n\r\n /**\r\n * Mapa de calor por cima dos pontos.\r\n *\r\n * Responde a outra pergunta: os marcadores dizem o que cada ordem é, o calor\r\n * diz onde há concentração. Com dez mil pontos, contar marcadores não se faz\r\n * — e agrupados, o número do grupo diz quantos mas não onde eles se apertam\r\n * lá dentro.\r\n *\r\n * Soma-se aos marcadores em vez de os substituir: quem liga o calor quer ver\r\n * a mancha E continuar a poder clicar numa ordem.\r\n */\r\n calor?: boolean\r\n\r\n /**\r\n * Quanto cada ponto pesa no calor. Por omissão, um.\r\n *\r\n * Serve para quando um marcador representa muitos — um concelho com 300\r\n * ordens não deve pesar o mesmo que uma ordem solta.\r\n */\r\n pesoCalor?: (p: T) => number\r\n\r\n /**\r\n * Selecção por caixa: `Shift` + arrastar devolve os pontos dentro dela.\r\n *\r\n * Com `Shift` e não só arrastar, porque arrastar já é a forma de deslocar o\r\n * mapa — tirar isso ao arrasto simples trocaria o gesto mais usado pelo mais\r\n * raro.\r\n */\r\n onSeleccionarArea?: (pontos: T[]) => void\r\n\r\n legenda?: React.ReactNode\r\n labels?: Partial<MapaPontosLabels>\r\n className?: string\r\n}\r\n\r\n/**\r\n * Tiles por omissão: OpenStreetMap.\r\n *\r\n * Não precisa de chave. O CARTO, que parecia a escolha óbvia pelo estilo mais\r\n * discreto, passou a exigir API key e os tiles vêm marcados com\r\n * \"API KEY REQUIRED\" por cima do mapa.\r\n *\r\n * Para um estilo próprio (Mapbox, CARTO com conta), passar `urlTiles` e\r\n * `atribuicaoTiles` — a chave fica do lado de quem a tem.\r\n */\r\nconst TILES_OMISSAO = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png'\r\nconst ATRIBUICAO_OMISSAO = '&copy; <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a>'\r\n\r\n/** Centro de Portugal continental, para quando não há pontos nem centro indicado. */\r\nconst CENTRO_OMISSAO: [number, number] = [39.6, -8.0]\r\n\r\nconst COR_OMISSAO = '#1F4E79'\r\nconst TAMANHO_PIN = 28\r\n\r\n/**\r\n * Pin em gota, com contorno branco e sombra.\r\n *\r\n * O contorno branco é o que o torna legível sobre qualquer fundo — sem ele, um\r\n * pin escuro desaparece numa zona escura do mapa. Um ponto aproximado fica\r\n * translúcido e com o contorno a tracejado, para não se confundir com uma\r\n * posição confirmada.\r\n */\r\nfunction pinSvg(cor: string, aproximado: boolean): string {\r\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${TAMANHO_PIN}\" height=\"${TAMANHO_PIN}\" viewBox=\"0 0 24 24\"\r\n style=\"filter:drop-shadow(0 1px 2px rgba(0,0,0,.45));opacity:${aproximado ? 0.55 : 1}\">\r\n <path d=\"M12 2C8.13 2 5 5.13 5 9c0 1.36.4 2.63 1.09 3.7L12 23l5.91-10.3A6.94 6.94 0 0 0 19 9c0-3.87-3.13-7-7-7z\"\r\n fill=\"${cor}\" stroke=\"#ffffff\" stroke-width=\"1.2\"${aproximado ? ' stroke-dasharray=\"2 1.5\"' : ''}/>\r\n <circle cx=\"12\" cy=\"9\" r=\"2.6\" fill=\"#ffffff\"/>\r\n </svg>`\r\n}\r\n\r\n/** Escapa o que vai para dentro de um atributo HTML (rótulos vindos dos dados). */\r\nfunction escapar(texto: string): string {\r\n return texto.replace(/[&<>\"']/g, (c) =>\r\n ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' })[c] as string)\r\n}\r\n\r\n/**\r\n * `conic-gradient` com uma fatia por cor, proporcional à contagem.\r\n *\r\n * Os limites de cada fatia levam a mesma percentagem duas vezes (fim da\r\n * anterior, início da seguinte) para o corte ser seco: sem isso o gradiente\r\n * interpola e as cores esfumam-se uma na outra.\r\n */\r\nfunction anelCss(fatias: FatiaMapa[]): string {\r\n const comValor = fatias.filter((f) => f.n > 0)\r\n if (!comValor.length) return '#CBD5E1'\r\n // Uma cor só: poupa ao browser um gradiente por cada marcador no ecrã.\r\n if (comValor.length === 1) return comValor[0]!.cor\r\n const total = comValor.reduce((s, f) => s + f.n, 0)\r\n let acc = 0\r\n const partes = comValor.map((f) => {\r\n const ini = (acc / total) * 100\r\n acc += f.n\r\n return `${f.cor} ${ini.toFixed(2)}% ${((acc / total) * 100).toFixed(2)}%`\r\n })\r\n return `conic-gradient(${partes.join(',')})`\r\n}\r\n\r\n/**\r\n * Marcador em anel: as fatias por fora, o número por dentro.\r\n *\r\n * O branco do meio é o que deixa o número legível seja qual for a composição —\r\n * texto por cima das fatias ficava ilegível em metade dos casos.\r\n */\r\nfunction anelHtml(\r\n fatias: FatiaMapa[],\r\n texto: string,\r\n lado: number,\r\n selo?: { texto: string; cor: string; titulo?: string } | null,\r\n contorno?: string | null,\r\n): string {\r\n // Espessura: o suficiente para a fatia mais fina se ver, sem apertar o número.\r\n const espessura = lado < 32 ? 4 : lado < 44 ? 5 : 7\r\n const titulo = fatias\r\n .filter((f) => f.n > 0)\r\n .map((f) => `${f.n}${f.rotulo ? ` ${f.rotulo}` : ''}`)\r\n .join(' · ')\r\n const d = Math.round(lado * 0.40)\r\n const marca = selo\r\n ? `<div title=\"${escapar(selo.titulo ?? selo.texto)}\" style=\"position:absolute;top:${-d * 0.18}px;right:${-d * 0.18}px;` +\r\n `width:${d}px;height:${d}px;border-radius:9999px;background:${selo.cor};border:1.5px solid #fff;` +\r\n `box-shadow:0 1px 2px rgba(0,0,0,.35);display:flex;align-items:center;justify-content:center;` +\r\n `color:#fff;font:800 ${Math.round(d * 0.66)}px/1 system-ui,sans-serif\">${escapar(selo.texto)}</div>`\r\n : ''\r\n const corpo = Math.max(9, Math.round(lado * (texto.length > 4 ? 0.26 : 0.32)))\r\n // O contorno é desenhado como sombra e não como `border`: um `border` encolhe\r\n // o conteúdo e as fatias mudavam de tamanho conforme houvesse contorno ou não.\r\n const risco = contorno ? `,0 0 0 2.5px ${contorno}` : ''\r\n return `<div title=\"${escapar(titulo)}\" style=\"width:${lado}px;height:${lado}px;border-radius:9999px;` +\r\n `background:${anelCss(fatias)};box-shadow:0 1px 3px rgba(0,0,0,.4)${risco};position:relative\">` +\r\n `<div style=\"position:absolute;inset:${espessura}px;border-radius:9999px;background:#fff;` +\r\n `display:flex;align-items:center;justify-content:center;color:#1e293b;` +\r\n `font:700 ${corpo}px/1 system-ui,sans-serif\">${escapar(texto)}</div>${marca}</div>`\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport default function MapaPontos<T extends PontoMapa>({\r\n pontos,\r\n cor,\r\n balao,\r\n forma = 'circulo',\r\n fatias,\r\n selo,\r\n contorno,\r\n raio,\r\n rotulo,\r\n aproximado,\r\n onPontoClick,\r\n centro,\r\n zoom = 7,\r\n altura = '100%',\r\n agrupar = true,\r\n tema = 'suave',\r\n urlTiles = TILES_OMISSAO,\r\n atribuicaoTiles = ATRIBUICAO_OMISSAO,\r\n truncadoEm,\r\n percurso,\r\n calor = false,\r\n pesoCalor,\r\n fundos,\r\n onSeleccionarArea,\r\n legenda,\r\n labels,\r\n className,\r\n}: MapaPontosProps<T>) {\r\n const txt = { ...LABELS_POR_OMISSAO, ...labels }\r\n const divRef = useRef<HTMLDivElement | null>(null)\r\n const mapaRef = useRef<any>(null)\r\n const camadaRef = useRef<any>(null)\r\n const tilesRef = useRef<any>(null)\r\n /** Os limites dos pontos, para reenquadrar quando o contentor mudar de tamanho. */\r\n const limitesRef = useRef<any>(null)\r\n /** O utilizador já mexeu no mapa? A partir daí a vista é dele. */\r\n const mexidoRef = useRef(false)\r\n /**\r\n * O conjunto de pontos que já foi enquadrado.\r\n *\r\n * O efeito do desenho depende das funções de aspecto (`rotulo`, `fatias`,\r\n * `forma`, `contorno`), que quem usa passa quase sempre inline — e portanto\r\n * mudam de identidade a CADA render do ecrã. Sem esta memória, qualquer\r\n * re-render reenquadrava o mapa: abrir e fechar a ficha de uma ordem\r\n * atirava o zoom de volta para o país inteiro.\r\n */\r\n const chaveEnquadradaRef = useRef<string | null>(null)\r\n\r\n /**\r\n * Um movimento nosso está a decorrer.\r\n *\r\n * O Leaflet dispara `zoomstart` tanto para o gesto da pessoa como para um\r\n * `fitBounds` nosso, e não há como os distinguir pelo evento. Sem esta\r\n * marca, o primeiro enquadramento marcava o mapa como \"já mexido\" e\r\n * bloqueava todos os seguintes.\r\n *\r\n * Dava isto, dentro de um modal: o mapa nasce com altura zero, o\r\n * `fitBounds` calcula contra 0x0 e cai no zoom mínimo, o contentor ganha\r\n * altura logo a seguir — e o reenquadramento que arrumava tudo já estava\r\n * proibido. Ficava o país inteiro.\r\n */\r\n const nossoMovimentoRef = useRef(false)\r\n\r\n /// O valor de `truncadoEm` que a pessoa já dispensou. Guardado o número e\r\n /// não um booleano para o aviso voltar quando o conjunto muda.\r\n const [avisoFechadoEm, setAvisoFechadoEm] = useState<number | null>(null)\r\n const [pronto, setPronto] = useState(false)\r\n const [fundo, setFundo] = useState(fundos?.[0]?.id ?? '')\r\n\r\n /**\r\n * Enquadrar os pontos, sem que isso conte como gesto da pessoa.\r\n *\r\n * A marca cai no `moveend`, que o Leaflet dispara no fim da animação —\r\n * incluindo quando não há animação nenhuma.\r\n */\r\n const enquadrar = useCallback((mapa: L.Map, limites: L.LatLngBounds): void => {\r\n nossoMovimentoRef.current = true\r\n mapa.once('moveend', () => { nossoMovimentoRef.current = false })\r\n mapa.fitBounds(limites, { padding: [24, 24], maxZoom: 14 })\r\n }, [])\r\n\r\n // Criação do mapa — uma só vez.\r\n useEffect(() => {\r\n if (!divRef.current || mapaRef.current) return\r\n\r\n mapaRef.current = L.map(divRef.current, {\r\n center: centro ?? CENTRO_OMISSAO,\r\n zoom,\r\n // Scroll da página não deve dar zoom sem querer; exige Ctrl.\r\n scrollWheelZoom: 'center',\r\n })\r\n const inicial = fundos?.[0]\r\n tilesRef.current = L.tileLayer(inicial?.url ?? urlTiles, {\r\n attribution: inicial?.atribuicao ?? atribuicaoTiles,\r\n maxZoom: 19,\r\n ...(inicial?.tamanhoTile ? { tileSize: inicial.tamanhoTile } : {}),\r\n ...(inicial?.deslocamentoZoom != null ? { zoomOffset: inicial.deslocamentoZoom } : {}),\r\n }).addTo(mapaRef.current)\r\n garantirVisivel(tilesRef.current)\r\n\r\n setPronto(true)\r\n\r\n /*\r\n O Leaflet mede o contentor UMA vez, na criação, e desenha para essa\r\n medida. Quando o mapa nasce antes de o layout assentar — uma coluna que\r\n ainda não tem largura, um painel lateral que abre — fica com metade da\r\n área a cinzento e o conteúdo encostado a um canto, e só se vê tudo\r\n tirando zoom à mão.\r\n\r\n O observador remedia-o a cada mudança de tamanho: apanha o primeiro\r\n assentar do layout, o abrir e fechar dos painéis e o redimensionar da\r\n janela, sem ninguém medir nada.\r\n */\r\n const observador = new ResizeObserver(() => {\r\n mapaRef.current?.invalidateSize()\r\n // Reenquadrar enquanto o utilizador não tiver mexido no mapa: depois\r\n // disso, a vista é dele e mexer-lhe seria roubar-lhe o sítio.\r\n if (!mexidoRef.current && limitesRef.current?.isValid() && mapaRef.current) {\r\n enquadrar(mapaRef.current, limitesRef.current)\r\n }\r\n })\r\n observador.observe(divRef.current)\r\n\r\n // Qualquer gesto do utilizador congela o reenquadramento automático.\r\n const marcarMexido = (): void => {\r\n if (nossoMovimentoRef.current) return\r\n mexidoRef.current = true\r\n }\r\n mapaRef.current.on('zoomstart dragstart', marcarMexido)\r\n\r\n return () => {\r\n observador.disconnect()\r\n mapaRef.current?.remove()\r\n mapaRef.current = null\r\n }\r\n }, [])\r\n\r\n /**\r\n * Selecção por caixa.\r\n *\r\n * O `boxZoom` do Leaflet usa o mesmo gesto (Shift + arrastar) e tem de ser\r\n * desligado, senão o mapa dá zoom à caixa ao mesmo tempo que se selecciona.\r\n */\r\n useEffect(() => {\r\n const mapa = mapaRef.current\r\n if (!mapa) return\r\n\r\n if (!onSeleccionarArea) {\r\n mapa.boxZoom?.enable()\r\n return\r\n }\r\n mapa.boxZoom?.disable()\r\n\r\n let inicio: L.LatLng | null = null\r\n let caixa: HTMLDivElement | null = null\r\n\r\n const posicionar = (a: L.Point, b: L.Point): void => {\r\n if (!caixa) return\r\n caixa.style.left = `${Math.min(a.x, b.x)}px`\r\n caixa.style.top = `${Math.min(a.y, b.y)}px`\r\n caixa.style.width = `${Math.abs(a.x - b.x)}px`\r\n caixa.style.height = `${Math.abs(a.y - b.y)}px`\r\n }\r\n\r\n const aoPremir = (e: L.LeafletMouseEvent): void => {\r\n const original = e.originalEvent as MouseEvent\r\n if (!original.shiftKey) return\r\n inicio = e.latlng\r\n mapa.dragging.disable()\r\n caixa = L.DomUtil.create('div', '', mapa.getPanes().overlayPane) as HTMLDivElement\r\n caixa.style.cssText =\r\n 'position:absolute;border:2px dashed #1F4E79;background:rgba(31,78,121,.12);pointer-events:none;z-index:600'\r\n posicionar(mapa.latLngToLayerPoint(inicio), mapa.latLngToLayerPoint(inicio))\r\n }\r\n\r\n const aoMover = (e: L.LeafletMouseEvent): void => {\r\n if (!inicio || !caixa) return\r\n posicionar(mapa.latLngToLayerPoint(inicio), mapa.latLngToLayerPoint(e.latlng))\r\n }\r\n\r\n const aoLargar = (e: L.LeafletMouseEvent): void => {\r\n if (!inicio) return\r\n const limites = L.latLngBounds(inicio, e.latlng)\r\n caixa?.remove()\r\n caixa = null\r\n inicio = null\r\n mapa.dragging.enable()\r\n // Um clique com Shift não é uma selecção: a caixa teria área zero e\r\n // devolveria lista vazia, o que se leria como \"não há nada aqui\".\r\n if (limites.getNorth() === limites.getSouth()) return\r\n onSeleccionarArea(pontos.filter((p) => limites.contains([p.lat, p.lng])))\r\n }\r\n\r\n mapa.on('mousedown', aoPremir)\r\n mapa.on('mousemove', aoMover)\r\n mapa.on('mouseup', aoLargar)\r\n\r\n return () => {\r\n mapa.off('mousedown', aoPremir)\r\n mapa.off('mousemove', aoMover)\r\n mapa.off('mouseup', aoLargar)\r\n caixa?.remove()\r\n mapa.dragging.enable()\r\n }\r\n }, [pronto, onSeleccionarArea, pontos])\r\n\r\n /*\r\n Troca do fundo.\r\n\r\n Substitui a camada em vez de acrescentar outra por cima — empilhadas, a de\r\n baixo continua a pedir tiles que ninguém vê.\r\n\r\n Duas regras que não são detalhe:\r\n\r\n 1. NÃO mexer quando o fundo já é o que está no mapa. A camada inicial é\r\n criada ao nascer o mapa; se este efeito voltasse a removê-la e a\r\n recriá-la na primeira passagem, estaria a desfazer trabalho acabado de\r\n fazer — e era aí que tudo corria mal.\r\n\r\n 2. A nova camada entra ANTES de a velha sair, e o `invalidateSize` fica\r\n para o quadro seguinte. Remover e recriar no mesmo tique, e logo a\r\n seguir forçar um recálculo de tamanho, apanha o Leaflet a meio da\r\n animação de aparecimento: os tiles chegam do servidor, são inseridos no\r\n DOM e ficam com opacidade 0 para sempre. O mapa fica branco com os\r\n marcadores por cima, e a consola não diz nada porque nada falhou.\r\n */\r\n const fundoAplicadoRef = useRef<string | null>(null)\r\n\r\n useEffect(() => {\r\n const mapa = mapaRef.current\r\n const escolhido = fundos?.find((f) => f.id === fundo)\r\n if (!mapa || !escolhido || !tilesRef.current) return\r\n if (fundoAplicadoRef.current === escolhido.id) return\r\n if (fundoAplicadoRef.current === null) {\r\n // A camada inicial já é esta. Marca-se como aplicada e não se lhe toca.\r\n fundoAplicadoRef.current = escolhido.id\r\n return\r\n }\r\n\r\n /*\r\n Guardar a vista antes de mexer nas camadas: fundos com tamanhos de tile\r\n diferentes (256 e 512) obrigam o Leaflet a recalcular a escala, e entre\r\n uma camada e outra o mapa fica sem referência — era o que fazia os\r\n marcadores saltarem para fora do contentor.\r\n */\r\n const centroActual = mapa.getCenter()\r\n const zoomActual = mapa.getZoom()\r\n const anterior = tilesRef.current\r\n\r\n const nova = L.tileLayer(escolhido.url, {\r\n attribution: escolhido.atribuicao ?? atribuicaoTiles,\r\n maxZoom: 19,\r\n ...(escolhido.tamanhoTile ? { tileSize: escolhido.tamanhoTile } : {}),\r\n ...(escolhido.deslocamentoZoom != null ? { zoomOffset: escolhido.deslocamentoZoom } : {}),\r\n }).addTo(mapa)\r\n // Os tiles pertencem ao painel de baixo; sem isto ficavam por cima dos\r\n // marcadores depois de uma troca.\r\n nova.bringToBack()\r\n garantirVisivel(nova)\r\n\r\n tilesRef.current = nova\r\n fundoAplicadoRef.current = escolhido.id\r\n anterior.remove()\r\n\r\n mapa.setView(centroActual, zoomActual, { animate: false })\r\n requestAnimationFrame(() => mapaRef.current?.invalidateSize())\r\n }, [pronto, fundo])\r\n\r\n /*\r\n O traçado.\r\n\r\n Camada própria e refeita quando o percurso muda, em vez de ir junto com os\r\n marcadores: os pontos redesenham-se a cada filtro e o traçado não tem de\r\n acompanhar esse ritmo.\r\n\r\n Vai para trás dos marcadores — uma linha por cima dos números tapava\r\n justamente o que ela serve para ligar.\r\n */\r\n /*\r\n O mapa de calor.\r\n\r\n Em camada própria e em efeito próprio: liga-se e desliga-se muitas vezes, e\r\n pendurá-lo no desenho dos marcadores obrigava a refazer dez mil marcadores\r\n de cada vez que alguém carregava na caixa.\r\n\r\n Fica POR BAIXO dos marcadores. Por cima, a mancha tapava justamente os\r\n pontos que ela serve para situar.\r\n */\r\n /** Identidade do conjunto de pontos, para não redesenhar o que não mudou. */\r\n const chavePontos = useMemo(() => `${pontos.length}:${pontos[0]?.id ?? ''}:${pontos[pontos.length - 1]?.id ?? ''}`, [pontos])\r\n\r\n const calorRef = useRef<any>(null)\r\n\r\n useEffect(() => {\r\n const mapa = mapaRef.current\r\n if (!mapa) return\r\n\r\n calorRef.current?.remove()\r\n calorRef.current = null\r\n if (!calor) return\r\n\r\n const dados = pontos\r\n .filter((p) => Number.isFinite(p.lat) && Number.isFinite(p.lng))\r\n .map((p) => [p.lat, p.lng, pesoCalor?.(p) ?? 1] as [number, number, number])\r\n if (!dados.length) return\r\n\r\n const heat = (L as any).heatLayer\r\n // Sem o plugin, não se desenha nada em vez de rebentar: o mapa continua a\r\n // servir para tudo o resto.\r\n if (typeof heat !== 'function') return\r\n\r\n calorRef.current = heat(dados, {\r\n radius: 22,\r\n blur: 18,\r\n // Sem tecto, um concelho com 2 000 ordens saturava o país inteiro a\r\n // vermelho e a mancha deixava de distinguir fosse o que fosse.\r\n max: Math.max(1, ...dados.map((d) => d[2])),\r\n minOpacity: 0.25,\r\n })\r\n calorRef.current.addTo(mapa)\r\n // A camada do calor nasce no painel dos overlays, que fica acima dos\r\n // marcadores; desce-se para os pontos continuarem clicáveis e visíveis.\r\n calorRef.current.getPane?.()\r\n const el = calorRef.current._canvas as HTMLElement | undefined\r\n if (el) el.style.zIndex = '350'\r\n\r\n return () => {\r\n calorRef.current?.remove()\r\n calorRef.current = null\r\n }\r\n }, [pronto, calor, chavePontos, pesoCalor])\r\n\r\n const percursoRef = useRef<any>(null)\r\n\r\n useEffect(() => {\r\n const mapa = mapaRef.current\r\n if (!mapa) return\r\n\r\n percursoRef.current?.remove()\r\n percursoRef.current = null\r\n if (!percurso?.length) return\r\n\r\n percursoRef.current = L.polyline(percurso, {\r\n color: '#1F4E79',\r\n weight: 3,\r\n opacity: 0.75,\r\n // Tracejado: lembra que é um percurso proposto, não um registo do que\r\n // foi feito.\r\n dashArray: '6 6',\r\n }).addTo(mapa)\r\n percursoRef.current.bringToBack()\r\n tilesRef.current?.bringToBack()\r\n }, [pronto, percurso])\r\n\r\n\r\n // Desenho dos pontos — refeito quando a lista muda.\r\n useEffect(() => {\r\n const mapa = mapaRef.current\r\n if (!mapa) return\r\n\r\n camadaRef.current?.remove()\r\n\r\n /**\r\n * Ícone do grupo: o mesmo anel dos marcadores, com a composição somada.\r\n *\r\n * Fechar pontos não pode apagar o que eles diziam — o grupo azul por\r\n * omissão do markercluster diz quantos, e nada sobre o que são.\r\n */\r\n const iconeGrupo = (c: any) => {\r\n const filhos: T[] = c.getAllChildMarkers()\r\n .map((mk: any) => mk.options.ponto)\r\n .filter(Boolean)\r\n const soma = new Map<string, FatiaMapa>()\r\n for (const f of filhos.flatMap((p) => fatias?.(p) ?? [{ cor: cor?.(p) ?? COR_OMISSAO, n: 1 }])) {\r\n const anterior = soma.get(f.cor)\r\n if (anterior) anterior.n += f.n\r\n else soma.set(f.cor, { ...f })\r\n }\r\n // Cada filho conta o que as suas fatias somam; sem fatias, conta por um.\r\n const total = filhos.length\r\n ? filhos.reduce((n, p) => n + ((fatias?.(p) ?? []).reduce((x, f) => x + f.n, 0) || 1), 0)\r\n : c.getChildCount()\r\n const lado = total < 10 ? 26 : total < 100 ? 32 : total < 1000 ? 38 : 46\r\n return L.divIcon({\r\n className: '',\r\n iconSize: [lado, lado],\r\n html: anelHtml([...soma.values()], total.toLocaleString('pt-PT'), lado),\r\n })\r\n }\r\n\r\n const camada = agrupar && (L as any).markerClusterGroup\r\n ? (L as any).markerClusterGroup({\r\n chunkedLoading: true,\r\n maxClusterRadius: 50,\r\n showCoverageOnHover: false,\r\n // Sem isto, marcadores na MESMA coordenada nunca se separam por muito\r\n // zoom que se faça, e os de baixo ficam inalcançáveis.\r\n spiderfyOnMaxZoom: true,\r\n ...(forma === 'anel' || fatias ? { iconCreateFunction: iconeGrupo } : {}),\r\n })\r\n : L.layerGroup()\r\n\r\n for (const p of pontos) {\r\n if (!Number.isFinite(p.lat) || !Number.isFinite(p.lng)) continue\r\n const estimado = aproximado?.(p) ?? false\r\n\r\n if (forma === 'anel') {\r\n const composicao = fatias?.(p) ?? [{ cor: cor?.(p) ?? COR_OMISSAO, n: 1 }]\r\n // Diâmetro: `raio` continua a ser o raio, para o `raio` dos outros\r\n // modos querer dizer a mesma coisa aqui.\r\n const lado = Math.round((raio?.(p) ?? 18) * 2)\r\n const marcadorAnel = L.marker([p.lat, p.lng], {\r\n icon: L.divIcon({\r\n className: '',\r\n iconSize: [lado, lado],\r\n iconAnchor: [lado / 2, lado / 2],\r\n popupAnchor: [0, -lado / 2],\r\n html: anelHtml(composicao, rotulo?.(p) ?? '', lado, selo?.(p), contorno?.(p)),\r\n }),\r\n })\r\n const htmlAnel = balao?.(p)\r\n if (htmlAnel) marcadorAnel.bindPopup(htmlAnel)\r\n if (onPontoClick) marcadorAnel.on('click', () => onPontoClick(p))\r\n ;(marcadorAnel.options as { ponto?: T }).ponto = p\r\n camada.addLayer(marcadorAnel)\r\n continue\r\n }\r\n\r\n const marcador = forma === 'pin'\r\n ? L.marker([p.lat, p.lng], {\r\n icon: L.divIcon({\r\n className: '',\r\n // A ponta do pin é que assenta na coordenada, não o centro do\r\n // ícone — daí a âncora no fundo, a meio da largura.\r\n iconSize: [TAMANHO_PIN, TAMANHO_PIN],\r\n iconAnchor: [TAMANHO_PIN / 2, TAMANHO_PIN],\r\n popupAnchor: [0, -TAMANHO_PIN + 4],\r\n html: pinSvg(cor?.(p) ?? COR_OMISSAO, estimado),\r\n }),\r\n })\r\n : L.circleMarker([p.lat, p.lng], {\r\n radius: raio?.(p) ?? 6,\r\n color: cor?.(p) ?? COR_OMISSAO,\r\n weight: estimado ? 1 : 2,\r\n // Tracejado e mais transparente: a posição é estimada, e o mapa não\r\n // deve sugerir uma precisão que não tem.\r\n dashArray: estimado ? '2,3' : undefined,\r\n fillOpacity: estimado ? 0.25 : 0.75,\r\n fillColor: cor?.(p) ?? COR_OMISSAO,\r\n })\r\n ;(marcador.options as { ponto?: T }).ponto = p\r\n const html = balao?.(p)\r\n if (html) marcador.bindPopup(html)\r\n if (onPontoClick) marcador.on('click', () => onPontoClick(p))\r\n camada.addLayer(marcador)\r\n\r\n const texto = rotulo?.(p)\r\n if (texto) {\r\n // `interactive: false` para o rótulo não roubar o clique ao círculo\r\n // que está por baixo — senão clicar no número não faz nada.\r\n camada.addLayer(\r\n L.marker([p.lat, p.lng], {\r\n interactive: false,\r\n icon: L.divIcon({\r\n className: '',\r\n iconSize: [0, 0],\r\n html:\r\n `<div style=\"transform:translate(-50%,-50%);white-space:nowrap;font:700 11px/1 system-ui,sans-serif;` +\r\n `color:#fff;text-shadow:0 1px 2px rgba(0,0,0,.7);pointer-events:none\">${texto}</div>`,\r\n }),\r\n })\r\n )\r\n }\r\n }\r\n\r\n camada.addTo(mapa)\r\n camadaRef.current = camada\r\n\r\n if (pontos.length) {\r\n const limites = L.latLngBounds(pontos.map((p) => [p.lat, p.lng]))\r\n limitesRef.current = limites.isValid() ? limites : null\r\n /*\r\n Pontos novos são um conjunto novo: vale a pena voltar a enquadrar,\r\n mesmo que o utilizador já tenha mexido — senão um filtro que reduz a\r\n 3 pontos deixava o mapa onde estava, aparentemente vazio.\r\n\r\n Mas só quando o CONJUNTO muda. Um re-render que apenas trocou a\r\n identidade de uma função de aspecto não é um conjunto novo, e tratá-lo\r\n como tal desfazia o zoom que a pessoa tinha acabado de dar.\r\n */\r\n if (limitesRef.current && !centro && chaveEnquadradaRef.current !== chavePontos) {\r\n chaveEnquadradaRef.current = chavePontos\r\n mexidoRef.current = false\r\n enquadrar(mapa, limitesRef.current)\r\n }\r\n }\r\n }, [pronto, chavePontos, agrupar, rotulo, forma, fatias, contorno])\r\n\r\n // Dessaturar o fundo? Só no tema suave, e nunca num satélite.\r\n const suavizar = tema === 'suave' && !fundos?.find((f) => f.id === fundo)?.semFiltro\r\n\r\n return (\r\n /*\r\n `overflow-hidden` e `isolate` não são decoração.\r\n\r\n O CORTE: os painéis do Leaflet são absolutos e deslocados por\r\n transformações. Se o mapa ficar com uma posição interna inconsistente —\r\n ao trocar de fundo, por exemplo — os marcadores pintam-se por cima do\r\n resto da página. Aconteceu. O corte garante que o pior caso é um mapa\r\n vazio, não a página desfeita.\r\n\r\n O ISOLAMENTO: o Leaflet dá z-index 1000 aos seus controlos e 400 aos\r\n painéis. `relative` sozinho NÃO cria contexto de empilhamento — só o cria\r\n com um `z-index` — por isso esses valores subiam até à raiz da página e\r\n competiam de igual para igual com tudo o resto. Um modal a z-50 ficava por\r\n baixo do mapa: abria-se uma ordem e o mapa pintava-se por cima da ficha.\r\n\r\n `isolate` fecha-os cá dentro. O mapa passa a valer como um elemento só na\r\n ordem de empilhamento da página, e deixa de haver maneira de uma peça\r\n interna dele passar à frente de um modal, de um menu ou de um tooltip.\r\n */\r\n <div\r\n className={`relative isolate overflow-hidden ${suavizar ? 'mapa-suave' : ''} ${className ?? ''}`}\r\n style={{ height: altura }}\r\n >\r\n {/* O filtro aplica-se SÓ ao painel dos tiles: os marcadores vivem em\r\n painéis acima e mantêm a cor. */}\r\n {suavizar && (\r\n <style>{`.mapa-suave .leaflet-tile-pane{filter:grayscale(.85) brightness(1.06) contrast(.95)}`}</style>\r\n )}\r\n {/*\r\n O contentor do Leaflet NÃO leva `className` do React.\r\n\r\n O Leaflet escreve as classes dele neste mesmo elemento\r\n (`leaflet-container`, `leaflet-grab`, `leaflet-fade-anim`…). O React\r\n controla o atributo `className` inteiro: bastava a condição mudar — ao\r\n trocar para um fundo de satélite, que dispensa a dessaturação — para\r\n ele reescrever o atributo e varrer as classes do Leaflet.\r\n\r\n Sem `leaflet-container`, os painéis perdem o posicionamento e o mapa\r\n fica branco com os marcadores por cima. E não voltava: ao trocar de\r\n novo, o React só reescrevia outra vez.\r\n\r\n A classe do filtro vive no invólucro, que é do React e mais ninguém\r\n lhe toca.\r\n */}\r\n <div ref={divRef} style={{ height: '100%', width: '100%' }} aria-label=\"Mapa\" />\r\n\r\n {pronto && !pontos.length && (\r\n <div className=\"absolute inset-0 flex items-center justify-center text-sm text-slate-500 pointer-events-none\">\r\n {txt.semPontos}\r\n </div>\r\n )}\r\n\r\n {!!fundos?.length && (\r\n <div className=\"absolute top-2 left-12 z-[400] bg-white/90 backdrop-blur-sm shadow-sm rounded flex text-[11px] overflow-hidden\">\r\n {fundos.map((f) => (\r\n <button\r\n key={f.id}\r\n onClick={() => setFundo(f.id)}\r\n className={`px-1.5 py-0.5 ${\r\n fundo === f.id ? 'bg-proef-navy text-white font-semibold' : 'text-slate-600 hover:bg-slate-100'\r\n }`}\r\n >\r\n {f.rotulo}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Compacta e encostada: a legenda explica o mapa, não o tapa. */}\r\n {legenda && (\r\n <div className=\"absolute bottom-2 left-2 z-[400] bg-white/90 backdrop-blur-sm rounded shadow-sm px-2 py-1 text-[11px] leading-tight\">\r\n {legenda}\r\n </div>\r\n )}\r\n\r\n {/*\r\n O aviso de truncagem fecha-se.\r\n\r\n Diz uma coisa importante na primeira vez — que o mapa não está a\r\n mostrar tudo — e nada de novo das vezes seguintes. Enquanto não se\r\n podia fechar, tapava o canto do mapa durante toda a sessão.\r\n\r\n Volta a aparecer quando o número muda: aí é um aviso diferente, sobre\r\n um conjunto diferente.\r\n */}\r\n {!!truncadoEm && txt.truncado && avisoFechadoEm !== truncadoEm && (\r\n <div className=\"absolute top-3 right-3 z-[400] flex items-start gap-2 bg-amber-50 border border-amber-300 text-amber-900 shadow rounded-lg px-2.5 py-1 text-[11px] max-w-[22rem]\">\r\n <span>{txt.truncado.replace('{n}', String(truncadoEm))}</span>\r\n <button\r\n onClick={() => setAvisoFechadoEm(truncadoEm)}\r\n aria-label={txt.fecharAviso ?? 'Fechar'}\r\n title={txt.fecharAviso ?? 'Fechar'}\r\n className=\"text-amber-700 hover:text-amber-900 leading-none font-bold\"\r\n >\r\n ×\r\n </button>\r\n </div>\r\n )}\r\n </div>\r\n )\r\n}\r\n"],"names":[],"mappings":"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"}