@kerros/viewer 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 (264) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -2
  3. package/dist/adapters/basemap.js +11 -0
  4. package/dist/adapters/basemap.js.map +1 -0
  5. package/dist/adapters/persistence.js +121 -0
  6. package/dist/adapters/persistence.js.map +1 -0
  7. package/dist/adapters/status.js +18 -0
  8. package/dist/adapters/status.js.map +1 -0
  9. package/dist/components/ElevatorPanel.js +120 -0
  10. package/dist/components/ElevatorPanel.js.map +1 -0
  11. package/dist/components/Icons.js +57 -0
  12. package/dist/components/Icons.js.map +1 -0
  13. package/dist/components/Inspector.js +1184 -0
  14. package/dist/components/Inspector.js.map +1 -0
  15. package/dist/components/NavigatePanel.js +301 -0
  16. package/dist/components/NavigatePanel.js.map +1 -0
  17. package/dist/components/NavigationGraph.js +234 -0
  18. package/dist/components/NavigationGraph.js.map +1 -0
  19. package/dist/components/StructureExplorer.js +510 -0
  20. package/dist/components/StructureExplorer.js.map +1 -0
  21. package/dist/components/StructureView.js +286 -0
  22. package/dist/components/StructureView.js.map +1 -0
  23. package/dist/components/controls.js +170 -0
  24. package/dist/components/controls.js.map +1 -0
  25. package/dist/components/graphLayout.js +27 -0
  26. package/dist/components/graphLayout.js.map +1 -0
  27. package/dist/host.js +169 -0
  28. package/dist/host.js.map +1 -0
  29. package/dist/i18n.js +88 -0
  30. package/dist/i18n.js.map +1 -0
  31. package/dist/index.js +171 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/map/CabinMaterials.js +81 -0
  34. package/dist/map/CabinMaterials.js.map +1 -0
  35. package/dist/map/CabinMirror.js +43 -0
  36. package/dist/map/CabinMirror.js.map +1 -0
  37. package/dist/map/Doors.js +80 -0
  38. package/dist/map/Doors.js.map +1 -0
  39. package/dist/map/ElevatorCabin.js +93 -0
  40. package/dist/map/ElevatorCabin.js.map +1 -0
  41. package/dist/map/FixtureLights.js +117 -0
  42. package/dist/map/FixtureLights.js.map +1 -0
  43. package/dist/map/MapCanvas.js +2161 -0
  44. package/dist/map/MapCanvas.js.map +1 -0
  45. package/dist/map/Passenger.js +69 -0
  46. package/dist/map/Passenger.js.map +1 -0
  47. package/dist/map/SceneLayer.js +1534 -0
  48. package/dist/map/SceneLayer.js.map +1 -0
  49. package/dist/map/UndergroundContext.js +153 -0
  50. package/dist/map/UndergroundContext.js.map +1 -0
  51. package/dist/map/ambience.js +194 -0
  52. package/dist/map/ambience.js.map +1 -0
  53. package/dist/map/architecture.js +305 -0
  54. package/dist/map/architecture.js.map +1 -0
  55. package/dist/map/bathMusic.js +92 -0
  56. package/dist/map/bathMusic.js.map +1 -0
  57. package/dist/map/cameraAim.js +33 -0
  58. package/dist/map/cameraAim.js.map +1 -0
  59. package/dist/map/elevators.js +56 -0
  60. package/dist/map/elevators.js.map +1 -0
  61. package/dist/map/excavation.js +52 -0
  62. package/dist/map/excavation.js.map +1 -0
  63. package/dist/map/exteriors.js +25 -0
  64. package/dist/map/exteriors.js.map +1 -0
  65. package/dist/map/features.js +218 -0
  66. package/dist/map/features.js.map +1 -0
  67. package/dist/map/fences.js +29 -0
  68. package/dist/map/fences.js.map +1 -0
  69. package/dist/map/journey.js +112 -0
  70. package/dist/map/journey.js.map +1 -0
  71. package/dist/map/levels.js +6 -0
  72. package/dist/map/levels.js.map +1 -0
  73. package/dist/map/lighting.js +142 -0
  74. package/dist/map/lighting.js.map +1 -0
  75. package/dist/map/loadBasemap.js +26 -0
  76. package/dist/map/loadBasemap.js.map +1 -0
  77. package/dist/map/materials.js +183 -0
  78. package/dist/map/materials.js.map +1 -0
  79. package/dist/map/poolLighting.js +39 -0
  80. package/dist/map/poolLighting.js.map +1 -0
  81. package/dist/map/projection.js +24 -0
  82. package/dist/map/projection.js.map +1 -0
  83. package/dist/map/rampGeometry.js +38 -0
  84. package/dist/map/rampGeometry.js.map +1 -0
  85. package/dist/map/route.js +107 -0
  86. package/dist/map/route.js.map +1 -0
  87. package/dist/map/stairSurfaces.js +115 -0
  88. package/dist/map/stairSurfaces.js.map +1 -0
  89. package/dist/map/surfaces.js +136 -0
  90. package/dist/map/surfaces.js.map +1 -0
  91. package/dist/map/textures.js +95 -0
  92. package/dist/map/textures.js.map +1 -0
  93. package/dist/map/underground.js +34 -0
  94. package/dist/map/underground.js.map +1 -0
  95. package/dist/map/walk.js +433 -0
  96. package/dist/map/walk.js.map +1 -0
  97. package/dist/map/walkContext.js +46 -0
  98. package/dist/map/walkContext.js.map +1 -0
  99. package/dist/map/walkDimensions.js +7 -0
  100. package/dist/map/walkDimensions.js.map +1 -0
  101. package/dist/map/walkJourney.js +85 -0
  102. package/dist/map/walkJourney.js.map +1 -0
  103. package/dist/map/walkSurfaces.js +106 -0
  104. package/dist/map/walkSurfaces.js.map +1 -0
  105. package/dist/map/wallJoins.js +70 -0
  106. package/dist/map/wallJoins.js.map +1 -0
  107. package/dist/map/water.js +274 -0
  108. package/dist/map/water.js.map +1 -0
  109. package/dist/model/authoring.js +80 -0
  110. package/dist/model/authoring.js.map +1 -0
  111. package/dist/model/boundaries.js +548 -0
  112. package/dist/model/boundaries.js.map +1 -0
  113. package/dist/model/coverage.js +30 -0
  114. package/dist/model/coverage.js.map +1 -0
  115. package/dist/model/document.js +52 -0
  116. package/dist/model/document.js.map +1 -0
  117. package/dist/model/doors.js +47 -0
  118. package/dist/model/doors.js.map +1 -0
  119. package/dist/model/factory.js +56 -0
  120. package/dist/model/factory.js.map +1 -0
  121. package/dist/model/geometry.js +394 -0
  122. package/dist/model/geometry.js.map +1 -0
  123. package/dist/model/inference.js +182 -0
  124. package/dist/model/inference.js.map +1 -0
  125. package/dist/model/materials.js +11 -0
  126. package/dist/model/materials.js.map +1 -0
  127. package/dist/model/mutations.js +157 -0
  128. package/dist/model/mutations.js.map +1 -0
  129. package/dist/model/navigation.js +275 -0
  130. package/dist/model/navigation.js.map +1 -0
  131. package/dist/model/ontology.js +109 -0
  132. package/dist/model/ontology.js.map +1 -0
  133. package/dist/model/passages.js +5 -0
  134. package/dist/model/passages.js.map +1 -0
  135. package/dist/model/portals.js +42 -0
  136. package/dist/model/portals.js.map +1 -0
  137. package/dist/model/precision.js +11 -0
  138. package/dist/model/precision.js.map +1 -0
  139. package/dist/model/project.js +17 -0
  140. package/dist/model/project.js.map +1 -0
  141. package/dist/model/ramps.js +10 -0
  142. package/dist/model/ramps.js.map +1 -0
  143. package/dist/model/roomNavigation.js +87 -0
  144. package/dist/model/roomNavigation.js.map +1 -0
  145. package/dist/model/routeClearance.js +72 -0
  146. package/dist/model/routeClearance.js.map +1 -0
  147. package/dist/model/spaces.js +104 -0
  148. package/dist/model/spaces.js.map +1 -0
  149. package/dist/model/stairGeometry.js +40 -0
  150. package/dist/model/stairGeometry.js.map +1 -0
  151. package/dist/model/stairTraversal.js +48 -0
  152. package/dist/model/stairTraversal.js.map +1 -0
  153. package/dist/model/topology.js +63 -0
  154. package/dist/model/topology.js.map +1 -0
  155. package/dist/model/types.js +35 -0
  156. package/dist/model/types.js.map +1 -0
  157. package/dist/model/validate.js +240 -0
  158. package/dist/model/validate.js.map +1 -0
  159. package/dist/model/vertical.js +129 -0
  160. package/dist/model/vertical.js.map +1 -0
  161. package/dist/model/walls.js +71 -0
  162. package/dist/model/walls.js.map +1 -0
  163. package/dist/styles.css +4931 -0
  164. package/dist/theme/index.js +34 -0
  165. package/dist/theme/index.js.map +1 -0
  166. package/dist/types/adapters/basemap.d.ts +2 -0
  167. package/dist/types/adapters/persistence.d.ts +29 -0
  168. package/dist/types/adapters/status.d.ts +4 -0
  169. package/dist/types/components/ElevatorPanel.d.ts +18 -0
  170. package/dist/types/components/Icons.d.ts +8 -0
  171. package/dist/types/components/Inspector.d.ts +38 -0
  172. package/dist/types/components/NavigatePanel.d.ts +27 -0
  173. package/dist/types/components/NavigationGraph.d.ts +10 -0
  174. package/dist/types/components/StructureExplorer.d.ts +8 -0
  175. package/dist/types/components/StructureView.d.ts +22 -0
  176. package/dist/types/components/controls.d.ts +52 -0
  177. package/dist/types/components/graphLayout.d.ts +9 -0
  178. package/dist/types/i18n.d.ts +85 -0
  179. package/dist/types/import/analysisPreview.d.ts +27 -0
  180. package/dist/types/import/brief.d.ts +22 -0
  181. package/dist/types/import/checkpoint.d.ts +49 -0
  182. package/dist/types/import/instructions.d.ts +7 -0
  183. package/dist/types/import/usage.d.ts +10 -0
  184. package/dist/types/map/CabinMaterials.d.ts +18 -0
  185. package/dist/types/map/CabinMirror.d.ts +13 -0
  186. package/dist/types/map/Doors.d.ts +11 -0
  187. package/dist/types/map/ElevatorCabin.d.ts +20 -0
  188. package/dist/types/map/FixtureLights.d.ts +35 -0
  189. package/dist/types/map/MapCanvas.d.ts +87 -0
  190. package/dist/types/map/Passenger.d.ts +18 -0
  191. package/dist/types/map/SceneLayer.d.ts +306 -0
  192. package/dist/types/map/UndergroundContext.d.ts +18 -0
  193. package/dist/types/map/ambience.d.ts +29 -0
  194. package/dist/types/map/architecture.d.ts +8 -0
  195. package/dist/types/map/bathMusic.d.ts +14 -0
  196. package/dist/types/map/cameraAim.d.ts +20 -0
  197. package/dist/types/map/elevators.d.ts +16 -0
  198. package/dist/types/map/excavation.d.ts +9 -0
  199. package/dist/types/map/exteriors.d.ts +3 -0
  200. package/dist/types/map/features.d.ts +33 -0
  201. package/dist/types/map/fences.d.ts +4 -0
  202. package/dist/types/map/journey.d.ts +36 -0
  203. package/dist/types/map/levels.d.ts +4 -0
  204. package/dist/types/map/lighting.d.ts +103 -0
  205. package/dist/types/map/loadBasemap.d.ts +4 -0
  206. package/dist/types/map/materials.d.ts +38 -0
  207. package/dist/types/map/poolLighting.d.ts +11 -0
  208. package/dist/types/map/projection.d.ts +9 -0
  209. package/dist/types/map/rampGeometry.d.ts +8 -0
  210. package/dist/types/map/route.d.ts +59 -0
  211. package/dist/types/map/stairSurfaces.d.ts +29 -0
  212. package/dist/types/map/surfaces.d.ts +36 -0
  213. package/dist/types/map/textures.d.ts +8 -0
  214. package/dist/types/map/underground.d.ts +30 -0
  215. package/dist/types/map/walk.d.ts +232 -0
  216. package/dist/types/map/walkContext.d.ts +11 -0
  217. package/dist/types/map/walkDimensions.d.ts +5 -0
  218. package/dist/types/map/walkJourney.d.ts +33 -0
  219. package/dist/types/map/walkSurfaces.d.ts +27 -0
  220. package/dist/types/map/wallJoins.d.ts +6 -0
  221. package/dist/types/map/water.d.ts +12 -0
  222. package/dist/types/model/authoring.d.ts +38 -0
  223. package/dist/types/model/boundaries.d.ts +41 -0
  224. package/dist/types/model/coverage.d.ts +8 -0
  225. package/dist/types/model/document.d.ts +9 -0
  226. package/dist/types/model/doors.d.ts +19 -0
  227. package/dist/types/model/factory.d.ts +5 -0
  228. package/dist/types/model/geometry.d.ts +99 -0
  229. package/dist/types/model/host.d.ts +154 -0
  230. package/dist/types/model/inference.d.ts +46 -0
  231. package/dist/types/model/live.d.ts +60 -0
  232. package/dist/types/model/materials.d.ts +28 -0
  233. package/dist/types/model/mutations.d.ts +178 -0
  234. package/dist/types/model/navigation.d.ts +70 -0
  235. package/dist/types/model/ontology.d.ts +43 -0
  236. package/dist/types/model/passages.d.ts +2 -0
  237. package/dist/types/model/portals.d.ts +9 -0
  238. package/dist/types/model/precision.d.ts +11 -0
  239. package/dist/types/model/project.d.ts +8 -0
  240. package/dist/types/model/ramps.d.ts +7 -0
  241. package/dist/types/model/roomNavigation.d.ts +15 -0
  242. package/dist/types/model/routeClearance.d.ts +11 -0
  243. package/dist/types/model/spaces.d.ts +46 -0
  244. package/dist/types/model/stairGeometry.d.ts +27 -0
  245. package/dist/types/model/stairTraversal.d.ts +8 -0
  246. package/dist/types/model/topology.d.ts +14 -0
  247. package/dist/types/model/types.d.ts +369 -0
  248. package/dist/types/model/validate.d.ts +38 -0
  249. package/dist/types/model/vertical.d.ts +145 -0
  250. package/dist/types/model/walls.d.ts +71 -0
  251. package/dist/types/schema/index.d.ts +25 -0
  252. package/dist/types/theme/index.d.ts +55 -0
  253. package/dist/types/viewer/FloorViewer.d.ts +76 -0
  254. package/dist/types/viewer/ViewerWorkspace.d.ts +2 -0
  255. package/dist/types/viewer/host.d.ts +11 -0
  256. package/dist/types/viewer/index.d.ts +2 -0
  257. package/dist/types/viewer/panels.d.ts +12 -0
  258. package/dist/viewer/FloorViewer.js +104 -0
  259. package/dist/viewer/FloorViewer.js.map +1 -0
  260. package/dist/viewer/ViewerWorkspace.js +370 -0
  261. package/dist/viewer/ViewerWorkspace.js.map +1 -0
  262. package/dist/viewer/panels.js +35 -0
  263. package/dist/viewer/panels.js.map +1 -0
  264. package/package.json +52 -4
@@ -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
+ }
@@ -0,0 +1,306 @@
1
+ import { type CustomLayerInterface, type Map as MapLibreMap, type CustomRenderMethodInput } from 'maplibre-gl';
2
+ import type { Floor, Point, ProjectDocument, Ring, SiteObject } from '../model/types';
3
+ import type { Route } from '../model/navigation';
4
+ import { type VoidOptions } from '../model/vertical';
5
+ import type { StatusReading } from '../model/live';
6
+ import type { MapStyleOptions } from '../theme';
7
+ import { type UndergroundView } from './underground';
8
+ import { type Sun } from './lighting';
9
+ export { rampJoins } from '../model/ramps';
10
+ export { rampVoids } from './rampGeometry';
11
+ export declare const nestingLift: (area: number) => number;
12
+ export { LIFT, SLAB } from './levels';
13
+ /** How far an absolutely-placed piece of geometry has to move to join the rest of the scene.
14
+ *
15
+ * Geometry arrives in two coordinate systems. Most of it is placed relative to the level in focus,
16
+ * which is what lets a cutaway sit on the map and a walk stand on the map's own ground plane. The
17
+ * rest carries the elevation the document authored: a ramp's slope, the parcel and the fences out
18
+ * of doors, the excavation and its cage. Nothing reconciled the two, so walking a P1 deck put the
19
+ * ramps 12.6 m under the walker and left the pavement level with a fifth-floor shop. This is the
20
+ * one number that carries an authored elevation into the frame everything else is drawn in. The
21
+ * stacked view is already drawn at authored elevations, so there it is nothing. */
22
+ export declare const sceneGround: (stack: boolean, rebase: number, activeElevation: number) => number;
23
+ /** Where an authored elevation ends up on screen, once the view's depth mapping has had its say.
24
+ *
25
+ * `undergroundView` compresses a shaft deeper than 96 m so a 400 m one can be looked at, and its
26
+ * header asks every consumer to share that one transform. They did not: the stack compressed its
27
+ * geometry vertex by vertex while a single-floor cutaway rebased to the compressed depth and then
28
+ * added raw deltas to it, which put a level 140 m under the one in focus 44 m into the sky. This is
29
+ * the mapping the plate, the flights climbing through it, the excavation's strata and the cage all
30
+ * go through. A walk is the one view it has nothing to say to: inside one storey there is no depth
31
+ * to compress, and the storey has been moved onto the map's ground plane anyway. */
32
+ export declare const sceneElevation: (view: UndergroundView, walk: boolean, z: number) => number;
33
+ /** The underside of a walked storey's ceiling, above the storey's own datum.
34
+ *
35
+ * It is the next slab's underside, not the storey height less a slab: fixtures are authored against
36
+ * the storey — the garage's 3.1 m luminaires, its 4.2 m pillars — and a lid a third of a metre low
37
+ * had them poking through it. And a storey the document drew too low for a person to stand in must
38
+ * still get a ceiling above the eye rather than one you look down onto: the 1.6 m entresol put its
39
+ * glowing plane at 1.42 m, a good half metre under the walker's eye. */
40
+ export declare const walkSoffit: (rebase: number, height: number) => number;
41
+ /** A mezzanine shares the surrounding hall's roof. Its own partial footprint cannot close the
42
+ * space seen beyond the gallery edge. Other floors keep their own ceiling. */
43
+ export declare function walkCeiling(project: ProjectDocument, floorId: string): {
44
+ floor: Floor;
45
+ soffit: number;
46
+ } | undefined;
47
+ /** The single plate a storey is drawn as when it is drawn as a shell — the ceiling you look down
48
+ * onto from the storey above — with the stairwells punched through it.
49
+ *
50
+ * Only the storey's top-level areas go in. A parking deck is one plate carrying four hundred bays
51
+ * drawn on it as zones; unioning every one of them is the input polygon-clipping's sweep line gives
52
+ * up on, and the caller's catch then left the deck with no slab at all. The bays are inside the
53
+ * plate anyway, so they say nothing about where the storey reaches. Sloped areas keep their own
54
+ * geometry: flattening their footprints into this plate seals the ramp with a horizontal lid.
55
+ *
56
+ * A storey drawn as rooms rather than as a zone has no single plate, and `floorOutline` already
57
+ * knows how to make one: rooms plus the walls between them, snapped and cached. */
58
+ export declare function shellPlate(project: ProjectDocument, floorId: string, primary?: Set<string>, voidOptions?: VoidOptions): Ring[][];
59
+ export declare class SceneLayer implements CustomLayerInterface {
60
+ id: string;
61
+ type: "custom";
62
+ renderingMode: "3d";
63
+ private map?;
64
+ private renderer?;
65
+ private scene;
66
+ private camera;
67
+ private worldToClip;
68
+ private clipToWorld;
69
+ private transform;
70
+ private center;
71
+ private unit;
72
+ private project?;
73
+ private stack;
74
+ private walking;
75
+ /** The walked floor has lamps of its own. Then the walk hands the interior over to them and
76
+ * turns the general ceiling light down; a floor without any keeps the general light, or it is
77
+ * a dark floor with a bright lid. */
78
+ private lampLit;
79
+ private poolLitOnly;
80
+ private poolOverview;
81
+ /** Per-storey ghost strength for the things a stack is FOR — the floor plates that carry each
82
+ * storey's plan — on the storeys ABOVE the one in focus. Shared out across however many of them
83
+ * the stack layers up between the eye and the focus. */
84
+ private ghostAlpha;
85
+ /** And for the storeys UNDER the one in focus, which are read through the active plate as well as
86
+ * through everything above it and need the strength to survive both. Keeping the two apart is
87
+ * also what lets the active plate be drawn between them — see the render-order pass. */
88
+ private underAlpha;
89
+ private activeFloor;
90
+ private hovered;
91
+ private rebase;
92
+ /** See sceneGround: what an authored elevation has to be shifted by to join the scene. */
93
+ private ground;
94
+ private growth;
95
+ private growthStart;
96
+ private materials;
97
+ private cabinMaterials?;
98
+ private passenger?;
99
+ private cabinFinishes;
100
+ wave(): void;
101
+ private fixtureLights?;
102
+ private waterTime;
103
+ private hasWater;
104
+ private batch;
105
+ private highlight;
106
+ private selected;
107
+ /** Where the sun stands over this project right now, and whether that counts as evening. */
108
+ private sunState;
109
+ private statuses;
110
+ private excavation;
111
+ /** Only the part of the feed the scene is built from — where the cars are and whether doors stand
112
+ * open. A tone changing from normal to alarm recolours a marker and must not rebuild the scene. */
113
+ private liftSignature;
114
+ /** Per-floor stairwell cut-outs; cleared with the scene. */
115
+ private voidCache;
116
+ /** Moving parts, rebuilt with the scene each update — see `rig`. */
117
+ private rigs;
118
+ /** Where each moving part has got to, carried ACROSS rebuilds. The geometry is disposed with the
119
+ * scene like everything else; this is not, or every lift car would jump back to the bottom of its
120
+ * shaft on any edit, and every open door would slam. */
121
+ private rigState;
122
+ /** Whether the last animation frame moved anything that casts a shadow. */
123
+ private shadowsMoved;
124
+ private lastFrame;
125
+ private revision;
126
+ private depthScale;
127
+ private buried;
128
+ private presentedElevation;
129
+ private cage;
130
+ private sun?;
131
+ /** The two lights that are not the sun, kept so the scene can be re-lit without being rebuilt. */
132
+ private skyLight?;
133
+ private roomLight?;
134
+ private route;
135
+ private routeStep;
136
+ private routeGroup;
137
+ private routeTile;
138
+ private mapStyle;
139
+ setMapStyle(style?: MapStyleOptions): void;
140
+ private xyCache;
141
+ private markerCache;
142
+ private occlusionCache;
143
+ private previousProjection;
144
+ private previousScale;
145
+ private previousSize;
146
+ private pickables;
147
+ private clipBounds;
148
+ private clipBoundsDirty;
149
+ onAdd(map: MapLibreMap, gl: WebGLRenderingContext | WebGL2RenderingContext): void;
150
+ /** A tiny procedural sky/ground gradient, prefiltered for image-based lighting. Without an
151
+ * environment every MeshStandardMaterial is lit by two lights alone and reads flat; with one, every
152
+ * surface picks up sky above and bounced ground below, which is most of what makes 3D look solid.
153
+ * Built once per lighting mood and cached — PMREM generation is not cheap. */
154
+ private envCache;
155
+ private environmentMap;
156
+ /** Move the existing lights to where a new sun puts them, without touching the geometry. Valid
157
+ * only while the dusk treatment is unchanged — see the caller. */
158
+ private relight;
159
+ /** Redraw every shadow map on the next frame: the sun's, and each lamp's. Shadows are drawn on
160
+ * demand, and each light says for itself whether it is owed a redraw — the sun's map is one
161
+ * 2048² pass over the whole model and a lamp's is six, so a lamp swapping under a walker must
162
+ * not cost the sun's as well. This is the "everything changed" case. */
163
+ private refreshShadows;
164
+ /** Point the sun at the model and shrink its shadow frustum to fit. A fixed +/-140 m box spends
165
+ * most of a 2048 map on empty ground: a small building got a handful of texels and its shadows
166
+ * came out as soft mush. Fitting to the real extent keeps texel density high whatever the scale. */
167
+ private fitShadowCamera;
168
+ private xy;
169
+ /** Several extrusions welded into one moving part. An escalator's step band is twenty boxes that
170
+ * travel together, and twenty meshes per flight — times a bank of four, times the flights in
171
+ * view — is a draw call apiece for something that moves as one thing. Merged, it is one. */
172
+ private parts;
173
+ /** Register a moving part. Called while the scene is being built; the geometry is fresh each time
174
+ * and the position it has reached is not, so a car mid-ride keeps riding across an edit.
175
+ *
176
+ * `settled` seeds the value the first time a part is ever seen, so opening a document does not
177
+ * send every lift travelling up from the basement to wherever it actually is. */
178
+ private rig;
179
+ /** Advance every moving part toward its target. Returns true while anything is still moving, which
180
+ * is what keeps asking the map to repaint — MapLibre draws on demand, so without that a ride would
181
+ * advance one frame per mouse move. */
182
+ private animate;
183
+ /** Ask for a repaint at the loop rate rather than at once, coalescing the requests so a dozen
184
+ * escalators still only cost one frame between them. */
185
+ private loopTimer?;
186
+ private paintSoon;
187
+ /** One vertex, mapped by the view's depth transform — see sceneElevation. Geometry is built at
188
+ * the elevations the document authored, so this is the last thing that touches a z before it
189
+ * reaches the buffer. It ran in the stacked view only, which left a deep cutaway drawing its
190
+ * plate at the compressed depth and everything around it at the real one. */
191
+ private present;
192
+ private surface;
193
+ /** A sloped area (garage ramp, loading incline): the plate's own footprint, but each vertex lifted
194
+ * to its elevation along the slope axis, then given thickness along -Z so the deck reads solid
195
+ * from below. Depth compression is applied per-vertex, exactly as for flat surfaces. */
196
+ private slopedSurface;
197
+ /** The façade envelope for a set of levels: each level's slab, its exterior walls with their
198
+ * authored finish, and the glazing punched into them. Interior partitions are deliberately left
199
+ * out — from outside they are hidden work, and they used to produce seams along the façade. */
200
+ private envelope;
201
+ private opening;
202
+ /** A door as a leaf in a frame, standing open when the feed says it is.
203
+ *
204
+ * In 3D a door had been a slab filling its whole opening — a door you could never walk through and
205
+ * that looked identical whether it was open, closed or unmonitored. The plan has drawn the swing
206
+ * for a long time; this is the same statement in three dimensions, hinged the same way, so the two
207
+ * views agree about which side it opens from.
208
+ *
209
+ * Unknown status means shut. The plan can draw the architectural swing symbol for "a door is here
210
+ * and this is how it opens" because a symbol is allowed to be about the door rather than about its
211
+ * state; a solid leaf in space is not, so it stays in the frame until something says otherwise. */
212
+ private leaf;
213
+ /** The inward-facing edge of an exterior wall.
214
+ *
215
+ * Which face is the inside is not a property of the wall — it is a question about the building
216
+ * around it — so it is answered the only way it can be: step off the wall each way and see which
217
+ * side lands within the floor's footprint. A wall with no footprint to be inside of (an outbuilding
218
+ * wall, a fence read as exterior) has no interior face. */
219
+ private interiorFace;
220
+ /** An area's rings with the shafts that climb through its level, and the ramps that drive through
221
+ * it, cut out of them.
222
+ *
223
+ * `through` says which plate is being cut: a floor is open where something arrives up through it,
224
+ * a ceiling where something sets off up through it. They are not the same holes — the bottom of a
225
+ * run departs without arriving and the top arrives without departing — and on a criss-cross
226
+ * escalator bank they are at opposite ends of the same box.
227
+ *
228
+ * `wells` is whether a stairwell may be punched at all — a hole onto a storey nobody is drawing
229
+ * is worse than no hole. A ramp is not subject to it: what is under a ramp's hole is the ramp.
230
+ *
231
+ * Cheap when there is nothing to cut, which is the usual case: a floor with no shaft through it
232
+ * gets its own rings back untouched, and one with a shaft pays a clip only for the areas the
233
+ * shaft actually lands in. */
234
+ private withVoids;
235
+ /** A stair, spiral or escalator, drawn as the climb it actually makes.
236
+ *
237
+ * The flights come from the levels the document says the shaft serves, not from whatever storey
238
+ * happens to sit above it, and each is drawn at the elevation of the level it leaves — so the
239
+ * flight arriving at the level you are standing on is there, coming up through the floor, instead
240
+ * of being filed invisibly under the storey below. */
241
+ private shaft;
242
+ /** A straight climb: treads for a stair, a ribbed deck between flat landing plates for an
243
+ * escalator. Both run along the object's own depth axis, which is where the plan put them. */
244
+ private flight;
245
+ /** A lift: the shaft as tall as the levels it serves, its doors on the level you are standing on,
246
+ * and the car where the feed says it is.
247
+ *
248
+ * It used to be a 1.2 m box — shorter than the doors it was supposed to contain — because the
249
+ * generic object path capped elevators there to stop them blocking the view. A lift is not
250
+ * furniture: it is a hole through the building, and drawing it as one is the only way the plan
251
+ * shows that floors 2 and 7 are on the same shaft. Above the level in focus it turns to ghost, so
252
+ * it reads as continuing without becoming a column in front of everything else. */
253
+ private lift;
254
+ /** A spiral: wedge treads winding around a central pole.
255
+ *
256
+ * Its exits are wherever it is served — a spiral passing three levels with a landing on each is
257
+ * one object serving three floors, which the document could already say and nothing drew. */
258
+ private spiral;
259
+ update(project: ProjectDocument, floorId: string | null, stack: boolean, selected: string | null, sun?: Sun, statuses?: Map<string, StatusReading> | null, excavation?: boolean,
260
+ /** Walk mode: put the floor being walked on the map's own ground plane. MapLibre's camera cannot
261
+ * go below that plane, so a basement drawn at its true depth would be unreachable on foot. */
262
+ walk?: boolean): void;
263
+ /** Show/replace the 3D route. When only the active step changed, restyle materials in place;
264
+ * otherwise rebuild the route group. Route state is retained across update() rebuilds — every
265
+ * rebuild re-runs buildRoute with FRESH materials, because disposeScene disposes all mesh
266
+ * materials and a cached material would die silently on the next floor switch. */
267
+ setRoute(route: Route | null, activeStep?: number | null): void;
268
+ /** The track's texture already carries the green and the white kerb, so the material's own colour
269
+ * stays white and only emphasis separates the step being walked from the rest of the path. A
270
+ * route is one route: dimming the other steps says "later", where recolouring them would say
271
+ * "different". */
272
+ private routeStyle;
273
+ private restyleRoute;
274
+ private buildRoute;
275
+ /** Flat mitred triangle-strip ribbon at a constant z, in scene metres. */
276
+ private ribbonGeometry;
277
+ animateIn(): void;
278
+ private refreshHighlight;
279
+ setHover(id: string | null): void;
280
+ get diagnostics(): {
281
+ revision: number;
282
+ drawCalls: number;
283
+ geometries: number;
284
+ textures: number;
285
+ animatedWater: boolean;
286
+ };
287
+ render(gl: WebGLRenderingContext | WebGL2RenderingContext, args: CustomRenderMethodInput): void;
288
+ /** Where a point on a floor's walking surface lands on screen — the avatar marker, which is not an
289
+ * object and has no occlusion to test. `visible` is the frustum only. */
290
+ projectPoint(pt: Point, floorId: string | null): {
291
+ x: number;
292
+ y: number;
293
+ visible: boolean;
294
+ } | null;
295
+ projectObject(o: SiteObject): {
296
+ x: number;
297
+ y: number;
298
+ visible: boolean;
299
+ } | null;
300
+ pick(point: {
301
+ x: number;
302
+ y: number;
303
+ }): string | null;
304
+ private disposeScene;
305
+ onRemove(): void;
306
+ }
@@ -0,0 +1,18 @@
1
+ import * as THREE from 'three';
2
+ import type { Point } from '../model/types';
3
+ /** A camera-facing cutaway cage. Rotating updates two existing buffers, never GPU resources. */
4
+ export declare class UndergroundCage extends THREE.Group {
5
+ private rings;
6
+ private columns;
7
+ private center;
8
+ private bottom;
9
+ private top;
10
+ private bearing;
11
+ private ringLines?;
12
+ private columnLines?;
13
+ configure(rings: THREE.Vector3[][], columns: Point[], bottom: number, top: number, evening: boolean): void;
14
+ setBearing(bearing: number): void;
15
+ dispose(): void;
16
+ }
17
+ /** Only the shaft boundary needs vertical faces; no 1.8 km cap to triangulate or raycast. */
18
+ export declare function undergroundPit(ring: Point[], floor: number, bottom: number, strata?: number[]): THREE.Group;
@@ -0,0 +1,29 @@
1
+ import type { Ambience, AmbiencePreset, Point, ProjectDocument } from '../model/types';
2
+ export declare const AMBIENCES: {
3
+ id: AmbiencePreset;
4
+ label: string;
5
+ description: string;
6
+ }[];
7
+ /** What a point on a floor sounds like: the space's own ambience, else the floor's, else nothing.
8
+ * `silent` resolves to null too, so a room can be the quiet one on a humming floor. */
9
+ export declare function ambienceAt(project: ProjectDocument, floorId: string | null, at: Point): Ambience | null;
10
+ /** Plays one ambience at a time and cross-fades between them. Owns its AudioContext, which the
11
+ * browser will only let run after the person has clicked or pressed something — resume() is for
12
+ * the host to call from such a gesture, and everything else copes with a context that is not yet
13
+ * running by starting silently and coming up when it is. */
14
+ export declare class AmbienceEngine {
15
+ private ctx?;
16
+ private master?;
17
+ private playing?;
18
+ private fading;
19
+ private muted;
20
+ get isMuted(): boolean;
21
+ /** Let the context run. Safe to call on every gesture; a running context ignores it. */
22
+ resume(): void;
23
+ setMuted(muted: boolean): void;
24
+ /** Play this — or nothing, for null — fading out whatever was playing. Same thing again is a no-op. */
25
+ set(ambience: Ambience | null): void;
26
+ dispose(): void;
27
+ private context;
28
+ private fadeOut;
29
+ }
@@ -0,0 +1,8 @@
1
+ import * as THREE from 'three';
2
+ import type { BuildingRoof, Point, SiteObject } from '../model/types';
3
+ import { MaterialLibrary } from './materials';
4
+ type ProjectXY = (point: Point) => Point;
5
+ /** Convex eaves fan into a ridge. Each plane receives actual interlocking tile geometry. */
6
+ export declare function makeRoof(roof: BuildingRoof, projectXY: ProjectXY, id: string, materials: MaterialLibrary): THREE.Group;
7
+ export declare function makeFixture(o: SiteObject, projectXY: ProjectXY, z: number, materials: MaterialLibrary, evening: boolean): THREE.Group;
8
+ export {};
@@ -0,0 +1,14 @@
1
+ /** An original, quiet score for the tiled baths: suspended chords and a sparse glass-bell melody.
2
+ * Synthesised locally, with a repeating forty-second phrase and a long stereo room tail. */
3
+ export declare const bathMusic: (ctx: BaseAudioContext, out: AudioNode) => {
4
+ nodes: AudioNode[];
5
+ sources: (OscillatorNode | {
6
+ stop(): void;
7
+ })[];
8
+ };
9
+ export declare const elevatorMusic: (ctx: BaseAudioContext, out: AudioNode) => {
10
+ nodes: AudioNode[];
11
+ sources: (OscillatorNode | {
12
+ stop(): void;
13
+ })[];
14
+ };
@@ -0,0 +1,20 @@
1
+ import * as maplibregl from 'maplibre-gl';
2
+ import type { Map as GLMap } from 'maplibre-gl';
3
+ import type { Point, ProjectDocument } from '../model/types';
4
+ export declare function cameraToCenterDistance(map: GLMap): number;
5
+ export declare function cameraPosition(map: GLMap): {
6
+ lngLat: maplibregl.LngLat;
7
+ altitude: number;
8
+ };
9
+ /** fit()'s depth-aim factored out and shared with the journey: with a pitched camera a plate at
10
+ * elevation elev projects off-centre unless the ground target shifts by elev·tan(pitch) along the
11
+ * view bearing. elev must already be the PRESENTED elevation (undergroundView().focusElevation). */
12
+ export declare function aimCenter(center: [number, number], elev: number, pitchDeg: number, bearingDeg: number): [number, number];
13
+ /** The map centre that brings a plan position on `floorId` under the crosshair. Anyone easing to a
14
+ * point in the document wants this rather than the raw ground coordinate: the storey is drawn at its
15
+ * presented elevation, and a pitched camera sees it displaced along the view bearing, so centring on
16
+ * the ground beneath a basement leaves the thing you asked for a good ten metres off screen centre. */
17
+ export declare function floorAim(map: GLMap, project: ProjectDocument, position: Point, floorId: string | null, view: {
18
+ threeD: boolean;
19
+ stack: boolean;
20
+ }): [number, number];
@@ -0,0 +1,16 @@
1
+ import type { Point, ProjectDocument, SiteObject } from '../model/types';
2
+ export declare const cabinDimensions: (o: SiteObject) => {
3
+ width: number;
4
+ depth: number;
5
+ };
6
+ /** The car supplies the floor inside its footprint, even at the shaft's lowest landing. */
7
+ export declare function cabinFloorVoids(project: ProjectDocument, floorId: string, primary: Set<string>): import("../schema").Ring[];
8
+ export declare const elevatorDoorWidth: (o: SiteObject, turn?: number) => number;
9
+ export declare const elevatorFacing: (o: SiteObject) => number;
10
+ export declare const elevatorLanding: (o: SiteObject) => Point;
11
+ export declare function insideElevator(o: SiteObject, at: Point): boolean;
12
+ /** Shaft faces and their jambs, shared by collision and the visible cabin. */
13
+ export declare function elevatorWalls(o: SiteObject, open: boolean): Point[][];
14
+ /** Prefer the back wall for a mirror, and a side wall for a through-car lift. */
15
+ export declare const elevatorMirrorFace: (o: SiteObject) => "left" | "right" | "front" | "back" | undefined;
16
+ export declare function elevatorMirrorPoint(o: SiteObject): Point;
@@ -0,0 +1,9 @@
1
+ import type { Floor, Point, ProjectDocument } from '../model/types';
2
+ /** The excavated volume's plan outline(s). A below-grade complex is rarely just the tower footprint:
3
+ * parking decks sprawl past it and driveway ramps reach out to the street. Scoping the pit to a single
4
+ * floor plate left everything beyond it hanging in open air, so union the plates of every below-grade
5
+ * level with the footprints of any ramps (which are few, and are what actually reach the surface).
6
+ * Returns one outline per disjoint excavation; empty when there is nothing below ground. */
7
+ export declare function excavationRings(project: ProjectDocument, levels: Floor[], ceiling?: number): Point[][];
8
+ /** Rings that lie wholly inside another ring in the list add nothing to an excavation outline. */
9
+ export declare function dropContained(rings: Point[][]): Point[][];
@@ -0,0 +1,3 @@
1
+ import type { ProjectDocument } from '../model/types';
2
+ /** Follow each floor's footprint, including stepped upper floors and courtyard edges. */
3
+ export declare function exteriorWalls(project: ProjectDocument): Set<string>;
@@ -0,0 +1,33 @@
1
+ import type { FeatureCollection } from 'geojson';
2
+ import type { MaterialKind, Point, ProjectDocument, Ring, SiteObject } from '../model/types';
3
+ import type { StatusReading } from '../model/live';
4
+ import type { MapStyleOptions } from '../theme';
5
+ export declare const COLORS: Record<string, string>;
6
+ export declare const visibleOnFloor: (object: {
7
+ floorId: string | null;
8
+ }, floorId: string | null) => boolean;
9
+ /** The same question for objects that span levels. A shaft is filed under the lowest level it serves
10
+ * and reaches the rest, so asking only where it is filed hides it from every storey it arrives at —
11
+ * on the plan as much as in the model. Takes the project because the answer is in `servedFloorIds`. */
12
+ export declare const onFloor: (project: ProjectDocument, object: SiteObject, floorId: string | null) => boolean;
13
+ export declare const objectRings: (o: SiteObject) => Ring[];
14
+ /** Roughly how wide a shape is on the plan, independent of its rotation. `width`/`depth` are an
15
+ * axis-aligned bounding box, which badly overstates anything drawn on a rotated site grid — a 2.5 m
16
+ * parking bay turned 55° measures nearly 5 m that way. 4·area/perimeter is the harmonic mean of a
17
+ * rectangle's sides (2wh/(w+h)), so it tracks the narrow dimension and does not care about angle. */
18
+ export declare function planWidth(o: SiteObject): number;
19
+ export interface WallPiece {
20
+ ring: Ring;
21
+ base: number;
22
+ height: number;
23
+ id: string;
24
+ color: string;
25
+ floorId: string | null;
26
+ material?: MaterialKind;
27
+ }
28
+ export declare function wallPieces(project: ProjectDocument, floorId: string | null, stack?: boolean): WallPiece[];
29
+ export declare function makeFeatures(project: ProjectDocument, floorId: string | null, selected: string | null, coverage: boolean, statuses?: Map<string, StatusReading>, mapStyle?: MapStyleOptions): FeatureCollection;
30
+ /** Edit-mode nav-graph overlay data (kerros-navgraph): nodes as points, edges as lines. Vertical edges
31
+ * join twin shaft positions so they render as a marker-sized stub rather than a long line. */
32
+ export declare function navGraphFeatures(project: ProjectDocument, floorId: string | null, selected: string | null): FeatureCollection;
33
+ export declare function draftFeatures(project: ProjectDocument, points: Point[], hover: Point | null, tool: string): FeatureCollection;
@@ -0,0 +1,4 @@
1
+ import * as THREE from 'three';
2
+ import type { Point, Ring } from '../model/types';
3
+ /** Open railing geometry for one wall piece; the piece interval already excludes gates. */
4
+ export declare function fenceGeometry(a: Point, b: Point, ring: Ring, base: number, height: number, thickness: number): THREE.BufferGeometry<THREE.NormalBufferAttributes, THREE.BufferGeometryEventMap>;
@@ -0,0 +1,36 @@
1
+ import type { Map as GLMap } from 'maplibre-gl';
2
+ import type { Origin } from '../model/types';
3
+ import type { Route } from '../model/navigation';
4
+ export { aimCenter, floorAim } from './cameraAim';
5
+ export interface JourneyCallbacks {
6
+ /** Ask the app to switch floors; the map rebuild follows via React. */
7
+ requestFloor(floorId: string | null): void;
8
+ /** Resolves once the app shows floorId and the view has rebuilt (implemented by MapCanvas). */
9
+ waitForFloor(floorId: string | null): Promise<void>;
10
+ /** Presented elevation of a floor: undergroundView(...).focusElevation in 3D, 0 in 2D. */
11
+ focusElevation(floorId: string | null): number;
12
+ onStep(index: number): void;
13
+ onEnd(): void;
14
+ }
15
+ export declare class JourneyPlayer {
16
+ private map;
17
+ private cb;
18
+ private cancelled;
19
+ private ended;
20
+ private _playing;
21
+ private origin;
22
+ constructor(map: GLMap, cb: JourneyCallbacks);
23
+ get playing(): boolean;
24
+ private onGesture;
25
+ play(route: Route, ctx: {
26
+ origin: Origin;
27
+ startFloorId: string | null;
28
+ }): void;
29
+ /** Cancel: abort the current ease, detach listeners, fire onEnd exactly once. Never resets the
30
+ * camera itself — the host re-runs fit if it wants to. */
31
+ stop(): void;
32
+ private end;
33
+ private ease;
34
+ private switchFloor;
35
+ private run;
36
+ }
@@ -0,0 +1,4 @@
1
+ /** Clearance between the floor's datum and the underside of its slab. */
2
+ export declare const LIFT = 0.15;
3
+ /** The slab itself. */
4
+ export declare const SLAB = 0.18;