@collabdt/core 0.0.57 → 0.2.1
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/README.md +29 -43
- package/dist/core/components/AppSidebarContent.d.ts.map +1 -1
- package/dist/core/components/AppSidebarContent.js +21 -27
- package/dist/core/components/AppSidebarContent.js.map +1 -1
- package/dist/core/components/authentication/AuthPage.d.ts.map +1 -1
- package/dist/core/components/authentication/AuthPage.js +32 -7
- package/dist/core/components/authentication/AuthPage.js.map +1 -1
- package/dist/core/components/authentication/SignInAuthHeader.d.ts +7 -0
- package/dist/core/components/authentication/SignInAuthHeader.d.ts.map +1 -0
- package/dist/core/components/authentication/SignInAuthHeader.js +32 -0
- package/dist/core/components/authentication/SignInAuthHeader.js.map +1 -0
- package/dist/core/components/authentication/Signin.d.ts.map +1 -1
- package/dist/core/components/authentication/Signin.js +308 -10
- package/dist/core/components/authentication/Signin.js.map +1 -1
- package/dist/core/components/settings/index.js +3 -3
- package/dist/core/components/settings/index.js.map +1 -1
- package/dist/core/components/settings/src/OrganizationSettingsPanel.d.ts.map +1 -1
- package/dist/core/components/settings/src/OrganizationSettingsPanel.js +5 -4
- package/dist/core/components/settings/src/OrganizationSettingsPanel.js.map +1 -1
- package/dist/core/components/settings/src/SettingsSidebar.d.ts.map +1 -1
- package/dist/core/components/settings/src/SettingsSidebar.js +12 -2
- package/dist/core/components/settings/src/SettingsSidebar.js.map +1 -1
- package/dist/core/components/support/BugReportDialog.d.ts.map +1 -1
- package/dist/core/components/support/BugReportDialog.js +122 -9
- package/dist/core/components/support/BugReportDialog.js.map +1 -1
- package/dist/core/components/support/FeatureRequestDialog.d.ts.map +1 -1
- package/dist/core/components/support/FeatureRequestDialog.js +61 -2
- package/dist/core/components/support/FeatureRequestDialog.js.map +1 -1
- package/dist/core/components/ui/AppSidebar.d.ts.map +1 -1
- package/dist/core/components/ui/AppSidebar.js +52 -9
- package/dist/core/components/ui/AppSidebar.js.map +1 -1
- package/dist/core/components/ui/DataTable.js +3 -3
- package/dist/core/components/ui/DataTable.js.map +1 -1
- package/dist/core/components/ui/Dialog.js +1 -1
- package/dist/core/components/ui/Dialog.js.map +1 -1
- package/dist/core/components/ui/InfoSidebar/Container.js +1 -1
- package/dist/core/components/ui/InfoSidebar/Container.js.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js +2 -2
- package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/SensorsSection.js +2 -1
- package/dist/core/components/ui/Sensors/SensorsSection.js.map +1 -1
- package/dist/core/components/ui/Sensors/sensorUtils.d.ts +9 -0
- package/dist/core/components/ui/Sensors/sensorUtils.d.ts.map +1 -1
- package/dist/core/components/ui/Sensors/sensorUtils.js +6 -0
- package/dist/core/components/ui/Sensors/sensorUtils.js.map +1 -1
- package/dist/core/components/ui/Sidebar.d.ts +4 -0
- package/dist/core/components/ui/Sidebar.d.ts.map +1 -1
- package/dist/core/components/ui/Sidebar.js +11 -5
- package/dist/core/components/ui/Sidebar.js.map +1 -1
- package/dist/core/components/ui/Table.js +2 -2
- package/dist/core/components/ui/Table.js.map +1 -1
- package/dist/core/components/viewers/Data/DataMenu.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/DataMenu.js +17 -9
- package/dist/core/components/viewers/Data/DataMenu.js.map +1 -1
- package/dist/core/components/viewers/Data/HeaderButtons.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/HeaderButtons.js +5 -12
- package/dist/core/components/viewers/Data/HeaderButtons.js.map +1 -1
- package/dist/core/components/viewers/Data/MoreOptions.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/MoreOptions.js +14 -27
- package/dist/core/components/viewers/Data/MoreOptions.js.map +1 -1
- package/dist/core/components/viewers/Data/buildingDetails/BuildingDetails.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/buildingDetails/BuildingDetails.js +26 -0
- package/dist/core/components/viewers/Data/buildingDetails/BuildingDetails.js.map +1 -1
- package/dist/core/components/viewers/Data/buildingDetails/FieldRenderer.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/buildingDetails/FieldRenderer.js +13 -18
- package/dist/core/components/viewers/Data/buildingDetails/FieldRenderer.js.map +1 -1
- package/dist/core/components/viewers/Data/details/DetailHeader.js +14 -14
- package/dist/core/components/viewers/Data/details/DetailHeader.js.map +1 -1
- package/dist/core/components/viewers/Data/details/FieldValue.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/details/FieldValue.js +13 -3
- package/dist/core/components/viewers/Data/details/FieldValue.js.map +1 -1
- package/dist/core/components/viewers/Data/details/TabSidebar.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/details/TabSidebar.js +22 -0
- package/dist/core/components/viewers/Data/details/TabSidebar.js.map +1 -1
- package/dist/core/components/viewers/Data/infrastructureDetails/InfrastructureDetails.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/infrastructureDetails/InfrastructureDetails.js +19 -0
- package/dist/core/components/viewers/Data/infrastructureDetails/InfrastructureDetails.js.map +1 -1
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.d.ts +2 -0
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.js +84 -3
- package/dist/core/components/viewers/Data/siteDetails/AssociatedBuildings.js.map +1 -1
- package/dist/core/components/viewers/Data/siteDetails/SiteDetails.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/siteDetails/SiteDetails.js +42 -2
- package/dist/core/components/viewers/Data/siteDetails/SiteDetails.js.map +1 -1
- package/dist/core/components/viewers/Data/utils/Columns.js +2 -2
- package/dist/core/components/viewers/Data/utils/Columns.js.map +1 -1
- package/dist/core/components/viewers/Data/utils/positionParser.d.ts.map +1 -1
- package/dist/core/components/viewers/Data/utils/positionParser.js +6 -5
- package/dist/core/components/viewers/Data/utils/positionParser.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 +8 -1
- 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 +7 -1
- package/dist/core/components/viewers/bim/src/BimSidebar/src/FileTab/src/FilesSection.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/RowActions.js +6 -6
- package/dist/core/components/viewers/map/datasets/RowActions.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/data.js +1 -1
- package/dist/core/components/viewers/map/datasets/data.js.map +1 -1
- package/dist/core/components/viewers/map/datasets/index.d.ts.map +1 -1
- package/dist/core/components/viewers/map/datasets/index.js +28 -9
- package/dist/core/components/viewers/map/datasets/index.js.map +1 -1
- 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 -0
- package/dist/core/components/viewers/map/src/MapLayers/index.js.map +1 -1
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteContextMenu.d.ts +19 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteContextMenu.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteContextMenu.js +163 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteContextMenu.js.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteLayer.d.ts +3 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteLayer.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteLayer.js +310 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/SiteLayer.js.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/siteGeometry.d.ts +30 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/siteGeometry.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/siteGeometry.js +122 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/siteGeometry.js.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/useShowSitesOnMap.d.ts +13 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/useShowSitesOnMap.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/useShowSitesOnMap.js +58 -0
- package/dist/core/components/viewers/map/src/MapLayers/src/SiteLayer/useShowSitesOnMap.js.map +1 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/AssociateBuildingsDialog.d.ts +18 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/AssociateBuildingsDialog.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/AssociateBuildingsDialog.js +102 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/AssociateBuildingsDialog.js.map +1 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/SiteAdder.d.ts.map +1 -1
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/SiteAdder.js +243 -176
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/SiteAdder.js.map +1 -1
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/persistSite.d.ts +24 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/persistSite.d.ts.map +1 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/persistSite.js +46 -0
- package/dist/core/components/viewers/map/src/tools/AddTools/AddSite/persistSite.js.map +1 -0
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.d.ts +1 -0
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.d.ts.map +1 -1
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js +1 -0
- package/dist/core/components/viewers/map/utils/MapEventManager/MapClickManager.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.d.ts.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.js +54 -31
- package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/index.js.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts +2 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts.map +1 -1
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js +5 -4
- package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js.map +1 -1
- package/dist/core/hooks/sites/createSiteHooks.d.ts.map +1 -1
- package/dist/core/hooks/sites/createSiteHooks.js +0 -1
- package/dist/core/hooks/sites/createSiteHooks.js.map +1 -1
- package/dist/core/hooks/useCaptureScreenshot.d.ts.map +1 -1
- package/dist/core/hooks/useCaptureScreenshot.js +111 -33
- package/dist/core/hooks/useCaptureScreenshot.js.map +1 -1
- package/dist/core/hooks/useCurrentViewerPosition.d.ts +18 -0
- package/dist/core/hooks/useCurrentViewerPosition.d.ts.map +1 -0
- package/dist/core/hooks/useCurrentViewerPosition.js +66 -0
- package/dist/core/hooks/useCurrentViewerPosition.js.map +1 -0
- package/dist/core/hooks/useShareUrl.d.ts +2 -0
- package/dist/core/hooks/useShareUrl.d.ts.map +1 -0
- package/dist/core/hooks/useShareUrl.js +74 -0
- package/dist/core/hooks/useShareUrl.js.map +1 -0
- package/dist/core/store/CombineProviders.d.ts.map +1 -1
- package/dist/core/store/CombineProviders.js +2 -0
- package/dist/core/store/CombineProviders.js.map +1 -1
- package/dist/core/store/MapSites/context.d.ts +16 -0
- package/dist/core/store/MapSites/context.d.ts.map +1 -0
- package/dist/core/store/MapSites/context.js +29 -0
- package/dist/core/store/MapSites/context.js.map +1 -0
- package/dist/core/store/MapSites/reducer.d.ts +52 -0
- package/dist/core/store/MapSites/reducer.d.ts.map +1 -0
- package/dist/core/store/MapSites/reducer.js +70 -0
- package/dist/core/store/MapSites/reducer.js.map +1 -0
- package/dist/core/store/index.d.ts +1 -0
- package/dist/core/store/index.d.ts.map +1 -1
- package/dist/core/store/index.js +1 -0
- package/dist/core/store/index.js.map +1 -1
- package/dist/core/styles/globals.css +46 -33
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/core/components/ui/Sensors/SensorsSection.tsx"],"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 { BuildingsContext, MenusContext, ToolsContext } from '../../../store'\r\nimport { Button } from '../Button'\r\nimport { CollapsibleSection } from '../CollapsibleSection'\r\nimport { SearchInput } from '../SearchInput'\r\nimport { DropdownMenu } from '../DropdownMenu'\r\nimport {\r\n DropdownMenuTrigger,\r\n DropdownMenuContent,\r\n DropdownMenuLabel,\r\n DropdownMenuSeparator,\r\n DropdownMenuRadioGroup,\r\n DropdownMenuRadioItem,\r\n} from '../DropdownMenu'\r\nimport { useTranslations } from 'next-intl'\r\nimport { CollapsibleSensorItem } from './CollapsibleSensorItem'\r\nimport { SensorsSectionSkeleton } from './SensorsSectionSkeleton'\r\nimport { useSensor, useSensors } from '../../../hooks/sensors/sensors'\r\nimport { toast } from 'sonner'\r\nimport type { Sensor } from '../../../types/dbTypes';\r\nimport { useSensorTypes } from '../../../hooks/sensorTypes/sensorTypes'\r\nimport * as LR from 'lucide-react'\r\nimport { stringToColour } from '../../viewers/map/utils/stringToColour'\r\n\r\ntype SensorAction = 'view' | 'edit' | 'delete'\r\n\r\n/** Stable key used in state for sensors with no tags — locale-independent */\r\nexport const UNTAGGED_TAG = '__untagged__'\r\n\r\nexport function SensorsSection({ minioBaseUrl }: { minioBaseUrl?: string }) {\r\n // Translation\r\n const t = useTranslations('SensorsSection')\r\n\r\n const { dispatch: toolsDispatch } = React.useContext(ToolsContext)\r\n const { state: menusState, dispatch: menusDispatch } = React.useContext(MenusContext)\r\n const { currentViewer, visibleSensorTypes, visibleSensorTags } = menusState.menus\r\n\r\n const { sensors: allSensors }: { sensors: Sensor[] } = useSensors()\r\n const { sensorTypes, isLoading } = useSensorTypes()\r\n\r\n const {state: buildingsState} = React.useContext(BuildingsContext)\r\n const buildingId = buildingsState?.buildings?.building?.id || -1\r\n \r\n const [sensorToDelete, setSensorToDelete] = React.useState<number | null>(null)\r\n const [searchQuery, setSearchQuery] = React.useState('')\r\n const [groupBy, setGroupBy] = React.useState<'type' | 'tag'>('type')\r\n const { deleteSensor } = useSensor(sensorToDelete)\r\n\r\n const handleAddSensor = React.useCallback((currentSensorTypeId?: number) => {\r\n if (!currentViewer) return\r\n toolsDispatch({\r\n type: 'SET-TOOL',\r\n payload: {\r\n currentToolId:\r\n currentViewer === 'bim'\r\n ? 'bim-add-sensor'\r\n : currentViewer === 'map'\r\n ? 'map-add-sensor'\r\n : undefined,\r\n },\r\n })\r\n if (currentSensorTypeId) {\r\n menusDispatch({\r\n type: 'SET_CURRENT_SENSOR_TYPE_ID',\r\n payload: { currentSensorTypeId },\r\n })\r\n }\r\n }, [toolsDispatch, currentViewer])\r\n \r\n const handleSensorAction = React.useCallback((action: SensorAction, id: number) => {\r\n switch (action) {\r\n case 'view':\r\n console.log(`View sensor ${id}`)\r\n break\r\n case 'edit':\r\n console.log(`Edit sensor ${id}`)\r\n break\r\n case 'delete':\r\n toast.success(t('sensorDeleted'))\r\n setSensorToDelete(id)\r\n break\r\n default:\r\n break\r\n }\r\n }, [t])\r\n\r\n // Trigger deletion when sensorToDelete changes\r\n React.useEffect(() => {\r\n if (sensorToDelete !== null) {\r\n deleteSensor()\r\n setSensorToDelete(null)\r\n }\r\n }, [sensorToDelete, deleteSensor])\r\n\r\n const currentSensors: Sensor[] = allSensors.filter((sensor) => currentViewer === sensor.viewer && (!sensor.buildingId || sensor.buildingId === buildingId))\r\n \r\n // Filter sensors based on search query\r\n const filteredSensors = React.useMemo(() => {\r\n if (!searchQuery.trim()) return currentSensors\r\n\r\n const query = searchQuery.toLowerCase()\r\n return currentSensors.filter((sensor) => {\r\n const sensorTypeName =\r\n sensorTypes.find(type => type.id === sensor.typeId)?.name ?? ''\r\n return (\r\n sensor.name?.toLowerCase().includes(query) ||\r\n sensorTypeName.toLowerCase().includes(query)\r\n )\r\n })\r\n }, [currentSensors, searchQuery])\r\n \r\n const toggleSensorTypeVisibility = React.useCallback((sensorTypeId: number) => {\r\n menusDispatch({\r\n type: 'TOGGLE_SENSOR_TYPE_VISIBILITY',\r\n payload: {\r\n viewer: currentViewer,\r\n sensorTypeId: sensorTypeId,\r\n },\r\n })\r\n }, [currentViewer, menusDispatch])\r\n\r\n const handleGroupByChange = React.useCallback((newGroupBy: 'type' | 'tag') => {\r\n setGroupBy(newGroupBy)\r\n // Clear the opposing visibility state so markers from the old filter don't bleed through\r\n if (newGroupBy === 'tag') {\r\n menusDispatch({ type: 'HIDE_ALL_SENSORS_IN_VIEWER', payload: { viewer: currentViewer } })\r\n } else {\r\n menusDispatch({ type: 'HIDE_ALL_SENSOR_TAGS_IN_VIEWER', payload: { viewer: currentViewer } })\r\n }\r\n }, [currentViewer, menusDispatch])\r\n\r\n const toggleSensorTagVisibility = React.useCallback((tag: string) => {\r\n menusDispatch({\r\n type: 'TOGGLE_SENSOR_TAG_VISIBILITY',\r\n payload: {\r\n viewer: currentViewer,\r\n sensorTag: tag,\r\n },\r\n })\r\n }, [currentViewer, menusDispatch])\r\n\r\n // Group sensors by type, using sensorTypes as the source of truth for types\r\n const sensorsByType = React.useMemo(() => {\r\n const grouped: Record<string, Sensor[]> = {}\r\n sensorTypes.forEach(type => {\r\n grouped[type.name] = []\r\n })\r\n filteredSensors.forEach(sensor => {\r\n const type = sensorTypes.find(t => t.id === sensor.typeId)\r\n const typeName = type?.name ?? 'Other'\r\n if (!grouped[typeName]) {\r\n grouped[typeName] = []\r\n }\r\n grouped[typeName].push(sensor)\r\n })\r\n // Remove empty groups\r\n Object.keys(grouped).forEach(key => {\r\n if (grouped[key].length === 0) {\r\n delete grouped[key]\r\n }\r\n })\r\n return grouped\r\n }, [filteredSensors, sensorTypes])\r\n\r\n // Group sensors by tag\r\n const sensorsByTag = React.useMemo(() => {\r\n const grouped: Record<string, Sensor[]> = {}\r\n filteredSensors.forEach(sensor => {\r\n const tags = sensor.tags && sensor.tags.length > 0 ? sensor.tags : [UNTAGGED_TAG]\r\n tags.forEach(tag => {\r\n if (!grouped[tag]) grouped[tag] = []\r\n grouped[tag].push(sensor)\r\n })\r\n })\r\n return grouped\r\n }, [filteredSensors])\r\n\r\n return (\r\n <div className=\"flex-1 flex flex-col space-y-4 overflow-hidden\">\r\n <div className=\"px-4 flex items-center gap-2\">\r\n <SearchInput\r\n placeholder={t('searchSensors')}\r\n value={searchQuery}\r\n onChange={e => setSearchQuery(e.target.value)}\r\n />\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button variant=\"outline\" size=\"icon\" title={t('filters')} className=\"flex-shrink-0\">\r\n <LR.Funnel size={16} />\r\n </Button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent align=\"end\">\r\n <DropdownMenuLabel>{t('groupBy')}</DropdownMenuLabel>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuRadioGroup value={groupBy} onValueChange={v => handleGroupByChange(v as 'type' | 'tag')}>\r\n <DropdownMenuRadioItem value=\"type\">\r\n <LR.Layers className=\"mr-2 h-4 w-4\" />\r\n {t('groupByType')}\r\n </DropdownMenuRadioItem>\r\n <DropdownMenuRadioItem value=\"tag\">\r\n <LR.Tag className=\"mr-2 h-4 w-4\" />\r\n {t('groupByTag')}\r\n </DropdownMenuRadioItem>\r\n </DropdownMenuRadioGroup>\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n </div>\r\n {isLoading ? (\r\n <SensorsSectionSkeleton />\r\n ) : \r\n filteredSensors.length === 0 ? (\r\n <div className=\"p-4 text-muted-foreground text-sm flex flex-col items-center\">\r\n <div>{t('noSensorsFound')}</div>\r\n <Button\r\n className=\"mt-2 px-4 \"\r\n variant='outline'\r\n onClick={() => handleAddSensor()}\r\n >\r\n {t('addSensorTitle')}\r\n </Button>\r\n </div>\r\n ) : groupBy === 'type' ? (\r\n Object.entries(sensorsByType).map(([typeName, sensorsOfType]) => {\r\n const type = sensorTypes.find(t => t.name === typeName)\r\n const typeId = type?.id ?? -1\r\n\r\n const viewerTypes = visibleSensorTypes?.[currentViewer]\r\n const isTypeVisible = viewerTypes?.length > 0 && viewerTypes.includes(typeId)\r\n\r\n const sensorIcon = LR[type?.icon] || LR.Radio\r\n\r\n return (\r\n <CollapsibleSection\r\n key={typeName}\r\n title={typeName.replace(/_/g, ' ')}\r\n icon={sensorIcon}\r\n className=\"overflow-y-auto\"\r\n itemCount={sensorsOfType.length}\r\n onAddItem={() => handleAddSensor(typeId)}\r\n addItemTitle={t('addSensorTitle')}\r\n defaultOpen={false}\r\n switchVariant={{\r\n checked: isTypeVisible,\r\n onCheckedChange: () => toggleSensorTypeVisibility(typeId),\r\n }}\r\n >\r\n <div className=\"space-y-2 mx-2 pr-2\">\r\n {sensorsOfType.map((sensor) => (\r\n <CollapsibleSensorItem\r\n key={sensor.id}\r\n sensor={sensor}\r\n sensorType={type}\r\n onAction={handleSensorAction}\r\n isVisible={isTypeVisible}\r\n minioBaseUrl={minioBaseUrl}\r\n onMouseEnter={() => menusDispatch({ type: 'SET_CURRENT_SENSOR_ID', payload: { currentSensorId: sensor.id } })}\r\n onMouseLeave={() => menusDispatch({ type: 'SET_CURRENT_SENSOR_ID', payload: { currentSensorId: null } })}\r\n />\r\n ))}\r\n </div>\r\n </CollapsibleSection>\r\n )\r\n })\r\n ) : (\r\n Object.entries(sensorsByTag).map(([tag, sensorsOfTag]) => {\r\n const isTagVisible = visibleSensorTags?.[currentViewer]?.includes(tag) ?? false\r\n return (\r\n <CollapsibleSection\r\n key={tag}\r\n title={tag === UNTAGGED_TAG ? t('untagged') : tag}\r\n icon={LR.Tag}\r\n colour={stringToColour(tag, 'max')}\r\n className=\"overflow-y-auto\"\r\n itemCount={sensorsOfTag.length}\r\n defaultOpen={false}\r\n switchVariant={{\r\n checked: isTagVisible,\r\n onCheckedChange: () => toggleSensorTagVisibility(tag),\r\n }}\r\n >\r\n <div className=\"space-y-2 mx-2 pr-2\">\r\n {sensorsOfTag.map((sensor) => {\r\n const type = sensorTypes.find(tp => tp.id === sensor.typeId)\r\n return (\r\n <CollapsibleSensorItem\r\n key={sensor.id}\r\n sensor={sensor}\r\n sensorType={type}\r\n onAction={handleSensorAction}\r\n isVisible={isTagVisible}\r\n minioBaseUrl={minioBaseUrl}\r\n onMouseEnter={() => menusDispatch({ type: 'SET_CURRENT_SENSOR_ID', payload: { currentSensorId: sensor.id } })}\r\n onMouseLeave={() => menusDispatch({ type: 'SET_CURRENT_SENSOR_ID', payload: { currentSensorId: null } })}\r\n />\r\n )\r\n })}\r\n </div>\r\n </CollapsibleSection>\r\n )\r\n })\r\n )}\r\n </div>\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b","t"]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/core/components/ui/Sensors/SensorsSection.tsx"],"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 { BuildingsContext, MenusContext, ToolsContext } from '../../../store'\r\nimport { Button } from '../Button'\r\nimport { CollapsibleSection } from '../CollapsibleSection'\r\nimport { SearchInput } from '../SearchInput'\r\nimport { DropdownMenu } from '../DropdownMenu'\r\nimport {\r\n DropdownMenuTrigger,\r\n DropdownMenuContent,\r\n DropdownMenuLabel,\r\n DropdownMenuSeparator,\r\n DropdownMenuRadioGroup,\r\n DropdownMenuRadioItem,\r\n} from '../DropdownMenu'\r\nimport { useTranslations } from 'next-intl'\r\nimport { CollapsibleSensorItem } from './CollapsibleSensorItem'\r\nimport { SensorsSectionSkeleton } from './SensorsSectionSkeleton'\r\nimport { useSensor, useSensors } from '../../../hooks/sensors/sensors'\r\nimport { toast } from 'sonner'\r\nimport type { Sensor } from '../../../types/dbTypes';\r\nimport { useSensorTypes } from '../../../hooks/sensorTypes/sensorTypes'\r\nimport * as LR from 'lucide-react'\r\nimport { stringToColour } from '../../viewers/map/utils/stringToColour'\r\nimport { resolveLucideIcon } from './sensorUtils'\r\n\r\ntype SensorAction = 'view' | 'edit' | 'delete'\r\n\r\n/** Stable key used in state for sensors with no tags — locale-independent */\r\nexport const UNTAGGED_TAG = '__untagged__'\r\n\r\nexport function SensorsSection({ minioBaseUrl }: { minioBaseUrl?: string }) {\r\n // Translation\r\n const t = useTranslations('SensorsSection')\r\n\r\n const { dispatch: toolsDispatch } = React.useContext(ToolsContext)\r\n const { state: menusState, dispatch: menusDispatch } = React.useContext(MenusContext)\r\n const { currentViewer, visibleSensorTypes, visibleSensorTags } = menusState.menus\r\n\r\n const { sensors: allSensors }: { sensors: Sensor[] } = useSensors()\r\n const { sensorTypes, isLoading } = useSensorTypes()\r\n\r\n const {state: buildingsState} = React.useContext(BuildingsContext)\r\n const buildingId = buildingsState?.buildings?.building?.id || -1\r\n \r\n const [sensorToDelete, setSensorToDelete] = React.useState<number | null>(null)\r\n const [searchQuery, setSearchQuery] = React.useState('')\r\n const [groupBy, setGroupBy] = React.useState<'type' | 'tag'>('type')\r\n const { deleteSensor } = useSensor(sensorToDelete)\r\n\r\n const handleAddSensor = React.useCallback((currentSensorTypeId?: number) => {\r\n if (!currentViewer) return\r\n toolsDispatch({\r\n type: 'SET-TOOL',\r\n payload: {\r\n currentToolId:\r\n currentViewer === 'bim'\r\n ? 'bim-add-sensor'\r\n : currentViewer === 'map'\r\n ? 'map-add-sensor'\r\n : undefined,\r\n },\r\n })\r\n if (currentSensorTypeId) {\r\n menusDispatch({\r\n type: 'SET_CURRENT_SENSOR_TYPE_ID',\r\n payload: { currentSensorTypeId },\r\n })\r\n }\r\n }, [toolsDispatch, currentViewer])\r\n \r\n const handleSensorAction = React.useCallback((action: SensorAction, id: number) => {\r\n switch (action) {\r\n case 'view':\r\n console.log(`View sensor ${id}`)\r\n break\r\n case 'edit':\r\n console.log(`Edit sensor ${id}`)\r\n break\r\n case 'delete':\r\n toast.success(t('sensorDeleted'))\r\n setSensorToDelete(id)\r\n break\r\n default:\r\n break\r\n }\r\n }, [t])\r\n\r\n // Trigger deletion when sensorToDelete changes\r\n React.useEffect(() => {\r\n if (sensorToDelete !== null) {\r\n deleteSensor()\r\n setSensorToDelete(null)\r\n }\r\n }, [sensorToDelete, deleteSensor])\r\n\r\n const currentSensors: Sensor[] = allSensors.filter((sensor) => currentViewer === sensor.viewer && (!sensor.buildingId || sensor.buildingId === buildingId))\r\n \r\n // Filter sensors based on search query\r\n const filteredSensors = React.useMemo(() => {\r\n if (!searchQuery.trim()) return currentSensors\r\n\r\n const query = searchQuery.toLowerCase()\r\n return currentSensors.filter((sensor) => {\r\n const sensorTypeName =\r\n sensorTypes.find(type => type.id === sensor.typeId)?.name ?? ''\r\n return (\r\n sensor.name?.toLowerCase().includes(query) ||\r\n sensorTypeName.toLowerCase().includes(query)\r\n )\r\n })\r\n }, [currentSensors, searchQuery])\r\n \r\n const toggleSensorTypeVisibility = React.useCallback((sensorTypeId: number) => {\r\n menusDispatch({\r\n type: 'TOGGLE_SENSOR_TYPE_VISIBILITY',\r\n payload: {\r\n viewer: currentViewer,\r\n sensorTypeId: sensorTypeId,\r\n },\r\n })\r\n }, [currentViewer, menusDispatch])\r\n\r\n const handleGroupByChange = React.useCallback((newGroupBy: 'type' | 'tag') => {\r\n setGroupBy(newGroupBy)\r\n // Clear the opposing visibility state so markers from the old filter don't bleed through\r\n if (newGroupBy === 'tag') {\r\n menusDispatch({ type: 'HIDE_ALL_SENSORS_IN_VIEWER', payload: { viewer: currentViewer } })\r\n } else {\r\n menusDispatch({ type: 'HIDE_ALL_SENSOR_TAGS_IN_VIEWER', payload: { viewer: currentViewer } })\r\n }\r\n }, [currentViewer, menusDispatch])\r\n\r\n const toggleSensorTagVisibility = React.useCallback((tag: string) => {\r\n menusDispatch({\r\n type: 'TOGGLE_SENSOR_TAG_VISIBILITY',\r\n payload: {\r\n viewer: currentViewer,\r\n sensorTag: tag,\r\n },\r\n })\r\n }, [currentViewer, menusDispatch])\r\n\r\n // Group sensors by type, using sensorTypes as the source of truth for types\r\n const sensorsByType = React.useMemo(() => {\r\n const grouped: Record<string, Sensor[]> = {}\r\n sensorTypes.forEach(type => {\r\n grouped[type.name] = []\r\n })\r\n filteredSensors.forEach(sensor => {\r\n const type = sensorTypes.find(t => t.id === sensor.typeId)\r\n const typeName = type?.name ?? 'Other'\r\n if (!grouped[typeName]) {\r\n grouped[typeName] = []\r\n }\r\n grouped[typeName].push(sensor)\r\n })\r\n // Remove empty groups\r\n Object.keys(grouped).forEach(key => {\r\n if (grouped[key].length === 0) {\r\n delete grouped[key]\r\n }\r\n })\r\n return grouped\r\n }, [filteredSensors, sensorTypes])\r\n\r\n // Group sensors by tag\r\n const sensorsByTag = React.useMemo(() => {\r\n const grouped: Record<string, Sensor[]> = {}\r\n filteredSensors.forEach(sensor => {\r\n const tags = sensor.tags && sensor.tags.length > 0 ? sensor.tags : [UNTAGGED_TAG]\r\n tags.forEach(tag => {\r\n if (!grouped[tag]) grouped[tag] = []\r\n grouped[tag].push(sensor)\r\n })\r\n })\r\n return grouped\r\n }, [filteredSensors])\r\n\r\n return (\r\n <div className=\"flex-1 flex flex-col space-y-4 overflow-hidden\">\r\n <div className=\"px-4 flex items-center gap-2\">\r\n <SearchInput\r\n placeholder={t('searchSensors')}\r\n value={searchQuery}\r\n onChange={e => setSearchQuery(e.target.value)}\r\n />\r\n <DropdownMenu>\r\n <DropdownMenuTrigger asChild>\r\n <Button variant=\"outline\" size=\"icon\" title={t('filters')} className=\"flex-shrink-0\">\r\n <LR.Funnel size={16} />\r\n </Button>\r\n </DropdownMenuTrigger>\r\n <DropdownMenuContent align=\"end\">\r\n <DropdownMenuLabel>{t('groupBy')}</DropdownMenuLabel>\r\n <DropdownMenuSeparator />\r\n <DropdownMenuRadioGroup value={groupBy} onValueChange={v => handleGroupByChange(v as 'type' | 'tag')}>\r\n <DropdownMenuRadioItem value=\"type\">\r\n <LR.Layers className=\"mr-2 h-4 w-4\" />\r\n {t('groupByType')}\r\n </DropdownMenuRadioItem>\r\n <DropdownMenuRadioItem value=\"tag\">\r\n <LR.Tag className=\"mr-2 h-4 w-4\" />\r\n {t('groupByTag')}\r\n </DropdownMenuRadioItem>\r\n </DropdownMenuRadioGroup>\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n </div>\r\n {isLoading ? (\r\n <SensorsSectionSkeleton />\r\n ) : \r\n filteredSensors.length === 0 ? (\r\n <div className=\"p-4 text-muted-foreground text-sm flex flex-col items-center\">\r\n <div>{t('noSensorsFound')}</div>\r\n <Button\r\n className=\"mt-2 px-4 \"\r\n variant='outline'\r\n onClick={() => handleAddSensor()}\r\n >\r\n {t('addSensorTitle')}\r\n </Button>\r\n </div>\r\n ) : groupBy === 'type' ? (\r\n Object.entries(sensorsByType).map(([typeName, sensorsOfType]) => {\r\n const type = sensorTypes.find(t => t.name === typeName)\r\n const typeId = type?.id ?? -1\r\n\r\n const viewerTypes = visibleSensorTypes?.[currentViewer]\r\n const isTypeVisible = viewerTypes?.length > 0 && viewerTypes.includes(typeId)\r\n\r\n const sensorIcon = resolveLucideIcon(type?.icon)\r\n\r\n return (\r\n <CollapsibleSection\r\n key={typeName}\r\n title={typeName.replace(/_/g, ' ')}\r\n icon={sensorIcon}\r\n className=\"overflow-y-auto\"\r\n itemCount={sensorsOfType.length}\r\n onAddItem={() => handleAddSensor(typeId)}\r\n addItemTitle={t('addSensorTitle')}\r\n defaultOpen={false}\r\n switchVariant={{\r\n checked: isTypeVisible,\r\n onCheckedChange: () => toggleSensorTypeVisibility(typeId),\r\n }}\r\n >\r\n <div className=\"space-y-2 mx-2 pr-2\">\r\n {sensorsOfType.map((sensor) => (\r\n <CollapsibleSensorItem\r\n key={sensor.id}\r\n sensor={sensor}\r\n sensorType={type}\r\n onAction={handleSensorAction}\r\n isVisible={isTypeVisible}\r\n minioBaseUrl={minioBaseUrl}\r\n onMouseEnter={() => menusDispatch({ type: 'SET_CURRENT_SENSOR_ID', payload: { currentSensorId: sensor.id } })}\r\n onMouseLeave={() => menusDispatch({ type: 'SET_CURRENT_SENSOR_ID', payload: { currentSensorId: null } })}\r\n />\r\n ))}\r\n </div>\r\n </CollapsibleSection>\r\n )\r\n })\r\n ) : (\r\n Object.entries(sensorsByTag).map(([tag, sensorsOfTag]) => {\r\n const isTagVisible = visibleSensorTags?.[currentViewer]?.includes(tag) ?? false\r\n return (\r\n <CollapsibleSection\r\n key={tag}\r\n title={tag === UNTAGGED_TAG ? t('untagged') : tag}\r\n icon={LR.Tag}\r\n colour={stringToColour(tag, 'max')}\r\n className=\"overflow-y-auto\"\r\n itemCount={sensorsOfTag.length}\r\n defaultOpen={false}\r\n switchVariant={{\r\n checked: isTagVisible,\r\n onCheckedChange: () => toggleSensorTagVisibility(tag),\r\n }}\r\n >\r\n <div className=\"space-y-2 mx-2 pr-2\">\r\n {sensorsOfTag.map((sensor) => {\r\n const type = sensorTypes.find(tp => tp.id === sensor.typeId)\r\n return (\r\n <CollapsibleSensorItem\r\n key={sensor.id}\r\n sensor={sensor}\r\n sensorType={type}\r\n onAction={handleSensorAction}\r\n isVisible={isTagVisible}\r\n minioBaseUrl={minioBaseUrl}\r\n onMouseEnter={() => menusDispatch({ type: 'SET_CURRENT_SENSOR_ID', payload: { currentSensorId: sensor.id } })}\r\n onMouseLeave={() => menusDispatch({ type: 'SET_CURRENT_SENSOR_ID', payload: { currentSensorId: null } })}\r\n />\r\n )\r\n })}\r\n </div>\r\n </CollapsibleSection>\r\n )\r\n })\r\n )}\r\n </div>\r\n )\r\n}\r\n"],"mappings":"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","names":["_a","_b","t"]}
|
|
@@ -2,6 +2,15 @@ import type { SensorTypes } from '../../../types/dbTypes';
|
|
|
2
2
|
import * as LR from 'lucide-react';
|
|
3
3
|
export declare const sensorTypeIcons: Record<SensorTypes, LR.LucideIcon>;
|
|
4
4
|
export declare function getSensorTypeIcon(sensorType: `${SensorTypes}`): LR.LucideIcon;
|
|
5
|
+
/**
|
|
6
|
+
* Sensor types also carry a free-text `icon` field (set via an admin UI) that
|
|
7
|
+
* gets indexed directly into the lucide-react namespace. Unlike a lookup
|
|
8
|
+
* miss (which just returns `undefined`), a value that happens to match a
|
|
9
|
+
* non-component export (e.g. a type/helper name) would pass a plain
|
|
10
|
+
* `LR[name] || LR.Radio` check and throw when rendered as JSX — validate the
|
|
11
|
+
* resolved value actually looks like a component first.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveLucideIcon(iconName: string | null | undefined): LR.LucideIcon;
|
|
5
14
|
type ColorPalette = {
|
|
6
15
|
max: string;
|
|
7
16
|
mid: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sensorUtils.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/ui/Sensors/sensorUtils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,cAAc,CAAA;AAElC,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,UAAU,CAY9D,CAAA;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,GAAG,WAAW,EAAE,GAAG,EAAE,CAAC,UAAU,CAE7E;AAGD,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAGF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,WAAW,EAAE,YAAY,CA6D9D,CAAC;AAGF,eAAO,MAAM,cAAc,EAAE,YAI5B,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,GAAG,WAAW,EAAE,GAAG,YAAY,CAE9E"}
|
|
1
|
+
{"version":3,"file":"sensorUtils.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/ui/Sensors/sensorUtils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,MAAM,cAAc,CAAA;AAElC,eAAO,MAAM,eAAe,EAAE,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC,UAAU,CAY9D,CAAA;AAED,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,GAAG,WAAW,EAAE,GAAG,EAAE,CAAC,UAAU,CAE7E;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,EAAE,CAAC,UAAU,CAKpF;AAGD,KAAK,YAAY,GAAG;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAGF,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,WAAW,EAAE,YAAY,CA6D9D,CAAC;AAGF,eAAO,MAAM,cAAc,EAAE,YAI5B,CAAC;AAEF,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,GAAG,WAAW,EAAE,GAAG,YAAY,CAE9E"}
|
|
@@ -15,6 +15,11 @@ const sensorTypeIcons = {
|
|
|
15
15
|
function getSensorTypeIcon(sensorType) {
|
|
16
16
|
return sensorTypeIcons[sensorType] || LR.Radio;
|
|
17
17
|
}
|
|
18
|
+
function resolveLucideIcon(iconName) {
|
|
19
|
+
const candidate = iconName ? LR[iconName] : void 0;
|
|
20
|
+
const isIconComponent = typeof candidate === "function" || typeof candidate === "object" && candidate !== null && "$$typeof" in candidate;
|
|
21
|
+
return isIconComponent ? candidate : LR.Radio;
|
|
22
|
+
}
|
|
18
23
|
const sensorTypeColors = {
|
|
19
24
|
"Temperature": {
|
|
20
25
|
max: "#EF4444",
|
|
@@ -125,6 +130,7 @@ export {
|
|
|
125
130
|
defaultPalette,
|
|
126
131
|
getSensorTypeColors,
|
|
127
132
|
getSensorTypeIcon,
|
|
133
|
+
resolveLucideIcon,
|
|
128
134
|
sensorTypeColors,
|
|
129
135
|
sensorTypeIcons
|
|
130
136
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../src/core/components/ui/Sensors/sensorUtils.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport type { SensorTypes } from '../../../types/dbTypes';\r\nimport * as LR from 'lucide-react'\r\n\r\nexport const sensorTypeIcons: Record<SensorTypes, LR.LucideIcon> = {\r\n 'Temperature': LR.Thermometer,\r\n 'Light': LR.Sun,\r\n 'Humidity': LR.Droplets,\r\n 'Energy_Consumption': LR.Zap,\r\n 'Movement': LR.Cctv,\r\n 'Air_Quality': LR.Wind,\r\n 'Atmospheric_Pressure': LR.Gauge,\r\n 'Irradiance': LR.Radiation,\r\n 'Flow': LR.Waves,\r\n 'State': LR.ToggleLeft,\r\n 'Noise_Level': LR.Volume2,\r\n}\r\n\r\nexport function getSensorTypeIcon(sensorType: `${SensorTypes}`): LR.LucideIcon {\r\n return sensorTypeIcons[sensorType] || LR.Radio\r\n}\r\n\r\n// Define a type for your color palette\r\ntype ColorPalette = {\r\n max: string; // Main icon color\r\n mid: string; // Muted accent\r\n min: string; // Very light max\r\n};\r\n\r\n// Muted, non-dramatic color map\r\nexport const sensorTypeColors: Record<SensorTypes, ColorPalette> = {\r\n 'Temperature': { \r\n max: '#EF4444', // Bold Red (Hot)\r\n mid: '#F8FAFC', // Slate-50 (Neutral/White)\r\n min: '#3B82F6' // Bold Blue (Cold)\r\n },\r\n 'Energy_Consumption': { \r\n max: '#B91C1C', // Deep Red (High Usage)\r\n mid: '#FACC15', // Bright Yellow (Moderate)\r\n min: '#16A34A' // Green (Efficient)\r\n },\r\n 'Air_Quality': { \r\n max: '#7F1D1D', // Dark Maroon (Poor)\r\n mid: '#F97316', // Orange (Moderate)\r\n min: '#10B981' // Emerald (Clean)\r\n },\r\n 'Humidity': { \r\n max: '#1E3A8A', // Navy (Saturated/Wet)\r\n mid: '#60A5FA', // Sky Blue\r\n min: '#E0F2FE' // Very Light Blue (Dry)\r\n },\r\n 'Light': { \r\n max: '#FDE047', // Sun Yellow (Bright)\r\n mid: '#F59E0B', // Amber\r\n min: '#451A03' // Dark Brown (Dim/Dark)\r\n },\r\n // 'Battery': { // Bonus for consistency\r\n // max: '#059669', // Green (Full)\r\n // mid: '#EAB308', // Yellow (Medium)\r\n // min: '#DC2626' // Red (Critical)\r\n // },\r\n 'Flow': { \r\n max: '#0891B2', // Dark Cyan (High Flow)\r\n mid: '#22D3EE', // Cyan\r\n min: '#CFFAFE' // Pale Cyan\r\n },\r\n 'Movement': { \r\n max: '#475569', // Slate-600 (Active)\r\n mid: '#94A3B8', // Slate-400\r\n min: '#F1F5F9' // Slate-100 (Still)\r\n },\r\n 'Atmospheric_Pressure': { \r\n max: '#4338CA', // Indigo-700\r\n mid: '#818CF8', // Indigo-400\r\n min: '#E0E7FF' // Indigo-100\r\n },\r\n 'Irradiance': { \r\n max: '#EA580C', // Deep Orange\r\n mid: '#FB923C', // Orange\r\n min: '#FFF7ED' // Shell\r\n },\r\n 'State': { \r\n max: '#27272A', // Zinc-800\r\n mid: '#71717A', // Zinc-500\r\n min: '#F4F4F5' // Zinc-100\r\n },\r\n 'Noise_Level': {\r\n max: '#EC4899', // Pink-500 (Loud/Peak)\r\n mid: '#8B5CF6', // Violet-500 (Active)\r\n min: '#14B8A6' // Teal-500 (Silent/Background)\r\n }\r\n};\r\n\r\n// Fallback palette (Neutral Grey)\r\nexport const defaultPalette: ColorPalette = {\r\n max: '#B91C1C', // Deep Red (High Usage)\r\n mid: '#FACC15', // Bright Yellow (Moderate)\r\n min: '#16A34A' // Green (Efficient)\r\n};\r\n\r\nexport function getSensorTypeColors(sensorType: `${SensorTypes}`): ColorPalette { \r\n return sensorTypeColors[sensorType] || defaultPalette;\r\n}"],"mappings":"AAIA,YAAY,QAAQ;AAEb,MAAM,kBAAsD;AAAA,EACjE,eAAe,GAAG;AAAA,EAClB,SAAS,GAAG;AAAA,EACZ,YAAY,GAAG;AAAA,EACf,sBAAsB,GAAG;AAAA,EACzB,YAAY,GAAG;AAAA,EACf,eAAe,GAAG;AAAA,EAClB,wBAAwB,GAAG;AAAA,EAC3B,cAAc,GAAG;AAAA,EACjB,QAAQ,GAAG;AAAA,EACX,SAAS,GAAG;AAAA,EACZ,eAAe,GAAG;AACpB;AAEO,SAAS,kBAAkB,YAA6C;AAC7E,SAAO,gBAAgB,UAAU,KAAK,GAAG;AAC3C;AAUO,MAAM,mBAAsD;AAAA,EACjE,eAAe;AAAA,IACb,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,sBAAsB;AAAA,IACpB,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,eAAe;AAAA,IACb,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,YAAY;AAAA,IACV,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,SAAS;AAAA,IACP,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ;AAAA,IACN,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,YAAY;AAAA,IACV,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,wBAAwB;AAAA,IACtB,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,cAAc;AAAA,IACZ,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,SAAS;AAAA,IACP,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,eAAe;AAAA,IACb,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AACF;AAGO,MAAM,iBAA+B;AAAA,EACxC,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AACT;AAEO,SAAS,oBAAoB,YAA4C;AAC9E,SAAO,iBAAiB,UAAU,KAAK;AACzC;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../../src/core/components/ui/Sensors/sensorUtils.ts"],"sourcesContent":["// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport type { SensorTypes } from '../../../types/dbTypes';\r\nimport * as LR from 'lucide-react'\r\n\r\nexport const sensorTypeIcons: Record<SensorTypes, LR.LucideIcon> = {\r\n 'Temperature': LR.Thermometer,\r\n 'Light': LR.Sun,\r\n 'Humidity': LR.Droplets,\r\n 'Energy_Consumption': LR.Zap,\r\n 'Movement': LR.Cctv,\r\n 'Air_Quality': LR.Wind,\r\n 'Atmospheric_Pressure': LR.Gauge,\r\n 'Irradiance': LR.Radiation,\r\n 'Flow': LR.Waves,\r\n 'State': LR.ToggleLeft,\r\n 'Noise_Level': LR.Volume2,\r\n}\r\n\r\nexport function getSensorTypeIcon(sensorType: `${SensorTypes}`): LR.LucideIcon {\r\n return sensorTypeIcons[sensorType] || LR.Radio\r\n}\r\n\r\n/**\r\n * Sensor types also carry a free-text `icon` field (set via an admin UI) that\r\n * gets indexed directly into the lucide-react namespace. Unlike a lookup\r\n * miss (which just returns `undefined`), a value that happens to match a\r\n * non-component export (e.g. a type/helper name) would pass a plain\r\n * `LR[name] || LR.Radio` check and throw when rendered as JSX — validate the\r\n * resolved value actually looks like a component first.\r\n */\r\nexport function resolveLucideIcon(iconName: string | null | undefined): LR.LucideIcon {\r\n const candidate = iconName ? (LR as unknown as Record<string, unknown>)[iconName] : undefined\r\n const isIconComponent = typeof candidate === 'function'\r\n || (typeof candidate === 'object' && candidate !== null && '$$typeof' in candidate)\r\n return (isIconComponent ? candidate : LR.Radio) as LR.LucideIcon\r\n}\r\n\r\n// Define a type for your color palette\r\ntype ColorPalette = {\r\n max: string; // Main icon color\r\n mid: string; // Muted accent\r\n min: string; // Very light max\r\n};\r\n\r\n// Muted, non-dramatic color map\r\nexport const sensorTypeColors: Record<SensorTypes, ColorPalette> = {\r\n 'Temperature': { \r\n max: '#EF4444', // Bold Red (Hot)\r\n mid: '#F8FAFC', // Slate-50 (Neutral/White)\r\n min: '#3B82F6' // Bold Blue (Cold)\r\n },\r\n 'Energy_Consumption': { \r\n max: '#B91C1C', // Deep Red (High Usage)\r\n mid: '#FACC15', // Bright Yellow (Moderate)\r\n min: '#16A34A' // Green (Efficient)\r\n },\r\n 'Air_Quality': { \r\n max: '#7F1D1D', // Dark Maroon (Poor)\r\n mid: '#F97316', // Orange (Moderate)\r\n min: '#10B981' // Emerald (Clean)\r\n },\r\n 'Humidity': { \r\n max: '#1E3A8A', // Navy (Saturated/Wet)\r\n mid: '#60A5FA', // Sky Blue\r\n min: '#E0F2FE' // Very Light Blue (Dry)\r\n },\r\n 'Light': { \r\n max: '#FDE047', // Sun Yellow (Bright)\r\n mid: '#F59E0B', // Amber\r\n min: '#451A03' // Dark Brown (Dim/Dark)\r\n },\r\n // 'Battery': { // Bonus for consistency\r\n // max: '#059669', // Green (Full)\r\n // mid: '#EAB308', // Yellow (Medium)\r\n // min: '#DC2626' // Red (Critical)\r\n // },\r\n 'Flow': { \r\n max: '#0891B2', // Dark Cyan (High Flow)\r\n mid: '#22D3EE', // Cyan\r\n min: '#CFFAFE' // Pale Cyan\r\n },\r\n 'Movement': { \r\n max: '#475569', // Slate-600 (Active)\r\n mid: '#94A3B8', // Slate-400\r\n min: '#F1F5F9' // Slate-100 (Still)\r\n },\r\n 'Atmospheric_Pressure': { \r\n max: '#4338CA', // Indigo-700\r\n mid: '#818CF8', // Indigo-400\r\n min: '#E0E7FF' // Indigo-100\r\n },\r\n 'Irradiance': { \r\n max: '#EA580C', // Deep Orange\r\n mid: '#FB923C', // Orange\r\n min: '#FFF7ED' // Shell\r\n },\r\n 'State': { \r\n max: '#27272A', // Zinc-800\r\n mid: '#71717A', // Zinc-500\r\n min: '#F4F4F5' // Zinc-100\r\n },\r\n 'Noise_Level': {\r\n max: '#EC4899', // Pink-500 (Loud/Peak)\r\n mid: '#8B5CF6', // Violet-500 (Active)\r\n min: '#14B8A6' // Teal-500 (Silent/Background)\r\n }\r\n};\r\n\r\n// Fallback palette (Neutral Grey)\r\nexport const defaultPalette: ColorPalette = {\r\n max: '#B91C1C', // Deep Red (High Usage)\r\n mid: '#FACC15', // Bright Yellow (Moderate)\r\n min: '#16A34A' // Green (Efficient)\r\n};\r\n\r\nexport function getSensorTypeColors(sensorType: `${SensorTypes}`): ColorPalette { \r\n return sensorTypeColors[sensorType] || defaultPalette;\r\n}"],"mappings":"AAIA,YAAY,QAAQ;AAEb,MAAM,kBAAsD;AAAA,EACjE,eAAe,GAAG;AAAA,EAClB,SAAS,GAAG;AAAA,EACZ,YAAY,GAAG;AAAA,EACf,sBAAsB,GAAG;AAAA,EACzB,YAAY,GAAG;AAAA,EACf,eAAe,GAAG;AAAA,EAClB,wBAAwB,GAAG;AAAA,EAC3B,cAAc,GAAG;AAAA,EACjB,QAAQ,GAAG;AAAA,EACX,SAAS,GAAG;AAAA,EACZ,eAAe,GAAG;AACpB;AAEO,SAAS,kBAAkB,YAA6C;AAC7E,SAAO,gBAAgB,UAAU,KAAK,GAAG;AAC3C;AAUO,SAAS,kBAAkB,UAAoD;AACpF,QAAM,YAAY,WAAY,GAA0C,QAAQ,IAAI;AACpF,QAAM,kBAAkB,OAAO,cAAc,cACvC,OAAO,cAAc,YAAY,cAAc,QAAQ,cAAc;AAC3E,SAAQ,kBAAkB,YAAY,GAAG;AAC3C;AAUO,MAAM,mBAAsD;AAAA,EACjE,eAAe;AAAA,IACb,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,sBAAsB;AAAA,IACpB,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,eAAe;AAAA,IACb,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,YAAY;AAAA,IACV,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,SAAS;AAAA,IACP,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ;AAAA,IACN,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,YAAY;AAAA,IACV,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,wBAAwB;AAAA,IACtB,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,cAAc;AAAA,IACZ,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,SAAS;AAAA,IACP,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AAAA,EACA,eAAe;AAAA,IACb,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,IACL,KAAK;AAAA;AAAA,EACP;AACF;AAGO,MAAM,iBAA+B;AAAA,EACxC,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AAAA,EACL,KAAK;AAAA;AACT;AAEO,SAAS,oBAAoB,YAA4C;AAC9E,SAAO,iBAAiB,UAAU,KAAK;AACzC;","names":[]}
|
|
@@ -14,6 +14,10 @@ type SidebarContextProps = {
|
|
|
14
14
|
toggleInfoSidebar: () => void;
|
|
15
15
|
geocodeEarthApiKey?: string;
|
|
16
16
|
geocoderUrl?: string;
|
|
17
|
+
bugReportOpen: boolean;
|
|
18
|
+
setBugReportOpen: (open: boolean) => void;
|
|
19
|
+
featureRequestOpen: boolean;
|
|
20
|
+
setFeatureRequestOpen: (open: boolean) => void;
|
|
17
21
|
};
|
|
18
22
|
declare function useSidebar(): SidebarContextProps;
|
|
19
23
|
declare const SidebarProvider: React.ForwardRefExoticComponent<Omit<React.ClassAttributes<HTMLDivElement> & React.HTMLAttributes<HTMLDivElement> & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../../src/core/components/ui/Sidebar.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAAE,YAAY,EAAO,MAAM,0BAA0B,CAAA;AAe5D,OAAO,EAEL,cAAc,EAGf,MAAM,WAAW,CAAA;AAmBlB,KAAK,mBAAmB,GAAG;IACzB,YAAY,EAAE,UAAU,GAAG,WAAW,CAAA;IACtC,IAAI,EAAE,OAAO,CAAA;IACb,WAAW,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACpC,UAAU,EAAE,OAAO,CAAA;IACnB,aAAa,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACpC,QAAQ,EAAE,OAAO,CAAA;IACjB,iBAAiB,EAAE,MAAM,IAAI,CAAA;IAC7B,iBAAiB,EAAE,MAAM,IAAI,CAAA;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../../src/core/components/ui/Sidebar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -104,6 +104,8 @@ const SidebarProvider = React.forwardRef(
|
|
|
104
104
|
const isMobile = useIsMobile();
|
|
105
105
|
const [openMobile, setOpenMobile] = React.useState(false);
|
|
106
106
|
const [openInfo, setOpenInfo] = React.useState(false);
|
|
107
|
+
const [bugReportOpen, setBugReportOpen] = React.useState(false);
|
|
108
|
+
const [featureRequestOpen, setFeatureRequestOpen] = React.useState(false);
|
|
107
109
|
const [_open, _setOpen] = React.useState(defaultOpen);
|
|
108
110
|
const open = openProp != null ? openProp : _open;
|
|
109
111
|
const setOpenMenu = React.useCallback(
|
|
@@ -169,9 +171,13 @@ const SidebarProvider = React.forwardRef(
|
|
|
169
171
|
toggleMenuSidebar,
|
|
170
172
|
toggleInfoSidebar,
|
|
171
173
|
geocodeEarthApiKey,
|
|
172
|
-
geocoderUrl
|
|
174
|
+
geocoderUrl,
|
|
175
|
+
bugReportOpen,
|
|
176
|
+
setBugReportOpen,
|
|
177
|
+
featureRequestOpen,
|
|
178
|
+
setFeatureRequestOpen
|
|
173
179
|
}),
|
|
174
|
-
[sidebarState, open, setOpenMenu, isMobile, openMobile, setOpenMobile, openInfo, setOpenInfo, toggleMenuSidebar, toggleInfoSidebar, geocodeEarthApiKey, geocoderUrl]
|
|
180
|
+
[sidebarState, open, setOpenMenu, isMobile, openMobile, setOpenMobile, openInfo, setOpenInfo, toggleMenuSidebar, toggleInfoSidebar, geocodeEarthApiKey, geocoderUrl, bugReportOpen, featureRequestOpen]
|
|
175
181
|
);
|
|
176
182
|
return /* @__PURE__ */ jsx(SidebarContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(TooltipProvider, { delayDuration: 0, children: /* @__PURE__ */ jsxs(
|
|
177
183
|
"div",
|
|
@@ -194,12 +200,12 @@ const SidebarProvider = React.forwardRef(
|
|
|
194
200
|
"data-state": openInfo ? "open" : "closed",
|
|
195
201
|
"aria-hidden": !openInfo,
|
|
196
202
|
className: cn(
|
|
197
|
-
"fixed inset-y-0 z-40 w-[410px] transition-[transform,opacity] duration-300 ease-in-out will-change-transform",
|
|
203
|
+
"fixed inset-y-0 z-40 w-full sm:w-[410px] overflow-hidden transition-[transform,opacity] duration-300 ease-in-out will-change-transform",
|
|
198
204
|
openInfo ? "translate-x-0 opacity-100" : "-translate-x-full opacity-0 pointer-events-none"
|
|
199
205
|
),
|
|
200
206
|
style: {
|
|
201
|
-
left: open ? "var(--sidebar-width)" :
|
|
202
|
-
width: "400px"
|
|
207
|
+
left: isMobile ? "0" : open ? "var(--sidebar-width)" : "var(--sidebar-width-icon)",
|
|
208
|
+
width: isMobile ? "100%" : "400px"
|
|
203
209
|
},
|
|
204
210
|
children: /* @__PURE__ */ jsx(InfoSidebar, { minioBaseUrl, martinBaseUrl, organization, pointcloudApiUrl })
|
|
205
211
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/components/ui/Sidebar.tsx"],"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 { Slot } from '@radix-ui/react-slot'\r\nimport { VariantProps, cva } from 'class-variance-authority'\r\nimport * as LR from 'lucide-react'\r\n\r\nimport { cn } from '../../utils/utils'\r\nimport { Button } from './Button'\r\nimport { Input } from './Input'\r\nimport { Separator } from './Separator'\r\nimport {\r\n Sheet,\r\n SheetContent,\r\n SheetDescription,\r\n SheetHeader,\r\n SheetTitle,\r\n} from './Sheet'\r\nimport { Skeleton } from './Skeleton'\r\nimport {\r\n Tooltip,\r\n TooltipContent,\r\n TooltipProvider,\r\n TooltipTrigger,\r\n} from './Tooltip'\r\nimport { useTranslations } from 'next-intl'\r\n\r\n// Menus context\r\nimport { MenusContext } from '../../store/Menus/context'\r\n\r\n// Custom components\r\nimport NavigationBar from '../TopNavigationBar'\r\nimport { InfoSidebar } from './InfoSidebar'\r\nimport { useIsMobile } from '../../hooks/ui/use-mobile'\r\n\r\n\r\nconst SIDEBAR_COOKIE_NAME = 'sidebar_state'\r\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7\r\nconst SIDEBAR_WIDTH = '16rem'\r\nconst SIDEBAR_WIDTH_MOBILE = '18rem'\r\nconst SIDEBAR_WIDTH_ICON = '3rem'\r\nconst SIDEBAR_KEYBOARD_SHORTCUT = 'b'\r\n\r\ntype SidebarContextProps = {\r\n sidebarState: 'expanded' | 'collapsed'\r\n open: boolean\r\n setOpenMenu: (open: boolean) => void\r\n openMobile: boolean\r\n setOpenMobile: (open: boolean) => void\r\n openInfo: boolean\r\n setOpenInfo: (open: boolean) => void\r\n isMobile: boolean\r\n toggleMenuSidebar: () => void\r\n toggleInfoSidebar: () => void\r\n geocodeEarthApiKey?: string\r\n geocoderUrl?: string\r\n}\r\n\r\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null)\r\n\r\nfunction useSidebar() {\r\n const context = React.useContext(SidebarContext)\r\n if (!context) {\r\n throw new Error('useSidebar must be used within a SidebarProvider.')\r\n }\r\n\r\n return context\r\n}\r\n\r\nconst SidebarProvider = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'> & {\r\n defaultOpen?: boolean\r\n open?: boolean\r\n onOpenChange?: (open: boolean) => void\r\n minioBaseUrl?: string\r\n martinBaseUrl?: string\r\n organization?: import('../../types/dbTypes').Organization\r\n pointcloudApiUrl?: string\r\n geocodeEarthApiKey?: string\r\n geocoderUrl?: string\r\n }\r\n >(\r\n (\r\n {\r\n defaultOpen = false,\r\n open: openProp,\r\n onOpenChange: setOpenProp,\r\n className,\r\n style,\r\n children,\r\n minioBaseUrl,\r\n martinBaseUrl,\r\n organization,\r\n pointcloudApiUrl,\r\n geocodeEarthApiKey,\r\n geocoderUrl,\r\n ...props\r\n },\r\n ref,\r\n ) => {\r\n const isMobile = useIsMobile()\r\n const [openMobile, setOpenMobile] = React.useState(false)\r\n const [openInfo, setOpenInfo] = React.useState(false)\r\n\r\n // This is the internal state of the sidebar.\r\n // We use openProp and setOpenProp for control from outside the component.\r\n const [_open, _setOpen] = React.useState(defaultOpen)\r\n const open = openProp ?? _open\r\n const setOpenMenu = React.useCallback(\r\n (value: boolean | ((value: boolean) => boolean)) => {\r\n const openState = typeof value === 'function' ? value(open) : value\r\n if (setOpenProp) {\r\n setOpenProp(openState)\r\n }\r\n else {\r\n _setOpen(openState)\r\n }\r\n\r\n // This sets the cookie to keep the sidebar state.\r\n document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`\r\n },\r\n [setOpenProp, open],\r\n )\r\n\r\n // Helper to toggle the menu sidebar.\r\n const toggleMenuSidebar = React.useCallback(() => {\r\n if (isMobile) {\r\n setOpenMobile(open => !open)\r\n }\r\n else {\r\n setOpenMenu((open) => {\r\n const newOpenState = !open\r\n // If opening menu sidebar, close info sidebar\r\n // if (newOpenState && openInfo) {\r\n // setOpenInfo(false)\r\n // }\r\n return newOpenState\r\n })\r\n }\r\n }, [isMobile, setOpenMenu, setOpenMobile, openInfo, setOpenInfo])\r\n\r\n // Helper to toggle the info sidebar.\r\n const toggleInfoSidebar = React.useCallback(() => {\r\n setOpenInfo((openInfoState) => {\r\n const newOpenInfoState = !openInfoState\r\n // If opening info sidebar, close menu sidebar\r\n if (newOpenInfoState && (isMobile ? openMobile : open)) {\r\n if (isMobile) {\r\n setOpenMobile(false)\r\n }\r\n else {\r\n setOpenMenu(false)\r\n }\r\n }\r\n return newOpenInfoState\r\n })\r\n }, [setOpenInfo, open, openMobile, isMobile, setOpenMenu, setOpenMobile])\r\n\r\n // Adds a keyboard shortcut to toggle the sidebar.\r\n React.useEffect(() => {\r\n const handleKeyDown = (event: KeyboardEvent) => {\r\n if (\r\n event.key === SIDEBAR_KEYBOARD_SHORTCUT\r\n && (event.metaKey || event.ctrlKey)\r\n ) {\r\n event.preventDefault()\r\n toggleMenuSidebar()\r\n }\r\n\r\n // Close InfoSidebar on Escape key\r\n if (event.key === 'Escape' && openInfo) {\r\n event.preventDefault()\r\n setOpenInfo(false)\r\n }\r\n }\r\n\r\n window.addEventListener('keydown', handleKeyDown)\r\n return () => window.removeEventListener('keydown', handleKeyDown)\r\n }, [toggleMenuSidebar, openInfo, setOpenInfo])\r\n\r\n // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\r\n // On mobile, reflect the Sheet open state; on desktop, reflect the sidebar open state.\r\n const sidebarState = (isMobile ? openMobile : open) ? 'expanded' : 'collapsed'\r\n\r\n const contextValue = React.useMemo<SidebarContextProps>(\r\n () => ({\r\n sidebarState,\r\n open,\r\n setOpenMenu,\r\n isMobile,\r\n openMobile,\r\n setOpenMobile,\r\n openInfo,\r\n setOpenInfo,\r\n toggleMenuSidebar,\r\n toggleInfoSidebar,\r\n geocodeEarthApiKey,\r\n geocoderUrl,\r\n }),\r\n [sidebarState, open, setOpenMenu, isMobile, openMobile, setOpenMobile, openInfo, setOpenInfo, toggleMenuSidebar, toggleInfoSidebar, geocodeEarthApiKey, geocoderUrl],\r\n )\r\n\r\n return (\r\n <SidebarContext.Provider value={contextValue}>\r\n <TooltipProvider delayDuration={0}>\r\n <div\r\n style={\r\n {\r\n '--sidebar-width': SIDEBAR_WIDTH,\r\n '--sidebar-width-icon': SIDEBAR_WIDTH_ICON,\r\n ...style,\r\n } as React.CSSProperties\r\n }\r\n className={cn(\r\n 'group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar',\r\n className,\r\n )}\r\n ref={ref}\r\n {...props}\r\n >\r\n {children}\r\n\r\n {/* InfoSidebar overlay */}\r\n\r\n <div\r\n data-state={openInfo ? 'open' : 'closed'}\r\n aria-hidden={!openInfo}\r\n className={cn(\r\n 'fixed inset-y-0 z-40 w-[410px] transition-[transform,opacity] duration-300 ease-in-out will-change-transform',\r\n openInfo\r\n ? 'translate-x-0 opacity-100'\r\n : '-translate-x-full opacity-0 pointer-events-none'\r\n )}\r\n style={{\r\n left: open\r\n ? 'var(--sidebar-width)'\r\n : (isMobile ? '0' : 'var(--sidebar-width-icon)'),\r\n width: '400px',\r\n }}\r\n >\r\n <InfoSidebar minioBaseUrl={minioBaseUrl} martinBaseUrl={martinBaseUrl} organization={organization} pointcloudApiUrl={pointcloudApiUrl} />\r\n </div>\r\n </div>\r\n </TooltipProvider>\r\n </SidebarContext.Provider>\r\n )\r\n },\r\n )\r\nSidebarProvider.displayName = 'SidebarProvider'\r\nconst Sidebar = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'> & {\r\n side?: 'left' | 'right'\r\n variant?: 'sidebar' | 'floating' | 'inset'\r\n collapsible?: 'offcanvas' | 'icon' | 'none'\r\n }\r\n>(\r\n (\r\n {\r\n side = 'left',\r\n variant = 'sidebar',\r\n collapsible = 'offcanvas',\r\n className,\r\n children,\r\n ...props\r\n },\r\n ref,\r\n ) => {\r\n // Get auth state from MenusContext\r\n const { state, isAuthPage } = React.useContext(MenusContext)\r\n const { isMobile, sidebarState, openMobile, setOpenMobile } = useSidebar()\r\n\r\n // Translation\r\n const t = useTranslations('Sidebar')\r\n\r\n // Don't render sidebar at all for auth pages\r\n if (isAuthPage || state.menus.currentViewer === 'auth') {\r\n return null\r\n }\r\n\r\n if (collapsible === 'none') {\r\n return (\r\n <div\r\n className={cn(\r\n 'flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground',\r\n className,\r\n )}\r\n ref={ref}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n )\r\n }\r\n\r\n if (isMobile) {\r\n return (\r\n <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>\r\n <SheetContent\r\n data-sidebar=\"sidebar\"\r\n data-mobile=\"true\"\r\n className=\"w-[--sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden\"\r\n style={\r\n {\r\n '--sidebar-width': SIDEBAR_WIDTH_MOBILE,\r\n } as React.CSSProperties\r\n }\r\n side={side}\r\n >\r\n <SheetHeader className=\"sr-only\">\r\n <SheetTitle>{t('title')}</SheetTitle>\r\n <SheetDescription>{t('description')}</SheetDescription>\r\n </SheetHeader>\r\n <div className=\"flex h-full w-full flex-col\">{children}</div>\r\n </SheetContent>\r\n </Sheet>\r\n )\r\n }\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className=\"group peer text-sidebar-foreground md:block\" // removed default hidden class\r\n data-state={sidebarState}\r\n data-collapsible={sidebarState === 'collapsed' ? collapsible : ''}\r\n data-variant={variant}\r\n data-side={side}\r\n >\r\n {/* This is what handles the sidebar gap on desktop */}\r\n <div\r\n className={cn(\r\n 'relative w-[--sidebar-width] bg-transparent transition-[width] duration-200 ease-linear',\r\n 'group-data-[collapsible=offcanvas]:w-0',\r\n 'group-data-[side=right]:rotate-180',\r\n variant === 'floating' || variant === 'inset'\r\n ? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]'\r\n : 'group-data-[collapsible=icon]:w-[--sidebar-width-icon]',\r\n )}\r\n />\r\n <div\r\n className={cn(\r\n // removed default hidden class\r\n 'fixed inset-y-0 z-10 h-svh w-[--sidebar-width] transition-[left,right,width] duration-200 ease-linear md:flex',\r\n side === 'left'\r\n ? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'\r\n : 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',\r\n // Adjust the padding for floating and inset variants.\r\n variant === 'floating' || variant === 'inset'\r\n ? 'p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]'\r\n : 'group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l',\r\n className,\r\n )}\r\n {...props}\r\n >\r\n <div\r\n data-sidebar=\"sidebar\"\r\n className=\"flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow\"\r\n >\r\n {children}\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n },\r\n)\r\nSidebar.displayName = 'Sidebar'\r\n\r\nconst SidebarTrigger = React.forwardRef<\r\n React.ElementRef<typeof Button>,\r\n React.ComponentProps<typeof Button>\r\n>(({ className, onClick, ...props }, ref) => {\r\n const { toggleMenuSidebar, geocodeEarthApiKey, geocoderUrl } = useSidebar()\r\n\r\n const { state } = React.useContext(MenusContext)\r\n const currentViewer = state.menus.currentViewer\r\n\r\n if (currentViewer === 'auth') return null\r\n\r\n // Render MenuButtons only for interactive viewers\r\n if (currentViewer === 'map' || currentViewer === 'bim' || currentViewer === 'pointcloud') {\r\n return <NavigationBar geocodeEarthApiKey={geocodeEarthApiKey} geocoderUrl={geocoderUrl} />\r\n }\r\n\r\n // Default trigger for all other content types\r\n return (\r\n <Button\r\n ref={ref}\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n data-sidebar=\"trigger\"\r\n onClick={(e) => {\r\n toggleMenuSidebar()\r\n onClick?.(e)\r\n }}\r\n\r\n className={cn(\r\n '',\r\n className,\r\n 'opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent',\r\n )}\r\n {...props}\r\n >\r\n <LR.PanelLeft />\r\n <span className=\"sr-only\">Toggle Sidebar</span>\r\n </Button>\r\n )\r\n})\r\nSidebarTrigger.displayName = 'SidebarTrigger'\r\n\r\nconst SidebarRail = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentProps<'button'>\r\n>(({ className, ...props }, ref) => {\r\n const { toggleMenuSidebar } = useSidebar()\r\n\r\n return (\r\n <button\r\n ref={ref}\r\n data-sidebar=\"rail\"\r\n aria-label=\"Toggle Sidebar\"\r\n tabIndex={-1}\r\n onClick={toggleMenuSidebar}\r\n title=\"Toggle Sidebar\"\r\n className={cn(\r\n // removed default hidden class\r\n 'absolute inset-y-0 z-20 w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex',\r\n '[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize',\r\n '[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize',\r\n 'group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar',\r\n '[[data-side=left][data-collapsible=offcanvas]_&]:-right-2',\r\n '[[data-side=right][data-collapsible=offcanvas]_&]:-left-2',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarRail.displayName = 'SidebarRail'\r\n\r\nconst SidebarInset = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'main'>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <main\r\n ref={ref}\r\n className={cn(\r\n 'relative flex w-full flex-1 flex-col bg-background',\r\n 'md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarInset.displayName = 'SidebarInset'\r\n\r\nconst SidebarInput = React.forwardRef<\r\n React.ElementRef<typeof Input>,\r\n React.ComponentProps<typeof Input>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <Input\r\n ref={ref}\r\n data-sidebar=\"input\"\r\n className={cn(\r\n 'h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarInput.displayName = 'SidebarInput'\r\n\r\nconst SidebarHeader = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"header\"\r\n className={cn('flex flex-col gap-2 p-2', className)}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarHeader.displayName = 'SidebarHeader'\r\n\r\nconst SidebarFooter = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"footer\"\r\n className={cn('flex flex-col gap-2 p-2', className)}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarFooter.displayName = 'SidebarFooter'\r\n\r\nconst SidebarSeparator = React.forwardRef<\r\n React.ElementRef<typeof Separator>,\r\n React.ComponentProps<typeof Separator>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <Separator\r\n ref={ref}\r\n data-sidebar=\"separator\"\r\n className={cn('mx-2 w-auto bg-sidebar-border', className)}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarSeparator.displayName = 'SidebarSeparator'\r\n\r\nconst SidebarContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"content\"\r\n className={cn(\r\n 'flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarContent.displayName = 'SidebarContent'\r\n\r\nconst SidebarGroup = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"group\"\r\n className={cn('relative flex w-full min-w-0 flex-col p-2', className)}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarGroup.displayName = 'SidebarGroup'\r\n\r\nconst SidebarGroupLabel = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'> & { asChild?: boolean }\r\n>(({ className, asChild = false, ...props }, ref) => {\r\n const Comp = asChild ? Slot : 'div'\r\n\r\n return (\r\n <Comp\r\n ref={ref}\r\n data-sidebar=\"group-label\"\r\n className={cn(\r\n 'flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',\r\n 'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarGroupLabel.displayName = 'SidebarGroupLabel'\r\n\r\nconst SidebarGroupAction = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentProps<'button'> & { asChild?: boolean }\r\n>(({ className, asChild = false, ...props }, ref) => {\r\n const Comp = asChild ? Slot : 'button'\r\n\r\n return (\r\n <Comp\r\n ref={ref}\r\n data-sidebar=\"group-action\"\r\n className={cn(\r\n 'absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',\r\n // Increases the hit area of the button on mobile.\r\n 'after:absolute after:-inset-2 after:md:hidden',\r\n 'group-data-[collapsible=icon]:hidden',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarGroupAction.displayName = 'SidebarGroupAction'\r\n\r\nconst SidebarGroupContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"group-content\"\r\n className={cn('w-full text-sm', className)}\r\n {...props}\r\n />\r\n))\r\nSidebarGroupContent.displayName = 'SidebarGroupContent'\r\n\r\nconst SidebarMenu = React.forwardRef<\r\n HTMLUListElement,\r\n React.ComponentProps<'ul'>\r\n>(({ className, ...props }, ref) => (\r\n <ul\r\n ref={ref}\r\n data-sidebar=\"menu\"\r\n className={cn('flex w-full min-w-0 flex-col gap-1', className)}\r\n {...props}\r\n />\r\n))\r\nSidebarMenu.displayName = 'SidebarMenu'\r\n\r\nconst SidebarMenuItem = React.forwardRef<\r\n HTMLLIElement,\r\n React.ComponentProps<'li'>\r\n>(({ className, ...props }, ref) => (\r\n <li\r\n ref={ref}\r\n data-sidebar=\"menu-item\"\r\n className={cn('group/menu-item relative', className)}\r\n {...props}\r\n />\r\n))\r\nSidebarMenuItem.displayName = 'SidebarMenuItem'\r\n\r\nconst sidebarMenuButtonVariants = cva(\r\n 'peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',\r\n {\r\n variants: {\r\n variant: {\r\n default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',\r\n outline:\r\n 'bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]',\r\n },\r\n size: {\r\n default: 'h-8 text-sm',\r\n sm: 'h-7 text-xs',\r\n lg: 'h-12 text-sm group-data-[collapsible=icon]:!p-0',\r\n },\r\n },\r\n defaultVariants: {\r\n variant: 'default',\r\n size: 'default',\r\n },\r\n },\r\n)\r\n\r\nconst SidebarMenuButton = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentProps<'button'> & {\r\n asChild?: boolean\r\n isActive?: boolean\r\n tooltip?: string | React.ComponentProps<typeof TooltipContent>\r\n } & VariantProps<typeof sidebarMenuButtonVariants>\r\n>(\r\n (\r\n {\r\n asChild = false,\r\n isActive = false,\r\n variant = 'default',\r\n size = 'default',\r\n tooltip,\r\n className,\r\n ...props\r\n },\r\n ref,\r\n ) => {\r\n const Comp = asChild ? Slot : 'button'\r\n const { isMobile, sidebarState } = useSidebar()\r\n\r\n const button = (\r\n <Comp\r\n ref={ref}\r\n data-sidebar=\"menu-button\"\r\n data-size={size}\r\n data-active={isActive}\r\n className={cn(sidebarMenuButtonVariants({ variant, size }), className)}\r\n {...props}\r\n />\r\n )\r\n\r\n if (!tooltip) {\r\n return button\r\n }\r\n\r\n if (typeof tooltip === 'string') {\r\n tooltip = {\r\n children: tooltip,\r\n }\r\n }\r\n\r\n return (\r\n <Tooltip>\r\n <TooltipTrigger asChild>{button}</TooltipTrigger>\r\n <TooltipContent\r\n side=\"right\"\r\n align=\"center\"\r\n hidden={sidebarState !== 'collapsed' || isMobile}\r\n {...tooltip}\r\n />\r\n </Tooltip>\r\n )\r\n },\r\n)\r\nSidebarMenuButton.displayName = 'SidebarMenuButton'\r\n\r\nconst SidebarMenuAction = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentProps<'button'> & {\r\n asChild?: boolean\r\n showOnHover?: boolean\r\n }\r\n>(({ className, asChild = false, showOnHover = false, ...props }, ref) => {\r\n const Comp = asChild ? Slot : 'button'\r\n\r\n return (\r\n <Comp\r\n ref={ref}\r\n data-sidebar=\"menu-action\"\r\n className={cn(\r\n 'absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0',\r\n // Increases the hit area of the button on mobile.\r\n 'after:absolute after:-inset-2 after:md:hidden',\r\n 'peer-data-[size=sm]/menu-button:top-1',\r\n 'peer-data-[size=default]/menu-button:top-1.5',\r\n 'peer-data-[size=lg]/menu-button:top-2.5',\r\n 'group-data-[collapsible=icon]:hidden',\r\n showOnHover\r\n && 'group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarMenuAction.displayName = 'SidebarMenuAction'\r\n\r\nconst SidebarMenuBadge = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"menu-badge\"\r\n className={cn(\r\n 'pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground',\r\n 'peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground',\r\n 'peer-data-[size=sm]/menu-button:top-1',\r\n 'peer-data-[size=default]/menu-button:top-1.5',\r\n 'peer-data-[size=lg]/menu-button:top-2.5',\r\n 'group-data-[collapsible=icon]:hidden',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nSidebarMenuBadge.displayName = 'SidebarMenuBadge'\r\n\r\nconst SidebarMenuSkeleton = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'> & {\r\n showIcon?: boolean\r\n }\r\n>(({ className, showIcon = false, ...props }, ref) => {\r\n // Random width between 50 to 90%.\r\n const width = React.useMemo(() => {\r\n return `${Math.floor(Math.random() * 40) + 50}%`\r\n }, [])\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"menu-skeleton\"\r\n className={cn('flex h-8 items-center gap-2 rounded-md px-2', className)}\r\n {...props}\r\n >\r\n {showIcon && (\r\n <Skeleton\r\n className=\"size-4 rounded-md\"\r\n data-sidebar=\"menu-skeleton-icon\"\r\n />\r\n )}\r\n <Skeleton\r\n className=\"h-4 max-w-[--skeleton-width] flex-1\"\r\n data-sidebar=\"menu-skeleton-text\"\r\n style={\r\n {\r\n '--skeleton-width': width,\r\n } as React.CSSProperties\r\n }\r\n />\r\n </div>\r\n )\r\n})\r\nSidebarMenuSkeleton.displayName = 'SidebarMenuSkeleton'\r\n\r\nconst SidebarMenuSub = React.forwardRef<\r\n HTMLUListElement,\r\n React.ComponentProps<'ul'>\r\n>(({ className, ...props }, ref) => (\r\n <ul\r\n ref={ref}\r\n data-sidebar=\"menu-sub\"\r\n className={cn(\r\n 'mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5',\r\n 'group-data-[collapsible=icon]:hidden',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nSidebarMenuSub.displayName = 'SidebarMenuSub'\r\n\r\nconst SidebarMenuSubItem = React.forwardRef<\r\n HTMLLIElement,\r\n React.ComponentProps<'li'>\r\n>(({ ...props }, ref) => <li ref={ref} {...props} />)\r\nSidebarMenuSubItem.displayName = 'SidebarMenuSubItem'\r\n\r\nconst SidebarMenuSubButton = React.forwardRef<\r\n HTMLAnchorElement,\r\n React.ComponentProps<'a'> & {\r\n asChild?: boolean\r\n size?: 'sm' | 'md'\r\n isActive?: boolean\r\n }\r\n>(({ asChild = false, size = 'md', isActive, className, ...props }, ref) => {\r\n const Comp = asChild ? Slot : 'a'\r\n\r\n return (\r\n <Comp\r\n ref={ref}\r\n data-sidebar=\"menu-sub-button\"\r\n data-size={size}\r\n data-active={isActive}\r\n className={cn(\r\n 'flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground',\r\n 'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',\r\n size === 'sm' && 'text-xs',\r\n size === 'md' && 'text-sm',\r\n 'group-data-[collapsible=icon]:hidden',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarMenuSubButton.displayName = 'SidebarMenuSubButton'\r\n\r\nexport {\r\n Sidebar,\r\n SidebarContent,\r\n SidebarFooter,\r\n SidebarGroup,\r\n SidebarGroupAction,\r\n SidebarGroupContent,\r\n SidebarGroupLabel,\r\n SidebarHeader,\r\n SidebarInput,\r\n SidebarInset,\r\n SidebarMenu,\r\n SidebarMenuAction,\r\n SidebarMenuBadge,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n SidebarMenuSkeleton,\r\n SidebarMenuSub,\r\n SidebarMenuSubButton,\r\n SidebarMenuSubItem,\r\n SidebarProvider,\r\n SidebarRail,\r\n SidebarSeparator,\r\n SidebarTrigger,\r\n useSidebar,\r\n}\r\n"],"mappings":"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","names":["open"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/components/ui/Sidebar.tsx"],"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 { Slot } from '@radix-ui/react-slot'\r\nimport { VariantProps, cva } from 'class-variance-authority'\r\nimport * as LR from 'lucide-react'\r\n\r\nimport { cn } from '../../utils/utils'\r\nimport { Button } from './Button'\r\nimport { Input } from './Input'\r\nimport { Separator } from './Separator'\r\nimport {\r\n Sheet,\r\n SheetContent,\r\n SheetDescription,\r\n SheetHeader,\r\n SheetTitle,\r\n} from './Sheet'\r\nimport { Skeleton } from './Skeleton'\r\nimport {\r\n Tooltip,\r\n TooltipContent,\r\n TooltipProvider,\r\n TooltipTrigger,\r\n} from './Tooltip'\r\nimport { useTranslations } from 'next-intl'\r\n\r\n// Menus context\r\nimport { MenusContext } from '../../store/Menus/context'\r\n\r\n// Custom components\r\nimport NavigationBar from '../TopNavigationBar'\r\nimport { InfoSidebar } from './InfoSidebar'\r\nimport { useIsMobile } from '../../hooks/ui/use-mobile'\r\n\r\n\r\nconst SIDEBAR_COOKIE_NAME = 'sidebar_state'\r\nconst SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7\r\nconst SIDEBAR_WIDTH = '16rem'\r\nconst SIDEBAR_WIDTH_MOBILE = '18rem'\r\nconst SIDEBAR_WIDTH_ICON = '3rem'\r\nconst SIDEBAR_KEYBOARD_SHORTCUT = 'b'\r\n\r\ntype SidebarContextProps = {\r\n sidebarState: 'expanded' | 'collapsed'\r\n open: boolean\r\n setOpenMenu: (open: boolean) => void\r\n openMobile: boolean\r\n setOpenMobile: (open: boolean) => void\r\n openInfo: boolean\r\n setOpenInfo: (open: boolean) => void\r\n isMobile: boolean\r\n toggleMenuSidebar: () => void\r\n toggleInfoSidebar: () => void\r\n geocodeEarthApiKey?: string\r\n geocoderUrl?: string\r\n // Rendered outside the mobile Sheet (see AppSidebar) so they survive the\r\n // Sheet closing — Radix unmounts the Sheet's whole subtree on close, which\r\n // would otherwise take these dialogs down with it right after they open.\r\n bugReportOpen: boolean\r\n setBugReportOpen: (open: boolean) => void\r\n featureRequestOpen: boolean\r\n setFeatureRequestOpen: (open: boolean) => void\r\n}\r\n\r\nconst SidebarContext = React.createContext<SidebarContextProps | null>(null)\r\n\r\nfunction useSidebar() {\r\n const context = React.useContext(SidebarContext)\r\n if (!context) {\r\n throw new Error('useSidebar must be used within a SidebarProvider.')\r\n }\r\n\r\n return context\r\n}\r\n\r\nconst SidebarProvider = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'> & {\r\n defaultOpen?: boolean\r\n open?: boolean\r\n onOpenChange?: (open: boolean) => void\r\n minioBaseUrl?: string\r\n martinBaseUrl?: string\r\n organization?: import('../../types/dbTypes').Organization\r\n pointcloudApiUrl?: string\r\n geocodeEarthApiKey?: string\r\n geocoderUrl?: string\r\n }\r\n >(\r\n (\r\n {\r\n defaultOpen = false,\r\n open: openProp,\r\n onOpenChange: setOpenProp,\r\n className,\r\n style,\r\n children,\r\n minioBaseUrl,\r\n martinBaseUrl,\r\n organization,\r\n pointcloudApiUrl,\r\n geocodeEarthApiKey,\r\n geocoderUrl,\r\n ...props\r\n },\r\n ref,\r\n ) => {\r\n const isMobile = useIsMobile()\r\n const [openMobile, setOpenMobile] = React.useState(false)\r\n const [openInfo, setOpenInfo] = React.useState(false)\r\n const [bugReportOpen, setBugReportOpen] = React.useState(false)\r\n const [featureRequestOpen, setFeatureRequestOpen] = React.useState(false)\r\n\r\n // This is the internal state of the sidebar.\r\n // We use openProp and setOpenProp for control from outside the component.\r\n const [_open, _setOpen] = React.useState(defaultOpen)\r\n const open = openProp ?? _open\r\n const setOpenMenu = React.useCallback(\r\n (value: boolean | ((value: boolean) => boolean)) => {\r\n const openState = typeof value === 'function' ? value(open) : value\r\n if (setOpenProp) {\r\n setOpenProp(openState)\r\n }\r\n else {\r\n _setOpen(openState)\r\n }\r\n\r\n // This sets the cookie to keep the sidebar state.\r\n document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`\r\n },\r\n [setOpenProp, open],\r\n )\r\n\r\n // Helper to toggle the menu sidebar.\r\n const toggleMenuSidebar = React.useCallback(() => {\r\n if (isMobile) {\r\n setOpenMobile(open => !open)\r\n }\r\n else {\r\n setOpenMenu((open) => {\r\n const newOpenState = !open\r\n // If opening menu sidebar, close info sidebar\r\n // if (newOpenState && openInfo) {\r\n // setOpenInfo(false)\r\n // }\r\n return newOpenState\r\n })\r\n }\r\n }, [isMobile, setOpenMenu, setOpenMobile, openInfo, setOpenInfo])\r\n\r\n // Helper to toggle the info sidebar.\r\n const toggleInfoSidebar = React.useCallback(() => {\r\n setOpenInfo((openInfoState) => {\r\n const newOpenInfoState = !openInfoState\r\n // If opening info sidebar, close menu sidebar\r\n if (newOpenInfoState && (isMobile ? openMobile : open)) {\r\n if (isMobile) {\r\n setOpenMobile(false)\r\n }\r\n else {\r\n setOpenMenu(false)\r\n }\r\n }\r\n return newOpenInfoState\r\n })\r\n }, [setOpenInfo, open, openMobile, isMobile, setOpenMenu, setOpenMobile])\r\n\r\n // Adds a keyboard shortcut to toggle the sidebar.\r\n React.useEffect(() => {\r\n const handleKeyDown = (event: KeyboardEvent) => {\r\n if (\r\n event.key === SIDEBAR_KEYBOARD_SHORTCUT\r\n && (event.metaKey || event.ctrlKey)\r\n ) {\r\n event.preventDefault()\r\n toggleMenuSidebar()\r\n }\r\n\r\n // Close InfoSidebar on Escape key\r\n if (event.key === 'Escape' && openInfo) {\r\n event.preventDefault()\r\n setOpenInfo(false)\r\n }\r\n }\r\n\r\n window.addEventListener('keydown', handleKeyDown)\r\n return () => window.removeEventListener('keydown', handleKeyDown)\r\n }, [toggleMenuSidebar, openInfo, setOpenInfo])\r\n\r\n // We add a state so that we can do data-state=\"expanded\" or \"collapsed\".\r\n // On mobile, reflect the Sheet open state; on desktop, reflect the sidebar open state.\r\n const sidebarState = (isMobile ? openMobile : open) ? 'expanded' : 'collapsed'\r\n\r\n const contextValue = React.useMemo<SidebarContextProps>(\r\n () => ({\r\n sidebarState,\r\n open,\r\n setOpenMenu,\r\n isMobile,\r\n openMobile,\r\n setOpenMobile,\r\n openInfo,\r\n setOpenInfo,\r\n toggleMenuSidebar,\r\n toggleInfoSidebar,\r\n geocodeEarthApiKey,\r\n geocoderUrl,\r\n bugReportOpen,\r\n setBugReportOpen,\r\n featureRequestOpen,\r\n setFeatureRequestOpen,\r\n }),\r\n [sidebarState, open, setOpenMenu, isMobile, openMobile, setOpenMobile, openInfo, setOpenInfo, toggleMenuSidebar, toggleInfoSidebar, geocodeEarthApiKey, geocoderUrl, bugReportOpen, featureRequestOpen],\r\n )\r\n\r\n return (\r\n <SidebarContext.Provider value={contextValue}>\r\n <TooltipProvider delayDuration={0}>\r\n <div\r\n style={\r\n {\r\n '--sidebar-width': SIDEBAR_WIDTH,\r\n '--sidebar-width-icon': SIDEBAR_WIDTH_ICON,\r\n ...style,\r\n } as React.CSSProperties\r\n }\r\n className={cn(\r\n 'group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar',\r\n className,\r\n )}\r\n ref={ref}\r\n {...props}\r\n >\r\n {children}\r\n\r\n {/* InfoSidebar overlay */}\r\n\r\n <div\r\n data-state={openInfo ? 'open' : 'closed'}\r\n aria-hidden={!openInfo}\r\n className={cn(\r\n 'fixed inset-y-0 z-40 w-full sm:w-[410px] overflow-hidden transition-[transform,opacity] duration-300 ease-in-out will-change-transform',\r\n openInfo\r\n ? 'translate-x-0 opacity-100'\r\n : '-translate-x-full opacity-0 pointer-events-none'\r\n )}\r\n style={{\r\n left: isMobile\r\n ? '0'\r\n : (open ? 'var(--sidebar-width)' : 'var(--sidebar-width-icon)'),\r\n width: isMobile ? '100%' : '400px',\r\n }}\r\n >\r\n <InfoSidebar minioBaseUrl={minioBaseUrl} martinBaseUrl={martinBaseUrl} organization={organization} pointcloudApiUrl={pointcloudApiUrl} />\r\n </div>\r\n </div>\r\n </TooltipProvider>\r\n </SidebarContext.Provider>\r\n )\r\n },\r\n )\r\nSidebarProvider.displayName = 'SidebarProvider'\r\nconst Sidebar = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'> & {\r\n side?: 'left' | 'right'\r\n variant?: 'sidebar' | 'floating' | 'inset'\r\n collapsible?: 'offcanvas' | 'icon' | 'none'\r\n }\r\n>(\r\n (\r\n {\r\n side = 'left',\r\n variant = 'sidebar',\r\n collapsible = 'offcanvas',\r\n className,\r\n children,\r\n ...props\r\n },\r\n ref,\r\n ) => {\r\n // Get auth state from MenusContext\r\n const { state, isAuthPage } = React.useContext(MenusContext)\r\n const { isMobile, sidebarState, openMobile, setOpenMobile } = useSidebar()\r\n\r\n // Translation\r\n const t = useTranslations('Sidebar')\r\n\r\n // Don't render sidebar at all for auth pages\r\n if (isAuthPage || state.menus.currentViewer === 'auth') {\r\n return null\r\n }\r\n\r\n if (collapsible === 'none') {\r\n return (\r\n <div\r\n className={cn(\r\n 'flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground',\r\n className,\r\n )}\r\n ref={ref}\r\n {...props}\r\n >\r\n {children}\r\n </div>\r\n )\r\n }\r\n\r\n if (isMobile) {\r\n return (\r\n <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>\r\n <SheetContent\r\n data-sidebar=\"sidebar\"\r\n data-mobile=\"true\"\r\n className=\"w-[--sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden\"\r\n style={\r\n {\r\n '--sidebar-width': SIDEBAR_WIDTH_MOBILE,\r\n } as React.CSSProperties\r\n }\r\n side={side}\r\n >\r\n <SheetHeader className=\"sr-only\">\r\n <SheetTitle>{t('title')}</SheetTitle>\r\n <SheetDescription>{t('description')}</SheetDescription>\r\n </SheetHeader>\r\n <div className=\"flex h-full w-full flex-col\">{children}</div>\r\n </SheetContent>\r\n </Sheet>\r\n )\r\n }\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className=\"group peer text-sidebar-foreground md:block\" // removed default hidden class\r\n data-state={sidebarState}\r\n data-collapsible={sidebarState === 'collapsed' ? collapsible : ''}\r\n data-variant={variant}\r\n data-side={side}\r\n >\r\n {/* This is what handles the sidebar gap on desktop */}\r\n <div\r\n className={cn(\r\n 'relative w-[--sidebar-width] bg-transparent transition-[width] duration-200 ease-linear',\r\n 'group-data-[collapsible=offcanvas]:w-0',\r\n 'group-data-[side=right]:rotate-180',\r\n variant === 'floating' || variant === 'inset'\r\n ? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]'\r\n : 'group-data-[collapsible=icon]:w-[--sidebar-width-icon]',\r\n )}\r\n />\r\n <div\r\n className={cn(\r\n // removed default hidden class\r\n 'fixed inset-y-0 z-10 h-svh w-[--sidebar-width] transition-[left,right,width] duration-200 ease-linear md:flex',\r\n side === 'left'\r\n ? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'\r\n : 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',\r\n // Adjust the padding for floating and inset variants.\r\n variant === 'floating' || variant === 'inset'\r\n ? 'p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]'\r\n : 'group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l',\r\n className,\r\n )}\r\n {...props}\r\n >\r\n <div\r\n data-sidebar=\"sidebar\"\r\n className=\"flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow\"\r\n >\r\n {children}\r\n </div>\r\n </div>\r\n </div>\r\n )\r\n },\r\n)\r\nSidebar.displayName = 'Sidebar'\r\n\r\nconst SidebarTrigger = React.forwardRef<\r\n React.ElementRef<typeof Button>,\r\n React.ComponentProps<typeof Button>\r\n>(({ className, onClick, ...props }, ref) => {\r\n const { toggleMenuSidebar, geocodeEarthApiKey, geocoderUrl } = useSidebar()\r\n\r\n const { state } = React.useContext(MenusContext)\r\n const currentViewer = state.menus.currentViewer\r\n\r\n if (currentViewer === 'auth') return null\r\n\r\n // Render MenuButtons only for interactive viewers\r\n if (currentViewer === 'map' || currentViewer === 'bim' || currentViewer === 'pointcloud') {\r\n return <NavigationBar geocodeEarthApiKey={geocodeEarthApiKey} geocoderUrl={geocoderUrl} />\r\n }\r\n\r\n // Default trigger for all other content types\r\n return (\r\n <Button\r\n ref={ref}\r\n variant=\"ghost\"\r\n size=\"icon\"\r\n data-sidebar=\"trigger\"\r\n onClick={(e) => {\r\n toggleMenuSidebar()\r\n onClick?.(e)\r\n }}\r\n\r\n className={cn(\r\n '',\r\n className,\r\n 'opacity-70 hover:opacity-100 transition-opacity duration-200 hover:bg-transparent',\r\n )}\r\n {...props}\r\n >\r\n <LR.PanelLeft />\r\n <span className=\"sr-only\">Toggle Sidebar</span>\r\n </Button>\r\n )\r\n})\r\nSidebarTrigger.displayName = 'SidebarTrigger'\r\n\r\nconst SidebarRail = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentProps<'button'>\r\n>(({ className, ...props }, ref) => {\r\n const { toggleMenuSidebar } = useSidebar()\r\n\r\n return (\r\n <button\r\n ref={ref}\r\n data-sidebar=\"rail\"\r\n aria-label=\"Toggle Sidebar\"\r\n tabIndex={-1}\r\n onClick={toggleMenuSidebar}\r\n title=\"Toggle Sidebar\"\r\n className={cn(\r\n // removed default hidden class\r\n 'absolute inset-y-0 z-20 w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex',\r\n '[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize',\r\n '[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize',\r\n 'group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar',\r\n '[[data-side=left][data-collapsible=offcanvas]_&]:-right-2',\r\n '[[data-side=right][data-collapsible=offcanvas]_&]:-left-2',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarRail.displayName = 'SidebarRail'\r\n\r\nconst SidebarInset = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'main'>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <main\r\n ref={ref}\r\n className={cn(\r\n 'relative flex w-full flex-1 flex-col bg-background',\r\n 'md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarInset.displayName = 'SidebarInset'\r\n\r\nconst SidebarInput = React.forwardRef<\r\n React.ElementRef<typeof Input>,\r\n React.ComponentProps<typeof Input>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <Input\r\n ref={ref}\r\n data-sidebar=\"input\"\r\n className={cn(\r\n 'h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarInput.displayName = 'SidebarInput'\r\n\r\nconst SidebarHeader = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"header\"\r\n className={cn('flex flex-col gap-2 p-2', className)}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarHeader.displayName = 'SidebarHeader'\r\n\r\nconst SidebarFooter = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"footer\"\r\n className={cn('flex flex-col gap-2 p-2', className)}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarFooter.displayName = 'SidebarFooter'\r\n\r\nconst SidebarSeparator = React.forwardRef<\r\n React.ElementRef<typeof Separator>,\r\n React.ComponentProps<typeof Separator>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <Separator\r\n ref={ref}\r\n data-sidebar=\"separator\"\r\n className={cn('mx-2 w-auto bg-sidebar-border', className)}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarSeparator.displayName = 'SidebarSeparator'\r\n\r\nconst SidebarContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"content\"\r\n className={cn(\r\n 'flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarContent.displayName = 'SidebarContent'\r\n\r\nconst SidebarGroup = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => {\r\n return (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"group\"\r\n className={cn('relative flex w-full min-w-0 flex-col p-2', className)}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarGroup.displayName = 'SidebarGroup'\r\n\r\nconst SidebarGroupLabel = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'> & { asChild?: boolean }\r\n>(({ className, asChild = false, ...props }, ref) => {\r\n const Comp = asChild ? Slot : 'div'\r\n\r\n return (\r\n <Comp\r\n ref={ref}\r\n data-sidebar=\"group-label\"\r\n className={cn(\r\n 'flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',\r\n 'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarGroupLabel.displayName = 'SidebarGroupLabel'\r\n\r\nconst SidebarGroupAction = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentProps<'button'> & { asChild?: boolean }\r\n>(({ className, asChild = false, ...props }, ref) => {\r\n const Comp = asChild ? Slot : 'button'\r\n\r\n return (\r\n <Comp\r\n ref={ref}\r\n data-sidebar=\"group-action\"\r\n className={cn(\r\n 'absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',\r\n // Increases the hit area of the button on mobile.\r\n 'after:absolute after:-inset-2 after:md:hidden',\r\n 'group-data-[collapsible=icon]:hidden',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarGroupAction.displayName = 'SidebarGroupAction'\r\n\r\nconst SidebarGroupContent = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"group-content\"\r\n className={cn('w-full text-sm', className)}\r\n {...props}\r\n />\r\n))\r\nSidebarGroupContent.displayName = 'SidebarGroupContent'\r\n\r\nconst SidebarMenu = React.forwardRef<\r\n HTMLUListElement,\r\n React.ComponentProps<'ul'>\r\n>(({ className, ...props }, ref) => (\r\n <ul\r\n ref={ref}\r\n data-sidebar=\"menu\"\r\n className={cn('flex w-full min-w-0 flex-col gap-1', className)}\r\n {...props}\r\n />\r\n))\r\nSidebarMenu.displayName = 'SidebarMenu'\r\n\r\nconst SidebarMenuItem = React.forwardRef<\r\n HTMLLIElement,\r\n React.ComponentProps<'li'>\r\n>(({ className, ...props }, ref) => (\r\n <li\r\n ref={ref}\r\n data-sidebar=\"menu-item\"\r\n className={cn('group/menu-item relative', className)}\r\n {...props}\r\n />\r\n))\r\nSidebarMenuItem.displayName = 'SidebarMenuItem'\r\n\r\nconst sidebarMenuButtonVariants = cva(\r\n 'peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',\r\n {\r\n variants: {\r\n variant: {\r\n default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',\r\n outline:\r\n 'bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]',\r\n },\r\n size: {\r\n default: 'h-8 text-sm',\r\n sm: 'h-7 text-xs',\r\n lg: 'h-12 text-sm group-data-[collapsible=icon]:!p-0',\r\n },\r\n },\r\n defaultVariants: {\r\n variant: 'default',\r\n size: 'default',\r\n },\r\n },\r\n)\r\n\r\nconst SidebarMenuButton = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentProps<'button'> & {\r\n asChild?: boolean\r\n isActive?: boolean\r\n tooltip?: string | React.ComponentProps<typeof TooltipContent>\r\n } & VariantProps<typeof sidebarMenuButtonVariants>\r\n>(\r\n (\r\n {\r\n asChild = false,\r\n isActive = false,\r\n variant = 'default',\r\n size = 'default',\r\n tooltip,\r\n className,\r\n ...props\r\n },\r\n ref,\r\n ) => {\r\n const Comp = asChild ? Slot : 'button'\r\n const { isMobile, sidebarState } = useSidebar()\r\n\r\n const button = (\r\n <Comp\r\n ref={ref}\r\n data-sidebar=\"menu-button\"\r\n data-size={size}\r\n data-active={isActive}\r\n className={cn(sidebarMenuButtonVariants({ variant, size }), className)}\r\n {...props}\r\n />\r\n )\r\n\r\n if (!tooltip) {\r\n return button\r\n }\r\n\r\n if (typeof tooltip === 'string') {\r\n tooltip = {\r\n children: tooltip,\r\n }\r\n }\r\n\r\n return (\r\n <Tooltip>\r\n <TooltipTrigger asChild>{button}</TooltipTrigger>\r\n <TooltipContent\r\n side=\"right\"\r\n align=\"center\"\r\n hidden={sidebarState !== 'collapsed' || isMobile}\r\n {...tooltip}\r\n />\r\n </Tooltip>\r\n )\r\n },\r\n)\r\nSidebarMenuButton.displayName = 'SidebarMenuButton'\r\n\r\nconst SidebarMenuAction = React.forwardRef<\r\n HTMLButtonElement,\r\n React.ComponentProps<'button'> & {\r\n asChild?: boolean\r\n showOnHover?: boolean\r\n }\r\n>(({ className, asChild = false, showOnHover = false, ...props }, ref) => {\r\n const Comp = asChild ? Slot : 'button'\r\n\r\n return (\r\n <Comp\r\n ref={ref}\r\n data-sidebar=\"menu-action\"\r\n className={cn(\r\n 'absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0',\r\n // Increases the hit area of the button on mobile.\r\n 'after:absolute after:-inset-2 after:md:hidden',\r\n 'peer-data-[size=sm]/menu-button:top-1',\r\n 'peer-data-[size=default]/menu-button:top-1.5',\r\n 'peer-data-[size=lg]/menu-button:top-2.5',\r\n 'group-data-[collapsible=icon]:hidden',\r\n showOnHover\r\n && 'group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarMenuAction.displayName = 'SidebarMenuAction'\r\n\r\nconst SidebarMenuBadge = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'>\r\n>(({ className, ...props }, ref) => (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"menu-badge\"\r\n className={cn(\r\n 'pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground',\r\n 'peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground',\r\n 'peer-data-[size=sm]/menu-button:top-1',\r\n 'peer-data-[size=default]/menu-button:top-1.5',\r\n 'peer-data-[size=lg]/menu-button:top-2.5',\r\n 'group-data-[collapsible=icon]:hidden',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nSidebarMenuBadge.displayName = 'SidebarMenuBadge'\r\n\r\nconst SidebarMenuSkeleton = React.forwardRef<\r\n HTMLDivElement,\r\n React.ComponentProps<'div'> & {\r\n showIcon?: boolean\r\n }\r\n>(({ className, showIcon = false, ...props }, ref) => {\r\n // Random width between 50 to 90%.\r\n const width = React.useMemo(() => {\r\n return `${Math.floor(Math.random() * 40) + 50}%`\r\n }, [])\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n data-sidebar=\"menu-skeleton\"\r\n className={cn('flex h-8 items-center gap-2 rounded-md px-2', className)}\r\n {...props}\r\n >\r\n {showIcon && (\r\n <Skeleton\r\n className=\"size-4 rounded-md\"\r\n data-sidebar=\"menu-skeleton-icon\"\r\n />\r\n )}\r\n <Skeleton\r\n className=\"h-4 max-w-[--skeleton-width] flex-1\"\r\n data-sidebar=\"menu-skeleton-text\"\r\n style={\r\n {\r\n '--skeleton-width': width,\r\n } as React.CSSProperties\r\n }\r\n />\r\n </div>\r\n )\r\n})\r\nSidebarMenuSkeleton.displayName = 'SidebarMenuSkeleton'\r\n\r\nconst SidebarMenuSub = React.forwardRef<\r\n HTMLUListElement,\r\n React.ComponentProps<'ul'>\r\n>(({ className, ...props }, ref) => (\r\n <ul\r\n ref={ref}\r\n data-sidebar=\"menu-sub\"\r\n className={cn(\r\n 'mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5',\r\n 'group-data-[collapsible=icon]:hidden',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nSidebarMenuSub.displayName = 'SidebarMenuSub'\r\n\r\nconst SidebarMenuSubItem = React.forwardRef<\r\n HTMLLIElement,\r\n React.ComponentProps<'li'>\r\n>(({ ...props }, ref) => <li ref={ref} {...props} />)\r\nSidebarMenuSubItem.displayName = 'SidebarMenuSubItem'\r\n\r\nconst SidebarMenuSubButton = React.forwardRef<\r\n HTMLAnchorElement,\r\n React.ComponentProps<'a'> & {\r\n asChild?: boolean\r\n size?: 'sm' | 'md'\r\n isActive?: boolean\r\n }\r\n>(({ asChild = false, size = 'md', isActive, className, ...props }, ref) => {\r\n const Comp = asChild ? Slot : 'a'\r\n\r\n return (\r\n <Comp\r\n ref={ref}\r\n data-sidebar=\"menu-sub-button\"\r\n data-size={size}\r\n data-active={isActive}\r\n className={cn(\r\n 'flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground',\r\n 'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',\r\n size === 'sm' && 'text-xs',\r\n size === 'md' && 'text-sm',\r\n 'group-data-[collapsible=icon]:hidden',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n )\r\n})\r\nSidebarMenuSubButton.displayName = 'SidebarMenuSubButton'\r\n\r\nexport {\r\n Sidebar,\r\n SidebarContent,\r\n SidebarFooter,\r\n SidebarGroup,\r\n SidebarGroupAction,\r\n SidebarGroupContent,\r\n SidebarGroupLabel,\r\n SidebarHeader,\r\n SidebarInput,\r\n SidebarInset,\r\n SidebarMenu,\r\n SidebarMenuAction,\r\n SidebarMenuBadge,\r\n SidebarMenuButton,\r\n SidebarMenuItem,\r\n SidebarMenuSkeleton,\r\n SidebarMenuSub,\r\n SidebarMenuSubButton,\r\n SidebarMenuSubItem,\r\n SidebarProvider,\r\n SidebarRail,\r\n SidebarSeparator,\r\n SidebarTrigger,\r\n useSidebar,\r\n}\r\n"],"mappings":"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","names":["open"]}
|
|
@@ -91,7 +91,7 @@ const TableHead = React.forwardRef((_k, ref) => {
|
|
|
91
91
|
__spreadValues({
|
|
92
92
|
ref,
|
|
93
93
|
className: cn(
|
|
94
|
-
"h-10 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
|
94
|
+
"h-10 px-2 sm:px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
|
95
95
|
className
|
|
96
96
|
)
|
|
97
97
|
}, props)
|
|
@@ -105,7 +105,7 @@ const TableCell = React.forwardRef((_m, ref) => {
|
|
|
105
105
|
__spreadValues({
|
|
106
106
|
ref,
|
|
107
107
|
className: cn(
|
|
108
|
-
"py-4 px-4 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
|
108
|
+
"py-4 px-2 sm:px-4 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
|
|
109
109
|
className
|
|
110
110
|
)
|
|
111
111
|
}, props)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/core/components/ui/Table.tsx"],"sourcesContent":["// 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 { cn } from '../../utils/utils'\r\n\r\nconst Table = React.forwardRef<\r\n HTMLTableElement,\r\n React.HTMLAttributes<HTMLTableElement>\r\n>(({ className, ...props }, ref) => (\r\n <div className=\"relative w-full\">\r\n <table\r\n ref={ref}\r\n className={cn('w-full caption-bottom text-sm', className)}\r\n {...props}\r\n />\r\n </div>\r\n))\r\nTable.displayName = 'Table'\r\n\r\nconst TableHeader = React.forwardRef<\r\n HTMLTableSectionElement,\r\n React.HTMLAttributes<HTMLTableSectionElement>\r\n>(({ className, ...props }, ref) => (\r\n <thead ref={ref} className={cn('[&_tr]:border-b', className)} {...props} />\r\n))\r\nTableHeader.displayName = 'TableHeader'\r\n\r\nconst TableBody = React.forwardRef<\r\n HTMLTableSectionElement,\r\n React.HTMLAttributes<HTMLTableSectionElement>\r\n>(({ className, ...props }, ref) => (\r\n <tbody\r\n ref={ref}\r\n className={cn('[&_tr:last-child]:border-0', className)}\r\n {...props}\r\n />\r\n))\r\nTableBody.displayName = 'TableBody'\r\n\r\nconst TableFooter = React.forwardRef<\r\n HTMLTableSectionElement,\r\n React.HTMLAttributes<HTMLTableSectionElement>\r\n>(({ className, ...props }, ref) => (\r\n <tfoot\r\n ref={ref}\r\n className={cn(\r\n 'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nTableFooter.displayName = 'TableFooter'\r\n\r\nconst TableRow = React.forwardRef<\r\n HTMLTableRowElement,\r\n React.HTMLAttributes<HTMLTableRowElement>\r\n>(({ className, ...props }, ref) => (\r\n <tr\r\n ref={ref}\r\n className={cn(\r\n 'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nTableRow.displayName = 'TableRow'\r\n\r\nconst TableHead = React.forwardRef<\r\n HTMLTableCellElement,\r\n React.ThHTMLAttributes<HTMLTableCellElement>\r\n>(({ className, ...props }, ref) => (\r\n <th\r\n ref={ref}\r\n className={cn(\r\n 'h-10 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nTableHead.displayName = 'TableHead'\r\n\r\nconst TableCell = React.forwardRef<\r\n HTMLTableCellElement,\r\n React.TdHTMLAttributes<HTMLTableCellElement>\r\n>(({ className, ...props }, ref) => (\r\n <td\r\n ref={ref}\r\n className={cn(\r\n 'py-4 px-4 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nTableCell.displayName = 'TableCell'\r\n\r\nconst TableCaption = React.forwardRef<\r\n HTMLTableCaptionElement,\r\n React.HTMLAttributes<HTMLTableCaptionElement>\r\n>(({ className, ...props }, ref) => (\r\n <caption\r\n ref={ref}\r\n className={cn('mt-4 text-sm text-muted-foreground', className)}\r\n {...props}\r\n />\r\n))\r\nTableCaption.displayName = 'TableCaption'\r\n\r\nexport {\r\n Table,\r\n TableHeader,\r\n TableBody,\r\n TableFooter,\r\n TableHead,\r\n TableRow,\r\n TableCell,\r\n TableCaption,\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYI;AATJ,YAAY,WAAW;AAEvB,SAAS,UAAU;AAEnB,MAAM,QAAQ,MAAM,WAGlB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YAVL,IAUG,IAAgB,kBAAhB,IAAgB,CAAd;AACH,6BAAC,SAAI,WAAU,mBACb;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,GAAG,iCAAiC,SAAS;AAAA,OACpD;AAAA,EACN,GACF;AAAA,CACD;AACD,MAAM,cAAc;AAEpB,MAAM,cAAc,MAAM,WAGxB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YAxBL,IAwBG,IAAgB,kBAAhB,IAAgB,CAAd;AACH,6BAAC,0BAAM,KAAU,WAAW,GAAG,mBAAmB,SAAS,KAAO,MAAO;AAAA,CAC1E;AACD,YAAY,cAAc;AAE1B,MAAM,YAAY,MAAM,WAGtB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YAhCL,IAgCG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,GAAG,8BAA8B,SAAS;AAAA,OACjD;AAAA,EACN;AAAA,CACD;AACD,UAAU,cAAc;AAExB,MAAM,cAAc,MAAM,WAGxB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YA5CL,IA4CG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,OACI;AAAA,EACN;AAAA,CACD;AACD,YAAY,cAAc;AAE1B,MAAM,WAAW,MAAM,WAGrB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YA3DL,IA2DG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,OACI;AAAA,EACN;AAAA,CACD;AACD,SAAS,cAAc;AAEvB,MAAM,YAAY,MAAM,WAGtB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YA1EL,IA0EG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,OACI;AAAA,EACN;AAAA,CACD;AACD,UAAU,cAAc;AAExB,MAAM,YAAY,MAAM,WAGtB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YAzFL,IAyFG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,OACI;AAAA,EACN;AAAA,CACD;AACD,UAAU,cAAc;AAExB,MAAM,eAAe,MAAM,WAGzB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YAxGL,IAwGG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,GAAG,sCAAsC,SAAS;AAAA,OACzD;AAAA,EACN;AAAA,CACD;AACD,aAAa,cAAc;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/core/components/ui/Table.tsx"],"sourcesContent":["// 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 { cn } from '../../utils/utils'\r\n\r\nconst Table = React.forwardRef<\r\n HTMLTableElement,\r\n React.HTMLAttributes<HTMLTableElement>\r\n>(({ className, ...props }, ref) => (\r\n <div className=\"relative w-full\">\r\n <table\r\n ref={ref}\r\n className={cn('w-full caption-bottom text-sm', className)}\r\n {...props}\r\n />\r\n </div>\r\n))\r\nTable.displayName = 'Table'\r\n\r\nconst TableHeader = React.forwardRef<\r\n HTMLTableSectionElement,\r\n React.HTMLAttributes<HTMLTableSectionElement>\r\n>(({ className, ...props }, ref) => (\r\n <thead ref={ref} className={cn('[&_tr]:border-b', className)} {...props} />\r\n))\r\nTableHeader.displayName = 'TableHeader'\r\n\r\nconst TableBody = React.forwardRef<\r\n HTMLTableSectionElement,\r\n React.HTMLAttributes<HTMLTableSectionElement>\r\n>(({ className, ...props }, ref) => (\r\n <tbody\r\n ref={ref}\r\n className={cn('[&_tr:last-child]:border-0', className)}\r\n {...props}\r\n />\r\n))\r\nTableBody.displayName = 'TableBody'\r\n\r\nconst TableFooter = React.forwardRef<\r\n HTMLTableSectionElement,\r\n React.HTMLAttributes<HTMLTableSectionElement>\r\n>(({ className, ...props }, ref) => (\r\n <tfoot\r\n ref={ref}\r\n className={cn(\r\n 'border-t bg-muted/50 font-medium [&>tr]:last:border-b-0',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nTableFooter.displayName = 'TableFooter'\r\n\r\nconst TableRow = React.forwardRef<\r\n HTMLTableRowElement,\r\n React.HTMLAttributes<HTMLTableRowElement>\r\n>(({ className, ...props }, ref) => (\r\n <tr\r\n ref={ref}\r\n className={cn(\r\n 'border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nTableRow.displayName = 'TableRow'\r\n\r\nconst TableHead = React.forwardRef<\r\n HTMLTableCellElement,\r\n React.ThHTMLAttributes<HTMLTableCellElement>\r\n>(({ className, ...props }, ref) => (\r\n <th\r\n ref={ref}\r\n className={cn(\r\n 'h-10 px-2 sm:px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nTableHead.displayName = 'TableHead'\r\n\r\nconst TableCell = React.forwardRef<\r\n HTMLTableCellElement,\r\n React.TdHTMLAttributes<HTMLTableCellElement>\r\n>(({ className, ...props }, ref) => (\r\n <td\r\n ref={ref}\r\n className={cn(\r\n 'py-4 px-2 sm:px-4 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]',\r\n className,\r\n )}\r\n {...props}\r\n />\r\n))\r\nTableCell.displayName = 'TableCell'\r\n\r\nconst TableCaption = React.forwardRef<\r\n HTMLTableCaptionElement,\r\n React.HTMLAttributes<HTMLTableCaptionElement>\r\n>(({ className, ...props }, ref) => (\r\n <caption\r\n ref={ref}\r\n className={cn('mt-4 text-sm text-muted-foreground', className)}\r\n {...props}\r\n />\r\n))\r\nTableCaption.displayName = 'TableCaption'\r\n\r\nexport {\r\n Table,\r\n TableHeader,\r\n TableBody,\r\n TableFooter,\r\n TableHead,\r\n TableRow,\r\n TableCell,\r\n TableCaption,\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYI;AATJ,YAAY,WAAW;AAEvB,SAAS,UAAU;AAEnB,MAAM,QAAQ,MAAM,WAGlB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YAVL,IAUG,IAAgB,kBAAhB,IAAgB,CAAd;AACH,6BAAC,SAAI,WAAU,mBACb;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,GAAG,iCAAiC,SAAS;AAAA,OACpD;AAAA,EACN,GACF;AAAA,CACD;AACD,MAAM,cAAc;AAEpB,MAAM,cAAc,MAAM,WAGxB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YAxBL,IAwBG,IAAgB,kBAAhB,IAAgB,CAAd;AACH,6BAAC,0BAAM,KAAU,WAAW,GAAG,mBAAmB,SAAS,KAAO,MAAO;AAAA,CAC1E;AACD,YAAY,cAAc;AAE1B,MAAM,YAAY,MAAM,WAGtB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YAhCL,IAgCG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,GAAG,8BAA8B,SAAS;AAAA,OACjD;AAAA,EACN;AAAA,CACD;AACD,UAAU,cAAc;AAExB,MAAM,cAAc,MAAM,WAGxB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YA5CL,IA4CG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,OACI;AAAA,EACN;AAAA,CACD;AACD,YAAY,cAAc;AAE1B,MAAM,WAAW,MAAM,WAGrB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YA3DL,IA2DG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,OACI;AAAA,EACN;AAAA,CACD;AACD,SAAS,cAAc;AAEvB,MAAM,YAAY,MAAM,WAGtB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YA1EL,IA0EG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,OACI;AAAA,EACN;AAAA,CACD;AACD,UAAU,cAAc;AAExB,MAAM,YAAY,MAAM,WAGtB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YAzFL,IAyFG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,OACI;AAAA,EACN;AAAA,CACD;AACD,UAAU,cAAc;AAExB,MAAM,eAAe,MAAM,WAGzB,CAAC,IAAyB,QAAK;AAA9B,eAAE,YAxGL,IAwGG,IAAgB,kBAAhB,IAAgB,CAAd;AACH;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,WAAW,GAAG,sCAAsC,SAAS;AAAA,OACzD;AAAA,EACN;AAAA,CACD;AACD,aAAa,cAAc;","names":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataMenu.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/Data/DataMenu.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAS9B,OAAO,KAAK,EAAwC,YAAY,EAAE,MAAM,wBAAwB,CAAA;AA6ChG,OAAO,EAA6B,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAKvE,KAAK,aAAa,GAAG;IACnB,aAAa,EAAE,WAAW,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAgB,QAAQ,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"DataMenu.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/viewers/Data/DataMenu.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAS9B,OAAO,KAAK,EAAwC,YAAY,EAAE,MAAM,wBAAwB,CAAA;AA6ChG,OAAO,EAA6B,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAKvE,KAAK,aAAa,GAAG;IACnB,aAAa,EAAE,WAAW,CAAA;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,wBAAgB,QAAQ,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,EAAE,aAAa,qBAikBlJ"}
|
|
@@ -116,7 +116,15 @@ function DataMenu({ currentViewer, height, hideTitle, hideActions, hideFrame, or
|
|
|
116
116
|
removeItemFromCompare
|
|
117
117
|
} = useBuildingsContext();
|
|
118
118
|
React.useEffect(() => {
|
|
119
|
-
|
|
119
|
+
var _a2;
|
|
120
|
+
const viewerToDataType = {
|
|
121
|
+
[ViewerNames.buildings]: DataTypesNames.building,
|
|
122
|
+
[ViewerNames.sites]: DataTypesNames.site,
|
|
123
|
+
[ViewerNames.infrastructure]: DataTypesNames.infrastructure,
|
|
124
|
+
[ViewerNames.files]: DataTypesNames.file,
|
|
125
|
+
[ViewerNames.users]: DataTypesNames.user
|
|
126
|
+
};
|
|
127
|
+
setDataType((_a2 = viewerToDataType[currentViewer]) != null ? _a2 : DataTypesNames.building);
|
|
120
128
|
}, [currentViewer]);
|
|
121
129
|
React.useEffect(() => {
|
|
122
130
|
setComparing(false);
|
|
@@ -301,8 +309,8 @@ function DataMenu({ currentViewer, height, hideTitle, hideActions, hideFrame, or
|
|
|
301
309
|
" to compare."
|
|
302
310
|
] })
|
|
303
311
|
] }) }),
|
|
304
|
-
/* @__PURE__ */ jsxs("div", { className: `flex ${hideTitle ? "justify-between" : "justify-end"} items-center px-6 py-4 gap-4`, children: [
|
|
305
|
-
/* @__PURE__ */ jsx("div", { className: hideTitle ? "w-64" : "w-96"
|
|
312
|
+
/* @__PURE__ */ jsxs("div", { className: `flex flex-col sm:flex-row ${hideTitle ? "sm:justify-between" : "sm:justify-end"} items-stretch sm:items-center px-3 sm:px-6 py-4 gap-3 sm:gap-4`, children: [
|
|
313
|
+
/* @__PURE__ */ jsx("div", { className: `w-full ${hideTitle ? "sm:w-64" : "sm:w-96"}`, children: /* @__PURE__ */ jsx(
|
|
306
314
|
Input,
|
|
307
315
|
{
|
|
308
316
|
placeholder: `${t("searchPlaceholder")} ${headerTitle}...`,
|
|
@@ -310,7 +318,7 @@ function DataMenu({ currentViewer, height, hideTitle, hideActions, hideFrame, or
|
|
|
310
318
|
onChange: (e) => setSearchTerm(e.target.value)
|
|
311
319
|
}
|
|
312
320
|
) }),
|
|
313
|
-
/* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
|
|
321
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-2", children: [
|
|
314
322
|
/* @__PURE__ */ jsx(
|
|
315
323
|
FilterButtons,
|
|
316
324
|
{
|
|
@@ -345,8 +353,8 @@ function DataMenu({ currentViewer, height, hideTitle, hideActions, hideFrame, or
|
|
|
345
353
|
/* @__PURE__ */ jsx(Separator, {})
|
|
346
354
|
] }) : (
|
|
347
355
|
// Detail View Header
|
|
348
|
-
/* @__PURE__ */ jsxs("div", { className: "flex justify-between items-center px-6 py-6", children: [
|
|
349
|
-
/* @__PURE__ */ jsx(
|
|
356
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col sm:flex-row sm:justify-between sm:items-center gap-3 px-4 sm:px-6 py-4 sm:py-6", children: [
|
|
357
|
+
/* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsx(
|
|
350
358
|
DetailHeader,
|
|
351
359
|
{
|
|
352
360
|
selectedItem,
|
|
@@ -356,8 +364,8 @@ function DataMenu({ currentViewer, height, hideTitle, hideActions, hideFrame, or
|
|
|
356
364
|
selectedUser,
|
|
357
365
|
countryCode: organization == null ? void 0 : organization.country
|
|
358
366
|
}
|
|
359
|
-
),
|
|
360
|
-
/* @__PURE__ */ jsx(
|
|
367
|
+
) }),
|
|
368
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap shrink-0 gap-2", children: /* @__PURE__ */ jsx(
|
|
361
369
|
DetailActions,
|
|
362
370
|
{
|
|
363
371
|
editing,
|
|
@@ -388,7 +396,7 @@ function DataMenu({ currentViewer, height, hideTitle, hideActions, hideFrame, or
|
|
|
388
396
|
},
|
|
389
397
|
setView
|
|
390
398
|
}
|
|
391
|
-
)
|
|
399
|
+
) })
|
|
392
400
|
] })
|
|
393
401
|
),
|
|
394
402
|
view === "detail" && /* @__PURE__ */ jsx(Separator, {})
|