@terraware/web-components 5.0.27-rc.0 → 5.0.27

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 (295) hide show
  1. package/components/AntSwitch/index.js +22 -19
  2. package/components/Autocomplete/Autocomplete.js +130 -106
  3. package/components/Badge/index.js +29 -28
  4. package/components/BusySpinner/index.js +45 -40
  5. package/components/Button/Button.js +47 -41
  6. package/components/Checkbox.js +63 -64
  7. package/components/Confirm/index.js +83 -74
  8. package/components/DatePicker/DatePicker.js +141 -138
  9. package/components/DialogBox/DialogBox.js +118 -111
  10. package/components/Divisor.js +18 -18
  11. package/components/Dropdown.js +94 -66
  12. package/components/EditableTable/index.js +271 -211
  13. package/components/ErrorBox/ErrorBox.js +49 -47
  14. package/components/FileChooser/index.js +135 -117
  15. package/components/FormBottomBar/index.js +84 -75
  16. package/components/Icon/Icon.js +20 -12
  17. package/components/Icon/icons/index.js +256 -256
  18. package/components/IconTooltip/index.js +60 -49
  19. package/components/Map/MapBox.js +452 -545
  20. package/components/Map/MapContainer.js +29 -25
  21. package/components/Map/MapDateSliderControl.js +64 -64
  22. package/components/Map/MapDrawer.js +47 -41
  23. package/components/Map/MapLegend.js +172 -176
  24. package/components/Map/MapViewStyleControl.js +63 -59
  25. package/components/Map/ReactMapboxWrapper.js +2 -3
  26. package/components/Map/index.js +180 -161
  27. package/components/Map/types.js +17 -12
  28. package/components/Map/useMaintainLayerOrder.js +26 -16
  29. package/components/Markdown/index.js +26 -25
  30. package/components/Message/Message.js +76 -73
  31. package/components/MultiSelect/index.js +124 -112
  32. package/components/Navbar/NavFooter.js +13 -9
  33. package/components/Navbar/NavItem.js +76 -70
  34. package/components/Navbar/NavSection.js +19 -17
  35. package/components/Navbar/Navbar.js +46 -39
  36. package/components/Navbar/SubNavbar.js +13 -9
  37. package/components/Note.js +22 -18
  38. package/components/OverlayModal/OverlayModal.js +63 -56
  39. package/components/PageForm/index.js +41 -33
  40. package/components/PhotoChooser/index.js +173 -165
  41. package/components/PhotosCarousel/PhotoSlide.js +35 -32
  42. package/components/PhotosCarousel/index.js +85 -80
  43. package/components/PhotosCarousel/usePhotosCarousel.js +76 -69
  44. package/components/Pill/index.js +45 -41
  45. package/components/PillList/index.js +24 -17
  46. package/components/PlacementWrapper/index.js +59 -38
  47. package/components/PopoverMenu/Popover.js +85 -68
  48. package/components/PopoverMenu/index.js +56 -51
  49. package/components/PopoverMultiSelect/index.js +59 -52
  50. package/components/ProgressCircle/ProgressCircle.js +32 -28
  51. package/components/RadioButton.js +19 -17
  52. package/components/Select/Select.js +15 -13
  53. package/components/Select/SelectT.js +250 -235
  54. package/components/Separator/index.js +17 -14
  55. package/components/Size.js +1 -0
  56. package/components/Slider/index.js +56 -43
  57. package/components/SummaryBox.js +72 -70
  58. package/components/Tabs/index.js +135 -133
  59. package/components/TextTruncated/index.js +130 -117
  60. package/components/Textfield/Textfield.js +190 -158
  61. package/components/Textfield/TruncatedTextArea.js +84 -70
  62. package/components/TimelineSlider/TimelineMarker.js +30 -25
  63. package/components/TimelineSlider/TimelineRail.js +11 -8
  64. package/components/TimelineSlider/index.js +66 -64
  65. package/components/TimelineSliderV2/ClusterBadge.js +29 -25
  66. package/components/TimelineSliderV2/TimelineDot.js +35 -31
  67. package/components/TimelineSliderV2/TimelineRail.js +11 -8
  68. package/components/TimelineSliderV2/index.js +103 -121
  69. package/components/TimelineSliderV2/layout.js +147 -124
  70. package/components/TimelineSliderV2/types.js +1 -0
  71. package/components/Tooltip/Tooltip.js +56 -47
  72. package/components/ViewPhotosDialog/index.js +35 -28
  73. package/components/VirtualWalkthrough/Annotation.js +207 -163
  74. package/components/VirtualWalkthrough/AnnotationEditPane.js +184 -198
  75. package/components/VirtualWalkthrough/AnnotationPanel.js +199 -187
  76. package/components/VirtualWalkthrough/Application.js +34 -31
  77. package/components/VirtualWalkthrough/AutoRotator.js +223 -85
  78. package/components/VirtualWalkthrough/BlockingSpinner.js +28 -26
  79. package/components/VirtualWalkthrough/BoundaryRing.js +34 -30
  80. package/components/VirtualWalkthrough/BoundaryWall.js +36 -32
  81. package/components/VirtualWalkthrough/CameraInfo.js +89 -100
  82. package/components/VirtualWalkthrough/ControlsInfoPane.js +195 -254
  83. package/components/VirtualWalkthrough/GradientSky.js +73 -72
  84. package/components/VirtualWalkthrough/SplatControls.js +221 -209
  85. package/components/VirtualWalkthrough/SplatCrop.js +20 -21
  86. package/components/VirtualWalkthrough/SplatFadeCrop.js +20 -21
  87. package/components/VirtualWalkthrough/SplatModel.js +85 -65
  88. package/components/VirtualWalkthrough/SplatRevealRain.js +46 -41
  89. package/components/VirtualWalkthrough/TfAnnotationManager.js +379 -197
  90. package/components/VirtualWalkthrough/TfXrNavigation.js +162 -73
  91. package/components/VirtualWalkthrough/VirtualWalkthroughViewer.js +431 -438
  92. package/components/VirtualWalkthrough/VrAnnotationPanel.js +22 -18
  93. package/components/VirtualWalkthrough/XrAnnotationInteraction.js +17 -14
  94. package/components/VirtualWalkthrough/XrExitButton.js +17 -14
  95. package/components/VirtualWalkthrough/XrGazeDwell.js +17 -14
  96. package/components/VirtualWalkthrough/XrPointerRay.js +17 -14
  97. package/components/VirtualWalkthrough/XrStartPose.js +121 -67
  98. package/components/VirtualWalkthrough/boundary-ring.js +117 -87
  99. package/components/VirtualWalkthrough/boundary-wall.js +258 -175
  100. package/components/VirtualWalkthrough/camera-adoption.js +64 -18
  101. package/components/VirtualWalkthrough/groundPlane.js +47 -32
  102. package/components/VirtualWalkthrough/gsplat-fade-crop-effect.js +35 -35
  103. package/components/VirtualWalkthrough/splatFormat.js +47 -13
  104. package/components/VirtualWalkthrough/useAdoptedCamera.js +44 -23
  105. package/components/VirtualWalkthrough/useRestartOnVr.js +37 -26
  106. package/components/VirtualWalkthrough/useXrRenderTuning.js +54 -33
  107. package/components/VirtualWalkthrough/vr-annotation-panel-layout.js +99 -67
  108. package/components/VirtualWalkthrough/vr-annotation-panel.js +433 -403
  109. package/components/VirtualWalkthrough/vr-annotation-scroll.js +28 -10
  110. package/components/VirtualWalkthrough/walkthrough-camera.js +329 -204
  111. package/components/VirtualWalkthrough/xr-annotation-candidate-buffer.js +80 -39
  112. package/components/VirtualWalkthrough/xr-annotation-candidates.js +18 -6
  113. package/components/VirtualWalkthrough/xr-annotation-interaction.js +56 -31
  114. package/components/VirtualWalkthrough/xr-annotation-targeting.js +38 -22
  115. package/components/VirtualWalkthrough/xr-button-arming.js +17 -7
  116. package/components/VirtualWalkthrough/xr-button-hold.js +36 -22
  117. package/components/VirtualWalkthrough/xr-exit-button-mask.js +36 -22
  118. package/components/VirtualWalkthrough/xr-exit-button.js +207 -148
  119. package/components/VirtualWalkthrough/xr-face-buttons.js +29 -19
  120. package/components/VirtualWalkthrough/xr-gaze-dwell-state.js +34 -23
  121. package/components/VirtualWalkthrough/xr-gaze-dwell.js +144 -107
  122. package/components/VirtualWalkthrough/xr-interactive-ui.js +24 -12
  123. package/components/VirtualWalkthrough/xr-pointer-ray.js +20 -13
  124. package/components/VirtualWalkthrough/xr-progress-pie-material.js +88 -117
  125. package/components/VirtualWalkthrough/xr-progress-pie.js +10 -1
  126. package/components/VirtualWalkthrough/xr-ray-quad.js +30 -16
  127. package/components/VirtualWalkthrough/xr-render-tuning.js +48 -17
  128. package/components/VirtualWalkthrough/xr-scene-bounds.js +37 -21
  129. package/components/VirtualWalkthrough/xr-start-pose.js +73 -27
  130. package/components/VirtualWalkthrough/xr-teleport-gesture.js +42 -16
  131. package/components/svg/BlobbyGrayIconImage.js +39 -41
  132. package/components/svg/BlobbyGrayIconImport.js +39 -41
  133. package/components/svg/BlobbyGrayIconUploadToTheCloud.js +39 -41
  134. package/components/svg/BlobbyIconCloudChecked.js +164 -202
  135. package/components/svg/BlobbyIconExportOrUploadPhoto.js +164 -202
  136. package/components/svg/BlobbyIconFolder.js +164 -202
  137. package/components/svg/BlobbyIconGraphReport.js +164 -202
  138. package/components/svg/BlobbyIconHappy.js +164 -202
  139. package/components/svg/BlobbyIconHeartMonitor.js +164 -202
  140. package/components/svg/BlobbyIconLeaf.js +164 -202
  141. package/components/svg/BlobbyIconLibrary.js +164 -202
  142. package/components/svg/BlobbyIconNursery.js +166 -204
  143. package/components/svg/BlobbyIconOrganization.js +164 -202
  144. package/components/svg/BlobbyIconParchment.js +164 -202
  145. package/components/svg/BlobbyIconPeople.js +164 -202
  146. package/components/svg/BlobbyIconSeedBank.js +164 -202
  147. package/components/svg/BlobbyIconSeedling.js +164 -202
  148. package/components/svg/BlobbyIconSeeds.js +164 -202
  149. package/components/svg/BlobbyIconSite.js +167 -206
  150. package/components/svg/BlobbyIconSparkles.js +164 -202
  151. package/components/svg/BlobbyIconWrench.js +164 -202
  152. package/components/svg/Bug.js +21 -19
  153. package/components/svg/Calendar.js +21 -19
  154. package/components/svg/CaretDown.js +21 -19
  155. package/components/svg/CaretLeft.js +21 -19
  156. package/components/svg/CaretRight.js +21 -19
  157. package/components/svg/CaretUp.js +21 -19
  158. package/components/svg/ChevronDown.js +21 -19
  159. package/components/svg/ChevronUp.js +21 -19
  160. package/components/svg/Close.js +21 -19
  161. package/components/svg/Critical.js +21 -19
  162. package/components/svg/Edit.js +164 -202
  163. package/components/svg/Error.js +21 -19
  164. package/components/svg/Filter.js +21 -19
  165. package/components/svg/Folder.js +21 -19
  166. package/components/svg/Help.js +21 -19
  167. package/components/svg/Home.js +21 -19
  168. package/components/svg/IconAdd.js +21 -19
  169. package/components/svg/IconArrowRight.js +23 -21
  170. package/components/svg/IconBusinessNetwork.js +21 -19
  171. package/components/svg/IconCalendar.js +21 -19
  172. package/components/svg/IconCancel.js +21 -19
  173. package/components/svg/IconChargingBattery.js +21 -19
  174. package/components/svg/IconChecklist.js +23 -21
  175. package/components/svg/IconCheckmark.js +21 -19
  176. package/components/svg/IconCoinInHand.js +21 -19
  177. package/components/svg/IconColumns.js +21 -19
  178. package/components/svg/IconComment.js +22 -20
  179. package/components/svg/IconDashboard.js +21 -19
  180. package/components/svg/IconDataMigration.js +21 -19
  181. package/components/svg/IconDocument.js +23 -21
  182. package/components/svg/IconDownloadFromTheCloud.js +23 -21
  183. package/components/svg/IconEdit.js +23 -21
  184. package/components/svg/IconExpand.js +23 -21
  185. package/components/svg/IconExport.js +21 -19
  186. package/components/svg/IconExternalLink.js +21 -19
  187. package/components/svg/IconEye.js +21 -19
  188. package/components/svg/IconEyeOff.js +21 -19
  189. package/components/svg/IconFile.js +21 -19
  190. package/components/svg/IconFolder.js +21 -19
  191. package/components/svg/IconFullScreen.js +22 -20
  192. package/components/svg/IconFutures.js +21 -19
  193. package/components/svg/IconGraphReport.js +21 -19
  194. package/components/svg/IconGrid.js +21 -19
  195. package/components/svg/IconHeartMonitor.js +21 -19
  196. package/components/svg/IconHelp.js +23 -21
  197. package/components/svg/IconHistory.js +21 -19
  198. package/components/svg/IconImport.js +21 -19
  199. package/components/svg/IconIndex.js +21 -19
  200. package/components/svg/IconLayers.js +21 -19
  201. package/components/svg/IconLibrary.js +22 -20
  202. package/components/svg/IconList.js +21 -19
  203. package/components/svg/IconLivePlant.js +21 -19
  204. package/components/svg/IconLocations.js +21 -19
  205. package/components/svg/IconMail.js +21 -19
  206. package/components/svg/IconManager.js +21 -19
  207. package/components/svg/IconMap.js +21 -19
  208. package/components/svg/IconMarker.js +21 -19
  209. package/components/svg/IconMenu.js +21 -19
  210. package/components/svg/IconMenuHorizontal.js +21 -19
  211. package/components/svg/IconModule.js +21 -19
  212. package/components/svg/IconMyLocation.js +21 -19
  213. package/components/svg/IconNote.js +23 -21
  214. package/components/svg/IconNursery.js +23 -21
  215. package/components/svg/IconOrg.js +21 -19
  216. package/components/svg/IconParchment.js +21 -19
  217. package/components/svg/IconPhoto.js +21 -19
  218. package/components/svg/IconPlantsFilled.js +21 -19
  219. package/components/svg/IconRedo.js +21 -19
  220. package/components/svg/IconRestorationSite.js +21 -19
  221. package/components/svg/IconSeedBank.js +21 -19
  222. package/components/svg/IconSeedling.js +21 -19
  223. package/components/svg/IconSettings.js +21 -19
  224. package/components/svg/IconSlice.js +21 -19
  225. package/components/svg/IconSubmit.js +21 -19
  226. package/components/svg/IconSubtract.js +23 -21
  227. package/components/svg/IconSynced.js +21 -19
  228. package/components/svg/IconTrashCan.js +21 -19
  229. package/components/svg/IconTreasureMap.js +21 -19
  230. package/components/svg/IconUnavailable.js +21 -19
  231. package/components/svg/IconUndo.js +21 -19
  232. package/components/svg/IconVariable.js +21 -19
  233. package/components/svg/IconVideo.js +31 -30
  234. package/components/svg/IconWifi.js +21 -19
  235. package/components/svg/Info.js +21 -19
  236. package/components/svg/Key.js +21 -19
  237. package/components/svg/Leaf.js +21 -19
  238. package/components/svg/Lock.js +21 -19
  239. package/components/svg/Logo.js +43 -48
  240. package/components/svg/MenuVertical.js +21 -19
  241. package/components/svg/Notification.js +21 -19
  242. package/components/svg/Person.js +21 -19
  243. package/components/svg/Plus.js +21 -19
  244. package/components/svg/RestorationSite.js +21 -19
  245. package/components/svg/Search.js +21 -19
  246. package/components/svg/Seeds.js +21 -19
  247. package/components/svg/Site.js +21 -19
  248. package/components/svg/Sparkles.js +21 -19
  249. package/components/svg/Species.js +21 -19
  250. package/components/svg/Species2.js +164 -202
  251. package/components/svg/Spinner.js +48 -54
  252. package/components/svg/Star.js +21 -19
  253. package/components/svg/Success.js +21 -19
  254. package/components/svg/SuccessFilled.js +21 -19
  255. package/components/svg/TerrawareLogoDesktop.js +49 -55
  256. package/components/svg/TerrawareLogoMobile.js +26 -25
  257. package/components/svg/Touchscreen.js +21 -19
  258. package/components/svg/UploadCloud.js +164 -202
  259. package/components/svg/Warning.js +21 -19
  260. package/components/svg/WelcomeClipboard.js +133 -156
  261. package/components/svg/index.js +129 -129
  262. package/components/table/EnhancedTableToolbar.js +74 -68
  263. package/components/table/EnhancedTableToolbarV2.js +41 -31
  264. package/components/table/TableCellRenderer.js +231 -196
  265. package/components/table/TableHeader.js +73 -71
  266. package/components/table/TableHeaderItem.js +102 -97
  267. package/components/table/density.js +19 -18
  268. package/components/table/index.js +369 -350
  269. package/components/table/sort.js +52 -27
  270. package/components/table/types.js +1 -0
  271. package/components/types/index.js +1 -0
  272. package/hooks/cameraEntityContext.js +13 -2
  273. package/hooks/useBoolean.js +13 -17
  274. package/hooks/useCameraPosition.js +56 -56
  275. package/hooks/useDevicePerformance.js +17 -17
  276. package/hooks/useXr.js +87 -85
  277. package/index.js +58 -58
  278. package/package.json +1 -1
  279. package/setupTests.js +4 -0
  280. package/strings/export.js +170 -111
  281. package/strings/index.js +54 -25
  282. package/strings/locales.js +41 -21
  283. package/strings/strings-en.js +51 -49
  284. package/strings/strings-es.js +51 -49
  285. package/strings/strings-fr.js +51 -49
  286. package/strings/strings-gx.js +51 -49
  287. package/style-dictionary-dist/TerrawareTheme.js +186 -186
  288. package/theme.js +76 -74
  289. package/utils/color.js +15 -8
  290. package/utils/date.js +108 -42
  291. package/utils/index.js +4 -4
  292. package/utils/preventDefaultEvent.js +3 -3
  293. package/utils/text.js +11 -11
  294. package/utils/useDeviceInfo.js +79 -42
  295. package/virtualWalkthrough.js +23 -23
@@ -1,554 +1,461 @@
1
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
- import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
- import { FullscreenControl, Layer, Marker, NavigationControl, Source } from "react-map-gl/mapbox";
4
- import { Box, useTheme } from "@mui/material";
5
- import "mapbox-gl/dist/mapbox-gl.css";
6
- import { useDeviceInfo } from "../../utils/index.js";
7
- import Icon from "../Icon/Icon.js";
8
- import MapViewStyleControl from "./MapViewStyleControl.js";
9
- import ReactMapboxWrapper from "./ReactMapboxWrapper.js";
10
- import { stylesUrl } from "./types.js";
11
- import { useMaintainLayerOrder } from "./useMaintainLayerOrder.js";
12
- const MapBox = (props)=>{
13
- const { clusterRadius, containerId, controlBottomLeft, controlTopRight, cursorInteract, cursorMap, disableDoubleClickZoom, disableZoom, drawerOpen, layers: featureGroups, hideFullScreenControl, hideMapViewStyleControl, hideZoomControl, highlightGroups, initialViewState, mapId, mapImageUrls, mapViewStyle, markerGroups, onClickCanvas, setMapViewStyle, token } = props;
14
- const theme = useTheme();
15
- const mapRef = useRef(null);
16
- const { isDesktop } = useDeviceInfo();
17
- const [cursor, setCursor] = useState('auto');
18
- const [hoverFeatureId, setHoverFeatureId] = useState();
19
- const [zoom, setZoom] = useState();
20
- const loadImages = useCallback((map)=>{
21
- mapImageUrls?.forEach((url)=>{
22
- if (!map.hasImage(url)) map.loadImage(url, (error, image)=>{
23
- if (image) map.addImage(url, image, {
24
- sdf: true
25
- });
1
+ import { useRef, useState, useCallback, useMemo, useEffect } from 'react';
2
+ import ReactMapbox, { Layer, Marker, FullscreenControl, NavigationControl, Source } from 'react-map-gl/mapbox';
3
+ import { useTheme, Box } from '@mui/material';
4
+ import 'mapbox-gl/dist/mapbox-gl.css';
5
+ import 'lodash';
6
+ import 'luxon';
7
+ import useDeviceInfo from '../../utils/useDeviceInfo.js';
8
+ import Icon from '../Icon/Icon.js';
9
+ import MapViewStyleControl from './MapViewStyleControl.js';
10
+ import { stylesUrl } from './types.js';
11
+ import { useMaintainLayerOrder } from './useMaintainLayerOrder.js';
12
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
13
+
14
+ const MapBox = props => {
15
+ const {
16
+ clusterRadius,
17
+ containerId,
18
+ controlBottomLeft,
19
+ controlTopRight,
20
+ cursorInteract,
21
+ cursorMap,
22
+ disableDoubleClickZoom,
23
+ disableZoom,
24
+ drawerOpen,
25
+ layers: featureGroups,
26
+ hideFullScreenControl,
27
+ hideMapViewStyleControl,
28
+ hideZoomControl,
29
+ highlightGroups,
30
+ initialViewState,
31
+ mapId,
32
+ mapImageUrls,
33
+ mapViewStyle,
34
+ markerGroups,
35
+ onClickCanvas,
36
+ setMapViewStyle,
37
+ token
38
+ } = props;
39
+ const theme = useTheme();
40
+ const mapRef = useRef(null);
41
+ const {
42
+ isDesktop
43
+ } = useDeviceInfo();
44
+ const [cursor, setCursor] = useState('auto');
45
+ const [hoverFeatureId, setHoverFeatureId] = useState();
46
+ const [zoom, setZoom] = useState();
47
+ const loadImages = useCallback(map => {
48
+ mapImageUrls?.forEach(url => {
49
+ if (!map.hasImage(url)) {
50
+ map.loadImage(url, (error, image) => {
51
+ if (image) {
52
+ map.addImage(url, image, {
53
+ sdf: true
26
54
  });
55
+ }
27
56
  });
28
- }, [
29
- mapImageUrls
30
- ]);
31
- const mapRefCallback = useCallback((map)=>{
32
- if (null !== map) {
33
- mapRef.current = map;
34
- setZoom(map.getZoom());
35
- loadImages(map);
36
- }
37
- }, []);
38
- const onMove = useCallback((view)=>{
39
- setZoom(view.viewState.zoom);
40
- }, []);
41
- const clusterMarkers = useCallback((map, markers)=>{
42
- if (!map || map.getZoom() > 15) return markers.map((marker)=>[
43
- marker
44
- ]);
45
- const visited = new Set();
46
- const markerPixels = {};
47
- markers.forEach((marker)=>{
48
- markerPixels[marker.id] = map.project({
49
- lat: marker.latitude,
50
- lon: marker.longitude
51
- });
52
- });
53
- const clusters = [];
54
- markers.forEach((marker, idx)=>{
55
- if (!visited.has(marker.id)) {
56
- const cluster = [
57
- marker
58
- ];
59
- markers.slice(idx + 1).forEach((otherMarker)=>{
60
- if (!visited.has(otherMarker.id)) {
61
- const dx = markerPixels[marker.id].x - markerPixels[otherMarker.id].x;
62
- const dy = markerPixels[marker.id].y - markerPixels[otherMarker.id].y;
63
- const dist = Math.sqrt(dx * dx + dy * dy);
64
- if (dist <= (clusterRadius ?? 40)) {
65
- cluster.push(otherMarker);
66
- visited.add(otherMarker.id);
67
- }
68
- }
69
- });
70
- clusters.push(cluster);
57
+ }
58
+ });
59
+ }, [mapImageUrls]);
60
+ const mapRefCallback = useCallback(map => {
61
+ if (map !== null) {
62
+ mapRef.current = map;
63
+ setZoom(map.getZoom());
64
+ loadImages(map);
65
+ }
66
+ }, []);
67
+ const onMove = useCallback(view => {
68
+ setZoom(view.viewState.zoom);
69
+ }, []);
70
+ const clusterMarkers = useCallback((map, markers) => {
71
+ if (!map || map.getZoom() > 15) {
72
+ // Too zoomed in. Return all marker as is
73
+ return markers.map(marker => [marker]);
74
+ }
75
+ const visited = new Set();
76
+ const markerPixels = {};
77
+ markers.forEach(marker => {
78
+ markerPixels[marker.id] = map.project({
79
+ lat: marker.latitude,
80
+ lon: marker.longitude
81
+ });
82
+ });
83
+ const clusters = [];
84
+ markers.forEach((marker, idx) => {
85
+ if (!visited.has(marker.id)) {
86
+ const cluster = [marker];
87
+ markers.slice(idx + 1).forEach(otherMarker => {
88
+ if (!visited.has(otherMarker.id)) {
89
+ const dx = markerPixels[marker.id].x - markerPixels[otherMarker.id].x;
90
+ const dy = markerPixels[marker.id].y - markerPixels[otherMarker.id].y;
91
+ const dist = Math.sqrt(dx * dx + dy * dy);
92
+ if (dist <= (clusterRadius ?? 40)) {
93
+ cluster.push(otherMarker);
94
+ visited.add(otherMarker.id);
71
95
  }
96
+ }
72
97
  });
73
- return clusters;
74
- }, [
75
- clusterRadius
76
- ]);
77
- const interactiveLayerIds = useMemo(()=>featureGroups?.filter((group)=>group.features.some((feature)=>void 0 !== feature.onClick))?.map((group)=>group.layerId), [
78
- featureGroups
79
- ]);
80
- const geojson = useMemo(()=>{
81
- const features = featureGroups?.flatMap((group)=>group.features.map((feature)=>{
82
- const properties = {
83
- id: feature.featureId,
84
- clickable: void 0 !== feature.onClick,
85
- label: feature.label,
86
- layerFeatureId: `${group.layerId}/${feature.featureId}`,
87
- layerId: group.layerId,
88
- priority: feature.priority ?? 0,
89
- selected: feature.selected ?? false
90
- };
91
- return {
92
- type: 'Feature',
93
- geometry: feature.geometry,
94
- properties
95
- };
96
- }));
97
- return features ? {
98
- type: 'FeatureCollection',
99
- features
100
- } : void 0;
101
- }, [
102
- featureGroups
103
- ]);
104
- const { borderLayers, fillLayers, textLayers } = useMemo(()=>{
105
- const _borderLayers = featureGroups?.map((group)=>/*#__PURE__*/ jsx(Layer, {
106
- id: `${group.layerId}-border`,
107
- source: 'mapData',
108
- type: "line",
109
- paint: {
110
- 'line-color': group.style.borderColor,
111
- 'line-width': 2
112
- },
113
- filter: [
114
- '==',
115
- [
116
- 'get',
117
- 'layerId'
118
- ],
119
- group.layerId
120
- ]
121
- }, `${group.layerId}-border`));
122
- const _fillLayers = featureGroups?.map((group)=>{
123
- const opacity = Math.min(0.4, group.style.opacity ?? 0.2);
124
- const selectedOpacity = 2 * opacity;
125
- const hoverOpacity = 1.5 * opacity;
126
- const hoverAndSelectedOpacity = 2.5 * opacity;
127
- const groupFilter = [
128
- '==',
129
- [
130
- 'get',
131
- 'layerId'
132
- ],
133
- group.layerId
134
- ];
135
- const clickableFilter = [
136
- '==',
137
- [
138
- 'get',
139
- 'clickable'
140
- ],
141
- true
142
- ];
143
- const selectedFilter = [
144
- '==',
145
- [
146
- 'get',
147
- 'selected'
148
- ],
149
- true
150
- ];
151
- const notSelectedFilter = [
152
- '==',
153
- [
154
- 'get',
155
- 'selected'
156
- ],
157
- false
158
- ];
159
- const hoverFilter = [
160
- '==',
161
- [
162
- 'get',
163
- 'id'
164
- ],
165
- hoverFeatureId ?? null
166
- ];
167
- const notHoverFilter = [
168
- '!=',
169
- [
170
- 'get',
171
- 'id'
172
- ],
173
- hoverFeatureId ?? null
174
- ];
175
- return /*#__PURE__*/ jsxs(Fragment, {
176
- children: [
177
- /*#__PURE__*/ jsx(Layer, {
178
- id: group.layerId,
179
- source: 'mapData',
180
- type: 'fill',
181
- paint: {
182
- 'fill-opacity': 0
183
- },
184
- filter: [
185
- 'all',
186
- groupFilter,
187
- clickableFilter
188
- ]
189
- }, group.layerId),
190
- /*#__PURE__*/ jsx(Layer, {
191
- id: `${group.layerId}-unselected`,
192
- source: 'mapData',
193
- type: 'fill',
194
- paint: group.style.fillPatternUrl ? {
195
- 'fill-pattern': group.style.fillPatternUrl,
196
- 'fill-opacity': opacity
197
- } : {
198
- 'fill-color': group.style.fillColor,
199
- 'fill-opacity': opacity
200
- },
201
- filter: [
202
- 'all',
203
- groupFilter,
204
- notSelectedFilter,
205
- notHoverFilter
206
- ]
207
- }, `${group.layerId}-unselected`),
208
- /*#__PURE__*/ jsx(Layer, {
209
- id: `${group.layerId}-selected`,
210
- slot: 'bottom',
211
- source: 'mapData',
212
- type: 'fill',
213
- paint: group.style.fillPatternUrl ? {
214
- 'fill-pattern': group.style.fillPatternUrl,
215
- 'fill-opacity': selectedOpacity
216
- } : {
217
- 'fill-color': group.style.fillColor,
218
- 'fill-opacity': selectedOpacity
219
- },
220
- filter: [
221
- 'all',
222
- groupFilter,
223
- selectedFilter,
224
- notHoverFilter
225
- ]
226
- }, `${group.layerId}-selected`),
227
- /*#__PURE__*/ jsx(Layer, {
228
- id: `${group.layerId}-hover`,
229
- source: 'mapData',
230
- type: 'fill',
231
- paint: group.style.fillPatternUrl ? {
232
- 'fill-pattern': group.style.fillPatternUrl,
233
- 'fill-opacity': hoverOpacity
234
- } : {
235
- 'fill-color': group.style.fillColor,
236
- 'fill-opacity': hoverOpacity
237
- },
238
- filter: [
239
- 'all',
240
- groupFilter,
241
- hoverFilter,
242
- notSelectedFilter
243
- ]
244
- }, `${group.layerId}-hover`),
245
- /*#__PURE__*/ jsx(Layer, {
246
- id: `${group.layerId}-selected-hover`,
247
- source: 'mapData',
248
- type: 'fill',
249
- paint: group.style.fillPatternUrl ? {
250
- 'fill-pattern': group.style.fillPatternUrl,
251
- 'fill-opacity': hoverAndSelectedOpacity
252
- } : {
253
- 'fill-color': group.style.fillColor,
254
- 'fill-opacity': hoverAndSelectedOpacity
255
- },
256
- filter: [
257
- 'all',
258
- groupFilter,
259
- hoverFilter,
260
- selectedFilter
261
- ]
262
- }, `${group.layerId}-selected-hover`)
263
- ]
264
- });
265
- });
266
- const _textLayers = featureGroups?.map((group)=>{
267
- const groupFilter = [
268
- '==',
269
- [
270
- 'get',
271
- 'layerId'
272
- ],
273
- group.layerId
274
- ];
275
- const labelFilter = [
276
- 'has',
277
- 'label'
278
- ];
279
- return /*#__PURE__*/ jsx(Layer, {
280
- id: `${group.layerId}-label`,
281
- source: 'mapData',
282
- type: 'symbol',
283
- layout: {
284
- 'text-field': [
285
- 'get',
286
- 'label'
287
- ],
288
- 'text-size': 14,
289
- 'text-line-height': 20,
290
- 'text-font': [
291
- 'Open Sans Bold',
292
- 'Arial Unicode MS Regular'
293
- ],
294
- 'text-anchor': 'center',
295
- 'text-justify': 'center'
296
- },
297
- paint: {
298
- 'text-color': '#ffffff'
299
- },
300
- filter: [
301
- 'all',
302
- groupFilter,
303
- labelFilter
304
- ]
305
- }, `${group.layerId}-label`);
306
- });
98
+ clusters.push(cluster);
99
+ }
100
+ });
101
+ return clusters;
102
+ }, [clusterRadius]);
103
+
104
+ // Find all layers with at least some clickable elements
105
+ const interactiveLayerIds = useMemo(() => {
106
+ return featureGroups?.filter(group => group.features.some(feature => feature.onClick !== undefined))?.map(group => group.layerId);
107
+ }, [featureGroups]);
108
+ const geojson = useMemo(() => {
109
+ const features = featureGroups?.flatMap(group => {
110
+ return group.features.map(feature => {
111
+ const properties = {
112
+ id: feature.featureId,
113
+ clickable: feature.onClick !== undefined,
114
+ label: feature.label,
115
+ layerFeatureId: `${group.layerId}/${feature.featureId}`,
116
+ layerId: group.layerId,
117
+ priority: feature.priority ?? 0,
118
+ selected: feature.selected ?? false
119
+ };
307
120
  return {
308
- borderLayers: _borderLayers ?? [],
309
- fillLayers: _fillLayers ?? [],
310
- textLayers: _textLayers ?? []
121
+ type: 'Feature',
122
+ geometry: feature.geometry,
123
+ properties
311
124
  };
312
- }, [
313
- featureGroups,
314
- hoverFeatureId
315
- ]);
316
- const highlightLayers = useMemo(()=>highlightGroups?.flatMap((group)=>group.highlights.map((highlight, index)=>{
317
- const highlightFeatureIds = highlight.featureIds.map(({ layerId, featureId })=>`${layerId}/${featureId}`);
318
- return /*#__PURE__*/ jsx(Layer, {
319
- id: `highlight-${group.highlightId}-${index}`,
320
- source: 'mapData',
321
- type: 'fill',
322
- paint: highlight.style.fillPatternUrl ? {
323
- 'fill-pattern': highlight.style.fillPatternUrl,
324
- 'fill-opacity': highlight.style.opacity ?? 0.5
325
- } : {
326
- 'fill-color': highlight.style.fillColor,
327
- 'fill-opacity': highlight.style.opacity ?? 0.5
328
- },
329
- filter: [
330
- 'all',
331
- [
332
- 'has',
333
- 'layerFeatureId'
334
- ],
335
- [
336
- 'match',
337
- [
338
- 'get',
339
- 'layerFeatureId'
340
- ],
341
- highlightFeatureIds,
342
- true,
343
- false
344
- ]
345
- ]
346
- }, `highlight-${group.highlightId}-${index}`);
347
- })) ?? [], [
348
- highlightGroups
349
- ]);
350
- const markersComponents = useMemo(()=>markerGroups?.flatMap((markerGroup)=>{
351
- const clusteredMarkers = clusterMarkers(mapRef.current, markerGroup.markers);
352
- return clusteredMarkers.map((markers, i)=>{
353
- if (1 === markers.length) {
354
- const marker = markers[0];
355
- return /*#__PURE__*/ jsx(Marker, {
356
- className: "map-marker",
357
- longitude: marker.longitude,
358
- latitude: marker.latitude,
359
- anchor: "center",
360
- onClick: (event)=>{
361
- marker.onClick?.();
362
- event.originalEvent.stopPropagation();
363
- },
364
- style: {
365
- backgroundColor: marker.selected ? markerGroup.style.iconColor : theme.palette.TwClrBg
366
- },
367
- children: /*#__PURE__*/ jsx(Icon, {
368
- fillColor: marker.selected ? theme.palette.TwClrBg : markerGroup.style.iconColor,
369
- name: markerGroup.style.iconName,
370
- size: 'small'
371
- })
372
- }, `marker-${i}`);
373
- } else if (markers.length > 1) {
374
- const latSum = markers.reduce((sum, marker)=>sum + marker.latitude, 0);
375
- const lngSum = markers.reduce((sum, marker)=>sum + marker.longitude, 0);
376
- const latAvg = latSum / markers.length;
377
- const lngAvg = lngSum / markers.length;
378
- const selected = markers.some((marker)=>marker.selected);
379
- return /*#__PURE__*/ jsxs(Marker, {
380
- className: "map-marker map-marker--cluster",
381
- longitude: lngAvg,
382
- latitude: latAvg,
383
- anchor: "center",
384
- onClick: (event)=>{
385
- mapRef.current?.easeTo({
386
- center: {
387
- lat: latAvg,
388
- lon: lngAvg
389
- },
390
- zoom: (zoom ?? 10) + 1,
391
- duration: 500
392
- });
393
- event.originalEvent.stopPropagation();
394
- },
395
- style: {
396
- backgroundColor: selected ? markerGroup.style.iconColor : theme.palette.TwClrBg
397
- },
398
- children: [
399
- /*#__PURE__*/ jsx("p", {
400
- className: "count",
401
- children: markers.length
402
- }),
403
- /*#__PURE__*/ jsx(Icon, {
404
- fillColor: selected ? theme.palette.TwClrBg : markerGroup.style.iconColor,
405
- name: markerGroup.style.iconName,
406
- size: 'small'
407
- })
408
- ]
409
- }, `marker-${i}`);
410
- }
411
- });
412
- }), [
413
- markerGroups,
414
- theme,
415
- zoom
416
- ]);
417
- const onMouseMove = useCallback((event)=>{
418
- if (event.features && event.features.length) {
419
- const properties = event.features.map((feature)=>feature.properties).filter((featureProperties)=>featureProperties && void 0 !== featureProperties.id && void 0 !== featureProperties.priority && featureProperties.clickable);
420
- if (properties.length) {
421
- const topPriorityFeature = properties.reduce((top, current)=>current.priority > top.priority ? current : top, properties[0]);
422
- setHoverFeatureId(topPriorityFeature.id);
423
- return;
424
- }
425
- }
426
- setHoverFeatureId(void 0);
427
- }, []);
428
- useEffect(()=>{
429
- if (!mapRef.current) return;
430
- const observer = new ResizeObserver(()=>{
431
- mapRef.current?.resize();
432
- });
433
- observer.observe(mapRef.current.getContainer());
434
- return ()=>observer.disconnect();
435
- }, []);
436
- useEffect(()=>{
437
- if (!mapRef.current) return;
438
- mapRef.current.resize();
439
- }, [
440
- drawerOpen
441
- ]);
442
- const onMouseEnter = useCallback(()=>setCursor(cursorInteract ?? 'pointer'), [
443
- cursorInteract
444
- ]);
445
- const onMouseLeave = useCallback(()=>setCursor('auto'), []);
446
- const onMouseOver = useCallback(()=>setCursor(cursorMap ?? 'auto'), [
447
- cursorMap
448
- ]);
449
- const onMouseOut = useCallback(()=>setCursor('auto'), []);
450
- const onMapClick = useCallback((event)=>{
451
- if (featureGroups && event.features?.length) {
452
- const properties = event.features.map((feature)=>feature.properties).filter((featureProperties)=>featureProperties && void 0 !== featureProperties.id && void 0 !== featureProperties.priority && featureProperties.clickable);
453
- if (properties.length) {
454
- const topPriorityFeature = properties.reduce((top, current)=>current.priority > top.priority ? current : top, properties[0]);
455
- const clickedItem = featureGroups.flatMap((group)=>group.features).find((feature)=>feature.featureId === topPriorityFeature.id);
456
- if (clickedItem && clickedItem.onClick) return void clickedItem.onClick();
457
- }
458
- }
459
- if (void 0 !== onClickCanvas) onClickCanvas(event);
460
- }, [
461
- featureGroups,
462
- onClickCanvas
463
- ]);
464
- const orderedLayerIds = useMemo(()=>[
465
- ...fillLayers.map((layer)=>layer.props.id),
466
- ...highlightLayers.map((layer)=>layer.props.id),
467
- ...borderLayers.map((layer)=>layer.props.id),
468
- ...textLayers.map((layer)=>layer.props.id)
469
- ], [
470
- borderLayers,
471
- fillLayers,
472
- highlightLayers,
473
- textLayers
474
- ]);
475
- useMaintainLayerOrder(mapRef, orderedLayerIds);
476
- return /*#__PURE__*/ jsxs(ReactMapboxWrapper, {
477
- attributionControl: false,
478
- cursor: cursor,
479
- doubleClickZoom: !disableZoom && !disableDoubleClickZoom,
480
- interactiveLayerIds: interactiveLayerIds,
481
- initialViewState: initialViewState,
482
- mapboxAccessToken: token,
483
- mapStyle: stylesUrl[mapViewStyle],
484
- ref: mapRefCallback,
485
- scrollZoom: !disableZoom,
486
- style: {
487
- width: 'auto',
488
- height: isDesktop ? 'auto' : '80vh',
489
- flexGrow: isDesktop ? 1 : void 0
125
+ });
126
+ });
127
+ return features ? {
128
+ type: 'FeatureCollection',
129
+ features
130
+ } : undefined;
131
+ }, [featureGroups]);
132
+ const {
133
+ borderLayers,
134
+ fillLayers,
135
+ textLayers
136
+ } = useMemo(() => {
137
+ const _borderLayers = featureGroups?.map(group => {
138
+ return /*#__PURE__*/jsx(Layer, {
139
+ id: `${group.layerId}-border`,
140
+ source: 'mapData',
141
+ type: "line",
142
+ paint: {
143
+ 'line-color': group.style.borderColor,
144
+ 'line-width': 2
490
145
  },
491
- onClick: onMapClick,
492
- onMove: onMove,
493
- onMouseEnter: onMouseEnter,
494
- onMouseLeave: onMouseLeave,
495
- onMouseOver: onMouseOver,
496
- onMouseOut: onMouseOut,
497
- onMouseMove: onMouseMove,
498
- children: [
499
- isDesktop && !hideFullScreenControl && /*#__PURE__*/ jsx(FullscreenControl, {
500
- position: "top-left",
501
- containerId: containerId
502
- }),
503
- !hideZoomControl && /*#__PURE__*/ jsx(NavigationControl, {
504
- showCompass: false,
505
- style: {
506
- marginRight: theme.spacing(2),
507
- marginBottom: theme.spacing(2)
508
- },
509
- position: "bottom-right"
510
- }),
511
- !hideMapViewStyleControl && /*#__PURE__*/ jsx(MapViewStyleControl, {
512
- containerId: containerId,
513
- mapViewStyle: mapViewStyle,
514
- setMapViewStyle: setMapViewStyle
515
- }),
516
- controlTopRight && /*#__PURE__*/ jsx(Box, {
517
- sx: {
518
- height: 'max-content',
519
- position: 'absolute',
520
- right: theme.spacing(2),
521
- top: theme.spacing(2),
522
- width: 'max-content',
523
- zIndex: 1000
524
- },
525
- children: controlTopRight
526
- }),
527
- controlBottomLeft && /*#__PURE__*/ jsx(Box, {
528
- style: {
529
- height: 'max-content',
530
- position: 'absolute',
531
- left: theme.spacing(2),
532
- bottom: theme.spacing(4),
533
- width: 'max-content',
534
- zIndex: 1000
146
+ filter: ['==', ['get', 'layerId'], group.layerId]
147
+ }, `${group.layerId}-border`);
148
+ });
149
+ const _fillLayers = featureGroups?.map(group => {
150
+ const opacity = Math.min(0.4, group.style.opacity ?? 0.2);
151
+ const selectedOpacity = opacity * 2;
152
+ const hoverOpacity = opacity * 1.5;
153
+ const hoverAndSelectedOpacity = opacity * 2.5;
154
+ const groupFilter = ['==', ['get', 'layerId'], group.layerId];
155
+ const clickableFilter = ['==', ['get', 'clickable'], true];
156
+ const selectedFilter = ['==', ['get', 'selected'], true];
157
+ const notSelectedFilter = ['==', ['get', 'selected'], false];
158
+ const hoverFilter = ['==', ['get', 'id'], hoverFeatureId ?? null];
159
+ const notHoverFilter = ['!=', ['get', 'id'], hoverFeatureId ?? null];
160
+ return /*#__PURE__*/jsxs(Fragment, {
161
+ children: [/*#__PURE__*/jsx(Layer, {
162
+ id: group.layerId,
163
+ source: 'mapData',
164
+ type: 'fill',
165
+ paint: {
166
+ 'fill-opacity': 0
167
+ },
168
+ filter: ['all', groupFilter, clickableFilter]
169
+ }, group.layerId), /*#__PURE__*/jsx(Layer, {
170
+ id: `${group.layerId}-unselected`,
171
+ source: 'mapData',
172
+ type: 'fill',
173
+ paint: group.style.fillPatternUrl ? {
174
+ 'fill-pattern': group.style.fillPatternUrl,
175
+ 'fill-opacity': opacity
176
+ } : {
177
+ 'fill-color': group.style.fillColor,
178
+ 'fill-opacity': opacity
179
+ },
180
+ filter: ['all', groupFilter, notSelectedFilter, notHoverFilter]
181
+ }, `${group.layerId}-unselected`), /*#__PURE__*/jsx(Layer, {
182
+ id: `${group.layerId}-selected`,
183
+ slot: 'bottom',
184
+ source: 'mapData',
185
+ type: 'fill',
186
+ paint: group.style.fillPatternUrl ? {
187
+ 'fill-pattern': group.style.fillPatternUrl,
188
+ 'fill-opacity': selectedOpacity
189
+ } : {
190
+ 'fill-color': group.style.fillColor,
191
+ 'fill-opacity': selectedOpacity
192
+ },
193
+ filter: ['all', groupFilter, selectedFilter, notHoverFilter]
194
+ }, `${group.layerId}-selected`), /*#__PURE__*/jsx(Layer, {
195
+ id: `${group.layerId}-hover`,
196
+ source: 'mapData',
197
+ type: 'fill',
198
+ paint: group.style.fillPatternUrl ? {
199
+ 'fill-pattern': group.style.fillPatternUrl,
200
+ 'fill-opacity': hoverOpacity
201
+ } : {
202
+ 'fill-color': group.style.fillColor,
203
+ 'fill-opacity': hoverOpacity
204
+ },
205
+ filter: ['all', groupFilter, hoverFilter, notSelectedFilter]
206
+ }, `${group.layerId}-hover`), /*#__PURE__*/jsx(Layer, {
207
+ id: `${group.layerId}-selected-hover`,
208
+ source: 'mapData',
209
+ type: 'fill',
210
+ paint: group.style.fillPatternUrl ? {
211
+ 'fill-pattern': group.style.fillPatternUrl,
212
+ 'fill-opacity': hoverAndSelectedOpacity
213
+ } : {
214
+ 'fill-color': group.style.fillColor,
215
+ 'fill-opacity': hoverAndSelectedOpacity
216
+ },
217
+ filter: ['all', groupFilter, hoverFilter, selectedFilter]
218
+ }, `${group.layerId}-selected-hover`)]
219
+ });
220
+ });
221
+ const _textLayers = featureGroups?.map(group => {
222
+ const groupFilter = ['==', ['get', 'layerId'], group.layerId];
223
+ const labelFilter = ['has', 'label'];
224
+ return /*#__PURE__*/jsx(Layer, {
225
+ id: `${group.layerId}-label`,
226
+ source: 'mapData',
227
+ type: 'symbol',
228
+ layout: {
229
+ 'text-field': ['get', 'label'],
230
+ 'text-size': 14,
231
+ 'text-line-height': 20,
232
+ 'text-font': ['Open Sans Bold', 'Arial Unicode MS Regular'],
233
+ 'text-anchor': 'center',
234
+ 'text-justify': 'center'
235
+ },
236
+ paint: {
237
+ 'text-color': '#ffffff'
238
+ },
239
+ filter: ['all', groupFilter, labelFilter]
240
+ }, `${group.layerId}-label`);
241
+ });
242
+ return {
243
+ borderLayers: _borderLayers ?? [],
244
+ fillLayers: _fillLayers ?? [],
245
+ textLayers: _textLayers ?? []
246
+ };
247
+ }, [featureGroups, hoverFeatureId]);
248
+ const highlightLayers = useMemo(() => {
249
+ return highlightGroups?.flatMap(group => {
250
+ return group.highlights.map((highlight, index) => {
251
+ const highlightFeatureIds = highlight.featureIds.map(({
252
+ layerId,
253
+ featureId
254
+ }) => `${layerId}/${featureId}`);
255
+ return /*#__PURE__*/jsx(Layer, {
256
+ id: `highlight-${group.highlightId}-${index}`,
257
+ source: 'mapData',
258
+ type: 'fill',
259
+ paint: highlight.style.fillPatternUrl ? {
260
+ 'fill-pattern': highlight.style.fillPatternUrl,
261
+ 'fill-opacity': highlight.style.opacity ?? 0.5
262
+ } : {
263
+ 'fill-color': highlight.style.fillColor,
264
+ 'fill-opacity': highlight.style.opacity ?? 0.5
265
+ },
266
+ filter: ['all', ['has', 'layerFeatureId'], ['match', ['get', 'layerFeatureId'], highlightFeatureIds, true, false]]
267
+ }, `highlight-${group.highlightId}-${index}`);
268
+ });
269
+ }) ?? [];
270
+ }, [highlightGroups]);
271
+ const markersComponents = useMemo(() => {
272
+ return markerGroups?.flatMap(markerGroup => {
273
+ // cluster markers here
274
+ const clusteredMarkers = clusterMarkers(mapRef.current, markerGroup.markers);
275
+ return clusteredMarkers.map((markers, i) => {
276
+ if (markers.length === 1) {
277
+ const marker = markers[0];
278
+ return /*#__PURE__*/jsx(Marker, {
279
+ className: "map-marker",
280
+ longitude: marker.longitude,
281
+ latitude: marker.latitude,
282
+ anchor: "center",
283
+ onClick: event => {
284
+ marker.onClick?.();
285
+ event.originalEvent.stopPropagation();
286
+ },
287
+ style: {
288
+ backgroundColor: marker.selected ? markerGroup.style.iconColor : theme.palette.TwClrBg
289
+ },
290
+ children: /*#__PURE__*/jsx(Icon, {
291
+ fillColor: marker.selected ? theme.palette.TwClrBg : markerGroup.style.iconColor,
292
+ name: markerGroup.style.iconName,
293
+ size: 'small'
294
+ })
295
+ }, `marker-${i}`);
296
+ } else if (markers.length > 1) {
297
+ const latSum = markers.reduce((sum, marker) => sum + marker.latitude, 0);
298
+ const lngSum = markers.reduce((sum, marker) => sum + marker.longitude, 0);
299
+ const latAvg = latSum / markers.length;
300
+ const lngAvg = lngSum / markers.length;
301
+ const selected = markers.some(marker => marker.selected);
302
+ return /*#__PURE__*/jsxs(Marker, {
303
+ className: "map-marker map-marker--cluster",
304
+ longitude: lngAvg,
305
+ latitude: latAvg,
306
+ anchor: "center",
307
+ onClick: event => {
308
+ mapRef.current?.easeTo({
309
+ center: {
310
+ lat: latAvg,
311
+ lon: lngAvg
535
312
  },
536
- children: controlBottomLeft
537
- }),
538
- geojson && /*#__PURE__*/ jsxs(Source, {
539
- id: "mapData",
540
- type: "geojson",
541
- data: geojson,
542
- children: [
543
- fillLayers,
544
- highlightLayers,
545
- borderLayers,
546
- textLayers
547
- ]
548
- }),
549
- markersComponents
550
- ]
551
- }, mapId);
313
+ zoom: (zoom ?? 10) + 1,
314
+ duration: 500
315
+ });
316
+ event.originalEvent.stopPropagation();
317
+ },
318
+ style: {
319
+ backgroundColor: selected ? markerGroup.style.iconColor : theme.palette.TwClrBg
320
+ },
321
+ children: [/*#__PURE__*/jsx("p", {
322
+ className: "count",
323
+ children: markers.length
324
+ }), /*#__PURE__*/jsx(Icon, {
325
+ fillColor: selected ? theme.palette.TwClrBg : markerGroup.style.iconColor,
326
+ name: markerGroup.style.iconName,
327
+ size: 'small'
328
+ })]
329
+ }, `marker-${i}`);
330
+ }
331
+ });
332
+ });
333
+ }, [markerGroups, theme, zoom]);
334
+ const onMouseMove = useCallback(event => {
335
+ if (event.features && event.features.length) {
336
+ const properties = event.features.map(feature => feature.properties).filter(featureProperties => featureProperties && featureProperties.id !== undefined && featureProperties.priority !== undefined && featureProperties.clickable);
337
+ if (properties.length) {
338
+ const topPriorityFeature = properties.reduce((top, current) => {
339
+ return current.priority > top.priority ? current : top;
340
+ }, properties[0]);
341
+ setHoverFeatureId(topPriorityFeature.id);
342
+ return;
343
+ }
344
+ }
345
+ setHoverFeatureId(undefined);
346
+ }, []);
347
+ useEffect(() => {
348
+ if (!mapRef.current) {
349
+ return;
350
+ }
351
+ const observer = new ResizeObserver(() => {
352
+ mapRef.current?.resize();
353
+ });
354
+ observer.observe(mapRef.current.getContainer());
355
+ return () => observer.disconnect();
356
+ }, []);
357
+ useEffect(() => {
358
+ if (!mapRef.current) {
359
+ return;
360
+ }
361
+ mapRef.current.resize();
362
+ }, [drawerOpen]);
363
+
364
+ // Hovering interactive layers
365
+ const onMouseEnter = useCallback(() => setCursor(cursorInteract ?? 'pointer'), [cursorInteract]);
366
+ const onMouseLeave = useCallback(() => setCursor('auto'), []);
367
+
368
+ // Entering and exiting canvases
369
+ const onMouseOver = useCallback(() => setCursor(cursorMap ?? 'auto'), [cursorMap]);
370
+ const onMouseOut = useCallback(() => setCursor('auto'), []);
371
+
372
+ // On layer click
373
+ const onMapClick = useCallback(event => {
374
+ if (featureGroups && event.features?.length) {
375
+ const properties = event.features.map(feature => feature.properties).filter(featureProperties => featureProperties && featureProperties.id !== undefined && featureProperties.priority !== undefined && featureProperties.clickable);
376
+ if (properties.length) {
377
+ const topPriorityFeature = properties.reduce((top, current) => {
378
+ return current.priority > top.priority ? current : top;
379
+ }, properties[0]);
380
+ const clickedItem = featureGroups.flatMap(group => group.features).find(feature => feature.featureId === topPriorityFeature.id);
381
+ if (clickedItem && clickedItem.onClick) {
382
+ clickedItem.onClick();
383
+ return;
384
+ }
385
+ }
386
+ // If feature not clickable or not handled, fall through to canvas
387
+ }
388
+ if (onClickCanvas !== undefined) {
389
+ onClickCanvas(event);
390
+ }
391
+ }, [featureGroups, onClickCanvas]);
392
+ const orderedLayerIds = useMemo(() => {
393
+ return [...fillLayers.map(layer => layer.props.id), ...highlightLayers.map(layer => layer.props.id), ...borderLayers.map(layer => layer.props.id), ...textLayers.map(layer => layer.props.id)];
394
+ }, [borderLayers, fillLayers, highlightLayers, textLayers]);
395
+ useMaintainLayerOrder(mapRef, orderedLayerIds);
396
+ return /*#__PURE__*/jsxs(ReactMapbox, {
397
+ attributionControl: false,
398
+ cursor: cursor,
399
+ doubleClickZoom: !disableZoom && !disableDoubleClickZoom,
400
+ interactiveLayerIds: interactiveLayerIds,
401
+ initialViewState: initialViewState,
402
+ mapboxAccessToken: token,
403
+ mapStyle: stylesUrl[mapViewStyle],
404
+ ref: mapRefCallback,
405
+ scrollZoom: !disableZoom,
406
+ style: {
407
+ width: 'auto',
408
+ height: isDesktop ? 'auto' : '80vh',
409
+ flexGrow: isDesktop ? 1 : undefined
410
+ },
411
+ onClick: onMapClick,
412
+ onMove: onMove,
413
+ onMouseEnter: onMouseEnter,
414
+ onMouseLeave: onMouseLeave,
415
+ onMouseOver: onMouseOver,
416
+ onMouseOut: onMouseOut,
417
+ onMouseMove: onMouseMove,
418
+ children: [isDesktop && !hideFullScreenControl && /*#__PURE__*/jsx(FullscreenControl, {
419
+ position: "top-left",
420
+ containerId: containerId
421
+ }), !hideZoomControl && /*#__PURE__*/jsx(NavigationControl, {
422
+ showCompass: false,
423
+ style: {
424
+ marginRight: theme.spacing(2),
425
+ marginBottom: theme.spacing(2)
426
+ },
427
+ position: "bottom-right"
428
+ }), !hideMapViewStyleControl && /*#__PURE__*/jsx(MapViewStyleControl, {
429
+ containerId: containerId,
430
+ mapViewStyle: mapViewStyle,
431
+ setMapViewStyle: setMapViewStyle
432
+ }), controlTopRight && /*#__PURE__*/jsx(Box, {
433
+ sx: {
434
+ height: 'max-content',
435
+ position: 'absolute',
436
+ right: theme.spacing(2),
437
+ top: theme.spacing(2),
438
+ width: 'max-content',
439
+ zIndex: 1000
440
+ },
441
+ children: controlTopRight
442
+ }), controlBottomLeft && /*#__PURE__*/jsx(Box, {
443
+ style: {
444
+ height: 'max-content',
445
+ position: 'absolute',
446
+ left: theme.spacing(2),
447
+ bottom: theme.spacing(4),
448
+ width: 'max-content',
449
+ zIndex: 1000
450
+ },
451
+ children: controlBottomLeft
452
+ }), geojson && /*#__PURE__*/jsxs(Source, {
453
+ id: "mapData",
454
+ type: "geojson",
455
+ data: geojson,
456
+ children: [fillLayers, highlightLayers, borderLayers, textLayers]
457
+ }), markersComponents]
458
+ }, mapId);
552
459
  };
553
- const Map_MapBox = MapBox;
554
- export default Map_MapBox;
460
+
461
+ export { MapBox as default };