@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,2161 @@
1
+ import { jsxs as S, jsx as m, Fragment as wt } from "react/jsx-runtime";
2
+ import { draggedDoorSwing as ho, doorSymbol as mo } from "../model/doors.js";
3
+ import { lazy as ko, useRef as L, useState as ae, useEffect as A, useMemo as le, Fragment as wo, Suspense as vo } from "react";
4
+ import * as et from "maplibre-gl";
5
+ import { PersonStanding as vt, Mountain as Sr, Plus as bo, Minus as po, RotateCcw as Io, RotateCw as jo, LocateFixed as xo, Compass as Lo } from "lucide-react";
6
+ import Po from "polygon-clipping";
7
+ import { isSpace as Do } from "../model/types.js";
8
+ import { barrierEnds as we, toLngLat as ce, drawingCorners as Mo, toLocal as se, rectangle as So, objectPosition as Be, pointInRing as Er, objectArea as bt, openRing as pt, add as Fr, rotate as Rr, ringArea as Cr, distance as It, closeRing as Nr, segmentProjection as Eo } from "../model/geometry.js";
9
+ import { statusLabel as jt, statusTone as tt } from "../adapters/status.js";
10
+ import { useKerrosTheme as Fo, useStrings as Ro } from "../theme/index.js";
11
+ import { neutralBasemap as $r } from "../adapters/basemap.js";
12
+ import { ambient as xt, sunlight as Co, mixColor as Tr } from "./lighting.js";
13
+ import { EntityIcon as No } from "../components/Icons.js";
14
+ import { draftFeatures as $o, navGraphFeatures as To, onFloor as Ao, visibleOnFloor as zo, makeFeatures as Ar } from "./features.js";
15
+ import { boundaryEdges as Oe } from "../model/boundaries.js";
16
+ import { routeFeatures as Bo, routeArrowImage as Oo, ROUTE_EDGE as rt, ROUTE_COLOR as Lt, ROUTE_SOFT as ot, routeFlowGradient as zr } from "./route.js";
17
+ import { cameraToCenterDistance as Wo, aimCenter as Pt, floorAim as qo, cameraPosition as Ko } from "./cameraAim.js";
18
+ import { LIFT as Dt, SLAB as Mt } from "./levels.js";
19
+ import { floorSupport as Yo, walkingWallRings as Uo, floorArrival as _o } from "./walkSurfaces.js";
20
+ import { stairSurfaces as Ho } from "./stairSurfaces.js";
21
+ import { MAX_MAP_ZOOM as Xo, walkFieldOfView as Br, DEFAULT_WALK_FOV as Or, WalkController as Vo, unstick as St, MAX_WALK_FOV as Zo, MIN_WALK_FOV as Jo } from "./walk.js";
22
+ import { AmbienceEngine as Go, ambienceAt as Wr } from "./ambience.js";
23
+ import { spaceAt as qr, spacePoint as Qo, inSpace as Kr } from "../model/spaces.js";
24
+ import { servedFloors as Yr } from "../model/vertical.js";
25
+ import { undergroundView as Me, floorIndex as Ur } from "./underground.js";
26
+ import { loadBasemap as en } from "./loadBasemap.js";
27
+ import { elevatorWalls as tn } from "./elevators.js";
28
+ import { EYE as Et } from "./walkDimensions.js";
29
+ const rn = ko(() => import("../components/ElevatorPanel.js").then((r) => ({ default: r.ElevatorPanel }))), Rt = { type: "FeatureCollection", features: [] }, on = {
30
+ type: "FeatureCollection",
31
+ features: [
32
+ {
33
+ type: "Feature",
34
+ properties: {},
35
+ geometry: {
36
+ type: "Polygon",
37
+ coordinates: [
38
+ [
39
+ [-180, -85],
40
+ [180, -85],
41
+ [180, 85],
42
+ [-180, 85],
43
+ [-180, -85]
44
+ ]
45
+ ]
46
+ }
47
+ }
48
+ ]
49
+ };
50
+ function nn(r, Z) {
51
+ if (r.threeD) return Rt;
52
+ const P = Ar(r.project, r.floorId, r.selected, r.coverage, r.statuses, Z), E = r.project.floors.find((h) => h.id === r.floorId);
53
+ if (E != null && E.mezzanine && !r.threeD) {
54
+ const h = r.project.floors.filter((O) => O.buildingId === E.buildingId && O.id !== E.id), de = h.filter((O) => O.elevation < E.elevation).sort((O, J) => J.elevation - O.elevation)[0], Y = h.filter((O) => O.elevation > E.elevation).sort((O, J) => O.elevation - J.elevation)[0], We = (O, J, Se) => O ? Ar(r.project, O.id, null, !1).features.filter(
55
+ (W) => {
56
+ var qe;
57
+ return ((qe = W.properties) == null ? void 0 : qe.floorId) === O.id && !W.properties.decoration && (Se || W.properties.kind !== "wall") && W.geometry.type === "Polygon";
58
+ }
59
+ ).map((W) => ({ ...W, properties: { kind: W.properties.kind, color: W.properties.color, context: J } })) : [];
60
+ P.features = [...We(de, "lower", !0), ...P.features, ...We(Y, "upper", !1)];
61
+ }
62
+ return P;
63
+ }
64
+ const Ft = (r) => r.origin[2] ?? 0, nt = { looking: !1, sound: !0, up: null, down: null, where: "", next: "" }, _r = "kerros:walk-muted", Hr = "kerros:walk-fov";
65
+ function Cn(r) {
66
+ var hr, mr, kr, wr, vr, br, pr, Ir, jr, xr, Lr, Pr, Dr;
67
+ const Z = L(null), P = L(null), E = L(null), h = L(r), de = L(/* @__PURE__ */ new Map());
68
+ h.current = r;
69
+ const [Y, We] = ae(!1), [O, J] = ae(0), [Se, W] = ae(""), [qe, Ct] = ae(0);
70
+ A(() => {
71
+ const e = (t) => {
72
+ var d;
73
+ const o = h.current;
74
+ if (o.threeD || o.walk || t.ctrlKey || t.metaKey || t.altKey || t.shiftKey || t.isComposing || (d = t.target) != null && d.closest('input, textarea, select, dialog, [contenteditable], [role="textbox"]') || o.canEdit && o.tool !== "select" && o.tool !== "pan") return;
75
+ const i = { w: [0, -140], a: [-140, 0], s: [0, 140], d: [140, 0] }[t.key.toLowerCase()];
76
+ !i || !P.current || (t.preventDefault(), t.stopImmediatePropagation(), P.current.panBy(i, { duration: 250 }));
77
+ };
78
+ return window.addEventListener("keydown", e, !0), () => window.removeEventListener("keydown", e, !0);
79
+ }, []);
80
+ const Nt = L(null), Ee = L(null), Xr = () => (Ee.current ?? (Ee.current = import("./SceneLayer.js").then((e) => {
81
+ Nt.current = e.SceneLayer;
82
+ })), Ee.current);
83
+ A(() => {
84
+ if (!r.threeD || !r.showPlan) return;
85
+ let e = !0;
86
+ return Xr().then(() => {
87
+ e && (Re(), J((t) => t + 1));
88
+ }).catch((t) => {
89
+ Ee.current = null, e && W(`The 3D view could not load: ${String(t)}`);
90
+ }), () => {
91
+ e = !1;
92
+ };
93
+ }, [r.threeD, r.showPlan]);
94
+ const Ke = L(!1), $t = L(null), Tt = L(null), Ye = L(!1), Ue = Fo().mapStyle, pe = L(Ue);
95
+ pe.current = Ue;
96
+ const At = Ro().map, Fe = L(At);
97
+ Fe.current = At;
98
+ const zt = le(
99
+ () => nn(r, Ue),
100
+ [
101
+ r.project,
102
+ r.floorId,
103
+ r.selected,
104
+ r.coverage,
105
+ r.threeD,
106
+ r.threeD ? null : r.statuses,
107
+ Ue
108
+ ]
109
+ ), Bt = le(
110
+ () => $o(r.project, r.draft, r.hover, r.tool),
111
+ [r.project, r.draft, r.hover, r.tool]
112
+ ), it = le(
113
+ () => ({
114
+ type: "FeatureCollection",
115
+ features: [
116
+ ...r.guides ?? [],
117
+ ...r.canEdit && !r.threeD ? (r.project.virtualBoundaries ?? []).filter((e) => e.floorId === r.floorId).map((e) => ({ id: e.id, role: "boundary", line: we(r.project, e) })) : []
118
+ ].map((e) => ({
119
+ type: "Feature",
120
+ properties: { role: e.role, ..."id" in e ? { id: e.id, kind: "boundary" } : {} },
121
+ geometry: { type: "LineString", coordinates: e.line.map((t) => ce(t, r.project.origin)) }
122
+ }))
123
+ }),
124
+ [r.guides, r.project, r.floorId, r.canEdit, r.threeD]
125
+ ), _e = r.tool === "route", Ot = !!r.selected && (!!((hr = r.project.navNodes) != null && hr.some((e) => e.id === r.selected)) || !!((mr = r.project.navEdges) != null && mr.some((e) => e.id === r.selected))), Wt = le(
126
+ () => r.route && !r.threeD ? Bo(
127
+ r.project,
128
+ r.route,
129
+ r.floorId,
130
+ r.activeStep ?? null
131
+ ) : Rt,
132
+ [r.project, r.route, r.floorId, r.activeStep, r.threeD]
133
+ ), qt = le(
134
+ () => !r.threeD && r.canEdit && (_e || Ot) ? To(r.project, r.floorId, r.selected) : Rt,
135
+ [r.project, r.floorId, r.selected, r.threeD, r.canEdit, _e, Ot]
136
+ ), Kt = L(zt), at = L(Bt), Yt = L(Wt), lt = L(it), Ut = L(qt);
137
+ Kt.current = zt, at.current = Bt, lt.current = it, Yt.current = Wt, Ut.current = qt;
138
+ const re = L(null), ct = L(/* @__PURE__ */ new Map()), _t = le(() => new Map(r.project.objects.map((e) => [e.id, e])), [r.project]), Ht = L(_t);
139
+ Ht.current = _t;
140
+ const Xt = (e) => {
141
+ const t = e.currentTarget.querySelector(".marker-tooltip"), o = Z.current;
142
+ if (!t || !o) return;
143
+ const n = o.getBoundingClientRect(), i = e.currentTarget.getBoundingClientRect(), d = t.offsetWidth / 2 + 10;
144
+ t.classList.toggle("flip-y", i.top - n.top < t.offsetHeight + 24), t.classList.toggle("nudge-left", i.left + d > n.right), t.classList.toggle("nudge-right", i.left - d < n.left);
145
+ }, Ie = L(/* @__PURE__ */ new Map()), Vt = () => {
146
+ const e = P.current;
147
+ if (!e || !e.getStyle()) return;
148
+ const t = h.current;
149
+ if (!!t.walk && t.floorId !== null)
150
+ for (const n of e.getStyle().layers ?? [])
151
+ n.id.startsWith("kerros-") || n.type === "background" || Ie.current.has(n.id) || (Ie.current.set(
152
+ n.id,
153
+ e.getLayoutProperty(n.id, "visibility") ?? "visible"
154
+ ), e.setLayoutProperty(n.id, "visibility", "none"));
155
+ else if (Ie.current.size) {
156
+ for (const [n, i] of Ie.current) e.getLayer(n) && e.setLayoutProperty(n, "visibility", i);
157
+ Ie.current.clear();
158
+ }
159
+ };
160
+ A(() => {
161
+ Y && Vt();
162
+ }, [r.walk, r.floorId, Y]);
163
+ const He = () => {
164
+ var i, d;
165
+ const e = P.current, t = $t.current, o = h.current;
166
+ if (!e || !t) return;
167
+ const n = Ht.current;
168
+ for (const l of Array.from(t.children)) {
169
+ const { wx: s, wy: a, oid: u, floor: f, bearing: k } = l.dataset;
170
+ if (!(s === void 0 || a === void 0))
171
+ if (k !== void 0 && l.style.setProperty("--turn", `${Number(k) - e.getBearing()}deg`), o.threeD && f !== void 0) {
172
+ const g = (i = E.current) == null ? void 0 : i.projectPoint([Number(s), Number(a)], f || null);
173
+ g && (l.style.left = `${g.x}px`, l.style.top = `${g.y}px`, l.style.visibility = g.visible ? "" : "hidden");
174
+ } else if (o.threeD && u) {
175
+ const g = n.get(u), b = g && ((d = E.current) == null ? void 0 : d.projectObject(g));
176
+ b && (l.style.left = `${b.x}px`, l.style.top = `${b.y}px`, l.style.visibility = b.visible ? "" : "hidden");
177
+ } else {
178
+ const g = e.project(ce([Number(s), Number(a)], o.project.origin));
179
+ l.style.left = `${g.x + Number(l.dataset.screenDx ?? 0)}px`, l.style.top = `${g.y + Number(l.dataset.screenDy ?? 0)}px`, l.style.visibility = "";
180
+ }
181
+ }
182
+ }, Xe = L(""), Zt = L(/* @__PURE__ */ new Set()), je = L(/* @__PURE__ */ new Map()), Jt = () => {
183
+ var a, u, f;
184
+ const e = P.current, t = h.current, o = (u = (a = t.basemap) == null ? void 0 : a.vectorSchema) == null ? void 0 : u.footprints;
185
+ if (!e || !o || !e.getLayer("kerros-city-3d")) return;
186
+ if (!t.threeD || Me(t.project, t.floorId, t.stack).buried) {
187
+ for (const [k, g] of je.current)
188
+ e.getLayer(k) && e.setFilter(k, g ?? void 0);
189
+ je.current.clear(), Xe.current = "";
190
+ return;
191
+ }
192
+ const n = e.getLayer("kerros-city-3d").source, i = t.project.objects.filter((k) => k.kind === "parcel" && k.rings), d = Zt.current;
193
+ for (const k of t.project.buildings) k.sourceId !== void 0 && d.add(k.sourceId);
194
+ for (const k of e.querySourceFeatures(n, { sourceLayer: o.sourceLayer })) {
195
+ const g = (f = k.properties) == null ? void 0 : f[o.idField];
196
+ if (g === void 0 || d.has(g)) continue;
197
+ const b = k.geometry, c = b.type === "Polygon" ? b.coordinates[0] : b.type === "MultiPolygon" ? b.coordinates[0][0] : null;
198
+ if (!c) continue;
199
+ const v = c.reduce((F, p) => [F[0] + p[0] / c.length, F[1] + p[1] / c.length], [0, 0]), R = se(v, t.project.origin);
200
+ i.some((F) => Er(R, F.rings[0])) && d.add(g);
201
+ }
202
+ const l = JSON.stringify([...d].sort());
203
+ if (l === Xe.current) return;
204
+ Xe.current = l;
205
+ const s = ["!", ["in", ["get", o.idField], ["literal", [...d]]]];
206
+ e.setFilter("kerros-city-3d", s);
207
+ for (const k of e.getStyle().layers) {
208
+ if (k.id === "kerros-city-3d" || !("source-layer" in k) || k["source-layer"] !== o.sourceLayer)
209
+ continue;
210
+ je.current.has(k.id) || je.current.set(k.id, e.getFilter(k.id) ?? null);
211
+ const g = je.current.get(k.id);
212
+ e.setFilter(k.id, g ? ["all", g, s] : s);
213
+ }
214
+ }, Vr = (e) => {
215
+ var a, u, f, k, g;
216
+ const t = P.current, o = h.current, n = (u = (a = o.basemap) == null ? void 0 : a.vectorSchema) == null ? void 0 : u.footprints;
217
+ if (!t || !n) return;
218
+ const i = t.getStyle().layers.filter((b) => "source-layer" in b && b["source-layer"] === n.sourceLayer && b.id !== "kerros-city-3d").map((b) => b.id), d = i.length ? t.queryRenderedFeatures(
219
+ [
220
+ [e.x - 3, e.y - 3],
221
+ [e.x + 3, e.y + 3]
222
+ ],
223
+ { layers: i }
224
+ ).find((b) => {
225
+ var c;
226
+ return ((c = b.properties) == null ? void 0 : c[n.idField]) !== void 0;
227
+ }) : void 0;
228
+ if (!d) {
229
+ o.onError(Fe.current.adoptMiss);
230
+ return;
231
+ }
232
+ const l = d.properties[n.idField], s = [];
233
+ for (const b of t.queryRenderedFeatures(void 0, {
234
+ layers: i,
235
+ filter: ["==", ["get", n.idField], l]
236
+ })) {
237
+ const c = b.geometry;
238
+ if (c.type === "Polygon") s.push(c.coordinates.map((v) => v.map((R) => se(R, o.project.origin))));
239
+ else if (c.type === "MultiPolygon")
240
+ for (const v of c.coordinates)
241
+ s.push(v.map((R) => R.map((F) => se(F, o.project.origin))));
242
+ }
243
+ try {
244
+ const c = [...Po.union(...s.map((F) => [F]))].sort((F, p) => Cr(p[0]) - Cr(F[0]))[0], v = (F) => {
245
+ const p = [];
246
+ for (const C of pt(F))
247
+ (!p.length || Math.hypot(C[0] - p[p.length - 1][0], C[1] - p[p.length - 1][1]) > 0.2) && p.push(C);
248
+ for (; p.length > 2 && Math.hypot(p[0][0] - p[p.length - 1][0], p[0][1] - p[p.length - 1][1]) < 0.2; )
249
+ p.pop();
250
+ return p;
251
+ }, R = c.map(v).filter((F) => F.length >= 3);
252
+ if (!R.length) throw new Error("degenerate footprint");
253
+ (g = o.onAdopt) == null || g.call(o, {
254
+ rings: R,
255
+ sourceId: l,
256
+ storeys: ((f = n.storeys) == null ? void 0 : f.call(n, d.properties)) ?? 1,
257
+ name: ((k = n.name) == null ? void 0 : k.call(n, d.properties)) ?? "City building"
258
+ });
259
+ } catch {
260
+ o.onError(Fe.current.adoptFail);
261
+ }
262
+ }, Gt = () => {
263
+ const e = P.current;
264
+ if (!(!Ye.current || !(e != null && e.getSource("kerros-draft"))))
265
+ for (const [t, o] of [
266
+ ["kerros-draft", at.current],
267
+ ["kerros-guide", lt.current]
268
+ ])
269
+ e.getSource(t).setData(o), ct.current.set(t, o);
270
+ }, Re = () => {
271
+ const e = P.current, t = h.current;
272
+ if (!(!e || !Ye.current))
273
+ try {
274
+ Zr(e, t);
275
+ } catch {
276
+ e.once("idle", Re);
277
+ }
278
+ }, Zr = (e, t) => {
279
+ var c, v, R, F, p, C, T, ne, he, M, Q, N;
280
+ e.hasImage("kerros-route-arrow") || e.addImage("kerros-route-arrow", Oo());
281
+ const o = {
282
+ dim: on,
283
+ entities: Kt.current,
284
+ draft: at.current,
285
+ guide: lt.current,
286
+ route: Yt.current,
287
+ navgraph: Ut.current
288
+ };
289
+ for (const [y, j] of Object.entries(o)) {
290
+ const $ = `kerros-${y}`;
291
+ e.getSource($) ? ct.current.get($) !== j && e.getSource($).setData(j) : e.addSource($, { type: "geojson", data: j, lineMetrics: y === "route" }), ct.current.set($, j);
292
+ }
293
+ if (!e.getLayer("kerros-areas")) {
294
+ const y = pe.current, j = (y == null ? void 0 : y.selection) ?? "#5a52d5", $ = (y == null ? void 0 : y.selectionFill) ?? "#c8c4f5", ge = (y == null ? void 0 : y.hover) ?? j, me = (y == null ? void 0 : y.draft) ?? j, Ae = (ke) => [
295
+ "case",
296
+ ["==", ["get", "kind"], "coverage"],
297
+ 0.13,
298
+ ["==", ["get", "kind"], "status-halo"],
299
+ 0.22,
300
+ ["==", ["get", "context"], "lower"],
301
+ 0.35,
302
+ ["==", ["get", "context"], "upper"],
303
+ 0,
304
+ ["==", ["get", "selected"], !0],
305
+ 1,
306
+ ["==", ["get", "small"], !0],
307
+ ke,
308
+ 1
309
+ ];
310
+ e.addLayer({
311
+ id: "kerros-dim",
312
+ type: "fill",
313
+ source: "kerros-dim",
314
+ paint: { "fill-color": "#0d0f16", "fill-opacity": 0.55 }
315
+ }), e.addLayer({
316
+ id: "kerros-underground",
317
+ type: "fill",
318
+ source: "kerros-dim",
319
+ paint: { "fill-color": "#262320", "fill-opacity": 0.985 }
320
+ }), e.addLayer({
321
+ id: "kerros-premises",
322
+ type: "fill",
323
+ source: "kerros-entities",
324
+ filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", ["get", "kind"], "parcel"]],
325
+ paint: { "fill-color": "#f3f4f0", "fill-opacity": 0.97 }
326
+ }), e.addLayer({
327
+ id: "kerros-premises-line",
328
+ type: "line",
329
+ source: "kerros-entities",
330
+ filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", ["get", "kind"], "parcel"]],
331
+ paint: { "line-color": "#9aa0ac", "line-width": 1.5, "line-dasharray": [4, 2] }
332
+ }), e.addLayer({
333
+ id: "kerros-areas",
334
+ type: "fill",
335
+ source: "kerros-entities",
336
+ filter: [
337
+ "all",
338
+ ["==", ["geometry-type"], "Polygon"],
339
+ ["!=", ["get", "kind"], "wall"],
340
+ ["!=", ["get", "kind"], "parcel"]
341
+ ],
342
+ paint: {
343
+ "fill-color": ["case", ["==", ["get", "selected"], !0], $, ["get", "color"]],
344
+ // Zoom expressions must be the OUTERMOST expression in a paint property — MapLibre throws
345
+ // (and silently drops the whole layer) if one is nested inside a `case`. So the data-driven
346
+ // chain is evaluated at each zoom stop, differing only in what a `small` feature gets.
347
+ "fill-opacity": ["interpolate", ["linear"], ["zoom"], 18.6, Ae(0), 19.6, Ae(1)]
348
+ }
349
+ }), e.addLayer({
350
+ id: "kerros-outline",
351
+ type: "line",
352
+ source: "kerros-entities",
353
+ filter: [
354
+ "all",
355
+ ["==", ["geometry-type"], "Polygon"],
356
+ ["!=", ["get", "kind"], "furniture"],
357
+ ["!=", ["get", "kind"], "parcel"],
358
+ ["!=", ["get", "context"], "upper"]
359
+ ],
360
+ paint: {
361
+ "line-color": ["case", ["==", ["get", "selected"], !0], j, "#a7adbb"],
362
+ "line-width": ["case", ["==", ["get", "selected"], !0], 2, 0.8],
363
+ // A narrow area is only a few pixels wide at building zoom; outlining hundreds of them
364
+ // (a garage of bays, a warehouse of racks) reads as a hatch rather than a plan. Fade them
365
+ // in once they are big enough to tell apart — a selected one always draws.
366
+ "line-opacity": [
367
+ "interpolate",
368
+ ["linear"],
369
+ ["zoom"],
370
+ 18.6,
371
+ ["case", ["==", ["get", "selected"], !0], 1, ["==", ["get", "small"], !0], 0, 1],
372
+ 19.6,
373
+ 1
374
+ ]
375
+ }
376
+ }), e.addLayer({
377
+ id: "kerros-detail",
378
+ type: "line",
379
+ source: "kerros-entities",
380
+ filter: ["==", ["geometry-type"], "LineString"],
381
+ paint: { "line-color": ["get", "color"], "line-width": 1 }
382
+ }), e.addLayer({
383
+ id: "kerros-walls",
384
+ type: "fill",
385
+ source: "kerros-entities",
386
+ filter: ["==", ["get", "kind"], "wall"],
387
+ paint: {
388
+ "fill-color": ["case", ["==", ["get", "selected"], !0], j, ["get", "color"]],
389
+ "fill-opacity": ["case", ["==", ["get", "context"], "lower"], 0.3, 1]
390
+ }
391
+ }), e.addLayer({
392
+ id: "kerros-context-upper",
393
+ type: "line",
394
+ source: "kerros-entities",
395
+ filter: ["==", ["get", "context"], "upper"],
396
+ paint: { "line-color": "#8b90a0", "line-width": 1.2, "line-dasharray": [2, 2] }
397
+ }), e.addLayer({
398
+ id: "kerros-plan-dim",
399
+ type: "fill",
400
+ source: "kerros-entities",
401
+ filter: ["all", ["==", ["geometry-type"], "Polygon"], ["==", ["get", "kind"], "parcel"]],
402
+ paint: { "fill-color": "#0d0f16", "fill-opacity": 0.58 }
403
+ }), e.addLayer({
404
+ id: "kerros-hover",
405
+ type: "line",
406
+ source: "kerros-entities",
407
+ filter: ["==", ["get", "id"], ""],
408
+ paint: { "line-color": ge, "line-width": 2.5 }
409
+ }), e.addLayer({
410
+ id: "kerros-guide-line",
411
+ type: "line",
412
+ source: "kerros-guide",
413
+ paint: {
414
+ "line-color": me,
415
+ "line-width": ["case", ["==", ["get", "role"], "proposal"], 3, 1.2],
416
+ "line-opacity": ["case", ["==", ["get", "role"], "proposal"], 0.9, 0.45],
417
+ "line-dasharray": [2, 2]
418
+ }
419
+ }), e.addLayer({
420
+ id: "kerros-draft-fill",
421
+ type: "fill",
422
+ source: "kerros-draft",
423
+ filter: ["==", ["geometry-type"], "Polygon"],
424
+ paint: { "fill-color": me, "fill-opacity": 0.13 }
425
+ }), e.addLayer({
426
+ id: "kerros-draft-line",
427
+ type: "line",
428
+ source: "kerros-draft",
429
+ paint: { "line-color": me, "line-width": 2, "line-dasharray": [3, 2] }
430
+ }), e.addLayer({
431
+ id: "kerros-navgraph-edge",
432
+ type: "line",
433
+ source: "kerros-navgraph",
434
+ filter: ["==", ["geometry-type"], "LineString"],
435
+ paint: {
436
+ "line-color": [
437
+ "case",
438
+ ["==", ["get", "selected"], !0],
439
+ "#5a52d5",
440
+ ["==", ["get", "kind"], "door"],
441
+ "#6a63d8",
442
+ "#8d85dc"
443
+ ],
444
+ "line-width": 1.4,
445
+ // A derived graph is drawn fainter and in longer dashes: it is what the plan implies, not
446
+ // what anyone drew, and the difference matters the moment you start editing it.
447
+ "line-dasharray": ["case", ["==", ["get", "derived"], !0], ["literal", [4, 3]], ["literal", [2, 2]]],
448
+ "line-opacity": ["case", ["==", ["get", "derived"], !0], 0.5, 0.85]
449
+ }
450
+ }), e.addLayer({
451
+ id: "kerros-navgraph-node",
452
+ type: "circle",
453
+ source: "kerros-navgraph",
454
+ filter: ["==", ["geometry-type"], "Point"],
455
+ paint: {
456
+ "circle-radius": ["case", ["==", ["get", "vertical"], !0], 5, ["==", ["get", "bound"], !0], 4.5, 3.5],
457
+ "circle-color": [
458
+ "case",
459
+ ["==", ["get", "selected"], !0],
460
+ "#5a52d5",
461
+ ["==", ["get", "vertical"], !0],
462
+ "#567c9a",
463
+ ["==", ["get", "bound"], !0],
464
+ "#6a63d8",
465
+ "#8d85dc"
466
+ ],
467
+ "circle-stroke-width": 1.2,
468
+ "circle-stroke-color": "#ffffff",
469
+ "circle-opacity": ["case", ["==", ["get", "derived"], !0], 0.55, 1]
470
+ }
471
+ });
472
+ const De = (ke) => ["interpolate", ["linear"], ["zoom"], 15, ke * 0.5, 18, ke * 0.82, 21, ke];
473
+ e.addLayer({
474
+ id: "kerros-route-casing",
475
+ type: "line",
476
+ source: "kerros-route",
477
+ filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", ["get", "flow"], !0]],
478
+ layout: { "line-cap": "round", "line-join": "round" },
479
+ paint: { "line-color": rt, "line-width": De(31), "line-opacity": 0.96 }
480
+ }), e.addLayer({
481
+ id: "kerros-route",
482
+ type: "line",
483
+ source: "kerros-route",
484
+ // Not the flow tracing: it covers the same ground, carries no `active`, and so painted itself
485
+ // over the whole path in the not-your-step tone — a route drawn twice, the second time wrong.
486
+ filter: [
487
+ "all",
488
+ ["==", ["geometry-type"], "LineString"],
489
+ ["==", ["get", "onFloor"], !0],
490
+ ["!=", ["get", "flow"], !0]
491
+ ],
492
+ layout: { "line-cap": "round", "line-join": "round" },
493
+ paint: {
494
+ "line-color": ["case", ["==", ["get", "active"], !0], Lt, ot],
495
+ "line-width": De(20),
496
+ "line-opacity": ["case", ["==", ["get", "active"], !0], 1, 0.9]
497
+ }
498
+ }), e.addLayer({
499
+ id: "kerros-route-flow",
500
+ type: "line",
501
+ source: "kerros-route",
502
+ filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", ["get", "flow"], !0]],
503
+ layout: { "line-cap": "butt", "line-join": "round" },
504
+ // Repainted on a timer while a route is shown; the static value is the band at rest.
505
+ paint: { "line-width": De(20), "line-gradient": zr(0) }
506
+ }), e.addLayer({
507
+ id: "kerros-route-off",
508
+ type: "line",
509
+ source: "kerros-route",
510
+ filter: [
511
+ "all",
512
+ ["==", ["geometry-type"], "LineString"],
513
+ ["!=", ["get", "onFloor"], !0],
514
+ ["!=", ["get", "flow"], !0]
515
+ ],
516
+ paint: { "line-color": ot, "line-width": 2.4, "line-dasharray": [2, 2], "line-opacity": 0.45 }
517
+ }), e.addLayer({
518
+ id: "kerros-route-arrows",
519
+ type: "symbol",
520
+ source: "kerros-route",
521
+ filter: ["all", ["==", ["geometry-type"], "LineString"], ["==", ["get", "flow"], !0]],
522
+ layout: {
523
+ "symbol-placement": "line",
524
+ "symbol-spacing": 52,
525
+ "icon-image": "kerros-route-arrow",
526
+ "icon-size": ["interpolate", ["linear"], ["zoom"], 15, 0.5, 18, 0.8, 21, 1],
527
+ "icon-rotation-alignment": "map",
528
+ "icon-allow-overlap": !0,
529
+ "icon-ignore-placement": !0
530
+ }
531
+ }), e.addLayer({
532
+ id: "kerros-route-vertical",
533
+ type: "circle",
534
+ source: "kerros-route",
535
+ filter: ["==", ["get", "vertical"], !0],
536
+ paint: {
537
+ "circle-radius": ["case", ["==", ["get", "active"], !0], 11, 8],
538
+ "circle-color": ["case", ["==", ["get", "active"], !0], Lt, ot],
539
+ "circle-stroke-width": 3,
540
+ "circle-stroke-color": rt,
541
+ "circle-opacity": ["case", ["==", ["get", "onFloor"], !0], 0.95, 0.4]
542
+ }
543
+ });
544
+ }
545
+ const n = t.showPlan && Me(t.project, t.floorId, t.threeD && t.stack).buried;
546
+ for (const y of [
547
+ "kerros-premises",
548
+ "kerros-premises-line",
549
+ "kerros-areas",
550
+ "kerros-outline",
551
+ "kerros-detail",
552
+ "kerros-walls",
553
+ "kerros-context-upper",
554
+ "kerros-hover"
555
+ ])
556
+ e.setLayoutProperty(y, "visibility", t.threeD || !t.showPlan ? "none" : "visible");
557
+ e.getLayer("kerros-underground") && (e.setLayoutProperty("kerros-underground", "visibility", n && !t.threeD ? "visible" : "none"), e.setPaintProperty("kerros-underground", "fill-color", "#15130f"));
558
+ const i = (1 - xt(t.sun).day) * (t.dark || n ? 0 : 1), d = Co(t.sun);
559
+ e.setLight({
560
+ anchor: "map",
561
+ position: d.mapPosition,
562
+ color: d.color,
563
+ intensity: 0.28 + 0.14 * xt(t.sun).day
564
+ });
565
+ const l = xt(t.sun).day;
566
+ e.setSky({
567
+ "sky-color": t.dark ? "#172435" : Tr("#5d6488", "#92b9d2", l),
568
+ "horizon-color": t.dark ? "#343b4c" : Tr("#d9ac92", "#e8e4d9", l),
569
+ "sky-horizon-blend": 0.65,
570
+ "atmosphere-blend": t.threeD && !n ? 0.65 : 0
571
+ }), e.setLayoutProperty("kerros-dim", "visibility", t.dark || n || i > 0.02 ? "visible" : "none"), e.setPaintProperty("kerros-dim", "fill-color", i > 0 ? "#141a2b" : "#0d0f16"), e.setPaintProperty("kerros-dim", "fill-opacity", i > 0 ? 0.42 * i : 0.55), e.setPaintProperty("kerros-premises", "fill-color", t.dark ? "#232734" : "#f3f4f0"), e.setPaintProperty("kerros-premises-line", "line-color", t.dark ? "#565d73" : "#9aa0ac"), e.setLayoutProperty("kerros-plan-dim", "visibility", t.dark && !t.threeD && t.showPlan ? "visible" : "none");
572
+ const s = !t.threeD && !!t.route;
573
+ for (const y of [
574
+ "kerros-route-casing",
575
+ "kerros-route",
576
+ "kerros-route-flow",
577
+ "kerros-route-off",
578
+ "kerros-route-arrows",
579
+ "kerros-route-vertical"
580
+ ])
581
+ e.setLayoutProperty(y, "visibility", s ? "visible" : "none");
582
+ const a = !t.threeD && t.canEdit && (t.tool === "route" || !!((c = t.project.navNodes) != null && c.some((y) => y.id === t.selected)) || !!((v = t.project.navEdges) != null && v.some((y) => y.id === t.selected)));
583
+ for (const y of ["kerros-navgraph-edge", "kerros-navgraph-node"])
584
+ e.setLayoutProperty(y, "visibility", a ? "visible" : "none");
585
+ e.setPaintProperty("kerros-route-casing", "line-color", rt);
586
+ {
587
+ const y = pe.current;
588
+ if (y != null && y.route || y != null && y.routeActive) {
589
+ const j = y.routeActive ?? Lt, $ = y.route ?? ot;
590
+ e.setPaintProperty("kerros-route", "line-color", [
591
+ "case",
592
+ ["==", ["get", "active"], !0],
593
+ j,
594
+ $
595
+ ]), e.setPaintProperty("kerros-route-vertical", "circle-color", [
596
+ "case",
597
+ ["==", ["get", "active"], !0],
598
+ j,
599
+ $
600
+ ]), e.setPaintProperty("kerros-route-off", "line-color", $);
601
+ }
602
+ }
603
+ e.setPaintProperty("kerros-route-vertical", "circle-stroke-color", rt), e.setPaintProperty("kerros-navgraph-node", "circle-stroke-color", t.dark ? "#14161f" : "#ffffff"), e.getLayer("background") && e.setPaintProperty("background", "background-color", t.dark ? "#14161f" : "#e6e8e4");
604
+ const u = (F = (R = t.basemap) == null ? void 0 : R.vectorSchema) == null ? void 0 : F.footprints, f = (C = (p = t.basemap) == null ? void 0 : p.vectorSchema) == null ? void 0 : C.context, k = u || f ? (T = Object.entries(e.getStyle().sources).find(([, y]) => y.type === "vector")) == null ? void 0 : T[0] : void 0;
605
+ if (k && u && (e.getLayer("kerros-city-3d") || e.addLayer(
606
+ {
607
+ id: "kerros-city-3d",
608
+ type: "fill-extrusion",
609
+ source: k,
610
+ "source-layer": u.sourceLayer,
611
+ paint: {
612
+ "fill-extrusion-opacity": 1,
613
+ "fill-extrusion-vertical-gradient": !0,
614
+ "fill-extrusion-height": u.heightExpression ?? 6.5
615
+ }
616
+ },
617
+ e.getLayer("kerros-3d") ? "kerros-3d" : void 0
618
+ ), e.setLayoutProperty(
619
+ "kerros-city-3d",
620
+ "visibility",
621
+ t.threeD && t.cityBuildings && !n ? "visible" : "none"
622
+ ), e.setPaintProperty(
623
+ "kerros-city-3d",
624
+ "fill-extrusion-color",
625
+ t.dark ? "#343a49" : [
626
+ "interpolate",
627
+ ["linear"],
628
+ ["to-number", u.heightExpression ?? 6.5],
629
+ 0,
630
+ "#c5beaf",
631
+ 12,
632
+ "#bcb7aa",
633
+ 30,
634
+ "#b0b4af",
635
+ 70,
636
+ "#a3adb0"
637
+ ]
638
+ ), Jt()), k && f) {
639
+ f.waterLayer && !e.getLayer("kerros-ug-water") && e.addLayer(
640
+ {
641
+ id: "kerros-ug-water",
642
+ type: "fill",
643
+ source: k,
644
+ "source-layer": f.waterLayer,
645
+ paint: { "fill-color": "#10151b", "fill-opacity": 0.55 }
646
+ },
647
+ "kerros-premises"
648
+ ), f.roadLayer && !e.getLayer("kerros-ug-roads") && e.addLayer(
649
+ {
650
+ id: "kerros-ug-roads",
651
+ type: "line",
652
+ source: k,
653
+ "source-layer": f.roadLayer,
654
+ paint: {
655
+ "line-color": "#7d766a",
656
+ "line-opacity": 0.33,
657
+ "line-width": ["interpolate", ["linear"], ["zoom"], 13, 0.5, 16, 2.5, 19, 8],
658
+ "line-dasharray": [4, 3]
659
+ }
660
+ },
661
+ "kerros-premises"
662
+ ), f.buildingLayer && !e.getLayer("kerros-ug-buildings") && e.addLayer(
663
+ {
664
+ id: "kerros-ug-buildings",
665
+ type: "line",
666
+ source: k,
667
+ "source-layer": f.buildingLayer,
668
+ paint: { "line-color": "#8a8375", "line-opacity": 0.4, "line-width": 1 }
669
+ },
670
+ "kerros-premises"
671
+ );
672
+ for (const y of ["kerros-ug-water", "kerros-ug-roads", "kerros-ug-buildings"])
673
+ e.getLayer(y) && e.setLayoutProperty(y, "visibility", n && !t.threeD ? "visible" : "none");
674
+ }
675
+ const g = (he = (ne = t.basemap) == null ? void 0 : ne.vectorSchema) == null ? void 0 : he.cadastre;
676
+ if (g) {
677
+ e.getSource("kerros-cadastre") || (e.addSource("kerros-cadastre", { type: "vector", url: g.tilejson, attribution: g.attribution }), e.addLayer(
678
+ {
679
+ id: "kerros-cadastre-fill",
680
+ type: "fill",
681
+ source: "kerros-cadastre",
682
+ "source-layer": g.parcelLayer,
683
+ paint: { "fill-color": "rgba(255,255,255,0.02)" }
684
+ },
685
+ "kerros-premises"
686
+ ), e.addLayer(
687
+ {
688
+ id: "kerros-cadastre-line",
689
+ type: "line",
690
+ source: "kerros-cadastre",
691
+ "source-layer": g.boundaryLayer,
692
+ paint: { "line-width": 1, "line-dasharray": [5, 2, 1, 2] }
693
+ },
694
+ "kerros-premises"
695
+ ), e.addLayer(
696
+ {
697
+ id: "kerros-cadastre-mark",
698
+ type: "circle",
699
+ source: "kerros-cadastre",
700
+ "source-layer": g.markLayer,
701
+ minzoom: 17,
702
+ paint: { "circle-radius": 2.4, "circle-stroke-width": 1 }
703
+ },
704
+ "kerros-premises"
705
+ ), e.addLayer(
706
+ {
707
+ id: "kerros-cadastre-label",
708
+ type: "symbol",
709
+ source: "kerros-cadastre",
710
+ "source-layer": g.labelLayer,
711
+ minzoom: 15.5,
712
+ layout: {
713
+ "text-field": ["get", g.labelField],
714
+ "text-font": [g.font],
715
+ "text-size": 10.5,
716
+ "text-padding": 12
717
+ },
718
+ paint: {}
719
+ },
720
+ "kerros-premises"
721
+ ));
722
+ for (const y of [
723
+ "kerros-cadastre-fill",
724
+ "kerros-cadastre-line",
725
+ "kerros-cadastre-mark",
726
+ "kerros-cadastre-label"
727
+ ])
728
+ e.setLayoutProperty(y, "visibility", t.cadastre && !n ? "visible" : "none");
729
+ e.setPaintProperty("kerros-cadastre-line", "line-color", t.dark ? "#8d80c9" : "#a5674f"), e.setPaintProperty("kerros-cadastre-line", "line-opacity", t.dark ? 0.75 : 0.8), e.setPaintProperty("kerros-cadastre-mark", "circle-color", t.dark ? "#8d80c9" : "#a5674f"), e.setPaintProperty("kerros-cadastre-mark", "circle-stroke-color", t.dark ? "#14161f" : "#ffffff"), e.setPaintProperty("kerros-cadastre-label", "text-color", t.dark ? "#a89ddb" : "#96604c"), e.setPaintProperty("kerros-cadastre-label", "text-halo-color", t.dark ? "#14161f" : "#f4f2ee"), e.setPaintProperty("kerros-cadastre-label", "text-halo-width", 1.1);
730
+ }
731
+ if (t.threeD && t.showPlan) {
732
+ if (!e.getLayer("kerros-3d")) {
733
+ const y = Nt.current;
734
+ if (!y) return;
735
+ E.current = new y(), e.addLayer(E.current), E.current.animateIn();
736
+ }
737
+ for (const y of ["kerros-dim", "kerros-underground"]) e.getLayer(y) && e.moveLayer(y, "kerros-3d");
738
+ (M = E.current) == null || M.setMapStyle(pe.current), (Q = E.current) == null || Q.update(
739
+ t.project,
740
+ t.floorId,
741
+ t.stack,
742
+ t.selected,
743
+ t.sun,
744
+ Ve.current ? new Map(
745
+ [...t.statuses].map(([y, j]) => {
746
+ const $ = t.project.objects.find((ge) => ge.id === Ve.current);
747
+ return [
748
+ y,
749
+ y === ($ == null ? void 0 : $.feedId) ? {
750
+ ...j,
751
+ carFloorId: t.floorId ?? void 0,
752
+ targetFloorId: void 0,
753
+ open: j.carFloorId === t.floorId && !j.targetFloorId && j.open
754
+ } : j
755
+ ];
756
+ })
757
+ ) : t.statuses,
758
+ t.excavation ?? !1,
759
+ t.walk ?? !1
760
+ ), (N = E.current) == null || N.setRoute(t.route ?? null, t.activeStep ?? null);
761
+ } else {
762
+ e.getLayer("kerros-3d") && (e.removeLayer("kerros-3d"), E.current = null);
763
+ for (const y of ["kerros-dim", "kerros-underground"])
764
+ e.getLayer(y) && e.moveLayer(y, "kerros-premises");
765
+ }
766
+ const b = new Set(t.project.drawings.map((y) => `drawing-${y.id}`));
767
+ for (const y of Object.keys(e.getStyle().sources).filter((j) => j.startsWith("drawing-") && !b.has(j)))
768
+ e.getLayer(y) && e.removeLayer(y), e.removeSource(y);
769
+ for (const y of t.project.drawings) {
770
+ const j = `drawing-${y.id}`, $ = de.current.get(y.assetId);
771
+ if (!$) continue;
772
+ const ge = Mo(y).map((me) => ce(me, t.project.origin));
773
+ e.getSource(j) ? (e.getSource(j).setCoordinates(ge), e.setPaintProperty(j, "raster-opacity", y.opacity)) : (e.addSource(j, { type: "image", url: $, coordinates: ge }), e.addLayer(
774
+ { id: j, source: j, type: "raster", paint: { "raster-opacity": y.opacity, "raster-fade-duration": 0 } },
775
+ "kerros-outline"
776
+ )), e.setLayoutProperty(j, "visibility", y.visible && y.floorId === t.floorId && !t.threeD ? "visible" : "none");
777
+ }
778
+ };
779
+ A(() => {
780
+ var g, b;
781
+ if (!Z.current) return;
782
+ let e;
783
+ const t = r.initialCamera;
784
+ try {
785
+ e = new et.Map({
786
+ container: Z.current,
787
+ style: $r.style,
788
+ transformRequest: (g = r.basemap) == null ? void 0 : g.transformRequest,
789
+ center: (t == null ? void 0 : t.center) ?? ce([0, -1], r.project.origin),
790
+ zoom: (t == null ? void 0 : t.zoom) ?? 18.5,
791
+ bearing: (t == null ? void 0 : t.bearing) ?? Ft(r.project),
792
+ pitch: (t == null ? void 0 : t.pitch) ?? 0,
793
+ // The plan camera's ceiling. Walk mode needs more — its eye is 2 m off the floor — and
794
+ // raises it to its own while it has the map, rather than letting the plan scroll in that far.
795
+ maxZoom: Xo,
796
+ minZoom: 5,
797
+ // Walk mode looks along the floor, a degree short of level. The default ceiling of 60° keeps
798
+ // the horizon off screen; 85 is as far as the plan camera's own drag will tilt, and the walk
799
+ // raises it to its own limit while it has the map.
800
+ maxPitch: 85,
801
+ attributionControl: !1,
802
+ canvasContextAttributes: { antialias: !0 },
803
+ dragRotate: !1,
804
+ pitchWithRotate: !1
805
+ });
806
+ } catch (c) {
807
+ W(`The map could not start: ${String(c)}`);
808
+ return;
809
+ }
810
+ P.current = e, e.addControl(new et.AttributionControl({ compact: !0 }), "bottom-right"), e.doubleClickZoom.disable();
811
+ let o = 0;
812
+ e.on("pitch", () => {
813
+ const c = performance.now();
814
+ c - o > 100 && (o = c, Ct(e.getPitch()));
815
+ }), e.on("pitchend", () => Ct(e.getPitch()));
816
+ let n;
817
+ const i = () => to(e), d = () => {
818
+ clearTimeout(n), n = setTimeout(() => ro(e), 220);
819
+ };
820
+ e.on("pitchstart", i), e.on("rotatestart", i), e.on("pitchend", d), e.on("rotateend", d), e.on("style.load", () => {
821
+ Ye.current = !0, Xe.current = "", Zt.current = /* @__PURE__ */ new Set(), je.current = /* @__PURE__ */ new Map(), Ie.current.clear(), e.getLayer("kerros-3d") || (E.current = null), Re(), Vt(), We(!0), J((c) => c + 1), W("");
822
+ }), e.on("load", () => {
823
+ var c;
824
+ (c = r.onReady) == null || c.call(r, e), !r.initialCamera && !h.current.playing && !h.current.walk && st();
825
+ });
826
+ let l = 0;
827
+ const s = () => J((c) => c + 1);
828
+ e.on("move", () => {
829
+ const c = performance.now();
830
+ c - l > 150 && (l = c, s());
831
+ });
832
+ const a = () => {
833
+ var c;
834
+ (c = re.current) != null && c.playing || s();
835
+ };
836
+ e.on("moveend", a), e.on("zoomend", a), e.on("idle", a), e.on("error", (c) => {
837
+ const v = c.sourceId;
838
+ /source layer/i.test(c.error.message) || v === "kerros-cadastre" || /tile/i.test(c.error.message) || W(Fe.current.basemapUnavailable);
839
+ }), e.on("mousemove", (c) => {
840
+ var T, ne, he, M, Q;
841
+ const v = h.current, R = se([c.lngLat.lng, c.lngLat.lat], v.project.origin), F = e.unproject([c.point.x + 10, c.point.y]), p = se([F.lng, F.lat], v.project.origin);
842
+ v.onHover(R, Math.hypot(p[0] - R[0], p[1] - R[1]));
843
+ let C = null;
844
+ v.threeD ? (C = ((T = E.current) == null ? void 0 : T.pick(c.point)) ?? null, (ne = E.current) == null || ne.setHover(C)) : v.tool === "select" && !e.isMoving() && e.getLayer("kerros-areas") && (C = ((he = e.queryRenderedFeatures(
845
+ [
846
+ [c.point.x - 3, c.point.y - 3],
847
+ [c.point.x + 3, c.point.y + 3]
848
+ ],
849
+ { layers: ["kerros-guide-line", "kerros-walls", "kerros-areas"].filter((y) => e.getLayer(y)) }
850
+ ).find(
851
+ (y) => y.properties.id && !["parcel", "building", "coverage", "status-halo", "furniture"].includes(y.properties.kind)
852
+ )) == null ? void 0 : he.properties.id) ?? null), C !== Tt.current && (Tt.current = C, (Q = (M = h.current).onHoverObject) == null || Q.call(M, C), e.getLayer("kerros-hover") && e.setFilter("kerros-hover", [
853
+ "all",
854
+ ["==", ["geometry-type"], "Polygon"],
855
+ ["==", ["get", "id"], C ?? ""]
856
+ ])), (v.tool === "select" || v.threeD) && (e.getCanvas().style.cursor = C ? "pointer" : "");
857
+ }), e.on("move", He), e.on("render", () => {
858
+ h.current.threeD && He();
859
+ });
860
+ const u = new ResizeObserver(() => {
861
+ e.resize(), He();
862
+ });
863
+ u.observe(Z.current);
864
+ const f = (c) => {
865
+ c.target.closest(".map-overlay") && (c.preventDefault(), c.stopPropagation(), e.getCanvasContainer().dispatchEvent(
866
+ new WheelEvent("wheel", {
867
+ deltaX: c.deltaX,
868
+ deltaY: c.deltaY,
869
+ deltaMode: c.deltaMode,
870
+ clientX: c.clientX,
871
+ clientY: c.clientY,
872
+ ctrlKey: c.ctrlKey,
873
+ bubbles: !0,
874
+ cancelable: !0
875
+ })
876
+ ));
877
+ }, k = (b = Z.current) == null ? void 0 : b.parentElement;
878
+ return k == null || k.addEventListener("wheel", f, { capture: !0, passive: !1 }), e.on("idle", () => Jt()), e.on("click", (c) => {
879
+ var C;
880
+ if (Ke.current) {
881
+ Ke.current = !1;
882
+ return;
883
+ }
884
+ const v = h.current;
885
+ if (v.tool === "adopt" && v.canEdit && !v.threeD) {
886
+ Vr(c.point);
887
+ return;
888
+ }
889
+ const R = ["kerros-guide-line", "kerros-walls", "kerros-areas"].filter((T) => e.getLayer(T)), p = (v.threeD ? [] : e.queryRenderedFeatures(
890
+ [
891
+ [c.point.x - 3, c.point.y - 3],
892
+ [c.point.x + 3, c.point.y + 3]
893
+ ],
894
+ { layers: R }
895
+ )).find(
896
+ (T) => T.properties.id && T.properties.kind !== "parcel" && T.properties.kind !== "building" && T.properties.kind !== "coverage" && T.properties.kind !== "status-halo"
897
+ );
898
+ v.walk || v.onClick(
899
+ se([c.lngLat.lng, c.lngLat.lat], v.project.origin),
900
+ v.threeD ? ((C = E.current) == null ? void 0 : C.pick(c.point)) ?? null : (p == null ? void 0 : p.properties.id) ?? null
901
+ );
902
+ }), () => {
903
+ var c;
904
+ clearTimeout(n), (c = re.current) == null || c.stop(), re.current = null, u.disconnect(), k == null || k.removeEventListener("wheel", f, { capture: !0 }), de.current.forEach(URL.revokeObjectURL), de.current.clear(), e.getLayer("kerros-3d") && e.removeLayer("kerros-3d"), E.current = null, e.remove(), P.current = null;
905
+ };
906
+ }, []);
907
+ function st(e) {
908
+ const t = P.current;
909
+ if (!t) return;
910
+ const o = h.current;
911
+ if (o.walk) return;
912
+ const n = e !== void 0 ? [
913
+ ...o.project.junctions.filter((g) => g.floorId === e).map((g) => g.position),
914
+ ...o.project.objects.filter((g) => g.floorId === e).flatMap((g) => {
915
+ var b;
916
+ return ((b = g.rings) == null ? void 0 : b[0]) ?? [g.position];
917
+ })
918
+ ] : [], i = n.length ? n : [
919
+ ...o.project.junctions.filter((g) => g.floorId).map((g) => g.position),
920
+ ...o.project.objects.filter((g) => g.floorId).flatMap((g) => {
921
+ var b;
922
+ return ((b = g.rings) == null ? void 0 : b[0]) ?? [g.position];
923
+ })
924
+ ], d = i.length ? i : [...o.project.junctions.map((g) => g.position), ...o.project.objects.flatMap((g) => {
925
+ var b;
926
+ return ((b = g.rings) == null ? void 0 : b[0]) ?? [g.position];
927
+ })], l = d.length ? d : [
928
+ [-40, -30],
929
+ [40, 30]
930
+ ], s = new et.LngLatBounds();
931
+ for (const g of l) s.extend(ce(g, o.project.origin));
932
+ const a = t.cameraForBounds(s, {
933
+ padding: { top: 64, bottom: o.canEdit && !o.threeD ? 150 : 72, left: 42, right: 42 },
934
+ bearing: t.getBearing(),
935
+ maxZoom: 20.5
936
+ });
937
+ if (!a) return;
938
+ let u = a.zoom ?? t.getZoom();
939
+ const f = e === void 0 ? o.floorId : e, k = Me(o.project, f, o.stack).focusElevation;
940
+ if (o.threeD && k) {
941
+ const g = 78271.5169 * Math.cos(t.getCenter().lat * Math.PI / 180) / Math.pow(2, u), c = Wo(t) * g * Math.cos(t.getPitch() * Math.PI / 180), v = c + k;
942
+ v > 25 && (u += Math.log2(c / v));
943
+ const R = et.LngLat.convert(a.center);
944
+ a.center = Pt([R.lng, R.lat], k, t.getPitch(), t.getBearing());
945
+ }
946
+ ht(t, { center: a.center, zoom: u, bearing: t.getBearing(), duration: 650 });
947
+ }
948
+ A(() => {
949
+ Y && !r.playing && !r.walk && st(r.floorId);
950
+ }, [r.floorId, r.stack]), A(() => {
951
+ const e = P.current;
952
+ if (!e || !Y || !r.route || r.threeD) return;
953
+ let t = 0;
954
+ const o = window.setInterval(() => {
955
+ t = (t + 0.011) % 1, e.getLayer("kerros-route-flow") && e.setPaintProperty("kerros-route-flow", "line-gradient", zr(t));
956
+ }, 40);
957
+ return () => window.clearInterval(o);
958
+ }, [Y, r.route, r.threeD]);
959
+ const z = L(null), Ve = L(null), Ze = L(null), [Qt, Jr] = ae(null), [Gr, Qr] = ae(0), [er, tr] = ae(""), dt = (e) => {
960
+ var t, o;
961
+ Ve.current = e, Jr(e), (o = Ze.current) == null || o.set(
962
+ e ? { preset: "elevator", level: 0.5 } : Wr(h.current.project, h.current.floorId, ((t = z.current) == null ? void 0 : t.position) ?? [0, 0])
963
+ );
964
+ }, ut = L(null), [G, ft] = ae(nt), rr = () => {
965
+ const e = Ze.current;
966
+ if (e) {
967
+ e.setMuted(!e.isMuted), e.resume();
968
+ try {
969
+ localStorage.setItem(_r, e.isMuted ? "1" : "0");
970
+ } catch {
971
+ }
972
+ H.current = { ...H.current, sound: !e.isMuted }, ft(H.current);
973
+ }
974
+ }, [xe, eo] = ae(() => {
975
+ try {
976
+ return Br(Number(localStorage.getItem(Hr) ?? Or));
977
+ } catch {
978
+ return Or;
979
+ }
980
+ }), H = L(nt), or = L(0), nr = L(0), [Ce, Je] = ae(null), Le = (e = h.current.threeD && !h.current.walk) => {
981
+ const t = h.current;
982
+ return e ? Me(t.project, t.floorId, t.stack).focusElevation + Dt + Mt : 0;
983
+ }, Ne = (e, t, o, n = Le()) => {
984
+ const i = h.current, d = e.unproject([t, o]), l = n ? Pt([d.lng, d.lat], -n, e.getPitch(), e.getBearing()) : [d.lng, d.lat];
985
+ return se(l, i.project.origin);
986
+ }, gt = (e, t, o, n) => {
987
+ const i = ce(e, h.current.project.origin);
988
+ return Pt([i[0], i[1]], t, o, n);
989
+ }, $e = L(null), yt = L(!1), ht = (e, t) => {
990
+ yt.current = !0, $e.current = null;
991
+ const o = () => {
992
+ clearTimeout(n), e.off("moveend", o), yt.current = !1;
993
+ }, n = setTimeout(o, (t.duration ?? 300) + 400);
994
+ e.on("moveend", o), e.easeTo(t);
995
+ }, to = (e) => {
996
+ var i;
997
+ const t = h.current;
998
+ if ($e.current || yt.current || !t.threeD || t.walk || (i = re.current) != null && i.playing) return;
999
+ const { clientWidth: o, clientHeight: n } = e.getCanvas();
1000
+ $e.current = Ne(e, o / 2, n / 2);
1001
+ }, ro = (e) => {
1002
+ var i;
1003
+ const t = $e.current;
1004
+ $e.current = null;
1005
+ const o = h.current;
1006
+ if (!t || !o.threeD || o.walk || (i = re.current) != null && i.playing) return;
1007
+ const n = Le();
1008
+ n && e.easeTo({ center: gt(t, n, e.getPitch(), e.getBearing()), duration: 300 });
1009
+ }, oo = (e) => {
1010
+ var s, a;
1011
+ const t = P.current, o = Z.current;
1012
+ if (e.currentTarget.releasePointerCapture(e.pointerId), Je(null), !t || !o) return;
1013
+ const n = o.getBoundingClientRect(), i = e.clientX - n.left, d = e.clientY - n.top;
1014
+ if (i < 0 || d < 0 || i > n.width || d > n.height || (s = document.elementFromPoint(e.clientX, e.clientY)) != null && s.closest(".map-navigator, .canvas-top-left")) return;
1015
+ const l = h.current;
1016
+ (a = l.onWalkAt) == null || a.call(l, {
1017
+ floorId: l.floorId,
1018
+ position: Ne(t, i, d),
1019
+ // Facing up the screen: the way the map is turned is the way the person dropped on it faces.
1020
+ heading: t.getBearing() - (l.project.origin[2] ?? 0)
1021
+ });
1022
+ }, ve = le(() => r.walk ? Yo(r.project) : null, [r.walk, r.project]), ir = le(
1023
+ () => r.walk ? Uo(r.project, r.floorId) : [],
1024
+ [r.walk, r.project, r.floorId]
1025
+ ), Te = le(
1026
+ () => r.walk ? [
1027
+ ...r.project.objects.filter(
1028
+ (e) => e.kind === "elevator" && Ur(r.project).primary.has(e.id) && Yr(r.project, e).some((t) => t.id === r.floorId)
1029
+ ).flatMap((e) => {
1030
+ const t = r.statuses.get(e.feedId ?? "");
1031
+ return tn(
1032
+ e,
1033
+ !!(t != null && t.open) && !t.moving && !t.targetFloorId && t.carFloorId === r.floorId
1034
+ );
1035
+ }),
1036
+ ...ir,
1037
+ // What stands on the floor is as solid as what encloses it: a parked car, a column,
1038
+ // a desk. Anything lower than a step is walked over; a rug is a fixture too.
1039
+ ...r.project.objects.filter(
1040
+ (e) => e.floorId === r.floorId && e.kind === "fixture" && e.height >= 0.3 && (e.baseHeight ?? 0) < Et && !e.slide && e.model !== "vent"
1041
+ ).map((e) => So(e.position, e.width, e.depth, e.rotation))
1042
+ ] : [],
1043
+ [r.walk, r.project, r.floorId, r.statuses, ir]
1044
+ ), no = (e) => {
1045
+ var b;
1046
+ const t = h.current, o = e.getBearing() - (t.project.origin[2] ?? 0), n = (b = t.route) == null ? void 0 : b.nodes.find((c) => c.floorId === t.floorId);
1047
+ if (n) return { position: n.position, heading: o };
1048
+ const i = t.avatar, { clientWidth: d, clientHeight: l } = e.getCanvas();
1049
+ if (i && i.floorId === t.floorId) {
1050
+ const c = e.project(ce(i.position, t.project.origin));
1051
+ if (c.x >= 0 && c.y >= 0 && c.x <= d && c.y <= l) return i;
1052
+ }
1053
+ const s = Ko(e), a = s.altitude < 2 * (Et + Dt + Mt), u = s.lngLat, f = a ? se([u.lng, u.lat], t.project.origin) : Ne(e, d / 2, l / 2, Le(t.threeD)), k = (c) => ({ position: c, heading: o, pitch: a ? e.getPitch() : void 0 });
1054
+ if (!t.floorId || qr(t.project, t.floorId, f)) return k(f);
1055
+ const g = t.project.objects.filter((c) => {
1056
+ var v;
1057
+ return c.floorId === t.floorId && Do(c.kind) && ((v = c.rings) == null ? void 0 : v.length);
1058
+ }).sort((c, v) => bt(v) - bt(c));
1059
+ for (const c of g) {
1060
+ const v = Qo(t.project, c);
1061
+ if (Kr(c, v)) return k(v);
1062
+ }
1063
+ return k(f);
1064
+ }, io = (e) => {
1065
+ const t = h.current, o = t.route;
1066
+ if (!(o != null && o.nodes.length)) return "";
1067
+ let n = -1, i = Number.POSITIVE_INFINITY;
1068
+ if (o.nodes.forEach((a, u) => {
1069
+ if (a.floorId !== t.floorId) return;
1070
+ const f = It(a.position, e);
1071
+ f < i && (i = f, n = u);
1072
+ }), n < 0) return "";
1073
+ const d = o.nodes[n + 1] ?? o.nodes[n], l = o.steps.find((a) => a.nodeIds.includes(d.id)), s = Math.round(It(d.position, e));
1074
+ return l ? `${s} m · ${l.text}` : `${s} m along the route`;
1075
+ }, ar = (e) => {
1076
+ const t = h.current, o = Ur(t.project), i = [...o.objects.get(t.floorId) ?? [], ...o.reaching.get(t.floorId ?? "") ?? []].find(
1077
+ (f) => f.kind === "elevator" ? It(f.position, e) < Math.max(f.width, f.depth) / 2 + 2 : f.kind === "stairs" && Kr(f, e)
1078
+ ), d = t.project.floors.find((f) => f.id === t.floorId);
1079
+ if (!i || !d) return { shaft: null, up: null, down: null };
1080
+ const l = Yr(t.project, i), s = i.stairModel === "escalator" ? i.travel ?? "up" : null, a = l.filter((f) => f.elevation > d.elevation)[0] ?? null, u = l.filter((f) => f.elevation < d.elevation).slice(-1)[0] ?? null;
1081
+ return { shaft: i, up: s === "down" ? null : a, down: s === "up" ? null : u };
1082
+ };
1083
+ A(() => {
1084
+ const e = P.current;
1085
+ if (!e || !r.walk) return;
1086
+ const t = h.current, o = new Go();
1087
+ Ze.current = o;
1088
+ let n = !1;
1089
+ try {
1090
+ n = localStorage.getItem(_r) === "1";
1091
+ } catch {
1092
+ }
1093
+ o.setMuted(n);
1094
+ const i = () => o.resume();
1095
+ window.addEventListener("pointerdown", i, !0), window.addEventListener("keydown", i, !0);
1096
+ const d = new Vo({
1097
+ onPose: (a) => {
1098
+ var R, F, p;
1099
+ const u = performance.now();
1100
+ u - nr.current >= 400 && (nr.current = u, (F = (R = h.current).onAvatar) == null || F.call(R, {
1101
+ floorId: h.current.floorId,
1102
+ position: a.position,
1103
+ heading: a.heading,
1104
+ pitch: a.pitch
1105
+ }));
1106
+ const f = u - or.current >= 150;
1107
+ if (!f && a.looking === H.current.looking) return;
1108
+ const k = f ? ar(a.position) : null, { up: g, down: b } = ((p = k == null ? void 0 : k.shaft) == null ? void 0 : p.kind) === "stairs" ? k : { up: null, down: null }, c = f ? qr(h.current.project, h.current.floorId, a.position) : null;
1109
+ f && (or.current = u, o.set(
1110
+ Ve.current ? { preset: "elevator", level: 0.5 } : Wr(h.current.project, h.current.floorId, a.position)
1111
+ ));
1112
+ const v = f ? {
1113
+ looking: a.looking,
1114
+ sound: !o.isMuted,
1115
+ up: (g == null ? void 0 : g.name) ?? null,
1116
+ down: (b == null ? void 0 : b.name) ?? null,
1117
+ where: (c == null ? void 0 : c.name) ?? "",
1118
+ next: io(a.position)
1119
+ } : { ...H.current, looking: a.looking };
1120
+ (v.looking !== H.current.looking || v.up !== H.current.up || v.down !== H.current.down || v.where !== H.current.where || v.next !== H.current.next) && (H.current = v, ft(v));
1121
+ },
1122
+ onUse: (a) => {
1123
+ var k, g, b, c;
1124
+ const u = ar(((k = z.current) == null ? void 0 : k.position) ?? [0, 0]);
1125
+ if (((g = u.shaft) == null ? void 0 : g.kind) === "elevator") {
1126
+ h.current.elevators && Qr((v) => v + 1);
1127
+ return;
1128
+ }
1129
+ const f = a ? u.down : u.up;
1130
+ f && ((c = (b = h.current).onRequestFloor) == null || c.call(b, f.id));
1131
+ },
1132
+ onDrop: (a) => {
1133
+ var u, f;
1134
+ return (f = (u = h.current).onRequestFloor) == null ? void 0 : f.call(u, a);
1135
+ },
1136
+ onFloor: (a) => {
1137
+ var u, f;
1138
+ return (f = (u = h.current).onRequestFloor) == null ? void 0 : f.call(u, a);
1139
+ },
1140
+ onExit: () => {
1141
+ var a, u;
1142
+ return (u = (a = h.current).onWalkExit) == null ? void 0 : u.call(a);
1143
+ },
1144
+ onSound: rr
1145
+ });
1146
+ z.current = d;
1147
+ const l = no(e), s = St(St(l.position, Te, 1), Te);
1148
+ return d.setFieldOfView(xe), d.attach(e, t.project.origin, { ...l, position: s }), () => {
1149
+ var f, k;
1150
+ const a = d.pose;
1151
+ d.detach(), o.dispose(), Ze.current = null, window.removeEventListener("pointerdown", i, !0), window.removeEventListener("keydown", i, !0);
1152
+ const u = {
1153
+ floorId: h.current.floorId,
1154
+ position: a.position,
1155
+ heading: a.heading,
1156
+ pitch: a.pitch
1157
+ };
1158
+ ut.current = u, (k = (f = h.current).onAvatar) == null || k.call(f, u), z.current = null, dt(null), H.current = nt, ft(nt);
1159
+ };
1160
+ }, [r.walk]), A(() => {
1161
+ var e;
1162
+ (e = z.current) == null || e.setFieldOfView(xe);
1163
+ }, [xe]);
1164
+ const lr = L(r.floorId), cr = le(
1165
+ () => r.walk ? Ho(r.project, r.statuses) : [],
1166
+ [r.walk, r.project, r.statuses]
1167
+ );
1168
+ A(() => {
1169
+ var e, t;
1170
+ if ((t = z.current) == null || t.setTerrain({
1171
+ walls: Te,
1172
+ eye: Et + Dt + Mt,
1173
+ floorId: r.floorId,
1174
+ elevation: ((e = r.project.floors.find((o) => o.id === r.floorId)) == null ? void 0 : e.elevation) ?? 0,
1175
+ stairs: cr,
1176
+ supports: ve == null ? void 0 : ve.supports,
1177
+ dropAt: (o) => ve == null ? void 0 : ve.dropAt(o, r.floorId)
1178
+ }), lr.current !== r.floorId && z.current && !z.current.onStairs) {
1179
+ const o = z.current.position, n = _o(r.project, r.floorId, o);
1180
+ n !== o && z.current.place(St(n, Te));
1181
+ }
1182
+ lr.current = r.floorId;
1183
+ }, [Te, cr, ve]);
1184
+ const sr = (e) => new Promise((t) => {
1185
+ var a;
1186
+ const o = P.current;
1187
+ if (!o) return t();
1188
+ const n = ((a = E.current) == null ? void 0 : a.diagnostics.revision) ?? -1;
1189
+ let i = 0;
1190
+ const d = () => {
1191
+ clearTimeout(l), o.off("render", s), t();
1192
+ }, l = setTimeout(d, 5e3), s = () => {
1193
+ var f;
1194
+ const u = h.current;
1195
+ if (u.floorId !== e) {
1196
+ i = 0;
1197
+ return;
1198
+ }
1199
+ (u.threeD ? (((f = E.current) == null ? void 0 : f.diagnostics.revision) ?? n + 1) > n : ++i >= 2) && d();
1200
+ };
1201
+ o.on("render", s), o.triggerRepaint();
1202
+ });
1203
+ A(() => {
1204
+ var n, i, d;
1205
+ const e = P.current;
1206
+ if (!r.playing || r.walk) {
1207
+ (n = re.current) == null || n.stop();
1208
+ return;
1209
+ }
1210
+ if (!e || !Y || re.current) return;
1211
+ const t = h.current.route;
1212
+ if (!t) {
1213
+ (d = (i = h.current).onJourneyEnd) == null || d.call(i);
1214
+ return;
1215
+ }
1216
+ let o = !1;
1217
+ return import("./journey.js").then(({ JourneyPlayer: l }) => {
1218
+ if (o) return;
1219
+ const s = new l(e, {
1220
+ requestFloor: (a) => {
1221
+ var u, f;
1222
+ return (f = (u = h.current).onRequestFloor) == null ? void 0 : f.call(u, a);
1223
+ },
1224
+ waitForFloor: sr,
1225
+ focusElevation: (a) => h.current.threeD ? Me(h.current.project, a, h.current.stack).focusElevation : 0,
1226
+ onStep: (a) => {
1227
+ var u, f;
1228
+ return (f = (u = h.current).onJourneyStep) == null ? void 0 : f.call(u, a);
1229
+ },
1230
+ onEnd: () => {
1231
+ var a, u;
1232
+ re.current = null, J((f) => f + 1), (u = (a = h.current).onJourneyEnd) == null || u.call(a);
1233
+ }
1234
+ });
1235
+ re.current = s, s.play(t, { origin: h.current.project.origin, startFloorId: h.current.floorId });
1236
+ }).catch((l) => {
1237
+ var s, a;
1238
+ o || (W(`Route playback could not load: ${String(l)}`), (a = (s = h.current).onJourneyEnd) == null || a.call(s));
1239
+ }), () => {
1240
+ var l;
1241
+ o = !0, (l = re.current) == null || l.stop();
1242
+ };
1243
+ }, [r.playing, r.walk, Y]), A(() => {
1244
+ var d, l;
1245
+ if (!r.playing || !r.walk || !z.current) return;
1246
+ const e = h.current.route;
1247
+ if (!e) {
1248
+ (l = (d = h.current).onJourneyEnd) == null || l.call(d);
1249
+ return;
1250
+ }
1251
+ let t = !1, o;
1252
+ const n = {
1253
+ project: h.current.project,
1254
+ floor: () => h.current.floorId,
1255
+ changeFloor: async (s) => {
1256
+ var a, u;
1257
+ if (h.current.floorId !== s && ((u = (a = h.current).onRequestFloor) == null || u.call(a, s), await sr(s), h.current.floorId !== s))
1258
+ throw new Error("The requested floor is not available.");
1259
+ },
1260
+ position: () => {
1261
+ var s;
1262
+ return ((s = z.current) == null ? void 0 : s.position) ?? [0, 0];
1263
+ },
1264
+ walk: (s, a) => new Promise((u, f) => {
1265
+ if (t || !z.current) {
1266
+ f(new Error("Route playback stopped."));
1267
+ return;
1268
+ }
1269
+ z.current.follow(s, u, {
1270
+ ...a,
1271
+ onCancel: () => f(new Error("Route playback stopped at an obstruction or by movement."))
1272
+ });
1273
+ }),
1274
+ controls: () => h.current.elevators,
1275
+ status: (s) => {
1276
+ var a;
1277
+ return ((a = h.current.elevators) == null ? void 0 : a.statuses.find((u) => u.feedId === s)) ?? h.current.statuses.get(s);
1278
+ },
1279
+ ride: dt,
1280
+ message: (s) => {
1281
+ t || tr(s);
1282
+ },
1283
+ step: (s) => {
1284
+ var a, u;
1285
+ return (u = (a = h.current).onJourneyStep) == null ? void 0 : u.call(a, s);
1286
+ }
1287
+ }, i = (s) => {
1288
+ var a, u;
1289
+ [
1290
+ "KeyW",
1291
+ "KeyA",
1292
+ "KeyS",
1293
+ "KeyD",
1294
+ "KeyQ",
1295
+ "KeyE",
1296
+ "ArrowUp",
1297
+ "ArrowDown",
1298
+ "ArrowLeft",
1299
+ "ArrowRight",
1300
+ "Escape"
1301
+ ].includes(s.code) && ((u = (a = h.current).onJourneyEnd) == null || u.call(a));
1302
+ };
1303
+ return window.addEventListener("keydown", i, !0), import("./walkJourney.js").then(({ WalkJourney: s }) => {
1304
+ if (!t)
1305
+ return o = new s(n), o.play(e);
1306
+ }).catch((s) => {
1307
+ t || tr(s instanceof Error ? s.message : "Route playback stopped.");
1308
+ }).finally(() => {
1309
+ var s, a;
1310
+ t || (a = (s = h.current).onJourneyEnd) == null || a.call(s);
1311
+ }), () => {
1312
+ var s;
1313
+ t = !0, o == null || o.stop(), (s = z.current) == null || s.cancelFollow(), window.removeEventListener("keydown", i, !0);
1314
+ };
1315
+ }, [r.playing, r.walk]);
1316
+ const dr = L(!0);
1317
+ A(() => {
1318
+ const e = P.current;
1319
+ if (!e) return;
1320
+ const t = new AbortController(), o = r.basemap ?? $r;
1321
+ return en(o, t.signal).then((n) => {
1322
+ t.signal.aborted || (e.setTransformRequest(o.transformRequest ?? ((i) => ({ url: i }))), Ye.current = !1, e.getLayer("kerros-3d") && e.removeLayer("kerros-3d"), E.current = null, e.setStyle(n, { diff: !1 }));
1323
+ }).catch((n) => {
1324
+ n.name !== "AbortError" && W(Fe.current.basemapUnavailablePlan);
1325
+ }), () => t.abort();
1326
+ }, [r.basemap]), A(() => {
1327
+ Re();
1328
+ }, [
1329
+ r.project,
1330
+ r.floorId,
1331
+ r.selected,
1332
+ r.threeD,
1333
+ r.stack,
1334
+ r.coverage,
1335
+ r.showPlan,
1336
+ r.sun,
1337
+ r.dark,
1338
+ r.cityBuildings,
1339
+ r.cadastre,
1340
+ r.statuses,
1341
+ Qt,
1342
+ r.route,
1343
+ r.activeStep,
1344
+ r.tool,
1345
+ r.canEdit,
1346
+ // The walk builds a different scene — the floor on the ground plane, a ceiling on it, the
1347
+ // batches cut for culling — and leaving it has to build the plan's scene back. Without this the
1348
+ // 3D view kept the walk's, and a garage came back as its deck lifted to street level, lidded,
1349
+ // inside the cage of the levels above it.
1350
+ r.walk,
1351
+ r.excavation,
1352
+ Y
1353
+ ]), A(() => {
1354
+ Gt();
1355
+ }, [it, r.draft, r.hover, r.guides, r.tool, Y]), A(() => {
1356
+ He();
1357
+ }), A(() => {
1358
+ let e = !1;
1359
+ const t = new Set(r.project.drawings.map((n) => n.assetId));
1360
+ for (const [n, i] of de.current)
1361
+ t.has(n) || (URL.revokeObjectURL(i), de.current.delete(n));
1362
+ let o = null;
1363
+ return Promise.all(
1364
+ r.project.drawings.map(async (n) => {
1365
+ if (de.current.has(n.assetId)) return;
1366
+ const i = await r.assets.get(n.assetId).catch(() => {
1367
+ });
1368
+ i ? e || de.current.set(n.assetId, URL.createObjectURL(i)) : o = n.name;
1369
+ })
1370
+ ).then(() => {
1371
+ e || (Re(), o && r.onError(`Reference image “${o}” is missing.`));
1372
+ }), () => {
1373
+ e = !0;
1374
+ };
1375
+ }, [r.project.drawings, r.assets]);
1376
+ const ur = L({ threeD: r.threeD, walk: r.walk });
1377
+ A(() => {
1378
+ var a;
1379
+ const e = P.current;
1380
+ if (!e) return;
1381
+ const t = ur.current;
1382
+ ur.current = { threeD: r.threeD, walk: r.walk };
1383
+ const o = dr.current && !!r.initialCamera || r.walk || r.playing;
1384
+ dr.current = !1;
1385
+ const n = r.threeD ? 35 : 0, i = Ft(r.project) + (r.threeD ? -12 : 0), { clientWidth: d, clientHeight: l } = e.getCanvas(), s = t.walk && !r.walk ? ut.current ?? r.avatar : null;
1386
+ if (ut.current = null, s) {
1387
+ const u = s.heading + (r.project.origin[2] ?? 0);
1388
+ ht(e, {
1389
+ center: gt(s.position, Le(r.threeD), n, u),
1390
+ zoom: 20,
1391
+ // room scale: the floor the walk happened on, not the whole storey
1392
+ pitch: n,
1393
+ bearing: u,
1394
+ duration: 700
1395
+ });
1396
+ } else if (!o) {
1397
+ const u = Ne(e, d / 2, l / 2, Le(t.threeD && !t.walk)), f = t.threeD !== r.threeD ? gt(u, Le(r.threeD), n, i) : null;
1398
+ ht(e, { ...f ? { center: f } : {}, pitch: n, bearing: i, duration: 600 });
1399
+ }
1400
+ if (r.walk)
1401
+ for (const u of ["dragPan", "dragRotate", "scrollZoom", "keyboard", "touchZoomRotate"]) (a = e[u]) == null || a.disable();
1402
+ else r.threeD ? (e.dragRotate.enable(), e.touchZoomRotate.enableRotation()) : (e.dragRotate.disable(), e.touchZoomRotate.disableRotation());
1403
+ }, [r.threeD, r.walk]), A(() => {
1404
+ const e = P.current;
1405
+ !e || r.walk || (e.getCanvas().style.cursor = r.tool === "pan" ? "grab" : r.tool === "select" ? "" : "crosshair");
1406
+ }, [r.tool, r.walk]), A(() => {
1407
+ var o;
1408
+ const e = P.current;
1409
+ if (r.playing) return;
1410
+ const t = r.project.objects.find((n) => n.id === r.focusId);
1411
+ if (r.walk) {
1412
+ t && ((o = z.current) == null || o.lookAt(Be(r.project, t)));
1413
+ return;
1414
+ }
1415
+ e && t && e.easeTo({
1416
+ center: qo(e, r.project, Be(r.project, t), t.floorId, r),
1417
+ duration: 500
1418
+ });
1419
+ }, [r.focusId]);
1420
+ const q = (e) => {
1421
+ var t;
1422
+ return (t = P.current) == null ? void 0 : t.project(ce(e, r.project.origin));
1423
+ };
1424
+ function ue(e, t, o, n, i) {
1425
+ e.stopPropagation(), e.preventDefault();
1426
+ const d = P.current;
1427
+ if (!d || !r.canEdit || (t === "node" ? !_e : r.tool !== "select")) return;
1428
+ d.dragPan.disable();
1429
+ const l = e.currentTarget, s = l.getBoundingClientRect(), a = Number(l.dataset.screenDx ?? 0) + e.clientX - s.left - s.width / 2, u = Number(l.dataset.screenDy ?? 0) + e.clientY - s.top - s.height / 2, f = [l.dataset.wx, l.dataset.wy], k = { x: e.clientX, y: e.clientY };
1430
+ let g = !1;
1431
+ const b = (p, C, T = !1) => {
1432
+ var $, ge, me, Ae, De, ke;
1433
+ const ne = d.getContainer().getBoundingClientRect(), he = d.unproject([p - ne.left - a, C - ne.top - u]), M = h.current, Q = se([he.lng, he.lat], M.project.origin), N = t === "junction" || t === "barrier" || t === "ring" ? (($ = M.onVertexPreview) == null ? void 0 : $.call(M, t, o, Q, n, i, T)) ?? Q : M.snapping && !T && (t === "object" || t === "node") ? [Math.round(Q[0] * 2) / 2, Math.round(Q[1] * 2) / 2] : Q, y = d.project(ce(N, M.project.origin));
1434
+ l.dataset.wx = String(N[0]), l.dataset.wy = String(N[1]), l.style.left = `${y.x + Number(l.dataset.screenDx ?? 0)}px`, l.style.top = `${y.y + Number(l.dataset.screenDy ?? 0)}px`;
1435
+ const j = [];
1436
+ if (t === "object") {
1437
+ const w = M.project.objects.find((I) => I.id === o);
1438
+ if (w != null && w.rings) {
1439
+ const I = N[0] - w.position[0], x = N[1] - w.position[1];
1440
+ j.push(Nr(w.rings[0].map((B) => [B[0] + I, B[1] + x])));
1441
+ }
1442
+ } else if (t === "ring") {
1443
+ const w = M.project.objects.find((x) => x.id === o), I = (ge = w == null ? void 0 : w.rings) == null ? void 0 : ge[n ?? 0];
1444
+ if (I) {
1445
+ const x = pt(I);
1446
+ j.push([
1447
+ x[((i ?? 0) + x.length - 1) % x.length],
1448
+ N,
1449
+ x[((i ?? 0) + 1) % x.length]
1450
+ ]);
1451
+ }
1452
+ } else if (t === "barrier") {
1453
+ const w = Oe(M.project).find((I) => I.id === o);
1454
+ if (w) {
1455
+ const [I, x] = we(M.project, w), B = [(I[0] + x[0]) / 2, (I[1] + x[1]) / 2], _ = Math.hypot(x[0] - I[0], x[1] - I[1]), U = -(x[1] - I[1]) / _, ee = (x[0] - I[0]) / _, V = (N[0] - B[0]) * U + (N[1] - B[1]) * ee, te = U * V, K = ee * V, ie = [I[0] + te, I[1] + K], Qe = [x[0] + te, x[1] + K];
1456
+ j.push([ie, Qe]);
1457
+ for (const ze of Oe(M.project).filter(
1458
+ (be) => be.id !== o && (be.startId === w.startId || be.endId === w.startId || be.startId === w.endId || be.endId === w.endId)
1459
+ )) {
1460
+ const [be, fo] = we(M.project, ze), Mr = ze.startId === w.startId || ze.startId === w.endId, go = Mr ? fo : be, yo = (Mr ? ze.startId : ze.endId) === w.startId ? ie : Qe;
1461
+ j.push([go, yo]);
1462
+ }
1463
+ }
1464
+ } else if (t === "opening") {
1465
+ const w = M.project.objects.find((x) => x.id === o), I = M.project.barriers.find((x) => x.id === (w == null ? void 0 : w.barrierId));
1466
+ if (w && I) {
1467
+ const [x, B] = we(M.project, I), _ = Eo(N, x, B), U = w.width / 2;
1468
+ if (_.length >= w.width) {
1469
+ const ee = Math.max(U, Math.min(_.length - U, _.t * _.length)), V = (B[0] - x[0]) / _.length, te = (B[1] - x[1]) / _.length, K = [x[0] + V * ee, x[1] + te * ee];
1470
+ if (j.push([
1471
+ [K[0] - V * U, K[1] - te * U],
1472
+ [K[0] + V * U, K[1] + te * U]
1473
+ ]), w.kind === "door") {
1474
+ const Qe = { ...w, offset: ee, position: K, doorSwing: ho(M.project, w, N) };
1475
+ j.push(...mo(M.project, Qe));
1476
+ }
1477
+ const ie = I.thickness;
1478
+ j.push([
1479
+ [K[0] + te * ie, K[1] - V * ie],
1480
+ [K[0] - te * ie, K[1] + V * ie]
1481
+ ]);
1482
+ }
1483
+ }
1484
+ } else if (t === "rotate") {
1485
+ const w = M.project.objects.find((I) => I.id === o);
1486
+ if (w) {
1487
+ const I = Math.atan2(N[1] - w.position[1], N[0] - w.position[0]);
1488
+ if (j.push([w.position, N]), (me = w.rings) != null && me[0]) {
1489
+ const x = Math.cos(I - (w.rotation ?? 0) * Math.PI / 180), B = Math.sin(I - (w.rotation ?? 0) * Math.PI / 180);
1490
+ j.push(
1491
+ Nr(
1492
+ w.rings[0].map((_) => {
1493
+ const U = _[0] - w.position[0], ee = _[1] - w.position[1];
1494
+ return [w.position[0] + U * x - ee * B, w.position[1] + U * B + ee * x];
1495
+ })
1496
+ )
1497
+ );
1498
+ }
1499
+ }
1500
+ } else if (t === "coverage") {
1501
+ const w = M.project.objects.find((I) => I.id === o);
1502
+ if (w) {
1503
+ const I = N[0] - w.position[0], x = N[1] - w.position[1], B = Math.max(1, Math.min(120, Math.hypot(I, x))), _ = Math.atan2(x, I) * 180 / Math.PI, U = Math.min(
1504
+ 175,
1505
+ Math.max(5, Math.abs(((_ - (w.rotation ?? 0)) % 360 + 540) % 360 - 180))
1506
+ ), ee = (w.rotation ?? 0) * Math.PI / 180, V = [w.position], te = 24;
1507
+ for (let K = 0; K <= te; K++) {
1508
+ const ie = ee + (-U + 2 * U * K / te) * Math.PI / 180;
1509
+ V.push([w.position[0] + Math.cos(ie) * B, w.position[1] + Math.sin(ie) * B]);
1510
+ }
1511
+ V.push(w.position), j.push(V);
1512
+ }
1513
+ } else if (t === "node") {
1514
+ const w = (Ae = M.project.navNodes) == null ? void 0 : Ae.find((I) => I.id === o);
1515
+ for (const I of (M.project.navEdges ?? []).filter((x) => x.aId === o || x.bId === o)) {
1516
+ const x = (De = M.project.navNodes) == null ? void 0 : De.find((B) => B.id === (I.aId === o ? I.bId : I.aId));
1517
+ x && w && x.floorId === w.floorId && j.push([x.position, N]);
1518
+ }
1519
+ } else
1520
+ for (const w of Oe(M.project).filter((I) => I.startId === o || I.endId === o)) {
1521
+ const I = M.project.junctions.find((x) => x.id === (w.startId === o ? w.endId : w.startId));
1522
+ I && j.push([I.position, N]);
1523
+ }
1524
+ (ke = d.getSource("kerros-draft")) == null || ke.setData({
1525
+ type: "FeatureCollection",
1526
+ features: j.map((w) => ({
1527
+ type: "Feature",
1528
+ properties: {},
1529
+ geometry: { type: "LineString", coordinates: w.map((I) => ce(I, M.project.origin)) }
1530
+ }))
1531
+ });
1532
+ };
1533
+ let c = 0, v;
1534
+ const R = (p) => {
1535
+ g || (g = Math.hypot(p.clientX - k.x, p.clientY - k.y) > 3), g && (v = { x: p.clientX, y: p.clientY, free: p.shiftKey }, c || (c = requestAnimationFrame(() => {
1536
+ c = 0, v && b(v.x, v.y, v.free);
1537
+ })));
1538
+ }, F = (p) => {
1539
+ if (cancelAnimationFrame(c), window.removeEventListener("pointermove", R), window.removeEventListener("pointerup", F), d.dragPan.enable(), l.dataset.wx = f[0] ?? "", l.dataset.wy = f[1] ?? "", Gt(), g) {
1540
+ Ke.current = !0;
1541
+ const C = d.getContainer().getBoundingClientRect(), T = d.unproject([p.clientX - C.left - a, p.clientY - C.top - u]);
1542
+ h.current.onVertexMove(
1543
+ t,
1544
+ o,
1545
+ se([T.lng, T.lat], r.project.origin),
1546
+ n,
1547
+ i,
1548
+ p.shiftKey
1549
+ ), J((ne) => ne + 1), setTimeout(() => {
1550
+ Ke.current = !1;
1551
+ }, 100);
1552
+ }
1553
+ };
1554
+ window.addEventListener("pointermove", R), window.addEventListener("pointerup", F, { once: !0 });
1555
+ }
1556
+ const D = r.project.objects.find((e) => e.id === r.selected), ye = Oe(r.project).find((e) => e.id === r.selected), oe = r.project.floors.find((e) => e.id === r.floorId), mt = Me(r.project, r.floorId, r.threeD && r.stack), fr = P.current;
1557
+ let Ge = 70;
1558
+ if (fr && Y && r.walk) Ge = 80;
1559
+ else if (fr && Y) {
1560
+ const e = q([0, 0]), t = q([10, 0]);
1561
+ e && t && (Ge = Math.hypot(t.x - e.x, t.y - e.y));
1562
+ }
1563
+ const fe = Ge / 10, Pe = (e) => e.id === r.selected || !!(e.feedId && tt(r.statuses.get(e.feedId)) === "critical"), ao = (e) => r.walk && (e.kind === "room" || e.kind === "zone" || e.kind === "light") || e.kind === "light" && !Pe(e) ? null : Pe(e) ? "full" : e.kind === "room" || e.kind === "zone" ? fe >= 3.5 && e.name.length * 6.5 <= e.width * fe * 1.2 ? "full" : fe >= 1.8 && e.width * fe >= 26 ? "mini" : null : e.kind === "poi" || e.kind === "gate" ? fe >= 1.2 ? "full" : fe >= 0.5 ? "mini" : null : (["door", "reader", "turnstile"].includes(e.kind) ? fe >= 6 : fe >= 5) ? "full" : fe >= 2.4 ? "mini" : null, lo = r.floorId === null || (((kr = r.project.floors.find((e) => e.id === r.floorId)) == null ? void 0 : kr.elevation) ?? 0) === 0, gr = {
1564
+ poi: 1,
1565
+ gate: 2,
1566
+ zone: 3,
1567
+ room: 4,
1568
+ camera: 5,
1569
+ elevator: 6,
1570
+ stairs: 7,
1571
+ turnstile: 8,
1572
+ reader: 9,
1573
+ door: 10
1574
+ }, kt = [];
1575
+ if (Y && r.showPlan)
1576
+ for (const e of r.project.objects) {
1577
+ if (!Ao(r.project, e, r.floorId) || !(lo || e.floorId !== null || Pe(e)) || ["window", "building", "parcel", "office", "container", "storage", "fixture", "landscape"].includes(e.kind))
1578
+ continue;
1579
+ const t = ao(e);
1580
+ if (!t) continue;
1581
+ const o = e.kind === "room" || e.kind === "zone";
1582
+ if (o && (!r.showLabels || r.threeD && r.stack && e.floorId !== r.floorId)) continue;
1583
+ const n = Be(r.project, e), i = r.threeD ? (wr = E.current) == null ? void 0 : wr.projectObject(e) : q(n);
1584
+ if (!i || "visible" in i && !i.visible) continue;
1585
+ const d = o && !!((vr = e.rings) != null && vr.slice(1).some((l) => Er(n, l)));
1586
+ kt.push({ o: e, s: i, world: n, isLabel: o && t === "full", mini: t === "mini", voidLabel: d });
1587
+ }
1588
+ kt.sort((e, t) => (Pe(e.o) ? 0 : gr[e.o.kind] ?? 9) - (Pe(t.o) ? 0 : gr[t.o.kind] ?? 9));
1589
+ const yr = [], co = kt.filter(({ o: e, s: t, isLabel: o, mini: n, voidLabel: i }) => {
1590
+ const d = n ? 8 : o ? i ? 90 : Math.max(36, e.name.length * 3.6) : 19, l = n ? 8 : o ? i ? 36 : 16 : 19;
1591
+ return !Pe(e) && yr.some((s) => Math.abs(s.x - t.x) < s.w + d && Math.abs(s.y - t.y) < s.h + l) ? !1 : (yr.push({ x: t.x, y: t.y, w: d, h: l }), !0);
1592
+ }), X = (br = pe.current) == null ? void 0 : br.statusTones, so = {
1593
+ normal: (X == null ? void 0 : X.normal) ?? "#2e9e6b",
1594
+ warning: (X == null ? void 0 : X.warning) ?? "#e39d3b",
1595
+ critical: (X == null ? void 0 : X.critical) ?? "#e0524e",
1596
+ unknown: (X == null ? void 0 : X.unknown) ?? "#9a9daf"
1597
+ }, uo = {
1598
+ room: "#a9b3c2",
1599
+ zone: "#96a58b",
1600
+ poi: "#1d2038",
1601
+ gate: "#5d6390",
1602
+ door: "#6a63d8",
1603
+ camera: "#7b74dd",
1604
+ elevator: "#567c9a",
1605
+ stairs: "#6d7a90",
1606
+ reader: "#4a7fb5",
1607
+ turnstile: "#4a7fb5",
1608
+ sensor: "#5b9bd0",
1609
+ alarm: "#e0524e",
1610
+ equipment: "#9a8f74"
1611
+ };
1612
+ return /* @__PURE__ */ S(
1613
+ "div",
1614
+ {
1615
+ className: `map-wrap ${r.threeD ? "perspective" : ""}`,
1616
+ "data-frame": O > 0 ? "ready" : "loading",
1617
+ "data-scene": r.threeD && r.showPlan ? (pr = E.current) != null && pr.diagnostics.drawCalls ? "ready" : "loading" : "off",
1618
+ children: [
1619
+ /* @__PURE__ */ m("div", { className: "map-surface", ref: Z, "data-testid": "map-canvas" }),
1620
+ /* @__PURE__ */ S("div", { className: "map-overlay", ref: $t, children: [
1621
+ co.map(({ o: e, s: t, world: o, isLabel: n, mini: i, voidLabel: d }) => {
1622
+ var s, a;
1623
+ const l = e.feedId ? r.statuses.get(e.feedId) : void 0;
1624
+ return i ? /* @__PURE__ */ m(
1625
+ "button",
1626
+ {
1627
+ onMouseEnter: Xt,
1628
+ className: `mini-marker ${e.category ? "cat-" + e.category : ""}`,
1629
+ "data-wx": o[0],
1630
+ "data-wy": o[1],
1631
+ "data-oid": e.id,
1632
+ "data-kind": e.kind,
1633
+ "data-category": e.category,
1634
+ style: {
1635
+ left: t.x,
1636
+ top: t.y,
1637
+ background: ((a = (s = pe.current) == null ? void 0 : s.objectColor) == null ? void 0 : a.call(s, e)) ?? (e.feedId ? so[tt(l)] : uo[e.kind] ?? e.color ?? "#9a9daf")
1638
+ },
1639
+ title: `${e.name}${e.feedId ? ` · ${jt(l)}` : ""}`,
1640
+ "aria-label": e.name,
1641
+ onClick: (u) => {
1642
+ u.stopPropagation(), r.tool === "select" || r.threeD ? r.onSelect(e.id) : r.onClick(Be(r.project, e), e.id);
1643
+ },
1644
+ children: /* @__PURE__ */ S("span", { className: "marker-tooltip", children: [
1645
+ e.name,
1646
+ e.feedId ? ` · ${jt(l)}` : ""
1647
+ ] })
1648
+ },
1649
+ e.id
1650
+ ) : n ? /* @__PURE__ */ S(
1651
+ "div",
1652
+ {
1653
+ className: `space-label ${e.floorId === null ? "outdoor" : ""} ${d ? "void-label" : ""}`,
1654
+ "data-wx": o[0],
1655
+ "data-wy": o[1],
1656
+ "data-oid": e.id,
1657
+ style: { left: t.x, top: t.y },
1658
+ children: [
1659
+ /* @__PURE__ */ m("span", { children: e.name }),
1660
+ e.kind === "room" && /* @__PURE__ */ S("small", { children: [
1661
+ Math.round(bt(e)),
1662
+ " m²"
1663
+ ] }),
1664
+ d && e.kind === "zone" && oe && /* @__PURE__ */ S("small", { children: [
1665
+ oe.code ? `${oe.code} · ` : "",
1666
+ oe.elevation.toFixed(0),
1667
+ " m"
1668
+ ] })
1669
+ ]
1670
+ },
1671
+ e.id
1672
+ ) : /* @__PURE__ */ S(
1673
+ "button",
1674
+ {
1675
+ onMouseEnter: Xt,
1676
+ className: `entity-marker ${e.kind === "poi" ? "poi" : ""} ${e.category ? "cat-" + e.category : ""} ${tt(l)} ${r.selected === e.id ? "selected" : ""}`,
1677
+ "data-wx": o[0],
1678
+ "data-wy": o[1],
1679
+ "data-oid": e.id,
1680
+ "data-kind": e.kind,
1681
+ "data-category": e.category,
1682
+ style: { left: t.x, top: t.y },
1683
+ title: `${e.name}${e.feedId ? ` · ${jt(l)}` : ""}`,
1684
+ "aria-label": e.name,
1685
+ onClick: (u) => {
1686
+ u.stopPropagation(), r.tool === "select" || r.threeD ? r.onSelect(e.id) : r.onClick(Be(r.project, e), e.id);
1687
+ },
1688
+ children: [
1689
+ /* @__PURE__ */ m(
1690
+ No,
1691
+ {
1692
+ kind: e.kind,
1693
+ size: e.kind === "door" ? 14 : 17,
1694
+ symbol: e.symbol,
1695
+ travel: (l == null ? void 0 : l.travel) ?? e.travel
1696
+ }
1697
+ ),
1698
+ e.feedId && /* @__PURE__ */ m("i", { className: `status-dot ${tt(l)}` }),
1699
+ /* @__PURE__ */ m("span", { className: "marker-tooltip", children: e.name })
1700
+ ]
1701
+ },
1702
+ e.id
1703
+ );
1704
+ }),
1705
+ r.canEdit && r.tool === "select" && !r.threeD && ((Ir = D == null ? void 0 : D.geometry) == null ? void 0 : Ir.mode) === "boundaries" && (() => {
1706
+ const e = new Set(D.geometry.loops.flat().map((n) => n.edgeId)), t = Oe(r.project).filter((n) => e.has(n.id)), o = new Set(t.flatMap((n) => [n.startId, n.endId]));
1707
+ return /* @__PURE__ */ S(wt, { children: [
1708
+ r.project.junctions.filter((n) => o.has(n.id)).map((n, i) => {
1709
+ const d = q(n.position);
1710
+ return d && /* @__PURE__ */ m(
1711
+ "button",
1712
+ {
1713
+ "aria-label": `Move space boundary corner ${i + 1}`,
1714
+ className: "vertex-handle",
1715
+ "data-wx": n.position[0],
1716
+ "data-wy": n.position[1],
1717
+ style: { left: d.x, top: d.y },
1718
+ onPointerDown: (l) => ue(l, "junction", n.id)
1719
+ },
1720
+ n.id
1721
+ );
1722
+ }),
1723
+ t.map((n, i) => {
1724
+ const [d, l] = we(r.project, n), s = [(d[0] + l[0]) / 2, (d[1] + l[1]) / 2], a = q(s);
1725
+ return a && /* @__PURE__ */ m(
1726
+ "button",
1727
+ {
1728
+ "aria-label": `Move space boundary ${i + 1}`,
1729
+ title: "Drag this boundary; connected spaces follow",
1730
+ className: "move-handle",
1731
+ "data-wx": s[0],
1732
+ "data-wy": s[1],
1733
+ style: { left: a.x, top: a.y },
1734
+ onPointerDown: (u) => ue(u, "barrier", n.id),
1735
+ children: "✥"
1736
+ },
1737
+ n.id
1738
+ );
1739
+ })
1740
+ ] });
1741
+ })(),
1742
+ r.canEdit && r.tool === "select" && !r.threeD && ((jr = D == null ? void 0 : D.geometry) == null ? void 0 : jr.mode) !== "boundaries" && ((xr = D == null ? void 0 : D.rings) == null ? void 0 : xr.flatMap(
1743
+ (e, t) => pt(e).map((o, n) => {
1744
+ const i = q(o);
1745
+ return i ? /* @__PURE__ */ m(
1746
+ "button",
1747
+ {
1748
+ "aria-label": `Move vertex ${n + 1}`,
1749
+ className: "vertex-handle",
1750
+ "data-wx": o[0],
1751
+ "data-wy": o[1],
1752
+ style: { left: i.x, top: i.y },
1753
+ onPointerDown: (d) => ue(d, "ring", D.id, t, n)
1754
+ },
1755
+ `${t}-${n}`
1756
+ ) : null;
1757
+ })
1758
+ )),
1759
+ r.canEdit && r.tool === "select" && // Ground-plane handles, like the vertex and junction ones: in 3D the object is drawn at its
1760
+ // storey's elevation and the handle would hang metres away from it, in open air over a
1761
+ // basement or inside the slab over a tower.
1762
+ !r.threeD && D && ((Lr = D.geometry) == null ? void 0 : Lr.mode) !== "boundaries" && (() => {
1763
+ const e = q(D.position), t = !!D.barrierId;
1764
+ return e ? /* @__PURE__ */ m(
1765
+ "button",
1766
+ {
1767
+ className: "move-handle",
1768
+ "aria-label": t ? "Slide along the wall" : "Move selected object",
1769
+ title: D.kind === "door" ? "Drag along the wall to slide; across it to flip the opening side" : void 0,
1770
+ "data-wx": D.position[0],
1771
+ "data-wy": D.position[1],
1772
+ style: { left: e.x, top: e.y },
1773
+ onPointerDown: (o) => ue(o, t ? "opening" : "object", D.id),
1774
+ children: "✥"
1775
+ }
1776
+ ) : null;
1777
+ })(),
1778
+ r.canEdit && r.tool === "select" && !r.threeD && D && ((Pr = D.geometry) == null ? void 0 : Pr.mode) !== "boundaries" && !D.barrierId && D.rotation !== void 0 && (() => {
1779
+ const e = Math.max(1.6, (Math.abs(D.width) + Math.abs(D.depth)) / 2 + 0.8), t = Fr(D.position, Rr([e, 0], D.rotation)), o = q(t);
1780
+ return o ? /* @__PURE__ */ m(
1781
+ "button",
1782
+ {
1783
+ className: "rotate-handle",
1784
+ "aria-label": "Turn selected object",
1785
+ "data-wx": t[0],
1786
+ "data-wy": t[1],
1787
+ style: { left: o.x, top: o.y },
1788
+ onPointerDown: (n) => ue(n, "rotate", D.id)
1789
+ }
1790
+ ) : null;
1791
+ })(),
1792
+ r.canEdit && r.tool === "select" && !r.threeD && (D == null ? void 0 : D.kind) === "camera" && (() => {
1793
+ const e = D.coverageRange ?? 12, t = (D.coverageAngle ?? 70) / 2, o = Fr(D.position, Rr([e, 0], D.rotation + t)), n = q(o);
1794
+ return n ? /* @__PURE__ */ m(
1795
+ "button",
1796
+ {
1797
+ className: "coverage-handle",
1798
+ "aria-label": "Camera reach and field of view",
1799
+ "data-wx": o[0],
1800
+ "data-wy": o[1],
1801
+ style: { left: n.x, top: n.y },
1802
+ onPointerDown: (i) => ue(i, "coverage", D.id)
1803
+ }
1804
+ ) : null;
1805
+ })(),
1806
+ r.canEdit && r.tool === "select" && !r.threeD && ye && we(r.project, ye).map((e, t) => {
1807
+ const o = q(e), n = q(we(r.project, ye)[1 - t]);
1808
+ if (!o || !n) return null;
1809
+ const i = o.x - n.x, d = o.y - n.y, l = Math.hypot(i, d), s = Math.max(0, 32 - l / 2), a = l ? i / l : t ? 1 : -1, u = l ? d / l : 0;
1810
+ return /* @__PURE__ */ S(wo, { children: [
1811
+ s > 0 && /* @__PURE__ */ m(
1812
+ "span",
1813
+ {
1814
+ "aria-hidden": "true",
1815
+ "data-wx": e[0],
1816
+ "data-wy": e[1],
1817
+ style: {
1818
+ position: "absolute",
1819
+ pointerEvents: "none",
1820
+ left: o.x,
1821
+ top: o.y,
1822
+ width: s,
1823
+ height: 1,
1824
+ background: "var(--accent)",
1825
+ transformOrigin: "0 0",
1826
+ transform: `rotate(${Math.atan2(u, a)}rad)`
1827
+ }
1828
+ }
1829
+ ),
1830
+ /* @__PURE__ */ m(
1831
+ "button",
1832
+ {
1833
+ className: "vertex-handle",
1834
+ "aria-label": `Move wall endpoint ${t + 1}`,
1835
+ "data-wx": e[0],
1836
+ "data-wy": e[1],
1837
+ "data-screen-dx": a * s,
1838
+ "data-screen-dy": u * s,
1839
+ style: { left: o.x + a * s, top: o.y + u * s },
1840
+ onPointerDown: (f) => ue(f, "junction", t ? ye.endId : ye.startId)
1841
+ }
1842
+ )
1843
+ ] }, t);
1844
+ }),
1845
+ r.canEdit && r.tool === "select" && !r.threeD && ye && (() => {
1846
+ const [e, t] = we(r.project, ye), o = [(e[0] + t[0]) / 2, (e[1] + t[1]) / 2], n = q(o);
1847
+ return n ? /* @__PURE__ */ m(
1848
+ "button",
1849
+ {
1850
+ className: "move-handle",
1851
+ "aria-label": "Move whole wall",
1852
+ title: "Drag to move the wall; connected walls follow",
1853
+ "data-wx": o[0],
1854
+ "data-wy": o[1],
1855
+ style: { left: n.x, top: n.y },
1856
+ onPointerDown: (i) => ue(i, "barrier", ye.id),
1857
+ children: "✥"
1858
+ }
1859
+ ) : null;
1860
+ })(),
1861
+ r.canEdit && _e && !r.threeD && (r.project.navNodes ?? []).filter((e) => zo(e, r.floorId)).map((e) => {
1862
+ const t = q(e.position);
1863
+ return t ? /* @__PURE__ */ m(
1864
+ "button",
1865
+ {
1866
+ className: "vertex-handle nav-node-handle",
1867
+ "aria-label": "Move route node",
1868
+ title: "Drag to move this route node",
1869
+ "data-wx": e.position[0],
1870
+ "data-wy": e.position[1],
1871
+ style: { left: t.x, top: t.y },
1872
+ onPointerDown: (o) => ue(o, "node", e.id)
1873
+ },
1874
+ e.id
1875
+ ) : null;
1876
+ }),
1877
+ r.draft.map((e, t) => {
1878
+ const o = q(e);
1879
+ return o ? /* @__PURE__ */ m("i", { className: "draft-node", "data-wx": e[0], "data-wy": e[1], style: { left: o.x, top: o.y } }, t) : null;
1880
+ }),
1881
+ (Dr = r.alignment) == null ? void 0 : Dr.map.map((e, t) => {
1882
+ const o = q(e);
1883
+ return o ? /* @__PURE__ */ m("b", { className: "alignment-pin", "data-wx": e[0], "data-wy": e[1], style: { left: o.x, top: o.y }, children: t + 1 }, t) : null;
1884
+ }),
1885
+ (() => {
1886
+ var n, i;
1887
+ const e = r.avatar;
1888
+ if (!e || r.walk || e.floorId !== r.floorId) return null;
1889
+ const t = (r.threeD ? (n = E.current) == null ? void 0 : n.projectPoint(e.position, e.floorId) : null) ?? q(e.position);
1890
+ if (!t) return null;
1891
+ const o = e.heading + (r.project.origin[2] ?? 0);
1892
+ return /* @__PURE__ */ S(
1893
+ "button",
1894
+ {
1895
+ className: "avatar-marker",
1896
+ "data-wx": e.position[0],
1897
+ "data-wy": e.position[1],
1898
+ "data-floor": e.floorId ?? "",
1899
+ "data-bearing": o,
1900
+ style: {
1901
+ left: t.x,
1902
+ top: t.y,
1903
+ "--turn": `${o - (((i = P.current) == null ? void 0 : i.getBearing()) ?? 0)}deg`
1904
+ },
1905
+ title: "Resume walking from here",
1906
+ "aria-label": "Resume walking from here",
1907
+ onClick: (d) => {
1908
+ var l;
1909
+ d.stopPropagation(), (l = r.onWalkAt) == null || l.call(r, e);
1910
+ },
1911
+ children: [
1912
+ /* @__PURE__ */ m("i", {}),
1913
+ /* @__PURE__ */ m(vt, { size: 13 })
1914
+ ]
1915
+ }
1916
+ );
1917
+ })()
1918
+ ] }),
1919
+ r.threeD && !r.walk && /* @__PURE__ */ S("label", { className: "pitch-control", title: "Camera inclination (⇧W / ⇧S)", children: [
1920
+ /* @__PURE__ */ m(Sr, { size: 14 }),
1921
+ /* @__PURE__ */ m(
1922
+ "input",
1923
+ {
1924
+ type: "range",
1925
+ min: 0,
1926
+ max: 75,
1927
+ step: 1,
1928
+ value: Math.round(qe),
1929
+ "aria-label": "Camera inclination",
1930
+ onChange: (e) => {
1931
+ var t;
1932
+ return (t = P.current) == null ? void 0 : t.easeTo({ pitch: Number(e.target.value), duration: 0 });
1933
+ }
1934
+ }
1935
+ )
1936
+ ] }),
1937
+ !r.walk && /* @__PURE__ */ S("div", { className: "map-navigator", children: [
1938
+ !r.walk && /* @__PURE__ */ S(wt, { children: [
1939
+ /* @__PURE__ */ m(
1940
+ "button",
1941
+ {
1942
+ className: `pegman ${Ce ? "lifted" : ""}`,
1943
+ title: "Drag onto the map to walk from there",
1944
+ "aria-label": "Drag onto the map to walk from there",
1945
+ onPointerDown: (e) => {
1946
+ var o;
1947
+ if (e.button !== 0) return;
1948
+ e.currentTarget.setPointerCapture(e.pointerId);
1949
+ const t = (o = Z.current) == null ? void 0 : o.getBoundingClientRect();
1950
+ t && Je({ x: e.clientX - t.left, y: e.clientY - t.top });
1951
+ },
1952
+ onPointerMove: (e) => {
1953
+ var o;
1954
+ if (!Ce) return;
1955
+ const t = (o = Z.current) == null ? void 0 : o.getBoundingClientRect();
1956
+ t && Je({ x: e.clientX - t.left, y: e.clientY - t.top });
1957
+ },
1958
+ onPointerUp: oo,
1959
+ onPointerCancel: (e) => {
1960
+ e.currentTarget.releasePointerCapture(e.pointerId), Je(null);
1961
+ },
1962
+ onClick: () => {
1963
+ var n;
1964
+ const e = P.current, t = h.current;
1965
+ if (!e) return;
1966
+ const o = t.avatar && t.avatar.floorId === t.floorId ? t.avatar : null;
1967
+ (n = t.onWalkAt) == null || n.call(
1968
+ t,
1969
+ o ?? {
1970
+ floorId: t.floorId,
1971
+ position: Ne(e, e.getCanvas().clientWidth / 2, e.getCanvas().clientHeight / 2),
1972
+ heading: e.getBearing() - (t.project.origin[2] ?? 0)
1973
+ }
1974
+ );
1975
+ },
1976
+ children: /* @__PURE__ */ m(vt, { size: 19 })
1977
+ }
1978
+ ),
1979
+ /* @__PURE__ */ m("div", {})
1980
+ ] }),
1981
+ /* @__PURE__ */ m("button", { title: "Zoom in", "aria-label": "Zoom in", onClick: () => {
1982
+ var e;
1983
+ return (e = P.current) == null ? void 0 : e.zoomIn();
1984
+ }, children: /* @__PURE__ */ m(bo, { size: 18 }) }),
1985
+ /* @__PURE__ */ m("button", { title: "Zoom out", "aria-label": "Zoom out", onClick: () => {
1986
+ var e;
1987
+ return (e = P.current) == null ? void 0 : e.zoomOut();
1988
+ }, children: /* @__PURE__ */ m(po, { size: 18 }) }),
1989
+ /* @__PURE__ */ m("div", {}),
1990
+ r.threeD && /* @__PURE__ */ S(wt, { children: [
1991
+ /* @__PURE__ */ m(
1992
+ "button",
1993
+ {
1994
+ title: "Tilt view",
1995
+ "aria-label": "Tilt view",
1996
+ onClick: () => {
1997
+ const e = P.current;
1998
+ e && e.easeTo({ pitch: e.getPitch() >= 50 ? 20 : e.getPitch() + 15, duration: 400 });
1999
+ },
2000
+ children: /* @__PURE__ */ m(Sr, { size: 17 })
2001
+ }
2002
+ ),
2003
+ /* @__PURE__ */ m(
2004
+ "button",
2005
+ {
2006
+ title: "Rotate left",
2007
+ "aria-label": "Rotate left",
2008
+ onClick: () => {
2009
+ const e = P.current;
2010
+ e && e.easeTo({ bearing: e.getBearing() - 45, duration: 450 });
2011
+ },
2012
+ children: /* @__PURE__ */ m(Io, { size: 17 })
2013
+ }
2014
+ ),
2015
+ /* @__PURE__ */ m(
2016
+ "button",
2017
+ {
2018
+ title: "Rotate right",
2019
+ "aria-label": "Rotate right",
2020
+ onClick: () => {
2021
+ const e = P.current;
2022
+ e && e.easeTo({ bearing: e.getBearing() + 45, duration: 450 });
2023
+ },
2024
+ children: /* @__PURE__ */ m(jo, { size: 17 })
2025
+ }
2026
+ ),
2027
+ /* @__PURE__ */ m("div", {})
2028
+ ] }),
2029
+ /* @__PURE__ */ m("button", { title: "Fit floor", "aria-label": "Fit floor", onClick: () => st(r.floorId), children: /* @__PURE__ */ m(xo, { size: 18 }) }),
2030
+ /* @__PURE__ */ m(
2031
+ "button",
2032
+ {
2033
+ title: "Reset north",
2034
+ "aria-label": "Reset north",
2035
+ onClick: () => {
2036
+ var e;
2037
+ return (e = P.current) == null ? void 0 : e.easeTo({ bearing: Ft(r.project), pitch: r.threeD ? 35 : 0 });
2038
+ },
2039
+ children: /* @__PURE__ */ m(Lo, { size: 18 })
2040
+ }
2041
+ )
2042
+ ] }),
2043
+ r.walk && r.elevators && /* @__PURE__ */ m(vo, { fallback: null, children: /* @__PURE__ */ m(
2044
+ rn,
2045
+ {
2046
+ project: r.project,
2047
+ floorId: r.floorId,
2048
+ controls: r.elevators,
2049
+ walker: z,
2050
+ riding: Qt,
2051
+ onRide: dt,
2052
+ onFloor: r.onRequestFloor,
2053
+ requested: Gr,
2054
+ onWave: () => {
2055
+ var e;
2056
+ return (e = E.current) == null ? void 0 : e.wave();
2057
+ },
2058
+ soundOn: G.sound,
2059
+ onSound: rr
2060
+ }
2061
+ ) }),
2062
+ r.walk && /* @__PURE__ */ S("label", { className: "walk-fov", title: "Horizontal field of view", children: [
2063
+ /* @__PURE__ */ S("span", { children: [
2064
+ "Field of view ",
2065
+ /* @__PURE__ */ S("output", { children: [
2066
+ xe,
2067
+ "°"
2068
+ ] })
2069
+ ] }),
2070
+ /* @__PURE__ */ m(
2071
+ "input",
2072
+ {
2073
+ type: "range",
2074
+ min: Jo,
2075
+ max: Zo,
2076
+ step: 1,
2077
+ value: xe,
2078
+ "aria-label": "POV field of view",
2079
+ "aria-valuetext": `${xe} degrees horizontally`,
2080
+ onChange: (e) => {
2081
+ const t = Br(Number(e.target.value));
2082
+ eo(t);
2083
+ try {
2084
+ localStorage.setItem(Hr, String(t));
2085
+ } catch {
2086
+ }
2087
+ }
2088
+ }
2089
+ )
2090
+ ] }),
2091
+ r.walk && /* @__PURE__ */ S("div", { className: "walk-hud", children: [
2092
+ /* @__PURE__ */ S("div", { className: "walk-status", children: [
2093
+ (er || G.next) && /* @__PURE__ */ m("em", { role: "status", children: er || G.next }),
2094
+ G.where && /* @__PURE__ */ m("b", { children: G.where }),
2095
+ G.up && /* @__PURE__ */ S("span", { children: [
2096
+ /* @__PURE__ */ m("kbd", { children: "F" }),
2097
+ " up to ",
2098
+ G.up
2099
+ ] }),
2100
+ G.down && /* @__PURE__ */ S("span", { children: [
2101
+ /* @__PURE__ */ m("kbd", { children: "⇧F" }),
2102
+ " down to ",
2103
+ G.down
2104
+ ] })
2105
+ ] }),
2106
+ /* @__PURE__ */ S("div", { className: `walk-keys ${G.looking ? "busy" : ""}`, children: [
2107
+ /* @__PURE__ */ m("span", { children: "Drag to look around" }),
2108
+ /* @__PURE__ */ S("span", { children: [
2109
+ /* @__PURE__ */ m("kbd", { children: "W" }),
2110
+ /* @__PURE__ */ m("kbd", { children: "S" }),
2111
+ " walk"
2112
+ ] }),
2113
+ /* @__PURE__ */ S("span", { children: [
2114
+ /* @__PURE__ */ m("kbd", { children: "A" }),
2115
+ /* @__PURE__ */ m("kbd", { children: "D" }),
2116
+ " turn"
2117
+ ] }),
2118
+ /* @__PURE__ */ S("span", { children: [
2119
+ /* @__PURE__ */ m("kbd", { children: "Q" }),
2120
+ /* @__PURE__ */ m("kbd", { children: "E" }),
2121
+ " sidestep"
2122
+ ] }),
2123
+ /* @__PURE__ */ S("span", { children: [
2124
+ /* @__PURE__ */ m("kbd", { children: "Shift" }),
2125
+ " run"
2126
+ ] }),
2127
+ /* @__PURE__ */ S("span", { children: [
2128
+ /* @__PURE__ */ m("kbd", { children: "M" }),
2129
+ " ",
2130
+ G.sound ? "mute" : "sound"
2131
+ ] }),
2132
+ /* @__PURE__ */ S("span", { children: [
2133
+ /* @__PURE__ */ m("kbd", { children: "Esc" }),
2134
+ " leave"
2135
+ ] })
2136
+ ] })
2137
+ ] }),
2138
+ Ce && /* @__PURE__ */ m("div", { className: "pegman-ghost", style: { left: Ce.x, top: Ce.y }, children: /* @__PURE__ */ m(vt, { size: 22 }) }),
2139
+ /* @__PURE__ */ S("div", { className: "map-scale", hidden: r.walk, children: [
2140
+ /* @__PURE__ */ m("span", { style: { width: Ge } }),
2141
+ "10 m ",
2142
+ /* @__PURE__ */ m("i", {}),
2143
+ " ",
2144
+ r.threeD ? `${r.stack ? "Building stack" : (oe == null ? void 0 : oe.name) ?? "Outdoor site"} · ${mt.buried ? `${oe ? `${Math.abs(oe.elevation).toFixed(1)} m below ground` : "Below-ground structure"}${mt.compressed ? oe ? ` · shown at ${Math.abs(mt.focusElevation).toFixed(1)} m` : " · depth compressed" : ""}` : "cutaway"}` : "metres"
2145
+ ] }),
2146
+ Se && /* @__PURE__ */ S("button", { className: "map-error", onClick: () => W(""), children: [
2147
+ Se,
2148
+ " ×"
2149
+ ] }),
2150
+ !Y && !Se && /* @__PURE__ */ S("div", { className: "map-loading", children: [
2151
+ /* @__PURE__ */ m("span", { className: "loading-orbit" }),
2152
+ "Preparing your space…"
2153
+ ] })
2154
+ ]
2155
+ }
2156
+ );
2157
+ }
2158
+ export {
2159
+ Cn as MapCanvas
2160
+ };
2161
+ //# sourceMappingURL=MapCanvas.js.map