@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,370 @@
1
+ import { jsxs as r, jsx as i, Fragment as q } from "react/jsx-runtime";
2
+ import { useState as s, useRef as b, useEffect as O, useMemo as oe } from "react";
3
+ import { Layers3 as ae, Footprints as De, Box as Ee, SlidersHorizontal as Re, Shapes as ze, Waypoints as Ve, PanelRightOpen as xe, X as Be } from "lucide-react";
4
+ import { FloorViewer as We } from "./FloorViewer.js";
5
+ import { openingFloorId as le } from "../model/project.js";
6
+ import { findRoute as $e, HERE as Ge } from "../model/navigation.js";
7
+ import { toLngLat as Te, footprint as ie } from "../model/geometry.js";
8
+ import { StructureView as Ue } from "../components/StructureView.js";
9
+ import { NavigationGraph as Je, NavigationPanel as Ke, ReadOnlyInspector as qe } from "./panels.js";
10
+ import { FloorSelect as He } from "../components/controls.js";
11
+ const H = {
12
+ showLabels: !0,
13
+ showPlan: !0,
14
+ coverage: !1,
15
+ excavation: !0,
16
+ cityBuildings: !1,
17
+ cadastre: !1
18
+ }, Ye = {
19
+ showLabels: "Object labels",
20
+ showPlan: "Floor plan",
21
+ coverage: "Device coverage",
22
+ excavation: "Underground context",
23
+ cityBuildings: "Surrounding buildings",
24
+ cadastre: "Cadastral parcels"
25
+ };
26
+ function lt(n) {
27
+ var ne;
28
+ const { project: l } = n, [ce, Y] = s(() => le(l)), [se, Z] = s(null), [re, R] = s(null), [de, ue] = s("2d"), [fe, me] = s(!1), [he, ve] = s(H), [we, ge] = s(null), [v, S] = s(null), [I, j] = s(!1), [ke, be] = s(), [C, ye] = s(null), [F, Se] = s(null), [Ie, X] = s(!1), [Ce, _] = s(null), d = n.floorId !== void 0 ? n.floorId : ce, z = n.selected !== void 0 ? n.selected : se, w = n.viewMode ?? (n.walk !== void 0 || n.threeD !== void 0 ? n.walk ? "walk" : n.threeD ? "3d" : "2d" : de), P = n.stack ?? fe, y = n.avatar !== void 0 ? n.avatar : we, V = n.playing ?? Ie, x = n.activeStep !== void 0 ? n.activeStep : Ce, B = Object.fromEntries(
29
+ Object.keys(H).map((e) => {
30
+ const t = e;
31
+ return [t, n[t] ?? he[t]];
32
+ })
33
+ ), N = b(null), Q = b(n.initialCamera), A = b(null), W = b(null), $ = b(null), [Fe, Pe] = s(0);
34
+ O(() => {
35
+ const e = setInterval(() => Pe((t) => t + 1), 5e3);
36
+ return () => clearInterval(e);
37
+ }, []);
38
+ const p = b(l);
39
+ O(() => {
40
+ var e;
41
+ n.floorId === void 0 && Y(
42
+ (t) => t === null || l.floors.some((o) => o.id === t) ? t : le(l)
43
+ ), n.selected === void 0 && Z(
44
+ (t) => [...l.objects, ...l.barriers, ...l.drawings, ...l.virtualBoundaries ?? []].some(
45
+ (o) => o.id === t
46
+ ) ? t : null
47
+ ), p.current !== l && (p.current = l, X(!1), $.current = null, (e = n.onPlayingChange) == null || e.call(n, !1));
48
+ }, [l]);
49
+ const G = oe(
50
+ () => {
51
+ var e;
52
+ return new Map([...n.statuses ?? [], ...((e = n.elevators) == null ? void 0 : e.statuses) ?? []].map((t) => [t.feedId, t]));
53
+ },
54
+ [n.statuses, (ne = n.elevators) == null ? void 0 : ne.statuses, Fe]
55
+ ), Ae = oe(() => {
56
+ const e = (a) => a === Ge ? y ? { floorId: y.floorId, position: y.position } : null : a, t = e(C), o = e(F);
57
+ return t && o ? $e(l, t, o, { statuses: G }) : null;
58
+ }, [l, C, F, y, G]), u = n.route !== void 0 ? n.route : V ? $.current : Ae, D = b(n.onRouteChange);
59
+ D.current = n.onRouteChange, O(() => {
60
+ var e;
61
+ return (e = D.current) == null ? void 0 : e.call(D, u);
62
+ }, [u]);
63
+ const f = (e) => {
64
+ var t;
65
+ Y(e), (t = n.onFloorChange) == null || t.call(n, e);
66
+ }, L = (e) => {
67
+ var t;
68
+ Z(e), (t = n.onSelect) == null || t.call(n, e);
69
+ }, Le = (e) => {
70
+ var o;
71
+ const t = l.objects.find((a) => a.id === e);
72
+ t && t.floorId !== d && !((o = t.servedFloorIds) != null && o.includes(d ?? "")) && f(t.floorId), L(e), R(e);
73
+ }, M = (e) => {
74
+ var t;
75
+ ue(e), (t = n.onViewModeChange) == null || t.call(n, e);
76
+ }, Me = (e) => {
77
+ var t;
78
+ me(e), (t = n.onStackChange) == null || t.call(n, e);
79
+ }, ee = (e) => {
80
+ var t;
81
+ ge(e), (t = n.onAvatar) == null || t.call(n, e);
82
+ }, h = (e) => {
83
+ var t;
84
+ X(e), (t = n.onPlayingChange) == null || t.call(n, e);
85
+ }, T = (e) => {
86
+ var t;
87
+ _(e), (t = n.onJourneyStep) == null || t.call(n, e);
88
+ }, E = (e, t) => {
89
+ h(!1), _(null), ye(e), Se(t);
90
+ }, U = () => {
91
+ const e = A.current, t = N.current;
92
+ if (!(e != null && e.length) || !t) return;
93
+ A.current = null;
94
+ const o = e.map((a) => Te(a, l.origin));
95
+ t.fitBounds(
96
+ [
97
+ [Math.min(...o.map((a) => a[0])), Math.min(...o.map((a) => a[1]))],
98
+ [Math.max(...o.map((a) => a[0])), Math.max(...o.map((a) => a[1]))]
99
+ ],
100
+ { padding: 80, maxZoom: 20, duration: 450 }
101
+ );
102
+ }, J = (e) => {
103
+ var g;
104
+ const t = new Set(e.objectIds ?? []), o = l.objects.filter((c) => t.has(c.id)), a = e.floorId !== void 0 ? e.floorId : o.some((c) => c.floorId === d) ? d : o.length ? o[0].floorId : d, m = o.filter((c) => {
105
+ var k;
106
+ return c.floorId === a || ((k = c.servedFloorIds) == null ? void 0 : k.includes(a ?? ""));
107
+ });
108
+ A.current = e.position ? [e.position] : m.flatMap((c) => ie(c).flat()), A.current.length || (A.current = l.objects.filter((c) => c.floorId === a).flatMap((c) => ie(c).flat())), h(!1), R(null), L(((g = m[0]) == null ? void 0 : g.id) ?? null), M("2d"), f(a), j(!1), requestAnimationFrame(U);
109
+ };
110
+ O(() => {
111
+ if (!I) {
112
+ const e = requestAnimationFrame(U);
113
+ return () => cancelAnimationFrame(e);
114
+ }
115
+ }, [I, d, w]);
116
+ const Oe = (e) => {
117
+ const t = N.current;
118
+ t && (Q.current = {
119
+ center: [t.getCenter().lng, t.getCenter().lat],
120
+ zoom: t.getZoom(),
121
+ bearing: t.getBearing(),
122
+ pitch: t.getPitch()
123
+ }), h(!1), be(e), j(!0), N.current = null;
124
+ }, te = (e) => {
125
+ if (!u) return;
126
+ const t = Math.max(0, Math.min(u.steps.length - 1, e)), o = u.steps[t], a = u.nodes.find((m) => m.id === o.nodeIds.at(-1));
127
+ h(!1), T(t), a ? J({ floorId: a.floorId, position: a.position }) : f(o.floorId);
128
+ }, K = (e) => S((t) => t === e ? null : e), je = [
129
+ { id: "outdoors", code: "OUT", name: "Outdoor site" },
130
+ ...[...l.floors].sort((e, t) => t.elevation - e.elevation).map((e) => {
131
+ var t;
132
+ return {
133
+ id: e.id,
134
+ code: e.code ?? `${e.elevation} m`,
135
+ name: e.name,
136
+ hint: l.buildings.length > 1 ? (t = l.buildings.find((o) => o.id === e.buildingId)) == null ? void 0 : t.name : void 0
137
+ };
138
+ })
139
+ ];
140
+ O(() => {
141
+ const e = (t) => {
142
+ var o;
143
+ if (!(I || t.defaultPrevented || t.ctrlKey || t.metaKey || t.altKey || !((o = W.current) != null && o.contains(document.activeElement)) || t.target.closest("input,textarea,select,[contenteditable=true],[role=dialog]"))) {
144
+ if (t.key.toLowerCase() === "t") M(w === "2d" ? "3d" : w === "3d" ? "walk" : "2d");
145
+ else if (t.key.toLowerCase() === "g") K("navigate");
146
+ else if (t.key.toLowerCase() === "i") K("properties");
147
+ else if (t.shiftKey && ["ArrowUp", "ArrowDown"].includes(t.key)) {
148
+ const a = [...l.floors].sort((c, k) => c.elevation - k.elevation), m = a.findIndex((c) => c.id === d), g = a[m + (t.key === "ArrowUp" ? 1 : -1)];
149
+ g && f(g.id);
150
+ } else return;
151
+ t.preventDefault();
152
+ }
153
+ };
154
+ return window.addEventListener("keydown", e), () => window.removeEventListener("keydown", e);
155
+ });
156
+ const Ne = (n.viewMode !== void 0 || n.threeD !== void 0 || n.walk !== void 0) && !n.onViewModeChange;
157
+ return /* @__PURE__ */ r(
158
+ "div",
159
+ {
160
+ ref: W,
161
+ className: `kerros-root kerros-surface viewer-workspace ${n.dark ? "dark" : ""}`,
162
+ tabIndex: -1,
163
+ onPointerDownCapture: (e) => {
164
+ var t;
165
+ e.target.closest("input,button,select,textarea,canvas") || (t = W.current) == null || t.focus();
166
+ },
167
+ children: [
168
+ /* @__PURE__ */ r("div", { className: "viewer-toolbar", "aria-label": "Viewer controls", children: [
169
+ /* @__PURE__ */ r("div", { className: "floor-chip", children: [
170
+ /* @__PURE__ */ i(ae, { size: 16 }),
171
+ /* @__PURE__ */ i(
172
+ He,
173
+ {
174
+ ariaLabel: "Active floor",
175
+ value: d ?? "outdoors",
176
+ entries: je,
177
+ onPick: (e) => {
178
+ f(e === "outdoors" ? null : e), L(null);
179
+ }
180
+ }
181
+ )
182
+ ] }),
183
+ !I && /* @__PURE__ */ r(q, { children: [
184
+ /* @__PURE__ */ i("div", { className: "view-switch", children: ["2d", "3d", "walk"].map((e) => /* @__PURE__ */ r(
185
+ "button",
186
+ {
187
+ disabled: Ne,
188
+ className: w === e ? "active" : "",
189
+ "aria-pressed": w === e,
190
+ onClick: () => M(e),
191
+ children: [
192
+ e === "walk" ? /* @__PURE__ */ i(De, { size: 14 }) : e === "3d" ? /* @__PURE__ */ i(Ee, { size: 14 }) : null,
193
+ e === "walk" ? "Walk" : e.toUpperCase()
194
+ ]
195
+ },
196
+ e
197
+ )) }),
198
+ w === "3d" && /* @__PURE__ */ r(
199
+ "button",
200
+ {
201
+ className: `stack-button ${P ? "active" : ""}`,
202
+ disabled: n.stack !== void 0 && !n.onStackChange,
203
+ "aria-pressed": P,
204
+ onClick: () => Me(!P),
205
+ children: [
206
+ /* @__PURE__ */ i(ae, { size: 14 }),
207
+ P ? "All floors" : "Cutaway"
208
+ ]
209
+ }
210
+ )
211
+ ] }),
212
+ /* @__PURE__ */ r("div", { className: "viewer-toolbar-actions", children: [
213
+ /* @__PURE__ */ r("details", { className: "viewer-display-options", children: [
214
+ /* @__PURE__ */ i("summary", { "aria-label": "View options", title: "View options", children: /* @__PURE__ */ i(Re, { size: 17 }) }),
215
+ /* @__PURE__ */ i("div", { children: Object.keys(H).map((e) => {
216
+ var t, o, a, m;
217
+ return /* @__PURE__ */ r("label", { children: [
218
+ /* @__PURE__ */ i(
219
+ "input",
220
+ {
221
+ type: "checkbox",
222
+ checked: B[e],
223
+ disabled: n[e] !== void 0 && !n.onDisplayChange || e === "cityBuildings" && !((o = (t = n.basemap) == null ? void 0 : t.vectorSchema) != null && o.footprints) || e === "cadastre" && !((m = (a = n.basemap) == null ? void 0 : a.vectorSchema) != null && m.cadastre),
224
+ onChange: (g) => {
225
+ var k;
226
+ const c = { ...B, [e]: g.target.checked };
227
+ ve(c), (k = n.onDisplayChange) == null || k.call(n, c);
228
+ }
229
+ }
230
+ ),
231
+ Ye[e]
232
+ ] }, e);
233
+ }) })
234
+ ] }),
235
+ [
236
+ ["structure", ze, "structure"],
237
+ ["navigate", Ve, "navigation"],
238
+ ["properties", xe, "properties"]
239
+ ].map(([e, t, o]) => /* @__PURE__ */ i(
240
+ "button",
241
+ {
242
+ className: `icon-button ${v === e ? "active" : ""}`,
243
+ "aria-pressed": v === e,
244
+ "aria-label": `${v === e ? "Hide" : "Show"} ${o} panel`,
245
+ title: `${o} panel`,
246
+ onClick: () => K(e),
247
+ children: /* @__PURE__ */ i(t, { size: 17 })
248
+ },
249
+ e
250
+ ))
251
+ ] })
252
+ ] }),
253
+ /* @__PURE__ */ r("div", { className: "viewer-content", children: [
254
+ /* @__PURE__ */ i("div", { className: "viewer-map", children: I ? /* @__PURE__ */ i(q, { children: /* @__PURE__ */ i(
255
+ Je,
256
+ {
257
+ project: l,
258
+ initialFloor: ke,
259
+ dark: n.dark ?? !1,
260
+ onLocate: J,
261
+ onClose: () => j(!1)
262
+ }
263
+ ) }) : /* @__PURE__ */ i(
264
+ We,
265
+ {
266
+ ...n,
267
+ ...B,
268
+ controls: !1,
269
+ floorId: d,
270
+ selected: z,
271
+ focusId: n.focusId !== void 0 ? n.focusId : re,
272
+ viewMode: w,
273
+ stack: P,
274
+ avatar: y,
275
+ route: u,
276
+ playing: V,
277
+ activeStep: x,
278
+ onFloorChange: f,
279
+ onSelect: (e) => {
280
+ L(e), e && !v && S("properties");
281
+ },
282
+ onAvatar: ee,
283
+ onWalkAt: (e) => {
284
+ var t;
285
+ ee(e), f(e.floorId), M("walk"), (t = n.onWalkAt) == null || t.call(n, e);
286
+ },
287
+ onWalkExit: () => {
288
+ var e;
289
+ M("3d"), (e = n.onWalkExit) == null || e.call(n);
290
+ },
291
+ onJourneyStep: T,
292
+ onJourneyEnd: () => {
293
+ var e;
294
+ h(!1), (e = n.onJourneyEnd) == null || e.call(n);
295
+ },
296
+ initialCamera: Q.current,
297
+ onReady: (e) => {
298
+ var t;
299
+ N.current = e, requestAnimationFrame(U), (t = n.onReady) == null || t.call(n, e);
300
+ }
301
+ }
302
+ ) }),
303
+ v && /* @__PURE__ */ i("div", { className: "viewer-panel", children: v === "structure" ? /* @__PURE__ */ r(q, { children: [
304
+ /* @__PURE__ */ i(
305
+ "button",
306
+ {
307
+ className: "icon-button viewer-close-panel",
308
+ "aria-label": "Close structure panel",
309
+ onClick: () => S(null),
310
+ children: /* @__PURE__ */ i(Be, { size: 16 })
311
+ }
312
+ ),
313
+ /* @__PURE__ */ i(
314
+ Ue,
315
+ {
316
+ project: l,
317
+ selected: z,
318
+ onSelect: L,
319
+ onFloorChange: f,
320
+ onLocate: J,
321
+ onGraphView: Oe
322
+ }
323
+ )
324
+ ] }) : v === "navigate" ? /* @__PURE__ */ i(
325
+ Ke,
326
+ {
327
+ project: l,
328
+ here: y,
329
+ from: C,
330
+ to: F,
331
+ route: u,
332
+ playing: V,
333
+ activeStep: x,
334
+ onFrom: (e) => E(e, F),
335
+ onTo: (e) => E(C, e),
336
+ onSwap: () => E(F, C),
337
+ onClear: () => E(null, null),
338
+ onPlay: () => {
339
+ j(!1), R(null), $.current = u, T(0), h(!0);
340
+ },
341
+ onPause: () => h(!1),
342
+ onStep: (e) => te((x ?? (e === 1 ? -1 : 1)) + e),
343
+ onSeek: te,
344
+ onClose: () => {
345
+ h(!1), S(null);
346
+ }
347
+ }
348
+ ) : /* @__PURE__ */ i(
349
+ qe,
350
+ {
351
+ project: l,
352
+ floorId: d,
353
+ selected: z,
354
+ statuses: G,
355
+ monitoring: !!(n.statuses || n.elevators),
356
+ renderStatusPanel: n.renderStatusPanel,
357
+ onClose: () => S(null),
358
+ onSelect: Le,
359
+ onFloor: f
360
+ }
361
+ ) })
362
+ ] })
363
+ ]
364
+ }
365
+ );
366
+ }
367
+ export {
368
+ lt as default
369
+ };
370
+ //# sourceMappingURL=ViewerWorkspace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ViewerWorkspace.js","sources":["../../../../src/viewer/ViewerWorkspace.tsx"],"sourcesContent":["// Optional read-only chrome. Loaded only when requested; shares the editor's panels and renderer,\n// without importing SitePlanner, history, persistence or import dialogs.\nimport { useEffect, useMemo, useRef, useState } from 'react';\nimport { Box, Footprints, Layers3, PanelRightOpen, Shapes, SlidersHorizontal, Waypoints, X } from 'lucide-react';\nimport type { Map as GLMap } from 'maplibre-gl';\nimport { FloorViewer, type FloorViewerProps, type ViewerDisplayOptions, type ViewerMode } from './FloorViewer';\nimport { openingFloorId } from '../model/project';\nimport { findRoute, HERE, type Route, type RouteEnd } from '../model/navigation';\nimport { footprint, toLngLat } from '../model/geometry';\nimport type { CameraState } from '../model/host';\nimport type { Point } from '../model/types';\nimport type { WalkAvatar } from '../map/walk';\nimport { StructureView, type StructureTarget } from '../components/StructureView';\nimport { NavigationPanel, NavigationGraph, ReadOnlyInspector } from './panels';\nimport { FloorSelect } from '../components/controls';\n\nconst DISPLAY: ViewerDisplayOptions = {\n showLabels: true,\n showPlan: true,\n coverage: false,\n excavation: true,\n cityBuildings: false,\n cadastre: false,\n};\nconst DISPLAY_LABELS: Record<keyof ViewerDisplayOptions, string> = {\n showLabels: 'Object labels',\n showPlan: 'Floor plan',\n coverage: 'Device coverage',\n excavation: 'Underground context',\n cityBuildings: 'Surrounding buildings',\n cadastre: 'Cadastral parcels',\n};\ntype Panel = 'structure' | 'navigate' | 'properties' | null;\n\nexport default function ViewerWorkspace(props: FloorViewerProps) {\n const { project } = props;\n const [ownFloor, setOwnFloor] = useState(() => openingFloorId(project));\n const [ownSelected, setOwnSelected] = useState<string | null>(null);\n const [focusId, setFocusId] = useState<string | null>(null);\n const [ownMode, setOwnMode] = useState<ViewerMode>('2d');\n const [ownStack, setOwnStack] = useState(false);\n const [ownDisplay, setOwnDisplay] = useState(DISPLAY);\n const [ownAvatar, setOwnAvatar] = useState<WalkAvatar | null>(null);\n const [panel, setPanel] = useState<Panel>(null);\n const [graph, setGraph] = useState(false);\n const [graphFloor, setGraphFloor] = useState<string | null | undefined>();\n const [from, setFrom] = useState<string | null>(null);\n const [to, setTo] = useState<string | null>(null);\n const [ownPlaying, setOwnPlaying] = useState(false);\n const [ownStep, setOwnStep] = useState<number | null>(null);\n const floorId = props.floorId !== undefined ? props.floorId : ownFloor;\n const selected = props.selected !== undefined ? props.selected : ownSelected;\n const mode =\n props.viewMode ??\n (props.walk !== undefined || props.threeD !== undefined\n ? props.walk\n ? 'walk'\n : props.threeD\n ? '3d'\n : '2d'\n : ownMode);\n const stack = props.stack ?? ownStack;\n const avatar = props.avatar !== undefined ? props.avatar : ownAvatar;\n const playing = props.playing ?? ownPlaying;\n const activeStep = props.activeStep !== undefined ? props.activeStep : ownStep;\n const display = Object.fromEntries(\n Object.keys(DISPLAY).map(key => {\n const name = key as keyof ViewerDisplayOptions;\n return [name, props[name] ?? ownDisplay[name]];\n }),\n ) as unknown as ViewerDisplayOptions;\n const map = useRef<GLMap | null>(null);\n const camera = useRef<CameraState | undefined>(props.initialCamera);\n const pending = useRef<Point[] | null>(null);\n const root = useRef<HTMLDivElement>(null);\n const heldRoute = useRef<Route | null>(null);\n const [statusTick, setStatusTick] = useState(0);\n useEffect(() => {\n const timer = setInterval(() => setStatusTick(tick => tick + 1), 5000);\n return () => clearInterval(timer);\n }, []);\n const lastProject = useRef(project);\n useEffect(() => {\n if (props.floorId === undefined)\n setOwnFloor(current =>\n current === null || project.floors.some(f => f.id === current) ? current : openingFloorId(project),\n );\n if (props.selected === undefined)\n setOwnSelected(current =>\n [...project.objects, ...project.barriers, ...project.drawings, ...(project.virtualBoundaries ?? [])].some(\n o => o.id === current,\n )\n ? current\n : null,\n );\n if (lastProject.current !== project) {\n lastProject.current = project;\n setOwnPlaying(false);\n heldRoute.current = null;\n props.onPlayingChange?.(false);\n }\n }, [project]);\n const statuses = useMemo(\n () => new Map([...(props.statuses ?? []), ...(props.elevators?.statuses ?? [])].map(s => [s.feedId, s])),\n [props.statuses, props.elevators?.statuses, statusTick],\n );\n const proposedRoute = useMemo(() => {\n const end = (id: string | null): RouteEnd | null =>\n id === HERE ? (avatar ? { floorId: avatar.floorId, position: avatar.position } : null) : id;\n const a = end(from),\n b = end(to);\n return a && b ? findRoute(project, a, b, { statuses }) : null;\n }, [project, from, to, avatar, statuses]);\n // Keep the chosen path while the avatar and lift readings move. Rebuilding it every status tick\n // restarts the journey just as the lift is arriving. Runtime transport checks still read live status.\n const route = props.route !== undefined ? props.route : playing ? heldRoute.current : proposedRoute;\n const latestRouteChange = useRef(props.onRouteChange);\n latestRouteChange.current = props.onRouteChange;\n useEffect(() => latestRouteChange.current?.(route), [route]);\n const changeFloor = (id: string | null) => {\n setOwnFloor(id);\n props.onFloorChange?.(id);\n };\n const select = (id: string | null) => {\n setOwnSelected(id);\n props.onSelect?.(id);\n };\n const focusSelection = (id: string) => {\n const object = project.objects.find(o => o.id === id);\n if (object && object.floorId !== floorId && !object.servedFloorIds?.includes(floorId ?? ''))\n changeFloor(object.floorId);\n select(id);\n setFocusId(id);\n };\n const changeMode = (next: ViewerMode) => {\n setOwnMode(next);\n props.onViewModeChange?.(next);\n };\n const changeStack = (next: boolean) => {\n setOwnStack(next);\n props.onStackChange?.(next);\n };\n const changeAvatar = (next: WalkAvatar) => {\n setOwnAvatar(next);\n props.onAvatar?.(next);\n };\n const changePlaying = (next: boolean) => {\n setOwnPlaying(next);\n props.onPlayingChange?.(next);\n };\n const changeStep = (index: number) => {\n setOwnStep(index);\n props.onJourneyStep?.(index);\n };\n const endpoints = (a: string | null, b: string | null) => {\n changePlaying(false);\n setOwnStep(null);\n setFrom(a);\n setTo(b);\n };\n const frameLocated = () => {\n const points = pending.current,\n m = map.current;\n if (!points?.length || !m) return;\n pending.current = null;\n const ll = points.map(point => toLngLat(point, project.origin));\n m.fitBounds(\n [\n [Math.min(...ll.map(p => p[0])), Math.min(...ll.map(p => p[1]))],\n [Math.max(...ll.map(p => p[0])), Math.max(...ll.map(p => p[1]))],\n ],\n { padding: 80, maxZoom: 20, duration: 450 },\n );\n };\n const locate = (target: StructureTarget) => {\n const ids = new Set(target.objectIds ?? []);\n const objects = project.objects.filter(o => ids.has(o.id));\n const nextFloor =\n target.floorId !== undefined\n ? target.floorId\n : objects.some(o => o.floorId === floorId)\n ? floorId\n : objects.length\n ? objects[0].floorId\n : floorId;\n const onFloor = objects.filter(o => o.floorId === nextFloor || o.servedFloorIds?.includes(nextFloor ?? ''));\n pending.current = target.position ? [target.position] : onFloor.flatMap(o => footprint(o).flat());\n if (!pending.current.length)\n pending.current = project.objects.filter(o => o.floorId === nextFloor).flatMap(o => footprint(o).flat());\n changePlaying(false);\n setFocusId(null);\n select(onFloor[0]?.id ?? null);\n changeMode('2d');\n changeFloor(nextFloor);\n setGraph(false);\n requestAnimationFrame(frameLocated);\n };\n useEffect(() => {\n if (!graph) {\n const frame = requestAnimationFrame(frameLocated);\n return () => cancelAnimationFrame(frame);\n }\n }, [graph, floorId, mode]);\n const openGraph = (floor?: string | null) => {\n const m = map.current;\n if (m)\n camera.current = {\n center: [m.getCenter().lng, m.getCenter().lat],\n zoom: m.getZoom(),\n bearing: m.getBearing(),\n pitch: m.getPitch(),\n };\n changePlaying(false);\n setGraphFloor(floor);\n setGraph(true);\n map.current = null;\n };\n const seek = (index: number) => {\n if (!route) return;\n const i = Math.max(0, Math.min(route.steps.length - 1, index));\n const step = route.steps[i],\n node = route.nodes.find(n => n.id === step.nodeIds.at(-1));\n changePlaying(false);\n changeStep(i);\n if (node) locate({ floorId: node.floorId, position: node.position });\n else changeFloor(step.floorId);\n };\n const togglePanel = (next: Exclude<Panel, null>) => setPanel(current => (current === next ? null : next));\n const floorEntries = [\n { id: 'outdoors', code: 'OUT', name: 'Outdoor site' },\n ...[...project.floors]\n .sort((a, b) => b.elevation - a.elevation)\n .map(f => ({\n id: f.id,\n code: f.code ?? `${f.elevation} m`,\n name: f.name,\n hint: project.buildings.length > 1 ? project.buildings.find(b => b.id === f.buildingId)?.name : undefined,\n })),\n ];\n useEffect(() => {\n const key = (event: KeyboardEvent) => {\n if (\n graph ||\n event.defaultPrevented ||\n event.ctrlKey ||\n event.metaKey ||\n event.altKey ||\n !root.current?.contains(document.activeElement) ||\n (event.target as HTMLElement).closest('input,textarea,select,[contenteditable=true],[role=dialog]')\n )\n return;\n if (event.key.toLowerCase() === 't') changeMode(mode === '2d' ? '3d' : mode === '3d' ? 'walk' : '2d');\n else if (event.key.toLowerCase() === 'g') togglePanel('navigate');\n else if (event.key.toLowerCase() === 'i') togglePanel('properties');\n else if (event.shiftKey && ['ArrowUp', 'ArrowDown'].includes(event.key)) {\n const floors = [...project.floors].sort((a, b) => a.elevation - b.elevation);\n const i = floors.findIndex(f => f.id === floorId),\n next = floors[i + (event.key === 'ArrowUp' ? 1 : -1)];\n if (next) changeFloor(next.id);\n } else return;\n event.preventDefault();\n };\n window.addEventListener('keydown', key);\n return () => window.removeEventListener('keydown', key);\n });\n const modeLocked =\n (props.viewMode !== undefined || props.threeD !== undefined || props.walk !== undefined) && !props.onViewModeChange;\n return (\n <div\n ref={root}\n className={`kerros-root kerros-surface viewer-workspace ${props.dark ? 'dark' : ''}`}\n tabIndex={-1}\n onPointerDownCapture={event => {\n if (!(event.target as HTMLElement).closest('input,button,select,textarea,canvas')) root.current?.focus();\n }}\n >\n <div className=\"viewer-toolbar\" aria-label=\"Viewer controls\">\n <div className=\"floor-chip\">\n <Layers3 size={16} />\n <FloorSelect\n ariaLabel=\"Active floor\"\n value={floorId ?? 'outdoors'}\n entries={floorEntries}\n onPick={id => {\n changeFloor(id === 'outdoors' ? null : id);\n select(null);\n }}\n />\n </div>\n {!graph && (\n <>\n <div className=\"view-switch\">\n {(['2d', '3d', 'walk'] as const).map(next => (\n <button\n key={next}\n disabled={modeLocked}\n className={mode === next ? 'active' : ''}\n aria-pressed={mode === next}\n onClick={() => changeMode(next)}\n >\n {next === 'walk' ? <Footprints size={14} /> : next === '3d' ? <Box size={14} /> : null}\n {next === 'walk' ? 'Walk' : next.toUpperCase()}\n </button>\n ))}\n </div>\n {mode === '3d' && (\n <button\n className={`stack-button ${stack ? 'active' : ''}`}\n disabled={props.stack !== undefined && !props.onStackChange}\n aria-pressed={stack}\n onClick={() => changeStack(!stack)}\n >\n <Layers3 size={14} />\n {stack ? 'All floors' : 'Cutaway'}\n </button>\n )}\n </>\n )}\n <div className=\"viewer-toolbar-actions\">\n <details className=\"viewer-display-options\">\n <summary aria-label=\"View options\" title=\"View options\">\n <SlidersHorizontal size={17} />\n </summary>\n <div>\n {(Object.keys(DISPLAY) as (keyof ViewerDisplayOptions)[]).map(name => (\n <label key={name}>\n <input\n type=\"checkbox\"\n checked={display[name]}\n disabled={\n (props[name] !== undefined && !props.onDisplayChange) ||\n (name === 'cityBuildings' && !props.basemap?.vectorSchema?.footprints) ||\n (name === 'cadastre' && !props.basemap?.vectorSchema?.cadastre)\n }\n onChange={event => {\n const next = { ...display, [name]: event.target.checked };\n setOwnDisplay(next);\n props.onDisplayChange?.(next);\n }}\n />\n {DISPLAY_LABELS[name]}\n </label>\n ))}\n </div>\n </details>\n {(\n [\n ['structure', Shapes, 'structure'],\n ['navigate', Waypoints, 'navigation'],\n ['properties', PanelRightOpen, 'properties'],\n ] as const\n ).map(([name, Icon, label]) => (\n <button\n key={name}\n className={`icon-button ${panel === name ? 'active' : ''}`}\n aria-pressed={panel === name}\n aria-label={`${panel === name ? 'Hide' : 'Show'} ${label} panel`}\n title={`${label} panel`}\n onClick={() => togglePanel(name)}\n >\n <Icon size={17} />\n </button>\n ))}\n </div>\n </div>\n <div className=\"viewer-content\">\n <div className=\"viewer-map\">\n {graph ? (\n <>\n <NavigationGraph\n project={project}\n initialFloor={graphFloor}\n dark={props.dark ?? false}\n onLocate={locate}\n onClose={() => setGraph(false)}\n />\n </>\n ) : (\n <FloorViewer\n {...props}\n {...display}\n controls={false}\n floorId={floorId}\n selected={selected}\n focusId={props.focusId !== undefined ? props.focusId : focusId}\n viewMode={mode}\n stack={stack}\n avatar={avatar}\n route={route}\n playing={playing}\n activeStep={activeStep}\n onFloorChange={changeFloor}\n onSelect={id => {\n select(id);\n if (id && !panel) setPanel('properties');\n }}\n onAvatar={changeAvatar}\n onWalkAt={at => {\n changeAvatar(at);\n changeFloor(at.floorId);\n changeMode('walk');\n props.onWalkAt?.(at);\n }}\n onWalkExit={() => {\n changeMode('3d');\n props.onWalkExit?.();\n }}\n onJourneyStep={changeStep}\n onJourneyEnd={() => {\n changePlaying(false);\n props.onJourneyEnd?.();\n }}\n initialCamera={camera.current}\n onReady={m => {\n map.current = m;\n requestAnimationFrame(frameLocated);\n props.onReady?.(m);\n }}\n />\n )}\n </div>\n {panel && (\n <div className=\"viewer-panel\">\n {panel === 'structure' ? (\n <>\n <button\n className=\"icon-button viewer-close-panel\"\n aria-label=\"Close structure panel\"\n onClick={() => setPanel(null)}\n >\n <X size={16} />\n </button>\n <StructureView\n project={project}\n selected={selected}\n onSelect={select}\n onFloorChange={changeFloor}\n onLocate={locate}\n onGraphView={openGraph}\n />\n </>\n ) : panel === 'navigate' ? (\n <NavigationPanel\n project={project}\n here={avatar}\n from={from}\n to={to}\n route={route}\n playing={playing}\n activeStep={activeStep}\n onFrom={id => endpoints(id, to)}\n onTo={id => endpoints(from, id)}\n onSwap={() => endpoints(to, from)}\n onClear={() => endpoints(null, null)}\n onPlay={() => {\n setGraph(false);\n setFocusId(null);\n heldRoute.current = route;\n changeStep(0);\n changePlaying(true);\n }}\n onPause={() => changePlaying(false)}\n onStep={delta => seek((activeStep ?? (delta === 1 ? -1 : 1)) + delta)}\n onSeek={seek}\n onClose={() => {\n changePlaying(false);\n setPanel(null);\n }}\n />\n ) : (\n <ReadOnlyInspector\n project={project}\n floorId={floorId}\n selected={selected}\n statuses={statuses}\n monitoring={!!(props.statuses || props.elevators)}\n renderStatusPanel={props.renderStatusPanel}\n onClose={() => setPanel(null)}\n onSelect={focusSelection}\n onFloor={changeFloor}\n />\n )}\n </div>\n )}\n </div>\n </div>\n );\n}\n"],"names":["DISPLAY","DISPLAY_LABELS","ViewerWorkspace","props","project","ownFloor","setOwnFloor","useState","openingFloorId","ownSelected","setOwnSelected","focusId","setFocusId","ownMode","setOwnMode","ownStack","setOwnStack","ownDisplay","setOwnDisplay","ownAvatar","setOwnAvatar","panel","setPanel","graph","setGraph","graphFloor","setGraphFloor","from","setFrom","to","setTo","ownPlaying","setOwnPlaying","ownStep","setOwnStep","floorId","selected","mode","stack","avatar","playing","activeStep","display","key","name","map","useRef","camera","pending","root","heldRoute","statusTick","setStatusTick","useEffect","timer","tick","lastProject","current","f","_a","statuses","useMemo","s","proposedRoute","end","id","HERE","a","b","findRoute","route","latestRouteChange","changeFloor","select","focusSelection","object","o","changeMode","next","changeStack","changeAvatar","changePlaying","changeStep","index","endpoints","frameLocated","points","m","ll","point","toLngLat","p","locate","target","ids","objects","nextFloor","onFloor","footprint","frame","openGraph","floor","seek","i","step","node","n","togglePanel","floorEntries","event","floors","modeLocked","jsxs","jsx","Layers3","FloorSelect","Fragment","Footprints","Box","SlidersHorizontal","_b","_d","_c","Shapes","Waypoints","PanelRightOpen","Icon","label","NavigationGraph","FloorViewer","at","X","StructureView","NavigationPanel","delta","ReadOnlyInspector"],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import { jsx as n } from "react/jsx-runtime";
2
+ import { lazy as o, Suspense as a } from "react";
3
+ const i = o(() => import("../components/NavigatePanel.js").then((e) => ({ default: e.NavigatePanel }))), r = o(() => import("../components/NavigationGraph.js").then((e) => ({ default: e.NavigationGraph }))), l = o(() => import("../components/Inspector.js").then((e) => ({ default: e.Inspector }))), t = () => {
4
+ };
5
+ function s(e) {
6
+ return /* @__PURE__ */ n(a, { fallback: /* @__PURE__ */ n("p", { role: "status", children: "Loading directions…" }), children: /* @__PURE__ */ n(i, { ...e, editing: !1 }) });
7
+ }
8
+ function d(e) {
9
+ return /* @__PURE__ */ n(a, { fallback: /* @__PURE__ */ n("p", { role: "status", children: "Loading navigation graph…" }), children: /* @__PURE__ */ n(r, { ...e }) });
10
+ }
11
+ function f(e) {
12
+ return /* @__PURE__ */ n(a, { fallback: /* @__PURE__ */ n("p", { role: "status", children: "Loading properties…" }), children: /* @__PURE__ */ n(
13
+ l,
14
+ {
15
+ ...e,
16
+ editing: !1,
17
+ live: !1,
18
+ onUpdateObject: t,
19
+ onUpdateBarrier: t,
20
+ onUpdateDrawing: t,
21
+ onUpdateFloor: t,
22
+ onSetInitialFloor: t,
23
+ onDeleteFloor: t,
24
+ onDuplicate: t,
25
+ onDelete: t,
26
+ onTraceFootprint: t
27
+ }
28
+ ) });
29
+ }
30
+ export {
31
+ d as NavigationGraph,
32
+ s as NavigationPanel,
33
+ f as ReadOnlyInspector
34
+ };
35
+ //# sourceMappingURL=panels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"panels.js","sources":["../../../../src/viewer/panels.tsx"],"sourcesContent":["import { lazy, Suspense } from 'react';\nimport type { NavigatePanelProps } from '../components/NavigatePanel';\nimport type { NavigationGraphProps } from '../components/NavigationGraph';\nimport type { InspectorProps } from '../components/Inspector';\n\nconst Directions = lazy(() => import('../components/NavigatePanel').then(m => ({ default: m.NavigatePanel })));\nconst Graph = lazy(() => import('../components/NavigationGraph').then(m => ({ default: m.NavigationGraph })));\nconst Details = lazy(() => import('../components/Inspector').then(m => ({ default: m.Inspector })));\nconst NOOP = () => {};\nexport type NavigationPanelProps = Omit<NavigatePanelProps, 'editing'>;\nexport type { NavigationGraphProps };\nexport type ReadOnlyInspectorProps = Pick<\n InspectorProps,\n | 'project'\n | 'floorId'\n | 'selected'\n | 'statuses'\n | 'monitoring'\n | 'renderStatusPanel'\n | 'onClose'\n | 'onSelect'\n | 'onFloor'\n>;\n\n/** The editor's directions panel, with no authoring controls. */\nexport function NavigationPanel(props: NavigationPanelProps) {\n return (\n <Suspense fallback={<p role=\"status\">Loading directions…</p>}>\n <Directions {...props} editing={false} />\n </Suspense>\n );\n}\n/** A view of the routing graph; force layout never changes the document's node coordinates. */\nexport function NavigationGraph(props: NavigationGraphProps) {\n return (\n <Suspense fallback={<p role=\"status\">Loading navigation graph…</p>}>\n <Graph {...props} />\n </Suspense>\n );\n}\n/** The same geometry, relationships and status details as the editor, without mutation callbacks. */\nexport function ReadOnlyInspector(props: ReadOnlyInspectorProps) {\n return (\n <Suspense fallback={<p role=\"status\">Loading properties…</p>}>\n <Details\n {...props}\n editing={false}\n live={false}\n onUpdateObject={NOOP}\n onUpdateBarrier={NOOP}\n onUpdateDrawing={NOOP}\n onUpdateFloor={NOOP}\n onSetInitialFloor={NOOP}\n onDeleteFloor={NOOP}\n onDuplicate={NOOP}\n onDelete={NOOP}\n onTraceFootprint={NOOP}\n />\n </Suspense>\n );\n}\n"],"names":["Directions","lazy","m","Graph","Details","NOOP","NavigationPanel","props","jsx","Suspense","NavigationGraph","ReadOnlyInspector"],"mappings":";;AAKA,MAAMA,IAAaC,EAAK,MAAM,OAAO,gCAA6B,EAAE,KAAK,CAAAC,OAAM,EAAE,SAASA,EAAE,cAAA,EAAgB,CAAC,GACvGC,IAAQF,EAAK,MAAM,OAAO,kCAA+B,EAAE,KAAK,CAAAC,OAAM,EAAE,SAASA,EAAE,gBAAA,EAAkB,CAAC,GACtGE,IAAUH,EAAK,MAAM,OAAO,4BAAyB,EAAE,KAAK,CAAAC,OAAM,EAAE,SAASA,EAAE,UAAA,EAAY,CAAC,GAC5FG,IAAO,MAAM;AAAC;AAiBb,SAASC,EAAgBC,GAA6B;AAC3D,SACE,gBAAAC,EAACC,GAAA,EAAS,UAAU,gBAAAD,EAAC,OAAE,MAAK,UAAS,UAAA,sBAAA,CAAmB,GACtD,4BAACR,GAAA,EAAY,GAAGO,GAAO,SAAS,IAAO,GACzC;AAEJ;AAEO,SAASG,EAAgBH,GAA6B;AAC3D,SACE,gBAAAC,EAACC,GAAA,EAAS,UAAU,gBAAAD,EAAC,KAAA,EAAE,MAAK,UAAS,UAAA,4BAAA,CAAyB,GAC5D,UAAA,gBAAAA,EAACL,GAAA,EAAO,GAAGI,GAAO,GACpB;AAEJ;AAEO,SAASI,EAAkBJ,GAA+B;AAC/D,SACE,gBAAAC,EAACC,KAAS,UAAU,gBAAAD,EAAC,OAAE,MAAK,UAAS,iCAAmB,GACtD,UAAA,gBAAAA;AAAA,IAACJ;AAAA,IAAA;AAAA,MACE,GAAGG;AAAA,MACJ,SAAS;AAAA,MACT,MAAM;AAAA,MACN,gBAAgBF;AAAA,MAChB,iBAAiBA;AAAA,MACjB,iBAAiBA;AAAA,MACjB,eAAeA;AAAA,MACf,mBAAmBA;AAAA,MACnB,eAAeA;AAAA,MACf,aAAaA;AAAA,MACb,UAAUA;AAAA,MACV,kBAAkBA;AAAA,IAAA;AAAA,EAAA,GAEtB;AAEJ;"}
package/package.json CHANGED
@@ -1,6 +1,54 @@
1
1
  {
2
2
  "name": "@kerros/viewer",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.0-rc.1",
4
+ "description": "Read-only live floor-plan viewer for Kerros projects: 2D/3D MapLibre + three rendering, device statuses, navigation routes and journeys.",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/kherrala/kerros.git",
10
+ "directory": "packages/viewer"
11
+ },
12
+ "homepage": "https://github.com/kherrala/kerros#readme",
13
+ "bugs": "https://github.com/kherrala/kerros/issues",
14
+ "keywords": ["floor-plan", "indoor-mapping", "maplibre", "react", "three.js"],
15
+ "module": "./dist/index.js",
16
+ "types": "./dist/types/viewer/index.d.ts",
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/types/viewer/index.d.ts",
25
+ "import": "./dist/index.js"
26
+ },
27
+ "./host": {
28
+ "types": "./dist/types/viewer/host.d.ts",
29
+ "import": "./dist/host.js"
30
+ },
31
+ "./styles.css": "./dist/styles.css"
32
+ },
33
+ "scripts": {
34
+ "build": "vite build && tsc -p tsconfig.dts.json && cat ../../node_modules/maplibre-gl/dist/maplibre-gl.css ../../src/styles.css > dist/styles.css",
35
+ "prepack": "npm run build"
36
+ },
37
+ "sideEffects": [
38
+ "*.css"
39
+ ],
40
+ "peerDependencies": {
41
+ "react": "^19.0.0",
42
+ "react-dom": "^19.0.0",
43
+ "maplibre-gl": "^6.4.1",
44
+ "three": ">=0.170.0 <1.0.0"
45
+ },
46
+ "dependencies": {
47
+ "lucide-react": "^0.468.0",
48
+ "polygon-clipping": "^0.15.7"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public",
52
+ "registry": "https://registry.npmjs.org/"
53
+ }
54
+ }