@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.
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 +58 -4
@@ -0,0 +1,22 @@
1
+ import type { Point } from '../schema';
2
+ import { type Wall } from './walls';
3
+ export interface ResolvedOpening {
4
+ kind: 'door' | 'window';
5
+ /** Along-axis centre and width, in the wall's own coordinate. */
6
+ centre: number;
7
+ width: number;
8
+ }
9
+ export interface GapResolution {
10
+ gap: [number, number];
11
+ openings: ResolvedOpening[];
12
+ /** A stretch with no wall at all — the barrier must be split around it. */
13
+ passage?: [number, number];
14
+ }
15
+ /** Envelope openings: door and window symbol clusters projected onto the wall. Door clusters win
16
+ * where the two overlap — a swing sweeps across the window symbols beside it. */
17
+ export declare function resolveEnvelopeOpenings(w: Wall, doorPts: Point[], windowPts: Point[]): ResolvedOpening[];
18
+ /** Partition gaps: the gap is the opening; symbols say the kind, and no symbol means a passage. */
19
+ export declare function resolvePartitionGap(w: Wall, gap: [number, number], doorPts: Point[], windowPts: Point[]): GapResolution;
20
+ /** The barrier spans a wall keeps once its passages are cut out of it. */
21
+ export declare function barrierSpans(w: Wall, passages: [number, number][]): [number, number][];
22
+ export declare const openingLabel: (w: Wall, o: ResolvedOpening) => string;
@@ -0,0 +1,22 @@
1
+ import type { Point, ProjectDocument } from '../schema';
2
+ import { type PlanEntity, type PlanImportOptions, type PlanImportReport } from './types';
3
+ /** Import a floor's worth of plan entities into `draft`. Call inside a transaction. */
4
+ export declare function importPlanEntities(draft: ProjectDocument, entities: PlanEntity[], options: PlanImportOptions): PlanImportReport;
5
+ /** Close an oblique doorway the Manhattan pass could not see.
6
+ *
7
+ * The reconstruction reads axis-aligned faces, which is what a Finnish prefab drawing is made of —
8
+ * except where it is not. A room cut off at 45° leaves two wall ends dangling a metre or so apart
9
+ * with nothing between them but the door symbol drawn across the gap, and every axis-aligned pass
10
+ * drops all three: the faces because they are oblique, the wall because it has no faces, the door
11
+ * because it has no wall. The region then leaks and two rooms import as one.
12
+ *
13
+ * What the drawing is actually saying there is legible without reading oblique geometry at all: two
14
+ * loose wall ends, a plausible door's distance apart, with door symbols standing on the line between
15
+ * them. That is a doorway, and this bridges it — a barrier on that line carrying the door.
16
+ *
17
+ * Deliberately conservative. It fires only between ends that nothing else has claimed, only when the
18
+ * span is a door's width, and only when the drawing put a door symbol there: it can close a gap the
19
+ * drawing shows a door in, and it cannot invent a wall anywhere else. */
20
+ export declare function bridgeDoorways(draft: ProjectDocument, floorId: string | null, doorPts: Point[], report: PlanImportReport): void;
21
+ export { VERTEX_LAYERS } from './types';
22
+ export type { PlanEntity, PlanImportOptions, PlanImportReport, PlanLayerMap } from './types';
@@ -0,0 +1,25 @@
1
+ import type { Point } from '../schema';
2
+ import type { PlanEntity } from './types';
3
+ import { type PlanLayerMap } from './types';
4
+ /** Every entity moved by (dx, dy). Sheets are registered before import, not after: the reconstruction
5
+ * snaps and welds as it goes, and moving the result would mean re-deciding all of it. */
6
+ export declare function shiftEntities(entities: PlanEntity[], dx: number, dy: number): PlanEntity[];
7
+ export interface Landmark {
8
+ centre: Point;
9
+ width: number;
10
+ height: number;
11
+ }
12
+ /** The blocks a layer's geometry falls into — a stair core on a plan, and nothing else on that layer.
13
+ * Single-link clustering: strokes of one stair touch, and two cores are metres apart. */
14
+ export declare function landmarks(entities: PlanEntity[], layer: RegExp): Landmark[];
15
+ /** The shift that puts `sheet` into `reference`'s frame, or null when they share no landmark.
16
+ *
17
+ * Matching is by SIZE: a stair core is a particular 1.87 x 2.05 m block and the one on the storey
18
+ * above is the same block, while a second core at the other end of the building is a different one.
19
+ * Two sheets whose stairs are the same size but in genuinely different places would register
20
+ * wrongly, so the answer is only offered when exactly one pairing is plausible — a registration
21
+ * that might be wrong is worse than none, because nothing downstream can tell.
22
+ *
23
+ * Returns null for a sheet with no stair drawn on it, which a cellar entered from outside will not
24
+ * have. There is nothing to match there and the caller must say where that storey goes. */
25
+ export declare function sheetOffset(reference: PlanEntity[], sheet: PlanEntity[], layers?: PlanLayerMap): Point | null;
@@ -0,0 +1,31 @@
1
+ import type { Point } from '../schema';
2
+ import type { PlanEntity } from './types';
3
+ export interface FaceSegment {
4
+ axis: 'h' | 'v';
5
+ c: number;
6
+ lo: number;
7
+ hi: number;
8
+ }
9
+ export interface Run extends FaceSegment {
10
+ /** Bridged gaps big enough to be openings, as [lo, hi] along the run. */
11
+ gaps: [number, number][];
12
+ }
13
+ export declare const EPS = 0.02;
14
+ /** Axis-aligned LINE/POLYLINE segments on a layer, as face segments. Oblique strokes are ignored —
15
+ * this importer reads Manhattan drawings. */
16
+ export declare function faceSegments(entities: PlanEntity[], layer: RegExp): FaceSegment[];
17
+ /** Merge collinear fragments into runs, bridging gaps up to `bridge` metres. Gaps in the opening
18
+ * size range are bridged but remembered — they are the doorways and windows. */
19
+ export declare function mergeRuns(segments: FaceSegment[], bridge: number, openingGaps?: [number, number]): Run[];
20
+ /** Every point a layer's geometry touches, sampled densely along strokes and arcs — the raw
21
+ * material for "is there a door/window symbol standing in this opening?" scoring. */
22
+ /** A symbol's own vertices, unsampled.
23
+ *
24
+ * symbolPoints walks every stroke at 20 cm so a door swing reads as a cloud standing in its
25
+ * opening, which is what finding a door needs. It is the wrong picture of a window: a window is
26
+ * drawn as a block at each jamb with the glass between them left empty, and the sampling fills that
27
+ * emptiness in at 20 cm intervals — so the one feature that says where a window begins and ends is
28
+ * the one thing sampling destroys. Where the shape of the symbol is the information, read the
29
+ * vertices. */
30
+ export declare function symbolVertices(entities: PlanEntity[], layer: RegExp): Point[];
31
+ export declare function symbolPoints(entities: PlanEntity[], layer: RegExp): Point[];
@@ -0,0 +1,33 @@
1
+ import type { AssetRepository } from '../model/types';
2
+ import { type ImportCheckpoint, type ImportBudget, type ImportPause } from './checkpoint';
3
+ import { type AiTokenUsage } from './usage';
4
+ export interface AiImportSession {
5
+ version: 1;
6
+ projectId: string;
7
+ sourceId: string;
8
+ sourceName: string;
9
+ sourceType: string;
10
+ instructions: string;
11
+ brief?: import('./brief').ImportBrief;
12
+ followUp: string;
13
+ tab?: 'setup' | 'analysis' | 'activity' | 'usage';
14
+ pendingInstructions?: import('./instructions').ImportInstruction[];
15
+ checkpoint?: ImportCheckpoint;
16
+ budget?: ImportBudget;
17
+ pause?: ImportPause;
18
+ messages: {
19
+ type: 'text' | 'tool' | 'user';
20
+ detail: string;
21
+ instructionId?: string;
22
+ }[];
23
+ phase: 'running' | 'done' | 'paused' | 'failed';
24
+ activity: string;
25
+ edits: number;
26
+ usage: AiTokenUsage;
27
+ hasUsage: boolean;
28
+ error: string;
29
+ }
30
+ /** Import state belongs to the host's asset store, alongside the original drawing. It is not
31
+ * another plan: all geometry lives in the normal project repository. */
32
+ export declare function loadAiImportSession(assets: AssetRepository, projectId: string): Promise<AiImportSession | null>;
33
+ export declare function saveAiImportSession(assets: AssetRepository, session: AiImportSession): Promise<void>;
@@ -0,0 +1,56 @@
1
+ import type { Point } from '../schema';
2
+ /** One normalized drawing entity, coordinates in metres. The shape scripts/plan-import/extract.mjs
3
+ * emits with `--expand --units m`; hosts producing entities elsewhere target this. */
4
+ export interface PlanEntity {
5
+ type: 'LINE' | 'POLYLINE' | 'ARC' | 'CIRCLE' | 'TEXT' | 'INSERT' | 'DIMENSION' | 'POINT';
6
+ layer: string;
7
+ a?: Point;
8
+ b?: Point;
9
+ points?: Point[];
10
+ closed?: boolean;
11
+ center?: Point;
12
+ r?: number;
13
+ start?: number;
14
+ end?: number;
15
+ at?: Point;
16
+ text?: string;
17
+ h?: number;
18
+ block?: string;
19
+ rotation?: number;
20
+ }
21
+ /** Which layers carry what. Defaults are the Vertex-style numbered taxonomy; override per source. */
22
+ export interface PlanLayerMap {
23
+ /** Outside face of the building envelope. */
24
+ exteriorFace: RegExp;
25
+ /** Inside face of the envelope — also the outline the interior plate is traced from. */
26
+ interiorFace: RegExp;
27
+ /** Interior wall face layers; each wall is a pair of parallel runs within these. */
28
+ partitionFaces: RegExp;
29
+ /** Door symbol geometry (leaves, swings). Decides whether a wall gap is a doorway. */
30
+ doors: RegExp;
31
+ /** Window symbol geometry. Decides whether a wall gap is a window. */
32
+ windows: RegExp;
33
+ /** Room label texts. Area figures (pure numbers) are ignored automatically. */
34
+ labels: RegExp;
35
+ /** Stair treads. Optional: a sheet with no stair on it simply has none, which is a fact about the
36
+ * building and not a failure. Where it is drawn, the symbol's extent is the flight's footprint. */
37
+ stairs?: RegExp;
38
+ }
39
+ export declare const VERTEX_LAYERS: PlanLayerMap;
40
+ export interface PlanImportOptions {
41
+ floorId: string | null;
42
+ layers?: PlanLayerMap;
43
+ }
44
+ export interface PlanImportReport {
45
+ walls: number;
46
+ /** Flights of stairs read off the drawing. */
47
+ stairs: number;
48
+ rooms: number;
49
+ doors: number;
50
+ windows: number;
51
+ /** Doorless openings — stretches where the wall was split rather than sealed. */
52
+ passages: number;
53
+ named: number;
54
+ /** Things the drawing suggested but the import declined, each with the reason. */
55
+ skipped: string[];
56
+ }
@@ -0,0 +1,10 @@
1
+ /** Disjoint provider-reported token counts. Input excludes cache reads and writes. */
2
+ export interface AiTokenUsage {
3
+ inputTokens: number;
4
+ outputTokens: number;
5
+ cacheReadTokens: number;
6
+ cacheWriteTokens: number;
7
+ }
8
+ export declare const emptyTokenUsage: () => AiTokenUsage;
9
+ export declare function addTokenUsage(a: AiTokenUsage, b: AiTokenUsage): AiTokenUsage;
10
+ export declare function readTokenUsage(value: unknown): AiTokenUsage;
@@ -0,0 +1,37 @@
1
+ import type { Point } from '../schema';
2
+ import type { Run } from './runs';
3
+ export interface Wall {
4
+ axis: 'h' | 'v';
5
+ c: number;
6
+ lo: number;
7
+ hi: number;
8
+ thickness: number;
9
+ gaps: [number, number][];
10
+ }
11
+ /** Pair opposing face runs into walls: same axis, cross-distance within a wall thickness, intervals
12
+ * overlapping. The wall sits on the centreline. `gapMode` decides what counts as an opening: for
13
+ * partitions both faces must break ('both'); for the envelope the silhouette line is often drawn
14
+ * continuous, so a break in either face counts ('either'). */
15
+ export declare function pairWalls(a: Run[], b: Run[], minT: number, maxT: number, minOverlap: number, gapMode?: 'both' | 'either',
16
+ /** Wall extent from the pair: 'union' for the envelope (its faces fragment unevenly and corners
17
+ * are closed afterwards); 'overlap' for partitions — a wall exists only where BOTH faces do,
18
+ * and taking the union would stretch it over stretches where a lone line means something else. */
19
+ extentMode?: 'union' | 'overlap'): Wall[];
20
+ export declare const wallEnds: (w: Wall) => [Point, Point];
21
+ export declare const along: (w: Wall, t: number) => Point;
22
+ /** Merge an opening gap into a wall, unioning with any gap it overlaps — both faces usually report
23
+ * the same opening at slightly different extents, and it must become ONE opening. */
24
+ export declare function addGap(w: Wall, gap: [number, number]): void;
25
+ /** Snap wall ends onto the centreline of the perpendicular wall they meet. CAD face lines are
26
+ * drawn to the crossing wall's far face — or stop at its near one — so raw run extents overshoot
27
+ * or undershoot T-junctions by half a thickness. Landing exactly on the centreline is what a
28
+ * hand-drawn wall does in the editor, and it is what lets rendered caps disappear inside the
29
+ * crossing wall instead of poking past it. */
30
+ export declare function snapEnds(walls: Wall[], targets: Wall[], tolerance?: number): void;
31
+ /** Extend each envelope wall to the centreline of its perpendicular neighbours, closing corners. */
32
+ export declare function closeCorners(envelope: Wall[]): void;
33
+ /** Chain envelope walls into the closed inner-face ring. Each corner is the intersection of two
34
+ * adjacent walls' INNER faces (centreline offset half a thickness toward the building), so the
35
+ * plate is the actual floor area, not the wall footprint. Handles L and T footprints; returns
36
+ * null when the walls do not close into one loop. */
37
+ export declare function traceRing(envelope: Wall[]): Point[] | null;
@@ -0,0 +1,18 @@
1
+ import * as THREE from 'three';
2
+ /** Private cabin finishes: their lighting environment is the ceiling diffuser, even in a dark
3
+ * basement. Metals reflect this environment; the cabin walls do not glow like the old grey box. */
4
+ export declare class CabinMaterials {
5
+ readonly steel: THREE.MeshPhysicalMaterial;
6
+ readonly trim: THREE.MeshStandardMaterial;
7
+ readonly wall: THREE.MeshStandardMaterial;
8
+ readonly floor: THREE.MeshStandardMaterial;
9
+ readonly dark: THREE.MeshStandardMaterial;
10
+ readonly lamp: THREE.MeshBasicMaterial;
11
+ readonly display: THREE.MeshBasicMaterial;
12
+ readonly environment: THREE.Texture;
13
+ private target;
14
+ private textures;
15
+ private owned;
16
+ constructor(renderer: THREE.WebGLRenderer);
17
+ dispose(): void;
18
+ }
@@ -0,0 +1,13 @@
1
+ import * as THREE from 'three';
2
+ import { Reflector } from 'three/addons/objects/Reflector.js';
3
+ /** The head is visible in the mirror, but never surrounds the first-person camera. */
4
+ export declare const REFLECTION_BODY = 29;
5
+ /** MapLibre's camera encodes rotation in its projection matrix. Give the mirror a conventional
6
+ * view frame while preserving the exact world-to-clip mapping, including the chosen POV lens. */
7
+ export declare function mirrorViewCamera(source: THREE.Camera, target: THREE.PerspectiveCamera): void;
8
+ /** One live planar reflection, rendered only near a visible cabin. No recursive mirror passes. */
9
+ export declare class CabinMirror extends Reflector {
10
+ private view;
11
+ private frames;
12
+ constructor(width: number, height: number);
13
+ }
@@ -0,0 +1,11 @@
1
+ import * as THREE from 'three';
2
+ import type { SiteObject } from '../model/types';
3
+ import type { MaterialLibrary } from './materials';
4
+ /** Local metres: X along the opening, Y toward side A, Z up. Hardware moves with its leaf. */
5
+ export declare function makeDoor(door: SiteObject, wallDepth: number, height: number, materials: MaterialLibrary): {
6
+ frame: THREE.Group<THREE.Object3DEventMap>;
7
+ panels: {
8
+ group: THREE.Group;
9
+ setOpen: (value: number) => void;
10
+ }[];
11
+ };
@@ -0,0 +1,20 @@
1
+ import * as THREE from 'three';
2
+ import type { SiteObject } from '../model/types';
3
+ import type { CabinMaterials } from './CabinMaterials';
4
+ export declare const FACE_TURN: {
5
+ front: number;
6
+ right: number;
7
+ back: number;
8
+ left: number;
9
+ };
10
+ export declare function makeElevatorCabin(o: SiteObject, height: number, finish: CabinMaterials, floorCode: string, moving: boolean): THREE.Group<THREE.Object3DEventMap>;
11
+ /** The visible portion of a leaf as it retracts behind the jamb. Clipping at the opening keeps
12
+ * the concealed leaf inside its pocket even on shafts narrower than a full exposed door travel. */
13
+ export declare function doorLeafSlice(gap: number, sign: number, progress: number): {
14
+ width: number;
15
+ center: number;
16
+ };
17
+ export declare function makeCabinDoor(gap: number, height: number, sign: number, finish: CabinMaterials): {
18
+ group: THREE.Group<THREE.Object3DEventMap>;
19
+ update: (progress: number) => void;
20
+ };
@@ -0,0 +1,35 @@
1
+ import * as THREE from 'three';
2
+ import type { Point, SiteObject } from '../model/types';
3
+ import type { MaterialLibrary } from './materials';
4
+ /** Occasional ballast dropouts, not a regular strobe. Stable per fixture and elapsed time. */
5
+ export declare function fixtureOutput(id: string, seconds: number, flicker?: number): number;
6
+ export declare const MAX_FIXTURE_LIGHTS = 4;
7
+ /** How many of those throw shadows. A shadowed lamp is six shadow passes when it moves and a cube
8
+ * of shadow taps on every pixel every frame; the two nearest carry the room, and the two beyond
9
+ * them light without shadow, which nobody notices past the first two. The count is held constant
10
+ * — an empty slot keeps its flag — because the shader is compiled for a number of shadowed lights
11
+ * and changing that number recompiles every material in the scene. */
12
+ export declare const SHADOWED_FIXTURE_LIGHTS = 2;
13
+ /** All fittings are two instanced draws. Only the nearest few cast light/shadows, keeping the
14
+ * shader and shadow-map budget constant whether the document contains ten lamps or ten thousand. */
15
+ export declare class FixtureLights {
16
+ private fixtures;
17
+ private points;
18
+ private colors;
19
+ private emitters;
20
+ private lights;
21
+ private active;
22
+ private lastFlicker;
23
+ private flickering;
24
+ constructor(scene: THREE.Scene, fixtures: SiteObject[], xy: (p: Point) => Point, base: number, materials: MaterialLibrary);
25
+ /** The shadows go to the nearest lamps, and stay with them until a lamp without one is clearly
26
+ * nearer — a swap redraws a shadow, so a walker straddling two lamps must not swap on every step.
27
+ * Always exactly SHADOWED_FIXTURE_LIGHTS flags are set, empty slots included: see the constant. */
28
+ private assignShadows;
29
+ /** Every lamp's shadow is stale — the scene changed under them. */
30
+ invalidate(): void;
31
+ update(eye: THREE.Vector3, seconds: number): {
32
+ shadowsChanged: boolean;
33
+ animate: boolean;
34
+ };
35
+ }
@@ -0,0 +1,87 @@
1
+ import type { Map as GLMap } from 'maplibre-gl';
2
+ import { type AssetRepository, type Point, type ProjectDocument, type Tool } from '../model/types';
3
+ import type { StatusReading } from '../model/live';
4
+ import type { BasemapConfig, ElevatorControls } from '../model/host';
5
+ import { type Sun } from './lighting';
6
+ import type { Route } from '../model/navigation';
7
+ import { type WalkAvatar } from './walk';
8
+ export interface MapCanvasProps {
9
+ project: ProjectDocument;
10
+ canEdit: boolean;
11
+ floorId: string | null;
12
+ selected: string | null;
13
+ tool: Tool;
14
+ draft: Point[];
15
+ hover: Point | null;
16
+ /** Alignment hints drawn under the draft: the axis a wall is being held to, or a whole segment
17
+ * the tool is offering. Both are previews — nothing here exists in the document yet. */
18
+ guides?: {
19
+ line: [Point, Point];
20
+ role: 'guide' | 'proposal';
21
+ }[];
22
+ threeD: boolean;
23
+ stack: boolean;
24
+ coverage: boolean;
25
+ showLabels: boolean;
26
+ showPlan: boolean;
27
+ /** Where the sun stands over this project now. Carries its own `evening` for the dusk look. */
28
+ sun: Sun;
29
+ dark: boolean;
30
+ cityBuildings: boolean;
31
+ cadastre: boolean;
32
+ basemap?: BasemapConfig;
33
+ assets: AssetRepository;
34
+ statuses: Map<string, StatusReading>;
35
+ elevators?: ElevatorControls;
36
+ /** Draw the soil section around below-grade floors. */
37
+ excavation?: boolean;
38
+ /** First-person walk mode: the camera becomes a person standing on `floorId`. Requires threeD.
39
+ * While it is on the map's own gestures are off and the floor is drawn at ground level. */
40
+ walk?: boolean;
41
+ /** Walk mode wants out (Escape). */
42
+ onWalkExit?: () => void;
43
+ /** Where the walker last stood, or was dropped — the person, kept apart from the camera. Drawn on
44
+ * its floor in the other modes, and a walk resumes from it when it is in view. */
45
+ avatar?: WalkAvatar | null;
46
+ /** The walker moved. Throttled to a few times a second, and once more on leaving the walk. */
47
+ onAvatar?: (avatar: WalkAvatar) => void;
48
+ /** The person marker was dropped on the map, or the avatar clicked: walk from here. */
49
+ onWalkAt?: (avatar: WalkAvatar) => void;
50
+ focusId?: string | null;
51
+ alignment?: {
52
+ image: Point[];
53
+ map: Point[];
54
+ };
55
+ /** Exact camera to restore (deep links); suppresses the automatic fit and 3D tilt-in on load. */
56
+ initialCamera?: {
57
+ center: [number, number];
58
+ zoom: number;
59
+ bearing: number;
60
+ pitch: number;
61
+ };
62
+ route?: Route | null;
63
+ activeStep?: number | null;
64
+ playing?: boolean;
65
+ onJourneyStep?: (index: number) => void;
66
+ onJourneyEnd?: () => void;
67
+ onRequestFloor?: (floorId: string | null) => void;
68
+ onClick: (point: Point, entityId: string | null) => void;
69
+ onHover: (point: Point, tolerance: number) => void;
70
+ onAdopt?: (adopted: {
71
+ rings: Point[][];
72
+ sourceId: string | number;
73
+ storeys: number;
74
+ name: string;
75
+ }) => void;
76
+ onSelect: (id: string) => void;
77
+ onHoverObject?: (id: string | null) => void;
78
+ /** Lightweight snapped preview. Model validation runs on release, before committing the drop. */
79
+ onVertexPreview?: (kind: 'junction' | 'barrier' | 'ring', id: string, point: Point, ring?: number, vertex?: number, free?: boolean) => Point;
80
+ snapping?: boolean;
81
+ onVertexMove(kind: 'junction' | 'ring' | 'object' | 'barrier' | 'node' | 'opening' | 'rotate' | 'coverage', id: string, point: Point, ring?: number, vertex?: number,
82
+ /** Shift was held on release: take the drop exactly as given, ignoring any snapping. */
83
+ free?: boolean): void;
84
+ onError: (message: string) => void;
85
+ onReady?: (map: GLMap) => void;
86
+ }
87
+ export declare function MapCanvas(props: MapCanvasProps): import("react").JSX.Element;
@@ -0,0 +1,18 @@
1
+ import * as THREE from 'three';
2
+ /** A small articulated passenger: tailored jacket, trousers, shoes and a recognisable face.
3
+ * The view uses the lower body; reflections include the head and shoulders. All motion follows
4
+ * the actual walker, so a mirror shows a passenger at the correct location, not a painted figure. */
5
+ export declare class Passenger extends THREE.Group {
6
+ private head;
7
+ private arms;
8
+ private elbows;
9
+ private legs;
10
+ private knees;
11
+ private previous?;
12
+ private phase;
13
+ private yaw?;
14
+ private waveUntil;
15
+ constructor(environment: THREE.Texture);
16
+ wave(now: number): void;
17
+ update(eye: THREE.Vector3, forward: THREE.Vector3, seconds: number, dt: number): boolean;
18
+ }