@kerros/editor 0.0.0-stage → 0.1.0-rc.2
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/LICENSE +21 -0
- package/README.md +35 -2
- package/dist/SitePlanner.js +1189 -0
- package/dist/SitePlanner.js.map +1 -0
- package/dist/adapters/basemap.js +11 -0
- package/dist/adapters/basemap.js.map +1 -0
- package/dist/adapters/persistence.js +121 -0
- package/dist/adapters/persistence.js.map +1 -0
- package/dist/adapters/status.js +11 -0
- package/dist/adapters/status.js.map +1 -0
- package/dist/adapters/useProjectPersistence.js +56 -0
- package/dist/adapters/useProjectPersistence.js.map +1 -0
- package/dist/components/AiImportPanel.js +635 -0
- package/dist/components/AiImportPanel.js.map +1 -0
- package/dist/components/AnalysisPreview.js +179 -0
- package/dist/components/AnalysisPreview.js.map +1 -0
- package/dist/components/ElevatorPanel.js +120 -0
- package/dist/components/ElevatorPanel.js.map +1 -0
- package/dist/components/Icons.js +57 -0
- package/dist/components/Icons.js.map +1 -0
- package/dist/components/ImportDialog.js +467 -0
- package/dist/components/ImportDialog.js.map +1 -0
- package/dist/components/Inspector.js +1184 -0
- package/dist/components/Inspector.js.map +1 -0
- package/dist/components/NavigatePanel.js +301 -0
- package/dist/components/NavigatePanel.js.map +1 -0
- package/dist/components/NavigationGraph.js +234 -0
- package/dist/components/NavigationGraph.js.map +1 -0
- package/dist/components/StructureExplorer.js +510 -0
- package/dist/components/StructureExplorer.js.map +1 -0
- package/dist/components/StructureView.js +286 -0
- package/dist/components/StructureView.js.map +1 -0
- package/dist/components/controls.js +209 -0
- package/dist/components/controls.js.map +1 -0
- package/dist/components/graphLayout.js +27 -0
- package/dist/components/graphLayout.js.map +1 -0
- package/dist/host.js +175 -0
- package/dist/host.js.map +1 -0
- package/dist/i18n.js +88 -0
- package/dist/i18n.js.map +1 -0
- package/dist/import/analysisPreview.js +41 -0
- package/dist/import/analysisPreview.js.map +1 -0
- package/dist/import/brief.js +29 -0
- package/dist/import/brief.js.map +1 -0
- package/dist/import/checkpoint.js +50 -0
- package/dist/import/checkpoint.js.map +1 -0
- package/dist/import/detect.js +120 -0
- package/dist/import/detect.js.map +1 -0
- package/dist/import/documentSvg.js +49 -0
- package/dist/import/documentSvg.js.map +1 -0
- package/dist/import/instructions.js +20 -0
- package/dist/import/instructions.js.map +1 -0
- package/dist/import/openings.js +61 -0
- package/dist/import/openings.js.map +1 -0
- package/dist/import/planImport.js +233 -0
- package/dist/import/planImport.js.map +1 -0
- package/dist/import/register.js +47 -0
- package/dist/import/register.js.map +1 -0
- package/dist/import/runs.js +67 -0
- package/dist/import/runs.js.map +1 -0
- package/dist/import/session.js +23 -0
- package/dist/import/session.js.map +1 -0
- package/dist/import/types.js +13 -0
- package/dist/import/types.js.map +1 -0
- package/dist/import/usage.js +29 -0
- package/dist/import/usage.js.map +1 -0
- package/dist/import/walls.js +112 -0
- package/dist/import/walls.js.map +1 -0
- package/dist/index.js +178 -0
- package/dist/index.js.map +1 -0
- package/dist/map/CabinMaterials.js +81 -0
- package/dist/map/CabinMaterials.js.map +1 -0
- package/dist/map/CabinMirror.js +43 -0
- package/dist/map/CabinMirror.js.map +1 -0
- package/dist/map/Doors.js +80 -0
- package/dist/map/Doors.js.map +1 -0
- package/dist/map/ElevatorCabin.js +93 -0
- package/dist/map/ElevatorCabin.js.map +1 -0
- package/dist/map/FixtureLights.js +117 -0
- package/dist/map/FixtureLights.js.map +1 -0
- package/dist/map/MapCanvas.js +2161 -0
- package/dist/map/MapCanvas.js.map +1 -0
- package/dist/map/Passenger.js +69 -0
- package/dist/map/Passenger.js.map +1 -0
- package/dist/map/SceneLayer.js +1534 -0
- package/dist/map/SceneLayer.js.map +1 -0
- package/dist/map/UndergroundContext.js +153 -0
- package/dist/map/UndergroundContext.js.map +1 -0
- package/dist/map/ambience.js +194 -0
- package/dist/map/ambience.js.map +1 -0
- package/dist/map/architecture.js +305 -0
- package/dist/map/architecture.js.map +1 -0
- package/dist/map/bathMusic.js +92 -0
- package/dist/map/bathMusic.js.map +1 -0
- package/dist/map/cameraAim.js +33 -0
- package/dist/map/cameraAim.js.map +1 -0
- package/dist/map/elevators.js +56 -0
- package/dist/map/elevators.js.map +1 -0
- package/dist/map/excavation.js +52 -0
- package/dist/map/excavation.js.map +1 -0
- package/dist/map/exteriors.js +25 -0
- package/dist/map/exteriors.js.map +1 -0
- package/dist/map/features.js +218 -0
- package/dist/map/features.js.map +1 -0
- package/dist/map/fences.js +29 -0
- package/dist/map/fences.js.map +1 -0
- package/dist/map/journey.js +112 -0
- package/dist/map/journey.js.map +1 -0
- package/dist/map/levels.js +6 -0
- package/dist/map/levels.js.map +1 -0
- package/dist/map/lighting.js +143 -0
- package/dist/map/lighting.js.map +1 -0
- package/dist/map/loadBasemap.js +26 -0
- package/dist/map/loadBasemap.js.map +1 -0
- package/dist/map/materials.js +183 -0
- package/dist/map/materials.js.map +1 -0
- package/dist/map/poolLighting.js +39 -0
- package/dist/map/poolLighting.js.map +1 -0
- package/dist/map/projection.js +24 -0
- package/dist/map/projection.js.map +1 -0
- package/dist/map/rampGeometry.js +38 -0
- package/dist/map/rampGeometry.js.map +1 -0
- package/dist/map/route.js +107 -0
- package/dist/map/route.js.map +1 -0
- package/dist/map/stairSurfaces.js +115 -0
- package/dist/map/stairSurfaces.js.map +1 -0
- package/dist/map/surfaces.js +136 -0
- package/dist/map/surfaces.js.map +1 -0
- package/dist/map/textures.js +95 -0
- package/dist/map/textures.js.map +1 -0
- package/dist/map/underground.js +34 -0
- package/dist/map/underground.js.map +1 -0
- package/dist/map/walk.js +433 -0
- package/dist/map/walk.js.map +1 -0
- package/dist/map/walkContext.js +46 -0
- package/dist/map/walkContext.js.map +1 -0
- package/dist/map/walkDimensions.js +7 -0
- package/dist/map/walkDimensions.js.map +1 -0
- package/dist/map/walkJourney.js +85 -0
- package/dist/map/walkJourney.js.map +1 -0
- package/dist/map/walkSurfaces.js +106 -0
- package/dist/map/walkSurfaces.js.map +1 -0
- package/dist/map/wallJoins.js +70 -0
- package/dist/map/wallJoins.js.map +1 -0
- package/dist/map/water.js +274 -0
- package/dist/map/water.js.map +1 -0
- package/dist/model/authoring.js +99 -0
- package/dist/model/authoring.js.map +1 -0
- package/dist/model/boundaries.js +548 -0
- package/dist/model/boundaries.js.map +1 -0
- package/dist/model/coverage.js +30 -0
- package/dist/model/coverage.js.map +1 -0
- package/dist/model/document.js +52 -0
- package/dist/model/document.js.map +1 -0
- package/dist/model/doors.js +47 -0
- package/dist/model/doors.js.map +1 -0
- package/dist/model/factory.js +56 -0
- package/dist/model/factory.js.map +1 -0
- package/dist/model/geometry.js +454 -0
- package/dist/model/geometry.js.map +1 -0
- package/dist/model/history.js +29 -0
- package/dist/model/history.js.map +1 -0
- package/dist/model/imports.js +45 -0
- package/dist/model/imports.js.map +1 -0
- package/dist/model/inference.js +182 -0
- package/dist/model/inference.js.map +1 -0
- package/dist/model/materials.js +11 -0
- package/dist/model/materials.js.map +1 -0
- package/dist/model/mutations.js +157 -0
- package/dist/model/mutations.js.map +1 -0
- package/dist/model/navigation.js +275 -0
- package/dist/model/navigation.js.map +1 -0
- package/dist/model/ontology.js +109 -0
- package/dist/model/ontology.js.map +1 -0
- package/dist/model/passages.js +5 -0
- package/dist/model/passages.js.map +1 -0
- package/dist/model/portals.js +42 -0
- package/dist/model/portals.js.map +1 -0
- package/dist/model/precision.js +11 -0
- package/dist/model/precision.js.map +1 -0
- package/dist/model/project.js +31 -0
- package/dist/model/project.js.map +1 -0
- package/dist/model/ramps.js +10 -0
- package/dist/model/ramps.js.map +1 -0
- package/dist/model/roomNavigation.js +87 -0
- package/dist/model/roomNavigation.js.map +1 -0
- package/dist/model/routeClearance.js +72 -0
- package/dist/model/routeClearance.js.map +1 -0
- package/dist/model/spaces.js +104 -0
- package/dist/model/spaces.js.map +1 -0
- package/dist/model/stairGeometry.js +40 -0
- package/dist/model/stairGeometry.js.map +1 -0
- package/dist/model/stairTraversal.js +48 -0
- package/dist/model/stairTraversal.js.map +1 -0
- package/dist/model/topology.js +63 -0
- package/dist/model/topology.js.map +1 -0
- package/dist/model/types.js +35 -0
- package/dist/model/types.js.map +1 -0
- package/dist/model/validate.js +240 -0
- package/dist/model/validate.js.map +1 -0
- package/dist/model/vertical.js +129 -0
- package/dist/model/vertical.js.map +1 -0
- package/dist/model/walls.js +261 -0
- package/dist/model/walls.js.map +1 -0
- package/dist/planner/DrawingDock.js +231 -0
- package/dist/planner/DrawingDock.js.map +1 -0
- package/dist/planner/FloorControls.js +93 -0
- package/dist/planner/FloorControls.js.map +1 -0
- package/dist/planner/MapSettings.js +143 -0
- package/dist/planner/MapSettings.js.map +1 -0
- package/dist/planner/PlannerHelp.js +57 -0
- package/dist/planner/PlannerHelp.js.map +1 -0
- package/dist/planner/ProjectSidebar.js +246 -0
- package/dist/planner/ProjectSidebar.js.map +1 -0
- package/dist/planner/floors.js +18 -0
- package/dist/planner/floors.js.map +1 -0
- package/dist/planner/useDrawingTools.js +341 -0
- package/dist/planner/useDrawingTools.js.map +1 -0
- package/dist/planner/useMapDisplay.js +51 -0
- package/dist/planner/useMapDisplay.js.map +1 -0
- package/dist/planner/usePlannerKeyboard.js +138 -0
- package/dist/planner/usePlannerKeyboard.js.map +1 -0
- package/dist/planner/useReferenceAlignment.js +50 -0
- package/dist/planner/useReferenceAlignment.js.map +1 -0
- package/dist/styles.css +4931 -0
- package/dist/theme/index.js +34 -0
- package/dist/theme/index.js.map +1 -0
- package/dist/types/SitePlanner.d.ts +5 -0
- package/dist/types/adapters/basemap.d.ts +2 -0
- package/dist/types/adapters/persistence.d.ts +29 -0
- package/dist/types/adapters/status.d.ts +4 -0
- package/dist/types/adapters/useProjectPersistence.d.ts +13 -0
- package/dist/types/components/AiImportPanel.d.ts +9 -0
- package/dist/types/components/AnalysisPreview.d.ts +4 -0
- package/dist/types/components/ElevatorPanel.d.ts +18 -0
- package/dist/types/components/Icons.d.ts +8 -0
- package/dist/types/components/ImportDialog.d.ts +42 -0
- package/dist/types/components/Inspector.d.ts +38 -0
- package/dist/types/components/NavigatePanel.d.ts +27 -0
- package/dist/types/components/NavigationGraph.d.ts +10 -0
- package/dist/types/components/StructureExplorer.d.ts +8 -0
- package/dist/types/components/StructureView.d.ts +22 -0
- package/dist/types/components/controls.d.ts +52 -0
- package/dist/types/components/graphLayout.d.ts +9 -0
- package/dist/types/editor/host.d.ts +9 -0
- package/dist/types/editor/index.d.ts +2 -0
- package/dist/types/i18n.d.ts +85 -0
- package/dist/types/import/analysisPreview.d.ts +27 -0
- package/dist/types/import/brief.d.ts +22 -0
- package/dist/types/import/checkpoint.d.ts +49 -0
- package/dist/types/import/detect.d.ts +34 -0
- package/dist/types/import/documentSvg.d.ts +2 -0
- package/dist/types/import/index.d.ts +10 -0
- package/dist/types/import/instructions.d.ts +7 -0
- package/dist/types/import/openings.d.ts +22 -0
- package/dist/types/import/planImport.d.ts +22 -0
- package/dist/types/import/register.d.ts +25 -0
- package/dist/types/import/runs.d.ts +31 -0
- package/dist/types/import/session.d.ts +33 -0
- package/dist/types/import/types.d.ts +56 -0
- package/dist/types/import/usage.d.ts +10 -0
- package/dist/types/import/walls.d.ts +37 -0
- package/dist/types/map/CabinMaterials.d.ts +18 -0
- package/dist/types/map/CabinMirror.d.ts +13 -0
- package/dist/types/map/Doors.d.ts +11 -0
- package/dist/types/map/ElevatorCabin.d.ts +20 -0
- package/dist/types/map/FixtureLights.d.ts +35 -0
- package/dist/types/map/MapCanvas.d.ts +87 -0
- package/dist/types/map/Passenger.d.ts +18 -0
- package/dist/types/map/SceneLayer.d.ts +306 -0
- package/dist/types/map/UndergroundContext.d.ts +18 -0
- package/dist/types/map/ambience.d.ts +29 -0
- package/dist/types/map/architecture.d.ts +8 -0
- package/dist/types/map/bathMusic.d.ts +14 -0
- package/dist/types/map/cameraAim.d.ts +20 -0
- package/dist/types/map/elevators.d.ts +16 -0
- package/dist/types/map/excavation.d.ts +9 -0
- package/dist/types/map/exteriors.d.ts +3 -0
- package/dist/types/map/features.d.ts +33 -0
- package/dist/types/map/fences.d.ts +4 -0
- package/dist/types/map/journey.d.ts +36 -0
- package/dist/types/map/levels.d.ts +4 -0
- package/dist/types/map/lighting.d.ts +103 -0
- package/dist/types/map/loadBasemap.d.ts +4 -0
- package/dist/types/map/materials.d.ts +38 -0
- package/dist/types/map/poolLighting.d.ts +11 -0
- package/dist/types/map/projection.d.ts +9 -0
- package/dist/types/map/rampGeometry.d.ts +8 -0
- package/dist/types/map/route.d.ts +59 -0
- package/dist/types/map/stairSurfaces.d.ts +29 -0
- package/dist/types/map/surfaces.d.ts +36 -0
- package/dist/types/map/textures.d.ts +8 -0
- package/dist/types/map/underground.d.ts +30 -0
- package/dist/types/map/walk.d.ts +232 -0
- package/dist/types/map/walkContext.d.ts +11 -0
- package/dist/types/map/walkDimensions.d.ts +5 -0
- package/dist/types/map/walkJourney.d.ts +33 -0
- package/dist/types/map/walkSurfaces.d.ts +27 -0
- package/dist/types/map/wallJoins.d.ts +6 -0
- package/dist/types/map/water.d.ts +12 -0
- package/dist/types/model/authoring.d.ts +38 -0
- package/dist/types/model/boundaries.d.ts +41 -0
- package/dist/types/model/coverage.d.ts +8 -0
- package/dist/types/model/document.d.ts +9 -0
- package/dist/types/model/doors.d.ts +19 -0
- package/dist/types/model/factory.d.ts +5 -0
- package/dist/types/model/geometry.d.ts +99 -0
- package/dist/types/model/history.d.ts +10 -0
- package/dist/types/model/host.d.ts +154 -0
- package/dist/types/model/imports.d.ts +7 -0
- package/dist/types/model/inference.d.ts +46 -0
- package/dist/types/model/live.d.ts +60 -0
- package/dist/types/model/materials.d.ts +28 -0
- package/dist/types/model/mutations.d.ts +178 -0
- package/dist/types/model/navigation.d.ts +70 -0
- package/dist/types/model/ontology.d.ts +43 -0
- package/dist/types/model/passages.d.ts +2 -0
- package/dist/types/model/portals.d.ts +9 -0
- package/dist/types/model/precision.d.ts +11 -0
- package/dist/types/model/project.d.ts +8 -0
- package/dist/types/model/ramps.d.ts +7 -0
- package/dist/types/model/roomNavigation.d.ts +15 -0
- package/dist/types/model/routeClearance.d.ts +11 -0
- package/dist/types/model/spaces.d.ts +46 -0
- package/dist/types/model/stairGeometry.d.ts +27 -0
- package/dist/types/model/stairTraversal.d.ts +8 -0
- package/dist/types/model/topology.d.ts +14 -0
- package/dist/types/model/types.d.ts +369 -0
- package/dist/types/model/validate.d.ts +38 -0
- package/dist/types/model/vertical.d.ts +145 -0
- package/dist/types/model/walls.d.ts +71 -0
- package/dist/types/planner/DrawingDock.d.ts +16 -0
- package/dist/types/planner/FloorControls.d.ts +17 -0
- package/dist/types/planner/MapSettings.d.ts +16 -0
- package/dist/types/planner/PlannerHelp.d.ts +3 -0
- package/dist/types/planner/ProjectSidebar.d.ts +32 -0
- package/dist/types/planner/floors.d.ts +3 -0
- package/dist/types/planner/types.d.ts +3 -0
- package/dist/types/planner/useDrawingTools.d.ts +52 -0
- package/dist/types/planner/useMapDisplay.d.ts +29 -0
- package/dist/types/planner/usePlannerKeyboard.d.ts +18 -0
- package/dist/types/planner/useReferenceAlignment.d.ts +30 -0
- package/dist/types/schema/index.d.ts +25 -0
- package/dist/types/theme/index.d.ts +55 -0
- package/package.json +58 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SitePlanner.js","sources":["../../../src/SitePlanner.tsx"],"sourcesContent":["import {\n ArrowDownToLine,\n ArrowUpFromLine,\n Bell,\n ChevronRight,\n CircleHelp,\n Eye,\n Layers3,\n Maximize2,\n Minimize2,\n Moon,\n MousePointer2,\n PanelLeftClose,\n PanelLeftOpen,\n PanelRightClose,\n PanelRightOpen,\n Plus,\n Radio,\n Settings2,\n Shapes,\n ShieldCheck,\n Sun,\n Waypoints,\n X,\n} from 'lucide-react';\nimport type { Map as GLMap } from 'maplibre-gl';\nimport { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { exportProject } from './adapters/persistence';\nimport { statusTone } from './adapters/status';\nimport { useProjectPersistence } from './adapters/useProjectPersistence';\nimport { AlignmentPanel, ImportDialog } from './components/ImportDialog';\nimport { Inspector } from './components/Inspector';\nimport { NavigatePanel } from './components/NavigatePanel';\nimport { StructureView, type StructureTarget } from './components/StructureView';\nimport { Modal } from './components/controls';\nimport { importPlanEntities, type PlanImportReport } from './import/planImport';\nimport { loadAiImportSession } from './import/session';\nimport { MapCanvas } from './map/MapCanvas';\nimport { floorAim } from './map/journey';\nimport type { WalkAvatar } from './map/walk';\nimport { boundaryEdges, connectSpace, disconnectSpace } from './model/boundaries';\nimport { createObject } from './model/factory';\nimport {\n add,\n addBarrier,\n closeRing,\n duplicateFloor,\n footprint,\n moveOrigin,\n removeBarrier,\n removeFloor,\n toLngLat,\n} from './model/geometry';\nimport { commitHistory, makeHistory, redoHistory, undoHistory } from './model/history';\nimport type { CameraState, SitePlannerProps } from './model/host';\nimport { mergeSpaces, spacesRejoinedBy } from './model/inference';\nimport type { StatusReading } from './model/live';\nimport { findRoute, HERE, type RouteEnd } from './model/navigation';\nimport { pruneOntology } from './model/ontology';\nimport { openingFloorId } from './model/project';\nimport { derivedGraph } from './model/topology';\nimport type { Barrier, Drawing, Floor, Point, ProjectDocument, SiteObject } from './model/types';\nimport { uid } from './model/types';\nimport { transact, validateProject } from './model/validate';\nimport { DrawingDock } from './planner/DrawingDock';\nimport { FloorControls } from './planner/FloorControls';\nimport { MapSettings } from './planner/MapSettings';\nimport { PlannerHelp } from './planner/PlannerHelp';\nimport { ProjectSidebar, useProjectSidebar } from './planner/ProjectSidebar';\nimport { floorBand } from './planner/floors';\nimport { useDrawingTools } from './planner/useDrawingTools';\nimport { useMapDisplay } from './planner/useMapDisplay';\nimport { usePlannerKeyboard } from './planner/usePlannerKeyboard';\nimport { useReferenceAlignment } from './planner/useReferenceAlignment';\nimport { useDarkMode, useKerrosTheme, useStrings } from './theme';\nconst NavigationGraph = lazy(() =>\n import('./components/NavigationGraph').then(module => ({ default: module.NavigationGraph })),\n);\n\nfunction download(text: string, name: string) {\n const url = URL.createObjectURL(new Blob([text], { type: 'application/json' }));\n const link = document.createElement('a');\n link.href = url;\n link.download = name;\n link.click();\n setTimeout(() => URL.revokeObjectURL(url), 1000);\n}\nexport function SitePlanner({\n project: initial,\n adapters,\n onChange,\n onSelectionChange,\n onBack,\n initialView,\n onViewChange,\n onModeChange,\n renderStatusPanel,\n elevators,\n readOnly = false,\n}: SitePlannerProps & { readOnly?: boolean }) {\n const [dark, toggleDark] = useDarkMode();\n const [history, setHistory] = useState(() => makeHistory(initial));\n const project = history.present;\n const [floorId, setFloorId] = useState<string | null>(\n initialView?.floor !== undefined &&\n (initialView.floor === null || initial.floors.some(f => f.id === initialView.floor))\n ? initialView.floor\n : openingFloorId(initial),\n ),\n [selected, setSelected] = useState<string | null>(null),\n [focusId, setFocusId] = useState<string | null>(null);\n // Three chrome modes: 'view' browses the plan read-only without live data, 'edit' is the full\n // authoring experience, 'live' overlays the host's status feed on the read-only plan. The last\n // exists only when the host supplied a StatusFeed — with no feed there is nothing to monitor.\n const monitoring = !!adapters.status;\n const [mode, setMode] = useState<'view' | 'edit' | 'live'>(() => {\n const wanted = initialView?.mode;\n if (wanted === 'edit') return readOnly ? 'view' : 'edit';\n if (wanted === 'live') return monitoring ? 'live' : 'view';\n if (wanted === 'view') return 'view';\n return readOnly && monitoring ? 'live' : 'view';\n });\n const [aiRunning, setAiRunning] = useState(false);\n const editing = mode === 'edit' && !aiRunning,\n live = mode === 'live';\n const [threeD, setThreeD] = useState(initialView?.threeD ?? initialView?.mode !== 'edit'),\n [stack, setStack] = useState(initialView?.stack ?? false),\n [walk, setWalk] = useState(initialView?.walk ?? false);\n const [merge, setMerge] = useState<{ wallId: string; a: SiteObject; b: SiteObject } | null>(null);\n // The editor owns its document through history, so `project` is the *initial* document — a host's\n // in-flight-edit echoes (same id) are ignored. But swapping to a genuinely different document\n // (new id) without remounting must reset the editor onto it, not silently keep editing the old one.\n const loadedProjectId = useRef(initial.id);\n useEffect(() => {\n if (initial.id === loadedProjectId.current) return;\n loadedProjectId.current = initial.id;\n setHistory(makeHistory(initial));\n setSelected(null);\n setDraft([]);\n setFloorId(openingFloorId(initial));\n }, [initial]);\n const [palette, setPalette] = useState(false);\n const [fullscreen, setFullscreen] = useState(false);\n const [sidebarOpen, setSidebarOpen] = useState(initialView?.mode === 'edit' && !readOnly);\n const [inspectorOpen, setInspectorOpen] = useState(false);\n const display = useMapDisplay(project, adapters.basemap, initialView);\n const {\n coverage,\n showLabels,\n showPlan,\n sun,\n excavation,\n cityBuildings,\n cadastre,\n settings,\n setSettings,\n basemap,\n canAdopt,\n } = display;\n const sidebar = useProjectSidebar();\n const [planImportOpen, setPlanImportOpen] = useState(false);\n const [planImportMounted, setPlanImportMounted] = useState(false);\n useEffect(() => {\n if (!adapters.aiImport || readOnly) return;\n let active = true;\n void loadAiImportSession(adapters.assets, initial.id)\n .then(session => {\n if (active && session) {\n setPlanImportMounted(true);\n setPlanImportOpen(true);\n setMode('edit');\n setSidebarOpen(true);\n }\n })\n .catch(() => {});\n return () => {\n active = false;\n };\n }, [adapters.aiImport, adapters.assets, initial.id, readOnly]);\n const [importOpen, setImportOpen] = useState(false),\n [floorModal, setFloorModal] = useState(false),\n [helpOpen, setHelpOpen] = useState(false),\n [deleteOpen, setDeleteOpen] = useState(false),\n [floorDeleteId, setFloorDeleteId] = useState<string | null>(null);\n const [toast, setToast] = useState(''),\n [activeTab, setActiveTab] = useState<'structure' | 'objects'>('structure'),\n [statuses, setStatuses] = useState<Map<string, StatusReading>>(new Map());\n // The person, apart from the camera: where the last walk ended, or where the person marker was\n // dropped. Survives leaving the walk — the 2D plan shows them standing there — and not the project.\n const [avatar, setAvatar] = useState<WalkAvatar | null>(null);\n const [graphView, setGraphView] = useState(false);\n const [graphFloor, setGraphFloor] = useState<string | null | undefined>(undefined);\n const graphCamera = useRef<CameraState | undefined>(undefined);\n const pendingLocate = useRef<{ points: Point[] } | null>(null);\n useEffect(() => setAvatar(null), [project.id]);\n // Indoor navigation: route-tool chaining anchor, the A-to-B panel and journey playback state.\n const [navigating, setNavigating] = useState(false),\n [structuring, setStructuring] = useState(false),\n [navFrom, setNavFrom] = useState<string | null>(null),\n [navTo, setNavTo] = useState<string | null>(null),\n [playing, setPlaying] = useState(false),\n [playStep, setPlayStep] = useState<number | null>(null);\n const playingRef = useRef(false); // Set imperatively so the final writeHash on journey end is not skipped by a stale ref.\n const stopPlaying = useCallback(() => {\n playingRef.current = false;\n setPlaying(false);\n }, []);\n // \"Where you are\" is the avatar — where the last walk left the person, or where the marker was\n // dropped — and it is the start most people want, so the panel proposes it. It is a point, not\n // an object, and the router takes it as one.\n // While a route is being played the person is being carried along it, and a start that followed\n // them would shorten the route under the playback step by step. The start is frozen where the\n // play began and follows the person again once it stops.\n const playStart = useRef<WalkAvatar | null>(null);\n const route = useMemo(() => {\n const at = playing ? (playStart.current ?? avatar) : avatar;\n const end = (id: string | null): RouteEnd | null =>\n id === HERE ? (at ? { floorId: at.floorId, position: at.position } : null) : id;\n const a = end(navFrom),\n b = end(navTo);\n return a && b\n ? findRoute(history.present, a, b, {\n statuses: new Map([...statuses, ...(elevators?.statuses ?? []).map(s => [s.feedId, s] as const)]),\n })\n : null;\n }, [history.present, navFrom, navTo, avatar, playing, statuses, elevators?.statuses]);\n useEffect(() => {\n stopPlaying();\n setPlayStep(null);\n }, [navFrom, navTo, stopPlaying]);\n useEffect(() => {\n if (!route && playingRef.current) stopPlaying();\n }, [route, stopPlaying]);\n const [newFloorName, setNewFloorName] = useState('New floor'),\n [newFloorElevation, setNewFloorElevation] = useState(3),\n [newFloorBuilding, setNewFloorBuilding] = useState(project.buildings[0].id),\n [newBuildingName, setNewBuildingName] = useState('');\n const mapRef = useRef<GLMap | null>(null),\n latestProject = useRef(project),\n onChangeRef = useRef(onChange),\n onViewChangeRef = useRef(onViewChange);\n latestProject.current = project;\n onChangeRef.current = onChange;\n onViewChangeRef.current = onViewChange;\n // The current view (floor, mode, camera pose) is emitted through onViewChange on state changes and\n // on every camera moveend; hosts persist it however they like (the reference app writes a deep-link\n // fragment). The library itself touches no URL. writeHash keeps its name for its call sites.\n const viewRef = useRef({ floorId, threeD, stack, walk });\n viewRef.current = { floorId, threeD, stack, walk };\n // `force` distinguishes a state change from a camera move. Walking writes a camera every animation\n // frame, and every write here is a history.replaceState — so while walking only the mode change\n // itself is published, and the pose it publishes is the one you set off from.\n const writeHash = useCallback((force = false) => {\n const m = mapRef.current;\n if (!m || playingRef.current) return;\n const v = viewRef.current;\n if (v.walk && !force) return;\n const c = m.getCenter();\n onViewChangeRef.current?.({\n floor: v.floorId,\n threeD: v.threeD,\n stack: v.stack,\n walk: v.walk,\n camera: { center: [c.lng, c.lat], zoom: m.getZoom(), bearing: m.getBearing(), pitch: m.getPitch() },\n });\n }, []);\n useEffect(() => {\n writeHash(true);\n }, [floorId, threeD, stack, walk, writeHash]);\n // The three ways of looking at a plan. 2D is the drawing, 3D is the model, walk is standing in it —\n // one cycle so a single key reaches all three, and one setter so the modes cannot half-overlap\n // (walking a stack of every floor at once is not a thing a person can do).\n const viewMode: 'walk' | '3d' | '2d' = walk ? 'walk' : threeD ? '3d' : '2d';\n const nextView = viewMode === '2d' ? '3d' : viewMode === '3d' ? 'walk' : '2d';\n const chooseMode = (next: 'walk' | '3d' | '2d') => {\n setWalk(next === 'walk');\n setThreeD(next !== '2d');\n if (next === 'walk') setStack(false);\n if (next !== '2d') {\n setTool('select');\n setDraft([]);\n }\n };\n const theme = useKerrosTheme();\n const en = useStrings();\n const notify = useCallback(\n (message: string) => {\n if (theme.notify) theme.notify(message);\n else setToast(message);\n },\n [theme],\n );\n // Any selection, from any code path, reveals the properties panel (closed by default).\n useEffect(() => {\n if (selected) setInspectorOpen(true);\n }, [selected]);\n const { state: saveState, flush, saveNow } = useProjectPersistence(project, adapters.projects, !readOnly, notify);\n const applyAiProject = useCallback(\n async (document: ProjectDocument) => {\n const next = validateProject({ ...document, id: latestProject.current.id, updatedAt: new Date().toISOString() });\n latestProject.current = next;\n setHistory(current => ({ ...commitHistory(current, next), present: next }));\n setFloorId(current => (next.floors.some(f => f.id === current) ? current : openingFloorId(next)));\n setSelected(null);\n setDraft([]);\n // Use the same ordered writer as ordinary autosave, without waiting for its debounce.\n await saveNow(next);\n },\n [saveNow],\n );\n const leave = async () => {\n try {\n await flush();\n onBack?.();\n } catch {\n /* Keep the editable project open on a failed save. */\n }\n };\n useEffect(() => {\n if (!toast) return;\n const t = setTimeout(() => setToast(''), 6500);\n return () => clearTimeout(t);\n }, [toast]);\n // Every edit is a transaction: transact works on a clone, runs the full rule set, and returns a\n // frozen document or the reason it refused — the plan on screen is always a valid one.\n const commit = (change: (draft: ProjectDocument) => void): boolean => {\n if (!editing) return false;\n const result = transact(project, change);\n if (!result.ok) {\n notify(result.error);\n return false;\n }\n setHistory(current => commitHistory(current, result.project));\n return true;\n };\n const drawing = useDrawingTools({\n project,\n floorId,\n selected,\n editing,\n threeD,\n commit,\n notify,\n setSelected,\n onSelect: select,\n onFloorChange: changeFloor,\n onChooseTool: () => {\n setPalette(false);\n setThreeD(false);\n },\n });\n const {\n tool,\n setTool,\n draft,\n setDraft,\n hover,\n snapping,\n setSnapping,\n routeAnchor,\n setRouteAnchor,\n chooseTool,\n finish,\n adoptBuilding,\n onHover,\n guides,\n geometryPreview,\n vertexMove,\n updateObject,\n } = drawing;\n const { alignment, setAlignment, startAlignment, previewAlignment, confirmAlignment, calibrate, displayProject } =\n useReferenceAlignment({\n project,\n floorId,\n assets: adapters.assets,\n commit,\n notify,\n setSelected,\n onStart: () => {\n setThreeD(false);\n setTool('select');\n },\n });\n // Geometry synchronization lives in transact, including host edits and every drawing tool.\n const reshape = commit;\n useEffect(() => {\n if (!readOnly) onChangeRef.current?.(project);\n }, [project, readOnly]);\n const bindingKey = project.objects\n .filter(o => o.feedId)\n .map(o => o.feedId)\n .sort()\n .join('|');\n useEffect(() => {\n setStatuses(new Map());\n }, [project.id]);\n useEffect(() => {\n return adapters.status?.subscribe(latestProject.current, values =>\n setStatuses(current => {\n const next = new Map(current);\n for (const status of values) next.set(status.feedId, status);\n return next;\n }),\n );\n }, [adapters.status, bindingKey, project.id]);\n useEffect(() => {\n const timer = setInterval(() => setStatuses(current => new Map(current)), 5000);\n return () => clearInterval(timer);\n }, []);\n // Plan viewer browses pure architecture; the editor keeps statuses visible (authors simulate\n // bindings while wiring them) and 'live' is the dedicated monitoring surface.\n const shownStatuses = useMemo(\n () =>\n new Map([...(mode === 'view' ? [] : statuses), ...(elevators?.statuses ?? []).map(s => [s.feedId, s] as const)]),\n [mode, statuses, elevators?.statuses],\n );\n const floor = project.floors.find(f => f.id === floorId);\n const alarms = useMemo(\n () => project.objects.filter(o => o.feedId && statusTone(statuses.get(o.feedId)) === 'critical'),\n [statuses, project],\n );\n const alarmFloors = useMemo(() => new Set(alarms.map(o => o.floorId)), [alarms]);\n // Report the current surface to the host (a monitoring host can start/stop its feed's traffic here).\n const onModeChangeRef = useRef(onModeChange);\n onModeChangeRef.current = onModeChange;\n useEffect(() => {\n onModeChangeRef.current?.(mode);\n }, [mode]);\n // Live view auto-attention: if the user has been idle for 5 s and a new alarm is active on the\n // open floor, pan to it (each alarm pans once; a cleared-then-retriggered binding pans again).\n const lastInput = useRef(Date.now()),\n autoPanned = useRef(new Set<string>());\n useEffect(() => {\n const mark = () => {\n lastInput.current = Date.now();\n };\n const types = ['pointerdown', 'wheel', 'keydown', 'touchstart'];\n for (const t of types) window.addEventListener(t, mark, true);\n return () => {\n for (const t of types) window.removeEventListener(t, mark, true);\n };\n }, []);\n useEffect(() => {\n if (!live) return;\n const timer = setInterval(() => {\n const active = new Set(alarms.map(o => o.id));\n for (const id of autoPanned.current) if (!active.has(id)) autoPanned.current.delete(id);\n if (Date.now() - lastInput.current < 5000) return;\n const target = alarms.find(o => o.floorId === floorId && !autoPanned.current.has(o.id));\n if (target) {\n autoPanned.current.add(target.id);\n setFocusId(target.id);\n }\n }, 1000);\n return () => clearInterval(timer);\n }, [live, alarms, floorId]); // eslint-disable-line react-hooks/exhaustive-deps\n // Mode entry keeps the chrome consistent: only the editor needs the side panels open by default.\n function enterView() {\n setMode('view');\n setTool('select');\n setDraft([]);\n setSidebarOpen(false);\n setInspectorOpen(false);\n setThreeD(true);\n }\n function enterEdit() {\n if (readOnly) return;\n setMode('edit');\n setThreeD(false);\n setSidebarOpen(true);\n }\n function enterLive() {\n setMode('live');\n setTool('select');\n setDraft([]);\n setSidebarOpen(false);\n setInspectorOpen(false);\n setThreeD(true);\n }\n function stepFloor(direction: 1 | -1) {\n const list = floorBand(project, floorId);\n const index = list.findIndex(f => f.id === floorId);\n const next = index < 0 ? (direction === 1 ? list[0] : list[list.length - 1]) : list[index + direction];\n if (next) changeFloor(next.id);\n }\n const keyHint = (label: string) => (showKeys ? <kbd className=\"key-hint\">{label}</kbd> : null);\n function select(id: string | null, focus = false) {\n const entity =\n project.objects.find(o => o.id === id) ??\n project.barriers.find(b => b.id === id) ??\n project.virtualBoundaries?.find(b => b.id === id) ??\n project.drawings.find(d => d.id === id);\n if (entity && entity.floorId !== floorId && entity.floorId !== null) {\n setFloorId(entity.floorId);\n setDraft([]);\n setRouteAnchor(null);\n if (tool !== 'select' && tool !== 'pan') setTool('select');\n }\n setSelected(id);\n onSelectionChange?.(id);\n if (id) setInspectorOpen(true);\n if (focus) setFocusId(id);\n }\n function openGraph(floor?: string | null) {\n const map = mapRef.current;\n if (map) {\n const center = map.getCenter();\n graphCamera.current = {\n center: [center.lng, center.lat],\n zoom: map.getZoom(),\n pitch: map.getPitch(),\n bearing: map.getBearing(),\n };\n }\n stopPlaying();\n setWalk(false);\n setGraphFloor(floor);\n setGraphView(true);\n mapRef.current = null;\n }\n function frameLocated() {\n const target = pendingLocate.current,\n map = mapRef.current;\n if (!target || !map) return;\n pendingLocate.current = null;\n if (!target.points.length) return;\n let west = Infinity,\n east = -Infinity,\n south = Infinity,\n north = -Infinity;\n for (const point of target.points) {\n const [lng, lat] = toLngLat(point, project.origin);\n west = Math.min(west, lng);\n east = Math.max(east, lng);\n south = Math.min(south, lat);\n north = Math.max(north, lat);\n }\n map.fitBounds(\n [\n [west, south],\n [east, north],\n ],\n { padding: 90, maxZoom: 20, duration: 450 },\n );\n }\n function locateStructure(target: StructureTarget) {\n const ids = new Set(target.objectIds ?? []);\n const objects = project.objects.filter(object => ids.has(object.id));\n const chosenFloor =\n target.floorId !== undefined\n ? target.floorId\n : objects.some(object => object.floorId === floorId)\n ? floorId\n : (objects[0]?.floorId ?? floorId);\n const onFloor = objects.filter(\n object => object.floorId === chosenFloor || object.servedFloorIds?.includes(chosenFloor ?? ''),\n );\n const points = target.position ? [target.position] : onFloor.flatMap(object => footprint(object).flat());\n if (!points.length)\n points.push(\n ...project.objects.filter(object => object.floorId === chosenFloor).flatMap(object => footprint(object).flat()),\n );\n pendingLocate.current = { points };\n setSelected(onFloor[0]?.id ?? null);\n onSelectionChange?.(onFloor[0]?.id ?? null);\n setGraphView(false);\n chooseMode('2d');\n setFloorId(chosenFloor);\n requestAnimationFrame(frameLocated);\n }\n useEffect(() => {\n if (!graphView) requestAnimationFrame(frameLocated);\n }, [graphView, floorId, threeD]);\n function changeFloor(id: string | null) {\n setFloorId(id);\n setSelected(null);\n setDraft([]);\n setTool('select');\n setAlignment(null);\n setRouteAnchor(null);\n }\n function mapClick(raw: Point, id: string | null) {\n // Reference alignment consumes map clicks before the drawing tools.\n if (window.matchMedia('(max-width: 840px)').matches) setSidebarOpen(false);\n if (alignment) {\n if (alignment.preview || alignment.imagePoints.length < 2 || alignment.mapPoints.length >= 2) return;\n setAlignment({ ...alignment, mapPoints: [...alignment.mapPoints, raw] });\n return;\n }\n drawing.mapClick(raw, id);\n }\n /** Write the derived graph into the document, so it can be edited.\n *\n * A plan with no authored graph still routes: navNodes() falls back to the dual of spaces and\n * portals, recomputed from the geometry, and that is usually the right thing to leave alone —\n * a stored graph is a second description of what connects to what, and two descriptions drift.\n * What you cannot do with a derived graph is change it. Adopting it freezes the current one into\n * the document as a starting point; from then on it is yours, and it stops following the plan. */\n function adoptDerivedGraph() {\n const { nodes, edges } = derivedGraph(project);\n if (\n commit(p => {\n p.navNodes = nodes.map(n => ({ ...n }));\n p.navEdges = edges.map(e => ({ ...e }));\n })\n )\n notify(\n `Adopted ${nodes.length} node${nodes.length === 1 ? '' : 's'} and ${edges.length} edges · the graph no longer follows the plan.`,\n );\n }\n function duplicateSelected() {\n if (!selected) return;\n commit(p => {\n const o = p.objects.find(o => o.id === selected);\n if (!o || o.barrierId) return;\n const clone = structuredClone(o);\n clone.id = uid();\n clone.name += ' copy';\n clone.feedId = undefined;\n clone.geometry = { mode: 'independent' };\n clone.parentId = undefined;\n clone.position = add(clone.position, [2, -2]);\n clone.rings = clone.rings?.map(r => r.map(pt => add(pt, [2, -2])));\n p.objects.push(clone);\n setSelected(clone.id);\n });\n }\n /** Deleting a floor takes its contents with it, so it always confirms — via the host's dialog when\n * one is supplied, otherwise the built-in modal. */\n function floorLoss(id: string) {\n const objects = project.objects.filter(o => o.floorId === id).length;\n const barriers = project.barriers.filter(b => b.floorId === id).length;\n const parts = [\n objects && `${objects} object${objects > 1 ? 's' : ''}`,\n barriers && `${barriers} wall${barriers > 1 ? 's' : ''}`,\n ].filter(Boolean);\n return parts.length ? `This also removes ${parts.join(' and ')}.` : 'This floor is empty.';\n }\n function deleteFloorNow(id: string) {\n const fallback = project.floors.filter(f => f.id !== id).sort((a, b) => a.elevation - b.elevation);\n if (commit(p => void removeFloor(p, id))) {\n if (floorId === id) changeFloor(fallback.find(f => f.elevation === 0)?.id ?? fallback[0]?.id ?? null);\n notify('Floor removed with everything on it. Undo restores it.');\n }\n setFloorDeleteId(null);\n }\n async function requestDeleteFloor(id: string) {\n if (project.floors.length <= 1) {\n notify('A project needs at least one floor.');\n return;\n }\n if (!theme.confirm) {\n setFloorDeleteId(id);\n return;\n }\n const floor = project.floors.find(f => f.id === id);\n if (\n await theme.confirm({\n title: `Delete ${floor?.name ?? 'this floor'}?`,\n body: floorLoss(id),\n danger: true,\n confirmLabel: 'Delete floor',\n })\n )\n deleteFloorNow(id);\n }\n async function requestDelete() {\n if (!selected) return;\n if (!theme.confirm) {\n setDeleteOpen(true);\n return;\n }\n if (\n await theme.confirm({\n title: 'Delete selected object?',\n body: deleteCount\n ? `This also removes ${deleteCount} attached opening${deleteCount > 1 ? 's' : ''}.`\n : 'Child zones become independent areas.',\n danger: true,\n confirmLabel: 'Delete object',\n })\n )\n deleteSelected();\n }\n function deleteSelected() {\n if (!selected) return;\n // A wall that was the only thing between two spaces leaves them open to each other. Saying\n // nothing would leave the plan showing two rooms where there is now one; merging silently would\n // destroy a name, its feed bindings and its zone memberships. So ask, and let the answer say which.\n const virtual = project.virtualBoundaries?.some(b => b.id === selected);\n const owners = virtual\n ? project.objects.filter(\n o => o.geometry?.mode === 'boundaries' && o.geometry.loops.some(l => l.some(u => u.edgeId === selected)),\n )\n : [];\n if (virtual && owners.length === 1) {\n notify('This boundary closes a space. Move it, or switch the space to Independent outline before removing it.');\n setDeleteOpen(false);\n return;\n }\n const rejoin =\n owners.length === 2\n ? owners\n : project.barriers.some(b => b.id === selected)\n ? spacesRejoinedBy(project, selected)\n : null;\n if (rejoin && !merge) {\n // One question at a time. The delete prompt has been answered — the wall is going — and what\n // is left to settle is what happens to the two spaces it separated. Leaving it open stacks a\n // second dialog on a first that is already spent, and answering the merge leaves the delete\n // prompt standing there asking again.\n setDeleteOpen(false);\n setMerge({ wallId: selected, a: rejoin[0], b: rejoin[1] });\n return;\n }\n if (\n // The transaction preserves referenced walls as virtual edges and regenerates space caches.\n reshape(p => {\n p.objects = p.objects.filter(o => o.id !== selected && o.barrierId !== selected);\n p.objects.forEach(o => {\n if (o.parentId === selected) o.parentId = undefined;\n });\n p.barriers = p.barriers.filter(b => b.id !== selected);\n if (p.virtualBoundaries) p.virtualBoundaries = p.virtualBoundaries.filter(b => b.id !== selected);\n p.drawings = p.drawings.filter(d => d.id !== selected);\n p.junctions = p.junctions.filter(j => boundaryEdges(p).some(b => b.startId === j.id || b.endId === j.id));\n // Navigation cascade: drop the nav node itself if selected, nodes bound to any removed object,\n // and every edge that lost an endpoint or its bound object (validateNavigation rejects dangling refs).\n if (p.navNodes?.length) {\n const objectIds = new Set(p.objects.map(o => o.id));\n p.navNodes = p.navNodes.filter(\n n => n.id !== selected && (n.objectId === undefined || objectIds.has(n.objectId)),\n );\n const nodeIds = new Set(p.navNodes.map(n => n.id));\n p.navEdges = (p.navEdges ?? []).filter(\n e => nodeIds.has(e.aId) && nodeIds.has(e.bId) && (e.objectId === undefined || objectIds.has(e.objectId)),\n );\n }\n // The ontology references objects too, and every reference is validated — without this the\n // whole delete is refused and nothing appears to happen.\n pruneOntology(p);\n })\n ) {\n select(null);\n setDeleteOpen(false);\n if (routeAnchor === selected) setRouteAnchor(null);\n }\n }\n // Seek the panel/journey to an instruction step: pause playback, emphasise the step, and bring\n // the view there — a floor switch lets MapCanvas's own fit frame the level; a same-floor seek\n // glides to the step's last node.\n function seekStep(index: number) {\n if (!route) return;\n const clamped = Math.max(0, Math.min(route.steps.length - 1, index));\n const step = route.steps[clamped];\n stopPlaying();\n setPlayStep(clamped);\n const moved = step.floorId !== floorId;\n if (moved) setFloorId(step.floorId);\n const node = route.nodes.find(n => n.id === step.nodeIds.at(-1));\n if (!moved && node && mapRef.current)\n mapRef.current.easeTo({\n // Through the map's own depth aim: in 3D the step is drawn at its storey's elevation, and a\n // node in the garage centred on its ground coordinate lands well outside the frame.\n center: floorAim(mapRef.current, project, node.position, step.floorId, { threeD, stack }),\n zoom: Math.max(mapRef.current.getZoom(), 18),\n duration: 550,\n });\n }\n async function doExport() {\n try {\n download(\n await exportProject(project, adapters.assets),\n `${project.name.toLowerCase().replace(/[^a-z0-9]+/g, '-')}.json`,\n );\n notify('Portable project exported with reference drawings.');\n } catch (e) {\n notify((e as Error).message);\n }\n }\n const showKeys = usePlannerKeyboard({\n graphView,\n editing,\n threeD,\n walk,\n hasDraft: !!draft.length,\n hasSelection: !!selected,\n mapRef,\n chooseTool,\n stepFloor,\n commands: {\n undo: () => {\n setHistory(undoHistory);\n setDraft([]);\n setRouteAnchor(null);\n },\n redo: () => {\n setHistory(redoHistory);\n setDraft([]);\n setRouteAnchor(null);\n },\n undoPoint: () => setDraft(draft.slice(0, -1)),\n export: doExport,\n cancel: () => {\n setDraft([]);\n setTool('select');\n setPalette(false);\n setInspectorOpen(false);\n setRouteAnchor(null);\n if (navigating) {\n stopPlaying();\n setNavigating(false);\n }\n if (alignment) setAlignment(null);\n else select(null);\n },\n finish,\n help: () => setHelpOpen(true),\n view: enterView,\n edit: enterEdit,\n walk: () => chooseMode('walk'),\n live: enterLive,\n cycleView: () => chooseMode(nextView),\n toggleStack: () => setStack(!stack),\n toggleSidebar: () => setSidebarOpen(!sidebarOpen),\n toggleInspector: () => {\n setPlanImportOpen(false);\n setStructuring(false);\n setNavigating(false);\n setInspectorOpen(!inspectorOpen);\n },\n toggleFullscreen: () => setFullscreen(!fullscreen),\n toggleNavigation: () => {\n setPlanImportOpen(false);\n if (navigating) stopPlaying();\n setNavigating(!navigating);\n },\n toggleTheme: toggleDark,\n deleteSelection: () => setDeleteOpen(true),\n duplicate: duplicateSelected,\n },\n });\n function traceFootprint(id: string) {\n const footprint = project.objects.find(o => o.id === id);\n if (!footprint?.rings) return;\n if (floorId === null) {\n notify('Select a destination floor, then select the footprint in Objects to create its walls.');\n return;\n }\n commit(p => {\n for (const ring of footprint.rings!) {\n const closed = closeRing(ring);\n for (let i = 1; i < closed.length; i++) addBarrier(p, closed[i - 1], closed[i], floorId, 'wall');\n }\n const area = createObject('zone', footprint.position, floorId, floor?.name ?? 'Floor');\n area.width = footprint.width;\n area.depth = footprint.depth;\n area.rings = structuredClone(footprint.rings);\n p.objects.push(area);\n });\n }\n const selectedBarrier = project.barriers.find(b => b.id === selected);\n const deleteCount = selectedBarrier ? project.objects.filter(o => o.barrierId === selected).length : 0;\n const renderImport = (importMode: 'reference' | 'plan') => (\n <ImportDialog\n key={`${project.id}:${importMode}`}\n mode={importMode}\n project={project}\n floorId={floorId}\n assets={adapters.assets}\n importProjections={adapters.importProjections}\n aiImport={adapters.aiImport}\n pdfDrawing={adapters.pdfDrawing}\n onAiProject={applyAiProject}\n onAiRunningChange={setAiRunning}\n onClose={() => (importMode === 'plan' ? setPlanImportOpen(false) : setImportOpen(false))}\n onDrawing={startAlignment}\n onProject={async p => {\n await flush();\n setHistory(makeHistory(p));\n setFloorId(p.floors[0]?.id ?? null);\n setNewFloorBuilding(p.buildings[0].id);\n select(null);\n }}\n onOrigin={bearing => {\n commit(d => {\n const [lng, lat] = d.origin;\n d.origin = (bearing ? [lng, lat, bearing] : [lng, lat]) as typeof d.origin;\n });\n }}\n onPlan={(entities, target, layers) => {\n let outcome: PlanImportReport | undefined;\n if (\n commit(d => {\n outcome = importPlanEntities(d, entities, layers ? { floorId: target, layers } : { floorId: target });\n }) &&\n outcome\n ) {\n if (target !== floorId) setFloorId(target);\n setActiveTab('structure');\n const skipped = outcome.skipped.length ? ` · ${outcome.skipped.length} skipped` : '';\n notify(\n `Plan imported: ${outcome.walls} walls, ${outcome.rooms} rooms, ${outcome.doors} doors, ${outcome.windows} windows${outcome.passages ? ` · ${outcome.passages} open passages` : ''}${skipped}.`,\n );\n }\n }}\n onFootprints={objects => {\n if (commit(p => p.objects.push(...objects))) {\n setSelected(objects[0]?.id ?? null);\n setActiveTab('objects');\n const first = objects[0];\n if (first && mapRef.current)\n mapRef.current.easeTo({ center: toLngLat(first.position, project.origin), zoom: 18 });\n notify(\n `Imported ${objects.length} ${objects.length === 1 ? 'footprint' : 'footprints'}. Select a floor to generate its walls.`,\n );\n }\n }}\n />\n );\n return (\n <div className={`kerros-root app-shell ${fullscreen ? 'fullscreen' : ''}`}>\n <header className=\"app-header\">\n <a\n className=\"brand\"\n href=\"#\"\n onClick={e => {\n e.preventDefault();\n void leave();\n }}\n >\n <span className=\"brand-mark\">\n <Layers3 size={22} strokeWidth={2} />\n </span>\n <strong>{en.brand}</strong>\n <span className=\"brand-divider\" />\n <span className=\"brand-product\">{en.app}</span>\n </a>\n <div className=\"mode-switch\">\n <button className={mode === 'view' ? 'active' : ''} onClick={enterView}>\n <Eye size={15} />\n <span className=\"mode-label\">{en.viewer}</span>\n {keyHint('1')}\n </button>\n {!readOnly && (\n <button className={mode === 'edit' ? 'active' : ''} onClick={enterEdit}>\n <MousePointer2 size={15} />\n <span className=\"mode-label\">{en.editor}</span>\n {keyHint('2')}\n </button>\n )}\n {monitoring && (\n <button className={mode === 'live' ? 'active' : ''} onClick={enterLive}>\n <Radio size={15} />\n <span className=\"mode-label\">{en.monitor}</span>\n {keyHint('3')}\n </button>\n )}\n </div>\n <div className=\"header-right\">\n <span className={`save-status ${saveState}`}>\n <span />\n {readOnly\n ? 'Read-only viewer'\n : en[saveState === 'saved' ? 'saved' : saveState === 'saving' ? 'saving' : 'saveError']}\n </span>\n <button\n className=\"icon-button\"\n title={dark ? 'Switch to light mode' : 'Switch to dark mode'}\n aria-label={dark ? 'Switch to light mode' : 'Switch to dark mode'}\n onClick={toggleDark}\n >\n {dark ? <Sun size={18} /> : <Moon size={18} />}\n {keyHint('N')}\n </button>\n <button\n className=\"icon-button help-button\"\n title=\"Help and shortcuts (?)\"\n aria-label=\"Help and shortcuts\"\n onClick={() => setHelpOpen(true)}\n >\n <CircleHelp size={19} />\n {keyHint('?')}\n </button>\n <span className=\"avatar\">KH</span>\n </div>\n </header>\n <div className=\"workspace\">\n {sidebarOpen && (\n <ProjectSidebar\n state={sidebar}\n project={project}\n floorId={floorId}\n selected={selected}\n mode={mode}\n editing={editing}\n readOnly={readOnly}\n statuses={statuses}\n alarmFloors={alarmFloors}\n activeTab={activeTab}\n setActiveTab={setActiveTab}\n leave={leave}\n select={select}\n changeFloor={changeFloor}\n onAnchor={() => {\n if (!editing) enterEdit();\n select(null);\n setInspectorOpen(true);\n }}\n onAddFloor={() => {\n setNewFloorElevation(Math.max(...project.floors.map(f => f.elevation + f.height)));\n setFloorModal(true);\n }}\n onDuplicateFloor={() => {\n let id = '';\n if (\n commit(p => {\n id = duplicateFloor(p, floorId!);\n })\n ) {\n setFloorId(id);\n notify('Floor duplicated with new IDs and cleared feed bindings.');\n }\n }}\n onImportReference={() => setImportOpen(true)}\n />\n )}\n <main className=\"canvas-column\">\n <div className=\"canvas-header\">\n <button\n className=\"icon-button\"\n aria-label={sidebarOpen ? 'Hide side panel' : 'Show side panel'}\n title={sidebarOpen ? 'Hide side panel' : 'Show side panel'}\n onClick={() => setSidebarOpen(!sidebarOpen)}\n >\n {sidebarOpen ? <PanelLeftClose size={17} /> : <PanelLeftOpen size={17} />}\n {keyHint('B')}\n </button>\n <div className=\"breadcrumb\">\n <span>{project.name}</span>\n <ChevronRight size={13} />\n <strong>{floor?.name ?? 'Outdoor site'}</strong>\n <span className=\"mode-pill\">{aiRunning ? 'AI IMPORT' : editing ? 'EDITING' : 'VIEWING'}</span>\n </div>\n <div>\n {(editing || aiRunning) && (\n <button\n className=\"icon-button\"\n aria-label=\"Import plan\"\n title=\"Import plan\"\n aria-pressed={planImportOpen}\n data-import-running={aiRunning || undefined}\n onClick={() => {\n setPlanImportMounted(true);\n setPlanImportOpen(!planImportOpen);\n if (!planImportOpen) {\n setNavigating(false);\n setStructuring(false);\n setInspectorOpen(false);\n }\n }}\n >\n <ArrowDownToLine size={17} />\n </button>\n )}\n <button\n className=\"icon-button\"\n aria-label=\"Export project\"\n title=\"Export portable project\"\n onClick={doExport}\n >\n <ArrowUpFromLine size={17} />\n </button>\n <button\n className={`icon-button ${structuring ? 'active-nav' : ''}`}\n aria-label={structuring ? 'Hide structure panel' : 'Show structure panel'}\n title=\"Structure — zones and portals\"\n onClick={() => {\n setPlanImportOpen(false);\n setStructuring(!structuring);\n if (!structuring) setNavigating(false);\n }}\n >\n <Shapes size={17} />\n </button>\n <button\n className={`icon-button ${navigating ? 'active-nav' : ''}`}\n aria-label={navigating ? 'Hide navigation panel' : 'Show navigation panel'}\n title=\"Navigate (G)\"\n onClick={() => {\n setPlanImportOpen(false);\n if (navigating) stopPlaying();\n setNavigating(!navigating);\n if (!navigating) setStructuring(false);\n }}\n >\n <Waypoints size={17} />\n {keyHint('G')}\n </button>\n <button\n className=\"icon-button\"\n aria-label={inspectorOpen ? 'Hide properties panel' : 'Show properties panel'}\n title={inspectorOpen ? 'Hide properties panel' : 'Show properties panel'}\n onClick={() => {\n setPlanImportOpen(false);\n setStructuring(false);\n setNavigating(false);\n setInspectorOpen(!inspectorOpen);\n }}\n >\n {inspectorOpen ? <PanelRightClose size={17} /> : <PanelRightOpen size={17} />}\n {keyHint('I')}\n </button>\n </div>\n </div>\n {graphView ? (\n <Suspense\n fallback={\n <p className=\"structure-empty\" role=\"status\">\n Loading navigation graph…\n </p>\n }\n >\n <NavigationGraph\n project={project}\n initialFloor={graphFloor}\n dark={dark}\n onLocate={locateStructure}\n onClose={() => setGraphView(false)}\n />\n </Suspense>\n ) : (\n <div className=\"canvas-body\">\n <MapCanvas\n project={displayProject}\n canEdit={editing}\n floorId={floorId}\n selected={selected}\n tool={tool}\n draft={draft}\n hover={hover}\n guides={guides}\n threeD={threeD}\n stack={stack}\n coverage={coverage}\n showLabels={showLabels}\n showPlan={showPlan}\n sun={sun}\n dark={dark}\n excavation={excavation}\n cityBuildings={cityBuildings}\n cadastre={cadastre}\n basemap={basemap}\n assets={adapters.assets}\n statuses={shownStatuses}\n elevators={elevators}\n focusId={focusId}\n alignment={alignment ? { image: alignment.imagePoints, map: alignment.mapPoints } : undefined}\n onClick={mapClick}\n onAdopt={adoptBuilding}\n onHover={onHover}\n onSelect={id => select(id)}\n onVertexMove={vertexMove}\n onVertexPreview={(kind, id, point, ring, vertex, free) =>\n geometryPreview(kind, id, point, free, ring, vertex)\n }\n snapping={snapping}\n onError={notify}\n route={route}\n activeStep={playStep}\n playing={playing}\n onJourneyStep={index => setPlayStep(index)}\n onJourneyEnd={() => {\n stopPlaying();\n writeHash(true);\n }}\n walk={walk}\n onWalkExit={() => chooseMode('3d')}\n avatar={avatar}\n onAvatar={setAvatar}\n onWalkAt={a => {\n setAvatar(a);\n if (a.floorId !== floorId) setFloorId(a.floorId);\n chooseMode('walk');\n }}\n onRequestFloor={id => setFloorId(id)}\n onReady={map => {\n mapRef.current = map;\n requestAnimationFrame(frameLocated);\n map.on('moveend', () => writeHash());\n writeHash(true);\n }}\n initialCamera={graphCamera.current ?? initialView?.camera}\n />\n <FloorControls\n project={project}\n floorId={floorId}\n mode={mode}\n viewMode={viewMode}\n stack={stack}\n alarmFloors={alarmFloors}\n showKeys={showKeys}\n changeFloor={changeFloor}\n chooseMode={chooseMode}\n setStack={setStack}\n stepFloor={stepFloor}\n />\n <div className=\"canvas-top-right\">\n {monitoring && mode !== 'view' && (\n <button\n className={`live-badge ${alarms.length ? 'has-alarm' : ''}`}\n onClick={() => {\n if (alarms[0]) select(alarms[0].id, true);\n else notify('Everything bound to the feed is reporting without active alarms.');\n }}\n >\n {alarms.length ? <Bell size={14} /> : <span className=\"live-pip\" />}\n {alarms.length ? `${alarms.length} active alarm${alarms.length > 1 ? 's' : ''}` : 'Status feed'}\n </button>\n )}\n <button\n className={`floating-icon ${fullscreen ? 'active' : ''}`}\n aria-label={fullscreen ? 'Exit full screen' : 'Full-screen map'}\n title={fullscreen ? 'Exit full screen' : 'Full-screen map'}\n onClick={() => setFullscreen(!fullscreen)}\n >\n {fullscreen ? <Minimize2 size={18} /> : <Maximize2 size={18} />}\n {keyHint('F')}\n </button>\n <button\n className={`floating-icon ${settings ? 'active' : ''}`}\n aria-label=\"Map settings\"\n onClick={() => setSettings(!settings)}\n >\n <Settings2 size={18} />\n </button>\n </div>\n {settings && (\n <MapSettings\n display={display}\n project={project}\n floorId={floorId}\n editing={editing}\n hostBasemap={adapters.basemap}\n commit={commit}\n snapping={snapping}\n setSnapping={setSnapping}\n />\n )}\n {editing && !threeD && !alignment && (\n <DrawingDock\n drawing={drawing}\n projectHasGraph={!!project.navNodes}\n showKeys={showKeys}\n palette={palette}\n setPalette={setPalette}\n canAdopt={canAdopt}\n adoptDerivedGraph={adoptDerivedGraph}\n canUndo={!!history.past.length}\n canRedo={!!history.future.length}\n onUndo={() => {\n setHistory(undoHistory);\n setDraft([]);\n setRouteAnchor(null);\n }}\n onRedo={() => {\n setHistory(redoHistory);\n setDraft([]);\n setRouteAnchor(null);\n }}\n />\n )}\n {mode !== 'view' && (\n <div className=\"map-legend\">\n <span>\n <i className=\"status-dot normal\" />\n Normal\n </span>\n <span>\n <i className=\"status-dot warning\" />\n Attention\n </span>\n <span>\n <i className=\"status-dot critical\" />\n Alarm\n </span>\n <span>\n <i className=\"status-dot unknown\" />\n Unknown\n </span>\n </div>\n )}\n </div>\n )}\n <div className=\"canvas-statusbar\">\n <span>\n <span className=\"status-dot normal\" />\n {graphView\n ? 'Navigation graph'\n : editing\n ? 'Editor ready'\n : live\n ? 'Live view ready'\n : 'Plan viewer ready'}\n </span>\n <span>\n {project.barriers.length} barriers <i />\n {project.objects.length} objects <i />\n {project.floors.length} floors\n </span>\n <span>\n {graphView\n ? 'Drag to arrange · scroll to zoom'\n : snapping\n ? 'Snapping on · 0.5 m · 15°'\n : 'Free positioning'}\n <kbd>?</kbd>\n </span>\n </div>\n </main>\n {planImportMounted && (\n <div className=\"plan-import-slot\" hidden={!planImportOpen}>\n {renderImport('plan')}\n </div>\n )}\n {!planImportOpen &&\n (alignment ? (\n <AlignmentPanel\n drawing={alignment.prepared}\n imagePoints={alignment.imagePoints}\n mapPoints={alignment.mapPoints}\n preview={alignment.preview}\n setImagePoints={imagePoints => setAlignment({ ...alignment, imagePoints, mapPoints: [], preview: false })}\n onCancel={() => setAlignment(null)}\n onPreview={previewAlignment}\n onConfirm={confirmAlignment}\n onKnownDistance={calibrate}\n />\n ) : structuring ? (\n <StructureView\n project={project}\n selected={selected}\n onSelect={setSelected}\n onFloorChange={changeFloor}\n onLocate={locateStructure}\n onGraphView={openGraph}\n // Same commit path as every map tool, so zones land in history and undo like anything else.\n onEdit={editing ? change => commit(change) : undefined}\n />\n ) : navigating ? (\n <NavigatePanel\n project={project}\n here={avatar ? { floorId: avatar.floorId, position: avatar.position } : null}\n from={navFrom}\n to={navTo}\n route={route}\n playing={playing}\n activeStep={playStep}\n editing={editing}\n onFrom={setNavFrom}\n onTo={setNavTo}\n onSwap={() => {\n setNavFrom(navTo);\n setNavTo(navFrom);\n }}\n onClear={() => {\n setNavFrom(null);\n setNavTo(null);\n }}\n onPlay={() => {\n setGraphView(false);\n playStart.current = avatar;\n playingRef.current = true;\n setPlayStep(0);\n setPlaying(true);\n }}\n onPause={stopPlaying}\n onStep={delta => seekStep((playStep ?? (delta === 1 ? -1 : 1)) + delta)}\n onSeek={seekStep}\n onClose={() => {\n stopPlaying();\n setNavigating(false);\n }}\n />\n ) : inspectorOpen ? (\n <Inspector\n onEdit={editing ? change => commit(change) : undefined}\n onSpaceGeometry={\n editing\n ? (id, source) =>\n commit(p => (source === 'independent' ? disconnectSpace(p, id) : connectSpace(p, id, source)))\n : undefined\n }\n onShiftOrigin={\n editing\n ? (east, north) =>\n commit(p => {\n p.origin = moveOrigin(p.origin, east, north);\n })\n : undefined\n }\n project={project}\n floorId={floorId}\n selected={selected}\n statuses={shownStatuses}\n monitoring={monitoring}\n editing={editing}\n live={live}\n renderStatusPanel={renderStatusPanel}\n onClose={() => {\n select(null);\n setInspectorOpen(false);\n if (window.matchMedia('(max-width: 840px)').matches) setSidebarOpen(false);\n }}\n onUpdateObject={updateObject}\n onUpdateBarrier={(id: string, patch: Partial<Barrier>) =>\n // Thickness is geometry: a wall that grows eats into the rooms on either side of it.\n reshape(p => Object.assign(p.barriers.find(b => b.id === id)!, patch))\n }\n onUpdateDrawing={(id: string, patch: Partial<Drawing>) =>\n commit(p => Object.assign(p.drawings.find(d => d.id === id)!, patch))\n }\n onUpdateFloor={(id: string, patch: Partial<Floor>) =>\n commit(p => Object.assign(p.floors.find(f => f.id === id)!, patch))\n }\n onDeleteFloor={requestDeleteFloor}\n onSetInitialFloor={(id: string | null) =>\n commit(p => {\n // Clearing drops the field entirely — an explicit null would mean \"open outdoors\",\n // which is a different intent from having no preference.\n if (id === null) delete p.initialFloorId;\n else p.initialFloorId = id;\n })\n }\n onDuplicate={duplicateSelected}\n onDelete={requestDelete}\n onSelect={id => select(id, true)}\n onFloor={changeFloor}\n onTraceFootprint={traceFootprint}\n />\n ) : null)}\n </div>\n {toast && (\n <div className=\"toast\" role=\"status\">\n <InfoIcon />\n <span>{toast}</span>\n <button aria-label=\"Dismiss notification\" onClick={() => setToast('')}>\n <X size={16} />\n </button>\n </div>\n )}\n {importOpen && renderImport('reference')}\n {floorModal && (\n <Modal\n title=\"Add a floor\"\n subtitle=\"Create a level at its real elevation relative to the site.\"\n onClose={() => setFloorModal(false)}\n >\n <label className=\"field\">\n <span>Floor name</span>\n <input aria-label=\"New floor name\" value={newFloorName} onChange={e => setNewFloorName(e.target.value)} />\n </label>\n <div className=\"field-grid\">\n <label className=\"field\">\n <span>Building</span>\n <select value={newFloorBuilding} onChange={e => setNewFloorBuilding(e.target.value)}>\n {project.buildings.map(b => (\n <option value={b.id} key={b.id}>\n {b.name}\n </option>\n ))}\n <option value=\"new\">+ New building</option>\n </select>\n </label>\n <label className=\"field\">\n <span>Elevation (m)</span>\n <input\n aria-label=\"New floor elevation\"\n type=\"number\"\n value={newFloorElevation}\n onChange={e => setNewFloorElevation(Number(e.target.value))}\n />\n </label>\n </div>\n {newFloorBuilding === 'new' && (\n <label className=\"field\">\n <span>Building name</span>\n <input value={newBuildingName} onChange={e => setNewBuildingName(e.target.value)} />\n </label>\n )}\n <footer>\n <button className=\"button secondary\" onClick={() => setFloorModal(false)}>\n Cancel\n </button>\n <button\n className=\"button primary\"\n disabled={!newFloorName.trim() || (newFloorBuilding === 'new' && !newBuildingName.trim())}\n onClick={() => {\n const id = uid();\n if (\n commit(p => {\n let buildingId = newFloorBuilding;\n if (buildingId === 'new') {\n buildingId = uid();\n p.buildings.push({ id: buildingId, name: newBuildingName });\n }\n p.floors.push({ id, name: newFloorName, buildingId, elevation: newFloorElevation, height: 3.5 });\n })\n ) {\n changeFloor(id);\n setFloorModal(false);\n }\n }}\n >\n Create floor\n <Plus size={16} />\n </button>\n </footer>\n </Modal>\n )}\n {merge && (\n <Modal\n title={\n project.virtualBoundaries?.some(b => b.id === merge.wallId)\n ? 'This boundary divides two spaces'\n : 'This wall was dividing two spaces'\n }\n subtitle={`Removing it leaves “${merge.a.name}” and “${merge.b.name}” open to each other. Keeping them apart is fine — they simply become connected. Merging is not reversible by redrawing the wall: the space that is absorbed loses its name, its feed binding and any zones it had joined.`}\n onClose={() => setMerge(null)}\n >\n <footer>\n <button className=\"button secondary\" onClick={() => setMerge(null)}>\n Cancel\n </button>\n <button\n className=\"button secondary\"\n onClick={() => {\n const wallId = merge.wallId;\n setMerge(null);\n reshape(p => {\n removeBarrier(p, wallId);\n pruneOntology(p);\n });\n select(null);\n }}\n >\n Keep both spaces\n </button>\n {[\n [merge.a, merge.b],\n [merge.b, merge.a],\n ].map(([keep, absorbed]) => (\n <button\n key={keep.id}\n className=\"button\"\n onClick={() => {\n const wallId = merge.wallId;\n setMerge(null);\n commit(p => {\n removeBarrier(p, wallId);\n mergeSpaces(p, keep.id, absorbed.id);\n pruneOntology(p);\n });\n select(null);\n }}\n >\n Merge into “{keep.name}”\n </button>\n ))}\n </footer>\n </Modal>\n )}\n {deleteOpen && (\n <Modal\n title=\"Delete selected object?\"\n subtitle={\n deleteCount\n ? `This also removes ${deleteCount} attached opening${deleteCount > 1 ? 's' : ''}. The operation can be undone.`\n : 'This operation can be undone. Child zones become independent areas.'\n }\n onClose={() => setDeleteOpen(false)}\n >\n <footer>\n <button className=\"button secondary\" onClick={() => setDeleteOpen(false)}>\n Cancel\n </button>\n <button className=\"button danger\" onClick={deleteSelected}>\n Delete object\n </button>\n </footer>\n </Modal>\n )}\n {floorDeleteId && (\n <Modal\n title={`Delete ${project.floors.find(f => f.id === floorDeleteId)?.name ?? 'floor'}?`}\n subtitle={`${floorLoss(floorDeleteId)} This operation can be undone.`}\n onClose={() => setFloorDeleteId(null)}\n >\n <footer>\n <button className=\"button secondary\" onClick={() => setFloorDeleteId(null)}>\n Cancel\n </button>\n <button className=\"button danger\" onClick={() => deleteFloorNow(floorDeleteId)}>\n Delete floor\n </button>\n </footer>\n </Modal>\n )}\n {helpOpen && <PlannerHelp onClose={() => setHelpOpen(false)} />}\n </div>\n );\n}\nfunction InfoIcon() {\n return <ShieldCheck size={18} />;\n}\nexport function SiteViewer(props: SitePlannerProps) {\n return <SitePlanner {...props} readOnly />;\n}\n"],"names":["NavigationGraph","lazy","module","download","text","name","url","link","SitePlanner","initial","adapters","onChange","onSelectionChange","onBack","initialView","onViewChange","onModeChange","renderStatusPanel","elevators","readOnly","dark","toggleDark","useDarkMode","history","setHistory","useState","makeHistory","project","floorId","setFloorId","f","openingFloorId","selected","setSelected","focusId","setFocusId","monitoring","mode","setMode","wanted","aiRunning","setAiRunning","editing","live","threeD","setThreeD","stack","setStack","walk","setWalk","merge","setMerge","loadedProjectId","useRef","useEffect","setDraft","palette","setPalette","fullscreen","setFullscreen","sidebarOpen","setSidebarOpen","inspectorOpen","setInspectorOpen","display","useMapDisplay","coverage","showLabels","showPlan","sun","excavation","cityBuildings","cadastre","settings","setSettings","basemap","canAdopt","sidebar","useProjectSidebar","planImportOpen","setPlanImportOpen","planImportMounted","setPlanImportMounted","active","loadAiImportSession","session","importOpen","setImportOpen","floorModal","setFloorModal","helpOpen","setHelpOpen","deleteOpen","setDeleteOpen","floorDeleteId","setFloorDeleteId","toast","setToast","activeTab","setActiveTab","statuses","setStatuses","avatar","setAvatar","graphView","setGraphView","graphFloor","setGraphFloor","graphCamera","pendingLocate","navigating","setNavigating","structuring","setStructuring","navFrom","setNavFrom","navTo","setNavTo","playing","setPlaying","playStep","setPlayStep","playingRef","stopPlaying","useCallback","playStart","route","useMemo","at","end","id","HERE","a","b","findRoute","s","newFloorName","setNewFloorName","newFloorElevation","setNewFloorElevation","newFloorBuilding","setNewFloorBuilding","newBuildingName","setNewBuildingName","mapRef","latestProject","onChangeRef","onViewChangeRef","viewRef","writeHash","force","m","v","c","_a","viewMode","nextView","chooseMode","next","setTool","theme","useKerrosTheme","en","useStrings","notify","message","saveState","flush","saveNow","useProjectPersistence","applyAiProject","document","validateProject","current","commitHistory","leave","t","commit","change","result","transact","drawing","useDrawingTools","select","changeFloor","tool","draft","hover","snapping","setSnapping","routeAnchor","setRouteAnchor","chooseTool","finish","adoptBuilding","onHover","guides","geometryPreview","vertexMove","updateObject","alignment","setAlignment","startAlignment","previewAlignment","confirmAlignment","calibrate","displayProject","useReferenceAlignment","reshape","bindingKey","o","values","status","timer","shownStatuses","floor","alarms","statusTone","alarmFloors","onModeChangeRef","lastInput","autoPanned","mark","types","target","enterView","enterEdit","enterLive","stepFloor","direction","list","floorBand","index","keyHint","label","showKeys","focus","entity","d","openGraph","map","center","frameLocated","west","east","south","north","point","lng","lat","toLngLat","locateStructure","ids","objects","object","chosenFloor","onFloor","points","footprint","_b","_c","mapClick","raw","adoptDerivedGraph","nodes","edges","derivedGraph","p","n","e","duplicateSelected","clone","uid","add","r","pt","floorLoss","barriers","parts","deleteFloorNow","fallback","removeFloor","requestDeleteFloor","requestDelete","deleteCount","deleteSelected","virtual","owners","l","u","rejoin","spacesRejoinedBy","j","boundaryEdges","objectIds","nodeIds","pruneOntology","seekStep","clamped","step","moved","node","floorAim","doExport","exportProject","usePlannerKeyboard","undoHistory","redoHistory","traceFootprint","ring","closed","closeRing","i","addBarrier","area","createObject","renderImport","importMode","jsx","ImportDialog","bearing","entities","layers","outcome","importPlanEntities","skipped","first","jsxs","Layers3","Eye","MousePointer2","Radio","Sun","Moon","CircleHelp","ProjectSidebar","duplicateFloor","PanelLeftClose","PanelLeftOpen","ChevronRight","ArrowDownToLine","ArrowUpFromLine","Shapes","Waypoints","PanelRightClose","PanelRightOpen","Suspense","MapCanvas","kind","vertex","free","FloorControls","Bell","Minimize2","Maximize2","Settings2","MapSettings","DrawingDock","AlignmentPanel","imagePoints","StructureView","NavigatePanel","delta","Inspector","source","disconnectSpace","connectSpace","moveOrigin","patch","InfoIcon","X","Modal","buildingId","Plus","wallId","removeBarrier","keep","absorbed","mergeSpaces","PlannerHelp","ShieldCheck","SiteViewer","props"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"basemap.js","sources":["../../../../src/adapters/basemap.ts"],"sourcesContent":["import type { BasemapConfig } from '../model/host';\nexport const neutralBasemap: BasemapConfig = {\n style: {\n version: 8,\n sources: {},\n layers: [{ id: 'background', type: 'background', paint: { 'background-color': '#e6e8e4' } }],\n },\n};\n"],"names":["neutralBasemap"],"mappings":"AACO,MAAMA,IAAgC;AAAA,EAC3C,OAAO;AAAA,IACL,SAAS;AAAA,IACT,SAAS,CAAA;AAAA,IACT,QAAQ,CAAC,EAAE,IAAI,cAAc,MAAM,cAAc,OAAO,EAAE,oBAAoB,YAAU,CAAG;AAAA,EAAA;AAE/F;"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
var u = Object.defineProperty;
|
|
2
|
+
var m = (c, e, t) => e in c ? u(c, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : c[e] = t;
|
|
3
|
+
var l = (c, e, t) => m(c, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
import { validateProject as p } from "../model/validate.js";
|
|
5
|
+
const d = "kerros:project:";
|
|
6
|
+
class b {
|
|
7
|
+
async list() {
|
|
8
|
+
const e = [];
|
|
9
|
+
for (let t = 0; t < localStorage.length; t++) {
|
|
10
|
+
const r = localStorage.key(t);
|
|
11
|
+
if (r != null && r.startsWith(d))
|
|
12
|
+
try {
|
|
13
|
+
const a = p(JSON.parse(localStorage.getItem(r)));
|
|
14
|
+
e.push({ id: a.id, name: a.name, updatedAt: a.updatedAt });
|
|
15
|
+
} catch {
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return e.sort((t, r) => r.updatedAt.localeCompare(t.updatedAt));
|
|
19
|
+
}
|
|
20
|
+
async load(e) {
|
|
21
|
+
const t = localStorage.getItem(d + e);
|
|
22
|
+
return t ? p(JSON.parse(t)) : null;
|
|
23
|
+
}
|
|
24
|
+
async save(e) {
|
|
25
|
+
localStorage.setItem(d + e.id, JSON.stringify(e));
|
|
26
|
+
}
|
|
27
|
+
async delete(e) {
|
|
28
|
+
localStorage.removeItem(d + e);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
class y {
|
|
32
|
+
constructor(e) {
|
|
33
|
+
l(this, "db");
|
|
34
|
+
this.previous = e;
|
|
35
|
+
}
|
|
36
|
+
open() {
|
|
37
|
+
return this.db ?? (this.db = new Promise((e, t) => {
|
|
38
|
+
const r = indexedDB.open("kerros-projects", 1);
|
|
39
|
+
r.onupgradeneeded = () => r.result.createObjectStore("projects"), r.onsuccess = () => e(r.result), r.onerror = () => t(r.error);
|
|
40
|
+
}).catch((e) => {
|
|
41
|
+
throw this.db = void 0, e;
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
async list() {
|
|
45
|
+
var s;
|
|
46
|
+
const e = await this.open(), [t, r] = await Promise.all([
|
|
47
|
+
new Promise((o, n) => {
|
|
48
|
+
const i = e.transaction("projects").objectStore("projects").getAll();
|
|
49
|
+
i.onsuccess = () => o(i.result), i.onerror = () => n(i.error);
|
|
50
|
+
}),
|
|
51
|
+
((s = this.previous) == null ? void 0 : s.list()) ?? Promise.resolve([])
|
|
52
|
+
]), a = new Map(r.map((o) => [o.id, o]));
|
|
53
|
+
for (const o of t) a.set(o.id, { id: o.id, name: o.name, updatedAt: o.updatedAt });
|
|
54
|
+
return [...a.values()].sort((o, n) => n.updatedAt.localeCompare(o.updatedAt));
|
|
55
|
+
}
|
|
56
|
+
async load(e) {
|
|
57
|
+
var a;
|
|
58
|
+
const t = await this.open(), r = await new Promise((s, o) => {
|
|
59
|
+
const n = t.transaction("projects").objectStore("projects").get(e);
|
|
60
|
+
n.onsuccess = () => s(n.result), n.onerror = () => o(n.error);
|
|
61
|
+
});
|
|
62
|
+
return r === void 0 ? ((a = this.previous) == null ? void 0 : a.load(e)) ?? null : p(r);
|
|
63
|
+
}
|
|
64
|
+
async write(e, t) {
|
|
65
|
+
const r = await this.open();
|
|
66
|
+
await new Promise((a, s) => {
|
|
67
|
+
const o = r.transaction("projects", "readwrite"), n = o.objectStore("projects");
|
|
68
|
+
t ? n.put(t, e) : n.delete(e), o.oncomplete = () => a(), o.onerror = () => s(o.error), o.onabort = () => s(o.error);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
async save(e) {
|
|
72
|
+
await this.write(e.id, e);
|
|
73
|
+
}
|
|
74
|
+
async delete(e) {
|
|
75
|
+
var t;
|
|
76
|
+
await ((t = this.previous) == null ? void 0 : t.delete(e)), await this.write(e);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
class S {
|
|
80
|
+
constructor() {
|
|
81
|
+
l(this, "db");
|
|
82
|
+
}
|
|
83
|
+
// Don't cache a rejected open promise — a transient failure (private mode, storage pressure)
|
|
84
|
+
// would otherwise disable all asset access for the session; clear it so the next call retries.
|
|
85
|
+
open() {
|
|
86
|
+
return this.db ?? (this.db = new Promise((e, t) => {
|
|
87
|
+
const r = indexedDB.open("kerros-assets", 1);
|
|
88
|
+
r.onupgradeneeded = () => r.result.createObjectStore("assets"), r.onsuccess = () => e(r.result), r.onerror = () => t(r.error);
|
|
89
|
+
}).catch((e) => {
|
|
90
|
+
throw this.db = void 0, e;
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
async get(e) {
|
|
94
|
+
const t = await this.open();
|
|
95
|
+
return new Promise((r, a) => {
|
|
96
|
+
const s = t.transaction("assets").objectStore("assets").get(e);
|
|
97
|
+
s.onsuccess = () => r(s.result), s.onerror = () => a(s.error);
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
async put(e, t) {
|
|
101
|
+
const r = await this.open();
|
|
102
|
+
return new Promise((a, s) => {
|
|
103
|
+
const o = r.transaction("assets", "readwrite");
|
|
104
|
+
o.objectStore("assets").put(t, e), o.oncomplete = () => a(), o.onerror = () => s(o.error), o.onabort = () => s(o.error);
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async delete(e) {
|
|
108
|
+
const t = await this.open();
|
|
109
|
+
return new Promise((r, a) => {
|
|
110
|
+
const s = t.transaction("assets", "readwrite");
|
|
111
|
+
s.objectStore("assets").delete(e), s.oncomplete = () => r(), s.onerror = () => a(s.error);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export {
|
|
116
|
+
S as IndexedAssetRepository,
|
|
117
|
+
y as IndexedProjectRepository,
|
|
118
|
+
b as LocalProjectRepository,
|
|
119
|
+
p as validateProject
|
|
120
|
+
};
|
|
121
|
+
//# sourceMappingURL=persistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persistence.js","sources":["../../../../src/adapters/persistence.ts"],"sourcesContent":["import type { AssetRepository, ProjectDocument, ProjectRepository, ProjectSummary } from '../model/types';\nimport { validateProject } from '../model/validate';\nexport { validateProject } from '../model/validate';\nexport { exportProject, importProject, blobDataUrl } from '../model/document';\n\nconst PREFIX = 'kerros:project:';\nexport class LocalProjectRepository implements ProjectRepository {\n async list(): Promise<ProjectSummary[]> {\n const result: ProjectSummary[] = [];\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i);\n if (!key?.startsWith(PREFIX)) continue;\n try {\n const p = validateProject(JSON.parse(localStorage.getItem(key)!));\n result.push({ id: p.id, name: p.name, updatedAt: p.updatedAt });\n } catch {\n /* Leave corrupt records untouched and exclude them from the picker. */\n }\n }\n return result.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n }\n async load(id: string) {\n const json = localStorage.getItem(PREFIX + id);\n return json ? validateProject(JSON.parse(json)) : null;\n }\n async save(project: ProjectDocument) {\n localStorage.setItem(PREFIX + project.id, JSON.stringify(project));\n }\n async delete(id: string) {\n localStorage.removeItem(PREFIX + id);\n }\n}\n/** Large documents belong in IndexedDB rather than localStorage's small synchronous quota.\n * An optional previous repository keeps existing browser saves readable; new saves take precedence. */\nexport class IndexedProjectRepository implements ProjectRepository {\n private db?: Promise<IDBDatabase>;\n constructor(private previous?: ProjectRepository) {}\n private open() {\n return (this.db ??= new Promise<IDBDatabase>((resolve, reject) => {\n const req = indexedDB.open('kerros-projects', 1);\n req.onupgradeneeded = () => req.result.createObjectStore('projects');\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n }).catch(e => {\n this.db = undefined;\n throw e;\n }));\n }\n async list(): Promise<ProjectSummary[]> {\n const db = await this.open();\n const [saved, previous] = await Promise.all([\n new Promise<ProjectDocument[]>((resolve, reject) => {\n const req = db.transaction('projects').objectStore('projects').getAll();\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n }),\n this.previous?.list() ?? Promise.resolve([]),\n ]);\n const summaries = new Map(previous.map(p => [p.id, p]));\n for (const p of saved) summaries.set(p.id, { id: p.id, name: p.name, updatedAt: p.updatedAt });\n return [...summaries.values()].sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));\n }\n async load(id: string): Promise<ProjectDocument | null> {\n const db = await this.open();\n const value = await new Promise<unknown>((resolve, reject) => {\n const req = db.transaction('projects').objectStore('projects').get(id);\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n return value === undefined ? (this.previous?.load(id) ?? null) : validateProject(value);\n }\n private async write(id: string, project?: ProjectDocument): Promise<void> {\n const db = await this.open();\n await new Promise<void>((resolve, reject) => {\n const tx = db.transaction('projects', 'readwrite'),\n store = tx.objectStore('projects');\n if (project) store.put(project, id);\n else store.delete(id);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n tx.onabort = () => reject(tx.error);\n });\n }\n async save(project: ProjectDocument) {\n await this.write(project.id, project);\n }\n async delete(id: string) {\n // Remove an older copy first so a failed legacy deletion cannot resurrect it on the next load.\n await this.previous?.delete(id);\n await this.write(id);\n }\n}\nexport class IndexedAssetRepository implements AssetRepository {\n private db?: Promise<IDBDatabase>;\n // Don't cache a rejected open promise — a transient failure (private mode, storage pressure)\n // would otherwise disable all asset access for the session; clear it so the next call retries.\n private open() {\n return (this.db ??= new Promise<IDBDatabase>((resolve, reject) => {\n const req = indexedDB.open('kerros-assets', 1);\n req.onupgradeneeded = () => req.result.createObjectStore('assets');\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n }).catch(e => {\n this.db = undefined;\n throw e;\n }));\n }\n async get(id: string): Promise<Blob | undefined> {\n const db = await this.open();\n return new Promise((resolve, reject) => {\n const req = db.transaction('assets').objectStore('assets').get(id);\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n }\n async put(id: string, asset: Blob): Promise<void> {\n const db = await this.open();\n return new Promise((resolve, reject) => {\n const tx = db.transaction('assets', 'readwrite');\n tx.objectStore('assets').put(asset, id);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n tx.onabort = () => reject(tx.error);\n });\n }\n async delete(id: string): Promise<void> {\n const db = await this.open();\n return new Promise((resolve, reject) => {\n const tx = db.transaction('assets', 'readwrite');\n tx.objectStore('assets').delete(id);\n tx.oncomplete = () => resolve();\n tx.onerror = () => reject(tx.error);\n });\n }\n}\n"],"names":["PREFIX","LocalProjectRepository","result","i","key","p","validateProject","a","b","id","json","project","IndexedProjectRepository","previous","__publicField","resolve","reject","req","db","saved","_a","summaries","value","tx","store","IndexedAssetRepository","asset"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function r(e, n = Date.now()) {
|
|
2
|
+
return e ? e.tone === "critical" ? "critical" : e.timestamp && n - e.timestamp > 3e4 ? "warning" : e.tone : "unknown";
|
|
3
|
+
}
|
|
4
|
+
function i(e, n = Date.now()) {
|
|
5
|
+
return e ? e.tone === "critical" ? e.label : e.timestamp && n - e.timestamp > 3e4 ? "Stale data" : e.label : "Not connected";
|
|
6
|
+
}
|
|
7
|
+
export {
|
|
8
|
+
i as statusLabel,
|
|
9
|
+
r as statusTone
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sources":["../../../../src/adapters/status.ts"],"sourcesContent":["import type { StatusReading, StatusTone } from '../model/live';\n// Pure interpretation helpers for a StatusReading — part of the viewer contract. The only judgement\n// the library makes is timestamp-based staleness (a silent feed can't report its own staleness);\n// everything else is the host-authored tone/label passed straight through.\nconst STALE_MS = 30_000;\nexport const unknownStatus = (feedId: string): StatusReading => ({\n feedId,\n tone: 'unknown',\n label: 'Unknown',\n timestamp: 0,\n});\nexport function statusTone(status?: StatusReading, now = Date.now()): StatusTone {\n if (!status) return 'unknown';\n if (status.tone === 'critical') return 'critical';\n if (status.timestamp && now - status.timestamp > STALE_MS) return 'warning';\n return status.tone;\n}\nexport function statusLabel(status?: StatusReading, now = Date.now()): string {\n if (!status) return 'Not connected';\n if (status.tone === 'critical') return status.label;\n if (status.timestamp && now - status.timestamp > STALE_MS) return 'Stale data';\n return status.label;\n}\n"],"names":["statusTone","status","now","statusLabel"],"mappings":"AAWO,SAASA,EAAWC,GAAwBC,IAAM,KAAK,OAAmB;AAC/E,SAAKD,IACDA,EAAO,SAAS,aAAmB,aACnCA,EAAO,aAAaC,IAAMD,EAAO,YAAY,MAAiB,YAC3DA,EAAO,OAHM;AAItB;AACO,SAASE,EAAYF,GAAwBC,IAAM,KAAK,OAAe;AAC5E,SAAKD,IACDA,EAAO,SAAS,aAAmBA,EAAO,QAC1CA,EAAO,aAAaC,IAAMD,EAAO,YAAY,MAAiB,eAC3DA,EAAO,QAHM;AAItB;"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
var y = Object.defineProperty;
|
|
2
|
+
var P = (t, e, r) => e in t ? y(t, e, { enumerable: !0, configurable: !0, writable: !0, value: r }) : t[e] = r;
|
|
3
|
+
var h = (t, e, r) => P(t, typeof e != "symbol" ? e + "" : e, r);
|
|
4
|
+
import { useRef as i, useState as T, useCallback as m, useEffect as w } from "react";
|
|
5
|
+
class g {
|
|
6
|
+
constructor(e) {
|
|
7
|
+
h(this, "queue", Promise.resolve());
|
|
8
|
+
this.repository = e;
|
|
9
|
+
}
|
|
10
|
+
save(e) {
|
|
11
|
+
const r = structuredClone(e);
|
|
12
|
+
return this.queue = this.queue.catch(() => {
|
|
13
|
+
}).then(() => this.repository.save(r)), this.queue;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
function x(t, e, r, d) {
|
|
17
|
+
const p = i(new g(e)), n = i(t), v = i(null), a = i(void 0), c = i(!0);
|
|
18
|
+
n.current = t;
|
|
19
|
+
const [q, s] = T("saved"), f = m(
|
|
20
|
+
async (u) => {
|
|
21
|
+
if (clearTimeout(a.current), !!r) {
|
|
22
|
+
if (n.current = u, v.current === n.current) {
|
|
23
|
+
c.current && s("saved");
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
c.current && s("saving");
|
|
27
|
+
try {
|
|
28
|
+
await p.current.save(u), v.current = u, c.current && n.current === u && s("saved");
|
|
29
|
+
} catch (l) {
|
|
30
|
+
throw c.current && (s("error"), d("Could not save to this browser. Your work is still open; export a backup before leaving.")), l;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
[r, d]
|
|
35
|
+
), o = m(() => f(n.current), [f]);
|
|
36
|
+
return w(() => {
|
|
37
|
+
if (r)
|
|
38
|
+
return s("saving"), a.current = setTimeout(() => {
|
|
39
|
+
o().catch(() => {
|
|
40
|
+
});
|
|
41
|
+
}, 450), () => clearTimeout(a.current);
|
|
42
|
+
}, [t, r, o]), w(() => (c.current = !0, () => {
|
|
43
|
+
c.current = !1, clearTimeout(a.current), o().catch(() => {
|
|
44
|
+
});
|
|
45
|
+
}), [o]), w(() => {
|
|
46
|
+
const u = (l) => {
|
|
47
|
+
r && v.current !== n.current && l.preventDefault();
|
|
48
|
+
};
|
|
49
|
+
return window.addEventListener("beforeunload", u), () => window.removeEventListener("beforeunload", u);
|
|
50
|
+
}, [r]), { state: q, flush: o, saveNow: f };
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
g as ProjectWriter,
|
|
54
|
+
x as useProjectPersistence
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=useProjectPersistence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useProjectPersistence.js","sources":["../../../../src/adapters/useProjectPersistence.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport type { ProjectDocument, ProjectRepository } from '../model/types';\n\n/** Orders writes even when a future server repository responds slowly. */\nexport class ProjectWriter {\n private queue: Promise<void> = Promise.resolve();\n constructor(private readonly repository: ProjectRepository) {}\n save(project: ProjectDocument): Promise<void> {\n const snapshot = structuredClone(project);\n this.queue = this.queue.catch(() => {}).then(() => this.repository.save(snapshot));\n return this.queue;\n }\n}\n\nexport function useProjectPersistence(\n project: ProjectDocument,\n repository: ProjectRepository,\n enabled: boolean,\n onError: (message: string) => void,\n) {\n const writer = useRef(new ProjectWriter(repository));\n const latest = useRef(project),\n saved = useRef<ProjectDocument | null>(null),\n timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const mounted = useRef(true);\n latest.current = project;\n const [state, setState] = useState<'saving' | 'saved' | 'error'>('saved');\n const saveNow = useCallback(\n async (snapshot: ProjectDocument) => {\n clearTimeout(timer.current);\n if (!enabled) return;\n latest.current = snapshot;\n // The debounce effect optimistically shows 'saving'; converge back to 'saved' even when the\n // snapshot turns out to be identical, so the indicator can never stick on \"Saving changes…\".\n if (saved.current === latest.current) {\n if (mounted.current) setState('saved');\n return;\n }\n if (mounted.current) setState('saving');\n try {\n await writer.current.save(snapshot);\n saved.current = snapshot;\n if (mounted.current && latest.current === snapshot) setState('saved');\n } catch (error) {\n if (mounted.current) {\n setState('error');\n onError('Could not save to this browser. Your work is still open; export a backup before leaving.');\n }\n throw error;\n }\n },\n [enabled, onError],\n );\n const flush = useCallback(() => saveNow(latest.current), [saveNow]);\n useEffect(() => {\n if (!enabled) return;\n setState('saving');\n timer.current = setTimeout(() => {\n void flush().catch(() => {});\n }, 450);\n return () => clearTimeout(timer.current);\n }, [project, enabled, flush]);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n clearTimeout(timer.current);\n void flush().catch(() => {});\n };\n }, [flush]);\n useEffect(() => {\n const warn = (e: BeforeUnloadEvent) => {\n if (enabled && saved.current !== latest.current) e.preventDefault();\n };\n window.addEventListener('beforeunload', warn);\n return () => window.removeEventListener('beforeunload', warn);\n }, [enabled]);\n return { state, flush, saveNow };\n}\n"],"names":["ProjectWriter","repository","__publicField","project","snapshot","useProjectPersistence","enabled","onError","writer","useRef","latest","saved","timer","mounted","state","setState","useState","saveNow","useCallback","error","flush","useEffect","warn","e"],"mappings":";;;;AAIO,MAAMA,EAAc;AAAA,EAEzB,YAA6BC,GAA+B;AADpD,IAAAC,EAAA,eAAuB,QAAQ,QAAA;AACV,SAAA,aAAAD;AAAA,EAAgC;AAAA,EAC7D,KAAKE,GAAyC;AAC5C,UAAMC,IAAW,gBAAgBD,CAAO;AACxC,gBAAK,QAAQ,KAAK,MAAM,MAAM,MAAM;AAAA,IAAC,CAAC,EAAE,KAAK,MAAM,KAAK,WAAW,KAAKC,CAAQ,CAAC,GAC1E,KAAK;AAAA,EACd;AACF;AAEO,SAASC,EACdF,GACAF,GACAK,GACAC,GACA;AACA,QAAMC,IAASC,EAAO,IAAIT,EAAcC,CAAU,CAAC,GAC7CS,IAASD,EAAON,CAAO,GAC3BQ,IAAQF,EAA+B,IAAI,GAC3CG,IAAQH,EAAkD,MAAS,GAC/DI,IAAUJ,EAAO,EAAI;AAC3B,EAAAC,EAAO,UAAUP;AACjB,QAAM,CAACW,GAAOC,CAAQ,IAAIC,EAAuC,OAAO,GAClEC,IAAUC;AAAA,IACd,OAAOd,MAA8B;AAEnC,UADA,aAAaQ,EAAM,OAAO,GACtB,EAACN,GAIL;AAAA,YAHAI,EAAO,UAAUN,GAGbO,EAAM,YAAYD,EAAO,SAAS;AACpC,UAAIG,EAAQ,WAASE,EAAS,OAAO;AACrC;AAAA,QACF;AACA,QAAIF,EAAQ,WAASE,EAAS,QAAQ;AACtC,YAAI;AACF,gBAAMP,EAAO,QAAQ,KAAKJ,CAAQ,GAClCO,EAAM,UAAUP,GACZS,EAAQ,WAAWH,EAAO,YAAYN,OAAmB,OAAO;AAAA,QACtE,SAASe,GAAO;AACd,gBAAIN,EAAQ,YACVE,EAAS,OAAO,GAChBR,EAAQ,0FAA0F,IAE9FY;AAAA,QACR;AAAA;AAAA,IACF;AAAA,IACA,CAACb,GAASC,CAAO;AAAA,EAAA,GAEba,IAAQF,EAAY,MAAMD,EAAQP,EAAO,OAAO,GAAG,CAACO,CAAO,CAAC;AAClE,SAAAI,EAAU,MAAM;AACd,QAAKf;AACL,aAAAS,EAAS,QAAQ,GACjBH,EAAM,UAAU,WAAW,MAAM;AAC/B,QAAKQ,EAAA,EAAQ,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MAC7B,GAAG,GAAG,GACC,MAAM,aAAaR,EAAM,OAAO;AAAA,EACzC,GAAG,CAACT,GAASG,GAASc,CAAK,CAAC,GAC5BC,EAAU,OACRR,EAAQ,UAAU,IACX,MAAM;AACX,IAAAA,EAAQ,UAAU,IAClB,aAAaD,EAAM,OAAO,GACrBQ,EAAA,EAAQ,MAAM,MAAM;AAAA,IAAC,CAAC;AAAA,EAC7B,IACC,CAACA,CAAK,CAAC,GACVC,EAAU,MAAM;AACd,UAAMC,IAAO,CAACC,MAAyB;AACrC,MAAIjB,KAAWK,EAAM,YAAYD,EAAO,aAAW,eAAA;AAAA,IACrD;AACA,kBAAO,iBAAiB,gBAAgBY,CAAI,GACrC,MAAM,OAAO,oBAAoB,gBAAgBA,CAAI;AAAA,EAC9D,GAAG,CAAChB,CAAO,CAAC,GACL,EAAE,OAAAQ,GAAO,OAAAM,GAAO,SAAAH,EAAA;AACzB;"}
|