@collabdt/core 0.0.42 → 0.0.44

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 (275) hide show
  1. package/dist/core/components/Toolbar.d.ts.map +1 -1
  2. package/dist/core/components/Toolbar.js.map +1 -1
  3. package/dist/core/components/ToolbarBody.js.map +1 -1
  4. package/dist/core/components/TopNavigationBar.js.map +1 -1
  5. package/dist/core/components/authentication/ForgotPassword.js.map +1 -1
  6. package/dist/core/components/authentication/Signin.js.map +1 -1
  7. package/dist/core/components/authentication/Signup.js.map +1 -1
  8. package/dist/core/components/settings/src/OrganizationSkeleton.js.map +1 -1
  9. package/dist/core/components/settings/src/SettingsSkeleton.js.map +1 -1
  10. package/dist/core/components/ui/Comments/CollapsibleCommentItem.d.ts.map +1 -1
  11. package/dist/core/components/ui/Comments/CollapsibleCommentItem.js.map +1 -1
  12. package/dist/core/components/ui/Comments/CommentsSection.d.ts.map +1 -1
  13. package/dist/core/components/ui/Comments/CommentsSection.js.map +1 -1
  14. package/dist/core/components/ui/DataTable.d.ts.map +1 -1
  15. package/dist/core/components/ui/DataTable.js +7 -0
  16. package/dist/core/components/ui/DataTable.js.map +1 -1
  17. package/dist/core/components/ui/FilesManager/src/FileItemComponent.d.ts.map +1 -1
  18. package/dist/core/components/ui/FilesManager/src/FileItemComponent.js.map +1 -1
  19. package/dist/core/components/ui/FilesManager/src/FileMarker.d.ts +5 -2
  20. package/dist/core/components/ui/FilesManager/src/FileMarker.d.ts.map +1 -1
  21. package/dist/core/components/ui/FilesManager/src/FileMarker.js +84 -21
  22. package/dist/core/components/ui/FilesManager/src/FileMarker.js.map +1 -1
  23. package/dist/core/components/ui/FilesManager/src/convertIfcToFragmentsFile.d.ts.map +1 -1
  24. package/dist/core/components/ui/FilesManager/src/convertIfcToFragmentsFile.js.map +1 -1
  25. package/dist/core/components/ui/FilesManager/src/useFileUploadHandler.d.ts.map +1 -1
  26. package/dist/core/components/ui/FilesManager/src/useFileUploadHandler.js.map +1 -1
  27. package/dist/core/components/ui/Icons/IfcIcon.d.ts.map +1 -1
  28. package/dist/core/components/ui/Icons/IfcIcon.js.map +1 -1
  29. package/dist/core/components/ui/InfoSidebar/index.d.ts.map +1 -1
  30. package/dist/core/components/ui/InfoSidebar/index.js.map +1 -1
  31. package/dist/core/components/ui/Navbar.d.ts.map +1 -1
  32. package/dist/core/components/ui/Navbar.js.map +1 -1
  33. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
  34. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
  35. package/dist/core/components/ui/Sensors/SensorTagsSection.d.ts.map +1 -1
  36. package/dist/core/components/ui/Sensors/SensorTagsSection.js.map +1 -1
  37. package/dist/core/components/ui/Sensors/SensorsSection.d.ts.map +1 -1
  38. package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
  39. package/dist/core/components/ui/ShareFeature/ShareToolSubmenu.d.ts.map +1 -1
  40. package/dist/core/components/ui/ShareFeature/ShareToolSubmenu.js.map +1 -1
  41. package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.js +2 -2
  42. package/dist/core/components/viewers/Data/buildingDetails/GeocoderInput.js.map +1 -1
  43. package/dist/core/components/viewers/Data/infrastructureDetails/FieldRenderer.d.ts.map +1 -1
  44. package/dist/core/components/viewers/Data/infrastructureDetails/FieldRenderer.js.map +1 -1
  45. package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.js +2 -2
  46. package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.js.map +1 -1
  47. package/dist/core/components/viewers/Viewer.d.ts.map +1 -1
  48. package/dist/core/components/viewers/Viewer.js +5 -1
  49. package/dist/core/components/viewers/Viewer.js.map +1 -1
  50. package/dist/core/components/viewers/bim/BimToolbar.d.ts.map +1 -1
  51. package/dist/core/components/viewers/bim/BimToolbar.js.map +1 -1
  52. package/dist/core/components/viewers/bim/BimViewer.d.ts.map +1 -1
  53. package/dist/core/components/viewers/bim/BimViewer.js +14 -5
  54. package/dist/core/components/viewers/bim/BimViewer.js.map +1 -1
  55. package/dist/core/components/viewers/bim/src/BimLoadingState/index.d.ts.map +1 -1
  56. package/dist/core/components/viewers/bim/src/BimLoadingState/index.js +6 -0
  57. package/dist/core/components/viewers/bim/src/BimLoadingState/index.js.map +1 -1
  58. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
  59. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js +168 -39
  60. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js.map +1 -1
  61. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
  62. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
  63. package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.d.ts.map +1 -1
  64. package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.js +1 -1
  65. package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.js.map +1 -1
  66. package/dist/core/components/viewers/bim/src/ClippingPlane.d.ts.map +1 -1
  67. package/dist/core/components/viewers/bim/src/ClippingPlane.js.map +1 -1
  68. package/dist/core/components/viewers/bim/src/DXFLoader/index.d.ts +14 -37
  69. package/dist/core/components/viewers/bim/src/DXFLoader/index.d.ts.map +1 -1
  70. package/dist/core/components/viewers/bim/src/DXFLoader/index.js +31 -318
  71. package/dist/core/components/viewers/bim/src/DXFLoader/index.js.map +1 -1
  72. package/dist/core/components/viewers/bim/src/FloorplanTool/index.d.ts +66 -7
  73. package/dist/core/components/viewers/bim/src/FloorplanTool/index.d.ts.map +1 -1
  74. package/dist/core/components/viewers/bim/src/FloorplanTool/index.js +253 -21
  75. package/dist/core/components/viewers/bim/src/FloorplanTool/index.js.map +1 -1
  76. package/dist/core/components/viewers/bim/src/ModelManager/index.d.ts.map +1 -1
  77. package/dist/core/components/viewers/bim/src/ModelManager/index.js +9 -0
  78. package/dist/core/components/viewers/bim/src/ModelManager/index.js.map +1 -1
  79. package/dist/core/components/viewers/bim/src/SimpleBimViewer.d.ts.map +1 -1
  80. package/dist/core/components/viewers/bim/src/SimpleBimViewer.js.map +1 -1
  81. package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.d.ts +3 -2
  82. package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.d.ts.map +1 -1
  83. package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.js.map +1 -1
  84. package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.d.ts.map +1 -1
  85. package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.js +3 -4
  86. package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.js.map +1 -1
  87. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts.map +1 -1
  88. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js +40 -18
  89. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js.map +1 -1
  90. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.d.ts +2 -5
  91. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.d.ts.map +1 -1
  92. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.js +45 -59
  93. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.js.map +1 -1
  94. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddSensor.d.ts.map +1 -1
  95. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddSensor.js.map +1 -1
  96. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js +1 -0
  97. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js.map +1 -1
  98. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.d.ts +10 -1
  99. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.d.ts.map +1 -1
  100. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.js +25 -73
  101. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.js.map +1 -1
  102. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.d.ts +7 -3
  103. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.d.ts.map +1 -1
  104. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.js +42 -78
  105. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.js.map +1 -1
  106. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.d.ts.map +1 -1
  107. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.js +52 -75
  108. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.js.map +1 -1
  109. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.d.ts +15 -3
  110. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.d.ts.map +1 -1
  111. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.js +165 -105
  112. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.js.map +1 -1
  113. package/dist/core/components/viewers/index.d.ts.map +1 -1
  114. package/dist/core/components/viewers/index.js.map +1 -1
  115. package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
  116. package/dist/core/components/viewers/map/MapViewer.js +32 -8
  117. package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
  118. package/dist/core/components/viewers/map/datasets/DatasetManager/index.d.ts.map +1 -1
  119. package/dist/core/components/viewers/map/datasets/DatasetManager/index.js +4 -3
  120. package/dist/core/components/viewers/map/datasets/DatasetManager/index.js.map +1 -1
  121. package/dist/core/components/viewers/map/datasets/RowActions.d.ts.map +1 -1
  122. package/dist/core/components/viewers/map/datasets/RowActions.js +148 -0
  123. package/dist/core/components/viewers/map/datasets/RowActions.js.map +1 -1
  124. package/dist/core/components/viewers/map/datasets/index.d.ts.map +1 -1
  125. package/dist/core/components/viewers/map/datasets/index.js +32 -15
  126. package/dist/core/components/viewers/map/datasets/index.js.map +1 -1
  127. package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.d.ts +4 -0
  128. package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.d.ts.map +1 -0
  129. package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.js +43 -0
  130. package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.js.map +1 -0
  131. package/dist/core/components/viewers/map/datasets/src/localDatasets.d.ts.map +1 -1
  132. package/dist/core/components/viewers/map/datasets/src/localDatasets.js +39 -3
  133. package/dist/core/components/viewers/map/datasets/src/localDatasets.js.map +1 -1
  134. package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts +1 -1
  135. package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts.map +1 -1
  136. package/dist/core/components/viewers/map/datasets/src/minioDatasets.js +2 -1
  137. package/dist/core/components/viewers/map/datasets/src/minioDatasets.js.map +1 -1
  138. package/dist/core/components/viewers/map/datasets/src/publishedTiles.d.ts +47 -0
  139. package/dist/core/components/viewers/map/datasets/src/publishedTiles.d.ts.map +1 -0
  140. package/dist/core/components/viewers/map/datasets/src/publishedTiles.js +114 -0
  141. package/dist/core/components/viewers/map/datasets/src/publishedTiles.js.map +1 -0
  142. package/dist/core/components/viewers/map/datasets/src/wmsTime.d.ts +49 -0
  143. package/dist/core/components/viewers/map/datasets/src/wmsTime.d.ts.map +1 -0
  144. package/dist/core/components/viewers/map/datasets/src/wmsTime.js +100 -0
  145. package/dist/core/components/viewers/map/datasets/src/wmsTime.js.map +1 -0
  146. package/dist/core/components/viewers/map/src/Geocoder.d.ts.map +1 -1
  147. package/dist/core/components/viewers/map/src/Geocoder.js +9 -9
  148. package/dist/core/components/viewers/map/src/Geocoder.js.map +1 -1
  149. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.d.ts.map +1 -1
  150. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js +25 -43
  151. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js.map +1 -1
  152. package/dist/core/components/viewers/map/src/MapLayers/index.d.ts.map +1 -1
  153. package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
  154. package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.d.ts.map +1 -1
  155. package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.js +19 -2
  156. package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.js.map +1 -1
  157. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.d.ts +9 -0
  158. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.d.ts.map +1 -0
  159. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.js +28 -0
  160. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.js.map +1 -0
  161. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.d.ts.map +1 -1
  162. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js +1 -16
  163. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js.map +1 -1
  164. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/FileModelLayer/FileModelLayer.d.ts.map +1 -1
  165. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/FileModelLayer/FileModelLayer.js.map +1 -1
  166. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.d.ts.map +1 -1
  167. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.js +31 -2
  168. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.js.map +1 -1
  169. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.d.ts +21 -0
  170. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.d.ts.map +1 -0
  171. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.js +111 -0
  172. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.js.map +1 -0
  173. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.d.ts.map +1 -1
  174. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.js +77 -2
  175. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.js.map +1 -1
  176. package/dist/core/components/viewers/map/src/MapSidebar/index.d.ts.map +1 -1
  177. package/dist/core/components/viewers/map/src/MapSidebar/index.js.map +1 -1
  178. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
  179. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js.map +1 -1
  180. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
  181. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
  182. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.d.ts.map +1 -1
  183. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.js +19 -9
  184. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/MapProjection.js.map +1 -1
  185. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.d.ts.map +1 -1
  186. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js +10 -3
  187. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js.map +1 -1
  188. package/dist/core/components/viewers/map/utils/geocoder.d.ts +6 -2
  189. package/dist/core/components/viewers/map/utils/geocoder.d.ts.map +1 -1
  190. package/dist/core/components/viewers/map/utils/geocoder.js +10 -62
  191. package/dist/core/components/viewers/map/utils/geocoder.js.map +1 -1
  192. package/dist/core/components/viewers/map/utils/geocoding/adapters.d.ts +5 -0
  193. package/dist/core/components/viewers/map/utils/geocoding/adapters.d.ts.map +1 -0
  194. package/dist/core/components/viewers/map/utils/geocoding/adapters.js +192 -0
  195. package/dist/core/components/viewers/map/utils/geocoding/adapters.js.map +1 -0
  196. package/dist/core/components/viewers/map/utils/geocoding/config.d.ts +6 -0
  197. package/dist/core/components/viewers/map/utils/geocoding/config.d.ts.map +1 -0
  198. package/dist/core/components/viewers/map/utils/geocoding/config.js +14 -0
  199. package/dist/core/components/viewers/map/utils/geocoding/config.js.map +1 -0
  200. package/dist/core/components/viewers/map/utils/geocoding/index.d.ts +8 -0
  201. package/dist/core/components/viewers/map/utils/geocoding/index.d.ts.map +1 -0
  202. package/dist/core/components/viewers/map/utils/geocoding/index.js +44 -0
  203. package/dist/core/components/viewers/map/utils/geocoding/index.js.map +1 -0
  204. package/dist/core/components/viewers/map/utils/geocoding/osm.d.ts +6 -0
  205. package/dist/core/components/viewers/map/utils/geocoding/osm.d.ts.map +1 -0
  206. package/dist/core/components/viewers/map/utils/geocoding/osm.js +39 -0
  207. package/dist/core/components/viewers/map/utils/geocoding/osm.js.map +1 -0
  208. package/dist/core/components/viewers/map/utils/geocoding/pelias.d.ts +8 -0
  209. package/dist/core/components/viewers/map/utils/geocoding/pelias.d.ts.map +1 -0
  210. package/dist/core/components/viewers/map/utils/geocoding/pelias.js +35 -0
  211. package/dist/core/components/viewers/map/utils/geocoding/pelias.js.map +1 -0
  212. package/dist/core/components/viewers/pointcloud/PointCloudToolbar.d.ts.map +1 -1
  213. package/dist/core/components/viewers/pointcloud/PointCloudToolbar.js.map +1 -1
  214. package/dist/core/components/viewers/pointcloud/PointCloudViewer.js +1 -3
  215. package/dist/core/components/viewers/pointcloud/PointCloudViewer.js.map +1 -1
  216. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.d.ts.map +1 -1
  217. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js +2 -3
  218. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js.map +1 -1
  219. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
  220. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.js +8 -2
  221. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.js.map +1 -1
  222. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts.map +1 -1
  223. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js.map +1 -1
  224. package/dist/core/components/viewers/pointcloud/src/tools/PerformanceSettingsTools/NodeSizeSelectionTool.js +9 -9
  225. package/dist/core/components/viewers/pointcloud/src/tools/PerformanceSettingsTools/NodeSizeSelectionTool.js.map +1 -1
  226. package/dist/core/hooks/provider.js.map +1 -1
  227. package/dist/core/plugins/host/provider.d.ts.map +1 -1
  228. package/dist/core/plugins/host/provider.js.map +1 -1
  229. package/dist/core/store/AppConfig/context.d.ts.map +1 -1
  230. package/dist/core/store/AppConfig/context.js.map +1 -1
  231. package/dist/core/store/BIM/context.d.ts.map +1 -1
  232. package/dist/core/store/BIM/context.js.map +1 -1
  233. package/dist/core/store/BIM/reducer.d.ts +0 -1
  234. package/dist/core/store/BIM/reducer.d.ts.map +1 -1
  235. package/dist/core/store/BIM/reducer.js +0 -4
  236. package/dist/core/store/BIM/reducer.js.map +1 -1
  237. package/dist/core/store/Buildings/context.d.ts.map +1 -1
  238. package/dist/core/store/Buildings/context.js.map +1 -1
  239. package/dist/core/store/Content/context.d.ts.map +1 -1
  240. package/dist/core/store/Content/context.js.map +1 -1
  241. package/dist/core/store/Datasets/context.d.ts.map +1 -1
  242. package/dist/core/store/Datasets/context.js +2 -1
  243. package/dist/core/store/Datasets/context.js.map +1 -1
  244. package/dist/core/store/Datasets/reducer.d.ts +2 -0
  245. package/dist/core/store/Datasets/reducer.d.ts.map +1 -1
  246. package/dist/core/store/Datasets/reducer.js +9 -4
  247. package/dist/core/store/Datasets/reducer.js.map +1 -1
  248. package/dist/core/store/Files/context.d.ts.map +1 -1
  249. package/dist/core/store/Files/context.js.map +1 -1
  250. package/dist/core/store/Map/context.d.ts.map +1 -1
  251. package/dist/core/store/Map/context.js.map +1 -1
  252. package/dist/core/store/Menus/context.d.ts.map +1 -1
  253. package/dist/core/store/Menus/context.js.map +1 -1
  254. package/dist/core/store/Permissions/context.d.ts.map +1 -1
  255. package/dist/core/store/Permissions/context.js.map +1 -1
  256. package/dist/core/store/PointCloud/context.d.ts.map +1 -1
  257. package/dist/core/store/PointCloud/context.js.map +1 -1
  258. package/dist/core/store/Tools/context.d.ts.map +1 -1
  259. package/dist/core/store/Tools/context.js.map +1 -1
  260. package/dist/core/types/datasetTypes.d.ts +8 -1
  261. package/dist/core/types/datasetTypes.d.ts.map +1 -1
  262. package/dist/core/types/dbTypes.d.ts +13 -13
  263. package/dist/core/types/dbTypes.d.ts.map +1 -1
  264. package/dist/core/types/dbTypes.js +13 -13
  265. package/dist/core/types/dbTypes.js.map +1 -1
  266. package/dist/core/types/index.d.ts +1 -1
  267. package/dist/core/types/index.d.ts.map +1 -1
  268. package/dist/core/types/index.js.map +1 -1
  269. package/dist/core/utils/imageUtils.js +1 -1
  270. package/dist/core/utils/imageUtils.js.map +1 -1
  271. package/package.json +4 -3
  272. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.d.ts +0 -3
  273. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.d.ts.map +0 -1
  274. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.js +0 -173
  275. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../src/core/components/viewers/map/src/Geocoder.tsx"],"sourcesContent":["'use client'\r\n\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\n\r\n// Context\r\nimport { MapContext } from '../../../../store'\r\n\r\n// Utility functions\r\nimport { fetchSuggestions, parseLocation, handleLocationSelect, buildingToFeature } from '../utils/geocoder'\r\n\r\n// Import the shadcn components\r\nimport { Command, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator } from '../../../ui/Command'\r\nimport { Button } from '../../../ui/Button'\r\nimport { Input } from '../../../ui/Input'\r\nimport { Separator } from '../../../ui/Separator'\r\n\r\n// Icons\r\nimport { Search } from 'lucide-react'\r\n\r\n// Building data hook\r\nimport { useBuildings } from '../../../../hooks/buildings/buildings'\r\n\r\nimport { usePathname } from 'next/navigation'\r\nimport type { CurrentLocation } from '../../../../types/map'\r\nimport { LoadingSpinner } from '../../../ui/LoadingSpinner'\r\n\r\ninterface GeocoderProps {\r\n onSelect?: (addressData: any) => void\r\n showDatabaseBuildings?: boolean\r\n alwaysExpanded?: boolean\r\n}\r\n\r\nexport default function Geocoder({\r\n onSelect,\r\n showDatabaseBuildings = true,\r\n alwaysExpanded = false,\r\n}: GeocoderProps) {\r\n // Translation\r\n const t = useTranslations('Geocoder')\r\n\r\n const [address, setAddress] = React.useState<string>('')\r\n const [query, setQuery] = React.useState('')\r\n const [suggestions, setSuggestions] = React.useState([])\r\n const [buildingResults, setBuildingResults] = React.useState([])\r\n const [focused, setFocused] = React.useState(alwaysExpanded)\r\n const [selectedAddress, setSelectedAddress] = React.useState(null)\r\n const [isExpanded, setIsExpanded] = React.useState(alwaysExpanded)\r\n const [loading, setLoading] = React.useState(false)\r\n\r\n const pathname = usePathname()\r\n\r\n const suggestionsRef = React.useRef(null)\r\n const inputRef = React.useRef(null)\r\n const debounceRef = React.useRef(null)\r\n\r\n const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext)\r\n const { map, currentLocation, organizationCountry } = mapState.map\r\n\r\n // Fetch buildings data from API only if showDatabaseBuildings is true\r\n const { buildings, isLoading: isBuildingsLoading } = useBuildings()\r\n\r\n // Filter buildings based on search query\r\n const filterBuildings = React.useCallback((searchQuery) => {\r\n if (!showDatabaseBuildings || !buildings || !searchQuery || searchQuery.length < 3) return []\r\n\r\n const lowerQuery = searchQuery.toLowerCase()\r\n\r\n if (Array.isArray(buildings) && buildings.length > 0) {\r\n return buildings.filter((building) => {\r\n return (\r\n (building.buildingName && building.buildingName.toLowerCase().includes(lowerQuery))\r\n || (building.buildingAddress && building.buildingAddress.toLowerCase().includes(lowerQuery))\r\n || (building.buildingMunicipality && building.buildingMunicipality.toLowerCase().includes(lowerQuery))\r\n || (building.buildingCountrySubdivision && building.buildingCountrySubdivision.toLowerCase().includes(lowerQuery))\r\n )\r\n }).slice(0, 3) // Limit to 3 results\r\n }\r\n return []\r\n }, [buildings, showDatabaseBuildings])\r\n\r\n // Debounce the API request to avoid rate limiting and excessive requests\r\n React.useEffect(() => {\r\n if (debounceRef.current) {\r\n clearTimeout(debounceRef.current)\r\n }\r\n\r\n debounceRef.current = setTimeout(async () => {\r\n if (!query || query.length < 3) {\r\n setSuggestions([])\r\n setBuildingResults([])\r\n setLoading(false)\r\n return\r\n }\r\n\r\n setLoading(true)\r\n try {\r\n // Filter buildings from our database only if enabled\r\n if (showDatabaseBuildings) {\r\n const filteredBuildings = filterBuildings(query)\r\n setBuildingResults(filteredBuildings)\r\n }\r\n\r\n // Fetch geocoding suggestions\r\n const geocodeResults = await fetchSuggestions(query, organizationCountry)\r\n \r\n // Deduplicate geocode results based on name and region\r\n const deduplicatedResults = geocodeResults.reduce((acc, feature) => {\r\n const location = parseLocation(feature)\r\n // Create a unique key based on name and region (case-insensitive)\r\n const key = `${location.name?.toLowerCase() || ''}_${location.region?.toLowerCase() || ''}`\r\n \r\n // Only add if we haven't seen this combination before\r\n if (!acc.seen.has(key)) {\r\n acc.seen.add(key)\r\n acc.features.push(feature)\r\n }\r\n \r\n return acc\r\n }, { seen: new Set(), features: [] })\r\n \r\n setSuggestions(deduplicatedResults.features)\r\n }\r\n catch (error) {\r\n console.error('Error fetching suggestions:', error)\r\n setSuggestions([])\r\n }\r\n finally {\r\n setLoading(false)\r\n }\r\n }, 300) // Increased debounce time for better API rate limiting\r\n\r\n return () => {\r\n if (debounceRef.current) clearTimeout(debounceRef.current)\r\n }\r\n }, [query, filterBuildings, showDatabaseBuildings])\r\n\r\n // Handle click outside to close suggestions\r\n React.useEffect(() => {\r\n const handleClickOutside = (event) => {\r\n if (suggestionsRef.current && !suggestionsRef.current.contains(event.target)\r\n && inputRef.current && !inputRef.current.contains(event.target) // Don't close if alwaysExpanded is true\r\n && !alwaysExpanded) {\r\n setFocused(false)\r\n }\r\n }\r\n\r\n document.addEventListener('mousedown', handleClickOutside)\r\n return () => {\r\n document.removeEventListener('mousedown', handleClickOutside)\r\n }\r\n }, [alwaysExpanded])\r\n\r\n // Handle suggestion selection\r\n const handleSelectSuggestion = (feature, type = '') => {\r\n setQuery('') // Clear the input field\r\n setSuggestions([])\r\n setBuildingResults([])\r\n if (!alwaysExpanded) {\r\n setFocused(false)\r\n }\r\n\r\n // handleLocationSelect will automatically remove any existing marker and add a new one\r\n const addressData = handleLocationSelect(feature, map, type)\r\n\r\n const address = addressData.formatted_address || feature.properties?.label || ''\r\n setAddress(address)\r\n setSelectedAddress(addressData)\r\n\r\n if (onSelect) onSelect(addressData)\r\n\r\n if (mapDispatch && currentLocation) {\r\n const [lng, lat] = addressData.coordinates\r\n const countrySubdivision: string = addressData.properties?.region_a\r\n // Extract municipality (3rd from the right)\r\n const parts = address.split(',').map(p => p.trim())\r\n const partsReverse = [...parts].reverse()\r\n console.log('parts', parts, 'partsReverse', partsReverse)\r\n let municipality = ''\r\n if (partsReverse[1] === countrySubdivision) municipality = partsReverse[2] || ''\r\n\r\n const newCurrentLocation: CurrentLocation = { ...currentLocation, municipality, countrySubdivision, longitude: lng, latitude: lat, address: parts[0] }\r\n mapDispatch({ type: 'UPDATE_LOCATION', payload: { currentLocation: newCurrentLocation } })\r\n if (municipality && countrySubdivision) {\r\n const url = new URL(window.location.href)\r\n url.searchParams.set('municipality', municipality)\r\n url.searchParams.set('countrySubdivision', countrySubdivision)\r\n url.searchParams.set('address', parts[0])\r\n url.searchParams.set('lng', lng.toString())\r\n url.searchParams.set('lat', lat.toString())\r\n url.searchParams.set('zoom', '18')\r\n window.history.replaceState({}, '', url.toString())\r\n }\r\n }\r\n }\r\n\r\n // Handle expand of menubar to display search input\r\n const handleExpand = () => {\r\n if (alwaysExpanded) return // Don't allow toggling if always expanded\r\n\r\n setIsExpanded(!isExpanded)\r\n if (isExpanded) {\r\n setFocused(false)\r\n setQuery('') // clear input and suggestions when collapsed\r\n setSuggestions([])\r\n setBuildingResults([])\r\n }\r\n else {\r\n setFocused(true)\r\n setTimeout(() => {\r\n inputRef.current?.focus()\r\n }, 100) // Small delay to ensure the input is rendered\r\n }\r\n }\r\n\r\n return (\r\n <Command>\r\n {/* Search input + button */}\r\n <div className={`flex flex-row justify-start items-center w-full h-auto `}>\r\n {!alwaysExpanded && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={handleExpand}\r\n className=\"opacity-70 w-6 justify-end hover:opacity-100 transition-opacity duration-200 hover:bg-transparent\"\r\n >\r\n <Search />\r\n </Button>\r\n )}\r\n {alwaysExpanded && (\r\n <Search className=\"h-4 w-4 opacity-50\" />\r\n )}\r\n <Input\r\n ref={inputRef}\r\n type=\"text\"\r\n value={query}\r\n onChange={e => setQuery(e.target.value)}\r\n onFocus={() => setFocused(true)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') {\r\n inputRef.current?.blur()\r\n }\r\n }}\r\n placeholder={alwaysExpanded ? t('placeholder1') : t('placeholder2')}\r\n className={`border-none focus-visible:ring-transparent text-sm transition-all ease-in-out duration-200 ${\r\n alwaysExpanded || isExpanded ? 'w-full' : 'w-0 p-0'\r\n }`}\r\n />\r\n </div>\r\n\r\n {focused && (loading || buildingResults.length > 0 || suggestions.length > 0) && (\r\n <div ref={suggestionsRef}>\r\n <Separator />\r\n <CommandList>\r\n {!loading && buildingResults.length === 0 && suggestions.length === 0 && query.length >= 3 && (\r\n <CommandEmpty>{showDatabaseBuildings ? t('noResults') : t('noAddresses')}</CommandEmpty>\r\n )}\r\n\r\n {loading && (\r\n <CommandEmpty><LoadingSpinner /></CommandEmpty>\r\n )}\r\n\r\n {/* Database Buildings section - only show if enabled */}\r\n {showDatabaseBuildings && !loading && buildingResults.length > 0 && (\r\n <CommandGroup heading={t('buildingHeader')}>\r\n {buildingResults.map((building) => {\r\n const buildingFeature = buildingToFeature(building)\r\n\r\n return (\r\n <CommandItem\r\n key={`building-${building.id}`}\r\n onSelect={() => handleSelectSuggestion(buildingFeature, 'dbBuilding')}\r\n className=\"cursor-pointer\"\r\n >\r\n <div className=\"font-medium\">{building.buildingName}</div>\r\n <div className=\"text-sm text-muted-foreground\">\r\n {building.buildingAddress}\r\n </div>\r\n </CommandItem>\r\n )\r\n })}\r\n </CommandGroup>\r\n )}\r\n\r\n {/* Separator between sections if both have results */}\r\n {showDatabaseBuildings && buildingResults.length > 0 && suggestions.length > 0 && (\r\n <CommandSeparator />\r\n )}\r\n\r\n {/* Geocoder suggestions section */}\r\n {!loading && suggestions.length > 0 && (\r\n <CommandGroup heading={showDatabaseBuildings ? t('suggestionsHeader') : undefined}>\r\n {suggestions.map((feature) => {\r\n const location = parseLocation(feature)\r\n const uniqueKey = feature.properties?.gid\r\n || `${feature.properties?.name}-${feature.geometry?.coordinates?.[0]}-${feature.geometry?.coordinates?.[1]}`\r\n\r\n return (\r\n <CommandItem\r\n key={uniqueKey}\r\n onSelect={() => handleSelectSuggestion(feature)}\r\n className=\"cursor-pointer\"\r\n >\r\n <div className=\"font-medium\">{location.name}</div>\r\n <div className=\"text-sm text-muted-foreground\">{location.region}</div>\r\n </CommandItem>\r\n )\r\n })}\r\n </CommandGroup>\r\n )}\r\n </CommandList>\r\n </div>\r\n )}\r\n </Command>\r\n )\r\n}"],"mappings":"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","names":["address"]}
1
+ {"version":3,"sources":["../../../../../../src/core/components/viewers/map/src/Geocoder.tsx"],"sourcesContent":["'use client'\r\n\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useTranslations } from 'next-intl'\r\n\r\n// Context\r\nimport { MapContext } from '../../../../store'\r\n\r\n// Utility functions\r\nimport { fetchSuggestions, parseLocation, handleLocationSelect, buildingToFeature } from '../utils/geocoder'\r\n\r\n// Import the shadcn components\r\nimport { Command, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandSeparator } from '../../../ui/Command'\r\nimport { Button } from '../../../ui/Button'\r\nimport { Input } from '../../../ui/Input'\r\nimport { Separator } from '../../../ui/Separator'\r\n\r\n// Icons\r\nimport { Search } from 'lucide-react'\r\n\r\n// Building data hook\r\nimport { useBuildings } from '../../../../hooks/buildings/buildings'\r\n\r\nimport { usePathname } from 'next/navigation'\r\nimport type { CurrentLocation } from '../../../../types/map'\r\nimport { LoadingSpinner } from '../../../ui/LoadingSpinner'\r\n\r\ninterface GeocoderProps {\r\n onSelect?: (addressData: any) => void\r\n showDatabaseBuildings?: boolean\r\n alwaysExpanded?: boolean\r\n}\r\n\r\nexport default function Geocoder({\r\n onSelect,\r\n showDatabaseBuildings = true,\r\n alwaysExpanded = false,\r\n}: GeocoderProps) {\r\n // Translation\r\n const t = useTranslations('Geocoder')\r\n\r\n const [address, setAddress] = React.useState<string>('')\r\n const [query, setQuery] = React.useState('')\r\n const [suggestions, setSuggestions] = React.useState([])\r\n const [buildingResults, setBuildingResults] = React.useState([])\r\n const [focused, setFocused] = React.useState(alwaysExpanded)\r\n const [selectedAddress, setSelectedAddress] = React.useState(null)\r\n const [isExpanded, setIsExpanded] = React.useState(alwaysExpanded)\r\n const [loading, setLoading] = React.useState(false)\r\n\r\n const pathname = usePathname()\r\n\r\n const suggestionsRef = React.useRef(null)\r\n const inputRef = React.useRef(null)\r\n const debounceRef = React.useRef(null)\r\n\r\n const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext)\r\n const { map, currentLocation, organizationCountry } = mapState.map\r\n\r\n // Fetch buildings data from API only if showDatabaseBuildings is true\r\n const { buildings, isLoading: isBuildingsLoading } = useBuildings()\r\n\r\n // Filter buildings based on search query\r\n const filterBuildings = React.useCallback((searchQuery) => {\r\n if (!showDatabaseBuildings || !buildings || !searchQuery || searchQuery.length < 3) return []\r\n\r\n const lowerQuery = searchQuery.toLowerCase()\r\n\r\n if (Array.isArray(buildings) && buildings.length > 0) {\r\n return buildings.filter((building) => {\r\n return (\r\n (building.buildingName && building.buildingName.toLowerCase().includes(lowerQuery))\r\n || (building.buildingAddress && building.buildingAddress.toLowerCase().includes(lowerQuery))\r\n || (building.buildingMunicipality && building.buildingMunicipality.toLowerCase().includes(lowerQuery))\r\n || (building.buildingCountrySubdivision && building.buildingCountrySubdivision.toLowerCase().includes(lowerQuery))\r\n )\r\n }).slice(0, 3) // Limit to 3 results\r\n }\r\n return []\r\n }, [buildings, showDatabaseBuildings])\r\n\r\n // Debounce the API request to avoid rate limiting and excessive requests\r\n React.useEffect(() => {\r\n if (debounceRef.current) {\r\n clearTimeout(debounceRef.current)\r\n }\r\n\r\n debounceRef.current = setTimeout(async () => {\r\n if (!query || query.length < 3) {\r\n setSuggestions([])\r\n setBuildingResults([])\r\n setLoading(false)\r\n return\r\n }\r\n\r\n setLoading(true)\r\n try {\r\n // Filter buildings from our database only if enabled\r\n if (showDatabaseBuildings) {\r\n const filteredBuildings = filterBuildings(query)\r\n setBuildingResults(filteredBuildings)\r\n }\r\n\r\n // Fetch geocoding suggestions\r\n const geocodeResults = await fetchSuggestions(query, organizationCountry)\r\n \r\n // Deduplicate geocode results based on name and region\r\n const deduplicatedResults = geocodeResults.reduce((acc, feature) => {\r\n const location = parseLocation(feature)\r\n // Create a unique key based on name and region (case-insensitive)\r\n const key = `${location.name?.toLowerCase() || ''}_${location.region?.toLowerCase() || ''}`\r\n \r\n // Only add if we haven't seen this combination before\r\n if (!acc.seen.has(key)) {\r\n acc.seen.add(key)\r\n acc.features.push(feature)\r\n }\r\n \r\n return acc\r\n }, { seen: new Set(), features: [] })\r\n \r\n setSuggestions(deduplicatedResults.features)\r\n }\r\n catch (error) {\r\n console.error('Error fetching suggestions:', error)\r\n setSuggestions([])\r\n }\r\n finally {\r\n setLoading(false)\r\n }\r\n }, 300) // Increased debounce time for better API rate limiting\r\n\r\n return () => {\r\n if (debounceRef.current) clearTimeout(debounceRef.current)\r\n }\r\n }, [query, filterBuildings, showDatabaseBuildings])\r\n\r\n // Handle click outside to close suggestions\r\n React.useEffect(() => {\r\n const handleClickOutside = (event) => {\r\n if (suggestionsRef.current && !suggestionsRef.current.contains(event.target)\r\n && inputRef.current && !inputRef.current.contains(event.target) // Don't close if alwaysExpanded is true\r\n && !alwaysExpanded) {\r\n setFocused(false)\r\n }\r\n }\r\n\r\n document.addEventListener('mousedown', handleClickOutside)\r\n return () => {\r\n document.removeEventListener('mousedown', handleClickOutside)\r\n }\r\n }, [alwaysExpanded])\r\n\r\n // Handle suggestion selection\r\n const handleSelectSuggestion = (feature, type = '') => {\r\n setQuery('') // Clear the input field\r\n setSuggestions([])\r\n setBuildingResults([])\r\n if (!alwaysExpanded) {\r\n setFocused(false)\r\n }\r\n\r\n // handleLocationSelect will automatically remove any existing marker and add a new one\r\n const addressData = handleLocationSelect(feature, map, type)\r\n\r\n const address = addressData.formatted_address || feature.properties?.label || ''\r\n setAddress(address)\r\n setSelectedAddress(addressData)\r\n\r\n if (onSelect) onSelect(addressData)\r\n\r\n if (mapDispatch && currentLocation) {\r\n const [lng, lat] = addressData.coordinates\r\n const props = addressData.properties || {}\r\n const parts = address.split(',').map(p => p.trim())\r\n // Read structured properties (provider-agnostic) instead of parsing label tokens,\r\n // which only matched Geocode Earth's \"…, ON, Canada\" abbreviation format and broke\r\n // on the Photon/Nominatim fallback.\r\n const countrySubdivision: string = props.region_a || props.region || ''\r\n const municipality: string = props.locality || props.neighbourhood || props.county || ''\r\n\r\n const newCurrentLocation: CurrentLocation = { ...currentLocation, municipality, countrySubdivision, longitude: lng, latitude: lat, address: parts[0] }\r\n mapDispatch({ type: 'UPDATE_LOCATION', payload: { currentLocation: newCurrentLocation } })\r\n if (municipality || countrySubdivision) {\r\n const url = new URL(window.location.href)\r\n // Write each field only when present, so an empty param doesn't shadow the\r\n // organization fallback MapViewer applies on reload.\r\n if (municipality) url.searchParams.set('municipality', municipality)\r\n else url.searchParams.delete('municipality')\r\n if (countrySubdivision) url.searchParams.set('countrySubdivision', countrySubdivision)\r\n else url.searchParams.delete('countrySubdivision')\r\n url.searchParams.set('address', parts[0])\r\n url.searchParams.set('lng', lng.toString())\r\n url.searchParams.set('lat', lat.toString())\r\n url.searchParams.set('zoom', '18')\r\n window.history.replaceState({}, '', url.toString())\r\n }\r\n }\r\n }\r\n\r\n // Handle expand of menubar to display search input\r\n const handleExpand = () => {\r\n if (alwaysExpanded) return // Don't allow toggling if always expanded\r\n\r\n setIsExpanded(!isExpanded)\r\n if (isExpanded) {\r\n setFocused(false)\r\n setQuery('') // clear input and suggestions when collapsed\r\n setSuggestions([])\r\n setBuildingResults([])\r\n }\r\n else {\r\n setFocused(true)\r\n setTimeout(() => {\r\n inputRef.current?.focus()\r\n }, 100) // Small delay to ensure the input is rendered\r\n }\r\n }\r\n\r\n return (\r\n <Command>\r\n {/* Search input + button */}\r\n <div className={`flex flex-row justify-start items-center w-full h-auto `}>\r\n {!alwaysExpanded && (\r\n <Button\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n onClick={handleExpand}\r\n className=\"opacity-70 w-6 justify-end hover:opacity-100 transition-opacity duration-200 hover:bg-transparent\"\r\n >\r\n <Search />\r\n </Button>\r\n )}\r\n {alwaysExpanded && (\r\n <Search className=\"h-4 w-4 opacity-50\" />\r\n )}\r\n <Input\r\n ref={inputRef}\r\n type=\"text\"\r\n value={query}\r\n onChange={e => setQuery(e.target.value)}\r\n onFocus={() => setFocused(true)}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') {\r\n inputRef.current?.blur()\r\n }\r\n }}\r\n placeholder={alwaysExpanded ? t('placeholder1') : t('placeholder2')}\r\n className={`border-none focus-visible:ring-transparent text-sm transition-all ease-in-out duration-200 ${\r\n alwaysExpanded || isExpanded ? 'w-full' : 'w-0 p-0'\r\n }`}\r\n />\r\n </div>\r\n\r\n {focused && (loading || buildingResults.length > 0 || suggestions.length > 0) && (\r\n <div ref={suggestionsRef}>\r\n <Separator />\r\n <CommandList>\r\n {!loading && buildingResults.length === 0 && suggestions.length === 0 && query.length >= 3 && (\r\n <CommandEmpty>{showDatabaseBuildings ? t('noResults') : t('noAddresses')}</CommandEmpty>\r\n )}\r\n\r\n {loading && (\r\n <CommandEmpty><LoadingSpinner /></CommandEmpty>\r\n )}\r\n\r\n {/* Database Buildings section - only show if enabled */}\r\n {showDatabaseBuildings && !loading && buildingResults.length > 0 && (\r\n <CommandGroup heading={t('buildingHeader')}>\r\n {buildingResults.map((building) => {\r\n const buildingFeature = buildingToFeature(building)\r\n\r\n return (\r\n <CommandItem\r\n key={`building-${building.id}`}\r\n onSelect={() => handleSelectSuggestion(buildingFeature, 'dbBuilding')}\r\n className=\"cursor-pointer\"\r\n >\r\n <div className=\"font-medium\">{building.buildingName}</div>\r\n <div className=\"text-sm text-muted-foreground\">\r\n {building.buildingAddress}\r\n </div>\r\n </CommandItem>\r\n )\r\n })}\r\n </CommandGroup>\r\n )}\r\n\r\n {/* Separator between sections if both have results */}\r\n {showDatabaseBuildings && buildingResults.length > 0 && suggestions.length > 0 && (\r\n <CommandSeparator />\r\n )}\r\n\r\n {/* Geocoder suggestions section */}\r\n {!loading && suggestions.length > 0 && (\r\n <CommandGroup heading={showDatabaseBuildings ? t('suggestionsHeader') : undefined}>\r\n {suggestions.map((feature) => {\r\n const location = parseLocation(feature)\r\n const uniqueKey = feature.properties?.gid\r\n || `${feature.properties?.name}-${feature.geometry?.coordinates?.[0]}-${feature.geometry?.coordinates?.[1]}`\r\n\r\n return (\r\n <CommandItem\r\n key={uniqueKey}\r\n onSelect={() => handleSelectSuggestion(feature)}\r\n className=\"cursor-pointer\"\r\n >\r\n <div className=\"font-medium\">{location.name}</div>\r\n <div className=\"text-sm text-muted-foreground\">{location.region}</div>\r\n </CommandItem>\r\n )\r\n })}\r\n </CommandGroup>\r\n )}\r\n </CommandList>\r\n </div>\r\n )}\r\n </Command>\r\n )\r\n}"],"mappings":"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","names":["address"]}
@@ -1 +1 @@
1
- {"version":3,"file":"NonDatabaseBuildingPopover.d.ts","sourceRoot":"","sources":["../../../../../../../../src/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAqB9B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAUpD,UAAU,+BAA+B;IACvC,OAAO,EAAE,iBAAiB,CAAA;IAC1B,MAAM,EAAE,OAAO,CAAA;IACf,aAAa,EAAE,MAAM,IAAI,CAAA;CAC1B;AAED,MAAM,CAAC,OAAO,UAAU,0BAA0B,CAAC,EACjD,OAAO,EACP,aAAa,GACd,EAAE,+BAA+B,qBAgejC"}
1
+ {"version":3,"file":"NonDatabaseBuildingPopover.d.ts","sourceRoot":"","sources":["../../../../../../../../src/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAqB9B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAWpD,UAAU,+BAA+B;IACvC,OAAO,EAAE,iBAAiB,CAAA;IAC1B,MAAM,EAAE,OAAO,CAAA;IACf,aAAa,EAAE,MAAM,IAAI,CAAA;CAC1B;AAED,MAAM,CAAC,OAAO,UAAU,0BAA0B,CAAC,EACjD,OAAO,EACP,aAAa,GACd,EAAE,+BAA+B,qBA4cjC"}
@@ -34,6 +34,7 @@ import * as LR from "lucide-react";
34
34
  import { MapContext } from "../../../../../../store";
35
35
  import { useMenusContext } from "../../../../../../store";
36
36
  import { MarkerManager } from "../../../utils/MarkerManager";
37
+ import { getDetailedAddress } from "../../../utils/geocoder";
37
38
  import { useCreateBuilding, useBuildings, useBuilding } from "../../../../../../hooks/buildings/buildings";
38
39
  import { LoadingSpinner } from "../../../../../ui/LoadingSpinner";
39
40
  function NonDatabaseBuildingPopover({
@@ -45,7 +46,7 @@ function NonDatabaseBuildingPopover({
45
46
  const { data: session } = useSession();
46
47
  const user = session == null ? void 0 : session.user;
47
48
  const { state: mapState } = React.useContext(MapContext);
48
- const { currentLocation, map } = mapState.map;
49
+ const { currentLocation, map, organizationCountry } = mapState.map;
49
50
  const { setSelectedItem } = useMenusContext();
50
51
  const { createBuilding, isMutating, createError, createdData } = useCreateBuilding();
51
52
  const { buildings } = useBuildings();
@@ -82,49 +83,30 @@ function NonDatabaseBuildingPopover({
82
83
  }, [setSelectedItem]);
83
84
  React.useEffect(() => {
84
85
  var _a;
85
- const getAddress = async (latitude, longitude) => {
86
- const params = new URLSearchParams({
87
- "api_key": process.env.NEXT_PUBLIC_GEOCODE_EARTH_API_KEY,
88
- "point.lat": latitude,
89
- "point.lon": longitude,
90
- "boundary.country": "CA",
91
- "layers": "address",
92
- "size": "1"
93
- // Limit to 1 result
94
- });
95
- const reverseGeocoderUrl = `https://api.geocode.earth/v1/reverse?${params}`;
86
+ const getAddress = async (longitude, latitude) => {
87
+ var _a2;
96
88
  try {
97
- const response = await fetch(reverseGeocoderUrl, {
98
- headers: {
99
- "User-Agent": "CDT/1.0 (cdt@email.com)"
100
- }
101
- });
102
- if (!response.ok) {
103
- throw new Error(`HTTP error! status: ${response.status}`);
89
+ const result = await getDetailedAddress([longitude, latitude], organizationCountry);
90
+ const geocodedAddress = (_a2 = result == null ? void 0 : result.properties) == null ? void 0 : _a2.name;
91
+ if (!geocodedAddress) {
92
+ clearExistingBuildingMatches();
93
+ return;
104
94
  }
105
- const data = await response.json();
106
- if (data.features && data.features.length > 0) {
107
- const feature2 = data.features[0];
108
- const properties = feature2.properties;
109
- const geocodedAddress = properties.name;
110
- setAddress(geocodedAddress);
111
- if (geocodedAddress && buildings && buildings.length > 0) {
112
- const normalizedGeocodedAddress = normalizeAddress(geocodedAddress);
113
- const matches = buildings.filter((building) => {
114
- if (!building.buildingAddress) return false;
115
- const normalizedBuildingAddress = normalizeAddress(building.buildingAddress);
116
- return normalizedBuildingAddress === normalizedGeocodedAddress || normalizedBuildingAddress.includes(normalizedGeocodedAddress) || normalizedGeocodedAddress.includes(normalizedBuildingAddress);
117
- });
118
- if (matches.length > 0) {
119
- setMatchingBuildings(matches);
120
- setSelectedMatchingBuildingId(matches[0].id.toString());
121
- setShowExistingBuildings(true);
122
- if (setSelectedItem) {
123
- setSelectedItem(matches[0]);
124
- didSetSelectedItemRef.current = true;
125
- }
126
- } else {
127
- clearExistingBuildingMatches();
95
+ setAddress(geocodedAddress);
96
+ if (buildings && buildings.length > 0) {
97
+ const normalizedGeocodedAddress = normalizeAddress(geocodedAddress);
98
+ const matches = buildings.filter((building) => {
99
+ if (!building.buildingAddress) return false;
100
+ const normalizedBuildingAddress = normalizeAddress(building.buildingAddress);
101
+ return normalizedBuildingAddress === normalizedGeocodedAddress || normalizedBuildingAddress.includes(normalizedGeocodedAddress) || normalizedGeocodedAddress.includes(normalizedBuildingAddress);
102
+ });
103
+ if (matches.length > 0) {
104
+ setMatchingBuildings(matches);
105
+ setSelectedMatchingBuildingId(matches[0].id.toString());
106
+ setShowExistingBuildings(true);
107
+ if (setSelectedItem) {
108
+ setSelectedItem(matches[0]);
109
+ didSetSelectedItemRef.current = true;
128
110
  }
129
111
  } else {
130
112
  clearExistingBuildingMatches();
@@ -139,7 +121,7 @@ function NonDatabaseBuildingPopover({
139
121
  if ((_a = feature.properties) == null ? void 0 : _a.coordinates) {
140
122
  const longitude = feature.properties.coordinates[0];
141
123
  const latitude = feature.properties.coordinates[1];
142
- getAddress(latitude, longitude);
124
+ getAddress(longitude, latitude);
143
125
  }
144
126
  }, [feature, buildings, setSelectedItem, normalizeAddress, clearExistingBuildingMatches]);
145
127
  React.useEffect(() => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../src/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.tsx"],"sourcesContent":["'use client'\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useSession } from 'next-auth/react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { usePermissions } from '../../../../../../store'\r\nimport { toast } from 'sonner'\r\n\r\n// Shadcn Components\r\nimport { Button, Label } from '../../../../../ui/'\r\nimport { PopoverContent } from '../../../../../ui/Popover'\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from '../../../../../ui/Select'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\n// Types / Utilities\r\nimport type { MapGeoJSONFeature } from 'maplibre-gl'\r\nimport { MapContext } from '../../../../../../store'\r\nimport { useMenusContext } from '../../../../../../store'\r\nimport type { Building } from '../../../../../../types/dbTypes'\r\nimport { MarkerManager } from '../../../utils/MarkerManager'\r\n\r\n// Hooks\r\nimport { useCreateBuilding, useBuildings, useBuilding } from '../../../../../../hooks/buildings/buildings'\r\nimport { LoadingSpinner } from '../../../../../ui/LoadingSpinner'\r\n\r\ninterface NonDatabaseBuildingPopoverProps {\r\n feature: MapGeoJSONFeature\r\n isOpen: boolean\r\n onCloseAction: () => void\r\n}\r\n\r\nexport default function NonDatabaseBuildingPopover({\r\n feature,\r\n onCloseAction,\r\n}: NonDatabaseBuildingPopoverProps) {\r\n // Translation\r\n const t = useTranslations('NonDatabaseBuildingPopover')\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const { data: session } = useSession()\r\n const user = session?.user\r\n\r\n const { state: mapState } = React.useContext(MapContext)\r\n const { currentLocation, map } = mapState.map\r\n\r\n const { setSelectedItem } = useMenusContext()\r\n\r\n // Use the create building hook\r\n const { createBuilding, isMutating, createError, createdData } = useCreateBuilding()\r\n \r\n // Get all buildings for searching\r\n const { buildings } = useBuildings()\r\n\r\n const featureProps = feature?.properties || {}\r\n const featureid = feature?.id\r\n const [name, setName] = React.useState('')\r\n const [address, setAddress] = React.useState('')\r\n const [type, setType] = React.useState('')\r\n const [matchingBuildings, setMatchingBuildings] = React.useState<Building[]>([])\r\n const [selectedMatchingBuildingId, setSelectedMatchingBuildingId] = React.useState<string>('')\r\n const [showExistingBuildings, setShowExistingBuildings] = React.useState(false)\r\n const [isAttaching, setIsAttaching] = React.useState(false)\r\n\r\n const { updateBuilding, isMutating: isUpdating } = useBuilding(selectedMatchingBuildingId ? Number(selectedMatchingBuildingId) : null)\r\n\r\n const normalizeAddress = React.useCallback((value: string) => {\r\n return value\r\n .toLowerCase()\r\n .replace(/\\./g, '')\r\n .replace(/,/g, ' ')\r\n .replace(/\\bdr\\b/g, 'drive')\r\n .replace(/\\brd\\b/g, 'road')\r\n .replace(/\\bst\\b/g, 'street')\r\n .replace(/\\bave\\b/g, 'avenue')\r\n .replace(/\\s+/g, ' ')\r\n .trim()\r\n }, [])\r\n\r\n const clearExistingBuildingMatches = React.useCallback(() => {\r\n setMatchingBuildings([])\r\n setSelectedMatchingBuildingId('')\r\n setShowExistingBuildings(false)\r\n\r\n if (didSetSelectedItemRef.current && setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n }, [setSelectedItem])\r\n\r\n // Track if we set the selected item in this component\r\n const didSetSelectedItemRef = React.useRef(false)\r\n\r\n // Cleanup on unmount\r\n React.useEffect(() => {\r\n return () => {\r\n // Clear selected item if we set it\r\n if (didSetSelectedItemRef.current && setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n }\r\n }, [setSelectedItem])\r\n\r\n // Get address and search for matching buildings\r\n React.useEffect(() => {\r\n const getAddress = async (latitude: string, longitude: string) => {\r\n const params = new URLSearchParams({\r\n 'api_key': process.env.NEXT_PUBLIC_GEOCODE_EARTH_API_KEY,\r\n 'point.lat': latitude,\r\n 'point.lon': longitude,\r\n 'boundary.country': 'CA',\r\n 'layers': 'address',\r\n 'size': '1', // Limit to 1 result\r\n })\r\n \r\n const reverseGeocoderUrl = `https://api.geocode.earth/v1/reverse?${params}`\r\n \r\n try {\r\n const response = await fetch(reverseGeocoderUrl, {\r\n headers: {\r\n 'User-Agent': 'CDT/1.0 (cdt@email.com)',\r\n },\r\n })\r\n \r\n if (!response.ok) {\r\n throw new Error(`HTTP error! status: ${response.status}`)\r\n }\r\n\r\n const data = await response.json()\r\n \r\n if (data.features && data.features.length > 0) {\r\n const feature = data.features[0]\r\n const properties = feature.properties\r\n \r\n const geocodedAddress = properties.name\r\n setAddress(geocodedAddress)\r\n \r\n // Search for existing buildings with this address\r\n if (geocodedAddress && buildings && buildings.length > 0) {\r\n const normalizedGeocodedAddress = normalizeAddress(geocodedAddress)\r\n\r\n const matches = buildings.filter((building) => {\r\n if (!building.buildingAddress) return false\r\n\r\n const normalizedBuildingAddress = normalizeAddress(building.buildingAddress)\r\n return (\r\n normalizedBuildingAddress === normalizedGeocodedAddress ||\r\n normalizedBuildingAddress.includes(normalizedGeocodedAddress) ||\r\n normalizedGeocodedAddress.includes(normalizedBuildingAddress)\r\n )\r\n })\r\n \r\n if (matches.length > 0) {\r\n setMatchingBuildings(matches)\r\n setSelectedMatchingBuildingId(matches[0].id.toString())\r\n setShowExistingBuildings(true)\r\n \r\n // Set the first match as the selected item for the update hook\r\n if (setSelectedItem) {\r\n setSelectedItem(matches[0])\r\n didSetSelectedItemRef.current = true\r\n }\r\n } else {\r\n clearExistingBuildingMatches()\r\n }\r\n } else {\r\n clearExistingBuildingMatches()\r\n }\r\n } else {\r\n clearExistingBuildingMatches()\r\n }\r\n }\r\n catch (error) {\r\n console.error('Error fetching municipality and countrySubdivision:', error)\r\n }\r\n }\r\n \r\n if (feature.properties?.coordinates) {\r\n const longitude = feature.properties.coordinates[0]\r\n const latitude = feature.properties.coordinates[1]\r\n getAddress(latitude, longitude)\r\n }\r\n }, [feature, buildings, setSelectedItem, normalizeAddress, clearExistingBuildingMatches])\r\n\r\n React.useEffect(() => {\r\n if (!setSelectedItem || !selectedMatchingBuildingId) return\r\n\r\n const selectedBuilding = matchingBuildings.find(\r\n building => building.id.toString() === selectedMatchingBuildingId,\r\n )\r\n\r\n if (!selectedBuilding) return\r\n\r\n setSelectedItem(selectedBuilding)\r\n didSetSelectedItemRef.current = true\r\n }, [matchingBuildings, selectedMatchingBuildingId, setSelectedItem])\r\n\r\n // Fallbacks from feature or map state\r\n const buildingCountrySubdivision = featureProps.de_ao_prov || currentLocation.countrySubdivision || null\r\n const buildingMunicipality = featureProps.de_ao_city || currentLocation.municipality || null\r\n const buildingPostalCode = featureProps.de_ao_post || currentLocation.postalCode || null\r\n const site = currentLocation.site || null\r\n const buildingOsmId = featureid.toString()\r\n\r\n // Create MarkerManager instance\r\n const markerManagerRef = React.useRef<MarkerManager | null>(null)\r\n\r\n // Initialize MarkerManager\r\n React.useEffect(() => {\r\n if (!markerManagerRef.current) {\r\n markerManagerRef.current = new MarkerManager()\r\n }\r\n\r\n // Cleanup on unmount\r\n return () => {\r\n if (markerManagerRef.current) {\r\n markerManagerRef.current.destroy()\r\n markerManagerRef.current = null\r\n }\r\n }\r\n }, [])\r\n\r\n // Get coordinates data from feature\r\n const [coordinates, setCoordinates] = React.useState(featureProps.coordinates || null)\r\n\r\n // Listen for marker coordinate changes\r\n React.useEffect(() => {\r\n if (!markerManagerRef.current) return\r\n\r\n const cleanup = markerManagerRef.current.onMoved((event) => {\r\n const newCoordinates = event.detail.coordinates\r\n if (newCoordinates) {\r\n setCoordinates(newCoordinates)\r\n }\r\n })\r\n\r\n return cleanup\r\n }, [])\r\n\r\n const handleBuildingNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n setName(event.target.value)\r\n }\r\n\r\n const handleAddressChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n setAddress(event.target.value)\r\n }\r\n\r\n const handleBuildingTypeChange = (event: React.ChangeEvent<HTMLSelectElement>) => {\r\n setType(event.target.value)\r\n }\r\n\r\n const selectedMatchingBuilding = matchingBuildings.find(\r\n building => building.id.toString() === selectedMatchingBuildingId,\r\n )\r\n\r\n const handleAttachExistingBuilding = async (building: Building) => {\r\n setIsAttaching(true)\r\n \r\n try {\r\n // Add OSM ID to existing building\r\n const result = await updateBuilding({\r\n buildingOsmId,\r\n // Set default storey number of 2 if building doesn't have one\r\n ...(building.buildingStoreyNum == null && { buildingStoreyNum: 2 })\r\n })\r\n \r\n toast.success(t('toastAttachSuccess'))\r\n \r\n // Clear the selected item after successful update\r\n if (setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n \r\n // Close the popover\r\n onCloseAction()\r\n \r\n } catch (error) {\r\n console.error('Error attaching building:', error)\r\n \r\n if (error?.status !== 401) {\r\n toast.error(t('toastAttachError'))\r\n }\r\n } finally {\r\n setIsAttaching(false)\r\n }\r\n }\r\n\r\n const handleCreateNewBuilding = async (event: React.FormEvent) => {\r\n event.preventDefault()\r\n\r\n // Get final values (prioritize user input, then existing data)\r\n const buildingName = name.trim() || featureProps._name || ''\r\n const finalAddress = address.trim() || address || ''\r\n\r\n if (!user?.organizationId) {\r\n toast.error(t('userNotFound'))\r\n return\r\n }\r\n\r\n // Use updated coordinates from marker if available\r\n const buildingCoordinates = coordinates || [featureProps.longitude, featureProps.latitude]\r\n\r\n const newBuilding: Partial<Building> = {\r\n buildingName,\r\n buildingAddress: finalAddress,\r\n buildingType: [type || 'Other'],\r\n buildingOsmId,\r\n buildingLatitude: buildingCoordinates ? buildingCoordinates[1] : null,\r\n buildingLongitude: buildingCoordinates ? buildingCoordinates[0] : null,\r\n buildingCountrySubdivision,\r\n buildingMunicipality,\r\n buildingPostalCode,\r\n }\r\n\r\n try {\r\n const result = await createBuilding({\r\n buildingData: newBuilding,\r\n organizationId: user.organizationId.toString(),\r\n })\r\n\r\n // Remove marker after creating building\r\n if (markerManagerRef.current) {\r\n markerManagerRef.current.remove()\r\n }\r\n \r\n toast.success(t('toastSuccess'))\r\n \r\n // Close the popover on success\r\n onCloseAction()\r\n }\r\n catch (error) {\r\n console.error('Error creating building:', error)\r\n toast.error(t('toastError'))\r\n }\r\n }\r\n\r\n const handleLocationEdit = () => {\r\n // Create marker at current coordinates with editing enabled\r\n if (markerManagerRef.current && coordinates && map) {\r\n console.log('Creating editable marker at coordinates:', coordinates)\r\n markerManagerRef.current.create(coordinates as [number, number], map, {\r\n editing: true })\r\n }\r\n else {\r\n console.warn('Cannot create marker: missing coordinates or map instance')\r\n }\r\n }\r\n\r\n return (\r\n <PopoverContent className=\"w-64 -m-1\" side=\"top\">\r\n <form onSubmit={handleCreateNewBuilding}>\r\n <div className=\"grid gap-4\">\r\n <Button\r\n type=\"button\"\r\n onClick={onCloseAction}\r\n variant=\"ghost\"\r\n className=\"absolute top-1 right-2 p-1 text-muted-foreground hover:text-foreground\"\r\n aria-label={t('closeAriaLabel')}\r\n >\r\n <LR.X className=\"w-4 h-4\" />\r\n </Button>\r\n \r\n {/* Show existing building if match found */}\r\n {showExistingBuildings && matchingBuildings.length > 0 && (\r\n <div className=\"space-y-1 mt-6\">\r\n <div className=\"text-xs text-muted-foreground\">\r\n {t('existingBuildingFound')}\r\n </div>\r\n <div className=\"flex flex-col justify-between gap-2 p-2 bg-muted/50 border rounded-lg\">\r\n <div className=\"grid gap-1\">\r\n <Label htmlFor=\"existing-building-select\" className=\"text-xs text-muted-foreground\">\r\n {t('selectExistingBuildingLabel')}\r\n </Label>\r\n <Select\r\n value={selectedMatchingBuildingId}\r\n onValueChange={setSelectedMatchingBuildingId}\r\n >\r\n <SelectTrigger id=\"existing-building-select\" className=\"h-9 w-full\">\r\n <SelectValue placeholder={t('selectExistingBuildingPlaceholder')} />\r\n </SelectTrigger>\r\n <SelectContent>\r\n {matchingBuildings.map((building) => (\r\n <SelectItem key={building.id} value={building.id.toString()}>\r\n {building.buildingName || building.buildingAddress || `${t('na')} (${building.id})`}\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className='w-full'\r\n onClick={() => selectedMatchingBuilding && handleAttachExistingBuilding(selectedMatchingBuilding)}\r\n disabled={isAttaching || isUpdating || !selectedMatchingBuilding}\r\n >\r\n {(isAttaching || isUpdating) ? (\r\n <>\r\n <LoadingSpinner />\r\n <span>{t('attaching')}</span>\r\n </>\r\n ) : (\r\n <>\r\n <LR.Link />\r\n {t('attachBuilding')}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n \r\n <div className=\"space-y-4\">\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-name\" className=\"text-xs text-muted-foreground\">\r\n {t('nameLabel')}\r\n </Label>\r\n <input\r\n id=\"building-name\"\r\n value={name}\r\n onChange={handleBuildingNameChange}\r\n placeholder={name || t('namePlaceholder')}\r\n className={`font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1 ${name ? 'placeholder:text-foreground' : 'placeholder:text-muted-foreground'}`}\r\n aria-label={t('nameInputAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n />\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-address\" className=\"text-xs text-muted-foreground\">\r\n {t('addressLabel')}\r\n </Label>\r\n <input\r\n id=\"building-address\"\r\n value={address}\r\n onChange={handleAddressChange}\r\n placeholder={address || t('addressPlaceholder')}\r\n className={`font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1 ${address ? 'placeholder:text-foreground' : 'placeholder:text-muted-foreground'}`}\r\n aria-label={t('addressAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n />\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-type\" className=\"text-xs text-muted-foreground\">\r\n {t('typeLabel')}\r\n </Label>\r\n <select\r\n id=\"building-type\"\r\n value={type}\r\n onChange={handleBuildingTypeChange}\r\n className=\"font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1\"\r\n aria-label={t('typeAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n >\r\n <option value=\"\">{t('defaultOption')}</option>\r\n <option value=\"Townhouses\">{t('townhouse')}</option>\r\n <option value=\"<4 Storey MURB\">{t('4MURB')}</option>\r\n <option value=\"4+ Storey MURB\">{t('4PlusMURB')}</option>\r\n <option value=\"Stacked Townhouses\">{t('stackedTownhouses')}</option>\r\n <option value=\"Detached\">{t('detached')}</option>\r\n <option value=\"Semi Detached\">{t('semiDetached')}</option>\r\n <option value=\"Other\">{t('other')}</option>\r\n </select>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2 py-2 px-1\">\r\n <Label className=\"text-xs text-muted-foreground min-w-fit\">{t('osmId')}</Label>\r\n <span className=\"text-sm font-medium text-foreground\">{buildingOsmId ?? t('na')}</span>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-3 justify-center mt-4\">\r\n <Button\r\n type=\"button\"\r\n variant=\"outline\"\r\n aria-label=\"Edit Location\"\r\n title=\"Edit Location\"\r\n onClick={handleLocationEdit}\r\n disabled={!ability.can('update', 'Building')}\r\n >\r\n <LR.LocationEdit className=\"w-4 h-4\" />\r\n </Button>\r\n\r\n <Button\r\n type=\"submit\"\r\n variant=\"outline\"\r\n aria-label={t('addBuilding')}\r\n title={t('addBuilding')}\r\n disabled={isMutating || !ability.can('create', 'Building')}\r\n >\r\n {isMutating\r\n ? (\r\n <>``\r\n <LoadingSpinner />\r\n <span className=\"text-sm\">{t('creating')}</span>\r\n </>\r\n )\r\n : (\r\n <>\r\n <LR.Building2 className=\"w-4 h-4\" />\r\n <span className=\"text-sm\">{t('addBuilding')}</span>\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </form>\r\n </PopoverContent>\r\n )\r\n}"],"mappings":"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","names":["feature"]}
1
+ {"version":3,"sources":["../../../../../../../../src/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.tsx"],"sourcesContent":["'use client'\r\n// Dependencies\r\nimport * as React from 'react'\r\nimport { useSession } from 'next-auth/react'\r\nimport { useTranslations } from 'next-intl'\r\nimport { usePermissions } from '../../../../../../store'\r\nimport { toast } from 'sonner'\r\n\r\n// Shadcn Components\r\nimport { Button, Label } from '../../../../../ui/'\r\nimport { PopoverContent } from '../../../../../ui/Popover'\r\nimport {\r\n Select,\r\n SelectContent,\r\n SelectItem,\r\n SelectTrigger,\r\n SelectValue,\r\n} from '../../../../../ui/Select'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\n// Types / Utilities\r\nimport type { MapGeoJSONFeature } from 'maplibre-gl'\r\nimport { MapContext } from '../../../../../../store'\r\nimport { useMenusContext } from '../../../../../../store'\r\nimport type { Building } from '../../../../../../types/dbTypes'\r\nimport { MarkerManager } from '../../../utils/MarkerManager'\r\nimport { getDetailedAddress } from '../../../utils/geocoder'\r\n\r\n// Hooks\r\nimport { useCreateBuilding, useBuildings, useBuilding } from '../../../../../../hooks/buildings/buildings'\r\nimport { LoadingSpinner } from '../../../../../ui/LoadingSpinner'\r\n\r\ninterface NonDatabaseBuildingPopoverProps {\r\n feature: MapGeoJSONFeature\r\n isOpen: boolean\r\n onCloseAction: () => void\r\n}\r\n\r\nexport default function NonDatabaseBuildingPopover({\r\n feature,\r\n onCloseAction,\r\n}: NonDatabaseBuildingPopoverProps) {\r\n // Translation\r\n const t = useTranslations('NonDatabaseBuildingPopover')\r\n // Permissions\r\n const { ability } = usePermissions()\r\n\r\n const { data: session } = useSession()\r\n const user = session?.user\r\n\r\n const { state: mapState } = React.useContext(MapContext)\r\n const { currentLocation, map, organizationCountry } = mapState.map\r\n\r\n const { setSelectedItem } = useMenusContext()\r\n\r\n // Use the create building hook\r\n const { createBuilding, isMutating, createError, createdData } = useCreateBuilding()\r\n\r\n // Get all buildings for searching\r\n const { buildings } = useBuildings()\r\n\r\n const featureProps = feature?.properties || {}\r\n const featureid = feature?.id\r\n const [name, setName] = React.useState('')\r\n const [address, setAddress] = React.useState('')\r\n const [type, setType] = React.useState('')\r\n const [matchingBuildings, setMatchingBuildings] = React.useState<Building[]>([])\r\n const [selectedMatchingBuildingId, setSelectedMatchingBuildingId] = React.useState<string>('')\r\n const [showExistingBuildings, setShowExistingBuildings] = React.useState(false)\r\n const [isAttaching, setIsAttaching] = React.useState(false)\r\n\r\n const { updateBuilding, isMutating: isUpdating } = useBuilding(selectedMatchingBuildingId ? Number(selectedMatchingBuildingId) : null)\r\n\r\n const normalizeAddress = React.useCallback((value: string) => {\r\n return value\r\n .toLowerCase()\r\n .replace(/\\./g, '')\r\n .replace(/,/g, ' ')\r\n .replace(/\\bdr\\b/g, 'drive')\r\n .replace(/\\brd\\b/g, 'road')\r\n .replace(/\\bst\\b/g, 'street')\r\n .replace(/\\bave\\b/g, 'avenue')\r\n .replace(/\\s+/g, ' ')\r\n .trim()\r\n }, [])\r\n\r\n const clearExistingBuildingMatches = React.useCallback(() => {\r\n setMatchingBuildings([])\r\n setSelectedMatchingBuildingId('')\r\n setShowExistingBuildings(false)\r\n\r\n if (didSetSelectedItemRef.current && setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n }, [setSelectedItem])\r\n\r\n // Track if we set the selected item in this component\r\n const didSetSelectedItemRef = React.useRef(false)\r\n\r\n // Cleanup on unmount\r\n React.useEffect(() => {\r\n return () => {\r\n // Clear selected item if we set it\r\n if (didSetSelectedItemRef.current && setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n }\r\n }, [setSelectedItem])\r\n\r\n // Get address and search for matching buildings\r\n React.useEffect(() => {\r\n const getAddress = async (longitude: number, latitude: number) => {\r\n try {\r\n // Reverse geocode through the shared provider (Geocode Earth / self-hosted\r\n // Pelias, falling back to public OSM) so this stays in sync with the geocoder.\r\n const result = await getDetailedAddress([longitude, latitude], organizationCountry)\r\n const geocodedAddress = result?.properties?.name as string | undefined\r\n\r\n if (!geocodedAddress) {\r\n clearExistingBuildingMatches()\r\n return\r\n }\r\n\r\n setAddress(geocodedAddress)\r\n\r\n // Search for existing buildings with this address\r\n if (buildings && buildings.length > 0) {\r\n const normalizedGeocodedAddress = normalizeAddress(geocodedAddress)\r\n\r\n const matches = buildings.filter((building) => {\r\n if (!building.buildingAddress) return false\r\n\r\n const normalizedBuildingAddress = normalizeAddress(building.buildingAddress)\r\n return (\r\n normalizedBuildingAddress === normalizedGeocodedAddress ||\r\n normalizedBuildingAddress.includes(normalizedGeocodedAddress) ||\r\n normalizedGeocodedAddress.includes(normalizedBuildingAddress)\r\n )\r\n })\r\n\r\n if (matches.length > 0) {\r\n setMatchingBuildings(matches)\r\n setSelectedMatchingBuildingId(matches[0].id.toString())\r\n setShowExistingBuildings(true)\r\n\r\n // Set the first match as the selected item for the update hook\r\n if (setSelectedItem) {\r\n setSelectedItem(matches[0])\r\n didSetSelectedItemRef.current = true\r\n }\r\n } else {\r\n clearExistingBuildingMatches()\r\n }\r\n } else {\r\n clearExistingBuildingMatches()\r\n }\r\n }\r\n catch (error) {\r\n console.error('Error fetching municipality and countrySubdivision:', error)\r\n }\r\n }\r\n\r\n if (feature.properties?.coordinates) {\r\n const longitude = feature.properties.coordinates[0]\r\n const latitude = feature.properties.coordinates[1]\r\n getAddress(longitude, latitude)\r\n }\r\n }, [feature, buildings, setSelectedItem, normalizeAddress, clearExistingBuildingMatches])\r\n\r\n React.useEffect(() => {\r\n if (!setSelectedItem || !selectedMatchingBuildingId) return\r\n\r\n const selectedBuilding = matchingBuildings.find(\r\n building => building.id.toString() === selectedMatchingBuildingId,\r\n )\r\n\r\n if (!selectedBuilding) return\r\n\r\n setSelectedItem(selectedBuilding)\r\n didSetSelectedItemRef.current = true\r\n }, [matchingBuildings, selectedMatchingBuildingId, setSelectedItem])\r\n\r\n // Fallbacks from feature or map state\r\n const buildingCountrySubdivision = featureProps.de_ao_prov || currentLocation.countrySubdivision || null\r\n const buildingMunicipality = featureProps.de_ao_city || currentLocation.municipality || null\r\n const buildingPostalCode = featureProps.de_ao_post || currentLocation.postalCode || null\r\n const site = currentLocation.site || null\r\n const buildingOsmId = featureid.toString()\r\n\r\n // Create MarkerManager instance\r\n const markerManagerRef = React.useRef<MarkerManager | null>(null)\r\n\r\n // Initialize MarkerManager\r\n React.useEffect(() => {\r\n if (!markerManagerRef.current) {\r\n markerManagerRef.current = new MarkerManager()\r\n }\r\n\r\n // Cleanup on unmount\r\n return () => {\r\n if (markerManagerRef.current) {\r\n markerManagerRef.current.destroy()\r\n markerManagerRef.current = null\r\n }\r\n }\r\n }, [])\r\n\r\n // Get coordinates data from feature\r\n const [coordinates, setCoordinates] = React.useState(featureProps.coordinates || null)\r\n\r\n // Listen for marker coordinate changes\r\n React.useEffect(() => {\r\n if (!markerManagerRef.current) return\r\n\r\n const cleanup = markerManagerRef.current.onMoved((event) => {\r\n const newCoordinates = event.detail.coordinates\r\n if (newCoordinates) {\r\n setCoordinates(newCoordinates)\r\n }\r\n })\r\n\r\n return cleanup\r\n }, [])\r\n\r\n const handleBuildingNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n setName(event.target.value)\r\n }\r\n\r\n const handleAddressChange = (event: React.ChangeEvent<HTMLInputElement>) => {\r\n setAddress(event.target.value)\r\n }\r\n\r\n const handleBuildingTypeChange = (event: React.ChangeEvent<HTMLSelectElement>) => {\r\n setType(event.target.value)\r\n }\r\n\r\n const selectedMatchingBuilding = matchingBuildings.find(\r\n building => building.id.toString() === selectedMatchingBuildingId,\r\n )\r\n\r\n const handleAttachExistingBuilding = async (building: Building) => {\r\n setIsAttaching(true)\r\n\r\n try {\r\n // Add OSM ID to existing building\r\n const result = await updateBuilding({\r\n buildingOsmId,\r\n // Set default storey number of 2 if building doesn't have one\r\n ...(building.buildingStoreyNum == null && { buildingStoreyNum: 2 })\r\n })\r\n\r\n toast.success(t('toastAttachSuccess'))\r\n\r\n // Clear the selected item after successful update\r\n if (setSelectedItem) {\r\n setSelectedItem(null)\r\n didSetSelectedItemRef.current = false\r\n }\r\n\r\n // Close the popover\r\n onCloseAction()\r\n\r\n } catch (error) {\r\n console.error('Error attaching building:', error)\r\n\r\n if (error?.status !== 401) {\r\n toast.error(t('toastAttachError'))\r\n }\r\n } finally {\r\n setIsAttaching(false)\r\n }\r\n }\r\n\r\n const handleCreateNewBuilding = async (event: React.FormEvent) => {\r\n event.preventDefault()\r\n\r\n // Get final values (prioritize user input, then existing data)\r\n const buildingName = name.trim() || featureProps._name || ''\r\n const finalAddress = address.trim() || address || ''\r\n\r\n if (!user?.organizationId) {\r\n toast.error(t('userNotFound'))\r\n return\r\n }\r\n\r\n // Use updated coordinates from marker if available\r\n const buildingCoordinates = coordinates || [featureProps.longitude, featureProps.latitude]\r\n\r\n const newBuilding: Partial<Building> = {\r\n buildingName,\r\n buildingAddress: finalAddress,\r\n buildingType: [type || 'Other'],\r\n buildingOsmId,\r\n buildingLatitude: buildingCoordinates ? buildingCoordinates[1] : null,\r\n buildingLongitude: buildingCoordinates ? buildingCoordinates[0] : null,\r\n buildingCountrySubdivision,\r\n buildingMunicipality,\r\n buildingPostalCode,\r\n }\r\n\r\n try {\r\n const result = await createBuilding({\r\n buildingData: newBuilding,\r\n organizationId: user.organizationId.toString(),\r\n })\r\n\r\n // Remove marker after creating building\r\n if (markerManagerRef.current) {\r\n markerManagerRef.current.remove()\r\n }\r\n\r\n toast.success(t('toastSuccess'))\r\n\r\n // Close the popover on success\r\n onCloseAction()\r\n }\r\n catch (error) {\r\n console.error('Error creating building:', error)\r\n toast.error(t('toastError'))\r\n }\r\n }\r\n\r\n const handleLocationEdit = () => {\r\n // Create marker at current coordinates with editing enabled\r\n if (markerManagerRef.current && coordinates && map) {\r\n console.log('Creating editable marker at coordinates:', coordinates)\r\n markerManagerRef.current.create(coordinates as [number, number], map, {\r\n editing: true\r\n })\r\n }\r\n else {\r\n console.warn('Cannot create marker: missing coordinates or map instance')\r\n }\r\n }\r\n\r\n return (\r\n <PopoverContent className=\"w-64 -m-1\" side=\"top\">\r\n <form onSubmit={handleCreateNewBuilding}>\r\n <div className=\"grid gap-4\">\r\n <Button\r\n type=\"button\"\r\n onClick={onCloseAction}\r\n variant=\"ghost\"\r\n className=\"absolute top-1 right-2 p-1 text-muted-foreground hover:text-foreground\"\r\n aria-label={t('closeAriaLabel')}\r\n >\r\n <LR.X className=\"w-4 h-4\" />\r\n </Button>\r\n\r\n {/* Show existing building if match found */}\r\n {showExistingBuildings && matchingBuildings.length > 0 && (\r\n <div className=\"space-y-1 mt-6\">\r\n <div className=\"text-xs text-muted-foreground\">\r\n {t('existingBuildingFound')}\r\n </div>\r\n <div className=\"flex flex-col justify-between gap-2 p-2 bg-muted/50 border rounded-lg\">\r\n <div className=\"grid gap-1\">\r\n <Label htmlFor=\"existing-building-select\" className=\"text-xs text-muted-foreground\">\r\n {t('selectExistingBuildingLabel')}\r\n </Label>\r\n <Select\r\n value={selectedMatchingBuildingId}\r\n onValueChange={setSelectedMatchingBuildingId}\r\n >\r\n <SelectTrigger id=\"existing-building-select\" className=\"h-9 w-full\">\r\n <SelectValue placeholder={t('selectExistingBuildingPlaceholder')} />\r\n </SelectTrigger>\r\n <SelectContent>\r\n {matchingBuildings.map((building) => (\r\n <SelectItem key={building.id} value={building.id.toString()}>\r\n {building.buildingName || building.buildingAddress || `${t('na')} (${building.id})`}\r\n </SelectItem>\r\n ))}\r\n </SelectContent>\r\n </Select>\r\n </div>\r\n <Button\r\n variant=\"outline\"\r\n size=\"sm\"\r\n className='w-full'\r\n onClick={() => selectedMatchingBuilding && handleAttachExistingBuilding(selectedMatchingBuilding)}\r\n disabled={isAttaching || isUpdating || !selectedMatchingBuilding}\r\n >\r\n {(isAttaching || isUpdating) ? (\r\n <>\r\n <LoadingSpinner />\r\n <span>{t('attaching')}</span>\r\n </>\r\n ) : (\r\n <>\r\n <LR.Link />\r\n {t('attachBuilding')}\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </div>\r\n )}\r\n\r\n <div className=\"space-y-4\">\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-name\" className=\"text-xs text-muted-foreground\">\r\n {t('nameLabel')}\r\n </Label>\r\n <input\r\n id=\"building-name\"\r\n value={name}\r\n onChange={handleBuildingNameChange}\r\n placeholder={name || t('namePlaceholder')}\r\n className={`font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1 ${name ? 'placeholder:text-foreground' : 'placeholder:text-muted-foreground'}`}\r\n aria-label={t('nameInputAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n />\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-address\" className=\"text-xs text-muted-foreground\">\r\n {t('addressLabel')}\r\n </Label>\r\n <input\r\n id=\"building-address\"\r\n value={address}\r\n onChange={handleAddressChange}\r\n placeholder={address || t('addressPlaceholder')}\r\n className={`font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1 ${address ? 'placeholder:text-foreground' : 'placeholder:text-muted-foreground'}`}\r\n aria-label={t('addressAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n />\r\n </div>\r\n\r\n <div className=\"grid gap-2\">\r\n <Label htmlFor=\"building-type\" className=\"text-xs text-muted-foreground\">\r\n {t('typeLabel')}\r\n </Label>\r\n <select\r\n id=\"building-type\"\r\n value={type}\r\n onChange={handleBuildingTypeChange}\r\n className=\"font-medium leading-none bg-transparent border-b border-gray-300 focus:outline-none focus:border-primary px-1 py-1\"\r\n aria-label={t('typeAriaLabel')}\r\n required\r\n disabled={!ability.can('create', 'Building')}\r\n >\r\n <option value=\"\">{t('defaultOption')}</option>\r\n <option value=\"Townhouses\">{t('townhouse')}</option>\r\n <option value=\"<4 Storey MURB\">{t('4MURB')}</option>\r\n <option value=\"4+ Storey MURB\">{t('4PlusMURB')}</option>\r\n <option value=\"Stacked Townhouses\">{t('stackedTownhouses')}</option>\r\n <option value=\"Detached\">{t('detached')}</option>\r\n <option value=\"Semi Detached\">{t('semiDetached')}</option>\r\n <option value=\"Other\">{t('other')}</option>\r\n </select>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2 py-2 px-1\">\r\n <Label className=\"text-xs text-muted-foreground min-w-fit\">{t('osmId')}</Label>\r\n <span className=\"text-sm font-medium text-foreground\">{buildingOsmId ?? t('na')}</span>\r\n </div>\r\n </div>\r\n\r\n <div className=\"flex items-center gap-3 justify-center mt-4\">\r\n <Button\r\n type=\"button\"\r\n variant=\"outline\"\r\n aria-label=\"Edit Location\"\r\n title=\"Edit Location\"\r\n onClick={handleLocationEdit}\r\n disabled={!ability.can('update', 'Building')}\r\n >\r\n <LR.LocationEdit className=\"w-4 h-4\" />\r\n </Button>\r\n\r\n <Button\r\n type=\"submit\"\r\n variant=\"outline\"\r\n aria-label={t('addBuilding')}\r\n title={t('addBuilding')}\r\n disabled={isMutating || !ability.can('create', 'Building')}\r\n >\r\n {isMutating\r\n ? (\r\n <>``\r\n <LoadingSpinner />\r\n <span className=\"text-sm\">{t('creating')}</span>\r\n </>\r\n )\r\n : (\r\n <>\r\n <LR.Building2 className=\"w-4 h-4\" />\r\n <span className=\"text-sm\">{t('addBuilding')}</span>\r\n </>\r\n )}\r\n </Button>\r\n </div>\r\n </form>\r\n </PopoverContent>\r\n )\r\n}"],"mappings":"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","names":["_a"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/src/MapLayers/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAmC9B,eAAO,MAAM,SAAS,yBAYrB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/src/MapLayers/index.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAsB9B,eAAO,MAAM,SAAS,yBAYrB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../src/core/components/viewers/map/src/MapLayers/index.tsx"],"sourcesContent":["'use client'\r\n\r\nimport * as React from 'react'\r\nimport dynamic from 'next/dynamic'\r\n\r\nimport { CountryLayer } from './src/CountryLayer'\r\nimport { CommentLayer } from './src/CommentLayer'\r\nimport { SensorLayers } from './src/SensorsLayer'\r\nimport { FileLayers } from './src/FileLayer'\r\nimport { OpenDataLayers } from './src/OpenDataLayer/src'\r\nimport { BuildingLayer } from './src/BuildingLayers'\r\nimport { useBimContext } from '../../../../../store'\r\n\r\n// Audit Phase 1.A (F-1b): lazy-load the on-map BIM custom layer.\r\n// BimLayer statically imports @thatopen/components, @thatopen/components-front,\r\n// @thatopen/fragments, and web-ifc — together about 800 KB gzipped on the\r\n// initial bundle. F-1 alone could not move them because BimLayer was rendered\r\n// eagerly inside MapLayers, keeping the static import chain alive.\r\n//\r\n// Strategy: render <LazyBimLayer /> through a tiny gate component that\r\n// consumes only the BIM context. While the user has no BIM models on the\r\n// map, the gate returns null and the dynamic chunk is never fetched. The\r\n// first time the user adds a model (dispatch ADD_BIM_MODEL_TO_MAP), the\r\n// gate flips, the chunk downloads (~456 KB gzipped, cached thereafter),\r\n// and BimLayer mounts. The gate isolates context consumption so MapLayers\r\n// itself does not re-render on every BIM state change.\r\nconst LazyBimLayer = dynamic(\r\n () => import('./src/BimLayer').then(m => ({ default: m.BimLayer })),\r\n { ssr: false },\r\n)\r\n\r\nfunction BimLayerGate() {\r\n const { state: bimState } = useBimContext()\r\n if (bimState.bim.bimModelsAddedToMap.length === 0) return null\r\n return <LazyBimLayer />\r\n}\r\n\r\nexport const MapLayers = () => {\r\n return (\r\n <>\r\n <CountryLayer />\r\n <OpenDataLayers />\r\n <BuildingLayer />\r\n <CommentLayer />\r\n <SensorLayers />\r\n <FileLayers />\r\n <BimLayerGate />\r\n </>\r\n )\r\n}\r\n"],"mappings":";AAkCS,SAKL,UALK,KAKL,YALK;AA/BT,OAAO,aAAa;AAEpB,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAC3B,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAe9B,MAAM,eAAe;AAAA,EACnB,MAAM,OAAO,gBAAgB,EAAE,KAAK,QAAM,EAAE,SAAS,EAAE,SAAS,EAAE;AAAA,EAClE,EAAE,KAAK,MAAM;AACf;AAEA,SAAS,eAAe;AACtB,QAAM,EAAE,OAAO,SAAS,IAAI,cAAc;AAC1C,MAAI,SAAS,IAAI,oBAAoB,WAAW,EAAG,QAAO;AAC1D,SAAO,oBAAC,gBAAa;AACvB;AAEO,MAAM,YAAY,MAAM;AAC7B,SACE,iCACE;AAAA,wBAAC,gBAAa;AAAA,IACd,oBAAC,kBAAe;AAAA,IAChB,oBAAC,iBAAc;AAAA,IACf,oBAAC,gBAAa;AAAA,IACd,oBAAC,gBAAa;AAAA,IACd,oBAAC,cAAW;AAAA,IACZ,oBAAC,gBAAa;AAAA,KAChB;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../../../../src/core/components/viewers/map/src/MapLayers/index.tsx"],"sourcesContent":["\r\n\r\n\r\n\r\n'use client'\r\n\r\nimport * as React from 'react'\r\nimport dynamic from 'next/dynamic'\r\n\r\nimport { CountryLayer } from './src/CountryLayer'\r\nimport { CommentLayer } from './src/CommentLayer'\r\nimport { SensorLayers } from './src/SensorsLayer'\r\nimport { FileLayers } from './src/FileLayer'\r\nimport { OpenDataLayers } from './src/OpenDataLayer/src'\r\nimport { BuildingLayer } from './src/BuildingLayers'\r\nimport { useBimContext } from '../../../../../store'\r\n\r\nconst LazyBimLayer = dynamic(\r\n () => import('./src/BimLayer').then(m => ({ default: m.BimLayer })),\r\n { ssr: false },\r\n)\r\n\r\nfunction BimLayerGate() {\r\n const { state: bimState } = useBimContext()\r\n if (bimState.bim.bimModelsAddedToMap.length === 0) return null\r\n return <LazyBimLayer />\r\n}\r\n\r\nexport const MapLayers = () => {\r\n return (\r\n <>\r\n <CountryLayer />\r\n <OpenDataLayers />\r\n <BuildingLayer />\r\n <CommentLayer />\r\n <SensorLayers />\r\n <FileLayers />\r\n <BimLayerGate />\r\n </>\r\n )\r\n}\r\n"],"mappings":";AAyBS,SAKL,UALK,KAKL,YALK;AAlBT,OAAO,aAAa;AAEpB,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAC7B,SAAS,kBAAkB;AAC3B,SAAS,sBAAsB;AAC/B,SAAS,qBAAqB;AAC9B,SAAS,qBAAqB;AAE9B,MAAM,eAAe;AAAA,EACnB,MAAM,OAAO,gBAAgB,EAAE,KAAK,QAAM,EAAE,SAAS,EAAE,SAAS,EAAE;AAAA,EAClE,EAAE,KAAK,MAAM;AACf;AAEA,SAAS,eAAe;AACtB,QAAM,EAAE,OAAO,SAAS,IAAI,cAAc;AAC1C,MAAI,SAAS,IAAI,oBAAoB,WAAW,EAAG,QAAO;AAC1D,SAAO,oBAAC,gBAAa;AACvB;AAEO,MAAM,YAAY,MAAM;AAC7B,SACE,iCACE;AAAA,wBAAC,gBAAa;AAAA,IACd,oBAAC,kBAAe;AAAA,IAChB,oBAAC,iBAAc;AAAA,IACf,oBAAC,gBAAa;AAAA,IACd,oBAAC,gBAAa;AAAA,IACd,oBAAC,cAAW;AAAA,IACZ,oBAAC,gBAAa;AAAA,KAChB;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/BimLayer/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,eAAO,MAAM,QAAQ,yBAkbpB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/BimLayer/index.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,eAAO,MAAM,QAAQ,yBAwdpB,CAAC"}
@@ -147,6 +147,16 @@ const BimLayer = () => {
147
147
  let model = null;
148
148
  let lastAppliedRotation = originalRotation;
149
149
  let lastLodUpdate = 0;
150
+ let cachedTerrainElev = 0;
151
+ let lastMoveTime = performance.now();
152
+ const SETTLE_MS = 1e3;
153
+ const recomputeTerrainElev = () => {
154
+ const { lng, lat } = extractPositionAndRotation(bimFile, building);
155
+ if (lng !== null && lat !== null) {
156
+ const e = map.queryTerrainElevation([lng, lat]);
157
+ if (e !== null && e !== void 0) cachedTerrainElev = e;
158
+ }
159
+ };
150
160
  let onMapMove;
151
161
  let onMapMoveEnd;
152
162
  const renderCamera = new THREE.PerspectiveCamera();
@@ -168,6 +178,8 @@ const BimLayer = () => {
168
178
  this.scene = scene;
169
179
  loadModel(buildingModel, fragments, scene, map2, lodCamera).then((loaded) => {
170
180
  model = loaded;
181
+ lastMoveTime = performance.now();
182
+ recomputeTerrainElev();
171
183
  map2.triggerRepaint();
172
184
  });
173
185
  if (!rendererRef.current) {
@@ -180,9 +192,12 @@ const BimLayer = () => {
180
192
  }
181
193
  this.renderer = rendererRef.current;
182
194
  onMapMove = () => {
195
+ lastMoveTime = performance.now();
183
196
  };
184
197
  onMapMoveEnd = () => {
198
+ lastMoveTime = performance.now();
185
199
  if (model) fragments.core.update(true);
200
+ recomputeTerrainElev();
186
201
  map2.triggerRepaint();
187
202
  };
188
203
  map2.on("move", onMapMove);
@@ -223,7 +238,7 @@ const BimLayer = () => {
223
238
  if (te !== void 0) modelElevation = te;
224
239
  }
225
240
  const modelOrigin = [modelLongitude, modelLatitude];
226
- const terrainElev = (_a = map.queryTerrainElevation([modelLongitude, modelLatitude])) != null ? _a : 0;
241
+ const terrainElev = editingBimModelRef.current === bimFile.name ? (_a = map.queryTerrainElevation([modelLongitude, modelLatitude])) != null ? _a : cachedTerrainElev : cachedTerrainElev;
227
242
  const modelAltitude = modelElevation + terrainElev;
228
243
  const scaling = 1;
229
244
  const modelMatrix = map.transform.getMatrixForModel(modelOrigin, modelAltitude);
@@ -253,7 +268,9 @@ const BimLayer = () => {
253
268
  lastLodUpdate = now;
254
269
  fragments.core.update();
255
270
  }
256
- map.triggerRepaint();
271
+ if (editingBimModelRef.current === bimFile.name || now - lastMoveTime < SETTLE_MS) {
272
+ map.triggerRepaint();
273
+ }
257
274
  }
258
275
  this.renderer.resetState();
259
276
  this.renderer.render(this.scene, renderCamera);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/BimLayer/index.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport * as React from \"react\";\r\nimport { type CustomLayerInterface, type LngLatLike } from \"maplibre-gl\";\r\nimport * as OBC from \"@thatopen/components\";\r\nimport * as FRAGS from \"@thatopen/fragments\";\r\nimport * as THREE from \"three\";\r\nimport { BimContext, MapContext } from \"../../../../../../../store\";\r\nimport type { Building, DbFile } from \"../../../../../../../types/dbTypes\";\r\nimport { Map } from \"maplibre-gl\";\r\nimport { Marker } from \"react-map-gl/maplibre\";\r\nimport * as LR from \"lucide-react\";\r\nimport { EditPosition, extractPositionAndRotation } from \"../EditPosition\";\r\nimport { disposeThreeScene } from \"../disposeThreeScene\";\r\nimport type { FileAction } from \"../../../../../../../types/global\";\r\nimport { ViewerContextMenu } from '../../../../../../ui/FilesManager';\r\n\r\nexport const BimLayer = () => {\r\n\r\n const { state: mapState } = React.useContext(MapContext);\r\n const { map } = mapState.map;\r\n\r\n const { state: bimState, dispatch: bimDispatch } = React.useContext(BimContext);\r\n const { bimModelsAddedToMap, editingBimModel } = bimState.bim;\r\n\r\n const rendererRef = React.useRef<THREE.WebGLRenderer | null>(null);\r\n\r\n const addedLayersRef = React.useRef<Set<string>>(new Set());\r\n const prevModelsRef = React.useRef<Set<string>>(new Set());\r\n\r\n const sharedRef = React.useRef<{\r\n components: OBC.Components;\r\n fragments: OBC.FragmentsManager;\r\n } | null>(null);\r\n\r\n const [loadingBuildings, setLoadingBuildings] = React.useState<Set<number>>(new Set());\r\n const [contextMenu, setContextMenu] = React.useState<{\r\n x: number; y: number; bimFile: DbFile\r\n } | null>(null);\r\n\r\n const handleContextMenuAction = React.useCallback((action: FileAction, file: DbFile) => {\r\n if (action === 'view') {\r\n bimDispatch({ type: 'REMOVE_BIM_FROM_MAP', payload: { bimModelName: file.name } });\r\n } else if (action === 'move') {\r\n bimDispatch({ type: 'EDIT_BIM_MODEL_BY_NAME', payload: { editingBimModel: file.name } });\r\n }\r\n }, [bimDispatch]);\r\n\r\n const tempPositionsRef = React.useRef<Record<string, { lat: number; lng: number }>>({});\r\n const tempRotationsRef = React.useRef<Record<string, number>>({});\r\n const tempElevationsRef = React.useRef<Record<string, number>>({});\r\n\r\n const editingBimModelRef = React.useRef<string | null>(editingBimModel);\r\n React.useEffect(() => {\r\n editingBimModelRef.current = editingBimModel;\r\n }, [editingBimModel]);\r\n\r\n const handleExitEditMode = React.useCallback(() => {\r\n bimDispatch({ type: \"EDIT_BIM_MODEL_BY_NAME\", payload: { editingBimModel: null } });\r\n }, [bimDispatch]);\r\n\r\n const handleMapRepaint = React.useCallback(() => {\r\n if (map) map.triggerRepaint();\r\n }, [map]);\r\n const getOrCreateShared = React.useCallback(async () => {\r\n if (sharedRef.current) return sharedRef.current;\r\n\r\n const components = new OBC.Components();\r\n const worlds = components.get(OBC.Worlds);\r\n const world = worlds.create<OBC.SimpleScene, OBC.SimpleCamera, OBC.SimpleRenderer>();\r\n world.scene = new OBC.SimpleScene(components);\r\n world.renderer = new OBC.SimpleRenderer(components, document.createElement(\"div\"));\r\n world.camera = new OBC.SimpleCamera(components);\r\n components.init();\r\n world.scene.setup();\r\n\r\n const fragments = components.get(OBC.FragmentsManager);\r\n const fetchedUrl = await fetch(\"https://thatopen.github.io/engine_fragment/resources/worker.mjs\");\r\n const workerBlob = await fetchedUrl.blob();\r\n const workerUrl = URL.createObjectURL(\r\n new File([workerBlob], \"worker.mjs\", { type: \"text/javascript\" })\r\n );\r\n fragments.init(workerUrl);\r\n\r\n sharedRef.current = { components, fragments };\r\n return sharedRef.current;\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n if (!map) return;\r\n\r\n const currentModelNames = new Set(bimModelsAddedToMap.map(bm => bm.bimFile.name));\r\n\r\n const modelsToRemove = Array.from(prevModelsRef.current).filter(\r\n name => !currentModelNames.has(name)\r\n );\r\n const modelsToAdd = bimModelsAddedToMap.filter(\r\n bm => !prevModelsRef.current.has(bm.bimFile.name)\r\n );\r\n\r\n modelsToRemove.forEach(layerName => {\r\n if (map.getLayer(layerName)) {\r\n map.removeLayer(layerName);\r\n addedLayersRef.current.delete(layerName);\r\n console.log(`Removed layer: ${layerName}`);\r\n }\r\n });\r\n\r\n prevModelsRef.current = currentModelNames;\r\n\r\n if (modelsToAdd.length === 0) return;\r\n\r\n // ─── Load a single BIM model ──────────────────────────────────────────\r\n const loadModel = async (\r\n buildingModel: { bimFile: DbFile; building?: Building | null },\r\n fragments: OBC.FragmentsManager,\r\n scene: THREE.Scene,\r\n map: Map,\r\n lodCamera: THREE.PerspectiveCamera\r\n ): Promise<FRAGS.FragmentsModel | null> => {\r\n\r\n const { bimFile, building } = buildingModel;\r\n if (!bimFile) return null;\r\n\r\n const buildingId = building?.id ?? bimFile.id;\r\n setLoadingBuildings(prev => new Set(prev).add(buildingId));\r\n\r\n try {\r\n const file = await fetch(bimFile.url);\r\n if (!file.ok) throw new Error(`Fetch failed: ${file.status} ${file.statusText}`);\r\n\r\n const buffer = await file.arrayBuffer();\r\n const model = await fragments.core.load(buffer, { modelId: bimFile.name });\r\n\r\n if (!model.box.isEmpty()) {\r\n const center = model.box.getCenter(new THREE.Vector3());\r\n const size = model.box.getSize(new THREE.Vector3());\r\n model.object.position.set(-center.x, 0, -center.z);\r\n\r\n // lodCamera: above the model's new IFC-space centre (XZ is now 0,0)\r\n lodCamera.position.set(0, center.y + Math.max(size.x, size.y, size.z) * 2, 0);\r\n lodCamera.lookAt(0, center.y, 0);\r\n } else {\r\n lodCamera.position.set(0, 100, 0);\r\n lodCamera.lookAt(0, 0, 0);\r\n }\r\n lodCamera.updateMatrixWorld();\r\n model.useCamera(lodCamera);\r\n\r\n model.graphicsQuality = 1;\r\n scene.add(model.object);\r\n fragments.core.update(true);\r\n map.triggerRepaint();\r\n\r\n return model;\r\n\r\n } catch (error) {\r\n console.error(\"Error loading BIM model:\", error);\r\n return null;\r\n } finally {\r\n setLoadingBuildings(prev => {\r\n const next = new Set(prev);\r\n next.delete(buildingId);\r\n return next;\r\n });\r\n }\r\n };\r\n\r\n // ─── Build a MapLibre custom layer for one model ──────────────────────\r\n const createCustomLayer = (\r\n buildingModel: { bimFile: DbFile; building?: Building | null },\r\n fragments: OBC.FragmentsManager,\r\n scene: THREE.Scene\r\n ): CustomLayerInterface | undefined => {\r\n\r\n const { bimFile, building } = buildingModel;\r\n const {\r\n lng: baseLng, lat: baseLat,\r\n rotation: originalRotation,\r\n } = extractPositionAndRotation(bimFile, building);\r\n if (baseLng === null || baseLat === null) return undefined;\r\n\r\n // Per-layer state kept in closure\r\n let model: FRAGS.FragmentsModel | null = null;\r\n let lastAppliedRotation = originalRotation;\r\n let lastLodUpdate = 0;\r\n\r\n let onMapMove: () => void;\r\n let onMapMoveEnd: () => void;\r\n const renderCamera = new THREE.PerspectiveCamera();\r\n const lodCamera = new THREE.PerspectiveCamera();\r\n // Reused per-frame matrices/vectors — render() must not allocate (audit B1).\r\n const _vp = new THREE.Matrix4();\r\n const _m = new THREE.Matrix4();\r\n const _p = new THREE.Matrix4();\r\n const _vm = new THREE.Matrix4();\r\n const _camPos = new THREE.Vector3();\r\n const _center = new THREE.Vector3();\r\n const _lookTarget = new THREE.Vector3();\r\n const _scaleVec = new THREE.Vector3(1, 1, 1);\r\n\r\n return {\r\n id: bimFile.name,\r\n type: \"custom\",\r\n renderingMode: \"3d\",\r\n\r\n onAdd(map, gl) {\r\n scene.rotateY(originalRotation * (Math.PI / 180));\r\n this.scene = scene;\r\n\r\n loadModel(buildingModel, fragments, scene, map, lodCamera).then(loaded => {\r\n model = loaded;\r\n map.triggerRepaint();\r\n });\r\n\r\n if (!rendererRef.current) {\r\n rendererRef.current = new THREE.WebGLRenderer({\r\n canvas: map.getCanvas(),\r\n context: gl,\r\n alpha: true,\r\n });\r\n rendererRef.current.autoClear = false;\r\n }\r\n this.renderer = rendererRef.current;\r\n onMapMove = () => { /* render() loop handles updates during movement */ };\r\n onMapMoveEnd = () => {\r\n if (model) fragments.core.update(true);\r\n map.triggerRepaint();\r\n };\r\n map.on(\"move\", onMapMove);\r\n map.on(\"moveend\", onMapMoveEnd);\r\n },\r\n\r\n render(_, args) {\r\n if (\r\n editingBimModelRef.current === bimFile.name &&\r\n tempRotationsRef.current[bimFile.name] !== undefined\r\n ) {\r\n const cur = tempRotationsRef.current[bimFile.name];\r\n if (cur !== lastAppliedRotation) {\r\n scene.rotateY((cur - lastAppliedRotation) * (Math.PI / 180));\r\n lastAppliedRotation = cur;\r\n map.triggerRepaint();\r\n }\r\n } else {\r\n const { rotation: baseRot } = extractPositionAndRotation(bimFile, building);\r\n if (baseRot !== lastAppliedRotation) {\r\n scene.rotateY((baseRot - lastAppliedRotation) * (Math.PI / 180));\r\n lastAppliedRotation = baseRot;\r\n map.triggerRepaint();\r\n }\r\n }\r\n\r\n const {\r\n lng: baseLngNow, lat: baseLatNow,\r\n elevation: baseElevNow,\r\n } = extractPositionAndRotation(bimFile, building);\r\n\r\n let modelLongitude = baseLngNow;\r\n let modelLatitude = baseLatNow;\r\n let modelElevation = baseElevNow;\r\n\r\n if (editingBimModelRef.current === bimFile.name) {\r\n const tp = tempPositionsRef.current[bimFile.name];\r\n if (tp) { modelLongitude = tp.lng; modelLatitude = tp.lat; }\r\n const te = tempElevationsRef.current[bimFile.name];\r\n if (te !== undefined) modelElevation = te;\r\n }\r\n\r\n const modelOrigin = [modelLongitude, modelLatitude] as LngLatLike;\r\n const terrainElev = map.queryTerrainElevation([modelLongitude, modelLatitude]) ?? 0;\r\n const modelAltitude = modelElevation + terrainElev;\r\n const scaling = 1;\r\n\r\n // ── Build renderCamera (VP × M, for Three.js rendering) ───\r\n // Reused temps — render() allocates nothing (audit B1). Math is\r\n // identical to the prior allocate-every-frame version.\r\n const modelMatrix = map.transform.getMatrixForModel(modelOrigin, modelAltitude);\r\n _scaleVec.set(scaling, scaling, scaling);\r\n _vp.fromArray(args.defaultProjectionData.mainMatrix);\r\n _m.fromArray(modelMatrix).scale(_scaleVec);\r\n renderCamera.projectionMatrix.multiplyMatrices(_vp, _m); // VP × M, into the camera's own matrix\r\n\r\n // camIFCPos = translation of (P⁻¹ · (VP×M))⁻¹\r\n _p.fromArray(args.projectionMatrix).invert(); // _p = P⁻¹\r\n _vm.multiplyMatrices(_p, renderCamera.projectionMatrix).invert();\r\n _camPos.setFromMatrixPosition(_vm);\r\n lodCamera.position.copy(_camPos);\r\n\r\n if (model) {\r\n model.box.getCenter(_center);\r\n _lookTarget.set(0, _center.y, 0);\r\n } else {\r\n _lookTarget.set(0, 0, 0);\r\n }\r\n lodCamera.lookAt(_lookTarget);\r\n lodCamera.fov = args.fov * (180 / Math.PI) + 40;\r\n lodCamera.aspect = map.getCanvas().width / map.getCanvas().height;\r\n lodCamera.updateProjectionMatrix(); // rebuilds projectionMatrix from fov/aspect\r\n lodCamera.updateMatrixWorld(); // rebuilds matrixWorld + matrixWorldInverse\r\n\r\n if (model) {\r\n model.useCamera(lodCamera);\r\n const now = performance.now();\r\n if (now - lastLodUpdate > 50) {\r\n lastLodUpdate = now;\r\n fragments.core.update();\r\n }\r\n map.triggerRepaint();\r\n }\r\n\r\n this.renderer.resetState();\r\n this.renderer.render(this.scene, renderCamera);\r\n },\r\n\r\n onRemove() {\r\n if (onMapMove) map.off(\"move\", onMapMove);\r\n if (onMapMoveEnd) map.off(\"moveend\", onMapMoveEnd);\r\n if (model) {\r\n model.dispose().catch(console.warn);\r\n model = null;\r\n }\r\n // Dispose all Three.js GPU resources (geometries, materials, textures)\r\n disposeThreeScene(scene);\r\n },\r\n };\r\n };\r\n\r\n modelsToAdd.forEach(async buildingModel => {\r\n try {\r\n const { fragments } = await getOrCreateShared();\r\n\r\n const layerName = buildingModel.bimFile.name;\r\n if (map.getLayer(layerName)) return;\r\n const scene = new THREE.Scene();\r\n scene.add(new THREE.AmbientLight(0xffffff, 0.8));\r\n const sun = new THREE.DirectionalLight(0xffffff, 1.0);\r\n sun.position.set(10, 20, 10);\r\n scene.add(sun);\r\n\r\n const customLayer = createCustomLayer(buildingModel, fragments, scene);\r\n if (!customLayer) return;\r\n\r\n map.addLayer(customLayer);\r\n addedLayersRef.current.add(layerName);\r\n console.log(`Added layer: ${layerName}`);\r\n\r\n } catch (err) {\r\n console.error(\"Error adding BIM layer:\", err);\r\n }\r\n });\r\n\r\n }, [map, bimModelsAddedToMap]);\r\n\r\n // Cleanup on unmount — dispose shared components and renderer\r\n React.useEffect(() => {\r\n return () => {\r\n if (map) {\r\n addedLayersRef.current.forEach(layerName => {\r\n if (map.getLayer(layerName)) map.removeLayer(layerName);\r\n });\r\n addedLayersRef.current.clear();\r\n }\r\n if (sharedRef.current) {\r\n sharedRef.current.components.dispose();\r\n sharedRef.current = null;\r\n }\r\n if (rendererRef.current) {\r\n rendererRef.current.dispose();\r\n rendererRef.current = null;\r\n }\r\n };\r\n }, [map]);\r\n\r\n return (\r\n <>\r\n {bimModelsAddedToMap.map((buildingModel, index) => {\r\n const { lng, lat } = extractPositionAndRotation(\r\n buildingModel.bimFile, buildingModel.building\r\n );\r\n const isLoading = loadingBuildings.has(\r\n buildingModel.building?.id ?? buildingModel.bimFile.id\r\n );\r\n if (lng === null || lat === null) return null;\r\n return (\r\n <React.Fragment key={buildingModel.bimFile.id + \"-fragment-\" + index}>\r\n {isLoading && (\r\n <Marker\r\n key={buildingModel.bimFile.id + \"-loading-animation\" + index}\r\n latitude={lat}\r\n longitude={lng}\r\n >\r\n <LR.Loader className=\"animate-spin w-6 h-6 text-gray-700\" />\r\n </Marker>\r\n )}\r\n {/* Invisible hit-target for right-click context menu on WebGL-rendered BIM models */}\r\n {buildingModel.bimFile.name !== editingBimModel && (\r\n <Marker\r\n key={buildingModel.bimFile.id + \"-ctx-target-\" + index}\r\n latitude={lat}\r\n longitude={lng}\r\n >\r\n <div\r\n className=\"w-10 h-10 opacity-0 cursor-context-menu\"\r\n onContextMenu={(e) => {\r\n e.preventDefault();\r\n setContextMenu({ x: e.clientX, y: e.clientY, bimFile: buildingModel.bimFile });\r\n }}\r\n />\r\n </Marker>\r\n )}\r\n </React.Fragment>\r\n );\r\n })}\r\n {editingBimModel && (() => {\r\n const currentModel = bimModelsAddedToMap.find(bm => bm.bimFile.name === editingBimModel);\r\n if (!currentModel) return null;\r\n const { lng, lat, rotation, elevation } = extractPositionAndRotation(\r\n currentModel.bimFile, currentModel.building\r\n );\r\n return (\r\n <EditPosition\r\n file={currentModel.bimFile}\r\n displayName={currentModel.building?.buildingName || currentModel.bimFile.name}\r\n mode=\"3d\"\r\n initialLat={lat}\r\n initialLng={lng}\r\n initialRotation={rotation}\r\n initialElevation={elevation}\r\n onExitEditMode={handleExitEditMode}\r\n tempPositionsRef={tempPositionsRef}\r\n tempRotationsRef={tempRotationsRef}\r\n tempElevationsRef={tempElevationsRef}\r\n onMapRepaint={handleMapRepaint}\r\n />\r\n );\r\n })()}\r\n\r\n {contextMenu && (\r\n <ViewerContextMenu\r\n x={contextMenu.x}\r\n y={contextMenu.y}\r\n file={{ ...contextMenu.bimFile, isVisible: true }}\r\n options={['view', 'move']}\r\n onAction={handleContextMenuAction}\r\n onClose={() => setContextMenu(null)}\r\n />\r\n )}\r\n </>\r\n );\r\n\r\n};\r\n"],"mappings":"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","names":["map"]}
1
+ {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/map/src/MapLayers/src/BimLayer/index.tsx"],"sourcesContent":["\"use client\"\r\n\r\nimport * as React from \"react\";\r\nimport { type CustomLayerInterface, type LngLatLike } from \"maplibre-gl\";\r\nimport * as OBC from \"@thatopen/components\";\r\nimport * as FRAGS from \"@thatopen/fragments\";\r\nimport * as THREE from \"three\";\r\nimport { BimContext, MapContext } from \"../../../../../../../store\";\r\nimport type { Building, DbFile } from \"../../../../../../../types/dbTypes\";\r\nimport { Map } from \"maplibre-gl\";\r\nimport { Marker } from \"react-map-gl/maplibre\";\r\nimport * as LR from \"lucide-react\";\r\nimport { EditPosition, extractPositionAndRotation } from \"../EditPosition\";\r\nimport { disposeThreeScene } from \"../disposeThreeScene\";\r\nimport type { FileAction } from \"../../../../../../../types/global\";\r\nimport { ViewerContextMenu } from '../../../../../../ui/FilesManager';\r\n\r\nexport const BimLayer = () => {\r\n\r\n const { state: mapState } = React.useContext(MapContext);\r\n const { map } = mapState.map;\r\n\r\n const { state: bimState, dispatch: bimDispatch } = React.useContext(BimContext);\r\n const { bimModelsAddedToMap, editingBimModel } = bimState.bim;\r\n\r\n const rendererRef = React.useRef<THREE.WebGLRenderer | null>(null);\r\n\r\n const addedLayersRef = React.useRef<Set<string>>(new Set());\r\n const prevModelsRef = React.useRef<Set<string>>(new Set());\r\n\r\n const sharedRef = React.useRef<{\r\n components: OBC.Components;\r\n fragments: OBC.FragmentsManager;\r\n } | null>(null);\r\n\r\n const [loadingBuildings, setLoadingBuildings] = React.useState<Set<number>>(new Set());\r\n const [contextMenu, setContextMenu] = React.useState<{\r\n x: number; y: number; bimFile: DbFile\r\n } | null>(null);\r\n\r\n const handleContextMenuAction = React.useCallback((action: FileAction, file: DbFile) => {\r\n if (action === 'view') {\r\n bimDispatch({ type: 'REMOVE_BIM_FROM_MAP', payload: { bimModelName: file.name } });\r\n } else if (action === 'move') {\r\n bimDispatch({ type: 'EDIT_BIM_MODEL_BY_NAME', payload: { editingBimModel: file.name } });\r\n }\r\n }, [bimDispatch]);\r\n\r\n const tempPositionsRef = React.useRef<Record<string, { lat: number; lng: number }>>({});\r\n const tempRotationsRef = React.useRef<Record<string, number>>({});\r\n const tempElevationsRef = React.useRef<Record<string, number>>({});\r\n\r\n const editingBimModelRef = React.useRef<string | null>(editingBimModel);\r\n React.useEffect(() => {\r\n editingBimModelRef.current = editingBimModel;\r\n }, [editingBimModel]);\r\n\r\n const handleExitEditMode = React.useCallback(() => {\r\n bimDispatch({ type: \"EDIT_BIM_MODEL_BY_NAME\", payload: { editingBimModel: null } });\r\n }, [bimDispatch]);\r\n\r\n const handleMapRepaint = React.useCallback(() => {\r\n if (map) map.triggerRepaint();\r\n }, [map]);\r\n const getOrCreateShared = React.useCallback(async () => {\r\n if (sharedRef.current) return sharedRef.current;\r\n\r\n const components = new OBC.Components();\r\n const worlds = components.get(OBC.Worlds);\r\n const world = worlds.create<OBC.SimpleScene, OBC.SimpleCamera, OBC.SimpleRenderer>();\r\n world.scene = new OBC.SimpleScene(components);\r\n world.renderer = new OBC.SimpleRenderer(components, document.createElement(\"div\"));\r\n world.camera = new OBC.SimpleCamera(components);\r\n components.init();\r\n world.scene.setup();\r\n\r\n const fragments = components.get(OBC.FragmentsManager);\r\n const fetchedUrl = await fetch(\"https://thatopen.github.io/engine_fragment/resources/worker.mjs\");\r\n const workerBlob = await fetchedUrl.blob();\r\n const workerUrl = URL.createObjectURL(\r\n new File([workerBlob], \"worker.mjs\", { type: \"text/javascript\" })\r\n );\r\n fragments.init(workerUrl);\r\n\r\n sharedRef.current = { components, fragments };\r\n return sharedRef.current;\r\n }, []);\r\n\r\n React.useEffect(() => {\r\n if (!map) return;\r\n\r\n const currentModelNames = new Set(bimModelsAddedToMap.map(bm => bm.bimFile.name));\r\n\r\n const modelsToRemove = Array.from(prevModelsRef.current).filter(\r\n name => !currentModelNames.has(name)\r\n );\r\n const modelsToAdd = bimModelsAddedToMap.filter(\r\n bm => !prevModelsRef.current.has(bm.bimFile.name)\r\n );\r\n\r\n modelsToRemove.forEach(layerName => {\r\n if (map.getLayer(layerName)) {\r\n map.removeLayer(layerName);\r\n addedLayersRef.current.delete(layerName);\r\n console.log(`Removed layer: ${layerName}`);\r\n }\r\n });\r\n\r\n prevModelsRef.current = currentModelNames;\r\n\r\n if (modelsToAdd.length === 0) return;\r\n\r\n // ─── Load a single BIM model ──────────────────────────────────────────\r\n const loadModel = async (\r\n buildingModel: { bimFile: DbFile; building?: Building | null },\r\n fragments: OBC.FragmentsManager,\r\n scene: THREE.Scene,\r\n map: Map,\r\n lodCamera: THREE.PerspectiveCamera\r\n ): Promise<FRAGS.FragmentsModel | null> => {\r\n\r\n const { bimFile, building } = buildingModel;\r\n if (!bimFile) return null;\r\n\r\n const buildingId = building?.id ?? bimFile.id;\r\n setLoadingBuildings(prev => new Set(prev).add(buildingId));\r\n\r\n try {\r\n const file = await fetch(bimFile.url);\r\n if (!file.ok) throw new Error(`Fetch failed: ${file.status} ${file.statusText}`);\r\n\r\n const buffer = await file.arrayBuffer();\r\n const model = await fragments.core.load(buffer, { modelId: bimFile.name });\r\n\r\n if (!model.box.isEmpty()) {\r\n const center = model.box.getCenter(new THREE.Vector3());\r\n const size = model.box.getSize(new THREE.Vector3());\r\n model.object.position.set(-center.x, 0, -center.z);\r\n\r\n // lodCamera: above the model's new IFC-space centre (XZ is now 0,0)\r\n lodCamera.position.set(0, center.y + Math.max(size.x, size.y, size.z) * 2, 0);\r\n lodCamera.lookAt(0, center.y, 0);\r\n } else {\r\n lodCamera.position.set(0, 100, 0);\r\n lodCamera.lookAt(0, 0, 0);\r\n }\r\n lodCamera.updateMatrixWorld();\r\n model.useCamera(lodCamera);\r\n\r\n model.graphicsQuality = 1;\r\n scene.add(model.object);\r\n fragments.core.update(true);\r\n map.triggerRepaint();\r\n\r\n return model;\r\n\r\n } catch (error) {\r\n console.error(\"Error loading BIM model:\", error);\r\n return null;\r\n } finally {\r\n setLoadingBuildings(prev => {\r\n const next = new Set(prev);\r\n next.delete(buildingId);\r\n return next;\r\n });\r\n }\r\n };\r\n\r\n // ─── Build a MapLibre custom layer for one model ──────────────────────\r\n const createCustomLayer = (\r\n buildingModel: { bimFile: DbFile; building?: Building | null },\r\n fragments: OBC.FragmentsManager,\r\n scene: THREE.Scene\r\n ): CustomLayerInterface | undefined => {\r\n\r\n const { bimFile, building } = buildingModel;\r\n const {\r\n lng: baseLng, lat: baseLat,\r\n rotation: originalRotation,\r\n } = extractPositionAndRotation(bimFile, building);\r\n if (baseLng === null || baseLat === null) return undefined;\r\n\r\n // Per-layer state kept in closure\r\n let model: FRAGS.FragmentsModel | null = null;\r\n let lastAppliedRotation = originalRotation;\r\n let lastLodUpdate = 0;\r\n // Render-on-demand: cache terrain elevation off the per-frame path and\r\n // only keep repainting while the camera recently moved, so an idle map\r\n // with a placed model stops re-rendering instead of pinning the main\r\n // thread (this was the freeze after a geocoder flyTo to high zoom).\r\n let cachedTerrainElev = 0;\r\n let lastMoveTime = performance.now();\r\n const SETTLE_MS = 1000;\r\n const recomputeTerrainElev = () => {\r\n const { lng, lat } = extractPositionAndRotation(bimFile, building);\r\n if (lng !== null && lat !== null) {\r\n const e = map.queryTerrainElevation([lng, lat]);\r\n if (e !== null && e !== undefined) cachedTerrainElev = e;\r\n }\r\n };\r\n\r\n let onMapMove: () => void;\r\n let onMapMoveEnd: () => void;\r\n const renderCamera = new THREE.PerspectiveCamera();\r\n const lodCamera = new THREE.PerspectiveCamera();\r\n // Reused per-frame matrices/vectors — render() must not allocate.\r\n const _vp = new THREE.Matrix4();\r\n const _m = new THREE.Matrix4();\r\n const _p = new THREE.Matrix4();\r\n const _vm = new THREE.Matrix4();\r\n const _camPos = new THREE.Vector3();\r\n const _center = new THREE.Vector3();\r\n const _lookTarget = new THREE.Vector3();\r\n const _scaleVec = new THREE.Vector3(1, 1, 1);\r\n\r\n return {\r\n id: bimFile.name,\r\n type: \"custom\",\r\n renderingMode: \"3d\",\r\n\r\n onAdd(map, gl) {\r\n scene.rotateY(originalRotation * (Math.PI / 180));\r\n this.scene = scene;\r\n\r\n loadModel(buildingModel, fragments, scene, map, lodCamera).then(loaded => {\r\n model = loaded;\r\n // Open the settle window so the just-loaded fragments stream\r\n // in and paint over the next frames, then idle.\r\n lastMoveTime = performance.now();\r\n recomputeTerrainElev();\r\n map.triggerRepaint();\r\n });\r\n\r\n if (!rendererRef.current) {\r\n rendererRef.current = new THREE.WebGLRenderer({\r\n canvas: map.getCanvas(),\r\n context: gl,\r\n alpha: true,\r\n });\r\n rendererRef.current.autoClear = false;\r\n }\r\n this.renderer = rendererRef.current;\r\n // Track movement so render() knows when it may stop repainting.\r\n onMapMove = () => { lastMoveTime = performance.now(); };\r\n onMapMoveEnd = () => {\r\n lastMoveTime = performance.now();\r\n if (model) fragments.core.update(true);\r\n // Terrain tiles for the new view are loaded once the camera\r\n // settles — refresh the cached elevation here, not per frame.\r\n recomputeTerrainElev();\r\n map.triggerRepaint();\r\n };\r\n map.on(\"move\", onMapMove);\r\n map.on(\"moveend\", onMapMoveEnd);\r\n },\r\n\r\n render(_, args) {\r\n if (\r\n editingBimModelRef.current === bimFile.name &&\r\n tempRotationsRef.current[bimFile.name] !== undefined\r\n ) {\r\n const cur = tempRotationsRef.current[bimFile.name];\r\n if (cur !== lastAppliedRotation) {\r\n scene.rotateY((cur - lastAppliedRotation) * (Math.PI / 180));\r\n lastAppliedRotation = cur;\r\n map.triggerRepaint();\r\n }\r\n } else {\r\n const { rotation: baseRot } = extractPositionAndRotation(bimFile, building);\r\n if (baseRot !== lastAppliedRotation) {\r\n scene.rotateY((baseRot - lastAppliedRotation) * (Math.PI / 180));\r\n lastAppliedRotation = baseRot;\r\n map.triggerRepaint();\r\n }\r\n }\r\n\r\n const {\r\n lng: baseLngNow, lat: baseLatNow,\r\n elevation: baseElevNow,\r\n } = extractPositionAndRotation(bimFile, building);\r\n\r\n let modelLongitude = baseLngNow;\r\n let modelLatitude = baseLatNow;\r\n let modelElevation = baseElevNow;\r\n\r\n if (editingBimModelRef.current === bimFile.name) {\r\n const tp = tempPositionsRef.current[bimFile.name];\r\n if (tp) { modelLongitude = tp.lng; modelLatitude = tp.lat; }\r\n const te = tempElevationsRef.current[bimFile.name];\r\n if (te !== undefined) modelElevation = te;\r\n }\r\n\r\n const modelOrigin = [modelLongitude, modelLatitude] as LngLatLike;\r\n // Use the cached terrain elevation (refreshed on moveend); query\r\n // live only while actively editing this model's position. Keeps\r\n // the expensive queryTerrainElevation off the hot path — the\r\n // per-frame query was a main driver of the high-zoom freeze.\r\n const terrainElev = editingBimModelRef.current === bimFile.name\r\n ? (map.queryTerrainElevation([modelLongitude, modelLatitude]) ?? cachedTerrainElev)\r\n : cachedTerrainElev;\r\n const modelAltitude = modelElevation + terrainElev;\r\n const scaling = 1;\r\n\r\n // ── Build renderCamera (VP × M, for Three.js rendering) ───\r\n // Reused temps — render() allocates nothing. Math is identical\r\n // to the prior allocate-every-frame version.\r\n const modelMatrix = map.transform.getMatrixForModel(modelOrigin, modelAltitude);\r\n _scaleVec.set(scaling, scaling, scaling);\r\n _vp.fromArray(args.defaultProjectionData.mainMatrix);\r\n _m.fromArray(modelMatrix).scale(_scaleVec);\r\n renderCamera.projectionMatrix.multiplyMatrices(_vp, _m); // VP × M, into the camera's own matrix\r\n\r\n // camIFCPos = translation of (P⁻¹ · (VP×M))⁻¹\r\n _p.fromArray(args.projectionMatrix).invert(); // _p = P⁻¹\r\n _vm.multiplyMatrices(_p, renderCamera.projectionMatrix).invert();\r\n _camPos.setFromMatrixPosition(_vm);\r\n lodCamera.position.copy(_camPos);\r\n\r\n if (model) {\r\n model.box.getCenter(_center);\r\n _lookTarget.set(0, _center.y, 0);\r\n } else {\r\n _lookTarget.set(0, 0, 0);\r\n }\r\n lodCamera.lookAt(_lookTarget);\r\n lodCamera.fov = args.fov * (180 / Math.PI) + 40;\r\n lodCamera.aspect = map.getCanvas().width / map.getCanvas().height;\r\n lodCamera.updateProjectionMatrix(); // rebuilds projectionMatrix from fov/aspect\r\n lodCamera.updateMatrixWorld(); // rebuilds matrixWorld + matrixWorldInverse\r\n\r\n if (model) {\r\n model.useCamera(lodCamera);\r\n const now = performance.now();\r\n if (now - lastLodUpdate > 50) {\r\n lastLodUpdate = now;\r\n fragments.core.update();\r\n }\r\n // Render-on-demand: only keep the frame loop alive while the\r\n // camera recently moved (settle window, for fragment\r\n // streaming) or this model is being edited. Idle map ⇒ no\r\n // self-scheduled repaints ⇒ main thread freed (no freeze).\r\n if (\r\n editingBimModelRef.current === bimFile.name ||\r\n now - lastMoveTime < SETTLE_MS\r\n ) {\r\n map.triggerRepaint();\r\n }\r\n }\r\n\r\n this.renderer.resetState();\r\n this.renderer.render(this.scene, renderCamera);\r\n },\r\n\r\n onRemove() {\r\n if (onMapMove) map.off(\"move\", onMapMove);\r\n if (onMapMoveEnd) map.off(\"moveend\", onMapMoveEnd);\r\n if (model) {\r\n model.dispose().catch(console.warn);\r\n model = null;\r\n }\r\n // Dispose all Three.js GPU resources (geometries, materials, textures)\r\n disposeThreeScene(scene);\r\n },\r\n };\r\n };\r\n\r\n modelsToAdd.forEach(async buildingModel => {\r\n try {\r\n const { fragments } = await getOrCreateShared();\r\n\r\n const layerName = buildingModel.bimFile.name;\r\n if (map.getLayer(layerName)) return;\r\n const scene = new THREE.Scene();\r\n scene.add(new THREE.AmbientLight(0xffffff, 0.8));\r\n const sun = new THREE.DirectionalLight(0xffffff, 1.0);\r\n sun.position.set(10, 20, 10);\r\n scene.add(sun);\r\n\r\n const customLayer = createCustomLayer(buildingModel, fragments, scene);\r\n if (!customLayer) return;\r\n\r\n map.addLayer(customLayer);\r\n addedLayersRef.current.add(layerName);\r\n console.log(`Added layer: ${layerName}`);\r\n\r\n } catch (err) {\r\n console.error(\"Error adding BIM layer:\", err);\r\n }\r\n });\r\n\r\n }, [map, bimModelsAddedToMap]);\r\n\r\n // Cleanup on unmount — dispose shared components and renderer\r\n React.useEffect(() => {\r\n return () => {\r\n if (map) {\r\n addedLayersRef.current.forEach(layerName => {\r\n if (map.getLayer(layerName)) map.removeLayer(layerName);\r\n });\r\n addedLayersRef.current.clear();\r\n }\r\n if (sharedRef.current) {\r\n sharedRef.current.components.dispose();\r\n sharedRef.current = null;\r\n }\r\n if (rendererRef.current) {\r\n rendererRef.current.dispose();\r\n rendererRef.current = null;\r\n }\r\n };\r\n }, [map]);\r\n\r\n return (\r\n <>\r\n {bimModelsAddedToMap.map((buildingModel, index) => {\r\n const { lng, lat } = extractPositionAndRotation(\r\n buildingModel.bimFile, buildingModel.building\r\n );\r\n const isLoading = loadingBuildings.has(\r\n buildingModel.building?.id ?? buildingModel.bimFile.id\r\n );\r\n if (lng === null || lat === null) return null;\r\n return (\r\n <React.Fragment key={buildingModel.bimFile.id + \"-fragment-\" + index}>\r\n {isLoading && (\r\n <Marker\r\n key={buildingModel.bimFile.id + \"-loading-animation\" + index}\r\n latitude={lat}\r\n longitude={lng}\r\n >\r\n <LR.Loader className=\"animate-spin w-6 h-6 text-gray-700\" />\r\n </Marker>\r\n )}\r\n {/* Invisible hit-target for right-click context menu on WebGL-rendered BIM models */}\r\n {buildingModel.bimFile.name !== editingBimModel && (\r\n <Marker\r\n key={buildingModel.bimFile.id + \"-ctx-target-\" + index}\r\n latitude={lat}\r\n longitude={lng}\r\n >\r\n <div\r\n className=\"w-10 h-10 opacity-0 cursor-context-menu\"\r\n onContextMenu={(e) => {\r\n e.preventDefault();\r\n setContextMenu({ x: e.clientX, y: e.clientY, bimFile: buildingModel.bimFile });\r\n }}\r\n />\r\n </Marker>\r\n )}\r\n </React.Fragment>\r\n );\r\n })}\r\n {editingBimModel && (() => {\r\n const currentModel = bimModelsAddedToMap.find(bm => bm.bimFile.name === editingBimModel);\r\n if (!currentModel) return null;\r\n const { lng, lat, rotation, elevation } = extractPositionAndRotation(\r\n currentModel.bimFile, currentModel.building\r\n );\r\n return (\r\n <EditPosition\r\n file={currentModel.bimFile}\r\n displayName={currentModel.building?.buildingName || currentModel.bimFile.name}\r\n mode=\"3d\"\r\n initialLat={lat}\r\n initialLng={lng}\r\n initialRotation={rotation}\r\n initialElevation={elevation}\r\n onExitEditMode={handleExitEditMode}\r\n tempPositionsRef={tempPositionsRef}\r\n tempRotationsRef={tempRotationsRef}\r\n tempElevationsRef={tempElevationsRef}\r\n onMapRepaint={handleMapRepaint}\r\n />\r\n );\r\n })()}\r\n\r\n {contextMenu && (\r\n <ViewerContextMenu\r\n x={contextMenu.x}\r\n y={contextMenu.y}\r\n file={{ ...contextMenu.bimFile, isVisible: true }}\r\n options={['view', 'move']}\r\n onAction={handleContextMenuAction}\r\n onClose={() => setContextMenu(null)}\r\n />\r\n )}\r\n </>\r\n );\r\n\r\n};\r\n"],"mappings":"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","names":["map"]}