@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.
- package/dist/core/components/authentication/ForgotPassword.d.ts.map +1 -1
- package/dist/core/components/authentication/ForgotPassword.js +0 -1
- package/dist/core/components/authentication/ForgotPassword.js.map +1 -1
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.d.ts +12 -2
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.js +137 -139
- package/dist/core/components/ui/Comments/CollapsibleCommentItem.js.map +1 -1
- package/dist/core/components/ui/Comments/Comment.d.ts +18 -1
- package/dist/core/components/ui/Comments/Comment.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/Comment.js +94 -23
- package/dist/core/components/ui/Comments/Comment.js.map +1 -1
- package/dist/core/components/ui/Comments/CommentActionButtons.d.ts +38 -0
- package/dist/core/components/ui/Comments/CommentActionButtons.d.ts.map +1 -0
- package/dist/core/components/ui/Comments/CommentActionButtons.js +134 -0
- package/dist/core/components/ui/Comments/CommentActionButtons.js.map +1 -0
- package/dist/core/components/ui/Comments/CommentInput.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CommentInput.js +5 -2
- package/dist/core/components/ui/Comments/CommentInput.js.map +1 -1
- package/dist/core/components/ui/Comments/CommentsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/CommentsSection.js +86 -42
- package/dist/core/components/ui/Comments/CommentsSection.js.map +1 -1
- package/dist/core/components/ui/Comments/commentUtils.d.ts.map +1 -1
- package/dist/core/components/ui/Comments/commentUtils.js +2 -1
- package/dist/core/components/ui/Comments/commentUtils.js.map +1 -1
- package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.d.ts.map +1 -1
- package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.js +0 -1
- package/dist/core/components/ui/FilesManager/src/useFileUploadWithProgress.js.map +1 -1
- package/dist/core/components/ui/InfoSidebar/Container.d.ts.map +1 -1
- package/dist/core/components/ui/InfoSidebar/Container.js +16 -12
- package/dist/core/components/ui/InfoSidebar/Container.js.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts +1 -2
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js +66 -94
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
- package/dist/core/components/ui/Sensors/Sensor.d.ts +16 -3
- package/dist/core/components/ui/Sensors/Sensor.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/Sensor.js +76 -37
- package/dist/core/components/ui/Sensors/Sensor.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorChart.d.ts +12 -2
- package/dist/core/components/ui/Sensors/SensorChart.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorChart.js +49 -12
- package/dist/core/components/ui/Sensors/SensorChart.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorDetailDialog.d.ts +9 -0
- package/dist/core/components/ui/Sensors/SensorDetailDialog.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/SensorDetailDialog.js +128 -0
- package/dist/core/components/ui/Sensors/SensorDetailDialog.js.map +1 -0
- package/dist/core/components/ui/Sensors/SensorInput.d.ts +6 -1
- package/dist/core/components/ui/Sensors/SensorInput.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorInput.js +94 -9
- package/dist/core/components/ui/Sensors/SensorInput.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.d.ts +3 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.js +4 -1
- package/dist/core/components/ui/Sensors/SensorTagsSection.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.d.ts +1 -3
- package/dist/core/components/ui/Sensors/SensorsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.js +33 -10
- package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
- package/dist/core/components/ui/Sensors/TimeZoneSelect.d.ts +7 -0
- package/dist/core/components/ui/Sensors/TimeZoneSelect.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/TimeZoneSelect.js +56 -0
- package/dist/core/components/ui/Sensors/TimeZoneSelect.js.map +1 -0
- package/dist/core/components/ui/Sensors/sensorData.d.ts +42 -0
- package/dist/core/components/ui/Sensors/sensorData.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/sensorData.js +118 -0
- package/dist/core/components/ui/Sensors/sensorData.js.map +1 -0
- package/dist/core/components/ui/Sensors/sensorRange.d.ts +24 -0
- package/dist/core/components/ui/Sensors/sensorRange.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/sensorRange.js +34 -0
- package/dist/core/components/ui/Sensors/sensorRange.js.map +1 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.d.ts +15 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.d.ts.map +1 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.js +63 -0
- package/dist/core/components/ui/Sensors/useSensorSeries.js.map +1 -0
- package/dist/core/components/ui/Sidebar.d.ts.map +1 -1
- package/dist/core/components/ui/Sidebar.js +27 -4
- package/dist/core/components/ui/Sidebar.js.map +1 -1
- package/dist/core/components/ui/ToolbarButton.d.ts.map +1 -1
- package/dist/core/components/ui/ToolbarButton.js +0 -1
- package/dist/core/components/ui/ToolbarButton.js.map +1 -1
- package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.js +0 -2
- package/dist/core/components/viewers/Data/advancedFilter/FiltersDialog.js.map +1 -1
- package/dist/core/components/viewers/Data/details/EnergySourcesGrid.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/details/EnergySourcesGrid.js +0 -10
- package/dist/core/components/viewers/Data/details/EnergySourcesGrid.js.map +1 -1
- package/dist/core/components/viewers/Data/files/DatatableFileAdder.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/files/DatatableFileAdder.js +0 -1
- package/dist/core/components/viewers/Data/files/DatatableFileAdder.js.map +1 -1
- package/dist/core/components/viewers/Data/files/utils/fuzzySearch.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/files/utils/fuzzySearch.js +0 -1
- package/dist/core/components/viewers/Data/files/utils/fuzzySearch.js.map +1 -1
- package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.js +0 -1
- package/dist/core/components/viewers/Data/userDetails/UserMoreOptions.js.map +1 -1
- package/dist/core/components/viewers/Data/utils/filterHelper.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/utils/filterHelper.js +0 -2
- package/dist/core/components/viewers/Data/utils/filterHelper.js.map +1 -1
- package/dist/core/components/viewers/Viewer.js +1 -1
- package/dist/core/components/viewers/Viewer.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.js +0 -3
- package/dist/core/components/viewers/bim/src/BimSidebar/src/CommunicationTab/src/TopicsSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js +1 -7
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js +1 -9
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts +1 -3
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js +2 -2
- package/dist/core/components/viewers/bim/src/BimSidebar/src/SensorsTab/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.js +4 -3
- package/dist/core/components/viewers/bim/src/BimSidebar/src/TabSelector.js.map +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js +1 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/ClippingPlane.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/ClippingPlane.js +0 -1
- package/dist/core/components/viewers/bim/src/ClippingPlane.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts +1 -2
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js +25 -2
- package/dist/core/components/viewers/bim/src/tools/AddToBim/index.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.d.ts +16 -10
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.js +26 -6
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimComment.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts +2 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.d.ts.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js +5 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimCommentCluster.js.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.d.ts +8 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js +15 -3
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/BimSensor.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.d.ts +44 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.d.ts.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.js +77 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace.js.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts +3 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.d.ts.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js +5 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentCameraUtils.js.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.d.ts +33 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.d.ts.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.js +90 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/commentMarkerConfig.js.map +1 -0
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.js +2 -2
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/renderCSS2DMarkers.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.d.ts +7 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js +50 -73
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useCommentMarkers.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts +7 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js +39 -11
- package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.js +1 -5
- package/dist/core/components/viewers/bim/src/tools/ClippingTool/ClippingTool.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.js +0 -1
- package/dist/core/components/viewers/bim/src/tools/ExplodeByLevelTool.js.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/measureBimTool.d.ts.map +1 -1
- package/dist/core/components/viewers/bim/src/tools/measureBimTool.js +1 -2
- package/dist/core/components/viewers/bim/src/tools/measureBimTool.js.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.d.ts +1 -2
- package/dist/core/components/viewers/map/MapViewer.d.ts.map +1 -1
- package/dist/core/components/viewers/map/MapViewer.js +2 -2
- package/dist/core/components/viewers/map/MapViewer.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.js +11 -14
- package/dist/core/components/viewers/map/datasets/src/arcGISDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/ckanDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/ckanDatasets.js +2 -5
- package/dist/core/components/viewers/map/datasets/src/ckanDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/localDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/localDatasets.js +0 -3
- package/dist/core/components/viewers/map/datasets/src/localDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.js +0 -11
- package/dist/core/components/viewers/map/datasets/src/opendatasoftDatasets.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.js +0 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/DatabaseBuildingPopover/src/BuildingsTools.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js +0 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/NonDatabaseBuildingPopover.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.js +0 -1
- package/dist/core/components/viewers/map/src/MapFeaturePopoverMenu/src/OpenDataFeaturePopover.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.d.ts +1 -2
- package/dist/core/components/viewers/map/src/MapLayers/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/index.js +2 -2
- package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.js +174 -53
- package/dist/core/components/viewers/map/src/MapLayers/src/CommentLayer/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.js +2 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/FileLayer/components/MapFileManager.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts +1 -3
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js +74 -42
- package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.js +4 -3
- package/dist/core/components/viewers/map/src/MapSidebar/TabSelector.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/index.js +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js +0 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/FilesSection.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js +1 -5
- package/dist/core/components/viewers/map/src/MapSidebar/src/FileTab/src/ModelsSection.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts +1 -3
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js +2 -2
- package/dist/core/components/viewers/map/src/MapSidebar/src/SensorsTab/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.js +1 -3
- package/dist/core/components/viewers/map/src/tools/AddTools/AddFile/utils/uploadToPresignedURLS.js.map +1 -1
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.d.ts.map +1 -1
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js +0 -1
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js.map +1 -1
- package/dist/core/components/viewers/map/utils/flyToEach.d.ts.map +1 -1
- package/dist/core/components/viewers/map/utils/flyToEach.js +0 -1
- package/dist/core/components/viewers/map/utils/flyToEach.js.map +1 -1
- package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.d.ts.map +1 -1
- package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.js +0 -2
- package/dist/core/components/viewers/map/utils/getOsmIdbyCoordinates.js.map +1 -1
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.d.ts +19 -0
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.js +108 -0
- package/dist/core/components/viewers/shared/markers/BimMarkerCluster.js.map +1 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.d.ts +24 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.js +27 -0
- package/dist/core/components/viewers/shared/markers/computeMarkerLookAt.js.map +1 -0
- package/dist/core/components/viewers/shared/markers/types.d.ts +66 -0
- package/dist/core/components/viewers/shared/markers/types.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/types.js +1 -0
- package/dist/core/components/viewers/shared/markers/types.js.map +1 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.d.ts +22 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.d.ts.map +1 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.js +233 -0
- package/dist/core/components/viewers/shared/markers/useMarkerLayerBim.js.map +1 -0
- package/dist/core/hooks/comments/comments.d.ts +11 -0
- package/dist/core/hooks/comments/comments.d.ts.map +1 -1
- package/dist/core/hooks/comments/comments.js +3 -1
- package/dist/core/hooks/comments/comments.js.map +1 -1
- package/dist/core/hooks/comments/createCommentHooks.d.ts +11 -0
- package/dist/core/hooks/comments/createCommentHooks.d.ts.map +1 -1
- package/dist/core/hooks/comments/createCommentHooks.js +30 -1
- package/dist/core/hooks/comments/createCommentHooks.js.map +1 -1
- package/dist/core/hooks/files/files.d.ts.map +1 -1
- package/dist/core/hooks/files/files.js +0 -1
- package/dist/core/hooks/files/files.js.map +1 -1
- package/dist/core/hooks/ui/useResizableSidebarWidth.d.ts +30 -0
- package/dist/core/hooks/ui/useResizableSidebarWidth.d.ts.map +1 -0
- package/dist/core/hooks/ui/useResizableSidebarWidth.js +75 -0
- package/dist/core/hooks/ui/useResizableSidebarWidth.js.map +1 -0
- package/dist/core/i18n/messages/en.json +10 -1
- package/dist/core/i18n/messages/es.json +11 -2
- package/dist/core/i18n/messages/fr.json +11 -2
- package/dist/core/store/AppConfig/context.d.ts.map +1 -1
- package/dist/core/store/AppConfig/context.js +4 -1
- package/dist/core/store/AppConfig/context.js.map +1 -1
- package/dist/core/store/AppConfig/reducer.d.ts +10 -0
- package/dist/core/store/AppConfig/reducer.d.ts.map +1 -1
- package/dist/core/store/AppConfig/reducer.js +10 -0
- package/dist/core/store/AppConfig/reducer.js.map +1 -1
- package/dist/core/store/Datasets/reducer.d.ts.map +1 -1
- package/dist/core/store/Datasets/reducer.js +0 -2
- package/dist/core/store/Datasets/reducer.js.map +1 -1
- package/dist/core/store/Files/reducer.js +0 -1
- package/dist/core/store/Files/reducer.js.map +1 -1
- package/dist/core/store/Menus/context.d.ts.map +1 -1
- package/dist/core/store/Menus/context.js +8 -2
- package/dist/core/store/Menus/context.js.map +1 -1
- package/dist/core/store/Menus/reducer.d.ts +65 -1
- package/dist/core/store/Menus/reducer.d.ts.map +1 -1
- package/dist/core/store/Menus/reducer.js +39 -3
- package/dist/core/store/Menus/reducer.js.map +1 -1
- package/dist/core/utils/markerUtils.d.ts +10 -0
- package/dist/core/utils/markerUtils.d.ts.map +1 -1
- package/dist/core/utils/markerUtils.js +9 -1
- package/dist/core/utils/markerUtils.js.map +1 -1
- package/dist/core/utils/memcache.d.ts.map +1 -1
- package/dist/core/utils/memcache.js +0 -7
- package/dist/core/utils/memcache.js.map +1 -1
- package/dist/core/utils/timeUtils.d.ts +24 -1
- package/dist/core/utils/timeUtils.d.ts.map +1 -1
- package/dist/core/utils/timeUtils.js +52 -3
- package/dist/core/utils/timeUtils.js.map +1 -1
- package/package.json +4 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
/** Bridges the framework to the parallel per-entity fields in the Menus store. */
|
|
3
|
+
export interface MarkerStoreAdapter {
|
|
4
|
+
currentId: number | null;
|
|
5
|
+
focusedId: number | null;
|
|
6
|
+
focusRequestId: number;
|
|
7
|
+
setCurrentId: (id: number | null) => void;
|
|
8
|
+
setFocusedId: (id: number | null) => void;
|
|
9
|
+
/** Opens the sidebar editor for this marker (dispatches REQUEST_*_ACTION). */
|
|
10
|
+
requestEdit: (id: number) => void;
|
|
11
|
+
}
|
|
12
|
+
/** One member inside a BIM cluster bubble. */
|
|
13
|
+
export interface ClusterMember {
|
|
14
|
+
id: number;
|
|
15
|
+
userName?: string;
|
|
16
|
+
imageFileId?: number | null;
|
|
17
|
+
}
|
|
18
|
+
/** An item positioned in the BIM scene. Must carry world coords + id. */
|
|
19
|
+
export interface BimMarkerItem {
|
|
20
|
+
id: number;
|
|
21
|
+
x: number;
|
|
22
|
+
y: number;
|
|
23
|
+
z: number;
|
|
24
|
+
isPending?: boolean;
|
|
25
|
+
}
|
|
26
|
+
/** Everything entity-specific the generic BIM marker hook needs. */
|
|
27
|
+
export interface BimMarkerConfig<T extends BimMarkerItem> {
|
|
28
|
+
markerIdKey: "commentId" | "sensorId";
|
|
29
|
+
sphereColor: string;
|
|
30
|
+
/** Camera pull-back distance for double-click focus. */
|
|
31
|
+
focusDistance?: number;
|
|
32
|
+
/** The CSS2D card component for a single marker. */
|
|
33
|
+
component: React.ComponentType<Record<string, unknown>>;
|
|
34
|
+
/** The cluster-bubble component. */
|
|
35
|
+
clusterComponent: React.ComponentType<{
|
|
36
|
+
members: ClusterMember[];
|
|
37
|
+
highlight: boolean;
|
|
38
|
+
onSelect: (id: number) => void;
|
|
39
|
+
onFocus: (id: number) => void;
|
|
40
|
+
}>;
|
|
41
|
+
/** Builds the card props for one item (highlight/focused/handlers injected by the hook). */
|
|
42
|
+
propsMapper: (item: T, ctx: {
|
|
43
|
+
highlight: boolean;
|
|
44
|
+
focused: boolean;
|
|
45
|
+
isAuthor: boolean;
|
|
46
|
+
onSelect: () => void;
|
|
47
|
+
onFocus: () => void;
|
|
48
|
+
onEdit?: () => void;
|
|
49
|
+
onRemove?: () => void;
|
|
50
|
+
}) => Record<string, unknown>;
|
|
51
|
+
/** Maps an item to its cluster-member representation. */
|
|
52
|
+
clusterMemberMapper: (item: T) => ClusterMember;
|
|
53
|
+
/** Per-item string folded into the re-render signature (e.g. text/name + pending flag). */
|
|
54
|
+
dataHashPart: (item: T) => string;
|
|
55
|
+
/** True if the current user may edit/delete this item (author check). */
|
|
56
|
+
isAuthor: (item: T) => boolean;
|
|
57
|
+
/** Delete handler (comment cascade vs sensor single-delete differ). */
|
|
58
|
+
onRemove: (id: number) => void;
|
|
59
|
+
/** Builds a placeholder item for a pending (being-created) marker. */
|
|
60
|
+
makePendingItem: (id: number, pos: {
|
|
61
|
+
x: number;
|
|
62
|
+
y: number;
|
|
63
|
+
z: number;
|
|
64
|
+
}) => T;
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/shared/markers/types.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAA;AAEnC,kFAAkF;AAClF,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IACzC,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IACzC,8EAA8E;IAC9E,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC;AAED,8CAA8C;AAC9C,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC5B;AAED,yEAAyE;AACzE,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,oEAAoE;AACpE,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,aAAa;IACtD,WAAW,EAAE,WAAW,GAAG,UAAU,CAAA;IACrC,WAAW,EAAE,MAAM,CAAA;IACnB,wDAAwD;IACxD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,oDAAoD;IACpD,SAAS,EAAE,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IACvD,oCAAoC;IACpC,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC;QACpC,OAAO,EAAE,aAAa,EAAE,CAAA;QACxB,SAAS,EAAE,OAAO,CAAA;QAClB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;QAC9B,OAAO,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;KAC9B,CAAC,CAAA;IACF,4FAA4F;IAC5F,WAAW,EAAE,CACX,IAAI,EAAE,CAAC,EACP,GAAG,EAAE;QAAE,SAAS,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAC7D,QAAQ,EAAE,MAAM,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,IAAI,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;KAAE,KACtF,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC5B,yDAAyD;IACzD,mBAAmB,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,aAAa,CAAA;IAC/C,2FAA2F;IAC3F,YAAY,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,MAAM,CAAA;IACjC,yEAAyE;IACzE,QAAQ,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,OAAO,CAAA;IAC9B,uEAAuE;IACvE,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IAC9B,sEAAsE;IACtE,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,CAAC,CAAA;CAC7E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type HooksBag } from "../../../../hooks/provider";
|
|
2
|
+
import type { BimMarkerConfig, BimMarkerItem, MarkerStoreAdapter } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* Generic BIM marker layer. Renders `items` as clustered CSS2D markers over a `three` world,
|
|
5
|
+
* driving selection/focus/edit/remove through a `MarkerStoreAdapter` and shaping every
|
|
6
|
+
* entity-specific detail through `config`. Behaviour is a straight generalization of the
|
|
7
|
+
* comment marker layer (screen-space clustering, rAF diffing, double-click focus).
|
|
8
|
+
*/
|
|
9
|
+
export declare function useMarkerLayerBim<T extends BimMarkerItem>(world: any, items: T[], opts: {
|
|
10
|
+
isVisible: boolean;
|
|
11
|
+
store: MarkerStoreAdapter;
|
|
12
|
+
coreHooks: HooksBag | null;
|
|
13
|
+
config: BimMarkerConfig<T>;
|
|
14
|
+
}): {
|
|
15
|
+
addPending: (pos: {
|
|
16
|
+
x: number;
|
|
17
|
+
y: number;
|
|
18
|
+
z: number;
|
|
19
|
+
}) => number;
|
|
20
|
+
removePending: (id: number) => void;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=useMarkerLayerBim.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useMarkerLayerBim.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/viewers/shared/markers/useMarkerLayerBim.ts"],"names":[],"mappings":"AAUA,OAAO,EAAY,KAAK,QAAQ,EAAE,MAAM,4BAA4B,CAAA;AAKpE,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA;AAyLjF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,aAAa,EACvD,KAAK,EAAE,GAAG,EACV,KAAK,EAAE,CAAC,EAAE,EACV,IAAI,EAAE;IACJ,SAAS,EAAE,OAAO,CAAA;IAClB,KAAK,EAAE,kBAAkB,CAAA;IACzB,SAAS,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC1B,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,CAAA;CAC3B,GACA;IAAE,UAAU,EAAE,CAAC,GAAG,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,KAAK,MAAM,CAAC;IAAC,aAAa,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;CAAE,CAiG3G"}
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __defProps = Object.defineProperties;
|
|
4
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
+
var __spreadValues = (a, b) => {
|
|
10
|
+
for (var prop in b || (b = {}))
|
|
11
|
+
if (__hasOwnProp.call(b, prop))
|
|
12
|
+
__defNormalProp(a, prop, b[prop]);
|
|
13
|
+
if (__getOwnPropSymbols)
|
|
14
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
+
if (__propIsEnum.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
}
|
|
18
|
+
return a;
|
|
19
|
+
};
|
|
20
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
|
+
import * as React from "react";
|
|
22
|
+
import { createRoot } from "react-dom/client";
|
|
23
|
+
import * as THREE from "three";
|
|
24
|
+
import { CSS2DObject } from "three/addons/renderers/CSS2DRenderer.js";
|
|
25
|
+
import { HooksCtx } from "../../../../hooks/provider";
|
|
26
|
+
import { clusterMarkersByScreenSpace } from "../../bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace";
|
|
27
|
+
import { renderCSS2DMarkers } from "../../bim/src/tools/AddToBim/src/renderCSS2DMarkers";
|
|
28
|
+
import { computeMarkerLookAt } from "./computeMarkerLookAt";
|
|
29
|
+
function makePropsMapper(state) {
|
|
30
|
+
const { config, currentId, focusedId, onSelect, onFocus, onEdit, onRemove } = state;
|
|
31
|
+
return (item) => {
|
|
32
|
+
const highlight = currentId === item.id;
|
|
33
|
+
const focused = focusedId === item.id;
|
|
34
|
+
if (item.isPending) {
|
|
35
|
+
return config.propsMapper(item, {
|
|
36
|
+
highlight,
|
|
37
|
+
focused,
|
|
38
|
+
isAuthor: false,
|
|
39
|
+
onSelect: () => onSelect(item.id),
|
|
40
|
+
onFocus: () => onFocus(item.id)
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return config.propsMapper(item, {
|
|
44
|
+
highlight,
|
|
45
|
+
focused,
|
|
46
|
+
isAuthor: config.isAuthor(item),
|
|
47
|
+
onSelect: () => onSelect(item.id),
|
|
48
|
+
onFocus: () => onFocus(item.id),
|
|
49
|
+
onEdit: () => onEdit(item.id),
|
|
50
|
+
onRemove: () => onRemove(item.id)
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function clearSingles(world, registry, config) {
|
|
55
|
+
renderCSS2DMarkers(world, {
|
|
56
|
+
items: [],
|
|
57
|
+
markerIdKey: config.markerIdKey,
|
|
58
|
+
registry,
|
|
59
|
+
component: config.component,
|
|
60
|
+
propsMapper: () => ({}),
|
|
61
|
+
sphereColor: config.sphereColor,
|
|
62
|
+
isVisible: false,
|
|
63
|
+
onRemove: () => {
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
function clearClusters(world, registry) {
|
|
68
|
+
registry.current.forEach(({ root, css2dObject }) => {
|
|
69
|
+
world.scene.three.remove(css2dObject);
|
|
70
|
+
const el = css2dObject.element;
|
|
71
|
+
el == null ? void 0 : el.remove();
|
|
72
|
+
root.unmount();
|
|
73
|
+
});
|
|
74
|
+
registry.current.clear();
|
|
75
|
+
}
|
|
76
|
+
function renderMarkers(state, singleRegistry, clusterRegistry, lastSignatureRef) {
|
|
77
|
+
var _a, _b, _c;
|
|
78
|
+
const { world, items, pending, isVisible, currentId, focusedId, coreHooks, config, onRemove, onSelect, onFocus } = state;
|
|
79
|
+
if (!world) return;
|
|
80
|
+
if (!isVisible) {
|
|
81
|
+
if (lastSignatureRef.current === "hidden") return;
|
|
82
|
+
clearSingles(world, singleRegistry, config);
|
|
83
|
+
clearClusters(world, clusterRegistry);
|
|
84
|
+
lastSignatureRef.current = "hidden";
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const camera = (_a = world.camera) == null ? void 0 : _a.three;
|
|
88
|
+
const dom = (_c = (_b = world.renderer) == null ? void 0 : _b.three) == null ? void 0 : _c.domElement;
|
|
89
|
+
if (!camera || !dom) return;
|
|
90
|
+
const width = dom.clientWidth || dom.width || 0;
|
|
91
|
+
const height = dom.clientHeight || dom.height || 0;
|
|
92
|
+
if (!width || !height) return;
|
|
93
|
+
const { clusters, singles } = clusterMarkersByScreenSpace(items, camera, width, height, 44);
|
|
94
|
+
const singleItems = [...singles, ...pending];
|
|
95
|
+
const clusterKeys = clusters.map((c) => c.key);
|
|
96
|
+
const dataHash = [...items, ...pending].map((c) => config.dataHashPart(c)).join(";");
|
|
97
|
+
const signature = `v2|${currentId}|${focusedId}|C:${clusterKeys.join(",")}|S:${singleItems.map((s) => s.id).join(",")}|D:${dataHash}`;
|
|
98
|
+
if (signature === lastSignatureRef.current) return;
|
|
99
|
+
lastSignatureRef.current = signature;
|
|
100
|
+
renderCSS2DMarkers(world, {
|
|
101
|
+
items: singleItems,
|
|
102
|
+
markerIdKey: config.markerIdKey,
|
|
103
|
+
registry: singleRegistry,
|
|
104
|
+
component: config.component,
|
|
105
|
+
hooksContextValue: coreHooks,
|
|
106
|
+
propsMapper: makePropsMapper(state),
|
|
107
|
+
sphereColor: config.sphereColor,
|
|
108
|
+
isVisible: true,
|
|
109
|
+
onRemove
|
|
110
|
+
});
|
|
111
|
+
singleRegistry.current.forEach((ref, id) => {
|
|
112
|
+
const nid = Number(id);
|
|
113
|
+
ref.css2dObject.renderOrder = nid === currentId || nid === focusedId ? 1 : 0;
|
|
114
|
+
});
|
|
115
|
+
const reg = clusterRegistry.current;
|
|
116
|
+
const wanted = new Set(clusterKeys);
|
|
117
|
+
for (const [key, ref] of reg) {
|
|
118
|
+
if (!wanted.has(key)) {
|
|
119
|
+
world.scene.three.remove(ref.css2dObject);
|
|
120
|
+
const el = ref.css2dObject.element;
|
|
121
|
+
el == null ? void 0 : el.remove();
|
|
122
|
+
ref.root.unmount();
|
|
123
|
+
reg.delete(key);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
for (const cluster of clusters) {
|
|
127
|
+
const members = cluster.members.map((m) => config.clusterMemberMapper(m));
|
|
128
|
+
const highlight = currentId != null && members.some((m) => m.id === currentId);
|
|
129
|
+
const element = React.createElement(config.clusterComponent, { members, highlight, onSelect, onFocus });
|
|
130
|
+
const wrapped = coreHooks ? React.createElement(HooksCtx.Provider, { value: coreHooks }, element) : element;
|
|
131
|
+
const existing = reg.get(cluster.key);
|
|
132
|
+
if (existing) {
|
|
133
|
+
existing.root.render(wrapped);
|
|
134
|
+
existing.css2dObject.position.set(cluster.worldCenter.x, cluster.worldCenter.y + 0.2, cluster.worldCenter.z);
|
|
135
|
+
existing.css2dObject.renderOrder = highlight ? 1 : 0;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const labelDiv = document.createElement("div");
|
|
139
|
+
labelDiv.style.pointerEvents = "auto";
|
|
140
|
+
const root = createRoot(labelDiv);
|
|
141
|
+
root.render(wrapped);
|
|
142
|
+
const css2dObject = new CSS2DObject(labelDiv);
|
|
143
|
+
css2dObject.position.set(cluster.worldCenter.x, cluster.worldCenter.y + 0.2, cluster.worldCenter.z);
|
|
144
|
+
css2dObject.element.style.pointerEvents = "auto";
|
|
145
|
+
css2dObject.renderOrder = highlight ? 1 : 0;
|
|
146
|
+
world.scene.three.add(css2dObject);
|
|
147
|
+
reg.set(cluster.key, { root, css2dObject });
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
function useMarkerLayerBim(world, items, opts) {
|
|
151
|
+
const { isVisible, store, coreHooks, config } = opts;
|
|
152
|
+
const singleRegistry = React.useRef(/* @__PURE__ */ new Map());
|
|
153
|
+
const clusterRegistry = React.useRef(/* @__PURE__ */ new Map());
|
|
154
|
+
const lastSignatureRef = React.useRef("");
|
|
155
|
+
const stateRef = React.useRef(null);
|
|
156
|
+
const itemsRef = React.useRef([]);
|
|
157
|
+
itemsRef.current = items;
|
|
158
|
+
const handleSelect = React.useCallback((id) => {
|
|
159
|
+
store.setCurrentId(id);
|
|
160
|
+
}, [store]);
|
|
161
|
+
const handleFocus = React.useCallback((id) => {
|
|
162
|
+
store.setCurrentId(id);
|
|
163
|
+
store.setFocusedId(id);
|
|
164
|
+
}, [store]);
|
|
165
|
+
const handleEdit = React.useCallback((id) => {
|
|
166
|
+
store.requestEdit(id);
|
|
167
|
+
}, [store]);
|
|
168
|
+
const [pending, setPending] = React.useState([]);
|
|
169
|
+
const addPending = React.useCallback((position) => {
|
|
170
|
+
const id = -Date.now();
|
|
171
|
+
setPending((prev) => [...prev, __spreadValues({ id }, position)]);
|
|
172
|
+
return id;
|
|
173
|
+
}, []);
|
|
174
|
+
const removePending = React.useCallback((id) => {
|
|
175
|
+
setPending((prev) => prev.filter((p) => p.id !== id));
|
|
176
|
+
}, []);
|
|
177
|
+
stateRef.current = {
|
|
178
|
+
world,
|
|
179
|
+
// Non-pending items carry an explicit isPending:false (parity with the pending placeholders).
|
|
180
|
+
// Cast: spreading a generic T and assigning back to T[] is not provably safe to tsc.
|
|
181
|
+
items: items.map((it) => __spreadProps(__spreadValues({}, it), { isPending: false })),
|
|
182
|
+
pending: pending.map((p) => config.makePendingItem(p.id, { x: p.x, y: p.y, z: p.z })),
|
|
183
|
+
isVisible,
|
|
184
|
+
currentId: store.currentId,
|
|
185
|
+
focusedId: store.focusedId,
|
|
186
|
+
coreHooks,
|
|
187
|
+
config,
|
|
188
|
+
onRemove: config.onRemove,
|
|
189
|
+
onSelect: handleSelect,
|
|
190
|
+
onFocus: handleFocus,
|
|
191
|
+
onEdit: handleEdit
|
|
192
|
+
};
|
|
193
|
+
React.useEffect(() => {
|
|
194
|
+
if (!world) return;
|
|
195
|
+
let raf = 0;
|
|
196
|
+
let frame = 0;
|
|
197
|
+
const loop = () => {
|
|
198
|
+
if ((frame++ & 1) === 0 && stateRef.current) {
|
|
199
|
+
renderMarkers(stateRef.current, singleRegistry, clusterRegistry, lastSignatureRef);
|
|
200
|
+
}
|
|
201
|
+
raf = requestAnimationFrame(loop);
|
|
202
|
+
};
|
|
203
|
+
raf = requestAnimationFrame(loop);
|
|
204
|
+
return () => {
|
|
205
|
+
cancelAnimationFrame(raf);
|
|
206
|
+
clearClusters(world, clusterRegistry);
|
|
207
|
+
clearSingles(world, singleRegistry, config);
|
|
208
|
+
lastSignatureRef.current = "";
|
|
209
|
+
};
|
|
210
|
+
}, [world]);
|
|
211
|
+
React.useEffect(() => {
|
|
212
|
+
var _a, _b;
|
|
213
|
+
if (store.focusedId == null || !world) return;
|
|
214
|
+
const target = itemsRef.current.find((it) => it.id === store.focusedId);
|
|
215
|
+
if (!target || target.x == null || target.y == null || target.z == null) return;
|
|
216
|
+
const controls = (_a = world.camera) == null ? void 0 : _a.controls;
|
|
217
|
+
if (!controls) return;
|
|
218
|
+
const camPos = controls.getPosition(new THREE.Vector3());
|
|
219
|
+
const camTarget = controls.getTarget(new THREE.Vector3());
|
|
220
|
+
const lookAt = computeMarkerLookAt(
|
|
221
|
+
{ x: camPos.x, y: camPos.y, z: camPos.z },
|
|
222
|
+
{ x: camTarget.x, y: camTarget.y, z: camTarget.z },
|
|
223
|
+
{ x: target.x, y: target.y, z: target.z },
|
|
224
|
+
(_b = config.focusDistance) != null ? _b : 8
|
|
225
|
+
);
|
|
226
|
+
void controls.setLookAt(lookAt.camX, lookAt.camY, lookAt.camZ, lookAt.tarX, lookAt.tarY, lookAt.tarZ, true);
|
|
227
|
+
}, [store.focusRequestId, world]);
|
|
228
|
+
return { addPending, removePending };
|
|
229
|
+
}
|
|
230
|
+
export {
|
|
231
|
+
useMarkerLayerBim
|
|
232
|
+
};
|
|
233
|
+
//# sourceMappingURL=useMarkerLayerBim.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../../../src/core/components/viewers/shared/markers/useMarkerLayerBim.ts"],"sourcesContent":["\"use client\"\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from \"react\"\r\nimport { createRoot } from \"react-dom/client\"\r\nimport * as THREE from \"three\"\r\nimport { CSS2DObject } from \"three/addons/renderers/CSS2DRenderer.js\"\r\n\r\nimport { HooksCtx, type HooksBag } from \"../../../../hooks/provider\"\r\nimport { clusterMarkersByScreenSpace } from \"../../bim/src/tools/AddToBim/src/clusterMarkersByScreenSpace\"\r\nimport { renderCSS2DMarkers, type MarkerRef } from \"../../bim/src/tools/AddToBim/src/renderCSS2DMarkers\"\r\n\r\nimport { computeMarkerLookAt } from \"./computeMarkerLookAt\"\r\nimport type { BimMarkerConfig, BimMarkerItem, MarkerStoreAdapter } from \"./types\"\r\n\r\ntype ClusterMarkerRef = { root: ReturnType<typeof createRoot>; css2dObject: CSS2DObject }\r\n\r\ninterface RenderState<T extends BimMarkerItem> {\r\n world: any\r\n /** Non-pending items eligible for clustering. */\r\n items: T[]\r\n /** Pending (being-created) markers — always rendered as singles. */\r\n pending: T[]\r\n isVisible: boolean\r\n currentId: number | null\r\n focusedId: number | null\r\n coreHooks: HooksBag | null\r\n config: BimMarkerConfig<T>\r\n onRemove: (id: number) => void\r\n onSelect: (id: number) => void\r\n onFocus: (id: number) => void\r\n onEdit: (id: number) => void\r\n}\r\n\r\n/**\r\n * Builds the per-item props for the card component, delegating entity-specific shaping to\r\n * `config.propsMapper`. Pending (being-created) items get a reduced context: `isAuthor:false`\r\n * and no author-gated (edit/remove) handlers.\r\n */\r\nfunction makePropsMapper<T extends BimMarkerItem>(state: RenderState<T>) {\r\n const { config, currentId, focusedId, onSelect, onFocus, onEdit, onRemove } = state\r\n return (item: T): Record<string, unknown> => {\r\n const highlight = currentId === item.id\r\n const focused = focusedId === item.id\r\n if (item.isPending) {\r\n return config.propsMapper(item, {\r\n highlight,\r\n focused,\r\n isAuthor: false,\r\n onSelect: () => onSelect(item.id),\r\n onFocus: () => onFocus(item.id),\r\n })\r\n }\r\n return config.propsMapper(item, {\r\n highlight,\r\n focused,\r\n isAuthor: config.isAuthor(item),\r\n onSelect: () => onSelect(item.id),\r\n onFocus: () => onFocus(item.id),\r\n onEdit: () => onEdit(item.id),\r\n onRemove: () => onRemove(item.id),\r\n })\r\n }\r\n}\r\n\r\nfunction clearSingles<T extends BimMarkerItem>(\r\n world: any,\r\n registry: React.MutableRefObject<Map<string, MarkerRef>>,\r\n config: BimMarkerConfig<T>,\r\n) {\r\n renderCSS2DMarkers(world, {\r\n items: [],\r\n markerIdKey: config.markerIdKey,\r\n registry,\r\n component: config.component,\r\n propsMapper: () => ({}),\r\n sphereColor: config.sphereColor,\r\n isVisible: false,\r\n onRemove: () => {},\r\n })\r\n}\r\n\r\nfunction clearClusters(world: any, registry: React.MutableRefObject<Map<string, ClusterMarkerRef>>) {\r\n registry.current.forEach(({ root, css2dObject }) => {\r\n world.scene.three.remove(css2dObject)\r\n const el = css2dObject.element as HTMLElement | undefined\r\n el?.remove()\r\n root.unmount()\r\n })\r\n registry.current.clear()\r\n}\r\n\r\n/**\r\n * Imperative render driven by a rAF loop. Recomputes screen-space clustering\r\n * from the current camera and only rebuilds DOM when the layout/data signature\r\n * changes (individual CSS2DObjects already track the camera every frame).\r\n */\r\nfunction renderMarkers<T extends BimMarkerItem>(\r\n state: RenderState<T>,\r\n singleRegistry: React.MutableRefObject<Map<string, MarkerRef>>,\r\n clusterRegistry: React.MutableRefObject<Map<string, ClusterMarkerRef>>,\r\n lastSignatureRef: React.MutableRefObject<string>,\r\n) {\r\n const { world, items, pending, isVisible, currentId, focusedId, coreHooks, config, onRemove, onSelect, onFocus } = state\r\n if (!world) return\r\n\r\n if (!isVisible) {\r\n if (lastSignatureRef.current === \"hidden\") return\r\n clearSingles(world, singleRegistry, config)\r\n clearClusters(world, clusterRegistry)\r\n lastSignatureRef.current = \"hidden\"\r\n return\r\n }\r\n\r\n const camera = world.camera?.three\r\n const dom = world.renderer?.three?.domElement\r\n if (!camera || !dom) return\r\n\r\n const width = dom.clientWidth || dom.width || 0\r\n const height = dom.clientHeight || dom.height || 0\r\n if (!width || !height) return\r\n\r\n const { clusters, singles } = clusterMarkersByScreenSpace(items, camera, width, height, 44)\r\n const singleItems = [...singles, ...pending]\r\n\r\n const clusterKeys = clusters.map((c) => c.key)\r\n const dataHash = [...items, ...pending].map((c) => config.dataHashPart(c)).join(\";\")\r\n const signature =\r\n `v2|${currentId}|${focusedId}|C:${clusterKeys.join(\",\")}` +\r\n `|S:${singleItems.map((s) => s.id).join(\",\")}|D:${dataHash}`\r\n if (signature === lastSignatureRef.current) return\r\n lastSignatureRef.current = signature\r\n\r\n // Singles (including pending) via the shared per-marker renderer\r\n renderCSS2DMarkers(world, {\r\n items: singleItems,\r\n markerIdKey: config.markerIdKey,\r\n registry: singleRegistry,\r\n component: config.component,\r\n hooksContextValue: coreHooks,\r\n propsMapper: makePropsMapper(state),\r\n sphereColor: config.sphereColor,\r\n isVisible: true,\r\n onRemove,\r\n })\r\n\r\n // Float the highlighted/focused marker above overlapping ones. The CSS2D renderer sorts by\r\n // renderOrder first (then camera distance), so this makes a selected marker that sits behind\r\n // nearer markers come to the front — visible and clickable instead of buried.\r\n singleRegistry.current.forEach((ref, id) => {\r\n const nid = Number(id)\r\n ref.css2dObject.renderOrder = nid === currentId || nid === focusedId ? 1 : 0\r\n })\r\n\r\n // Cluster bubbles, managed imperatively\r\n const reg = clusterRegistry.current\r\n const wanted = new Set(clusterKeys)\r\n for (const [key, ref] of reg) {\r\n if (!wanted.has(key)) {\r\n world.scene.three.remove(ref.css2dObject)\r\n const el = ref.css2dObject.element as HTMLElement | undefined\r\n el?.remove()\r\n ref.root.unmount()\r\n reg.delete(key)\r\n }\r\n }\r\n\r\n for (const cluster of clusters) {\r\n const members = cluster.members.map((m) => config.clusterMemberMapper(m))\r\n const highlight = currentId != null && members.some((m) => m.id === currentId)\r\n const element = React.createElement(config.clusterComponent, { members, highlight, onSelect, onFocus })\r\n const wrapped = coreHooks\r\n ? React.createElement(HooksCtx.Provider, { value: coreHooks }, element)\r\n : element\r\n\r\n const existing = reg.get(cluster.key)\r\n if (existing) {\r\n existing.root.render(wrapped)\r\n existing.css2dObject.position.set(cluster.worldCenter.x, cluster.worldCenter.y + 0.2, cluster.worldCenter.z)\r\n existing.css2dObject.renderOrder = highlight ? 1 : 0\r\n continue\r\n }\r\n\r\n const labelDiv = document.createElement(\"div\")\r\n labelDiv.style.pointerEvents = \"auto\"\r\n const root = createRoot(labelDiv)\r\n root.render(wrapped)\r\n\r\n const css2dObject = new CSS2DObject(labelDiv)\r\n css2dObject.position.set(cluster.worldCenter.x, cluster.worldCenter.y + 0.2, cluster.worldCenter.z)\r\n css2dObject.element.style.pointerEvents = \"auto\"\r\n css2dObject.renderOrder = highlight ? 1 : 0\r\n world.scene.three.add(css2dObject)\r\n\r\n reg.set(cluster.key, { root, css2dObject })\r\n }\r\n}\r\n\r\n/**\r\n * Generic BIM marker layer. Renders `items` as clustered CSS2D markers over a `three` world,\r\n * driving selection/focus/edit/remove through a `MarkerStoreAdapter` and shaping every\r\n * entity-specific detail through `config`. Behaviour is a straight generalization of the\r\n * comment marker layer (screen-space clustering, rAF diffing, double-click focus).\r\n */\r\nexport function useMarkerLayerBim<T extends BimMarkerItem>(\r\n world: any,\r\n items: T[],\r\n opts: {\r\n isVisible: boolean\r\n store: MarkerStoreAdapter\r\n coreHooks: HooksBag | null\r\n config: BimMarkerConfig<T>\r\n },\r\n): { addPending: (pos: { x: number; y: number; z: number }) => number; removePending: (id: number) => void } {\r\n const { isVisible, store, coreHooks, config } = opts\r\n\r\n const singleRegistry = React.useRef<Map<string, MarkerRef>>(new Map())\r\n const clusterRegistry = React.useRef<Map<string, ClusterMarkerRef>>(new Map())\r\n const lastSignatureRef = React.useRef<string>(\"\")\r\n const stateRef = React.useRef<RenderState<T> | null>(null)\r\n const itemsRef = React.useRef<T[]>([])\r\n\r\n itemsRef.current = items\r\n\r\n const handleSelect = React.useCallback((id: number) => {\r\n store.setCurrentId(id)\r\n }, [store])\r\n\r\n const handleFocus = React.useCallback((id: number) => {\r\n store.setCurrentId(id)\r\n store.setFocusedId(id)\r\n }, [store])\r\n\r\n const handleEdit = React.useCallback((id: number) => {\r\n store.requestEdit(id)\r\n }, [store])\r\n\r\n // Pending markers for loading indicators while an item is being created\r\n const [pending, setPending] = React.useState<Array<{ id: number; x: number; y: number; z: number }>>([])\r\n\r\n const addPending = React.useCallback((position: { x: number; y: number; z: number }) => {\r\n const id = -Date.now()\r\n setPending((prev) => [...prev, { id, ...position }])\r\n return id\r\n }, [])\r\n\r\n const removePending = React.useCallback((id: number) => {\r\n setPending((prev) => prev.filter((p) => p.id !== id))\r\n }, [])\r\n\r\n // Keep the latest inputs available to the rAF render loop (avoids stale closures)\r\n stateRef.current = {\r\n world,\r\n // Non-pending items carry an explicit isPending:false (parity with the pending placeholders).\r\n // Cast: spreading a generic T and assigning back to T[] is not provably safe to tsc.\r\n items: items.map((it) => ({ ...it, isPending: false })) as T[],\r\n pending: pending.map((p) => config.makePendingItem(p.id, { x: p.x, y: p.y, z: p.z })),\r\n isVisible,\r\n currentId: store.currentId,\r\n focusedId: store.focusedId,\r\n coreHooks,\r\n config,\r\n onRemove: config.onRemove,\r\n onSelect: handleSelect,\r\n onFocus: handleFocus,\r\n onEdit: handleEdit,\r\n }\r\n\r\n React.useEffect(() => {\r\n if (!world) return\r\n let raf = 0\r\n let frame = 0\r\n const loop = () => {\r\n // Recompute at most every other frame; renderMarkers no-ops unless the\r\n // cluster layout or data actually changed.\r\n if ((frame++ & 1) === 0 && stateRef.current) {\r\n renderMarkers(stateRef.current, singleRegistry, clusterRegistry, lastSignatureRef)\r\n }\r\n raf = requestAnimationFrame(loop)\r\n }\r\n raf = requestAnimationFrame(loop)\r\n\r\n return () => {\r\n cancelAnimationFrame(raf)\r\n clearClusters(world, clusterRegistry)\r\n clearSingles(world, singleRegistry, config)\r\n lastSignatureRef.current = \"\"\r\n }\r\n }, [world])\r\n\r\n // Zoom to a marker when it is focused (double-clicked here or in the sidebar).\r\n React.useEffect(() => {\r\n if (store.focusedId == null || !world) return\r\n const target = itemsRef.current.find((it) => it.id === store.focusedId)\r\n if (!target || target.x == null || target.y == null || target.z == null) return\r\n const controls = world.camera?.controls\r\n if (!controls) return\r\n\r\n const camPos = controls.getPosition(new THREE.Vector3())\r\n const camTarget = controls.getTarget(new THREE.Vector3())\r\n const lookAt = computeMarkerLookAt(\r\n { x: camPos.x, y: camPos.y, z: camPos.z },\r\n { x: camTarget.x, y: camTarget.y, z: camTarget.z },\r\n { x: target.x, y: target.y, z: target.z },\r\n config.focusDistance ?? 8,\r\n )\r\n void controls.setLookAt(lookAt.camX, lookAt.camY, lookAt.camZ, lookAt.tarX, lookAt.tarY, lookAt.tarZ, true)\r\n }, [store.focusRequestId, world])\r\n\r\n return { addPending, removePending }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAKA,YAAY,WAAW;AACvB,SAAS,kBAAkB;AAC3B,YAAY,WAAW;AACvB,SAAS,mBAAmB;AAE5B,SAAS,gBAA+B;AACxC,SAAS,mCAAmC;AAC5C,SAAS,0BAA0C;AAEnD,SAAS,2BAA2B;AA2BpC,SAAS,gBAAyC,OAAuB;AACvE,QAAM,EAAE,QAAQ,WAAW,WAAW,UAAU,SAAS,QAAQ,SAAS,IAAI;AAC9E,SAAO,CAAC,SAAqC;AAC3C,UAAM,YAAY,cAAc,KAAK;AACrC,UAAM,UAAU,cAAc,KAAK;AACnC,QAAI,KAAK,WAAW;AAClB,aAAO,OAAO,YAAY,MAAM;AAAA,QAC9B;AAAA,QACA;AAAA,QACA,UAAU;AAAA,QACV,UAAU,MAAM,SAAS,KAAK,EAAE;AAAA,QAChC,SAAS,MAAM,QAAQ,KAAK,EAAE;AAAA,MAChC,CAAC;AAAA,IACH;AACA,WAAO,OAAO,YAAY,MAAM;AAAA,MAC9B;AAAA,MACA;AAAA,MACA,UAAU,OAAO,SAAS,IAAI;AAAA,MAC9B,UAAU,MAAM,SAAS,KAAK,EAAE;AAAA,MAChC,SAAS,MAAM,QAAQ,KAAK,EAAE;AAAA,MAC9B,QAAQ,MAAM,OAAO,KAAK,EAAE;AAAA,MAC5B,UAAU,MAAM,SAAS,KAAK,EAAE;AAAA,IAClC,CAAC;AAAA,EACH;AACF;AAEA,SAAS,aACP,OACA,UACA,QACA;AACA,qBAAmB,OAAO;AAAA,IACxB,OAAO,CAAC;AAAA,IACR,aAAa,OAAO;AAAA,IACpB;AAAA,IACA,WAAW,OAAO;AAAA,IAClB,aAAa,OAAO,CAAC;AAAA,IACrB,aAAa,OAAO;AAAA,IACpB,WAAW;AAAA,IACX,UAAU,MAAM;AAAA,IAAC;AAAA,EACnB,CAAC;AACH;AAEA,SAAS,cAAc,OAAY,UAAiE;AAClG,WAAS,QAAQ,QAAQ,CAAC,EAAE,MAAM,YAAY,MAAM;AAClD,UAAM,MAAM,MAAM,OAAO,WAAW;AACpC,UAAM,KAAK,YAAY;AACvB,6BAAI;AACJ,SAAK,QAAQ;AAAA,EACf,CAAC;AACD,WAAS,QAAQ,MAAM;AACzB;AAOA,SAAS,cACP,OACA,gBACA,iBACA,kBACA;AAxGF;AAyGE,QAAM,EAAE,OAAO,OAAO,SAAS,WAAW,WAAW,WAAW,WAAW,QAAQ,UAAU,UAAU,QAAQ,IAAI;AACnH,MAAI,CAAC,MAAO;AAEZ,MAAI,CAAC,WAAW;AACd,QAAI,iBAAiB,YAAY,SAAU;AAC3C,iBAAa,OAAO,gBAAgB,MAAM;AAC1C,kBAAc,OAAO,eAAe;AACpC,qBAAiB,UAAU;AAC3B;AAAA,EACF;AAEA,QAAM,UAAS,WAAM,WAAN,mBAAc;AAC7B,QAAM,OAAM,iBAAM,aAAN,mBAAgB,UAAhB,mBAAuB;AACnC,MAAI,CAAC,UAAU,CAAC,IAAK;AAErB,QAAM,QAAQ,IAAI,eAAe,IAAI,SAAS;AAC9C,QAAM,SAAS,IAAI,gBAAgB,IAAI,UAAU;AACjD,MAAI,CAAC,SAAS,CAAC,OAAQ;AAEvB,QAAM,EAAE,UAAU,QAAQ,IAAI,4BAA4B,OAAO,QAAQ,OAAO,QAAQ,EAAE;AAC1F,QAAM,cAAc,CAAC,GAAG,SAAS,GAAG,OAAO;AAE3C,QAAM,cAAc,SAAS,IAAI,CAAC,MAAM,EAAE,GAAG;AAC7C,QAAM,WAAW,CAAC,GAAG,OAAO,GAAG,OAAO,EAAE,IAAI,CAAC,MAAM,OAAO,aAAa,CAAC,CAAC,EAAE,KAAK,GAAG;AACnF,QAAM,YACJ,MAAM,SAAS,IAAI,SAAS,MAAM,YAAY,KAAK,GAAG,CAAC,MACjD,YAAY,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,GAAG,CAAC,MAAM,QAAQ;AAC5D,MAAI,cAAc,iBAAiB,QAAS;AAC5C,mBAAiB,UAAU;AAG3B,qBAAmB,OAAO;AAAA,IACxB,OAAO;AAAA,IACP,aAAa,OAAO;AAAA,IACpB,UAAU;AAAA,IACV,WAAW,OAAO;AAAA,IAClB,mBAAmB;AAAA,IACnB,aAAa,gBAAgB,KAAK;AAAA,IAClC,aAAa,OAAO;AAAA,IACpB,WAAW;AAAA,IACX;AAAA,EACF,CAAC;AAKD,iBAAe,QAAQ,QAAQ,CAAC,KAAK,OAAO;AAC1C,UAAM,MAAM,OAAO,EAAE;AACrB,QAAI,YAAY,cAAc,QAAQ,aAAa,QAAQ,YAAY,IAAI;AAAA,EAC7E,CAAC;AAGD,QAAM,MAAM,gBAAgB;AAC5B,QAAM,SAAS,IAAI,IAAI,WAAW;AAClC,aAAW,CAAC,KAAK,GAAG,KAAK,KAAK;AAC5B,QAAI,CAAC,OAAO,IAAI,GAAG,GAAG;AACpB,YAAM,MAAM,MAAM,OAAO,IAAI,WAAW;AACxC,YAAM,KAAK,IAAI,YAAY;AAC3B,+BAAI;AACJ,UAAI,KAAK,QAAQ;AACjB,UAAI,OAAO,GAAG;AAAA,IAChB;AAAA,EACF;AAEA,aAAW,WAAW,UAAU;AAC9B,UAAM,UAAU,QAAQ,QAAQ,IAAI,CAAC,MAAM,OAAO,oBAAoB,CAAC,CAAC;AACxE,UAAM,YAAY,aAAa,QAAQ,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO,SAAS;AAC7E,UAAM,UAAU,MAAM,cAAc,OAAO,kBAAkB,EAAE,SAAS,WAAW,UAAU,QAAQ,CAAC;AACtG,UAAM,UAAU,YACZ,MAAM,cAAc,SAAS,UAAU,EAAE,OAAO,UAAU,GAAG,OAAO,IACpE;AAEJ,UAAM,WAAW,IAAI,IAAI,QAAQ,GAAG;AACpC,QAAI,UAAU;AACZ,eAAS,KAAK,OAAO,OAAO;AAC5B,eAAS,YAAY,SAAS,IAAI,QAAQ,YAAY,GAAG,QAAQ,YAAY,IAAI,KAAK,QAAQ,YAAY,CAAC;AAC3G,eAAS,YAAY,cAAc,YAAY,IAAI;AACnD;AAAA,IACF;AAEA,UAAM,WAAW,SAAS,cAAc,KAAK;AAC7C,aAAS,MAAM,gBAAgB;AAC/B,UAAM,OAAO,WAAW,QAAQ;AAChC,SAAK,OAAO,OAAO;AAEnB,UAAM,cAAc,IAAI,YAAY,QAAQ;AAC5C,gBAAY,SAAS,IAAI,QAAQ,YAAY,GAAG,QAAQ,YAAY,IAAI,KAAK,QAAQ,YAAY,CAAC;AAClG,gBAAY,QAAQ,MAAM,gBAAgB;AAC1C,gBAAY,cAAc,YAAY,IAAI;AAC1C,UAAM,MAAM,MAAM,IAAI,WAAW;AAEjC,QAAI,IAAI,QAAQ,KAAK,EAAE,MAAM,YAAY,CAAC;AAAA,EAC5C;AACF;AAQO,SAAS,kBACd,OACA,OACA,MAM2G;AAC3G,QAAM,EAAE,WAAW,OAAO,WAAW,OAAO,IAAI;AAEhD,QAAM,iBAAiB,MAAM,OAA+B,oBAAI,IAAI,CAAC;AACrE,QAAM,kBAAkB,MAAM,OAAsC,oBAAI,IAAI,CAAC;AAC7E,QAAM,mBAAmB,MAAM,OAAe,EAAE;AAChD,QAAM,WAAW,MAAM,OAA8B,IAAI;AACzD,QAAM,WAAW,MAAM,OAAY,CAAC,CAAC;AAErC,WAAS,UAAU;AAEnB,QAAM,eAAe,MAAM,YAAY,CAAC,OAAe;AACrD,UAAM,aAAa,EAAE;AAAA,EACvB,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,cAAc,MAAM,YAAY,CAAC,OAAe;AACpD,UAAM,aAAa,EAAE;AACrB,UAAM,aAAa,EAAE;AAAA,EACvB,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,aAAa,MAAM,YAAY,CAAC,OAAe;AACnD,UAAM,YAAY,EAAE;AAAA,EACtB,GAAG,CAAC,KAAK,CAAC;AAGV,QAAM,CAAC,SAAS,UAAU,IAAI,MAAM,SAAiE,CAAC,CAAC;AAEvG,QAAM,aAAa,MAAM,YAAY,CAAC,aAAkD;AACtF,UAAM,KAAK,CAAC,KAAK,IAAI;AACrB,eAAW,CAAC,SAAS,CAAC,GAAG,MAAM,iBAAE,MAAO,SAAU,CAAC;AACnD,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgB,MAAM,YAAY,CAAC,OAAe;AACtD,eAAW,CAAC,SAAS,KAAK,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;AAAA,EACtD,GAAG,CAAC,CAAC;AAGL,WAAS,UAAU;AAAA,IACjB;AAAA;AAAA;AAAA,IAGA,OAAO,MAAM,IAAI,CAAC,OAAQ,iCAAK,KAAL,EAAS,WAAW,MAAM,EAAE;AAAA,IACtD,SAAS,QAAQ,IAAI,CAAC,MAAM,OAAO,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,GAAG,EAAE,GAAG,GAAG,EAAE,EAAE,CAAC,CAAC;AAAA,IACpF;AAAA,IACA,WAAW,MAAM;AAAA,IACjB,WAAW,MAAM;AAAA,IACjB;AAAA,IACA;AAAA,IACA,UAAU,OAAO;AAAA,IACjB,UAAU;AAAA,IACV,SAAS;AAAA,IACT,QAAQ;AAAA,EACV;AAEA,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,MAAO;AACZ,QAAI,MAAM;AACV,QAAI,QAAQ;AACZ,UAAM,OAAO,MAAM;AAGjB,WAAK,UAAU,OAAO,KAAK,SAAS,SAAS;AAC3C,sBAAc,SAAS,SAAS,gBAAgB,iBAAiB,gBAAgB;AAAA,MACnF;AACA,YAAM,sBAAsB,IAAI;AAAA,IAClC;AACA,UAAM,sBAAsB,IAAI;AAEhC,WAAO,MAAM;AACX,2BAAqB,GAAG;AACxB,oBAAc,OAAO,eAAe;AACpC,mBAAa,OAAO,gBAAgB,MAAM;AAC1C,uBAAiB,UAAU;AAAA,IAC7B;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AAGV,QAAM,UAAU,MAAM;AArSxB;AAsSI,QAAI,MAAM,aAAa,QAAQ,CAAC,MAAO;AACvC,UAAM,SAAS,SAAS,QAAQ,KAAK,CAAC,OAAO,GAAG,OAAO,MAAM,SAAS;AACtE,QAAI,CAAC,UAAU,OAAO,KAAK,QAAQ,OAAO,KAAK,QAAQ,OAAO,KAAK,KAAM;AACzE,UAAM,YAAW,WAAM,WAAN,mBAAc;AAC/B,QAAI,CAAC,SAAU;AAEf,UAAM,SAAS,SAAS,YAAY,IAAI,MAAM,QAAQ,CAAC;AACvD,UAAM,YAAY,SAAS,UAAU,IAAI,MAAM,QAAQ,CAAC;AACxD,UAAM,SAAS;AAAA,MACb,EAAE,GAAG,OAAO,GAAG,GAAG,OAAO,GAAG,GAAG,OAAO,EAAE;AAAA,MACxC,EAAE,GAAG,UAAU,GAAG,GAAG,UAAU,GAAG,GAAG,UAAU,EAAE;AAAA,MACjD,EAAE,GAAG,OAAO,GAAG,GAAG,OAAO,GAAG,GAAG,OAAO,EAAE;AAAA,OACxC,YAAO,kBAAP,YAAwB;AAAA,IAC1B;AACA,SAAK,SAAS,UAAU,OAAO,MAAM,OAAO,MAAM,OAAO,MAAM,OAAO,MAAM,OAAO,MAAM,OAAO,MAAM,IAAI;AAAA,EAC5G,GAAG,CAAC,MAAM,gBAAgB,KAAK,CAAC;AAEhC,SAAO,EAAE,YAAY,cAAc;AACrC;","names":[]}
|
|
@@ -37,4 +37,15 @@ export declare const useCreateComment: () => {
|
|
|
37
37
|
createError: any;
|
|
38
38
|
createdData: import("../..").Comment;
|
|
39
39
|
};
|
|
40
|
+
export declare const useDeleteComments: () => {
|
|
41
|
+
deleteComments: import("swr/mutation").TriggerWithOptionsArgs<{
|
|
42
|
+
ids: number[];
|
|
43
|
+
buildingIds: number[];
|
|
44
|
+
authorIds: number[];
|
|
45
|
+
}, any, [string], {
|
|
46
|
+
ids: number[];
|
|
47
|
+
}>;
|
|
48
|
+
isDeleting: boolean;
|
|
49
|
+
deleteError: any;
|
|
50
|
+
};
|
|
40
51
|
//# sourceMappingURL=comments.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/comments/comments.ts"],"names":[],"mappings":"AAOA;;;GAGG;AAEH,eAAO,MAAM,WAAW;;;;CACc,CAAC;AAEvC,eAAO,MAAM,UAAU,GAAI,IAAI,MAAM,GAAG,IAAI;;;;;;;;;;;CACL,CAAC;AAExC,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,GAAG,IAAI;;;;CACL,CAAC;AAEvD,eAAO,MAAM,qBAAqB,GAAI,YAAY,MAAM,GAAG,IAAI;;;;CACL,CAAC;AAE3D,eAAO,MAAM,gBAAgB;;;;;;;CACc,CAAC"}
|
|
1
|
+
{"version":3,"file":"comments.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/comments/comments.ts"],"names":[],"mappings":"AAOA;;;GAGG;AAEH,eAAO,MAAM,WAAW;;;;CACc,CAAC;AAEvC,eAAO,MAAM,UAAU,GAAI,IAAI,MAAM,GAAG,IAAI;;;;;;;;;;;CACL,CAAC;AAExC,eAAO,MAAM,mBAAmB,GAAI,UAAU,MAAM,GAAG,IAAI;;;;CACL,CAAC;AAEvD,eAAO,MAAM,qBAAqB,GAAI,YAAY,MAAM,GAAG,IAAI;;;;CACL,CAAC;AAE3D,eAAO,MAAM,gBAAgB;;;;;;;CACc,CAAC;AAE5C,eAAO,MAAM,iBAAiB;;;;;;;;;;CACc,CAAC"}
|
|
@@ -5,11 +5,13 @@ const useComment = (id) => useCoreHooks().comment.useComment(id);
|
|
|
5
5
|
const useCommentsByAuthor = (authorId) => useCoreHooks().comment.useCommentsByAuthor(authorId);
|
|
6
6
|
const useCommentsByBuilding = (buildingId) => useCoreHooks().comment.useCommentsByBuilding(buildingId);
|
|
7
7
|
const useCreateComment = () => useCoreHooks().comment.useCreateComment();
|
|
8
|
+
const useDeleteComments = () => useCoreHooks().comment.useDeleteComments();
|
|
8
9
|
export {
|
|
9
10
|
useComment,
|
|
10
11
|
useComments,
|
|
11
12
|
useCommentsByAuthor,
|
|
12
13
|
useCommentsByBuilding,
|
|
13
|
-
useCreateComment
|
|
14
|
+
useCreateComment,
|
|
15
|
+
useDeleteComments
|
|
14
16
|
};
|
|
15
17
|
//# sourceMappingURL=comments.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/hooks/comments/comments.ts"],"sourcesContent":["\"use client\";\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport { useCoreHooks } from \"../provider\";\r\n\r\n/**\r\n * Convenience wrapper so components can import hooks directly from src/core/hooks/comments\r\n * Instead of calling useCoreHooks().comments first from src/core/hooks/provider.tsx\r\n */\r\n\r\nexport const useComments = () =>\r\n useCoreHooks().comment.useComments();\r\n\r\nexport const useComment = (id: number | null) =>\r\n useCoreHooks().comment.useComment(id);\r\n\r\nexport const useCommentsByAuthor = (authorId: number | null) =>\r\n useCoreHooks().comment.useCommentsByAuthor(authorId);\r\n\r\nexport const useCommentsByBuilding = (buildingId: number | null) =>\r\n useCoreHooks().comment.useCommentsByBuilding(buildingId);\r\n\r\nexport const useCreateComment = () =>\r\n useCoreHooks().comment.useCreateComment();"],"mappings":";AAKA,SAAS,oBAAoB;AAOtB,MAAM,cAAc,MACzB,aAAa,EAAE,QAAQ,YAAY;AAE9B,MAAM,aAAa,CAAC,OACzB,aAAa,EAAE,QAAQ,WAAW,EAAE;AAE/B,MAAM,sBAAsB,CAAC,aAClC,aAAa,EAAE,QAAQ,oBAAoB,QAAQ;AAE9C,MAAM,wBAAwB,CAAC,eACpC,aAAa,EAAE,QAAQ,sBAAsB,UAAU;AAElD,MAAM,mBAAmB,MAC9B,aAAa,EAAE,QAAQ,iBAAiB;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/hooks/comments/comments.ts"],"sourcesContent":["\"use client\";\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport { useCoreHooks } from \"../provider\";\r\n\r\n/**\r\n * Convenience wrapper so components can import hooks directly from src/core/hooks/comments\r\n * Instead of calling useCoreHooks().comments first from src/core/hooks/provider.tsx\r\n */\r\n\r\nexport const useComments = () =>\r\n useCoreHooks().comment.useComments();\r\n\r\nexport const useComment = (id: number | null) =>\r\n useCoreHooks().comment.useComment(id);\r\n\r\nexport const useCommentsByAuthor = (authorId: number | null) =>\r\n useCoreHooks().comment.useCommentsByAuthor(authorId);\r\n\r\nexport const useCommentsByBuilding = (buildingId: number | null) =>\r\n useCoreHooks().comment.useCommentsByBuilding(buildingId);\r\n\r\nexport const useCreateComment = () =>\r\n useCoreHooks().comment.useCreateComment();\r\n\r\nexport const useDeleteComments = () =>\r\n useCoreHooks().comment.useDeleteComments();"],"mappings":";AAKA,SAAS,oBAAoB;AAOtB,MAAM,cAAc,MACzB,aAAa,EAAE,QAAQ,YAAY;AAE9B,MAAM,aAAa,CAAC,OACzB,aAAa,EAAE,QAAQ,WAAW,EAAE;AAE/B,MAAM,sBAAsB,CAAC,aAClC,aAAa,EAAE,QAAQ,oBAAoB,QAAQ;AAE9C,MAAM,wBAAwB,CAAC,eACpC,aAAa,EAAE,QAAQ,sBAAsB,UAAU;AAElD,MAAM,mBAAmB,MAC9B,aAAa,EAAE,QAAQ,iBAAiB;AAEnC,MAAM,oBAAoB,MAC/B,aAAa,EAAE,QAAQ,kBAAkB;","names":[]}
|
|
@@ -36,5 +36,16 @@ export declare function createCommentHooks(adapter: ApiAdapter): {
|
|
|
36
36
|
isLoading: boolean;
|
|
37
37
|
isError: any;
|
|
38
38
|
};
|
|
39
|
+
useDeleteComments: () => {
|
|
40
|
+
deleteComments: import("swr/mutation").TriggerWithOptionsArgs<{
|
|
41
|
+
ids: number[];
|
|
42
|
+
buildingIds: number[];
|
|
43
|
+
authorIds: number[];
|
|
44
|
+
}, any, [string], {
|
|
45
|
+
ids: number[];
|
|
46
|
+
}>;
|
|
47
|
+
isDeleting: boolean;
|
|
48
|
+
deleteError: any;
|
|
49
|
+
};
|
|
39
50
|
};
|
|
40
51
|
//# sourceMappingURL=createCommentHooks.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createCommentHooks.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/comments/createCommentHooks.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU;;;;;;qBA6B1B,MAAM,GAAG,IAAI;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"createCommentHooks.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/comments/createCommentHooks.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,UAAU;;;;;;qBA6B1B,MAAM,GAAG,IAAI;;;;;;;;;;;;oCAkHE,MAAM,GAAG,IAAI;;;;;;;yBAnBA,OAAO,CAAC,OAAO,CAAC;;;;;;wCA5GzB,MAAM,GAAG,IAAI;;;;;;;;;;;iBA6EZ,MAAM,EAAE;;;;;EAwEvD"}
|
|
@@ -76,6 +76,34 @@ function createCommentHooks(adapter) {
|
|
|
76
76
|
deleteError
|
|
77
77
|
};
|
|
78
78
|
};
|
|
79
|
+
const useDeleteComments = () => {
|
|
80
|
+
const { trigger: deleteComments, isMutating: isDeleting, error: deleteError } = useSWRMutation(
|
|
81
|
+
["deleteComments"],
|
|
82
|
+
async (_key, { arg }) => {
|
|
83
|
+
const buildingIds = /* @__PURE__ */ new Set();
|
|
84
|
+
const authorIds = /* @__PURE__ */ new Set();
|
|
85
|
+
for (const cid of arg.ids) {
|
|
86
|
+
try {
|
|
87
|
+
const comment = await adapter.getComment(cid);
|
|
88
|
+
if (comment == null ? void 0 : comment.buildingId) buildingIds.add(comment.buildingId);
|
|
89
|
+
if (comment == null ? void 0 : comment.authorId) authorIds.add(comment.authorId);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
}
|
|
92
|
+
await adapter.deleteComment(cid);
|
|
93
|
+
}
|
|
94
|
+
return { ids: arg.ids, buildingIds: [...buildingIds], authorIds: [...authorIds] };
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
onSuccess: ({ ids, buildingIds, authorIds }) => {
|
|
98
|
+
ids.forEach((cid) => mutate(["comment", cid], void 0, { revalidate: false }));
|
|
99
|
+
mutate(["comments"]);
|
|
100
|
+
buildingIds.forEach((bId) => mutate(["comments", "building", bId]));
|
|
101
|
+
authorIds.forEach((aId) => mutate(["commentsByAuthor", aId]));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
return { deleteComments, isDeleting, deleteError };
|
|
106
|
+
};
|
|
79
107
|
const useCreateComment = () => {
|
|
80
108
|
const { trigger: createComment, isMutating, data: createdData, error } = useSWRMutation(
|
|
81
109
|
["createComment"],
|
|
@@ -112,7 +140,8 @@ function createCommentHooks(adapter) {
|
|
|
112
140
|
useComment,
|
|
113
141
|
useCommentsByAuthor,
|
|
114
142
|
useCreateComment,
|
|
115
|
-
useCommentsByBuilding
|
|
143
|
+
useCommentsByBuilding,
|
|
144
|
+
useDeleteComments
|
|
116
145
|
};
|
|
117
146
|
}
|
|
118
147
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/hooks/comments/createCommentHooks.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n//needs private instance to work\r\nimport useSWR, { mutate } from \"swr\";\r\nimport useSWRMutation from \"swr/mutation\";\r\n\r\nimport type { Comment } from '../../types/dbTypes'\r\nimport type { ApiAdapter } from \"../ports/apiAdapter\";\r\n\r\nexport function createCommentHooks(adapter: ApiAdapter) {\r\n //Call adapter methods inside hooks\r\n\r\n const useComments = () => {\r\n const key = [\"comments\"]; // no endpoint string\r\n const { data, error, isLoading } = useSWR<Comment[]>(\r\n key,\r\n () => adapter.getComments(),\r\n );\r\n return {\r\n comments: data ?? [],\r\n isLoading,\r\n isError: error,\r\n };\r\n };\r\n\r\n const useCommentsByBuilding = (buildingId: number | null) => {\r\n const key = buildingId ? [\"comments\", \"building\", buildingId] as const : null;\r\n const { data, error, isLoading } = useSWR<Comment[]>(\r\n key,\r\n () => adapter.getCommentsByBuilding(buildingId as number),\r\n );\r\n return {\r\n comments: data ?? [],\r\n isLoading,\r\n isError: error,\r\n }\r\n };\r\n\r\n const useComment = (id: number | null) => {\r\n const key = id ? [\"comment\", id] as const : null;\r\n const { data, error, isLoading } = useSWR<Comment>(\r\n key,\r\n () => adapter.getComment(id as number),\r\n //{ refreshInterval: 1000 }\r\n );\r\n\r\n // SWR Mutation for updating a comment\r\n const { trigger: updateComment, isMutating, data: updatedData, error: updateError } = useSWRMutation(\r\n id ? [\"updateComment\", id] : null,\r\n async (_key, { arg }: { arg: Partial<Comment> }) =>\r\n adapter.updateComment(id as number, arg),\r\n {\r\n onSuccess: (updated) => {\r\n if (!id) return;\r\n // Revalidate the same keys used above\r\n mutate([\"comment\", id]);\r\n mutate([\"comments\"]);\r\n if (updated.buildingId) mutate([\"comments\", \"building\", updated.buildingId]);\r\n if (updated.authorId) mutate([\"commentsByAuthor\", updated.authorId]);\r\n if (data?.buildingId && data.buildingId !== updated.buildingId) mutate([\"comments\", \"building\", data.buildingId]);\r\n if (data?.authorId && data.authorId !== updated.authorId) mutate([\"commentsByAuthor\", data.authorId]);\r\n },\r\n }\r\n );\r\n\r\n const { trigger: deleteComment, isMutating: isDeleting, error: deleteError } = useSWRMutation(\r\n id ? [\"deleteComment\", id] as const : null,\r\n async () => {\r\n const comment = await adapter.getComment(id as number);\r\n await adapter.deleteComment(id as number);\r\n return comment; // onSuccess context\r\n },\r\n {\r\n onSuccess: (comment) => {\r\n mutate([\"comment\", comment.id], undefined, { revalidate: false });\r\n mutate([\"comments\"]);\r\n if (comment.buildingId) mutate([\"comments\", \"building\", comment.buildingId]);\r\n if (comment.authorId) mutate([\"commentsByAuthor\", comment.authorId]);\r\n },\r\n }\r\n );\r\n\r\n return {\r\n comment: data ?? null,\r\n isLoading,\r\n isError: error,\r\n updateComment,\r\n isMutating,\r\n updateError,\r\n updatedData,\r\n deleteComment,\r\n isDeleting,\r\n deleteError\r\n };\r\n };\r\n\r\n const useCreateComment = () => {\r\n const { trigger: createComment, isMutating, data: createdData, error } = useSWRMutation(\r\n [\"createComment\"],\r\n async (_key, { arg }: { arg: { commentData: Partial<Comment> } }) =>\r\n adapter.createComment(arg),\r\n {\r\n onSuccess: (created) => {\r\n mutate([\"comments\"]);\r\n if (created.buildingId) mutate([\"comments\", \"building\", created.buildingId]);\r\n if (created.authorId) mutate([\"commentsByAuthor\", created.authorId]);\r\n },\r\n }\r\n );\r\n\r\n return {\r\n createComment,\r\n isMutating,\r\n createError: error,\r\n createdData,\r\n };\r\n };\r\n\r\n const useCommentsByAuthor = (authorId: number | null) => {\r\n const key = authorId ? [\"commentsByAuthor\", authorId] as const : null;\r\n const { data, error, isLoading } = useSWR<Comment[]>(\r\n key,\r\n () => adapter.getCommentsByAuthor(authorId as number),\r\n );\r\n return {\r\n comments: data ?? [],\r\n isLoading,\r\n isError: error,\r\n };\r\n };\r\n\r\n // Return all hooks\r\n return {\r\n useComments,\r\n useComment,\r\n useCommentsByAuthor,\r\n useCreateComment,\r\n useCommentsByBuilding\r\n };\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/hooks/comments/createCommentHooks.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\n//needs private instance to work\r\nimport useSWR, { mutate } from \"swr\";\r\nimport useSWRMutation from \"swr/mutation\";\r\n\r\nimport type { Comment } from '../../types/dbTypes'\r\nimport type { ApiAdapter } from \"../ports/apiAdapter\";\r\n\r\nexport function createCommentHooks(adapter: ApiAdapter) {\r\n //Call adapter methods inside hooks\r\n\r\n const useComments = () => {\r\n const key = [\"comments\"]; // no endpoint string\r\n const { data, error, isLoading } = useSWR<Comment[]>(\r\n key,\r\n () => adapter.getComments(),\r\n );\r\n return {\r\n comments: data ?? [],\r\n isLoading,\r\n isError: error,\r\n };\r\n };\r\n\r\n const useCommentsByBuilding = (buildingId: number | null) => {\r\n const key = buildingId ? [\"comments\", \"building\", buildingId] as const : null;\r\n const { data, error, isLoading } = useSWR<Comment[]>(\r\n key,\r\n () => adapter.getCommentsByBuilding(buildingId as number),\r\n );\r\n return {\r\n comments: data ?? [],\r\n isLoading,\r\n isError: error,\r\n }\r\n };\r\n\r\n const useComment = (id: number | null) => {\r\n const key = id ? [\"comment\", id] as const : null;\r\n const { data, error, isLoading } = useSWR<Comment>(\r\n key,\r\n () => adapter.getComment(id as number),\r\n //{ refreshInterval: 1000 }\r\n );\r\n\r\n // SWR Mutation for updating a comment\r\n const { trigger: updateComment, isMutating, data: updatedData, error: updateError } = useSWRMutation(\r\n id ? [\"updateComment\", id] : null,\r\n async (_key, { arg }: { arg: Partial<Comment> }) =>\r\n adapter.updateComment(id as number, arg),\r\n {\r\n onSuccess: (updated) => {\r\n if (!id) return;\r\n // Revalidate the same keys used above\r\n mutate([\"comment\", id]);\r\n mutate([\"comments\"]);\r\n if (updated.buildingId) mutate([\"comments\", \"building\", updated.buildingId]);\r\n if (updated.authorId) mutate([\"commentsByAuthor\", updated.authorId]);\r\n if (data?.buildingId && data.buildingId !== updated.buildingId) mutate([\"comments\", \"building\", data.buildingId]);\r\n if (data?.authorId && data.authorId !== updated.authorId) mutate([\"commentsByAuthor\", data.authorId]);\r\n },\r\n }\r\n );\r\n\r\n const { trigger: deleteComment, isMutating: isDeleting, error: deleteError } = useSWRMutation(\r\n id ? [\"deleteComment\", id] as const : null,\r\n async () => {\r\n const comment = await adapter.getComment(id as number);\r\n await adapter.deleteComment(id as number);\r\n return comment; // onSuccess context\r\n },\r\n {\r\n onSuccess: (comment) => {\r\n mutate([\"comment\", comment.id], undefined, { revalidate: false });\r\n mutate([\"comments\"]);\r\n if (comment.buildingId) mutate([\"comments\", \"building\", comment.buildingId]);\r\n if (comment.authorId) mutate([\"commentsByAuthor\", comment.authorId]);\r\n },\r\n }\r\n );\r\n\r\n return {\r\n comment: data ?? null,\r\n isLoading,\r\n isError: error,\r\n updateComment,\r\n isMutating,\r\n updateError,\r\n updatedData,\r\n deleteComment,\r\n isDeleting,\r\n deleteError\r\n };\r\n };\r\n\r\n // Delete one or more comments in a single call. Used to cascade-delete a comment together\r\n // with its replies (the DB self-relation is onDelete: SetNull, so replies must be removed\r\n // explicitly rather than relying on the database to cascade).\r\n const useDeleteComments = () => {\r\n const { trigger: deleteComments, isMutating: isDeleting, error: deleteError } = useSWRMutation(\r\n [\"deleteComments\"],\r\n async (_key, { arg }: { arg: { ids: number[] } }) => {\r\n const buildingIds = new Set<number>();\r\n const authorIds = new Set<number>();\r\n for (const cid of arg.ids) {\r\n try {\r\n const comment = await adapter.getComment(cid);\r\n if (comment?.buildingId) buildingIds.add(comment.buildingId);\r\n if (comment?.authorId) authorIds.add(comment.authorId);\r\n }\r\n catch {\r\n // Comment may already be gone; deletion below is still safe to attempt.\r\n }\r\n await adapter.deleteComment(cid);\r\n }\r\n return { ids: arg.ids, buildingIds: [...buildingIds], authorIds: [...authorIds] };\r\n },\r\n {\r\n onSuccess: ({ ids, buildingIds, authorIds }) => {\r\n ids.forEach((cid) => mutate([\"comment\", cid], undefined, { revalidate: false }));\r\n mutate([\"comments\"]);\r\n buildingIds.forEach((bId) => mutate([\"comments\", \"building\", bId]));\r\n authorIds.forEach((aId) => mutate([\"commentsByAuthor\", aId]));\r\n },\r\n }\r\n );\r\n return { deleteComments, isDeleting, deleteError };\r\n };\r\n\r\n const useCreateComment = () => {\r\n const { trigger: createComment, isMutating, data: createdData, error } = useSWRMutation(\r\n [\"createComment\"],\r\n async (_key, { arg }: { arg: { commentData: Partial<Comment> } }) =>\r\n adapter.createComment(arg),\r\n {\r\n onSuccess: (created) => {\r\n mutate([\"comments\"]);\r\n if (created.buildingId) mutate([\"comments\", \"building\", created.buildingId]);\r\n if (created.authorId) mutate([\"commentsByAuthor\", created.authorId]);\r\n },\r\n }\r\n );\r\n\r\n return {\r\n createComment,\r\n isMutating,\r\n createError: error,\r\n createdData,\r\n };\r\n };\r\n\r\n const useCommentsByAuthor = (authorId: number | null) => {\r\n const key = authorId ? [\"commentsByAuthor\", authorId] as const : null;\r\n const { data, error, isLoading } = useSWR<Comment[]>(\r\n key,\r\n () => adapter.getCommentsByAuthor(authorId as number),\r\n );\r\n return {\r\n comments: data ?? [],\r\n isLoading,\r\n isError: error,\r\n };\r\n };\r\n\r\n // Return all hooks\r\n return {\r\n useComments,\r\n useComment,\r\n useCommentsByAuthor,\r\n useCreateComment,\r\n useCommentsByBuilding,\r\n useDeleteComments\r\n };\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/files/files.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,eAAO,MAAM,QAAQ;;;;CAAuC,CAAC;AAE7D,eAAO,MAAM,OAAO,GAAI,IAAI,MAAM,GAAG,IAAI;;;;;;;;CAAoC,CAAC;AAE9E,eAAO,MAAM,oBAAoB,GAAI,YAAY,MAAM,EAAE,MAAM,MAAM;;;;CACV,CAAC;AAE5D,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM;;;;CACV,CAAC;AAEpD,eAAO,MAAM,uBAAuB,GAAI,YAAY,MAAM;;;;;;;CACD,CAAC;AAE1D,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM;;;;;;;CACD,CAAC;AAElD,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM;;;;;;;CACD,CAAC;AAElD,eAAO,MAAM,aAAa,GAAI,aAAa,MAAM,EAAE,SAAS,MAAM;;;;;CACX,CAAC;AAExD,wBAAgB,eAAe;yBAIK,GAAG,aAAa,MAAM;;;
|
|
1
|
+
{"version":3,"file":"files.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/files/files.ts"],"names":[],"mappings":"AASA;;;GAGG;AACH,eAAO,MAAM,QAAQ;;;;CAAuC,CAAC;AAE7D,eAAO,MAAM,OAAO,GAAI,IAAI,MAAM,GAAG,IAAI;;;;;;;;CAAoC,CAAC;AAE9E,eAAO,MAAM,oBAAoB,GAAI,YAAY,MAAM,EAAE,MAAM,MAAM;;;;CACV,CAAC;AAE5D,eAAO,MAAM,gBAAgB,GAAI,QAAQ,MAAM,EAAE,MAAM,MAAM;;;;CACV,CAAC;AAEpD,eAAO,MAAM,uBAAuB,GAAI,YAAY,MAAM;;;;;;;CACD,CAAC;AAE1D,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM;;;;;;;CACD,CAAC;AAElD,eAAO,MAAM,mBAAmB,GAAI,QAAQ,MAAM;;;;;;;CACD,CAAC;AAElD,eAAO,MAAM,aAAa,GAAI,aAAa,MAAM,EAAE,SAAS,MAAM;;;;;CACX,CAAC;AAExD,wBAAgB,eAAe;yBAIK,GAAG,aAAa,MAAM;;;EAsFzD"}
|
|
@@ -28,7 +28,6 @@ function useDownloadFile() {
|
|
|
28
28
|
if (!downloadUrl) {
|
|
29
29
|
throw new Error("No download URL available for this file");
|
|
30
30
|
}
|
|
31
|
-
console.log("Attempting to download from:", downloadUrl);
|
|
32
31
|
const finalFileName = fileName || file.name || ((_c = file.originalFile) == null ? void 0 : _c.name) || ((_d = file.metadata) == null ? void 0 : _d.name) || "download";
|
|
33
32
|
if (downloadUrl.startsWith("http")) {
|
|
34
33
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/hooks/files/files.ts"],"sourcesContent":["\"use client\";\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from \"react\";\r\n\r\nimport { useCoreHooks } from \"../provider\";\r\n\r\n/**\r\n * Convenience wrapper so components can import hooks directly from src/core/hooks/files\r\n * Instead of calling useCoreHooks().file first from src/core/hooks/provider.tsx\r\n */\r\nexport const useFiles = () => useCoreHooks().file.useFiles();\r\n\r\nexport const useFile = (id: number | null) => useCoreHooks().file.useFile(id);\r\n\r\nexport const useFilesByBuildingId = (buildingId: number, tag?: string) =>\r\n useCoreHooks().file.useFilesByBuildingId(buildingId, tag);\r\n\r\nexport const useFilesBySiteId = (siteId: number, tag?: string) =>\r\n useCoreHooks().file.useFilesBySiteId(siteId, tag);\r\n\r\nexport const useUploadFileToBuilding = (buildingId: number) =>\r\n useCoreHooks().file.useUploadFileToBuilding(buildingId);\r\n\r\nexport const useUploadFileToSite = (siteId: number) =>\r\n useCoreHooks().file.useUploadFileToSite(siteId);\r\n\r\nexport const useUploadFileToUser = (userId: number) =>\r\n useCoreHooks().file.useUploadFileToUser(userId);\r\n\r\nexport const useDeleteFile = (buildingId?: number, siteId?: number) =>\r\n useCoreHooks().file.useDeleteFile(buildingId, siteId);\r\n\r\nexport function useDownloadFile() {\r\n const [isDownloading, setIsDownloading] = React.useState(false)\r\n const [downloadError, setDownloadError] = React.useState<Error | null>(null)\r\n\r\n const downloadFile = async (file: any, fileName?: string) => {\r\n setIsDownloading(true)\r\n setDownloadError(null)\r\n\r\n try {\r\n let downloadUrl: string | null = null\r\n\r\n if (file.originalFile?.url) {\r\n downloadUrl = file.originalFile.url\r\n }\r\n // If we have metadata with URL\r\n else if (file.metadata?.url) {\r\n downloadUrl = file.metadata.url\r\n }\r\n else if (file.url && file.url.startsWith('http')) {\r\n downloadUrl = file.url\r\n }\r\n\r\n if (!downloadUrl) {\r\n throw new Error('No download URL available for this file')\r\n }\r\n\r\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/hooks/files/files.ts"],"sourcesContent":["\"use client\";\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from \"react\";\r\n\r\nimport { useCoreHooks } from \"../provider\";\r\n\r\n/**\r\n * Convenience wrapper so components can import hooks directly from src/core/hooks/files\r\n * Instead of calling useCoreHooks().file first from src/core/hooks/provider.tsx\r\n */\r\nexport const useFiles = () => useCoreHooks().file.useFiles();\r\n\r\nexport const useFile = (id: number | null) => useCoreHooks().file.useFile(id);\r\n\r\nexport const useFilesByBuildingId = (buildingId: number, tag?: string) =>\r\n useCoreHooks().file.useFilesByBuildingId(buildingId, tag);\r\n\r\nexport const useFilesBySiteId = (siteId: number, tag?: string) =>\r\n useCoreHooks().file.useFilesBySiteId(siteId, tag);\r\n\r\nexport const useUploadFileToBuilding = (buildingId: number) =>\r\n useCoreHooks().file.useUploadFileToBuilding(buildingId);\r\n\r\nexport const useUploadFileToSite = (siteId: number) =>\r\n useCoreHooks().file.useUploadFileToSite(siteId);\r\n\r\nexport const useUploadFileToUser = (userId: number) =>\r\n useCoreHooks().file.useUploadFileToUser(userId);\r\n\r\nexport const useDeleteFile = (buildingId?: number, siteId?: number) =>\r\n useCoreHooks().file.useDeleteFile(buildingId, siteId);\r\n\r\nexport function useDownloadFile() {\r\n const [isDownloading, setIsDownloading] = React.useState(false)\r\n const [downloadError, setDownloadError] = React.useState<Error | null>(null)\r\n\r\n const downloadFile = async (file: any, fileName?: string) => {\r\n setIsDownloading(true)\r\n setDownloadError(null)\r\n\r\n try {\r\n let downloadUrl: string | null = null\r\n\r\n if (file.originalFile?.url) {\r\n downloadUrl = file.originalFile.url\r\n }\r\n // If we have metadata with URL\r\n else if (file.metadata?.url) {\r\n downloadUrl = file.metadata.url\r\n }\r\n else if (file.url && file.url.startsWith('http')) {\r\n downloadUrl = file.url\r\n }\r\n\r\n if (!downloadUrl) {\r\n throw new Error('No download URL available for this file')\r\n }\r\n\r\n // Determine filename\r\n const finalFileName = fileName\r\n || file.name\r\n || file.originalFile?.name\r\n || file.metadata?.name\r\n || 'download'\r\n\r\n // For presigned URLs, download as blob\r\n if (downloadUrl.startsWith('http')) {\r\n try {\r\n const response = await fetch(downloadUrl, {\r\n method: 'GET',\r\n mode: 'cors',\r\n })\r\n\r\n if (!response.ok) {\r\n throw new Error(`Download failed: ${response.status} ${response.statusText}`)\r\n }\r\n\r\n const blob = await response.blob()\r\n\r\n if (blob.size === 0) {\r\n throw new Error('Downloaded file is empty')\r\n }\r\n\r\n // Create download link and trigger download\r\n const url = window.URL.createObjectURL(blob)\r\n const link = document.createElement('a')\r\n link.href = url\r\n link.download = finalFileName\r\n link.style.display = 'none'\r\n document.body.append(link)\r\n link.click()\r\n\r\n // Cleanup with a small delay\r\n setTimeout(() => {\r\n link.remove()\r\n window.URL.revokeObjectURL(url)\r\n }, 100)\r\n }\r\n catch (fetchError) {\r\n console.error('Blob download failed, trying direct link:', fetchError)\r\n window.open(downloadUrl, '_blank')\r\n }\r\n }\r\n else {\r\n window.open(downloadUrl, '_blank')\r\n }\r\n }\r\n catch (error) {\r\n const errorMessage = error instanceof Error ? error.message : 'Download failed'\r\n setDownloadError(new Error(errorMessage))\r\n console.error('File download error:', error)\r\n }\r\n finally {\r\n setIsDownloading(false)\r\n }\r\n }\r\n\r\n return {\r\n downloadFile,\r\n isDownloading,\r\n downloadError,\r\n }\r\n}"],"mappings":";AAKA,YAAY,WAAW;AAEvB,SAAS,oBAAoB;AAMtB,MAAM,WAAW,MAAM,aAAa,EAAE,KAAK,SAAS;AAEpD,MAAM,UAAU,CAAC,OAAsB,aAAa,EAAE,KAAK,QAAQ,EAAE;AAErE,MAAM,uBAAuB,CAAC,YAAoB,QACvD,aAAa,EAAE,KAAK,qBAAqB,YAAY,GAAG;AAEnD,MAAM,mBAAmB,CAAC,QAAgB,QAC/C,aAAa,EAAE,KAAK,iBAAiB,QAAQ,GAAG;AAE3C,MAAM,0BAA0B,CAAC,eACtC,aAAa,EAAE,KAAK,wBAAwB,UAAU;AAEjD,MAAM,sBAAsB,CAAC,WAClC,aAAa,EAAE,KAAK,oBAAoB,MAAM;AAEzC,MAAM,sBAAsB,CAAC,WAClC,aAAa,EAAE,KAAK,oBAAoB,MAAM;AAEzC,MAAM,gBAAgB,CAAC,YAAqB,WACjD,aAAa,EAAE,KAAK,cAAc,YAAY,MAAM;AAE/C,SAAS,kBAAkB;AAChC,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAS,KAAK;AAC9D,QAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM,SAAuB,IAAI;AAE3E,QAAM,eAAe,OAAO,MAAW,aAAsB;AAvC/D;AAwCI,qBAAiB,IAAI;AACrB,qBAAiB,IAAI;AAErB,QAAI;AACF,UAAI,cAA6B;AAEjC,WAAI,UAAK,iBAAL,mBAAmB,KAAK;AAC1B,sBAAc,KAAK,aAAa;AAAA,MAClC,YAES,UAAK,aAAL,mBAAe,KAAK;AAC3B,sBAAc,KAAK,SAAS;AAAA,MAC9B,WACS,KAAK,OAAO,KAAK,IAAI,WAAW,MAAM,GAAG;AAChD,sBAAc,KAAK;AAAA,MACrB;AAEA,UAAI,CAAC,aAAa;AAChB,cAAM,IAAI,MAAM,yCAAyC;AAAA,MAC3D;AAGA,YAAM,gBAAgB,YACjB,KAAK,UACL,UAAK,iBAAL,mBAAmB,WACnB,UAAK,aAAL,mBAAe,SACf;AAGL,UAAI,YAAY,WAAW,MAAM,GAAG;AAClC,YAAI;AACF,gBAAM,WAAW,MAAM,MAAM,aAAa;AAAA,YACxC,QAAQ;AAAA,YACR,MAAM;AAAA,UACR,CAAC;AAED,cAAI,CAAC,SAAS,IAAI;AAChB,kBAAM,IAAI,MAAM,oBAAoB,SAAS,MAAM,IAAI,SAAS,UAAU,EAAE;AAAA,UAC9E;AAEA,gBAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,cAAI,KAAK,SAAS,GAAG;AACnB,kBAAM,IAAI,MAAM,0BAA0B;AAAA,UAC5C;AAGA,gBAAM,MAAM,OAAO,IAAI,gBAAgB,IAAI;AAC3C,gBAAM,OAAO,SAAS,cAAc,GAAG;AACvC,eAAK,OAAO;AACZ,eAAK,WAAW;AAChB,eAAK,MAAM,UAAU;AACrB,mBAAS,KAAK,OAAO,IAAI;AACzB,eAAK,MAAM;AAGX,qBAAW,MAAM;AACf,iBAAK,OAAO;AACZ,mBAAO,IAAI,gBAAgB,GAAG;AAAA,UAChC,GAAG,GAAG;AAAA,QACR,SACO,YAAY;AACjB,kBAAQ,MAAM,6CAA6C,UAAU;AACrE,iBAAO,KAAK,aAAa,QAAQ;AAAA,QACnC;AAAA,MACF,OACK;AACH,eAAO,KAAK,aAAa,QAAQ;AAAA,MACnC;AAAA,IACF,SACO,OAAO;AACZ,YAAM,eAAe,iBAAiB,QAAQ,MAAM,UAAU;AAC9D,uBAAiB,IAAI,MAAM,YAAY,CAAC;AACxC,cAAQ,MAAM,wBAAwB,KAAK;AAAA,IAC7C,UACA;AACE,uBAAiB,KAAK;AAAA,IACxB;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
/** Minimum sidebar width. Equal to the previous fixed width, so it never shrinks below the old default. */
|
|
3
|
+
export declare const MIN_SIDEBAR_WIDTH = 410;
|
|
4
|
+
/** Maximum sidebar width, roughly half a laptop viewport. */
|
|
5
|
+
export declare const MAX_SIDEBAR_WIDTH = 720;
|
|
6
|
+
export declare const DEFAULT_SIDEBAR_WIDTH = 410;
|
|
7
|
+
export declare const SIDEBAR_WIDTH_STORAGE_KEY = "cdt:sidebar-width";
|
|
8
|
+
/** Clamp to [MIN, MAX]. NaN falls back to the default; ±Infinity clamps to the bounds. */
|
|
9
|
+
export declare function clampSidebarWidth(width: number): number;
|
|
10
|
+
/** SSR-safe read of the persisted width, clamped; falls back to the default on missing/corrupt values. */
|
|
11
|
+
export declare function readStoredSidebarWidth(): number;
|
|
12
|
+
/** SSR-safe persist of a clamped width. Swallows storage errors (private mode, quota). */
|
|
13
|
+
export declare function writeStoredSidebarWidth(width: number): void;
|
|
14
|
+
export interface ResizableSidebarWidth {
|
|
15
|
+
/** Current width in px. Only meaningful when `canResize` is true; mobile stays full-width via CSS. */
|
|
16
|
+
width: number;
|
|
17
|
+
/** True while a drag is in progress (for cursor / no-select styling). */
|
|
18
|
+
isResizing: boolean;
|
|
19
|
+
/** True on desktop only. Mobile is full-width and not resizable. */
|
|
20
|
+
canResize: boolean;
|
|
21
|
+
/** Attach to the drag handle's onPointerDown. */
|
|
22
|
+
startResize: (e: React.PointerEvent) => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Drives a user-resizable sidebar width on desktop. Width is restored from and persisted to
|
|
26
|
+
* localStorage, clamped to [MIN_SIDEBAR_WIDTH, MAX_SIDEBAR_WIDTH]. On mobile (`useIsMobile`)
|
|
27
|
+
* resizing is disabled and the sidebar is expected to render full-width via CSS.
|
|
28
|
+
*/
|
|
29
|
+
export declare function useResizableSidebarWidth(): ResizableSidebarWidth;
|
|
30
|
+
//# sourceMappingURL=useResizableSidebarWidth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useResizableSidebarWidth.d.ts","sourceRoot":"","sources":["../../../../src/core/hooks/ui/useResizableSidebarWidth.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,2GAA2G;AAC3G,eAAO,MAAM,iBAAiB,MAAM,CAAA;AACpC,6DAA6D;AAC7D,eAAO,MAAM,iBAAiB,MAAM,CAAA;AACpC,eAAO,MAAM,qBAAqB,MAAoB,CAAA;AACtD,eAAO,MAAM,yBAAyB,sBAAsB,CAAA;AAE5D,0FAA0F;AAC1F,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED,0GAA0G;AAC1G,wBAAgB,sBAAsB,IAAI,MAAM,CAW/C;AAED,0FAA0F;AAC1F,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAO3D;AAED,MAAM,WAAW,qBAAqB;IACpC,sGAAsG;IACtG,KAAK,EAAE,MAAM,CAAA;IACb,yEAAyE;IACzE,UAAU,EAAE,OAAO,CAAA;IACnB,oEAAoE;IACpE,SAAS,EAAE,OAAO,CAAA;IAClB,iDAAiD;IACjD,WAAW,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,YAAY,KAAK,IAAI,CAAA;CAC7C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,qBAAqB,CA0ChE"}
|