@expofp/floorplan 3.26.0 → 3.27.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 (203) hide show
  1. package/dist/browser/{Button-DI5g1CPS.js → Button-KGleP3m4.js} +6 -6
  2. package/dist/browser/{CookieConsent-Qws_nQ3N.js → CookieConsent-_czkUaUS.js} +8 -8
  3. package/dist/browser/{Debug-DTNPNDds.js → Debug-bz6KlGgY.js} +8 -8
  4. package/dist/browser/DebugTools-CHRXev1e.js +1922 -0
  5. package/dist/browser/{Demo-BDZjOBQc.js → Demo-Duw5xaxW.js} +10 -10
  6. package/dist/browser/{Free-Cage9TkV.js → Free-CTEgif-b.js} +10 -10
  7. package/dist/browser/{GalleryContainer-EeLKgziN.js → GalleryContainer-DHLJOPfK.js} +11 -11
  8. package/dist/browser/{GpsLoader-CJMX_mJN.js → GpsLoader-CJ5KyhZa.js} +34 -34
  9. package/dist/browser/{KioskStore-BSza48xl.js → KioskStore-BMvlzIQe.js} +58 -107
  10. package/dist/browser/{MaplibreAdapter-evVQiVQj.js → MaplibreAdapter-YyHtIPQy.js} +2056 -2141
  11. package/dist/browser/{ModalContainer-CTKDfIyR.js → ModalContainer-DuilVP6n.js} +11 -11
  12. package/dist/browser/{PermissionNotice-O469DuWb.js → PermissionNotice-C5Z1g99X.js} +7 -7
  13. package/dist/browser/SetKioskMode-BcAj0bcd.js +48 -0
  14. package/dist/browser/{ShowKiosk-DumFiuHU.js → ShowKiosk-D7Klhgza.js} +11 -11
  15. package/dist/browser/{ViewerMenuPanel-ByFemA_T.js → ViewerMenuPanel-apP-IAf0.js} +17 -17
  16. package/dist/browser/{add-debug-secret-listener-TLumKuSo.js → add-debug-secret-listener-HZVxK64L.js} +1 -1
  17. package/dist/browser/{adopt-global-settings-ghJrZaU5.js → adopt-global-settings-CWSlkexR.js} +10 -10
  18. package/dist/browser/{boolean-editor-WIpm-pFP.js → boolean-editor-BcBAWb-G.js} +10 -10
  19. package/dist/browser/{bootIntercom-BR_Ehbyl.js → bootIntercom-Jil5W-0K.js} +3 -3
  20. package/dist/browser/bundle.json +77 -65
  21. package/dist/browser/camera-events-DrdhxgVS.js +18 -0
  22. package/dist/browser/{classnames-BmlkHMS8.js → classnames-BU0Ok49m.js} +2 -2
  23. package/dist/browser/{client-CIHxJZmk.js → client-BU_uyO3_.js} +793 -992
  24. package/dist/browser/{components-7lxOhyyi.js → components-CppHY7O7.js} +1952 -2013
  25. package/dist/browser/debug-context-C_w9lssh.js +24315 -0
  26. package/dist/browser/{debug-overlay-B7jCqVlX.js → debug-overlay-fKIQx7R_.js} +11 -11
  27. package/dist/browser/{debug-ui-D1ApG52e.js → debug-ui-BO_gZvdf.js} +7 -7
  28. package/dist/browser/dimming-WtGfPnAD.js +1108 -0
  29. package/dist/browser/{dist-BrF5yJyj.js → dist-BfpVKsX1.js} +6 -6
  30. package/dist/browser/{dist-C67OkD_4.js → dist-C2P11Xlj.js} +7 -7
  31. package/dist/browser/{dist-CnpnDA-V.js → dist-PTVsGItC.js} +3 -3
  32. package/dist/browser/{efp-debug-init-BqEN61Fo.js → efp-debug-init-Ce-CZeeI.js} +4 -4
  33. package/dist/browser/{enum-editor-Cy6VeZZd.js → enum-editor-CupsYrxs.js} +5 -5
  34. package/dist/browser/{es5-DyV1fctu.js → es5-DI5LkTYN.js} +2 -2
  35. package/dist/browser/{event-not-found-BpFVdXz_.js → event-not-found-D4Xi--mZ.js} +1 -1
  36. package/dist/browser/{exports-C7NzL4lf.js → exports-CePcAVlz.js} +1 -1
  37. package/dist/browser/{favicon-BHscWjwp.js → favicon-Dcly9HEc.js} +1 -1
  38. package/dist/browser/{fetch-retry.umd-BytZeydp.js → fetch-retry.umd-dWO0gw3b.js} +2 -2
  39. package/dist/browser/{flex-BQBLAC6l.js → flex-nmgYIErO.js} +6 -6
  40. package/dist/browser/{floorplan.loader-DkaQPhwC.js → floorplan.loader-Nb2QDU7l.js} +10 -10
  41. package/dist/browser/{floorplan.ready-DwuXZphI.js → floorplan.ready-D_9nn960.js} +344 -308
  42. package/dist/browser/{fuse-DZTwJ52u.js → fuse-s0oxaMyr.js} +2 -2
  43. package/dist/browser/{i18n-Bcv8xw_q.js → i18n-D0X-IbhS.js} +5 -5
  44. package/dist/browser/index.js +14 -14
  45. package/dist/browser/{index.module-BFxDVa3K.js → index.module-CtQP4Qv8.js} +4 -4
  46. package/dist/browser/{integrateKiosk-VTNZSSfD.js → integrateKiosk-CTKZOTyE.js} +5 -5
  47. package/dist/browser/{is-webview-CjItzxdV.js → is-webview-C5K2dDqT.js} +1 -1
  48. package/dist/browser/{jsx-runtime-CT2c-IhD.js → jsx-runtime-hIg99QxI.js} +2 -2
  49. package/dist/browser/{kiosk-record-v7r7q7t0.js → kiosk-record-BkSt5SU1.js} +1 -1
  50. package/dist/browser/{lib-DGh8lZgT.js → lib-DyJ1LDRt.js} +3 -3
  51. package/dist/browser/{loadImage-a_ahClbD.js → loadImage-Chw6Qd0w.js} +4 -4
  52. package/dist/browser/{logDeviceInfo-DHfa6NcE.js → logDeviceInfo-3jqov_0t.js} +9 -9
  53. package/dist/browser/{mobx-dAtztuiQ.js → mobx-C29RNezs.js} +7 -7
  54. package/dist/browser/{optional-boolean-editor-D43-yLO3.js → optional-boolean-editor-DYudule5.js} +4 -4
  55. package/dist/browser/{optional-enum-editor-Cvn8TV-x.js → optional-enum-editor-CdOjFlrE.js} +5 -5
  56. package/dist/browser/{optional-string-editor-sY0yVw_j.js → optional-string-editor-DIJigrO5.js} +5 -5
  57. package/dist/browser/{particles.min-BD7iDSr6.js → particles.min-BZCTScUM.js} +2 -2
  58. package/dist/browser/{react-BJopqGbW.js → react-D4xfjtF6.js} +2 -2
  59. package/dist/browser/{react-dom-B77nDdqp.js → react-dom-B6MtngPG.js} +3 -3
  60. package/dist/browser/{rolldown-runtime-BmHtYG9i.js → rolldown-runtime-hkgDPyCj.js} +1 -1
  61. package/dist/browser/scheduler-CUIe3W2m.js +212 -0
  62. package/dist/browser/{select-ByU-Ym6-.js → select-Dt6UIEBZ.js} +11 -11
  63. package/dist/browser/{settings-CEH1i0Pj.js → settings-CyYgXisa.js} +2 -2
  64. package/dist/browser/{settings-item-_PTji9Bz.js → settings-item-COIUD8kZ.js} +7 -7
  65. package/dist/browser/store-C33lZtwI.js +31207 -0
  66. package/dist/browser/{string-editor-DaF1t7MK.js → string-editor-kOSWCbwh.js} +5 -5
  67. package/dist/browser/{text-field-XRLZPyNV.js → text-field-DD6CFKaL.js} +6 -6
  68. package/dist/browser/{theme-D0OZcdto.js → theme-gxjTjrZ9.js} +9 -9
  69. package/dist/browser/{ui-7ozfXlN3.js → ui-DBItAumt.js} +9 -9
  70. package/dist/browser/{useRenderTarget-BG295f3e.js → useRenderTarget-DkuQpLE2.js} +5 -5
  71. package/dist/browser/viewport-A_9Nzrm0.js +41 -0
  72. package/dist/esm/components/Kiosk/KioskStore.d.ts +5 -2
  73. package/dist/esm/components/Kiosk/KioskStore.js +1 -1
  74. package/dist/esm/components/Kiosk/SetKioskMode.d.ts +1 -2
  75. package/dist/esm/components/Kiosk/SetKioskMode.js +1 -1
  76. package/dist/esm/components/Map/Map.d.ts +1 -1
  77. package/dist/esm/components/Map/Map.js +1 -1
  78. package/dist/esm/components/Map/MapCamera.d.ts +17 -0
  79. package/dist/esm/components/Map/MapCamera.js +1 -0
  80. package/dist/esm/components/Map/MapViewport.d.ts +12 -0
  81. package/dist/esm/components/Map/MapViewport.js +1 -0
  82. package/dist/esm/components/Map/booth-by-xy.d.ts +13 -0
  83. package/dist/esm/components/Map/booth-by-xy.js +1 -1
  84. package/dist/esm/components/Map/camera-events.d.ts +16 -0
  85. package/dist/esm/components/Map/camera-events.js +1 -0
  86. package/dist/esm/components/Map/camera.d.ts +48 -0
  87. package/dist/esm/components/Map/camera.js +1 -0
  88. package/dist/esm/components/Map/drawing/config/TextFitter.d.ts +1 -1
  89. package/dist/esm/components/Map/drawing/config/config-all.d.ts +1 -2
  90. package/dist/esm/components/Map/drawing/config/config-all.js +1 -1
  91. package/dist/esm/components/Map/drawing/config/config-bg.d.ts +1 -2
  92. package/dist/esm/components/Map/drawing/config/config-bg.js +1 -1
  93. package/dist/esm/components/Map/drawing/config/config-booth-badge.d.ts +70 -3
  94. package/dist/esm/components/Map/drawing/config/config-booth-badge.js +1 -1
  95. package/dist/esm/components/Map/drawing/config/config-booth-bg.d.ts +3 -6
  96. package/dist/esm/components/Map/drawing/config/config-booth-bg.js +1 -1
  97. package/dist/esm/components/Map/drawing/config/config-booth-bookmark.d.ts +11 -7
  98. package/dist/esm/components/Map/drawing/config/config-booth-bookmark.js +1 -1
  99. package/dist/esm/components/Map/drawing/config/config-booth-border.d.ts +2 -3
  100. package/dist/esm/components/Map/drawing/config/config-booth-border.js +1 -1
  101. package/dist/esm/components/Map/drawing/config/config-booth-labels-special.d.ts +16 -3
  102. package/dist/esm/components/Map/drawing/config/config-booth-labels-special.js +2 -2
  103. package/dist/esm/components/Map/drawing/config/config-booth-labels.d.ts +18 -4
  104. package/dist/esm/components/Map/drawing/config/config-booth-labels.js +1 -1
  105. package/dist/esm/components/Map/drawing/config/config-booths.d.ts +1 -2
  106. package/dist/esm/components/Map/drawing/config/config-booths.js +1 -1
  107. package/dist/esm/components/Map/drawing/config/config-load-layer.d.ts +1 -2
  108. package/dist/esm/components/Map/drawing/config/config-load-layer.js +1 -1
  109. package/dist/esm/components/Map/drawing/config/config-markers.d.ts +23 -2
  110. package/dist/esm/components/Map/drawing/config/config-markers.js +1 -1
  111. package/dist/esm/components/Map/drawing/config/layer-images.d.ts +35 -0
  112. package/dist/esm/components/Map/drawing/config/layer-images.js +1 -0
  113. package/dist/esm/components/Map/drawing/config/loadBoothsImages.d.ts +38 -3
  114. package/dist/esm/components/Map/drawing/config/loadBoothsImages.js +1 -1
  115. package/dist/esm/components/Map/pointer.d.ts +73 -0
  116. package/dist/esm/components/Map/pointer.js +1 -0
  117. package/dist/esm/components/Map/scene.d.ts +20 -0
  118. package/dist/esm/components/Map/scene.js +1 -0
  119. package/dist/esm/components/Map/traffic/trafficLayers.d.ts +2 -7
  120. package/dist/esm/components/Map/traffic/trafficLayers.js +1 -1
  121. package/dist/esm/components/Map/traffic/useBuildRoute.d.ts +4 -3
  122. package/dist/esm/components/Map/traffic/useBuildRoute.js +6 -6
  123. package/dist/esm/components/Map/traffic/useManageTraffic.d.ts +4 -3
  124. package/dist/esm/components/Map/traffic/useManageTraffic.js +1 -1
  125. package/dist/esm/components/Map/viewport.d.ts +63 -0
  126. package/dist/esm/components/Map/viewport.js +1 -0
  127. package/dist/esm/components/Maplibre/MaplibreAdapter.d.ts +6 -2
  128. package/dist/esm/components/Maplibre/MaplibreAdapter.js +1 -1
  129. package/dist/esm/components/Maplibre/MaplibreWrapper.d.ts +30 -8
  130. package/dist/esm/components/Maplibre/MaplibreWrapper.js +1 -1
  131. package/dist/esm/components/Maplibre/useDimming.d.ts +2 -2
  132. package/dist/esm/components/Maplibre/useDimming.js +1 -1
  133. package/dist/esm/components/Maplibre/useKioskIdleEvents.d.ts +5 -6
  134. package/dist/esm/components/Maplibre/useLayerVisibilitySync.d.ts +2 -2
  135. package/dist/esm/components/Maplibre/useLayerVisibilitySync.js +1 -1
  136. package/dist/esm/components/Maplibre/usePoiMarkers.d.ts +1 -2
  137. package/dist/esm/components/Maplibre/useWayfindingAndMarkers.d.ts +8 -5
  138. package/dist/esm/components/Maplibre/useWayfindingAndMarkers.js +1 -1
  139. package/dist/esm/components/Maplibre/utils/layer-defs.d.ts +8 -3
  140. package/dist/esm/components/Maplibre/utils/layer-defs.js +1 -1
  141. package/dist/esm/components/Maplibre/utils/poi-marker-hit-test.d.ts +3 -3
  142. package/dist/esm/components/Ws.js +1 -1
  143. package/dist/esm/engine/defs.d.ts +30 -0
  144. package/dist/esm/engine/defs.js +3 -0
  145. package/dist/esm/engine/fonts.js +1 -0
  146. package/dist/esm/engine/update-def.d.ts +52 -0
  147. package/dist/esm/engine/update-def.js +1 -0
  148. package/dist/esm/engine/utils/rotation.d.ts +6 -0
  149. package/dist/esm/engine/utils/rotation.js +1 -0
  150. package/dist/esm/floorplan.ready.d.ts +2 -0
  151. package/dist/esm/floorplan.ready.js +1 -1
  152. package/dist/esm/store/BoothStore.d.ts +11 -0
  153. package/dist/esm/store/LayerStore.d.ts +2 -0
  154. package/dist/esm/store/LayerStore.js +1 -1
  155. package/dist/esm/store/RootStore.d.ts +0 -2
  156. package/dist/esm/store/RootStore.js +1 -1
  157. package/dist/esm/store/RouteStore.js +1 -1
  158. package/dist/esm/store/UIState.js +1 -1
  159. package/dist/esm/store/details-events.d.ts +11 -0
  160. package/dist/esm/store/details-events.js +1 -0
  161. package/dist/esm/store/init/init-booths.js +1 -1
  162. package/dist/esm/utils/dimming.d.ts +13 -2
  163. package/dist/esm/utils/dimming.js +1 -1
  164. package/dist/esm/utils/mobx.d.ts +2 -2
  165. package/dist/esm/utils/mobx.js +1 -1
  166. package/dist/esm/utils/scene-bounds.d.ts +1 -1
  167. package/dist/esm/utils/scene-bounds.js +1 -1
  168. package/dist/esm/wayfinding/adapters/canvasIconProvider.js +1 -1
  169. package/dist/esm/wayfinding/createWayfinding.d.ts +19 -2
  170. package/dist/esm/wayfinding/createWayfinding.js +1 -1
  171. package/package.json +11 -10
  172. package/dist/browser/SetKioskMode-DUk4c-Gs.js +0 -57
  173. package/dist/browser/booth-by-xy-CyZpg1Fn.js +0 -1130
  174. package/dist/browser/main-sUuehgQu.js +0 -289
  175. package/dist/browser/store-Oj0dGPnb.js +0 -41431
  176. package/dist/esm/components/Map/pointInConvexQuad.d.ts +0 -3
  177. package/dist/esm/components/Map/pointInConvexQuad.js +0 -1
  178. package/dist/esm/components/Map/visibleArea.d.ts +0 -16
  179. package/dist/esm/components/Map/visibleArea.js +0 -1
  180. package/dist/esm/components/Maplibre/useRendererEvents.d.ts +0 -9
  181. package/dist/esm/components/Maplibre/useRendererEvents.js +0 -1
  182. package/dist/esm/components/Maplibre/utils/update-pump.d.ts +0 -18
  183. package/dist/esm/components/Maplibre/utils/update-pump.js +0 -1
  184. package/dist/esm/renderer/HandlerRegistry.d.ts +0 -18
  185. package/dist/esm/renderer/HandlerRegistry.js +0 -1
  186. package/dist/esm/renderer/RendererService.d.ts +0 -44
  187. package/dist/esm/renderer/RendererService.js +0 -1
  188. package/dist/esm/renderer/engine-core/defs.d.ts +0 -40
  189. package/dist/esm/renderer/engine-core/defs.js +0 -3
  190. package/dist/esm/renderer/engine-core/fonts.js +0 -1
  191. package/dist/esm/renderer/engine-core/settings.d.ts +0 -4
  192. package/dist/esm/renderer/engine-core/settings.js +0 -1
  193. package/dist/esm/renderer/engine-core/types.d.ts +0 -50
  194. package/dist/esm/renderer/engine-core/types.js +0 -1
  195. package/dist/esm/renderer/engine-core/update-def.d.ts +0 -12
  196. package/dist/esm/renderer/engine-core/update-def.js +0 -1
  197. package/dist/esm/renderer/engine-core/utils/rotation.d.ts +0 -17
  198. package/dist/esm/renderer/engine-core/utils/rotation.js +0 -1
  199. package/dist/esm/renderer/index.d.ts +0 -19
  200. package/dist/esm/renderer/index.js +0 -1
  201. /package/dist/esm/{renderer/engine-core → engine}/canvases.d.ts +0 -0
  202. /package/dist/esm/{renderer/engine-core → engine}/canvases.js +0 -0
  203. /package/dist/esm/{renderer/engine-core → engine}/fonts.d.ts +0 -0
@@ -0,0 +1,73 @@
1
+ import { type PointerEventData, type PointerMissedEventData, type ShapeDef } from '@expofp/renderer';
2
+ import { type Booth } from '../../store/BoothStore';
3
+ import { type FloorPlanMarkerEvent } from '../../types';
4
+ /** How a click on the plan resolves to a marker. See {@link setMarkerResolver}. */
5
+ export type MarkerResolver = (x: number, y: number) => FloorPlanMarkerEvent | null;
6
+ /**
7
+ * Registers a listener for every click that lands on the plan, hit or miss, before selection acts
8
+ * on it — the seam the kiosk setup screen and the route-authoring tool take their clicks from,
9
+ * which the imperative renderer served with its own `pointer:click` listeners.
10
+ *
11
+ * One listener at a time: the two consumers are modal and never active together.
12
+ * @param listener - Receives the plan point; omitted to unregister.
13
+ */
14
+ export declare function setPlanClickListener(listener?: (point: {
15
+ x: number;
16
+ y: number;
17
+ }) => void): void;
18
+ /**
19
+ * Registers how a click resolves to a marker, for as long as markers are drawn.
20
+ *
21
+ * The same inversion {@link rememberBoothShapes} performs for booths, and for the same reason: this
22
+ * seam is reached from a click and must stay free of the modules that build defs — the marker hit
23
+ * test needs both the marker data and the pixel size their own layer is laid out at.
24
+ * @param resolve - Returns the marker under a plan point, or `null`; omitted to unregister.
25
+ */
26
+ export declare function setMarkerResolver(resolve?: MarkerResolver): void;
27
+ /**
28
+ * Records which booth a set of background shapes belongs to, so a pointer hit can name it.
29
+ *
30
+ * A booth draws as one rect, or as several polygons when it comes from paths, and the renderer
31
+ * reports whichever def was hit. Registered where the defs are built rather than searched for later:
32
+ * the alternative is scanning every booth's shapes on every pointer move.
33
+ * @param booth - The booth the shapes draw.
34
+ * @param shapes - Its background shapes.
35
+ */
36
+ export declare function rememberBoothShapes(booth: Booth, shapes: readonly ShapeDef[]): void;
37
+ /**
38
+ * The booth a hit def draws, if any.
39
+ * @param def - The def the renderer reported.
40
+ * @returns The booth, or `null` for a def that is not a booth background.
41
+ */
42
+ export declare function boothOfShape(def: ShapeDef): Booth | null;
43
+ /**
44
+ * Tracks the booth under the pointer. Declared on the booth background layer, which is the only
45
+ * layer the plan picks in.
46
+ * @param event - The def under the pointer.
47
+ */
48
+ export declare function hoverBooth(event: PointerEventData<ShapeDef>): void;
49
+ /**
50
+ * Clears the hovered booth as the pointer leaves it.
51
+ */
52
+ export declare function clearHoveredBooth(): void;
53
+ /**
54
+ * Selects the booth that was clicked.
55
+ * @param event - The def that was clicked, and where on the plan.
56
+ */
57
+ export declare function selectBooth(event: PointerEventData<ShapeDef>): void;
58
+ /**
59
+ * Handles a click that reached no booth — empty background, or a def in a layer the plan does not
60
+ * pick in — which deselects, exactly as clicking away from a booth always has.
61
+ * @param event - Where on the plan the click landed.
62
+ */
63
+ export declare function clearSelection(event: PointerMissedEventData): void;
64
+ /**
65
+ * Calls the host page's reset hook, if it left one. A global the embedding page installs; the SDK
66
+ * only ever calls it.
67
+ *
68
+ * Exported because a camera move clears it too, not only a click: `MapCamera` calls it from the
69
+ * controls' own update event, which is what the imperative renderer's `navigation:change` listener
70
+ * did.
71
+ */
72
+ export declare function resetExternalOverlay(): void;
73
+ //# sourceMappingURL=pointer.d.ts.map
@@ -0,0 +1 @@
1
+ import n,{uiState as o}from"../../store";import{LayerMode as l}from"../../store/LayerStore";import{poiMarkerHitTest as a}from"../Maplibre/utils/poi-marker-hit-test";import d from"./booth-by-xy";export function setPlanClickListener(e){c=e}export function setMarkerResolver(e){u=e}export function rememberBoothShapes(e,t){for(const r of t)s.set(r,e)}export function boothOfShape(e){return s.get(e)??null}export function hoverBooth(e){o.setKioskModeEnabled||(o.hoveredBooth=i(e.point,e.def))}export function clearHoveredBooth(){o.setKioskModeEnabled||(o.hoveredBooth=null)}export function selectBooth(e){f(e.point)&&n.clickBooth(i(e.point,e.def))}export function clearSelection(e){f(e.point)&&n.clickBooth(i(e.point))}function i(e,t){const r=t?boothOfShape(t):null;return r||d(e.x,e.y)}function f(e){if(!o.rootElement)return!1;if(resetExternalOverlay(),c?.(e),o.overlayPosition==="bottom"&&o.overlaySize==="full"&&n.showMap(),o.onGetCoordsClick){const t=n.layerStore.layers.find(r=>r.visible&&(r.mode===l.TurnedOn||r.mode===l.TurnedOff));o.onGetCoordsClick({x:e.x,y:e.y,z:t?.name||null})}if(o.setKioskModeEnabled||a.test(e.x,e.y))return!1;if(o.onMarkerClick){const t=u?.(e.x,e.y)??null;o.onMarkerClick(t)}return!0}export function resetExternalOverlay(){if(typeof window>"u")return;const e=window.__resett;e?.()}const s=new WeakMap;let u,c;
@@ -0,0 +1,20 @@
1
+ import { type SceneDef } from '@expofp/renderer';
2
+ /**
3
+ * Publishes the scene the mounted map is drawing, for as long as it is on screen.
4
+ *
5
+ * The same inversion `setMapCamera` and `setMapViewport` perform, for the same callers: the parts
6
+ * of the SDK that are not components — the venue-fit resolution in `UIState.fitBounds`, the traffic
7
+ * hooks — need the def tree the map built, and the map is the one place that knows it. The
8
+ * imperative path parked the scene on `RendererService`; this hands it out without the service.
9
+ * @param scene - The scene; omitted to unpublish it as the map unmounts.
10
+ */
11
+ export declare function setMapScene(scene?: SceneDef): void;
12
+ /**
13
+ * The scene the mounted map is drawing, if one is on screen.
14
+ *
15
+ * Absent before the map has built its scene, and after it unmounts. In MapLibre mode the adapter
16
+ * publishes the embed's prepared scene the same way.
17
+ * @returns The scene, or `undefined`.
18
+ */
19
+ export declare function mapScene(): SceneDef | undefined;
20
+ //# sourceMappingURL=scene.d.ts.map
@@ -0,0 +1 @@
1
+ export function setMapScene(n){e=n}export function mapScene(){return e}let e;
@@ -3,15 +3,10 @@ export declare const TRAFFIC_ROUTE_STOP_PREFIX = "traffic_route_stop";
3
3
  export declare const TRAFFIC_VEHICLES = "traffic_vehicles";
4
4
  export declare const BUILD_ROUTE_LINES = "build_route_lines";
5
5
  export declare const BUILD_ROUTE_DOTS = "build_route_dots";
6
- export declare function createTrafficLayers(): ({
6
+ export declare function createTrafficLayers(): {
7
7
  name: string;
8
8
  children: never[];
9
- interactive?: undefined;
10
- } | {
11
- name: string;
12
- children: never[];
13
- interactive: boolean;
14
- })[];
9
+ }[];
15
10
  export declare function getRouteLayerRegex(): RegExp;
16
11
  export declare function getRouteStopLayerRegex(): RegExp;
17
12
  //# sourceMappingURL=trafficLayers.d.ts.map
@@ -1 +1 @@
1
- export const TRAFFIC_ROUTE_PREFIX="traffic_route",TRAFFIC_ROUTE_STOP_PREFIX="traffic_route_stop",TRAFFIC_VEHICLES="traffic_vehicles",BUILD_ROUTE_LINES="build_route_lines",BUILD_ROUTE_DOTS="build_route_dots";const o=5;export function createTrafficLayers(){const e=[];for(let t=0;t<5;t++)e.push({name:r(t),children:[]}),e.push({name:n(t),children:[],interactive:!0});return e.push({name:TRAFFIC_VEHICLES,children:[],interactive:!0}),e.push({name:BUILD_ROUTE_LINES,children:[]}),e.push({name:BUILD_ROUTE_DOTS,children:[],interactive:!0}),e}function r(e){return`${TRAFFIC_ROUTE_PREFIX}_${e+1}`}function n(e){return`${TRAFFIC_ROUTE_STOP_PREFIX}_${e+1}`}export function getRouteLayerRegex(){return new RegExp(`^${TRAFFIC_ROUTE_PREFIX}_\\d+$`)}export function getRouteStopLayerRegex(){return new RegExp(`^${TRAFFIC_ROUTE_STOP_PREFIX}_\\d+$`)}
1
+ export const TRAFFIC_ROUTE_PREFIX="traffic_route",TRAFFIC_ROUTE_STOP_PREFIX="traffic_route_stop",TRAFFIC_VEHICLES="traffic_vehicles",BUILD_ROUTE_LINES="build_route_lines",BUILD_ROUTE_DOTS="build_route_dots";const o=5;export function createTrafficLayers(){const e=[];for(let t=0;t<5;t++)e.push({name:r(t),children:[]}),e.push({name:n(t),children:[]});return e.push({name:TRAFFIC_VEHICLES,children:[]}),e.push({name:BUILD_ROUTE_LINES,children:[]}),e.push({name:BUILD_ROUTE_DOTS,children:[]}),e}function r(e){return`${TRAFFIC_ROUTE_PREFIX}_${e+1}`}function n(e){return`${TRAFFIC_ROUTE_STOP_PREFIX}_${e+1}`}export function getRouteLayerRegex(){return new RegExp(`^${TRAFFIC_ROUTE_PREFIX}_\\d+$`)}export function getRouteStopLayerRegex(){return new RegExp(`^${TRAFFIC_ROUTE_STOP_PREFIX}_\\d+$`)}
@@ -1,8 +1,9 @@
1
- import { RendererService } from '../../../renderer';
1
+ import { SceneDef } from '@expofp/renderer';
2
2
  export interface BuildRouteParams {
3
3
  enabled: boolean;
4
- rendererService: RendererService;
4
+ /** The scene whose build-route layers this draws into. */
5
+ scene: SceneDef | undefined;
5
6
  cb?: () => void;
6
7
  }
7
- export declare function useBuildRoute({ enabled, rendererService }: BuildRouteParams): void;
8
+ export declare function useBuildRoute({ enabled, scene }: BuildRouteParams): void;
8
9
  //# sourceMappingURL=useBuildRoute.d.ts.map
@@ -1,7 +1,7 @@
1
- import{lineIntersection as M}from"@expofp/geometry";import{useCallback as x,useEffect as T,useMemo as _,useRef as P}from"react";import{rectToRenderer as O}from"../../../renderer";import{createCircleCanvas as S,getBounds as b}from"../../../renderer/engine-core/canvases";import{isDefaultScene as U,pickDefaultScene as $}from"../../../renderer/engine-core/defs";import{BUILD_ROUTE_DOTS as K,BUILD_ROUTE_LINES as H}from"./trafficLayers";import{UpdateQueue as B}from"./UpdateQueue";const v=49,C=`hsl(257, 76%, ${v}%)`,Y=`hsl(339.903, 82%, ${v}%)`,J=`hsl(257, 76%, ${Math.round(v*1.82)}%)`,I=4,j=I,R="U",D="R",A="S",N="P";class q{constructor(){this._state=[[]],this.index=0,this.pointHashSet=new Set,this.locked=!1,this.storageKey="expofp_build_route_state",this._selected=0}get points(){return this._state[this.index]}set points(t){this._state.push(t),this.setIndex(),this.save()}setIndex(){this.index=Math.max(this._state.length-1,0)}genPointHash(t){return`${t.x},${t.y}`}add(t){const a=this.genPointHash(t);this.pointHashSet.has(a)||(this.pointHashSet.add(a),this.points=[...this.points,t])}undo(){this.index&&(this._state.pop(),this.setIndex(),this.save(),this.select(this.points.length-1))}execute(t){try{if(this.locked)return;this.locked=!0,t()}finally{requestAnimationFrame(()=>{this.locked=!1})}}log(t,a=12){console.log(`%c${t}`,`color: black; font-size: ${a}px; background: LemonChiffon;`)}instruct(){this.log(`How to Build a Route:
1
+ import{lineIntersection as U}from"@expofp/geometry";import{update as O}from"@expofp/renderer";import{useCallback as x,useEffect as $,useMemo as S,useRef as P}from"react";import{createCircleCanvas as v,getBounds as b}from"../../../engine/canvases";import{mapCamera as K}from"../camera";import{setPlanClickListener as E}from"../pointer";import{BUILD_ROUTE_DOTS as T,BUILD_ROUTE_LINES as H}from"./trafficLayers";import{UpdateQueue as B}from"./UpdateQueue";const C=49,R=`hsl(257, 76%, ${C}%)`,Y=`hsl(339.903, 82%, ${C}%)`,J=`hsl(257, 76%, ${Math.round(C*1.82)}%)`,I=4,j=I,D="U",A="R",N="S",M="P";class q{constructor(){this._state=[[]],this.index=0,this.pointHashSet=new Set,this.locked=!1,this.storageKey="expofp_build_route_state",this._selected=0}get points(){return this._state[this.index]}set points(e){this._state.push(e),this.setIndex(),this.save()}setIndex(){this.index=Math.max(this._state.length-1,0)}genPointHash(e){return`${e.x},${e.y}`}add(e){const l=this.genPointHash(e);this.pointHashSet.has(l)||(this.pointHashSet.add(l),this.points=[...this.points,e])}undo(){this.index&&(this._state.pop(),this.setIndex(),this.save(),this.select(this.points.length-1))}execute(e){try{if(this.locked)return;this.locked=!0,e()}finally{requestAnimationFrame(()=>{this.locked=!1})}}log(e,l=12){console.log(`%c${e}`,`color: black; font-size: ${l}px; background: LemonChiffon;`)}instruct(){this.log(`How to Build a Route:
2
2
  Add Point: Click on the map.
3
- Apply Smoothing: Press ${D}.
4
- Apply Simplification: Press ${A}.
5
- Undo: Press ${R}.
6
- Enable/Disable Preview: Press ${N}.
7
- `,16)}applyChaikinSmoothing(t,a,d){let r=[];if(d>=1&&t.length>=2){r=[t[0]];for(let h=1;h<t.length;h++){const e=t[h-1],u=t[h];for(let o=1;o<=d;o++){const n=o/(d+1);r.push({x:e.x+(u.x-e.x)*n,y:e.y+(u.y-e.y)*n})}r.push(u)}}else r=t.slice();for(let h=0;h<a&&!(r.length<2);h++){const e=[{...r[0]}];for(let u=1;u<r.length;u++){const o=r[u-1],n=r[u];e.push({x:.75*o.x+.25*n.x,y:.75*o.y+.25*n.y}),e.push({x:.25*o.x+.75*n.x,y:.25*o.y+.75*n.y})}e.push({...r[r.length-1]}),r=e}return r}applySmoothing(){this.points.length<3||(this.points=this.applyChaikinSmoothing(this.points,1,0),this.select(this.points.length-1))}save(){try{this.points.length?sessionStorage.setItem(this.storageKey,JSON.stringify(this.points)):sessionStorage.removeItem(this.storageKey)}catch(t){console.warn(t)}}restore(){try{const t=sessionStorage.getItem(this.storageKey);if(!t)return;const a=JSON.parse(t);if(!Array.isArray(a))return;a.forEach(d=>this.add(d)),this.select(this.points.length-1)}catch(t){console.warn(t)}}topologyPreservingSimplify(t,a){if(t.length<=2)return t.map(o=>({...o}));const d=(o,n,y)=>{const g=o.x,f=o.y,s=n.x,i=n.y,c=y.x,l=y.y,m=Math.abs((l-i)*g-(c-s)*f+c*i-l*s),p=Math.sqrt((l-i)**2+(c-s)**2);return m/(p||1e-10)},r=(o,n,y,g)=>{const f=M({p0:o,p1:n},{p0:y,p1:g});return f!==null&&f.onLine1&&f.onLine2},h=new Array(t.length).fill(!1);h[0]=h[h.length-1]=!0;const e=[],u=(o,n)=>{if(n<=o+1)return;const y=t[o],g=t[n];let f=0,s=0;for(let i=o+1;i<n;i++){const c=d(t[i],y,g);c>f&&(f=c,s=i)}if(f>a){const i=t[s];let c=!0;for(let l=0;l<e.length-1;l++)if(r(e[l],e[l+1],y,i)||r(e[l],e[l+1],i,g)){c=!1;break}c&&(h[s]=!0,u(o,s),u(s,n))}};return u(0,t.length-1),t.filter((o,n)=>h[n])}applySimplification(){this.points=this.topologyPreservingSimplify(this.points,.5),this.select(this.points.length-1)}get selected(){return this._selected}select(t){this._selected=Math.max(0,Math.min(t,this.points.length-1))}}export function useBuildRoute({enabled:L,rendererService:t}){const a=P(!1),d=P(),r=_(()=>S(I,C),[]),h=_(()=>S(I,Y),[]),e=_(()=>new q,[]),u=P(new B),o=_(()=>{if(!t.scene)return{};const s=t.scene.rootLayer.children,i=s.find(l=>l.name===H),c=s.find(l=>l.name===K);return{linesLayer:i,pointsLayer:c}},[t.scene]),n=x(()=>{if(!t?.renderer||!o||!r||!h)return;const{linesLayer:s,pointsLayer:i}=o;if(!s||!i)return;const c=e.points,l=a.current;l?i.children.length=0:i.children=c.map(({x:p,y:k},w)=>{const E=w==e.selected?h:r;return{source:E,bounds:O(b(p,k,E.width,E.height,d.current))}});const m=[];for(let p=1;p<c.length;p++){const k=c[p-1],w=c[p];m.push({points:[k,w],color:l?C:J,width:j})}m.length?s.children=m:s.children.length=0,u.current.add(()=>t.update(i,s)),e.instruct(),e.log(JSON.stringify(e.points))},[t,e,o,r,h]),y=x(s=>{const i=s.key.toUpperCase();e.execute(()=>{switch(i){case R:s.preventDefault(),e.undo(),a.current=!1,n();break;case D:s.preventDefault(),e.applySmoothing(),a.current=!1,n();break;case A:s.preventDefault(),e.applySimplification(),a.current=!1,n();break;case N:s.preventDefault(),a.current=!a.current,n();break}})},[e,n]),g=x(({ptScale:s,sceneId:i})=>{if(!U(i)||!t?.renderer||!o)return;const{pointsLayer:c}=o;c&&(d.current=s,e.execute(()=>{const l=c.children,m=[];for(const p of l)p.bounds=O(b(p.bounds.center.x,p.bounds.center.y,p.source.width,p.source.height,d.current)),m.push(p);u.current.add(()=>t.update(...m))}))},[t,o,e]),f=x(({data:s})=>{e.execute(()=>{const{point:i}=$(s);e.add({x:i.x,y:i.y}),e.select(e.points.length-1),n()})},[e,n]);T(()=>{const s=t.renderer;if(!(!L||!s))return d.current=t.scale,e.execute(()=>{e.restore(),n()}),s.events.addEventListener("pointer:click",f),s.events.addEventListener("viewport:ptscale",g),window.addEventListener("keyup",y),()=>{window.removeEventListener("keyup",y),s.events.removeEventListener("pointer:click",f),s.events.removeEventListener("viewport:ptscale",g),u.current.destroy()}},[L,t,e,n,f,g,y])}
3
+ Apply Smoothing: Press ${A}.
4
+ Apply Simplification: Press ${N}.
5
+ Undo: Press ${D}.
6
+ Enable/Disable Preview: Press ${M}.
7
+ `,16)}applyChaikinSmoothing(e,l,p){let o;if(p>=1&&e.length>=2){o=[e[0]];for(let h=1;h<e.length;h++){const t=e[h-1],u=e[h];for(let n=1;n<=p;n++){const r=n/(p+1);o.push({x:t.x+(u.x-t.x)*r,y:t.y+(u.y-t.y)*r})}o.push(u)}}else o=e.slice();for(let h=0;h<l&&!(o.length<2);h++){const t=[{...o[0]}];for(let u=1;u<o.length;u++){const n=o[u-1],r=o[u];t.push({x:.75*n.x+.25*r.x,y:.75*n.y+.25*r.y}),t.push({x:.25*n.x+.75*r.x,y:.25*n.y+.75*r.y})}t.push({...o[o.length-1]}),o=t}return o}applySmoothing(){this.points.length<3||(this.points=this.applyChaikinSmoothing(this.points,1,0),this.select(this.points.length-1))}save(){try{this.points.length?sessionStorage.setItem(this.storageKey,JSON.stringify(this.points)):sessionStorage.removeItem(this.storageKey)}catch(e){console.warn(e)}}restore(){try{const e=sessionStorage.getItem(this.storageKey);if(!e)return;const l=JSON.parse(e);if(!Array.isArray(l))return;l.forEach(p=>this.add(p)),this.select(this.points.length-1)}catch(e){console.warn(e)}}topologyPreservingSimplify(e,l){if(e.length<=2)return e.map(n=>({...n}));const p=(n,r,y)=>{const g=n.x,f=n.y,s=r.x,i=r.y,c=y.x,a=y.y,d=Math.abs((a-i)*g-(c-s)*f+c*i-a*s),m=Math.sqrt((a-i)**2+(c-s)**2);return d/(m||1e-10)},o=(n,r,y,g)=>{const f=U({p0:n,p1:r},{p0:y,p1:g});return f!==null&&f.onLine1&&f.onLine2},h=new Array(e.length).fill(!1);h[0]=h[h.length-1]=!0;const t=[],u=(n,r)=>{if(r<=n+1)return;const y=e[n],g=e[r];let f=0,s=0;for(let i=n+1;i<r;i++){const c=p(e[i],y,g);c>f&&(f=c,s=i)}if(f>l){const i=e[s];let c=!0;for(let a=0;a<t.length-1;a++)if(o(t[a],t[a+1],y,i)||o(t[a],t[a+1],i,g)){c=!1;break}c&&(h[s]=!0,u(n,s),u(s,r))}};return u(0,e.length-1),e.filter((n,r)=>h[r])}applySimplification(){this.points=this.topologyPreservingSimplify(this.points,.5),this.select(this.points.length-1)}get selected(){return this._selected}select(e){this._selected=Math.max(0,Math.min(e,this.points.length-1))}}export function useBuildRoute({enabled:_,scene:e}){const l=P(!1),p=P(),o=S(()=>v(I,R),[]),h=S(()=>v(I,Y),[]),t=S(()=>new q,[]),u=P(new B),n=S(()=>{if(!e)return{};const s=e.rootLayer.children,i=s.find(a=>a.name===H),c=s.find(a=>a.name===T);return{linesLayer:i,pointsLayer:c}},[e]),r=x(()=>{if(!n||!o||!h)return;const{linesLayer:s,pointsLayer:i}=n;if(!s||!i)return;const c=t.points,a=l.current;a?i.children.length=0:i.children=c.map(({x:m,y:L},k)=>{const w=k==t.selected?h:o;return{source:w,bounds:b(m,L,w.width,w.height,p.current)}});const d=[];for(let m=1;m<c.length;m++){const L=c[m-1],k=c[m];d.push({points:{p0:L,p1:k},color:a?R:J,width:j})}d.length?s.children=d:s.children.length=0,u.current.add(()=>O(i,s)),t.instruct(),t.log(JSON.stringify(t.points))},[t,n,o,h]),y=x(s=>{const i=s.key.toUpperCase();t.execute(()=>{switch(i){case D:s.preventDefault(),t.undo(),l.current=!1,r();break;case A:s.preventDefault(),t.applySmoothing(),l.current=!1,r();break;case N:s.preventDefault(),t.applySimplification(),l.current=!1,r();break;case M:s.preventDefault(),l.current=!l.current,r();break}})},[t,r]),g=x(s=>{p.current=s;const{pointsLayer:i}=n;if(!i)return[];const c=[];return t.execute(()=>{const a=i.children;for(const d of a)d.bounds=b(d.bounds.center.x,d.bounds.center.y,d.source.width,d.source.height,p.current),c.push(d)}),c},[n,t]),f=x(s=>{t.execute(()=>{t.add({x:s.x,y:s.y}),t.select(t.points.length-1),r()})},[t,r]);$(()=>{if(!_||!n?.pointsLayer)return;const{pointsLayer:s}=n;return p.current=K()?.state().pixelSize??1,t.execute(()=>{t.restore(),r()}),s.onScale=({pixelSize:i})=>g(i),u.current.add(()=>O(s)),E(f),window.addEventListener("keyup",y),()=>{window.removeEventListener("keyup",y),E(),s.onScale=void 0,u.current.destroy()}},[_,n,t,r,f,g,y])}
@@ -1,9 +1,10 @@
1
- import { RendererService } from '../../../renderer';
1
+ import { SceneDef } from '@expofp/renderer';
2
2
  export interface ManageTrafficParams {
3
3
  permission: boolean;
4
- rendererService: RendererService;
4
+ /** The scene whose traffic layers this fills; `config-all` pre-creates them in it. */
5
+ scene: SceneDef | undefined;
5
6
  dataJsonUrl: string;
6
7
  websocketUrl: string;
7
8
  }
8
- export declare function useManageTraffic({ permission, rendererService, dataJsonUrl, websocketUrl, }: ManageTrafficParams): void;
9
+ export declare function useManageTraffic({ permission, scene, dataJsonUrl, websocketUrl, }: ManageTrafficParams): void;
9
10
  //# sourceMappingURL=useManageTraffic.d.ts.map
@@ -1 +1 @@
1
- import{degToRad as It,lineAngle as ut,pointDistance as lt}from"@expofp/geometry";import{useEffect as xt,useRef as L}from"react";import{getBounds as k,rectToRenderer as Y}from"../../../renderer";import{isDefaultScene as Mt}from"../../../renderer/engine-core/defs";import Lt from"../../../tools/base-runtime-url";import{loadImage as bt}from"../../../utils/loadImage";import{createImageCanvas as Ft}from"../drawing/config/canvases";import{getRouteLayerRegex as Rt,getRouteStopLayerRegex as At,TRAFFIC_VEHICLES as Tt}from"./trafficLayers";import{UpdateQueue as Pt}from"./UpdateQueue";const nt=2,vt=nt*3.5,Q=nt*12,dt=Q*.7,_t=8,Ct="transport_locations",Nt=150,ot="#a4aab6",ht=1e3,St=2e4,ft=500;export function useManageTraffic({permission:e,rendererService:n,dataJsonUrl:c,websocketUrl:s}){const t=L(window.devicePixelRatio),r=L(new Map),o=L(new Map),i=L(),w=L(),m=L(performance.now()),x=L(1),y=L(new Pt),F=L(new Map),E=L(),h=L(ht),I=L(new Map),l=L();xt(()=>{let A;async function N(){if(!(!e||!n.scene))try{let f;try{const a=await fetch(c,{method:"GET",headers:{"Content-Type":"application/json"}});if(!a.ok||a.status===204)return;f=await a.json()}catch(a){console.warn("useManageTraffic failed to get JSON",a)}if(!f||f?.disabled||f?.error)return;t.current=gt(n.scale);const Z=new Map(f.routes.map(({id:a,color:p})=>[a,p])),H=n.scene.rootLayer.children,V=new Map;Z.forEach(a=>{V.set(a,Ht({radius:vt,color:a,scale:window.devicePixelRatio}))});const j=Rt(),q=H.filter(a=>j.test(a.name)),B=At(),G=H.filter(a=>B.test(a.name));f.routes.slice(0,q.length).forEach(({id:a,color:p,path:P,stops:W,hiddenPoints:v},d)=>{F.current.set(a,P);const _=q[d];if(_){const C=new Map(v?.map(u=>[rt(u),u])??[]);for(let u=1;u<P.length;u++){const S=P[u-1],D=P[u];C.has(rt(S))||C.has(rt(D))||_.children.push({points:[S,D],color:p,width:nt})}_.children.length&&y.current.add(()=>n.update(_))}const g=G[d];if(g&&W?.length){const C=V.get(p);W.forEach(u=>{g.children.push({source:C,bounds:Y(k(u.x,u.y,C.width,C.height,t.current))})}),g.children.length&&y.current.add(()=>n.update(g))}});const z=H.find(a=>a.name===Tt),J=new Map;E.current=a=>{try{const{ptScale:p,sceneId:P}=Dt(a);if(!Mt(P))return;t.current=gt(p);const W=[];for(const d of G){const _=d.children;for(const g of _)g.bounds=Y(k(g.bounds.center.x,g.bounds.center.y,g.source.width,g.source.height,t.current,g.bounds.rotation)),W.push(g)}const v=[...r.current.values()];for(const d of v)d.bounds=Y(k(d.bounds.center.x,d.bounds.center.y,d.source.width,d.source.height,t.current,d.bounds.rotation));y.current.add(()=>n.update(...W,...v))}catch(p){console.error("ptscale",p)}},n.renderer.events.addEventListener("viewport:ptscale",E.current),A=requestAnimationFrame(()=>{E.current?.(n.scale)}),Z.forEach((a,p)=>{J.set(p,mt({id:p,width:Q,height:Q,color:a,scale:window.devicePixelRatio}))}),J.set(ot,mt({id:"orphan",width:Q,height:Q,color:ot,scale:window.devicePixelRatio}));let U=null;try{const a=await bt(`${Lt}icons/bus-white.svg`);U=Ft(a,dt,dt,window.devicePixelRatio)}catch(a){console.error(a)}w.current=a=>{try{const p=JSON.parse(a.data);if(p.type!==Ct)return;const P=a.timeStamp||performance.now();x.current=Math.round(P-m.current),m.current=P;const W=Math.max(x.current??ft,ft),v=o.current,d=r.current,_=z.children,g=y.current;let C=!1;p.data.forEach(({id:u,x:S,y:D,route_id:st,hidden:yt})=>{if(v.has(u)&&(v.get(u)?.(),v.delete(u)),yt&&d.has(u)&&d.has(X(u))){const R=d.get(u);R.hidden=!0;const b=d.get(X(u));b.hidden=!0,g.add(()=>n.update(R,b));return}if(I.current.set(u,performance.now()),!d.has(u)){const R=J.get(st)||J.get(ot),b={id:u,source:R,bounds:Y(k(S,D,R.width,R.height,t.current,0))};if(d.set(u,b),U){const $=X(u),at={id:$,source:U,bounds:Y(k(S,D,U.width,U.height,t.current,0))};U.setAttribute("id",$),d.set($,at),_.push(b,at)}else _.push(b);C=!0;return}const K=d.get(u),it=d.get(X(u)),Et=K.bounds.center,et=Wt(Et,{x:S,y:D},F.current.get(st));if(et.reduce((R,b,$)=>$===0?R:R+ct(et[$-1],b),0)>=Nt||document.hidden)pt({rendererService:n,updateQueue:g,vehicle:K,vehicleFinery:it,x:S,y:D,scale:t.current,angle:Ot(K.bounds.center,{x:S,y:D})});else{const R=kt(et,W,b=>{pt({rendererService:n,updateQueue:g,vehicle:K,vehicleFinery:it,x:b.x,y:b.y,scale:t.current,angle:b.angle})});v.set(u,R)}}),C&&g.add(()=>n.update(z))}catch(p){console.error("handleSocketMessage",p)}},M(),O(f.config?(Number(f.config.vehicle_inactive_interval)||20)*1e3:St)}catch(f){console.warn(f)}}N();function M(){i.current?.readyState===WebSocket.OPEN||i.current?.readyState===WebSocket.CONNECTING||(i.current=new WebSocket(s),i.current.onmessage=w.current,i.current.onopen=()=>{h.current=ht},i.current.onclose=()=>{if(!navigator.onLine)return;setTimeout(M,h.current);const f=3e4;h.current=Math.min(h.current*2,f)})}function T(){M()}window.addEventListener("online",T);function O(f){clearInterval(l.current),l.current=window.setInterval(()=>{const Z=performance.now(),H=[],V=[];I.current.forEach((j,q)=>{if(Z-j<f)return;const B=r.current.get(q);B&&(B.hidden=!0,V.push(B),H.push(q));const G=X(q),z=r.current.get(G);z&&(z.hidden=!0,V.push(z),H.push(G))}),V.length&&y.current.add(()=>n.update(...V)),H.forEach(j=>I.current.delete(j))},f)}return()=>{E.current&&n.renderer&&n.renderer.events.removeEventListener("viewport:ptscale",E.current),A!==void 0&&cancelAnimationFrame(A),o.current.forEach(f=>f?.()),o.current.clear(),r.current.clear(),y.current.destroy(),window.removeEventListener("online",T),clearInterval(l.current)}},[e,n,c,s])}function gt(e){return Math.min(e||window.devicePixelRatio,_t)}function Dt(e){return typeof e=="number"?{ptScale:e}:e}function Ot(e,n){return ut(e,n)}function Ht({radius:e,scale:n,color:c}){const s=document.createElement("canvas"),t=s.getContext("2d");t.imageSmoothingEnabled=!1;const r=Math.ceil(e*2*n),o=r/2,i=e*.78,w=e*.33;return s.width=r,s.height=r,t.translate(o,o),t.scale(n,n),t.beginPath(),t.arc(0,0,e,0,2*Math.PI),t.fillStyle="#FFFFFF",t.fill(),t.beginPath(),t.arc(0,0,i,0,2*Math.PI),t.fillStyle=c,t.fill(),t.beginPath(),t.arc(0,0,w,0,2*Math.PI),t.fillStyle="#FFFFFF",t.fill(),s}function mt({id:e,width:n,height:c,color:s,scale:t}){const r=2*t,o=n/2*t,i=c*t,w=.6,m=.01,x=i*w,y=i,F=8*t,E=y+r+x/2+F*2,h=o*2+x+r+F*2,I=document.createElement("canvas");I.setAttribute("id",e),I.width=E,I.height=h;const l=I.getContext("2d"),A=E/2,N=h/2;l.save(),l.translate(A,N),l.rotate(-Math.PI/2),l.translate(-A,-N);const M=A,T=N-y/2+o,O=T+x;return l.shadowColor="rgba(16, 24, 40, 0.2)",l.shadowBlur=F/2,l.beginPath(),l.arc(M,T,o,Math.PI,0,!1),l.bezierCurveTo(M+o,T+i*.3,M+m*o,O,M,O),l.bezierCurveTo(M-m*o,O,M-o,T+i*.3,M-o,T),l.closePath(),l.fillStyle=s,l.fill(),l.strokeStyle="#FFFFFF",l.lineWidth=r,l.stroke(),l.restore(),I}function ct(e,n){return lt(e,n)}function X(e){return`${e}_finery`}function pt({rendererService:e,updateQueue:n,vehicle:c,vehicleFinery:s,x:t,y:r,scale:o,angle:i}){c.bounds=Y(k(t,r,c.source.width,c.source.height,o,i)),c.hidden=!1,s?(s.bounds=Y(k(t,r,s.source.width,s.source.height,o,It(e.angle))),s.hidden=!1,n.add(()=>e.update(s,c))):n.add(()=>e.update(c))}function tt(e,n,c){return{x:e.x+(n.x-e.x)*c,y:e.y+(n.y-e.y)*c}}function wt(e,n){let c=1/0,s={index:0,t:0};for(let t=0;t<n.length-1;t++){const r=n[t],o=n[t+1],i=o.x-r.x,w=o.y-r.y,m=i*i+w*w,x=m?((e.x-r.x)*i+(e.y-r.y)*w)/m:0,y=Math.max(0,Math.min(1,x)),F=tt(r,o,y),E=ct(e,F);E<c&&(c=E,s={index:t,t:y})}return s}function Vt(e,n,c){const s=ct(e,n),t=Math.max(2,Math.ceil(s/c)+1),r=[];for(let o=0;o<t;o++){const i=o/(t-1),w=tt(e,n,i);r.push(w)}return r}function Wt(e,n,c){if(!c||!c.length)return Vt(e,n,10);const s=wt(e,c),t=wt(n,c),r=[],o=i=>r.push(i);s.index+1<c.length?o(tt(c[s.index],c[s.index+1],s.t)):o(c[s.index]);for(let i=s.index+1;i<=t.index&&i<c.length;i++)o(c[i]);return t.index+1<c.length?o(tt(c[t.index],c[t.index+1],t.t)):o(c[t.index]),r}function kt(e,n,c,s){if(e.length<2)return()=>{};let t=null,r;const o=[];let i=0;for(let m=0;m<e.length-1;m++){const x=lt(e[m],e[m+1]);o.push(x),i+=x}const w=m=>{t||(t=m);const x=m-t,y=Math.min(x/n,1),F=y*i;let E=0,h=0;for(;h<o.length&&E+o[h]<F;)E+=o[h],h++;h>=o.length&&(h=o.length-1);const I=e[h],l=e[Math.min(h+1,e.length-1)],A=o[h]||0,N=A===0?0:(F-E)/A,M=I.x+(l.x-I.x)*N,T=I.y+(l.y-I.y)*N,O=ut(I,l);c({x:M,y:T,angle:O}),y<1?r=requestAnimationFrame(w):s&&s()};return r=requestAnimationFrame(w),()=>{r&&cancelAnimationFrame(r)}}function rt(e){return`${e.x},${e.y}`}
1
+ import{degToRad as xe,lineAngle as ie,pointDistance as ae}from"@expofp/geometry";import{update as O}from"@expofp/renderer";import{useEffect as Ee,useRef as R}from"react";import{getBounds as k}from"../../../engine/canvases";import Me from"../../../tools/base-runtime-url";import{loadImage as ve}from"../../../utils/loadImage";import{mapCamera as ue}from"../camera";import{createImageCanvas as Le}from"../drawing/config/canvases";import{getRouteLayerRegex as Re,getRouteStopLayerRegex as Se,TRAFFIC_VEHICLES as le}from"./trafficLayers";import{UpdateQueue as be}from"./UpdateQueue";const ee=2,Ae=ee*3.5,G=ee*12,de=G*.7,Fe=8,Te="transport_locations",Pe=150,te="#a4aab6",he=1e3,Ce=2e4,fe=500;export function useManageTraffic({permission:t,scene:r,dataJsonUrl:o,websocketUrl:a}){const e=R(window.devicePixelRatio),c=R(new Map),n=R(new Map),s=R(),w=R(),f=R(performance.now()),M=R(1),p=R(new be),S=R(new Map),I=R(he),g=R(new Map),y=R();Ee(()=>{async function d(){if(!(!t||!r))try{let u;try{const i=await fetch(o,{method:"GET",headers:{"Content-Type":"application/json"}});if(!i.ok||i.status===204)return;u=await i.json()}catch(i){console.warn("useManageTraffic failed to get JSON",i)}if(!u||u?.disabled||u?.error)return;e.current=ge(ue()?.state().pixelSize??window.devicePixelRatio);const x=new Map(u.routes.map(({id:i,color:m})=>[i,m])),H=r.rootLayer.children,V=new Map;x.forEach(i=>{V.set(i,Ne({radius:Ae,color:i,scale:window.devicePixelRatio}))});const j=Re(),Y=H.filter(i=>j.test(i.name)),q=Se(),B=H.filter(i=>q.test(i.name));u.routes.slice(0,Y.length).forEach(({id:i,color:m,path:h,stops:U,hiddenPoints:E},v)=>{S.current.set(i,h);const W=Y[v];if(W){const C=new Map(E?.map(l=>[oe(l),l])??[]);for(let l=1;l<h.length;l++){const N=h[l-1],D=h[l];C.has(oe(N))||C.has(oe(D))||W.children.push({points:{p0:N,p1:D},color:m,width:ee})}W.children.length&&p.current.add(()=>O(W))}const P=B[v];if(P&&U?.length){const C=V.get(m);U.forEach(l=>{P.children.push({source:C,bounds:k(l.x,l.y,C.width,C.height,e.current)})}),P.children.length&&p.current.add(()=>O(P))}});const _=H.find(i=>i.name===le),X=new Map;_.onScale=({pixelSize:i})=>{e.current=ge(i);const m=[];for(const h of B){const U=h.children;for(const E of U)E.bounds=k(E.bounds.center.x,E.bounds.center.y,E.source.width,E.source.height,e.current,E.bounds.rotation),m.push(E)}for(const h of c.current.values())h.bounds=k(h.bounds.center.x,h.bounds.center.y,h.source.width,h.source.height,e.current,h.bounds.rotation),m.push(h);return m},p.current.add(()=>O(_)),x.forEach((i,m)=>{X.set(m,me({id:m,width:G,height:G,color:i,scale:window.devicePixelRatio}))}),X.set(te,me({id:"orphan",width:G,height:G,color:te,scale:window.devicePixelRatio}));let z=null;try{const i=await ve(`${Me}icons/bus-white.svg`);z=Le(i,de,de,window.devicePixelRatio)}catch(i){console.error(i)}w.current=i=>{try{const m=JSON.parse(i.data);if(m.type!==Te)return;const h=i.timeStamp||performance.now();M.current=Math.round(h-f.current),f.current=h;const U=Math.max(M.current??fe,fe),E=n.current,v=c.current,W=_.children,P=p.current;let C=!1;m.data.forEach(({id:l,x:N,y:D,route_id:re,hidden:ye})=>{if(E.has(l)&&(E.get(l)?.(),E.delete(l)),ye&&v.has(l)&&v.has(Q(l))){const A=v.get(l);A.hidden=!0;const L=v.get(Q(l));L.hidden=!0,P.add(()=>O(A,L));return}if(g.current.set(l,performance.now()),!v.has(l)){const A=X.get(re)||X.get(te),L={id:l,source:A,bounds:k(N,D,A.width,A.height,e.current,0)};if(v.set(l,L),z){const $=Q(l),se={id:$,source:z,bounds:k(N,D,z.width,z.height,e.current,0)};z.setAttribute("id",$),v.set($,se),W.push(L,se)}else W.push(L);C=!0;return}const Z=v.get(l),ce=v.get(Q(l)),Ie=Z.bounds.center,K=Oe(Ie,{x:N,y:D},S.current.get(re));if(K.reduce((A,L,$)=>$===0?A:A+ne(K[$-1],L),0)>=Pe||document.hidden)we({updateQueue:P,vehicle:Z,vehicleFinery:ce,x:N,y:D,scale:e.current,angle:_e(Z.bounds.center,{x:N,y:D})});else{const A=He(K,U,L=>{we({updateQueue:P,vehicle:Z,vehicleFinery:ce,x:L.x,y:L.y,scale:e.current,angle:L.angle})});E.set(l,A)}}),C&&P.add(()=>O(_))}catch(m){console.error("handleSocketMessage",m)}},F(),b(u.config?(Number(u.config.vehicle_inactive_interval)||20)*1e3:Ce)}catch(u){console.warn(u)}}d();function F(){s.current?.readyState===WebSocket.OPEN||s.current?.readyState===WebSocket.CONNECTING||(s.current=new WebSocket(a),s.current.onmessage=w.current,s.current.onopen=()=>{I.current=he},s.current.onclose=()=>{if(!navigator.onLine)return;setTimeout(F,I.current);const u=3e4;I.current=Math.min(I.current*2,u)})}function T(){F()}window.addEventListener("online",T);function b(u){clearInterval(y.current),y.current=window.setInterval(()=>{const x=performance.now(),H=[],V=[];g.current.forEach((j,Y)=>{if(x-j<u)return;const q=c.current.get(Y);q&&(q.hidden=!0,V.push(q),H.push(Y));const B=Q(Y),_=c.current.get(B);_&&(_.hidden=!0,V.push(_),H.push(B))}),V.length&&p.current.add(()=>O(...V)),H.forEach(j=>g.current.delete(j))},u)}return()=>{const u=r?.rootLayer.children?.find(x=>x.name===le);u&&(u.onScale=void 0),n.current.forEach(x=>x?.()),n.current.clear(),c.current.clear(),p.current.destroy(),window.removeEventListener("online",T),clearInterval(y.current)}},[t,r,o,a])}function ge(t){return Math.min(t||window.devicePixelRatio,Fe)}function _e(t,r){return ie(t,r)}function Ne({radius:t,scale:r,color:o}){const a=document.createElement("canvas"),e=a.getContext("2d");e.imageSmoothingEnabled=!1;const c=Math.ceil(t*2*r),n=c/2,s=t*.78,w=t*.33;return a.width=c,a.height=c,e.translate(n,n),e.scale(r,r),e.beginPath(),e.arc(0,0,t,0,2*Math.PI),e.fillStyle="#FFFFFF",e.fill(),e.beginPath(),e.arc(0,0,s,0,2*Math.PI),e.fillStyle=o,e.fill(),e.beginPath(),e.arc(0,0,w,0,2*Math.PI),e.fillStyle="#FFFFFF",e.fill(),a}function me({id:t,width:r,height:o,color:a,scale:e}){const c=2*e,n=r/2*e,s=o*e,w=.6,f=.01,M=s*w,p=s,S=8*e,I=p+c+M/2+S*2,g=n*2+M+c+S*2,y=document.createElement("canvas");y.setAttribute("id",t),y.width=I,y.height=g;const d=y.getContext("2d"),F=I/2,T=g/2;d.save(),d.translate(F,T),d.rotate(-Math.PI/2),d.translate(-F,-T);const b=F,u=T-p/2+n,x=u+M;return d.shadowColor="rgba(16, 24, 40, 0.2)",d.shadowBlur=S/2,d.beginPath(),d.arc(b,u,n,Math.PI,0,!1),d.bezierCurveTo(b+n,u+s*.3,b+f*n,x,b,x),d.bezierCurveTo(b-f*n,x,b-n,u+s*.3,b-n,u),d.closePath(),d.fillStyle=a,d.fill(),d.strokeStyle="#FFFFFF",d.lineWidth=c,d.stroke(),d.restore(),y}function ne(t,r){return ae(t,r)}function Q(t){return`${t}_finery`}function we({updateQueue:t,vehicle:r,vehicleFinery:o,x:a,y:e,scale:c,angle:n}){if(r.bounds=k(a,e,r.source.width,r.source.height,c,n),r.hidden=!1,o){const s=ue()?.state().roll??0;o.bounds=k(a,e,o.source.width,o.source.height,c,xe(s)),o.hidden=!1,t.add(()=>O(o,r))}else t.add(()=>O(r))}function J(t,r,o){return{x:t.x+(r.x-t.x)*o,y:t.y+(r.y-t.y)*o}}function pe(t,r){let o=1/0,a={index:0,t:0};for(let e=0;e<r.length-1;e++){const c=r[e],n=r[e+1],s=n.x-c.x,w=n.y-c.y,f=s*s+w*w,M=f?((t.x-c.x)*s+(t.y-c.y)*w)/f:0,p=Math.max(0,Math.min(1,M)),S=J(c,n,p),I=ne(t,S);I<o&&(o=I,a={index:e,t:p})}return a}function De(t,r,o){const a=ne(t,r),e=Math.max(2,Math.ceil(a/o)+1),c=[];for(let n=0;n<e;n++){const s=n/(e-1),w=J(t,r,s);c.push(w)}return c}function Oe(t,r,o){if(!o||!o.length)return De(t,r,10);const a=pe(t,o),e=pe(r,o),c=[],n=s=>c.push(s);a.index+1<o.length?n(J(o[a.index],o[a.index+1],a.t)):n(o[a.index]);for(let s=a.index+1;s<=e.index&&s<o.length;s++)n(o[s]);return e.index+1<o.length?n(J(o[e.index],o[e.index+1],e.t)):n(o[e.index]),c}function He(t,r,o,a){if(t.length<2)return()=>{};let e=null,c;const n=[];let s=0;for(let f=0;f<t.length-1;f++){const M=ae(t[f],t[f+1]);n.push(M),s+=M}const w=f=>{e||(e=f);const M=f-e,p=Math.min(M/r,1),S=p*s;let I=0,g=0;for(;g<n.length&&I+n[g]<S;)I+=n[g],g++;g>=n.length&&(g=n.length-1);const y=t[g],d=t[Math.min(g+1,t.length-1)],F=n[g]||0,T=F===0?0:(S-I)/F,b=y.x+(d.x-y.x)*T,u=y.y+(d.y-y.y)*T,x=ie(y,d);o({x:b,y:u,angle:x}),p<1?c=requestAnimationFrame(w):a&&a()};return c=requestAnimationFrame(w),()=>{c&&cancelAnimationFrame(c)}}function oe(t){return`${t.x},${t.y}`}
@@ -0,0 +1,63 @@
1
+ import { type ViewportAPI } from '@expofp/renderer';
2
+ import { type FloorPlanGetCoordsEvent } from '../../types';
3
+ /**
4
+ * What the mounted map holds, and hands the handle below a live view of.
5
+ *
6
+ * The renderer's conversions themselves, unwrapped: unlike the camera, there is nothing to publish
7
+ * here *besides* them — no reader to pair with the commands — so the handle is the same shape as
8
+ * what it forwards to.
9
+ */
10
+ export interface MountedViewport {
11
+ /** The conversions, as the renderer last handed them over. */
12
+ api: ViewportAPI;
13
+ }
14
+ /**
15
+ * Wraps the map's live coordinate conversions in a handle whose identity never changes.
16
+ *
17
+ * The same inversion `createMapCamera` performs, and for the same reason: the renderer's hooks
18
+ * return a fresh object on every render — they memoize nothing, so that the cost of a settled
19
+ * identity is paid by whoever knows how often they render. That is this map, which reads them
20
+ * through a ref and hands out this one object for the life of the mount.
21
+ * @param viewport - A live view of what the mounted map holds.
22
+ * @returns The handle to publish.
23
+ */
24
+ export declare function createMapViewport(viewport: {
25
+ readonly current: MountedViewport;
26
+ }): ViewportAPI;
27
+ /**
28
+ * Publishes the plan's coordinate conversions, for as long as the map is on screen.
29
+ *
30
+ * The same inversion `setMapCamera` performs: the renderer's viewport is reached through a
31
+ * hook, which only resolves inside a component mounted under `<Renderer>` — deliberately, since that
32
+ * is what stops anything measuring the plan before the canvas exists. The SDK's own methods and the
33
+ * kiosk store are not components and cannot hold a hook, so the map hands the conversions out here
34
+ * once it is safe.
35
+ * @param viewport - The conversions; omitted to unpublish them as the map unmounts.
36
+ */
37
+ export declare function setMapViewport(viewport?: ViewportAPI): void;
38
+ /**
39
+ * The plan's coordinate conversions, if the plan is on screen.
40
+ *
41
+ * Absent only before the canvas has mounted. Present in MapLibre mode as much as on the standalone
42
+ * plan: the conversions read the scene's space and the camera three draws with, and in external mode
43
+ * that camera is the one MapLibre's matrix is decomposed onto — so `canvasToPlan` casts its ray
44
+ * through the venue exactly as it does when this renderer owns the camera.
45
+ * @returns The conversions, or `undefined`.
46
+ */
47
+ export declare function mapViewport(): ViewportAPI | undefined;
48
+ /**
49
+ * What the middle of the canvas is looking at, which is what the SDK's `getCenterCoordinates`
50
+ * reports.
51
+ *
52
+ * The canvas center rather than the camera's own target, and the two are not the same point: a
53
+ * `visibleRect` moves where the camera looks without moving the canvas under it. This is what the
54
+ * imperative map converted through `viewport.canvasToSvg`.
55
+ *
56
+ * Shared by both views. Each passes the canvas it owns — the plan's own, or the one MapLibre draws
57
+ * on — and the answer comes back in plan coordinates either way, so the SDK's method means the same
58
+ * thing in map mode as on the plan.
59
+ * @param canvas - The canvas the plan is drawn on, once it has mounted.
60
+ * @returns The plan coordinates, and the floor they are on.
61
+ */
62
+ export declare function centerCoordinates(canvas: HTMLCanvasElement | null): FloorPlanGetCoordsEvent;
63
+ //# sourceMappingURL=viewport.d.ts.map
@@ -0,0 +1 @@
1
+ import p from"../../store";import{LayerMode as o}from"../../store/LayerStore";export function createMapViewport(e){return{canvasToPlan:n=>e.current.api.canvasToPlan(n),planToCanvas:n=>e.current.api.planToCanvas(n),isVisible:n=>e.current.api.isVisible(n)}}export function setMapViewport(e){i=e}export function mapViewport(){return i}let i;export function centerCoordinates(e){const n=mapViewport();if(!e||!n)throw new Error("Canvas not ready");const r=n.canvasToPlan({x:e.clientWidth/2,y:e.clientHeight/2});if(!r)throw new Error("The camera is not looking at the plan");const a=p.layerStore.visible.find(t=>t.mode===o.TurnedOff||t.mode===o.TurnedOn);return{x:r.x,y:r.y,z:a?.name||null}}
@@ -3,8 +3,12 @@ import { type MaplibreViewMode } from '../../store/MaplibreStore';
3
3
  * Main MobX adapter component that bridges application state to the
4
4
  * state-agnostic MaplibreWrapper.
5
5
  *
6
- * Reused renderer config modules still read singleton stores internally;
7
- * MaplibreWrapper itself remains pure and decoupled from application state.
6
+ * The embed renders through the ordinary `<Renderer>` in external mode, so everything the
7
+ * standalone map wires through defs works identically here: picking through the layers' own
8
+ * handlers, label re-layout through `onScale`, counter-rotation through `onRoll` measured off the
9
+ * map's matrix every frame — no rotate listeners, no scale registries, no roll sync. Reused
10
+ * renderer config modules still read singleton stores internally; MaplibreWrapper itself remains
11
+ * pure and decoupled from application state.
8
12
  */
9
13
  interface MaplibreAdapterProps {
10
14
  viewMode: MaplibreViewMode;
@@ -1 +1 @@
1
- import{jsx as re}from"react/jsx-runtime";import{degToRad as $}from"@expofp/geometry";import te from"color";import{runInAction as oe}from"mobx";import{observer as ne}from"mobx-react-lite";import{useCallback as B,useEffect as j,useMemo as b,useRef as d,useState as N}from"react";import ie from"../../data";import{getLayerSvg as ae,svgArea as P,svgAreaExplicit as ce}from"../../data/svg";import{createSceneDef as se}from"../../renderer";import{pickDefaultScenePoint as le}from"../../renderer/engine-core/defs";import c,{uiState as s}from"../../store";import{LayerMode as U}from"../../store/LayerStore";import T from"../../tools/settings";import{fitRectIsFraming as ue,getVenueFitMarginPercent as fe,resolveVenueFitRect as me}from"../../utils/scene-bounds";import pe from"../Map/drawing/config/config-all";import{loadLayersImages as de}from"../Map/drawing/config/loadBoothsImages";import{useBuildRoute as ge}from"../Map/traffic/useBuildRoute";import{useManageTraffic as be}from"../Map/traffic/useManageTraffic";import Se from"./MaplibreWrapper";import{useCameraReactions as Re}from"./useCameraReactions";import{useDimming as ye}from"./useDimming";import{useKioskIdleEvents as he}from"./useKioskIdleEvents";import{useLayerVisibilitySync as Ce}from"./useLayerVisibilitySync";import{usePoiMarkers as Me}from"./usePoiMarkers";import{useRendererEvents as ve}from"./useRendererEvents";import{useWayfindingAndMarkers as Ae}from"./useWayfindingAndMarkers";import{cameraForLocalRect as De,deriveGeoConfig as Pe,getLocalRectGeoBounds as Te,getVisibleRectFitPadding as ze,INITIAL_FIT_ZOOM_ADJUSTMENT as Le}from"./utils/geo-config";import{applyMapOptions as V,DEFAULT_MAP_OPTIONS as Oe,getTileSource as Ee,MAP_2D_OPTIONS as xe}from"./utils/map-helpers";import{calculateTransformMatrix as ke}from"./utils/solver";const G="routes-api.expofp.com",_e=800;function Fe(r,l,a){return{getCameraState:()=>{const o=r.getCenter();return{lng:o.lng,lat:o.lat,zoom:r.getZoom(),bearing:r.getBearing(),pitch:r.getPitch()}},applyCameraState:o=>{r.easeTo({center:[o.lng,o.lat],zoom:o.zoom,bearing:o.bearing??l,pitch:o.pitch??a(),duration:_e,essential:!0})},resetPitch:()=>{const o=a();r.getPitch()!==o&&r.jumpTo({pitch:o})}}}function W(){c.poiMarkerStore.clear(),oe(()=>{c.layerStore.layers.forEach(r=>{r.configured=!1,r.children=[],r.loaded=!1}),c.layerStore.layersLoaded=!1})}function X(r,l){const a=[];for(const o of r.rollRegistry.invoke(l))Array.isArray(o)?a.push(...o):a.push(o);a.length&&r.update(...a)}function we(r){const l=Math.abs(r[0]??0),a=Math.hypot(r[0]??0,r[1]??0);return l<=0||a<=0?1:l/a}const Ie=ne(function({viewMode:l}){const[a,o]=N(null),[C,x]=N(null),n=c.rendererService,z=d(null),u=d(null),M=d(null),L=d(null),k=d(null),v=d(null),e=b(()=>Pe(),[]),O=b(()=>me({layerViewbox:c.layerStore.viewboxRectangle,explicitArea:ce?P:null,layerRectangle:c.layerStore.rectangle,sceneDef:a,svgArea:P}),[a]),A=O.rect,S=b(()=>{if(!e)return null;const i=ue(O.source)?0:fe(A,P),t=ze(0);i&&s.screenSize&&(t.left+=s.screenSize.width*i,t.right+=s.screenSize.width*i,t.top+=s.screenSize.height*i,t.bottom+=s.screenSize.height*i);const m=s.screenSize?De(A,e.gpsConfig,e.bearing,{width:s.screenSize.width,height:s.screenSize.height},t):null;return m?{center:m.center,bearing:e.bearing,zoom:m.zoom}:{center:e.center,bearing:e.bearing,zoom:e.zoom,bounds:Te(A,e.gpsConfig),fitPadding:t,zoomAdjustment:Le}},[e,O,A]),R=b(()=>e?ke(e.gpsConfig,ae()?.getAttribute("units")):null,[e]),y=b(()=>({...l==="map2d"?xe:Oe}),[l]),E=d(y),H=b(()=>Ee(),[]),{mapDimAnimatorRef:_,venueDimAnimatorRef:F,applyDimmingTarget:w,handleMapDimLayerReady:J}=ye(u,n);j(()=>{if(!e)return;let i=!1;W();const t=pe(n).then(({layers:f,cleanup:p})=>{if(i){p();return}L.current=p;const D=te(T.backgroundColor==="none"?"#ebebeb":T.backgroundColor).string(),g=se(f,P,D);o(g)}).catch(f=>{i||console.warn("Maplibre scene configuration failed.",f)}),m=_.current,h=F.current;return()=>{i=!0,W();const f=z.current;t.finally(()=>n.disposeIfCurrent(f)),M.current?.(),M.current=null,L.current?.(),L.current=null,v.current&&(c.maplibreStore.clearCameraPortIfCurrent(v.current),v.current=null),z.current=null,u.current=null,k.current=null,x(null),m?.stop(),h?.stop(),s.sceneDefReady=!1}},[e,_,n,F]);const K=B((i,t,m,h)=>{z.current=i,u.current=t,k.current=h,x(i),n.attach(i,m,h,R?we(R):1),V(t,E.current);const f=Fe(t,e?.bearing??t.getBearing(),()=>E.current.pitch??0);v.current=f,c.maplibreStore.setCameraPort(f),c.fp.getCenterCoordinates=()=>{const{canvas:g}=i,q=le(i.viewport.canvasToSvg({x:g.clientWidth/2,y:g.clientHeight/2})),ee=c.layerStore.visible.find(I=>I.mode===U.TurnedOff||I.mode===U.TurnedOn);return{...q,z:ee?.name||null}},w({immediate:!0}),M.current?.();const p=()=>{const g=t.getBearing()-(e?.bearing??0);X(n,$(g))};t.on("rotate",p),t.on("rotateend",p),M.current=()=>{t.off("rotate",p),t.off("rotateend",p)},de(n);const D=n.ptScaleRegistry.invoke(n.scale||1);D.length&&n.update(...D),X(n,$(t.getBearing()-(e?.bearing??0))),c.layerStore.layersLoaded=!0,c.fp.onFpConfigured&&c.fp.onFpConfigured(),s.sceneDefReady=!0,h()},[n,w,R,e]);j(()=>{E.current=y,V(u.current,y,!0)},[y]),ve(C,n),he(C,u),Ae(C,n),Me(C,u,e),Ce(n,u,e),Re(u,e,a),ge({enabled:c.layerStore.layersLoaded&&s.buildRoute,rendererService:n});const Z=ie.busRoutes??!1;be({permission:c.layerStore.layersLoaded&&Z,rendererService:n,dataJsonUrl:`https://${G}/v1/routes?expo=${T.EXPO}`,websocketUrl:`wss://${G}/locations?expo=${T.EXPO}`});const Q=B(i=>{console.warn("Maplibre map failed to load; falling back to floorplan mode.",i),c.maplibreStore.deactivateMaplibre()},[]);if(!e||!S||!R||!a)return null;const Y=`${S.center.join(",")}:${S.bearing}:${S.zoom}`;return re(Se,{sceneDef:a,geoConfig:S,staticTransform:R,tileSource:H,mapOptions:y,onRendererReady:K,onMapDimLayerReady:J,onMapLoadError:Q},Y)});export default Ie;
1
+ import{jsx as x}from"react/jsx-runtime";import{isLayerDefs as Z}from"@expofp/renderer";import H from"color";import{runInAction as Q}from"mobx";import{observer as Y}from"mobx-react-lite";import{useCallback as F,useEffect as h,useMemo as m,useRef as f,useState as k}from"react";import q from"../../data";import{getLayerSvg as ee,svgArea as C,svgAreaExplicit as re}from"../../data/svg";import{createSceneDef as te}from"../../engine/defs";import t,{uiState as c}from"../../store";import M from"../../tools/settings";import oe from"../../utils/is-debug";import{fitRectIsFraming as ne,getVenueFitMarginPercent as ie,resolveVenueFitRect as ae}from"../../utils/scene-bounds";import ce from"../Map/drawing/config/config-all";import{loadLayersImages as se}from"../Map/drawing/config/loadBoothsImages";import{MapViewport as le}from"../Map/MapViewport";import{clearSelection as ue}from"../Map/pointer";import{setMapScene as $}from"../Map/scene";import{useBuildRoute as me}from"../Map/traffic/useBuildRoute";import{useManageTraffic as fe}from"../Map/traffic/useManageTraffic";import{centerCoordinates as pe}from"../Map/viewport";import de from"./MaplibreWrapper";import{useCameraReactions as ge}from"./useCameraReactions";import{useDimming as be}from"./useDimming";import{useKioskIdleEvents as Se}from"./useKioskIdleEvents";import{useLayerVisibilitySync as ye}from"./useLayerVisibilitySync";import{usePoiMarkers as Re}from"./usePoiMarkers";import{useWayfindingAndMarkers as he}from"./useWayfindingAndMarkers";import{cameraForLocalRect as Ce,deriveGeoConfig as Me,getLocalRectGeoBounds as Ae,getVisibleRectFitPadding as Le,INITIAL_FIT_ZOOM_ADJUSTMENT as Pe}from"./utils/geo-config";import{applyMapOptions as V,DEFAULT_MAP_OPTIONS as De,getTileSource as ze,MAP_2D_OPTIONS as Te}from"./utils/map-helpers";import{calculateTransformMatrix as ve}from"./utils/solver";const j="routes-api.expofp.com",Oe=800;function Ee(i,g,s){return{getCameraState:()=>{const o=i.getCenter();return{lng:o.lng,lat:o.lat,zoom:i.getZoom(),bearing:i.getBearing(),pitch:i.getPitch()}},applyCameraState:o=>{i.easeTo({center:[o.lng,o.lat],zoom:o.zoom,bearing:o.bearing??g,pitch:o.pitch??s(),duration:Oe,essential:!0})},resetPitch:()=>{const o=s();i.getPitch()!==o&&i.jumpTo({pitch:o})}}}function N(){t.poiMarkerStore.clear(),Q(()=>{t.layerStore.layers.forEach(i=>{i.configured=!1,i.children=[],i.loaded=!1}),t.layerStore.layersLoaded=!1})}const Ie=Y(function({viewMode:g}){const[s,o]=k(null),[z,T]=k(!1),u=f(null),b=f(null),A=f(null),v=f(null),S=f(null),r=m(()=>Me(),[]),L=m(()=>ae({layerViewbox:t.layerStore.viewboxRectangle,explicitArea:re?C:null,layerRectangle:t.layerStore.rectangle,sceneDef:s,svgArea:C}),[s]),y=L.rect,p=m(()=>{if(!r)return null;const e=ne(L.source)?0:ie(y,C),n=Le(0);e&&c.screenSize&&(n.left+=c.screenSize.width*e,n.right+=c.screenSize.width*e,n.top+=c.screenSize.height*e,n.bottom+=c.screenSize.height*e);const l=c.screenSize?Ce(y,r.gpsConfig,r.bearing,{width:c.screenSize.width,height:c.screenSize.height},n):null;return l?{center:l.center,bearing:r.bearing,zoom:l.zoom}:{center:r.center,bearing:r.bearing,zoom:r.zoom,bounds:Ae(y,r.gpsConfig),fitPadding:n,zoomAdjustment:Pe}},[r,L,y]),R=m(()=>r?ve(r.gpsConfig,ee()?.getAttribute("units")):null,[r]),d=m(()=>({...g==="map2d"?Te:De}),[g]),P=f(d),U=m(()=>ze(),[]),a=m(()=>{if(!s||!R)return null;const e=s.rootLayer.children,n=Z(e)?e.filter(l=>l.name.toLowerCase()!=="areamap"):e;return{...s,rootLayer:{...s.rootLayer,children:n},background:void 0,staticTransform:R}},[s,R]),O=f(null);h(()=>{O.current=a},[a]),h(()=>{if(a)return $(a),()=>$(void 0)},[a]);const{mapDimAnimatorRef:E,venueDimAnimatorRef:I,applyDimmingTarget:_,handleMapDimLayerReady:B}=be(u,O);h(()=>{if(!r)return;let e=!1;N(),ce().then(({layers:D,cleanup:w})=>{if(e){w();return}A.current=w;const X=H(M.backgroundColor==="none"?"#ebebeb":M.backgroundColor).string();o(te(D,C,X))}).catch(D=>{e||console.warn("Maplibre scene configuration failed.",D)});const n=E.current,l=I.current;return()=>{e=!0,N(),A.current?.(),A.current=null,S.current&&(t.maplibreStore.clearCameraPortIfCurrent(S.current),S.current=null),u.current=null,b.current=null,v.current=null,T(!1),n?.stop(),l?.stop(),c.sceneDefReady=!1}},[r,E,I]);const G=F((e,n)=>{u.current=e,b.current=e.getCanvas(),v.current=n,T(!0),V(e,P.current);const l=Ee(e,r?.bearing??e.getBearing(),()=>P.current.pitch??0);S.current=l,t.maplibreStore.setCameraPort(l),t.fp.getCenterCoordinates=()=>pe(b.current),_({immediate:!0}),se(),t.layerStore.layersLoaded=!0,t.fp.onFpConfigured&&t.fp.onFpConfigured(),c.sceneDefReady=!0,n()},[_,r]);h(()=>{P.current=d,V(u.current,d,!0)},[d]),Se(z,u),he(a,b),Re(z,u,r),ye(a,u,r),ge(u,r,a),me({enabled:t.layerStore.layersLoaded&&c.buildRoute,scene:a??void 0});const J=q.busRoutes??!1;fe({permission:t.layerStore.layersLoaded&&J,scene:a??void 0,dataJsonUrl:`https://${j}/v1/routes?expo=${M.EXPO}`,websocketUrl:`wss://${j}/locations?expo=${M.EXPO}`});const K=F(e=>{console.warn("Maplibre map failed to load; falling back to floorplan mode.",e),t.maplibreStore.deactivateMaplibre()},[]);if(!r||!p||!R||!a)return null;const W=`${p.center.join(",")}:${p.bearing}:${p.zoom}`;return x(de,{sceneDef:a,geoConfig:p,tileSource:U,mapOptions:d,debug:oe,onMapReady:G,onMapDimLayerReady:B,onMapLoadError:K,onPointerMissed:ue,children:x(le,{})},W)});export default Ie;
@@ -1,6 +1,7 @@
1
1
  import 'maplibre-gl/dist/maplibre-gl.css';
2
- import { Renderer, type SceneDef } from '@expofp/renderer';
2
+ import { type PointerMissedEventData, type SceneDef } from '@expofp/renderer';
3
3
  import { type LngLatBoundsLike, Map as MaplibreMap, type StyleSpecification } from 'maplibre-gl';
4
+ import { type ReactNode } from 'react';
4
5
  export declare const MAP_DIM_LAYER_ID = "expofp-map-dim";
5
6
  /**
6
7
  * Configuration for the map tile source.
@@ -46,29 +47,50 @@ export interface MapOptions {
46
47
  maxBounds?: LngLatBoundsLike;
47
48
  }
48
49
  export interface MaplibreWrapperProps {
49
- /** The scene definition to render inside the map */
50
+ /**
51
+ * The scene to render inside the map, already prepared for external mode by the caller:
52
+ * MapLibre is the only basemap (no areamap layer), the map paints the background, and the
53
+ * scene's `staticTransform` places the plan in Mercator.
54
+ */
50
55
  sceneDef: SceneDef;
51
56
  /** Geographic configuration for map positioning and floorplan locking */
52
57
  geoConfig: GeoConfig;
53
- /** Static SVG-to-Mercator transform prepared by the adapter */
54
- staticTransform: number[];
55
58
  /** Tile source configuration (online style URL for now) */
56
59
  tileSource: TileSourceConfig;
57
60
  /** Map camera constraints and defaults */
58
61
  mapOptions?: MapOptions;
59
- /** Called when the renderer instance is ready for external interaction */
60
- onRendererReady?: (renderer: Renderer, map: MaplibreMap, sceneDef: SceneDef, requestRepaint: () => void) => void;
62
+ /**
63
+ * Mounts the renderer's debug overlay. Fixed for the wrapper's lifetime: when set, map creation
64
+ * waits for `prepareDebug()`, so the map's context is created already instrumented and the
65
+ * GPU-memory panel has figures to show.
66
+ */
67
+ debug?: boolean;
68
+ /**
69
+ * Called once the map exists and its custom layer received the shared WebGL context — the
70
+ * moment the caller can wire map-level state: camera port, options, store flags.
71
+ */
72
+ onMapReady?: (map: MaplibreMap, requestRepaint: () => void) => void;
61
73
  /** Called when the dim overlay layer is available for paint updates. */
62
74
  onMapDimLayerReady?: (map: MaplibreMap) => void;
63
75
  /** Called when the map style cannot be loaded. */
64
76
  onMapLoadError?: (error: unknown) => void;
77
+ /** Forwarded to the renderer: a click that reached no layer handler. */
78
+ onPointerMissed?: (event: PointerMissedEventData) => void;
79
+ /** Components rendered inside the renderer's tree, under the scene's space. */
80
+ children?: ReactNode;
65
81
  }
66
82
  /**
67
83
  * A pure, state-agnostic React component that renders a Maplibre map
68
84
  * with the ExpoFP floorplan embedded via CustomLayerInterface.
69
85
  *
86
+ * The floorplan draws through the ordinary `<Renderer>` in external mode: the custom layer hands
87
+ * over the map's WebGL context when MapLibre creates it, repaint demand becomes
88
+ * `map.triggerRepaint()`, and every frame the map draws forwards its projection matrix to the
89
+ * renderer's subscribed draw. There is no update pump: the renderer asks the host for frames
90
+ * itself, through the same demand channel its own canvas would use.
91
+ *
70
92
  * This component does NOT import MobX or any application state.
71
- * All state synchronization is done externally via the onRendererReady callback.
93
+ * All state synchronization is done externally via the onMapReady callback.
72
94
  */
73
- export default function MaplibreWrapper({ sceneDef, geoConfig, staticTransform, tileSource, mapOptions, onRendererReady, onMapDimLayerReady, onMapLoadError, }: MaplibreWrapperProps): import("react").JSX.Element;
95
+ export default function MaplibreWrapper({ sceneDef, geoConfig, tileSource, mapOptions, debug, onMapReady, onMapDimLayerReady, onMapLoadError, onPointerMissed, children, }: MaplibreWrapperProps): import("react").JSX.Element;
74
96
  //# sourceMappingURL=MaplibreWrapper.d.ts.map
@@ -1 +1 @@
1
- import{jsx as N}from"react/jsx-runtime";import"maplibre-gl/dist/maplibre-gl.css";import{Renderer as G}from"@expofp/renderer";import{addProtocol as Y,Map as k}from"maplibre-gl";import{Protocol as q}from"pmtiles";import{useEffect as E,useRef as l}from"react";import{registerPmtilesArchive as H}from"./utils/pmtiles-range-fallback";import{createStyleTransform as J}from"./utils/resolve-map-style";import{createUpdatePump as Q}from"./utils/update-pump";export const MAP_DIM_LAYER_ID="expofp-map-dim";const g="expofp-map-dim-source",V="3d-expofp";let b=null;const W=["coalesce",["get","name:en"],["get","name_en"],["get","name:latin"],["get","name"]],X={type:"Feature",geometry:{type:"Polygon",coordinates:[[[-180,-85],[180,-85],[180,85],[-180,85],[-180,-85]]]},properties:{}};function I(e){if(!e||typeof e!="object")return!1;const r=e.length;if(typeof r!="number"||r<16)return!1;const n=e[0];return typeof n=="number"&&Number.isFinite(n)}function K(e){if(I(e))return Array.from(e);const n=e?.defaultProjectionData?.mainMatrix;return I(n)?Array.from(n):(console.warn("Maplibre custom layer received an unsupported projection matrix payload.",e),null)}function h(e){return typeof e=="string"?e.includes("name"):Array.isArray(e)?e.some(r=>h(r)):!e||typeof e!="object"?!1:Object.values(e).some(r=>h(r))}function $(e){return e.type!=="symbol"||!e.id||!e.layout?!1:h(e.layout["text-field"])}function v(e){const r=e.getStyle();for(const n of r.layers??[])$(n)&&e.setLayoutProperty(n.id,"text-field",W)}function ee(){if(b)return b;const e=new q;b=e;try{Y("pmtiles",e.tile)}catch(r){console.warn("Maplibre PMTiles protocol registration failed.",r)}return e}export default function te({sceneDef:e,geoConfig:r,staticTransform:n,tileSource:w,mapOptions:O,onRendererReady:x,onMapDimLayerReady:P,onMapLoadError:M}){const m=l(null),L=l(null),a=l(null),S=l(x),A=l(P),_=l(M),C=l({sceneDef:e,geoConfig:r,staticTransform:n,tileSource:w,mapOptions:O});return E(()=>{S.current=x,A.current=P,_.current=M}),E(()=>{if(!m.current)return;const{sceneDef:d,geoConfig:i,staticTransform:F,tileSource:p,mapOptions:f}=C.current;let y=!1;const u={...d};u.rootLayer={...d.rootLayer};const T=d.rootLayer.children;u.rootLayer.children=T.filter(o=>o?.name?.toString().toLowerCase()!=="areamap"),u.background=void 0,u.staticTransform=F;const z=ee(),U=i.bounds?{bounds:i.bounds,fitBoundsOptions:{padding:i.fitPadding,bearing:i.bearing}}:{center:i.center,zoom:i.zoom},j=J(p.style,p.offline?o=>H(z,o):void 0),t=new k({container:m.current,...U,bearing:i.bearing,pitch:f?.pitch??30,maxPitch:f?.maxPitch??70,minZoom:f?.minZoom,maxZoom:f?.maxZoom,maxBounds:f?.maxBounds,bearingSnap:0,canvasContextAttributes:{antialias:!0}});i.zoomAdjustment&&t.jumpTo({zoom:t.getZoom()+i.zoomAdjustment}),L.current=t,t.once("error",o=>{t.isStyleLoaded()||_.current?.(o?.error??o)});const R=o=>{const s=o?.id;!s||t.hasImage(s)||t.addImage(s,{width:1,height:1,data:new Uint8Array(4)})};t.on("styleimagemissing",R);const Z=Q({requestFrame:()=>t.triggerRepaint()}),B={id:V,type:"custom",renderingMode:"3d",onAdd(o,s){if(y)return;const c=new G({canvas:t.getCanvas(),gl:s});if(y){c.dispose();return}c.init(u),a.current=c,S.current?.(c,t,u,()=>t.triggerRepaint())},render(o,s){if(!a.current||a.current.isDisposed)return;const c=K(s??o);c&&(a.current.render(c),Z(a.current))}},D=()=>{v(t),t.getSource(g)||t.addSource(g,{type:"geojson",data:X}),t.getLayer(MAP_DIM_LAYER_ID)||t.addLayer({id:MAP_DIM_LAYER_ID,type:"fill",source:g,paint:{"fill-color":"#000000","fill-opacity":0,"fill-opacity-transition":{duration:0,delay:0}}}),A.current?.(t),t.addLayer(B)};return t.on("style.load",D),t.setStyle(p.style,j?{transformStyle:j}:void 0),()=>{y=!0,t.off("style.load",D),t.off("styleimagemissing",R),a.current?.dispose(),a.current=null,t.remove(),L.current=null}},[]),N("div",{ref:m,style:{position:"absolute",top:0,left:0,width:"100%",height:"100%"}})}
1
+ import{jsx as F}from"react/jsx-runtime";import"maplibre-gl/dist/maplibre-gl.css";import{prepareDebug as H,Renderer as J}from"@expofp/renderer";import{addProtocol as V,Map as W}from"maplibre-gl";import{Protocol as X}from"pmtiles";import{useEffect as z,useRef as l,useState as k}from"react";import{registerPmtilesArchive as K}from"./utils/pmtiles-range-fallback";import{createStyleTransform as Q}from"./utils/resolve-map-style";export const MAP_DIM_LAYER_ID="expofp-map-dim";const p="expofp-map-dim-source",$="3d-expofp";let y=null;const v=["coalesce",["get","name:en"],["get","name_en"],["get","name:latin"],["get","name"]],ee={type:"Feature",geometry:{type:"Polygon",coordinates:[[[-180,-85],[180,-85],[180,85],[-180,85],[-180,-85]]]},properties:{}};function T(e){if(!e||typeof e!="object")return!1;const o=e.length;if(typeof o!="number"||o<16)return!1;const r=e[0];return typeof r=="number"&&Number.isFinite(r)}function te(e){if(T(e))return Array.from(e);const r=e?.defaultProjectionData?.mainMatrix;return T(r)?Array.from(r):(console.warn("Maplibre custom layer received an unsupported projection matrix payload.",e),null)}function g(e){return typeof e=="string"?e.includes("name"):Array.isArray(e)?e.some(o=>g(o)):!e||typeof e!="object"?!1:Object.values(e).some(o=>g(o))}function oe(e){return e.type!=="symbol"||!e.id||!e.layout?!1:g(e.layout["text-field"])}function re(e){const o=e.getStyle();for(const r of o.layers??[])oe(r)&&e.setLayoutProperty(r.id,"text-field",v)}function ne(){if(y)return y;const e=new X;y=e;try{V("pmtiles",e.tile)}catch(o){console.warn("Maplibre PMTiles protocol registration failed.",o)}return e}export default function ie({sceneDef:e,geoConfig:o,tileSource:r,mapOptions:Z,debug:b,onMapReady:x,onMapDimLayerReady:h,onMapLoadError:M,onPointerMissed:B,children:C}){const P=l(null),[A,S]=k(),_=l(x),L=l(h),j=l(M),N=l({geoConfig:o,tileSource:r,mapOptions:Z,debug:b});return z(()=>{_.current=x,L.current=h,j.current=M}),z(()=>{const E=P.current;if(!E)return;const{geoConfig:n,tileSource:d,mapOptions:s,debug:U}=N.current;let m=!1,I;const R=()=>{const G=ne(),Y=n.bounds?{bounds:n.bounds,fitBoundsOptions:{padding:n.fitPadding,bearing:n.bearing}}:{center:n.center,zoom:n.zoom},D=Q(d.style,d.offline?i=>K(G,i):void 0),t=new W({container:E,...Y,bearing:n.bearing,pitch:s?.pitch??30,maxPitch:s?.maxPitch??70,minZoom:s?.minZoom,maxZoom:s?.maxZoom,maxBounds:s?.maxBounds,bearingSnap:0,canvasContextAttributes:{antialias:!0}});n.zoomAdjustment&&t.jumpTo({zoom:t.getZoom()+n.zoomAdjustment}),t.once("error",i=>{t.isStyleLoaded()||j.current?.(i?.error??i)});const O=i=>{const a=i?.id;!a||t.hasImage(a)||t.addImage(a,{width:1,height:1,data:new Uint8Array(4)})};t.on("styleimagemissing",O);let f;const u=()=>t.triggerRepaint(),q={id:$,type:"custom",renderingMode:"3d",onAdd(i,a){m||(S({gl:a,requestFrame:u,onFrame:c=>(f=c,u(),()=>{f===c&&(f=void 0)})}),_.current?.(t,u))},render(i,a){const c=te(a??i);c&&f?.(c)}},w=()=>{re(t),t.getSource(p)||t.addSource(p,{type:"geojson",data:ee}),t.getLayer(MAP_DIM_LAYER_ID)||t.addLayer({id:MAP_DIM_LAYER_ID,type:"fill",source:p,paint:{"fill-color":"#000000","fill-opacity":0,"fill-opacity-transition":{duration:0,delay:0}}}),L.current?.(t),t.addLayer(q)};t.on("style.load",w),t.setStyle(d.style,D?{transformStyle:D}:void 0),I=()=>{t.off("style.load",w),t.off("styleimagemissing",O),t.remove()}};return U?H().then(()=>{m||R()}):R(),()=>{m=!0,I?.(),S(void 0)}},[]),F("div",{ref:P,style:{position:"absolute",top:0,left:0,width:"100%",height:"100%"},children:A&&F(J,{...A,scene:e,debug:b,onPointerMissed:B,children:C})})}
@@ -1,6 +1,6 @@
1
+ import { type SceneDef } from '@expofp/renderer';
1
2
  import { type Map as MaplibreMap } from 'maplibre-gl';
2
3
  import { type RefObject } from 'react';
3
- import { type RendererService } from '../../renderer/RendererService';
4
4
  import { type DimmingAnimator } from '../../utils/dimming';
5
5
  export interface DimmingControls {
6
6
  mapDimAnimatorRef: RefObject<DimmingAnimator | null>;
@@ -21,5 +21,5 @@ export declare function getMapDimTarget(): boolean;
21
21
  * keeps them in sync with uiState.dimmed via a MobX reaction,
22
22
  * and provides a callback for when the map dim layer is ready.
23
23
  */
24
- export declare function useDimming(mapRef: RefObject<MaplibreMap | null>, rendererService: RendererService): DimmingControls;
24
+ export declare function useDimming(mapRef: RefObject<MaplibreMap | null>, sceneRef: RefObject<SceneDef | null>): DimmingControls;
25
25
  //# sourceMappingURL=useDimming.d.ts.map
@@ -1 +1 @@
1
- import{useCallback as p,useEffect as s,useRef as o}from"react";import T,{uiState as I}from"../../store";import{applyVenueDimValue as M,createDimmingAnimator as l,DIM_INTENSITY as D,VENUE_DIM_INTENSITY as V}from"../../utils/dimming";import{useReaction as d}from"../../utils/mobx";import{applyMapDimValue as f}from"./utils/map-helpers";export function getMapDimTarget(){return I.dimmed&&!T.poiMarkerStore.dimSuppressed}export function useDimming(a,m){const i=o(m);s(()=>{i.current=m},[m]);const e=o(null),n=o(null),c=p(t=>{const r=getMapDimTarget();e.current?.setTarget(r,t),n.current?.setTarget(r,t)},[]);s(()=>{const t=l(u=>{f(a.current,u*D)}),r=l(u=>{M(i.current,u*V)});return e.current=t,n.current=r,()=>{t.stop(),r.stop(),e.current=null,n.current=null}},[a]),d(()=>getMapDimTarget(),()=>c());const g=p(t=>{const r=e.current?.getValue()??(getMapDimTarget()?1:0);f(t,r*D)},[]);return{mapDimAnimatorRef:e,venueDimAnimatorRef:n,applyDimmingTarget:c,handleMapDimLayerReady:g}}
1
+ import{update as g}from"@expofp/renderer";import{useCallback as c,useEffect as T,useRef as p}from"react";import d,{uiState as y}from"../../store";import{applyVenueDim as I,createDimmingAnimator as s,DIM_INTENSITY as l,VENUE_DIM_INTENSITY as M}from"../../utils/dimming";import{useReaction as A}from"../../utils/mobx";import{applyMapDimValue as D}from"./utils/map-helpers";export function getMapDimTarget(){return y.dimmed&&!d.poiMarkerStore.dimSuppressed}export function useDimming(i,u){const e=p(null),n=p(null),a=c(r=>{const t=getMapDimTarget();e.current?.setTarget(t,r),n.current?.setTarget(t,r)},[]);T(()=>{const r=s(m=>{D(i.current,m*l)}),t=s(m=>{const o=u.current;o&&I(o,m*M)&&g(o.rootLayer)});return e.current=r,n.current=t,()=>{r.stop(),t.stop(),e.current=null,n.current=null}},[i,u]),A(()=>getMapDimTarget(),()=>a());const f=c(r=>{const t=e.current?.getValue()??(getMapDimTarget()?1:0);D(r,t*l)},[]);return{mapDimAnimatorRef:e,venueDimAnimatorRef:n,applyDimmingTarget:a,handleMapDimLayerReady:f}}
@@ -1,4 +1,3 @@
1
- import { type Renderer } from '@expofp/renderer';
2
1
  import { type Map as MaplibreMap } from 'maplibre-gl';
3
2
  import { type RefObject } from 'react';
4
3
  /**
@@ -9,10 +8,10 @@ import { type RefObject } from 'react';
9
8
  * these listeners the timer runs out mid-gesture for a visitor who only moves
10
9
  * the map.
11
10
  *
12
- * `renderer` is not read; it is the mount signal. `mapRef.current` is assigned
13
- * in the same `handleRendererReady` call that sets `renderer`, so keying the
14
- * effect on `renderer` is what guarantees there is a map to subscribe to — the
15
- * early return below is the assertion of that contract, not a tolerated miss.
11
+ * `ready` is the mount signal: `mapRef.current` is assigned in the same
12
+ * `handleMapReady` call that sets it, so keying the effect on `ready` is what
13
+ * guarantees there is a map to subscribe to — the early return below is the
14
+ * assertion of that contract, not a tolerated miss.
16
15
  */
17
- export declare function useKioskIdleEvents(renderer: Renderer | null, mapRef: RefObject<MaplibreMap | null>): void;
16
+ export declare function useKioskIdleEvents(ready: boolean, mapRef: RefObject<MaplibreMap | null>): void;
18
17
  //# sourceMappingURL=useKioskIdleEvents.d.ts.map
@@ -1,11 +1,11 @@
1
+ import { type SceneDef } from '@expofp/renderer';
1
2
  import type { Map as MaplibreMap } from 'maplibre-gl';
2
3
  import { type RefObject } from 'react';
3
- import type { RendererService } from '../../renderer/RendererService';
4
4
  import { type GeoConfig } from './utils/geo-config';
5
5
  /**
6
6
  * Keeps the 3D scene layer visibility in sync with LayerStore.
7
7
  * When a layer's visibility changes, updates the corresponding LayerDefs
8
8
  * and fits the camera to the newly visible floor.
9
9
  */
10
- export declare function useLayerVisibilitySync(rendererService: RendererService, mapRef: RefObject<MaplibreMap | null>, geoConfig: GeoConfig | null): void;
10
+ export declare function useLayerVisibilitySync(scene: SceneDef | null, mapRef: RefObject<MaplibreMap | null>, geoConfig: GeoConfig | null): void;
11
11
  //# sourceMappingURL=useLayerVisibilitySync.d.ts.map
@@ -1 +1 @@
1
- import{useRef as m}from"react";import s from"../../store";import{useReaction as L}from"../../utils/mobx";import{fitMapToLocalRect as b}from"./utils/geo-config";import{collectLayerDefsByName as h}from"./utils/layer-defs";export function useLayerVisibilitySync(f,u,y){const t=m(null),a=m(null);L(()=>s.layerStore.layers.map(e=>`${e.name}:${e.visible?1:0}`),()=>{const e=f.scene;if(!e)return;t.current?.rootLayer!==e.rootLayer&&(t.current={rootLayer:e.rootLayer,defsByName:h(e.rootLayer)});const d=t.current.defsByName,n=[];for(const o of s.layerStore.layers){const c=d.get(o.name);if(c?.length)for(const i of c){const l=!o.visible;i.hidden!==l&&(i.hidden=l,n.push(i))}}n.length&&f.update(...n);const r=s.layerStore.layers.find(o=>o.visible&&!o.frozen&&!o.rootParent&&!o.pathway);if(!r||a.current===r.name)return;a.current=r.name;const p=r.viewbox??r.rect;b(u.current,p??null,y)})}
1
+ import{update as p}from"@expofp/renderer";import{useRef as y}from"react";import a from"../../store";import{useReaction as L}from"../../utils/mobx";import{fitMapToLocalRect as b}from"./utils/geo-config";import{collectLayerDefsByName as h}from"./utils/layer-defs";export function useLayerVisibilitySync(r,s,l){const n=y(null),c=y(null);L(()=>a.layerStore.layers.map(t=>`${t.name}:${t.visible?1:0}`),()=>{if(!r)return;n.current?.rootLayer!==r.rootLayer&&(n.current={rootLayer:r.rootLayer,defsByName:h(r.rootLayer)});const t=n.current.defsByName,i=[];for(const e of a.layerStore.layers){const m=t.get(e.name);if(m?.length)for(const f of m){const u=!e.visible;f.hidden!==u&&(f.hidden=u,i.push(f))}}i.length&&p(...i);const o=a.layerStore.layers.find(e=>e.visible&&!e.frozen&&!e.rootParent&&!e.pathway);if(!o||c.current===o.name)return;c.current=o.name;const d=o.viewbox??o.rect;b(s.current,d??null,l)},void 0,[r,s,l])}