@collabdt/core 0.0.42 → 0.0.43

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 (264) 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/siteDetails/AssociatedBuildings.js +2 -2
  44. package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.js.map +1 -1
  45. package/dist/core/components/viewers/Viewer.d.ts.map +1 -1
  46. package/dist/core/components/viewers/Viewer.js +5 -1
  47. package/dist/core/components/viewers/Viewer.js.map +1 -1
  48. package/dist/core/components/viewers/bim/BimToolbar.d.ts.map +1 -1
  49. package/dist/core/components/viewers/bim/BimToolbar.js.map +1 -1
  50. package/dist/core/components/viewers/bim/BimViewer.d.ts.map +1 -1
  51. package/dist/core/components/viewers/bim/BimViewer.js +14 -5
  52. package/dist/core/components/viewers/bim/BimViewer.js.map +1 -1
  53. package/dist/core/components/viewers/bim/src/BimLoadingState/index.d.ts.map +1 -1
  54. package/dist/core/components/viewers/bim/src/BimLoadingState/index.js +6 -0
  55. package/dist/core/components/viewers/bim/src/BimLoadingState/index.js.map +1 -1
  56. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
  57. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js +168 -39
  58. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js.map +1 -1
  59. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
  60. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
  61. package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.d.ts.map +1 -1
  62. package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.js +1 -1
  63. package/dist/core/components/viewers/bim/src/BimSidebar/src/LayersTab/src/FloorplanSection.js.map +1 -1
  64. package/dist/core/components/viewers/bim/src/DXFLoader/index.d.ts +14 -37
  65. package/dist/core/components/viewers/bim/src/DXFLoader/index.d.ts.map +1 -1
  66. package/dist/core/components/viewers/bim/src/DXFLoader/index.js +31 -318
  67. package/dist/core/components/viewers/bim/src/DXFLoader/index.js.map +1 -1
  68. package/dist/core/components/viewers/bim/src/FloorplanTool/index.d.ts +66 -7
  69. package/dist/core/components/viewers/bim/src/FloorplanTool/index.d.ts.map +1 -1
  70. package/dist/core/components/viewers/bim/src/FloorplanTool/index.js +253 -21
  71. package/dist/core/components/viewers/bim/src/FloorplanTool/index.js.map +1 -1
  72. package/dist/core/components/viewers/bim/src/ModelManager/index.d.ts.map +1 -1
  73. package/dist/core/components/viewers/bim/src/ModelManager/index.js +9 -0
  74. package/dist/core/components/viewers/bim/src/ModelManager/index.js.map +1 -1
  75. package/dist/core/components/viewers/bim/src/SimpleBimViewer.d.ts.map +1 -1
  76. package/dist/core/components/viewers/bim/src/SimpleBimViewer.js.map +1 -1
  77. package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.d.ts +3 -2
  78. package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.d.ts.map +1 -1
  79. package/dist/core/components/viewers/bim/src/lib/TrueNorthPopover.js.map +1 -1
  80. package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.d.ts.map +1 -1
  81. package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.js +3 -4
  82. package/dist/core/components/viewers/bim/src/lib/useFriendlyIfcClassName.js.map +1 -1
  83. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts.map +1 -1
  84. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js +40 -18
  85. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js.map +1 -1
  86. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.d.ts +2 -5
  87. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.d.ts.map +1 -1
  88. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.js +45 -59
  89. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/AddDxf.js.map +1 -1
  90. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js +1 -0
  91. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js.map +1 -1
  92. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.d.ts +10 -1
  93. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.d.ts.map +1 -1
  94. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.js +25 -73
  95. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileHandler.js.map +1 -1
  96. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.d.ts +7 -3
  97. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.d.ts.map +1 -1
  98. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.js +42 -78
  99. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/FileMarkerUtils.js.map +1 -1
  100. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.d.ts.map +1 -1
  101. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.js +52 -75
  102. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/Position3DCard.js.map +1 -1
  103. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.d.ts +15 -3
  104. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.d.ts.map +1 -1
  105. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.js +165 -105
  106. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.js.map +1 -1
  107. package/dist/core/components/viewers/index.d.ts.map +1 -1
  108. package/dist/core/components/viewers/index.js.map +1 -1
  109. package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
  110. package/dist/core/components/viewers/map/MapViewer.js +1 -0
  111. package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
  112. package/dist/core/components/viewers/map/datasets/DatasetManager/index.d.ts.map +1 -1
  113. package/dist/core/components/viewers/map/datasets/DatasetManager/index.js +4 -3
  114. package/dist/core/components/viewers/map/datasets/DatasetManager/index.js.map +1 -1
  115. package/dist/core/components/viewers/map/datasets/RowActions.d.ts.map +1 -1
  116. package/dist/core/components/viewers/map/datasets/RowActions.js +148 -0
  117. package/dist/core/components/viewers/map/datasets/RowActions.js.map +1 -1
  118. package/dist/core/components/viewers/map/datasets/index.d.ts.map +1 -1
  119. package/dist/core/components/viewers/map/datasets/index.js +32 -15
  120. package/dist/core/components/viewers/map/datasets/index.js.map +1 -1
  121. package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.d.ts +4 -0
  122. package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.d.ts.map +1 -0
  123. package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.js +43 -0
  124. package/dist/core/components/viewers/map/datasets/src/builtinLiveDatasets.js.map +1 -0
  125. package/dist/core/components/viewers/map/datasets/src/localDatasets.d.ts.map +1 -1
  126. package/dist/core/components/viewers/map/datasets/src/localDatasets.js +39 -3
  127. package/dist/core/components/viewers/map/datasets/src/localDatasets.js.map +1 -1
  128. package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts +1 -1
  129. package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts.map +1 -1
  130. package/dist/core/components/viewers/map/datasets/src/minioDatasets.js +2 -1
  131. package/dist/core/components/viewers/map/datasets/src/minioDatasets.js.map +1 -1
  132. package/dist/core/components/viewers/map/datasets/src/publishedTiles.d.ts +47 -0
  133. package/dist/core/components/viewers/map/datasets/src/publishedTiles.d.ts.map +1 -0
  134. package/dist/core/components/viewers/map/datasets/src/publishedTiles.js +114 -0
  135. package/dist/core/components/viewers/map/datasets/src/publishedTiles.js.map +1 -0
  136. package/dist/core/components/viewers/map/datasets/src/wmsTime.d.ts +49 -0
  137. package/dist/core/components/viewers/map/datasets/src/wmsTime.d.ts.map +1 -0
  138. package/dist/core/components/viewers/map/datasets/src/wmsTime.js +100 -0
  139. package/dist/core/components/viewers/map/datasets/src/wmsTime.js.map +1 -0
  140. package/dist/core/components/viewers/map/src/Geocoder.d.ts.map +1 -1
  141. package/dist/core/components/viewers/map/src/Geocoder.js +9 -9
  142. package/dist/core/components/viewers/map/src/Geocoder.js.map +1 -1
  143. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.d.ts.map +1 -1
  144. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js +25 -43
  145. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js.map +1 -1
  146. package/dist/core/components/viewers/map/src/MapLayers/index.d.ts.map +1 -1
  147. package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
  148. package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.d.ts.map +1 -1
  149. package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.js +19 -2
  150. package/dist/core/components/viewers/map/src/MapLayers/src/BimLayer/index.js.map +1 -1
  151. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.d.ts +9 -0
  152. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.d.ts.map +1 -0
  153. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.js +28 -0
  154. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/countryLayerUtils.js.map +1 -0
  155. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.d.ts.map +1 -1
  156. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js +1 -16
  157. package/dist/core/components/viewers/map/src/MapLayers/src/CountryLayer/index.js.map +1 -1
  158. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/FileModelLayer/FileModelLayer.d.ts.map +1 -1
  159. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/FileModelLayer/FileModelLayer.js.map +1 -1
  160. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.d.ts.map +1 -1
  161. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.js +31 -2
  162. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/utils/CustomModelLayer.js.map +1 -1
  163. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.d.ts +21 -0
  164. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.d.ts.map +1 -0
  165. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.js +111 -0
  166. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/WmsTimeControl.js.map +1 -0
  167. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.d.ts.map +1 -1
  168. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.js +77 -2
  169. package/dist/core/components/viewers/map/src/MapLayers/src/OpenDataLayer/src/index.js.map +1 -1
  170. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
  171. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js.map +1 -1
  172. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
  173. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
  174. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.d.ts.map +1 -1
  175. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js +10 -3
  176. package/dist/core/components/viewers/map/src/MapSidebar/src/SettingsTab/src/TerrainLevel.js.map +1 -1
  177. package/dist/core/components/viewers/map/utils/geocoder.d.ts +6 -2
  178. package/dist/core/components/viewers/map/utils/geocoder.d.ts.map +1 -1
  179. package/dist/core/components/viewers/map/utils/geocoder.js +10 -62
  180. package/dist/core/components/viewers/map/utils/geocoder.js.map +1 -1
  181. package/dist/core/components/viewers/map/utils/geocoding/adapters.d.ts +5 -0
  182. package/dist/core/components/viewers/map/utils/geocoding/adapters.d.ts.map +1 -0
  183. package/dist/core/components/viewers/map/utils/geocoding/adapters.js +192 -0
  184. package/dist/core/components/viewers/map/utils/geocoding/adapters.js.map +1 -0
  185. package/dist/core/components/viewers/map/utils/geocoding/config.d.ts +6 -0
  186. package/dist/core/components/viewers/map/utils/geocoding/config.d.ts.map +1 -0
  187. package/dist/core/components/viewers/map/utils/geocoding/config.js +14 -0
  188. package/dist/core/components/viewers/map/utils/geocoding/config.js.map +1 -0
  189. package/dist/core/components/viewers/map/utils/geocoding/index.d.ts +8 -0
  190. package/dist/core/components/viewers/map/utils/geocoding/index.d.ts.map +1 -0
  191. package/dist/core/components/viewers/map/utils/geocoding/index.js +44 -0
  192. package/dist/core/components/viewers/map/utils/geocoding/index.js.map +1 -0
  193. package/dist/core/components/viewers/map/utils/geocoding/osm.d.ts +6 -0
  194. package/dist/core/components/viewers/map/utils/geocoding/osm.d.ts.map +1 -0
  195. package/dist/core/components/viewers/map/utils/geocoding/osm.js +39 -0
  196. package/dist/core/components/viewers/map/utils/geocoding/osm.js.map +1 -0
  197. package/dist/core/components/viewers/map/utils/geocoding/pelias.d.ts +8 -0
  198. package/dist/core/components/viewers/map/utils/geocoding/pelias.d.ts.map +1 -0
  199. package/dist/core/components/viewers/map/utils/geocoding/pelias.js +35 -0
  200. package/dist/core/components/viewers/map/utils/geocoding/pelias.js.map +1 -0
  201. package/dist/core/components/viewers/pointcloud/PointCloudToolbar.d.ts.map +1 -1
  202. package/dist/core/components/viewers/pointcloud/PointCloudToolbar.js.map +1 -1
  203. package/dist/core/components/viewers/pointcloud/PointCloudViewer.js +1 -3
  204. package/dist/core/components/viewers/pointcloud/PointCloudViewer.js.map +1 -1
  205. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.d.ts.map +1 -1
  206. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js +2 -3
  207. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js.map +1 -1
  208. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
  209. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.js +8 -2
  210. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/FilesSection.js.map +1 -1
  211. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts.map +1 -1
  212. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js.map +1 -1
  213. package/dist/core/components/viewers/pointcloud/src/tools/PerformanceSettingsTools/NodeSizeSelectionTool.js +9 -9
  214. package/dist/core/components/viewers/pointcloud/src/tools/PerformanceSettingsTools/NodeSizeSelectionTool.js.map +1 -1
  215. package/dist/core/hooks/provider.js.map +1 -1
  216. package/dist/core/plugins/host/provider.d.ts.map +1 -1
  217. package/dist/core/plugins/host/provider.js.map +1 -1
  218. package/dist/core/store/AppConfig/context.d.ts.map +1 -1
  219. package/dist/core/store/AppConfig/context.js.map +1 -1
  220. package/dist/core/store/BIM/context.d.ts.map +1 -1
  221. package/dist/core/store/BIM/context.js.map +1 -1
  222. package/dist/core/store/BIM/reducer.d.ts +0 -1
  223. package/dist/core/store/BIM/reducer.d.ts.map +1 -1
  224. package/dist/core/store/BIM/reducer.js +0 -4
  225. package/dist/core/store/BIM/reducer.js.map +1 -1
  226. package/dist/core/store/Buildings/context.d.ts.map +1 -1
  227. package/dist/core/store/Buildings/context.js.map +1 -1
  228. package/dist/core/store/Content/context.d.ts.map +1 -1
  229. package/dist/core/store/Content/context.js.map +1 -1
  230. package/dist/core/store/Datasets/context.d.ts.map +1 -1
  231. package/dist/core/store/Datasets/context.js +2 -1
  232. package/dist/core/store/Datasets/context.js.map +1 -1
  233. package/dist/core/store/Datasets/reducer.d.ts +2 -0
  234. package/dist/core/store/Datasets/reducer.d.ts.map +1 -1
  235. package/dist/core/store/Datasets/reducer.js +9 -4
  236. package/dist/core/store/Datasets/reducer.js.map +1 -1
  237. package/dist/core/store/Files/context.d.ts.map +1 -1
  238. package/dist/core/store/Files/context.js.map +1 -1
  239. package/dist/core/store/Map/context.d.ts.map +1 -1
  240. package/dist/core/store/Map/context.js.map +1 -1
  241. package/dist/core/store/Menus/context.d.ts.map +1 -1
  242. package/dist/core/store/Menus/context.js.map +1 -1
  243. package/dist/core/store/Permissions/context.d.ts.map +1 -1
  244. package/dist/core/store/Permissions/context.js.map +1 -1
  245. package/dist/core/store/PointCloud/context.d.ts.map +1 -1
  246. package/dist/core/store/PointCloud/context.js.map +1 -1
  247. package/dist/core/store/Tools/context.d.ts.map +1 -1
  248. package/dist/core/store/Tools/context.js.map +1 -1
  249. package/dist/core/types/datasetTypes.d.ts +8 -1
  250. package/dist/core/types/datasetTypes.d.ts.map +1 -1
  251. package/dist/core/types/dbTypes.d.ts +13 -13
  252. package/dist/core/types/dbTypes.d.ts.map +1 -1
  253. package/dist/core/types/dbTypes.js +13 -13
  254. package/dist/core/types/dbTypes.js.map +1 -1
  255. package/dist/core/types/index.d.ts +1 -1
  256. package/dist/core/types/index.d.ts.map +1 -1
  257. package/dist/core/types/index.js.map +1 -1
  258. package/dist/core/utils/imageUtils.js +1 -1
  259. package/dist/core/utils/imageUtils.js.map +1 -1
  260. package/package.json +4 -3
  261. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.d.ts +0 -3
  262. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.d.ts.map +0 -1
  263. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.js +0 -173
  264. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudViewer-old.js.map +0 -1
@@ -7,20 +7,33 @@ import { Highlighter } from "../../../Highlighter";
7
7
  import { Cursor } from "../../../Cursor";
8
8
  import { AddDxf } from "./AddDxf";
9
9
  import { addFileToScene } from "./FileHandler";
10
+ import { removeMarker } from "./FileMarkerUtils";
10
11
  import { getFileExtension } from "../../../../../../../utils/utils";
11
- function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildingId, uploadFileToDB) {
12
+ const GROUND_PLANE = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
13
+ const pointOnGroundPlane = (camera, canvas, clientX, clientY) => {
14
+ const rect = canvas.getBoundingClientRect();
15
+ const ndc = new THREE.Vector2(
16
+ (clientX - rect.left) / rect.width * 2 - 1,
17
+ -((clientY - rect.top) / rect.height) * 2 + 1
18
+ );
19
+ const raycaster = new THREE.Raycaster();
20
+ raycaster.setFromCamera(ndc, camera);
21
+ const target = new THREE.Vector3();
22
+ return raycaster.ray.intersectPlane(GROUND_PLANE, target) ? target : null;
23
+ };
24
+ function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildingId, uploadFileToDB, onMarkerAction) {
12
25
  const [selectedFile, setSelectedFile] = React.useState(null);
13
- const [addedFiles, setAddedFiles] = React.useState([]);
14
26
  const [mousePosition, setMousePosition] = React.useState({ x: 0, y: 0 });
15
27
  const [isPlacingFile, setIsPlacingFile] = React.useState(false);
16
28
  const [fileScale, setFileScale] = React.useState(1);
17
29
  const [fileRotation, setFileRotation] = React.useState(0);
18
- const [confirmed3DFiles, setConfirmed3DFiles] = React.useState(/* @__PURE__ */ new Set());
19
30
  const [show3DScaleCard, setShow3DScaleCard] = React.useState(false);
20
31
  const [current3DFileId, setCurrent3DFileId] = React.useState(null);
21
32
  const [current3DFileType, setCurrent3DFileType] = React.useState(null);
22
33
  const [modelManager, setModelManager] = React.useState(null);
23
34
  const [addDxf, setAddDxf] = React.useState(null);
35
+ const placedFilesRef = React.useRef(/* @__PURE__ */ new Map());
36
+ const [markerCount, setMarkerCount] = React.useState(0);
24
37
  const highlighter = React.useMemo(() => {
25
38
  if (!bimComponents) return null;
26
39
  try {
@@ -35,16 +48,12 @@ function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildi
35
48
  const manager = bimComponents.get(ModelManager);
36
49
  if (manager) setModelManager(manager);
37
50
  }
38
- if (!addDxf) {
39
- const dxfUtility = new AddDxf(bimComponents, world);
40
- setAddDxf(dxfUtility);
41
- }
51
+ if (!addDxf) setAddDxf(new AddDxf(bimComponents, world));
42
52
  }, [bimComponents, world, modelManager, addDxf]);
43
53
  const setCursor = React.useCallback((cursor) => {
44
54
  if (!bimComponents) return;
45
55
  const currentCursor = bimComponents.get(Cursor);
46
- if (!currentCursor) return;
47
- currentCursor.cursor = cursor;
56
+ if (currentCursor) currentCursor.cursor = cursor;
48
57
  }, [bimComponents]);
49
58
  const raycast = React.useCallback(async (data) => {
50
59
  if (!fragments || !highlighter) return null;
@@ -54,23 +63,18 @@ function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildi
54
63
  const result = await model.raycast(data);
55
64
  if (result) results.push(result);
56
65
  }
57
- await Promise.all(results);
58
66
  if (results.length === 0) return null;
59
- let closestResult = results[0];
60
- let minDistance = closestResult.distance;
67
+ let closest = results[0];
61
68
  for (let i = 1; i < results.length; i++) {
62
- if (results[i].distance < minDistance) {
63
- minDistance = results[i].distance;
64
- closestResult = results[i];
65
- }
69
+ if (results[i].distance < closest.distance) closest = results[i];
66
70
  }
67
- return closestResult;
71
+ return closest;
68
72
  }, [fragments, highlighter]);
69
73
  const processFileObject = React.useCallback((file, addingMode) => {
70
74
  const fileName = file.name.toLowerCase();
71
75
  if (addingMode === "bim-add-cad") {
72
76
  if (!fileName.endsWith(".dxf")) {
73
- alert("Please select a valid CAD file (.dxf)");
77
+ toast.error("Please select a valid CAD file (.dxf)");
74
78
  return;
75
79
  }
76
80
  setShow3DScaleCard(true);
@@ -90,7 +94,7 @@ function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildi
90
94
  setSelectedFile(file);
91
95
  setIsPlacingFile(true);
92
96
  setCursor("crosshair");
93
- toast.info(`Double-click on the model to place: "${file.name}"`, {
97
+ toast.info(`Double-click in the scene to place: "${file.name}"`, {
94
98
  id: "place-bim-file-toast",
95
99
  duration: Infinity
96
100
  });
@@ -98,8 +102,7 @@ function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildi
98
102
  const handleFileSelect = React.useCallback((event, addingMode) => {
99
103
  var _a;
100
104
  const file = (_a = event.target.files) == null ? void 0 : _a[0];
101
- if (!file) return;
102
- processFileObject(file, addingMode);
105
+ if (file) processFileObject(file, addingMode);
103
106
  }, [processFileObject]);
104
107
  const handleFileDrop = React.useCallback((file, addingMode) => {
105
108
  processFileObject(file, addingMode);
@@ -116,9 +119,47 @@ function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildi
116
119
  toast.dismiss("place-bim-file-toast");
117
120
  toolsDispatch({ type: "CLEAR-TOOLS" });
118
121
  }, [setCursor, toolsDispatch]);
122
+ const uploadPlacedFile = React.useCallback(async (file, point, rotation = 0) => {
123
+ if (!uploadFileToDB || buildingId <= 0) return;
124
+ try {
125
+ const assetId = crypto.randomUUID();
126
+ const presignedResponse = await fetch(`/api/presigned-url-upload?asset=${assetId}`);
127
+ if (!presignedResponse.ok) return;
128
+ const { presignedUrl } = await presignedResponse.json();
129
+ await fetch(presignedUrl, {
130
+ method: "PUT",
131
+ body: file,
132
+ headers: { "Content-Type": file.type }
133
+ });
134
+ await uploadFileToDB({
135
+ fileData: {
136
+ name: file.name,
137
+ type: "bim-file",
138
+ mimeType: file.type,
139
+ extension: getFileExtension(file),
140
+ sizeBytes: file.size,
141
+ tag: "file",
142
+ uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
143
+ url: "",
144
+ assetId,
145
+ description: "",
146
+ attachedFilesBuildingId: buildingId,
147
+ isVisible: true,
148
+ x: point.x,
149
+ y: point.y,
150
+ z: point.z,
151
+ rotation
152
+ },
153
+ buildingId
154
+ });
155
+ } catch (err) {
156
+ console.error("Error uploading placed file:", err);
157
+ }
158
+ }, [uploadFileToDB, buildingId]);
119
159
  React.useEffect(() => {
120
160
  if (!selectedFile || !bimComponents || !world || !isPlacingFile) return;
121
161
  const mouse = new THREE.Vector2();
162
+ const canvas = world.renderer.three.domElement;
122
163
  const handleMouseMove = (e) => {
123
164
  setMousePosition({ x: e.clientX, y: e.clientY });
124
165
  mouse.x = e.clientX;
@@ -127,76 +168,44 @@ function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildi
127
168
  const handleDblClick = async (e) => {
128
169
  mouse.x = e.clientX;
129
170
  mouse.y = e.clientY;
130
- const result = await raycast({
131
- camera: world.camera.three,
132
- mouse,
133
- dom: world.renderer.three.domElement
134
- });
135
- if ((result == null ? void 0 : result.point) && (result.point.x !== 0 || result.point.y !== 0 || result.point.z !== 0)) {
136
- const newAddedFile = {
137
- id: Date.now().toString(),
138
- file: selectedFile,
139
- position: result.point.clone(),
140
- imageUrl: selectedFile.type.startsWith("image/") ? URL.createObjectURL(selectedFile) : void 0
141
- };
142
- setAddedFiles((prev) => [...prev, newAddedFile]);
143
- await addFileToScene(
144
- newAddedFile,
145
- fileScale,
146
- fileRotation,
147
- world,
148
- modelManager,
149
- addDxf,
150
- toolsDispatch,
151
- setCurrent3DFileId
152
- );
153
- if (uploadFileToDB && buildingId > 0) {
154
- try {
155
- const fileId = crypto.randomUUID();
156
- const presignedResponse = await fetch(`/api/presigned-url-upload?asset=${fileId}`);
157
- if (presignedResponse.ok) {
158
- const { presignedUrl } = await presignedResponse.json();
159
- await fetch(presignedUrl, {
160
- method: "PUT",
161
- body: selectedFile,
162
- headers: { "Content-Type": selectedFile.type }
163
- });
164
- await uploadFileToDB({
165
- fileData: {
166
- name: selectedFile.name,
167
- type: "bim-file",
168
- mimeType: selectedFile.type,
169
- extension: getFileExtension(selectedFile),
170
- sizeBytes: selectedFile.size,
171
- tag: "file",
172
- uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
173
- url: "",
174
- assetId: fileId,
175
- description: "",
176
- attachedFilesBuildingId: buildingId,
177
- isVisible: true,
178
- x: result.point.x,
179
- y: result.point.y,
180
- z: result.point.z
181
- },
182
- buildingId
183
- });
184
- }
185
- } catch (err) {
186
- console.error("Error uploading file to database:", err);
187
- }
188
- }
189
- const fileName = selectedFile.name.toLowerCase();
190
- const is3DFile = fileName.endsWith(".dxf") || fileName.endsWith(".glb") || fileName.endsWith(".gltf");
191
- if (is3DFile) {
192
- setIsPlacingFile(false);
193
- setCursor("");
194
- } else {
195
- cancelPlacement();
196
- }
171
+ const modelHit = await raycast({ camera: world.camera.three, mouse, dom: canvas });
172
+ const point = (modelHit == null ? void 0 : modelHit.point) ? modelHit.point.clone() : pointOnGroundPlane(world.camera.three, canvas, e.clientX, e.clientY);
173
+ if (!point) return;
174
+ const addedFile = {
175
+ id: Date.now().toString(),
176
+ file: selectedFile,
177
+ position: point,
178
+ imageUrl: selectedFile.type.startsWith("image/") ? URL.createObjectURL(selectedFile) : void 0
179
+ };
180
+ const placed = await addFileToScene(
181
+ addedFile,
182
+ fileScale,
183
+ fileRotation,
184
+ world,
185
+ modelManager,
186
+ addDxf,
187
+ setCurrent3DFileId,
188
+ (action) => onMarkerAction == null ? void 0 : onMarkerAction(addedFile.id, action)
189
+ );
190
+ if (placed) {
191
+ placedFilesRef.current.set(addedFile.id, {
192
+ id: addedFile.id,
193
+ name: selectedFile.name,
194
+ kind: placed.kind,
195
+ marker: placed.marker,
196
+ object3D: placed.object3D
197
+ });
198
+ setMarkerCount((c) => c + 1);
199
+ }
200
+ const fileName = selectedFile.name.toLowerCase();
201
+ const is3DFile = fileName.endsWith(".dxf") || fileName.endsWith(".glb") || fileName.endsWith(".gltf");
202
+ if (is3DFile) {
203
+ setIsPlacingFile(false);
204
+ setCursor("");
205
+ } else {
206
+ void uploadPlacedFile(selectedFile, point);
207
+ cancelPlacement();
197
208
  }
198
- document.removeEventListener("mousemove", handleMouseMove);
199
- document.removeEventListener("dblclick", handleDblClick);
200
209
  };
201
210
  document.addEventListener("mousemove", handleMouseMove);
202
211
  document.addEventListener("dblclick", handleDblClick);
@@ -204,21 +213,27 @@ function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildi
204
213
  document.removeEventListener("mousemove", handleMouseMove);
205
214
  document.removeEventListener("dblclick", handleDblClick);
206
215
  };
207
- }, [selectedFile, bimComponents, world, isPlacingFile, fileScale, fileRotation, modelManager, addDxf, toolsDispatch, raycast, cancelPlacement, setCursor]);
216
+ }, [selectedFile, bimComponents, world, isPlacingFile, fileScale, fileRotation, modelManager, addDxf, toolsDispatch, raycast, cancelPlacement, setCursor, uploadPlacedFile, onMarkerAction]);
208
217
  const confirmPlacement = React.useCallback(() => {
209
- if (!selectedFile || addedFiles.length === 0 || !current3DFileId) return;
210
- const latest3DFile = addedFiles.findLast((f) => {
211
- const name = f.file.name.toLowerCase();
212
- return name.endsWith(".dxf") || name.endsWith(".glb") || name.endsWith(".gltf");
213
- });
214
- if (latest3DFile) {
215
- if (current3DFileType === "dxf" && addDxf) {
216
- addDxf.confirmPlacement(current3DFileId);
217
- } else if (current3DFileType === "model" && modelManager) {
218
- modelManager.toggleGizmo(current3DFileId, false);
218
+ if (!current3DFileId) return;
219
+ let finalPos;
220
+ let finalRot = fileRotation;
221
+ if (current3DFileType === "dxf" && addDxf) {
222
+ const info = addDxf.getDxf(current3DFileId);
223
+ if (info) {
224
+ finalPos = info.group.position.clone();
225
+ finalRot = THREE.MathUtils.radToDeg(info.group.rotation.y);
226
+ }
227
+ addDxf.confirmPlacement(current3DFileId);
228
+ } else if (current3DFileType === "model" && modelManager) {
229
+ const info = modelManager.getModel(current3DFileId);
230
+ if (info) {
231
+ finalPos = info.model.position.clone();
232
+ finalRot = THREE.MathUtils.radToDeg(info.model.rotation.y);
219
233
  }
220
- setConfirmed3DFiles((prev) => new Set(prev).add(latest3DFile.id));
234
+ modelManager.toggleGizmo(current3DFileId, false);
221
235
  }
236
+ if (selectedFile && finalPos) void uploadPlacedFile(selectedFile, finalPos, finalRot);
222
237
  setShow3DScaleCard(false);
223
238
  setCurrent3DFileId(null);
224
239
  setCurrent3DFileType(null);
@@ -229,7 +244,7 @@ function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildi
229
244
  setCursor("");
230
245
  toast.dismiss("place-bim-file-toast");
231
246
  toolsDispatch({ type: "CLEAR-TOOLS" });
232
- }, [selectedFile, addedFiles, current3DFileId, current3DFileType, addDxf, modelManager, setCursor, toolsDispatch]);
247
+ }, [current3DFileId, current3DFileType, addDxf, modelManager, selectedFile, fileRotation, uploadPlacedFile, setCursor, toolsDispatch]);
233
248
  React.useEffect(() => {
234
249
  if (!current3DFileId || !show3DScaleCard || !current3DFileType) return;
235
250
  if (current3DFileType === "dxf" && addDxf) {
@@ -240,9 +255,51 @@ function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildi
240
255
  modelManager.setRotation(current3DFileId, new THREE.Euler(0, THREE.MathUtils.degToRad(fileRotation), 0));
241
256
  }
242
257
  }, [fileScale, fileRotation, current3DFileId, show3DScaleCard, current3DFileType, addDxf, modelManager]);
258
+ React.useEffect(() => {
259
+ if (!world || markerCount === 0) return;
260
+ let raf = 0;
261
+ const worldPos = new THREE.Vector3();
262
+ const tick = () => {
263
+ placedFilesRef.current.forEach((placed) => {
264
+ var _a, _b;
265
+ if (!placed.marker) return;
266
+ placed.object3D.getWorldPosition(worldPos);
267
+ placed.marker.position.set(worldPos.x, worldPos.y + 0.2, worldPos.z);
268
+ const editing = placed.kind === "dxf" ? !!((_a = addDxf == null ? void 0 : addDxf.getDxf(placed.id)) == null ? void 0 : _a.gizmoController) : placed.kind === "model" ? !!((_b = modelManager == null ? void 0 : modelManager.getModel(placed.id)) == null ? void 0 : _b.gizmoController) : false;
269
+ placed.marker.visible = !editing;
270
+ });
271
+ raf = requestAnimationFrame(tick);
272
+ };
273
+ raf = requestAnimationFrame(tick);
274
+ return () => cancelAnimationFrame(raf);
275
+ }, [world, addDxf, modelManager, markerCount]);
276
+ const getPlacedFile = React.useCallback((id) => {
277
+ return placedFilesRef.current.get(id);
278
+ }, []);
279
+ const editPlacedFile = React.useCallback((id, mode = "translate") => {
280
+ var _a, _b;
281
+ const placed = placedFilesRef.current.get(id);
282
+ if (!placed) return;
283
+ if (placed.kind === "dxf" && addDxf) {
284
+ addDxf.toggleGizmo(id, true);
285
+ addDxf.setGizmoMode(id, mode);
286
+ } else if (placed.kind === "model" && modelManager) {
287
+ modelManager.toggleGizmo(id, true);
288
+ (_b = (_a = modelManager.getModel(id)) == null ? void 0 : _a.gizmoController) == null ? void 0 : _b.setMode(mode);
289
+ }
290
+ }, [addDxf, modelManager]);
291
+ const removePlacedFile = React.useCallback((id) => {
292
+ const placed = placedFilesRef.current.get(id);
293
+ if (!placed) return;
294
+ if (placed.kind === "dxf") addDxf == null ? void 0 : addDxf.removeDxf(id);
295
+ else if (placed.kind === "model") modelManager == null ? void 0 : modelManager.remove(id);
296
+ else if (world) world.scene.three.remove(placed.object3D);
297
+ removeMarker(placed.marker, world);
298
+ placedFilesRef.current.delete(id);
299
+ setMarkerCount((c) => Math.max(0, c - 1));
300
+ }, [addDxf, modelManager, world]);
243
301
  return {
244
302
  selectedFile,
245
- addedFiles,
246
303
  mousePosition,
247
304
  isPlacingFile,
248
305
  fileScale,
@@ -256,7 +313,10 @@ function useFilePlacement(bimComponents, world, fragments, toolsDispatch, buildi
256
313
  cancelPlacement,
257
314
  confirmPlacement,
258
315
  setCursor,
259
- raycast
316
+ raycast,
317
+ getPlacedFile,
318
+ editPlacedFile,
319
+ removePlacedFile
260
320
  };
261
321
  }
262
322
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.ts"],"sourcesContent":["\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport * as THREE from \"three\"\r\nimport * as OBC from \"@thatopen/components\"\r\nimport { toast } from \"sonner\"\r\nimport { ModelManager } from \"../../../ModelManager\"\r\nimport { Highlighter } from \"../../../Highlighter\"\r\nimport { Cursor } from \"../../../Cursor\"\r\nimport { AddDxf } from \"./AddDxf\"\r\nimport { addFileToScene } from \"./FileHandler\"\r\nimport type { AddedFile } from \"./FileMarkerUtils\"\r\nimport type { BimToolbarToolsType } from \"../../bimToolbar\"\r\nimport { getFileExtension } from \"../../../../../../../utils/utils\"\r\n\r\nexport function useFilePlacement(\r\n bimComponents: OBC.Components | null,\r\n world: OBC.World | null,\r\n fragments: OBC.FragmentsManager | null,\r\n toolsDispatch: React.Dispatch<any>,\r\n buildingId: number,\r\n uploadFileToDB?: (args: { fileData: any; buildingId: number }) => Promise<any>,\r\n) {\r\n const [selectedFile, setSelectedFile] = React.useState<File | null>(null)\r\n const [addedFiles, setAddedFiles] = React.useState<AddedFile[]>([])\r\n const [mousePosition, setMousePosition] = React.useState({ x: 0, y: 0 })\r\n const [isPlacingFile, setIsPlacingFile] = React.useState(false)\r\n\r\n const [fileScale, setFileScale] = React.useState(1)\r\n const [fileRotation, setFileRotation] = React.useState(0)\r\n const [confirmed3DFiles, setConfirmed3DFiles] = React.useState<Set<string>>(new Set())\r\n const [show3DScaleCard, setShow3DScaleCard] = React.useState(false)\r\n const [current3DFileId, setCurrent3DFileId] = React.useState<string | null>(null)\r\n const [current3DFileType, setCurrent3DFileType] = React.useState<\"dxf\" | \"model\" | null>(null)\r\n\r\n // Managers\r\n const [modelManager, setModelManager] = React.useState<ModelManager | null>(null)\r\n const [addDxf, setAddDxf] = React.useState<AddDxf | null>(null)\r\n\r\n const highlighter = React.useMemo(() => {\r\n if (!bimComponents) return null\r\n try { return bimComponents.get(Highlighter) } catch { return null }\r\n }, [bimComponents])\r\n\r\n React.useEffect(() => {\r\n if (!bimComponents || !world) return\r\n if (!modelManager) {\r\n const manager = bimComponents.get(ModelManager)\r\n if (manager) setModelManager(manager)\r\n }\r\n if (!addDxf) {\r\n const dxfUtility = new AddDxf(bimComponents, world)\r\n setAddDxf(dxfUtility)\r\n }\r\n }, [bimComponents, world, modelManager, addDxf])\r\n\r\n const setCursor = React.useCallback((cursor: string) => {\r\n if (!bimComponents) return\r\n const currentCursor = bimComponents.get(Cursor)\r\n if (!currentCursor) return\r\n currentCursor.cursor = cursor as any\r\n }, [bimComponents])\r\n\r\n const raycast = React.useCallback(async (data: {\r\n camera: THREE.PerspectiveCamera | THREE.OrthographicCamera\r\n mouse: THREE.Vector2\r\n dom: HTMLCanvasElement\r\n }) => {\r\n if (!fragments || !highlighter) return null\r\n\r\n const results = []\r\n for (const [modelName, model] of fragments.core.models.list) {\r\n if (highlighter.isModelDisabled(modelName)) continue\r\n const result = await model.raycast(data)\r\n if (result) results.push(result)\r\n }\r\n\r\n await Promise.all(results)\r\n if (results.length === 0) return null\r\n\r\n let closestResult = results[0]\r\n let minDistance = closestResult.distance\r\n for (let i = 1; i < results.length; i++) {\r\n if (results[i].distance < minDistance) {\r\n minDistance = results[i].distance\r\n closestResult = results[i]\r\n }\r\n }\r\n\r\n return closestResult\r\n }, [fragments, highlighter])\r\n\r\n const processFileObject = React.useCallback((file: File, addingMode: BimToolbarToolsType) => {\r\n const fileName = file.name.toLowerCase()\r\n\r\n if (addingMode === \"bim-add-cad\") {\r\n if (!fileName.endsWith(\".dxf\")) {\r\n alert(\"Please select a valid CAD file (.dxf)\")\r\n return\r\n }\r\n setShow3DScaleCard(true)\r\n setCurrent3DFileType(\"dxf\")\r\n setFileScale(0.001)\r\n } else if (addingMode === \"bim-add-file\") {\r\n if (fileName.endsWith(\".glb\") || fileName.endsWith(\".gltf\")) {\r\n setShow3DScaleCard(true)\r\n setCurrent3DFileType(\"model\")\r\n setFileScale(1)\r\n } else if (fileName.endsWith(\".dxf\")) {\r\n setShow3DScaleCard(true)\r\n setCurrent3DFileType(\"dxf\")\r\n setFileScale(0.001)\r\n }\r\n }\r\n\r\n setSelectedFile(file)\r\n setIsPlacingFile(true)\r\n setCursor(\"crosshair\")\r\n toast.info(`Double-click on the model to place: \"${file.name}\"`, {\r\n id: 'place-bim-file-toast',\r\n duration: Infinity,\r\n })\r\n }, [setCursor])\r\n\r\n const handleFileSelect = React.useCallback((event: React.ChangeEvent<HTMLInputElement>, addingMode: BimToolbarToolsType) => {\r\n const file = event.target.files?.[0]\r\n if (!file) return\r\n processFileObject(file, addingMode)\r\n }, [processFileObject])\r\n\r\n const handleFileDrop = React.useCallback((file: File, addingMode: BimToolbarToolsType) => {\r\n processFileObject(file, addingMode)\r\n }, [processFileObject])\r\n\r\n const cancelPlacement = React.useCallback(() => {\r\n setSelectedFile(null)\r\n setIsPlacingFile(false)\r\n setShow3DScaleCard(false)\r\n setCurrent3DFileId(null)\r\n setCurrent3DFileType(null)\r\n setFileScale(1)\r\n setFileRotation(0)\r\n setCursor(\"\")\r\n toast.dismiss('place-bim-file-toast')\r\n toolsDispatch({ type: \"CLEAR-TOOLS\" })\r\n }, [setCursor, toolsDispatch])\r\n\r\n // Handle file placement on double-click\r\n React.useEffect(() => {\r\n if (!selectedFile || !bimComponents || !world || !isPlacingFile) return\r\n\r\n const mouse = new THREE.Vector2()\r\n\r\n const handleMouseMove = (e: MouseEvent) => {\r\n setMousePosition({ x: e.clientX, y: e.clientY })\r\n mouse.x = e.clientX\r\n mouse.y = e.clientY\r\n }\r\n\r\n const handleDblClick = async (e: MouseEvent) => {\r\n mouse.x = e.clientX\r\n mouse.y = e.clientY\r\n\r\n const result = await raycast({\r\n camera: world.camera.three,\r\n mouse,\r\n dom: world.renderer!.three.domElement!,\r\n })\r\n\r\n if (result?.point && (result.point.x !== 0 || result.point.y !== 0 || result.point.z !== 0)) {\r\n const newAddedFile: AddedFile = {\r\n id: Date.now().toString(),\r\n file: selectedFile,\r\n position: result.point.clone(),\r\n imageUrl: selectedFile.type.startsWith(\"image/\")\r\n ? URL.createObjectURL(selectedFile)\r\n : undefined,\r\n }\r\n\r\n setAddedFiles(prev => [...prev, newAddedFile])\r\n await addFileToScene(\r\n newAddedFile, fileScale, fileRotation,\r\n world, modelManager, addDxf, toolsDispatch, setCurrent3DFileId,\r\n )\r\n\r\n // Upload the file to the database with its 3D position\r\n if (uploadFileToDB && buildingId > 0) {\r\n try {\r\n const fileId = crypto.randomUUID()\r\n const presignedResponse = await fetch(`/api/presigned-url-upload?asset=${fileId}`)\r\n if (presignedResponse.ok) {\r\n const { presignedUrl } = await presignedResponse.json()\r\n await fetch(presignedUrl, {\r\n method: \"PUT\",\r\n body: selectedFile,\r\n headers: { \"Content-Type\": selectedFile.type },\r\n })\r\n await uploadFileToDB({\r\n fileData: {\r\n name: selectedFile.name,\r\n type: \"bim-file\",\r\n mimeType: selectedFile.type,\r\n extension: getFileExtension(selectedFile),\r\n sizeBytes: selectedFile.size,\r\n tag: \"file\",\r\n uploadedAt: new Date().toISOString(),\r\n url: \"\",\r\n assetId: fileId,\r\n description: \"\",\r\n attachedFilesBuildingId: buildingId,\r\n isVisible: true,\r\n x: result.point.x,\r\n y: result.point.y,\r\n z: result.point.z,\r\n },\r\n buildingId,\r\n })\r\n }\r\n } catch (err) {\r\n console.error(\"Error uploading file to database:\", err)\r\n }\r\n }\r\n\r\n const fileName = selectedFile.name.toLowerCase()\r\n const is3DFile = fileName.endsWith(\".dxf\") || fileName.endsWith(\".glb\") || fileName.endsWith(\".gltf\")\r\n\r\n if (is3DFile) {\r\n setIsPlacingFile(false)\r\n setCursor(\"\")\r\n } else {\r\n cancelPlacement()\r\n }\r\n }\r\n\r\n document.removeEventListener(\"mousemove\", handleMouseMove)\r\n document.removeEventListener(\"dblclick\", handleDblClick)\r\n }\r\n\r\n document.addEventListener(\"mousemove\", handleMouseMove)\r\n document.addEventListener(\"dblclick\", handleDblClick)\r\n\r\n return () => {\r\n document.removeEventListener(\"mousemove\", handleMouseMove)\r\n document.removeEventListener(\"dblclick\", handleDblClick)\r\n }\r\n }, [selectedFile, bimComponents, world, isPlacingFile, fileScale, fileRotation, modelManager, addDxf, toolsDispatch, raycast, cancelPlacement, setCursor])\r\n\r\n const confirmPlacement = React.useCallback(() => {\r\n if (!selectedFile || addedFiles.length === 0 || !current3DFileId) return\r\n\r\n const latest3DFile = addedFiles.findLast(f => {\r\n const name = f.file.name.toLowerCase()\r\n return name.endsWith(\".dxf\") || name.endsWith(\".glb\") || name.endsWith(\".gltf\")\r\n })\r\n\r\n if (latest3DFile) {\r\n if (current3DFileType === \"dxf\" && addDxf) {\r\n addDxf.confirmPlacement(current3DFileId)\r\n } else if (current3DFileType === \"model\" && modelManager) {\r\n modelManager.toggleGizmo(current3DFileId, false)\r\n }\r\n setConfirmed3DFiles(prev => new Set(prev).add(latest3DFile.id))\r\n }\r\n\r\n setShow3DScaleCard(false)\r\n setCurrent3DFileId(null)\r\n setCurrent3DFileType(null)\r\n setFileRotation(0)\r\n setFileScale(1)\r\n setSelectedFile(null)\r\n setIsPlacingFile(false)\r\n setCursor(\"\")\r\n toast.dismiss('place-bim-file-toast')\r\n toolsDispatch({ type: \"CLEAR-TOOLS\" })\r\n }, [selectedFile, addedFiles, current3DFileId, current3DFileType, addDxf, modelManager, setCursor, toolsDispatch])\r\n\r\n // Real-time scale/rotation updates for 3D files\r\n React.useEffect(() => {\r\n if (!current3DFileId || !show3DScaleCard || !current3DFileType) return\r\n\r\n if (current3DFileType === \"dxf\" && addDxf) {\r\n addDxf.updateScale(current3DFileId, fileScale)\r\n addDxf.updateRotation(current3DFileId, fileRotation)\r\n } else if (current3DFileType === \"model\" && modelManager) {\r\n modelManager.setScale(current3DFileId, fileScale)\r\n modelManager.setRotation(current3DFileId, new THREE.Euler(0, THREE.MathUtils.degToRad(fileRotation), 0))\r\n }\r\n }, [fileScale, fileRotation, current3DFileId, show3DScaleCard, current3DFileType, addDxf, modelManager])\r\n\r\n return {\r\n selectedFile,\r\n addedFiles,\r\n mousePosition,\r\n isPlacingFile,\r\n fileScale,\r\n fileRotation,\r\n show3DScaleCard,\r\n current3DFileType,\r\n setFileScale,\r\n setFileRotation,\r\n handleFileSelect,\r\n handleFileDrop,\r\n cancelPlacement,\r\n confirmPlacement,\r\n setCursor,\r\n raycast,\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../../../../../../src/core/components/viewers/bim/src/tools/AddToBim/src/useFilePlacement.ts"],"sourcesContent":["\"use client\"\r\n\r\nimport * as React from \"react\"\r\nimport * as THREE from \"three\"\r\nimport * as OBC from \"@thatopen/components\"\r\nimport { toast } from \"sonner\"\r\nimport { ModelManager } from \"../../../ModelManager\"\r\nimport { Highlighter } from \"../../../Highlighter\"\r\nimport { Cursor } from \"../../../Cursor\"\r\nimport { AddDxf } from \"./AddDxf\"\r\nimport { addFileToScene, type PlacedKind } from \"./FileHandler\"\r\nimport { type AddedFile, removeMarker } from \"./FileMarkerUtils\"\r\nimport type { FileMarkerAction } from \"../../../../../../ui/FilesManager/src/FileMarker\"\r\nimport type { CSS2DObject } from \"three/addons/renderers/CSS2DRenderer.js\"\r\nimport type { BimToolbarToolsType } from \"../../bimToolbar\"\r\nimport { getFileExtension } from \"../../../../../../../utils/utils\"\r\n\r\nexport type GizmoMode = \"translate\" | \"rotate\" | \"scale\"\r\n\r\nexport interface PlacedFile {\r\n id: string\r\n name: string\r\n kind: PlacedKind\r\n marker: CSS2DObject | null\r\n object3D: THREE.Object3D\r\n}\r\n\r\n// Horizontal floor at world height 0; used when a double-click misses all BIM geometry.\r\nconst GROUND_PLANE = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0)\r\n\r\nconst pointOnGroundPlane = (\r\n camera: THREE.Camera,\r\n canvas: HTMLCanvasElement,\r\n clientX: number,\r\n clientY: number,\r\n): THREE.Vector3 | null => {\r\n const rect = canvas.getBoundingClientRect()\r\n const ndc = new THREE.Vector2(\r\n ((clientX - rect.left) / rect.width) * 2 - 1,\r\n -((clientY - rect.top) / rect.height) * 2 + 1,\r\n )\r\n const raycaster = new THREE.Raycaster()\r\n raycaster.setFromCamera(ndc, camera)\r\n const target = new THREE.Vector3()\r\n return raycaster.ray.intersectPlane(GROUND_PLANE, target) ? target : null\r\n}\r\n\r\nexport function useFilePlacement(\r\n bimComponents: OBC.Components | null,\r\n world: OBC.World | null,\r\n fragments: OBC.FragmentsManager | null,\r\n toolsDispatch: React.Dispatch<any>,\r\n buildingId: number,\r\n uploadFileToDB?: (args: { fileData: any; buildingId: number }) => Promise<any>,\r\n onMarkerAction?: (id: string, action: FileMarkerAction) => void,\r\n) {\r\n const [selectedFile, setSelectedFile] = React.useState<File | null>(null)\r\n const [mousePosition, setMousePosition] = React.useState({ x: 0, y: 0 })\r\n const [isPlacingFile, setIsPlacingFile] = React.useState(false)\r\n\r\n const [fileScale, setFileScale] = React.useState(1)\r\n const [fileRotation, setFileRotation] = React.useState(0)\r\n const [show3DScaleCard, setShow3DScaleCard] = React.useState(false)\r\n const [current3DFileId, setCurrent3DFileId] = React.useState<string | null>(null)\r\n const [current3DFileType, setCurrent3DFileType] = React.useState<\"dxf\" | \"model\" | null>(null)\r\n\r\n const [modelManager, setModelManager] = React.useState<ModelManager | null>(null)\r\n const [addDxf, setAddDxf] = React.useState<AddDxf | null>(null)\r\n\r\n const placedFilesRef = React.useRef<Map<string, PlacedFile>>(new Map())\r\n const [markerCount, setMarkerCount] = React.useState(0)\r\n\r\n const highlighter = React.useMemo(() => {\r\n if (!bimComponents) return null\r\n try { return bimComponents.get(Highlighter) } catch { return null }\r\n }, [bimComponents])\r\n\r\n React.useEffect(() => {\r\n if (!bimComponents || !world) return\r\n if (!modelManager) {\r\n const manager = bimComponents.get(ModelManager)\r\n if (manager) setModelManager(manager)\r\n }\r\n if (!addDxf) setAddDxf(new AddDxf(bimComponents, world))\r\n }, [bimComponents, world, modelManager, addDxf])\r\n\r\n const setCursor = React.useCallback((cursor: string) => {\r\n if (!bimComponents) return\r\n const currentCursor = bimComponents.get(Cursor)\r\n if (currentCursor) currentCursor.cursor = cursor as any\r\n }, [bimComponents])\r\n\r\n const raycast = React.useCallback(async (data: {\r\n camera: THREE.PerspectiveCamera | THREE.OrthographicCamera\r\n mouse: THREE.Vector2\r\n dom: HTMLCanvasElement\r\n }) => {\r\n if (!fragments || !highlighter) return null\r\n\r\n const results = []\r\n for (const [modelName, model] of fragments.core.models.list) {\r\n if (highlighter.isModelDisabled(modelName)) continue\r\n const result = await model.raycast(data)\r\n if (result) results.push(result)\r\n }\r\n if (results.length === 0) return null\r\n\r\n let closest = results[0]\r\n for (let i = 1; i < results.length; i++) {\r\n if (results[i].distance < closest.distance) closest = results[i]\r\n }\r\n return closest\r\n }, [fragments, highlighter])\r\n\r\n const processFileObject = React.useCallback((file: File, addingMode: BimToolbarToolsType) => {\r\n const fileName = file.name.toLowerCase()\r\n\r\n if (addingMode === \"bim-add-cad\") {\r\n if (!fileName.endsWith(\".dxf\")) {\r\n toast.error(\"Please select a valid CAD file (.dxf)\")\r\n return\r\n }\r\n setShow3DScaleCard(true)\r\n setCurrent3DFileType(\"dxf\")\r\n setFileScale(0.001)\r\n } else if (addingMode === \"bim-add-file\") {\r\n if (fileName.endsWith(\".glb\") || fileName.endsWith(\".gltf\")) {\r\n setShow3DScaleCard(true)\r\n setCurrent3DFileType(\"model\")\r\n setFileScale(1)\r\n } else if (fileName.endsWith(\".dxf\")) {\r\n setShow3DScaleCard(true)\r\n setCurrent3DFileType(\"dxf\")\r\n setFileScale(0.001)\r\n }\r\n }\r\n\r\n setSelectedFile(file)\r\n setIsPlacingFile(true)\r\n setCursor(\"crosshair\")\r\n toast.info(`Double-click in the scene to place: \"${file.name}\"`, {\r\n id: 'place-bim-file-toast',\r\n duration: Infinity,\r\n })\r\n }, [setCursor])\r\n\r\n const handleFileSelect = React.useCallback((event: React.ChangeEvent<HTMLInputElement>, addingMode: BimToolbarToolsType) => {\r\n const file = event.target.files?.[0]\r\n if (file) processFileObject(file, addingMode)\r\n }, [processFileObject])\r\n\r\n const handleFileDrop = React.useCallback((file: File, addingMode: BimToolbarToolsType) => {\r\n processFileObject(file, addingMode)\r\n }, [processFileObject])\r\n\r\n const cancelPlacement = React.useCallback(() => {\r\n setSelectedFile(null)\r\n setIsPlacingFile(false)\r\n setShow3DScaleCard(false)\r\n setCurrent3DFileId(null)\r\n setCurrent3DFileType(null)\r\n setFileScale(1)\r\n setFileRotation(0)\r\n setCursor(\"\")\r\n toast.dismiss('place-bim-file-toast')\r\n toolsDispatch({ type: \"CLEAR-TOOLS\" })\r\n }, [setCursor, toolsDispatch])\r\n\r\n const uploadPlacedFile = React.useCallback(async (file: File, point: THREE.Vector3, rotation = 0) => {\r\n if (!uploadFileToDB || buildingId <= 0) return\r\n try {\r\n const assetId = crypto.randomUUID()\r\n const presignedResponse = await fetch(`/api/presigned-url-upload?asset=${assetId}`)\r\n if (!presignedResponse.ok) return\r\n const { presignedUrl } = await presignedResponse.json()\r\n await fetch(presignedUrl, {\r\n method: \"PUT\",\r\n body: file,\r\n headers: { \"Content-Type\": file.type },\r\n })\r\n await uploadFileToDB({\r\n fileData: {\r\n name: file.name,\r\n type: \"bim-file\",\r\n mimeType: file.type,\r\n extension: getFileExtension(file),\r\n sizeBytes: file.size,\r\n tag: \"file\",\r\n uploadedAt: new Date().toISOString(),\r\n url: \"\",\r\n assetId,\r\n description: \"\",\r\n attachedFilesBuildingId: buildingId,\r\n isVisible: true,\r\n x: point.x,\r\n y: point.y,\r\n z: point.z,\r\n rotation,\r\n },\r\n buildingId,\r\n })\r\n } catch (err) {\r\n console.error(\"Error uploading placed file:\", err)\r\n }\r\n }, [uploadFileToDB, buildingId])\r\n\r\n React.useEffect(() => {\r\n if (!selectedFile || !bimComponents || !world || !isPlacingFile) return\r\n\r\n const mouse = new THREE.Vector2()\r\n const canvas = world.renderer!.three.domElement!\r\n\r\n const handleMouseMove = (e: MouseEvent) => {\r\n setMousePosition({ x: e.clientX, y: e.clientY })\r\n mouse.x = e.clientX\r\n mouse.y = e.clientY\r\n }\r\n\r\n const handleDblClick = async (e: MouseEvent) => {\r\n mouse.x = e.clientX\r\n mouse.y = e.clientY\r\n\r\n const modelHit = await raycast({ camera: world.camera.three, mouse, dom: canvas })\r\n const point = modelHit?.point\r\n ? modelHit.point.clone()\r\n : pointOnGroundPlane(world.camera.three, canvas, e.clientX, e.clientY)\r\n if (!point) return\r\n\r\n const addedFile: AddedFile = {\r\n id: Date.now().toString(),\r\n file: selectedFile,\r\n position: point,\r\n imageUrl: selectedFile.type.startsWith(\"image/\")\r\n ? URL.createObjectURL(selectedFile)\r\n : undefined,\r\n }\r\n\r\n const placed = await addFileToScene(\r\n addedFile, fileScale, fileRotation,\r\n world, modelManager, addDxf, setCurrent3DFileId,\r\n (action) => onMarkerAction?.(addedFile.id, action),\r\n )\r\n\r\n if (placed) {\r\n placedFilesRef.current.set(addedFile.id, {\r\n id: addedFile.id,\r\n name: selectedFile.name,\r\n kind: placed.kind,\r\n marker: placed.marker,\r\n object3D: placed.object3D,\r\n })\r\n setMarkerCount(c => c + 1)\r\n }\r\n\r\n const fileName = selectedFile.name.toLowerCase()\r\n const is3DFile = fileName.endsWith(\".dxf\") || fileName.endsWith(\".glb\") || fileName.endsWith(\".gltf\")\r\n if (is3DFile) {\r\n // Persist on confirm instead, so the final position/rotation is saved.\r\n setIsPlacingFile(false)\r\n setCursor(\"\")\r\n } else {\r\n void uploadPlacedFile(selectedFile, point)\r\n cancelPlacement()\r\n }\r\n }\r\n\r\n document.addEventListener(\"mousemove\", handleMouseMove)\r\n document.addEventListener(\"dblclick\", handleDblClick)\r\n return () => {\r\n document.removeEventListener(\"mousemove\", handleMouseMove)\r\n document.removeEventListener(\"dblclick\", handleDblClick)\r\n }\r\n }, [selectedFile, bimComponents, world, isPlacingFile, fileScale, fileRotation, modelManager, addDxf, toolsDispatch, raycast, cancelPlacement, setCursor, uploadPlacedFile, onMarkerAction])\r\n\r\n const confirmPlacement = React.useCallback(() => {\r\n if (!current3DFileId) return\r\n\r\n // Capture the final transform from the placed object, then persist it.\r\n let finalPos: THREE.Vector3 | undefined\r\n let finalRot = fileRotation\r\n if (current3DFileType === \"dxf\" && addDxf) {\r\n const info = addDxf.getDxf(current3DFileId)\r\n if (info) {\r\n finalPos = info.group.position.clone()\r\n finalRot = THREE.MathUtils.radToDeg(info.group.rotation.y)\r\n }\r\n addDxf.confirmPlacement(current3DFileId)\r\n } else if (current3DFileType === \"model\" && modelManager) {\r\n const info = modelManager.getModel(current3DFileId)\r\n if (info) {\r\n finalPos = info.model.position.clone()\r\n finalRot = THREE.MathUtils.radToDeg(info.model.rotation.y)\r\n }\r\n modelManager.toggleGizmo(current3DFileId, false)\r\n }\r\n if (selectedFile && finalPos) void uploadPlacedFile(selectedFile, finalPos, finalRot)\r\n\r\n setShow3DScaleCard(false)\r\n setCurrent3DFileId(null)\r\n setCurrent3DFileType(null)\r\n setFileRotation(0)\r\n setFileScale(1)\r\n setSelectedFile(null)\r\n setIsPlacingFile(false)\r\n setCursor(\"\")\r\n toast.dismiss('place-bim-file-toast')\r\n toolsDispatch({ type: \"CLEAR-TOOLS\" })\r\n }, [current3DFileId, current3DFileType, addDxf, modelManager, selectedFile, fileRotation, uploadPlacedFile, setCursor, toolsDispatch])\r\n\r\n // Real-time scale/rotation updates while the placement card is open.\r\n React.useEffect(() => {\r\n if (!current3DFileId || !show3DScaleCard || !current3DFileType) return\r\n if (current3DFileType === \"dxf\" && addDxf) {\r\n addDxf.updateScale(current3DFileId, fileScale)\r\n addDxf.updateRotation(current3DFileId, fileRotation)\r\n } else if (current3DFileType === \"model\" && modelManager) {\r\n modelManager.setScale(current3DFileId, fileScale)\r\n modelManager.setRotation(current3DFileId, new THREE.Euler(0, THREE.MathUtils.degToRad(fileRotation), 0))\r\n }\r\n }, [fileScale, fileRotation, current3DFileId, show3DScaleCard, current3DFileType, addDxf, modelManager])\r\n\r\n // Markers follow their object every frame and hide while that object's gizmo is active.\r\n React.useEffect(() => {\r\n if (!world || markerCount === 0) return\r\n let raf = 0\r\n const worldPos = new THREE.Vector3()\r\n const tick = () => {\r\n placedFilesRef.current.forEach((placed) => {\r\n if (!placed.marker) return\r\n placed.object3D.getWorldPosition(worldPos)\r\n placed.marker.position.set(worldPos.x, worldPos.y + 0.2, worldPos.z)\r\n const editing = placed.kind === \"dxf\"\r\n ? !!addDxf?.getDxf(placed.id)?.gizmoController\r\n : placed.kind === \"model\"\r\n ? !!modelManager?.getModel(placed.id)?.gizmoController\r\n : false\r\n placed.marker.visible = !editing\r\n })\r\n raf = requestAnimationFrame(tick)\r\n }\r\n raf = requestAnimationFrame(tick)\r\n return () => cancelAnimationFrame(raf)\r\n }, [world, addDxf, modelManager, markerCount])\r\n\r\n const getPlacedFile = React.useCallback((id: string): PlacedFile | undefined => {\r\n return placedFilesRef.current.get(id)\r\n }, [])\r\n\r\n const editPlacedFile = React.useCallback((id: string, mode: GizmoMode = \"translate\") => {\r\n const placed = placedFilesRef.current.get(id)\r\n if (!placed) return\r\n if (placed.kind === \"dxf\" && addDxf) {\r\n addDxf.toggleGizmo(id, true)\r\n addDxf.setGizmoMode(id, mode)\r\n } else if (placed.kind === \"model\" && modelManager) {\r\n modelManager.toggleGizmo(id, true)\r\n modelManager.getModel(id)?.gizmoController?.setMode(mode)\r\n }\r\n }, [addDxf, modelManager])\r\n\r\n const removePlacedFile = React.useCallback((id: string) => {\r\n const placed = placedFilesRef.current.get(id)\r\n if (!placed) return\r\n if (placed.kind === \"dxf\") addDxf?.removeDxf(id)\r\n else if (placed.kind === \"model\") modelManager?.remove(id)\r\n else if (world) world.scene.three.remove(placed.object3D)\r\n removeMarker(placed.marker, world)\r\n placedFilesRef.current.delete(id)\r\n setMarkerCount(c => Math.max(0, c - 1))\r\n }, [addDxf, modelManager, world])\r\n\r\n return {\r\n selectedFile,\r\n mousePosition,\r\n isPlacingFile,\r\n fileScale,\r\n fileRotation,\r\n show3DScaleCard,\r\n current3DFileType,\r\n setFileScale,\r\n setFileRotation,\r\n handleFileSelect,\r\n handleFileDrop,\r\n cancelPlacement,\r\n confirmPlacement,\r\n setCursor,\r\n raycast,\r\n getPlacedFile,\r\n editPlacedFile,\r\n removePlacedFile,\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/components/viewers/index.ts"],"names":[],"mappings":"AAYA,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAA;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/components/viewers/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAA;AACxB,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAA;AACnE,OAAO,EAAE,yBAAyB,EAAE,MAAM,yCAAyC,CAAA;AACnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAA;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/components/viewers/index.ts"],"sourcesContent":["// Audit Phase 1.B (F-13): BimViewer, PointCloudViewer and DataMenu used to\r\n// be re-exported here. Even though Viewer.tsx imports all three via\r\n// next/dynamic (F-1 + F-13), these barrel re-exports were separate STATIC\r\n// references — webpack followed them through components/index.ts →\r\n// core/index.ts → every `import … from 'src/core'` in the app, dragging\r\n// @thatopen, three/webgpu and the entire Data subtree into the eager bundle.\r\n//\r\n// Consumers that genuinely need these symbols use direct file paths:\r\n// - Viewer.tsx -> dynamic-imports all three\r\n// - FilePreview.tsx -> direct import of BimViewer / SimpleBimViewer\r\n// - UsersSettingsPanel.tsx -> direct import of DataMenu\r\n// Verified by `grep` (2026-05-24): no consumer needs the barrel re-export.\r\nexport * from './Viewer'\r\nexport * from './map/MapViewer'\r\nexport { fetchArcGISDatasets } from './map/datasets/src/arcGISDatasets'\r\nexport { fetchCkanDatasets } from './map/datasets/src/ckanDatasets'\r\nexport { fetchOpenDataSoftDatasets } from './map/datasets/src/opendatasoftDatasets'\r\nexport { fetchSocrataDatasets } from './map/datasets/src/socrataDatasets'\r\nexport { fetchLocalDatasets } from './map/datasets/src/localDatasets'"],"mappings":"AAYA,cAAc;AACd,cAAc;AACd,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAClC,SAAS,iCAAiC;AAC1C,SAAS,4BAA4B;AACrC,SAAS,0BAA0B;","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/components/viewers/index.ts"],"sourcesContent":["export * from './Viewer'\r\nexport * from './map/MapViewer'\r\nexport { fetchArcGISDatasets } from './map/datasets/src/arcGISDatasets'\r\nexport { fetchCkanDatasets } from './map/datasets/src/ckanDatasets'\r\nexport { fetchOpenDataSoftDatasets } from './map/datasets/src/opendatasoftDatasets'\r\nexport { fetchSocrataDatasets } from './map/datasets/src/socrataDatasets'\r\nexport { fetchLocalDatasets } from './map/datasets/src/localDatasets'"],"mappings":"AAAA,cAAc;AACd,cAAc;AACd,SAAS,2BAA2B;AACpC,SAAS,yBAAyB;AAClC,SAAS,iCAAiC;AAC1C,SAAS,4BAA4B;AACrC,SAAS,0BAA0B;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"MapViewer.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/map/MapViewer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAA;AAazB,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAgBrD,UAAU,KAAK;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,YAAY,CAAA;CAC3B;AAED,wBAAgB,SAAS,CAAC,EAAE,KAAc,EAAE,MAAe,EAAE,YAAY,EAAG,EAAE,KAAK,qBAkJlF"}
1
+ {"version":3,"file":"MapViewer.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/map/MapViewer.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAA;AAazB,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAcrD,UAAU,KAAK;IACb,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,YAAY,CAAA;CAC3B;AAED,wBAAgB,SAAS,CAAC,EAAE,KAAc,EAAE,MAAe,EAAE,YAAY,EAAG,EAAE,KAAK,qBAkJlF"}
@@ -124,6 +124,7 @@ function MapViewer({ width = "100%", height = "100%", organization }) {
124
124
  isMapLoaded && /* @__PURE__ */ jsxs(Fragment, { children: [
125
125
  /* @__PURE__ */ jsx(MapLayers, {}),
126
126
  /* @__PURE__ */ jsxs("div", { className: "absolute bottom-[10px] left-3 z-10 flex flex-col gap-2 pointer-events-none", children: [
127
+ /* @__PURE__ */ jsx("div", { id: "wms-time-slot", style: { display: "contents" } }),
127
128
  /* @__PURE__ */ jsx(MapLegendHost, {}),
128
129
  /* @__PURE__ */ jsx(DatasetManagerMenu, {})
129
130
  ] })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../../src/core/components/viewers/map/MapViewer.tsx"],"sourcesContent":["'use client'\r\n\r\nimport Map, { MapRef, NavigationControl } from 'react-map-gl/maplibre'\r\nimport React from 'react'\r\n\r\nimport maplibregl, { LngLatBoundsLike } from 'maplibre-gl'\r\nimport { useSearchParams } from 'next/navigation'\r\n\r\nimport { MapContext } from '../../../store'\r\nimport { resolveBounds } from './utils/validateBounds'\r\n\r\nimport { MapClickManager } from './utils/MapEventManager/MapClickManager'\r\nimport DatasetManagerMenu from './datasets/DatasetManager'\r\nimport { MapLegendHost } from './legends/MapLegendHost'\r\nimport { StatsOverlay } from '../../ui/stats'\r\nimport { MapHoverManager } from './utils/MapEventManager/MapHoverManager'\r\nimport { Organization } from '../../../types/dbTypes'\r\nimport { CurrentLocation } from '../../../types/map'\r\nimport { MapLayers } from './src/MapLayers'\r\nimport SettingsButton from '../../ui/SettingsButton'\r\n\r\n// Audit Phase 1.D (F-4): hoist out of the component body so the object\r\n// identity is stable across renders. Was being recreated per render.\r\nconst CANADA_DEFAULTS = {\r\n maxBounds: [-141.0, 41.6751050889, -52.6480987209, 83.23324] as LngLatBoundsLike,\r\n zoom: 3,\r\n lat: 56.415,\r\n long: -98.74,\r\n} as const\r\n\r\nconst DEFAULT_MAP_STYLE = { name: 'Satellite', url: 'mapStyles/satellite.json' } as const\r\n\r\ninterface Props {\r\n width?: string\r\n height?: string\r\n organization: Organization\r\n}\r\n\r\nexport function MapViewer({ width = '100%', height = '100%', organization }: Props) {\r\n\r\n const searchParams = useSearchParams()\r\n\r\n // Add state to track if map is loaded\r\n const [isMapLoaded, setIsMapLoaded] = React.useState(false)\r\n\r\n // Audit Phase 1.D (F-4): memoize viewState so the Map sees a stable\r\n // initialViewState prop across re-renders. Was recreated every render.\r\n const viewState = React.useMemo(() => {\r\n return searchParams.size === 0\r\n ? {\r\n zoom: organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n bearing: organization.bearing ?? 0,\r\n pitch: organization.pitch ?? 0,\r\n longitude: organization.long ?? CANADA_DEFAULTS.long,\r\n latitude: organization.lat ?? CANADA_DEFAULTS.lat,\r\n }\r\n : {\r\n latitude: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n longitude: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n }\r\n }, [searchParams, organization])\r\n\r\n // Audit Phase 1.D (F-4): memoize the inline style object that gets passed to <Map>.\r\n const mapContainerStyle = React.useMemo(\r\n () => ({ width, height, backgroundColor: 'black' }),\r\n [width, height],\r\n )\r\n\r\n // Audit Phase 1.D (F-8): adaptive pixel ratio. Was hardcoded `2` which on a\r\n // 1× DPR desktop monitor doubles the fragment-shader cost for zero visual\r\n // gain. On phones with DPR 3-4 the cap of 2 stays effective.\r\n const pixelRatio = React.useMemo(\r\n () => Math.min(typeof window !== 'undefined' ? window.devicePixelRatio : 1, 2),\r\n [],\r\n )\r\n\r\n const mapRef = React.useRef<MapRef>(null)\r\n const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext)\r\n\r\n const handleMapLoad = () => {\r\n const map = mapRef.current.getMap()\r\n\r\n // Only dispatch SET_MAP after map is fully loaded\r\n if (mapRef.current) {\r\n mapDispatch({\r\n type: 'SET_MAP',\r\n payload: { map },\r\n })\r\n }\r\n // initilize a new click manager\r\n const mapClickManager = new MapClickManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_CLICK_MANAGER',\r\n payload: { mapClickManager },\r\n })\r\n\r\n const mapHoverManager = new MapHoverManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_HOVER_MANAGER',\r\n payload: { mapHoverManager },\r\n })\r\n\r\n // update current Location with URL params or fallback to theme location\r\n const updatedLocation: CurrentLocation = {\r\n // Then override with URL params (this ensures URL params take precedence)\r\n lat: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n lng: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n // Add location details from URL params if available\r\n countrySubdivision: searchParams.has('countrySubdivision') ? searchParams.get('countrySubdivision') : (organization.countrySubdivision ?? ''),\r\n municipality: searchParams.has('municipality') ? searchParams.get('municipality') : (organization.municipality ?? ''),\r\n address: searchParams.has('address') ? searchParams.get('address') : '', // organization.address,\r\n site: searchParams.has('site') ? searchParams.get('site') : String(organization.locationSiteId ?? ''),\r\n id: String(organization.id),\r\n }\r\n\r\n mapDispatch({\r\n type: 'UPDATE_LOCATION',\r\n payload: { currentLocation: updatedLocation },\r\n })\r\n\r\n // Set map as loaded after all dispatches are complete\r\n setIsMapLoaded(true)\r\n }\r\n\r\n // Audit Phase 0: enable the perf HUD by appending ?debug=1 to the URL.\r\n // Never reaches production users unless they explicitly opt in.\r\n const isDebug = searchParams.get('debug') === '1'\r\n\r\n // Audit Phase 1.D (F-10): useCallback so the onDblClick prop identity is\r\n // stable across renders of MapViewer (was a new function each render,\r\n // causing react-map-gl to detach/re-attach the listener). Also gated the\r\n // console.log behind a dev-mode check.\r\n const onDblClick = React.useCallback((e) => {\r\n if (process.env.NODE_ENV === 'production') return\r\n const { lng, lat } = e.lngLat\r\n const elevation = mapRef.current?.queryTerrainElevation([lng, lat]) || 0\r\n const coordinates = { lng, lat, elevation, zoom: mapRef.current?.getZoom() }\r\n console.log('📍 Map coordinates:', coordinates)\r\n }, [])\r\n\r\n const mapStyle = mapState?.map.mapStyle ?? DEFAULT_MAP_STYLE;\r\n\r\n return (\r\n <>\r\n <Map\r\n id=\"map-component\"\r\n mapStyle={ mapStyle.url}\r\n mapLib={maplibregl}\r\n onLoad={handleMapLoad}\r\n ref={mapRef}\r\n style={mapContainerStyle}\r\n initialViewState={viewState}\r\n maxPitch={60}\r\n minZoom={organization?.minZoom ?? CANADA_DEFAULTS.zoom}\r\n maxBounds={resolveBounds(organization?.maxBounds, CANADA_DEFAULTS.maxBounds)}\r\n projection=\"globe\"\r\n doubleClickZoom={false}\r\n onDblClick={onDblClick}\r\n pixelRatio={pixelRatio}\r\n >\r\n <NavigationControl visualizePitch />\r\n <SettingsButton /> \r\n {isMapLoaded\r\n && (\r\n <>\r\n <MapLayers />\r\n {/* Bottom-left stack: legend above the layers/styling card, gap auto-managed by flex. */}\r\n <div className=\"absolute bottom-[10px] left-3 z-10 flex flex-col gap-2 pointer-events-none\">\r\n <MapLegendHost />\r\n <DatasetManagerMenu />\r\n </div>\r\n </>\r\n )}\r\n </Map>\r\n <StatsOverlay mapRef={mapRef} enabled={isDebug} />\r\n </>\r\n\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b"]}
1
+ {"version":3,"sources":["../../../../../src/core/components/viewers/map/MapViewer.tsx"],"sourcesContent":["'use client'\r\n\r\nimport Map, { MapRef, NavigationControl } from 'react-map-gl/maplibre'\r\nimport React from 'react'\r\n\r\nimport maplibregl, { LngLatBoundsLike } from 'maplibre-gl'\r\nimport { useSearchParams } from 'next/navigation'\r\n\r\nimport { MapContext } from '../../../store'\r\nimport { resolveBounds } from './utils/validateBounds'\r\n\r\nimport { MapClickManager } from './utils/MapEventManager/MapClickManager'\r\nimport DatasetManagerMenu from './datasets/DatasetManager'\r\nimport { MapLegendHost } from './legends/MapLegendHost'\r\nimport { StatsOverlay } from '../../ui/stats'\r\nimport { MapHoverManager } from './utils/MapEventManager/MapHoverManager'\r\nimport { Organization } from '../../../types/dbTypes'\r\nimport { CurrentLocation } from '../../../types/map'\r\nimport { MapLayers } from './src/MapLayers'\r\nimport SettingsButton from '../../ui/SettingsButton'\r\n\r\nconst CANADA_DEFAULTS = {\r\n maxBounds: [-141.0, 41.6751050889, -52.6480987209, 83.23324] as LngLatBoundsLike,\r\n zoom: 3,\r\n lat: 56.415,\r\n long: -98.74,\r\n} as const\r\n\r\nconst DEFAULT_MAP_STYLE = { name: 'Satellite', url: 'mapStyles/satellite.json' } as const\r\n\r\ninterface Props {\r\n width?: string\r\n height?: string\r\n organization: Organization\r\n}\r\n\r\nexport function MapViewer({ width = '100%', height = '100%', organization }: Props) {\r\n\r\n const searchParams = useSearchParams()\r\n\r\n // Add state to track if map is loaded\r\n const [isMapLoaded, setIsMapLoaded] = React.useState(false)\r\n\r\n const viewState = React.useMemo(() => {\r\n return searchParams.size === 0\r\n ? {\r\n zoom: organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n bearing: organization.bearing ?? 0,\r\n pitch: organization.pitch ?? 0,\r\n longitude: organization.long ?? CANADA_DEFAULTS.long,\r\n latitude: organization.lat ?? CANADA_DEFAULTS.lat,\r\n }\r\n : {\r\n latitude: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n longitude: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n }\r\n }, [searchParams, organization])\r\n\r\n // Memoize the inline style object that gets passed to <Map> for a stable prop identity.\r\n const mapContainerStyle = React.useMemo(\r\n () => ({ width, height, backgroundColor: 'black' }),\r\n [width, height],\r\n )\r\n\r\n // Adaptive pixel ratio. A hardcoded 2 doubled fragment-shader cost on 1× DPR\r\n // desktops for zero visual gain; capping at 2 keeps phones (DPR 3-4) effective.\r\n const pixelRatio = React.useMemo(\r\n () => Math.min(typeof window !== 'undefined' ? window.devicePixelRatio : 1, 2),\r\n [],\r\n )\r\n\r\n const mapRef = React.useRef<MapRef>(null)\r\n const { dispatch: mapDispatch, state: mapState } = React.useContext(MapContext)\r\n\r\n const handleMapLoad = () => {\r\n const map = mapRef.current.getMap()\r\n\r\n // Only dispatch SET_MAP after map is fully loaded\r\n if (mapRef.current) {\r\n mapDispatch({\r\n type: 'SET_MAP',\r\n payload: { map },\r\n })\r\n }\r\n // initilize a new click manager\r\n const mapClickManager = new MapClickManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_CLICK_MANAGER',\r\n payload: { mapClickManager },\r\n })\r\n\r\n const mapHoverManager = new MapHoverManager(map)\r\n mapDispatch({\r\n type: 'ADD_MAP_HOVER_MANAGER',\r\n payload: { mapHoverManager },\r\n })\r\n\r\n // update current Location with URL params or fallback to theme location\r\n const updatedLocation: CurrentLocation = {\r\n // Then override with URL params (this ensures URL params take precedence)\r\n lat: searchParams.has('lat') ? Number.parseFloat(searchParams.get('lat')) : organization.lat ?? CANADA_DEFAULTS.lat,\r\n lng: searchParams.has('lng') ? Number.parseFloat(searchParams.get('lng')) : organization.long ?? CANADA_DEFAULTS.long,\r\n bearing: searchParams.has('bearing') ? Number.parseFloat(searchParams.get('bearing')) : organization.bearing ?? 0,\r\n pitch: searchParams.has('pitch') ? Number.parseFloat(searchParams.get('pitch')) : organization.pitch ?? 0,\r\n zoom: searchParams.has('zoom') ? Number.parseFloat(searchParams.get('zoom')) : organization.zoom ?? CANADA_DEFAULTS.zoom,\r\n // Add location details from URL params if available\r\n countrySubdivision: searchParams.has('countrySubdivision') ? searchParams.get('countrySubdivision') : (organization.countrySubdivision ?? ''),\r\n municipality: searchParams.has('municipality') ? searchParams.get('municipality') : (organization.municipality ?? ''),\r\n address: searchParams.has('address') ? searchParams.get('address') : '', // organization.address,\r\n site: searchParams.has('site') ? searchParams.get('site') : String(organization.locationSiteId ?? ''),\r\n id: String(organization.id),\r\n }\r\n\r\n mapDispatch({\r\n type: 'UPDATE_LOCATION',\r\n payload: { currentLocation: updatedLocation },\r\n })\r\n\r\n // Set map as loaded after all dispatches are complete\r\n setIsMapLoaded(true)\r\n }\r\n\r\n // Enable the perf HUD by appending ?debug=1 to the URL. Never reaches\r\n // production users unless they explicitly opt in.\r\n const isDebug = searchParams.get('debug') === '1'\r\n\r\n // useCallback so the onDblClick prop identity is stable across renders of\r\n // MapViewer; a new function each render caused react-map-gl to detach/re-attach\r\n // the listener. The console.log is gated behind a dev-mode check.\r\n const onDblClick = React.useCallback((e) => {\r\n if (process.env.NODE_ENV === 'production') return\r\n const { lng, lat } = e.lngLat\r\n const elevation = mapRef.current?.queryTerrainElevation([lng, lat]) || 0\r\n const coordinates = { lng, lat, elevation, zoom: mapRef.current?.getZoom() }\r\n console.log('📍 Map coordinates:', coordinates)\r\n }, [])\r\n\r\n const mapStyle = mapState?.map.mapStyle ?? DEFAULT_MAP_STYLE;\r\n\r\n return (\r\n <>\r\n <Map\r\n id=\"map-component\"\r\n mapStyle={ mapStyle.url}\r\n mapLib={maplibregl}\r\n onLoad={handleMapLoad}\r\n ref={mapRef}\r\n style={mapContainerStyle}\r\n initialViewState={viewState}\r\n maxPitch={60}\r\n minZoom={organization?.minZoom ?? CANADA_DEFAULTS.zoom}\r\n maxBounds={resolveBounds(organization?.maxBounds, CANADA_DEFAULTS.maxBounds)}\r\n projection=\"globe\"\r\n doubleClickZoom={false}\r\n onDblClick={onDblClick}\r\n pixelRatio={pixelRatio}\r\n >\r\n <NavigationControl visualizePitch />\r\n <SettingsButton /> \r\n {isMapLoaded\r\n && (\r\n <>\r\n <MapLayers />\r\n {/* Bottom-left stack: legend above the layers/styling card, gap auto-managed by flex. */}\r\n <div className=\"absolute bottom-[10px] left-3 z-10 flex flex-col gap-2 pointer-events-none\">\r\n {/* Portal slot for on-map WMS time controls; display:contents so an\r\n empty slot adds no flex item / gap, but a mounted control stacks\r\n above the legend + dataset-manager cards. */}\r\n <div id=\"wms-time-slot\" style={{ display: 'contents' }} />\r\n <MapLegendHost />\r\n <DatasetManagerMenu />\r\n </div>\r\n </>\r\n )}\r\n </Map>\r\n <StatsOverlay mapRef={mapRef} enabled={isDebug} />\r\n </>\r\n\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b"]}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/datasets/DatasetManager/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA6H9B,MAAM,CAAC,OAAO,UAAU,kBAAkB,sBA+LzC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/core/components/viewers/map/datasets/DatasetManager/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAmI9B,MAAM,CAAC,OAAO,UAAU,kBAAkB,sBA+LzC"}
@@ -71,6 +71,7 @@ const SortableTableRow = ({
71
71
  transition,
72
72
  opacity: isDragging ? 0.5 : 1
73
73
  };
74
+ const isRaster = dataset.datasetType === "WMS" || dataset.type === "WMS";
74
75
  return /* @__PURE__ */ jsxs(Fragment, { children: [
75
76
  /* @__PURE__ */ jsxs(TableRow, { ref: setNodeRef, style, className: "hover:bg-muted/50", children: [
76
77
  /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
@@ -90,7 +91,7 @@ const SortableTableRow = ({
90
91
  checked: dataset.visible !== false,
91
92
  onCheckedChange: () => onToggleDataset(dataset),
92
93
  className: "shrink-0",
93
- style: dataset.visible === false ? {} : { backgroundColor: dataset.layerColor.color }
94
+ style: dataset.visible === false || isRaster ? {} : { backgroundColor: dataset.layerColor.color }
94
95
  }
95
96
  )
96
97
  ] }) }),
@@ -98,7 +99,7 @@ const SortableTableRow = ({
98
99
  dataset.name.replaceAll("_", " "),
99
100
  dataset.total && /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "ml-2 text-xs", children: dataset.total })
100
101
  ] }),
101
- /* @__PURE__ */ jsx(TableCell, { children: /* @__PURE__ */ jsx(
102
+ /* @__PURE__ */ jsx(TableCell, { children: !isRaster && /* @__PURE__ */ jsx(
102
103
  Button,
103
104
  {
104
105
  variant: "ghost",
@@ -114,7 +115,7 @@ const SortableTableRow = ({
114
115
  }
115
116
  ) })
116
117
  ] }),
117
- expandedDatasets.has(dataset.name) && /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: 4, className: "p-0 pb-1", children: /* @__PURE__ */ jsx(
118
+ !isRaster && expandedDatasets.has(dataset.name) && /* @__PURE__ */ jsx(TableRow, { children: /* @__PURE__ */ jsx(TableCell, { colSpan: 4, className: "p-0 pb-1", children: /* @__PURE__ */ jsx(
118
119
  FieldsTable,
119
120
  {
120
121
  dataset