@collabdt/core 0.3.1 → 0.3.3

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 (300) hide show
  1. package/dist/core/components/authentication/ForgotPassword.d.ts.map +1 -1
  2. package/dist/core/components/authentication/ForgotPassword.js +0 -1
  3. package/dist/core/components/authentication/ForgotPassword.js.map +1 -1
  4. package/dist/core/components/ui/Comments/CollapsibleCommentItem.d.ts +12 -2
  5. package/dist/core/components/ui/Comments/CollapsibleCommentItem.d.ts.map +1 -1
  6. package/dist/core/components/ui/Comments/CollapsibleCommentItem.js +137 -139
  7. package/dist/core/components/ui/Comments/CollapsibleCommentItem.js.map +1 -1
  8. package/dist/core/components/ui/Comments/Comment.d.ts +18 -1
  9. package/dist/core/components/ui/Comments/Comment.d.ts.map +1 -1
  10. package/dist/core/components/ui/Comments/Comment.js +94 -23
  11. package/dist/core/components/ui/Comments/Comment.js.map +1 -1
  12. package/dist/core/components/ui/Comments/CommentActionButtons.d.ts +38 -0
  13. package/dist/core/components/ui/Comments/CommentActionButtons.d.ts.map +1 -0
  14. package/dist/core/components/ui/Comments/CommentActionButtons.js +134 -0
  15. package/dist/core/components/ui/Comments/CommentActionButtons.js.map +1 -0
  16. package/dist/core/components/ui/Comments/CommentInput.d.ts.map +1 -1
  17. package/dist/core/components/ui/Comments/CommentInput.js +5 -2
  18. package/dist/core/components/ui/Comments/CommentInput.js.map +1 -1
  19. package/dist/core/components/ui/Comments/CommentsSection.d.ts.map +1 -1
  20. package/dist/core/components/ui/Comments/CommentsSection.js +86 -42
  21. package/dist/core/components/ui/Comments/CommentsSection.js.map +1 -1
  22. package/dist/core/components/ui/Comments/commentUtils.d.ts.map +1 -1
  23. package/dist/core/components/ui/Comments/commentUtils.js +2 -1
  24. package/dist/core/components/ui/Comments/commentUtils.js.map +1 -1
  25. package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.d.ts.map +1 -1
  26. package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.js +0 -1
  27. package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.js.map +1 -1
  28. package/dist/core/components/ui/InfoSidebar/Container.d.ts.map +1 -1
  29. package/dist/core/components/ui/InfoSidebar/Container.js +16 -12
  30. package/dist/core/components/ui/InfoSidebar/Container.js.map +1 -1
  31. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts +1 -2
  32. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
  33. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js +66 -94
  34. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
  35. package/dist/core/components/ui/Sensors/Sensor.d.ts +16 -3
  36. package/dist/core/components/ui/Sensors/Sensor.d.ts.map +1 -1
  37. package/dist/core/components/ui/Sensors/Sensor.js +76 -37
  38. package/dist/core/components/ui/Sensors/Sensor.js.map +1 -1
  39. package/dist/core/components/ui/Sensors/SensorChart.d.ts +12 -2
  40. package/dist/core/components/ui/Sensors/SensorChart.d.ts.map +1 -1
  41. package/dist/core/components/ui/Sensors/SensorChart.js +49 -12
  42. package/dist/core/components/ui/Sensors/SensorChart.js.map +1 -1
  43. package/dist/core/components/ui/Sensors/SensorDetailDialog.d.ts +9 -0
  44. package/dist/core/components/ui/Sensors/SensorDetailDialog.d.ts.map +1 -0
  45. package/dist/core/components/ui/Sensors/SensorDetailDialog.js +128 -0
  46. package/dist/core/components/ui/Sensors/SensorDetailDialog.js.map +1 -0
  47. package/dist/core/components/ui/Sensors/SensorInput.d.ts +6 -1
  48. package/dist/core/components/ui/Sensors/SensorInput.d.ts.map +1 -1
  49. package/dist/core/components/ui/Sensors/SensorInput.js +94 -9
  50. package/dist/core/components/ui/Sensors/SensorInput.js.map +1 -1
  51. package/dist/core/components/ui/Sensors/SensorTagsSection.d.ts +3 -1
  52. package/dist/core/components/ui/Sensors/SensorTagsSection.d.ts.map +1 -1
  53. package/dist/core/components/ui/Sensors/SensorTagsSection.js +4 -1
  54. package/dist/core/components/ui/Sensors/SensorTagsSection.js.map +1 -1
  55. package/dist/core/components/ui/Sensors/SensorsSection.d.ts +1 -3
  56. package/dist/core/components/ui/Sensors/SensorsSection.d.ts.map +1 -1
  57. package/dist/core/components/ui/Sensors/SensorsSection.js +33 -10
  58. package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
  59. package/dist/core/components/ui/Sensors/TimeZoneSelect.d.ts +7 -0
  60. package/dist/core/components/ui/Sensors/TimeZoneSelect.d.ts.map +1 -0
  61. package/dist/core/components/ui/Sensors/TimeZoneSelect.js +56 -0
  62. package/dist/core/components/ui/Sensors/TimeZoneSelect.js.map +1 -0
  63. package/dist/core/components/ui/Sensors/sensorData.d.ts +42 -0
  64. package/dist/core/components/ui/Sensors/sensorData.d.ts.map +1 -0
  65. package/dist/core/components/ui/Sensors/sensorData.js +118 -0
  66. package/dist/core/components/ui/Sensors/sensorData.js.map +1 -0
  67. package/dist/core/components/ui/Sensors/sensorRange.d.ts +24 -0
  68. package/dist/core/components/ui/Sensors/sensorRange.d.ts.map +1 -0
  69. package/dist/core/components/ui/Sensors/sensorRange.js +34 -0
  70. package/dist/core/components/ui/Sensors/sensorRange.js.map +1 -0
  71. package/dist/core/components/ui/Sensors/useSensorSeries.d.ts +15 -0
  72. package/dist/core/components/ui/Sensors/useSensorSeries.d.ts.map +1 -0
  73. package/dist/core/components/ui/Sensors/useSensorSeries.js +63 -0
  74. package/dist/core/components/ui/Sensors/useSensorSeries.js.map +1 -0
  75. package/dist/core/components/ui/Sidebar.d.ts.map +1 -1
  76. package/dist/core/components/ui/Sidebar.js +27 -4
  77. package/dist/core/components/ui/Sidebar.js.map +1 -1
  78. package/dist/core/components/ui/ToolbarButton.d.ts.map +1 -1
  79. package/dist/core/components/ui/ToolbarButton.js +0 -1
  80. package/dist/core/components/ui/ToolbarButton.js.map +1 -1
  81. package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.d.ts.map +1 -1
  82. package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.js +0 -2
  83. package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.js.map +1 -1
  84. package/dist/core/components/viewers/Data/details/EnergySourcesGrid.d.ts.map +1 -1
  85. package/dist/core/components/viewers/Data/details/EnergySourcesGrid.js +0 -10
  86. package/dist/core/components/viewers/Data/details/EnergySourcesGrid.js.map +1 -1
  87. package/dist/core/components/viewers/Data/files/DatatableFileAdder.d.ts.map +1 -1
  88. package/dist/core/components/viewers/Data/files/DatatableFileAdder.js +0 -1
  89. package/dist/core/components/viewers/Data/files/DatatableFileAdder.js.map +1 -1
  90. package/dist/core/components/viewers/Data/files/utils/fuzzySearch.d.ts.map +1 -1
  91. package/dist/core/components/viewers/Data/files/utils/fuzzySearch.js +0 -1
  92. package/dist/core/components/viewers/Data/files/utils/fuzzySearch.js.map +1 -1
  93. package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.d.ts.map +1 -1
  94. package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.js +0 -1
  95. package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.js.map +1 -1
  96. package/dist/core/components/viewers/Data/utils/filterHelper.d.ts.map +1 -1
  97. package/dist/core/components/viewers/Data/utils/filterHelper.js +0 -2
  98. package/dist/core/components/viewers/Data/utils/filterHelper.js.map +1 -1
  99. package/dist/core/components/viewers/Viewer.js +1 -1
  100. package/dist/core/components/viewers/Viewer.js.map +1 -1
  101. package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.d.ts.map +1 -1
  102. package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.js +0 -3
  103. package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.js.map +1 -1
  104. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
  105. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js +1 -7
  106. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js.map +1 -1
  107. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
  108. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js +1 -9
  109. package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
  110. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts +1 -3
  111. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts.map +1 -1
  112. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js +2 -2
  113. package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js.map +1 -1
  114. package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.d.ts.map +1 -1
  115. package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.js +4 -3
  116. package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.js.map +1 -1
  117. package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js +1 -1
  118. package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js.map +1 -1
  119. package/dist/core/components/viewers/bim/src/ClippingPlane.d.ts.map +1 -1
  120. package/dist/core/components/viewers/bim/src/ClippingPlane.js +0 -1
  121. package/dist/core/components/viewers/bim/src/ClippingPlane.js.map +1 -1
  122. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts +1 -2
  123. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts.map +1 -1
  124. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js +25 -2
  125. package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js.map +1 -1
  126. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.d.ts +16 -10
  127. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.d.ts.map +1 -1
  128. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.js +26 -6
  129. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.js.map +1 -1
  130. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts +2 -0
  131. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts.map +1 -0
  132. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js +5 -0
  133. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js.map +1 -0
  134. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.d.ts +8 -1
  135. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.d.ts.map +1 -1
  136. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js +15 -3
  137. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js.map +1 -1
  138. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.d.ts +44 -0
  139. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.d.ts.map +1 -0
  140. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.js +77 -0
  141. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.js.map +1 -0
  142. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts +3 -0
  143. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts.map +1 -0
  144. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js +5 -0
  145. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js.map +1 -0
  146. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.d.ts +33 -0
  147. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.d.ts.map +1 -0
  148. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.js +90 -0
  149. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.js.map +1 -0
  150. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.d.ts.map +1 -1
  151. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.js +2 -2
  152. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.js.map +1 -1
  153. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.d.ts +7 -1
  154. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.d.ts.map +1 -1
  155. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js +50 -73
  156. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js.map +1 -1
  157. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts +7 -1
  158. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts.map +1 -1
  159. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js +39 -11
  160. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js.map +1 -1
  161. package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.d.ts.map +1 -1
  162. package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.js +1 -5
  163. package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.js.map +1 -1
  164. package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.d.ts.map +1 -1
  165. package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.js +0 -1
  166. package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.js.map +1 -1
  167. package/dist/core/components/viewers/bim/src/tools/measureBimTool.d.ts.map +1 -1
  168. package/dist/core/components/viewers/bim/src/tools/measureBimTool.js +1 -2
  169. package/dist/core/components/viewers/bim/src/tools/measureBimTool.js.map +1 -1
  170. package/dist/core/components/viewers/map/MapViewer.d.ts +1 -2
  171. package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
  172. package/dist/core/components/viewers/map/MapViewer.js +2 -2
  173. package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
  174. package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.d.ts.map +1 -1
  175. package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.js +11 -14
  176. package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.js.map +1 -1
  177. package/dist/core/components/viewers/map/datasets/src/ckanDatasets.d.ts.map +1 -1
  178. package/dist/core/components/viewers/map/datasets/src/ckanDatasets.js +2 -5
  179. package/dist/core/components/viewers/map/datasets/src/ckanDatasets.js.map +1 -1
  180. package/dist/core/components/viewers/map/datasets/src/localDatasets.d.ts.map +1 -1
  181. package/dist/core/components/viewers/map/datasets/src/localDatasets.js +0 -3
  182. package/dist/core/components/viewers/map/datasets/src/localDatasets.js.map +1 -1
  183. package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.d.ts.map +1 -1
  184. package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.js +0 -11
  185. package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.js.map +1 -1
  186. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.d.ts.map +1 -1
  187. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.js +0 -1
  188. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.js.map +1 -1
  189. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.d.ts.map +1 -1
  190. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js +0 -1
  191. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js.map +1 -1
  192. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.d.ts.map +1 -1
  193. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.js +0 -1
  194. package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.js.map +1 -1
  195. package/dist/core/components/viewers/map/src/MapLayers/index.d.ts +1 -2
  196. package/dist/core/components/viewers/map/src/MapLayers/index.d.ts.map +1 -1
  197. package/dist/core/components/viewers/map/src/MapLayers/index.js +2 -2
  198. package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
  199. package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.d.ts.map +1 -1
  200. package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.js +174 -53
  201. package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.js.map +1 -1
  202. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.d.ts.map +1 -1
  203. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.js +2 -1
  204. package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.js.map +1 -1
  205. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts +1 -3
  206. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts.map +1 -1
  207. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js +74 -42
  208. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js.map +1 -1
  209. package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.d.ts.map +1 -1
  210. package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.js +4 -3
  211. package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.js.map +1 -1
  212. package/dist/core/components/viewers/map/src/MapSidebar/index.js +1 -1
  213. package/dist/core/components/viewers/map/src/MapSidebar/index.js.map +1 -1
  214. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
  215. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js +0 -1
  216. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js.map +1 -1
  217. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
  218. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js +1 -5
  219. package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
  220. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts +1 -3
  221. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts.map +1 -1
  222. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js +2 -2
  223. package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js.map +1 -1
  224. package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.d.ts.map +1 -1
  225. package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.js +1 -3
  226. package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.js.map +1 -1
  227. package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.d.ts.map +1 -1
  228. package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js +0 -1
  229. package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js.map +1 -1
  230. package/dist/core/components/viewers/map/utils/flyToEach.d.ts.map +1 -1
  231. package/dist/core/components/viewers/map/utils/flyToEach.js +0 -1
  232. package/dist/core/components/viewers/map/utils/flyToEach.js.map +1 -1
  233. package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.d.ts.map +1 -1
  234. package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.js +0 -2
  235. package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.js.map +1 -1
  236. package/dist/core/components/viewers/shared/markers/BimMarkerCluster.d.ts +19 -0
  237. package/dist/core/components/viewers/shared/markers/BimMarkerCluster.d.ts.map +1 -0
  238. package/dist/core/components/viewers/shared/markers/BimMarkerCluster.js +108 -0
  239. package/dist/core/components/viewers/shared/markers/BimMarkerCluster.js.map +1 -0
  240. package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.d.ts +24 -0
  241. package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.d.ts.map +1 -0
  242. package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.js +27 -0
  243. package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.js.map +1 -0
  244. package/dist/core/components/viewers/shared/markers/types.d.ts +66 -0
  245. package/dist/core/components/viewers/shared/markers/types.d.ts.map +1 -0
  246. package/dist/core/components/viewers/shared/markers/types.js +1 -0
  247. package/dist/core/components/viewers/shared/markers/types.js.map +1 -0
  248. package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.d.ts +22 -0
  249. package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.d.ts.map +1 -0
  250. package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.js +233 -0
  251. package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.js.map +1 -0
  252. package/dist/core/hooks/comments/comments.d.ts +11 -0
  253. package/dist/core/hooks/comments/comments.d.ts.map +1 -1
  254. package/dist/core/hooks/comments/comments.js +3 -1
  255. package/dist/core/hooks/comments/comments.js.map +1 -1
  256. package/dist/core/hooks/comments/createCommentHooks.d.ts +11 -0
  257. package/dist/core/hooks/comments/createCommentHooks.d.ts.map +1 -1
  258. package/dist/core/hooks/comments/createCommentHooks.js +30 -1
  259. package/dist/core/hooks/comments/createCommentHooks.js.map +1 -1
  260. package/dist/core/hooks/files/files.d.ts.map +1 -1
  261. package/dist/core/hooks/files/files.js +0 -1
  262. package/dist/core/hooks/files/files.js.map +1 -1
  263. package/dist/core/hooks/ui/useResizableSidebarWidth.d.ts +30 -0
  264. package/dist/core/hooks/ui/useResizableSidebarWidth.d.ts.map +1 -0
  265. package/dist/core/hooks/ui/useResizableSidebarWidth.js +75 -0
  266. package/dist/core/hooks/ui/useResizableSidebarWidth.js.map +1 -0
  267. package/dist/core/i18n/messages/en.json +10 -1
  268. package/dist/core/i18n/messages/es.json +11 -2
  269. package/dist/core/i18n/messages/fr.json +11 -2
  270. package/dist/core/store/AppConfig/context.d.ts.map +1 -1
  271. package/dist/core/store/AppConfig/context.js +4 -1
  272. package/dist/core/store/AppConfig/context.js.map +1 -1
  273. package/dist/core/store/AppConfig/reducer.d.ts +10 -0
  274. package/dist/core/store/AppConfig/reducer.d.ts.map +1 -1
  275. package/dist/core/store/AppConfig/reducer.js +10 -0
  276. package/dist/core/store/AppConfig/reducer.js.map +1 -1
  277. package/dist/core/store/Datasets/reducer.d.ts.map +1 -1
  278. package/dist/core/store/Datasets/reducer.js +0 -2
  279. package/dist/core/store/Datasets/reducer.js.map +1 -1
  280. package/dist/core/store/Files/reducer.js +0 -1
  281. package/dist/core/store/Files/reducer.js.map +1 -1
  282. package/dist/core/store/Menus/context.d.ts.map +1 -1
  283. package/dist/core/store/Menus/context.js +8 -2
  284. package/dist/core/store/Menus/context.js.map +1 -1
  285. package/dist/core/store/Menus/reducer.d.ts +65 -1
  286. package/dist/core/store/Menus/reducer.d.ts.map +1 -1
  287. package/dist/core/store/Menus/reducer.js +39 -3
  288. package/dist/core/store/Menus/reducer.js.map +1 -1
  289. package/dist/core/utils/markerUtils.d.ts +10 -0
  290. package/dist/core/utils/markerUtils.d.ts.map +1 -1
  291. package/dist/core/utils/markerUtils.js +9 -1
  292. package/dist/core/utils/markerUtils.js.map +1 -1
  293. package/dist/core/utils/memcache.d.ts.map +1 -1
  294. package/dist/core/utils/memcache.js +0 -7
  295. package/dist/core/utils/memcache.js.map +1 -1
  296. package/dist/core/utils/timeUtils.d.ts +24 -1
  297. package/dist/core/utils/timeUtils.d.ts.map +1 -1
  298. package/dist/core/utils/timeUtils.js +52 -3
  299. package/dist/core/utils/timeUtils.js.map +1 -1
  300. package/package.json +4 -1
@@ -1,17 +1,41 @@
1
1
  import type { ViewerNames } from '../../types/dbTypes';
2
2
  import type { ActionMap } from '../ActionMap';
3
3
  export type SidebarTabType = 'file' | 'layers' | 'communication' | 'sensors' | 'settings';
4
+ /** Request from a viewer marker to open a comment's editor/reply box in the sidebar. */
5
+ export type CommentActionRequest = {
6
+ commentId: number;
7
+ action: 'edit' | 'reply';
8
+ /** Monotonic id so the same request fires again even if the target is unchanged. */
9
+ requestId: number;
10
+ };
11
+ /** Request from a viewer marker to open a sensor's editor in the sidebar. */
12
+ export type SensorActionRequest = {
13
+ sensorId: number;
14
+ action: 'edit';
15
+ /** Monotonic id so the same request fires again even if the target is unchanged. */
16
+ requestId: number;
17
+ };
4
18
  interface MenusTypes {
5
19
  currentViewer: ViewerNames;
6
20
  rowsPerPage: number;
7
21
  selectedTab: SidebarTabType;
8
22
  commentsVisibleInViewer: ViewerNames[];
9
23
  currentCommentId: number | null;
24
+ /** Comment double-clicked to zoom/focus. Drives the thick focus ring + camera move. */
25
+ focusedCommentId: number | null;
26
+ /** Monotonic counter bumped on every focus dispatch so re-focusing the same comment re-zooms. */
27
+ focusRequestId: number;
28
+ pendingCommentAction: CommentActionRequest | null;
10
29
  sensorsVisibleInViewer: ViewerNames[];
11
30
  visibleSensorTypes: Partial<Record<ViewerNames, number[]>>;
12
31
  visibleSensorTags: Partial<Record<ViewerNames, string[]>>;
13
32
  currentSensorId: number | null;
14
33
  currentSensorTypeId: number | null;
34
+ /** Sensor double-clicked to zoom/focus. Drives the thick focus ring + camera move. */
35
+ focusedSensorId: number | null;
36
+ /** Monotonic counter bumped on every sensor focus dispatch so re-focusing re-zooms. */
37
+ sensorFocusRequestId: number;
38
+ pendingSensorAction: SensorActionRequest | null;
15
39
  }
16
40
  export type MenusState = MenusTypes;
17
41
  export type MenusPayload = {
@@ -27,6 +51,14 @@ export type MenusPayload = {
27
51
  ['SET_CURRENT_COMMENT_ID']: {
28
52
  commentId: number | null;
29
53
  };
54
+ ['SET_FOCUSED_COMMENT_ID']: {
55
+ commentId: number | null;
56
+ };
57
+ ['REQUEST_COMMENT_ACTION']: {
58
+ commentId: number;
59
+ action: 'edit' | 'reply';
60
+ };
61
+ ['CLEAR_PENDING_COMMENT_ACTION']: undefined;
30
62
  ['TOGGLE_SENSOR_TYPE_VISIBILITY']: {
31
63
  viewer: ViewerNames;
32
64
  sensorTypeId: number;
@@ -48,8 +80,40 @@ export type MenusPayload = {
48
80
  };
49
81
  ['SET_CURRENT_SENSOR_ID']: Pick<MenusTypes, 'currentSensorId'>;
50
82
  ['SET_CURRENT_SENSOR_TYPE_ID']: Pick<MenusTypes, 'currentSensorTypeId'>;
83
+ ['SET_FOCUSED_SENSOR_ID']: {
84
+ sensorId: number | null;
85
+ };
86
+ ['REQUEST_SENSOR_ACTION']: {
87
+ sensorId: number;
88
+ };
89
+ ['CLEAR_PENDING_SENSOR_ACTION']: undefined;
51
90
  };
52
91
  export type MenusActions = ActionMap<MenusPayload>[keyof ActionMap<MenusPayload>];
53
- export declare const MenusReducer: (state: MenusState, action: MenusActions) => MenusTypes;
92
+ export declare const MenusReducer: (state: MenusState, action: MenusActions) => {
93
+ pendingSensorAction: {
94
+ sensorId: number;
95
+ action: string;
96
+ requestId: number;
97
+ };
98
+ currentViewer: ViewerNames;
99
+ rowsPerPage: number;
100
+ selectedTab: SidebarTabType;
101
+ commentsVisibleInViewer: ViewerNames[];
102
+ currentCommentId: number | null;
103
+ /** Comment double-clicked to zoom/focus. Drives the thick focus ring + camera move. */
104
+ focusedCommentId: number | null;
105
+ /** Monotonic counter bumped on every focus dispatch so re-focusing the same comment re-zooms. */
106
+ focusRequestId: number;
107
+ pendingCommentAction: CommentActionRequest | null;
108
+ sensorsVisibleInViewer: ViewerNames[];
109
+ visibleSensorTypes: Partial<Record<ViewerNames, number[]>>;
110
+ visibleSensorTags: Partial<Record<ViewerNames, string[]>>;
111
+ currentSensorId: number | null;
112
+ currentSensorTypeId: number | null;
113
+ /** Sensor double-clicked to zoom/focus. Drives the thick focus ring + camera move. */
114
+ focusedSensorId: number | null;
115
+ /** Monotonic counter bumped on every sensor focus dispatch so re-focusing re-zooms. */
116
+ sensorFocusRequestId: number;
117
+ };
54
118
  export {};
55
119
  //# sourceMappingURL=reducer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../../../src/core/store/Menus/reducer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAc,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,eAAe,GAAI,SAAS,GAAG,UAAU,CAAA;AAE1F,UAAU,UAAU;IAClB,aAAa,EAAE,WAAW,CAAA;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,cAAc,CAAA;IAC3B,uBAAuB,EAAE,WAAW,EAAE,CAAA;IACtC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,sBAAsB,EAAE,WAAW,EAAE,CAAA;IACrC,kBAAkB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAC1D,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IACzD,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;CACnC;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAA;AAEnC,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAA;IACjD,CAAC,8BAA8B,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAA;IACjE,CAAC,0BAA0B,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAA;IAC7D,CAAC,yBAAyB,CAAC,EAAE;QAAC,MAAM,EAAE,WAAW,CAAA;KAAC,CAAA;IAClD,CAAC,yBAAyB,CAAC,EAAE;QAAC,MAAM,EAAE,WAAW,CAAA;KAAC,CAAA;IAClD,CAAC,wBAAwB,CAAC,EAAE;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,CAAA;IACtD,CAAC,+BAA+B,CAAC,EAAE;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;IACjG,CAAC,8BAA8B,CAAC,EAAE;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;IAC7F,CAAC,2BAA2B,CAAC,EAAE;QAAC,MAAM,EAAE,WAAW,CAAA;KAAC,CAAA;IACpD,CAAC,4BAA4B,CAAC,EAAE;QAAC,MAAM,EAAE,WAAW,CAAA;KAAC,CAAA;IACrD,CAAC,gCAAgC,CAAC,EAAE;QAAC,MAAM,EAAE,WAAW,CAAA;KAAC,CAAA;IACzD,CAAC,uBAAuB,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAA;IAC9D,CAAC,4BAA4B,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAA;CACxE,CAAA;AAED,MAAM,MAAM,YAAY,GACpB,SAAS,CAAC,YAAY,CAAC,CAAC,MAAM,SAAS,CAAC,YAAY,CAAC,CAAC,CAAA;AAE1D,eAAO,MAAM,YAAY,GAAI,OAAO,UAAU,EAAE,QAAQ,YAAY,eAoHnE,CAAA"}
1
+ {"version":3,"file":"reducer.d.ts","sourceRoot":"","sources":["../../../../src/core/store/Menus/reducer.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAE7C,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,QAAQ,GAAG,eAAe,GAAI,SAAS,GAAG,UAAU,CAAA;AAE1F,wFAAwF;AACxF,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;IACxB,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,6EAA6E;AAC7E,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,oFAAoF;IACpF,SAAS,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,UAAU,UAAU;IAClB,aAAa,EAAE,WAAW,CAAA;IAC1B,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,cAAc,CAAA;IAC3B,uBAAuB,EAAE,WAAW,EAAE,CAAA;IACtC,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,uFAAuF;IACvF,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;IAC/B,iGAAiG;IACjG,cAAc,EAAE,MAAM,CAAA;IACtB,oBAAoB,EAAE,oBAAoB,GAAG,IAAI,CAAA;IACjD,sBAAsB,EAAE,WAAW,EAAE,CAAA;IACrC,kBAAkB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAC1D,iBAAiB,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IACzD,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,sFAAsF;IACtF,eAAe,EAAE,MAAM,GAAG,IAAI,CAAA;IAC9B,uFAAuF;IACvF,oBAAoB,EAAE,MAAM,CAAA;IAC5B,mBAAmB,EAAE,mBAAmB,GAAG,IAAI,CAAA;CAChD;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAA;AAEnC,MAAM,MAAM,YAAY,GAAG;IACzB,CAAC,YAAY,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,eAAe,CAAC,CAAA;IACjD,CAAC,8BAA8B,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAA;IACjE,CAAC,0BAA0B,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAA;IAC7D,CAAC,yBAAyB,CAAC,EAAE;QAAC,MAAM,EAAE,WAAW,CAAA;KAAC,CAAA;IAClD,CAAC,yBAAyB,CAAC,EAAE;QAAC,MAAM,EAAE,WAAW,CAAA;KAAC,CAAA;IAClD,CAAC,wBAAwB,CAAC,EAAE;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,CAAA;IACtD,CAAC,wBAAwB,CAAC,EAAE;QAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,CAAA;IACtD,CAAC,wBAAwB,CAAC,EAAE;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAA;KAAC,CAAA;IACzE,CAAC,8BAA8B,CAAC,EAAE,SAAS,CAAA;IAC3C,CAAC,+BAA+B,CAAC,EAAE;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;IACjG,CAAC,8BAA8B,CAAC,EAAE;QAAE,MAAM,EAAE,WAAW,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;IAC7F,CAAC,2BAA2B,CAAC,EAAE;QAAC,MAAM,EAAE,WAAW,CAAA;KAAC,CAAA;IACpD,CAAC,4BAA4B,CAAC,EAAE;QAAC,MAAM,EAAE,WAAW,CAAA;KAAC,CAAA;IACrD,CAAC,gCAAgC,CAAC,EAAE;QAAC,MAAM,EAAE,WAAW,CAAA;KAAC,CAAA;IACzD,CAAC,uBAAuB,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,iBAAiB,CAAC,CAAA;IAC9D,CAAC,4BAA4B,CAAC,EAAE,IAAI,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAA;IACvE,CAAC,uBAAuB,CAAC,EAAE;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAC,CAAA;IACpD,CAAC,uBAAuB,CAAC,EAAE;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAC,CAAA;IAC7C,CAAC,6BAA6B,CAAC,EAAE,SAAS,CAAA;CAC3C,CAAA;AAED,MAAM,MAAM,YAAY,GACpB,SAAS,CAAC,YAAY,CAAC,CAAC,MAAM,SAAS,CAAC,YAAY,CAAC,CAAC,CAAA;AAE1D,eAAO,MAAM,YAAY,GAAI,OAAO,UAAU,EAAE,QAAQ,YAAY;;;;;;mBAjDnD,WAAW;iBACb,MAAM;iBACN,cAAc;6BACF,WAAW,EAAE;sBACpB,MAAM,GAAG,IAAI;IAC/B,uFAAuF;sBACrE,MAAM,GAAG,IAAI;IAC/B,iGAAiG;oBACjF,MAAM;0BACA,oBAAoB,GAAG,IAAI;4BACzB,WAAW,EAAE;wBACjB,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;uBACvC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,CAAC,CAAC;qBACxC,MAAM,GAAG,IAAI;yBACT,MAAM,GAAG,IAAI;IAClC,sFAAsF;qBACrE,MAAM,GAAG,IAAI;IAC9B,uFAAuF;0BACjE,MAAM;CA6L7B,CAAA"}
@@ -18,7 +18,7 @@ var __spreadValues = (a, b) => {
18
18
  };
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
20
  const MenusReducer = (state, action) => {
21
- var _a, _b;
21
+ var _a, _b, _c, _d, _e, _f;
22
22
  switch (action.type) {
23
23
  case "SET_VIEWER":
24
24
  return __spreadProps(__spreadValues({}, state), {
@@ -51,6 +51,24 @@ const MenusReducer = (state, action) => {
51
51
  return __spreadProps(__spreadValues({}, state), {
52
52
  currentCommentId: action.payload.commentId
53
53
  });
54
+ case "SET_FOCUSED_COMMENT_ID":
55
+ return __spreadProps(__spreadValues({}, state), {
56
+ focusedCommentId: action.payload.commentId,
57
+ focusRequestId: state.focusRequestId + 1
58
+ });
59
+ case "REQUEST_COMMENT_ACTION":
60
+ return __spreadProps(__spreadValues({}, state), {
61
+ pendingCommentAction: {
62
+ commentId: action.payload.commentId,
63
+ action: action.payload.action,
64
+ requestId: ((_b = (_a = state.pendingCommentAction) == null ? void 0 : _a.requestId) != null ? _b : 0) + 1
65
+ }
66
+ });
67
+ case "CLEAR_PENDING_COMMENT_ACTION":
68
+ if (state.pendingCommentAction === null) return state;
69
+ return __spreadProps(__spreadValues({}, state), {
70
+ pendingCommentAction: null
71
+ });
54
72
  case "SET_CURRENT_SENSOR_ID":
55
73
  return __spreadProps(__spreadValues({}, state), {
56
74
  currentSensorId: action.payload.currentSensorId
@@ -59,6 +77,24 @@ const MenusReducer = (state, action) => {
59
77
  return __spreadProps(__spreadValues({}, state), {
60
78
  currentSensorTypeId: action.payload.currentSensorTypeId
61
79
  });
80
+ case "SET_FOCUSED_SENSOR_ID":
81
+ return __spreadProps(__spreadValues({}, state), {
82
+ focusedSensorId: action.payload.sensorId,
83
+ sensorFocusRequestId: state.sensorFocusRequestId + 1
84
+ });
85
+ case "REQUEST_SENSOR_ACTION":
86
+ return __spreadProps(__spreadValues({}, state), {
87
+ pendingSensorAction: {
88
+ sensorId: action.payload.sensorId,
89
+ action: "edit",
90
+ requestId: ((_d = (_c = state.pendingSensorAction) == null ? void 0 : _c.requestId) != null ? _d : 0) + 1
91
+ }
92
+ });
93
+ case "CLEAR_PENDING_SENSOR_ACTION":
94
+ if (state.pendingSensorAction === null) return state;
95
+ return __spreadProps(__spreadValues({}, state), {
96
+ pendingSensorAction: null
97
+ });
62
98
  case "HIDE_ALL_SENSORS_IN_VIEWER":
63
99
  const sensorViewerToHide = action.payload.viewer;
64
100
  if (!sensorViewerToHide) return state;
@@ -82,7 +118,7 @@ const MenusReducer = (state, action) => {
82
118
  case "TOGGLE_SENSOR_TYPE_VISIBILITY":
83
119
  const { viewer: toggleViewer, sensorTypeId, force } = action.payload;
84
120
  if (!toggleViewer || !sensorTypeId) return state;
85
- const currentTypesForViewer = ((_a = state.visibleSensorTypes) == null ? void 0 : _a[toggleViewer]) || [];
121
+ const currentTypesForViewer = ((_e = state.visibleSensorTypes) == null ? void 0 : _e[toggleViewer]) || [];
86
122
  const isCurrentlyVisible = currentTypesForViewer.includes(sensorTypeId);
87
123
  if (force && isCurrentlyVisible) return state;
88
124
  return __spreadProps(__spreadValues({}, state), {
@@ -93,7 +129,7 @@ const MenusReducer = (state, action) => {
93
129
  case "TOGGLE_SENSOR_TAG_VISIBILITY":
94
130
  const { viewer: toggleTagViewer, sensorTag, force: forceTag } = action.payload;
95
131
  if (!toggleTagViewer || !sensorTag) return state;
96
- const currentTagsForViewer = ((_b = state.visibleSensorTags) == null ? void 0 : _b[toggleTagViewer]) || [];
132
+ const currentTagsForViewer = ((_f = state.visibleSensorTags) == null ? void 0 : _f[toggleTagViewer]) || [];
97
133
  const isTagCurrentlyVisible = currentTagsForViewer.includes(sensorTag);
98
134
  if (forceTag && isTagCurrentlyVisible) return state;
99
135
  return __spreadProps(__spreadValues({}, state), {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/store/Menus/reducer.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport type { SensorType, ViewerNames } from '../../types/dbTypes'\r\nimport type { ActionMap } from '../ActionMap'\r\n\r\nexport type SidebarTabType = 'file' | 'layers' | 'communication' | 'sensors' | 'settings'\r\n\r\ninterface MenusTypes {\r\n currentViewer: ViewerNames\r\n rowsPerPage: number\r\n selectedTab: SidebarTabType\r\n commentsVisibleInViewer: ViewerNames[]\r\n currentCommentId: number | null\r\n sensorsVisibleInViewer: ViewerNames[]\r\n visibleSensorTypes: Partial<Record<ViewerNames, number[]>>\r\n visibleSensorTags: Partial<Record<ViewerNames, string[]>>\r\n currentSensorId: number | null\r\n currentSensorTypeId: number | null\r\n}\r\n\r\nexport type MenusState = MenusTypes\r\n\r\nexport type MenusPayload = {\r\n ['SET_VIEWER']: Pick<MenusTypes, 'currentViewer'>\r\n ['SET_PAGINATION_ROWS_PER_PAGE']: Pick<MenusTypes, 'rowsPerPage'>\r\n ['SET_SIDEBAR_SELECTED_TAB']: Pick<MenusTypes, 'selectedTab'>\r\n ['SHOW_COMMENTS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_COMMENTS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['SET_CURRENT_COMMENT_ID']: {commentId: number | null}\r\n ['TOGGLE_SENSOR_TYPE_VISIBILITY']: { viewer: ViewerNames; sensorTypeId: number; force?: boolean }\r\n ['TOGGLE_SENSOR_TAG_VISIBILITY']: { viewer: ViewerNames; sensorTag: string; force?: boolean }\r\n ['SHOW_ALL_SENSOR_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_ALL_SENSORS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_ALL_SENSOR_TAGS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['SET_CURRENT_SENSOR_ID']: Pick<MenusTypes, 'currentSensorId'>\r\n ['SET_CURRENT_SENSOR_TYPE_ID']: Pick<MenusTypes, 'currentSensorTypeId'>\r\n}\r\n\r\nexport type MenusActions\r\n = ActionMap<MenusPayload>[keyof ActionMap<MenusPayload>]\r\n\r\nexport const MenusReducer = (state: MenusState, action: MenusActions) => {\r\n switch (action.type) {\r\n case 'SET_VIEWER':\r\n return {\r\n ...state,\r\n currentViewer: action.payload.currentViewer,\r\n }\r\n case 'SET_PAGINATION_ROWS_PER_PAGE':\r\n return {\r\n ...state,\r\n rowsPerPage: action.payload.rowsPerPage,\r\n }\r\n case 'SET_SIDEBAR_SELECTED_TAB':\r\n return {\r\n ...state,\r\n selectedTab: action.payload.selectedTab,\r\n }\r\n case 'SHOW_COMMENTS_IN_VIEWER':\r\n const viewerToShow = action.payload.viewer\r\n if (!viewerToShow) return state\r\n const commentsCurrentlyVisible = state.commentsVisibleInViewer || []\r\n return {\r\n ...state,\r\n commentsVisibleInViewer: commentsCurrentlyVisible.includes(viewerToShow)\r\n ? commentsCurrentlyVisible\r\n : [...commentsCurrentlyVisible, viewerToShow],\r\n }\r\n case 'HIDE_COMMENTS_IN_VIEWER':\r\n const viewerToHide = action.payload.viewer\r\n if (!viewerToHide) return state\r\n return {\r\n ...state,\r\n commentsVisibleInViewer: (state.commentsVisibleInViewer || []).filter(\r\n v => v !== viewerToHide\r\n ),\r\n }\r\n case 'SET_CURRENT_COMMENT_ID':\r\n return {\r\n ...state,\r\n currentCommentId: action.payload.commentId,\r\n }\r\n case 'SET_CURRENT_SENSOR_ID':\r\n return {\r\n ...state,\r\n currentSensorId: action.payload.currentSensorId,\r\n }\r\n case 'SET_CURRENT_SENSOR_TYPE_ID':\r\n return {\r\n ...state,\r\n currentSensorTypeId: action.payload.currentSensorTypeId,\r\n }\r\n case 'HIDE_ALL_SENSORS_IN_VIEWER':\r\n const sensorViewerToHide = action.payload.viewer\r\n if (!sensorViewerToHide) return state\r\n return {\r\n ...state,\r\n sensorsVisibleInViewer: (state.sensorsVisibleInViewer || []).filter(\r\n v => v !== sensorViewerToHide\r\n ),\r\n // Also hide all sensor types for this viewer\r\n visibleSensorTypes: {\r\n ...state.visibleSensorTypes,\r\n [sensorViewerToHide]: [],\r\n },\r\n }\r\n case 'HIDE_ALL_SENSOR_TAGS_IN_VIEWER':\r\n const tagViewerToHide = action.payload.viewer\r\n if (!tagViewerToHide) return state\r\n return {\r\n ...state,\r\n visibleSensorTags: {\r\n ...state.visibleSensorTags,\r\n [tagViewerToHide]: [],\r\n },\r\n }\r\n case 'TOGGLE_SENSOR_TYPE_VISIBILITY':\r\n const { viewer: toggleViewer, sensorTypeId, force } = action.payload\r\n if (!toggleViewer || !sensorTypeId) return state\r\n const currentTypesForViewer = state.visibleSensorTypes?.[toggleViewer] || []\r\n const isCurrentlyVisible = currentTypesForViewer.includes(sensorTypeId)\r\n // force=true → only show (idempotent); force=false/undefined → toggle\r\n if (force && isCurrentlyVisible) return state\r\n return {\r\n ...state,\r\n visibleSensorTypes: {\r\n ...state.visibleSensorTypes,\r\n [toggleViewer]: (force || !isCurrentlyVisible)\r\n ? [...currentTypesForViewer, sensorTypeId]\r\n : currentTypesForViewer.filter(t => t !== sensorTypeId),\r\n },\r\n }\r\n case 'TOGGLE_SENSOR_TAG_VISIBILITY':\r\n const { viewer: toggleTagViewer, sensorTag, force: forceTag } = action.payload\r\n if (!toggleTagViewer || !sensorTag) return state\r\n const currentTagsForViewer = state.visibleSensorTags?.[toggleTagViewer] || []\r\n const isTagCurrentlyVisible = currentTagsForViewer.includes(sensorTag)\r\n if (forceTag && isTagCurrentlyVisible) return state\r\n return {\r\n ...state,\r\n visibleSensorTags: {\r\n ...state.visibleSensorTags,\r\n [toggleTagViewer]: (forceTag || !isTagCurrentlyVisible)\r\n ? [...currentTagsForViewer, sensorTag]\r\n : currentTagsForViewer.filter(t => t !== sensorTag),\r\n },\r\n }\r\n\r\n case 'SHOW_ALL_SENSOR_IN_VIEWER':\r\n const showAllViewer = action.payload.viewer\r\n if (!showAllViewer) return state\r\n // This is called when opening the add sensor tool - we don't know all types yet\r\n // So we just ensure the viewer is in sensorsVisibleInViewer\r\n return state\r\n default:\r\n return state\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/store/Menus/reducer.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport type { ViewerNames } from '../../types/dbTypes'\r\nimport type { ActionMap } from '../ActionMap'\r\n\r\nexport type SidebarTabType = 'file' | 'layers' | 'communication' | 'sensors' | 'settings'\r\n\r\n/** Request from a viewer marker to open a comment's editor/reply box in the sidebar. */\r\nexport type CommentActionRequest = {\r\n commentId: number\r\n action: 'edit' | 'reply'\r\n /** Monotonic id so the same request fires again even if the target is unchanged. */\r\n requestId: number\r\n}\r\n\r\n/** Request from a viewer marker to open a sensor's editor in the sidebar. */\r\nexport type SensorActionRequest = {\r\n sensorId: number\r\n action: 'edit'\r\n /** Monotonic id so the same request fires again even if the target is unchanged. */\r\n requestId: number\r\n}\r\n\r\ninterface MenusTypes {\r\n currentViewer: ViewerNames\r\n rowsPerPage: number\r\n selectedTab: SidebarTabType\r\n commentsVisibleInViewer: ViewerNames[]\r\n currentCommentId: number | null\r\n /** Comment double-clicked to zoom/focus. Drives the thick focus ring + camera move. */\r\n focusedCommentId: number | null\r\n /** Monotonic counter bumped on every focus dispatch so re-focusing the same comment re-zooms. */\r\n focusRequestId: number\r\n pendingCommentAction: CommentActionRequest | null\r\n sensorsVisibleInViewer: ViewerNames[]\r\n visibleSensorTypes: Partial<Record<ViewerNames, number[]>>\r\n visibleSensorTags: Partial<Record<ViewerNames, string[]>>\r\n currentSensorId: number | null\r\n currentSensorTypeId: number | null\r\n /** Sensor double-clicked to zoom/focus. Drives the thick focus ring + camera move. */\r\n focusedSensorId: number | null\r\n /** Monotonic counter bumped on every sensor focus dispatch so re-focusing re-zooms. */\r\n sensorFocusRequestId: number\r\n pendingSensorAction: SensorActionRequest | null\r\n}\r\n\r\nexport type MenusState = MenusTypes\r\n\r\nexport type MenusPayload = {\r\n ['SET_VIEWER']: Pick<MenusTypes, 'currentViewer'>\r\n ['SET_PAGINATION_ROWS_PER_PAGE']: Pick<MenusTypes, 'rowsPerPage'>\r\n ['SET_SIDEBAR_SELECTED_TAB']: Pick<MenusTypes, 'selectedTab'>\r\n ['SHOW_COMMENTS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_COMMENTS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['SET_CURRENT_COMMENT_ID']: {commentId: number | null}\r\n ['SET_FOCUSED_COMMENT_ID']: {commentId: number | null}\r\n ['REQUEST_COMMENT_ACTION']: {commentId: number; action: 'edit' | 'reply'}\r\n ['CLEAR_PENDING_COMMENT_ACTION']: undefined\r\n ['TOGGLE_SENSOR_TYPE_VISIBILITY']: { viewer: ViewerNames; sensorTypeId: number; force?: boolean }\r\n ['TOGGLE_SENSOR_TAG_VISIBILITY']: { viewer: ViewerNames; sensorTag: string; force?: boolean }\r\n ['SHOW_ALL_SENSOR_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_ALL_SENSORS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['HIDE_ALL_SENSOR_TAGS_IN_VIEWER']: {viewer: ViewerNames}\r\n ['SET_CURRENT_SENSOR_ID']: Pick<MenusTypes, 'currentSensorId'>\r\n ['SET_CURRENT_SENSOR_TYPE_ID']: Pick<MenusTypes, 'currentSensorTypeId'>\r\n ['SET_FOCUSED_SENSOR_ID']: {sensorId: number | null}\r\n ['REQUEST_SENSOR_ACTION']: {sensorId: number}\r\n ['CLEAR_PENDING_SENSOR_ACTION']: undefined\r\n}\r\n\r\nexport type MenusActions\r\n = ActionMap<MenusPayload>[keyof ActionMap<MenusPayload>]\r\n\r\nexport const MenusReducer = (state: MenusState, action: MenusActions) => {\r\n switch (action.type) {\r\n case 'SET_VIEWER':\r\n return {\r\n ...state,\r\n currentViewer: action.payload.currentViewer,\r\n }\r\n case 'SET_PAGINATION_ROWS_PER_PAGE':\r\n return {\r\n ...state,\r\n rowsPerPage: action.payload.rowsPerPage,\r\n }\r\n case 'SET_SIDEBAR_SELECTED_TAB':\r\n return {\r\n ...state,\r\n selectedTab: action.payload.selectedTab,\r\n }\r\n case 'SHOW_COMMENTS_IN_VIEWER':\r\n const viewerToShow = action.payload.viewer\r\n if (!viewerToShow) return state\r\n const commentsCurrentlyVisible = state.commentsVisibleInViewer || []\r\n return {\r\n ...state,\r\n commentsVisibleInViewer: commentsCurrentlyVisible.includes(viewerToShow)\r\n ? commentsCurrentlyVisible\r\n : [...commentsCurrentlyVisible, viewerToShow],\r\n }\r\n case 'HIDE_COMMENTS_IN_VIEWER':\r\n const viewerToHide = action.payload.viewer\r\n if (!viewerToHide) return state\r\n return {\r\n ...state,\r\n commentsVisibleInViewer: (state.commentsVisibleInViewer || []).filter(\r\n v => v !== viewerToHide\r\n ),\r\n }\r\n case 'SET_CURRENT_COMMENT_ID':\r\n return {\r\n ...state,\r\n currentCommentId: action.payload.commentId,\r\n }\r\n case 'SET_FOCUSED_COMMENT_ID':\r\n return {\r\n ...state,\r\n focusedCommentId: action.payload.commentId,\r\n focusRequestId: state.focusRequestId + 1,\r\n }\r\n case 'REQUEST_COMMENT_ACTION':\r\n return {\r\n ...state,\r\n pendingCommentAction: {\r\n commentId: action.payload.commentId,\r\n action: action.payload.action,\r\n requestId: (state.pendingCommentAction?.requestId ?? 0) + 1,\r\n },\r\n }\r\n case 'CLEAR_PENDING_COMMENT_ACTION':\r\n if (state.pendingCommentAction === null) return state\r\n return {\r\n ...state,\r\n pendingCommentAction: null,\r\n }\r\n case 'SET_CURRENT_SENSOR_ID':\r\n return {\r\n ...state,\r\n currentSensorId: action.payload.currentSensorId,\r\n }\r\n case 'SET_CURRENT_SENSOR_TYPE_ID':\r\n return {\r\n ...state,\r\n currentSensorTypeId: action.payload.currentSensorTypeId,\r\n }\r\n case 'SET_FOCUSED_SENSOR_ID':\r\n return {\r\n ...state,\r\n focusedSensorId: action.payload.sensorId,\r\n sensorFocusRequestId: state.sensorFocusRequestId + 1,\r\n }\r\n case 'REQUEST_SENSOR_ACTION':\r\n return {\r\n ...state,\r\n pendingSensorAction: {\r\n sensorId: action.payload.sensorId,\r\n action: 'edit',\r\n requestId: (state.pendingSensorAction?.requestId ?? 0) + 1,\r\n },\r\n }\r\n case 'CLEAR_PENDING_SENSOR_ACTION':\r\n if (state.pendingSensorAction === null) return state\r\n return {\r\n ...state,\r\n pendingSensorAction: null,\r\n }\r\n case 'HIDE_ALL_SENSORS_IN_VIEWER':\r\n const sensorViewerToHide = action.payload.viewer\r\n if (!sensorViewerToHide) return state\r\n return {\r\n ...state,\r\n sensorsVisibleInViewer: (state.sensorsVisibleInViewer || []).filter(\r\n v => v !== sensorViewerToHide\r\n ),\r\n // Also hide all sensor types for this viewer\r\n visibleSensorTypes: {\r\n ...state.visibleSensorTypes,\r\n [sensorViewerToHide]: [],\r\n },\r\n }\r\n case 'HIDE_ALL_SENSOR_TAGS_IN_VIEWER':\r\n const tagViewerToHide = action.payload.viewer\r\n if (!tagViewerToHide) return state\r\n return {\r\n ...state,\r\n visibleSensorTags: {\r\n ...state.visibleSensorTags,\r\n [tagViewerToHide]: [],\r\n },\r\n }\r\n case 'TOGGLE_SENSOR_TYPE_VISIBILITY':\r\n const { viewer: toggleViewer, sensorTypeId, force } = action.payload\r\n if (!toggleViewer || !sensorTypeId) return state\r\n const currentTypesForViewer = state.visibleSensorTypes?.[toggleViewer] || []\r\n const isCurrentlyVisible = currentTypesForViewer.includes(sensorTypeId)\r\n // force=true → only show (idempotent); force=false/undefined → toggle\r\n if (force && isCurrentlyVisible) return state\r\n return {\r\n ...state,\r\n visibleSensorTypes: {\r\n ...state.visibleSensorTypes,\r\n [toggleViewer]: (force || !isCurrentlyVisible)\r\n ? [...currentTypesForViewer, sensorTypeId]\r\n : currentTypesForViewer.filter(t => t !== sensorTypeId),\r\n },\r\n }\r\n case 'TOGGLE_SENSOR_TAG_VISIBILITY':\r\n const { viewer: toggleTagViewer, sensorTag, force: forceTag } = action.payload\r\n if (!toggleTagViewer || !sensorTag) return state\r\n const currentTagsForViewer = state.visibleSensorTags?.[toggleTagViewer] || []\r\n const isTagCurrentlyVisible = currentTagsForViewer.includes(sensorTag)\r\n if (forceTag && isTagCurrentlyVisible) return state\r\n return {\r\n ...state,\r\n visibleSensorTags: {\r\n ...state.visibleSensorTags,\r\n [toggleTagViewer]: (forceTag || !isTagCurrentlyVisible)\r\n ? [...currentTagsForViewer, sensorTag]\r\n : currentTagsForViewer.filter(t => t !== sensorTag),\r\n },\r\n }\r\n\r\n case 'SHOW_ALL_SENSOR_IN_VIEWER':\r\n const showAllViewer = action.payload.viewer\r\n if (!showAllViewer) return state\r\n // This is called when opening the add sensor tool - we don't know all types yet\r\n // So we just ensure the viewer is in sensorsVisibleInViewer\r\n return state\r\n default:\r\n return state\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1,3 +1,13 @@
1
+ /** Platform highlight colour, shared by map + BIM comment/sensor markers. */
2
+ export declare const HIGHLIGHT_COLOR = "#73cee2";
1
3
  export declare const markerStyle: string;
2
4
  export declare const markerStyleHighlight: string;
5
+ /**
6
+ * `box-shadow` ring for a comment marker, shared by every surface so the ring widths stay
7
+ * consistent: 1px white (idle), 2px highlight (hover/selected), 3px focus (double-click zoom).
8
+ */
9
+ export declare function commentRingShadow({ highlight, focused }: {
10
+ highlight?: boolean;
11
+ focused?: boolean;
12
+ }): string;
3
13
  //# sourceMappingURL=markerUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"markerUtils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/markerUtils.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,QAEiB,CAAC;AAG1C,eAAO,MAAM,oBAAoB,QAGQ,CAAC"}
1
+ {"version":3,"file":"markerUtils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/markerUtils.ts"],"names":[],"mappings":"AAGA,6EAA6E;AAC7E,eAAO,MAAM,eAAe,YAAY,CAAA;AAGxC,eAAO,MAAM,WAAW,QAEiB,CAAC;AAG1C,eAAO,MAAM,oBAAoB,QAGQ,CAAC;AAE1C;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE;IAAE,SAAS,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAI5G"}
@@ -1,6 +1,14 @@
1
+ const HIGHLIGHT_COLOR = "#73cee2";
1
2
  const markerStyle = "absolute z-[99999] pointer-events-auto rounded-[16px] transition-[box-shadow] translate-x-[-50%] translate-y-[-90%]";
2
- const markerStyleHighlight = "absolute z-[99999] pointer-events-auto rounded-[16px] transition-[box-shadow] shadow-[0_0_0_3px_#73cee2,0_0_16px_4px_rgba(115,206,226,0.5)] translate-x-[-50%] translate-y-[-90%]";
3
+ const markerStyleHighlight = "absolute z-[99999] pointer-events-auto rounded-[16px] transition-[box-shadow] shadow-[0_0_0_2px_#73cee2,0_0_16px_4px_rgba(115,206,226,0.5)] translate-x-[-50%] translate-y-[-90%]";
4
+ function commentRingShadow({ highlight, focused }) {
5
+ if (focused) return `0 0 0 3px ${HIGHLIGHT_COLOR}, 0 0 12px rgba(115, 206, 226, 0.6)`;
6
+ if (highlight) return `0 0 0 2px ${HIGHLIGHT_COLOR}, 0 0 8px rgba(115, 206, 226, 0.5)`;
7
+ return "0 0 0 1px white";
8
+ }
3
9
  export {
10
+ HIGHLIGHT_COLOR,
11
+ commentRingShadow,
4
12
  markerStyle,
5
13
  markerStyleHighlight
6
14
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/utils/markerUtils.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n// Tailwind class string for marker highlight style\r\nexport const markerStyle =\r\n 'absolute z-[99999] pointer-events-auto rounded-[16px] transition-[box-shadow] ' +\r\n 'translate-x-[-50%] translate-y-[-90%]';\r\n\r\n// Tailwind class string for marker style\r\nexport const markerStyleHighlight =\r\n 'absolute z-[99999] pointer-events-auto rounded-[16px] transition-[box-shadow] ' +\r\n 'shadow-[0_0_0_3px_#73cee2,0_0_16px_4px_rgba(115,206,226,0.5)] ' +\r\n 'translate-x-[-50%] translate-y-[-90%]';\r\n\r\n"],"mappings":"AAIO,MAAM,cACX;AAIK,MAAM,uBACX;","names":[]}
1
+ {"version":3,"sources":["../../../src/core/utils/markerUtils.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n/** Platform highlight colour, shared by map + BIM comment/sensor markers. */\r\nexport const HIGHLIGHT_COLOR = '#73cee2'\r\n\r\n// Tailwind class string for marker highlight style\r\nexport const markerStyle =\r\n 'absolute z-[99999] pointer-events-auto rounded-[16px] transition-[box-shadow] ' +\r\n 'translate-x-[-50%] translate-y-[-90%]';\r\n\r\n// Tailwind class string for marker style\r\nexport const markerStyleHighlight =\r\n 'absolute z-[99999] pointer-events-auto rounded-[16px] transition-[box-shadow] ' +\r\n 'shadow-[0_0_0_2px_#73cee2,0_0_16px_4px_rgba(115,206,226,0.5)] ' +\r\n 'translate-x-[-50%] translate-y-[-90%]';\r\n\r\n/**\r\n * `box-shadow` ring for a comment marker, shared by every surface so the ring widths stay\r\n * consistent: 1px white (idle), 2px highlight (hover/selected), 3px focus (double-click zoom).\r\n */\r\nexport function commentRingShadow({ highlight, focused }: { highlight?: boolean; focused?: boolean }): string {\r\n if (focused) return `0 0 0 3px ${HIGHLIGHT_COLOR}, 0 0 12px rgba(115, 206, 226, 0.6)`\r\n if (highlight) return `0 0 0 2px ${HIGHLIGHT_COLOR}, 0 0 8px rgba(115, 206, 226, 0.5)`\r\n return '0 0 0 1px white'\r\n}\r\n\r\n"],"mappings":"AAIO,MAAM,kBAAkB;AAGxB,MAAM,cACX;AAIK,MAAM,uBACX;AAQK,SAAS,kBAAkB,EAAE,WAAW,QAAQ,GAAuD;AAC5G,MAAI,QAAS,QAAO,aAAa,eAAe;AAChD,MAAI,UAAW,QAAO,aAAa,eAAe;AAClD,SAAO;AACT;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"memcache.d.ts","sourceRoot":"","sources":["../../../src/core/utils/memcache.ts"],"names":[],"mappings":"AAwDA,wBAAsB,WAAW,CAAC,CAAC,EACjC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,UAAU,GAAE,MAAa,GACxB,OAAO,CAAC,OAAO,CAAC,CAelB;AAED,wBAAsB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAqBnE;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAclE;AAED,wBAAsB,YAAY,CAAC,CAAC,EAClC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAaZ;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CActD"}
1
+ {"version":3,"file":"memcache.d.ts","sourceRoot":"","sources":["../../../src/core/utils/memcache.ts"],"names":[],"mappings":"AAqDA,wBAAsB,WAAW,CAAC,CAAC,EACjC,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,CAAC,EACR,UAAU,GAAE,MAAa,GACxB,OAAO,CAAC,OAAO,CAAC,CAclB;AAED,wBAAsB,WAAW,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAmBnE;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAalE;AAED,wBAAsB,YAAY,CAAC,CAAC,EAClC,GAAG,EAAE,MAAM,EACX,UAAU,EAAE,MAAM,EAClB,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACnB,OAAO,CAAC,CAAC,CAAC,CAaZ;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,CAatD"}
@@ -27,14 +27,12 @@ async function getMemcacheClient() {
27
27
  return null;
28
28
  }
29
29
  const memcacheServer = process.env.MEMCACHE_SERVER;
30
- console.log(`Connecting to Memcache server: ${memcacheServer}`);
31
30
  client = memjsLib.Client.create(memcacheServer, {
32
31
  username: process.env.MEMCACHE_USERNAME,
33
32
  password: process.env.MEMCACHE_PASSWORD,
34
33
  timeout: 5,
35
34
  retries: 2
36
35
  });
37
- console.log("Memcache client initialized successfully");
38
36
  return client;
39
37
  } catch (error) {
40
38
  console.error("Failed to initialize Memcache client:", error);
@@ -49,7 +47,6 @@ async function setMemcache(key, value, ttlSeconds = 3600) {
49
47
  try {
50
48
  const serialized = JSON.stringify(value);
51
49
  await client2.set(key, serialized, { expires: ttlSeconds });
52
- console.log(`Memcache SET: ${key} (TTL: ${ttlSeconds}s)`);
53
50
  return true;
54
51
  } catch (error) {
55
52
  console.error(`Failed to set Memcache key ${key}:`, error);
@@ -64,11 +61,9 @@ async function getMemcache(key) {
64
61
  try {
65
62
  const result = await client2.get(key);
66
63
  if (!result.value) {
67
- console.log(`Memcache MISS: ${key}`);
68
64
  return null;
69
65
  }
70
66
  const deserialized = JSON.parse(result.value.toString());
71
- console.log(`Memcache HIT: ${key}`);
72
67
  return deserialized;
73
68
  } catch (error) {
74
69
  console.error(`Failed to get Memcache key ${key}:`, error);
@@ -82,7 +77,6 @@ async function deleteMemcache(key) {
82
77
  }
83
78
  try {
84
79
  await client2.delete(key);
85
- console.log(`Memcache DELETE: ${key}`);
86
80
  return true;
87
81
  } catch (error) {
88
82
  console.error(`Failed to delete Memcache key ${key}:`, error);
@@ -107,7 +101,6 @@ async function flushMemcache() {
107
101
  }
108
102
  try {
109
103
  await client2.flush();
110
- console.log("Memcache FLUSHED");
111
104
  return true;
112
105
  } catch (error) {
113
106
  console.error("Failed to flush Memcache:", error);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/utils/memcache.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nlet memjs: typeof import('memjs') | null = null\r\nlet client: any = null\r\n\r\nasync function loadMemjs() {\r\n if (typeof window !== 'undefined') {\r\n return null\r\n }\r\n\r\n if (!memjs) {\r\n try {\r\n memjs = await import('memjs')\r\n } catch (error) {\r\n console.error('Failed to load memjs:', error)\r\n return null\r\n }\r\n }\r\n return memjs\r\n}\r\n\r\nasync function getMemcacheClient() {\r\n if (typeof window !== 'undefined') {\r\n return null\r\n }\r\n\r\n if (client) {\r\n return client\r\n }\r\n\r\n try {\r\n const memjsLib = await loadMemjs()\r\n if (!memjsLib) {\r\n return null\r\n }\r\n\r\n const memcacheServer = process.env.MEMCACHE_SERVER\r\n\r\n console.log(`Connecting to Memcache server: ${memcacheServer}`)\r\n\r\n client = memjsLib.Client.create(memcacheServer, {\r\n username: process.env.MEMCACHE_USERNAME,\r\n password: process.env.MEMCACHE_PASSWORD,\r\n timeout: 5,\r\n retries: 2,\r\n })\r\n\r\n console.log('Memcache client initialized successfully')\r\n return client\r\n } catch (error) {\r\n console.error('Failed to initialize Memcache client:', error)\r\n return null\r\n }\r\n}\r\n\r\nexport async function setMemcache<T>(\r\n key: string,\r\n value: T,\r\n ttlSeconds: number = 3600\r\n): Promise<boolean> {\r\n const client = await getMemcacheClient()\r\n if (!client) {\r\n return false\r\n }\r\n\r\n try {\r\n const serialized = JSON.stringify(value)\r\n await client.set(key, serialized, { expires: ttlSeconds })\r\n console.log(`Memcache SET: ${key} (TTL: ${ttlSeconds}s)`)\r\n return true\r\n } catch (error) {\r\n console.error(`Failed to set Memcache key ${key}:`, error)\r\n return false\r\n }\r\n}\r\n\r\nexport async function getMemcache<T>(key: string): Promise<T | null> {\r\n const client = await getMemcacheClient()\r\n if (!client) {\r\n return null\r\n }\r\n\r\n try {\r\n const result = await client.get(key)\r\n\r\n if (!result.value) {\r\n console.log(`Memcache MISS: ${key}`)\r\n return null\r\n }\r\n\r\n const deserialized = JSON.parse(result.value.toString()) as T\r\n console.log(`Memcache HIT: ${key}`)\r\n return deserialized\r\n } catch (error) {\r\n console.error(`Failed to get Memcache key ${key}:`, error)\r\n return null\r\n }\r\n}\r\n\r\nexport async function deleteMemcache(key: string): Promise<boolean> {\r\n const client = await getMemcacheClient()\r\n if (!client) {\r\n return false\r\n }\r\n\r\n try {\r\n await client.delete(key)\r\n console.log(`Memcache DELETE: ${key}`)\r\n return true\r\n } catch (error) {\r\n console.error(`Failed to delete Memcache key ${key}:`, error)\r\n return false\r\n }\r\n}\r\n\r\nexport async function withMemcache<T>(\r\n key: string,\r\n ttlSeconds: number,\r\n fn: () => Promise<T>\r\n): Promise<T> {\r\n const cached = await getMemcache<T>(key)\r\n if (cached !== null) {\r\n return cached\r\n }\r\n\r\n const result = await fn()\r\n\r\n setMemcache(key, result, ttlSeconds).catch(err => {\r\n console.error('Background Memcache set failed:', err)\r\n })\r\n\r\n return result\r\n}\r\n\r\nexport async function flushMemcache(): Promise<boolean> {\r\n const client = await getMemcacheClient()\r\n if (!client) {\r\n return false\r\n }\r\n\r\n try {\r\n await client.flush()\r\n console.log('Memcache FLUSHED')\r\n return true\r\n } catch (error) {\r\n console.error('Failed to flush Memcache:', error)\r\n return false\r\n }\r\n}\r\n"],"mappings":"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","names":["client"]}
1
+ {"version":3,"sources":["../../../src/core/utils/memcache.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nlet memjs: typeof import('memjs') | null = null\r\nlet client: any = null\r\n\r\nasync function loadMemjs() {\r\n if (typeof window !== 'undefined') {\r\n return null\r\n }\r\n\r\n if (!memjs) {\r\n try {\r\n memjs = await import('memjs')\r\n } catch (error) {\r\n console.error('Failed to load memjs:', error)\r\n return null\r\n }\r\n }\r\n return memjs\r\n}\r\n\r\nasync function getMemcacheClient() {\r\n if (typeof window !== 'undefined') {\r\n return null\r\n }\r\n\r\n if (client) {\r\n return client\r\n }\r\n\r\n try {\r\n const memjsLib = await loadMemjs()\r\n if (!memjsLib) {\r\n return null\r\n }\r\n\r\n const memcacheServer = process.env.MEMCACHE_SERVER\r\n\r\n client = memjsLib.Client.create(memcacheServer, {\r\n username: process.env.MEMCACHE_USERNAME,\r\n password: process.env.MEMCACHE_PASSWORD,\r\n timeout: 5,\r\n retries: 2,\r\n })\r\n\r\n return client\r\n } catch (error) {\r\n console.error('Failed to initialize Memcache client:', error)\r\n return null\r\n }\r\n}\r\n\r\nexport async function setMemcache<T>(\r\n key: string,\r\n value: T,\r\n ttlSeconds: number = 3600\r\n): Promise<boolean> {\r\n const client = await getMemcacheClient()\r\n if (!client) {\r\n return false\r\n }\r\n\r\n try {\r\n const serialized = JSON.stringify(value)\r\n await client.set(key, serialized, { expires: ttlSeconds })\r\n return true\r\n } catch (error) {\r\n console.error(`Failed to set Memcache key ${key}:`, error)\r\n return false\r\n }\r\n}\r\n\r\nexport async function getMemcache<T>(key: string): Promise<T | null> {\r\n const client = await getMemcacheClient()\r\n if (!client) {\r\n return null\r\n }\r\n\r\n try {\r\n const result = await client.get(key)\r\n\r\n if (!result.value) {\r\n return null\r\n }\r\n\r\n const deserialized = JSON.parse(result.value.toString()) as T\r\n return deserialized\r\n } catch (error) {\r\n console.error(`Failed to get Memcache key ${key}:`, error)\r\n return null\r\n }\r\n}\r\n\r\nexport async function deleteMemcache(key: string): Promise<boolean> {\r\n const client = await getMemcacheClient()\r\n if (!client) {\r\n return false\r\n }\r\n\r\n try {\r\n await client.delete(key)\r\n return true\r\n } catch (error) {\r\n console.error(`Failed to delete Memcache key ${key}:`, error)\r\n return false\r\n }\r\n}\r\n\r\nexport async function withMemcache<T>(\r\n key: string,\r\n ttlSeconds: number,\r\n fn: () => Promise<T>\r\n): Promise<T> {\r\n const cached = await getMemcache<T>(key)\r\n if (cached !== null) {\r\n return cached\r\n }\r\n\r\n const result = await fn()\r\n\r\n setMemcache(key, result, ttlSeconds).catch(err => {\r\n console.error('Background Memcache set failed:', err)\r\n })\r\n\r\n return result\r\n}\r\n\r\nexport async function flushMemcache(): Promise<boolean> {\r\n const client = await getMemcacheClient()\r\n if (!client) {\r\n return false\r\n }\r\n\r\n try {\r\n await client.flush()\r\n return true\r\n } catch (error) {\r\n console.error('Failed to flush Memcache:', error)\r\n return false\r\n }\r\n}\r\n"],"mappings":"AAGA,IAAI,QAAuC;AAC3C,IAAI,SAAc;AAElB,eAAe,YAAY;AACzB,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,OAAO;AACV,QAAI;AACF,cAAQ,MAAM,OAAO,OAAO;AAAA,IAC9B,SAAS,OAAO;AACd,cAAQ,MAAM,yBAAyB,KAAK;AAC5C,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,eAAe,oBAAoB;AACjC,MAAI,OAAO,WAAW,aAAa;AACjC,WAAO;AAAA,EACT;AAEA,MAAI,QAAQ;AACV,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,WAAW,MAAM,UAAU;AACjC,QAAI,CAAC,UAAU;AACb,aAAO;AAAA,IACT;AAEA,UAAM,iBAAiB,QAAQ,IAAI;AAEnC,aAAS,SAAS,OAAO,OAAO,gBAAgB;AAAA,MAC9C,UAAU,QAAQ,IAAI;AAAA,MACtB,UAAU,QAAQ,IAAI;AAAA,MACtB,SAAS;AAAA,MACT,SAAS;AAAA,IACX,CAAC;AAED,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,yCAAyC,KAAK;AAC5D,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,YACpB,KACA,OACA,aAAqB,MACH;AAClB,QAAMA,UAAS,MAAM,kBAAkB;AACvC,MAAI,CAACA,SAAQ;AACX,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,aAAa,KAAK,UAAU,KAAK;AACvC,UAAMA,QAAO,IAAI,KAAK,YAAY,EAAE,SAAS,WAAW,CAAC;AACzD,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,8BAA8B,GAAG,KAAK,KAAK;AACzD,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,YAAe,KAAgC;AACnE,QAAMA,UAAS,MAAM,kBAAkB;AACvC,MAAI,CAACA,SAAQ;AACX,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,SAAS,MAAMA,QAAO,IAAI,GAAG;AAEnC,QAAI,CAAC,OAAO,OAAO;AACjB,aAAO;AAAA,IACT;AAEA,UAAM,eAAe,KAAK,MAAM,OAAO,MAAM,SAAS,CAAC;AACvD,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,8BAA8B,GAAG,KAAK,KAAK;AACzD,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,eAAe,KAA+B;AAClE,QAAMA,UAAS,MAAM,kBAAkB;AACvC,MAAI,CAACA,SAAQ;AACX,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAMA,QAAO,OAAO,GAAG;AACvB,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,iCAAiC,GAAG,KAAK,KAAK;AAC5D,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,aACpB,KACA,YACA,IACY;AACZ,QAAM,SAAS,MAAM,YAAe,GAAG;AACvC,MAAI,WAAW,MAAM;AACnB,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,MAAM,GAAG;AAExB,cAAY,KAAK,QAAQ,UAAU,EAAE,MAAM,SAAO;AAChD,YAAQ,MAAM,mCAAmC,GAAG;AAAA,EACtD,CAAC;AAED,SAAO;AACT;AAEA,eAAsB,gBAAkC;AACtD,QAAMA,UAAS,MAAM,kBAAkB;AACvC,MAAI,CAACA,SAAQ;AACX,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAMA,QAAO,MAAM;AACnB,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,6BAA6B,KAAK;AAChD,WAAO;AAAA,EACT;AACF;","names":["client"]}
@@ -11,8 +11,12 @@ export declare function timeAgo(then: Date): string;
11
11
  * Format a timestamp for display
12
12
  * - If today: shows relative time (e.g., "5 min")
13
13
  * - If not today: shows formatted date (e.g., "Jan 15, 2026")
14
+ *
15
+ * The `timeZone` arg only affects the absolute-date rendering; the today/relative
16
+ * boundary is computed in the host local day (a known cosmetic limitation near
17
+ * midnight across zones).
14
18
  */
15
- export declare function formatTimestamp(input: string | Date): string;
19
+ export declare function formatTimestamp(input: string | Date, timeZone?: string): string;
16
20
  /**
17
21
  * Format milliseconds to human-readable duration
18
22
  * Examples: "500 ms", "1 sec", "30 sec", "5 min", "1 hr", "2 days"
@@ -35,4 +39,23 @@ export declare const frequencyUnits: readonly [{
35
39
  readonly value: 3600000;
36
40
  readonly label: "Hours";
37
41
  }];
42
+ /** Browser IANA zone, e.g. "America/Toronto". Falls back to "UTC" if unavailable. */
43
+ export declare function detectTimeZone(): string;
44
+ /**
45
+ * Longitude -> nearest whole-hour offset -> an Etc/GMT±N id. Note POSIX sign inversion:
46
+ * a positive (east) offset is Etc/GMT-N. This is a rough approximation: no DST, no
47
+ * political borders. 0 -> "UTC".
48
+ */
49
+ export declare function offsetZoneFromLongitude(longitude: number): string;
50
+ /**
51
+ * Default display zone. Prefers the browser's IANA zone: it is DST-correct and, for a user
52
+ * in the sensor's region, already the right local zone. Only when detection is unavailable
53
+ * (returns "UTC") does it fall back to a longitude-derived fixed offset, trying each
54
+ * candidate longitude in order. Callers pass candidates in priority order: BIM sensors sit
55
+ * in a building (building longitude first), map sensors carry their own coordinates (sensor
56
+ * longitude first).
57
+ */
58
+ export declare function resolveDefaultTimeZone(longitudeCandidates: Array<number | null | undefined>): string;
59
+ /** Format an epoch in a specific zone. Handles Etc/GMT±N and true IANA zones alike. */
60
+ export declare function formatInZone(epochMs: number, timeZone: string, opts?: Intl.DateTimeFormatOptions): string;
38
61
  //# sourceMappingURL=timeUtils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"timeUtils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/timeUtils.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAMnD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAuB1C;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAY5D;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAcjD;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;EAKjB,CAAA"}
1
+ {"version":3,"file":"timeUtils.d.ts","sourceRoot":"","sources":["../../../src/core/utils/timeUtils.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAgB,SAAS,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,GAAG,OAAO,CAMnD;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAuB1C;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAa/E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAcjD;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;EAKjB,CAAA;AAEV,qFAAqF;AACrF,wBAAgB,cAAc,IAAI,MAAM,CAMvC;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAMjE;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,mBAAmB,EAAE,KAAK,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,MAAM,CAOpG;AAED,uFAAuF;AACvF,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,IAAI,CAAC,EAAE,IAAI,CAAC,qBAAqB,GAChC,MAAM,CAMR"}
@@ -1,3 +1,19 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
3
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
4
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
5
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
+ var __spreadValues = (a, b) => {
7
+ for (var prop in b || (b = {}))
8
+ if (__hasOwnProp.call(b, prop))
9
+ __defNormalProp(a, prop, b[prop]);
10
+ if (__getOwnPropSymbols)
11
+ for (var prop of __getOwnPropSymbols(b)) {
12
+ if (__propIsEnum.call(b, prop))
13
+ __defNormalProp(a, prop, b[prop]);
14
+ }
15
+ return a;
16
+ };
1
17
  function isSameDay(a, b) {
2
18
  return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
3
19
  }
@@ -18,16 +34,16 @@ function timeAgo(then) {
18
34
  const diffYears = Math.floor(diffDays / 365);
19
35
  return `${diffYears}y`;
20
36
  }
21
- function formatTimestamp(input) {
37
+ function formatTimestamp(input, timeZone) {
22
38
  const then = typeof input === "string" ? new Date(input) : input;
23
39
  const now = /* @__PURE__ */ new Date();
24
40
  if (Number.isNaN(then.getTime())) return "";
25
41
  if (isSameDay(now, then)) return timeAgo(then);
26
- return then.toLocaleDateString(void 0, {
42
+ return then.toLocaleDateString(void 0, __spreadValues({
27
43
  year: "numeric",
28
44
  month: "short",
29
45
  day: "2-digit"
30
- });
46
+ }, timeZone ? { timeZone } : {}));
31
47
  }
32
48
  function formatDuration(ms) {
33
49
  if (ms < 1e3) return `${ms} ms`;
@@ -46,11 +62,44 @@ const frequencyUnits = [
46
62
  { value: 6e4, label: "Minutes" },
47
63
  { value: 36e5, label: "Hours" }
48
64
  ];
65
+ function detectTimeZone() {
66
+ try {
67
+ return Intl.DateTimeFormat().resolvedOptions().timeZone || "UTC";
68
+ } catch (e) {
69
+ return "UTC";
70
+ }
71
+ }
72
+ function offsetZoneFromLongitude(longitude) {
73
+ if (!Number.isFinite(longitude)) return "UTC";
74
+ let h = Math.round(longitude / 15);
75
+ h = Math.max(-12, Math.min(12, h));
76
+ if (h === 0) return "UTC";
77
+ return `Etc/GMT${h > 0 ? "-" : "+"}${Math.abs(h)}`;
78
+ }
79
+ function resolveDefaultTimeZone(longitudeCandidates) {
80
+ const detected = detectTimeZone();
81
+ if (detected && detected !== "UTC") return detected;
82
+ for (const lng of longitudeCandidates) {
83
+ if (typeof lng === "number" && Number.isFinite(lng)) return offsetZoneFromLongitude(lng);
84
+ }
85
+ return detected || "UTC";
86
+ }
87
+ function formatInZone(epochMs, timeZone, opts) {
88
+ try {
89
+ return new Intl.DateTimeFormat(void 0, __spreadValues({ timeZone }, opts)).format(epochMs);
90
+ } catch (e) {
91
+ return new Intl.DateTimeFormat(void 0, opts).format(epochMs);
92
+ }
93
+ }
49
94
  export {
95
+ detectTimeZone,
50
96
  formatDuration,
97
+ formatInZone,
51
98
  formatTimestamp,
52
99
  frequencyUnits,
53
100
  isSameDay,
101
+ offsetZoneFromLongitude,
102
+ resolveDefaultTimeZone,
54
103
  timeAgo
55
104
  };
56
105
  //# sourceMappingURL=timeUtils.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/core/utils/timeUtils.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n/**\r\n * Check if two dates are on the same day (ignoring time)\r\n */\r\nexport function isSameDay(a: Date, b: Date): boolean {\r\n return (\r\n a.getFullYear() === b.getFullYear()\r\n && a.getMonth() === b.getMonth()\r\n && a.getDate() === b.getDate()\r\n )\r\n}\r\n\r\n/**\r\n * Calculate time elapsed since a given date and return a human-readable string\r\n * Examples: \"5s\", \"10 min\", \"3h\", \"2d\", \"1w\", \"3mo\", \"2y\"\r\n */\r\nexport function timeAgo(then: Date): string {\r\n const now = new Date()\r\n const diffSeconds = Math.floor((now.getTime() - then.getTime()) / 1000)\r\n\r\n if (diffSeconds < 60) return `${diffSeconds}s`\r\n\r\n const diffMinutes = Math.floor(diffSeconds / 60)\r\n if (diffMinutes < 60) return `${diffMinutes} min`\r\n\r\n const diffHours = Math.floor(diffMinutes / 60)\r\n if (diffHours < 24) return `${diffHours}h`\r\n\r\n const diffDays = Math.floor(diffHours / 24)\r\n if (diffDays < 7) return `${diffDays}d`\r\n\r\n const diffWeeks = Math.floor(diffDays / 7)\r\n if (diffWeeks < 4) return `${diffWeeks}w`\r\n\r\n const diffMonths = Math.floor(diffDays / 30)\r\n if (diffMonths < 12) return `${diffMonths}mo`\r\n\r\n const diffYears = Math.floor(diffDays / 365)\r\n return `${diffYears}y`\r\n}\r\n\r\n/**\r\n * Format a timestamp for display\r\n * - If today: shows relative time (e.g., \"5 min\")\r\n * - If not today: shows formatted date (e.g., \"Jan 15, 2026\")\r\n */\r\nexport function formatTimestamp(input: string | Date): string {\r\n const then = typeof input === 'string' ? new Date(input) : input\r\n const now = new Date()\r\n\r\n if (Number.isNaN(then.getTime())) return ''\r\n if (isSameDay(now, then)) return timeAgo(then)\r\n\r\n return then.toLocaleDateString(undefined, {\r\n year: 'numeric',\r\n month: 'short',\r\n day: '2-digit',\r\n })\r\n}\r\n\r\n/**\r\n * Format milliseconds to human-readable duration\r\n * Examples: \"500 ms\", \"1 sec\", \"30 sec\", \"5 min\", \"1 hr\", \"2 days\"\r\n */\r\nexport function formatDuration(ms: number): string {\r\n if (ms < 1000) return `${ms} ms`\r\n\r\n const seconds = ms / 1000\r\n if (seconds < 60) return seconds === 1 ? '1 sec' : `${seconds} sec`\r\n\r\n const minutes = seconds / 60\r\n if (minutes < 60) return minutes === 1 ? '1 min' : `${Math.floor(minutes)} min`\r\n\r\n const hours = minutes / 60\r\n if (hours < 24) return hours === 1 ? '1 hr' : `${Math.floor(hours)} hr`\r\n\r\n const days = hours / 24\r\n return days === 1 ? '1 day' : `${Math.floor(days)} days`\r\n}\r\n\r\n/**\r\n * Time frequency units for duration inputs\r\n * Value is the multiplier to convert to milliseconds\r\n */\r\nexport const frequencyUnits = [\r\n { value: 1, label: 'Milliseconds' },\r\n { value: 1000, label: 'Seconds' },\r\n { value: 60000, label: 'Minutes' },\r\n { value: 3600000, label: 'Hours' },\r\n] as const\r\n"],"mappings":"AAMO,SAAS,UAAU,GAAS,GAAkB;AACnD,SACE,EAAE,YAAY,MAAM,EAAE,YAAY,KAC/B,EAAE,SAAS,MAAM,EAAE,SAAS,KAC5B,EAAE,QAAQ,MAAM,EAAE,QAAQ;AAEjC;AAMO,SAAS,QAAQ,MAAoB;AAC1C,QAAM,MAAM,oBAAI,KAAK;AACrB,QAAM,cAAc,KAAK,OAAO,IAAI,QAAQ,IAAI,KAAK,QAAQ,KAAK,GAAI;AAEtE,MAAI,cAAc,GAAI,QAAO,GAAG,WAAW;AAE3C,QAAM,cAAc,KAAK,MAAM,cAAc,EAAE;AAC/C,MAAI,cAAc,GAAI,QAAO,GAAG,WAAW;AAE3C,QAAM,YAAY,KAAK,MAAM,cAAc,EAAE;AAC7C,MAAI,YAAY,GAAI,QAAO,GAAG,SAAS;AAEvC,QAAM,WAAW,KAAK,MAAM,YAAY,EAAE;AAC1C,MAAI,WAAW,EAAG,QAAO,GAAG,QAAQ;AAEpC,QAAM,YAAY,KAAK,MAAM,WAAW,CAAC;AACzC,MAAI,YAAY,EAAG,QAAO,GAAG,SAAS;AAEtC,QAAM,aAAa,KAAK,MAAM,WAAW,EAAE;AAC3C,MAAI,aAAa,GAAI,QAAO,GAAG,UAAU;AAEzC,QAAM,YAAY,KAAK,MAAM,WAAW,GAAG;AAC3C,SAAO,GAAG,SAAS;AACrB;AAOO,SAAS,gBAAgB,OAA8B;AAC5D,QAAM,OAAO,OAAO,UAAU,WAAW,IAAI,KAAK,KAAK,IAAI;AAC3D,QAAM,MAAM,oBAAI,KAAK;AAErB,MAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,EAAG,QAAO;AACzC,MAAI,UAAU,KAAK,IAAI,EAAG,QAAO,QAAQ,IAAI;AAE7C,SAAO,KAAK,mBAAmB,QAAW;AAAA,IACxC,MAAM;AAAA,IACN,OAAO;AAAA,IACP,KAAK;AAAA,EACP,CAAC;AACH;AAMO,SAAS,eAAe,IAAoB;AACjD,MAAI,KAAK,IAAM,QAAO,GAAG,EAAE;AAE3B,QAAM,UAAU,KAAK;AACrB,MAAI,UAAU,GAAI,QAAO,YAAY,IAAI,UAAU,GAAG,OAAO;AAE7D,QAAM,UAAU,UAAU;AAC1B,MAAI,UAAU,GAAI,QAAO,YAAY,IAAI,UAAU,GAAG,KAAK,MAAM,OAAO,CAAC;AAEzE,QAAM,QAAQ,UAAU;AACxB,MAAI,QAAQ,GAAI,QAAO,UAAU,IAAI,SAAS,GAAG,KAAK,MAAM,KAAK,CAAC;AAElE,QAAM,OAAO,QAAQ;AACrB,SAAO,SAAS,IAAI,UAAU,GAAG,KAAK,MAAM,IAAI,CAAC;AACnD;AAMO,MAAM,iBAAiB;AAAA,EAC5B,EAAE,OAAO,GAAG,OAAO,eAAe;AAAA,EAClC,EAAE,OAAO,KAAM,OAAO,UAAU;AAAA,EAChC,EAAE,OAAO,KAAO,OAAO,UAAU;AAAA,EACjC,EAAE,OAAO,MAAS,OAAO,QAAQ;AACnC;","names":[]}
1
+ {"version":3,"sources":["../../../src/core/utils/timeUtils.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n/**\r\n * Check if two dates are on the same day (ignoring time)\r\n */\r\nexport function isSameDay(a: Date, b: Date): boolean {\r\n return (\r\n a.getFullYear() === b.getFullYear()\r\n && a.getMonth() === b.getMonth()\r\n && a.getDate() === b.getDate()\r\n )\r\n}\r\n\r\n/**\r\n * Calculate time elapsed since a given date and return a human-readable string\r\n * Examples: \"5s\", \"10 min\", \"3h\", \"2d\", \"1w\", \"3mo\", \"2y\"\r\n */\r\nexport function timeAgo(then: Date): string {\r\n const now = new Date()\r\n const diffSeconds = Math.floor((now.getTime() - then.getTime()) / 1000)\r\n\r\n if (diffSeconds < 60) return `${diffSeconds}s`\r\n\r\n const diffMinutes = Math.floor(diffSeconds / 60)\r\n if (diffMinutes < 60) return `${diffMinutes} min`\r\n\r\n const diffHours = Math.floor(diffMinutes / 60)\r\n if (diffHours < 24) return `${diffHours}h`\r\n\r\n const diffDays = Math.floor(diffHours / 24)\r\n if (diffDays < 7) return `${diffDays}d`\r\n\r\n const diffWeeks = Math.floor(diffDays / 7)\r\n if (diffWeeks < 4) return `${diffWeeks}w`\r\n\r\n const diffMonths = Math.floor(diffDays / 30)\r\n if (diffMonths < 12) return `${diffMonths}mo`\r\n\r\n const diffYears = Math.floor(diffDays / 365)\r\n return `${diffYears}y`\r\n}\r\n\r\n/**\r\n * Format a timestamp for display\r\n * - If today: shows relative time (e.g., \"5 min\")\r\n * - If not today: shows formatted date (e.g., \"Jan 15, 2026\")\r\n *\r\n * The `timeZone` arg only affects the absolute-date rendering; the today/relative\r\n * boundary is computed in the host local day (a known cosmetic limitation near\r\n * midnight across zones).\r\n */\r\nexport function formatTimestamp(input: string | Date, timeZone?: string): string {\r\n const then = typeof input === 'string' ? new Date(input) : input\r\n const now = new Date()\r\n\r\n if (Number.isNaN(then.getTime())) return ''\r\n if (isSameDay(now, then)) return timeAgo(then)\r\n\r\n return then.toLocaleDateString(undefined, {\r\n year: 'numeric',\r\n month: 'short',\r\n day: '2-digit',\r\n ...(timeZone ? { timeZone } : {}),\r\n })\r\n}\r\n\r\n/**\r\n * Format milliseconds to human-readable duration\r\n * Examples: \"500 ms\", \"1 sec\", \"30 sec\", \"5 min\", \"1 hr\", \"2 days\"\r\n */\r\nexport function formatDuration(ms: number): string {\r\n if (ms < 1000) return `${ms} ms`\r\n\r\n const seconds = ms / 1000\r\n if (seconds < 60) return seconds === 1 ? '1 sec' : `${seconds} sec`\r\n\r\n const minutes = seconds / 60\r\n if (minutes < 60) return minutes === 1 ? '1 min' : `${Math.floor(minutes)} min`\r\n\r\n const hours = minutes / 60\r\n if (hours < 24) return hours === 1 ? '1 hr' : `${Math.floor(hours)} hr`\r\n\r\n const days = hours / 24\r\n return days === 1 ? '1 day' : `${Math.floor(days)} days`\r\n}\r\n\r\n/**\r\n * Time frequency units for duration inputs\r\n * Value is the multiplier to convert to milliseconds\r\n */\r\nexport const frequencyUnits = [\r\n { value: 1, label: 'Milliseconds' },\r\n { value: 1000, label: 'Seconds' },\r\n { value: 60000, label: 'Minutes' },\r\n { value: 3600000, label: 'Hours' },\r\n] as const\r\n\r\n/** Browser IANA zone, e.g. \"America/Toronto\". Falls back to \"UTC\" if unavailable. */\r\nexport function detectTimeZone(): string {\r\n try {\r\n return Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC'\r\n } catch {\r\n return 'UTC'\r\n }\r\n}\r\n\r\n/**\r\n * Longitude -> nearest whole-hour offset -> an Etc/GMT±N id. Note POSIX sign inversion:\r\n * a positive (east) offset is Etc/GMT-N. This is a rough approximation: no DST, no\r\n * political borders. 0 -> \"UTC\".\r\n */\r\nexport function offsetZoneFromLongitude(longitude: number): string {\r\n if (!Number.isFinite(longitude)) return 'UTC'\r\n let h = Math.round(longitude / 15)\r\n h = Math.max(-12, Math.min(12, h))\r\n if (h === 0) return 'UTC'\r\n return `Etc/GMT${h > 0 ? '-' : '+'}${Math.abs(h)}`\r\n}\r\n\r\n/**\r\n * Default display zone. Prefers the browser's IANA zone: it is DST-correct and, for a user\r\n * in the sensor's region, already the right local zone. Only when detection is unavailable\r\n * (returns \"UTC\") does it fall back to a longitude-derived fixed offset, trying each\r\n * candidate longitude in order. Callers pass candidates in priority order: BIM sensors sit\r\n * in a building (building longitude first), map sensors carry their own coordinates (sensor\r\n * longitude first).\r\n */\r\nexport function resolveDefaultTimeZone(longitudeCandidates: Array<number | null | undefined>): string {\r\n const detected = detectTimeZone()\r\n if (detected && detected !== 'UTC') return detected\r\n for (const lng of longitudeCandidates) {\r\n if (typeof lng === 'number' && Number.isFinite(lng)) return offsetZoneFromLongitude(lng)\r\n }\r\n return detected || 'UTC'\r\n}\r\n\r\n/** Format an epoch in a specific zone. Handles Etc/GMT±N and true IANA zones alike. */\r\nexport function formatInZone(\r\n epochMs: number,\r\n timeZone: string,\r\n opts?: Intl.DateTimeFormatOptions,\r\n): string {\r\n try {\r\n return new Intl.DateTimeFormat(undefined, { timeZone, ...opts }).format(epochMs)\r\n } catch {\r\n return new Intl.DateTimeFormat(undefined, opts).format(epochMs)\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@collabdt/core",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "CDT Core contains all the core technology for your CDT platform",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -180,6 +180,9 @@
180
180
  "eslint-formatter-summary": "^2.0.2",
181
181
  "eslint-import-resolver-typescript": "^3.10.1",
182
182
  "eslint-plugin-import": "^2.32.0",
183
+ "eslint-plugin-jsx-a11y": "^6.10.2",
184
+ "eslint-plugin-react": "^7.37.5",
185
+ "eslint-plugin-react-hooks": "^5.2.0",
183
186
  "eslint-plugin-sonarjs": "^3.0.4",
184
187
  "eslint-plugin-unicorn": "^60.0.0",
185
188
  "framer-motion": "^12.23.24",