@kerros/editor 0.0.0-stage → 0.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (345) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +35 -2
  3. package/dist/SitePlanner.js +1189 -0
  4. package/dist/SitePlanner.js.map +1 -0
  5. package/dist/adapters/basemap.js +11 -0
  6. package/dist/adapters/basemap.js.map +1 -0
  7. package/dist/adapters/persistence.js +121 -0
  8. package/dist/adapters/persistence.js.map +1 -0
  9. package/dist/adapters/status.js +11 -0
  10. package/dist/adapters/status.js.map +1 -0
  11. package/dist/adapters/useProjectPersistence.js +56 -0
  12. package/dist/adapters/useProjectPersistence.js.map +1 -0
  13. package/dist/components/AiImportPanel.js +635 -0
  14. package/dist/components/AiImportPanel.js.map +1 -0
  15. package/dist/components/AnalysisPreview.js +179 -0
  16. package/dist/components/AnalysisPreview.js.map +1 -0
  17. package/dist/components/ElevatorPanel.js +120 -0
  18. package/dist/components/ElevatorPanel.js.map +1 -0
  19. package/dist/components/Icons.js +57 -0
  20. package/dist/components/Icons.js.map +1 -0
  21. package/dist/components/ImportDialog.js +467 -0
  22. package/dist/components/ImportDialog.js.map +1 -0
  23. package/dist/components/Inspector.js +1184 -0
  24. package/dist/components/Inspector.js.map +1 -0
  25. package/dist/components/NavigatePanel.js +301 -0
  26. package/dist/components/NavigatePanel.js.map +1 -0
  27. package/dist/components/NavigationGraph.js +234 -0
  28. package/dist/components/NavigationGraph.js.map +1 -0
  29. package/dist/components/StructureExplorer.js +510 -0
  30. package/dist/components/StructureExplorer.js.map +1 -0
  31. package/dist/components/StructureView.js +286 -0
  32. package/dist/components/StructureView.js.map +1 -0
  33. package/dist/components/controls.js +209 -0
  34. package/dist/components/controls.js.map +1 -0
  35. package/dist/components/graphLayout.js +27 -0
  36. package/dist/components/graphLayout.js.map +1 -0
  37. package/dist/host.js +175 -0
  38. package/dist/host.js.map +1 -0
  39. package/dist/i18n.js +88 -0
  40. package/dist/i18n.js.map +1 -0
  41. package/dist/import/analysisPreview.js +41 -0
  42. package/dist/import/analysisPreview.js.map +1 -0
  43. package/dist/import/brief.js +29 -0
  44. package/dist/import/brief.js.map +1 -0
  45. package/dist/import/checkpoint.js +50 -0
  46. package/dist/import/checkpoint.js.map +1 -0
  47. package/dist/import/detect.js +120 -0
  48. package/dist/import/detect.js.map +1 -0
  49. package/dist/import/documentSvg.js +49 -0
  50. package/dist/import/documentSvg.js.map +1 -0
  51. package/dist/import/instructions.js +20 -0
  52. package/dist/import/instructions.js.map +1 -0
  53. package/dist/import/openings.js +61 -0
  54. package/dist/import/openings.js.map +1 -0
  55. package/dist/import/planImport.js +233 -0
  56. package/dist/import/planImport.js.map +1 -0
  57. package/dist/import/register.js +47 -0
  58. package/dist/import/register.js.map +1 -0
  59. package/dist/import/runs.js +67 -0
  60. package/dist/import/runs.js.map +1 -0
  61. package/dist/import/session.js +23 -0
  62. package/dist/import/session.js.map +1 -0
  63. package/dist/import/types.js +13 -0
  64. package/dist/import/types.js.map +1 -0
  65. package/dist/import/usage.js +29 -0
  66. package/dist/import/usage.js.map +1 -0
  67. package/dist/import/walls.js +112 -0
  68. package/dist/import/walls.js.map +1 -0
  69. package/dist/index.js +178 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/map/CabinMaterials.js +81 -0
  72. package/dist/map/CabinMaterials.js.map +1 -0
  73. package/dist/map/CabinMirror.js +43 -0
  74. package/dist/map/CabinMirror.js.map +1 -0
  75. package/dist/map/Doors.js +80 -0
  76. package/dist/map/Doors.js.map +1 -0
  77. package/dist/map/ElevatorCabin.js +93 -0
  78. package/dist/map/ElevatorCabin.js.map +1 -0
  79. package/dist/map/FixtureLights.js +117 -0
  80. package/dist/map/FixtureLights.js.map +1 -0
  81. package/dist/map/MapCanvas.js +2161 -0
  82. package/dist/map/MapCanvas.js.map +1 -0
  83. package/dist/map/Passenger.js +69 -0
  84. package/dist/map/Passenger.js.map +1 -0
  85. package/dist/map/SceneLayer.js +1534 -0
  86. package/dist/map/SceneLayer.js.map +1 -0
  87. package/dist/map/UndergroundContext.js +153 -0
  88. package/dist/map/UndergroundContext.js.map +1 -0
  89. package/dist/map/ambience.js +194 -0
  90. package/dist/map/ambience.js.map +1 -0
  91. package/dist/map/architecture.js +305 -0
  92. package/dist/map/architecture.js.map +1 -0
  93. package/dist/map/bathMusic.js +92 -0
  94. package/dist/map/bathMusic.js.map +1 -0
  95. package/dist/map/cameraAim.js +33 -0
  96. package/dist/map/cameraAim.js.map +1 -0
  97. package/dist/map/elevators.js +56 -0
  98. package/dist/map/elevators.js.map +1 -0
  99. package/dist/map/excavation.js +52 -0
  100. package/dist/map/excavation.js.map +1 -0
  101. package/dist/map/exteriors.js +25 -0
  102. package/dist/map/exteriors.js.map +1 -0
  103. package/dist/map/features.js +218 -0
  104. package/dist/map/features.js.map +1 -0
  105. package/dist/map/fences.js +29 -0
  106. package/dist/map/fences.js.map +1 -0
  107. package/dist/map/journey.js +112 -0
  108. package/dist/map/journey.js.map +1 -0
  109. package/dist/map/levels.js +6 -0
  110. package/dist/map/levels.js.map +1 -0
  111. package/dist/map/lighting.js +143 -0
  112. package/dist/map/lighting.js.map +1 -0
  113. package/dist/map/loadBasemap.js +26 -0
  114. package/dist/map/loadBasemap.js.map +1 -0
  115. package/dist/map/materials.js +183 -0
  116. package/dist/map/materials.js.map +1 -0
  117. package/dist/map/poolLighting.js +39 -0
  118. package/dist/map/poolLighting.js.map +1 -0
  119. package/dist/map/projection.js +24 -0
  120. package/dist/map/projection.js.map +1 -0
  121. package/dist/map/rampGeometry.js +38 -0
  122. package/dist/map/rampGeometry.js.map +1 -0
  123. package/dist/map/route.js +107 -0
  124. package/dist/map/route.js.map +1 -0
  125. package/dist/map/stairSurfaces.js +115 -0
  126. package/dist/map/stairSurfaces.js.map +1 -0
  127. package/dist/map/surfaces.js +136 -0
  128. package/dist/map/surfaces.js.map +1 -0
  129. package/dist/map/textures.js +95 -0
  130. package/dist/map/textures.js.map +1 -0
  131. package/dist/map/underground.js +34 -0
  132. package/dist/map/underground.js.map +1 -0
  133. package/dist/map/walk.js +433 -0
  134. package/dist/map/walk.js.map +1 -0
  135. package/dist/map/walkContext.js +46 -0
  136. package/dist/map/walkContext.js.map +1 -0
  137. package/dist/map/walkDimensions.js +7 -0
  138. package/dist/map/walkDimensions.js.map +1 -0
  139. package/dist/map/walkJourney.js +85 -0
  140. package/dist/map/walkJourney.js.map +1 -0
  141. package/dist/map/walkSurfaces.js +106 -0
  142. package/dist/map/walkSurfaces.js.map +1 -0
  143. package/dist/map/wallJoins.js +70 -0
  144. package/dist/map/wallJoins.js.map +1 -0
  145. package/dist/map/water.js +274 -0
  146. package/dist/map/water.js.map +1 -0
  147. package/dist/model/authoring.js +99 -0
  148. package/dist/model/authoring.js.map +1 -0
  149. package/dist/model/boundaries.js +548 -0
  150. package/dist/model/boundaries.js.map +1 -0
  151. package/dist/model/coverage.js +30 -0
  152. package/dist/model/coverage.js.map +1 -0
  153. package/dist/model/document.js +52 -0
  154. package/dist/model/document.js.map +1 -0
  155. package/dist/model/doors.js +47 -0
  156. package/dist/model/doors.js.map +1 -0
  157. package/dist/model/factory.js +56 -0
  158. package/dist/model/factory.js.map +1 -0
  159. package/dist/model/geometry.js +454 -0
  160. package/dist/model/geometry.js.map +1 -0
  161. package/dist/model/history.js +29 -0
  162. package/dist/model/history.js.map +1 -0
  163. package/dist/model/imports.js +45 -0
  164. package/dist/model/imports.js.map +1 -0
  165. package/dist/model/inference.js +182 -0
  166. package/dist/model/inference.js.map +1 -0
  167. package/dist/model/materials.js +11 -0
  168. package/dist/model/materials.js.map +1 -0
  169. package/dist/model/mutations.js +157 -0
  170. package/dist/model/mutations.js.map +1 -0
  171. package/dist/model/navigation.js +275 -0
  172. package/dist/model/navigation.js.map +1 -0
  173. package/dist/model/ontology.js +109 -0
  174. package/dist/model/ontology.js.map +1 -0
  175. package/dist/model/passages.js +5 -0
  176. package/dist/model/passages.js.map +1 -0
  177. package/dist/model/portals.js +42 -0
  178. package/dist/model/portals.js.map +1 -0
  179. package/dist/model/precision.js +11 -0
  180. package/dist/model/precision.js.map +1 -0
  181. package/dist/model/project.js +31 -0
  182. package/dist/model/project.js.map +1 -0
  183. package/dist/model/ramps.js +10 -0
  184. package/dist/model/ramps.js.map +1 -0
  185. package/dist/model/roomNavigation.js +87 -0
  186. package/dist/model/roomNavigation.js.map +1 -0
  187. package/dist/model/routeClearance.js +72 -0
  188. package/dist/model/routeClearance.js.map +1 -0
  189. package/dist/model/spaces.js +104 -0
  190. package/dist/model/spaces.js.map +1 -0
  191. package/dist/model/stairGeometry.js +40 -0
  192. package/dist/model/stairGeometry.js.map +1 -0
  193. package/dist/model/stairTraversal.js +48 -0
  194. package/dist/model/stairTraversal.js.map +1 -0
  195. package/dist/model/topology.js +63 -0
  196. package/dist/model/topology.js.map +1 -0
  197. package/dist/model/types.js +35 -0
  198. package/dist/model/types.js.map +1 -0
  199. package/dist/model/validate.js +240 -0
  200. package/dist/model/validate.js.map +1 -0
  201. package/dist/model/vertical.js +129 -0
  202. package/dist/model/vertical.js.map +1 -0
  203. package/dist/model/walls.js +261 -0
  204. package/dist/model/walls.js.map +1 -0
  205. package/dist/planner/DrawingDock.js +231 -0
  206. package/dist/planner/DrawingDock.js.map +1 -0
  207. package/dist/planner/FloorControls.js +93 -0
  208. package/dist/planner/FloorControls.js.map +1 -0
  209. package/dist/planner/MapSettings.js +143 -0
  210. package/dist/planner/MapSettings.js.map +1 -0
  211. package/dist/planner/PlannerHelp.js +57 -0
  212. package/dist/planner/PlannerHelp.js.map +1 -0
  213. package/dist/planner/ProjectSidebar.js +246 -0
  214. package/dist/planner/ProjectSidebar.js.map +1 -0
  215. package/dist/planner/floors.js +18 -0
  216. package/dist/planner/floors.js.map +1 -0
  217. package/dist/planner/useDrawingTools.js +341 -0
  218. package/dist/planner/useDrawingTools.js.map +1 -0
  219. package/dist/planner/useMapDisplay.js +51 -0
  220. package/dist/planner/useMapDisplay.js.map +1 -0
  221. package/dist/planner/usePlannerKeyboard.js +138 -0
  222. package/dist/planner/usePlannerKeyboard.js.map +1 -0
  223. package/dist/planner/useReferenceAlignment.js +50 -0
  224. package/dist/planner/useReferenceAlignment.js.map +1 -0
  225. package/dist/styles.css +4931 -0
  226. package/dist/theme/index.js +34 -0
  227. package/dist/theme/index.js.map +1 -0
  228. package/dist/types/SitePlanner.d.ts +5 -0
  229. package/dist/types/adapters/basemap.d.ts +2 -0
  230. package/dist/types/adapters/persistence.d.ts +29 -0
  231. package/dist/types/adapters/status.d.ts +4 -0
  232. package/dist/types/adapters/useProjectPersistence.d.ts +13 -0
  233. package/dist/types/components/AiImportPanel.d.ts +9 -0
  234. package/dist/types/components/AnalysisPreview.d.ts +4 -0
  235. package/dist/types/components/ElevatorPanel.d.ts +18 -0
  236. package/dist/types/components/Icons.d.ts +8 -0
  237. package/dist/types/components/ImportDialog.d.ts +42 -0
  238. package/dist/types/components/Inspector.d.ts +38 -0
  239. package/dist/types/components/NavigatePanel.d.ts +27 -0
  240. package/dist/types/components/NavigationGraph.d.ts +10 -0
  241. package/dist/types/components/StructureExplorer.d.ts +8 -0
  242. package/dist/types/components/StructureView.d.ts +22 -0
  243. package/dist/types/components/controls.d.ts +52 -0
  244. package/dist/types/components/graphLayout.d.ts +9 -0
  245. package/dist/types/editor/host.d.ts +9 -0
  246. package/dist/types/editor/index.d.ts +2 -0
  247. package/dist/types/i18n.d.ts +85 -0
  248. package/dist/types/import/analysisPreview.d.ts +27 -0
  249. package/dist/types/import/brief.d.ts +22 -0
  250. package/dist/types/import/checkpoint.d.ts +49 -0
  251. package/dist/types/import/detect.d.ts +34 -0
  252. package/dist/types/import/documentSvg.d.ts +2 -0
  253. package/dist/types/import/index.d.ts +10 -0
  254. package/dist/types/import/instructions.d.ts +7 -0
  255. package/dist/types/import/openings.d.ts +22 -0
  256. package/dist/types/import/planImport.d.ts +22 -0
  257. package/dist/types/import/register.d.ts +25 -0
  258. package/dist/types/import/runs.d.ts +31 -0
  259. package/dist/types/import/session.d.ts +33 -0
  260. package/dist/types/import/types.d.ts +56 -0
  261. package/dist/types/import/usage.d.ts +10 -0
  262. package/dist/types/import/walls.d.ts +37 -0
  263. package/dist/types/map/CabinMaterials.d.ts +18 -0
  264. package/dist/types/map/CabinMirror.d.ts +13 -0
  265. package/dist/types/map/Doors.d.ts +11 -0
  266. package/dist/types/map/ElevatorCabin.d.ts +20 -0
  267. package/dist/types/map/FixtureLights.d.ts +35 -0
  268. package/dist/types/map/MapCanvas.d.ts +87 -0
  269. package/dist/types/map/Passenger.d.ts +18 -0
  270. package/dist/types/map/SceneLayer.d.ts +306 -0
  271. package/dist/types/map/UndergroundContext.d.ts +18 -0
  272. package/dist/types/map/ambience.d.ts +29 -0
  273. package/dist/types/map/architecture.d.ts +8 -0
  274. package/dist/types/map/bathMusic.d.ts +14 -0
  275. package/dist/types/map/cameraAim.d.ts +20 -0
  276. package/dist/types/map/elevators.d.ts +16 -0
  277. package/dist/types/map/excavation.d.ts +9 -0
  278. package/dist/types/map/exteriors.d.ts +3 -0
  279. package/dist/types/map/features.d.ts +33 -0
  280. package/dist/types/map/fences.d.ts +4 -0
  281. package/dist/types/map/journey.d.ts +36 -0
  282. package/dist/types/map/levels.d.ts +4 -0
  283. package/dist/types/map/lighting.d.ts +103 -0
  284. package/dist/types/map/loadBasemap.d.ts +4 -0
  285. package/dist/types/map/materials.d.ts +38 -0
  286. package/dist/types/map/poolLighting.d.ts +11 -0
  287. package/dist/types/map/projection.d.ts +9 -0
  288. package/dist/types/map/rampGeometry.d.ts +8 -0
  289. package/dist/types/map/route.d.ts +59 -0
  290. package/dist/types/map/stairSurfaces.d.ts +29 -0
  291. package/dist/types/map/surfaces.d.ts +36 -0
  292. package/dist/types/map/textures.d.ts +8 -0
  293. package/dist/types/map/underground.d.ts +30 -0
  294. package/dist/types/map/walk.d.ts +232 -0
  295. package/dist/types/map/walkContext.d.ts +11 -0
  296. package/dist/types/map/walkDimensions.d.ts +5 -0
  297. package/dist/types/map/walkJourney.d.ts +33 -0
  298. package/dist/types/map/walkSurfaces.d.ts +27 -0
  299. package/dist/types/map/wallJoins.d.ts +6 -0
  300. package/dist/types/map/water.d.ts +12 -0
  301. package/dist/types/model/authoring.d.ts +38 -0
  302. package/dist/types/model/boundaries.d.ts +41 -0
  303. package/dist/types/model/coverage.d.ts +8 -0
  304. package/dist/types/model/document.d.ts +9 -0
  305. package/dist/types/model/doors.d.ts +19 -0
  306. package/dist/types/model/factory.d.ts +5 -0
  307. package/dist/types/model/geometry.d.ts +99 -0
  308. package/dist/types/model/history.d.ts +10 -0
  309. package/dist/types/model/host.d.ts +154 -0
  310. package/dist/types/model/imports.d.ts +7 -0
  311. package/dist/types/model/inference.d.ts +46 -0
  312. package/dist/types/model/live.d.ts +60 -0
  313. package/dist/types/model/materials.d.ts +28 -0
  314. package/dist/types/model/mutations.d.ts +178 -0
  315. package/dist/types/model/navigation.d.ts +70 -0
  316. package/dist/types/model/ontology.d.ts +43 -0
  317. package/dist/types/model/passages.d.ts +2 -0
  318. package/dist/types/model/portals.d.ts +9 -0
  319. package/dist/types/model/precision.d.ts +11 -0
  320. package/dist/types/model/project.d.ts +8 -0
  321. package/dist/types/model/ramps.d.ts +7 -0
  322. package/dist/types/model/roomNavigation.d.ts +15 -0
  323. package/dist/types/model/routeClearance.d.ts +11 -0
  324. package/dist/types/model/spaces.d.ts +46 -0
  325. package/dist/types/model/stairGeometry.d.ts +27 -0
  326. package/dist/types/model/stairTraversal.d.ts +8 -0
  327. package/dist/types/model/topology.d.ts +14 -0
  328. package/dist/types/model/types.d.ts +369 -0
  329. package/dist/types/model/validate.d.ts +38 -0
  330. package/dist/types/model/vertical.d.ts +145 -0
  331. package/dist/types/model/walls.d.ts +71 -0
  332. package/dist/types/planner/DrawingDock.d.ts +16 -0
  333. package/dist/types/planner/FloorControls.d.ts +17 -0
  334. package/dist/types/planner/MapSettings.d.ts +16 -0
  335. package/dist/types/planner/PlannerHelp.d.ts +3 -0
  336. package/dist/types/planner/ProjectSidebar.d.ts +32 -0
  337. package/dist/types/planner/floors.d.ts +3 -0
  338. package/dist/types/planner/types.d.ts +3 -0
  339. package/dist/types/planner/useDrawingTools.d.ts +52 -0
  340. package/dist/types/planner/useMapDisplay.d.ts +29 -0
  341. package/dist/types/planner/usePlannerKeyboard.d.ts +18 -0
  342. package/dist/types/planner/useReferenceAlignment.d.ts +30 -0
  343. package/dist/types/schema/index.d.ts +25 -0
  344. package/dist/types/theme/index.d.ts +55 -0
  345. package/package.json +52 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AiImportPanel.js","sources":["../../../../src/components/AiImportPanel.tsx"],"sourcesContent":["import { useEffect, useRef, useState, useId } from 'react';\nimport type { AiImportAdapter } from '../model/host';\nimport type { AssetRepository, ProjectDocument } from '../model/types';\nimport { addTokenUsage, emptyTokenUsage } from '../import/usage';\nimport { loadAiImportSession, saveAiImportSession, type AiImportSession } from '../import/session';\nimport { readImportBrief } from '../import/brief';\nimport { DEFAULT_IMPORT_BUDGET, readImportBudget, type ImportBudget } from '../import/checkpoint';\nimport { mergeImportInstructions, readImportInstruction } from '../import/instructions';\nimport { AnalysisPreview } from './AnalysisPreview';\nimport {\n loadAnalysisPreview,\n saveAnalysisPreview,\n deleteAnalysisPreview,\n type ImportAnalysisPreview,\n} from '../import/analysisPreview';\n\nexport function AiImportPanel({\n adapter,\n assets,\n onProject,\n onRunningChange,\n currentProject,\n}: {\n adapter: AiImportAdapter;\n assets: AssetRepository;\n onProject: (project: ProjectDocument) => void | Promise<void>;\n onRunningChange: (running: boolean) => void;\n currentProject: ProjectDocument;\n}) {\n const [loading, setLoading] = useState(true);\n type ImportTab = 'setup' | 'analysis' | 'activity' | 'usage';\n const [tab, setTab] = useState<ImportTab>('setup');\n const tabId = useId();\n const [file, setFile] = useState<File | null>(null);\n const [instructions, setInstructions] = useState('');\n const [widthMetres, setWidthMetres] = useState('');\n const [depthMetres, setDepthMetres] = useState('');\n const [buildingType, setBuildingType] = useState('');\n const [floorCount, setFloorCount] = useState('');\n const [footprintArea, setFootprintArea] = useState('');\n const [followUp, setFollowUp] = useState('');\n const [budget, setBudget] = useState<ImportBudget>(DEFAULT_IMPORT_BUDGET);\n const [analysisPreview, setAnalysisPreview] = useState<ImportAnalysisPreview>();\n const [session, setSession] = useState<AiImportSession | null>(null);\n const latest = useRef(session);\n const projectRef = useRef(currentProject);\n const acceptProject = useRef(onProject);\n projectRef.current = currentProject;\n acceptProject.current = onProject;\n const [elapsed, setElapsed] = useState(0);\n const [error, setError] = useState('');\n const [saving, setSaving] = useState(false);\n const [sending, setSending] = useState(false);\n const [activeJob, setActiveJob] = useState<string>();\n const controller = useRef<AbortController | null>(null);\n const queue = useRef<Promise<void>>(Promise.resolve());\n const chat = useRef<HTMLDivElement>(null);\n const follow = useRef(true);\n const running = session?.phase === 'running';\n const phase = session?.phase ?? 'ready';\n const messages = session?.messages ?? [];\n const usage = session?.usage ?? emptyTokenUsage();\n const hasUsage = session?.hasUsage ?? false;\n const edits = session?.edits ?? 0;\n const activity = session?.activity ?? '';\n\n // Capture each state before yielding. Ordered writes prevent slow saves from restoring an\n // older transcript or phase over a newer one. Geometry is persisted by onProject first.\n const persist = (next: AiImportSession) => {\n latest.current = next;\n setSession(next);\n const write = queue.current.catch(() => {}).then(() => saveAiImportSession(assets, next));\n queue.current = write;\n return write;\n };\n useEffect(() => {\n let active = true;\n void loadAiImportSession(assets, currentProject.id)\n .then(async saved => {\n if (!active) return;\n latest.current = saved;\n setSession(saved);\n setInstructions(saved?.instructions ?? '');\n setFollowUp(saved?.followUp ?? '');\n setWidthMetres(saved?.brief?.widthMetres?.toString() ?? '');\n setDepthMetres(saved?.brief?.depthMetres?.toString() ?? '');\n setBuildingType(saved?.brief?.buildingType ?? '');\n setFloorCount(saved?.brief?.floorCount?.toString() ?? '');\n setFootprintArea(saved?.brief?.footprintAreaM2?.toString() ?? '');\n setError(saved?.error ?? '');\n setBudget(saved?.budget ?? DEFAULT_IMPORT_BUDGET);\n setTab(saved?.tab ?? (saved ? 'activity' : 'setup'));\n if (saved) {\n const preview = await loadAnalysisPreview(assets, saved.sourceId);\n if (active) setAnalysisPreview(preview);\n }\n })\n .catch(e => {\n if (active) setError((e as Error).message);\n })\n .finally(() => {\n if (active) setLoading(false);\n });\n return () => {\n active = false;\n controller.current?.abort();\n controller.current = null;\n };\n }, [assets, currentProject.id]);\n useEffect(() => {\n if (follow.current && chat.current) chat.current.scrollTop = 0;\n }, [session?.messages]);\n useEffect(() => {\n onRunningChange(running);\n return () => onRunningChange(false);\n }, [running, onRunningChange]);\n useEffect(() => {\n if (!running) return;\n const started = Date.now();\n setElapsed(0);\n const timer = setInterval(() => setElapsed(Math.floor((Date.now() - started) / 1000)), 1000);\n return () => clearInterval(timer);\n }, [running]);\n\n const start = async (continuing = false) => {\n if (controller.current || loading) return;\n const request = new AbortController();\n controller.current = request;\n setSaving(true);\n setError('');\n let previousUsage = emptyTokenUsage();\n try {\n const previous = latest.current;\n const runBudget = readImportBudget(budget);\n const brief = readImportBrief({\n buildingType: buildingType || undefined,\n floorCount: floorCount ? Number(floorCount) : undefined,\n widthMetres: widthMetres ? Number(widthMetres) : undefined,\n depthMetres: depthMetres ? Number(depthMetres) : undefined,\n footprintAreaM2: footprintArea ? Number(footprintArea) : undefined,\n });\n let selected = file;\n if (continuing && previous) {\n const blob = await assets.get(previous.sourceId);\n if (!blob) throw new Error('The saved source drawing is missing. Choose it again to continue.');\n selected = new File([blob], previous.sourceName, { type: previous.sourceType });\n }\n if (\n !selected ||\n !/\\.(dwg|pdf|png|jpe?g|webp)$/i.test(selected.name) ||\n !selected.size ||\n selected.size > 25 * 1024 * 1024\n )\n throw new Error('Choose a non-empty DWG, PDF, PNG, JPEG or WebP file under 25 MB.');\n const sourceId = continuing && previous ? previous.sourceId : `ai-import:source:${crypto.randomUUID()}`;\n if (!continuing) await assets.put(sourceId, selected);\n if (!continuing) setAnalysisPreview(undefined);\n request.signal.throwIfAborted();\n const next: AiImportSession =\n continuing && previous\n ? {\n ...previous,\n brief,\n phase: 'running',\n tab: 'activity',\n budget: runBudget,\n pause: undefined,\n error: '',\n followUp: '',\n activity: 'Preparing import',\n messages: previous.messages,\n }\n : {\n version: 1,\n projectId: projectRef.current.id,\n sourceId,\n sourceName: selected.name,\n sourceType: selected.type,\n instructions,\n brief,\n followUp: '',\n messages: [\n {\n type: 'user',\n detail: [\n instructions.trim(),\n [\n brief?.buildingType,\n brief?.floorCount && `${brief.floorCount} floors`,\n brief?.widthMetres && `Width ${brief.widthMetres} m`,\n brief?.depthMetres && `Depth ${brief.depthMetres} m`,\n brief?.footprintAreaM2 && `Footprint ${brief.footprintAreaM2} m² per floor`,\n ]\n .filter(Boolean)\n .join(' · '),\n ]\n .filter(Boolean)\n .join('\\n'),\n },\n ].filter(m => m.detail) as AiImportSession['messages'],\n phase: 'running',\n tab: 'activity',\n budget: runBudget,\n pause: undefined,\n activity: 'Preparing import',\n edits: 0,\n usage: emptyTokenUsage(),\n hasUsage: false,\n error: '',\n };\n if (continuing) {\n if (followUp.trim()) {\n const instruction = readImportInstruction({ id: crypto.randomUUID(), text: followUp });\n next.pendingInstructions = [...(next.pendingInstructions ?? []), instruction];\n next.messages = [...next.messages, { type: 'user', detail: instruction.text, instructionId: instruction.id }];\n }\n if (next.pendingInstructions?.length)\n next.checkpoint = {\n version: 1,\n projectId: projectRef.current.id,\n brief: next.brief,\n phase: 'inspect',\n notes: '',\n sourcePlan: '',\n mutationKinds: [],\n analysis: [],\n lastAssistantText: '',\n lastToolReport: '',\n ...next.checkpoint,\n steering: mergeImportInstructions(next.checkpoint?.steering ?? [], next.pendingInstructions),\n };\n }\n previousUsage = continuing && previous ? previous.usage : emptyTokenUsage();\n await persist(next);\n setFollowUp('');\n if (!continuing && previous && previous.sourceId !== sourceId)\n await Promise.all([assets.delete(previous.sourceId), deleteAnalysisPreview(assets, previous.sourceId)]).catch(\n () => {},\n );\n request.signal.throwIfAborted();\n setTab('activity');\n setFile(null);\n setSaving(false);\n follow.current = true;\n let lastDocument: ProjectDocument | undefined;\n const result = await adapter.run(selected, {\n origin: projectRef.current.origin,\n brief: next.brief,\n instructions: next.instructions,\n // The live document includes manual corrections made between runs. Never restore an\n // earlier import snapshot over them or switch to a newly generated project ID.\n base: projectRef.current,\n checkpoint: next.checkpoint,\n budget: runBudget,\n onSession: jobId => {\n if (!request.signal.aborted) setActiveJob(jobId);\n },\n onAnalysis: async preview => {\n if (request.signal.aborted) return;\n await saveAnalysisPreview(assets, sourceId, preview);\n if (!request.signal.aborted) setAnalysisPreview(preview);\n },\n onCheckpoint: async checkpoint => {\n if (!request.signal.aborted) {\n const acknowledged = new Set(checkpoint.steering?.map(m => m.id));\n await persist({\n ...latest.current!,\n checkpoint,\n pendingInstructions: latest.current!.pendingInstructions?.filter(m => !acknowledged.has(m.id)),\n });\n }\n },\n onPause: async pause => {\n if (!request.signal.aborted) await persist({ ...latest.current!, pause, activity: pause.message });\n },\n signal: request.signal,\n onUsage: async snapshot => {\n if (!request.signal.aborted)\n await persist({ ...latest.current!, usage: addTokenUsage(previousUsage, snapshot), hasUsage: true });\n },\n onDocument: async document => {\n if (request.signal.aborted) return;\n await acceptProject.current(document);\n lastDocument = document;\n await persist({ ...latest.current!, edits: latest.current!.edits + 1 });\n },\n onProgress: async event => {\n if (request.signal.aborted) return;\n const state = latest.current!;\n if (event.type === 'status') return persist({ ...state, activity: event.detail });\n const last = state.messages.at(-1);\n const messages: AiImportSession['messages'] =\n event.type === 'text' && last?.type === 'text'\n ? [...state.messages.slice(0, -1), { type: 'text', detail: last.detail + event.detail }]\n : [...state.messages, { type: event.type, detail: event.detail }];\n await persist({ ...state, messages });\n },\n });\n if (!request.signal.aborted) {\n if (!lastDocument || JSON.stringify(result) !== JSON.stringify(lastDocument))\n await acceptProject.current(result);\n await persist({ ...latest.current!, phase: latest.current!.pause ? 'paused' : 'done' });\n }\n } catch (e) {\n if (controller.current !== request) return;\n const message = request.signal.aborted ? '' : (e as Error).message;\n setError(message);\n if (latest.current) {\n try {\n await persist({ ...latest.current, phase: request.signal.aborted ? 'paused' : 'failed', error: message });\n } catch {\n setError('Could not save the import session. Keep this page open and retry when storage is available.');\n }\n }\n } finally {\n if (controller.current === request) {\n controller.current = null;\n setActiveJob(undefined);\n }\n setSaving(false);\n }\n };\n const sendInstruction = async () => {\n if (!followUp.trim() || sending || saving || !latest.current) return;\n if (!running) return start(true);\n if (!activeJob || !adapter.sendInstruction) return;\n setSending(true);\n setError('');\n try {\n const instruction = readImportInstruction({ id: crypto.randomUUID(), text: followUp });\n const pending = [...(latest.current.pendingInstructions ?? []), instruction];\n if (pending.length > 20 || JSON.stringify(pending).length > 8000)\n throw new Error('Wait for Claude to receive the queued instructions before sending more.');\n await persist({\n ...latest.current,\n followUp: '',\n pendingInstructions: pending,\n messages: [\n ...latest.current.messages,\n { type: 'user', detail: instruction.text, instructionId: instruction.id },\n ],\n });\n setFollowUp('');\n await adapter.sendInstruction(activeJob, instruction);\n } catch (e) {\n setError((e as Error).message);\n } finally {\n setSending(false);\n }\n };\n const changeBrief = (\n patch: Partial<{\n widthMetres: string;\n depthMetres: string;\n footprintArea: string;\n buildingType: string;\n floorCount: string;\n }>,\n ) => {\n const next = { widthMetres, depthMetres, footprintArea, buildingType, floorCount, ...patch };\n setWidthMetres(next.widthMetres);\n setDepthMetres(next.depthMetres);\n setFootprintArea(next.footprintArea);\n setBuildingType(next.buildingType);\n setFloorCount(next.floorCount);\n if (!latest.current) return;\n try {\n const brief = readImportBrief({\n buildingType: next.buildingType || undefined,\n floorCount: next.floorCount ? Number(next.floorCount) : undefined,\n widthMetres: next.widthMetres ? Number(next.widthMetres) : undefined,\n depthMetres: next.depthMetres ? Number(next.depthMetres) : undefined,\n footprintAreaM2: next.footprintArea ? Number(next.footprintArea) : undefined,\n });\n void persist({ ...latest.current, brief }).catch(() => setError('Could not save the import template.'));\n } catch {\n /* Keep partial input editable; Start/Continue validates it. */\n }\n };\n const scaleFields = (\n <fieldset className=\"ai-import-scale\">\n <legend>Import template · optional</legend>\n <div className=\"field-grid\">\n <label className=\"field\">\n <span>Building type</span>\n <select\n aria-label=\"Import building type\"\n value={buildingType}\n disabled={saving || running}\n onChange={e => changeBrief({ buildingType: e.target.value })}\n >\n <option value=\"\">Use the drawing</option>\n <option value=\"apartment\">Apartment</option>\n <option value=\"house\">Detached house</option>\n <option value=\"office\">Office</option>\n <option value=\"retail\">Shop / retail</option>\n <option value=\"other\">Other building</option>\n </select>\n </label>\n <label className=\"field\">\n <span>Floor count</span>\n <input\n type=\"number\"\n min=\"1\"\n max=\"100\"\n step=\"1\"\n aria-label=\"Import floor count\"\n value={floorCount}\n placeholder=\"e.g. 1\"\n disabled={saving || running}\n onChange={e => changeBrief({ floorCount: e.target.value })}\n />\n </label>\n <label className=\"field\">\n <span>Overall width (m)</span>\n <input\n type=\"number\"\n min=\"0.01\"\n step=\"any\"\n aria-label=\"Overall width (m)\"\n value={widthMetres}\n placeholder=\"e.g. 20\"\n disabled={saving || running}\n onChange={e => changeBrief({ widthMetres: e.target.value })}\n />\n </label>\n <label className=\"field\">\n <span>Overall depth (m)</span>\n <input\n type=\"number\"\n min=\"0.01\"\n step=\"any\"\n aria-label=\"Overall depth (m)\"\n value={depthMetres}\n placeholder=\"Optional\"\n disabled={saving || running}\n onChange={e => changeBrief({ depthMetres: e.target.value })}\n />\n </label>\n <label className=\"field\">\n <span>Footprint per floor (m²)</span>\n <input\n type=\"number\"\n min=\"0.01\"\n step=\"any\"\n aria-label=\"Floor footprint (m²)\"\n value={footprintArea}\n placeholder=\"Whole floor area\"\n disabled={saving || running}\n onChange={e => changeBrief({ footprintArea: e.target.value })}\n />\n </label>\n </div>\n <small>\n Dimensions follow the plan’s main axes, to the outside of the walls. Footprint includes wall area and applies\n per floor, not to the sum of all floors. One known value can establish scale; others cross-check it. Leave\n measurements blank only when the drawing has readable dimensions. Different floor footprints can be described in\n the instructions.\n </small>\n </fieldset>\n );\n const budgetFields = (\n <details className=\"ai-import-budget\">\n <summary>\n Budget per run · {budget.maxTurns ?? 40} turns · {budget.inputTokens.toLocaleString()} input /{' '}\n {budget.outputTokens.toLocaleString()} output\n </summary>\n <p className=\"helper\">\n Input includes cached tokens. Output includes model thinking. Continue starts another paid run using the saved\n working state. Limits are checked between responses.\n </p>\n <div className=\"field-grid\">\n <label className=\"field\">\n <span>Turn limit</span>\n <input\n type=\"number\"\n aria-label=\"Turn limit\"\n min=\"1\"\n max=\"100\"\n step=\"1\"\n value={budget.maxTurns ?? 40}\n disabled={running || saving}\n onChange={e => {\n const next = { ...budget, maxTurns: Number(e.target.value) };\n setBudget(next);\n try {\n const valid = readImportBudget(next);\n if (latest.current)\n void persist({ ...latest.current, budget: valid }).catch(() =>\n setError('Could not save import budget.'),\n );\n } catch {\n /* Start validates completed values. */\n }\n }}\n />\n </label>\n {(['inputTokens', 'outputTokens'] as const).map(key => (\n <label className=\"field\" key={key}>\n <span>{key === 'inputTokens' ? 'Input token limit' : 'Output token limit'}</span>\n <input\n type=\"number\"\n aria-label={key === 'inputTokens' ? 'Input token limit' : 'Output token limit'}\n min={key === 'inputTokens' ? 10000 : 1000}\n max={key === 'inputTokens' ? 2000000 : 100000}\n step=\"1000\"\n value={budget[key]}\n disabled={running || saving}\n onChange={e => {\n const next = { ...budget, [key]: Number(e.target.value) };\n setBudget(next);\n try {\n const valid = readImportBudget(next);\n if (latest.current)\n void persist({ ...latest.current, budget: valid }).catch(() =>\n setError('Could not save import budget.'),\n );\n } catch {\n /* Start validates completed values. */\n }\n }}\n />\n </label>\n ))}\n </div>\n </details>\n );\n const tabs = [\n ['setup', 'Setup'],\n ['analysis', 'Analysis'],\n ['activity', 'Activity'],\n ['usage', 'Usage'],\n ] as const;\n const chooseTab = (next: ImportTab) => {\n setTab(next);\n if (latest.current)\n void persist({ ...latest.current, tab: next }).catch(() => setError('Could not save the import view.'));\n };\n if (loading) return <p role=\"status\">Restoring import session…</p>;\n const newSource = !!file || !session;\n return (\n <section className=\"ai-import-panel ai-import-organized\">\n <header className=\"ai-import-sticky\">\n <strong className=\"ai-import-source\" title={file?.name ?? session?.sourceName}>\n {file?.name ?? session?.sourceName ?? 'Choose a source drawing'}\n </strong>\n <div className=\"ai-import-toolbar\">\n <span role=\"status\">\n {running\n ? `Importing · ${edits} accepted edits · ${Math.floor(elapsed / 60)}:${String(elapsed % 60).padStart(2, '0')}`\n : phase === 'done'\n ? `Saved to project · ${edits} accepted edits`\n : phase === 'paused'\n ? 'Paused · accepted changes saved'\n : phase === 'failed'\n ? 'Import interrupted'\n : 'Ready to import'}\n </span>\n {running ? (\n <button className=\"button secondary\" onClick={() => controller.current?.abort()}>\n Stop import\n </button>\n ) : (\n <button\n className=\"button primary\"\n disabled={saving || (newSource && !file)}\n onClick={() => start(!newSource)}\n >\n {saving ? 'Preparing…' : newSource ? 'Start AI import' : 'Continue import'}\n </button>\n )}\n </div>\n {running && <p className=\"ai-import-activity\">{activity || 'Claude is working…'}</p>}\n {!running && session?.pause && (\n <p className=\"ai-import-pause\" aria-live=\"polite\">\n {session.pause.message}\n </p>\n )}\n {error && (\n <p className=\"form-error\" role=\"alert\">\n {error}\n </p>\n )}\n </header>\n <div className=\"ai-import-tablist\" role=\"tablist\" aria-label=\"AI import sections\">\n {tabs.map(([key, label], index) => (\n <button\n key={key}\n id={`${tabId}-${key}`}\n data-tab={key}\n role=\"tab\"\n aria-selected={tab === key}\n aria-controls={`${tabId}-${key}-panel`}\n tabIndex={tab === key ? 0 : -1}\n onClick={() => chooseTab(key)}\n onKeyDown={e => {\n const next =\n e.key === 'ArrowRight'\n ? (index + 1) % tabs.length\n : e.key === 'ArrowLeft'\n ? (index + tabs.length - 1) % tabs.length\n : e.key === 'Home'\n ? 0\n : e.key === 'End'\n ? tabs.length - 1\n : -1;\n if (next < 0) return;\n e.preventDefault();\n chooseTab(tabs[next][0]);\n (\n e.currentTarget.parentElement?.querySelector(`[data-tab=\"${tabs[next][0]}\"]`) as HTMLButtonElement\n )?.focus();\n }}\n >\n {label}\n {key === 'analysis' && analysisPreview && <i aria-hidden=\"true\" title=\"Preview available\" />}\n </button>\n ))}\n </div>\n <div\n className=\"ai-import-tab-scroll\"\n role=\"tabpanel\"\n id={`${tabId}-setup-panel`}\n aria-labelledby={`${tabId}-setup`}\n hidden={tab !== 'setup'}\n >\n <p className=\"helper\">\n Claude edits the live project and saves accepted changes. Starting or continuing uses your backend API key and\n incurs API usage.\n </p>\n <div className=\"ai-import-inputs\">\n <label className=\"field\">\n <span>{session ? 'Replace source drawing' : 'Source drawing'}</span>\n <input\n type=\"file\"\n aria-label=\"AI source drawing\"\n accept=\".dwg,.pdf,.png,.jpg,.jpeg,.webp\"\n disabled={running || saving}\n onChange={e => {\n setFile(e.target.files?.[0] ?? null);\n e.currentTarget.value = '';\n }}\n />\n <small>Images, PDF (up to 20 pages), or DWG · up to 25 MB</small>\n </label>\n {file && session && (\n <button className=\"text-button\" onClick={() => setFile(null)}>\n Keep current source\n </button>\n )}\n <label className=\"field\">\n <span>Import instructions</span>\n <textarea\n aria-label=\"Import instructions\"\n maxLength={8000}\n rows={3}\n disabled={running || saving}\n value={instructions}\n onChange={e => {\n setInstructions(e.target.value);\n if (latest.current)\n void persist({ ...latest.current, instructions: e.target.value }).catch(() =>\n setError('Could not save instructions.'),\n );\n }}\n placeholder=\"For example: page 2 is the ground floor, exterior width 18.4 m. Include room names and openings.\"\n />\n </label>\n </div>\n {scaleFields}\n {budgetFields}\n <p className=\"helper\">\n Stop before making manual edits. Continue uses the current project and saved working notes. Closing this\n sidebar keeps an active import running.\n </p>\n </div>\n <div\n className=\"ai-import-tab-scroll\"\n role=\"tabpanel\"\n id={`${tabId}-analysis-panel`}\n aria-labelledby={`${tabId}-analysis`}\n hidden={tab !== 'analysis'}\n >\n {analysisPreview ? (\n <AnalysisPreview preview={analysisPreview} />\n ) : (\n <p className=\"ai-import-empty\">\n The source SVG will appear here when Claude analyses the drawing. It shows detected evidence; accepted\n geometry appears on the main map.\n </p>\n )}\n </div>\n <div\n className=\"ai-import-activity-panel\"\n role=\"tabpanel\"\n id={`${tabId}-activity-panel`}\n aria-labelledby={`${tabId}-activity`}\n hidden={tab !== 'activity'}\n >\n <div\n className=\"ai-import-tab-scroll\"\n ref={chat}\n onScroll={e => {\n follow.current = e.currentTarget.scrollTop < 60;\n }}\n >\n <section className=\"ai-import-conversation\" aria-label=\"AI conversation\">\n {!messages.length && (\n <p className=\"ai-import-empty\">Claude’s latest message and tool activity will appear at the top.</p>\n )}\n {[...messages].reverse().map((message, i) => (\n <div key={messages.length - 1 - i} className={`ai-import-message ${message.type}`}>\n <small>\n {message.type === 'text'\n ? 'Claude'\n : message.type === 'user'\n ? session?.pendingInstructions?.some(m => m.id === message.instructionId)\n ? 'You · queued'\n : 'You'\n : 'Tool'}\n </small>\n <p>{message.detail}</p>\n </div>\n ))}\n </section>\n </div>\n <form\n className=\"ai-import-composer\"\n onSubmit={e => {\n e.preventDefault();\n void sendInstruction();\n }}\n >\n <label className=\"field\">\n <span>Message to AI</span>\n <textarea\n aria-label=\"Message to AI\"\n rows={3}\n maxLength={2000}\n value={followUp}\n disabled={!session || saving || sending || !!file}\n onChange={e => {\n setFollowUp(e.target.value);\n if (latest.current)\n void persist({ ...latest.current, followUp: e.target.value }).catch(() =>\n setError('Could not save your draft.'),\n );\n }}\n placeholder=\"Give a correction or describe what to do next…\"\n />\n </label>\n <div>\n <small>\n {running\n ? 'Queued for Claude’s next turn.'\n : session\n ? 'Resumes with the saved project. Uses API tokens.'\n : 'Start an import in Setup to chat.'}\n </small>\n <button\n className=\"button primary\"\n type=\"submit\"\n disabled={\n !session ||\n !followUp.trim() ||\n saving ||\n sending ||\n !!file ||\n (running && (!activeJob || !adapter.sendInstruction))\n }\n >\n {sending ? 'Sending…' : running ? 'Send' : 'Send & continue'}\n </button>\n </div>\n </form>\n </div>\n <div\n className=\"ai-import-tab-scroll\"\n role=\"tabpanel\"\n id={`${tabId}-usage-panel`}\n aria-labelledby={`${tabId}-usage`}\n hidden={tab !== 'usage'}\n >\n <section className=\"ai-import-usage\" aria-label=\"Token usage\">\n <strong>\n Tokens reported ·{' '}\n {Object.values(usage)\n .reduce((sum, n) => sum + n, 0)\n .toLocaleString()}\n </strong>\n <dl>\n {(\n [\n ['Input', usage.inputTokens],\n ['Output', usage.outputTokens],\n ['Cache read', usage.cacheReadTokens],\n ['Cache write', usage.cacheWriteTokens],\n ] as const\n ).map(([label, count]) => (\n <div key={label}>\n <dt>{label}</dt>\n <dd>{count.toLocaleString()}</dd>\n </div>\n ))}\n </dl>\n <small>\n {!hasUsage\n ? 'Waiting for Claude to report usage.'\n : 'Includes continuations in this session. Saved with this project; interrupted runs may report incomplete usage.'}\n </small>\n </section>\n <p className=\"helper\">\n Per run: {budget.maxTurns ?? 40} turns, {budget.inputTokens.toLocaleString()} input (including cache),{' '}\n {budget.outputTokens.toLocaleString()} output tokens. Adjust limits in Setup. Reaching a limit pauses the\n import; Continue starts the next paid run from the saved checkpoint.\n </p>\n </div>\n </section>\n );\n}\n"],"names":["AiImportPanel","adapter","assets","onProject","onRunningChange","currentProject","loading","setLoading","useState","tab","setTab","tabId","useId","file","setFile","instructions","setInstructions","widthMetres","setWidthMetres","depthMetres","setDepthMetres","buildingType","setBuildingType","floorCount","setFloorCount","footprintArea","setFootprintArea","followUp","setFollowUp","budget","setBudget","DEFAULT_IMPORT_BUDGET","analysisPreview","setAnalysisPreview","session","setSession","latest","useRef","projectRef","acceptProject","elapsed","setElapsed","error","setError","saving","setSaving","sending","setSending","activeJob","setActiveJob","controller","queue","chat","follow","running","phase","messages","usage","emptyTokenUsage","hasUsage","edits","activity","persist","next","write","saveAiImportSession","useEffect","active","loadAiImportSession","saved","_b","_a","_d","_c","_e","_g","_f","_i","_h","preview","loadAnalysisPreview","started","timer","start","continuing","request","previousUsage","previous","runBudget","readImportBudget","brief","readImportBrief","selected","blob","sourceId","m","instruction","readImportInstruction","mergeImportInstructions","deleteAnalysisPreview","lastDocument","result","jobId","saveAnalysisPreview","checkpoint","acknowledged","pause","snapshot","addTokenUsage","document","event","state","last","e","message","sendInstruction","pending","changeBrief","patch","scaleFields","jsxs","jsx","budgetFields","valid","key","tabs","chooseTab","newSource","label","index","AnalysisPreview","i","sum","n","count"],"mappings":"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"}
@@ -0,0 +1,179 @@
1
+ import { jsxs as n, Fragment as k, jsx as t } from "react/jsx-runtime";
2
+ import { useState as c, useRef as v, useEffect as y } from "react";
3
+ import { Maximize2 as A } from "lucide-react";
4
+ import { Modal as L } from "./controls.js";
5
+ import { analysisPreviewSvg as M } from "../import/analysisPreview.js";
6
+ const P = [
7
+ ["wall", "Walls"],
8
+ ["outline", "Outlines"],
9
+ ["label", "Labels"],
10
+ ["symbol", "Symbols"],
11
+ ["path", "Source strokes"]
12
+ ];
13
+ function T({ preview: a }) {
14
+ const [C, G] = c(!0), [d, V] = c([]), [m, h] = c(1), [o, O] = c(""), [g, R] = c(!0), [i, U] = c(0.85), [r, f] = c(!1), S = v(null), p = v(null), [x, $] = c();
15
+ y(() => {
16
+ const e = p.current;
17
+ if (!e) return;
18
+ const s = () => {
19
+ var F;
20
+ const l = (F = a.svg.match(/viewBox="([^"]+)"/)) == null ? void 0 : F[1].split(/[ ,]+/).map(Number), b = l && l[2] > 0 && l[3] > 0 ? l[2] / l[3] : 1;
21
+ $(
22
+ r ? Math.min(e.clientWidth, Math.max(1, e.clientHeight - 16) * b + 16) : e.clientWidth
23
+ );
24
+ }, u = new ResizeObserver(s);
25
+ return u.observe(e), s(), () => u.disconnect();
26
+ }, [r, a.svg]);
27
+ const z = () => {
28
+ f(!1), requestAnimationFrame(() => {
29
+ var e;
30
+ return (e = S.current) == null ? void 0 : e.focus();
31
+ });
32
+ };
33
+ y(() => {
34
+ const e = M(a, d, g, i), s = URL.createObjectURL(new Blob([e], { type: "image/svg+xml" }));
35
+ return O(s), () => URL.revokeObjectURL(s);
36
+ }, [a, d, g, i]), y(() => {
37
+ h(1);
38
+ }, [a.artifactId]);
39
+ const N = /* @__PURE__ */ n(k, { children: [
40
+ /* @__PURE__ */ n("p", { className: "helper", children: [
41
+ "Detected source geometry ·",
42
+ " ",
43
+ a.transformId ? `calibrated in metres (${a.metresPerUnit.toPrecision(4)} m/source unit)` : `uncalibrated ${a.units === "px" ? "pixels" : a.units === "pt" ? "PDF points" : "metres"}`,
44
+ ". Accepted edits appear on the main map."
45
+ ] }),
46
+ /* @__PURE__ */ t("div", { className: "ai-analysis-layers", "aria-label": "Analysis layers", children: P.filter(([e]) => a.counts[e]).map(([e, s]) => /* @__PURE__ */ n("label", { children: [
47
+ /* @__PURE__ */ t(
48
+ "input",
49
+ {
50
+ type: "checkbox",
51
+ checked: !d.includes(e),
52
+ onChange: (u) => V((l) => u.target.checked ? l.filter((b) => b !== e) : [...l, e])
53
+ }
54
+ ),
55
+ s,
56
+ " ",
57
+ /* @__PURE__ */ t("small", { children: a.counts[e] })
58
+ ] }, e)) }),
59
+ a.background && /* @__PURE__ */ n("div", { className: "ai-analysis-overlay-controls", children: [
60
+ /* @__PURE__ */ n("label", { children: [
61
+ /* @__PURE__ */ t("input", { type: "checkbox", checked: g, onChange: (e) => R(e.target.checked) }),
62
+ "Original drawing"
63
+ ] }),
64
+ /* @__PURE__ */ n("label", { children: [
65
+ "SVG opacity",
66
+ " ",
67
+ /* @__PURE__ */ t(
68
+ "input",
69
+ {
70
+ type: "range",
71
+ "aria-label": "SVG opacity",
72
+ min: "0",
73
+ max: "1",
74
+ step: "0.05",
75
+ value: i,
76
+ onChange: (e) => U(Number(e.target.value))
77
+ }
78
+ ),
79
+ /* @__PURE__ */ n("output", { children: [
80
+ Math.round(i * 100),
81
+ "%"
82
+ ] })
83
+ ] })
84
+ ] }),
85
+ /* @__PURE__ */ n("div", { className: "ai-analysis-toolbar", children: [
86
+ /* @__PURE__ */ n("label", { children: [
87
+ "Zoom",
88
+ " ",
89
+ /* @__PURE__ */ t(
90
+ "input",
91
+ {
92
+ type: "range",
93
+ "aria-label": "Analysis zoom",
94
+ min: "1",
95
+ max: "4",
96
+ step: "0.25",
97
+ value: m,
98
+ onChange: (e) => h(Number(e.target.value))
99
+ }
100
+ )
101
+ ] }),
102
+ /* @__PURE__ */ t(
103
+ "button",
104
+ {
105
+ type: "button",
106
+ className: "button secondary",
107
+ onClick: () => {
108
+ var e;
109
+ h(1), (e = p.current) == null || e.scrollTo(0, 0);
110
+ },
111
+ children: "Fit"
112
+ }
113
+ ),
114
+ !r && /* @__PURE__ */ t(
115
+ "button",
116
+ {
117
+ ref: S,
118
+ type: "button",
119
+ className: "icon-button",
120
+ "aria-label": "Fullscreen SVG preview",
121
+ title: "Fullscreen SVG preview",
122
+ onClick: () => f(!0),
123
+ children: /* @__PURE__ */ t(A, { size: 16 })
124
+ }
125
+ ),
126
+ o && /* @__PURE__ */ t("a", { href: o, download: `source-page-${a.page}.svg`, children: "Save SVG" })
127
+ ] }),
128
+ /* @__PURE__ */ t("div", { ref: p, className: "ai-analysis-canvas", tabIndex: 0, "aria-label": "Source vector preview", children: o && /* @__PURE__ */ t(
129
+ "img",
130
+ {
131
+ src: o,
132
+ alt: `Source analysis SVG, page ${a.page}`,
133
+ style: { width: x ? x * m : `${m * 100}%` }
134
+ }
135
+ ) }),
136
+ /* @__PURE__ */ n("p", { className: "helper", children: [
137
+ "Blue: walls · amber: outlines · purple: symbols · red: latest selection. ",
138
+ a.shown,
139
+ " of ",
140
+ a.total,
141
+ " ",
142
+ "candidates shown",
143
+ a.shown < a.total ? "; preview capped for large sheets" : "",
144
+ "."
145
+ ] }),
146
+ a.calibration && /* @__PURE__ */ t("p", { className: "helper", children: a.calibration }),
147
+ !!a.warnings.length && /* @__PURE__ */ n("details", { children: [
148
+ /* @__PURE__ */ n("summary", { children: [
149
+ "Detection uncertainties (",
150
+ a.warnings.length,
151
+ ")"
152
+ ] }),
153
+ /* @__PURE__ */ t("ul", { children: a.warnings.map((e, s) => /* @__PURE__ */ t("li", { children: e }, s)) })
154
+ ] })
155
+ ] });
156
+ return /* @__PURE__ */ n(k, { children: [
157
+ /* @__PURE__ */ n(
158
+ "details",
159
+ {
160
+ className: "ai-analysis-preview",
161
+ open: C,
162
+ hidden: r,
163
+ onToggle: (e) => G(e.currentTarget.open),
164
+ children: [
165
+ /* @__PURE__ */ n("summary", { children: [
166
+ "Source analysis · SVG · page ",
167
+ a.page
168
+ ] }),
169
+ !r && N
170
+ ]
171
+ }
172
+ ),
173
+ r && /* @__PURE__ */ t(L, { fullscreen: !0, title: `Source analysis · page ${a.page}`, onClose: z, children: /* @__PURE__ */ t("div", { className: "ai-analysis-fullscreen", children: N }) })
174
+ ] });
175
+ }
176
+ export {
177
+ T as AnalysisPreview
178
+ };
179
+ //# sourceMappingURL=AnalysisPreview.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalysisPreview.js","sources":["../../../../src/components/AnalysisPreview.tsx"],"sourcesContent":["import { useEffect, useState, useRef } from 'react';\nimport { Maximize2 } from 'lucide-react';\nimport { Modal } from './controls';\nimport { analysisPreviewSvg, type ImportAnalysisPreview } from '../import/analysisPreview';\n\nconst layers = [\n ['wall', 'Walls'],\n ['outline', 'Outlines'],\n ['label', 'Labels'],\n ['symbol', 'Symbols'],\n ['path', 'Source strokes'],\n] as const;\nexport function AnalysisPreview({ preview }: { preview: ImportAnalysisPreview }) {\n const [expanded, setExpanded] = useState(true);\n const [hidden, setHidden] = useState<string[]>([]);\n const [zoom, setZoom] = useState(1);\n const [url, setUrl] = useState('');\n const [showSource, setShowSource] = useState(true);\n const [opacity, setOpacity] = useState(0.85);\n const [fullscreen, setFullscreen] = useState(false);\n const expandButton = useRef<HTMLButtonElement>(null);\n const canvas = useRef<HTMLDivElement>(null);\n const [fitWidth, setFitWidth] = useState<number>();\n useEffect(() => {\n const el = canvas.current;\n if (!el) return;\n const measure = () => {\n const box = preview.svg\n .match(/viewBox=\"([^\"]+)\"/)?.[1]\n .split(/[ ,]+/)\n .map(Number);\n const aspect = box && box[2] > 0 && box[3] > 0 ? box[2] / box[3] : 1;\n setFitWidth(\n fullscreen ? Math.min(el.clientWidth, Math.max(1, el.clientHeight - 16) * aspect + 16) : el.clientWidth,\n );\n };\n const observer = new ResizeObserver(measure);\n observer.observe(el);\n measure();\n return () => observer.disconnect();\n }, [fullscreen, preview.svg]);\n const closeFullscreen = () => {\n setFullscreen(false);\n requestAnimationFrame(() => expandButton.current?.focus());\n };\n useEffect(() => {\n const svg = analysisPreviewSvg(preview, hidden, showSource, opacity);\n const url = URL.createObjectURL(new Blob([svg], { type: 'image/svg+xml' }));\n setUrl(url);\n return () => URL.revokeObjectURL(url);\n }, [preview, hidden, showSource, opacity]);\n useEffect(() => {\n setZoom(1);\n }, [preview.artifactId]);\n const contents = (\n <>\n <p className=\"helper\">\n Detected source geometry ·{' '}\n {preview.transformId\n ? `calibrated in metres (${preview.metresPerUnit!.toPrecision(4)} m/source unit)`\n : `uncalibrated ${preview.units === 'px' ? 'pixels' : preview.units === 'pt' ? 'PDF points' : 'metres'}`}\n . Accepted edits appear on the main map.\n </p>\n <div className=\"ai-analysis-layers\" aria-label=\"Analysis layers\">\n {layers\n .filter(([kind]) => preview.counts[kind])\n .map(([kind, label]) => (\n <label key={kind}>\n <input\n type=\"checkbox\"\n checked={!hidden.includes(kind)}\n onChange={e =>\n setHidden(previous => (e.target.checked ? previous.filter(k => k !== kind) : [...previous, kind]))\n }\n />\n {label} <small>{preview.counts[kind]}</small>\n </label>\n ))}\n </div>\n {preview.background && (\n <div className=\"ai-analysis-overlay-controls\">\n <label>\n <input type=\"checkbox\" checked={showSource} onChange={e => setShowSource(e.target.checked)} />\n Original drawing\n </label>\n <label>\n SVG opacity{' '}\n <input\n type=\"range\"\n aria-label=\"SVG opacity\"\n min=\"0\"\n max=\"1\"\n step=\"0.05\"\n value={opacity}\n onChange={e => setOpacity(Number(e.target.value))}\n />\n <output>{Math.round(opacity * 100)}%</output>\n </label>\n </div>\n )}\n <div className=\"ai-analysis-toolbar\">\n <label>\n Zoom{' '}\n <input\n type=\"range\"\n aria-label=\"Analysis zoom\"\n min=\"1\"\n max=\"4\"\n step=\"0.25\"\n value={zoom}\n onChange={e => setZoom(Number(e.target.value))}\n />\n </label>\n <button\n type=\"button\"\n className=\"button secondary\"\n onClick={() => {\n setZoom(1);\n canvas.current?.scrollTo(0, 0);\n }}\n >\n Fit\n </button>\n {!fullscreen && (\n <button\n ref={expandButton}\n type=\"button\"\n className=\"icon-button\"\n aria-label=\"Fullscreen SVG preview\"\n title=\"Fullscreen SVG preview\"\n onClick={() => setFullscreen(true)}\n >\n <Maximize2 size={16} />\n </button>\n )}\n {url && (\n <a href={url} download={`source-page-${preview.page}.svg`}>\n Save SVG\n </a>\n )}\n </div>\n <div ref={canvas} className=\"ai-analysis-canvas\" tabIndex={0} aria-label=\"Source vector preview\">\n {url && (\n <img\n src={url}\n alt={`Source analysis SVG, page ${preview.page}`}\n style={{ width: fitWidth ? fitWidth * zoom : `${zoom * 100}%` }}\n />\n )}\n </div>\n <p className=\"helper\">\n Blue: walls · amber: outlines · purple: symbols · red: latest selection. {preview.shown} of {preview.total}{' '}\n candidates shown{preview.shown < preview.total ? '; preview capped for large sheets' : ''}.\n </p>\n {preview.calibration && <p className=\"helper\">{preview.calibration}</p>}\n {!!preview.warnings.length && (\n <details>\n <summary>Detection uncertainties ({preview.warnings.length})</summary>\n <ul>\n {preview.warnings.map((warning, i) => (\n <li key={i}>{warning}</li>\n ))}\n </ul>\n </details>\n )}\n </>\n );\n return (\n <>\n <details\n className=\"ai-analysis-preview\"\n open={expanded}\n hidden={fullscreen}\n onToggle={e => setExpanded(e.currentTarget.open)}\n >\n <summary>Source analysis · SVG · page {preview.page}</summary>\n {!fullscreen && contents}\n </details>\n {fullscreen && (\n <Modal fullscreen title={`Source analysis · page ${preview.page}`} onClose={closeFullscreen}>\n <div className=\"ai-analysis-fullscreen\">{contents}</div>\n </Modal>\n )}\n </>\n );\n}\n"],"names":["layers","AnalysisPreview","preview","expanded","setExpanded","useState","hidden","setHidden","zoom","setZoom","url","setUrl","showSource","setShowSource","opacity","setOpacity","fullscreen","setFullscreen","expandButton","useRef","canvas","fitWidth","setFitWidth","useEffect","el","measure","box","_a","aspect","observer","closeFullscreen","svg","analysisPreviewSvg","contents","jsxs","Fragment","jsx","kind","label","e","previous","k","Maximize2","warning","i","Modal"],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ import { jsxs as t, jsx as n, Fragment as y } from "react/jsx-runtime";
2
+ import { useMemo as B, useState as F, useEffect as g } from "react";
3
+ import { distance as G } from "../model/geometry.js";
4
+ import { primaryShafts as H, servedFloors as W } from "../model/vertical.js";
5
+ import { elevatorMirrorFace as J, elevatorMirrorPoint as K, elevatorLanding as $, insideElevator as L, elevatorFacing as O } from "../map/elevators.js";
6
+ function _({
7
+ project: d,
8
+ floorId: a,
9
+ controls: h,
10
+ walker: s,
11
+ riding: o,
12
+ onRide: m,
13
+ onFloor: b,
14
+ requested: E,
15
+ onWave: P,
16
+ soundOn: x,
17
+ onSound: S
18
+ }) {
19
+ const f = B(() => {
20
+ const r = H(d);
21
+ return d.objects.filter(
22
+ (i) => i.kind === "elevator" && i.feedId && r.has(i.id) && W(d, i).some((c) => c.id === a)
23
+ );
24
+ }, [d, a]), [p, u] = F(!1), [A, D] = F(), [C, T] = F(!1), l = f.find((r) => r.id === (o ?? A)) ?? f[0], e = h.statuses.find((r) => r.feedId === (l == null ? void 0 : l.feedId)), v = !!(e != null && e.open) && !e.moving && !e.targetFloorId && e.carFloorId === a, k = o === (l == null ? void 0 : l.id) && v;
25
+ if (g(() => {
26
+ E && u(!0);
27
+ }, [E]), g(() => {
28
+ if (!l) return;
29
+ const r = () => {
30
+ var M;
31
+ const c = (M = s.current) == null ? void 0 : M.position;
32
+ c && (T(G(c, $(l)) < 2.5), L(l, c) && v && !o ? (m(l.id), u(!0)) : !L(l, c) && k && m(null));
33
+ };
34
+ r();
35
+ const i = setInterval(r, 120);
36
+ return () => clearInterval(i);
37
+ }, [l, v, o, k, s, m]), g(() => {
38
+ o && (e != null && e.carFloorId) && !e.targetFloorId && e.carFloorId !== a && (b == null || b(e.carFloorId));
39
+ }, [o, e == null ? void 0 : e.carFloorId, e == null ? void 0 : e.targetFloorId, a, b]), !l) return null;
40
+ const Y = W(d, l).slice().reverse(), I = d.floors.find((r) => r.id === (e == null ? void 0 : e.carFloorId)), N = d.floors.find((r) => r.id === (e == null ? void 0 : e.targetFloorId)), z = (r) => {
41
+ var i;
42
+ !v || !C || (m(r.id), (i = s.current) == null || i.place(r.position, -O(r)));
43
+ };
44
+ return /* @__PURE__ */ t("aside", { className: "walk-elevator", "aria-label": "Elevator controls", children: [
45
+ /* @__PURE__ */ t("button", { className: "elevator-toggle", "aria-expanded": p, onClick: () => u((r) => !r), children: [
46
+ "Elevator controls ",
47
+ /* @__PURE__ */ n("span", { children: p ? "−" : "+" })
48
+ ] }),
49
+ p && /* @__PURE__ */ t("div", { className: "elevator-body", children: [
50
+ f.length > 1 ? /* @__PURE__ */ n(
51
+ "select",
52
+ {
53
+ "aria-label": "Choose elevator",
54
+ value: l.id,
55
+ disabled: !!o,
56
+ onChange: (r) => D(r.target.value),
57
+ children: f.map((r) => /* @__PURE__ */ n("option", { value: r.id, children: r.name }, r.id))
58
+ }
59
+ ) : /* @__PURE__ */ n("strong", { children: l.name }),
60
+ /* @__PURE__ */ n("p", { role: "status", children: N ? `Travelling to ${N.name}` : `${(e == null ? void 0 : e.label) ?? "Waiting"} · ${(I == null ? void 0 : I.name) ?? "—"}` }),
61
+ o ? /* @__PURE__ */ n("p", { children: "You are inside the elevator." }) : /* @__PURE__ */ t(y, { children: [
62
+ /* @__PURE__ */ n("button", { disabled: !e || e.moving, onClick: () => h.call(l.feedId, a), children: "Call to this floor" }),
63
+ /* @__PURE__ */ n("button", { disabled: !v || !C, onClick: () => z(l), children: "Enter elevator" }),
64
+ !C && /* @__PURE__ */ n("small", { children: "Walk to the elevator doors to enter." })
65
+ ] }),
66
+ o && /* @__PURE__ */ n("div", { className: "elevator-floors", "aria-label": "Destination floor", children: Y.map((r) => /* @__PURE__ */ t(
67
+ "button",
68
+ {
69
+ "aria-pressed": r.id === a,
70
+ disabled: !e || e.moving || r.id === a,
71
+ onClick: () => h.call(l.feedId, r.id),
72
+ children: [
73
+ r.code,
74
+ " · ",
75
+ r.name
76
+ ]
77
+ },
78
+ r.id
79
+ )) }),
80
+ o && /* @__PURE__ */ t(y, { children: [
81
+ /* @__PURE__ */ t("button", { "aria-pressed": x, onClick: S, children: [
82
+ x ? "Cabin music on" : "Cabin music muted",
83
+ " · M"
84
+ ] }),
85
+ J(l) && /* @__PURE__ */ t("div", { className: "elevator-door-buttons", children: [
86
+ /* @__PURE__ */ n("button", { onClick: () => {
87
+ var r;
88
+ return (r = s.current) == null ? void 0 : r.lookAt(K(l));
89
+ }, children: "Look in mirror" }),
90
+ /* @__PURE__ */ n("button", { onClick: P, children: "Wave" })
91
+ ] })
92
+ ] }),
93
+ /* @__PURE__ */ t("div", { className: "elevator-door-buttons", children: [
94
+ /* @__PURE__ */ n(
95
+ "button",
96
+ {
97
+ disabled: !e || e.moving || e.carFloorId !== a,
98
+ onClick: () => h.hold(l.feedId, !(e != null && e.open)),
99
+ children: e != null && e.open ? "Close doors" : "Open doors"
100
+ }
101
+ ),
102
+ o && /* @__PURE__ */ n(
103
+ "button",
104
+ {
105
+ disabled: !k,
106
+ onClick: () => {
107
+ var r;
108
+ m(null), (r = s.current) == null || r.place($(l));
109
+ },
110
+ children: "Exit elevator"
111
+ }
112
+ )
113
+ ] })
114
+ ] })
115
+ ] });
116
+ }
117
+ export {
118
+ _ as ElevatorPanel
119
+ };
120
+ //# sourceMappingURL=ElevatorPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ElevatorPanel.js","sources":["../../../../src/components/ElevatorPanel.tsx"],"sourcesContent":["import { useEffect, useMemo, useState } from 'react';\nimport type { ElevatorControls } from '../model/host';\nimport type { ProjectDocument, SiteObject } from '../model/types';\nimport type { WalkController } from '../map/walk';\nimport { distance } from '../model/geometry';\nimport { servedFloors, primaryShafts } from '../model/vertical';\nimport {\n elevatorFacing,\n elevatorLanding,\n elevatorMirrorFace,\n elevatorMirrorPoint,\n insideElevator,\n} from '../map/elevators';\n\nexport function ElevatorPanel({\n project,\n floorId,\n controls,\n walker,\n riding,\n onRide,\n onFloor,\n requested,\n onWave,\n soundOn,\n onSound,\n}: {\n project: ProjectDocument;\n floorId: string | null;\n controls: ElevatorControls;\n walker: { current: WalkController | null };\n riding: string | null;\n onRide(id: string | null): void;\n onFloor?(id: string): void;\n requested: number;\n onWave(): void;\n soundOn: boolean;\n onSound(): void;\n}) {\n const banks = useMemo(() => {\n const primary = primaryShafts(project);\n return project.objects.filter(\n o =>\n o.kind === 'elevator' && o.feedId && primary.has(o.id) && servedFloors(project, o).some(f => f.id === floorId),\n );\n }, [project, floorId]);\n const [expanded, setExpanded] = useState(false),\n [chosen, setChosen] = useState<string>();\n const [near, setNear] = useState(false);\n const object = banks.find(o => o.id === (riding ?? chosen)) ?? banks[0];\n const status = controls.statuses.find(s => s.feedId === object?.feedId);\n const accessible = !!status?.open && !status.moving && !status.targetFloorId && status.carFloorId === floorId;\n const safeExit = riding === object?.id && accessible;\n useEffect(() => {\n if (requested) setExpanded(true);\n }, [requested]);\n useEffect(() => {\n if (!object) return;\n const check = () => {\n const at = walker.current?.position;\n if (!at) return;\n setNear(distance(at, elevatorLanding(object)) < 2.5);\n if (insideElevator(object, at) && accessible && !riding) {\n onRide(object.id);\n setExpanded(true);\n } else if (!insideElevator(object, at) && safeExit) onRide(null);\n };\n check();\n const timer = setInterval(check, 120);\n return () => clearInterval(timer);\n }, [object, accessible, riding, safeExit, walker, onRide]);\n useEffect(() => {\n if (riding && status?.carFloorId && !status.targetFloorId && status.carFloorId !== floorId)\n onFloor?.(status.carFloorId);\n }, [riding, status?.carFloorId, status?.targetFloorId, floorId, onFloor]);\n if (!object) return null;\n const floors = servedFloors(project, object).slice().reverse();\n const at = project.floors.find(f => f.id === status?.carFloorId);\n const destination = project.floors.find(f => f.id === status?.targetFloorId);\n const board = (o: SiteObject) => {\n if (!accessible || !near) return;\n onRide(o.id);\n walker.current?.place(o.position, -elevatorFacing(o));\n };\n return (\n <aside className=\"walk-elevator\" aria-label=\"Elevator controls\">\n <button className=\"elevator-toggle\" aria-expanded={expanded} onClick={() => setExpanded(v => !v)}>\n Elevator controls <span>{expanded ? '−' : '+'}</span>\n </button>\n {expanded && (\n <div className=\"elevator-body\">\n {banks.length > 1 ? (\n <select\n aria-label=\"Choose elevator\"\n value={object.id}\n disabled={!!riding}\n onChange={e => setChosen(e.target.value)}\n >\n {banks.map(o => (\n <option key={o.id} value={o.id}>\n {o.name}\n </option>\n ))}\n </select>\n ) : (\n <strong>{object.name}</strong>\n )}\n <p role=\"status\">\n {destination ? `Travelling to ${destination.name}` : `${status?.label ?? 'Waiting'} · ${at?.name ?? '—'}`}\n </p>\n {riding ? (\n <p>You are inside the elevator.</p>\n ) : (\n <>\n <button disabled={!status || status.moving} onClick={() => controls.call(object.feedId!, floorId!)}>\n Call to this floor\n </button>\n <button disabled={!accessible || !near} onClick={() => board(object)}>\n Enter elevator\n </button>\n {!near && <small>Walk to the elevator doors to enter.</small>}\n </>\n )}\n {riding && (\n <div className=\"elevator-floors\" aria-label=\"Destination floor\">\n {floors.map(f => (\n <button\n key={f.id}\n aria-pressed={f.id === floorId}\n disabled={!status || status.moving || f.id === floorId}\n onClick={() => controls.call(object.feedId!, f.id)}\n >\n {f.code} · {f.name}\n </button>\n ))}\n </div>\n )}\n {riding && (\n <>\n <button aria-pressed={soundOn} onClick={onSound}>\n {soundOn ? 'Cabin music on' : 'Cabin music muted'} · M\n </button>\n {elevatorMirrorFace(object) && (\n <div className=\"elevator-door-buttons\">\n <button onClick={() => walker.current?.lookAt(elevatorMirrorPoint(object))}>Look in mirror</button>\n <button onClick={onWave}>Wave</button>\n </div>\n )}\n </>\n )}\n <div className=\"elevator-door-buttons\">\n <button\n disabled={!status || status.moving || status.carFloorId !== floorId}\n onClick={() => controls.hold(object.feedId!, !status?.open)}\n >\n {status?.open ? 'Close doors' : 'Open doors'}\n </button>\n {riding && (\n <button\n disabled={!safeExit}\n onClick={() => {\n onRide(null);\n walker.current?.place(elevatorLanding(object));\n }}\n >\n Exit elevator\n </button>\n )}\n </div>\n </div>\n )}\n </aside>\n );\n}\n"],"names":["ElevatorPanel","project","floorId","controls","walker","riding","onRide","onFloor","requested","onWave","soundOn","onSound","banks","useMemo","primary","primaryShafts","o","servedFloors","f","expanded","setExpanded","useState","chosen","setChosen","near","setNear","object","status","s","accessible","safeExit","useEffect","check","at","_a","distance","elevatorLanding","insideElevator","timer","floors","destination","board","elevatorFacing","jsxs","v","jsx","e","Fragment","elevatorMirrorFace","elevatorMirrorPoint"],"mappings":";;;;;AAcO,SAASA,EAAc;AAAA,EAC5B,SAAAC;AAAA,EACA,SAAAC;AAAA,EACA,UAAAC;AAAA,EACA,QAAAC;AAAA,EACA,QAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,WAAAC;AAAA,EACA,QAAAC;AAAA,EACA,SAAAC;AAAA,EACA,SAAAC;AACF,GAYG;AACD,QAAMC,IAAQC,EAAQ,MAAM;AAC1B,UAAMC,IAAUC,EAAcd,CAAO;AACrC,WAAOA,EAAQ,QAAQ;AAAA,MACrB,OACEe,EAAE,SAAS,cAAcA,EAAE,UAAUF,EAAQ,IAAIE,EAAE,EAAE,KAAKC,EAAahB,GAASe,CAAC,EAAE,KAAK,CAAAE,MAAKA,EAAE,OAAOhB,CAAO;AAAA,IAAA;AAAA,EAEnH,GAAG,CAACD,GAASC,CAAO,CAAC,GACf,CAACiB,GAAUC,CAAW,IAAIC,EAAS,EAAK,GAC5C,CAACC,GAAQC,CAAS,IAAIF,EAAA,GAClB,CAACG,GAAMC,CAAO,IAAIJ,EAAS,EAAK,GAChCK,IAASd,EAAM,KAAK,CAAAI,MAAKA,EAAE,QAAQX,KAAUiB,EAAO,KAAKV,EAAM,CAAC,GAChEe,IAASxB,EAAS,SAAS,KAAK,OAAKyB,EAAE,YAAWF,KAAA,gBAAAA,EAAQ,OAAM,GAChEG,IAAa,CAAC,EAACF,KAAA,QAAAA,EAAQ,SAAQ,CAACA,EAAO,UAAU,CAACA,EAAO,iBAAiBA,EAAO,eAAezB,GAChG4B,IAAWzB,OAAWqB,KAAA,gBAAAA,EAAQ,OAAMG;AAuB1C,MAtBAE,EAAU,MAAM;AACd,IAAIvB,OAAuB,EAAI;AAAA,EACjC,GAAG,CAACA,CAAS,CAAC,GACduB,EAAU,MAAM;AACd,QAAI,CAACL,EAAQ;AACb,UAAMM,IAAQ,MAAM;;AAClB,YAAMC,KAAKC,IAAA9B,EAAO,YAAP,gBAAA8B,EAAgB;AAC3B,MAAKD,MACLR,EAAQU,EAASF,GAAIG,EAAgBV,CAAM,CAAC,IAAI,GAAG,GAC/CW,EAAeX,GAAQO,CAAE,KAAKJ,KAAc,CAACxB,KAC/CC,EAAOoB,EAAO,EAAE,GAChBN,EAAY,EAAI,KACP,CAACiB,EAAeX,GAAQO,CAAE,KAAKH,OAAiB,IAAI;AAAA,IACjE;AACA,IAAAE,EAAA;AACA,UAAMM,IAAQ,YAAYN,GAAO,GAAG;AACpC,WAAO,MAAM,cAAcM,CAAK;AAAA,EAClC,GAAG,CAACZ,GAAQG,GAAYxB,GAAQyB,GAAU1B,GAAQE,CAAM,CAAC,GACzDyB,EAAU,MAAM;AACd,IAAI1B,MAAUsB,KAAA,QAAAA,EAAQ,eAAc,CAACA,EAAO,iBAAiBA,EAAO,eAAezB,MACjFK,KAAA,QAAAA,EAAUoB,EAAO;AAAA,EACrB,GAAG,CAACtB,GAAQsB,KAAA,gBAAAA,EAAQ,YAAYA,KAAA,gBAAAA,EAAQ,eAAezB,GAASK,CAAO,CAAC,GACpE,CAACmB,EAAQ,QAAO;AACpB,QAAMa,IAAStB,EAAahB,GAASyB,CAAM,EAAE,MAAA,EAAQ,QAAA,GAC/CO,IAAKhC,EAAQ,OAAO,KAAK,OAAKiB,EAAE,QAAOS,KAAA,gBAAAA,EAAQ,WAAU,GACzDa,IAAcvC,EAAQ,OAAO,KAAK,OAAKiB,EAAE,QAAOS,KAAA,gBAAAA,EAAQ,cAAa,GACrEc,IAAQ,CAACzB,MAAkB;;AAC/B,IAAI,CAACa,KAAc,CAACL,MACpBlB,EAAOU,EAAE,EAAE,IACXkB,IAAA9B,EAAO,YAAP,QAAA8B,EAAgB,MAAMlB,EAAE,UAAU,CAAC0B,EAAe1B,CAAC;AAAA,EACrD;AACA,SACE,gBAAA2B,EAAC,SAAA,EAAM,WAAU,iBAAgB,cAAW,qBAC1C,UAAA;AAAA,IAAA,gBAAAA,EAAC,UAAA,EAAO,WAAU,mBAAkB,iBAAexB,GAAU,SAAS,MAAMC,EAAY,CAAAwB,MAAK,CAACA,CAAC,GAAG,UAAA;AAAA,MAAA;AAAA,MAC9E,gBAAAC,EAAC,QAAA,EAAM,UAAA1B,IAAW,MAAM,IAAA,CAAI;AAAA,IAAA,GAChD;AAAA,IACCA,KACC,gBAAAwB,EAAC,OAAA,EAAI,WAAU,iBACZ,UAAA;AAAA,MAAA/B,EAAM,SAAS,IACd,gBAAAiC;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,cAAW;AAAA,UACX,OAAOnB,EAAO;AAAA,UACd,UAAU,CAAC,CAACrB;AAAA,UACZ,UAAU,CAAAyC,MAAKvB,EAAUuB,EAAE,OAAO,KAAK;AAAA,UAEtC,UAAAlC,EAAM,IAAI,CAAAI,MACT,gBAAA6B,EAAC,UAAA,EAAkB,OAAO7B,EAAE,IACzB,UAAAA,EAAE,KAAA,GADQA,EAAE,EAEf,CACD;AAAA,QAAA;AAAA,MAAA,IAGH,gBAAA6B,EAAC,UAAA,EAAQ,UAAAnB,EAAO,KAAA,CAAK;AAAA,wBAEtB,KAAA,EAAE,MAAK,UACL,UAAAc,IAAc,iBAAiBA,EAAY,IAAI,KAAK,IAAGb,KAAA,gBAAAA,EAAQ,UAAS,SAAS,OAAMM,KAAA,gBAAAA,EAAI,SAAQ,GAAG,IACzG;AAAA,MACC5B,IACC,gBAAAwC,EAAC,KAAA,EAAE,UAAA,+BAAA,CAA4B,IAE/B,gBAAAF,EAAAI,GAAA,EACE,UAAA;AAAA,QAAA,gBAAAF,EAAC,UAAA,EAAO,UAAU,CAAClB,KAAUA,EAAO,QAAQ,SAAS,MAAMxB,EAAS,KAAKuB,EAAO,QAASxB,CAAQ,GAAG,UAAA,sBAEpG;AAAA,QACA,gBAAA2C,EAAC,UAAA,EAAO,UAAU,CAAChB,KAAc,CAACL,GAAM,SAAS,MAAMiB,EAAMf,CAAM,GAAG,UAAA,iBAAA,CAEtE;AAAA,QACC,CAACF,KAAQ,gBAAAqB,EAAC,SAAA,EAAM,UAAA,uCAAA,CAAoC;AAAA,MAAA,GACvD;AAAA,MAEDxC,uBACE,OAAA,EAAI,WAAU,mBAAkB,cAAW,qBACzC,UAAAkC,EAAO,IAAI,CAAArB,MACV,gBAAAyB;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,gBAAczB,EAAE,OAAOhB;AAAA,UACvB,UAAU,CAACyB,KAAUA,EAAO,UAAUT,EAAE,OAAOhB;AAAA,UAC/C,SAAS,MAAMC,EAAS,KAAKuB,EAAO,QAASR,EAAE,EAAE;AAAA,UAEhD,UAAA;AAAA,YAAAA,EAAE;AAAA,YAAK;AAAA,YAAIA,EAAE;AAAA,UAAA;AAAA,QAAA;AAAA,QALTA,EAAE;AAAA,MAAA,CAOV,GACH;AAAA,MAEDb,KACC,gBAAAsC,EAAAI,GAAA,EACE,UAAA;AAAA,QAAA,gBAAAJ,EAAC,UAAA,EAAO,gBAAcjC,GAAS,SAASC,GACrC,UAAA;AAAA,UAAAD,IAAU,mBAAmB;AAAA,UAAoB;AAAA,QAAA,GACpD;AAAA,QACCsC,EAAmBtB,CAAM,KACxB,gBAAAiB,EAAC,OAAA,EAAI,WAAU,yBACb,UAAA;AAAA,UAAA,gBAAAE,EAAC,UAAA,EAAO,SAAS,MAAA;;AAAM,oBAAAX,IAAA9B,EAAO,YAAP,gBAAA8B,EAAgB,OAAOe,EAAoBvB,CAAM;AAAA,aAAI,UAAA,iBAAA,CAAc;AAAA,UAC1F,gBAAAmB,EAAC,UAAA,EAAO,SAASpC,GAAQ,UAAA,OAAA,CAAI;AAAA,QAAA,EAAA,CAC/B;AAAA,MAAA,GAEJ;AAAA,MAEF,gBAAAkC,EAAC,OAAA,EAAI,WAAU,yBACb,UAAA;AAAA,QAAA,gBAAAE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,UAAU,CAAClB,KAAUA,EAAO,UAAUA,EAAO,eAAezB;AAAA,YAC5D,SAAS,MAAMC,EAAS,KAAKuB,EAAO,QAAS,EAACC,KAAA,QAAAA,EAAQ,KAAI;AAAA,YAEzD,UAAAA,KAAA,QAAAA,EAAQ,OAAO,gBAAgB;AAAA,UAAA;AAAA,QAAA;AAAA,QAEjCtB,KACC,gBAAAwC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,UAAU,CAACf;AAAA,YACX,SAAS,MAAM;;AACb,cAAAxB,EAAO,IAAI,IACX4B,IAAA9B,EAAO,YAAP,QAAA8B,EAAgB,MAAME,EAAgBV,CAAM;AAAA,YAC9C;AAAA,YACD,UAAA;AAAA,UAAA;AAAA,QAAA;AAAA,MAED,EAAA,CAEJ;AAAA,IAAA,EAAA,CACF;AAAA,EAAA,GAEJ;AAEJ;"}
@@ -0,0 +1,57 @@
1
+ import { jsx as i } from "react/jsx-runtime";
2
+ import { SquareDashed as a, BellRing as m, LogOut as d, BriefcaseMedical as f, FireExtinguisher as h, HeartPulse as w, Info as v, Footprints as S, CarFront as s, ArrowDownToLine as C, PersonStanding as P, ShieldAlert as x, Cpu as D, Siren as L, Lightbulb as R, Activity as q, Square as y, LandPlot as c, Building2 as u, SquareDashedBottom as A, Grid2X2 as B, Package as F, Container as M, MoveDownRight as b, MoveUpRight as I, ArrowUpRight as T, Camera as E, KeyRound as K, ScanLine as O, Fence as l, PanelTop as U, DoorOpen as j, MapPin as G } from "lucide-react";
3
+ import { useKerrosTheme as H } from "../theme/index.js";
4
+ function N({
5
+ kind: e,
6
+ size: o = 17,
7
+ symbol: r,
8
+ travel: p
9
+ }) {
10
+ var t;
11
+ const n = (t = H().icons) == null ? void 0 : t[e === "poi" && r ? r : e];
12
+ if (n)
13
+ return /* @__PURE__ */ i(n, { size: o });
14
+ const g = e === "boundary" ? a : e === "poi" ? {
15
+ personnel: P,
16
+ service: C,
17
+ driveway: s,
18
+ parking: s,
19
+ assembly: S,
20
+ info: v,
21
+ aed: w,
22
+ extinguisher: h,
23
+ firstaid: f,
24
+ exit: d,
25
+ firealarm: m
26
+ }[r ?? "personnel"] : {
27
+ door: j,
28
+ window: U,
29
+ gate: l,
30
+ fence: l,
31
+ wall: a,
32
+ turnstile: O,
33
+ reader: K,
34
+ camera: E,
35
+ elevator: T,
36
+ stairs: p === "down" ? b : I,
37
+ office: u,
38
+ container: M,
39
+ storage: F,
40
+ zone: c,
41
+ room: B,
42
+ enclose: A,
43
+ building: u,
44
+ parcel: c,
45
+ rectangle: y,
46
+ sensor: q,
47
+ light: R,
48
+ alarm: L,
49
+ equipment: D,
50
+ evacuation: x
51
+ }[e] ?? G;
52
+ return /* @__PURE__ */ i(g, { size: o, strokeWidth: 1.75 });
53
+ }
54
+ export {
55
+ N as EntityIcon
56
+ };
57
+ //# sourceMappingURL=Icons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Icons.js","sources":["../../../../src/components/Icons.tsx"],"sourcesContent":["import {\n Activity,\n Lightbulb,\n ArrowDownToLine,\n ArrowUpRight,\n BellRing,\n BriefcaseMedical,\n Building2,\n Camera,\n CarFront,\n Container,\n Cpu,\n DoorOpen,\n Fence,\n FireExtinguisher,\n Footprints,\n Grid2X2,\n HeartPulse,\n Info,\n KeyRound,\n LandPlot,\n LogOut,\n MapPin,\n MoveDownRight,\n MoveUpRight,\n Package,\n PanelTop,\n PersonStanding,\n ScanLine,\n ShieldAlert,\n Siren,\n Square,\n SquareDashed,\n SquareDashedBottom,\n} from 'lucide-react';\nimport type { ObjectKind, SiteObject, Tool } from '../model/types';\nimport { useKerrosTheme } from '../theme';\nexport function EntityIcon({\n kind,\n size = 17,\n symbol,\n travel,\n}: {\n kind: ObjectKind | Tool | 'wall' | 'fence';\n size?: number;\n symbol?: SiteObject['symbol'];\n /** An escalator's direction, so a descending one is not drawn with an arrow pointing up. */\n travel?: SiteObject['travel'];\n}) {\n const custom = useKerrosTheme().icons?.[kind === 'poi' && symbol ? symbol : kind];\n if (custom) {\n const Custom = custom;\n return <Custom size={size} />;\n }\n const Icon =\n kind === 'boundary'\n ? SquareDashed\n : kind === 'poi'\n ? {\n personnel: PersonStanding,\n service: ArrowDownToLine,\n driveway: CarFront,\n parking: CarFront,\n assembly: Footprints,\n info: Info,\n aed: HeartPulse,\n extinguisher: FireExtinguisher,\n firstaid: BriefcaseMedical,\n exit: LogOut,\n firealarm: BellRing,\n }[symbol ?? 'personnel']\n : ((\n {\n door: DoorOpen,\n window: PanelTop,\n gate: Fence,\n fence: Fence,\n wall: SquareDashed,\n turnstile: ScanLine,\n reader: KeyRound,\n camera: Camera,\n elevator: ArrowUpRight,\n stairs: travel === 'down' ? MoveDownRight : MoveUpRight,\n office: Building2,\n container: Container,\n storage: Package,\n zone: LandPlot,\n room: Grid2X2,\n enclose: SquareDashedBottom,\n building: Building2,\n parcel: LandPlot,\n rectangle: Square,\n sensor: Activity,\n light: Lightbulb,\n alarm: Siren,\n equipment: Cpu,\n evacuation: ShieldAlert,\n } as Record<string, typeof MapPin>\n )[kind] ?? MapPin);\n return <Icon size={size} strokeWidth={1.75} />;\n}\n"],"names":["EntityIcon","kind","size","symbol","travel","custom","_a","useKerrosTheme","jsx","Icon","SquareDashed","PersonStanding","ArrowDownToLine","CarFront","Footprints","Info","HeartPulse","FireExtinguisher","BriefcaseMedical","LogOut","BellRing","DoorOpen","PanelTop","Fence","ScanLine","KeyRound","Camera","ArrowUpRight","MoveDownRight","MoveUpRight","Building2","Container","Package","LandPlot","Grid2X2","SquareDashedBottom","Square","Activity","Lightbulb","Siren","Cpu","ShieldAlert","MapPin"],"mappings":";;;AAqCO,SAASA,EAAW;AAAA,EACzB,MAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,QAAAC;AAAA,EACA,QAAAC;AACF,GAMG;;AACD,QAAMC,KAASC,IAAAC,IAAiB,UAAjB,gBAAAD,EAAyBL,MAAS,SAASE,IAASA,IAASF;AAC5E,MAAII;AAEF,WAAO,gBAAAG,EADQH,KACA,MAAAH,GAAY;AAE7B,QAAMO,IACJR,MAAS,aACLS,IACAT,MAAS,QACP;AAAA,IACE,WAAWU;AAAA,IACX,SAASC;AAAA,IACT,UAAUC;AAAA,IACV,SAASA;AAAA,IACT,UAAUC;AAAA,IACV,MAAMC;AAAA,IACN,KAAKC;AAAA,IACL,cAAcC;AAAA,IACd,UAAUC;AAAA,IACV,MAAMC;AAAA,IACN,WAAWC;AAAA,EAAA,EACXjB,KAAU,WAAW,IAErB;AAAA,IACE,MAAMkB;AAAA,IACN,QAAQC;AAAA,IACR,MAAMC;AAAA,IACN,OAAOA;AAAA,IACP,MAAMb;AAAA,IACN,WAAWc;AAAA,IACX,QAAQC;AAAA,IACR,QAAQC;AAAA,IACR,UAAUC;AAAA,IACV,QAAQvB,MAAW,SAASwB,IAAgBC;AAAA,IAC5C,QAAQC;AAAA,IACR,WAAWC;AAAA,IACX,SAASC;AAAA,IACT,MAAMC;AAAA,IACN,MAAMC;AAAA,IACN,SAASC;AAAA,IACT,UAAUL;AAAA,IACV,QAAQG;AAAA,IACR,WAAWG;AAAA,IACX,QAAQC;AAAA,IACR,OAAOC;AAAA,IACP,OAAOC;AAAA,IACP,WAAWC;AAAA,IACX,YAAYC;AAAA,EAAA,EAEdxC,CAAI,KAAKyC;AACnB,SAAO,gBAAAlC,EAACC,GAAA,EAAK,MAAAP,GAAY,aAAa,KAAA,CAAM;AAC9C;"}